diff --git a/.doctrees/advanced.doctree b/.doctrees/advanced.doctree
index 66e9b80f5..2fc8bc34f 100644
Binary files a/.doctrees/advanced.doctree and b/.doctrees/advanced.doctree differ
diff --git a/.doctrees/advanced/iron_python.doctree b/.doctrees/advanced/iron_python.doctree
index e8821db29..7c2cd0fdf 100644
Binary files a/.doctrees/advanced/iron_python.doctree and b/.doctrees/advanced/iron_python.doctree differ
diff --git a/.doctrees/advanced/packaging.doctree b/.doctrees/advanced/packaging.doctree
index 92caa349f..85d909400 100644
Binary files a/.doctrees/advanced/packaging.doctree and b/.doctrees/advanced/packaging.doctree differ
diff --git a/.doctrees/attachments.doctree b/.doctrees/attachments.doctree
deleted file mode 100644
index 67e6c0456..000000000
Binary files a/.doctrees/attachments.doctree and /dev/null differ
diff --git a/.doctrees/authentication.doctree b/.doctrees/authentication.doctree
index 850a9a549..0cd1276d4 100644
Binary files a/.doctrees/authentication.doctree and b/.doctrees/authentication.doctree differ
diff --git a/.doctrees/changelog.doctree b/.doctrees/changelog.doctree
index ddb3bf05d..25de0991c 100644
Binary files a/.doctrees/changelog.doctree and b/.doctrees/changelog.doctree differ
diff --git a/.doctrees/cookbook.doctree b/.doctrees/cookbook.doctree
index 686fb71e9..f6ea410d9 100644
Binary files a/.doctrees/cookbook.doctree and b/.doctrees/cookbook.doctree differ
diff --git a/.doctrees/cookbook/attachments.doctree b/.doctrees/cookbook/attachments.doctree
index c537918b0..3c1f96902 100644
Binary files a/.doctrees/cookbook/attachments.doctree and b/.doctrees/cookbook/attachments.doctree differ
diff --git a/.doctrees/cookbook/examples/ami_handler.doctree b/.doctrees/cookbook/examples/ami_handler.doctree
index 7083a5841..b0be53909 100644
Binary files a/.doctrees/cookbook/examples/ami_handler.doctree and b/.doctrees/cookbook/examples/ami_handler.doctree differ
diff --git a/.doctrees/cookbook/examples/ami_version_packager.doctree b/.doctrees/cookbook/examples/ami_version_packager.doctree
index a41ad3709..57b923fd6 100644
Binary files a/.doctrees/cookbook/examples/ami_version_packager.doctree and b/.doctrees/cookbook/examples/ami_version_packager.doctree differ
diff --git a/.doctrees/cookbook/examples/basic_create_shot.doctree b/.doctrees/cookbook/examples/basic_create_shot.doctree
index 8b452a528..918f4a6ae 100644
Binary files a/.doctrees/cookbook/examples/basic_create_shot.doctree and b/.doctrees/cookbook/examples/basic_create_shot.doctree differ
diff --git a/.doctrees/cookbook/examples/basic_create_shot_task_template.doctree b/.doctrees/cookbook/examples/basic_create_shot_task_template.doctree
index 85bdd6a5d..953c2fe46 100644
Binary files a/.doctrees/cookbook/examples/basic_create_shot_task_template.doctree and b/.doctrees/cookbook/examples/basic_create_shot_task_template.doctree differ
diff --git a/.doctrees/cookbook/examples/basic_create_version_link_shot.doctree b/.doctrees/cookbook/examples/basic_create_version_link_shot.doctree
index 993d04ba1..03591844e 100644
Binary files a/.doctrees/cookbook/examples/basic_create_version_link_shot.doctree and b/.doctrees/cookbook/examples/basic_create_version_link_shot.doctree differ
diff --git a/.doctrees/cookbook/examples/basic_delete_shot.doctree b/.doctrees/cookbook/examples/basic_delete_shot.doctree
index b96263fd6..2ceaa8163 100644
Binary files a/.doctrees/cookbook/examples/basic_delete_shot.doctree and b/.doctrees/cookbook/examples/basic_delete_shot.doctree differ
diff --git a/.doctrees/cookbook/examples/basic_find_shot.doctree b/.doctrees/cookbook/examples/basic_find_shot.doctree
index 4f6f7dab7..2ff2ed7be 100644
Binary files a/.doctrees/cookbook/examples/basic_find_shot.doctree and b/.doctrees/cookbook/examples/basic_find_shot.doctree differ
diff --git a/.doctrees/cookbook/examples/basic_sg_instance.doctree b/.doctrees/cookbook/examples/basic_sg_instance.doctree
index aa08312bb..f91a00aac 100644
Binary files a/.doctrees/cookbook/examples/basic_sg_instance.doctree and b/.doctrees/cookbook/examples/basic_sg_instance.doctree differ
diff --git a/.doctrees/cookbook/examples/basic_update_shot.doctree b/.doctrees/cookbook/examples/basic_update_shot.doctree
index 513c4cf7f..7716cc70e 100644
Binary files a/.doctrees/cookbook/examples/basic_update_shot.doctree and b/.doctrees/cookbook/examples/basic_update_shot.doctree differ
diff --git a/.doctrees/cookbook/examples/basic_upload_thumbnail_version.doctree b/.doctrees/cookbook/examples/basic_upload_thumbnail_version.doctree
index a2f0b4997..6c6762ba7 100644
Binary files a/.doctrees/cookbook/examples/basic_upload_thumbnail_version.doctree and b/.doctrees/cookbook/examples/basic_upload_thumbnail_version.doctree differ
diff --git a/.doctrees/cookbook/examples/svn_integration.doctree b/.doctrees/cookbook/examples/svn_integration.doctree
index a8a7847fa..cb6d8c851 100644
Binary files a/.doctrees/cookbook/examples/svn_integration.doctree and b/.doctrees/cookbook/examples/svn_integration.doctree differ
diff --git a/.doctrees/cookbook/smart_cut_fields.doctree b/.doctrees/cookbook/smart_cut_fields.doctree
index d5ecaadd8..eb85cecd1 100644
Binary files a/.doctrees/cookbook/smart_cut_fields.doctree and b/.doctrees/cookbook/smart_cut_fields.doctree differ
diff --git a/.doctrees/cookbook/tasks.doctree b/.doctrees/cookbook/tasks.doctree
index abe1c895d..964a51e6c 100644
Binary files a/.doctrees/cookbook/tasks.doctree and b/.doctrees/cookbook/tasks.doctree differ
diff --git a/.doctrees/cookbook/tasks/split_tasks.doctree b/.doctrees/cookbook/tasks/split_tasks.doctree
index d1a4b5131..c5e8d02e4 100644
Binary files a/.doctrees/cookbook/tasks/split_tasks.doctree and b/.doctrees/cookbook/tasks/split_tasks.doctree differ
diff --git a/.doctrees/cookbook/tasks/task_dependencies.doctree b/.doctrees/cookbook/tasks/task_dependencies.doctree
index 02db4f6ee..2847ea2eb 100644
Binary files a/.doctrees/cookbook/tasks/task_dependencies.doctree and b/.doctrees/cookbook/tasks/task_dependencies.doctree differ
diff --git a/.doctrees/cookbook/tasks/updating_tasks.doctree b/.doctrees/cookbook/tasks/updating_tasks.doctree
index a33d8eb57..a9e881df7 100644
Binary files a/.doctrees/cookbook/tasks/updating_tasks.doctree and b/.doctrees/cookbook/tasks/updating_tasks.doctree differ
diff --git a/.doctrees/cookbook/tutorials.doctree b/.doctrees/cookbook/tutorials.doctree
index 3edecd01b..e3a8052cb 100644
Binary files a/.doctrees/cookbook/tutorials.doctree and b/.doctrees/cookbook/tutorials.doctree differ
diff --git a/.doctrees/cookbook/usage_tips.doctree b/.doctrees/cookbook/usage_tips.doctree
index bef7e91ee..b7754448f 100644
Binary files a/.doctrees/cookbook/usage_tips.doctree and b/.doctrees/cookbook/usage_tips.doctree differ
diff --git a/.doctrees/data_types.doctree b/.doctrees/data_types.doctree
deleted file mode 100644
index 8e49e9cc8..000000000
Binary files a/.doctrees/data_types.doctree and /dev/null differ
diff --git a/.doctrees/environment.pickle b/.doctrees/environment.pickle
index 48effe4a5..b7f706318 100644
Binary files a/.doctrees/environment.pickle and b/.doctrees/environment.pickle differ
diff --git a/.doctrees/event_types.doctree b/.doctrees/event_types.doctree
deleted file mode 100644
index 10d1fef92..000000000
Binary files a/.doctrees/event_types.doctree and /dev/null differ
diff --git a/.doctrees/examples/ami_handler.doctree b/.doctrees/examples/ami_handler.doctree
deleted file mode 100644
index 52a262763..000000000
Binary files a/.doctrees/examples/ami_handler.doctree and /dev/null differ
diff --git a/.doctrees/examples/ami_version_packager.doctree b/.doctrees/examples/ami_version_packager.doctree
deleted file mode 100644
index c9993eff3..000000000
Binary files a/.doctrees/examples/ami_version_packager.doctree and /dev/null differ
diff --git a/.doctrees/examples/basic_create_shot.doctree b/.doctrees/examples/basic_create_shot.doctree
deleted file mode 100644
index 4356c4d09..000000000
Binary files a/.doctrees/examples/basic_create_shot.doctree and /dev/null differ
diff --git a/.doctrees/examples/basic_create_shot_task_template.doctree b/.doctrees/examples/basic_create_shot_task_template.doctree
deleted file mode 100644
index 8b1eb7555..000000000
Binary files a/.doctrees/examples/basic_create_shot_task_template.doctree and /dev/null differ
diff --git a/.doctrees/examples/basic_create_version_link_shot.doctree b/.doctrees/examples/basic_create_version_link_shot.doctree
deleted file mode 100644
index d3f5aa815..000000000
Binary files a/.doctrees/examples/basic_create_version_link_shot.doctree and /dev/null differ
diff --git a/.doctrees/examples/basic_delete_shot.doctree b/.doctrees/examples/basic_delete_shot.doctree
deleted file mode 100644
index 20daa46af..000000000
Binary files a/.doctrees/examples/basic_delete_shot.doctree and /dev/null differ
diff --git a/.doctrees/examples/basic_find_shot.doctree b/.doctrees/examples/basic_find_shot.doctree
deleted file mode 100644
index 75b089848..000000000
Binary files a/.doctrees/examples/basic_find_shot.doctree and /dev/null differ
diff --git a/.doctrees/examples/basic_sg_instance.doctree b/.doctrees/examples/basic_sg_instance.doctree
deleted file mode 100644
index 57a32e0ed..000000000
Binary files a/.doctrees/examples/basic_sg_instance.doctree and /dev/null differ
diff --git a/.doctrees/examples/basic_update_shot.doctree b/.doctrees/examples/basic_update_shot.doctree
deleted file mode 100644
index 12d29acb3..000000000
Binary files a/.doctrees/examples/basic_update_shot.doctree and /dev/null differ
diff --git a/.doctrees/examples/basic_upload_thumbnail_version.doctree b/.doctrees/examples/basic_upload_thumbnail_version.doctree
deleted file mode 100644
index cf24a75f9..000000000
Binary files a/.doctrees/examples/basic_upload_thumbnail_version.doctree and /dev/null differ
diff --git a/.doctrees/examples/svn_integration.doctree b/.doctrees/examples/svn_integration.doctree
deleted file mode 100644
index 041e582aa..000000000
Binary files a/.doctrees/examples/svn_integration.doctree and /dev/null differ
diff --git a/.doctrees/exceptions.doctree b/.doctrees/exceptions.doctree
deleted file mode 100644
index 7a2e67c23..000000000
Binary files a/.doctrees/exceptions.doctree and /dev/null differ
diff --git a/.doctrees/filter_syntax.doctree b/.doctrees/filter_syntax.doctree
deleted file mode 100644
index 910608f0c..000000000
Binary files a/.doctrees/filter_syntax.doctree and /dev/null differ
diff --git a/.doctrees/getting_started.doctree b/.doctrees/getting_started.doctree
deleted file mode 100644
index a52228ab3..000000000
Binary files a/.doctrees/getting_started.doctree and /dev/null differ
diff --git a/.doctrees/index.doctree b/.doctrees/index.doctree
index 762451bba..fcf1edc26 100644
Binary files a/.doctrees/index.doctree and b/.doctrees/index.doctree differ
diff --git a/.doctrees/installation.doctree b/.doctrees/installation.doctree
index 1d4b2c497..b4f459933 100644
Binary files a/.doctrees/installation.doctree and b/.doctrees/installation.doctree differ
diff --git a/.doctrees/local_files.doctree b/.doctrees/local_files.doctree
deleted file mode 100644
index 07cfd6ceb..000000000
Binary files a/.doctrees/local_files.doctree and /dev/null differ
diff --git a/.doctrees/packaging.doctree b/.doctrees/packaging.doctree
deleted file mode 100644
index 4aaf8c2ff..000000000
Binary files a/.doctrees/packaging.doctree and /dev/null differ
diff --git a/.doctrees/reference.doctree b/.doctrees/reference.doctree
index 86e7e7e70..a4e8b7290 100644
Binary files a/.doctrees/reference.doctree and b/.doctrees/reference.doctree differ
diff --git a/.doctrees/server_changelog.doctree b/.doctrees/server_changelog.doctree
deleted file mode 100644
index 6617a9d97..000000000
Binary files a/.doctrees/server_changelog.doctree and /dev/null differ
diff --git a/.doctrees/smart_cut_fields.doctree b/.doctrees/smart_cut_fields.doctree
deleted file mode 100644
index bcb7264a5..000000000
Binary files a/.doctrees/smart_cut_fields.doctree and /dev/null differ
diff --git a/.doctrees/tasks.doctree b/.doctrees/tasks.doctree
deleted file mode 100644
index 51381ef83..000000000
Binary files a/.doctrees/tasks.doctree and /dev/null differ
diff --git a/.doctrees/tasks/split_tasks.doctree b/.doctrees/tasks/split_tasks.doctree
deleted file mode 100644
index 23647c2f7..000000000
Binary files a/.doctrees/tasks/split_tasks.doctree and /dev/null differ
diff --git a/.doctrees/tasks/task_dependencies.doctree b/.doctrees/tasks/task_dependencies.doctree
deleted file mode 100644
index 5c79e621d..000000000
Binary files a/.doctrees/tasks/task_dependencies.doctree and /dev/null differ
diff --git a/.doctrees/tasks/updating_tasks.doctree b/.doctrees/tasks/updating_tasks.doctree
deleted file mode 100644
index 35139b126..000000000
Binary files a/.doctrees/tasks/updating_tasks.doctree and /dev/null differ
diff --git a/.doctrees/tutorials.doctree b/.doctrees/tutorials.doctree
deleted file mode 100644
index a7b173461..000000000
Binary files a/.doctrees/tutorials.doctree and /dev/null differ
diff --git a/.doctrees/usage_tips.doctree b/.doctrees/usage_tips.doctree
deleted file mode 100644
index 476ed8760..000000000
Binary files a/.doctrees/usage_tips.doctree and /dev/null differ
diff --git a/_sources/advanced.txt b/_sources/advanced.txt
deleted file mode 100644
index 4c7e4a2bf..000000000
--- a/_sources/advanced.txt
+++ /dev/null
@@ -1,16 +0,0 @@
-.. _advanced_topics:
-
-###############
-Advanced Topics
-###############
-
-Below are some more advanced topics regarding usage of the Python API. If you would like to see
-something that's missing here, please feel free to contact support at support@shotgunsoftware.com
-with your suggestions and we'll get it added!
-
-.. toctree::
- :maxdepth: 1
-
- advanced/packaging
- advanced/iron_python
- changelog
diff --git a/_sources/advanced/iron_python.txt b/_sources/advanced/iron_python.txt
deleted file mode 100644
index 6aac0a6a9..000000000
--- a/_sources/advanced/iron_python.txt
+++ /dev/null
@@ -1,37 +0,0 @@
-**********
-IronPython
-**********
-
-We do not test against IronPython and cannot be sure that we won't introduce breaking changes or
-that we will be compatible with future releases of IronPython. While we don't officially support
-IronPython, we certainly will do our best to figure out any issues that come up while using it and
-how to avoid them.
-
-As of July 9, 2015 you can look at this fork of the repo to see what changes were needed as of that
-date to make things work. The original fork was as of v3.0.20 of the API. Big thanks to our awesome
-clients Pixomondo for making their work public and letting us refer to it:
-
-https://github.com/Pixomondo/python-api/tree/v3.0.20.ipy
-
-v3.0.20 can be used with IronPython with a little bit of added work:
-
-- The Python API uses the zlib module to handle decompressing the gzipped response from the server.
- There's no built-in zlib module in IronPython, but there's a potential solution from Jeff Hardy at
- https://bitbucket.org/jdhardy/ironpythonzlib/src/. And the blog post about it here
- http://blog.jdhardy.ca/2008/12/solving-zlib-problem-ironpythonzlib.html
-
-- If you encounter any SSL errors like
- ``unknown field: SERIALNUMBER=0123456789`` or ``:SSL3_GET_SERVER_CERTIFICATE:certificate verify failed``.
- For now you can workaround this problem by disabling ssl certificate validation which we've
- encountered some intermittent issues with. Set ``NO_SSL_VALIDATION = True`` for either case.
- See :const:`shotgun_api3.shotgun.NO_SSL_VALIDATION`
-
-- If you encounter ``LookupError: unknown encoding: idna``, you can force utf-8 by changing
- iri2uri.py ~ln 71 from ``authority = authority.encode('idna')`` to
- ``authority = authority.encode('utf-8')``
-
-- If you encounter an SSL error such as ``SSL3_READ_BYTES:sslv3 alert handshake failure``, then the
- lower level SSL library backing python's network infrastructure is attempting to connect to our
- servers via SSLv3, which is no longer supported. You can use the code from this gist to force the
- SSL connections to use a specific protocol. The forked repo linked above has an example of how to
- do that to force the use of TLSv1.
\ No newline at end of file
diff --git a/_sources/advanced/packaging.txt b/_sources/advanced/packaging.txt
deleted file mode 100644
index a09e159ad..000000000
--- a/_sources/advanced/packaging.txt
+++ /dev/null
@@ -1,40 +0,0 @@
-.. _packaging:
-
-################################################
-Packaging an application with py2app (or py2exe)
-################################################
-
-You can create standalone applications with Python scripts by using
-`py2app `_ on OS X or `py2exe `_ on
-Windows. This is often done to more easily distribute applications that have a GUI based on
-toolkits like Tk, Qt or others.
-
-There are caveats you need to be aware of when creating such an app.
-
-********************************
-HTTPS Validation and cacerts.txt
-********************************
-When creating the connection to Shotgun a file is used to validate the Shotgun certificate. This
-file is located at ``shotgun_api3/lib/httplib2/cacerts.txt``. Because this file is not a Python
-file imported by your application, py2app will not know to include it in your package, it will
-need to be explicitly specified in your ``setup.py`` file (edit the path based on the location
-where your ``shotgun_api3`` package is located)::
-
- DATA_FILES = [
- ('shotgun_api3', ['/shotgun/src/python-api/shotgun_api3/lib/httplib2/cacerts.txt'])
- ]
-
-Once you create your py2app package its contents should include two files (among others) in the
-following structure::
-
- ./Contents/Resources/shotgun_api3/cacerts.txt
- ./Contents/Resources/my_script.py
-
-Where in ``my_script.py`` you can access the ``cacerts.txt`` file using a relative path to pass it
-into the Shotgun connection's constructor::
-
- ca_certs = os.path.join(os.path.dirname(__file__), 'shotgun_api3', 'cacerts.txt')
- sg = shotgun_api3.Shotgun('https://yoursite.shotgunstudio.com', 'script_name', 'script_key',
- ca_certs=ca_certs)
-
-The process for py2exe should be similar.
\ No newline at end of file
diff --git a/_sources/attachments.txt b/_sources/attachments.txt
deleted file mode 100644
index aa7881961..000000000
--- a/_sources/attachments.txt
+++ /dev/null
@@ -1,177 +0,0 @@
-.. _attachments:
-
-##################
-Working With Files
-##################
-
-The Shotgun web application stores Files as Attachment entities. You can see these on a Files page,
-or a Files tab on a detail page, for example. You can access Attachments via the API to create and
-modify uploaded files, url links, and local files, and link them to other entities (Shots,
-Versions, etc). This entity works a lot like other entity types within Shotgun with a few
-exceptions which are detailed below.
-
-.. note::
- If you are simply looking for information about how to upload and link things in Shotgun, this
- doc is not for you. Instead look at the :meth:`~shotgun_api3.Shotgun.upload` and
- :meth:`~shotgun_api3.Shotgun.upload_thumbnail` methods.
-
- This doc describes the detailed structure of the Attachment entities that represent files
- in Shotgun and how to interact with them. If that sounds cool too, then read on!
-
-.. versionadded:: 3.0.3
- Requires Shotgun Server v2.2.0+
-
-*****************
-Default structure
-*****************
-The following is a list of the default fields that Shotgun creates for Attachments. Your server
-instance may look slightly different depending on your own customizations. Many of these fields are
-optional and some are automatically filled in. These exceptions are listed below in the
-descriptions of each field.
-
-- **description** (:obj:`str`):
- Optional field to provide descriptive text about the file.
-
-- **this_file** (:obj:`dict`):
- The actual file reference. Within the dictionary is a ``link_type`` key which designates the
- Attachment as an uploaded file, a url link, or a local file. There are additional keys
- returned for :ref:`local_files`. You cannot modify this field after you have created an
- Attachment. See below for examples of this field.
-
-- **filename** (:obj:`str`):
- For uploaded files only. This is automatically assigned when the file is uploaded and stores
- the filename of the file.
-
-- **file_size** (:obj:`int`):
- For uploaded files only. This is automatically assigned when the file is uploaded and stores
- the size of the file in bytes.
-
-- **id** (:obj:`int`):
- The internal Shotgun id for this Attachment entity.
-
-- **attachment_links** (:obj:`list`):
- A list of entity dictionaries used for linking Attachments to multiple entities.
-
-- **open_notes** (:obj:`list`):
- A List of Note entities linked to the current Attachment that have a status that does not
- equal 'clsd'. *Read-only*
-
-- **open_notes_count** (:obj:`int`):
- An integer count of the list of Note entities linked to the current Attachment that have a
- status that does not equal 'clsd'. *(Read-only)*
-
-- **project** (:obj:`dict`):
- *(Required)* The Project entity that this Attachment belongs to. This must be assigned when
- creating an Attachment.
-
-- **attachment_reference_links** (:obj:`list`):
- Similar to ``attachment_links`` but used specifically for linking files to multiple entities as
- reference.
-
-- **sg_status_list** (:obj:`str`):
- Status value returned as the short code.
-
-- **tag_list** (:obj:`list`):
- List of tags (as strings) that are currently assigned to the Attachment.
-
-- **image** (:obj:`str`):
- The url location of the thumbnail image assigned to this Attachment. For uploads, Shotgun
- automatically tries to create a thumbnail from the file. Alternatively, you can assign your
- own thumbnail to an Attachment using the :meth:`~shotgun_api3.Shotgun.upload_thumbnail` method.
-
-- **sg_type** (:obj:`str`):
- An optional field for designating different types of Attachments
-
-
-File type structures (``this_file``)
-====================================
-
-Depending on the type of file the Attachment entity is representing, the value of ``this_file``
-will vary.
-
-- **Uploads**
- Designated by ``link_type: 'upload'``, this represents a file that was uploaded to Shotgun.
- Uploading files to Shotgun can be done using the :meth:`~shotgun_api3.Shotgun.upload` method.
- You cannot create an Attachment with an uploaded file directly.
-
- ::
-
- {'content_type': 'image/jpeg',
- 'link_type': 'upload',
- 'name': 'western1FULL.jpg',
- 'url': 'https://superdeathcarracer.shotgunstudio.com/file_serve/attachment/538'}
-
-- **Web links**
- Designated by ``link_type: 'web'``, this is represents a url link. Examples include an
- ``http://`` link to another server or a custom protocol used to launch a local application
- like ``rvlink://`` or ``cinesync://``
- ::
-
- {'content_type': None,
- 'link_type': 'web',
- 'name': 'Join GUN12158',
- 'url': 'cinesync://session/GUN12158'}
-
-- **Local Files**
- Designated by ``link_type: 'local'``, this is represents a local file link. Additional keys
- are provided in order to give access to the relative path information on other platforms.
-
- .. seealso:: :ref:`local_files`
-
- ::
-
- { 'content_type': 'video/quicktime',
- 'link_type': 'local',
- 'name': 'my_test_movie.mov',
- 'local_path': '/Users/kp/Movies/testing/test_movie_002.mov'
- 'local_path_linux': '/home/users/macusers/kp/Movies/testing/test_movie_002.mov'
- 'local_path_mac': '/Users/kp/Movies/testing/test_movie_002.mov'
- 'local_path_windows': 'M:\\macusers\kp\Movies\testing\test_movie_002.mov'
- 'local_storage': {'id': 1,
- 'name': 'Dailies Directories',
- 'type': 'LocalStorage'},
- 'url': 'file:///Users/kp/Movies/testing/test_movie_002.mov'}
-
-
-********************
-Creating Attachments
-********************
-
-Web Links
-=========
-::
-
- myurl = {
- 'url': 'http://apple.com/itunes',
- 'name': 'Apple: iTunes'
- }
- data = {
- 'this_file': myurl,
- 'project': {'type':'Project','id':64}
- }
- result = sg.create('Attachment', data)
-
-
-Uploads
-=======
-Uploads cannot be created directly on Attachments. Instead, you need to use the
-:meth:`~shotgun_api3.Shotgun.upload` method.
-
-Local Files
-===========
-See :ref:`creating_local_files`.
-
-********************
-Updating Attachments
-********************
-You cannot modify the ``this_file`` field after you create an Attachment. If you need to provide a
-different file, you will have to create a new Attachment entity. Otherwise, the process for
-updating Attachments is exactly like updating other entity types in Shotgun and is the same for all
-Attachment types. See :meth:`~shotgun_api3.Shotgun.update` for more info.
-
-
-********************
-Deleting Attachments
-********************
-The process of deleting an Attachment is just like other entities in Shotgun. See
-:meth:`~shotgun_api3.Shotgun.delete` for more info.
diff --git a/_sources/authentication.txt b/_sources/authentication.txt
deleted file mode 100644
index 7708ad026..000000000
--- a/_sources/authentication.txt
+++ /dev/null
@@ -1,65 +0,0 @@
-##############
-Authentication
-##############
-
-In order to communicate with your Shotgun server via the API, you must provide valid authentication credentials. The API allows you to authenticate with user-based, or script-based credentials.
-
-*************************
-User-based Authentication
-*************************
-When authenticating as a user, you provide your normal login and password when instantiating your :class:`shotgun_api3.Shotgun` object. The actions performed by this instance will be limited to your permission level just as they are in the Shotgun web application. ::
-
- sg = shotgun_api3.Shotgun("https://piedpiper.shotgunstudio.com",
- login="rhendriks",
- password="c0mPre$Hi0n")
-
-
-***************************
-Script-based Authentication
-***************************
-In order to authenticate as a script, your script must be :ref:`registered with Shotgun and have a valid API key `. When creating your :class:`shotgun_api3.Shotgun` object, provide the ``script_name`` and ``api_key``.::
-
- sg = shotgun_api3.Shotgun("https://piedpiper.shotgunstudio.com",
- script_name="compress",
- api_key="0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef")
-
-.. note:: When using script-based authentication, we **strongly** recommend you register each script separately with Shotgun and have individual API keys for each. This allows you to track down each of your scripts and the actions they are performing much more accurately in the event logs.
-
-
-.. _setting_up_shotgun:
-
-Adding Script Users
-===================
-If you'll be using script-based authentication, you need to create a Script entity in Shotgun. To create a new key, click the + button on the "Scripts" page in the Admin section and give your script a useful name. It's a good idea to add any other relevant information that be be helpful to your other friendly Shotgun users such as a description of what the script does that is using this key, the email address of the maintainer, etc.:
-
-.. image:: images/scripts_page.png
-
-Once you save your new Script entity, Shotgun will automatically generate an application key which will act as the script's password. The key will look something like this: ``0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef``.
-
-Why have different application keys for different scripts?
-==========================================================
-We recommend you create a new Script entity (and application key) for each script that is using script-based authentication so you can accurately log what scripts are doing what in case one of them causes problems. This will also allow you to better see what scripts are performing what actions in the EventLog. We've found that even though you may *think* you'll probably never need to know, the extra 2 minutes of setup now can prevent hours of headache in the future.
-
-Event Logging
-=============
-By default, events generated by scripts using an script-based authentication are logged in Shotgun's event log. You can turn this off by un-checking the "Generate Events" checkbox either in the script detail page or from the main Scripts admin page in Shotgun.
-
-.. note:: Turning off event logging will also prevent any email notifications from being triggered by your scripts since the email notifier relies on the event log to find events to notify for.
-
-Scripts using user-based authentication will generate events similarly to if you were performing the same actions in the Shotgun web application, though there is some additional metadata stored in the ``EventLogEntry`` that identifies the event as created from a script acting on behalf of the user.
-
-Why would you want to turn event logging off for scripts?
----------------------------------------------------------
-It is an optimization that is not used often, but some users have integration scripts that are pushing data into Shotgun just for reference, like publishes from their asset management system. This publish data is never changed later, so the data itself has the entire history, and the events would just clutter the event log. The event log can grow very large. So if you have no need to audit the history of what your script does, and it's generating an large amount of event log entries, you may find it's not necessary to create these events.
-
-***********
-Permissions
-***********
-Users and scripts are both bound by the restrictions of their permission role in Shotgun. The permission role is assigned by the **Permission Role** field for each entity type.
-
-For Scripts, the default permission role is "API Admin User" which allows full access to create, update, and delete entities and fields, including editing the "date created" audit field and creating event log entries. If you have other permission roles for ApiUsers, you can set the default role that will be assigned when a new script is created, in your Shotgun site preferences.
-
-When using user-based authentication in your script, it will be bound by the permission role assigned to you in Shotgun. For example, if you don't have access to edit the status field on Shots, your script won't be able to either. Attempting to perform actions that are prohibited by permissions will raise an appropriate exception.
-
-.. seealso:: `Shotgun Support: Permissions `_
-
diff --git a/_sources/changelog.txt b/_sources/changelog.txt
deleted file mode 100644
index f07fa1f9c..000000000
--- a/_sources/changelog.txt
+++ /dev/null
@@ -1,3 +0,0 @@
-.. currentmodule:: shotgun_api3.shotgun.Shotgun
-
-.. include:: ../HISTORY.rst
\ No newline at end of file
diff --git a/_sources/cookbook.txt b/_sources/cookbook.txt
deleted file mode 100644
index 5c4c1be78..000000000
--- a/_sources/cookbook.txt
+++ /dev/null
@@ -1,62 +0,0 @@
-************
-API Cookbook
-************
-
-Here we have a collection of useful information you can use for reference when writing your API
-scripts. From usage tips and gotchas to deeper examples of working with entities like Tasks and
-Files, there's a lot of example code in here for you to play with.
-
-.. rubric:: Usage Tips
-
-These are some best-practices and good guidelines to follow when developing your scripts.
-You'll also find some gotchas you can avoid.
-
-.. toctree::
- :maxdepth: 2
-
- cookbook/usage_tips
-
-.. rubric:: Examples
-
-Some basic example scripts that we walk you through from beginning to end. Feel free to copy
-and paste any of these into your own scripts.
-
-.. toctree::
- :maxdepth: 3
-
- cookbook/tutorials
-
-.. rubric:: Working With Files
-
-You'll probably be doing some work with files at your studio. This is a deep dive into some of
-the inners of how Shotgun handles files (also called Attachments) and the different ways to link
-to them.
-
-.. toctree::
- :maxdepth: 2
-
- cookbook/attachments
-
-.. rubric:: Working With Tasks
-
-Scheduling is a complex beast. Shotgun can handle lots of different types of functionality around
-scheduling like split tasks, dependencies, and more. These docs walk you through the details of
-how Shotgun thinks when it's handling Task changes and how you can make your scripts do what you
-need to do.
-
-.. toctree::
- :maxdepth: 2
-
- cookbook/tasks
-
-.. rubric:: Smart Cut Fields
-
-Smart Cut Fields are deprecated in favor of the
-`new cut support added in Shotgun v7.0 `_.
-This documentation remains only to support studios who may not have upgraded to the new cut support
-features.
-
-.. toctree::
- :maxdepth: 2
-
- cookbook/smart_cut_fields
\ No newline at end of file
diff --git a/_sources/cookbook/attachments.txt b/_sources/cookbook/attachments.txt
deleted file mode 100644
index 5988e9041..000000000
--- a/_sources/cookbook/attachments.txt
+++ /dev/null
@@ -1,325 +0,0 @@
-.. _attachments:
-
-################################
-Details About Working With Files
-################################
-
-The Shotgun web application stores Files as Attachment entities. You can see these on a Files page,
-or a Files tab on a detail page, for example. You can access Attachments via the API to create and
-modify uploaded files, url links, and local files, and link them to other entities (Shots,
-Versions, etc). This entity works a lot like other entity types within Shotgun with a few
-exceptions which are detailed below.
-
-.. note::
- If you are simply looking for information about how to upload and link things in Shotgun, this
- doc is not for you. Instead look at the :meth:`~shotgun_api3.Shotgun.upload` and
- :meth:`~shotgun_api3.Shotgun.upload_thumbnail` methods.
-
- This doc describes the detailed structure of the Attachment entities that represent files
- in Shotgun and how to interact with them. If that sounds cool too, then read on!
-
-.. versionadded:: 3.0.3
- Requires Shotgun Server v2.2.0+
-
-*****************
-Default structure
-*****************
-The following is a list of the default fields that Shotgun creates for Attachments. Your server
-instance may look slightly different depending on your own customizations. Many of these fields are
-optional and some are automatically filled in. These exceptions are listed below in the
-descriptions of each field.
-
-- **description** (:obj:`str`):
- Optional field to provide descriptive text about the file.
-
-- **this_file** (:obj:`dict`):
- The actual file reference. Within the dictionary is a ``link_type`` key which designates the
- Attachment as an uploaded file, a url link, or a local file. There are additional keys
- returned for :ref:`local_files`. You cannot modify this field after you have created an
- Attachment. See below for examples of this field.
-
-- **filename** (:obj:`str`):
- For uploaded files only. This is automatically assigned when the file is uploaded and stores
- the filename of the file.
-
-- **file_size** (:obj:`int`):
- For uploaded files only. This is automatically assigned when the file is uploaded and stores
- the size of the file in bytes.
-
-- **id** (:obj:`int`):
- The internal Shotgun id for this Attachment entity.
-
-- **attachment_links** (:obj:`list`):
- A list of entity dictionaries used for linking Attachments to multiple entities.
-
-- **open_notes** (:obj:`list`):
- A List of Note entities linked to the current Attachment that have a status that does not
- equal 'clsd'. *Read-only*
-
-- **open_notes_count** (:obj:`int`):
- An integer count of the list of Note entities linked to the current Attachment that have a
- status that does not equal 'clsd'. *(Read-only)*
-
-- **project** (:obj:`dict`):
- *(Required)* The Project entity that this Attachment belongs to. This must be assigned when
- creating an Attachment.
-
-- **attachment_reference_links** (:obj:`list`):
- Similar to ``attachment_links`` but used specifically for linking files to multiple entities as
- reference.
-
-- **sg_status_list** (:obj:`str`):
- Status value returned as the short code.
-
-- **tag_list** (:obj:`list`):
- List of tags (as strings) that are currently assigned to the Attachment.
-
-- **image** (:obj:`str`):
- The url location of the thumbnail image assigned to this Attachment. For uploads, Shotgun
- automatically tries to create a thumbnail from the file. Alternatively, you can assign your
- own thumbnail to an Attachment using the :meth:`~shotgun_api3.Shotgun.upload_thumbnail` method.
-
-- **sg_type** (:obj:`str`):
- An optional field for designating different types of Attachments
-
-
-File type structures (``this_file``)
-====================================
-
-Depending on the type of file the Attachment entity is representing, the value of ``this_file``
-will vary.
-
-- **Uploads**
- Designated by ``link_type: 'upload'``, this represents a file that was uploaded to Shotgun.
- Uploading files to Shotgun can be done using the :meth:`~shotgun_api3.Shotgun.upload` method.
- You cannot create an Attachment with an uploaded file directly.
-
- ::
-
- {'content_type': 'image/jpeg',
- 'link_type': 'upload',
- 'name': 'western1FULL.jpg',
- 'url': 'https://superdeathcarracer.shotgunstudio.com/file_serve/attachment/538'}
-
-- **Web links**
- Designated by ``link_type: 'web'``, this is represents a url link. Examples include an
- ``http://`` link to another server or a custom protocol used to launch a local application
- like ``rvlink://`` or ``cinesync://``
- ::
-
- {'content_type': None,
- 'link_type': 'web',
- 'name': 'Join GUN12158',
- 'url': 'cinesync://session/GUN12158'}
-
-- **Local Files**
- Designated by ``link_type: 'local'``, this is represents a local file link. Additional keys
- are provided in order to give access to the relative path information on other platforms.
-
- .. seealso:: :ref:`local_files`
-
- ::
-
- { 'content_type': 'video/quicktime',
- 'link_type': 'local',
- 'name': 'my_test_movie.mov',
- 'local_path': '/Users/kp/Movies/testing/test_movie_002.mov'
- 'local_path_linux': '/home/users/macusers/kp/Movies/testing/test_movie_002.mov'
- 'local_path_mac': '/Users/kp/Movies/testing/test_movie_002.mov'
- 'local_path_windows': 'M:\\macusers\kp\Movies\testing\test_movie_002.mov'
- 'local_storage': {'id': 1,
- 'name': 'Dailies Directories',
- 'type': 'LocalStorage'},
- 'url': 'file:///Users/kp/Movies/testing/test_movie_002.mov'}
-
-
-********************
-Creating Attachments
-********************
-
-Web Links
-=========
-::
-
- myurl = {
- 'url': 'http://apple.com/itunes',
- 'name': 'Apple: iTunes'
- }
- data = {
- 'this_file': myurl,
- 'project': {'type':'Project','id':64}
- }
- result = sg.create('Attachment', data)
-
-
-Uploads
-=======
-Uploads cannot be created directly on Attachments. Instead, you need to use the
-:meth:`~shotgun_api3.Shotgun.upload` method.
-
-Local Files
-===========
-See :ref:`creating_local_files`.
-
-********************
-Updating Attachments
-********************
-You cannot modify the ``this_file`` field after you create an Attachment. If you need to provide a
-different file, you will have to create a new Attachment entity. Otherwise, the process for
-updating Attachments is exactly like updating other entity types in Shotgun and is the same for all
-Attachment types. See :meth:`~shotgun_api3.Shotgun.update` for more info.
-
-
-********************
-Deleting Attachments
-********************
-The process of deleting an Attachment is just like other entities in Shotgun. See
-:meth:`~shotgun_api3.Shotgun.delete` for more info.
-
-.. _local_files:
-
-*****************************
-Working With Local File Types
-*****************************
-
-We added support for linking to local files in the UI in Shotgun Server v2.1. This doc covers how
-to work with these local file links using the API.
-
-Requirements
-============
-
-- Python API v3.0.3+
-- Shotgun Server v2.1.10+
-
-Structure of Local File Values
-==============================
-
-There is a key in the dictionary that represents file/link fields called ``link_type`` which can be
-one of ``local``, ``upload``, ``web``. This is used to determine what type of link the field value
-contains. For local files this value is always ``local`` and there are additional keys that
-are available:
-
-- **content_type** (:obj:`str`):
- The mime-type of the associated local file. This is assigned
- automatically using a best-guess based on the file extension. You can override this by setting
- this explicitly.
-
-- **link_type** (:obj:`str`) *read-only*:
- Always 'local' for local files.
-
-- **name** (:obj:`str`):
- the display name of the local file. This is set to the filename by
- default but can be overridden by setting this explicitly.
-
-- **local_path** (:obj:`str`):
- The full path to the file on the current platform. The Python API tries to determine the
- platform it is currently running on and then copies the value from the corresponding key above
- to this field for convenience.
-
-- **local_path_linux** (:obj:`str`) *read-only*:
- Full path to file on Linux as defined by the LocalStorage (or ``None`` if no Linux path is set)
-
-- **local_path_mac** (:obj:`str`) *read-only*:
- Full path to file on Mac OS X as defined by the LocalStorage (or ``None`` if no Mac path is set)
-
-- **local_path_windows** (:obj:`str`) *read-only*:
- Full path to file on Windows as defined by the LocalStorage (or ``None`` if no Windows path
- is set)
-
-- **local_storage** (:obj:`dict`) *read-only*:
- A dictionary representing which LocalStorage entity is applied for this local file link.
-
-- **url** (:obj:`str`) *read-only*:
- A file:// link provided for convenience pointing to the value in the ``local_path``
-
-Reading Local File Fields
-=========================
-
-::
-
- fields = ['sg_uploaded_movie']
- result = sg.find('Version', [['id', 'is', 123]], fields)
-
-Returns::
-
- {'id':123,
- 'sg_uploaded_movie': { 'content_type': None,
- 'link_type': 'local',
- 'name': 'my_test_movie.mov',
- 'local_path': '/Users/kp/Movies/testing/test_movie_001_.mov'
- 'local_path_linux': '/home/users/macusers/kp/Movies/testing/test_movie_001_.mov'
- 'local_path_mac': '/Users/kp/Movies/testing/test_movie_001_.mov'
- 'local_path_windows': 'M:\\macusers\kp\Movies\testing\test_movie_001_.mov'
- 'local_storage': {'id': 1,
- 'name': 'Dailies Directories',
- 'type': 'LocalStorage'},
- 'url': 'file:///Users/kp/Movies/testing/test_movie_001_.mov'},
- 'type': 'Version'}
-
-.. note::
- When viewing results that include file/link fields with local file link values, all of the
- keys will be returned regardless of whether there are values in them. So in the above example,
- if there was no Windows path set for the local storage, ``local_path_windows`` would be
- ``None``.
-
-.. _creating_local_files:
-
-Creating & Updating Local file Fields
-=====================================
-
-When setting a file/link field value to a local file, only the ``local_path`` is mandatory. Shotgun
-will automatically select the appropriate matching local storage for your file based on the path.
-You can optionally specify the ``name`` and ``content_type`` fields if you wish to override their
-defaults. Any other keys that are provided will be ignored.
-
-* **content_type** :obj:`str`:
- Optionally set the mime-type of the associated local file. This is assigned automatically
- using a best-guess based on the file extension.
-
-
-* **name** :obj:`str`:
- Optional display name of the local file. This is set to the filename by default.
-
-* **local_path** :obj:`str`:
- The full local path to the file. Shotgun will find the LocalStorage
- that has the most specific match to this path and automatically assign that LocalStorage to
- the file.
-
-::
-
- data = {'sg_uploaded_movie': {'local_path': '/Users/kp/Movies/testing/test_movie_002.mov',
- 'name': 'Better Movie'}
- result = sg.update('Version', 123, data)
-
-Returns::
-
- {'id':123,
- 'sg_uploaded_movie': { 'content_type': 'video/quicktime',
- 'link_type': 'local',
- 'name': 'my_test_movie.mov',
- 'local_path': '/Users/kp/Movies/testing/test_movie_002.mov'
- 'local_path_linux': '/home/users/macusers/kp/Movies/testing/test_movie_002.mov'
- 'local_path_mac': '/Users/kp/Movies/testing/test_movie_002.mov'
- 'local_path_windows': 'M:\\macusers\kp\Movies\testing\test_movie_002.mov'
- 'local_storage': {'id': 1,
- 'name': 'Dailies Directories',
- 'type': 'LocalStorage'},
- 'url': 'file:///Users/kp/Movies/testing/test_movie_002.mov'},
- 'type': 'Version'}]
-
-The ``content_type`` was assigned a best-guess value based on the file extension. Shotgun selected
-the most appropriate specific LocalStorage match and assigned it to local_storage automatically.
-
-Un-setting local file field values
-==================================
-
-Removing a a local file field value is simple. Just set the value to ``None``::
-
- data = {'sg_uploaded_movie': None}
- result = sg.update('Version', 123, data)
-
-Returns::
-
- {'id':123,
- 'sg_uploaded_movie': None,
- 'type': 'Version'}]
diff --git a/_sources/cookbook/examples/ami_handler.txt b/_sources/cookbook/examples/ami_handler.txt
deleted file mode 100644
index d4b88f006..000000000
--- a/_sources/cookbook/examples/ami_handler.txt
+++ /dev/null
@@ -1,246 +0,0 @@
-.. _ami_handler:
-
-###############################
-Handling Action Menu Item Calls
-###############################
-
-This is an example ActionMenu Python class to handle the ``GET`` request sent from an
-ActionMenuItem. It doesn't manage dispatching custom protocols but rather takes the arguments
-from any ``GET`` data and parses them into the easily accessible and correctly typed instance
-variables for your Python scripts.
-
-Available as a Gist at https://gist.github.com/3253287
-
-.. seealso::
- Our `support site has more information about Action Menu Items
- `_.
-
-************
-GET vs. POST
-************
-
-Action Menu Items that open a url via `http` or `https` to another web server send their data
-via ``POST``. If you're using a custom protocol the data is sent via ``GET``.
-
-.. note::
- Browsers limit the length of a ``GET`` request. If you exceed this limit by attempting to
- select a lot of rows and launch your custom protocol, you may encounter
- "Failed to load resource" errors in your console.
-
-.. seealso::
- This `Stack Overflow article "What is the maximum length of a URL in different browsers?"
- `_
-
-::
-
- #!/usr/bin/env python
- # encoding: utf-8
-
- # ---------------------------------------------------------------------------------------------
- # Description
- # ---------------------------------------------------------------------------------------------
- """
- The values sent by the Action Menu Item are in the form of a GET request that is similar to the
- format: myCoolProtocol://doSomethingCool?user_id=24&user_login=shotgun&title=All%20Versions&...
-
- In a more human-readable state that would translate to something like this:
- {
- 'project_name': 'Demo Project',
- 'user_id': '24',
- 'title': 'All Versions',
- 'user_login': 'shotgun',
- 'sort_column': 'created_at',
- 'entity_type': 'Version',
- 'cols': 'created_at',
- 'ids': '5,2',
- 'selected_ids': '2,5',
- 'sort_direction': 'desc',
- 'project_id': '4',
- 'session_uuid': 'd8592bd6-fc41-11e1-b2c5-000c297a5f50',
- 'column_display_names':
- [
- 'Version Name',
- 'Thumbnail',
- 'Link',
- 'Artist',
- 'Description',
- 'Status',
- 'Path to frames',
- 'QT',
- 'Date Created'
- ]
- }
-
- This simple class parses the url into easy to access types variables from the parameters,
- action, and protocol sections of the url. This example url
- myCoolProtocol://doSomethingCool?user_id=123&user_login=miled&title=All%20Versions&...
- would be parsed like this:
-
- (string) protocol: myCoolProtocol
- (string) action: doSomethingCool
- (dict) params: user_id=123&user_login=miled&title=All%20Versions&...
-
- The parameters variable will be returned as a dictionary of string key/value pairs. Here's
- how to instantiate:
-
- sa = ShotgunAction(sys.argv[1]) # sys.argv[1]
-
- sa.params['user_login'] # returns 'miled'
- sa.params['user_id'] # returns 123
- sa.protocol # returns 'myCoolProtocol'
- """
-
-
- # ---------------------------------------------------------------------------------------------
- # Imports
- # ---------------------------------------------------------------------------------------------
- import sys, os
- import urllib
- import logging as logger
-
- from pprint import pprint
-
- # ---------------------------------------------------------------------------------------------
- # Variables
- # ---------------------------------------------------------------------------------------------
- # location to write logfile for this script
- # logging is a bit of overkill for this class, but can still be useful.
- logfile = os.path.dirname(sys.argv[0])+"/shotgun_action.log"
-
-
- # ----------------------------------------------
- # Generic ShotgunAction Exception Class
- # ----------------------------------------------
- class ShotgunActionException(Exception):
- pass
-
-
- # ----------------------------------------------
- # ShotgunAction Class to manage ActionMenuItem call
- # ----------------------------------------------
- class ShotgunAction():
-
- def __init__(self, url):
- self.logger = self._init_log(logfile)
- self.url = url
- self.protocol, self.action, self.params = self._parse_url()
-
- # entity type that the page was displaying
- self.entity_type = self.params['entity_type']
-
- # Project info (if the ActionMenuItem was launched from a page not belonging
- # to a Project (Global Page, My Page, etc.), this will be blank
- if 'project_id' in self.params:
- self.project = { 'id':int(self.params['project_id']), 'name':self.params['project_name'] }
- else:
- self.project = None
-
- # Internal column names currently displayed on the page
- self.columns = self.params['cols']
-
- # Human readable names of the columns currently displayed on the page
- self.column_display_names = self.params['column_display_names']
-
- # All ids of the entities returned by the query (not just those visible on the page)
- self.ids = []
- if len(self.params['ids']) > 0:
- ids = self.params['ids'].split(',')
- self.ids = [int(id) for id in ids]
-
- # All ids of the entities returned by the query in filter format ready
- # to use in a find() query
- self.ids_filter = self._convert_ids_to_filter(self.ids)
-
- # ids of entities that were currently selected
- self.selected_ids = []
- if len(self.params['selected_ids']) > 0:
- sids = self.params['selected_ids'].split(',')
- self.selected_ids = [int(id) for id in sids]
-
- # All selected ids of the entities returned by the query in filter format ready
- # to use in a find() query
- self.selected_ids_filter = self._convert_ids_to_filter(self.selected_ids)
-
- # sort values for the page
- # (we don't allow no sort anymore, but not sure if there's legacy here)
- if 'sort_column' in self.params:
- self.sort = { 'column':self.params['sort_column'], 'direction':self.params['sort_direction'] }
- else:
- self.sort = None
-
- # title of the page
- self.title = self.params['title']
-
- # user info who launched the ActionMenuItem
- self.user = { 'id':self.params['user_id'], 'login':self.params['user_login']}
-
- # session_uuid
- self.session_uuid = self.params['session_uuid']
-
- # ----------------------------------------------
- # Set up logging
- # ----------------------------------------------
- def _init_log(self, filename="shotgun_action.log"):
- try:
- logger.basicConfig(level=logger.DEBUG,
- format='%(asctime)s %(levelname)-8s %(message)s',
- datefmt='%Y-%b-%d %H:%M:%S',
- filename=filename,
- filemode='w+')
- except IOError, e:
- raise ShotgunActionException ("Unable to open logfile for writing: %s" % e)
- logger.info("ShotgunAction logging started.")
- return logger
-
-
- # ----------------------------------------------
- # Parse ActionMenuItem call into protocol, action and params
- # ----------------------------------------------
- def _parse_url(self):
- logger.info("Parsing full url received: %s" % self.url)
-
- # get the protocol used
- protocol, path = self.url.split(":", 1)
- logger.info("protocol: %s" % protocol)
-
- # extract the action
- action, params = path.split("?", 1)
- action = action.strip("/")
- logger.info("action: %s" % action)
-
- # extract the parameters
- # 'column_display_names' and 'cols' occurs once for each column displayed so we store it as a list
- params = params.split("&")
- p = {'column_display_names':[], 'cols':[]}
- for arg in params:
- key, value = map(urllib.unquote, arg.split("=", 1))
- if key == 'column_display_names' or key == 'cols' :
- p[key].append(value)
- else:
- p[key] = value
- params = p
- logger.info("params: %s" % params)
- return (protocol, action, params)
-
-
- # ----------------------------------------------
- # Convert IDs to filter format to us in find() queries
- # ----------------------------------------------
- def _convert_ids_to_filter(self, ids):
- filter = []
- for id in ids:
- filter.append(['id','is',id])
- logger.debug("parsed ids into: %s" % filter)
- return filter
-
-
- # ----------------------------------------------
- # Main Block
- # ----------------------------------------------
- if __name__ == "__main__":
- try:
- sa = ShotgunAction(sys.argv[1])
- logger.info("ShotgunAction: Firing... %s" % (sys.argv[1]) )
- except IndexError, e:
- raise ShotgunActionException("Missing GET arguments")
- logger.info("ShotgunAction process finished.")
diff --git a/_sources/cookbook/examples/ami_version_packager.txt b/_sources/cookbook/examples/ami_version_packager.txt
deleted file mode 100644
index f0b08b942..000000000
--- a/_sources/cookbook/examples/ami_version_packager.txt
+++ /dev/null
@@ -1,257 +0,0 @@
-.. _ami_version_packager:
-
-########################################################
-Using an ActionMenuItem to Package Versions for a Client
-########################################################
-
-This is an example script to demonstrate how you can use an ActionMenuItem to launch a local
-script to package up files for a client. It performs the following:
-
-- Downloads Attachments from a specified field for all selected entities.
-- Creates an archive.
-- Copies the archive to a specified directory.
-
-It is intended to be used in conjunction with the script dicussed in :ref:`ami_handler`.
-
-::
-
- #!/usr/bin/env python
- # encoding: utf-8
- """
- version_packager.py
-
- This example script is meant to be run from an ActionMenuItem in Shotgun. The menu item uses a custom
- protocol in order to launch this script, and is followed by the action 'package4client'. So the full
- url would be something like launchme://package4client?.... See:
- http://support.shotgunsoftware.com/hc/en-us/articles/219031318-Creating-custom-Action-Menu-Items
-
- It uses the example ActionMenu Python class also located in our docs for parsing the ActionMenuItem
- POST variables. For more information about it and accessing the variables in the ActionMenuItem POST request,
- See: http://developer.shotgunsoftware.com/python-api/examples/ami_handler
-
- The purpose of this script is to download attachment files from Shotgun, create an archive of them
- and copy them to a specified directory. You can invoke it with the following minimal example to connect
- to Shotgun, download any file that exists in the specified field ('sg_qt') for each selected_id passed from the
- ActionMenu. Then it will create a single archive of the files and move it to the specified directory
- ('/path/where/i/want/to/put/the/archive/'). The archive is named with the Project Name, timestamp, and user
- login who ran the ActionMenuItem ('Demo_Project_2010-04-29-172210_kp.tar.gz'):
-
- sa = ShotgunAction(sys.argv[1])
- sg = shotgun_connect()
- if sa.action == 'package4client':
- r = packageFilesForClient('sg_qt','/path/where/i/want/to/put/the/archive/')
-
- """
-
- # ---------------------------------------------------------------------------------------------
- # Imports
- # ---------------------------------------------------------------------------------------------
- import sys, os
- import logging as logger
- import subprocess
- import re
- from datetime import datetime
-
- from shotgun_api3 import Shotgun
- from shotgun_action import ShotgunAction
- from pprint import pprint
-
- # ---------------------------------------------------------------------------------------------
- # Variables
- # ---------------------------------------------------------------------------------------------
- # Shotgun server auth info
- shotgun_conf = {
- 'url':'https://YOURSTUDIO.shotgunstudio.com',
- 'name':'YOUR_SCRIPT_NAME_HERE',
- 'key':'YOUR_SCRIPT_KEY_HERE'
- }
-
- # location to write logfile for this script
- logfile = os.path.dirname(sys.argv[0])+"/version_packager.log"
-
- # temporary directory to download movie files to and create thumbnail files in
- file_dir = os.path.dirname(sys.argv[0])+"/tmp"
-
- # compress command
- # tar czf /home/user/backup_www.tar.gz -C / var/www/html
- compress_cmd = "tar czf %s -C / %s"
-
-
-
- # ----------------------------------------------
- # Generic Shotgun Exception Class
- # ----------------------------------------------
- class ShotgunException(Exception):
- pass
-
-
-
- # ----------------------------------------------
- # Set up logging
- # ----------------------------------------------
- def init_log(filename="version_packager.log"):
- try:
- logger.basicConfig(level=logger.DEBUG,
- format='%(asctime)s %(levelname)-8s %(message)s',
- datefmt='%Y-%b-%d %H:%M:%s',
- filename=filename,
- filemode='w+')
- except IOError, e:
- raise ShotgunException ("Unable to open logfile for writing: %s" % e)
- logger.info("Version Packager logging started.")
- return logger
-
-
- # ----------------------------------------------
- # Extract Attachment id from entity field
- # ----------------------------------------------
- def extract_attachment_id(attachment):
- # extract the Attachment id from the url location
- attachment_id = attachment['url'].rsplit('/',1)[1]
- try:
- attachment_id = int(attachment_id)
- except:
- # not an integer.
- return None
- # raise ShotgunException("invalid Attachment id returned. Expected an integer: %s "% attachment_id)
-
- return attachment_id
-
-
- # ----------------------------------------------
- # Download Movie to Disk
- # ----------------------------------------------
- def download_attachment_to_disk(attachment,destination_filename):
- attachment_id = extract_attachment_id(attachment)
- if type(attachment_id) != int:
- return None
- # download the attachment file from Shotgun and write it to local disk
- logger.info("Downloading Attachment #%s" % (attachment_id))
- stream = sg.download_attachment(attachment_id)
- try:
- file = open(destination_filename, 'w')
- file.write(stream)
- file.close()
- logger.info("Downloaded attachment %s" % (destination_filename))
- return True
- except e:
- raise ShotgunException("unable to write attachment to disk: %s"% e)
-
-
- # ----------------------------------------------
- # Compress files
- # ----------------------------------------------
- def compress_files(files,destination_filename):
- destination_filename += ".tar.gz"
- files = [path.lstrip("/") for path in files]
- squish_me = compress_cmd % (destination_filename, " ".join(files) )
- logger.info("Compressing %s files..." % len(files))
- logger.info("Running command: %s" % squish_me)
- try:
- output = subprocess.Popen(squish_me, shell=True, stdout=subprocess.PIPE).stdout.read()
- logger.info('tar/gzip command returned: %s' % output)
- except e:
- raise ShotgunException("unable compress files: %s"% e)
- logger.info("compressed files to: %s" % destination_filename)
- return destination_filename
-
-
- # ----------------------------------------------
- # Remove downloaded files
- # ----------------------------------------------
- def remove_downloaded_files(files):
- remove_me = 'rm %s' % ( " ".join(files) )
- logger.info("Removing %s files..." % len(files))
- logger.info("Running command: %s" % remove_me)
- try:
- output = subprocess.Popen(remove_me, shell=True, stdout=subprocess.PIPE).stdout.read()
- logger.info('rm command returned: %s' % output)
- logger.info("removed downloaded files")
- return True
- except e:
- logger.error("unable remove files: %s"% e)
- return False
-
-
- # ----------------------------------------------
- # Copy files
- # ----------------------------------------------
- def copy_files(files,destination_directory):
- if type(files) == list:
- files = " ".join(files)
- copy_me_args = "%s %s" % (files, destination_directory)
- logger.info("Running command: mv %s" % copy_me_args)
- try:
- result = subprocess.Popen("mv " + copy_me_args, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
- # 0 = success, 1 = recoverable issues
- if result.returncode > 0:
- response = result.stderr.read()
- logger.error("Copy failed: %s"% response)
- raise ShotgunException("Copy failed: %s"% response)
- except OSError, e:
- raise ShotgunException("unable copy files: %s"% e)
-
- logger.info("copied files to: %s" % destination_directory)
- return destination_directory
-
-
-
- def packageFilesForClient(file_field,destination_dir):
-
- # get entities matching the selected ids
- logger.info("Querying Shotgun for %s %ss" % (len(sa.selected_ids_filter), sa.params['entity_type']))
- entities = sg.find(sa.params['entity_type'],sa.selected_ids_filter,['id','code',file_field],filter_operator='any')
-
- # download the attachments for each entity, zip them, and copy to destination directory
- files = []
- for e in entities:
- if not e[file_field]:
- logger.info("%s #%s: No file exists. Skippinsa." % (sa.params['entity_type'], e['id']))
- else:
- logger.info("%s #%s: %s" % (sa.params['entity_type'], e['id'], e[file_field]))
- path_to_file = file_dir+"/"+re.sub(r"\s+", '_', e[file_field]['name'])
- result = download_attachment_to_disk(e[file_field], path_to_file )
-
- # only include attachments. urls won't return true
- if result:
- files.append(path_to_file)
-
- # compress files
- # create a nice valid destination filename
- project_name = ''
- if 'project_name' in sa.params:
- project_name = re.sub(r"\s+", '_', sa.params['project_name'])+'_'
- dest_filename = project_name+datetime.today().strftime('%Y-%m-%d-%H%M%S')+"_"+sa.params['user_login']
- archive = compress_files(files,file_dir+"/"+dest_filename)
-
- # now that we have the archive, remove the downloads
- r = remove_downloaded_files(files)
-
- # copy to directory
- result = copy_files([archive],destination_dir)
-
- return True
-
-
- # ----------------------------------------------
- # Main Block
- # ----------------------------------------------
- if __name__ == "__main__":
- init_log(logfile)
-
- try:
- sa = ShotgunAction(sys.argv[1])
- logger.info("Firing... %s" % (sys.argv[1]) )
- except IndexError, e:
- raise ShotgunException("Missing POST arguments")
-
- sg = Shotgun(shotgun_conf['url'], shotgun_conf['name'], shotgun_conf['key'],convert_datetimes_to_utc=convert_tz)
-
- if sa.action == 'package4client':
- result = packageFilesForClient('sg_qt','/Users/kp/Documents/shotgun/dev/api/files/')
- else:
- raise ShotgunException("Unknown action... :%s" % sa.action)
-
-
- print "\nVersion Packager done!"
-
diff --git a/_sources/cookbook/examples/basic_create_shot.txt b/_sources/cookbook/examples/basic_create_shot.txt
deleted file mode 100644
index 0bd376b69..000000000
--- a/_sources/cookbook/examples/basic_create_shot.txt
+++ /dev/null
@@ -1,103 +0,0 @@
-.. _example_create_shot:
-
-Create A Shot
-=============
-
-Building the data and calling :meth:`~shotgun_api3.Shotgun.create`
-------------------------------------------------------------------
-To create a Shot, you need to provide the following values:
-
-- ``project`` is a link to the Project the Shot belongs to. It should be a dictionary like
- ``{"type": "Project", "id": 123}`` where ``id`` is the ``id`` of the Project.
-- ``code`` (this is the field that stores the name Shot)
-- optionally any other info you want to provide
-
-Example::
-
- data = {
- 'project': {"type":"Project","id": 4},
- 'code': '100_010',
- 'description': 'Open on a beautiful field with fuzzy bunnies',
- 'sg_status_list': 'ip'
- }
- result = sg.create('Shot', data)
-
-
-This will create a new Shot named "100_010" in the Project "Gunslinger" (which has an ``id`` of 4).
-
-- ``data`` is a list of key/value pairs where the key is the column name to update and the value
- is the the value to set.
-- ``sg`` is the Shotgun API instance you created in :ref:`example_sg_instance`.
-- ``create()`` is the :meth:`shotgun_api3.Shotgun.create` API method we are calling. We pass in the
- entity type we're searching for and the data we're setting.
-
-.. rubric:: Result
-
-The variable ``result`` now contains a dictionary hash with the Shot information you created.::
-
- {
- 'code': '100_010',
- 'description': 'Open on a beautiful field with fuzzy bunnies',
- 'id': 40435,
- 'project': {'id': 4, 'name': 'Demo Project', 'type': 'Project'},
- 'sg_status_list': 'ip',
- 'type': 'Shot'
- }
-
-In addition, Shotgun has returned the ``id`` that it has assigned to the Shot, as well as a
-``type`` value. ``type`` is provided for convenience simply to help you identify what entity type
-this dictionary represents. It does not correspond to any field in Shotgun.
-
-Shotgun will *always* return the ``id`` and ``type`` keys in the dictionary when there are results
-representing an entity.
-
-The Complete Example
---------------------
-::
-
- #!/usr/bin/env python
-
- # --------------------------------------
- # Imports
- # --------------------------------------
- import shotgun_api3
- from pprint import pprint # useful for debugging
-
- # --------------------------------------
- # Globals
- # --------------------------------------
- # make sure to change this to match your Shotgun server and auth credentials.
- SERVER_PATH = "https://mystudio.shotgunstudio.com"
- SCRIPT_NAME = 'my_script'
- SCRIPT_KEY = '27b65d7063f46b82e670fe807bd2b6f3fd1676c1'
-
- # --------------------------------------
- # Main
- # --------------------------------------
- if __name__ == '__main__':
-
- sg = shotgun_api3.Shotgun(SERVER_PATH, SCRIPT_NAME, SCRIPT_KEY)
-
- # --------------------------------------
- # Create a Shot with data
- # --------------------------------------
- data = {
- 'project': {"type":"Project","id": 4},
- 'code': '100_010',
- 'description': 'Open on a beautiful field with fuzzy bunnies',
- 'sg_status_list': 'ip'
- }
- result = sg.create('Shot', data)
- pprint(result)
- print "The id of the %s is %d." % (result['type'], result['id'])
-
-And here is the output::
-
- {'code': '100_010',
- 'description': 'Open on a beautiful field with fuzzy bunnies',
- 'id': 40435,
- 'project': {'id': 4, 'name': 'Demo Project', 'type': 'Project'},
- 'sg_status_list': 'ip',
- 'type': 'Shot'}
- The id of the Shot is 40435.
-
diff --git a/_sources/cookbook/examples/basic_create_shot_task_template.txt b/_sources/cookbook/examples/basic_create_shot_task_template.txt
deleted file mode 100644
index 76eb169e8..000000000
--- a/_sources/cookbook/examples/basic_create_shot_task_template.txt
+++ /dev/null
@@ -1,77 +0,0 @@
-Create a Shot with a Task Template
-==================================
-Creating a new Shot with a Task Template is just like linking it to another entity, but Shotgun will apply the Task Template in the background and create the appropriate Tasks on the Shot for you.
-
-Find the Task Template
-----------------------
-First we need to find the Task Template we're going to apply. We'll assume you know the name of the Task Template you want to use.
-::
-
- filters = [['code','is', '3D Shot Template' ]]
- template = sg.find_one('TaskTemplate', filters)
-
-
-The Resulting Task Template
----------------------------
-
-Assuming the task template was found, we will now have something like this in our ``template``
-variable::
-
- {'type': 'TaskTemplate', 'id': 12}
-
-Create the Shot
----------------
-Now we can create the Shot with the link to the ``TaskTemplate`` to apply.
-::
-
- data = {'project': {'type': 'Project','id': 4},
- 'code': '100_010',
- 'description': 'dark shot with wicked cool ninjas',
- 'task_template': template }
- result = sg.create('Shot', data)
-
-This will create a new Shot named "100_010" linked to the TaskTemplate "3D Shot Template" and
-Shotgun will then create the Tasks defined in the template and link them to the Shot you just
-created.
-
-- ``data`` is a list of key/value pairs where the key is the column name to update and the value is
- the value.
-- ``project`` and `code` are required
-- ``description`` is just a text field that you might want to update as well
-- ``task_template`` is another entity column where we set the Task Template which has the Tasks we
- wish to create by default on this Shot. We found the specific template we wanted to assign in the
- previous block by searching
-
-Result
-------
-The variable ``result`` now contains the dictionary of the new Shot that was created.
-::
-
- {
- 'code': '010_010',
- 'description': 'dark shot with wicked cool ninjas',
- 'id': 2345,
- 'project': {'id': 4, 'name': 'Gunslinger', 'type': 'Project'},
- 'task_template': {'id': 12,
- 'name': '3D Shot Template',
- 'type': 'TaskTemplate'},
- 'type': 'Shot'
- }
-
-
-If we now search for the Tasks linked to the Shot, we'll find the Tasks that match our
-``TaskTemplate``::
-
- tasks = sg.find('Task', filters=[['entity', 'is', result]])
-
-.. note:: You can use an entity dictionary that was returned from the API in a filter as we have
- done above. Shotgun will only look at the ``id`` and ``type`` keys and will ignore the rest.
- This is a handy way to pass around entity dictionaries without having to reformat them.
-
-Now the ``tasks`` variable contains the following::
-
- [{'id': 3253, 'type': 'Task'},
- {'id': 3254, 'type': 'Task'},
- {'id': 3255, 'type': 'Task'},
- {'id': 3256, 'type': 'Task'},
- {'id': 3257, 'type': 'Task'}]
diff --git a/_sources/cookbook/examples/basic_create_version_link_shot.txt b/_sources/cookbook/examples/basic_create_version_link_shot.txt
deleted file mode 100644
index d93983ebb..000000000
--- a/_sources/cookbook/examples/basic_create_version_link_shot.txt
+++ /dev/null
@@ -1,82 +0,0 @@
-Create a Version Linked to a Shot
-=================================
-You've just created a sweet new Version of your shot. Now you want to update Shotgun and create a
-new ``Version`` entity linked to the Shot.
-
-Find the Shot
--------------
-First we need to find the Shot since we'll need to know know its ``id`` in order to link our Version
-to it.
-::
-
- filters = [ ['project', 'is', {'type': 'Project', 'id': 4}],
- ['code', 'is', '100_010'] ]
- shot = sg.find_one('Shot', filters)
-
-
-Find the Task
--------------
-Now we find the Task that the Version relates to, again so we can use the ``id`` to link it to the
-Version we're creating. For this search we'll use the Shot ``id`` (which we have now in the ``shot``
-variable from the previous search) and the Task Name, which maps to the ``content`` field.
-::
-
- filters = [ ['project', 'is', {'type': 'Project', 'id': 4}],
- ['entity', 'is',{'type':'Shot', 'id': shot['id']}],
- ['content', 'is', 'Animation'] ]
- task = sg.find_one('Task', filters)
-
-.. note:: Linking a Task to the Version is good practice. By doing so it is easy for users to see
- at what stage a particular Version was created, and opens up other possibilities for tracking
- in Shotgun. We highly recommend doing this whenever possible.
-
-Create the Version
-------------------
-Now we can create the Version with the link to the Shot and the Task::
-
- data = { 'project': {'type': 'Project','id': 4},
- 'code': '100_010_anim_v1',
- 'description': 'first pass at opening shot with bunnies',
- 'sg_path_to_frames': '/v1/gun/s100/010/frames/anim/100_010_animv1_jack.#.jpg',
- 'sg_status_list': 'rev',
- 'entity': {'type': 'Shot', 'id': shot['id']},
- 'sg_task': {'type': 'Task', 'id': task['id']},
- 'user': {'type': 'HumanUser', 'id': 165} }
- result = sg.create('Version', data)
-
-This will create a new Version named '100_010_anim_v1' linked to the 'Animation' Task for Shot
-'100_010' in the Project 'Gunslinger'.
-
-- ``data`` is a list of key/value pairs where the key is the column name to update and the value is
- the value to set.
-- ``project`` and ``code`` are required
-- ``description`` and ``sg_path_to_frames`` are just text fields that you might want to update as
- well
-- ``sg_status_list`` is the status column for the Version. Here we are setting it to "rev" (Pending
- Review) so that it will get reviewed in the next dailies session and people will "ooh" and "aaah".
-- ``entity`` is where we link this version to the Shot. Entity columns are always handled with this
- format. You must provide the entity ``type`` and its ``id``.
-- ``sg_task`` is another entity link field specifically for the Version's Task link. This uses the
- same entity format as the Shot link, but pointing to the Task entity this time.
-- ``user`` is another entity column where we set the artist responsible for this masterpiece. In
- this example, I know the 'id' that corresponds to this user, but if you don't know the id you can
- look it up by searching on any of the fields, similar to what we did for the Shot above, like::
-
- filters = [['login', 'is', 'jschmoe']]
- user = sg.find('HumanUser', filters)
-
-The ``result`` variable now contains the ``id`` of the new Version that was created::
-
- 214
-
-
-Upload a movie for review in Screening Room
--------------------------------------------
-If Screening Room's transcoding feature is enabled on your site (hosted sites have this by
-default), then you can use the :meth:`~shotgun_api3.Shotgun.upload` method to upload a QuickTime
-movie, PDF, still image, etc. to the ``sg_uploaded_movie`` field on a Version. Once the movie is
-uploaded, it will automatically be queued for transcoding. When transcoding is complete, the
-Version will be playable in the Screening Room app, or in the Overlay player by clicking on the
-Play button that will appear on the Version's thumbnail.
-
-.. note:: Transcoding also generates a thumbnail and filmstrip thumbnail automatically.
\ No newline at end of file
diff --git a/_sources/cookbook/examples/basic_delete_shot.txt b/_sources/cookbook/examples/basic_delete_shot.txt
deleted file mode 100644
index 779fc9659..000000000
--- a/_sources/cookbook/examples/basic_delete_shot.txt
+++ /dev/null
@@ -1,52 +0,0 @@
-Delete A Shot
-=============
-
-Calling :meth:`~shotgun_api3.Shotgun.delete`
---------------------------------------------
-Deleting an entity in Shotgun is pretty straight-forward. No extraneous steps required.::
-
- result = sg.delete("Shot", 40435)
-
-Result
-------
-If the Shot was deleted successfully ``result`` will contain::
-
- True
-
-The Complete Example
---------------------
-::
-
- #!/usr/bin/env python
-
- # --------------------------------------
- # Imports
- # --------------------------------------
- import shotgun_api3
- from pprint import pprint # useful for debugging
-
- # --------------------------------------
- # Globals
- # --------------------------------------
- # make sure to change this to match your Shotgun server and auth credentials.
- SERVER_PATH = "https://mystudio.shotgunstudio.com"
- SCRIPT_NAME = 'my_script'
- SCRIPT_KEY = '27b65d7063f46b82e670fe807bd2b6f3fd1676c1'
-
- # --------------------------------------
- # Main
- # --------------------------------------
- if __name__ == '__main__':
-
- sg = shotgun_api3.Shotgun(SERVER_PATH, SCRIPT_NAME, SCRIPT_KEY)
-
- # --------------------------------------
- # Delete a Shot by id
- # --------------------------------------
- result = sg.delete("Shot", 40435)
- pprint(result)
-
-And here is the output::
-
- True
-
diff --git a/_sources/cookbook/examples/basic_find_shot.txt b/_sources/cookbook/examples/basic_find_shot.txt
deleted file mode 100644
index ee223c89b..000000000
--- a/_sources/cookbook/examples/basic_find_shot.txt
+++ /dev/null
@@ -1,76 +0,0 @@
-.. _example_find_shot:
-
-Find a Shot
-===========
-
-Building the Query
-------------------
-We are going to assume we know the 'id' of the Shot we're looking for in this example.::
-
- filters = [['id', 'is', 40435]]
- result = sg.find_one('Shot', filters)
-
-Pretty simple right? Well here's a little more insight into what's going on.
-
-- ``filters`` is an list of filter conditions. In this example we are filtering for Shots where
- the ``id`` column is **40435**.
-- ``sg`` is the Shotgun API instance.
-- ``find_one()`` is the :meth:`~shotgun_api3.Shotgun.find_one` API method we are calling. We
- provide it with the entity type we're searching for and our filters.
-
-
-Seeing the Result
------------------
-So what does this return? The variable result now contains::
-
- {'type': 'Shot','id': 40435}
-
-By default, :meth:`~shotgun_api3.Shotgun.find_one` returns a single dictionary object with
-the ``type`` and ``id`` fields. So in this example, we found a Shot matching that id, and Shotgun
-returned it as a dictionary object with ``type`` and ``id`` keys .
-
-How do we know that result contains the Shot dictionary object? You can trust us... but just to be
-sure, the :mod:`pprint` (PrettyPrint) module from the Python standard library is a really good tool
-to help with debugging. It will print out objects in a nicely formatted way that makes things
-easier to read. So we'll add that to the import section of our script.::
-
- import shotgun_api3
- from pprint import pprint # useful for debugging
-
-The Complete Example
---------------------
-::
-
- #!/usr/bin/env python
-
- # --------------------------------------
- # Imports
- # --------------------------------------
- import shotgun_api3
- from pprint import pprint # useful for debugging
-
- # --------------------------------------
- # Globals
- # --------------------------------------
- # make sure to change this to match your Shotgun server and auth credentials.
- SERVER_PATH = "https://mystudio.shotgunstudio.com"
- SCRIPT_NAME = 'my_script'
- SCRIPT_KEY = '27b65d7063f46b82e670fe807bd2b6f3fd1676c1'
-
- # --------------------------------------
- # Main
- # --------------------------------------
- if __name__ == '__main__':
-
- sg = shotgun_api3.Shotgun(SERVER_PATH, SCRIPT_NAME, SCRIPT_KEY)
-
- # --------------------------------------
- # Find a Shot by id
- # --------------------------------------
- filters = [['id', 'is', 40435]]
- result = sg.find_one('Shot', filters)
- pprint(result)
-
-And here is the output::
-
- {'type': 'Shot','id': 40435}
diff --git a/_sources/cookbook/examples/basic_sg_instance.txt b/_sources/cookbook/examples/basic_sg_instance.txt
deleted file mode 100644
index 6d2d1dd08..000000000
--- a/_sources/cookbook/examples/basic_sg_instance.txt
+++ /dev/null
@@ -1,26 +0,0 @@
-.. _example_sg_instance:
-
-Create a Shotgun API instance
-=============================
-
-This example shows you how to establish your initial connection to Shotgun using script-based
-authentication. ``sg`` represents your Shotgun API instance. Be sure you've read
-:ref:`Setting Up Shotgun for API Access `.
-::
-
- import pprint # Useful for debugging
-
- import shotgun_api3
-
- SERVER_PATH = "https://your_site.shotgunstudio.com"
- SCRIPT_NAME = 'my_script'
- SCRIPT_KEY = '27b65d7063f46b82e670fe807bd2b6f3fd1676c1'
-
- sg = shotgun_api3.Shotgun(SERVER_PATH, SCRIPT_NAME, SCRIPT_KEY)
-
- # Just for demo purposes, this will print out property and method names available on the
- # sg connection object
- pprint.pprint([symbol for symbol in sorted(dir(sg)) if not symbol.startswith('_')])
-
-For further information on what you can do with this Shotgun object you can read the
-:ref:`API reference `.
\ No newline at end of file
diff --git a/_sources/cookbook/examples/basic_update_shot.txt b/_sources/cookbook/examples/basic_update_shot.txt
deleted file mode 100644
index 555114578..000000000
--- a/_sources/cookbook/examples/basic_update_shot.txt
+++ /dev/null
@@ -1,86 +0,0 @@
-Update A Shot
-=============
-
-Building the data and calling :meth:`~shotgun_api3.Shotgun.update`
-------------------------------------------------------------------
-To update a Shot, you need to provide the ``id`` of the Shot and a list of fields you want to
-update.::
-
- data = {
- 'description': 'Open on a beautiful field with fuzzy bunnies',
- 'sg_status_list': 'ip'
- }
- result = sg.update('Shot', 40435, data)
-
-This will update the ``description`` and the ``sg_status_list`` fields for the Shot with ``id`` of
-**40435**.
-
-- ``data`` is a list of key/value pairs where the key is the field name to update and the value to
- update it to.
-- ``sg`` is the Shotgun API instance.
-- ``update()`` is the :meth:`shotgun_api3.Shotgun.update` API method we are calling. We provide it
- with the entity type we're updating, the ``id`` of the entity, and the data we're updating it
- with.
-
-Result
-------
-The variable ``result`` now contains the Shot object that with the updated values.::
-
- {
- 'description': 'Opening establishing shot with titles and fuzzy bunnies',
- 'sg_status_list': 'ip',
- 'type': 'Shot',
- 'id': 40435
- }
-
-In addition, Shotgun has returned the ``id`` for the Shot, as well as a ``type`` value. ``type``
-is provided for convenience simply to help you identify what entity type this dictionary represents.
-It does not correspond to any field in Shotgun.
-
-Shotgun will *always* return the ``id`` and ``type`` keys in the dictionary when there are results
-representing an entity.
-
-The Complete Example
---------------------
-::
-
- #!/usr/bin/env python
-
- # --------------------------------------
- # Imports
- # --------------------------------------
- import shotgun_api3
- from pprint import pprint # useful for debugging
-
- # --------------------------------------
- # Globals
- # --------------------------------------
- # make sure to change this to match your Shotgun server and auth credentials.
- SERVER_PATH = "https://mystudio.shotgunstudio.com"
- SCRIPT_NAME = 'my_script'
- SCRIPT_KEY = '27b65d7063f46b82e670fe807bd2b6f3fd1676c1'
-
- # --------------------------------------
- # Main
- # --------------------------------------
- if __name__ == '__main__':
-
- sg = shotgun_api3.Shotgun(SERVER_PATH, SCRIPT_NAME, SCRIPT_KEY)
-
- # --------------------------------------
- # Update Shot with data
- # --------------------------------------
- data = {
- 'description': 'Open on a beautiful field with fuzzy bunnies',
- 'sg_status_list': 'ip'
- }
- result = sg.update('Shot', 40435, data)
- pprint(result)
-
-And here is the output::
-
- {'description': 'Opening establishing shot with titles and fuzzy bunnies',
- 'id': 40435,
- 'sg_status_list': 'ip',
- 'type': 'Shot'}
-
diff --git a/_sources/cookbook/examples/basic_upload_thumbnail_version.txt b/_sources/cookbook/examples/basic_upload_thumbnail_version.txt
deleted file mode 100644
index 62713aa90..000000000
--- a/_sources/cookbook/examples/basic_upload_thumbnail_version.txt
+++ /dev/null
@@ -1,27 +0,0 @@
-Upload a Thumbnail for a Version
-================================
-
-So you've created a new Version of a Shot, and you've updated Shotgun, but now you want to upload a
-beauty frame to display as the thumbnail for your Version. We'll assume you already have the image
-made (located on your machine at ``/v1/gun/s100/010/beauties/anim/100_010_animv1.jpg``) . And since
-you've just created your Version in Shotgun, you know its ``id`` is **214**.
-
-.. note:: If you upload a movie file or image to the ``sg_uploaded_movie`` field and you have
- transcoding enabled on your server (the default for hosted sites), a thumbnail will be
- generated automatically as well as a filmstrip thumbnail (if possible). But this example is
- provided just to show the basic process of uploading a thumbnail manually where is may be
- necessary.
-
-Upload the Image using :meth:`~shotgun_api3.Shotgun.upload_thumbnail`
----------------------------------------------------------------------
-::
-
- sg.upload_thumbnail("Version", 214, "/v1/gun/s100/010/beauties/anim/100_010_animv1.jpg")
-
-
-Shotgun will take care of resizing the thumbnail for you. If something does go wrong, an exception
-will be thrown and you'll see the error details.
-
-.. note:: The result returned by :meth:`~shotgun_api3.Shotgun.upload_thumbnail` is an integer
- representing the id of a special ``Attachment`` entity in Shotgun. Working with Attachments
- is beyond the scope of this example. :)
\ No newline at end of file
diff --git a/_sources/cookbook/examples/svn_integration.txt b/_sources/cookbook/examples/svn_integration.txt
deleted file mode 100644
index ade057af6..000000000
--- a/_sources/cookbook/examples/svn_integration.txt
+++ /dev/null
@@ -1,170 +0,0 @@
-.. _svn_integration:
-
-############################
-Subversion (SVN) Integration
-############################
-
-Integrating Shotgun with Subversion consists of two basic parts:
-
-- Setup a post-commit hook in Subversion.
-- Create a Shotgun API script to create the Revision in Shotgun. This script will be called by
- the post-commit hook.
-
-****************
-Post-Commit Hook
-****************
-
-To setup the post-commit hook:
-
-- Locate the ``post-commit.tmpl`` file, which is found inside the ``hooks`` folder in your
- repository directory. This is a template script that has lots of useful comments and can serve
- as a starting point for the real thing.
-- Create your very own executable script, and save it in the same ``hooks`` folder, name it
- ``post-commit``, and give it executable permission.
-- In your ``post-commit`` script, invoke your Shotgun API script.
-
-If this is entirely new to you, we highly suggest reading up on the topic. O'Reilly has `a free
-online guide for Subversion 1.5 and 1.6
-`_
-
-Here's an example of a post-commit hook that we've made for Subversion 1.6 using an executable
-Unix shell script. The last line invokes "shotgun_api_script.py" which is our Python script that
-will do all the heavy lifting. Lines 4 thru 8 queue up some objects that we'll use later on.
-
-.. code-block:: sh
- :linenos:
-
- #!/bin/sh
- # POST-COMMIT HOOK
-
- REPOS="$1"
- REV="$2"
-
- export AUTHOR="$(svnlook author $REPOS --revision $REV)"
- export COMMENT="$(svnlook log $REPOS --revision $REV)"
-
- /Absolute/path/to/shotgun_api_script.py
-
-Explanation of selected lines
-=============================
-
-- lines ``4-5``: After the commit, Subversion leaves us two string objects in the environment:
- ``REPOS`` and ``REV`` (the repository path and the revision number, respectively).
-- lines ``7-8``: Here we use the shell command ``export`` to create two more string objects in the
- environment: ``AUTHOR`` and ``COMMENT``. To get each value, we use the ``svnlook`` command with
- our ``REPOS`` and ``REV`` values, first with the ``author``, and then with ``log`` subcommand.
- These are actually the first two original lines of code - everything else to this point was
- pre-written already in the ``post-commit.tmpl`` file. nice :)
-- line ``10``: This is the absolute path to our Shotgun API Script.
-
-******************
-Shotgun API Script
-******************
-
-This script will create the Revision and populate it with some metadata using the Shotgun Python
-API. It will create our Revision in Shotgun along with the author, comment, and because we use
-Trac (a web-based interface for Subversion), it will also populate a URL field with a clickable
-link to the Revision.
-
-.. code-block:: python
- :linenos:
-
-
- #!/usr/bin/env python
- # ---------------------------------------------------------------------------------------------
-
- # ---------------------------------------------------------------------------------------------
- # Imports
- # ---------------------------------------------------------------------------------------------
- import sys
- from shotgun_api3_preview import Shotgun
- import os
-
- # ---------------------------------------------------------------------------------------------
- # Globals - update all of these values to those of your studio
- # ---------------------------------------------------------------------------------------------
- SERVER_PATH = 'https ://studio_name.shotgunstudio.com' # or http:
- SCRIPT_USER = 'script_name'
- SCRIPT_KEY = '3333333333333333333333333333333333333333'
- REVISIONS_PATH = 'https ://serveraddress/trac/changeset/' # or other web-based UI
- PROJECT = {'type':'Project', 'id':27}
-
- # ---------------------------------------------------------------------------------------------
- # Main
- # ---------------------------------------------------------------------------------------------
- if __name__ == '__main__':
-
- sg = Shotgun(SERVER_PATH, SCRIPT_USER, SCRIPT_KEY)
-
- # Set Python variables from the environment objects
- revision_code = os.environ['REV']
- repository = os.environ['REPOS']
- description = os.environ['COMMENT']
- author = os.environ['AUTHOR']
-
- # Set the Trac path for this specific revision
- revision_url = REVISIONS_PATH + revision_code
-
- # Validate that author is a valid Shotgun HumanUser
- result = sg.find_one("HumanUser", [['login', 'is', author]])
- if result:
- # Create Revision
- url = {'content_type':'http_url', 'url':revision_url, 'name':'Trac'}
- parameters = {'project':PROJECT,
- 'code':str(revision_code),
- 'description':description,
- 'attachment':url,
- 'created_by':{"type":"HumanUser", "id":result['id']}
- }
- revision = sg.create("Revision", parameters)
- print "created Revision #"+str(revision_code)
-
- # Send error message if valid HumanUser is not found
- else:
- print "Unable to find valid Shotgun User with login: "+author+", Revision not created in Shotgun."
-
-
-
-Explanation of selected lines:
-==============================
-
-- line ``14``: This should be the URL to your instance of Shotgun.
-- lines ``15-16``: Make sure you get these values from the "Scripts" page in the Admin section of
- the Shotgun web application. If you're not sure how to do this, check out :doc:`authentication`.
-- line ``17``: This is the address of Trac, our web-based interface that we use with Subversion.
- You may use a different interface, or none at all, so feel free to adjust this line or ignore it
- as your case may be.
-- line ``18``: Every Revision in Shotgun must have a Project, which is passed to the API as a
- dictionary with two keys, the ``type`` and the ``id``. Of course the ``type`` value will always
- remain ``Project`` (case sensitive), but the ``id`` will change by Project. To find out the
- ``id`` of your Project, go to the Projects page in the Shotgun web application, locate the
- Project where you want your Revisions created, and then locate its ``id`` field (which you may
- need to display - if you don't see it, right click on any column header then select
- "Insert Column" > "Id"). Note that for this example we assume that all Revisions in this
- Subversion repository will belong to the same Project.
-- lines ``28-31``: Grab the values from the objects that were left for us in the environment.
-- line ``34``: Add the Revision number to complete the path of our Trac url.
-- line ``37``: Make sure that a valid User exists in Shotgun. In our example, we assume that our
- Users' Shotgun logins match their Subversion names. If the user exists in Shotgun, that
- user's ``id`` will be returned as ``result['id']``, which we will need later on in line 46.
-- lines ``40-48``: Use all the meta data we've gathered to create a Revision in Shotgun. If none
- of these lines make any sense, check out more on the :meth:`~shotgun_api3.Shotgun.create` method
- here. Line 41 deserves special mention: notice that we define a dictionary called ``url`` that
- has three important keys: ``content_type``, ``url``, and ``name``, and we then pass this in as
- the value for the ``attachment`` field when we create the Revision. If you're even in doubt,
- double check the syntax and requirements for the different field types here.
-
-***************
-Troubleshooting
-***************
-
-My post-commit script is simply not running. I can run it manually, but commits are not triggering it.
-======================================================================================================
-
-Make sure that the script is has explicitly been made executable and that all users who will
-invoke it have appropriate permissions for the script and that folders going back to root.
-
-My Shotgun API script is not getting called by the post-commit hook.
-====================================================================
-
-Make sure that the script is called using its absolute path.
diff --git a/_sources/cookbook/smart_cut_fields.txt b/_sources/cookbook/smart_cut_fields.txt
deleted file mode 100644
index 9dd7fcae1..000000000
--- a/_sources/cookbook/smart_cut_fields.txt
+++ /dev/null
@@ -1,53 +0,0 @@
-.. _smart_cut_fields:
-
-################
-Smart Cut Fields
-################
-
-.. warning::
- Smart Cut Fields should be considered deprecated. Shotgun v7.0, introduced a new version of
- cut support. `Read the Cut Support Documentation here `_.
-
-If you want to work with 'smart' cut fields through the API, your script should use a corresponding
-'raw' fields for all updates. The 'smart_cut_fields' are primarily for display in the UI, the real
-data is stored in a set of 'raw' fields that have different names.
-
-************
-Smart Fields
-************
-
-In the UI these fields attempt to calculate values based on data entered into the various fields.
-These fields can be queried via the API using the find() method, but not updated. Note that we are
-deprecating this feature and recommend creating your own cut fields from scratch, which will not
-contain any calculations which have proven to be too magical at times.
-
-- ``smart_cut_duration``
-- ``smart_cut_in``
-- ``smart_cut_out``
-- ``smart_cut_summary_display`` *
-- ``smart_cut_duration_display`` *
-- ``smart_head_duration``
-- ``smart_head_in``
-- ``smart_head_out``
-- ``smart_tail_duration``
-- ``smart_tail_in``
-- ``smart_tail_out``
-- ``smart_working_duration`` *
-
-.. note:: \* these are special summary fields that have no corresponding "raw" field.
-
-**********
-Raw Fields
-**********
-
-These are the "raw" fields that can be queried and updated through the API:
-
-- ``cut_duration``
-- ``cut_in``
-- ``cut_out``
-- ``head_duration``
-- ``head_in``
-- ``head_out``
-- ``tail_duration``
-- ``tail_in``
-- ``tail_out``
diff --git a/_sources/cookbook/tasks.txt b/_sources/cookbook/tasks.txt
deleted file mode 100644
index 0acb5f5e7..000000000
--- a/_sources/cookbook/tasks.txt
+++ /dev/null
@@ -1,13 +0,0 @@
-##################
-Working With Tasks
-##################
-
-Tasks have various special functionality available in the UI that can also be queried and
-manipulated through the API. The sections below cover these topics.
-
-.. toctree::
- :maxdepth: 2
-
- tasks/updating_tasks
- tasks/task_dependencies
- tasks/split_tasks
diff --git a/_sources/cookbook/tasks/split_tasks.txt b/_sources/cookbook/tasks/split_tasks.txt
deleted file mode 100644
index c8628c0f9..000000000
--- a/_sources/cookbook/tasks/split_tasks.txt
+++ /dev/null
@@ -1,257 +0,0 @@
-.. _split_tasks:
-
-###########
-Split Tasks
-###########
-
-Split tasks can be created and edited via the API but must comply to some rules. Before going
-further, a good understanding of :ref:`how Shotgun handles task dates is useful `.
-
-********
-Overview
-********
-
-The Task entity has a field called ``splits`` which is a list of dictionaries. Each dictionary
-in the list has two string keys, ``start`` and ``end``, who's values are strings representing dates
-in the ``YYYY-mm-dd`` format.
-
-::
-
- [{'start': '2012-12-11', 'end': '2012-12-12'}, {'start': '2012-12-18', 'end': '2012-12-19'}]
-
-- Splits should be ordered from eldest to newest.
-- There should be gaps between each split.
-
- - Gaps are defined as at least one working day. Non-workdays such as weekends and holidays
- are not gaps.
-
-If there are multiple splits but there between two or more splits there is no gap, an error will be
-raised. For example::
-
- >>> sg.update('Task', 2088, {'splits':[{'start':'2012-12-10', 'end':'2012-12-11'}, {'start':'2012-12-12', 'end':'2012-12-14'}, {'start':'2012-12-19', 'end':'2012-12-20'}]})
- Traceback (most recent call last):
- File "", line 1, in
- File "/shotgun/src/python-api/shotgun_api3/shotgun.py", line 600, in update
- record = self._call_rpc("update", params)
- File "/shotgun/src/python-api/shotgun_api3/shotgun.py", line 1239, in _call_rpc
- self._response_errors(response)
- File "/shotgun/src/python-api/shotgun_api3/shotgun.py", line 1435, in _response_errors
- "Unknown Error"))
- shotgun_api3.shotgun.Fault: API update() CRUD ERROR #5: Update failed for [Task.splits]: (task.rb) The start date in split segment 2 is only one calendar day away from the end date of the previous segment. There must be calendar days between split segments.
-
-Alternately, a split value can be set to ``None`` to remove splits (you can also use an empty list).
-This will preserve the ``start_date`` and ``due_date`` values but recalculate the ``duration`` value
-while appropriately considering all workday rules in effect.
-
-********************************************************
-How Do Splits Influence Dates And Dates Influence Splits
-********************************************************
-
-- If splits are specified the supplied ``start_date``, ``due_date`` and ``duration`` fields will be ignored.
-- The ``start_date`` will be inferred from the earliest split.
-- The ``due_date`` will be inferred from the last split.
-- If the ``start_date`` is changed on a task that has splits the first split will be moved to start
- on the new ``start_date`` and all further splits will be moved while maintaining gap lengths
- between splits and respecting workday rules.
-- If the ``due_date`` is changed on a task that has splits the last split will be moved to end on
- the new ``due_date`` and all prior splits will be moved while maintaining gap lengths between
- splits and respecting workday rules.
-- If the ``duration`` is changed two scenarios are possible
-
- - In the case of a longer duration, additional days will be added to the end of the last split
- - In the case of a shorter duration splits, starting with the latest ones, will be either
- removed or shortened until the new duration is met.
-
-Examples
-========
-Throughout the following examples, each successive one will build on the previous.
-
-start_date, due_date and duration being ignored
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-
-::
-
- sg.update('Task', 2088, {
- 'start_date': '2012-12-06',
- 'due_date': '2012-12-23',
- 'duration': 3600,
- 'splits': [
- {'start': '2012-12-11', 'end': '2012-12-12'},
- {'start': '2012-12-18', 'end': '2012-12-19'}
- ]
- })
-
- # Task = {
- # 'start_date': '2012-12-11',
- # 'due_date': '2012-12-19',
- # 'duration': 2400,
- # 'splits': [
- # {'start': '2012-12-11', 'end': '2012-12-12'},
- # {'start': '2012-12-18', 'end': '2012-12-19'}
- # ]
- # }
-
-Result:
-
-.. image:: /images/split_tasks_1.png
-
-Moving the start_date of a split task
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-
-::
-
- sg.update('Task', 2088, {
- 'start_date': '2012-12-10'
- })
-
- # Task = {
- # 'start_date': '2012-12-10',
- # 'due_date': '2012-12-18',
- # 'splits': [
- # {'start': '2012-12-10', 'end': '2012-12-11'},
- # {'start': '2012-12-14', 'end': '2012-12-18'}
- # ]
- # }
-
-Result:
-
-.. image:: /images/split_tasks_2.png
-
-Moving the due_date of a split task
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-
-::
-
- sg.update('Task', 2088, {
- 'due_date': '2012-12-19'
- })
-
- # Task = {
- # 'start_date': '2012-12-10',
- # 'due_date': '2012-12-19',
- # 'splits': [
- # {'start': '2012-12-10', 'end': '2012-12-11'},
- # {'start': '2012-12-14', 'end': '2012-12-19'}
- # ]
- # }
-
-Result:
-
-.. image:: /images/split_tasks_3.png
-
-Setting a longer duration
-~~~~~~~~~~~~~~~~~~~~~~~~~
-
-::
-
- sg.update('Task', 2088, {
- 'duration': 4200
- })
-
- # Task = {
- # 'start_date': '2012-12-10',
- # 'due_date': '2012-12-21',
- # 'duration': 4200,
- # 'splits': [
- # {'start': '2012-12-10', 'end': '2012-12-11'},
- # {'start': '2012-12-14', 'end': '2012-12-21'}
- # ]
- # }
-
-Result:
-
-.. image:: /images/split_tasks_4.png
-
-Setting a shorter duration
-~~~~~~~~~~~~~~~~~~~~~~~~~~
-
-::
-
- sg.update('Task', 2088, {
- 'duration': 2400
- })
-
- # Task = {
- # 'start_date': '2012-12-10',
- # 'due_date': '2012-12-18',
- # 'duration': 2400,
- # 'splits': [
- # {'start': '2012-12-10', 'end': '2012-12-11'},
- # {'start': '2012-12-14', 'end': '2012-12-18'}
- # ]
- # }
-
-Result:
-
-.. image:: /images/split_tasks_5.png
-
-Another example of shorter duration
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-We won't be using the previous result for this example but rather, the following:
-
-.. image:: /images/split_tasks_6.png
-
-who's duration we will shorten past the last split.
-
-::
-
- sg.update('Task', 2088, {
- 'duration': 1800
- })
-
- # Task = {
- # 'start_date': '2012-12-10',
- # 'due_date': '2012-12-18',
- # 'duration': 2400,
- # 'splits': [
- # {'start': '2012-12-10', 'end': '2012-12-11'},
- # {'start': '2012-12-14', 'end': '2012-12-18'}
- # ]
- # }
-
-Result:
-
-.. image:: /images/split_tasks_7.png
-
-Setting the due_date in a gap
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-
-When a due date is set in a gap later splits are removed and the day of the due date is considered
-a day when work will be done.
-
-For this example let's assume as a starting point the result of the 5th example:
-
-.. image:: /images/split_tasks_8.png
-
-::
-
- sg.update('Task', 2088, {
- 'due_date': '2012-12-13'
- })
-
- # Task = {
- # 'start_date': '2012-12-10',
- # 'due_date': '2012-12-13',
- # 'duration': 1800,
- # 'splits': [
- # {'start': '2012-12-10', 'end': '2012-12-11'},
- # {'start': '2012-12-13', 'end': '2012-12-13'}
- # ]
- # }
-
-Result:
-
-.. image:: /images/split_tasks_9.png
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/_sources/cookbook/tasks/task_dependencies.txt b/_sources/cookbook/tasks/task_dependencies.txt
deleted file mode 100644
index fde003783..000000000
--- a/_sources/cookbook/tasks/task_dependencies.txt
+++ /dev/null
@@ -1,339 +0,0 @@
-.. _task_dependencies:
-
-#################
-Task Dependencies
-#################
-
-Task dependencies work the same way in the API as they do in the UI. You can filter and sort on
-any of the fields. For information about Task Dependencies in Shotgun, check out the `main
-documentation page on our support site
-`_
-
-************
-Create Tasks
-************
-
-Let's create a couple of Tasks and create dependencies between them. First we'll create a "Layout"
-Task for our Shot::
-
- data = {
- 'project': {'type':'Project', 'id':65},
- 'content': 'Layout',
- 'start_date': '2010-04-28',
- 'due_date': '2010-05-05',
- 'entity': {'type':'Shot', 'id':860}
- }
- result = sg.create(Task, data)
-
-
-Returns::
-
- {'content': 'Layout',
- 'due_date': '2010-05-05',
- 'entity': {'id': 860, 'name': 'bunny_010_0010', 'type': 'Shot'},
- 'id': 556,
- 'project': {'id': 65, 'name': 'Demo Animation Project', 'type': 'Project'},
- 'start_date': '2010-04-28',
- 'type': 'Task'}
-
-
-Now let's create an "Anm" Task for our Shot::
-
- data = {
- 'project': {'type':'Project', 'id':65},
- 'content': 'Anm',
- 'start_date': '2010-05-06',
- 'due_date': '2010-05-12',
- 'entity': {'type':'Shot', 'id':860}
- }
- result = sg.create(Task, data)
-
-Returns::
-
- {'content': 'Anm',
- 'due_date': '2010-05-12',
- 'entity': {'id': 860, 'name': 'bunny_010_0010', 'type': 'Shot'},
- 'id': 557,
- 'project': {'id': 65, 'name': 'Demo Animation Project', 'type': 'Project'},
- 'start_date': '2010-05-06,
- 'type': 'Task'}
-
-
-*******************
-Create A Dependency
-*******************
-
-Tasks each have an ``upstream_tasks`` field and a ``downstream_tasks`` field. Each field is a
-list ``[]`` type and can contain zero, one, or multiple Task entity dictionaries representing the
-dependent Tasks. Here is how to create a dependency between our "Layout" and "Anim" Tasks::
-
- # make 'Layout' and upstream Task to 'Anm'. (aka, make 'Anm' dependent on 'Layout')
- result = sg.update('Task', 557, {'upstream_tasks':[{'type':'Task','id':556}]})
-
-Returns::
-
- [{'id': 557,
- 'type': 'Task',
- 'upstream_tasks': [{'id': 556, 'name': 'Layout', 'type': 'Task'}]}]
-
-This will also automatically update the `downstream_tasks` field on 'Layout' to include the 'Anm' Task.
-
-**********************************
-Query Tasks with Dependency Fields
-**********************************
-
-So now lets look at the Tasks we've created and their dependency-related fields::
-
- filters = [
- ['entity', 'is', {'type':'Shot', 'id':860}]
- ]
- fields = [
- 'content',
- 'start_date',
- 'due_date',
- 'upstream_tasks',
- 'downstream_tasks',
- 'dependency_violation',
- 'pinned'
- ]
- result = sg.find("Task", filters, fields)
-
-Returns::
-
- [{'content': 'Layout',
- 'dependency_violation': False,
- 'downstream_tasks': [{'type': 'Task', 'name': 'Anm', 'id': 557}],
- 'due_date': '2010-05-05',
- 'id': 556,
- 'pinned': False,
- 'start_date': '2010-04-28',
- 'type': 'Task',
- 'upstream_tasks': []},
- {'content': 'Anm',
- 'dependency_violation': False,
- 'downstream_tasks': [{'type': 'Task', 'name': 'FX', 'id': 558}],
- 'due_date': '2010-05-12',
- 'id': 557,
- 'pinned': False,
- 'start_date': '2010-05-06',
- 'type': 'Task',
- 'upstream_tasks': [{'type': 'Task', 'name': 'Layout', 'id': 556}]},
- ...
-
-*Note that we have also created additional Tasks for this Shot but we're going to focus on these
-first two for simplicity.*
-
-*****************************************************************
-Updating the End Date on a Task with Downstream Task Dependencies
-*****************************************************************
-
-If we update the ``due_date`` field on our "Layout" Task, we'll see that the "Anm" Task dates
-will automatically get pushed back to keep the dependency satisfied::
-
- result = sg.update('Task', 556, {'due_date': '2010-05-07'})
-
-Returns::
-
- [{'due_date': '2010-05-07', 'type': 'Task', 'id': 556}]
-
-Our Tasks now look like this (notice the new dates on the "Anm" Task)::
-
- [{'content': 'Layout',
- 'dependency_violation': False,
- 'downstream_tasks': [{'type': 'Task', 'name': 'Anm', 'id': 557}],
- 'due_date': '2010-05-07',
- 'id': 556,
- 'pinned': False,
- 'start_date': '2010-04-28',
- 'type': 'Task',
- 'upstream_tasks': []},
- {'content': 'Anm',
- 'dependency_violation': False,
- 'downstream_tasks': [{'type': 'Task', 'name': 'FX', 'id': 558}],
- 'due_date': '2010-05-14',
- 'id': 557,
- 'pinned': False,
- 'start_date': '2010-05-10',
- 'type': 'Task',
- 'upstream_tasks': [{'type': 'Task', 'name': 'Layout', 'id': 556}]},
- ...
-
-
-**********************************************************
-Creating a Dependency Violation by pushing up a Start Date
-**********************************************************
-
-Task Dependencies can work nicely if you are pushing out an end date for a Task as it will just
-recalculate the dates for all of the dependent Tasks. But what if we push up the Start Date of our
-"Anm" Task to start before our "Layout" Task is scheduled to end?
-
-::
-
- result = sg.update('Task', 557, {'start_date': '2010-05-06'})
-
-Returns::
-
- [{'type': 'Task', 'start_date': '2010-05-06', 'id': 557}]
-
-Our Tasks now look like this::
-
- [{'content': 'Layout',
- 'dependency_violation': False,
- 'downstream_tasks': [{'type': 'Task', 'name': 'Anm', 'id': 557}],
- 'due_date': '2010-05-07',
- 'id': 556,
- 'pinned': False,
- 'start_date': '2010-04-28',
- 'type': 'Task',
- 'upstream_tasks': []},
- {'content': 'Anm',
- 'dependency_violation': True,
- 'downstream_tasks': [{'type': 'Task', 'name': 'FX', 'id': 558}],
- 'due_date': '2010-05-12',
- 'id': 557,
- 'pinned': True,
- 'start_date': '2010-05-06',
- 'type': 'Task',
- 'upstream_tasks': [{'type': 'Task', 'name': 'Layout', 'id': 556}]},
- ...
-
-Because the "Anm" Task ``start_date`` depends on the ``due_date`` of the "Layout" Task, this
-change creates a dependency violation. The update succeeds, but Shotgun has also set the
-``dependency_violation`` field to ``True`` and has also updated the ``pinned`` field to ``True``.
-
-The ``pinned`` field simply means that if the upstream Task(s) are moved, the "Anm" Task will no
-longer get moved with it. The dependency is still there (in ``upstream_tasks``) but the Task is
-now "pinned" to those dates until the Dependency Violation is resolved.
-
-***********************************************************
-Resolving a Dependency Violation by updating the Start Date
-***********************************************************
-
-We don't want that violation there. Let's revert that change so the Start Date for "Anm" is after
-the End Date of "Layout"::
-
- result = sg.update('Task', 557, {'start_date': '2010-05-10'})
-
-Returns::
-
- [{'type': 'Task', 'start_date': '2010-05-10', 'id': 557}]
-
-Our Tasks now look like this::
-
- [{'content': 'Layout',
- 'dependency_violation': False,
- 'downstream_tasks': [{'type': 'Task', 'name': 'Anm', 'id': 557}],
- 'due_date': '2010-05-07',
- 'id': 556,
- 'pinned': False,
- 'start_date': '2010-04-28',
- 'type': 'Task',
- 'upstream_tasks': []},
- {'content': 'Anm',
- 'dependency_violation': False,
- 'downstream_tasks': [{'type': 'Task', 'name': 'FX', 'id': 558}],
- 'due_date': '2010-05-14',
- 'id': 557,
- 'pinned': True,
- 'start_date': '2010-05-10',
- 'type': 'Task',
- 'upstream_tasks': [{'type': 'Task', 'name': 'Layout', 'id': 556}]},
- ...
-
-The ``dependency_violation`` field has now been set back to ``False`` since there is no longer
-a violation. But notice that the ``pinned`` field is still ``True``. We will have to manually
-update that if we want the Task to travel with its dependencies again::
-
- result = sg.update('Task', 557, {'pinned': False})
-
-Returns::
-
- [{'pinned': False, 'type': 'Task', 'id': 557}]
-
-Our Tasks now look like this::
-
- [{'content': 'Layout',
- 'dependency_violation': False,
- 'downstream_tasks': [{'type': 'Task', 'name': 'Anm', 'id': 557}],
- 'due_date': '2010-05-07',
- 'id': 556,
- 'pinned': False,
- 'start_date': '2010-04-28',
- 'type': 'Task',
- 'upstream_tasks': []},
- {'content': 'Anm',
- 'dependency_violation': False,
- 'downstream_tasks': [{'type': 'Task', 'name': 'FX', 'id': 558}],
- 'due_date': '2010-05-14',
- 'id': 557,
- 'pinned': False,
- 'start_date': '2010-05-10',
- 'type': 'Task',
- 'upstream_tasks': [{'type': 'Task', 'name': 'Layout', 'id': 556}]},
- ...
-
-Looks great. But that's an annoying manual process. What if we want to just reset a Task so that
-it automatically gets updated so that the Start Date is after its dependent Tasks?
-
-*******************************************************************
-Updating the ``pinned`` field on a Task with a Dependency Violation
-*******************************************************************
-
-Let's go back a couple of steps to where our "Anm" Task had a Dependency Violation because we had
-moved the Start Date up before the "Layout" Task End Date. Remember that the ``pinned`` field
-was also ``True``. If we simply update the ``pinned`` field to be ``False``, Shotgun will also
-automatically update the Task dates to satisfy the upstream dependencies and reset the
-``dependency_violation`` value to ``False``::
-
- result = sg.update('Task', 557, {'pinned': False})
-
-Returns::
-
- [{'pinned': False, 'type': 'Task', 'id': 557}]
-
-
-Our Tasks now look like this::
-
- [{'content': 'Layout',
- 'dependency_violation': False,
- 'downstream_tasks': [{'type': 'Task', 'name': 'Anm', 'id': 557}],
- 'due_date': '2010-05-07',
- 'id': 556,
- 'pinned': False,
- 'start_date': '2010-04-28',
- 'type': 'Task',
- 'upstream_tasks': []},
- {'content': 'Anm',
- 'dependency_violation': False,
- 'downstream_tasks': [{'type': 'Task', 'name': 'FX', 'id': 558}],
- 'due_date': '2010-05-14',
- 'id': 557,
- 'pinned': False,
- 'start_date': '2010-05-10',
- 'type': 'Task',
- 'upstream_tasks': [{'type': 'Task', 'name': 'Layout', 'id': 556}]},
- ...
-
-
-Notice by updating ``pinned`` to ``False``, Shotgun also updated the ``start_date`` and
-``due_date`` fields of our "Anm" Task so it will satisfy the upstream Task dependencies. And since
-that succeeded, the ``dependency_violation`` field has also been set to ``False``
-
-*******************************************
-``dependency_violation`` field is read-only
-*******************************************
-
-The ``dependency_violation`` field is the only dependency-related field that is read-only. Trying
-to modify it will generate a Fault::
-
- result = sg.update('Task', 557, {'dependency_violation': False})
-
-Returns::
-
- # --------------------------------------------------------------------------------
- # XMLRPC Fault 103:
- # API update() Task.dependency_violation is read only:
- # {"value"=>false, "field_name"=>"dependency_violation"}
- # --------------------------------------------------------------------------------
- # Traceback (most recent call last):
- # ...
diff --git a/_sources/cookbook/tasks/updating_tasks.txt b/_sources/cookbook/tasks/updating_tasks.txt
deleted file mode 100644
index 445ecdfc6..000000000
--- a/_sources/cookbook/tasks/updating_tasks.txt
+++ /dev/null
@@ -1,386 +0,0 @@
-.. _updating_tasks:
-
-#######################################
-Updating Task Dates: How Shotgun Thinks
-#######################################
-
-When updating Task dates in an API update() request, there is no specified order to the values that
-are passed in. Shotgun also does automatic calculation of the``start_date``,``due_date``, and ``duration`` fields for convenience. In order to clarify how updates are handled by Shotgun we are
-providing some general rules below and examples of what will happen when you make updates to your
-Tasks.
-
-**************
-General Rules
-**************
-
-- Updating the ``start_date`` automatically updates the ``due_date`` (``duration`` remains constant)
-- Updating the ``due_date`` automatically updates the ``duration`` (``start_date`` remains constant)
-- Updating the ``duration`` automatically updates the ``due_date`` (``start_date`` remains constant)
-- When updating Task values, Shotgun sets schedule fields (``milestone``, ``duration``,
- ``start_date``, ``due_date``) after all other fields, because the Project and Task Assignees
- affect schedule calculations.
-- If ``start_date`` and ``due_date`` are both set, ``duration`` is ignored (``duration`` can often
- be wrong since it's easy to calculate scheduling incorrectly).
-- If both ``start_date`` and ``due_date`` are provided, Shotgun sets ``start_date`` before
- ``due_date``.
-- Set ``milestone`` before other schedule fields (because ``start_date``, ``due_date``, and
- ``duration`` get lost if ``milestone`` is not set to ``False`` first)
-- If ``milestone`` is being set to ``True``, ``duration`` is ignored.
-- If ``milestone`` is set to ``True`` and ``start_date`` and ``due_date`` are also being set to
- conflicting values, an Exception is raised.
-- If ``due_date`` and ``duration`` are set together (without ``start_date``), ``duration`` is set
- first, then ``due_date`` (otherwise setting ``duration`` will change ``due_date`` after it is
- set).
-
-********
-Examples
-********
-
-The following examples show what the resulting Task object will look like after being run on the
-initial Task object listed under the header of each section.
-
-The ``duration`` values in the following examples assume your Shotgun instance is set to
-10-hour work days. If your server is configured with a different setting, the ``duration`` values
-will vary.
-
-.. note:: The ``duration`` field stores ``duration`` values in minutes
-
-
-----
-
-.. rubric:: Universal
-
-Regardless of current values on the Task, this behavior rules::
-
- Task = {'start_date': '2011-05-20', 'due_date': '2011-05-25', 'duration': 2400, 'id':123}
-
-**Update start_date and due_date**
-
-``duration`` is ignored if also provided. It is instead set automatically as (``due_date`` -
-``start_date``)
-
-::
-
- sg.update ('Task', 123, {'start_date':'2011-05-25', 'due_date':'2011-05-30', 'duration':1200})
- # Task = {'start_date': '2011-05-25', 'due_date': '2011-05-30', 'duration': 2400, 'id':123}
-
-- ``start_date`` is updated.
-- ``due_date`` is updated.
-- ``duration`` is calculated as (``due_date`` - ``start_date``)
-
-.. note:: The value provided in the update() is ignored (and in this case was also incorrect).
-
-**Update start_date and duration**
-
-::
-
- sg.update ('Task', 123, {'start_date':'2011-05-25', 'duration':3600})
- # Task = {'start_date': '2011-05-25', 'due_date': '2011-06-01', 'duration': 3600, 'id':123}
-
-- ``start_date`` is updated.
-- ``duration`` is updated.
-- ``due_date`` is updated to (``start_date`` + ``duration``).
-
-**Update due_date and duration**
-
-::
-
- sg.update ('Task', 123, {'due_date': '2011-05-20', 'duration':3600})
- # Task = {'start_date': '2011-05-20', 'due_date': '2011-05-20', 'duration': 600, 'id':123}
-
-- ``duration`` is updated.
-- ``due_date`` is updated.
-- ``duration`` is calculated as (``due_date`` - ``start_date``)
-
-.. note:: This means the ``duration`` provided is overwritten.
-
-
-----
-
-.. rubric:: Task has start_date only
-
-If the Task only has a ``start_date`` value and has no other date values, this is how updates
-will behave.
-
-::
-
- Task = {'start_date': '2011-05-20', 'due_date': None, 'duration': None, 'id':123}
-
-**Update start_date**
-
-::
-
- sg.update ('Task', 123, {'start_date':'2011-05-25'})
- # Task = {'start_date': '2011-05-25', 'due_date': None, 'duration': None, 'id':123}
-
-- Only ``start_date`` is updated.
-
-**Update due_date**
-
-::
-
- sg.update ('Task', 123, {'due_date':'2011-05-25'})
- # Task = {'start_date': '2011-05-20', 'due_date': '2011-05-25', 'duration': 2400, 'id':123}
-
-- ``due_date`` is updated.
-- ``duration`` is updated to (``due_date`` - ``start_date``).
-
-**Update duration**
-
-::
-
- sg.update ('Task', 123, {'duration':2400})
- # Task = {'start_date': '2011-05-20', 'due_date': '2011-05-25', 'duration': 2400, 'id':123}
-
-- ``duration`` is updated.
-- ``due_date`` is set to (``start_date`` + ``duration``)
-
-
-----
-
-.. rubric:: Task has due_date only
-
-If the Task only has a ``due_date`` value and has no other date values, this is how updates
-will behave.
-
-::
-
- # Task = {'start_date': None, 'due_date': '2011-05-25', 'duration': None, 'id':123}
-
-**Update start_date**
-
-::
-
- sg.update ('Task', 123, {'start_date':'2011-05-20'})
- # Task = {'start_date': '2011-05-20', 'due_date': '2011-05-25', 'duration': 2400, 'id':123}
-
-- ``start_date`` is updated.
-- ``duration`` is updated to (``due_date`` - ``start_date``).
-
-**Update due_date**
-
-::
-
- sg.update ('Task', 123, {'due_date':'2011-05-20'})
- # Task = {'start_date': None, 'due_date': '2011-05-20', 'duration': None, 'id':123}
-
-- only ``due_date`` is updated.
-
-**Update duration**
-
-::
-
- sg.update ('Task', 123, {'duration':2400})
- # Task = {'start_date': '2011-05-20', 'due_date': '2011-05-25', 'duration': 2400, 'id':123}
-
-- ``duration`` is updated.
-- ``start_date`` is set to (``due_date`` - ``duration``)
-
-
-----
-
-.. rubric:: Task has duration only
-
-If the Task only has a ``duration`` value and has no other date values, this is how updates
-will behave.
-
-::
-
- # Task = {'start_date': None, 'due_date': None, 'duration': 2400, 'id':123}
-
-**Update start_date**
-
-::
-
- sg.update ('Task', 123, {'start_date':'2011-05-20'})
- # Task = {'start_date': '2011-05-20', 'due_date': '2011-05-25', 'duration': 2400, 'id':123}
-
-- ``start_date`` is updated.
-- ``due_date`` is updated to (``start_date`` + ``duration``).
-
-**Update due_date**
-
-::
-
- sg.update ('Task', 123, {'due_date':'2011-05-25'})
- # Task = {'start_date': '2011-05-20', 'due_date': '2011-05-25', 'duration': 2400, 'id':123}
-
-- ``due_date`` is updated.
-- ``start_date`` is updated to (``due_date`` - ``duration``)
-
-**Update duration**
-
-::
-
- sg.update ('Task', 123, {'duration':3600})
- # Task = {'start_date': None, 'due_date': None, 'duration': 3600, 'id':123}
-
-- only ``duration`` is updated.
-
-
-----
-
-.. rubric:: Task has start_date and due_date
-
-If the Task has ``start_date`` and ``due_date`` values but has no ``duration``, this is how updates
-will behave.
-
-::
-
- # Task = {'start_date': '2011-05-20', 'due_date': '2011-05-25', 'duration': None, 'id':123}
-
-**Update start_date**
-
-::
-
- sg.update ('Task', 123, {'start_date':'2011-05-25'})
- # Task = {'start_date': '2011-05-25', 'due_date': '2011-05-25', 'duration': 600, 'id':123}
-
-- ``start_date`` is updated.
-- ``duration`` is updated to (``due_date`` - ``start_date``).
-
-**Update due_date**
-
-::
-
- sg.update ('Task', 123, {'due_date':'2011-05-30'})
- # Task = {'start_date': '2011-05-20', 'due_date': '2011-05-30', 'duration': 4200, 'id':123}
-
-- ``due_date`` is updated.
-- ``duration`` is updated to (``due_date`` - ``start_date``)
-
-**Update duration**
-
-::
-
- sg.update ('Task', 123, {'duration':3600})
- # Task = {'start_date': '2011-05-20', 'due_date': '2011-05-27', 'duration': 3600, 'id':123}
-
-- ``duration`` is updated.
-- ``due_date`` is updated to (``start_date`` + ``duration``)
-
-
-----
-
-.. rubric:: Task has start_date and duration
-
-If the Task has ``start_date`` and ``duration`` values but has no ``due_date``, this is how updates
-will behave.
-
-::
-
- # Task = {'start_date': '2011-05-20', 'due_date': None, 'duration': 2400, 'id':123}
-
-**Update start_date**
-
-::
-
- sg.update ('Task', 123, {'start_date':'2011-05-25'})
- # Task = {'start_date': '2011-05-25', 'due_date': '2011-05-30', 'duration': 2400, 'id':123}
-
-- ``start_date`` is updated.
-- ``due_date`` is updated to (``start_date`` +``duration``).
-
-**Update due_date**
-
-::
-
- sg.update ('Task', 123, {'due_date':'2011-05-30'})
- # Task = {'start_date': '2011-05-20', 'due_date': '2011-05-30', 'duration': 4200, 'id':123}
-
-- ``due_date`` is updated.
-- ``duration`` is updated to (``due_date`` - ``start_date``).
-
-**Update duration**
-
-::
-
- sg.update ('Task', 123, {'duration':3600})
- # Task = {'start_date': '2011-05-20', 'due_date': '2011-05-27', 'duration': 3600, 'id':123}
-
-- ``duration`` is updated.
-- ``due_date`` is updated to (``start_date`` + ``duration``)
-
-
-----
-
-.. rubric:: Task has due_date and duration
-
-If the Task has ``due_date`` and ``duration`` values but has no ``start_date``, this is how updates
-will behave.
-
-::
-
- # Task = {'start_date': None, 'due_date': '2011-05-25', 'duration': 2400, 'id':123}
-
-**Update start_date**
-
-::
-
- sg.update ('Task', 123, {'start_date':'2011-05-25'})
- # Task = {'start_date': '2011-05-25', 'due_date': '2011-05-30', 'duration': 2400, 'id':123}
-
-- ``start_date`` is updated.
-- ``due_date`` is updated to (``start_date`` + ``duration``).
-
-**Update due_date**
-
-::
-
- sg.update ('Task', 123, {'due_date':'2011-05-30'})
- # Task = {'start_date': '2011-05-25', 'due_date': '2011-05-30', 'duration': 2400, 'id':123}
-
-- ``due_date`` is updated.
-- ``start_date`` is updated to (``due_date`` - ``duration``).
-
-**Update duration**
-
-::
-
- sg.update ('Task', 123, {'duration':3600})
- # Task = {'start_date': '2011-05-18', 'due_date': '2011-05-25', 'duration': 3600, 'id':123}
-
-- ``duration`` is updated.
-- ``start_date`` is updated to (``due_date`` - ``duration``)
-
-
-----
-
-.. rubric:: Task has start_date ,due_date, and duration
-
-If the Task has ``start_date``, ``due_date``, and ``duration``, this is how updates
-will behave.
-
-::
-
- # Task = {'start_date': '2011-05-20', 'due_date': '2011-05-25', 'duration': 2400, 'id':123}
-
-**Update start_date**
-
-::
-
- sg.update ('Task', 123, {'start_date':'2011-05-25'})
- # Task = {'start_date': '2011-05-20', 'due_date': '2011-05-30', 'duration': 2400, 'id':123}
-
-- ``start_date`` is updated.
-- ``due_date`` is updated to (``start_date`` + ``duration``).
-
-**Update due_date**
-
-::
-
- sg.update ('Task', 123, {'due_date':'2011-05-30'})
- # Task = {'start_date': '2011-05-20', 'due_date': '2011-05-30', 'duration': 4200, 'id':123}
-
-- ``due_date`` is updated.
-- ``duration`` is updated to (``due_date`` - ``start_date``)
-
-**Update duration**
-
-::
-
- sg.update ('Task', 123, {'duration':3600})
- # Task = {'start_date': '2011-05-20', 'due_date': '2011-05-27', 'duration': 3600, 'id':123}
-
-- ``duration`` is updated.
-- ``due_date`` is updated to (``start_date`` + ``duration``)
\ No newline at end of file
diff --git a/_sources/cookbook/tutorials.txt b/_sources/cookbook/tutorials.txt
deleted file mode 100644
index 2eb2e0d4d..000000000
--- a/_sources/cookbook/tutorials.txt
+++ /dev/null
@@ -1,33 +0,0 @@
-########
-Examples
-########
-
-Here's a list of various simple tutorials to walk through that should provide you with a good base
-understanding of how to use the Shotgun API and what you can do with it.
-
-*****
-Basic
-*****
-
-.. toctree::
- :maxdepth: 1
-
- examples/basic_sg_instance
- examples/basic_create_shot
- examples/basic_find_shot
- examples/basic_update_shot
- examples/basic_delete_shot
- examples/basic_create_shot_task_template
- examples/basic_create_version_link_shot
- examples/basic_upload_thumbnail_version
-
-********
-Advanced
-********
-
-.. toctree::
- :maxdepth: 1
-
- examples/ami_handler
- examples/ami_version_packager
- examples/svn_integration
diff --git a/_sources/cookbook/usage_tips.txt b/_sources/cookbook/usage_tips.txt
deleted file mode 100644
index 8a909f7fc..000000000
--- a/_sources/cookbook/usage_tips.txt
+++ /dev/null
@@ -1,302 +0,0 @@
-##############
-API Usage Tips
-##############
-
-Below is a list of helpful tips when using the Shotgun API. We have tried to make the API very
-simple to use with predictable results while remaining a powerful tool to integrate with your
-pipeline. However, there's always a couple of things that crop up that our users might not be
-aware of. Those are the types of things you'll find below. We'll be adding to this document over
-time as new questions come up from our users that exhibit these types of cases.
-
-*********
-Importing
-*********
-
-We strongly recommend you import the entire `shotgun_api3` module instead of just importing the
-:class:`shotgun_api3.Shotgun` class from the module. There is other important functionality that
-is managed at the module level which may not work as expected if you only import the
-:class:`shotgun_api3.Shotgun` object.
-
-Do::
-
- import shotgun_api3
-
-Don't::
-
- from shotgun_api3 import Shotgun
-
-***************
-Multi-threading
-***************
-The Shotgun API is not thread-safe. If you want to do threading we strongly suggest that you use
-one connection object per thread and not share the connection.
-
-*************
-Entity Fields
-*************
-
-When you do a :meth:`~shotgun_api3.Shotgun.find` call that returns a field of type entity or
-multi-entity (for example the 'assets' column on Shot), the entities are returned in a standard
-dictionary::
-
- {'type': 'Asset', 'name': 'redBall', 'id': 1}
-
-For each entity returned, you will get a ``type``, ``name``, and ``id`` key. This does not mean
-there are fields named ``type`` and ``name`` on the Asset. These are only used to provide a
-consistent way to represent entities returned via the API.
-
-- ``type``: the entity type (CamelCase)
-- ``name``: the display name of the entity. For most entity types this is the value of the ``code``
- field but not always. For example, on the Ticket and Delivery entities the ``name`` key would
- contain the value of the ``title`` field.
-
-.. _custom_entities:
-
-**************
-CustomEntities
-**************
-Entity types are always referenced by their original names. So if you enable CustomEntity01 and
-call it **Widget**. When you access it via the API, you'll still use CustomEntity01 as the
-``entity_type``.
-
-If you want to be able to remember what all of your CustomEntities represent in a way where you
-don't need to go look it up all the time when you're writing a new script, we'd suggest creating
-a mapping table or something similar and dumping it in a shared module that your studio uses.
-Something like the following::
-
- # studio_globals.py
-
- entity_type_map = {
- 'Widget': 'CustomEntity01',
- 'Foobar': 'CustomEntity02',
- 'Baz': 'CustomNonProjectEntity01,
- }
-
- # or even simpler, you could use a global like this
- ENTITY_WIDGET = 'CustomEntity01'
- ENTITY_FOOBAR = 'CustomEntity02'
- ENTITY_BAZ = 'CustomNonProjectEntity01'
-
-Then when you're writing scripts, you don't need to worry about remembering which Custom Entity
-"Foobars" are, you just use your global::
-
- import shotgun_api3
- import studio_globals
-
- sg = Shotgun('https://mystudio.shotgunstudio.com', 'script_name', '0123456789abcdef0123456789abcdef0123456')
- result = sg.find(studio_globals.ENTITY_WIDGET,
- filters=[['sg_status_list', 'is', 'ip']],
- fields=['code', 'sg_shot'])
-
-.. _connection_entities:
-
-******************
-ConnectionEntities
-******************
-
-Connection entities exist behind the scenes for any many-to-many relationship. Most of the time
-you won't need to pay any attention to them. But in some cases, you may need to track information
-on the instance of one entity's relationship to another.
-
-For example, when viewing a list of Versions on a Playlist, the Sort Order (``sg_sort_order``) field is an
-example of a field that resides on the connection entity between Playlists and Versions. This
-connection entity is appropriately called `PlaylistVersionConnection`. Because any Version can
-exist in multiple Playlists, the sort order isn't specific to the Version, it's specific to
-each _instance_ of the Version in a Playlist. These instances are tracked using connection
-entities in Shtogun and are accessible just like any other entity type in Shotgun.
-
-To find information about your Versions in the Playlist "Director Review" (let's say it has an
-``id`` of 4). We'd run a query like so::
-
- filters = [['playlist', 'is', {'type':'Playlist', 'id':4}]]
- fields = ['playlist.Playlist.code', 'sg_sort_order', 'version.Version.code', 'version.Version.user', 'version.Version.entity']
- order=[{'column':'sg_sort_order','direction':'asc'}]
- result = sg.find('PlaylistVersionConnection', filters, fields, order)
-
-
-Which returns the following::
-
- [{'id': 28,
- 'playlist.Playlist.code': 'Director Review',
- 'sg_sort_order': 1.0,
- 'type': 'PlaylistVersionConnection',
- 'version.Version.code': 'bunny_020_0010_comp_v003',
- 'version.Version.entity': {'id': 880,
- 'name': 'bunny_020_0010',
- 'type': 'Shot'},
- 'version.Version.user': {'id': 19, 'name': 'Artist 1', 'type': 'HumanUser'}},
- {'id': 29,
- 'playlist.Playlist.code': 'Director Review',
- 'sg_sort_order': 2.0,
- 'type': 'PlaylistVersionConnection',
- 'version.Version.code': 'bunny_020_0020_comp_v003',
- 'version.Version.entity': {'id': 881,
- 'name': 'bunny_020_0020',
- 'type': 'Shot'},
- 'version.Version.user': {'id': 12, 'name': 'Artist 8', 'type': 'HumanUser'}},
- {'id': 30,
- 'playlist.Playlist.code': 'Director Review',
- 'sg_sort_order': 3.0,
- 'type': 'PlaylistVersionConnection',
- 'version.Version.code': 'bunny_020_0030_comp_v003',
- 'version.Version.entity': {'id': 882,
- 'name': 'bunny_020_0030',
- 'type': 'Shot'},
- 'version.Version.user': {'id': 33, 'name': 'Admin 5', 'type': 'HumanUser'}},
- {'id': 31,
- 'playlist.Playlist.code': 'Director Review',
- 'sg_sort_order': 4.0,
- 'type': 'PlaylistVersionConnection',
- 'version.Version.code': 'bunny_020_0040_comp_v003',
- 'version.Version.entity': {'id': 883,
- 'name': 'bunny_020_0040',
- 'type': 'Shot'},
- 'version.Version.user': {'id': 18, 'name': 'Artist 2', 'type': 'HumanUser'}},
- {'id': 32,
- 'playlist.Playlist.code': 'Director Review',
- 'sg_sort_order': 5.0,
- 'type': 'PlaylistVersionConnection',
- 'version.Version.code': 'bunny_020_0050_comp_v003',
- 'version.Version.entity': {'id': 884,
- 'name': 'bunny_020_0050',
- 'type': 'Shot'},
- 'version.Version.user': {'id': 15, 'name': 'Artist 5', 'type': 'HumanUser'}}]
-
-
-- ``version`` is the Version record for this connection instance.
-- ``playlist`` is the Playlist record for this connection instance.
-- ``sg_sort_order`` is the sort order field on the connection instance.
-
-We can pull in field values from the linked Playlist and Version entities using dot notation like
-``version.Version.code``. The syntax is ``fieldname.EntityType.fieldname``. In this example,
-``PlaylistVersionConnection`` has a field named ``version``. That field contains a ``Version``
-entity. The field we are interested on the Version is ``code``. Put those together with our f
-riend the dot and we have ``version.Version.code``.
-
-*******************************************
-Shotgun UI fields not available via the API
-*******************************************
-
-Summary type fields like Query Fields and Pipeline Step summary fields are currently only available
-via the UI. Some other fields may not work as expected through the API because they are "display
-only" fields made available for convenience and are only available in the browser UI.
-
-HumanUser
-=========
-
-- ``name``: This is a UI-only field that is a combination of the ``firstname`` + ``' '`` +
- ``lastname``.
-
-Shot
-====
-
-**Smart Cut Fields**: These fields are available only in the browser UI. You can read more about
-smart cut fields and the API in the :ref:`Smart Cut Fields doc `::
-
- smart_cut_in
- smart_cut_out
- smart_cut_duration
- smart_cut_summary_display
- smart_duration_summary_display
- smart_head_in
- smart_head_out
- smart_head_duration
- smart_tail_in
- smart_tail_out
- smart_tail_duration
- smart_working_duration
-
-
-Pipeline Step summary fields on entities
-========================================
-
-The Pipeline Step summary fields on entities that have Tasks aren't currently available via the API
-and are calculated on the client side in the UI. These fields are like ``step_0``, or ``step_13``.
-Note that the Pipeline Step entity itself is available via the API as the entity type ``Step``.
-
-Query Fields
-============
-
-Query fields are also summary fields like Pipeline Steps, the query is run from the client side UI
-and therefore is not currently supported in the API.
-
-************
-Audit Fields
-************
-You can set the ``created_by`` and ``created_at`` fields via the API at creation time. This is
-often useful for when you're importing or migrating data from another source and want to keep the
-history in tact. However, you cannot set the ``updated_by`` and ``updated_at`` fields. These are
-automatically set whenever an entity is created or updated.
-
-.. _logging:
-
-*****************************
-Logging Messages from the API
-*****************************
-
-The API uses standard python logging but does not define a handler.
-
-To see the logging output in stdout, define a streamhandler in your script::
-
- import logging
- import shotgun_api3 as shotgun
- logging.basicConfig(level=logging.DEBUG)
-
-To write logging output from the shotgun API to a file, define a file handler in your script::
-
- import logging
- import shotgun_api3 as shotgun
- logging.basicConfig(level=logging.DEBUG, filename='/path/to/your/log')
-
-To suppress the logging output from the API in a script which uses logging, set the level of the
-Shotgun logger to a higher level::
-
- import logging
- import shotgun_api3 as shotgun
- sg_log = logging.getLogger('shotgun_api3')
- sg_log.setLevel(logging.ERROR)
-
-*************
-Optimizations
-*************
-
-Combining Related Queries
-=========================
-Reducing round-trips for data via the API can significantly improve the speed of your application.
-Much like "Bubble Fields" / "Field Hopping" in the UI, we can poll Shotgun for data on the fields
-of entities linked to our main query, both as a part of the query parameters as well as in the
-data returned.
-
-Starting with a simple and common example, many queries require knowing what project your data is
-associated with. Without using "field hopping" in an API call, you would first get the project and
-then use that data for your follow up query, like so::
-
- # Get the project
- project_name = 'Big Buck Bunny'
- sg_project = sg.find("Project", [['name', 'is', project_name]])
-
- # Use project result to get associated shots
- sg_shots = sg.find("Shot", [['project', 'is', sg_project]], ['code'])
-
-With "field hopping" you can combine these queries into::
-
- # Get all shots on 'Big Buck Bunny' project
- project_name = 'Big Buck Bunny'
- sg_shots = sg.find("Shot", [['project.Project.name', 'is', project_name]], ['code'])
-
-As you can see above, the syntax is to use "``.``" dot notation, joining field names to entity
-types in a chain. In this example we start with the field ``project`` on the Shot entity, then
-specify we're looking for the "name" field on the Project entity by specifying ``Project.name``.
-
-Now that we've demonstrated querying using dot notation, let's take a look at returning linked data
-by adding the status of each Sequence entity associated with each Shot in our previous query::
-
- # Get shot codes and sequence status all in one query
- project_name = 'Big Buck Bunny'
- sg_shots = sg.find("Shot", [['project.Project.name', 'is', project_name]],
- ['code', 'sg_sequence.Sequence.sg_status_list'])
-
-.. note::
- Due to performance concerns with deep linking, we only support using dot syntax chains for
- single-entity relationships. This means that if you try to pull data through a multi-entity
- field you will not get the desired result.
\ No newline at end of file
diff --git a/_sources/data_types.txt b/_sources/data_types.txt
deleted file mode 100644
index 2e136b4fd..000000000
--- a/_sources/data_types.txt
+++ /dev/null
@@ -1,241 +0,0 @@
-.. _data_types:
-
-##########
-Data Types
-##########
-
-
-**********
-addressing
-**********
-
-:value: :obj:`list`
-
-List of dicts::
-
- [
- {
- 'type': 'HumanUser' | 'Group',
- 'id': int,
- ...
- },
- ...
- ]
-
-
-********
-checkbox
-********
-
-:value: :obj:`bool` (``True`` | ``False``)
-
-*****
-color
-*****
-
-:value: :obj:`str`
-:example: ``255,0,0`` | ``pipeline_step``
-
-``pipeline_step`` indicates the Task color inherits from the Pipeline Step color.
-
-********
-currency
-********
-
-:value: :obj:`float` | :obj:`None`
-:range: ``-9999999999999.99``, ``9999999999999.99``
-
-****
-date
-****
-
-:value: :obj:`str` | :obj:`None`
-:range: Year must be >= 1970
-:example: ``YYYY-MM-DD``
-
-*********
-date_time
-*********
-
-:value: :mod:`datetime` | :obj:`None`
-:range: Year must be >= 1970
-
- .. note::
- Datetimes are stored as UTC on the server. The Shotgun API is configured to automatically
- convert between client local time and UTC. This can be overridden.
-
-********
-duration
-********
-
-:value: :obj:`int` | :obj:`None`
-:range: ``-2147483648``, ``2147483647``
-
-Length of time, in minutes
-
-******
-entity
-******
-
-:value: :obj:`dict` | :obj:`None`
-
-::
-
- {
- 'type': "string",
- 'id': int,
- ...
- }
-
-*****
-float
-*****
-
-:value: :obj:`float` | :obj:`None`
-:range: ``-999999999.999999``, ``999999999.999999``
-
-*******
-footage
-*******
-
-:value: :obj:`str` | :obj:`None` ``FF-ff``
-:range: Frames must be < Preferences value for "Advanced > Number of frames per foot of film"
-
- .. note::
- Format matches Preference value for "Formatting > Display of footage fields".
- Example above is default.F=Feet f=Frames.
-
-*****************
-image (read-only)
-*****************
-
-:value: :obj:`str` | :obj:`None`
-
-****
-list
-****
-
-:value: :obj:`str` | :obj:`None`
-
-************
-multi_entity
-************
-
-:value: :obj:`list`
-
-List of dicts
-
-::
-
- [
- {
- 'type': "string",
- 'id': int,
- ...
- },
- ...
- ]
-
-******
-number
-******
-
-:value: :obj:`int` | ``None``
-:range: ``-2147483648``, ``2147483647``
-
-********
-password
-********
-
-:value: :obj:`string` | ``None``
-
-Returned values of password fields are replaced with ``*******`` for security
-
-*******
-percent
-*******
-
-:value: :obj:`int` | ``None``
-:range: ``-2147483648``, ``2147483647``
-
-************
-serializable
-************
-
-:value: :obj:`dict` | ``None``
-
-***********
-status_list
-***********
-
-:value: :obj:`str` | ``None``
-
-*****************************
-system_task_type (deprecated)
-*****************************
-
-:value: :obj:`str` | ``None``
-
-********
-tag_list
-********
-
-:value: :obj:`list`
-
-********
-text
-********
-
-:value: :obj:`str` | ``None``
-
-********
-timecode
-********
-
-:value: :obj:`int` | ``None``
-:range: ``-2147483648``, ``2147483647``
-
-Length of time, in milliseconds (1000 = 1 second)
-
-*********************
-url (file/link field)
-*********************
-
-:value: :obj:`dict` | ``None``
-
-::
-
- {
- 'content_type': "string",
- 'link_type': "local" | "url" | "upload",
- 'name': "string",
- 'url': "string"
- }
-
-Local File Links
-================
-
-Additional keys exist for local file links
-
-:value: :obj:`dict` | ``None``
-
-::
-
- {
- 'content_type': "string",
- 'link_type': "local",
- 'local_path': "string" | None,
- 'local_path_linux': "string" | None,
- 'local_path_mac': "string" | None,
- 'local_path_windows': "string" | None,
- 'local_storage': {dictionary},
- 'name': "string",
- 'url': "string",
- }
- API versions < v3.0.3:
-
- {
- 'url': "string",
- 'name': "string",
- 'content_type': "string"
- }
\ No newline at end of file
diff --git a/_sources/event_types.txt b/_sources/event_types.txt
deleted file mode 100644
index 9ea1f37c2..000000000
--- a/_sources/event_types.txt
+++ /dev/null
@@ -1,81 +0,0 @@
-.. _event_types:
-
-###########
-Event Types
-###########
-
-Shotgun generates read-only EventLogEntries for every destructive action performed by a user. And
-by "destructive", we simply mean an action that updates the database somehow, not some tantrum
-that a user has (hopefully). Shotgun also logs some additional useful events that to help keep
-track of activity on your Shotgun instance.
-
-************************
-Structure of Event Types
-************************
-
-The basic structure of event types is broken into 3 parts:
-
-``Application_EntityType_Action``
-
-- ``Application``: Is always "Shotgun" for events automatically created by the Shotgun server.
- Other Shotgun products may use their name in here, for example, Toolkit has its own events
- that it logs and the application portion is identified by "Toolkit". If you decide to use the
- EventLogEntry entity to log events for your scripts or tools, you would use your tool name here.
-- ``EntityType``: This is the entity type in Shotgun that was acted upon (eg. Shot, Asset, etc.)
-- ``Action``: The general action that was taken. (eg. New, Change, Retirement, Revival)
-
-
-********************
-Standard Event Types
-********************
-
-Each entity type has a standard set of events associated with it when it's created, updated,
-deleted, and revived. They follow this pattern:
-
-- ``Shotgun_EntityType_New``: a new entity was created. Example: ``Shotgun_Task_New``
-- ``Shotgun_EntityType_Change``: an entity was modified. Example: ``Shotgun_HumanUser_Change``
-- ``Shotgun_EntityType_Retirement``: an entity was deleted. Example: ``Shotgun_Ticket_Retirement``
-- ``Shotgun_EntityType_Revival``: an entity was revived. Example: ``Shotgun_CustomEntity03_Revival``
-
-**********************
-Additional Event Types
-**********************
-
-These are _some_ of the additional event types that are logged by Shotgun:
-
-- ``Shotgun_Attachment_View``: an Attachment (file) was viewed by a user.
-- ``Shotgun_Reading_Change``: a threaded entity has been marked read or unread. For example, a
- Note was read by a user. The readings are unique to the entity<->user connection so when a
- Note is read by user "joe" it may still be unread by user "jane".
-- ``Shotgun_User_Login``: a user logged in to Shotgun.
-- ``Shotgun_User_Logout``: a user logged out of Shotgun.
-
-
-******************
-Custom Event Types
-******************
-
-Since ``EventLogEntries`` are entities themselves, you can create them using the API just like any
-other entity type. As mentioned previously, if you'd like to have your scripts or tools log to
-the Shotgun event log, simply devise a thoughtful naming structure for your event types and
-create the EventLogEntry as needed following the usual methods for creating entities via the API.
-
-Again, other Shotgun products like Toolkit use event logs this way.
-
-.. note::
- EventLogEntries cannot be updated or deleted (that would defeat the purpose of course).
-
-***********
-Performance
-***********
-
-Event log database tables can get large very quickly. While Shotgun does very well with event logs
-that get into the millions of records, there's an inevitable degradation of performance for pages
-that display them in the web application as well as any API queries for events when they get too
-big. This volume of events is not the norm, but can be reached if your server expereinces high
-usage.
-
-This **does not** mean your Shotgun server performance will suffer in general, just any pages that
-are specifically displaying EventLogEntries in the web application, or API queries on the event
-log that are run. We are always looking for ways to improve this in the future. If you have any
-immediate concerns, please `reach out to our support team `_
diff --git a/_sources/examples/ami_handler.txt b/_sources/examples/ami_handler.txt
deleted file mode 100644
index d4b88f006..000000000
--- a/_sources/examples/ami_handler.txt
+++ /dev/null
@@ -1,246 +0,0 @@
-.. _ami_handler:
-
-###############################
-Handling Action Menu Item Calls
-###############################
-
-This is an example ActionMenu Python class to handle the ``GET`` request sent from an
-ActionMenuItem. It doesn't manage dispatching custom protocols but rather takes the arguments
-from any ``GET`` data and parses them into the easily accessible and correctly typed instance
-variables for your Python scripts.
-
-Available as a Gist at https://gist.github.com/3253287
-
-.. seealso::
- Our `support site has more information about Action Menu Items
- `_.
-
-************
-GET vs. POST
-************
-
-Action Menu Items that open a url via `http` or `https` to another web server send their data
-via ``POST``. If you're using a custom protocol the data is sent via ``GET``.
-
-.. note::
- Browsers limit the length of a ``GET`` request. If you exceed this limit by attempting to
- select a lot of rows and launch your custom protocol, you may encounter
- "Failed to load resource" errors in your console.
-
-.. seealso::
- This `Stack Overflow article "What is the maximum length of a URL in different browsers?"
- `_
-
-::
-
- #!/usr/bin/env python
- # encoding: utf-8
-
- # ---------------------------------------------------------------------------------------------
- # Description
- # ---------------------------------------------------------------------------------------------
- """
- The values sent by the Action Menu Item are in the form of a GET request that is similar to the
- format: myCoolProtocol://doSomethingCool?user_id=24&user_login=shotgun&title=All%20Versions&...
-
- In a more human-readable state that would translate to something like this:
- {
- 'project_name': 'Demo Project',
- 'user_id': '24',
- 'title': 'All Versions',
- 'user_login': 'shotgun',
- 'sort_column': 'created_at',
- 'entity_type': 'Version',
- 'cols': 'created_at',
- 'ids': '5,2',
- 'selected_ids': '2,5',
- 'sort_direction': 'desc',
- 'project_id': '4',
- 'session_uuid': 'd8592bd6-fc41-11e1-b2c5-000c297a5f50',
- 'column_display_names':
- [
- 'Version Name',
- 'Thumbnail',
- 'Link',
- 'Artist',
- 'Description',
- 'Status',
- 'Path to frames',
- 'QT',
- 'Date Created'
- ]
- }
-
- This simple class parses the url into easy to access types variables from the parameters,
- action, and protocol sections of the url. This example url
- myCoolProtocol://doSomethingCool?user_id=123&user_login=miled&title=All%20Versions&...
- would be parsed like this:
-
- (string) protocol: myCoolProtocol
- (string) action: doSomethingCool
- (dict) params: user_id=123&user_login=miled&title=All%20Versions&...
-
- The parameters variable will be returned as a dictionary of string key/value pairs. Here's
- how to instantiate:
-
- sa = ShotgunAction(sys.argv[1]) # sys.argv[1]
-
- sa.params['user_login'] # returns 'miled'
- sa.params['user_id'] # returns 123
- sa.protocol # returns 'myCoolProtocol'
- """
-
-
- # ---------------------------------------------------------------------------------------------
- # Imports
- # ---------------------------------------------------------------------------------------------
- import sys, os
- import urllib
- import logging as logger
-
- from pprint import pprint
-
- # ---------------------------------------------------------------------------------------------
- # Variables
- # ---------------------------------------------------------------------------------------------
- # location to write logfile for this script
- # logging is a bit of overkill for this class, but can still be useful.
- logfile = os.path.dirname(sys.argv[0])+"/shotgun_action.log"
-
-
- # ----------------------------------------------
- # Generic ShotgunAction Exception Class
- # ----------------------------------------------
- class ShotgunActionException(Exception):
- pass
-
-
- # ----------------------------------------------
- # ShotgunAction Class to manage ActionMenuItem call
- # ----------------------------------------------
- class ShotgunAction():
-
- def __init__(self, url):
- self.logger = self._init_log(logfile)
- self.url = url
- self.protocol, self.action, self.params = self._parse_url()
-
- # entity type that the page was displaying
- self.entity_type = self.params['entity_type']
-
- # Project info (if the ActionMenuItem was launched from a page not belonging
- # to a Project (Global Page, My Page, etc.), this will be blank
- if 'project_id' in self.params:
- self.project = { 'id':int(self.params['project_id']), 'name':self.params['project_name'] }
- else:
- self.project = None
-
- # Internal column names currently displayed on the page
- self.columns = self.params['cols']
-
- # Human readable names of the columns currently displayed on the page
- self.column_display_names = self.params['column_display_names']
-
- # All ids of the entities returned by the query (not just those visible on the page)
- self.ids = []
- if len(self.params['ids']) > 0:
- ids = self.params['ids'].split(',')
- self.ids = [int(id) for id in ids]
-
- # All ids of the entities returned by the query in filter format ready
- # to use in a find() query
- self.ids_filter = self._convert_ids_to_filter(self.ids)
-
- # ids of entities that were currently selected
- self.selected_ids = []
- if len(self.params['selected_ids']) > 0:
- sids = self.params['selected_ids'].split(',')
- self.selected_ids = [int(id) for id in sids]
-
- # All selected ids of the entities returned by the query in filter format ready
- # to use in a find() query
- self.selected_ids_filter = self._convert_ids_to_filter(self.selected_ids)
-
- # sort values for the page
- # (we don't allow no sort anymore, but not sure if there's legacy here)
- if 'sort_column' in self.params:
- self.sort = { 'column':self.params['sort_column'], 'direction':self.params['sort_direction'] }
- else:
- self.sort = None
-
- # title of the page
- self.title = self.params['title']
-
- # user info who launched the ActionMenuItem
- self.user = { 'id':self.params['user_id'], 'login':self.params['user_login']}
-
- # session_uuid
- self.session_uuid = self.params['session_uuid']
-
- # ----------------------------------------------
- # Set up logging
- # ----------------------------------------------
- def _init_log(self, filename="shotgun_action.log"):
- try:
- logger.basicConfig(level=logger.DEBUG,
- format='%(asctime)s %(levelname)-8s %(message)s',
- datefmt='%Y-%b-%d %H:%M:%S',
- filename=filename,
- filemode='w+')
- except IOError, e:
- raise ShotgunActionException ("Unable to open logfile for writing: %s" % e)
- logger.info("ShotgunAction logging started.")
- return logger
-
-
- # ----------------------------------------------
- # Parse ActionMenuItem call into protocol, action and params
- # ----------------------------------------------
- def _parse_url(self):
- logger.info("Parsing full url received: %s" % self.url)
-
- # get the protocol used
- protocol, path = self.url.split(":", 1)
- logger.info("protocol: %s" % protocol)
-
- # extract the action
- action, params = path.split("?", 1)
- action = action.strip("/")
- logger.info("action: %s" % action)
-
- # extract the parameters
- # 'column_display_names' and 'cols' occurs once for each column displayed so we store it as a list
- params = params.split("&")
- p = {'column_display_names':[], 'cols':[]}
- for arg in params:
- key, value = map(urllib.unquote, arg.split("=", 1))
- if key == 'column_display_names' or key == 'cols' :
- p[key].append(value)
- else:
- p[key] = value
- params = p
- logger.info("params: %s" % params)
- return (protocol, action, params)
-
-
- # ----------------------------------------------
- # Convert IDs to filter format to us in find() queries
- # ----------------------------------------------
- def _convert_ids_to_filter(self, ids):
- filter = []
- for id in ids:
- filter.append(['id','is',id])
- logger.debug("parsed ids into: %s" % filter)
- return filter
-
-
- # ----------------------------------------------
- # Main Block
- # ----------------------------------------------
- if __name__ == "__main__":
- try:
- sa = ShotgunAction(sys.argv[1])
- logger.info("ShotgunAction: Firing... %s" % (sys.argv[1]) )
- except IndexError, e:
- raise ShotgunActionException("Missing GET arguments")
- logger.info("ShotgunAction process finished.")
diff --git a/_sources/examples/ami_version_packager.txt b/_sources/examples/ami_version_packager.txt
deleted file mode 100644
index f0b08b942..000000000
--- a/_sources/examples/ami_version_packager.txt
+++ /dev/null
@@ -1,257 +0,0 @@
-.. _ami_version_packager:
-
-########################################################
-Using an ActionMenuItem to Package Versions for a Client
-########################################################
-
-This is an example script to demonstrate how you can use an ActionMenuItem to launch a local
-script to package up files for a client. It performs the following:
-
-- Downloads Attachments from a specified field for all selected entities.
-- Creates an archive.
-- Copies the archive to a specified directory.
-
-It is intended to be used in conjunction with the script dicussed in :ref:`ami_handler`.
-
-::
-
- #!/usr/bin/env python
- # encoding: utf-8
- """
- version_packager.py
-
- This example script is meant to be run from an ActionMenuItem in Shotgun. The menu item uses a custom
- protocol in order to launch this script, and is followed by the action 'package4client'. So the full
- url would be something like launchme://package4client?.... See:
- http://support.shotgunsoftware.com/hc/en-us/articles/219031318-Creating-custom-Action-Menu-Items
-
- It uses the example ActionMenu Python class also located in our docs for parsing the ActionMenuItem
- POST variables. For more information about it and accessing the variables in the ActionMenuItem POST request,
- See: http://developer.shotgunsoftware.com/python-api/examples/ami_handler
-
- The purpose of this script is to download attachment files from Shotgun, create an archive of them
- and copy them to a specified directory. You can invoke it with the following minimal example to connect
- to Shotgun, download any file that exists in the specified field ('sg_qt') for each selected_id passed from the
- ActionMenu. Then it will create a single archive of the files and move it to the specified directory
- ('/path/where/i/want/to/put/the/archive/'). The archive is named with the Project Name, timestamp, and user
- login who ran the ActionMenuItem ('Demo_Project_2010-04-29-172210_kp.tar.gz'):
-
- sa = ShotgunAction(sys.argv[1])
- sg = shotgun_connect()
- if sa.action == 'package4client':
- r = packageFilesForClient('sg_qt','/path/where/i/want/to/put/the/archive/')
-
- """
-
- # ---------------------------------------------------------------------------------------------
- # Imports
- # ---------------------------------------------------------------------------------------------
- import sys, os
- import logging as logger
- import subprocess
- import re
- from datetime import datetime
-
- from shotgun_api3 import Shotgun
- from shotgun_action import ShotgunAction
- from pprint import pprint
-
- # ---------------------------------------------------------------------------------------------
- # Variables
- # ---------------------------------------------------------------------------------------------
- # Shotgun server auth info
- shotgun_conf = {
- 'url':'https://YOURSTUDIO.shotgunstudio.com',
- 'name':'YOUR_SCRIPT_NAME_HERE',
- 'key':'YOUR_SCRIPT_KEY_HERE'
- }
-
- # location to write logfile for this script
- logfile = os.path.dirname(sys.argv[0])+"/version_packager.log"
-
- # temporary directory to download movie files to and create thumbnail files in
- file_dir = os.path.dirname(sys.argv[0])+"/tmp"
-
- # compress command
- # tar czf /home/user/backup_www.tar.gz -C / var/www/html
- compress_cmd = "tar czf %s -C / %s"
-
-
-
- # ----------------------------------------------
- # Generic Shotgun Exception Class
- # ----------------------------------------------
- class ShotgunException(Exception):
- pass
-
-
-
- # ----------------------------------------------
- # Set up logging
- # ----------------------------------------------
- def init_log(filename="version_packager.log"):
- try:
- logger.basicConfig(level=logger.DEBUG,
- format='%(asctime)s %(levelname)-8s %(message)s',
- datefmt='%Y-%b-%d %H:%M:%s',
- filename=filename,
- filemode='w+')
- except IOError, e:
- raise ShotgunException ("Unable to open logfile for writing: %s" % e)
- logger.info("Version Packager logging started.")
- return logger
-
-
- # ----------------------------------------------
- # Extract Attachment id from entity field
- # ----------------------------------------------
- def extract_attachment_id(attachment):
- # extract the Attachment id from the url location
- attachment_id = attachment['url'].rsplit('/',1)[1]
- try:
- attachment_id = int(attachment_id)
- except:
- # not an integer.
- return None
- # raise ShotgunException("invalid Attachment id returned. Expected an integer: %s "% attachment_id)
-
- return attachment_id
-
-
- # ----------------------------------------------
- # Download Movie to Disk
- # ----------------------------------------------
- def download_attachment_to_disk(attachment,destination_filename):
- attachment_id = extract_attachment_id(attachment)
- if type(attachment_id) != int:
- return None
- # download the attachment file from Shotgun and write it to local disk
- logger.info("Downloading Attachment #%s" % (attachment_id))
- stream = sg.download_attachment(attachment_id)
- try:
- file = open(destination_filename, 'w')
- file.write(stream)
- file.close()
- logger.info("Downloaded attachment %s" % (destination_filename))
- return True
- except e:
- raise ShotgunException("unable to write attachment to disk: %s"% e)
-
-
- # ----------------------------------------------
- # Compress files
- # ----------------------------------------------
- def compress_files(files,destination_filename):
- destination_filename += ".tar.gz"
- files = [path.lstrip("/") for path in files]
- squish_me = compress_cmd % (destination_filename, " ".join(files) )
- logger.info("Compressing %s files..." % len(files))
- logger.info("Running command: %s" % squish_me)
- try:
- output = subprocess.Popen(squish_me, shell=True, stdout=subprocess.PIPE).stdout.read()
- logger.info('tar/gzip command returned: %s' % output)
- except e:
- raise ShotgunException("unable compress files: %s"% e)
- logger.info("compressed files to: %s" % destination_filename)
- return destination_filename
-
-
- # ----------------------------------------------
- # Remove downloaded files
- # ----------------------------------------------
- def remove_downloaded_files(files):
- remove_me = 'rm %s' % ( " ".join(files) )
- logger.info("Removing %s files..." % len(files))
- logger.info("Running command: %s" % remove_me)
- try:
- output = subprocess.Popen(remove_me, shell=True, stdout=subprocess.PIPE).stdout.read()
- logger.info('rm command returned: %s' % output)
- logger.info("removed downloaded files")
- return True
- except e:
- logger.error("unable remove files: %s"% e)
- return False
-
-
- # ----------------------------------------------
- # Copy files
- # ----------------------------------------------
- def copy_files(files,destination_directory):
- if type(files) == list:
- files = " ".join(files)
- copy_me_args = "%s %s" % (files, destination_directory)
- logger.info("Running command: mv %s" % copy_me_args)
- try:
- result = subprocess.Popen("mv " + copy_me_args, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
- # 0 = success, 1 = recoverable issues
- if result.returncode > 0:
- response = result.stderr.read()
- logger.error("Copy failed: %s"% response)
- raise ShotgunException("Copy failed: %s"% response)
- except OSError, e:
- raise ShotgunException("unable copy files: %s"% e)
-
- logger.info("copied files to: %s" % destination_directory)
- return destination_directory
-
-
-
- def packageFilesForClient(file_field,destination_dir):
-
- # get entities matching the selected ids
- logger.info("Querying Shotgun for %s %ss" % (len(sa.selected_ids_filter), sa.params['entity_type']))
- entities = sg.find(sa.params['entity_type'],sa.selected_ids_filter,['id','code',file_field],filter_operator='any')
-
- # download the attachments for each entity, zip them, and copy to destination directory
- files = []
- for e in entities:
- if not e[file_field]:
- logger.info("%s #%s: No file exists. Skippinsa." % (sa.params['entity_type'], e['id']))
- else:
- logger.info("%s #%s: %s" % (sa.params['entity_type'], e['id'], e[file_field]))
- path_to_file = file_dir+"/"+re.sub(r"\s+", '_', e[file_field]['name'])
- result = download_attachment_to_disk(e[file_field], path_to_file )
-
- # only include attachments. urls won't return true
- if result:
- files.append(path_to_file)
-
- # compress files
- # create a nice valid destination filename
- project_name = ''
- if 'project_name' in sa.params:
- project_name = re.sub(r"\s+", '_', sa.params['project_name'])+'_'
- dest_filename = project_name+datetime.today().strftime('%Y-%m-%d-%H%M%S')+"_"+sa.params['user_login']
- archive = compress_files(files,file_dir+"/"+dest_filename)
-
- # now that we have the archive, remove the downloads
- r = remove_downloaded_files(files)
-
- # copy to directory
- result = copy_files([archive],destination_dir)
-
- return True
-
-
- # ----------------------------------------------
- # Main Block
- # ----------------------------------------------
- if __name__ == "__main__":
- init_log(logfile)
-
- try:
- sa = ShotgunAction(sys.argv[1])
- logger.info("Firing... %s" % (sys.argv[1]) )
- except IndexError, e:
- raise ShotgunException("Missing POST arguments")
-
- sg = Shotgun(shotgun_conf['url'], shotgun_conf['name'], shotgun_conf['key'],convert_datetimes_to_utc=convert_tz)
-
- if sa.action == 'package4client':
- result = packageFilesForClient('sg_qt','/Users/kp/Documents/shotgun/dev/api/files/')
- else:
- raise ShotgunException("Unknown action... :%s" % sa.action)
-
-
- print "\nVersion Packager done!"
-
diff --git a/_sources/examples/basic_create_shot.txt b/_sources/examples/basic_create_shot.txt
deleted file mode 100644
index c979975de..000000000
--- a/_sources/examples/basic_create_shot.txt
+++ /dev/null
@@ -1,103 +0,0 @@
-.. _example_create_shot:
-
-Create A Shot
-=============
-
-Building the data and calling :meth:`~shotgun_api3.Shotgun.create`
-------------------------------------------------------------------
-To create a Shot, you need to provide the following values:
-
-- ``project`` is a link to the Project the Shot belongs to. It should be a dictionary like
- ``{"type": "Project", "id": 123}`` where ``id`` is the ``id`` of the Project.
-- ``code`` (this is the field that stores the name Shot)
-- optionally any other info you want to provide
-
-Example::
-
- data = {
- 'project': {"type":"Project","id": 4},
- 'code': '100_010',
- 'description': 'Open on a beautiful field with fuzzy bunnies',
- 'sg_status_list': 'ip'
- }
- result = sg.create('Shot', data)
-
-
-This will create a new Shot named "100_010" in the Project "Gunslinger" (which has an ``id`` of 4).
-
-- ``data`` is a list of key/value pairs where the key is the column name to update and the value
- is the the value to set.
-- ``sg`` is the Shotgun API instance you created in :ref:`example_sg_instance`.
-- ``create()`` is the :meth:`shotgun_api3.Shotgun.create` API method we are calling. We pass in the
- entity type we're searching for and the data we're setting.
-
-Result
-------
-The variable ``result`` now contains a dictionary hash with the Shot information you created.::
-
- {
- 'code': '100_010',
- 'description': 'Open on a beautiful field with fuzzy bunnies',
- 'id': 40435,
- 'project': {'id': 4, 'name': 'Demo Project', 'type': 'Project'},
- 'sg_status_list': 'ip',
- 'type': 'Shot'
- }
-
-In addition, Shotgun has returned the ``id`` that it has assigned to the Shot, as well as a
-``type`` value. ``type`` is provided for convenience simply to help you identify what entity type
-this dictionary represents. It does not correspond to any field in Shotgun.
-
-Shotgun will *always* return the ``id`` and ``type`` keys in the dictionary when there are results
-representing an entity.
-
-The Complete Example
---------------------
-::
-
- #!/usr/bin/env python
-
- # --------------------------------------
- # Imports
- # --------------------------------------
- import shotgun_api3
- from pprint import pprint # useful for debugging
-
- # --------------------------------------
- # Globals
- # --------------------------------------
- # make sure to change this to match your Shotgun server and auth credentials.
- SERVER_PATH = "https://mystudio.shotgunstudio.com"
- SCRIPT_NAME = 'my_script'
- SCRIPT_KEY = '27b65d7063f46b82e670fe807bd2b6f3fd1676c1'
-
- # --------------------------------------
- # Main
- # --------------------------------------
- if __name__ == '__main__':
-
- sg = shotgun_api3.Shotgun(SERVER_PATH, SCRIPT_NAME, SCRIPT_KEY)
-
- # --------------------------------------
- # Create a Shot with data
- # --------------------------------------
- data = {
- 'project': {"type":"Project","id": 4},
- 'code': '100_010',
- 'description': 'Open on a beautiful field with fuzzy bunnies',
- 'sg_status_list': 'ip'
- }
- result = sg.create('Shot', data)
- pprint(result)
- print "The id of the %s is %d." % (result['type'], result['id'])
-
-And here is the output::
-
- {'code': '100_010',
- 'description': 'Open on a beautiful field with fuzzy bunnies',
- 'id': 40435,
- 'project': {'id': 4, 'name': 'Demo Project', 'type': 'Project'},
- 'sg_status_list': 'ip',
- 'type': 'Shot'}
- The id of the Shot is 40435.
-
diff --git a/_sources/examples/basic_create_shot_task_template.txt b/_sources/examples/basic_create_shot_task_template.txt
deleted file mode 100644
index 76eb169e8..000000000
--- a/_sources/examples/basic_create_shot_task_template.txt
+++ /dev/null
@@ -1,77 +0,0 @@
-Create a Shot with a Task Template
-==================================
-Creating a new Shot with a Task Template is just like linking it to another entity, but Shotgun will apply the Task Template in the background and create the appropriate Tasks on the Shot for you.
-
-Find the Task Template
-----------------------
-First we need to find the Task Template we're going to apply. We'll assume you know the name of the Task Template you want to use.
-::
-
- filters = [['code','is', '3D Shot Template' ]]
- template = sg.find_one('TaskTemplate', filters)
-
-
-The Resulting Task Template
----------------------------
-
-Assuming the task template was found, we will now have something like this in our ``template``
-variable::
-
- {'type': 'TaskTemplate', 'id': 12}
-
-Create the Shot
----------------
-Now we can create the Shot with the link to the ``TaskTemplate`` to apply.
-::
-
- data = {'project': {'type': 'Project','id': 4},
- 'code': '100_010',
- 'description': 'dark shot with wicked cool ninjas',
- 'task_template': template }
- result = sg.create('Shot', data)
-
-This will create a new Shot named "100_010" linked to the TaskTemplate "3D Shot Template" and
-Shotgun will then create the Tasks defined in the template and link them to the Shot you just
-created.
-
-- ``data`` is a list of key/value pairs where the key is the column name to update and the value is
- the value.
-- ``project`` and `code` are required
-- ``description`` is just a text field that you might want to update as well
-- ``task_template`` is another entity column where we set the Task Template which has the Tasks we
- wish to create by default on this Shot. We found the specific template we wanted to assign in the
- previous block by searching
-
-Result
-------
-The variable ``result`` now contains the dictionary of the new Shot that was created.
-::
-
- {
- 'code': '010_010',
- 'description': 'dark shot with wicked cool ninjas',
- 'id': 2345,
- 'project': {'id': 4, 'name': 'Gunslinger', 'type': 'Project'},
- 'task_template': {'id': 12,
- 'name': '3D Shot Template',
- 'type': 'TaskTemplate'},
- 'type': 'Shot'
- }
-
-
-If we now search for the Tasks linked to the Shot, we'll find the Tasks that match our
-``TaskTemplate``::
-
- tasks = sg.find('Task', filters=[['entity', 'is', result]])
-
-.. note:: You can use an entity dictionary that was returned from the API in a filter as we have
- done above. Shotgun will only look at the ``id`` and ``type`` keys and will ignore the rest.
- This is a handy way to pass around entity dictionaries without having to reformat them.
-
-Now the ``tasks`` variable contains the following::
-
- [{'id': 3253, 'type': 'Task'},
- {'id': 3254, 'type': 'Task'},
- {'id': 3255, 'type': 'Task'},
- {'id': 3256, 'type': 'Task'},
- {'id': 3257, 'type': 'Task'}]
diff --git a/_sources/examples/basic_create_version_link_shot.txt b/_sources/examples/basic_create_version_link_shot.txt
deleted file mode 100644
index d93983ebb..000000000
--- a/_sources/examples/basic_create_version_link_shot.txt
+++ /dev/null
@@ -1,82 +0,0 @@
-Create a Version Linked to a Shot
-=================================
-You've just created a sweet new Version of your shot. Now you want to update Shotgun and create a
-new ``Version`` entity linked to the Shot.
-
-Find the Shot
--------------
-First we need to find the Shot since we'll need to know know its ``id`` in order to link our Version
-to it.
-::
-
- filters = [ ['project', 'is', {'type': 'Project', 'id': 4}],
- ['code', 'is', '100_010'] ]
- shot = sg.find_one('Shot', filters)
-
-
-Find the Task
--------------
-Now we find the Task that the Version relates to, again so we can use the ``id`` to link it to the
-Version we're creating. For this search we'll use the Shot ``id`` (which we have now in the ``shot``
-variable from the previous search) and the Task Name, which maps to the ``content`` field.
-::
-
- filters = [ ['project', 'is', {'type': 'Project', 'id': 4}],
- ['entity', 'is',{'type':'Shot', 'id': shot['id']}],
- ['content', 'is', 'Animation'] ]
- task = sg.find_one('Task', filters)
-
-.. note:: Linking a Task to the Version is good practice. By doing so it is easy for users to see
- at what stage a particular Version was created, and opens up other possibilities for tracking
- in Shotgun. We highly recommend doing this whenever possible.
-
-Create the Version
-------------------
-Now we can create the Version with the link to the Shot and the Task::
-
- data = { 'project': {'type': 'Project','id': 4},
- 'code': '100_010_anim_v1',
- 'description': 'first pass at opening shot with bunnies',
- 'sg_path_to_frames': '/v1/gun/s100/010/frames/anim/100_010_animv1_jack.#.jpg',
- 'sg_status_list': 'rev',
- 'entity': {'type': 'Shot', 'id': shot['id']},
- 'sg_task': {'type': 'Task', 'id': task['id']},
- 'user': {'type': 'HumanUser', 'id': 165} }
- result = sg.create('Version', data)
-
-This will create a new Version named '100_010_anim_v1' linked to the 'Animation' Task for Shot
-'100_010' in the Project 'Gunslinger'.
-
-- ``data`` is a list of key/value pairs where the key is the column name to update and the value is
- the value to set.
-- ``project`` and ``code`` are required
-- ``description`` and ``sg_path_to_frames`` are just text fields that you might want to update as
- well
-- ``sg_status_list`` is the status column for the Version. Here we are setting it to "rev" (Pending
- Review) so that it will get reviewed in the next dailies session and people will "ooh" and "aaah".
-- ``entity`` is where we link this version to the Shot. Entity columns are always handled with this
- format. You must provide the entity ``type`` and its ``id``.
-- ``sg_task`` is another entity link field specifically for the Version's Task link. This uses the
- same entity format as the Shot link, but pointing to the Task entity this time.
-- ``user`` is another entity column where we set the artist responsible for this masterpiece. In
- this example, I know the 'id' that corresponds to this user, but if you don't know the id you can
- look it up by searching on any of the fields, similar to what we did for the Shot above, like::
-
- filters = [['login', 'is', 'jschmoe']]
- user = sg.find('HumanUser', filters)
-
-The ``result`` variable now contains the ``id`` of the new Version that was created::
-
- 214
-
-
-Upload a movie for review in Screening Room
--------------------------------------------
-If Screening Room's transcoding feature is enabled on your site (hosted sites have this by
-default), then you can use the :meth:`~shotgun_api3.Shotgun.upload` method to upload a QuickTime
-movie, PDF, still image, etc. to the ``sg_uploaded_movie`` field on a Version. Once the movie is
-uploaded, it will automatically be queued for transcoding. When transcoding is complete, the
-Version will be playable in the Screening Room app, or in the Overlay player by clicking on the
-Play button that will appear on the Version's thumbnail.
-
-.. note:: Transcoding also generates a thumbnail and filmstrip thumbnail automatically.
\ No newline at end of file
diff --git a/_sources/examples/basic_delete_shot.txt b/_sources/examples/basic_delete_shot.txt
deleted file mode 100644
index 779fc9659..000000000
--- a/_sources/examples/basic_delete_shot.txt
+++ /dev/null
@@ -1,52 +0,0 @@
-Delete A Shot
-=============
-
-Calling :meth:`~shotgun_api3.Shotgun.delete`
---------------------------------------------
-Deleting an entity in Shotgun is pretty straight-forward. No extraneous steps required.::
-
- result = sg.delete("Shot", 40435)
-
-Result
-------
-If the Shot was deleted successfully ``result`` will contain::
-
- True
-
-The Complete Example
---------------------
-::
-
- #!/usr/bin/env python
-
- # --------------------------------------
- # Imports
- # --------------------------------------
- import shotgun_api3
- from pprint import pprint # useful for debugging
-
- # --------------------------------------
- # Globals
- # --------------------------------------
- # make sure to change this to match your Shotgun server and auth credentials.
- SERVER_PATH = "https://mystudio.shotgunstudio.com"
- SCRIPT_NAME = 'my_script'
- SCRIPT_KEY = '27b65d7063f46b82e670fe807bd2b6f3fd1676c1'
-
- # --------------------------------------
- # Main
- # --------------------------------------
- if __name__ == '__main__':
-
- sg = shotgun_api3.Shotgun(SERVER_PATH, SCRIPT_NAME, SCRIPT_KEY)
-
- # --------------------------------------
- # Delete a Shot by id
- # --------------------------------------
- result = sg.delete("Shot", 40435)
- pprint(result)
-
-And here is the output::
-
- True
-
diff --git a/_sources/examples/basic_find_shot.txt b/_sources/examples/basic_find_shot.txt
deleted file mode 100644
index ee223c89b..000000000
--- a/_sources/examples/basic_find_shot.txt
+++ /dev/null
@@ -1,76 +0,0 @@
-.. _example_find_shot:
-
-Find a Shot
-===========
-
-Building the Query
-------------------
-We are going to assume we know the 'id' of the Shot we're looking for in this example.::
-
- filters = [['id', 'is', 40435]]
- result = sg.find_one('Shot', filters)
-
-Pretty simple right? Well here's a little more insight into what's going on.
-
-- ``filters`` is an list of filter conditions. In this example we are filtering for Shots where
- the ``id`` column is **40435**.
-- ``sg`` is the Shotgun API instance.
-- ``find_one()`` is the :meth:`~shotgun_api3.Shotgun.find_one` API method we are calling. We
- provide it with the entity type we're searching for and our filters.
-
-
-Seeing the Result
------------------
-So what does this return? The variable result now contains::
-
- {'type': 'Shot','id': 40435}
-
-By default, :meth:`~shotgun_api3.Shotgun.find_one` returns a single dictionary object with
-the ``type`` and ``id`` fields. So in this example, we found a Shot matching that id, and Shotgun
-returned it as a dictionary object with ``type`` and ``id`` keys .
-
-How do we know that result contains the Shot dictionary object? You can trust us... but just to be
-sure, the :mod:`pprint` (PrettyPrint) module from the Python standard library is a really good tool
-to help with debugging. It will print out objects in a nicely formatted way that makes things
-easier to read. So we'll add that to the import section of our script.::
-
- import shotgun_api3
- from pprint import pprint # useful for debugging
-
-The Complete Example
---------------------
-::
-
- #!/usr/bin/env python
-
- # --------------------------------------
- # Imports
- # --------------------------------------
- import shotgun_api3
- from pprint import pprint # useful for debugging
-
- # --------------------------------------
- # Globals
- # --------------------------------------
- # make sure to change this to match your Shotgun server and auth credentials.
- SERVER_PATH = "https://mystudio.shotgunstudio.com"
- SCRIPT_NAME = 'my_script'
- SCRIPT_KEY = '27b65d7063f46b82e670fe807bd2b6f3fd1676c1'
-
- # --------------------------------------
- # Main
- # --------------------------------------
- if __name__ == '__main__':
-
- sg = shotgun_api3.Shotgun(SERVER_PATH, SCRIPT_NAME, SCRIPT_KEY)
-
- # --------------------------------------
- # Find a Shot by id
- # --------------------------------------
- filters = [['id', 'is', 40435]]
- result = sg.find_one('Shot', filters)
- pprint(result)
-
-And here is the output::
-
- {'type': 'Shot','id': 40435}
diff --git a/_sources/examples/basic_sg_instance.txt b/_sources/examples/basic_sg_instance.txt
deleted file mode 100644
index 6d2d1dd08..000000000
--- a/_sources/examples/basic_sg_instance.txt
+++ /dev/null
@@ -1,26 +0,0 @@
-.. _example_sg_instance:
-
-Create a Shotgun API instance
-=============================
-
-This example shows you how to establish your initial connection to Shotgun using script-based
-authentication. ``sg`` represents your Shotgun API instance. Be sure you've read
-:ref:`Setting Up Shotgun for API Access `.
-::
-
- import pprint # Useful for debugging
-
- import shotgun_api3
-
- SERVER_PATH = "https://your_site.shotgunstudio.com"
- SCRIPT_NAME = 'my_script'
- SCRIPT_KEY = '27b65d7063f46b82e670fe807bd2b6f3fd1676c1'
-
- sg = shotgun_api3.Shotgun(SERVER_PATH, SCRIPT_NAME, SCRIPT_KEY)
-
- # Just for demo purposes, this will print out property and method names available on the
- # sg connection object
- pprint.pprint([symbol for symbol in sorted(dir(sg)) if not symbol.startswith('_')])
-
-For further information on what you can do with this Shotgun object you can read the
-:ref:`API reference `.
\ No newline at end of file
diff --git a/_sources/examples/basic_update_shot.txt b/_sources/examples/basic_update_shot.txt
deleted file mode 100644
index 555114578..000000000
--- a/_sources/examples/basic_update_shot.txt
+++ /dev/null
@@ -1,86 +0,0 @@
-Update A Shot
-=============
-
-Building the data and calling :meth:`~shotgun_api3.Shotgun.update`
-------------------------------------------------------------------
-To update a Shot, you need to provide the ``id`` of the Shot and a list of fields you want to
-update.::
-
- data = {
- 'description': 'Open on a beautiful field with fuzzy bunnies',
- 'sg_status_list': 'ip'
- }
- result = sg.update('Shot', 40435, data)
-
-This will update the ``description`` and the ``sg_status_list`` fields for the Shot with ``id`` of
-**40435**.
-
-- ``data`` is a list of key/value pairs where the key is the field name to update and the value to
- update it to.
-- ``sg`` is the Shotgun API instance.
-- ``update()`` is the :meth:`shotgun_api3.Shotgun.update` API method we are calling. We provide it
- with the entity type we're updating, the ``id`` of the entity, and the data we're updating it
- with.
-
-Result
-------
-The variable ``result`` now contains the Shot object that with the updated values.::
-
- {
- 'description': 'Opening establishing shot with titles and fuzzy bunnies',
- 'sg_status_list': 'ip',
- 'type': 'Shot',
- 'id': 40435
- }
-
-In addition, Shotgun has returned the ``id`` for the Shot, as well as a ``type`` value. ``type``
-is provided for convenience simply to help you identify what entity type this dictionary represents.
-It does not correspond to any field in Shotgun.
-
-Shotgun will *always* return the ``id`` and ``type`` keys in the dictionary when there are results
-representing an entity.
-
-The Complete Example
---------------------
-::
-
- #!/usr/bin/env python
-
- # --------------------------------------
- # Imports
- # --------------------------------------
- import shotgun_api3
- from pprint import pprint # useful for debugging
-
- # --------------------------------------
- # Globals
- # --------------------------------------
- # make sure to change this to match your Shotgun server and auth credentials.
- SERVER_PATH = "https://mystudio.shotgunstudio.com"
- SCRIPT_NAME = 'my_script'
- SCRIPT_KEY = '27b65d7063f46b82e670fe807bd2b6f3fd1676c1'
-
- # --------------------------------------
- # Main
- # --------------------------------------
- if __name__ == '__main__':
-
- sg = shotgun_api3.Shotgun(SERVER_PATH, SCRIPT_NAME, SCRIPT_KEY)
-
- # --------------------------------------
- # Update Shot with data
- # --------------------------------------
- data = {
- 'description': 'Open on a beautiful field with fuzzy bunnies',
- 'sg_status_list': 'ip'
- }
- result = sg.update('Shot', 40435, data)
- pprint(result)
-
-And here is the output::
-
- {'description': 'Opening establishing shot with titles and fuzzy bunnies',
- 'id': 40435,
- 'sg_status_list': 'ip',
- 'type': 'Shot'}
-
diff --git a/_sources/examples/basic_upload_thumbnail_version.txt b/_sources/examples/basic_upload_thumbnail_version.txt
deleted file mode 100644
index 62713aa90..000000000
--- a/_sources/examples/basic_upload_thumbnail_version.txt
+++ /dev/null
@@ -1,27 +0,0 @@
-Upload a Thumbnail for a Version
-================================
-
-So you've created a new Version of a Shot, and you've updated Shotgun, but now you want to upload a
-beauty frame to display as the thumbnail for your Version. We'll assume you already have the image
-made (located on your machine at ``/v1/gun/s100/010/beauties/anim/100_010_animv1.jpg``) . And since
-you've just created your Version in Shotgun, you know its ``id`` is **214**.
-
-.. note:: If you upload a movie file or image to the ``sg_uploaded_movie`` field and you have
- transcoding enabled on your server (the default for hosted sites), a thumbnail will be
- generated automatically as well as a filmstrip thumbnail (if possible). But this example is
- provided just to show the basic process of uploading a thumbnail manually where is may be
- necessary.
-
-Upload the Image using :meth:`~shotgun_api3.Shotgun.upload_thumbnail`
----------------------------------------------------------------------
-::
-
- sg.upload_thumbnail("Version", 214, "/v1/gun/s100/010/beauties/anim/100_010_animv1.jpg")
-
-
-Shotgun will take care of resizing the thumbnail for you. If something does go wrong, an exception
-will be thrown and you'll see the error details.
-
-.. note:: The result returned by :meth:`~shotgun_api3.Shotgun.upload_thumbnail` is an integer
- representing the id of a special ``Attachment`` entity in Shotgun. Working with Attachments
- is beyond the scope of this example. :)
\ No newline at end of file
diff --git a/_sources/examples/svn_integration.txt b/_sources/examples/svn_integration.txt
deleted file mode 100644
index db59d0411..000000000
--- a/_sources/examples/svn_integration.txt
+++ /dev/null
@@ -1,170 +0,0 @@
-.. _svn_integration:
-
-############################
-Subversion (SVN) Integration
-############################
-
-Integrating Shotgun with Subversion consists of two basic parts:
-
-- Setup a post-commit hook in Subversion.
-- Create a Shotgun API script to create the Revision in Shotgun. This script will be called by
- the post-commit hook.
-
-****************
-Post-Commit Hook
-****************
-
-To setup the post-commit hook:
-
-- Locate the ``post-commit.tmpl`` file, which is found inside the ``hooks`` folder in your
- repository directory. This is a template script that has lots of useful comments and can serve
- as a starting point for the real thing.
-- Create your very own executable script, and save it in the same ``hooks`` folder, name it
- ``post-commit``, and give it executable permission.
-- In your ``post-commit`` script, invoke your Shotgun API script.
-
-If this is entirely new to you, we highly suggest reading up on the topic. O'Reilly has `a free
-online guide for Subversion 1.5 and 1.6
-`_
-
-Here's an example of a post-commit hook that we've made for Subversion 1.6 using an executable
-Unix shell script. The last line invokes "shotgun_api_script.py" which is our Python script that
-will do all the heavy lifting. Lines 4 thru 8 queue up some objects that we'll use later on.
-
-.. code-block:: sh
- :linenos:
-
- #!/bin/sh
- # POST-COMMIT HOOK
-
- REPOS="$1"
- REV="$2"
-
- export AUTHOR="$(svnlook author $REPOS --revision $REV)"
- export COMMENT="$(svnlook log $REPOS --revision $REV)"
-
- /Absolute/path/to/shotgun_api_script.py
-
-Explanation of selected lines
-=============================
-
-- lines ``4-5``: After the commit, Subversion leaves us two string objects in the environment:
- ``REPOS`` and ``REV`` (the repository path and the revision number, respectively).
-* lines ``7-8``: Here we use the shell command ``export`` to create two more string objects in the
- environment: ``AUTHOR`` and ``COMMENT``. To get each value, we use the ``svnlook`` command with
- our ``REPOS`` and ``REV`` values, first with the ``author``, and then with ``log`` subcommand.
- These are actually the first two original lines of code - everything else to this point was
- pre-written already in the ``post-commit.tmpl`` file. nice :)
-* line ``10``: This is the absolute path to our Shotgun API Script.
-
-******************
-Shotgun API Script
-******************
-
-This script will create the Revision and populate it with some metadata using the Shotgun Python
-API. It will create our Revision in Shotgun along with the author, comment, and because we use
-Trac (a web-based interface for Subversion), it will also populate a URL field with a clickable
-link to the Revision.
-
-.. code-block:: python
- :linenos:
-
-
- #!/usr/bin/env python
- # ---------------------------------------------------------------------------------------------
-
- # ---------------------------------------------------------------------------------------------
- # Imports
- # ---------------------------------------------------------------------------------------------
- import sys
- from shotgun_api3_preview import Shotgun
- import os
-
- # ---------------------------------------------------------------------------------------------
- # Globals - update all of these values to those of your studio
- # ---------------------------------------------------------------------------------------------
- SERVER_PATH = 'https ://studio_name.shotgunstudio.com' # or http:
- SCRIPT_USER = 'script_name'
- SCRIPT_KEY = '3333333333333333333333333333333333333333'
- REVISIONS_PATH = 'https ://serveraddress/trac/changeset/' # or other web-based UI
- PROJECT = {'type':'Project', 'id':27}
-
- # ---------------------------------------------------------------------------------------------
- # Main
- # ---------------------------------------------------------------------------------------------
- if __name__ == '__main__':
-
- sg = Shotgun(SERVER_PATH, SCRIPT_USER, SCRIPT_KEY)
-
- # Set Python variables from the environment objects
- revision_code = os.environ['REV']
- repository = os.environ['REPOS']
- description = os.environ['COMMENT']
- author = os.environ['AUTHOR']
-
- # Set the Trac path for this specific revision
- revision_url = REVISIONS_PATH + revision_code
-
- # Validate that author is a valid Shotgun HumanUser
- result = sg.find_one("HumanUser", [['login', 'is', author]])
- if result:
- # Create Revision
- url = {'content_type':'http_url', 'url':revision_url, 'name':'Trac'}
- parameters = {'project':PROJECT,
- 'code':str(revision_code),
- 'description':description,
- 'attachment':url,
- 'created_by':{"type":"HumanUser", "id":result['id']}
- }
- revision = sg.create("Revision", parameters)
- print "created Revision #"+str(revision_code)
-
- # Send error message if valid HumanUser is not found
- else:
- print "Unable to find valid Shotgun User with login: "+author+", Revision not created in Shotgun."
-
-
-
-Explanation of selected lines:
-==============================
-
-- line ``14``: This should be the URL to your instance of Shotgun.
-- lines ``15-16``: Make sure you get these values from the "Scripts" page in the Admin section of
- the Shotgun web application. If you're not sure how to do this, check out :doc:`authentication`.
-- line ``17``: This is the address of Trac, our web-based interface that we use with Subversion.
- You may use a different interface, or none at all, so feel free to adjust this line or ignore it
- as your case may be.
-- line ``18``: Every Revision in Shotgun must have a Project, which is passed to the API as a
- dictionary with two keys, the ``type`` and the ``id``. Of course the ``type`` value will always
- remain ``Project`` (case sensitive), but the ``id`` will change by Project. To find out the
- ``id`` of your Project, go to the Projects page in the Shotgun web application, locate the
- Project where you want your Revisions created, and then locate its ``id`` field (which you may
- need to display - if you don't see it, right click on any column header then select
- "Insert Column" > "Id"). Note that for this example we assume that all Revisions in this
- Subversion repository will belong to the same Project.
-- lines ``28-31``: Grab the values from the objects that were left for us in the environment.
-- line ``34``: Add the Revision number to complete the path of our Trac url.
-- line ``37``: Make sure that a valid User exists in Shotgun. In our example, we assume that our
- Users' Shotgun logins match their Subversion names. If the user exists in Shotgun, that
- user's ``id`` will be returned as ``result['id']``, which we will need later on in line 46.
-- lines ``40-48``: Use all the meta data we've gathered to create a Revision in Shotgun. If none
- of these lines make any sense, check out more on the :meth:`~shotgun_api3.Shotgun.create` method
- here. Line 41 deserves special mention: notice that we define a dictionary called ``url`` that
- has three important keys: ``content_type``, ``url``, and ``name``, and we then pass this in as
- the value for the ``attachment`` field when we create the Revision. If you're even in doubt,
- double check the syntax and requirements for the different field types here.
-
-***************
-Troubleshooting
-***************
-
-My post-commit script is simply not running. I can run it manually, but commits are not triggering it.
-=====================
-
-Make sure that the script is has explicitly been made executable and that all users who will
-invoke it have appropriate permissions for the script and that folders going back to root.
-
-My Shotgun API script is not getting called by the post-commit hook.
-=====================
-
-Make sure that the script is called using its absolute path.
diff --git a/_sources/exceptions.txt b/_sources/exceptions.txt
deleted file mode 100644
index 73d3ab829..000000000
--- a/_sources/exceptions.txt
+++ /dev/null
@@ -1,5 +0,0 @@
-Exceptions
-==========
-
-.. automodule:: shotgun_api3.shotgun
- :members: ShotgunError, ShotgunError, ShotgunFileDownloadError, Fault, AuthenticationFault
\ No newline at end of file
diff --git a/_sources/filter_syntax.txt b/_sources/filter_syntax.txt
deleted file mode 100644
index c5f908644..000000000
--- a/_sources/filter_syntax.txt
+++ /dev/null
@@ -1,360 +0,0 @@
-.. _filter_syntax:
-
-#############
-Filter Syntax
-#############
-
-*************
-Basic Filters
-*************
-
-Filters are represented as a list of conditions that will be combined using the supplied
-filter_operator (``any`` or ``all``). Each condition follows the basic simple form::
-
- [, , ]
-
-Example
-=======
-Using the default filter_operator ``"all"``, the following filters will return all Shots whose status
-is "ip" AND is linked to Asset #9::
-
- filters = [
- ["sg_status_list", "is", "ip"],
- ["assets", "is", {"type": "Asset", "id": 9}]
- ]
- result = sg.find("Shot", filters)
-
-
-***************
-Complex Filters
-***************
-
-.. versionadded::3.0.11
-
-Complex filters can be a dictionary that represents a complex sub-condition of the form::
-
- {"filter_operator": "any", "filters": []}
-
-Example
-=======
-Using the default filter_operator ``"all"``, the following filters will return all Shots whose status
-is "ip" AND is linked to either Asset #9 OR Asset #23::
-
- filters = [
- ["sg_status_list", "is", "ip"],
- {
- "filter_operator": "any",
- "filters": [
- ["assets", "is", {"type": "Asset", "id": 9}],
- ["assets", "is", {"type": "Asset", "id": 23}]
- ]
- }
- ]
- result = sg.find("Shot", filters)
-
-
-***********************
-Operators and Arguments
-***********************
-
-::
-
- Operator Arguments
- -------- ---------
- 'is' [field_value] | None
- 'is_not' [field_value] | None
- 'less_than' [field_value] | None
- 'greater_than' [field_value] | None
- 'contains' [field_value] | None
- 'not_contains' [field_value] | None
- 'starts_with' [string]
- 'ends_with' [string]
- 'between' [[field_value] | None, [field_value] | None]
- 'not_between' [[field_value] | None, [field_value] | None]
- 'in_last' [[int], 'HOUR' | 'DAY' | 'WEEK' | 'MONTH' | 'YEAR']
- # note that brackets are not literal (eg. ['start_date', 'in_last', 1, 'DAY'])
- 'in_next' [[int], 'HOUR' | 'DAY' | 'WEEK' | 'MONTH' | 'YEAR']
- # note that brackets are not literal (eg. ['start_date', 'in_next', 1, 'DAY'])
- 'in' [[field_value] | None, ...] # Array of field values
- 'type_is' [string] | None # Shotgun entity type
- 'type_is_not' [string] | None # Shotgun entity type
- 'in_calendar_day' [int] # Offset (e.g. 0 = today, 1 = tomorrow,
- # -1 = yesterday)
- 'in_calendar_week' [int] # Offset (e.g. 0 = this week, 1 = next week,
- # -1 = last week)
- 'in_calendar_month' [int] # Offset (e.g. 0 = this month, 1 = next month,
- # -1 = last month)
- 'name_contains' [string]
- 'name_not_contains' [string]
- 'name_starts_with' [string]
- 'name_ends_with' [string]
-
-
-****************************
-Valid Operators By Data Type
-****************************
-
-::
-
- addressing 'is'
- 'is_not'
- 'contains'
- 'not_contains'
- 'in'
- 'type_is'
- 'type_is_not'
- 'name_contains'
- 'name_not_contains'
- 'name_starts_with'
- 'name_ends_with'
-
- checkbox 'is'
- 'is_not'
-
- currency 'is'
- 'is_not'
- 'less_than'
- 'greater_than'
- 'between'
- 'not_between'
- 'in'
- 'not_in'
-
- date 'is'
- 'is_not'
- 'greater_than'
- 'less_than'
- 'in_last'
- 'not_in_last'
- 'in_next'
- 'not_in_next'
- 'in_calendar_day'
- 'in_calendar_week'
- 'in_calendar_month'
- 'in_calendar_year'
- 'between'
- 'in'
- 'not_in'
-
- date_time 'is'
- 'is_not'
- 'greater_than'
- 'less_than'
- 'in_last'
- 'not_in_last'
- 'in_next'
- 'not_in_next'
- 'in_calendar_day'
- 'in_calendar_week'
- 'in_calendar_month'
- 'in_calendar_year'
- 'between'
- 'in'
- 'not_in'
-
- duration 'is'
- 'is_not'
- 'greater_than'
- 'less_than'
- 'between'
- 'in'
- 'not_in'
-
- entity 'is'
- 'is_not'
- 'type_is'
- 'type_is_not'
- 'name_contains'
- 'name_not_contains'
- 'name_is'
- 'in'
- 'not_in'
-
- float 'is'
- 'is_not'
- 'greater_than'
- 'less_than'
- 'between'
- 'in'
- 'not_in'
-
- image 'is' ** Note: For both 'is' and 'is_not', the only supported value is None,
- 'is_not' ** which supports detecting the presence or lack of a thumbnail.
-
- list 'is'
- 'is_not'
- 'in'
- 'not_in'
-
- multi_entity 'is' ** Note: when used on multi_entity, this functions as
- you would expect 'contains' to function
- 'is_not'
- 'type_is'
- 'type_is_not'
- 'name_contains'
- 'name_not_contains'
- 'in'
- 'not_in'
-
- number 'is'
- 'is_not'
- 'less_than'
- 'greater_than'
- 'between'
- 'not_between'
- 'in'
- 'not_in'
-
- password ** Filtering by this data type field not supported
-
- percent 'is'
- 'is_not'
- 'greater_than'
- 'less_than'
- 'between'
- 'in'
- 'not_in'
-
- serializable ** Filtering by this data type field not supported
-
- status_list 'is'
- 'is_not'
- 'in'
- 'not_in'
-
- summary ** Filtering by this data type field not supported
-
-
- tag_list 'is' ** Note: when used on tag_list, this functions as
- you would expect 'contains' to function
- 'is_not'
- 'name_contains'
- 'name_not_contains'
- 'name_id'
-
- text 'is'
- 'is_not'
- 'contains'
- 'not_contains'
- 'starts_with'
- 'ends_with'
- 'in'
- 'not_in'
-
-
- timecode 'is'
- 'is_not'
- 'greater_than'
- 'less_than'
- 'between'
- 'in'
- 'not_in'
-
- url ** Filtering by this data type field is not supported
-
-
-
-*************************
-Additional Filter Presets
-*************************
-
-
-As of Shotgun version 7.0 it is possible to also use filter presets. These presets provide a simple
-way to specify powerful query filters that would otherwise be costly and difficult to craft using
-traditional filters.
-
-Multiple presets can be specified in cases where it makes sense.
-
-Also, these presets can be used alongside normal filters. The result returned is an AND operation
-between the specified filters.
-
-Example Uses
-============
-
-The following query will return the Version with the name 'ABC' that is linked to the latest entity
-created::
-
- additional_filter_presets = [
- {
- "preset_name": "LATEST",
- "latest_by": "ENTITIES_CREATED_AT"
- }
- ]
-
- filters = [['code', 'is', 'ABC']]
-
- result = sg.find('Version', filters = filters, additional_filter_presets = additional_filter_presets)
-
-
-The following query will find all CutItems associated to Cut #1 and return all Versions associated
-to the Shot linked to each of these CutItems::
-
- additional_filter_presets = [
- {
- "preset_name": "CUT_SHOT_VERSIONS",
- "cut_id": 1
- }
- ]
-
- result = sg.find('Version', additional_filter_presets = additional_filter_presets)
-
-Available Filter Presets by Entity Type
-=======================================
-
-Allowed filter presets (and preset parameter values) depend on the entity type being searched.
-
-The table bellow gives the details about which filter preset can be used on each entity type and
-with which parameters.
-
-::
-
- Entity Type Preset Name Preset Parameters Allowed Preset Parameter Values
- ----------- ----------- ----------------- -------------------------------
- Cut LATEST [string] latest_by 'REVISION_NUMBER':
- Returns the cuts that have the
- highest revision number.
- This is typically used with a query
- filter that returns cuts with the
- same value for a given field
- (e.g. code field). This preset
- therefore allows to get
- the Cut of that set that has
- the highest revision_number value.
-
- Version CUT_SHOT_VERSIONS [int] cut_id Valid Cut entity id.
- Returns all Version entities
- associated to the Shot entity
- associated to the CutItems
- of the given Cut.
- This basically allows to find all
- Versions associated to the given
- Cut, via its CutItems.
-
- LATEST [string] latest_by 'ENTITIES_CREATED_AT':
- When dealing with multiple
- Versions associated to a group
- of entities, returns only the
- last Version created for each
- entity.
- For example, when dealing with a
- set of Shots, this preset allows
- to find the latest Version created
- for each of these Shots.
-
- 'BY_PIPELINE_STEP_NUMBER_AND_ENTITIES_CREATED_AT':
- When dealing with multiple versions
- associated to the same entity *and*
- to Tasks, returns the Version
- associated to the Task with highest
- step.list_order.
- If multiple Versions are found for
- that step.list_order, only the
- latest Version is returned.
- This allows to isolate the Version
- entity that is the farthest along
- in the pipeline for a given entity.
- For example, when dealing with a Shot
- with multiple Versions, this preset
- will return the Version associated
- to the Task with the highest
- step.list_order value.
\ No newline at end of file
diff --git a/_sources/getting_started.txt b/_sources/getting_started.txt
deleted file mode 100644
index 7c5d6ad12..000000000
--- a/_sources/getting_started.txt
+++ /dev/null
@@ -1,202 +0,0 @@
-Getting Started
-######################################
-
-Overview
-========
-
-The Shotgun API allows users to integrate their tools with Shotgun very easily. Using the simple Python-based API we provide, you can quickly get your scripts integrated with Shotgun's CRUD-based API. Because the needs of every studio can prove to be very different, we don't do a lot of "automation" or "smarts" in our API. We have kept it pretty low-level and leave most of those decisions to you. The API is powerful enough you can write your own "smarts" in a wrapper on top of the Shotgun API.
-
-CRUD
-----
-
-The API follows the CRUD pattern allowing simple Create, Read, Update, and Delete actions. Each request acts on a single entity type and depending on the specific action, can define filters, columns to return, sorting information, and some additional options.
-
-Media Files
------------
-
-The API has additional methods for managing thumbnails, images, and both uploaded and linked media.
-
-Authentication
---------------
-
-In order to communicate with the Shotgun server via the API, your script must be registered with Shotgun and have a valid API key. Then authentication is simple. You just provide your script name and it's API key. We strongly recommend you register each script separately and have individual API keys for each. This allows you to track down each of your scripts and the actions they are performing much more accurately in the event logs.
-
-
-
-
-Setting Up Shotgun for API Access
-=================================
-
-Before writing scripts to interact with the Shotgun API, you need to create add a script entity in Shotgun. This will automatically generate an application key which will act as the script's password. The key will look something like this: "bc29517b4928b8336e007ae48e71f082eb0e7c88". To create a new key, click the + button on the "Scripts" page in the Admin section:
-
-.. image:: images/scripts_page.png
-
-
-Why have different application keys for different scripts?
-----------------------------------------------------------
-
-We recommend you create a new key for each script so you can log what scripts are doing what in case one of them causes problems. This will also allow you to better see what scripts are performing what actions in the EventLog. We've found that even though you may think you'll probably never need to know, an extra 2 minutes of setup now can prevent hours of headache in the future.
-
-Permissions
------------
-Script users are bound restrictions of their permission role, which is edited on the script record in the "Permission Role" field. The default permission role for all scripts is "API Admin User" which allows full access to create, update, and delete entities and fields, including editing the "date created" audit field and creating event log entries. If you have other permission roles for ApiUsers, you can set the default role that will be assigned when a new script is created, in the site preferences.
-
-Event Logging
--------------
-
-By default, events generated by scripts using an application key are logged in Shotgun's event log. You can turn this off by unchecking the "Generate Events" checkbox either in the script detail page or from the main Scripts admin page. Note that this will also prevent any email notifications from being triggered by your scripts since the email notifier relies on the event log to find events to notify for.
-
-Why would you want to turn logging off?
----------------------------------------
-
-It is an optimization that is not used often, but some clients have integration scripts that are pushing data into Shotgun just for reference, like publishes from their asset management system. This publish data is never changed later, so the data itself has the entire history, and the events would just clutter the event log.
-
-
-
-
-API Usage Tips
-==============
-
-Below is a list of helpful tips when using the Shotgun API. We have tried to make the API very simple to use with predictable results while remaining a powerful tool to integrate with your pipeline. However, there's always a couple of things that crop up that our users might not be aware of. Those are the types of things you'll find below. We'll be adding to this document over time as new questions come up from our users that exhibit these types of cases.
-
-Entity Fields
--------------
-
-When you do a `find()` that returns a field of type entity or multi-entity (for example the 'assets' column on Shot), the entities are returned in a standard hash (dict) format::
-
- {'type':'Asset', 'name':'redBall', 'id':1}
-
-For each entity returned, you will get a ``'type'``, ``'name'``, and ``'id'`` key. This does not mean there are fields named ``'type'`` and ``'name'`` on the Asset. This is only used to provide a consistent way to represent entities returned via the API.
-
-- ``type``: the entity type (CamelCase)
-- ``name``: the display name of the entity. For most entity types this is the field named ``code`` but not always. For example, on the Ticket and Delivery entities the name key would contain the value of the ``title`` field.
-
-Shotgun UI fields not available via the API
--------------------------------------------
-
-Summary type fields like Query Fields and Pipeline Step summary fields are currently only available via the UI. Some other fields may not work as expected through the API because they are "display only" fields made available for convenience and are only available in the browser UI.
-
-HumanUser
-.........
-
-- ``name``: This is a UI-only field that is a combination of the ``'firstname' + ' ' + 'lastname'``.
-
-Shot
-....
-
-**Smart Cut Fields**: These fields are available only in the browser UI. You can read more about smart cut fields and the API in the Smart Cut Fields doc (link TK).::
-
- smart_cut_in
- smart_cut_out
- smart_cut_duration
- smart_cut_summary_display
- smart_duration_summary_display
- smart_head_in
- smart_head_out
- smart_head_duration
- smart_tail_in
- smart_tail_out
- smart_tail_duration
- smart_working_duration
-
-
-Pipeline Step summary fields on entities
-........................................
-
-The Pipeline Step summary fields on entities that have Tasks aren't currently available via the API and are calculated on the client side in the UI. These fields are like ``step_0``, or ``step_13``. Note that the Pipeline Step entity itself is available via the API as the entity type ``Step``.
-
-Query Fields
-............
-
-Query fields are also summary fields like Pipeline Steps, the query is run from the client side UI and therefore is not currently supported in the API.
-
-
-Audit Fields
-------------
-You can set the ``created_by`` and ``created_at`` fields via the API at creation time. This is often useful for when you're importing or migrating data from another source and want to keep the history in tact. However, you cannot set the ``updated_by`` and ``updated_at`` fields. These are automatically set whenever an entity is created or updated.
-
-Logging
--------
-
-The API uses standard python logging but does not define a handler.
-
-To see the logging output in stdout, define a streamhandler in your script::
-
- import logging
- import shotgun_api3 as shotgun
- logging.basicConfig(level=logging.DEBUG)
-
-To write logging output from the shotgun API to a file, define a file handler in your script::
-
- import logging
- import shotgun_api3 as shotgun
- logging.basicConfig(level=logging.DEBUG, filename='/path/to/your/log')
-
-To suppress the logging output from the API in a script which uses logging, set the level of the shotgun logger to a higher level::
-
- import logging
- import shotgun_api3 as shotgun
- sg_log = logging.getLogger('shotgun_api3')
- sg_log.setLevel(logging.ERROR)
-
-IronPython
-----------
-
-We do not test against IronPython and cannot be sure that we won't introduce breaking changes or that we will be compatible with future releases of IronPython. While we don't officially support IronPython, we certainly will do our best to figure out any issues that come up while using it and how to avoid them.
-
-As of July 9, 2015 you can look at this fork of the repo to see what changes were needed as of that date to make things work. The original fork was as of v3.0.20 of the API. Big thanks to our awesome clients Pixomondo for making their work public and letting us refer to it:
-
-https://github.com/Pixomondo/python-api/tree/v3.0.20.ipy
-
-v3.0.20 can be used with IronPython with a little bit of added work:
-
-- The Python API uses the zlib module to handle decompressing the gzipped response from the server. There's no built-in zlib module in IronPython, but there's a potential solution from Jeff Hardy at https://bitbucket.org/jdhardy/ironpythonzlib/src/. And the blog post about it here http://blog.jdhardy.ca/2008/12/solving-zlib-problem-ironpythonzlib.html
-
-- If you encounter any SSL errors like ``unknown field: SERIALNUMBER=0123456789`` or ``:SSL3_GET_SERVER_CERTIFICATE:certificate verify failed``. For now you can workaround this problem by disabling ssl certificate validation which we've encountered some intermittent issues with. In the block ~ln 70 of ``shotgun.py``, force ``NO_SSL_VALIDATION = True`` for either case.
-
-- If you encounter ``LookupError: unknown encoding: idna``, you can force utf-8 by changing iri2uri.py ~ln 71 from ``authority = authority.encode('idna')`` to ``authority = authority.encode('utf-8')``
-
-- If you encounter an SSL error such as ``SSL3_READ_BYTES:sslv3 alert handshake failure``, then the lower level SSL library backing python's network infrastructure is attempting to connect to our servers via SSLv3, which is no longer supported. You can use the code from this gist to force the SSL connections to use a specific protocol. The forked repo linked above has an example of how to do that to force the use of TLSv1.
-
-
-
-
-Shotgun Server API Changelog
-============================
-
-:note: This list is out of date and has not been updated since 5/2014
-
-The following is a list of changes in the Shotgun server code that affect the API. These are not changes in the Python API code, rather fixes/changes to the Shotgun server's API interface that may affect behavior. Generally changes to the Shotgun server API code are ensured to be non-breaking and backwards compatible bug fixes and feature enhancements. This is to ensure your scripts will not unexpectedly break when updating.
-
-These updates should also appear on the general Release Notes pages but are provided here for convenience.
-
-Format: **[Shotgun server version]**: Description of change made. [internal ticket #]
-
-- **[5.3.15]**: Added filtering out Archived projects. [25082]
-- **[5.3.12]**: Added support for api sudo as user. [19989]
-- **[5.1.22]**: Added followers, follow, and unfollow methods to code handling api requests. [20562]
-- **[3.3.1]**: Modified CRUD code so that if a request reads, sorts, or summarizes a join (ConnectionEntity) field, and the parent entity has not been passed in the request, the code will try to infer it from the filter conditions. Prior to this fix on 3.3 - the API was returning an error when trying to sort Versions on playlists.PlaylistVersionConnection.sg_sort_order. Note that if the parent entity cannot be inferred automatically, this error will still occur. [17107]
-- **[3.3.0]**: Added support for returning the full paths of thumbnail fields in regular api calls. This works for thumbnail fields on the entity, linked thumbnails, and filmstrip thumbnails. [10693]
-- **[3.0.0]**: We've released v3.08 of the Python API which now includes a JSON backend. The JSON transport is up to 40% faster than the XML-RPC based transport. The XML-RPC interface will continue to be supported but may not include new features, so previous versions of the API will still be supported as-is.
-- **[3.0.0]**: Added support for name_is filter operator on single and multi-entity fields, both in the API and the UI.
-- **[2.4.8]**: Added support for id inquery filters in the API. The syntax is slightly different than similar filters, in that the filter value is not an array. [14261]
-- **[2.4.6]**: Fixed issue with multi-entity field filters where Python None was passed in. Prior to this fix, one could not use the api to create filters such as "['task_assignees', 'is', None]" or "['task_assignees', 'is_not', None]", without generating an api error. These filters are now allowed, and work as expected. [14111]
-- **[2.4.0]**: Added query builder and API support for next/previous modifiers for the ""in calendar period"" filter operators for date and datetime fields. For example, "find tasks that were created in the last 7 months..."
-- **[2.4.0]**: Ensured that the UI and the API disallow configuring Note Links field to allow the Task or Note entity type.
-- **[2.4.0]**: Date fields now require YYYY-MM-DD format. Previously they were documented as requiring that format, but would actually allow other date formats if the server was able to parse them into a valid date.
-- **[2.3.9]**: Ensured that creating a task (via the API) with ONLY the duration set - if that task is created with an upstream task that has an end date - results in the created task having both its Start and Due date set by the task dependency logic. [13407]
-- **[2.3.7]**: Ensured api parity with UI in terms of passing in filters on linked fields more than 1 link away. [12867]
-- **[2.3.7]**: Ensured that api errors are not thrown when creating/updating a task with milestone=True, and start date=end date. This behavior is true when using create(), update(), or either method with batch(). Also, added a unit test to cover this. [13318]
-- **[2.3.5]**: Added api support for getting Shotgun's version and build number. Usage requires Shotgun Wrapper version 3.0.6 or higher.
-- **[2.3.3]**: Fixed bug with api where local file paths for windows mount points were being double-escaped, resulting in "\" character sequences. [13119]
-- **[2.2.5]**: Ensured that api calls requesting summary fields do not result in silent logging on errors to production.log. This fix results in no change for api programmers, but does ensure that such api calls can occur without the possibility of killing apache due to unwieldy and unnecessary logging. [12850]
-- **[2.2.4]**: Ensured that creating a Task Template Task through the api doesn't require a project id - unlike creating a non template task. [11283]
-- **[2.2.4]**: Fixed error generated when trying to revive a Script (ApiUser) via the API [12794]
-- **[2.0.0]**: Added the ability to link to local files via the API.
-- **[2.1.2]**: Enforced uniqueness on Script Names (API_user class) so that when creating scripts, the naming conflicts will no longer be allowed. [11479]
-- **[2.1.0]**: added a revive() method in the API. Syntax follows that of delete()
-- **[2.0.8]**: Disallowed retired scripts from authenticating via the api. The main Shotgun method wills till return a valid Shotgun instance, but any other method calls will return the following error...shotgun.Fault: [11480]
-- **[2.0.0]**: Provided API support for layout_project for project creation. Functionality mirrors the web interface: omitting layout_project creates the project based on template project. Supplying layout_project ensures that the new project is based on the supplied project. This fixes the problem of script-created projects having no pages - since they lacked a template, implicit or explicit.
-- **[2.0.0]**: Improved API error message resulting when trying to set the default_value property on non status list fields, using schema_field_create().
-- **[2.0.0]**: Removed legacy support for sg_system_task_type. Now, all API methods should use Pipeline Steps instead.
-- **[2.0.0]**: ended support for API v2 (API2)
\ No newline at end of file
diff --git a/_sources/index.txt b/_sources/index.txt
deleted file mode 100644
index ac6184014..000000000
--- a/_sources/index.txt
+++ /dev/null
@@ -1,70 +0,0 @@
-###################
-Shotgun Python API3
-###################
-Release |version|. (:ref:`Installation `)
-
-.. image:: https://img.shields.io/badge/shotgun-api-blue.svg?style=flat-square
-.. image:: https://img.shields.io/travis/shotgunsoftware/python-api.svg?style=flat-square
-
-
-
-Shotgun provides a simple Python-based API for accessing Shotgun and integrating with other tools.
-The Shotgun API allows users to integrate their tools with Shotgun very easily. Using this simple
-but powerful python module , you can quickly get your scripts integrated with Shotgun's CRUD-based
-API.
-
-Because the needs of every studio can prove to be very different, we don't include a lot of
-"automation" or "smarts" in our API. We have kept it pretty low-level and leave most of those
-decisions to you. The API is powerful enough you can write your own "smarts" in a wrapper on top
-of the Shotgun API.
-
-In addition to basic metadata, the API contains methods for managing media including thumbnails,
-filmstrip thumbnails, images, uploaded, and both locally and remotely linked media like
-Quicktimes, etc.
-
-**Example**::
-
- sg = shotgun_api3.Shotgun("https://piedpiper.shotgunstudio.com",
- login="rhendriks",
- password="c0mPre$Hi0n")
- sg.find("Shot", filters=[["sg_status_list", "is", "ip"]], fields=["code", "sg_status_list])
-
-**Output**::
-
- [{'code': 'bunny_020_0170',
- 'id': 896,
- 'sg_sequence': {'id': 5, 'name': 'bunny_020', 'type': 'Sequence'},
- 'sg_status_list': 'ip',
- 'type': 'Shot'},
- {'code': 'bunny_020_0200',
- 'id': 899,
- 'sg_sequence': {'id': 5, 'name': 'bunny_020', 'type': 'Sequence'},
- 'sg_status_list': 'ip',
- 'type': 'Shot'},
- {'code': 'bunny_030_0080',
- 'id': 907,
- 'sg_sequence': {'id': 6, 'name': 'bunny_030', 'type': 'Sequence'},
- 'sg_status_list': 'ip',
- 'type': 'Shot'}]
-
-
-**********
-User Guide
-**********
-.. toctree::
- :maxdepth: 2
-
- installation
- authentication
- reference
- cookbook
- advanced
-
-
-Indices and tables
-==================
-
-* :ref:`genindex`
-* :ref:`modindex`
-* :ref:`search`
-
diff --git a/_sources/installation.txt b/_sources/installation.txt
deleted file mode 100644
index b6659ec25..000000000
--- a/_sources/installation.txt
+++ /dev/null
@@ -1,57 +0,0 @@
-############
-Installation
-############
-
-********************
-Minimum Requirements
-********************
-
-- Shotgun server v5.4.14 or higher for API v3.0.16+.
-- Shotgun server v2.4.12 or higher for API v3.0.8.
-- Shotgun server v1.8 or higher for API v3.0.7.
-- Python v2.4 - v2.7. (We do not currently support Python 3)
-
-.. note::
- Some features of the API are only supported by more recent versions of the Shotgun server.
- These features are added to the Python API in a backwards compatible way so that existing
- scripts will continue to function as expected. Accessing a method that is not supported for
- your version of Shotgun will raise an appropriate exception. In general, we attempt to
- document these where possible.
-
-
-*******************
-Installing manually
-*******************
-You can `download the latest release from Github `_
-or `clone the repo `_ to your local filesystem.
-You'll need to save it somewhere your local Python installation can find it.
-
-.. seealso:: For more information on ``PYTHONPATH`` and using modules in Python, see
- http://docs.python.org/tutorial/modules.html
-
-***********************
-Installing with ``pip``
-***********************
-
-Installing the Master Branch From Github
-========================================
-If you wish to install the current master, use the following command::
-
- pip install git+git://github.com/shotgunsoftware/python-api.git
-
-.. note:: The master branch contains the latest revisions and while largely considered "stable" it
- is not an official packaged release.
-
-Installing A specific Version From Github
-=========================================
-To install a specific version of the package from Github, run the following command. This example
-installs the v3.0.26 tag, replace the version tag with the one you want::
-
- pip install git+git://github.com/shotgunsoftware/python-api.git@v3.0.26
-
-
-requirements.txt
-~~~~~~~~~~~~~~~~
-If you're using pip with `requirements.txt`, add the following line::
-
- git+git://github.com/shotgunsoftware/python-api.git
diff --git a/_sources/local_files.txt b/_sources/local_files.txt
deleted file mode 100644
index 460088d3c..000000000
--- a/_sources/local_files.txt
+++ /dev/null
@@ -1,151 +0,0 @@
-.. _local_files:
-
-########################
-Working With Local Files
-########################
-
-We added support for linking to local files in the UI in Shotgun Server v2.1. This doc covers how
-to work with these local file links using the API.
-
-************
-Requirements
-************
-
-* Python API v3.0.3+
-* Shotgun Server v2.1.10+
-
-******************************
-Structure of Local File Values
-******************************
-
-There is a key in the dictionary that represents file/link fields called ``link_type`` which can be
-one of ``local``, ``upload``, ``web``. This is used to determine what type of link the field value
-contains. For local files this value is always ``local`` and there are additional keys that
-are available:
-
-- **content_type** (:obj:`str`):
- The mime-type of the associated local file. This is assigned
- automatically using a best-guess based on the file extension. You can override this by setting
- this explicitly.
-
-- **link_type** (:obj:`str`) *read-only*:
- Always 'local' for local files.
-
-- **name** (:obj:`str`):
- the display name of the local file. This is set to the filename by
- default but can be overridden by setting this explicitly.
-
-- **local_path** (:obj:`str`):
- The full path to the file on the current platform. The Python API tries to determine the
- platform it is currently running on and then copies the value from the corresponding key above
- to this field for convenience.
-
-- **local_path_linux** (:obj:`str`) *read-only*:
- Full path to file on Linux as defined by the LocalStorage (or ``None`` if no Linux path is set)
-
-- **local_path_mac** (:obj:`str`) *read-only*:
- Full path to file on Mac OS X as defined by the LocalStorage (or ``None`` if no Mac path is set)
-
-- **local_path_windows** (:obj:`str`) *read-only*:
- Full path to file on Windows as defined by the LocalStorage (or ``None`` if no Windows path
- is set)
-
-- **local_storage** (:obj:`dict`) *read-only*:
- A dictionary representing which LocalStorage entity is applied for this local file link.
-
-- **url** (:obj:`str`) *read-only*:
- A file:// link provided for convenience pointing to the value in the ``local_path``
-
-*************************
-Reading Local File Fields
-*************************
-
-::
-
- fields = ['sg_uploaded_movie']
- result = sg.find('Version', [['id', 'is', 123]], fields)
-
-Returns::
-
- {'id':123,
- 'sg_uploaded_movie': { 'content_type': None,
- 'link_type': 'local',
- 'name': 'my_test_movie.mov',
- 'local_path': '/Users/kp/Movies/testing/test_movie_001_.mov'
- 'local_path_linux': '/home/users/macusers/kp/Movies/testing/test_movie_001_.mov'
- 'local_path_mac': '/Users/kp/Movies/testing/test_movie_001_.mov'
- 'local_path_windows': 'M:\\macusers\kp\Movies\testing\test_movie_001_.mov'
- 'local_storage': {'id': 1,
- 'name': 'Dailies Directories',
- 'type': 'LocalStorage'},
- 'url': 'file:///Users/kp/Movies/testing/test_movie_001_.mov'},
- 'type': 'Version'}
-
-.. note::
- When viewing results that include file/link fields with local file link values, all of the
- keys will be returned regardless of whether there are values in them. So in the above example,
- if there was no Windows path set for the local storage, ``local_path_windows`` would be
- ``None``.
-
-.. _creating_local_files:
-
-*************************************
-Creating & Updating Local file Fields
-*************************************
-When setting a file/link field value to a local file, only the ``local_path`` is mandatory. Shotgun
-will automatically select the appropriate matching local storage for your file based on the path.
-You can optionally specify the ``name`` and ``content_type`` fields if you wish to override their
-defaults. Any other keys that are provided will be ignored.
-
-* **content_type** :obj:`str`:
- Optionally set the mime-type of the associated local file. This is assigned automatically
- using a best-guess based on the file extension.
-
-
-* **name** :obj:`str`:
- Optional display name of the local file. This is set to the filename by default.
-
-* **local_path** :obj:`str`:
- The full local path to the file. Shotgun will find the LocalStorage
- that has the most specific match to this path and automatically assign that LocalStorage to
- the file.
-
-::
-
- data = {'sg_uploaded_movie': {'local_path': '/Users/kp/Movies/testing/test_movie_002.mov',
- 'name': 'Better Movie'}
- result = sg.update('Version', 123, data)
-
-Returns::
-
- {'id':123,
- 'sg_uploaded_movie': { 'content_type': 'video/quicktime',
- 'link_type': 'local',
- 'name': 'my_test_movie.mov',
- 'local_path': '/Users/kp/Movies/testing/test_movie_002.mov'
- 'local_path_linux': '/home/users/macusers/kp/Movies/testing/test_movie_002.mov'
- 'local_path_mac': '/Users/kp/Movies/testing/test_movie_002.mov'
- 'local_path_windows': 'M:\\macusers\kp\Movies\testing\test_movie_002.mov'
- 'local_storage': {'id': 1,
- 'name': 'Dailies Directories',
- 'type': 'LocalStorage'},
- 'url': 'file:///Users/kp/Movies/testing/test_movie_002.mov'},
- 'type': 'Version'}]
-
-The ``content_type`` was assigned a best-guess value based on the file extension. Shotgun selected
-the most appropriate specific LocalStorage match and assigned it to local_storage automatically.
-
-**********************************
-Un-setting local file field values
-**********************************
-
-Removing a a local file field value is simple. Just set the value to ``None``::
-
- data = {'sg_uploaded_movie': None}
- result = sg.update('Version', 123, data)
-
-Returns::
-
- {'id':123,
- 'sg_uploaded_movie': None,
- 'type': 'Version'}]
diff --git a/_sources/packaging.txt b/_sources/packaging.txt
deleted file mode 100644
index a09e159ad..000000000
--- a/_sources/packaging.txt
+++ /dev/null
@@ -1,40 +0,0 @@
-.. _packaging:
-
-################################################
-Packaging an application with py2app (or py2exe)
-################################################
-
-You can create standalone applications with Python scripts by using
-`py2app `_ on OS X or `py2exe `_ on
-Windows. This is often done to more easily distribute applications that have a GUI based on
-toolkits like Tk, Qt or others.
-
-There are caveats you need to be aware of when creating such an app.
-
-********************************
-HTTPS Validation and cacerts.txt
-********************************
-When creating the connection to Shotgun a file is used to validate the Shotgun certificate. This
-file is located at ``shotgun_api3/lib/httplib2/cacerts.txt``. Because this file is not a Python
-file imported by your application, py2app will not know to include it in your package, it will
-need to be explicitly specified in your ``setup.py`` file (edit the path based on the location
-where your ``shotgun_api3`` package is located)::
-
- DATA_FILES = [
- ('shotgun_api3', ['/shotgun/src/python-api/shotgun_api3/lib/httplib2/cacerts.txt'])
- ]
-
-Once you create your py2app package its contents should include two files (among others) in the
-following structure::
-
- ./Contents/Resources/shotgun_api3/cacerts.txt
- ./Contents/Resources/my_script.py
-
-Where in ``my_script.py`` you can access the ``cacerts.txt`` file using a relative path to pass it
-into the Shotgun connection's constructor::
-
- ca_certs = os.path.join(os.path.dirname(__file__), 'shotgun_api3', 'cacerts.txt')
- sg = shotgun_api3.Shotgun('https://yoursite.shotgunstudio.com', 'script_name', 'script_key',
- ca_certs=ca_certs)
-
-The process for py2exe should be similar.
\ No newline at end of file
diff --git a/_sources/reference.txt b/_sources/reference.txt
deleted file mode 100644
index 39a97abce..000000000
--- a/_sources/reference.txt
+++ /dev/null
@@ -1,870 +0,0 @@
-.. currentmodule:: shotgun_api3
-
-.. _apireference:
-
-#############
-API Reference
-#############
-
-
-*****************************
-``shotgun`` Module Attributes
-*****************************
-
-The :mod:`~shotgun_api3.shotgun` module is a container for the :class:`~shotgun.Shotgun`
-class. There are a couple of useful attributes to note.
-
-.. automodule:: shotgun_api3.shotgun
- :members: NO_SSL_VALIDATION, LOG
- :private-members:
- :special-members:
-
-***************
-Shotgun()
-***************
-
-.. autoclass:: Shotgun
- :show-inheritance:
-
-***************
-Shotgun Methods
-***************
-
-The majority of functionality is contained within the :class:`~shotgun_api3.Shotgun` class.
-The documentation for all of the methods you'll need in your scripts lives in here.
-
-.. rubric:: Connection & Authentication
-
-.. autosummary::
- :nosignatures:
-
- Shotgun.connect
- Shotgun.close
- Shotgun.authenticate_human_user
- Shotgun.get_session_token
- Shotgun.set_up_auth_cookie
- Shotgun.add_user_agent
- Shotgun.reset_user_agent
- Shotgun.set_session_uuid
- Shotgun.info
-
-.. rubric:: CRUD Methods
-
-.. autosummary::
- :nosignatures:
-
- Shotgun.create
- Shotgun.find
- Shotgun.find_one
- Shotgun.update
- Shotgun.delete
- Shotgun.revive
- Shotgun.batch
- Shotgun.summarize
- Shotgun.note_thread_read
- Shotgun.text_search
- Shotgun.update_project_last_accessed
- Shotgun.work_schedule_read
- Shotgun.work_schedule_update
-
-.. rubric:: Working With Files
-
-.. autosummary::
- :nosignatures:
-
- Shotgun.upload
- Shotgun.upload_thumbnail
- Shotgun.upload_filmstrip_thumbnail
- Shotgun.download_attachment
- Shotgun.get_attachment_download_url
- Shotgun.share_thumbnail
-
-.. rubric:: Activity Stream
-
-.. autosummary::
- :nosignatures:
-
- Shotgun.activity_stream_read
- Shotgun.follow
- Shotgun.unfollow
- Shotgun.followers
-
-.. rubric:: Working with the Shotgun Schema
-
-.. autosummary::
- :nosignatures:
-
- Shotgun.schema_entity_read
- Shotgun.schema_field_read
- Shotgun.schema_field_create
- Shotgun.schema_field_update
- Shotgun.schema_field_delete
- Shotgun.schema_read
- Shotgun.schema
- Shotgun.entity_types
-
-
-Connection & Authentication
-===========================
-
-These methods are used for connecting and authenticating with your Shotgun server. Most of
-this is done automatically when you instantiate your instance. But if you need finer-grain
-control, these methods are available.
-
-.. automethod:: Shotgun.connect
-.. automethod:: Shotgun.close
-.. automethod:: Shotgun.authenticate_human_user
-.. automethod:: Shotgun.get_session_token
-.. automethod:: Shotgun.set_up_auth_cookie
-.. automethod:: Shotgun.add_user_agent
-.. automethod:: Shotgun.reset_user_agent
-.. automethod:: Shotgun.set_session_uuid
-.. automethod:: Shotgun.info
-
-CRUD Methods
-============
-
-These are the main methods for creating, reading, updating, and deleting information. There are
-also some specialized convenience methods for accessing particular types of information.
-
-.. automethod:: Shotgun.create
-.. automethod:: Shotgun.find
-.. automethod:: Shotgun.find_one
-.. automethod:: Shotgun.update
-.. automethod:: Shotgun.delete
-.. automethod:: Shotgun.revive
-.. automethod:: Shotgun.batch
-.. automethod:: Shotgun.summarize
-.. automethod:: Shotgun.note_thread_read
-.. automethod:: Shotgun.text_search
-.. automethod:: Shotgun.update_project_last_accessed
-.. automethod:: Shotgun.work_schedule_read
-.. automethod:: Shotgun.work_schedule_update
-
-Working With Files
-==================
-
-Methods that handle uploading and downloading files including thumbnails.
-
-.. seealso:: :ref:`attachments`
-
-.. automethod:: Shotgun.upload
-.. automethod:: Shotgun.upload_thumbnail
-.. automethod:: Shotgun.upload_filmstrip_thumbnail
-.. automethod:: Shotgun.download_attachment
-.. automethod:: Shotgun.get_attachment_download_url
-.. automethod:: Shotgun.share_thumbnail
-
-Activity Stream
-===============
-
-Methods that relate to the activity stream and following of entities in Shotgun.
-
-.. automethod:: Shotgun.activity_stream_read
-.. automethod:: Shotgun.follow
-.. automethod:: Shotgun.unfollow
-.. automethod:: Shotgun.followers
-
-Working with the Shotgun Schema
-===============================
-
-Methods allow you to introspect and modify the Shotgun schema.
-
-.. automethod:: Shotgun.schema_entity_read
-.. automethod:: Shotgun.schema_field_read
-.. automethod:: Shotgun.schema_field_create
-.. automethod:: Shotgun.schema_field_update
-.. automethod:: Shotgun.schema_field_delete
-.. automethod:: Shotgun.schema_read
-.. automethod:: Shotgun.schema
-.. automethod:: Shotgun.entity_types
-
-**********
-Exceptions
-**********
-
-These are the various exceptions that the Shotgun API will raise.
-
-.. autoclass:: shotgun_api3.ShotgunError
- :show-inheritance:
- :inherited-members:
- :members:
-
-.. autoclass:: shotgun_api3.ShotgunFileDownloadError
- :show-inheritance:
- :inherited-members:
- :members:
-
-.. autoclass:: shotgun_api3.Fault
- :show-inheritance:
- :inherited-members:
- :members:
-
-.. autoclass:: shotgun_api3.AuthenticationFault
- :show-inheritance:
- :inherited-members:
- :members:
-
-.. autoclass:: shotgun_api3.MissingTwoFactorAuthenticationFault
- :show-inheritance:
- :inherited-members:
- :members:
-
-
-.. _filter_syntax:
-
-*************
-Filter Syntax
-*************
-
-Basic Filters
-=============
-
-Filters are represented as a list of conditions that will be combined using the supplied
-filter_operator (``any`` or ``all``). Each condition follows the basic simple form::
-
- [, , ]
-
-Basic Example
--------------
-Using the default filter_operator ``"all"``, the following filters will return all Shots whose status
-is "ip" AND is linked to Asset #9::
-
- filters = [
- ["sg_status_list", "is", "ip"],
- ["assets", "is", {"type": "Asset", "id": 9}]
- ]
- result = sg.find("Shot", filters)
-
-
-Complex Filters
-===============
-
-.. versionadded::3.0.11
-
-Complex filters can be a dictionary that represents a complex sub-condition of the form::
-
- {"filter_operator": "any", "filters": []}
-
-Complex Example
----------------
-Using the default filter_operator ``"all"``, the following filters will return all Shots whose status
-is "ip" AND is linked to either Asset #9 OR Asset #23::
-
- filters = [
- ["sg_status_list", "is", "ip"],
- {
- "filter_operator": "any",
- "filters": [
- ["assets", "is", {"type": "Asset", "id": 9}],
- ["assets", "is", {"type": "Asset", "id": 23}]
- ]
- }
- ]
- result = sg.find("Shot", filters)
-
-
-Operators and Arguments
-=======================
-
-::
-
- Operator Arguments
- -------- ---------
- 'is' [field_value] | None
- 'is_not' [field_value] | None
- 'less_than' [field_value] | None
- 'greater_than' [field_value] | None
- 'contains' [field_value] | None
- 'not_contains' [field_value] | None
- 'starts_with' [string]
- 'ends_with' [string]
- 'between' [[field_value] | None, [field_value] | None]
- 'not_between' [[field_value] | None, [field_value] | None]
- 'in_last' [[int], 'HOUR' | 'DAY' | 'WEEK' | 'MONTH' | 'YEAR']
- # note that brackets are not literal (eg. ['start_date', 'in_last', 1, 'DAY'])
- 'in_next' [[int], 'HOUR' | 'DAY' | 'WEEK' | 'MONTH' | 'YEAR']
- # note that brackets are not literal (eg. ['start_date', 'in_next', 1, 'DAY'])
- 'in' [[field_value] | None, ...] # Array of field values
- 'type_is' [string] | None # Shotgun entity type
- 'type_is_not' [string] | None # Shotgun entity type
- 'in_calendar_day' [int] # Offset (e.g. 0 = today, 1 = tomorrow,
- # -1 = yesterday)
- 'in_calendar_week' [int] # Offset (e.g. 0 = this week, 1 = next week,
- # -1 = last week)
- 'in_calendar_month' [int] # Offset (e.g. 0 = this month, 1 = next month,
- # -1 = last month)
- 'name_contains' [string]
- 'name_not_contains' [string]
- 'name_starts_with' [string]
- 'name_ends_with' [string]
-
-
-Valid Operators By Data Type
-============================
-
-::
-
- addressing 'is'
- 'is_not'
- 'contains'
- 'not_contains'
- 'in'
- 'type_is'
- 'type_is_not'
- 'name_contains'
- 'name_not_contains'
- 'name_starts_with'
- 'name_ends_with'
-
- checkbox 'is'
- 'is_not'
-
- currency 'is'
- 'is_not'
- 'less_than'
- 'greater_than'
- 'between'
- 'not_between'
- 'in'
- 'not_in'
-
- date 'is'
- 'is_not'
- 'greater_than'
- 'less_than'
- 'in_last'
- 'not_in_last'
- 'in_next'
- 'not_in_next'
- 'in_calendar_day'
- 'in_calendar_week'
- 'in_calendar_month'
- 'in_calendar_year'
- 'between'
- 'in'
- 'not_in'
-
- date_time 'is'
- 'is_not'
- 'greater_than'
- 'less_than'
- 'in_last'
- 'not_in_last'
- 'in_next'
- 'not_in_next'
- 'in_calendar_day'
- 'in_calendar_week'
- 'in_calendar_month'
- 'in_calendar_year'
- 'between'
- 'in'
- 'not_in'
-
- duration 'is'
- 'is_not'
- 'greater_than'
- 'less_than'
- 'between'
- 'in'
- 'not_in'
-
- entity 'is'
- 'is_not'
- 'type_is'
- 'type_is_not'
- 'name_contains'
- 'name_not_contains'
- 'name_is'
- 'in'
- 'not_in'
-
- float 'is'
- 'is_not'
- 'greater_than'
- 'less_than'
- 'between'
- 'in'
- 'not_in'
-
- image 'is' ** Note: For both 'is' and 'is_not', the only supported value is None,
- 'is_not' ** which supports detecting the presence or lack of a thumbnail.
-
- list 'is'
- 'is_not'
- 'in'
- 'not_in'
-
- multi_entity 'is' ** Note: when used on multi_entity, this functions as
- you would expect 'contains' to function
- 'is_not'
- 'type_is'
- 'type_is_not'
- 'name_contains'
- 'name_not_contains'
- 'in'
- 'not_in'
-
- number 'is'
- 'is_not'
- 'less_than'
- 'greater_than'
- 'between'
- 'not_between'
- 'in'
- 'not_in'
-
- password ** Filtering by this data type field not supported
-
- percent 'is'
- 'is_not'
- 'greater_than'
- 'less_than'
- 'between'
- 'in'
- 'not_in'
-
- serializable ** Filtering by this data type field not supported
-
- status_list 'is'
- 'is_not'
- 'in'
- 'not_in'
-
- summary ** Filtering by this data type field not supported
-
-
- tag_list 'is' ** Note: when used on tag_list, this functions as
- you would expect 'contains' to function
- 'is_not'
- 'name_contains'
- 'name_not_contains'
- 'name_id'
-
- text 'is'
- 'is_not'
- 'contains'
- 'not_contains'
- 'starts_with'
- 'ends_with'
- 'in'
- 'not_in'
-
-
- timecode 'is'
- 'is_not'
- 'greater_than'
- 'less_than'
- 'between'
- 'in'
- 'not_in'
-
- url ** Filtering by this data type field is not supported
-
-
-.. _additional_filter_presets:
-
-Additional Filter Presets
-=========================
-
-As of Shotgun version 7.0 it is possible to also use filter presets. These presets provide a simple
-way to specify powerful query filters that would otherwise be costly and difficult to craft using
-traditional filters.
-
-Multiple presets can be specified in cases where it makes sense.
-
-Also, these presets can be used alongside normal filters. The result returned is an AND operation
-between the specified filters.
-
-Example Uses
-------------
-
-The following query will return the Version with the name 'ABC' that is linked to the latest entity
-created::
-
- additional_filter_presets = [
- {
- "preset_name": "LATEST",
- "latest_by": "ENTITIES_CREATED_AT"
- }
- ]
-
- filters = [['code', 'is', 'ABC']]
-
- result = sg.find('Version', filters = filters, additional_filter_presets = additional_filter_presets)
-
-
-The following query will find all CutItems associated to Cut #1 and return all Versions associated
-to the Shot linked to each of these CutItems::
-
- additional_filter_presets = [
- {
- "preset_name": "CUT_SHOT_VERSIONS",
- "cut_id": 1
- }
- ]
-
- result = sg.find('Version', additional_filter_presets = additional_filter_presets)
-
-Available Filter Presets by Entity Type
----------------------------------------
-
-Allowed filter presets (and preset parameter values) depend on the entity type being searched.
-
-The table bellow gives the details about which filter preset can be used on each entity type and
-with which parameters.
-
-::
-
- Entity Type Preset Name Preset Parameters Allowed Preset Parameter Values
- ----------- ----------- ----------------- -------------------------------
- Cut LATEST [string] latest_by 'REVISION_NUMBER':
- Returns the cuts that have the
- highest revision number.
- This is typically used with a query
- filter that returns cuts with the
- same value for a given field
- (e.g. code field). This preset
- therefore allows to get
- the Cut of that set that has
- the highest revision_number value.
-
- Version CUT_SHOT_VERSIONS [int] cut_id Valid Cut entity id.
- Returns all Version entities
- associated to the Shot entity
- associated to the CutItems
- of the given Cut.
- This basically allows to find all
- Versions associated to the given
- Cut, via its CutItems.
-
- LATEST [string] latest_by 'ENTITIES_CREATED_AT':
- When dealing with multiple
- Versions associated to a group
- of entities, returns only the
- last Version created for each
- entity.
- For example, when dealing with a
- set of Shots, this preset allows
- to find the latest Version created
- for each of these Shots.
-
- 'BY_PIPELINE_STEP_NUMBER_AND_ENTITIES_CREATED_AT':
- When dealing with multiple versions
- associated to the same entity *and*
- to Tasks, returns the Version
- associated to the Task with highest
- step.list_order.
- If multiple Versions are found for
- that step.list_order, only the
- latest Version is returned.
- This allows to isolate the Version
- entity that is the farthest along
- in the pipeline for a given entity.
- For example, when dealing with a Shot
- with multiple Versions, this preset
- will return the Version associated
- to the Task with the highest
- step.list_order value.
-
-.. _data_types:
-
-**********
-Data Types
-**********
-
-addressing
-==========
-
-:value: :obj:`list`
-
-List of dicts::
-
- [
- {
- 'type': 'HumanUser' | 'Group',
- 'id': int,
- ...
- },
- ...
- ]
-
-checkbox
-========
-
-:value: :obj:`bool` (``True`` | ``False``)
-
-color
-=====
-
-:value: :obj:`str`
-:example: ``255,0,0`` | ``pipeline_step``
-
-``pipeline_step`` indicates the Task color inherits from the Pipeline Step color.
-
-currency
-========
-
-:value: :obj:`float` | :obj:`None`
-:range: ``-9999999999999.99``, ``9999999999999.99``
-
-date
-====
-
-:value: :obj:`str` | :obj:`None`
-:range: Year must be >= 1970
-:example: ``YYYY-MM-DD``
-
-date_time
-=========
-
-:value: :mod:`datetime` | :obj:`None`
-:range: Year must be >= 1970
-
- .. note::
- Datetimes are stored as UTC on the server. The Shotgun API is configured to automatically
- convert between client local time and UTC. This can be overridden.
-
-duration
-========
-
-:value: :obj:`int` | :obj:`None`
-:range: ``-2147483648``, ``2147483647``
-
-Length of time, in minutes
-
-entity
-======
-
-:value: :obj:`dict` | :obj:`None`
-
-::
-
- {
- 'type': "string",
- 'id': int,
- ...
- }
-
-float
-=====
-
-:value: :obj:`float` | :obj:`None`
-:range: ``-999999999.999999``, ``999999999.999999``
-
-footage
-=======
-
-:value: :obj:`str` | :obj:`None` ``FF-ff``
-:range: Frames must be < Preferences value for "Advanced > Number of frames per foot of film"
-
- .. note::
- Format matches Preference value for "Formatting > Display of footage fields".
- Example above is default.F=Feet f=Frames.
-
-image (read-only)
-=================
-
-:value: :obj:`str` | :obj:`None`
-
-list
-====
-
-:value: :obj:`str` | :obj:`None`
-
-multi_entity
-============
-
-:value: :obj:`list`
-
-List of dicts
-
-::
-
- [
- {
- 'type': "string",
- 'id': int,
- ...
- },
- ...
- ]
-
-number
-======
-
-:value: :obj:`int` | ``None``
-:range: ``-2147483648``, ``2147483647``
-
-password
-========
-
-:value: :obj:`string` | ``None``
-
-Returned values of password fields are replaced with ``*******`` for security
-
-percent
-=======
-
-:value: :obj:`int` | ``None``
-:range: ``-2147483648``, ``2147483647``
-
-serializable
-============
-
-:value: :obj:`dict` | ``None``
-
-status_list
-===========
-
-:value: :obj:`str` | ``None``
-
-system_task_type (deprecated)
-=============================
-
-:value: :obj:`str` | ``None``
-
-tag_list
-========
-
-:value: :obj:`list`
-
-text
-====
-
-:value: :obj:`str` | ``None``
-
-timecode
-========
-
-:value: :obj:`int` | ``None``
-:range: ``-2147483648``, ``2147483647``
-
-Length of time, in milliseconds (1000 = 1 second)
-
-url (file/link field)
-=====================
-
-:value: :obj:`dict` | ``None``
-
-::
-
- {
- 'content_type': "string",
- 'link_type': "local" | "url" | "upload",
- 'name': "string",
- 'url': "string"
- }
-
-Local File Links
-----------------
-
-Additional keys exist for local file links
-
-:value: :obj:`dict` | ``None``
-
-::
-
- {
- 'content_type': "string",
- 'link_type': "local",
- 'local_path': "string" | None,
- 'local_path_linux': "string" | None,
- 'local_path_mac': "string" | None,
- 'local_path_windows': "string" | None,
- 'local_storage': {dictionary},
- 'name': "string",
- 'url': "string",
- }
- API versions < v3.0.3:
-
- {
- 'url': "string",
- 'name': "string",
- 'content_type': "string"
- }
-
-.. _event_types:
-
-***********
-Event Types
-***********
-
-Whenever a user makes a change to any data in Shotgun, an event log entry record is created,
-capturing the value before and after. Shotgun also logs some additional useful events that help keep
-track of various activity on your Shotgun instance.
-
-Event-based Triggers
-====================
-
-Events are particularlly useful when used in conjunction with a trigger framework like the
-`Shotgun Event Daemon `_. This allows you to
-write plug-ins that watch for certain types of events and then run code when they occur.
-
-Structure of Event Types
-========================
-
-The basic structure of event types is broken into 3 parts:
-
-``Application_EntityType_Action``
-
-- ``Application``: Is always "Shotgun" for events automatically created by the Shotgun server.
- Other Shotgun products may use their name in here, for example, Toolkit has its own events
- that it logs and the application portion is identified by "Toolkit". If you decide to use the
- EventLogEntry entity to log events for your scripts or tools, you would use your tool name here.
-- ``EntityType``: This is the entity type in Shotgun that was acted upon (eg. Shot, Asset, etc.)
-- ``Action``: The general action that was taken. (eg. New, Change, Retirement, Revival)
-
-
-Standard Event Types
-====================
-
-Each entity type has a standard set of events associated with it when it's created, updated,
-deleted, and revived. They follow this pattern:
-
-- ``Shotgun_EntityType_New``: a new entity was created. Example: ``Shotgun_Task_New``
-- ``Shotgun_EntityType_Change``: an entity was modified. Example: ``Shotgun_HumanUser_Change``
-- ``Shotgun_EntityType_Retirement``: an entity was deleted. Example: ``Shotgun_Ticket_Retirement``
-- ``Shotgun_EntityType_Revival``: an entity was revived. Example: ``Shotgun_CustomEntity03_Revival``
-
-Additional Event Types
-======================
-
-These are _some_ of the additional event types that are logged by Shotgun:
-
-- ``Shotgun_Attachment_View``: an Attachment (file) was viewed by a user.
-- ``Shotgun_Reading_Change``: a threaded entity has been marked read or unread. For example, a
- Note was read by a user. The readings are unique to the entity<->user connection so when a
- Note is read by user "joe" it may still be unread by user "jane".
-- ``Shotgun_User_Login``: a user logged in to Shotgun.
-- ``Shotgun_User_Logout``: a user logged out of Shotgun.
-
-
-Custom Event Types
-==================
-
-Since ``EventLogEntries`` are entities themselves, you can create them using the API just like any
-other entity type. As mentioned previously, if you'd like to have your scripts or tools log to
-the Shotgun event log, simply devise a thoughtful naming structure for your event types and
-create the EventLogEntry as needed following the usual methods for creating entities via the API.
-
-Again, other Shotgun products like Toolkit use event logs this way.
-
-.. note::
- EventLogEntries cannot be updated or deleted (that would defeat the purpose of course).
-
-Performance
-===========
-
-Event log database tables can get large very quickly. While Shotgun does very well with event logs
-that get into the millions of records, there's an inevitable degradation of performance for pages
-that display them in the web application as well as any API queries for events when they get too
-big. This volume of events is not the norm, but can be reached if your server expereinces high
-usage.
-
-This **does not** mean your Shotgun server performance will suffer in general, just any pages that
-are specifically displaying EventLogEntries in the web application, or API queries on the event
-log that are run. We are always looking for ways to improve this in the future. If you have any
-immediate concerns, please `reach out to our support team `_
-
-
diff --git a/_sources/server_changelog.txt b/_sources/server_changelog.txt
deleted file mode 100644
index acc835d1f..000000000
--- a/_sources/server_changelog.txt
+++ /dev/null
@@ -1,71 +0,0 @@
-############################
-Shotgun Server API Changelog
-############################
-
-.. warning:: This list is out of date and has not been updated since 5/2014
-
-The following is a list of changes in the Shotgun server code that affect the API. These are not changes in the Python API code, rather fixes/changes to the Shotgun server's API interface that may affect behavior. Generally changes to the Shotgun server API code are ensured to be non-breaking and backwards compatible bug fixes and feature enhancements. This is to ensure your scripts will not unexpectedly break when updating.
-
-These updates should also appear on the general Release Notes pages but are provided here for convenience.
-
-Format: **[Shotgun server version]**: Description of change made. [internal ticket #]
-
-****
-5.3
-****
-- **[5.3.15]**: Added filtering out Archived projects. [25082]
-- **[5.3.12]**: Added support for API ``sudo_as_user``. [19989]
-
-****
-5.1
-****
-- **[5.1.22]**: Added ``followers()``, ``follow()``, and ``unfollow()`` methods to code handling API requests. [20562]
-
-****
-3.3
-****
-- **[3.3.1]**: Modified CRUD code so that if a request reads, sorts, or summarizes a join (ConnectionEntity) field, and the parent entity has not been passed in the request, the code will try to infer it from the filter conditions. Prior to this fix on 3.3 - the API was returning an error when trying to sort Versions on ``playlists.PlaylistVersionConnection.sg_sort_order``. Note that if the parent entity cannot be inferred automatically, this error will still occur. [17107]
-- **[3.3.0]**: Added support for returning the full paths of thumbnail fields in regular API calls. This works for thumbnail fields on the entity, linked thumbnails, and filmstrip thumbnails. [10693]
-- **[3.0.0]**: We've released v3.0.8 of the Python API which now includes a JSON backend. The JSON transport is up to 40% faster than the XML-RPC based transport. The XML-RPC interface will continue to be supported but may not include new features, so previous versions of the API will still be supported as-is.
-- **[3.0.0]**: Added support for ``name_is`` filter operator on single and multi-entity fields, both in the API and the UI.
-
-****
-2.4
-****
-- **[2.4.8]**: Added support for ``id`` inquiry filters in the API. The syntax is slightly different than similar filters, in that the filter value is not an array. [14261]
-- **[2.4.6]**: Fixed issue with multi-entity field filters where Python ``None`` was passed in. Prior to this fix, one could not use the API to create filters such as ``['task_assignees', 'is', None]`` or ``['task_assignees', 'is_not', None]``, without generating an API error. These filters are now allowed, and work as expected. [14111]
-- **[2.4.0]**: Added query builder and API support for next/previous modifiers for the ``in calendar period`` filter operators for date and datetime fields. For example, "find tasks that were created in the last 7 months..."
-- **[2.4.0]**: Ensured that the UI and the API disallow configuring Note Links field to allow the Task or Note entity type.
-- **[2.4.0]**: Date fields now require ``YYYY-MM-DD`` format. Previously they were documented as requiring that format, but would actually allow other date formats if the server was able to parse them into a valid date.
-
-****
-2.3
-****
-- **[2.3.9]**: Ensured that creating a task (via the API) with ONLY the duration set - if that task is created with an upstream task that has an end date - results in the created task having both its Start and Due date set by the task dependency logic. [13407]
-- **[2.3.7]**: Ensured API parity with UI in terms of passing in filters on linked fields more than 1 link away. [12867]
-- **[2.3.7]**: Ensured that API errors are not thrown when creating/updating a task with ``milestone=True``, and ``start_date=end_date``. This behavior is true when using ``create()``, ``update()``, or either method with ``batch()``. Also, added a unit test to cover this. [13318]
-- **[2.3.5]**: Added API support for getting Shotgun's version and build number. Usage requires Shotgun Python API v3.0.6 or higher.
-- **[2.3.3]**: Fixed bug with API where local file paths for windows mount points were being double-escaped, resulting in ``\`` character sequences. [13119]
-
-****
-2.2
-****
-- **[2.2.5]**: Ensured that API calls requesting summary fields do not result in silent logging on errors to production.log. This fix results in no change for API programmers, but does ensure that such API calls can occur without the possibility of killing apache due to unwieldy and unnecessary logging. [12850]
-- **[2.2.4]**: Ensured that creating a Task Template Task through the API doesn't require a project id - unlike creating a non template task. [11283]
-- **[2.2.4]**: Fixed error generated when trying to revive a Script (``ApiUser``) via the API [12794]
-
-****
-2.1
-****
-- **[2.1.2]**: Enforced uniqueness on Script names (``ApiUser``) so that when creating scripts, the naming conflicts will no longer be allowed. [11479]
-- **[2.1.0]**: added a ``revive()`` method in the API. Syntax follows that of ``delete()``
-
-****
-2.0
-****
-- **[2.0.8]**: Disallowed retired scripts from authenticating via the API. The main Shotgun method will still return a valid Shotgun instance, but any other method calls will return the following error... ``shotgun.Fault: [11480]``
-- **[2.0.0]**: Added the ability to link to local files via the API.
-- **[2.0.0]**: Provided API support for ``layout_project`` for Project creation. Functionality mirrors the web interface: omitting ``layout_project`` creates the Project based on Template Project. Supplying ``layout_project`` ensures that the new project is based on the supplied project. This fixes the problem of script-created projects having no pages - since they lacked a template, implicit or explicit.
-- **[2.0.0]**: Improved API error message resulting when trying to set the ``default_value`` property on non status list fields, using ``schema_field_create()``.
-- **[2.0.0]**: Removed legacy support for ``sg_system_task_type``. Now, all API methods should use Pipeline Steps instead.
-- **[2.0.0]**: ended support for API v2 (API2)
\ No newline at end of file
diff --git a/_sources/smart_cut_fields.txt b/_sources/smart_cut_fields.txt
deleted file mode 100644
index f6949e902..000000000
--- a/_sources/smart_cut_fields.txt
+++ /dev/null
@@ -1,49 +0,0 @@
-.. _smart_cut_fields:
-
-################
-Smart Cut Fields
-################
-
-If you want to work with 'smart' cut fields through the API, your script should use a corresponding
-'raw' fields for all updates. The 'smart_cut_fields' are primarily for display in the UI, the real
-data is stored in a set of 'raw' fields that have different names.
-
-************
-Smart Fields
-************
-
-In the UI these fields attempt to calculate values based on data entered into the various fields.
-These fields can be queried via the API using the find() method, but not updated. Note that we are
-deprecating this feature and recommend creating your own cut fields from scratch, which will not
-contain any calculations which have proven to be too magical at times.
-
-- ``smart_cut_duration``
-- ``smart_cut_in``
-- ``smart_cut_out``
-- ``smart_cut_summary_display`` *
-- ``smart_cut_duration_display`` *
-- ``smart_head_duration``
-- ``smart_head_in``
-- ``smart_head_out``
-- ``smart_tail_duration``
-- ``smart_tail_in``
-- ``smart_tail_out``
-- ``smart_working_duration`` *
-
-.. note:: \* these are special summary fields that have no corresponding "raw" field.
-
-**********
-Raw Fields
-**********
-
-These are the "raw" fields that can be queried and updated through the API:
-
-- ``cut_duration``
-- ``cut_in``
-- ``cut_out``
-- ``head_duration``
-- ``head_in``
-- ``head_out``
-- ``tail_duration``
-- ``tail_in``
-- ``tail_out``
diff --git a/_sources/tasks.txt b/_sources/tasks.txt
deleted file mode 100644
index 13dd02660..000000000
--- a/_sources/tasks.txt
+++ /dev/null
@@ -1,14 +0,0 @@
-##################
-Working With Tasks
-##################
-
-Tasks have various special functionality available in the UI that can also be queried and
-manipulated through the API. The sections below cover these topics.
-
-.. toctree::
- :maxdepth: 2
-
-
- tasks/updating_tasks
- tasks/task_dependencies
- tasks/split_tasks
diff --git a/_sources/tasks/split_tasks.txt b/_sources/tasks/split_tasks.txt
deleted file mode 100644
index 5134d2e78..000000000
--- a/_sources/tasks/split_tasks.txt
+++ /dev/null
@@ -1,257 +0,0 @@
-.. _split_tasks:
-
-###########
-Split Tasks
-###########
-
-Split tasks can be created and edited via the API but must comply to some rules. Before going
-further, a good understanding of :ref:`how Shotgun handles task dates is useful `.
-
-********
-Overview
-********
-
-The Task entity has a field called ``splits`` which is a list of dictionaries. Each dictionary
-in the list has two string keys, ``start`` and ``end``, who's values are strings representing dates
-in the ``YYYY-mm-dd`` format.
-
-::
-
- [{'start': '2012-12-11', 'end': '2012-12-12'}, {'start': '2012-12-18', 'end': '2012-12-19'}]
-
-- Splits should be ordered from eldest to newest.
-- There should be gaps between each split.
-
- - Gaps are defined as at least one working day. Non-workdays such as weekends and holidays
- are not gaps.
-
-If there are multiple splits but there between two or more splits there is no gap, an error will be
-raised. For example::
-
- >>> sg.update('Task', 2088, {'splits':[{'start':'2012-12-10', 'end':'2012-12-11'}, {'start':'2012-12-12', 'end':'2012-12-14'}, {'start':'2012-12-19', 'end':'2012-12-20'}]})
- Traceback (most recent call last):
- File "", line 1, in
- File "/shotgun/src/python-api/shotgun_api3/shotgun.py", line 600, in update
- record = self._call_rpc("update", params)
- File "/shotgun/src/python-api/shotgun_api3/shotgun.py", line 1239, in _call_rpc
- self._response_errors(response)
- File "/shotgun/src/python-api/shotgun_api3/shotgun.py", line 1435, in _response_errors
- "Unknown Error"))
- shotgun_api3.shotgun.Fault: API update() CRUD ERROR #5: Update failed for [Task.splits]: (task.rb) The start date in split segment 2 is only one calendar day away from the end date of the previous segment. There must be calendar days between split segments.
-
-Alternately, a split value can be set to ``None`` to remove splits (you can also use an empty list).
-This will preserve the ``start_date`` and ``due_date`` values but recalculate the ``duration`` value
-while appropriately considering all workday rules in effect.
-
-********************************************************
-How Do Splits Influence Dates And Dates Influence Splits
-********************************************************
-
-- If splits are specified the supplied ``start_date``, ``due_date`` and ``duration`` fields will be ignored.
-- The ``start_date`` will be inferred from the earliest split.
-- The ``due_date`` will be inferred from the last split.
-- If the ``start_date`` is changed on a task that has splits the first split will be moved to start
- on the new ``start_date`` and all further splits will be moved while maintaining gap lengths
- between splits and respecting workday rules.
-- If the ``due_date`` is changed on a task that has splits the last split will be moved to end on
- the new ``due_date`` and all prior splits will be moved while maintaining gap lengths between
- splits and respecting workday rules.
-- If the ``duration`` is changed two scenarios are possible
-
- - In the case of a longer duration, additional days will be added to the end of the last split
- - In the case of a shorter duration splits, starting with the latest ones, will be either
- removed or shortened until the new duration is met.
-
-Examples
-========
-Throughout the following examples, each successive one will build on the previous.
-
-start_date, due_date and duration being ignored
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-
-::
-
- sg.update('Task', 2088, {
- 'start_date': '2012-12-06',
- 'due_date': '2012-12-23',
- 'duration': 3600,
- 'splits': [
- {'start': '2012-12-11', 'end': '2012-12-12'},
- {'start': '2012-12-18', 'end': '2012-12-19'}
- ]
- })
-
- # Task = {
- # 'start_date': '2012-12-11',
- # 'due_date': '2012-12-19',
- # 'duration': 2400,
- # 'splits': [
- # {'start': '2012-12-11', 'end': '2012-12-12'},
- # {'start': '2012-12-18', 'end': '2012-12-19'}
- # ]
- # }
-
-Result:
-
-.. image:: images/split_tasks_1.png
-
-Moving the start_date of a split task
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-
-::
-
- sg.update('Task', 2088, {
- 'start_date': '2012-12-10'
- })
-
- # Task = {
- # 'start_date': '2012-12-10',
- # 'due_date': '2012-12-18',
- # 'splits': [
- # {'start': '2012-12-10', 'end': '2012-12-11'},
- # {'start': '2012-12-14', 'end': '2012-12-18'}
- # ]
- # }
-
-Result:
-
-.. image:: images/split_tasks_2.png
-
-Moving the due_date of a split task
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-
-::
-
- sg.update('Task', 2088, {
- 'due_date': '2012-12-19'
- })
-
- # Task = {
- # 'start_date': '2012-12-10',
- # 'due_date': '2012-12-19',
- # 'splits': [
- # {'start': '2012-12-10', 'end': '2012-12-11'},
- # {'start': '2012-12-14', 'end': '2012-12-19'}
- # ]
- # }
-
-Result:
-
-.. image:: images/split_tasks_3.png
-
-Setting a longer duration
-~~~~~~~~~~~~~~~~~~~~~~~~~
-
-::
-
- sg.update('Task', 2088, {
- 'duration': 4200
- })
-
- # Task = {
- # 'start_date': '2012-12-10',
- # 'due_date': '2012-12-21',
- # 'duration': 4200,
- # 'splits': [
- # {'start': '2012-12-10', 'end': '2012-12-11'},
- # {'start': '2012-12-14', 'end': '2012-12-21'}
- # ]
- # }
-
-Result:
-
-.. image:: images/split_tasks_4.png
-
-Setting a shorter duration
-~~~~~~~~~~~~~~~~~~~~~~~~~~
-
-::
-
- sg.update('Task', 2088, {
- 'duration': 2400
- })
-
- # Task = {
- # 'start_date': '2012-12-10',
- # 'due_date': '2012-12-18',
- # 'duration': 2400,
- # 'splits': [
- # {'start': '2012-12-10', 'end': '2012-12-11'},
- # {'start': '2012-12-14', 'end': '2012-12-18'}
- # ]
- # }
-
-Result:
-
-.. image:: images/split_tasks_5.png
-
-Another example of shorter duration
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-We won't be using the previous result for this example but rather, the following:
-
-.. image:: images/split_tasks_6.png
-
-who's duration we will shorten past the last split.
-
-::
-
- sg.update('Task', 2088, {
- 'duration': 1800
- })
-
- # Task = {
- # 'start_date': '2012-12-10',
- # 'due_date': '2012-12-18',
- # 'duration': 2400,
- # 'splits': [
- # {'start': '2012-12-10', 'end': '2012-12-11'},
- # {'start': '2012-12-14', 'end': '2012-12-18'}
- # ]
- # }
-
-Result:
-
-.. image:: images/split_tasks_7.png
-
-Setting the due_date in a gap
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-
-When a due date is set in a gap later splits are removed and the day of the due date is considered
-a day when work will be done.
-
-For this example let's assume as a starting point the result of the 5th example:
-
-.. image:: images/split_tasks_8.png
-
-::
-
- sg.update('Task', 2088, {
- 'due_date': '2012-12-13'
- })
-
- # Task = {
- # 'start_date': '2012-12-10',
- # 'due_date': '2012-12-13',
- # 'duration': 1800,
- # 'splits': [
- # {'start': '2012-12-10', 'end': '2012-12-11'},
- # {'start': '2012-12-13', 'end': '2012-12-13'}
- # ]
- # }
-
-Result:
-
-.. image:: images/split_tasks_9.png
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/_sources/tasks/task_dependencies.txt b/_sources/tasks/task_dependencies.txt
deleted file mode 100644
index fde003783..000000000
--- a/_sources/tasks/task_dependencies.txt
+++ /dev/null
@@ -1,339 +0,0 @@
-.. _task_dependencies:
-
-#################
-Task Dependencies
-#################
-
-Task dependencies work the same way in the API as they do in the UI. You can filter and sort on
-any of the fields. For information about Task Dependencies in Shotgun, check out the `main
-documentation page on our support site
-`_
-
-************
-Create Tasks
-************
-
-Let's create a couple of Tasks and create dependencies between them. First we'll create a "Layout"
-Task for our Shot::
-
- data = {
- 'project': {'type':'Project', 'id':65},
- 'content': 'Layout',
- 'start_date': '2010-04-28',
- 'due_date': '2010-05-05',
- 'entity': {'type':'Shot', 'id':860}
- }
- result = sg.create(Task, data)
-
-
-Returns::
-
- {'content': 'Layout',
- 'due_date': '2010-05-05',
- 'entity': {'id': 860, 'name': 'bunny_010_0010', 'type': 'Shot'},
- 'id': 556,
- 'project': {'id': 65, 'name': 'Demo Animation Project', 'type': 'Project'},
- 'start_date': '2010-04-28',
- 'type': 'Task'}
-
-
-Now let's create an "Anm" Task for our Shot::
-
- data = {
- 'project': {'type':'Project', 'id':65},
- 'content': 'Anm',
- 'start_date': '2010-05-06',
- 'due_date': '2010-05-12',
- 'entity': {'type':'Shot', 'id':860}
- }
- result = sg.create(Task, data)
-
-Returns::
-
- {'content': 'Anm',
- 'due_date': '2010-05-12',
- 'entity': {'id': 860, 'name': 'bunny_010_0010', 'type': 'Shot'},
- 'id': 557,
- 'project': {'id': 65, 'name': 'Demo Animation Project', 'type': 'Project'},
- 'start_date': '2010-05-06,
- 'type': 'Task'}
-
-
-*******************
-Create A Dependency
-*******************
-
-Tasks each have an ``upstream_tasks`` field and a ``downstream_tasks`` field. Each field is a
-list ``[]`` type and can contain zero, one, or multiple Task entity dictionaries representing the
-dependent Tasks. Here is how to create a dependency between our "Layout" and "Anim" Tasks::
-
- # make 'Layout' and upstream Task to 'Anm'. (aka, make 'Anm' dependent on 'Layout')
- result = sg.update('Task', 557, {'upstream_tasks':[{'type':'Task','id':556}]})
-
-Returns::
-
- [{'id': 557,
- 'type': 'Task',
- 'upstream_tasks': [{'id': 556, 'name': 'Layout', 'type': 'Task'}]}]
-
-This will also automatically update the `downstream_tasks` field on 'Layout' to include the 'Anm' Task.
-
-**********************************
-Query Tasks with Dependency Fields
-**********************************
-
-So now lets look at the Tasks we've created and their dependency-related fields::
-
- filters = [
- ['entity', 'is', {'type':'Shot', 'id':860}]
- ]
- fields = [
- 'content',
- 'start_date',
- 'due_date',
- 'upstream_tasks',
- 'downstream_tasks',
- 'dependency_violation',
- 'pinned'
- ]
- result = sg.find("Task", filters, fields)
-
-Returns::
-
- [{'content': 'Layout',
- 'dependency_violation': False,
- 'downstream_tasks': [{'type': 'Task', 'name': 'Anm', 'id': 557}],
- 'due_date': '2010-05-05',
- 'id': 556,
- 'pinned': False,
- 'start_date': '2010-04-28',
- 'type': 'Task',
- 'upstream_tasks': []},
- {'content': 'Anm',
- 'dependency_violation': False,
- 'downstream_tasks': [{'type': 'Task', 'name': 'FX', 'id': 558}],
- 'due_date': '2010-05-12',
- 'id': 557,
- 'pinned': False,
- 'start_date': '2010-05-06',
- 'type': 'Task',
- 'upstream_tasks': [{'type': 'Task', 'name': 'Layout', 'id': 556}]},
- ...
-
-*Note that we have also created additional Tasks for this Shot but we're going to focus on these
-first two for simplicity.*
-
-*****************************************************************
-Updating the End Date on a Task with Downstream Task Dependencies
-*****************************************************************
-
-If we update the ``due_date`` field on our "Layout" Task, we'll see that the "Anm" Task dates
-will automatically get pushed back to keep the dependency satisfied::
-
- result = sg.update('Task', 556, {'due_date': '2010-05-07'})
-
-Returns::
-
- [{'due_date': '2010-05-07', 'type': 'Task', 'id': 556}]
-
-Our Tasks now look like this (notice the new dates on the "Anm" Task)::
-
- [{'content': 'Layout',
- 'dependency_violation': False,
- 'downstream_tasks': [{'type': 'Task', 'name': 'Anm', 'id': 557}],
- 'due_date': '2010-05-07',
- 'id': 556,
- 'pinned': False,
- 'start_date': '2010-04-28',
- 'type': 'Task',
- 'upstream_tasks': []},
- {'content': 'Anm',
- 'dependency_violation': False,
- 'downstream_tasks': [{'type': 'Task', 'name': 'FX', 'id': 558}],
- 'due_date': '2010-05-14',
- 'id': 557,
- 'pinned': False,
- 'start_date': '2010-05-10',
- 'type': 'Task',
- 'upstream_tasks': [{'type': 'Task', 'name': 'Layout', 'id': 556}]},
- ...
-
-
-**********************************************************
-Creating a Dependency Violation by pushing up a Start Date
-**********************************************************
-
-Task Dependencies can work nicely if you are pushing out an end date for a Task as it will just
-recalculate the dates for all of the dependent Tasks. But what if we push up the Start Date of our
-"Anm" Task to start before our "Layout" Task is scheduled to end?
-
-::
-
- result = sg.update('Task', 557, {'start_date': '2010-05-06'})
-
-Returns::
-
- [{'type': 'Task', 'start_date': '2010-05-06', 'id': 557}]
-
-Our Tasks now look like this::
-
- [{'content': 'Layout',
- 'dependency_violation': False,
- 'downstream_tasks': [{'type': 'Task', 'name': 'Anm', 'id': 557}],
- 'due_date': '2010-05-07',
- 'id': 556,
- 'pinned': False,
- 'start_date': '2010-04-28',
- 'type': 'Task',
- 'upstream_tasks': []},
- {'content': 'Anm',
- 'dependency_violation': True,
- 'downstream_tasks': [{'type': 'Task', 'name': 'FX', 'id': 558}],
- 'due_date': '2010-05-12',
- 'id': 557,
- 'pinned': True,
- 'start_date': '2010-05-06',
- 'type': 'Task',
- 'upstream_tasks': [{'type': 'Task', 'name': 'Layout', 'id': 556}]},
- ...
-
-Because the "Anm" Task ``start_date`` depends on the ``due_date`` of the "Layout" Task, this
-change creates a dependency violation. The update succeeds, but Shotgun has also set the
-``dependency_violation`` field to ``True`` and has also updated the ``pinned`` field to ``True``.
-
-The ``pinned`` field simply means that if the upstream Task(s) are moved, the "Anm" Task will no
-longer get moved with it. The dependency is still there (in ``upstream_tasks``) but the Task is
-now "pinned" to those dates until the Dependency Violation is resolved.
-
-***********************************************************
-Resolving a Dependency Violation by updating the Start Date
-***********************************************************
-
-We don't want that violation there. Let's revert that change so the Start Date for "Anm" is after
-the End Date of "Layout"::
-
- result = sg.update('Task', 557, {'start_date': '2010-05-10'})
-
-Returns::
-
- [{'type': 'Task', 'start_date': '2010-05-10', 'id': 557}]
-
-Our Tasks now look like this::
-
- [{'content': 'Layout',
- 'dependency_violation': False,
- 'downstream_tasks': [{'type': 'Task', 'name': 'Anm', 'id': 557}],
- 'due_date': '2010-05-07',
- 'id': 556,
- 'pinned': False,
- 'start_date': '2010-04-28',
- 'type': 'Task',
- 'upstream_tasks': []},
- {'content': 'Anm',
- 'dependency_violation': False,
- 'downstream_tasks': [{'type': 'Task', 'name': 'FX', 'id': 558}],
- 'due_date': '2010-05-14',
- 'id': 557,
- 'pinned': True,
- 'start_date': '2010-05-10',
- 'type': 'Task',
- 'upstream_tasks': [{'type': 'Task', 'name': 'Layout', 'id': 556}]},
- ...
-
-The ``dependency_violation`` field has now been set back to ``False`` since there is no longer
-a violation. But notice that the ``pinned`` field is still ``True``. We will have to manually
-update that if we want the Task to travel with its dependencies again::
-
- result = sg.update('Task', 557, {'pinned': False})
-
-Returns::
-
- [{'pinned': False, 'type': 'Task', 'id': 557}]
-
-Our Tasks now look like this::
-
- [{'content': 'Layout',
- 'dependency_violation': False,
- 'downstream_tasks': [{'type': 'Task', 'name': 'Anm', 'id': 557}],
- 'due_date': '2010-05-07',
- 'id': 556,
- 'pinned': False,
- 'start_date': '2010-04-28',
- 'type': 'Task',
- 'upstream_tasks': []},
- {'content': 'Anm',
- 'dependency_violation': False,
- 'downstream_tasks': [{'type': 'Task', 'name': 'FX', 'id': 558}],
- 'due_date': '2010-05-14',
- 'id': 557,
- 'pinned': False,
- 'start_date': '2010-05-10',
- 'type': 'Task',
- 'upstream_tasks': [{'type': 'Task', 'name': 'Layout', 'id': 556}]},
- ...
-
-Looks great. But that's an annoying manual process. What if we want to just reset a Task so that
-it automatically gets updated so that the Start Date is after its dependent Tasks?
-
-*******************************************************************
-Updating the ``pinned`` field on a Task with a Dependency Violation
-*******************************************************************
-
-Let's go back a couple of steps to where our "Anm" Task had a Dependency Violation because we had
-moved the Start Date up before the "Layout" Task End Date. Remember that the ``pinned`` field
-was also ``True``. If we simply update the ``pinned`` field to be ``False``, Shotgun will also
-automatically update the Task dates to satisfy the upstream dependencies and reset the
-``dependency_violation`` value to ``False``::
-
- result = sg.update('Task', 557, {'pinned': False})
-
-Returns::
-
- [{'pinned': False, 'type': 'Task', 'id': 557}]
-
-
-Our Tasks now look like this::
-
- [{'content': 'Layout',
- 'dependency_violation': False,
- 'downstream_tasks': [{'type': 'Task', 'name': 'Anm', 'id': 557}],
- 'due_date': '2010-05-07',
- 'id': 556,
- 'pinned': False,
- 'start_date': '2010-04-28',
- 'type': 'Task',
- 'upstream_tasks': []},
- {'content': 'Anm',
- 'dependency_violation': False,
- 'downstream_tasks': [{'type': 'Task', 'name': 'FX', 'id': 558}],
- 'due_date': '2010-05-14',
- 'id': 557,
- 'pinned': False,
- 'start_date': '2010-05-10',
- 'type': 'Task',
- 'upstream_tasks': [{'type': 'Task', 'name': 'Layout', 'id': 556}]},
- ...
-
-
-Notice by updating ``pinned`` to ``False``, Shotgun also updated the ``start_date`` and
-``due_date`` fields of our "Anm" Task so it will satisfy the upstream Task dependencies. And since
-that succeeded, the ``dependency_violation`` field has also been set to ``False``
-
-*******************************************
-``dependency_violation`` field is read-only
-*******************************************
-
-The ``dependency_violation`` field is the only dependency-related field that is read-only. Trying
-to modify it will generate a Fault::
-
- result = sg.update('Task', 557, {'dependency_violation': False})
-
-Returns::
-
- # --------------------------------------------------------------------------------
- # XMLRPC Fault 103:
- # API update() Task.dependency_violation is read only:
- # {"value"=>false, "field_name"=>"dependency_violation"}
- # --------------------------------------------------------------------------------
- # Traceback (most recent call last):
- # ...
diff --git a/_sources/tasks/updating_tasks.txt b/_sources/tasks/updating_tasks.txt
deleted file mode 100644
index b7c57a051..000000000
--- a/_sources/tasks/updating_tasks.txt
+++ /dev/null
@@ -1,371 +0,0 @@
-.. _updating_tasks:
-
-#######################################
-Updating Task Dates: How Shotgun Thinks
-#######################################
-
-When updating Task dates in an API update() request, there is no specified order to the values that
-are passed in. Shotgun also does automatic calculation of the``start_date``,``due_date``, and ``duration`` fields for convenience. In order to clarify how updates are handled by Shotgun we are
-providing some general rules below and examples of what will happen when you make updates to your
-Tasks.
-
-**************
-General Rules
-**************
-
-- Updating the ``start_date`` automatically updates the ``due_date`` (``duration`` remains constant)
-- Updating the ``due_date`` automatically updates the ``duration`` (``start_date`` remains constant)
-- Updating the ``duration`` automatically updates the ``due_date`` (``start_date`` remains constant)
-- When updating Task values, Shotgun sets schedule fields (``milestone``, ``duration``,
- ``start_date``, ``due_date``) after all other fields, because the Project and Task Assignees
- affect schedule calculations.
-- If ``start_date`` and ``due_date`` are both set, ``duration`` is ignored (``duration`` can often
- be wrong since it's easy to calculate scheduling incorrectly).
-- If both ``start_date`` and ``due_date`` are provided, Shotgun sets ``start_date`` before
- ``due_date``.
-- Set ``milestone`` before other schedule fields (because ``start_date``, ``due_date``, and
- ``duration`` get lost if ``milestone`` is not set to ``False`` first)
-- If ``milestone`` is being set to ``True``, ``duration`` is ignored.
-- If ``milestone`` is set to ``True`` and ``start_date`` and ``due_date`` are also being set to
- conflicting values, an Exception is raised.
-- If ``due_date`` and ``duration`` are set together (without ``start_date``), ``duration`` is set
- first, then ``due_date`` (otherwise setting ``duration`` will change ``due_date`` after it is
- set).
-
-********
-Examples
-********
-
-The following examples show what the resulting Task object will look like after being run on the
-initial Task object listed under the header of each section.
-
-The ``duration`` values in the following examples assume your Shotgun instance is set to
-10-hour work days. If your server is configured with a different setting, the ``duration`` values
-will vary.
-
-.. note:: The ``duration`` field stores ``duration`` values in minutes
-
-Universal
-=========
-Regardless of current values on the Task, this behavior rules::
-
- Task = {'start_date': '2011-05-20', 'due_date': '2011-05-25', 'duration': 2400, 'id':123}
-
-Update start_date and due_date
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-``duration`` is ignored if also provided. It is instead set automatically as (``due_date`` -
-``start_date``)
-
-::
-
- sg.update ('Task', 123, {'start_date':'2011-05-25', 'due_date':'2011-05-30', 'duration':1200})
- # Task = {'start_date': '2011-05-25', 'due_date': '2011-05-30', 'duration': 2400, 'id':123}
-
-- ``start_date`` is updated.
-- ``due_date`` is updated.
-- ``duration`` is calculated as (``due_date`` - ``start_date``)
-
-.. note:: The value provided in the update() is ignored (and in this case was also incorrect).
-
-Update start_date and duration
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-
-::
-
- sg.update ('Task', 123, {'start_date':'2011-05-25', 'duration':3600})
- # Task = {'start_date': '2011-05-25', 'due_date': '2011-06-01', 'duration': 3600, 'id':123}
-
-- ``start_date`` is updated.
-- ``duration`` is updated.
-- ``due_date`` is updated to (``start_date`` + ``duration``).
-
-Update due_date and duration
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-
-::
-
- sg.update ('Task', 123, {'due_date': '2011-05-20', 'duration':3600})
- # Task = {'start_date': '2011-05-20', 'due_date': '2011-05-20', 'duration': 600, 'id':123}
-
-- ``duration`` is updated.
-- ``due_date`` is updated.
-- ``duration`` is calculated as (``due_date`` - ``start_date``)
-
-.. note:: This means the ``duration`` provided is overwritten.
-
-Task has start_date only
-========================
-
-::
-
- Task = {'start_date': '2011-05-20', 'due_date': None, 'duration': None, 'id':123}
-
-Update start_date
-~~~~~~~~~~~~~~~~~
-
-::
-
- sg.update ('Task', 123, {'start_date':'2011-05-25'})
- # Task = {'start_date': '2011-05-25', 'due_date': None, 'duration': None, 'id':123}
-
-- Only ``start_date`` is updated.
-
-Update due_date
-~~~~~~~~~~~~~~~
-
-::
-
- sg.update ('Task', 123, {'due_date':'2011-05-25'})
- # Task = {'start_date': '2011-05-20', 'due_date': '2011-05-25', 'duration': 2400, 'id':123}
-
-- ``due_date`` is updated.
-- ``duration`` is updated to (``due_date`` - ``start_date``).
-
-Update duration
-~~~~~~~~~~~~~~~
-
-::
-
- sg.update ('Task', 123, {'duration':2400})
- # Task = {'start_date': '2011-05-20', 'due_date': '2011-05-25', 'duration': 2400, 'id':123}
-
-- ``duration`` is updated.
-- ``due_date`` is set to (``start_date`` + ``duration``)
-
-Task has due_date only
-======================
-
-::
-
- # Task = {'start_date': None, 'due_date': '2011-05-25', 'duration': None, 'id':123}
-
-Update start_date
-~~~~~~~~~~~~~~~~~
-
-::
-
- sg.update ('Task', 123, {'start_date':'2011-05-20'})
- # Task = {'start_date': '2011-05-20', 'due_date': '2011-05-25', 'duration': 2400, 'id':123}
-
-- ``start_date`` is updated.
-- ``duration`` is updated to (``due_date`` - ``start_date``).
-
-Update due_date
-~~~~~~~~~~~~~~~
-
-::
-
- sg.update ('Task', 123, {'due_date':'2011-05-20'})
- # Task = {'start_date': None, 'due_date': '2011-05-20', 'duration': None, 'id':123}
-
-- only ``due_date`` is updated.
-
-Update duration
-~~~~~~~~~~~~~~~
-
-::
-
- sg.update ('Task', 123, {'duration':2400})
- # Task = {'start_date': '2011-05-20', 'due_date': '2011-05-25', 'duration': 2400, 'id':123}
-
-- ``duration`` is updated.
-- ``start_date`` is set to (``due_date`` - ``duration``)
-
-Task has duration only
-======================
-
-::
-
- # Task = {'start_date': None, 'due_date': None, 'duration': 2400, 'id':123}
-
-Update start_date
-~~~~~~~~~~~~~~~~~
-
-::
-
- sg.update ('Task', 123, {'start_date':'2011-05-20'})
- # Task = {'start_date': '2011-05-20', 'due_date': '2011-05-25', 'duration': 2400, 'id':123}
-
-- ``start_date`` is updated.
-- ``due_date`` is updated to (``start_date`` + ``duration``).
-
-Update due_date
-~~~~~~~~~~~~~~~
-
-::
-
- sg.update ('Task', 123, {'due_date':'2011-05-25'})
- # Task = {'start_date': '2011-05-20', 'due_date': '2011-05-25', 'duration': 2400, 'id':123}
-
-- ``due_date`` is updated.
-- ``start_date`` is updated to (``due_date`` - ``duration``)
-
-Update duration
-~~~~~~~~~~~~~~~
-
-::
-
- sg.update ('Task', 123, {'duration':3600})
- # Task = {'start_date': None, 'due_date': None, 'duration': 3600, 'id':123}
-
-- only ``duration`` is updated.
-
-Task has start_date and due_date (no duration)
-==============================================
-
-::
-
- # Task = {'start_date': '2011-05-20', 'due_date': '2011-05-25', 'duration': None, 'id':123}
-
-Update start_date
-~~~~~~~~~~~~~~~~~
-
-::
-
- sg.update ('Task', 123, {'start_date':'2011-05-25'})
- # Task = {'start_date': '2011-05-25', 'due_date': '2011-05-25', 'duration': 600, 'id':123}
-
-- ``start_date`` is updated.
-- ``duration`` is updated to (``due_date`` - ``start_date``).
-
-Update due_date
-~~~~~~~~~~~~~~~
-
-::
-
- sg.update ('Task', 123, {'due_date':'2011-05-30'})
- # Task = {'start_date': '2011-05-20', 'due_date': '2011-05-30', 'duration': 4200, 'id':123}
-
-- ``due_date`` is updated.
-- ``duration`` is updated to (``due_date`` - ``start_date``)
-
-Update duration
-~~~~~~~~~~~~~~~
-
-::
-
- sg.update ('Task', 123, {'duration':3600})
- # Task = {'start_date': '2011-05-20', 'due_date': '2011-05-27', 'duration': 3600, 'id':123}
-
-- ``duration`` is updated.
-- ``due_date`` is updated to (``start_date`` + ``duration``)
-
-Task has start_date and duration (no due_date)
-==============================================
-
-::
-
- # Task = {'start_date': '2011-05-20', 'due_date': None, 'duration': 2400, 'id':123}
-
-Update start_date
-~~~~~~~~~~~~~~~~~
-
-::
-
- sg.update ('Task', 123, {'start_date':'2011-05-25'})
- # Task = {'start_date': '2011-05-25', 'due_date': '2011-05-30', 'duration': 2400, 'id':123}
-
-- ``start_date`` is updated.
-- ``due_date`` is updated to (``start_date`` +``duration``).
-
-Update due_date
-~~~~~~~~~~~~~~~
-
-::
-
- sg.update ('Task', 123, {'due_date':'2011-05-30'})
- # Task = {'start_date': '2011-05-20', 'due_date': '2011-05-30', 'duration': 4200, 'id':123}
-
-- ``due_date`` is updated.
-- ``duration`` is updated to (``due_date`` - ``start_date``).
-
-Update duration
-~~~~~~~~~~~~~~~
-
-::
-
- sg.update ('Task', 123, {'duration':3600})
- # Task = {'start_date': '2011-05-20', 'due_date': '2011-05-27', 'duration': 3600, 'id':123}
-
-- ``duration`` is updated.
-- ``due_date`` is updated to (``start_date`` + ``duration``)
-
-Task has due_date and duration (no start_date)
-==============================================
-
-::
-
- # Task = {'start_date': None, 'due_date': '2011-05-25', 'duration': 2400, 'id':123}
-
-Update start_date
-~~~~~~~~~~~~~~~~~
-
-::
-
- sg.update ('Task', 123, {'start_date':'2011-05-25'})
- # Task = {'start_date': '2011-05-25', 'due_date': '2011-05-30', 'duration': 2400, 'id':123}
-
-- ``start_date`` is updated.
-- ``due_date`` is updated to (``start_date`` + ``duration``).
-
-Update due_date
-~~~~~~~~~~~~~~~
-
-::
-
- sg.update ('Task', 123, {'due_date':'2011-05-30'})
- # Task = {'start_date': '2011-05-25', 'due_date': '2011-05-30', 'duration': 2400, 'id':123}
-
-- ``due_date`` is updated.
-- ``start_date`` is updated to (``due_date`` - ``duration``).
-
-Update duration
-~~~~~~~~~~~~~~~
-
-::
-
- sg.update ('Task', 123, {'duration':3600})
- # Task = {'start_date': '2011-05-18', 'due_date': '2011-05-25', 'duration': 3600, 'id':123}
-
-- ``duration`` is updated.
-- ``start_date`` is updated to (``due_date`` - ``duration``)
-
-Task has start_date ,due_date, and duration
-===========================================
-
-::
-
- # Task = {'start_date': '2011-05-20', 'due_date': '2011-05-25', 'duration': 2400, 'id':123}
-
-Update start_date
-~~~~~~~~~~~~~~~~~
-
-::
-
- sg.update ('Task', 123, {'start_date':'2011-05-25'})
- # Task = {'start_date': '2011-05-20', 'due_date': '2011-05-30', 'duration': 2400, 'id':123}
-
-- ``start_date`` is updated.
-- ``due_date`` is updated to (``start_date`` + ``duration``).
-
-Update due_date
-~~~~~~~~~~~~~~~
-
-::
-
- sg.update ('Task', 123, {'due_date':'2011-05-30'})
- # Task = {'start_date': '2011-05-20', 'due_date': '2011-05-30', 'duration': 4200, 'id':123}
-
-- ``due_date`` is updated.
-- ``duration`` is updated to (``due_date`` - ``start_date``)
-
-Update duration
-~~~~~~~~~~~~~~~
-
-::
-
- sg.update ('Task', 123, {'duration':3600})
- # Task = {'start_date': '2011-05-20', 'due_date': '2011-05-27', 'duration': 3600, 'id':123}
-
-- ``duration`` is updated.
-- ``due_date`` is updated to (``start_date`` + ``duration``)
\ No newline at end of file
diff --git a/_sources/tutorials.txt b/_sources/tutorials.txt
deleted file mode 100644
index 24930746b..000000000
--- a/_sources/tutorials.txt
+++ /dev/null
@@ -1,29 +0,0 @@
-########
-Examples
-########
-
-Here's a list of various simple tutorials to walk through that should provide you with a good base
-understanding of how to use the Shotgun API and what you can do with it.
-
-.. toctree::
- :maxdepth: 1
-
- examples/basic_sg_instance
- examples/basic_create_shot
- examples/basic_find_shot
- examples/basic_update_shot
- examples/basic_delete_shot
- examples/basic_create_shot_task_template
- examples/basic_create_version_link_shot
- examples/basic_upload_thumbnail_version
-
-********
-Advanced
-********
-
-.. toctree::
- :maxdepth: 1
-
- examples/ami_handler
- examples/ami_version_packager
- examples/svn_integration
diff --git a/_sources/usage_tips.txt b/_sources/usage_tips.txt
deleted file mode 100644
index 8a909f7fc..000000000
--- a/_sources/usage_tips.txt
+++ /dev/null
@@ -1,302 +0,0 @@
-##############
-API Usage Tips
-##############
-
-Below is a list of helpful tips when using the Shotgun API. We have tried to make the API very
-simple to use with predictable results while remaining a powerful tool to integrate with your
-pipeline. However, there's always a couple of things that crop up that our users might not be
-aware of. Those are the types of things you'll find below. We'll be adding to this document over
-time as new questions come up from our users that exhibit these types of cases.
-
-*********
-Importing
-*********
-
-We strongly recommend you import the entire `shotgun_api3` module instead of just importing the
-:class:`shotgun_api3.Shotgun` class from the module. There is other important functionality that
-is managed at the module level which may not work as expected if you only import the
-:class:`shotgun_api3.Shotgun` object.
-
-Do::
-
- import shotgun_api3
-
-Don't::
-
- from shotgun_api3 import Shotgun
-
-***************
-Multi-threading
-***************
-The Shotgun API is not thread-safe. If you want to do threading we strongly suggest that you use
-one connection object per thread and not share the connection.
-
-*************
-Entity Fields
-*************
-
-When you do a :meth:`~shotgun_api3.Shotgun.find` call that returns a field of type entity or
-multi-entity (for example the 'assets' column on Shot), the entities are returned in a standard
-dictionary::
-
- {'type': 'Asset', 'name': 'redBall', 'id': 1}
-
-For each entity returned, you will get a ``type``, ``name``, and ``id`` key. This does not mean
-there are fields named ``type`` and ``name`` on the Asset. These are only used to provide a
-consistent way to represent entities returned via the API.
-
-- ``type``: the entity type (CamelCase)
-- ``name``: the display name of the entity. For most entity types this is the value of the ``code``
- field but not always. For example, on the Ticket and Delivery entities the ``name`` key would
- contain the value of the ``title`` field.
-
-.. _custom_entities:
-
-**************
-CustomEntities
-**************
-Entity types are always referenced by their original names. So if you enable CustomEntity01 and
-call it **Widget**. When you access it via the API, you'll still use CustomEntity01 as the
-``entity_type``.
-
-If you want to be able to remember what all of your CustomEntities represent in a way where you
-don't need to go look it up all the time when you're writing a new script, we'd suggest creating
-a mapping table or something similar and dumping it in a shared module that your studio uses.
-Something like the following::
-
- # studio_globals.py
-
- entity_type_map = {
- 'Widget': 'CustomEntity01',
- 'Foobar': 'CustomEntity02',
- 'Baz': 'CustomNonProjectEntity01,
- }
-
- # or even simpler, you could use a global like this
- ENTITY_WIDGET = 'CustomEntity01'
- ENTITY_FOOBAR = 'CustomEntity02'
- ENTITY_BAZ = 'CustomNonProjectEntity01'
-
-Then when you're writing scripts, you don't need to worry about remembering which Custom Entity
-"Foobars" are, you just use your global::
-
- import shotgun_api3
- import studio_globals
-
- sg = Shotgun('https://mystudio.shotgunstudio.com', 'script_name', '0123456789abcdef0123456789abcdef0123456')
- result = sg.find(studio_globals.ENTITY_WIDGET,
- filters=[['sg_status_list', 'is', 'ip']],
- fields=['code', 'sg_shot'])
-
-.. _connection_entities:
-
-******************
-ConnectionEntities
-******************
-
-Connection entities exist behind the scenes for any many-to-many relationship. Most of the time
-you won't need to pay any attention to them. But in some cases, you may need to track information
-on the instance of one entity's relationship to another.
-
-For example, when viewing a list of Versions on a Playlist, the Sort Order (``sg_sort_order``) field is an
-example of a field that resides on the connection entity between Playlists and Versions. This
-connection entity is appropriately called `PlaylistVersionConnection`. Because any Version can
-exist in multiple Playlists, the sort order isn't specific to the Version, it's specific to
-each _instance_ of the Version in a Playlist. These instances are tracked using connection
-entities in Shtogun and are accessible just like any other entity type in Shotgun.
-
-To find information about your Versions in the Playlist "Director Review" (let's say it has an
-``id`` of 4). We'd run a query like so::
-
- filters = [['playlist', 'is', {'type':'Playlist', 'id':4}]]
- fields = ['playlist.Playlist.code', 'sg_sort_order', 'version.Version.code', 'version.Version.user', 'version.Version.entity']
- order=[{'column':'sg_sort_order','direction':'asc'}]
- result = sg.find('PlaylistVersionConnection', filters, fields, order)
-
-
-Which returns the following::
-
- [{'id': 28,
- 'playlist.Playlist.code': 'Director Review',
- 'sg_sort_order': 1.0,
- 'type': 'PlaylistVersionConnection',
- 'version.Version.code': 'bunny_020_0010_comp_v003',
- 'version.Version.entity': {'id': 880,
- 'name': 'bunny_020_0010',
- 'type': 'Shot'},
- 'version.Version.user': {'id': 19, 'name': 'Artist 1', 'type': 'HumanUser'}},
- {'id': 29,
- 'playlist.Playlist.code': 'Director Review',
- 'sg_sort_order': 2.0,
- 'type': 'PlaylistVersionConnection',
- 'version.Version.code': 'bunny_020_0020_comp_v003',
- 'version.Version.entity': {'id': 881,
- 'name': 'bunny_020_0020',
- 'type': 'Shot'},
- 'version.Version.user': {'id': 12, 'name': 'Artist 8', 'type': 'HumanUser'}},
- {'id': 30,
- 'playlist.Playlist.code': 'Director Review',
- 'sg_sort_order': 3.0,
- 'type': 'PlaylistVersionConnection',
- 'version.Version.code': 'bunny_020_0030_comp_v003',
- 'version.Version.entity': {'id': 882,
- 'name': 'bunny_020_0030',
- 'type': 'Shot'},
- 'version.Version.user': {'id': 33, 'name': 'Admin 5', 'type': 'HumanUser'}},
- {'id': 31,
- 'playlist.Playlist.code': 'Director Review',
- 'sg_sort_order': 4.0,
- 'type': 'PlaylistVersionConnection',
- 'version.Version.code': 'bunny_020_0040_comp_v003',
- 'version.Version.entity': {'id': 883,
- 'name': 'bunny_020_0040',
- 'type': 'Shot'},
- 'version.Version.user': {'id': 18, 'name': 'Artist 2', 'type': 'HumanUser'}},
- {'id': 32,
- 'playlist.Playlist.code': 'Director Review',
- 'sg_sort_order': 5.0,
- 'type': 'PlaylistVersionConnection',
- 'version.Version.code': 'bunny_020_0050_comp_v003',
- 'version.Version.entity': {'id': 884,
- 'name': 'bunny_020_0050',
- 'type': 'Shot'},
- 'version.Version.user': {'id': 15, 'name': 'Artist 5', 'type': 'HumanUser'}}]
-
-
-- ``version`` is the Version record for this connection instance.
-- ``playlist`` is the Playlist record for this connection instance.
-- ``sg_sort_order`` is the sort order field on the connection instance.
-
-We can pull in field values from the linked Playlist and Version entities using dot notation like
-``version.Version.code``. The syntax is ``fieldname.EntityType.fieldname``. In this example,
-``PlaylistVersionConnection`` has a field named ``version``. That field contains a ``Version``
-entity. The field we are interested on the Version is ``code``. Put those together with our f
-riend the dot and we have ``version.Version.code``.
-
-*******************************************
-Shotgun UI fields not available via the API
-*******************************************
-
-Summary type fields like Query Fields and Pipeline Step summary fields are currently only available
-via the UI. Some other fields may not work as expected through the API because they are "display
-only" fields made available for convenience and are only available in the browser UI.
-
-HumanUser
-=========
-
-- ``name``: This is a UI-only field that is a combination of the ``firstname`` + ``' '`` +
- ``lastname``.
-
-Shot
-====
-
-**Smart Cut Fields**: These fields are available only in the browser UI. You can read more about
-smart cut fields and the API in the :ref:`Smart Cut Fields doc `::
-
- smart_cut_in
- smart_cut_out
- smart_cut_duration
- smart_cut_summary_display
- smart_duration_summary_display
- smart_head_in
- smart_head_out
- smart_head_duration
- smart_tail_in
- smart_tail_out
- smart_tail_duration
- smart_working_duration
-
-
-Pipeline Step summary fields on entities
-========================================
-
-The Pipeline Step summary fields on entities that have Tasks aren't currently available via the API
-and are calculated on the client side in the UI. These fields are like ``step_0``, or ``step_13``.
-Note that the Pipeline Step entity itself is available via the API as the entity type ``Step``.
-
-Query Fields
-============
-
-Query fields are also summary fields like Pipeline Steps, the query is run from the client side UI
-and therefore is not currently supported in the API.
-
-************
-Audit Fields
-************
-You can set the ``created_by`` and ``created_at`` fields via the API at creation time. This is
-often useful for when you're importing or migrating data from another source and want to keep the
-history in tact. However, you cannot set the ``updated_by`` and ``updated_at`` fields. These are
-automatically set whenever an entity is created or updated.
-
-.. _logging:
-
-*****************************
-Logging Messages from the API
-*****************************
-
-The API uses standard python logging but does not define a handler.
-
-To see the logging output in stdout, define a streamhandler in your script::
-
- import logging
- import shotgun_api3 as shotgun
- logging.basicConfig(level=logging.DEBUG)
-
-To write logging output from the shotgun API to a file, define a file handler in your script::
-
- import logging
- import shotgun_api3 as shotgun
- logging.basicConfig(level=logging.DEBUG, filename='/path/to/your/log')
-
-To suppress the logging output from the API in a script which uses logging, set the level of the
-Shotgun logger to a higher level::
-
- import logging
- import shotgun_api3 as shotgun
- sg_log = logging.getLogger('shotgun_api3')
- sg_log.setLevel(logging.ERROR)
-
-*************
-Optimizations
-*************
-
-Combining Related Queries
-=========================
-Reducing round-trips for data via the API can significantly improve the speed of your application.
-Much like "Bubble Fields" / "Field Hopping" in the UI, we can poll Shotgun for data on the fields
-of entities linked to our main query, both as a part of the query parameters as well as in the
-data returned.
-
-Starting with a simple and common example, many queries require knowing what project your data is
-associated with. Without using "field hopping" in an API call, you would first get the project and
-then use that data for your follow up query, like so::
-
- # Get the project
- project_name = 'Big Buck Bunny'
- sg_project = sg.find("Project", [['name', 'is', project_name]])
-
- # Use project result to get associated shots
- sg_shots = sg.find("Shot", [['project', 'is', sg_project]], ['code'])
-
-With "field hopping" you can combine these queries into::
-
- # Get all shots on 'Big Buck Bunny' project
- project_name = 'Big Buck Bunny'
- sg_shots = sg.find("Shot", [['project.Project.name', 'is', project_name]], ['code'])
-
-As you can see above, the syntax is to use "``.``" dot notation, joining field names to entity
-types in a chain. In this example we start with the field ``project`` on the Shot entity, then
-specify we're looking for the "name" field on the Project entity by specifying ``Project.name``.
-
-Now that we've demonstrated querying using dot notation, let's take a look at returning linked data
-by adding the status of each Sequence entity associated with each Shot in our previous query::
-
- # Get shot codes and sequence status all in one query
- project_name = 'Big Buck Bunny'
- sg_shots = sg.find("Shot", [['project.Project.name', 'is', project_name]],
- ['code', 'sg_sequence.Sequence.sg_status_list'])
-
-.. note::
- Due to performance concerns with deep linking, we only support using dot syntax chains for
- single-entity relationships. This means that if you try to pull data through a multi-entity
- field you will not get the desired result.
\ No newline at end of file
diff --git a/_static/ajax-loader.gif b/_static/ajax-loader.gif
deleted file mode 100644
index 61faf8cab..000000000
Binary files a/_static/ajax-loader.gif and /dev/null differ
diff --git a/_static/comment-bright.png b/_static/comment-bright.png
deleted file mode 100644
index 15e27edb1..000000000
Binary files a/_static/comment-bright.png and /dev/null differ
diff --git a/_static/comment-close.png b/_static/comment-close.png
deleted file mode 100644
index 4d91bcf57..000000000
Binary files a/_static/comment-close.png and /dev/null differ
diff --git a/_static/comment.png b/_static/comment.png
deleted file mode 100644
index dfbc0cbd5..000000000
Binary files a/_static/comment.png and /dev/null differ
diff --git a/_static/down-pressed.png b/_static/down-pressed.png
deleted file mode 100644
index 5756c8cad..000000000
Binary files a/_static/down-pressed.png and /dev/null differ
diff --git a/_static/down.png b/_static/down.png
deleted file mode 100644
index 1b3bdad2c..000000000
Binary files a/_static/down.png and /dev/null differ
diff --git a/_static/fonts/Inconsolata-Bold.ttf b/_static/fonts/Inconsolata-Bold.ttf
deleted file mode 100644
index 809c1f582..000000000
Binary files a/_static/fonts/Inconsolata-Bold.ttf and /dev/null differ
diff --git a/_static/fonts/Inconsolata-Regular.ttf b/_static/fonts/Inconsolata-Regular.ttf
deleted file mode 100644
index fc981ce7a..000000000
Binary files a/_static/fonts/Inconsolata-Regular.ttf and /dev/null differ
diff --git a/_static/fonts/Inconsolata.ttf b/_static/fonts/Inconsolata.ttf
deleted file mode 100644
index 4b8a36d24..000000000
Binary files a/_static/fonts/Inconsolata.ttf and /dev/null differ
diff --git a/_static/fonts/Lato-Bold.ttf b/_static/fonts/Lato-Bold.ttf
deleted file mode 100644
index 1d23c7066..000000000
Binary files a/_static/fonts/Lato-Bold.ttf and /dev/null differ
diff --git a/_static/fonts/Lato-Regular.ttf b/_static/fonts/Lato-Regular.ttf
deleted file mode 100644
index 0f3d0f837..000000000
Binary files a/_static/fonts/Lato-Regular.ttf and /dev/null differ
diff --git a/_static/fonts/Lato/lato-bold.eot b/_static/fonts/Lato/lato-bold.eot
deleted file mode 100644
index 3361183a4..000000000
Binary files a/_static/fonts/Lato/lato-bold.eot and /dev/null differ
diff --git a/_static/fonts/Lato/lato-bold.ttf b/_static/fonts/Lato/lato-bold.ttf
deleted file mode 100644
index 29f691d5e..000000000
Binary files a/_static/fonts/Lato/lato-bold.ttf and /dev/null differ
diff --git a/_static/fonts/Lato/lato-bold.woff b/_static/fonts/Lato/lato-bold.woff
deleted file mode 100644
index c6dff51f0..000000000
Binary files a/_static/fonts/Lato/lato-bold.woff and /dev/null differ
diff --git a/_static/fonts/Lato/lato-bold.woff2 b/_static/fonts/Lato/lato-bold.woff2
deleted file mode 100644
index bb195043c..000000000
Binary files a/_static/fonts/Lato/lato-bold.woff2 and /dev/null differ
diff --git a/_static/fonts/Lato/lato-bolditalic.eot b/_static/fonts/Lato/lato-bolditalic.eot
deleted file mode 100644
index 3d4154936..000000000
Binary files a/_static/fonts/Lato/lato-bolditalic.eot and /dev/null differ
diff --git a/_static/fonts/Lato/lato-bolditalic.ttf b/_static/fonts/Lato/lato-bolditalic.ttf
deleted file mode 100644
index f402040b3..000000000
Binary files a/_static/fonts/Lato/lato-bolditalic.ttf and /dev/null differ
diff --git a/_static/fonts/Lato/lato-bolditalic.woff b/_static/fonts/Lato/lato-bolditalic.woff
deleted file mode 100644
index 88ad05b9f..000000000
Binary files a/_static/fonts/Lato/lato-bolditalic.woff and /dev/null differ
diff --git a/_static/fonts/Lato/lato-bolditalic.woff2 b/_static/fonts/Lato/lato-bolditalic.woff2
deleted file mode 100644
index c4e3d804b..000000000
Binary files a/_static/fonts/Lato/lato-bolditalic.woff2 and /dev/null differ
diff --git a/_static/fonts/Lato/lato-italic.eot b/_static/fonts/Lato/lato-italic.eot
deleted file mode 100644
index 3f826421a..000000000
Binary files a/_static/fonts/Lato/lato-italic.eot and /dev/null differ
diff --git a/_static/fonts/Lato/lato-italic.ttf b/_static/fonts/Lato/lato-italic.ttf
deleted file mode 100644
index b4bfc9b24..000000000
Binary files a/_static/fonts/Lato/lato-italic.ttf and /dev/null differ
diff --git a/_static/fonts/Lato/lato-italic.woff b/_static/fonts/Lato/lato-italic.woff
deleted file mode 100644
index 76114bc03..000000000
Binary files a/_static/fonts/Lato/lato-italic.woff and /dev/null differ
diff --git a/_static/fonts/Lato/lato-italic.woff2 b/_static/fonts/Lato/lato-italic.woff2
deleted file mode 100644
index 3404f37e2..000000000
Binary files a/_static/fonts/Lato/lato-italic.woff2 and /dev/null differ
diff --git a/_static/fonts/Lato/lato-regular.eot b/_static/fonts/Lato/lato-regular.eot
deleted file mode 100644
index 11e3f2a5f..000000000
Binary files a/_static/fonts/Lato/lato-regular.eot and /dev/null differ
diff --git a/_static/fonts/Lato/lato-regular.ttf b/_static/fonts/Lato/lato-regular.ttf
deleted file mode 100644
index 74decd9eb..000000000
Binary files a/_static/fonts/Lato/lato-regular.ttf and /dev/null differ
diff --git a/_static/fonts/Lato/lato-regular.woff b/_static/fonts/Lato/lato-regular.woff
deleted file mode 100644
index ae1307ff5..000000000
Binary files a/_static/fonts/Lato/lato-regular.woff and /dev/null differ
diff --git a/_static/fonts/Lato/lato-regular.woff2 b/_static/fonts/Lato/lato-regular.woff2
deleted file mode 100644
index 3bf984332..000000000
Binary files a/_static/fonts/Lato/lato-regular.woff2 and /dev/null differ
diff --git a/_static/fonts/RobotoSlab-Bold.ttf b/_static/fonts/RobotoSlab-Bold.ttf
deleted file mode 100644
index df5d1df27..000000000
Binary files a/_static/fonts/RobotoSlab-Bold.ttf and /dev/null differ
diff --git a/_static/fonts/RobotoSlab-Regular.ttf b/_static/fonts/RobotoSlab-Regular.ttf
deleted file mode 100644
index eb52a7907..000000000
Binary files a/_static/fonts/RobotoSlab-Regular.ttf and /dev/null differ
diff --git a/_static/fonts/RobotoSlab/roboto-slab-v7-bold.eot b/_static/fonts/RobotoSlab/roboto-slab-v7-bold.eot
deleted file mode 100644
index 79dc8efed..000000000
Binary files a/_static/fonts/RobotoSlab/roboto-slab-v7-bold.eot and /dev/null differ
diff --git a/_static/fonts/RobotoSlab/roboto-slab-v7-bold.ttf b/_static/fonts/RobotoSlab/roboto-slab-v7-bold.ttf
deleted file mode 100644
index df5d1df27..000000000
Binary files a/_static/fonts/RobotoSlab/roboto-slab-v7-bold.ttf and /dev/null differ
diff --git a/_static/fonts/RobotoSlab/roboto-slab-v7-bold.woff b/_static/fonts/RobotoSlab/roboto-slab-v7-bold.woff
deleted file mode 100644
index 6cb600001..000000000
Binary files a/_static/fonts/RobotoSlab/roboto-slab-v7-bold.woff and /dev/null differ
diff --git a/_static/fonts/RobotoSlab/roboto-slab-v7-bold.woff2 b/_static/fonts/RobotoSlab/roboto-slab-v7-bold.woff2
deleted file mode 100644
index 7059e2314..000000000
Binary files a/_static/fonts/RobotoSlab/roboto-slab-v7-bold.woff2 and /dev/null differ
diff --git a/_static/fonts/RobotoSlab/roboto-slab-v7-regular.eot b/_static/fonts/RobotoSlab/roboto-slab-v7-regular.eot
deleted file mode 100644
index 2f7ca78a1..000000000
Binary files a/_static/fonts/RobotoSlab/roboto-slab-v7-regular.eot and /dev/null differ
diff --git a/_static/fonts/RobotoSlab/roboto-slab-v7-regular.ttf b/_static/fonts/RobotoSlab/roboto-slab-v7-regular.ttf
deleted file mode 100644
index eb52a7907..000000000
Binary files a/_static/fonts/RobotoSlab/roboto-slab-v7-regular.ttf and /dev/null differ
diff --git a/_static/fonts/RobotoSlab/roboto-slab-v7-regular.woff b/_static/fonts/RobotoSlab/roboto-slab-v7-regular.woff
deleted file mode 100644
index f815f63f9..000000000
Binary files a/_static/fonts/RobotoSlab/roboto-slab-v7-regular.woff and /dev/null differ
diff --git a/_static/fonts/RobotoSlab/roboto-slab-v7-regular.woff2 b/_static/fonts/RobotoSlab/roboto-slab-v7-regular.woff2
deleted file mode 100644
index f2c76e5bd..000000000
Binary files a/_static/fonts/RobotoSlab/roboto-slab-v7-regular.woff2 and /dev/null differ
diff --git a/_static/fonts/fontawesome-webfont.eot b/_static/fonts/fontawesome-webfont.eot
deleted file mode 100644
index e9f60ca95..000000000
Binary files a/_static/fonts/fontawesome-webfont.eot and /dev/null differ
diff --git a/_static/fonts/fontawesome-webfont.svg b/_static/fonts/fontawesome-webfont.svg
deleted file mode 100644
index 855c845e5..000000000
--- a/_static/fonts/fontawesome-webfont.svg
+++ /dev/null
@@ -1,2671 +0,0 @@
-
-
-
diff --git a/_static/fonts/fontawesome-webfont.ttf b/_static/fonts/fontawesome-webfont.ttf
deleted file mode 100644
index 35acda2fa..000000000
Binary files a/_static/fonts/fontawesome-webfont.ttf and /dev/null differ
diff --git a/_static/fonts/fontawesome-webfont.woff b/_static/fonts/fontawesome-webfont.woff
deleted file mode 100644
index 400014a4b..000000000
Binary files a/_static/fonts/fontawesome-webfont.woff and /dev/null differ
diff --git a/_static/fonts/fontawesome-webfont.woff2 b/_static/fonts/fontawesome-webfont.woff2
deleted file mode 100644
index 4d13fc604..000000000
Binary files a/_static/fonts/fontawesome-webfont.woff2 and /dev/null differ
diff --git a/_static/jquery-1.11.1.js b/_static/jquery-1.11.1.js
deleted file mode 100644
index d4b67f7e6..000000000
--- a/_static/jquery-1.11.1.js
+++ /dev/null
@@ -1,10308 +0,0 @@
-/*!
- * jQuery JavaScript Library v1.11.1
- * http://jquery.com/
- *
- * Includes Sizzle.js
- * http://sizzlejs.com/
- *
- * Copyright 2005, 2014 jQuery Foundation, Inc. and other contributors
- * Released under the MIT license
- * http://jquery.org/license
- *
- * Date: 2014-05-01T17:42Z
- */
-
-(function( global, factory ) {
-
- if ( typeof module === "object" && typeof module.exports === "object" ) {
- // For CommonJS and CommonJS-like environments where a proper window is present,
- // execute the factory and get jQuery
- // For environments that do not inherently posses a window with a document
- // (such as Node.js), expose a jQuery-making factory as module.exports
- // This accentuates the need for the creation of a real window
- // e.g. var jQuery = require("jquery")(window);
- // See ticket #14549 for more info
- module.exports = global.document ?
- factory( global, true ) :
- function( w ) {
- if ( !w.document ) {
- throw new Error( "jQuery requires a window with a document" );
- }
- return factory( w );
- };
- } else {
- factory( global );
- }
-
-// Pass this if window is not defined yet
-}(typeof window !== "undefined" ? window : this, function( window, noGlobal ) {
-
-// Can't do this because several apps including ASP.NET trace
-// the stack via arguments.caller.callee and Firefox dies if
-// you try to trace through "use strict" call chains. (#13335)
-// Support: Firefox 18+
-//
-
-var deletedIds = [];
-
-var slice = deletedIds.slice;
-
-var concat = deletedIds.concat;
-
-var push = deletedIds.push;
-
-var indexOf = deletedIds.indexOf;
-
-var class2type = {};
-
-var toString = class2type.toString;
-
-var hasOwn = class2type.hasOwnProperty;
-
-var support = {};
-
-
-
-var
- version = "1.11.1",
-
- // Define a local copy of jQuery
- jQuery = function( selector, context ) {
- // The jQuery object is actually just the init constructor 'enhanced'
- // Need init if jQuery is called (just allow error to be thrown if not included)
- return new jQuery.fn.init( selector, context );
- },
-
- // Support: Android<4.1, IE<9
- // Make sure we trim BOM and NBSP
- rtrim = /^[\s\uFEFF\xA0]+|[\s\uFEFF\xA0]+$/g,
-
- // Matches dashed string for camelizing
- rmsPrefix = /^-ms-/,
- rdashAlpha = /-([\da-z])/gi,
-
- // Used by jQuery.camelCase as callback to replace()
- fcamelCase = function( all, letter ) {
- return letter.toUpperCase();
- };
-
-jQuery.fn = jQuery.prototype = {
- // The current version of jQuery being used
- jquery: version,
-
- constructor: jQuery,
-
- // Start with an empty selector
- selector: "",
-
- // The default length of a jQuery object is 0
- length: 0,
-
- toArray: function() {
- return slice.call( this );
- },
-
- // Get the Nth element in the matched element set OR
- // Get the whole matched element set as a clean array
- get: function( num ) {
- return num != null ?
-
- // Return just the one element from the set
- ( num < 0 ? this[ num + this.length ] : this[ num ] ) :
-
- // Return all the elements in a clean array
- slice.call( this );
- },
-
- // Take an array of elements and push it onto the stack
- // (returning the new matched element set)
- pushStack: function( elems ) {
-
- // Build a new jQuery matched element set
- var ret = jQuery.merge( this.constructor(), elems );
-
- // Add the old object onto the stack (as a reference)
- ret.prevObject = this;
- ret.context = this.context;
-
- // Return the newly-formed element set
- return ret;
- },
-
- // Execute a callback for every element in the matched set.
- // (You can seed the arguments with an array of args, but this is
- // only used internally.)
- each: function( callback, args ) {
- return jQuery.each( this, callback, args );
- },
-
- map: function( callback ) {
- return this.pushStack( jQuery.map(this, function( elem, i ) {
- return callback.call( elem, i, elem );
- }));
- },
-
- slice: function() {
- return this.pushStack( slice.apply( this, arguments ) );
- },
-
- first: function() {
- return this.eq( 0 );
- },
-
- last: function() {
- return this.eq( -1 );
- },
-
- eq: function( i ) {
- var len = this.length,
- j = +i + ( i < 0 ? len : 0 );
- return this.pushStack( j >= 0 && j < len ? [ this[j] ] : [] );
- },
-
- end: function() {
- return this.prevObject || this.constructor(null);
- },
-
- // For internal use only.
- // Behaves like an Array's method, not like a jQuery method.
- push: push,
- sort: deletedIds.sort,
- splice: deletedIds.splice
-};
-
-jQuery.extend = jQuery.fn.extend = function() {
- var src, copyIsArray, copy, name, options, clone,
- target = arguments[0] || {},
- i = 1,
- length = arguments.length,
- deep = false;
-
- // Handle a deep copy situation
- if ( typeof target === "boolean" ) {
- deep = target;
-
- // skip the boolean and the target
- target = arguments[ i ] || {};
- i++;
- }
-
- // Handle case when target is a string or something (possible in deep copy)
- if ( typeof target !== "object" && !jQuery.isFunction(target) ) {
- target = {};
- }
-
- // extend jQuery itself if only one argument is passed
- if ( i === length ) {
- target = this;
- i--;
- }
-
- for ( ; i < length; i++ ) {
- // Only deal with non-null/undefined values
- if ( (options = arguments[ i ]) != null ) {
- // Extend the base object
- for ( name in options ) {
- src = target[ name ];
- copy = options[ name ];
-
- // Prevent never-ending loop
- if ( target === copy ) {
- continue;
- }
-
- // Recurse if we're merging plain objects or arrays
- if ( deep && copy && ( jQuery.isPlainObject(copy) || (copyIsArray = jQuery.isArray(copy)) ) ) {
- if ( copyIsArray ) {
- copyIsArray = false;
- clone = src && jQuery.isArray(src) ? src : [];
-
- } else {
- clone = src && jQuery.isPlainObject(src) ? src : {};
- }
-
- // Never move original objects, clone them
- target[ name ] = jQuery.extend( deep, clone, copy );
-
- // Don't bring in undefined values
- } else if ( copy !== undefined ) {
- target[ name ] = copy;
- }
- }
- }
- }
-
- // Return the modified object
- return target;
-};
-
-jQuery.extend({
- // Unique for each copy of jQuery on the page
- expando: "jQuery" + ( version + Math.random() ).replace( /\D/g, "" ),
-
- // Assume jQuery is ready without the ready module
- isReady: true,
-
- error: function( msg ) {
- throw new Error( msg );
- },
-
- noop: function() {},
-
- // See test/unit/core.js for details concerning isFunction.
- // Since version 1.3, DOM methods and functions like alert
- // aren't supported. They return false on IE (#2968).
- isFunction: function( obj ) {
- return jQuery.type(obj) === "function";
- },
-
- isArray: Array.isArray || function( obj ) {
- return jQuery.type(obj) === "array";
- },
-
- isWindow: function( obj ) {
- /* jshint eqeqeq: false */
- return obj != null && obj == obj.window;
- },
-
- isNumeric: function( obj ) {
- // parseFloat NaNs numeric-cast false positives (null|true|false|"")
- // ...but misinterprets leading-number strings, particularly hex literals ("0x...")
- // subtraction forces infinities to NaN
- return !jQuery.isArray( obj ) && obj - parseFloat( obj ) >= 0;
- },
-
- isEmptyObject: function( obj ) {
- var name;
- for ( name in obj ) {
- return false;
- }
- return true;
- },
-
- isPlainObject: function( obj ) {
- var key;
-
- // Must be an Object.
- // Because of IE, we also have to check the presence of the constructor property.
- // Make sure that DOM nodes and window objects don't pass through, as well
- if ( !obj || jQuery.type(obj) !== "object" || obj.nodeType || jQuery.isWindow( obj ) ) {
- return false;
- }
-
- try {
- // Not own constructor property must be Object
- if ( obj.constructor &&
- !hasOwn.call(obj, "constructor") &&
- !hasOwn.call(obj.constructor.prototype, "isPrototypeOf") ) {
- return false;
- }
- } catch ( e ) {
- // IE8,9 Will throw exceptions on certain host objects #9897
- return false;
- }
-
- // Support: IE<9
- // Handle iteration over inherited properties before own properties.
- if ( support.ownLast ) {
- for ( key in obj ) {
- return hasOwn.call( obj, key );
- }
- }
-
- // Own properties are enumerated firstly, so to speed up,
- // if last one is own, then all properties are own.
- for ( key in obj ) {}
-
- return key === undefined || hasOwn.call( obj, key );
- },
-
- type: function( obj ) {
- if ( obj == null ) {
- return obj + "";
- }
- return typeof obj === "object" || typeof obj === "function" ?
- class2type[ toString.call(obj) ] || "object" :
- typeof obj;
- },
-
- // Evaluates a script in a global context
- // Workarounds based on findings by Jim Driscoll
- // http://weblogs.java.net/blog/driscoll/archive/2009/09/08/eval-javascript-global-context
- globalEval: function( data ) {
- if ( data && jQuery.trim( data ) ) {
- // We use execScript on Internet Explorer
- // We use an anonymous function so that context is window
- // rather than jQuery in Firefox
- ( window.execScript || function( data ) {
- window[ "eval" ].call( window, data );
- } )( data );
- }
- },
-
- // Convert dashed to camelCase; used by the css and data modules
- // Microsoft forgot to hump their vendor prefix (#9572)
- camelCase: function( string ) {
- return string.replace( rmsPrefix, "ms-" ).replace( rdashAlpha, fcamelCase );
- },
-
- nodeName: function( elem, name ) {
- return elem.nodeName && elem.nodeName.toLowerCase() === name.toLowerCase();
- },
-
- // args is for internal usage only
- each: function( obj, callback, args ) {
- var value,
- i = 0,
- length = obj.length,
- isArray = isArraylike( obj );
-
- if ( args ) {
- if ( isArray ) {
- for ( ; i < length; i++ ) {
- value = callback.apply( obj[ i ], args );
-
- if ( value === false ) {
- break;
- }
- }
- } else {
- for ( i in obj ) {
- value = callback.apply( obj[ i ], args );
-
- if ( value === false ) {
- break;
- }
- }
- }
-
- // A special, fast, case for the most common use of each
- } else {
- if ( isArray ) {
- for ( ; i < length; i++ ) {
- value = callback.call( obj[ i ], i, obj[ i ] );
-
- if ( value === false ) {
- break;
- }
- }
- } else {
- for ( i in obj ) {
- value = callback.call( obj[ i ], i, obj[ i ] );
-
- if ( value === false ) {
- break;
- }
- }
- }
- }
-
- return obj;
- },
-
- // Support: Android<4.1, IE<9
- trim: function( text ) {
- return text == null ?
- "" :
- ( text + "" ).replace( rtrim, "" );
- },
-
- // results is for internal usage only
- makeArray: function( arr, results ) {
- var ret = results || [];
-
- if ( arr != null ) {
- if ( isArraylike( Object(arr) ) ) {
- jQuery.merge( ret,
- typeof arr === "string" ?
- [ arr ] : arr
- );
- } else {
- push.call( ret, arr );
- }
- }
-
- return ret;
- },
-
- inArray: function( elem, arr, i ) {
- var len;
-
- if ( arr ) {
- if ( indexOf ) {
- return indexOf.call( arr, elem, i );
- }
-
- len = arr.length;
- i = i ? i < 0 ? Math.max( 0, len + i ) : i : 0;
-
- for ( ; i < len; i++ ) {
- // Skip accessing in sparse arrays
- if ( i in arr && arr[ i ] === elem ) {
- return i;
- }
- }
- }
-
- return -1;
- },
-
- merge: function( first, second ) {
- var len = +second.length,
- j = 0,
- i = first.length;
-
- while ( j < len ) {
- first[ i++ ] = second[ j++ ];
- }
-
- // Support: IE<9
- // Workaround casting of .length to NaN on otherwise arraylike objects (e.g., NodeLists)
- if ( len !== len ) {
- while ( second[j] !== undefined ) {
- first[ i++ ] = second[ j++ ];
- }
- }
-
- first.length = i;
-
- return first;
- },
-
- grep: function( elems, callback, invert ) {
- var callbackInverse,
- matches = [],
- i = 0,
- length = elems.length,
- callbackExpect = !invert;
-
- // Go through the array, only saving the items
- // that pass the validator function
- for ( ; i < length; i++ ) {
- callbackInverse = !callback( elems[ i ], i );
- if ( callbackInverse !== callbackExpect ) {
- matches.push( elems[ i ] );
- }
- }
-
- return matches;
- },
-
- // arg is for internal usage only
- map: function( elems, callback, arg ) {
- var value,
- i = 0,
- length = elems.length,
- isArray = isArraylike( elems ),
- ret = [];
-
- // Go through the array, translating each of the items to their new values
- if ( isArray ) {
- for ( ; i < length; i++ ) {
- value = callback( elems[ i ], i, arg );
-
- if ( value != null ) {
- ret.push( value );
- }
- }
-
- // Go through every key on the object,
- } else {
- for ( i in elems ) {
- value = callback( elems[ i ], i, arg );
-
- if ( value != null ) {
- ret.push( value );
- }
- }
- }
-
- // Flatten any nested arrays
- return concat.apply( [], ret );
- },
-
- // A global GUID counter for objects
- guid: 1,
-
- // Bind a function to a context, optionally partially applying any
- // arguments.
- proxy: function( fn, context ) {
- var args, proxy, tmp;
-
- if ( typeof context === "string" ) {
- tmp = fn[ context ];
- context = fn;
- fn = tmp;
- }
-
- // Quick check to determine if target is callable, in the spec
- // this throws a TypeError, but we will just return undefined.
- if ( !jQuery.isFunction( fn ) ) {
- return undefined;
- }
-
- // Simulated bind
- args = slice.call( arguments, 2 );
- proxy = function() {
- return fn.apply( context || this, args.concat( slice.call( arguments ) ) );
- };
-
- // Set the guid of unique handler to the same of original handler, so it can be removed
- proxy.guid = fn.guid = fn.guid || jQuery.guid++;
-
- return proxy;
- },
-
- now: function() {
- return +( new Date() );
- },
-
- // jQuery.support is not used in Core but other projects attach their
- // properties to it so it needs to exist.
- support: support
-});
-
-// Populate the class2type map
-jQuery.each("Boolean Number String Function Array Date RegExp Object Error".split(" "), function(i, name) {
- class2type[ "[object " + name + "]" ] = name.toLowerCase();
-});
-
-function isArraylike( obj ) {
- var length = obj.length,
- type = jQuery.type( obj );
-
- if ( type === "function" || jQuery.isWindow( obj ) ) {
- return false;
- }
-
- if ( obj.nodeType === 1 && length ) {
- return true;
- }
-
- return type === "array" || length === 0 ||
- typeof length === "number" && length > 0 && ( length - 1 ) in obj;
-}
-var Sizzle =
-/*!
- * Sizzle CSS Selector Engine v1.10.19
- * http://sizzlejs.com/
- *
- * Copyright 2013 jQuery Foundation, Inc. and other contributors
- * Released under the MIT license
- * http://jquery.org/license
- *
- * Date: 2014-04-18
- */
-(function( window ) {
-
-var i,
- support,
- Expr,
- getText,
- isXML,
- tokenize,
- compile,
- select,
- outermostContext,
- sortInput,
- hasDuplicate,
-
- // Local document vars
- setDocument,
- document,
- docElem,
- documentIsHTML,
- rbuggyQSA,
- rbuggyMatches,
- matches,
- contains,
-
- // Instance-specific data
- expando = "sizzle" + -(new Date()),
- preferredDoc = window.document,
- dirruns = 0,
- done = 0,
- classCache = createCache(),
- tokenCache = createCache(),
- compilerCache = createCache(),
- sortOrder = function( a, b ) {
- if ( a === b ) {
- hasDuplicate = true;
- }
- return 0;
- },
-
- // General-purpose constants
- strundefined = typeof undefined,
- MAX_NEGATIVE = 1 << 31,
-
- // Instance methods
- hasOwn = ({}).hasOwnProperty,
- arr = [],
- pop = arr.pop,
- push_native = arr.push,
- push = arr.push,
- slice = arr.slice,
- // Use a stripped-down indexOf if we can't use a native one
- indexOf = arr.indexOf || function( elem ) {
- var i = 0,
- len = this.length;
- for ( ; i < len; i++ ) {
- if ( this[i] === elem ) {
- return i;
- }
- }
- return -1;
- },
-
- booleans = "checked|selected|async|autofocus|autoplay|controls|defer|disabled|hidden|ismap|loop|multiple|open|readonly|required|scoped",
-
- // Regular expressions
-
- // Whitespace characters http://www.w3.org/TR/css3-selectors/#whitespace
- whitespace = "[\\x20\\t\\r\\n\\f]",
- // http://www.w3.org/TR/css3-syntax/#characters
- characterEncoding = "(?:\\\\.|[\\w-]|[^\\x00-\\xa0])+",
-
- // Loosely modeled on CSS identifier characters
- // An unquoted value should be a CSS identifier http://www.w3.org/TR/css3-selectors/#attribute-selectors
- // Proper syntax: http://www.w3.org/TR/CSS21/syndata.html#value-def-identifier
- identifier = characterEncoding.replace( "w", "w#" ),
-
- // Attribute selectors: http://www.w3.org/TR/selectors/#attribute-selectors
- attributes = "\\[" + whitespace + "*(" + characterEncoding + ")(?:" + whitespace +
- // Operator (capture 2)
- "*([*^$|!~]?=)" + whitespace +
- // "Attribute values must be CSS identifiers [capture 5] or strings [capture 3 or capture 4]"
- "*(?:'((?:\\\\.|[^\\\\'])*)'|\"((?:\\\\.|[^\\\\\"])*)\"|(" + identifier + "))|)" + whitespace +
- "*\\]",
-
- pseudos = ":(" + characterEncoding + ")(?:\\((" +
- // To reduce the number of selectors needing tokenize in the preFilter, prefer arguments:
- // 1. quoted (capture 3; capture 4 or capture 5)
- "('((?:\\\\.|[^\\\\'])*)'|\"((?:\\\\.|[^\\\\\"])*)\")|" +
- // 2. simple (capture 6)
- "((?:\\\\.|[^\\\\()[\\]]|" + attributes + ")*)|" +
- // 3. anything else (capture 2)
- ".*" +
- ")\\)|)",
-
- // Leading and non-escaped trailing whitespace, capturing some non-whitespace characters preceding the latter
- rtrim = new RegExp( "^" + whitespace + "+|((?:^|[^\\\\])(?:\\\\.)*)" + whitespace + "+$", "g" ),
-
- rcomma = new RegExp( "^" + whitespace + "*," + whitespace + "*" ),
- rcombinators = new RegExp( "^" + whitespace + "*([>+~]|" + whitespace + ")" + whitespace + "*" ),
-
- rattributeQuotes = new RegExp( "=" + whitespace + "*([^\\]'\"]*?)" + whitespace + "*\\]", "g" ),
-
- rpseudo = new RegExp( pseudos ),
- ridentifier = new RegExp( "^" + identifier + "$" ),
-
- matchExpr = {
- "ID": new RegExp( "^#(" + characterEncoding + ")" ),
- "CLASS": new RegExp( "^\\.(" + characterEncoding + ")" ),
- "TAG": new RegExp( "^(" + characterEncoding.replace( "w", "w*" ) + ")" ),
- "ATTR": new RegExp( "^" + attributes ),
- "PSEUDO": new RegExp( "^" + pseudos ),
- "CHILD": new RegExp( "^:(only|first|last|nth|nth-last)-(child|of-type)(?:\\(" + whitespace +
- "*(even|odd|(([+-]|)(\\d*)n|)" + whitespace + "*(?:([+-]|)" + whitespace +
- "*(\\d+)|))" + whitespace + "*\\)|)", "i" ),
- "bool": new RegExp( "^(?:" + booleans + ")$", "i" ),
- // For use in libraries implementing .is()
- // We use this for POS matching in `select`
- "needsContext": new RegExp( "^" + whitespace + "*[>+~]|:(even|odd|eq|gt|lt|nth|first|last)(?:\\(" +
- whitespace + "*((?:-\\d)?\\d*)" + whitespace + "*\\)|)(?=[^-]|$)", "i" )
- },
-
- rinputs = /^(?:input|select|textarea|button)$/i,
- rheader = /^h\d$/i,
-
- rnative = /^[^{]+\{\s*\[native \w/,
-
- // Easily-parseable/retrievable ID or TAG or CLASS selectors
- rquickExpr = /^(?:#([\w-]+)|(\w+)|\.([\w-]+))$/,
-
- rsibling = /[+~]/,
- rescape = /'|\\/g,
-
- // CSS escapes http://www.w3.org/TR/CSS21/syndata.html#escaped-characters
- runescape = new RegExp( "\\\\([\\da-f]{1,6}" + whitespace + "?|(" + whitespace + ")|.)", "ig" ),
- funescape = function( _, escaped, escapedWhitespace ) {
- var high = "0x" + escaped - 0x10000;
- // NaN means non-codepoint
- // Support: Firefox<24
- // Workaround erroneous numeric interpretation of +"0x"
- return high !== high || escapedWhitespace ?
- escaped :
- high < 0 ?
- // BMP codepoint
- String.fromCharCode( high + 0x10000 ) :
- // Supplemental Plane codepoint (surrogate pair)
- String.fromCharCode( high >> 10 | 0xD800, high & 0x3FF | 0xDC00 );
- };
-
-// Optimize for push.apply( _, NodeList )
-try {
- push.apply(
- (arr = slice.call( preferredDoc.childNodes )),
- preferredDoc.childNodes
- );
- // Support: Android<4.0
- // Detect silently failing push.apply
- arr[ preferredDoc.childNodes.length ].nodeType;
-} catch ( e ) {
- push = { apply: arr.length ?
-
- // Leverage slice if possible
- function( target, els ) {
- push_native.apply( target, slice.call(els) );
- } :
-
- // Support: IE<9
- // Otherwise append directly
- function( target, els ) {
- var j = target.length,
- i = 0;
- // Can't trust NodeList.length
- while ( (target[j++] = els[i++]) ) {}
- target.length = j - 1;
- }
- };
-}
-
-function Sizzle( selector, context, results, seed ) {
- var match, elem, m, nodeType,
- // QSA vars
- i, groups, old, nid, newContext, newSelector;
-
- if ( ( context ? context.ownerDocument || context : preferredDoc ) !== document ) {
- setDocument( context );
- }
-
- context = context || document;
- results = results || [];
-
- if ( !selector || typeof selector !== "string" ) {
- return results;
- }
-
- if ( (nodeType = context.nodeType) !== 1 && nodeType !== 9 ) {
- return [];
- }
-
- if ( documentIsHTML && !seed ) {
-
- // Shortcuts
- if ( (match = rquickExpr.exec( selector )) ) {
- // Speed-up: Sizzle("#ID")
- if ( (m = match[1]) ) {
- if ( nodeType === 9 ) {
- elem = context.getElementById( m );
- // Check parentNode to catch when Blackberry 4.6 returns
- // nodes that are no longer in the document (jQuery #6963)
- if ( elem && elem.parentNode ) {
- // Handle the case where IE, Opera, and Webkit return items
- // by name instead of ID
- if ( elem.id === m ) {
- results.push( elem );
- return results;
- }
- } else {
- return results;
- }
- } else {
- // Context is not a document
- if ( context.ownerDocument && (elem = context.ownerDocument.getElementById( m )) &&
- contains( context, elem ) && elem.id === m ) {
- results.push( elem );
- return results;
- }
- }
-
- // Speed-up: Sizzle("TAG")
- } else if ( match[2] ) {
- push.apply( results, context.getElementsByTagName( selector ) );
- return results;
-
- // Speed-up: Sizzle(".CLASS")
- } else if ( (m = match[3]) && support.getElementsByClassName && context.getElementsByClassName ) {
- push.apply( results, context.getElementsByClassName( m ) );
- return results;
- }
- }
-
- // QSA path
- if ( support.qsa && (!rbuggyQSA || !rbuggyQSA.test( selector )) ) {
- nid = old = expando;
- newContext = context;
- newSelector = nodeType === 9 && selector;
-
- // qSA works strangely on Element-rooted queries
- // We can work around this by specifying an extra ID on the root
- // and working up from there (Thanks to Andrew Dupont for the technique)
- // IE 8 doesn't work on object elements
- if ( nodeType === 1 && context.nodeName.toLowerCase() !== "object" ) {
- groups = tokenize( selector );
-
- if ( (old = context.getAttribute("id")) ) {
- nid = old.replace( rescape, "\\$&" );
- } else {
- context.setAttribute( "id", nid );
- }
- nid = "[id='" + nid + "'] ";
-
- i = groups.length;
- while ( i-- ) {
- groups[i] = nid + toSelector( groups[i] );
- }
- newContext = rsibling.test( selector ) && testContext( context.parentNode ) || context;
- newSelector = groups.join(",");
- }
-
- if ( newSelector ) {
- try {
- push.apply( results,
- newContext.querySelectorAll( newSelector )
- );
- return results;
- } catch(qsaError) {
- } finally {
- if ( !old ) {
- context.removeAttribute("id");
- }
- }
- }
- }
- }
-
- // All others
- return select( selector.replace( rtrim, "$1" ), context, results, seed );
-}
-
-/**
- * Create key-value caches of limited size
- * @returns {Function(string, Object)} Returns the Object data after storing it on itself with
- * property name the (space-suffixed) string and (if the cache is larger than Expr.cacheLength)
- * deleting the oldest entry
- */
-function createCache() {
- var keys = [];
-
- function cache( key, value ) {
- // Use (key + " ") to avoid collision with native prototype properties (see Issue #157)
- if ( keys.push( key + " " ) > Expr.cacheLength ) {
- // Only keep the most recent entries
- delete cache[ keys.shift() ];
- }
- return (cache[ key + " " ] = value);
- }
- return cache;
-}
-
-/**
- * Mark a function for special use by Sizzle
- * @param {Function} fn The function to mark
- */
-function markFunction( fn ) {
- fn[ expando ] = true;
- return fn;
-}
-
-/**
- * Support testing using an element
- * @param {Function} fn Passed the created div and expects a boolean result
- */
-function assert( fn ) {
- var div = document.createElement("div");
-
- try {
- return !!fn( div );
- } catch (e) {
- return false;
- } finally {
- // Remove from its parent by default
- if ( div.parentNode ) {
- div.parentNode.removeChild( div );
- }
- // release memory in IE
- div = null;
- }
-}
-
-/**
- * Adds the same handler for all of the specified attrs
- * @param {String} attrs Pipe-separated list of attributes
- * @param {Function} handler The method that will be applied
- */
-function addHandle( attrs, handler ) {
- var arr = attrs.split("|"),
- i = attrs.length;
-
- while ( i-- ) {
- Expr.attrHandle[ arr[i] ] = handler;
- }
-}
-
-/**
- * Checks document order of two siblings
- * @param {Element} a
- * @param {Element} b
- * @returns {Number} Returns less than 0 if a precedes b, greater than 0 if a follows b
- */
-function siblingCheck( a, b ) {
- var cur = b && a,
- diff = cur && a.nodeType === 1 && b.nodeType === 1 &&
- ( ~b.sourceIndex || MAX_NEGATIVE ) -
- ( ~a.sourceIndex || MAX_NEGATIVE );
-
- // Use IE sourceIndex if available on both nodes
- if ( diff ) {
- return diff;
- }
-
- // Check if b follows a
- if ( cur ) {
- while ( (cur = cur.nextSibling) ) {
- if ( cur === b ) {
- return -1;
- }
- }
- }
-
- return a ? 1 : -1;
-}
-
-/**
- * Returns a function to use in pseudos for input types
- * @param {String} type
- */
-function createInputPseudo( type ) {
- return function( elem ) {
- var name = elem.nodeName.toLowerCase();
- return name === "input" && elem.type === type;
- };
-}
-
-/**
- * Returns a function to use in pseudos for buttons
- * @param {String} type
- */
-function createButtonPseudo( type ) {
- return function( elem ) {
- var name = elem.nodeName.toLowerCase();
- return (name === "input" || name === "button") && elem.type === type;
- };
-}
-
-/**
- * Returns a function to use in pseudos for positionals
- * @param {Function} fn
- */
-function createPositionalPseudo( fn ) {
- return markFunction(function( argument ) {
- argument = +argument;
- return markFunction(function( seed, matches ) {
- var j,
- matchIndexes = fn( [], seed.length, argument ),
- i = matchIndexes.length;
-
- // Match elements found at the specified indexes
- while ( i-- ) {
- if ( seed[ (j = matchIndexes[i]) ] ) {
- seed[j] = !(matches[j] = seed[j]);
- }
- }
- });
- });
-}
-
-/**
- * Checks a node for validity as a Sizzle context
- * @param {Element|Object=} context
- * @returns {Element|Object|Boolean} The input node if acceptable, otherwise a falsy value
- */
-function testContext( context ) {
- return context && typeof context.getElementsByTagName !== strundefined && context;
-}
-
-// Expose support vars for convenience
-support = Sizzle.support = {};
-
-/**
- * Detects XML nodes
- * @param {Element|Object} elem An element or a document
- * @returns {Boolean} True iff elem is a non-HTML XML node
- */
-isXML = Sizzle.isXML = function( elem ) {
- // documentElement is verified for cases where it doesn't yet exist
- // (such as loading iframes in IE - #4833)
- var documentElement = elem && (elem.ownerDocument || elem).documentElement;
- return documentElement ? documentElement.nodeName !== "HTML" : false;
-};
-
-/**
- * Sets document-related variables once based on the current document
- * @param {Element|Object} [doc] An element or document object to use to set the document
- * @returns {Object} Returns the current document
- */
-setDocument = Sizzle.setDocument = function( node ) {
- var hasCompare,
- doc = node ? node.ownerDocument || node : preferredDoc,
- parent = doc.defaultView;
-
- // If no document and documentElement is available, return
- if ( doc === document || doc.nodeType !== 9 || !doc.documentElement ) {
- return document;
- }
-
- // Set our document
- document = doc;
- docElem = doc.documentElement;
-
- // Support tests
- documentIsHTML = !isXML( doc );
-
- // Support: IE>8
- // If iframe document is assigned to "document" variable and if iframe has been reloaded,
- // IE will throw "permission denied" error when accessing "document" variable, see jQuery #13936
- // IE6-8 do not support the defaultView property so parent will be undefined
- if ( parent && parent !== parent.top ) {
- // IE11 does not have attachEvent, so all must suffer
- if ( parent.addEventListener ) {
- parent.addEventListener( "unload", function() {
- setDocument();
- }, false );
- } else if ( parent.attachEvent ) {
- parent.attachEvent( "onunload", function() {
- setDocument();
- });
- }
- }
-
- /* Attributes
- ---------------------------------------------------------------------- */
-
- // Support: IE<8
- // Verify that getAttribute really returns attributes and not properties (excepting IE8 booleans)
- support.attributes = assert(function( div ) {
- div.className = "i";
- return !div.getAttribute("className");
- });
-
- /* getElement(s)By*
- ---------------------------------------------------------------------- */
-
- // Check if getElementsByTagName("*") returns only elements
- support.getElementsByTagName = assert(function( div ) {
- div.appendChild( doc.createComment("") );
- return !div.getElementsByTagName("*").length;
- });
-
- // Check if getElementsByClassName can be trusted
- support.getElementsByClassName = rnative.test( doc.getElementsByClassName ) && assert(function( div ) {
- div.innerHTML = "";
-
- // Support: Safari<4
- // Catch class over-caching
- div.firstChild.className = "i";
- // Support: Opera<10
- // Catch gEBCN failure to find non-leading classes
- return div.getElementsByClassName("i").length === 2;
- });
-
- // Support: IE<10
- // Check if getElementById returns elements by name
- // The broken getElementById methods don't pick up programatically-set names,
- // so use a roundabout getElementsByName test
- support.getById = assert(function( div ) {
- docElem.appendChild( div ).id = expando;
- return !doc.getElementsByName || !doc.getElementsByName( expando ).length;
- });
-
- // ID find and filter
- if ( support.getById ) {
- Expr.find["ID"] = function( id, context ) {
- if ( typeof context.getElementById !== strundefined && documentIsHTML ) {
- var m = context.getElementById( id );
- // Check parentNode to catch when Blackberry 4.6 returns
- // nodes that are no longer in the document #6963
- return m && m.parentNode ? [ m ] : [];
- }
- };
- Expr.filter["ID"] = function( id ) {
- var attrId = id.replace( runescape, funescape );
- return function( elem ) {
- return elem.getAttribute("id") === attrId;
- };
- };
- } else {
- // Support: IE6/7
- // getElementById is not reliable as a find shortcut
- delete Expr.find["ID"];
-
- Expr.filter["ID"] = function( id ) {
- var attrId = id.replace( runescape, funescape );
- return function( elem ) {
- var node = typeof elem.getAttributeNode !== strundefined && elem.getAttributeNode("id");
- return node && node.value === attrId;
- };
- };
- }
-
- // Tag
- Expr.find["TAG"] = support.getElementsByTagName ?
- function( tag, context ) {
- if ( typeof context.getElementsByTagName !== strundefined ) {
- return context.getElementsByTagName( tag );
- }
- } :
- function( tag, context ) {
- var elem,
- tmp = [],
- i = 0,
- results = context.getElementsByTagName( tag );
-
- // Filter out possible comments
- if ( tag === "*" ) {
- while ( (elem = results[i++]) ) {
- if ( elem.nodeType === 1 ) {
- tmp.push( elem );
- }
- }
-
- return tmp;
- }
- return results;
- };
-
- // Class
- Expr.find["CLASS"] = support.getElementsByClassName && function( className, context ) {
- if ( typeof context.getElementsByClassName !== strundefined && documentIsHTML ) {
- return context.getElementsByClassName( className );
- }
- };
-
- /* QSA/matchesSelector
- ---------------------------------------------------------------------- */
-
- // QSA and matchesSelector support
-
- // matchesSelector(:active) reports false when true (IE9/Opera 11.5)
- rbuggyMatches = [];
-
- // qSa(:focus) reports false when true (Chrome 21)
- // We allow this because of a bug in IE8/9 that throws an error
- // whenever `document.activeElement` is accessed on an iframe
- // So, we allow :focus to pass through QSA all the time to avoid the IE error
- // See http://bugs.jquery.com/ticket/13378
- rbuggyQSA = [];
-
- if ( (support.qsa = rnative.test( doc.querySelectorAll )) ) {
- // Build QSA regex
- // Regex strategy adopted from Diego Perini
- assert(function( div ) {
- // Select is set to empty string on purpose
- // This is to test IE's treatment of not explicitly
- // setting a boolean content attribute,
- // since its presence should be enough
- // http://bugs.jquery.com/ticket/12359
- div.innerHTML = "";
-
- // Support: IE8, Opera 11-12.16
- // Nothing should be selected when empty strings follow ^= or $= or *=
- // The test attribute must be unknown in Opera but "safe" for WinRT
- // http://msdn.microsoft.com/en-us/library/ie/hh465388.aspx#attribute_section
- if ( div.querySelectorAll("[msallowclip^='']").length ) {
- rbuggyQSA.push( "[*^$]=" + whitespace + "*(?:''|\"\")" );
- }
-
- // Support: IE8
- // Boolean attributes and "value" are not treated correctly
- if ( !div.querySelectorAll("[selected]").length ) {
- rbuggyQSA.push( "\\[" + whitespace + "*(?:value|" + booleans + ")" );
- }
-
- // Webkit/Opera - :checked should return selected option elements
- // http://www.w3.org/TR/2011/REC-css3-selectors-20110929/#checked
- // IE8 throws error here and will not see later tests
- if ( !div.querySelectorAll(":checked").length ) {
- rbuggyQSA.push(":checked");
- }
- });
-
- assert(function( div ) {
- // Support: Windows 8 Native Apps
- // The type and name attributes are restricted during .innerHTML assignment
- var input = doc.createElement("input");
- input.setAttribute( "type", "hidden" );
- div.appendChild( input ).setAttribute( "name", "D" );
-
- // Support: IE8
- // Enforce case-sensitivity of name attribute
- if ( div.querySelectorAll("[name=d]").length ) {
- rbuggyQSA.push( "name" + whitespace + "*[*^$|!~]?=" );
- }
-
- // FF 3.5 - :enabled/:disabled and hidden elements (hidden elements are still enabled)
- // IE8 throws error here and will not see later tests
- if ( !div.querySelectorAll(":enabled").length ) {
- rbuggyQSA.push( ":enabled", ":disabled" );
- }
-
- // Opera 10-11 does not throw on post-comma invalid pseudos
- div.querySelectorAll("*,:x");
- rbuggyQSA.push(",.*:");
- });
- }
-
- if ( (support.matchesSelector = rnative.test( (matches = docElem.matches ||
- docElem.webkitMatchesSelector ||
- docElem.mozMatchesSelector ||
- docElem.oMatchesSelector ||
- docElem.msMatchesSelector) )) ) {
-
- assert(function( div ) {
- // Check to see if it's possible to do matchesSelector
- // on a disconnected node (IE 9)
- support.disconnectedMatch = matches.call( div, "div" );
-
- // This should fail with an exception
- // Gecko does not error, returns false instead
- matches.call( div, "[s!='']:x" );
- rbuggyMatches.push( "!=", pseudos );
- });
- }
-
- rbuggyQSA = rbuggyQSA.length && new RegExp( rbuggyQSA.join("|") );
- rbuggyMatches = rbuggyMatches.length && new RegExp( rbuggyMatches.join("|") );
-
- /* Contains
- ---------------------------------------------------------------------- */
- hasCompare = rnative.test( docElem.compareDocumentPosition );
-
- // Element contains another
- // Purposefully does not implement inclusive descendent
- // As in, an element does not contain itself
- contains = hasCompare || rnative.test( docElem.contains ) ?
- function( a, b ) {
- var adown = a.nodeType === 9 ? a.documentElement : a,
- bup = b && b.parentNode;
- return a === bup || !!( bup && bup.nodeType === 1 && (
- adown.contains ?
- adown.contains( bup ) :
- a.compareDocumentPosition && a.compareDocumentPosition( bup ) & 16
- ));
- } :
- function( a, b ) {
- if ( b ) {
- while ( (b = b.parentNode) ) {
- if ( b === a ) {
- return true;
- }
- }
- }
- return false;
- };
-
- /* Sorting
- ---------------------------------------------------------------------- */
-
- // Document order sorting
- sortOrder = hasCompare ?
- function( a, b ) {
-
- // Flag for duplicate removal
- if ( a === b ) {
- hasDuplicate = true;
- return 0;
- }
-
- // Sort on method existence if only one input has compareDocumentPosition
- var compare = !a.compareDocumentPosition - !b.compareDocumentPosition;
- if ( compare ) {
- return compare;
- }
-
- // Calculate position if both inputs belong to the same document
- compare = ( a.ownerDocument || a ) === ( b.ownerDocument || b ) ?
- a.compareDocumentPosition( b ) :
-
- // Otherwise we know they are disconnected
- 1;
-
- // Disconnected nodes
- if ( compare & 1 ||
- (!support.sortDetached && b.compareDocumentPosition( a ) === compare) ) {
-
- // Choose the first element that is related to our preferred document
- if ( a === doc || a.ownerDocument === preferredDoc && contains(preferredDoc, a) ) {
- return -1;
- }
- if ( b === doc || b.ownerDocument === preferredDoc && contains(preferredDoc, b) ) {
- return 1;
- }
-
- // Maintain original order
- return sortInput ?
- ( indexOf.call( sortInput, a ) - indexOf.call( sortInput, b ) ) :
- 0;
- }
-
- return compare & 4 ? -1 : 1;
- } :
- function( a, b ) {
- // Exit early if the nodes are identical
- if ( a === b ) {
- hasDuplicate = true;
- return 0;
- }
-
- var cur,
- i = 0,
- aup = a.parentNode,
- bup = b.parentNode,
- ap = [ a ],
- bp = [ b ];
-
- // Parentless nodes are either documents or disconnected
- if ( !aup || !bup ) {
- return a === doc ? -1 :
- b === doc ? 1 :
- aup ? -1 :
- bup ? 1 :
- sortInput ?
- ( indexOf.call( sortInput, a ) - indexOf.call( sortInput, b ) ) :
- 0;
-
- // If the nodes are siblings, we can do a quick check
- } else if ( aup === bup ) {
- return siblingCheck( a, b );
- }
-
- // Otherwise we need full lists of their ancestors for comparison
- cur = a;
- while ( (cur = cur.parentNode) ) {
- ap.unshift( cur );
- }
- cur = b;
- while ( (cur = cur.parentNode) ) {
- bp.unshift( cur );
- }
-
- // Walk down the tree looking for a discrepancy
- while ( ap[i] === bp[i] ) {
- i++;
- }
-
- return i ?
- // Do a sibling check if the nodes have a common ancestor
- siblingCheck( ap[i], bp[i] ) :
-
- // Otherwise nodes in our document sort first
- ap[i] === preferredDoc ? -1 :
- bp[i] === preferredDoc ? 1 :
- 0;
- };
-
- return doc;
-};
-
-Sizzle.matches = function( expr, elements ) {
- return Sizzle( expr, null, null, elements );
-};
-
-Sizzle.matchesSelector = function( elem, expr ) {
- // Set document vars if needed
- if ( ( elem.ownerDocument || elem ) !== document ) {
- setDocument( elem );
- }
-
- // Make sure that attribute selectors are quoted
- expr = expr.replace( rattributeQuotes, "='$1']" );
-
- if ( support.matchesSelector && documentIsHTML &&
- ( !rbuggyMatches || !rbuggyMatches.test( expr ) ) &&
- ( !rbuggyQSA || !rbuggyQSA.test( expr ) ) ) {
-
- try {
- var ret = matches.call( elem, expr );
-
- // IE 9's matchesSelector returns false on disconnected nodes
- if ( ret || support.disconnectedMatch ||
- // As well, disconnected nodes are said to be in a document
- // fragment in IE 9
- elem.document && elem.document.nodeType !== 11 ) {
- return ret;
- }
- } catch(e) {}
- }
-
- return Sizzle( expr, document, null, [ elem ] ).length > 0;
-};
-
-Sizzle.contains = function( context, elem ) {
- // Set document vars if needed
- if ( ( context.ownerDocument || context ) !== document ) {
- setDocument( context );
- }
- return contains( context, elem );
-};
-
-Sizzle.attr = function( elem, name ) {
- // Set document vars if needed
- if ( ( elem.ownerDocument || elem ) !== document ) {
- setDocument( elem );
- }
-
- var fn = Expr.attrHandle[ name.toLowerCase() ],
- // Don't get fooled by Object.prototype properties (jQuery #13807)
- val = fn && hasOwn.call( Expr.attrHandle, name.toLowerCase() ) ?
- fn( elem, name, !documentIsHTML ) :
- undefined;
-
- return val !== undefined ?
- val :
- support.attributes || !documentIsHTML ?
- elem.getAttribute( name ) :
- (val = elem.getAttributeNode(name)) && val.specified ?
- val.value :
- null;
-};
-
-Sizzle.error = function( msg ) {
- throw new Error( "Syntax error, unrecognized expression: " + msg );
-};
-
-/**
- * Document sorting and removing duplicates
- * @param {ArrayLike} results
- */
-Sizzle.uniqueSort = function( results ) {
- var elem,
- duplicates = [],
- j = 0,
- i = 0;
-
- // Unless we *know* we can detect duplicates, assume their presence
- hasDuplicate = !support.detectDuplicates;
- sortInput = !support.sortStable && results.slice( 0 );
- results.sort( sortOrder );
-
- if ( hasDuplicate ) {
- while ( (elem = results[i++]) ) {
- if ( elem === results[ i ] ) {
- j = duplicates.push( i );
- }
- }
- while ( j-- ) {
- results.splice( duplicates[ j ], 1 );
- }
- }
-
- // Clear input after sorting to release objects
- // See https://github.com/jquery/sizzle/pull/225
- sortInput = null;
-
- return results;
-};
-
-/**
- * Utility function for retrieving the text value of an array of DOM nodes
- * @param {Array|Element} elem
- */
-getText = Sizzle.getText = function( elem ) {
- var node,
- ret = "",
- i = 0,
- nodeType = elem.nodeType;
-
- if ( !nodeType ) {
- // If no nodeType, this is expected to be an array
- while ( (node = elem[i++]) ) {
- // Do not traverse comment nodes
- ret += getText( node );
- }
- } else if ( nodeType === 1 || nodeType === 9 || nodeType === 11 ) {
- // Use textContent for elements
- // innerText usage removed for consistency of new lines (jQuery #11153)
- if ( typeof elem.textContent === "string" ) {
- return elem.textContent;
- } else {
- // Traverse its children
- for ( elem = elem.firstChild; elem; elem = elem.nextSibling ) {
- ret += getText( elem );
- }
- }
- } else if ( nodeType === 3 || nodeType === 4 ) {
- return elem.nodeValue;
- }
- // Do not include comment or processing instruction nodes
-
- return ret;
-};
-
-Expr = Sizzle.selectors = {
-
- // Can be adjusted by the user
- cacheLength: 50,
-
- createPseudo: markFunction,
-
- match: matchExpr,
-
- attrHandle: {},
-
- find: {},
-
- relative: {
- ">": { dir: "parentNode", first: true },
- " ": { dir: "parentNode" },
- "+": { dir: "previousSibling", first: true },
- "~": { dir: "previousSibling" }
- },
-
- preFilter: {
- "ATTR": function( match ) {
- match[1] = match[1].replace( runescape, funescape );
-
- // Move the given value to match[3] whether quoted or unquoted
- match[3] = ( match[3] || match[4] || match[5] || "" ).replace( runescape, funescape );
-
- if ( match[2] === "~=" ) {
- match[3] = " " + match[3] + " ";
- }
-
- return match.slice( 0, 4 );
- },
-
- "CHILD": function( match ) {
- /* matches from matchExpr["CHILD"]
- 1 type (only|nth|...)
- 2 what (child|of-type)
- 3 argument (even|odd|\d*|\d*n([+-]\d+)?|...)
- 4 xn-component of xn+y argument ([+-]?\d*n|)
- 5 sign of xn-component
- 6 x of xn-component
- 7 sign of y-component
- 8 y of y-component
- */
- match[1] = match[1].toLowerCase();
-
- if ( match[1].slice( 0, 3 ) === "nth" ) {
- // nth-* requires argument
- if ( !match[3] ) {
- Sizzle.error( match[0] );
- }
-
- // numeric x and y parameters for Expr.filter.CHILD
- // remember that false/true cast respectively to 0/1
- match[4] = +( match[4] ? match[5] + (match[6] || 1) : 2 * ( match[3] === "even" || match[3] === "odd" ) );
- match[5] = +( ( match[7] + match[8] ) || match[3] === "odd" );
-
- // other types prohibit arguments
- } else if ( match[3] ) {
- Sizzle.error( match[0] );
- }
-
- return match;
- },
-
- "PSEUDO": function( match ) {
- var excess,
- unquoted = !match[6] && match[2];
-
- if ( matchExpr["CHILD"].test( match[0] ) ) {
- return null;
- }
-
- // Accept quoted arguments as-is
- if ( match[3] ) {
- match[2] = match[4] || match[5] || "";
-
- // Strip excess characters from unquoted arguments
- } else if ( unquoted && rpseudo.test( unquoted ) &&
- // Get excess from tokenize (recursively)
- (excess = tokenize( unquoted, true )) &&
- // advance to the next closing parenthesis
- (excess = unquoted.indexOf( ")", unquoted.length - excess ) - unquoted.length) ) {
-
- // excess is a negative index
- match[0] = match[0].slice( 0, excess );
- match[2] = unquoted.slice( 0, excess );
- }
-
- // Return only captures needed by the pseudo filter method (type and argument)
- return match.slice( 0, 3 );
- }
- },
-
- filter: {
-
- "TAG": function( nodeNameSelector ) {
- var nodeName = nodeNameSelector.replace( runescape, funescape ).toLowerCase();
- return nodeNameSelector === "*" ?
- function() { return true; } :
- function( elem ) {
- return elem.nodeName && elem.nodeName.toLowerCase() === nodeName;
- };
- },
-
- "CLASS": function( className ) {
- var pattern = classCache[ className + " " ];
-
- return pattern ||
- (pattern = new RegExp( "(^|" + whitespace + ")" + className + "(" + whitespace + "|$)" )) &&
- classCache( className, function( elem ) {
- return pattern.test( typeof elem.className === "string" && elem.className || typeof elem.getAttribute !== strundefined && elem.getAttribute("class") || "" );
- });
- },
-
- "ATTR": function( name, operator, check ) {
- return function( elem ) {
- var result = Sizzle.attr( elem, name );
-
- if ( result == null ) {
- return operator === "!=";
- }
- if ( !operator ) {
- return true;
- }
-
- result += "";
-
- return operator === "=" ? result === check :
- operator === "!=" ? result !== check :
- operator === "^=" ? check && result.indexOf( check ) === 0 :
- operator === "*=" ? check && result.indexOf( check ) > -1 :
- operator === "$=" ? check && result.slice( -check.length ) === check :
- operator === "~=" ? ( " " + result + " " ).indexOf( check ) > -1 :
- operator === "|=" ? result === check || result.slice( 0, check.length + 1 ) === check + "-" :
- false;
- };
- },
-
- "CHILD": function( type, what, argument, first, last ) {
- var simple = type.slice( 0, 3 ) !== "nth",
- forward = type.slice( -4 ) !== "last",
- ofType = what === "of-type";
-
- return first === 1 && last === 0 ?
-
- // Shortcut for :nth-*(n)
- function( elem ) {
- return !!elem.parentNode;
- } :
-
- function( elem, context, xml ) {
- var cache, outerCache, node, diff, nodeIndex, start,
- dir = simple !== forward ? "nextSibling" : "previousSibling",
- parent = elem.parentNode,
- name = ofType && elem.nodeName.toLowerCase(),
- useCache = !xml && !ofType;
-
- if ( parent ) {
-
- // :(first|last|only)-(child|of-type)
- if ( simple ) {
- while ( dir ) {
- node = elem;
- while ( (node = node[ dir ]) ) {
- if ( ofType ? node.nodeName.toLowerCase() === name : node.nodeType === 1 ) {
- return false;
- }
- }
- // Reverse direction for :only-* (if we haven't yet done so)
- start = dir = type === "only" && !start && "nextSibling";
- }
- return true;
- }
-
- start = [ forward ? parent.firstChild : parent.lastChild ];
-
- // non-xml :nth-child(...) stores cache data on `parent`
- if ( forward && useCache ) {
- // Seek `elem` from a previously-cached index
- outerCache = parent[ expando ] || (parent[ expando ] = {});
- cache = outerCache[ type ] || [];
- nodeIndex = cache[0] === dirruns && cache[1];
- diff = cache[0] === dirruns && cache[2];
- node = nodeIndex && parent.childNodes[ nodeIndex ];
-
- while ( (node = ++nodeIndex && node && node[ dir ] ||
-
- // Fallback to seeking `elem` from the start
- (diff = nodeIndex = 0) || start.pop()) ) {
-
- // When found, cache indexes on `parent` and break
- if ( node.nodeType === 1 && ++diff && node === elem ) {
- outerCache[ type ] = [ dirruns, nodeIndex, diff ];
- break;
- }
- }
-
- // Use previously-cached element index if available
- } else if ( useCache && (cache = (elem[ expando ] || (elem[ expando ] = {}))[ type ]) && cache[0] === dirruns ) {
- diff = cache[1];
-
- // xml :nth-child(...) or :nth-last-child(...) or :nth(-last)?-of-type(...)
- } else {
- // Use the same loop as above to seek `elem` from the start
- while ( (node = ++nodeIndex && node && node[ dir ] ||
- (diff = nodeIndex = 0) || start.pop()) ) {
-
- if ( ( ofType ? node.nodeName.toLowerCase() === name : node.nodeType === 1 ) && ++diff ) {
- // Cache the index of each encountered element
- if ( useCache ) {
- (node[ expando ] || (node[ expando ] = {}))[ type ] = [ dirruns, diff ];
- }
-
- if ( node === elem ) {
- break;
- }
- }
- }
- }
-
- // Incorporate the offset, then check against cycle size
- diff -= last;
- return diff === first || ( diff % first === 0 && diff / first >= 0 );
- }
- };
- },
-
- "PSEUDO": function( pseudo, argument ) {
- // pseudo-class names are case-insensitive
- // http://www.w3.org/TR/selectors/#pseudo-classes
- // Prioritize by case sensitivity in case custom pseudos are added with uppercase letters
- // Remember that setFilters inherits from pseudos
- var args,
- fn = Expr.pseudos[ pseudo ] || Expr.setFilters[ pseudo.toLowerCase() ] ||
- Sizzle.error( "unsupported pseudo: " + pseudo );
-
- // The user may use createPseudo to indicate that
- // arguments are needed to create the filter function
- // just as Sizzle does
- if ( fn[ expando ] ) {
- return fn( argument );
- }
-
- // But maintain support for old signatures
- if ( fn.length > 1 ) {
- args = [ pseudo, pseudo, "", argument ];
- return Expr.setFilters.hasOwnProperty( pseudo.toLowerCase() ) ?
- markFunction(function( seed, matches ) {
- var idx,
- matched = fn( seed, argument ),
- i = matched.length;
- while ( i-- ) {
- idx = indexOf.call( seed, matched[i] );
- seed[ idx ] = !( matches[ idx ] = matched[i] );
- }
- }) :
- function( elem ) {
- return fn( elem, 0, args );
- };
- }
-
- return fn;
- }
- },
-
- pseudos: {
- // Potentially complex pseudos
- "not": markFunction(function( selector ) {
- // Trim the selector passed to compile
- // to avoid treating leading and trailing
- // spaces as combinators
- var input = [],
- results = [],
- matcher = compile( selector.replace( rtrim, "$1" ) );
-
- return matcher[ expando ] ?
- markFunction(function( seed, matches, context, xml ) {
- var elem,
- unmatched = matcher( seed, null, xml, [] ),
- i = seed.length;
-
- // Match elements unmatched by `matcher`
- while ( i-- ) {
- if ( (elem = unmatched[i]) ) {
- seed[i] = !(matches[i] = elem);
- }
- }
- }) :
- function( elem, context, xml ) {
- input[0] = elem;
- matcher( input, null, xml, results );
- return !results.pop();
- };
- }),
-
- "has": markFunction(function( selector ) {
- return function( elem ) {
- return Sizzle( selector, elem ).length > 0;
- };
- }),
-
- "contains": markFunction(function( text ) {
- return function( elem ) {
- return ( elem.textContent || elem.innerText || getText( elem ) ).indexOf( text ) > -1;
- };
- }),
-
- // "Whether an element is represented by a :lang() selector
- // is based solely on the element's language value
- // being equal to the identifier C,
- // or beginning with the identifier C immediately followed by "-".
- // The matching of C against the element's language value is performed case-insensitively.
- // The identifier C does not have to be a valid language name."
- // http://www.w3.org/TR/selectors/#lang-pseudo
- "lang": markFunction( function( lang ) {
- // lang value must be a valid identifier
- if ( !ridentifier.test(lang || "") ) {
- Sizzle.error( "unsupported lang: " + lang );
- }
- lang = lang.replace( runescape, funescape ).toLowerCase();
- return function( elem ) {
- var elemLang;
- do {
- if ( (elemLang = documentIsHTML ?
- elem.lang :
- elem.getAttribute("xml:lang") || elem.getAttribute("lang")) ) {
-
- elemLang = elemLang.toLowerCase();
- return elemLang === lang || elemLang.indexOf( lang + "-" ) === 0;
- }
- } while ( (elem = elem.parentNode) && elem.nodeType === 1 );
- return false;
- };
- }),
-
- // Miscellaneous
- "target": function( elem ) {
- var hash = window.location && window.location.hash;
- return hash && hash.slice( 1 ) === elem.id;
- },
-
- "root": function( elem ) {
- return elem === docElem;
- },
-
- "focus": function( elem ) {
- return elem === document.activeElement && (!document.hasFocus || document.hasFocus()) && !!(elem.type || elem.href || ~elem.tabIndex);
- },
-
- // Boolean properties
- "enabled": function( elem ) {
- return elem.disabled === false;
- },
-
- "disabled": function( elem ) {
- return elem.disabled === true;
- },
-
- "checked": function( elem ) {
- // In CSS3, :checked should return both checked and selected elements
- // http://www.w3.org/TR/2011/REC-css3-selectors-20110929/#checked
- var nodeName = elem.nodeName.toLowerCase();
- return (nodeName === "input" && !!elem.checked) || (nodeName === "option" && !!elem.selected);
- },
-
- "selected": function( elem ) {
- // Accessing this property makes selected-by-default
- // options in Safari work properly
- if ( elem.parentNode ) {
- elem.parentNode.selectedIndex;
- }
-
- return elem.selected === true;
- },
-
- // Contents
- "empty": function( elem ) {
- // http://www.w3.org/TR/selectors/#empty-pseudo
- // :empty is negated by element (1) or content nodes (text: 3; cdata: 4; entity ref: 5),
- // but not by others (comment: 8; processing instruction: 7; etc.)
- // nodeType < 6 works because attributes (2) do not appear as children
- for ( elem = elem.firstChild; elem; elem = elem.nextSibling ) {
- if ( elem.nodeType < 6 ) {
- return false;
- }
- }
- return true;
- },
-
- "parent": function( elem ) {
- return !Expr.pseudos["empty"]( elem );
- },
-
- // Element/input types
- "header": function( elem ) {
- return rheader.test( elem.nodeName );
- },
-
- "input": function( elem ) {
- return rinputs.test( elem.nodeName );
- },
-
- "button": function( elem ) {
- var name = elem.nodeName.toLowerCase();
- return name === "input" && elem.type === "button" || name === "button";
- },
-
- "text": function( elem ) {
- var attr;
- return elem.nodeName.toLowerCase() === "input" &&
- elem.type === "text" &&
-
- // Support: IE<8
- // New HTML5 attribute values (e.g., "search") appear with elem.type === "text"
- ( (attr = elem.getAttribute("type")) == null || attr.toLowerCase() === "text" );
- },
-
- // Position-in-collection
- "first": createPositionalPseudo(function() {
- return [ 0 ];
- }),
-
- "last": createPositionalPseudo(function( matchIndexes, length ) {
- return [ length - 1 ];
- }),
-
- "eq": createPositionalPseudo(function( matchIndexes, length, argument ) {
- return [ argument < 0 ? argument + length : argument ];
- }),
-
- "even": createPositionalPseudo(function( matchIndexes, length ) {
- var i = 0;
- for ( ; i < length; i += 2 ) {
- matchIndexes.push( i );
- }
- return matchIndexes;
- }),
-
- "odd": createPositionalPseudo(function( matchIndexes, length ) {
- var i = 1;
- for ( ; i < length; i += 2 ) {
- matchIndexes.push( i );
- }
- return matchIndexes;
- }),
-
- "lt": createPositionalPseudo(function( matchIndexes, length, argument ) {
- var i = argument < 0 ? argument + length : argument;
- for ( ; --i >= 0; ) {
- matchIndexes.push( i );
- }
- return matchIndexes;
- }),
-
- "gt": createPositionalPseudo(function( matchIndexes, length, argument ) {
- var i = argument < 0 ? argument + length : argument;
- for ( ; ++i < length; ) {
- matchIndexes.push( i );
- }
- return matchIndexes;
- })
- }
-};
-
-Expr.pseudos["nth"] = Expr.pseudos["eq"];
-
-// Add button/input type pseudos
-for ( i in { radio: true, checkbox: true, file: true, password: true, image: true } ) {
- Expr.pseudos[ i ] = createInputPseudo( i );
-}
-for ( i in { submit: true, reset: true } ) {
- Expr.pseudos[ i ] = createButtonPseudo( i );
-}
-
-// Easy API for creating new setFilters
-function setFilters() {}
-setFilters.prototype = Expr.filters = Expr.pseudos;
-Expr.setFilters = new setFilters();
-
-tokenize = Sizzle.tokenize = function( selector, parseOnly ) {
- var matched, match, tokens, type,
- soFar, groups, preFilters,
- cached = tokenCache[ selector + " " ];
-
- if ( cached ) {
- return parseOnly ? 0 : cached.slice( 0 );
- }
-
- soFar = selector;
- groups = [];
- preFilters = Expr.preFilter;
-
- while ( soFar ) {
-
- // Comma and first run
- if ( !matched || (match = rcomma.exec( soFar )) ) {
- if ( match ) {
- // Don't consume trailing commas as valid
- soFar = soFar.slice( match[0].length ) || soFar;
- }
- groups.push( (tokens = []) );
- }
-
- matched = false;
-
- // Combinators
- if ( (match = rcombinators.exec( soFar )) ) {
- matched = match.shift();
- tokens.push({
- value: matched,
- // Cast descendant combinators to space
- type: match[0].replace( rtrim, " " )
- });
- soFar = soFar.slice( matched.length );
- }
-
- // Filters
- for ( type in Expr.filter ) {
- if ( (match = matchExpr[ type ].exec( soFar )) && (!preFilters[ type ] ||
- (match = preFilters[ type ]( match ))) ) {
- matched = match.shift();
- tokens.push({
- value: matched,
- type: type,
- matches: match
- });
- soFar = soFar.slice( matched.length );
- }
- }
-
- if ( !matched ) {
- break;
- }
- }
-
- // Return the length of the invalid excess
- // if we're just parsing
- // Otherwise, throw an error or return tokens
- return parseOnly ?
- soFar.length :
- soFar ?
- Sizzle.error( selector ) :
- // Cache the tokens
- tokenCache( selector, groups ).slice( 0 );
-};
-
-function toSelector( tokens ) {
- var i = 0,
- len = tokens.length,
- selector = "";
- for ( ; i < len; i++ ) {
- selector += tokens[i].value;
- }
- return selector;
-}
-
-function addCombinator( matcher, combinator, base ) {
- var dir = combinator.dir,
- checkNonElements = base && dir === "parentNode",
- doneName = done++;
-
- return combinator.first ?
- // Check against closest ancestor/preceding element
- function( elem, context, xml ) {
- while ( (elem = elem[ dir ]) ) {
- if ( elem.nodeType === 1 || checkNonElements ) {
- return matcher( elem, context, xml );
- }
- }
- } :
-
- // Check against all ancestor/preceding elements
- function( elem, context, xml ) {
- var oldCache, outerCache,
- newCache = [ dirruns, doneName ];
-
- // We can't set arbitrary data on XML nodes, so they don't benefit from dir caching
- if ( xml ) {
- while ( (elem = elem[ dir ]) ) {
- if ( elem.nodeType === 1 || checkNonElements ) {
- if ( matcher( elem, context, xml ) ) {
- return true;
- }
- }
- }
- } else {
- while ( (elem = elem[ dir ]) ) {
- if ( elem.nodeType === 1 || checkNonElements ) {
- outerCache = elem[ expando ] || (elem[ expando ] = {});
- if ( (oldCache = outerCache[ dir ]) &&
- oldCache[ 0 ] === dirruns && oldCache[ 1 ] === doneName ) {
-
- // Assign to newCache so results back-propagate to previous elements
- return (newCache[ 2 ] = oldCache[ 2 ]);
- } else {
- // Reuse newcache so results back-propagate to previous elements
- outerCache[ dir ] = newCache;
-
- // A match means we're done; a fail means we have to keep checking
- if ( (newCache[ 2 ] = matcher( elem, context, xml )) ) {
- return true;
- }
- }
- }
- }
- }
- };
-}
-
-function elementMatcher( matchers ) {
- return matchers.length > 1 ?
- function( elem, context, xml ) {
- var i = matchers.length;
- while ( i-- ) {
- if ( !matchers[i]( elem, context, xml ) ) {
- return false;
- }
- }
- return true;
- } :
- matchers[0];
-}
-
-function multipleContexts( selector, contexts, results ) {
- var i = 0,
- len = contexts.length;
- for ( ; i < len; i++ ) {
- Sizzle( selector, contexts[i], results );
- }
- return results;
-}
-
-function condense( unmatched, map, filter, context, xml ) {
- var elem,
- newUnmatched = [],
- i = 0,
- len = unmatched.length,
- mapped = map != null;
-
- for ( ; i < len; i++ ) {
- if ( (elem = unmatched[i]) ) {
- if ( !filter || filter( elem, context, xml ) ) {
- newUnmatched.push( elem );
- if ( mapped ) {
- map.push( i );
- }
- }
- }
- }
-
- return newUnmatched;
-}
-
-function setMatcher( preFilter, selector, matcher, postFilter, postFinder, postSelector ) {
- if ( postFilter && !postFilter[ expando ] ) {
- postFilter = setMatcher( postFilter );
- }
- if ( postFinder && !postFinder[ expando ] ) {
- postFinder = setMatcher( postFinder, postSelector );
- }
- return markFunction(function( seed, results, context, xml ) {
- var temp, i, elem,
- preMap = [],
- postMap = [],
- preexisting = results.length,
-
- // Get initial elements from seed or context
- elems = seed || multipleContexts( selector || "*", context.nodeType ? [ context ] : context, [] ),
-
- // Prefilter to get matcher input, preserving a map for seed-results synchronization
- matcherIn = preFilter && ( seed || !selector ) ?
- condense( elems, preMap, preFilter, context, xml ) :
- elems,
-
- matcherOut = matcher ?
- // If we have a postFinder, or filtered seed, or non-seed postFilter or preexisting results,
- postFinder || ( seed ? preFilter : preexisting || postFilter ) ?
-
- // ...intermediate processing is necessary
- [] :
-
- // ...otherwise use results directly
- results :
- matcherIn;
-
- // Find primary matches
- if ( matcher ) {
- matcher( matcherIn, matcherOut, context, xml );
- }
-
- // Apply postFilter
- if ( postFilter ) {
- temp = condense( matcherOut, postMap );
- postFilter( temp, [], context, xml );
-
- // Un-match failing elements by moving them back to matcherIn
- i = temp.length;
- while ( i-- ) {
- if ( (elem = temp[i]) ) {
- matcherOut[ postMap[i] ] = !(matcherIn[ postMap[i] ] = elem);
- }
- }
- }
-
- if ( seed ) {
- if ( postFinder || preFilter ) {
- if ( postFinder ) {
- // Get the final matcherOut by condensing this intermediate into postFinder contexts
- temp = [];
- i = matcherOut.length;
- while ( i-- ) {
- if ( (elem = matcherOut[i]) ) {
- // Restore matcherIn since elem is not yet a final match
- temp.push( (matcherIn[i] = elem) );
- }
- }
- postFinder( null, (matcherOut = []), temp, xml );
- }
-
- // Move matched elements from seed to results to keep them synchronized
- i = matcherOut.length;
- while ( i-- ) {
- if ( (elem = matcherOut[i]) &&
- (temp = postFinder ? indexOf.call( seed, elem ) : preMap[i]) > -1 ) {
-
- seed[temp] = !(results[temp] = elem);
- }
- }
- }
-
- // Add elements to results, through postFinder if defined
- } else {
- matcherOut = condense(
- matcherOut === results ?
- matcherOut.splice( preexisting, matcherOut.length ) :
- matcherOut
- );
- if ( postFinder ) {
- postFinder( null, results, matcherOut, xml );
- } else {
- push.apply( results, matcherOut );
- }
- }
- });
-}
-
-function matcherFromTokens( tokens ) {
- var checkContext, matcher, j,
- len = tokens.length,
- leadingRelative = Expr.relative[ tokens[0].type ],
- implicitRelative = leadingRelative || Expr.relative[" "],
- i = leadingRelative ? 1 : 0,
-
- // The foundational matcher ensures that elements are reachable from top-level context(s)
- matchContext = addCombinator( function( elem ) {
- return elem === checkContext;
- }, implicitRelative, true ),
- matchAnyContext = addCombinator( function( elem ) {
- return indexOf.call( checkContext, elem ) > -1;
- }, implicitRelative, true ),
- matchers = [ function( elem, context, xml ) {
- return ( !leadingRelative && ( xml || context !== outermostContext ) ) || (
- (checkContext = context).nodeType ?
- matchContext( elem, context, xml ) :
- matchAnyContext( elem, context, xml ) );
- } ];
-
- for ( ; i < len; i++ ) {
- if ( (matcher = Expr.relative[ tokens[i].type ]) ) {
- matchers = [ addCombinator(elementMatcher( matchers ), matcher) ];
- } else {
- matcher = Expr.filter[ tokens[i].type ].apply( null, tokens[i].matches );
-
- // Return special upon seeing a positional matcher
- if ( matcher[ expando ] ) {
- // Find the next relative operator (if any) for proper handling
- j = ++i;
- for ( ; j < len; j++ ) {
- if ( Expr.relative[ tokens[j].type ] ) {
- break;
- }
- }
- return setMatcher(
- i > 1 && elementMatcher( matchers ),
- i > 1 && toSelector(
- // If the preceding token was a descendant combinator, insert an implicit any-element `*`
- tokens.slice( 0, i - 1 ).concat({ value: tokens[ i - 2 ].type === " " ? "*" : "" })
- ).replace( rtrim, "$1" ),
- matcher,
- i < j && matcherFromTokens( tokens.slice( i, j ) ),
- j < len && matcherFromTokens( (tokens = tokens.slice( j )) ),
- j < len && toSelector( tokens )
- );
- }
- matchers.push( matcher );
- }
- }
-
- return elementMatcher( matchers );
-}
-
-function matcherFromGroupMatchers( elementMatchers, setMatchers ) {
- var bySet = setMatchers.length > 0,
- byElement = elementMatchers.length > 0,
- superMatcher = function( seed, context, xml, results, outermost ) {
- var elem, j, matcher,
- matchedCount = 0,
- i = "0",
- unmatched = seed && [],
- setMatched = [],
- contextBackup = outermostContext,
- // We must always have either seed elements or outermost context
- elems = seed || byElement && Expr.find["TAG"]( "*", outermost ),
- // Use integer dirruns iff this is the outermost matcher
- dirrunsUnique = (dirruns += contextBackup == null ? 1 : Math.random() || 0.1),
- len = elems.length;
-
- if ( outermost ) {
- outermostContext = context !== document && context;
- }
-
- // Add elements passing elementMatchers directly to results
- // Keep `i` a string if there are no elements so `matchedCount` will be "00" below
- // Support: IE<9, Safari
- // Tolerate NodeList properties (IE: "length"; Safari: ) matching elements by id
- for ( ; i !== len && (elem = elems[i]) != null; i++ ) {
- if ( byElement && elem ) {
- j = 0;
- while ( (matcher = elementMatchers[j++]) ) {
- if ( matcher( elem, context, xml ) ) {
- results.push( elem );
- break;
- }
- }
- if ( outermost ) {
- dirruns = dirrunsUnique;
- }
- }
-
- // Track unmatched elements for set filters
- if ( bySet ) {
- // They will have gone through all possible matchers
- if ( (elem = !matcher && elem) ) {
- matchedCount--;
- }
-
- // Lengthen the array for every element, matched or not
- if ( seed ) {
- unmatched.push( elem );
- }
- }
- }
-
- // Apply set filters to unmatched elements
- matchedCount += i;
- if ( bySet && i !== matchedCount ) {
- j = 0;
- while ( (matcher = setMatchers[j++]) ) {
- matcher( unmatched, setMatched, context, xml );
- }
-
- if ( seed ) {
- // Reintegrate element matches to eliminate the need for sorting
- if ( matchedCount > 0 ) {
- while ( i-- ) {
- if ( !(unmatched[i] || setMatched[i]) ) {
- setMatched[i] = pop.call( results );
- }
- }
- }
-
- // Discard index placeholder values to get only actual matches
- setMatched = condense( setMatched );
- }
-
- // Add matches to results
- push.apply( results, setMatched );
-
- // Seedless set matches succeeding multiple successful matchers stipulate sorting
- if ( outermost && !seed && setMatched.length > 0 &&
- ( matchedCount + setMatchers.length ) > 1 ) {
-
- Sizzle.uniqueSort( results );
- }
- }
-
- // Override manipulation of globals by nested matchers
- if ( outermost ) {
- dirruns = dirrunsUnique;
- outermostContext = contextBackup;
- }
-
- return unmatched;
- };
-
- return bySet ?
- markFunction( superMatcher ) :
- superMatcher;
-}
-
-compile = Sizzle.compile = function( selector, match /* Internal Use Only */ ) {
- var i,
- setMatchers = [],
- elementMatchers = [],
- cached = compilerCache[ selector + " " ];
-
- if ( !cached ) {
- // Generate a function of recursive functions that can be used to check each element
- if ( !match ) {
- match = tokenize( selector );
- }
- i = match.length;
- while ( i-- ) {
- cached = matcherFromTokens( match[i] );
- if ( cached[ expando ] ) {
- setMatchers.push( cached );
- } else {
- elementMatchers.push( cached );
- }
- }
-
- // Cache the compiled function
- cached = compilerCache( selector, matcherFromGroupMatchers( elementMatchers, setMatchers ) );
-
- // Save selector and tokenization
- cached.selector = selector;
- }
- return cached;
-};
-
-/**
- * A low-level selection function that works with Sizzle's compiled
- * selector functions
- * @param {String|Function} selector A selector or a pre-compiled
- * selector function built with Sizzle.compile
- * @param {Element} context
- * @param {Array} [results]
- * @param {Array} [seed] A set of elements to match against
- */
-select = Sizzle.select = function( selector, context, results, seed ) {
- var i, tokens, token, type, find,
- compiled = typeof selector === "function" && selector,
- match = !seed && tokenize( (selector = compiled.selector || selector) );
-
- results = results || [];
-
- // Try to minimize operations if there is no seed and only one group
- if ( match.length === 1 ) {
-
- // Take a shortcut and set the context if the root selector is an ID
- tokens = match[0] = match[0].slice( 0 );
- if ( tokens.length > 2 && (token = tokens[0]).type === "ID" &&
- support.getById && context.nodeType === 9 && documentIsHTML &&
- Expr.relative[ tokens[1].type ] ) {
-
- context = ( Expr.find["ID"]( token.matches[0].replace(runescape, funescape), context ) || [] )[0];
- if ( !context ) {
- return results;
-
- // Precompiled matchers will still verify ancestry, so step up a level
- } else if ( compiled ) {
- context = context.parentNode;
- }
-
- selector = selector.slice( tokens.shift().value.length );
- }
-
- // Fetch a seed set for right-to-left matching
- i = matchExpr["needsContext"].test( selector ) ? 0 : tokens.length;
- while ( i-- ) {
- token = tokens[i];
-
- // Abort if we hit a combinator
- if ( Expr.relative[ (type = token.type) ] ) {
- break;
- }
- if ( (find = Expr.find[ type ]) ) {
- // Search, expanding context for leading sibling combinators
- if ( (seed = find(
- token.matches[0].replace( runescape, funescape ),
- rsibling.test( tokens[0].type ) && testContext( context.parentNode ) || context
- )) ) {
-
- // If seed is empty or no tokens remain, we can return early
- tokens.splice( i, 1 );
- selector = seed.length && toSelector( tokens );
- if ( !selector ) {
- push.apply( results, seed );
- return results;
- }
-
- break;
- }
- }
- }
- }
-
- // Compile and execute a filtering function if one is not provided
- // Provide `match` to avoid retokenization if we modified the selector above
- ( compiled || compile( selector, match ) )(
- seed,
- context,
- !documentIsHTML,
- results,
- rsibling.test( selector ) && testContext( context.parentNode ) || context
- );
- return results;
-};
-
-// One-time assignments
-
-// Sort stability
-support.sortStable = expando.split("").sort( sortOrder ).join("") === expando;
-
-// Support: Chrome<14
-// Always assume duplicates if they aren't passed to the comparison function
-support.detectDuplicates = !!hasDuplicate;
-
-// Initialize against the default document
-setDocument();
-
-// Support: Webkit<537.32 - Safari 6.0.3/Chrome 25 (fixed in Chrome 27)
-// Detached nodes confoundingly follow *each other*
-support.sortDetached = assert(function( div1 ) {
- // Should return 1, but returns 4 (following)
- return div1.compareDocumentPosition( document.createElement("div") ) & 1;
-});
-
-// Support: IE<8
-// Prevent attribute/property "interpolation"
-// http://msdn.microsoft.com/en-us/library/ms536429%28VS.85%29.aspx
-if ( !assert(function( div ) {
- div.innerHTML = "";
- return div.firstChild.getAttribute("href") === "#" ;
-}) ) {
- addHandle( "type|href|height|width", function( elem, name, isXML ) {
- if ( !isXML ) {
- return elem.getAttribute( name, name.toLowerCase() === "type" ? 1 : 2 );
- }
- });
-}
-
-// Support: IE<9
-// Use defaultValue in place of getAttribute("value")
-if ( !support.attributes || !assert(function( div ) {
- div.innerHTML = "";
- div.firstChild.setAttribute( "value", "" );
- return div.firstChild.getAttribute( "value" ) === "";
-}) ) {
- addHandle( "value", function( elem, name, isXML ) {
- if ( !isXML && elem.nodeName.toLowerCase() === "input" ) {
- return elem.defaultValue;
- }
- });
-}
-
-// Support: IE<9
-// Use getAttributeNode to fetch booleans when getAttribute lies
-if ( !assert(function( div ) {
- return div.getAttribute("disabled") == null;
-}) ) {
- addHandle( booleans, function( elem, name, isXML ) {
- var val;
- if ( !isXML ) {
- return elem[ name ] === true ? name.toLowerCase() :
- (val = elem.getAttributeNode( name )) && val.specified ?
- val.value :
- null;
- }
- });
-}
-
-return Sizzle;
-
-})( window );
-
-
-
-jQuery.find = Sizzle;
-jQuery.expr = Sizzle.selectors;
-jQuery.expr[":"] = jQuery.expr.pseudos;
-jQuery.unique = Sizzle.uniqueSort;
-jQuery.text = Sizzle.getText;
-jQuery.isXMLDoc = Sizzle.isXML;
-jQuery.contains = Sizzle.contains;
-
-
-
-var rneedsContext = jQuery.expr.match.needsContext;
-
-var rsingleTag = (/^<(\w+)\s*\/?>(?:<\/\1>|)$/);
-
-
-
-var risSimple = /^.[^:#\[\.,]*$/;
-
-// Implement the identical functionality for filter and not
-function winnow( elements, qualifier, not ) {
- if ( jQuery.isFunction( qualifier ) ) {
- return jQuery.grep( elements, function( elem, i ) {
- /* jshint -W018 */
- return !!qualifier.call( elem, i, elem ) !== not;
- });
-
- }
-
- if ( qualifier.nodeType ) {
- return jQuery.grep( elements, function( elem ) {
- return ( elem === qualifier ) !== not;
- });
-
- }
-
- if ( typeof qualifier === "string" ) {
- if ( risSimple.test( qualifier ) ) {
- return jQuery.filter( qualifier, elements, not );
- }
-
- qualifier = jQuery.filter( qualifier, elements );
- }
-
- return jQuery.grep( elements, function( elem ) {
- return ( jQuery.inArray( elem, qualifier ) >= 0 ) !== not;
- });
-}
-
-jQuery.filter = function( expr, elems, not ) {
- var elem = elems[ 0 ];
-
- if ( not ) {
- expr = ":not(" + expr + ")";
- }
-
- return elems.length === 1 && elem.nodeType === 1 ?
- jQuery.find.matchesSelector( elem, expr ) ? [ elem ] : [] :
- jQuery.find.matches( expr, jQuery.grep( elems, function( elem ) {
- return elem.nodeType === 1;
- }));
-};
-
-jQuery.fn.extend({
- find: function( selector ) {
- var i,
- ret = [],
- self = this,
- len = self.length;
-
- if ( typeof selector !== "string" ) {
- return this.pushStack( jQuery( selector ).filter(function() {
- for ( i = 0; i < len; i++ ) {
- if ( jQuery.contains( self[ i ], this ) ) {
- return true;
- }
- }
- }) );
- }
-
- for ( i = 0; i < len; i++ ) {
- jQuery.find( selector, self[ i ], ret );
- }
-
- // Needed because $( selector, context ) becomes $( context ).find( selector )
- ret = this.pushStack( len > 1 ? jQuery.unique( ret ) : ret );
- ret.selector = this.selector ? this.selector + " " + selector : selector;
- return ret;
- },
- filter: function( selector ) {
- return this.pushStack( winnow(this, selector || [], false) );
- },
- not: function( selector ) {
- return this.pushStack( winnow(this, selector || [], true) );
- },
- is: function( selector ) {
- return !!winnow(
- this,
-
- // If this is a positional/relative selector, check membership in the returned set
- // so $("p:first").is("p:last") won't return true for a doc with two "p".
- typeof selector === "string" && rneedsContext.test( selector ) ?
- jQuery( selector ) :
- selector || [],
- false
- ).length;
- }
-});
-
-
-// Initialize a jQuery object
-
-
-// A central reference to the root jQuery(document)
-var rootjQuery,
-
- // Use the correct document accordingly with window argument (sandbox)
- document = window.document,
-
- // A simple way to check for HTML strings
- // Prioritize #id over to avoid XSS via location.hash (#9521)
- // Strict HTML recognition (#11290: must start with <)
- rquickExpr = /^(?:\s*(<[\w\W]+>)[^>]*|#([\w-]*))$/,
-
- init = jQuery.fn.init = function( selector, context ) {
- var match, elem;
-
- // HANDLE: $(""), $(null), $(undefined), $(false)
- if ( !selector ) {
- return this;
- }
-
- // Handle HTML strings
- if ( typeof selector === "string" ) {
- if ( selector.charAt(0) === "<" && selector.charAt( selector.length - 1 ) === ">" && selector.length >= 3 ) {
- // Assume that strings that start and end with <> are HTML and skip the regex check
- match = [ null, selector, null ];
-
- } else {
- match = rquickExpr.exec( selector );
- }
-
- // Match html or make sure no context is specified for #id
- if ( match && (match[1] || !context) ) {
-
- // HANDLE: $(html) -> $(array)
- if ( match[1] ) {
- context = context instanceof jQuery ? context[0] : context;
-
- // scripts is true for back-compat
- // Intentionally let the error be thrown if parseHTML is not present
- jQuery.merge( this, jQuery.parseHTML(
- match[1],
- context && context.nodeType ? context.ownerDocument || context : document,
- true
- ) );
-
- // HANDLE: $(html, props)
- if ( rsingleTag.test( match[1] ) && jQuery.isPlainObject( context ) ) {
- for ( match in context ) {
- // Properties of context are called as methods if possible
- if ( jQuery.isFunction( this[ match ] ) ) {
- this[ match ]( context[ match ] );
-
- // ...and otherwise set as attributes
- } else {
- this.attr( match, context[ match ] );
- }
- }
- }
-
- return this;
-
- // HANDLE: $(#id)
- } else {
- elem = document.getElementById( match[2] );
-
- // Check parentNode to catch when Blackberry 4.6 returns
- // nodes that are no longer in the document #6963
- if ( elem && elem.parentNode ) {
- // Handle the case where IE and Opera return items
- // by name instead of ID
- if ( elem.id !== match[2] ) {
- return rootjQuery.find( selector );
- }
-
- // Otherwise, we inject the element directly into the jQuery object
- this.length = 1;
- this[0] = elem;
- }
-
- this.context = document;
- this.selector = selector;
- return this;
- }
-
- // HANDLE: $(expr, $(...))
- } else if ( !context || context.jquery ) {
- return ( context || rootjQuery ).find( selector );
-
- // HANDLE: $(expr, context)
- // (which is just equivalent to: $(context).find(expr)
- } else {
- return this.constructor( context ).find( selector );
- }
-
- // HANDLE: $(DOMElement)
- } else if ( selector.nodeType ) {
- this.context = this[0] = selector;
- this.length = 1;
- return this;
-
- // HANDLE: $(function)
- // Shortcut for document ready
- } else if ( jQuery.isFunction( selector ) ) {
- return typeof rootjQuery.ready !== "undefined" ?
- rootjQuery.ready( selector ) :
- // Execute immediately if ready is not present
- selector( jQuery );
- }
-
- if ( selector.selector !== undefined ) {
- this.selector = selector.selector;
- this.context = selector.context;
- }
-
- return jQuery.makeArray( selector, this );
- };
-
-// Give the init function the jQuery prototype for later instantiation
-init.prototype = jQuery.fn;
-
-// Initialize central reference
-rootjQuery = jQuery( document );
-
-
-var rparentsprev = /^(?:parents|prev(?:Until|All))/,
- // methods guaranteed to produce a unique set when starting from a unique set
- guaranteedUnique = {
- children: true,
- contents: true,
- next: true,
- prev: true
- };
-
-jQuery.extend({
- dir: function( elem, dir, until ) {
- var matched = [],
- cur = elem[ dir ];
-
- while ( cur && cur.nodeType !== 9 && (until === undefined || cur.nodeType !== 1 || !jQuery( cur ).is( until )) ) {
- if ( cur.nodeType === 1 ) {
- matched.push( cur );
- }
- cur = cur[dir];
- }
- return matched;
- },
-
- sibling: function( n, elem ) {
- var r = [];
-
- for ( ; n; n = n.nextSibling ) {
- if ( n.nodeType === 1 && n !== elem ) {
- r.push( n );
- }
- }
-
- return r;
- }
-});
-
-jQuery.fn.extend({
- has: function( target ) {
- var i,
- targets = jQuery( target, this ),
- len = targets.length;
-
- return this.filter(function() {
- for ( i = 0; i < len; i++ ) {
- if ( jQuery.contains( this, targets[i] ) ) {
- return true;
- }
- }
- });
- },
-
- closest: function( selectors, context ) {
- var cur,
- i = 0,
- l = this.length,
- matched = [],
- pos = rneedsContext.test( selectors ) || typeof selectors !== "string" ?
- jQuery( selectors, context || this.context ) :
- 0;
-
- for ( ; i < l; i++ ) {
- for ( cur = this[i]; cur && cur !== context; cur = cur.parentNode ) {
- // Always skip document fragments
- if ( cur.nodeType < 11 && (pos ?
- pos.index(cur) > -1 :
-
- // Don't pass non-elements to Sizzle
- cur.nodeType === 1 &&
- jQuery.find.matchesSelector(cur, selectors)) ) {
-
- matched.push( cur );
- break;
- }
- }
- }
-
- return this.pushStack( matched.length > 1 ? jQuery.unique( matched ) : matched );
- },
-
- // Determine the position of an element within
- // the matched set of elements
- index: function( elem ) {
-
- // No argument, return index in parent
- if ( !elem ) {
- return ( this[0] && this[0].parentNode ) ? this.first().prevAll().length : -1;
- }
-
- // index in selector
- if ( typeof elem === "string" ) {
- return jQuery.inArray( this[0], jQuery( elem ) );
- }
-
- // Locate the position of the desired element
- return jQuery.inArray(
- // If it receives a jQuery object, the first element is used
- elem.jquery ? elem[0] : elem, this );
- },
-
- add: function( selector, context ) {
- return this.pushStack(
- jQuery.unique(
- jQuery.merge( this.get(), jQuery( selector, context ) )
- )
- );
- },
-
- addBack: function( selector ) {
- return this.add( selector == null ?
- this.prevObject : this.prevObject.filter(selector)
- );
- }
-});
-
-function sibling( cur, dir ) {
- do {
- cur = cur[ dir ];
- } while ( cur && cur.nodeType !== 1 );
-
- return cur;
-}
-
-jQuery.each({
- parent: function( elem ) {
- var parent = elem.parentNode;
- return parent && parent.nodeType !== 11 ? parent : null;
- },
- parents: function( elem ) {
- return jQuery.dir( elem, "parentNode" );
- },
- parentsUntil: function( elem, i, until ) {
- return jQuery.dir( elem, "parentNode", until );
- },
- next: function( elem ) {
- return sibling( elem, "nextSibling" );
- },
- prev: function( elem ) {
- return sibling( elem, "previousSibling" );
- },
- nextAll: function( elem ) {
- return jQuery.dir( elem, "nextSibling" );
- },
- prevAll: function( elem ) {
- return jQuery.dir( elem, "previousSibling" );
- },
- nextUntil: function( elem, i, until ) {
- return jQuery.dir( elem, "nextSibling", until );
- },
- prevUntil: function( elem, i, until ) {
- return jQuery.dir( elem, "previousSibling", until );
- },
- siblings: function( elem ) {
- return jQuery.sibling( ( elem.parentNode || {} ).firstChild, elem );
- },
- children: function( elem ) {
- return jQuery.sibling( elem.firstChild );
- },
- contents: function( elem ) {
- return jQuery.nodeName( elem, "iframe" ) ?
- elem.contentDocument || elem.contentWindow.document :
- jQuery.merge( [], elem.childNodes );
- }
-}, function( name, fn ) {
- jQuery.fn[ name ] = function( until, selector ) {
- var ret = jQuery.map( this, fn, until );
-
- if ( name.slice( -5 ) !== "Until" ) {
- selector = until;
- }
-
- if ( selector && typeof selector === "string" ) {
- ret = jQuery.filter( selector, ret );
- }
-
- if ( this.length > 1 ) {
- // Remove duplicates
- if ( !guaranteedUnique[ name ] ) {
- ret = jQuery.unique( ret );
- }
-
- // Reverse order for parents* and prev-derivatives
- if ( rparentsprev.test( name ) ) {
- ret = ret.reverse();
- }
- }
-
- return this.pushStack( ret );
- };
-});
-var rnotwhite = (/\S+/g);
-
-
-
-// String to Object options format cache
-var optionsCache = {};
-
-// Convert String-formatted options into Object-formatted ones and store in cache
-function createOptions( options ) {
- var object = optionsCache[ options ] = {};
- jQuery.each( options.match( rnotwhite ) || [], function( _, flag ) {
- object[ flag ] = true;
- });
- return object;
-}
-
-/*
- * Create a callback list using the following parameters:
- *
- * options: an optional list of space-separated options that will change how
- * the callback list behaves or a more traditional option object
- *
- * By default a callback list will act like an event callback list and can be
- * "fired" multiple times.
- *
- * Possible options:
- *
- * once: will ensure the callback list can only be fired once (like a Deferred)
- *
- * memory: will keep track of previous values and will call any callback added
- * after the list has been fired right away with the latest "memorized"
- * values (like a Deferred)
- *
- * unique: will ensure a callback can only be added once (no duplicate in the list)
- *
- * stopOnFalse: interrupt callings when a callback returns false
- *
- */
-jQuery.Callbacks = function( options ) {
-
- // Convert options from String-formatted to Object-formatted if needed
- // (we check in cache first)
- options = typeof options === "string" ?
- ( optionsCache[ options ] || createOptions( options ) ) :
- jQuery.extend( {}, options );
-
- var // Flag to know if list is currently firing
- firing,
- // Last fire value (for non-forgettable lists)
- memory,
- // Flag to know if list was already fired
- fired,
- // End of the loop when firing
- firingLength,
- // Index of currently firing callback (modified by remove if needed)
- firingIndex,
- // First callback to fire (used internally by add and fireWith)
- firingStart,
- // Actual callback list
- list = [],
- // Stack of fire calls for repeatable lists
- stack = !options.once && [],
- // Fire callbacks
- fire = function( data ) {
- memory = options.memory && data;
- fired = true;
- firingIndex = firingStart || 0;
- firingStart = 0;
- firingLength = list.length;
- firing = true;
- for ( ; list && firingIndex < firingLength; firingIndex++ ) {
- if ( list[ firingIndex ].apply( data[ 0 ], data[ 1 ] ) === false && options.stopOnFalse ) {
- memory = false; // To prevent further calls using add
- break;
- }
- }
- firing = false;
- if ( list ) {
- if ( stack ) {
- if ( stack.length ) {
- fire( stack.shift() );
- }
- } else if ( memory ) {
- list = [];
- } else {
- self.disable();
- }
- }
- },
- // Actual Callbacks object
- self = {
- // Add a callback or a collection of callbacks to the list
- add: function() {
- if ( list ) {
- // First, we save the current length
- var start = list.length;
- (function add( args ) {
- jQuery.each( args, function( _, arg ) {
- var type = jQuery.type( arg );
- if ( type === "function" ) {
- if ( !options.unique || !self.has( arg ) ) {
- list.push( arg );
- }
- } else if ( arg && arg.length && type !== "string" ) {
- // Inspect recursively
- add( arg );
- }
- });
- })( arguments );
- // Do we need to add the callbacks to the
- // current firing batch?
- if ( firing ) {
- firingLength = list.length;
- // With memory, if we're not firing then
- // we should call right away
- } else if ( memory ) {
- firingStart = start;
- fire( memory );
- }
- }
- return this;
- },
- // Remove a callback from the list
- remove: function() {
- if ( list ) {
- jQuery.each( arguments, function( _, arg ) {
- var index;
- while ( ( index = jQuery.inArray( arg, list, index ) ) > -1 ) {
- list.splice( index, 1 );
- // Handle firing indexes
- if ( firing ) {
- if ( index <= firingLength ) {
- firingLength--;
- }
- if ( index <= firingIndex ) {
- firingIndex--;
- }
- }
- }
- });
- }
- return this;
- },
- // Check if a given callback is in the list.
- // If no argument is given, return whether or not list has callbacks attached.
- has: function( fn ) {
- return fn ? jQuery.inArray( fn, list ) > -1 : !!( list && list.length );
- },
- // Remove all callbacks from the list
- empty: function() {
- list = [];
- firingLength = 0;
- return this;
- },
- // Have the list do nothing anymore
- disable: function() {
- list = stack = memory = undefined;
- return this;
- },
- // Is it disabled?
- disabled: function() {
- return !list;
- },
- // Lock the list in its current state
- lock: function() {
- stack = undefined;
- if ( !memory ) {
- self.disable();
- }
- return this;
- },
- // Is it locked?
- locked: function() {
- return !stack;
- },
- // Call all callbacks with the given context and arguments
- fireWith: function( context, args ) {
- if ( list && ( !fired || stack ) ) {
- args = args || [];
- args = [ context, args.slice ? args.slice() : args ];
- if ( firing ) {
- stack.push( args );
- } else {
- fire( args );
- }
- }
- return this;
- },
- // Call all the callbacks with the given arguments
- fire: function() {
- self.fireWith( this, arguments );
- return this;
- },
- // To know if the callbacks have already been called at least once
- fired: function() {
- return !!fired;
- }
- };
-
- return self;
-};
-
-
-jQuery.extend({
-
- Deferred: function( func ) {
- var tuples = [
- // action, add listener, listener list, final state
- [ "resolve", "done", jQuery.Callbacks("once memory"), "resolved" ],
- [ "reject", "fail", jQuery.Callbacks("once memory"), "rejected" ],
- [ "notify", "progress", jQuery.Callbacks("memory") ]
- ],
- state = "pending",
- promise = {
- state: function() {
- return state;
- },
- always: function() {
- deferred.done( arguments ).fail( arguments );
- return this;
- },
- then: function( /* fnDone, fnFail, fnProgress */ ) {
- var fns = arguments;
- return jQuery.Deferred(function( newDefer ) {
- jQuery.each( tuples, function( i, tuple ) {
- var fn = jQuery.isFunction( fns[ i ] ) && fns[ i ];
- // deferred[ done | fail | progress ] for forwarding actions to newDefer
- deferred[ tuple[1] ](function() {
- var returned = fn && fn.apply( this, arguments );
- if ( returned && jQuery.isFunction( returned.promise ) ) {
- returned.promise()
- .done( newDefer.resolve )
- .fail( newDefer.reject )
- .progress( newDefer.notify );
- } else {
- newDefer[ tuple[ 0 ] + "With" ]( this === promise ? newDefer.promise() : this, fn ? [ returned ] : arguments );
- }
- });
- });
- fns = null;
- }).promise();
- },
- // Get a promise for this deferred
- // If obj is provided, the promise aspect is added to the object
- promise: function( obj ) {
- return obj != null ? jQuery.extend( obj, promise ) : promise;
- }
- },
- deferred = {};
-
- // Keep pipe for back-compat
- promise.pipe = promise.then;
-
- // Add list-specific methods
- jQuery.each( tuples, function( i, tuple ) {
- var list = tuple[ 2 ],
- stateString = tuple[ 3 ];
-
- // promise[ done | fail | progress ] = list.add
- promise[ tuple[1] ] = list.add;
-
- // Handle state
- if ( stateString ) {
- list.add(function() {
- // state = [ resolved | rejected ]
- state = stateString;
-
- // [ reject_list | resolve_list ].disable; progress_list.lock
- }, tuples[ i ^ 1 ][ 2 ].disable, tuples[ 2 ][ 2 ].lock );
- }
-
- // deferred[ resolve | reject | notify ]
- deferred[ tuple[0] ] = function() {
- deferred[ tuple[0] + "With" ]( this === deferred ? promise : this, arguments );
- return this;
- };
- deferred[ tuple[0] + "With" ] = list.fireWith;
- });
-
- // Make the deferred a promise
- promise.promise( deferred );
-
- // Call given func if any
- if ( func ) {
- func.call( deferred, deferred );
- }
-
- // All done!
- return deferred;
- },
-
- // Deferred helper
- when: function( subordinate /* , ..., subordinateN */ ) {
- var i = 0,
- resolveValues = slice.call( arguments ),
- length = resolveValues.length,
-
- // the count of uncompleted subordinates
- remaining = length !== 1 || ( subordinate && jQuery.isFunction( subordinate.promise ) ) ? length : 0,
-
- // the master Deferred. If resolveValues consist of only a single Deferred, just use that.
- deferred = remaining === 1 ? subordinate : jQuery.Deferred(),
-
- // Update function for both resolve and progress values
- updateFunc = function( i, contexts, values ) {
- return function( value ) {
- contexts[ i ] = this;
- values[ i ] = arguments.length > 1 ? slice.call( arguments ) : value;
- if ( values === progressValues ) {
- deferred.notifyWith( contexts, values );
-
- } else if ( !(--remaining) ) {
- deferred.resolveWith( contexts, values );
- }
- };
- },
-
- progressValues, progressContexts, resolveContexts;
-
- // add listeners to Deferred subordinates; treat others as resolved
- if ( length > 1 ) {
- progressValues = new Array( length );
- progressContexts = new Array( length );
- resolveContexts = new Array( length );
- for ( ; i < length; i++ ) {
- if ( resolveValues[ i ] && jQuery.isFunction( resolveValues[ i ].promise ) ) {
- resolveValues[ i ].promise()
- .done( updateFunc( i, resolveContexts, resolveValues ) )
- .fail( deferred.reject )
- .progress( updateFunc( i, progressContexts, progressValues ) );
- } else {
- --remaining;
- }
- }
- }
-
- // if we're not waiting on anything, resolve the master
- if ( !remaining ) {
- deferred.resolveWith( resolveContexts, resolveValues );
- }
-
- return deferred.promise();
- }
-});
-
-
-// The deferred used on DOM ready
-var readyList;
-
-jQuery.fn.ready = function( fn ) {
- // Add the callback
- jQuery.ready.promise().done( fn );
-
- return this;
-};
-
-jQuery.extend({
- // Is the DOM ready to be used? Set to true once it occurs.
- isReady: false,
-
- // A counter to track how many items to wait for before
- // the ready event fires. See #6781
- readyWait: 1,
-
- // Hold (or release) the ready event
- holdReady: function( hold ) {
- if ( hold ) {
- jQuery.readyWait++;
- } else {
- jQuery.ready( true );
- }
- },
-
- // Handle when the DOM is ready
- ready: function( wait ) {
-
- // Abort if there are pending holds or we're already ready
- if ( wait === true ? --jQuery.readyWait : jQuery.isReady ) {
- return;
- }
-
- // Make sure body exists, at least, in case IE gets a little overzealous (ticket #5443).
- if ( !document.body ) {
- return setTimeout( jQuery.ready );
- }
-
- // Remember that the DOM is ready
- jQuery.isReady = true;
-
- // If a normal DOM Ready event fired, decrement, and wait if need be
- if ( wait !== true && --jQuery.readyWait > 0 ) {
- return;
- }
-
- // If there are functions bound, to execute
- readyList.resolveWith( document, [ jQuery ] );
-
- // Trigger any bound ready events
- if ( jQuery.fn.triggerHandler ) {
- jQuery( document ).triggerHandler( "ready" );
- jQuery( document ).off( "ready" );
- }
- }
-});
-
-/**
- * Clean-up method for dom ready events
- */
-function detach() {
- if ( document.addEventListener ) {
- document.removeEventListener( "DOMContentLoaded", completed, false );
- window.removeEventListener( "load", completed, false );
-
- } else {
- document.detachEvent( "onreadystatechange", completed );
- window.detachEvent( "onload", completed );
- }
-}
-
-/**
- * The ready event handler and self cleanup method
- */
-function completed() {
- // readyState === "complete" is good enough for us to call the dom ready in oldIE
- if ( document.addEventListener || event.type === "load" || document.readyState === "complete" ) {
- detach();
- jQuery.ready();
- }
-}
-
-jQuery.ready.promise = function( obj ) {
- if ( !readyList ) {
-
- readyList = jQuery.Deferred();
-
- // Catch cases where $(document).ready() is called after the browser event has already occurred.
- // we once tried to use readyState "interactive" here, but it caused issues like the one
- // discovered by ChrisS here: http://bugs.jquery.com/ticket/12282#comment:15
- if ( document.readyState === "complete" ) {
- // Handle it asynchronously to allow scripts the opportunity to delay ready
- setTimeout( jQuery.ready );
-
- // Standards-based browsers support DOMContentLoaded
- } else if ( document.addEventListener ) {
- // Use the handy event callback
- document.addEventListener( "DOMContentLoaded", completed, false );
-
- // A fallback to window.onload, that will always work
- window.addEventListener( "load", completed, false );
-
- // If IE event model is used
- } else {
- // Ensure firing before onload, maybe late but safe also for iframes
- document.attachEvent( "onreadystatechange", completed );
-
- // A fallback to window.onload, that will always work
- window.attachEvent( "onload", completed );
-
- // If IE and not a frame
- // continually check to see if the document is ready
- var top = false;
-
- try {
- top = window.frameElement == null && document.documentElement;
- } catch(e) {}
-
- if ( top && top.doScroll ) {
- (function doScrollCheck() {
- if ( !jQuery.isReady ) {
-
- try {
- // Use the trick by Diego Perini
- // http://javascript.nwbox.com/IEContentLoaded/
- top.doScroll("left");
- } catch(e) {
- return setTimeout( doScrollCheck, 50 );
- }
-
- // detach all dom ready events
- detach();
-
- // and execute any waiting functions
- jQuery.ready();
- }
- })();
- }
- }
- }
- return readyList.promise( obj );
-};
-
-
-var strundefined = typeof undefined;
-
-
-
-// Support: IE<9
-// Iteration over object's inherited properties before its own
-var i;
-for ( i in jQuery( support ) ) {
- break;
-}
-support.ownLast = i !== "0";
-
-// Note: most support tests are defined in their respective modules.
-// false until the test is run
-support.inlineBlockNeedsLayout = false;
-
-// Execute ASAP in case we need to set body.style.zoom
-jQuery(function() {
- // Minified: var a,b,c,d
- var val, div, body, container;
-
- body = document.getElementsByTagName( "body" )[ 0 ];
- if ( !body || !body.style ) {
- // Return for frameset docs that don't have a body
- return;
- }
-
- // Setup
- div = document.createElement( "div" );
- container = document.createElement( "div" );
- container.style.cssText = "position:absolute;border:0;width:0;height:0;top:0;left:-9999px";
- body.appendChild( container ).appendChild( div );
-
- if ( typeof div.style.zoom !== strundefined ) {
- // Support: IE<8
- // Check if natively block-level elements act like inline-block
- // elements when setting their display to 'inline' and giving
- // them layout
- div.style.cssText = "display:inline;margin:0;border:0;padding:1px;width:1px;zoom:1";
-
- support.inlineBlockNeedsLayout = val = div.offsetWidth === 3;
- if ( val ) {
- // Prevent IE 6 from affecting layout for positioned elements #11048
- // Prevent IE from shrinking the body in IE 7 mode #12869
- // Support: IE<8
- body.style.zoom = 1;
- }
- }
-
- body.removeChild( container );
-});
-
-
-
-
-(function() {
- var div = document.createElement( "div" );
-
- // Execute the test only if not already executed in another module.
- if (support.deleteExpando == null) {
- // Support: IE<9
- support.deleteExpando = true;
- try {
- delete div.test;
- } catch( e ) {
- support.deleteExpando = false;
- }
- }
-
- // Null elements to avoid leaks in IE.
- div = null;
-})();
-
-
-/**
- * Determines whether an object can have data
- */
-jQuery.acceptData = function( elem ) {
- var noData = jQuery.noData[ (elem.nodeName + " ").toLowerCase() ],
- nodeType = +elem.nodeType || 1;
-
- // Do not set data on non-element DOM nodes because it will not be cleared (#8335).
- return nodeType !== 1 && nodeType !== 9 ?
- false :
-
- // Nodes accept data unless otherwise specified; rejection can be conditional
- !noData || noData !== true && elem.getAttribute("classid") === noData;
-};
-
-
-var rbrace = /^(?:\{[\w\W]*\}|\[[\w\W]*\])$/,
- rmultiDash = /([A-Z])/g;
-
-function dataAttr( elem, key, data ) {
- // If nothing was found internally, try to fetch any
- // data from the HTML5 data-* attribute
- if ( data === undefined && elem.nodeType === 1 ) {
-
- var name = "data-" + key.replace( rmultiDash, "-$1" ).toLowerCase();
-
- data = elem.getAttribute( name );
-
- if ( typeof data === "string" ) {
- try {
- data = data === "true" ? true :
- data === "false" ? false :
- data === "null" ? null :
- // Only convert to a number if it doesn't change the string
- +data + "" === data ? +data :
- rbrace.test( data ) ? jQuery.parseJSON( data ) :
- data;
- } catch( e ) {}
-
- // Make sure we set the data so it isn't changed later
- jQuery.data( elem, key, data );
-
- } else {
- data = undefined;
- }
- }
-
- return data;
-}
-
-// checks a cache object for emptiness
-function isEmptyDataObject( obj ) {
- var name;
- for ( name in obj ) {
-
- // if the public data object is empty, the private is still empty
- if ( name === "data" && jQuery.isEmptyObject( obj[name] ) ) {
- continue;
- }
- if ( name !== "toJSON" ) {
- return false;
- }
- }
-
- return true;
-}
-
-function internalData( elem, name, data, pvt /* Internal Use Only */ ) {
- if ( !jQuery.acceptData( elem ) ) {
- return;
- }
-
- var ret, thisCache,
- internalKey = jQuery.expando,
-
- // We have to handle DOM nodes and JS objects differently because IE6-7
- // can't GC object references properly across the DOM-JS boundary
- isNode = elem.nodeType,
-
- // Only DOM nodes need the global jQuery cache; JS object data is
- // attached directly to the object so GC can occur automatically
- cache = isNode ? jQuery.cache : elem,
-
- // Only defining an ID for JS objects if its cache already exists allows
- // the code to shortcut on the same path as a DOM node with no cache
- id = isNode ? elem[ internalKey ] : elem[ internalKey ] && internalKey;
-
- // Avoid doing any more work than we need to when trying to get data on an
- // object that has no data at all
- if ( (!id || !cache[id] || (!pvt && !cache[id].data)) && data === undefined && typeof name === "string" ) {
- return;
- }
-
- if ( !id ) {
- // Only DOM nodes need a new unique ID for each element since their data
- // ends up in the global cache
- if ( isNode ) {
- id = elem[ internalKey ] = deletedIds.pop() || jQuery.guid++;
- } else {
- id = internalKey;
- }
- }
-
- if ( !cache[ id ] ) {
- // Avoid exposing jQuery metadata on plain JS objects when the object
- // is serialized using JSON.stringify
- cache[ id ] = isNode ? {} : { toJSON: jQuery.noop };
- }
-
- // An object can be passed to jQuery.data instead of a key/value pair; this gets
- // shallow copied over onto the existing cache
- if ( typeof name === "object" || typeof name === "function" ) {
- if ( pvt ) {
- cache[ id ] = jQuery.extend( cache[ id ], name );
- } else {
- cache[ id ].data = jQuery.extend( cache[ id ].data, name );
- }
- }
-
- thisCache = cache[ id ];
-
- // jQuery data() is stored in a separate object inside the object's internal data
- // cache in order to avoid key collisions between internal data and user-defined
- // data.
- if ( !pvt ) {
- if ( !thisCache.data ) {
- thisCache.data = {};
- }
-
- thisCache = thisCache.data;
- }
-
- if ( data !== undefined ) {
- thisCache[ jQuery.camelCase( name ) ] = data;
- }
-
- // Check for both converted-to-camel and non-converted data property names
- // If a data property was specified
- if ( typeof name === "string" ) {
-
- // First Try to find as-is property data
- ret = thisCache[ name ];
-
- // Test for null|undefined property data
- if ( ret == null ) {
-
- // Try to find the camelCased property
- ret = thisCache[ jQuery.camelCase( name ) ];
- }
- } else {
- ret = thisCache;
- }
-
- return ret;
-}
-
-function internalRemoveData( elem, name, pvt ) {
- if ( !jQuery.acceptData( elem ) ) {
- return;
- }
-
- var thisCache, i,
- isNode = elem.nodeType,
-
- // See jQuery.data for more information
- cache = isNode ? jQuery.cache : elem,
- id = isNode ? elem[ jQuery.expando ] : jQuery.expando;
-
- // If there is already no cache entry for this object, there is no
- // purpose in continuing
- if ( !cache[ id ] ) {
- return;
- }
-
- if ( name ) {
-
- thisCache = pvt ? cache[ id ] : cache[ id ].data;
-
- if ( thisCache ) {
-
- // Support array or space separated string names for data keys
- if ( !jQuery.isArray( name ) ) {
-
- // try the string as a key before any manipulation
- if ( name in thisCache ) {
- name = [ name ];
- } else {
-
- // split the camel cased version by spaces unless a key with the spaces exists
- name = jQuery.camelCase( name );
- if ( name in thisCache ) {
- name = [ name ];
- } else {
- name = name.split(" ");
- }
- }
- } else {
- // If "name" is an array of keys...
- // When data is initially created, via ("key", "val") signature,
- // keys will be converted to camelCase.
- // Since there is no way to tell _how_ a key was added, remove
- // both plain key and camelCase key. #12786
- // This will only penalize the array argument path.
- name = name.concat( jQuery.map( name, jQuery.camelCase ) );
- }
-
- i = name.length;
- while ( i-- ) {
- delete thisCache[ name[i] ];
- }
-
- // If there is no data left in the cache, we want to continue
- // and let the cache object itself get destroyed
- if ( pvt ? !isEmptyDataObject(thisCache) : !jQuery.isEmptyObject(thisCache) ) {
- return;
- }
- }
- }
-
- // See jQuery.data for more information
- if ( !pvt ) {
- delete cache[ id ].data;
-
- // Don't destroy the parent cache unless the internal data object
- // had been the only thing left in it
- if ( !isEmptyDataObject( cache[ id ] ) ) {
- return;
- }
- }
-
- // Destroy the cache
- if ( isNode ) {
- jQuery.cleanData( [ elem ], true );
-
- // Use delete when supported for expandos or `cache` is not a window per isWindow (#10080)
- /* jshint eqeqeq: false */
- } else if ( support.deleteExpando || cache != cache.window ) {
- /* jshint eqeqeq: true */
- delete cache[ id ];
-
- // When all else fails, null
- } else {
- cache[ id ] = null;
- }
-}
-
-jQuery.extend({
- cache: {},
-
- // The following elements (space-suffixed to avoid Object.prototype collisions)
- // throw uncatchable exceptions if you attempt to set expando properties
- noData: {
- "applet ": true,
- "embed ": true,
- // ...but Flash objects (which have this classid) *can* handle expandos
- "object ": "clsid:D27CDB6E-AE6D-11cf-96B8-444553540000"
- },
-
- hasData: function( elem ) {
- elem = elem.nodeType ? jQuery.cache[ elem[jQuery.expando] ] : elem[ jQuery.expando ];
- return !!elem && !isEmptyDataObject( elem );
- },
-
- data: function( elem, name, data ) {
- return internalData( elem, name, data );
- },
-
- removeData: function( elem, name ) {
- return internalRemoveData( elem, name );
- },
-
- // For internal use only.
- _data: function( elem, name, data ) {
- return internalData( elem, name, data, true );
- },
-
- _removeData: function( elem, name ) {
- return internalRemoveData( elem, name, true );
- }
-});
-
-jQuery.fn.extend({
- data: function( key, value ) {
- var i, name, data,
- elem = this[0],
- attrs = elem && elem.attributes;
-
- // Special expections of .data basically thwart jQuery.access,
- // so implement the relevant behavior ourselves
-
- // Gets all values
- if ( key === undefined ) {
- if ( this.length ) {
- data = jQuery.data( elem );
-
- if ( elem.nodeType === 1 && !jQuery._data( elem, "parsedAttrs" ) ) {
- i = attrs.length;
- while ( i-- ) {
-
- // Support: IE11+
- // The attrs elements can be null (#14894)
- if ( attrs[ i ] ) {
- name = attrs[ i ].name;
- if ( name.indexOf( "data-" ) === 0 ) {
- name = jQuery.camelCase( name.slice(5) );
- dataAttr( elem, name, data[ name ] );
- }
- }
- }
- jQuery._data( elem, "parsedAttrs", true );
- }
- }
-
- return data;
- }
-
- // Sets multiple values
- if ( typeof key === "object" ) {
- return this.each(function() {
- jQuery.data( this, key );
- });
- }
-
- return arguments.length > 1 ?
-
- // Sets one value
- this.each(function() {
- jQuery.data( this, key, value );
- }) :
-
- // Gets one value
- // Try to fetch any internally stored data first
- elem ? dataAttr( elem, key, jQuery.data( elem, key ) ) : undefined;
- },
-
- removeData: function( key ) {
- return this.each(function() {
- jQuery.removeData( this, key );
- });
- }
-});
-
-
-jQuery.extend({
- queue: function( elem, type, data ) {
- var queue;
-
- if ( elem ) {
- type = ( type || "fx" ) + "queue";
- queue = jQuery._data( elem, type );
-
- // Speed up dequeue by getting out quickly if this is just a lookup
- if ( data ) {
- if ( !queue || jQuery.isArray(data) ) {
- queue = jQuery._data( elem, type, jQuery.makeArray(data) );
- } else {
- queue.push( data );
- }
- }
- return queue || [];
- }
- },
-
- dequeue: function( elem, type ) {
- type = type || "fx";
-
- var queue = jQuery.queue( elem, type ),
- startLength = queue.length,
- fn = queue.shift(),
- hooks = jQuery._queueHooks( elem, type ),
- next = function() {
- jQuery.dequeue( elem, type );
- };
-
- // If the fx queue is dequeued, always remove the progress sentinel
- if ( fn === "inprogress" ) {
- fn = queue.shift();
- startLength--;
- }
-
- if ( fn ) {
-
- // Add a progress sentinel to prevent the fx queue from being
- // automatically dequeued
- if ( type === "fx" ) {
- queue.unshift( "inprogress" );
- }
-
- // clear up the last queue stop function
- delete hooks.stop;
- fn.call( elem, next, hooks );
- }
-
- if ( !startLength && hooks ) {
- hooks.empty.fire();
- }
- },
-
- // not intended for public consumption - generates a queueHooks object, or returns the current one
- _queueHooks: function( elem, type ) {
- var key = type + "queueHooks";
- return jQuery._data( elem, key ) || jQuery._data( elem, key, {
- empty: jQuery.Callbacks("once memory").add(function() {
- jQuery._removeData( elem, type + "queue" );
- jQuery._removeData( elem, key );
- })
- });
- }
-});
-
-jQuery.fn.extend({
- queue: function( type, data ) {
- var setter = 2;
-
- if ( typeof type !== "string" ) {
- data = type;
- type = "fx";
- setter--;
- }
-
- if ( arguments.length < setter ) {
- return jQuery.queue( this[0], type );
- }
-
- return data === undefined ?
- this :
- this.each(function() {
- var queue = jQuery.queue( this, type, data );
-
- // ensure a hooks for this queue
- jQuery._queueHooks( this, type );
-
- if ( type === "fx" && queue[0] !== "inprogress" ) {
- jQuery.dequeue( this, type );
- }
- });
- },
- dequeue: function( type ) {
- return this.each(function() {
- jQuery.dequeue( this, type );
- });
- },
- clearQueue: function( type ) {
- return this.queue( type || "fx", [] );
- },
- // Get a promise resolved when queues of a certain type
- // are emptied (fx is the type by default)
- promise: function( type, obj ) {
- var tmp,
- count = 1,
- defer = jQuery.Deferred(),
- elements = this,
- i = this.length,
- resolve = function() {
- if ( !( --count ) ) {
- defer.resolveWith( elements, [ elements ] );
- }
- };
-
- if ( typeof type !== "string" ) {
- obj = type;
- type = undefined;
- }
- type = type || "fx";
-
- while ( i-- ) {
- tmp = jQuery._data( elements[ i ], type + "queueHooks" );
- if ( tmp && tmp.empty ) {
- count++;
- tmp.empty.add( resolve );
- }
- }
- resolve();
- return defer.promise( obj );
- }
-});
-var pnum = (/[+-]?(?:\d*\.|)\d+(?:[eE][+-]?\d+|)/).source;
-
-var cssExpand = [ "Top", "Right", "Bottom", "Left" ];
-
-var isHidden = function( elem, el ) {
- // isHidden might be called from jQuery#filter function;
- // in that case, element will be second argument
- elem = el || elem;
- return jQuery.css( elem, "display" ) === "none" || !jQuery.contains( elem.ownerDocument, elem );
- };
-
-
-
-// Multifunctional method to get and set values of a collection
-// The value/s can optionally be executed if it's a function
-var access = jQuery.access = function( elems, fn, key, value, chainable, emptyGet, raw ) {
- var i = 0,
- length = elems.length,
- bulk = key == null;
-
- // Sets many values
- if ( jQuery.type( key ) === "object" ) {
- chainable = true;
- for ( i in key ) {
- jQuery.access( elems, fn, i, key[i], true, emptyGet, raw );
- }
-
- // Sets one value
- } else if ( value !== undefined ) {
- chainable = true;
-
- if ( !jQuery.isFunction( value ) ) {
- raw = true;
- }
-
- if ( bulk ) {
- // Bulk operations run against the entire set
- if ( raw ) {
- fn.call( elems, value );
- fn = null;
-
- // ...except when executing function values
- } else {
- bulk = fn;
- fn = function( elem, key, value ) {
- return bulk.call( jQuery( elem ), value );
- };
- }
- }
-
- if ( fn ) {
- for ( ; i < length; i++ ) {
- fn( elems[i], key, raw ? value : value.call( elems[i], i, fn( elems[i], key ) ) );
- }
- }
- }
-
- return chainable ?
- elems :
-
- // Gets
- bulk ?
- fn.call( elems ) :
- length ? fn( elems[0], key ) : emptyGet;
-};
-var rcheckableType = (/^(?:checkbox|radio)$/i);
-
-
-
-(function() {
- // Minified: var a,b,c
- var input = document.createElement( "input" ),
- div = document.createElement( "div" ),
- fragment = document.createDocumentFragment();
-
- // Setup
- div.innerHTML = "
a";
-
- // IE strips leading whitespace when .innerHTML is used
- support.leadingWhitespace = div.firstChild.nodeType === 3;
-
- // Make sure that tbody elements aren't automatically inserted
- // IE will insert them into empty tables
- support.tbody = !div.getElementsByTagName( "tbody" ).length;
-
- // Make sure that link elements get serialized correctly by innerHTML
- // This requires a wrapper element in IE
- support.htmlSerialize = !!div.getElementsByTagName( "link" ).length;
-
- // Makes sure cloning an html5 element does not cause problems
- // Where outerHTML is undefined, this still works
- support.html5Clone =
- document.createElement( "nav" ).cloneNode( true ).outerHTML !== "<:nav>";
-
- // Check if a disconnected checkbox will retain its checked
- // value of true after appended to the DOM (IE6/7)
- input.type = "checkbox";
- input.checked = true;
- fragment.appendChild( input );
- support.appendChecked = input.checked;
-
- // Make sure textarea (and checkbox) defaultValue is properly cloned
- // Support: IE6-IE11+
- div.innerHTML = "";
- support.noCloneChecked = !!div.cloneNode( true ).lastChild.defaultValue;
-
- // #11217 - WebKit loses check when the name is after the checked attribute
- fragment.appendChild( div );
- div.innerHTML = "";
-
- // Support: Safari 5.1, iOS 5.1, Android 4.x, Android 2.3
- // old WebKit doesn't clone checked state correctly in fragments
- support.checkClone = div.cloneNode( true ).cloneNode( true ).lastChild.checked;
-
- // Support: IE<9
- // Opera does not clone events (and typeof div.attachEvent === undefined).
- // IE9-10 clones events bound via attachEvent, but they don't trigger with .click()
- support.noCloneEvent = true;
- if ( div.attachEvent ) {
- div.attachEvent( "onclick", function() {
- support.noCloneEvent = false;
- });
-
- div.cloneNode( true ).click();
- }
-
- // Execute the test only if not already executed in another module.
- if (support.deleteExpando == null) {
- // Support: IE<9
- support.deleteExpando = true;
- try {
- delete div.test;
- } catch( e ) {
- support.deleteExpando = false;
- }
- }
-})();
-
-
-(function() {
- var i, eventName,
- div = document.createElement( "div" );
-
- // Support: IE<9 (lack submit/change bubble), Firefox 23+ (lack focusin event)
- for ( i in { submit: true, change: true, focusin: true }) {
- eventName = "on" + i;
-
- if ( !(support[ i + "Bubbles" ] = eventName in window) ) {
- // Beware of CSP restrictions (https://developer.mozilla.org/en/Security/CSP)
- div.setAttribute( eventName, "t" );
- support[ i + "Bubbles" ] = div.attributes[ eventName ].expando === false;
- }
- }
-
- // Null elements to avoid leaks in IE.
- div = null;
-})();
-
-
-var rformElems = /^(?:input|select|textarea)$/i,
- rkeyEvent = /^key/,
- rmouseEvent = /^(?:mouse|pointer|contextmenu)|click/,
- rfocusMorph = /^(?:focusinfocus|focusoutblur)$/,
- rtypenamespace = /^([^.]*)(?:\.(.+)|)$/;
-
-function returnTrue() {
- return true;
-}
-
-function returnFalse() {
- return false;
-}
-
-function safeActiveElement() {
- try {
- return document.activeElement;
- } catch ( err ) { }
-}
-
-/*
- * Helper functions for managing events -- not part of the public interface.
- * Props to Dean Edwards' addEvent library for many of the ideas.
- */
-jQuery.event = {
-
- global: {},
-
- add: function( elem, types, handler, data, selector ) {
- var tmp, events, t, handleObjIn,
- special, eventHandle, handleObj,
- handlers, type, namespaces, origType,
- elemData = jQuery._data( elem );
-
- // Don't attach events to noData or text/comment nodes (but allow plain objects)
- if ( !elemData ) {
- return;
- }
-
- // Caller can pass in an object of custom data in lieu of the handler
- if ( handler.handler ) {
- handleObjIn = handler;
- handler = handleObjIn.handler;
- selector = handleObjIn.selector;
- }
-
- // Make sure that the handler has a unique ID, used to find/remove it later
- if ( !handler.guid ) {
- handler.guid = jQuery.guid++;
- }
-
- // Init the element's event structure and main handler, if this is the first
- if ( !(events = elemData.events) ) {
- events = elemData.events = {};
- }
- if ( !(eventHandle = elemData.handle) ) {
- eventHandle = elemData.handle = function( e ) {
- // Discard the second event of a jQuery.event.trigger() and
- // when an event is called after a page has unloaded
- return typeof jQuery !== strundefined && (!e || jQuery.event.triggered !== e.type) ?
- jQuery.event.dispatch.apply( eventHandle.elem, arguments ) :
- undefined;
- };
- // Add elem as a property of the handle fn to prevent a memory leak with IE non-native events
- eventHandle.elem = elem;
- }
-
- // Handle multiple events separated by a space
- types = ( types || "" ).match( rnotwhite ) || [ "" ];
- t = types.length;
- while ( t-- ) {
- tmp = rtypenamespace.exec( types[t] ) || [];
- type = origType = tmp[1];
- namespaces = ( tmp[2] || "" ).split( "." ).sort();
-
- // There *must* be a type, no attaching namespace-only handlers
- if ( !type ) {
- continue;
- }
-
- // If event changes its type, use the special event handlers for the changed type
- special = jQuery.event.special[ type ] || {};
-
- // If selector defined, determine special event api type, otherwise given type
- type = ( selector ? special.delegateType : special.bindType ) || type;
-
- // Update special based on newly reset type
- special = jQuery.event.special[ type ] || {};
-
- // handleObj is passed to all event handlers
- handleObj = jQuery.extend({
- type: type,
- origType: origType,
- data: data,
- handler: handler,
- guid: handler.guid,
- selector: selector,
- needsContext: selector && jQuery.expr.match.needsContext.test( selector ),
- namespace: namespaces.join(".")
- }, handleObjIn );
-
- // Init the event handler queue if we're the first
- if ( !(handlers = events[ type ]) ) {
- handlers = events[ type ] = [];
- handlers.delegateCount = 0;
-
- // Only use addEventListener/attachEvent if the special events handler returns false
- if ( !special.setup || special.setup.call( elem, data, namespaces, eventHandle ) === false ) {
- // Bind the global event handler to the element
- if ( elem.addEventListener ) {
- elem.addEventListener( type, eventHandle, false );
-
- } else if ( elem.attachEvent ) {
- elem.attachEvent( "on" + type, eventHandle );
- }
- }
- }
-
- if ( special.add ) {
- special.add.call( elem, handleObj );
-
- if ( !handleObj.handler.guid ) {
- handleObj.handler.guid = handler.guid;
- }
- }
-
- // Add to the element's handler list, delegates in front
- if ( selector ) {
- handlers.splice( handlers.delegateCount++, 0, handleObj );
- } else {
- handlers.push( handleObj );
- }
-
- // Keep track of which events have ever been used, for event optimization
- jQuery.event.global[ type ] = true;
- }
-
- // Nullify elem to prevent memory leaks in IE
- elem = null;
- },
-
- // Detach an event or set of events from an element
- remove: function( elem, types, handler, selector, mappedTypes ) {
- var j, handleObj, tmp,
- origCount, t, events,
- special, handlers, type,
- namespaces, origType,
- elemData = jQuery.hasData( elem ) && jQuery._data( elem );
-
- if ( !elemData || !(events = elemData.events) ) {
- return;
- }
-
- // Once for each type.namespace in types; type may be omitted
- types = ( types || "" ).match( rnotwhite ) || [ "" ];
- t = types.length;
- while ( t-- ) {
- tmp = rtypenamespace.exec( types[t] ) || [];
- type = origType = tmp[1];
- namespaces = ( tmp[2] || "" ).split( "." ).sort();
-
- // Unbind all events (on this namespace, if provided) for the element
- if ( !type ) {
- for ( type in events ) {
- jQuery.event.remove( elem, type + types[ t ], handler, selector, true );
- }
- continue;
- }
-
- special = jQuery.event.special[ type ] || {};
- type = ( selector ? special.delegateType : special.bindType ) || type;
- handlers = events[ type ] || [];
- tmp = tmp[2] && new RegExp( "(^|\\.)" + namespaces.join("\\.(?:.*\\.|)") + "(\\.|$)" );
-
- // Remove matching events
- origCount = j = handlers.length;
- while ( j-- ) {
- handleObj = handlers[ j ];
-
- if ( ( mappedTypes || origType === handleObj.origType ) &&
- ( !handler || handler.guid === handleObj.guid ) &&
- ( !tmp || tmp.test( handleObj.namespace ) ) &&
- ( !selector || selector === handleObj.selector || selector === "**" && handleObj.selector ) ) {
- handlers.splice( j, 1 );
-
- if ( handleObj.selector ) {
- handlers.delegateCount--;
- }
- if ( special.remove ) {
- special.remove.call( elem, handleObj );
- }
- }
- }
-
- // Remove generic event handler if we removed something and no more handlers exist
- // (avoids potential for endless recursion during removal of special event handlers)
- if ( origCount && !handlers.length ) {
- if ( !special.teardown || special.teardown.call( elem, namespaces, elemData.handle ) === false ) {
- jQuery.removeEvent( elem, type, elemData.handle );
- }
-
- delete events[ type ];
- }
- }
-
- // Remove the expando if it's no longer used
- if ( jQuery.isEmptyObject( events ) ) {
- delete elemData.handle;
-
- // removeData also checks for emptiness and clears the expando if empty
- // so use it instead of delete
- jQuery._removeData( elem, "events" );
- }
- },
-
- trigger: function( event, data, elem, onlyHandlers ) {
- var handle, ontype, cur,
- bubbleType, special, tmp, i,
- eventPath = [ elem || document ],
- type = hasOwn.call( event, "type" ) ? event.type : event,
- namespaces = hasOwn.call( event, "namespace" ) ? event.namespace.split(".") : [];
-
- cur = tmp = elem = elem || document;
-
- // Don't do events on text and comment nodes
- if ( elem.nodeType === 3 || elem.nodeType === 8 ) {
- return;
- }
-
- // focus/blur morphs to focusin/out; ensure we're not firing them right now
- if ( rfocusMorph.test( type + jQuery.event.triggered ) ) {
- return;
- }
-
- if ( type.indexOf(".") >= 0 ) {
- // Namespaced trigger; create a regexp to match event type in handle()
- namespaces = type.split(".");
- type = namespaces.shift();
- namespaces.sort();
- }
- ontype = type.indexOf(":") < 0 && "on" + type;
-
- // Caller can pass in a jQuery.Event object, Object, or just an event type string
- event = event[ jQuery.expando ] ?
- event :
- new jQuery.Event( type, typeof event === "object" && event );
-
- // Trigger bitmask: & 1 for native handlers; & 2 for jQuery (always true)
- event.isTrigger = onlyHandlers ? 2 : 3;
- event.namespace = namespaces.join(".");
- event.namespace_re = event.namespace ?
- new RegExp( "(^|\\.)" + namespaces.join("\\.(?:.*\\.|)") + "(\\.|$)" ) :
- null;
-
- // Clean up the event in case it is being reused
- event.result = undefined;
- if ( !event.target ) {
- event.target = elem;
- }
-
- // Clone any incoming data and prepend the event, creating the handler arg list
- data = data == null ?
- [ event ] :
- jQuery.makeArray( data, [ event ] );
-
- // Allow special events to draw outside the lines
- special = jQuery.event.special[ type ] || {};
- if ( !onlyHandlers && special.trigger && special.trigger.apply( elem, data ) === false ) {
- return;
- }
-
- // Determine event propagation path in advance, per W3C events spec (#9951)
- // Bubble up to document, then to window; watch for a global ownerDocument var (#9724)
- if ( !onlyHandlers && !special.noBubble && !jQuery.isWindow( elem ) ) {
-
- bubbleType = special.delegateType || type;
- if ( !rfocusMorph.test( bubbleType + type ) ) {
- cur = cur.parentNode;
- }
- for ( ; cur; cur = cur.parentNode ) {
- eventPath.push( cur );
- tmp = cur;
- }
-
- // Only add window if we got to document (e.g., not plain obj or detached DOM)
- if ( tmp === (elem.ownerDocument || document) ) {
- eventPath.push( tmp.defaultView || tmp.parentWindow || window );
- }
- }
-
- // Fire handlers on the event path
- i = 0;
- while ( (cur = eventPath[i++]) && !event.isPropagationStopped() ) {
-
- event.type = i > 1 ?
- bubbleType :
- special.bindType || type;
-
- // jQuery handler
- handle = ( jQuery._data( cur, "events" ) || {} )[ event.type ] && jQuery._data( cur, "handle" );
- if ( handle ) {
- handle.apply( cur, data );
- }
-
- // Native handler
- handle = ontype && cur[ ontype ];
- if ( handle && handle.apply && jQuery.acceptData( cur ) ) {
- event.result = handle.apply( cur, data );
- if ( event.result === false ) {
- event.preventDefault();
- }
- }
- }
- event.type = type;
-
- // If nobody prevented the default action, do it now
- if ( !onlyHandlers && !event.isDefaultPrevented() ) {
-
- if ( (!special._default || special._default.apply( eventPath.pop(), data ) === false) &&
- jQuery.acceptData( elem ) ) {
-
- // Call a native DOM method on the target with the same name name as the event.
- // Can't use an .isFunction() check here because IE6/7 fails that test.
- // Don't do default actions on window, that's where global variables be (#6170)
- if ( ontype && elem[ type ] && !jQuery.isWindow( elem ) ) {
-
- // Don't re-trigger an onFOO event when we call its FOO() method
- tmp = elem[ ontype ];
-
- if ( tmp ) {
- elem[ ontype ] = null;
- }
-
- // Prevent re-triggering of the same event, since we already bubbled it above
- jQuery.event.triggered = type;
- try {
- elem[ type ]();
- } catch ( e ) {
- // IE<9 dies on focus/blur to hidden element (#1486,#12518)
- // only reproducible on winXP IE8 native, not IE9 in IE8 mode
- }
- jQuery.event.triggered = undefined;
-
- if ( tmp ) {
- elem[ ontype ] = tmp;
- }
- }
- }
- }
-
- return event.result;
- },
-
- dispatch: function( event ) {
-
- // Make a writable jQuery.Event from the native event object
- event = jQuery.event.fix( event );
-
- var i, ret, handleObj, matched, j,
- handlerQueue = [],
- args = slice.call( arguments ),
- handlers = ( jQuery._data( this, "events" ) || {} )[ event.type ] || [],
- special = jQuery.event.special[ event.type ] || {};
-
- // Use the fix-ed jQuery.Event rather than the (read-only) native event
- args[0] = event;
- event.delegateTarget = this;
-
- // Call the preDispatch hook for the mapped type, and let it bail if desired
- if ( special.preDispatch && special.preDispatch.call( this, event ) === false ) {
- return;
- }
-
- // Determine handlers
- handlerQueue = jQuery.event.handlers.call( this, event, handlers );
-
- // Run delegates first; they may want to stop propagation beneath us
- i = 0;
- while ( (matched = handlerQueue[ i++ ]) && !event.isPropagationStopped() ) {
- event.currentTarget = matched.elem;
-
- j = 0;
- while ( (handleObj = matched.handlers[ j++ ]) && !event.isImmediatePropagationStopped() ) {
-
- // Triggered event must either 1) have no namespace, or
- // 2) have namespace(s) a subset or equal to those in the bound event (both can have no namespace).
- if ( !event.namespace_re || event.namespace_re.test( handleObj.namespace ) ) {
-
- event.handleObj = handleObj;
- event.data = handleObj.data;
-
- ret = ( (jQuery.event.special[ handleObj.origType ] || {}).handle || handleObj.handler )
- .apply( matched.elem, args );
-
- if ( ret !== undefined ) {
- if ( (event.result = ret) === false ) {
- event.preventDefault();
- event.stopPropagation();
- }
- }
- }
- }
- }
-
- // Call the postDispatch hook for the mapped type
- if ( special.postDispatch ) {
- special.postDispatch.call( this, event );
- }
-
- return event.result;
- },
-
- handlers: function( event, handlers ) {
- var sel, handleObj, matches, i,
- handlerQueue = [],
- delegateCount = handlers.delegateCount,
- cur = event.target;
-
- // Find delegate handlers
- // Black-hole SVG