[PYTHON] Think about how to write a filter with the Shotgun API-Contact Versions

What is this?

I would like to use the Shotgun API to get information about the "Versions" entity.

Premise

Based on the flow so far http://qiita.com/it_ks/items/e026f61fb8c3683ac035

--Shotgun API installed in Python environment --Script user created on Shotgun

I would like to start from that point.

Versions entity

In Shotgun terms, the deliverables (videos / images, including the middle) that are submitted when receiving reviews or reporting progress to clients are called "versions". (By the way, the delimiter that the worker puts at the appropriate work stage is retained by the name "snapshot") The former is managed / shared by uploading it to the cloud, but the latter is a kind of worker's category or discretionary handling.

--Version to be checked = "Version" = To the cloud --In-worker version = "snapshot" = limited to hand

An entity is a data table on Shotgun. Various types such as Shot, Asset, and Task are available, and Version is one of them.

Use the schema_entity_read () method when examining an entity.

>>> sg.schema_entity_read().keys()
['Candidate', 'MocapTake', 'ActionMenuItem', 'Asset', 'Department', 'RevisionTicketConnection', 'Revision', 'CutVersionC
onnection', 'PublishedFileDependency', 'Step', 'MocapPass', 'Icon', 'Task', 'ApiUser', 'Launch', 'Ticket_sg_test_ticket_
to_task_Connection', 'Project', 'CutItem', 'LocalStorage', 'Release', 'LaunchSceneConnection', 'ReleaseTicketConnection'
, 'LaunchShotConnection', 'CustomEntity01', 'Shot', 'BannerUserConnection', 'AssetAssetConnection', 'EventLogEntry', 'As
setShootDayConnection', 'DeliveryTarget', 'PageSetting', 'Playlist', 'ShootDaySceneConnection', 'Camera', 'TankAction',
'Routine', 'Reply', 'AppWelcomeUserConnection', 'Attachment', 'Tool', 'TicketTicketConnection', 'PhysicalAssetMocapTakeC
onnection', 'Cut', 'Group', 'MocapSetup', 'Note', 'TaskDependency', 'PageHit', 'TemerityNode', 'Status', 'AssetElementCo
nnection', 'Slate', 'MocapTakeRangeShotConnection', 'TimeLog', 'ShootDay', 'AssetBlendshapeConnection', 'MocapTakeRange'
, 'PublishedFile', 'ProjectUserConnection', 'ShotShotConnection', 'PublishedFileType', 'TankType', 'TaskTemplate', 'Play
listShare', 'PerformerShootDayConnection', 'PipelineConfiguration', 'HumanUser', 'FilesystemLocation', 'Performer', 'Ver
sion', 'PhysicalAsset', 'ElementShotConnection', 'AssetSceneConnection', 'AssetMocapTakeConnection', 'PlaylistVersionCon
nection', 'Booking', 'PublishEvent', 'CameraMocapTakeConnection', 'Delivery', 'AssetLibrary', 'Phase', 'Ticket', 'AssetS
hotConnection', 'ClientUser', 'TankContainer', 'RvLicense', 'PerformerRoutineConnection', 'Element', 'PermissionRuleSet'
, 'Blendshape', 'GroupUserConnection', 'AssetSequenceConnection', 'Page', 'TankPublishedFile', 'Sequence', 'TankDependen
cy', 'Scene', 'PerformerMocapTakeConnection', 'RevisionRevisionConnection']

>>> len(sg.schema_entity_read().keys())
99

When I counted it, it returned "99", but if the entity name ends with "Connection", it is for linking entities, so you can ignore it. The number of Connection-type entities and "Custom Entity" varies depending on how you use them, so the number of 99 entities here is not fixed.

If you upload an image or video to the Versions entity, you can view it in the Media App.

find The most basic method to use for queries is find. If you want to check Versions for the time being without thinking about filters etc., you can write like this

sg.find('Version',[],[])

However, I think you should stop making this inquiry. If you don't filter anything, all ** versions including the ** sample project will be the target, so it will take some time just to get it. In actual use, it's best to use at least a filter that limits your project. In this article, we will consider how to filter, including that area.

find_one Since a large number of results will be returned without a filter, switch to the ** find_one ** method that returns only one result. While using this, let's think about how to filter.

>>> sg.find_one('Version',[],[])
{'type': 'Version', 'id': 2}

For both find and find_one, the third argument is "I want you to include it in the return value ** field **". If you don't specify anything, only type and id will be returned, as in the example sentence above.

schema_field_read() Use the schema_field_read () method to see what fields the entity has. Here we want to find out what fields the "Version" entity has, so Feeling like this sg.schema_field_read('Version').keys()

>>> sg.schema_field_read('Version').keys()
['sg_version_type', 'open_notes_count', 'code', 'playlists', 'sg_task', 'image', 'updated_at', 'sg_uploaded_movie_frame_
rate', 'sg_path_to_frames', 'tasks', 'sg_department', 'frame_range', 'client_approved', 'id', 'updated_by', 'sg_path_to_
movie', 'sg_uploaded_movie_webm', 'open_notes', 'client_approved_at', 'cached_display_name', 'task_template', 'created_b
y', 'sg_status_list', 'notes', 'sg_frames_aspect_ratio', 'sg_first_frame', 'sg_frames_have_slate', 'sg_uploaded_movie_mp
4', 'description', 'sg_uploaded_movie_image', 'media_center_import_time', 'viewed_by_current_user_at', 'client_code', 's
g_movie_has_slate', 'sg_uploaded_movie', 'user', 'entity', 'published_files', 'step_0', 'sg_last_frame', 'viewed_by_curr
ent_user', 'sg_uploaded_movie_transcoding_status', 'sg_movie_aspect_ratio', 'created_at', 'client_approved_by', 'project
', 'filmstrip_image', 'tag_list', 'frame_count', 'flagged']

By the way, the Version entity has as many fields as the Shot entity. field.png (Version is "50", shot is "63". It seems that it will increase or decrease with the version upgrade of shotgun itself)

Try filtering by "project"

Let's say you have a policy of "let's filter by project!".

Find out

First, let's check how the project information is written in the project field. Using find_one from earlier, I will make an inquiry like this.

sg.find_one('Version',[],['project'])

Then

>>> sg.find_one('Version',[],['project'])
{'project': {'type': 'Project', 'id': 65, 'name': 'Big Buck Bunny'}, 'type': 'Version', 'id': 2}

I found that the project data was written in the project field in the form of "{'type':'Project','id': 65,'name':'Big Buck Bunny'}".

If you pass this to the second argument of the find method, You should be able to inquire ** "Version belonging to the XX project" **.

Try it 1 (common mistake)

It's time to get all the results, so I'm going back to normal find instead of find_one. Using the project information obtained earlier as a filter, write it like this.

sg.find('Version',[{'type': 'Project', 'id': 65, 'name': 'Big Buck Bunny'}],[])

>>> sg.find('Version',[{'type': 'Project', 'id': 65, 'name': 'Big Buck Bunny'}],[])
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "C:\Users\~~\site-packages\shotgun_api3\shotgun.py", line 606, in find
    filters = _translate_filters(filters, filter_operator)
  File "C:\Users\~~\site-packages\shotgun_api3\shotgun.py", line 2646, in _translate_filters
    return _translate_filters_dict(wrapped_filters)
  File "C:\Users\~~\site-packages\shotgun_api3\shotgun.py", line 2662, in _translate_filters_dict
    new_filters["conditions"] = _translate_filters_list(sg_filter["filters"])
  File "C:\Users\~~\site-packages\shotgun_api3\shotgun.py", line 2673, in _translate_filters_list
    conditions.append(_translate_filters_dict(sg_filter))
  File "C:\Users\~~\site-packages\shotgun_api3\shotgun.py", line 2657, in _translate_filters_dict
    raise ShotgunError("Invalid filter_operator %s" % filter_operator)
shotgun_api3.shotgun.ShotgunError: Invalid filter_operator None

Even if you just push it into the filter, you will get an error like this. Filters have a unique way of writing.

How to write a filter

How to write a filter is officially summarized here

Reference: Filter Syntax https://github.com/shotgunsoftware/python-api/wiki/Reference:-Filter-Syntax

You can specify multiple filters at once. One filter will be a list of configurations as shown below

['{Field}','Relation','Value']

** Field ** is the field you want to use for sorting, which you got earlier with schema_field_read. Here it is'project'. (You can right-click the column on Shotgun (web) and select "Configure field ..." instead of schema_field_read.)

** Relation ** controls the behavior of filters such as "returns what corresponds to ..." and "returns what does not correspond". There are'is','is_not','contains','between' ... and so on. Here we use'is'.

** Value ** is the value used for the search. Here, there are various types for each ** type ** of the field. I will write after getting an example with find_one.

This list with 3 elements becomes one filter, and the ** double list ** that combines multiple of these becomes the filter notation.

** Single ** lists are only allowed if there is no filter Even if you think "specify only one filter", you need to make a double list. (There is also a more complicated way of specifying)

The filter this time looks like this.

[['project','is',{'type': 'Project', 'id': 65, 'name': 'Big Buck Bunny'}]]

Try it 2 (Limit the amount returned)

sg.find('Version',[['project','is',{'type': 'Project', 'id': 65, 'name': 'Big Buck Bunny'}]],[])

… Actually, a considerable number of versions are registered in the sample project “Big Buck Bunny”. You can specify the quantity of the return value with the limit argument.

sg.find('Version',[['project','is',{'type': 'Project', 'id': 65, 'name': 'Big Buck Bunny'}]],[],limit=10)
>>> sg.find('Version',[['project','is',{'type': 'Project', 'id': 65, 'name': 'Big Buck Bunny'}]],[],limit=10)
[{'type': 'Version', 'id': 2}, {'type': 'Version', 'id': 3}, {'type': 'Version', 'id': 4}, {'type': 'Version', 'id': 5},
 {'type': 'Version', 'id': 6}, {'type': 'Version', 'id': 7}, {'type': 'Version', 'id': 8}, {'type': 'Version', 'id': 9},
 {'type': 'Version', 'id': 10}, {'type': 'Version', 'id': 11}]

It's a shame, but about the project filter. Here, for the time being, I used the one obtained by find_one as it is, but In fact, it can be used for ** filtering without **'name'.

>> sg.find('Version',[['project','is',{'type': 'Project', 'id': 65}]],[],limit=10)
{'type': 'Version', 'id': 2}, {'type': 'Version', 'id': 3}, {'type': 'Version', 'id': 4}, {'type': 'Version', 'id': 5},
{'type': 'Version', 'id': 6}, {'type': 'Version', 'id': 7}, {'type': 'Version', 'id': 8}, {'type': 'Version', 'id': 9},
{'type': 'Version', 'id': 10}, {'type': 'Version', 'id': 11}]

Try it 3 (Get only the version attached to Shot)

Add something like the following to the previous filter.

['entity','type_is','Shot']

Now, the version where the "link" column in Shotgun (web) is linked to the shot, = You can only get the version for the shot.

>>> sg.find('Version',[['project','is',{'type': 'Project', 'id': 65}],['entity','type_is','Shot']],['entity'],limit=10)
[{'type': 'Version', 'id': 2, 'entity': {'type': 'Shot', 'id': 860, 'name': 'bunny_010_0010'}}, {'type': 'Version', 'id'
: 3, 'entity': {'type': 'Shot', 'id': 860, 'name': 'bunny_010_0010'}}, {'type': 'Version', 'id': 4, 'entity': {'type': '
Shot', 'id': 860, 'name': 'bunny_010_0010'}}, {'type': 'Version', 'id': 5, 'entity': {'type': 'Shot', 'id': 860, 'name':
 'bunny_010_0010'}}, {'type': 'Version', 'id': 6, 'entity': {'type': 'Shot', 'id': 860, 'name': 'bunny_010_0010'}}, {'ty
pe': 'Version', 'id': 7, 'entity': {'type': 'Shot', 'id': 860, 'name': 'bunny_010_0010'}}, {'type': 'Version', 'id': 8,
'entity': {'type': 'Shot', 'id': 860, 'name': 'bunny_010_0010'}}, {'type': 'Version', 'id': 9, 'entity': {'type': 'Shot'
, 'id': 860, 'name': 'bunny_010_0010'}}, {'type': 'Version', 'id': 10, 'entity': {'type': 'Shot', 'id': 860, 'name': 'bu
nny_010_0010'}}, {'type': 'Version', 'id': 11, 'entity': {'type': 'Shot', 'id': 860, 'name': 'bunny_010_0010'}}]

This is the version for Asset

>>> sg.find('Version',[['project','is',{'type': 'Project', 'id': 65}],['entity','type_is','Asset']],['entity'],limit=10)

[{'type': 'Version', 'id': 6002, 'entity': {'type': 'Asset', 'id': 726, 'name': 'Buck'}}]

linktype.png

Summary

Is it a version to an asset?

Recommended Posts

Think about how to write a filter with the Shotgun API-Contact Versions
A story about how to deal with the CORS problem
[Introduction to Python] How to write a character string with the format function
Think about how to program Python on the iPad
How to write a GUI using the maya command
How to create a submenu with the [Blender] plugin
How to display a list of installable versions with pyenv
How to write a Python class
[Introduction to Python] How to split a character string with the split function
How to make a command to read the configuration file with pyramid
Write a script to calculate the distance with Elasticsearch 5 system painless
How to write a docstring to create a named tuple document with sphinx
How to send a request to the DMM (FANZA) API with python
Qiita (1) How to write a code name
How to add a package with PyCharm
The 16th offline real-time how to write problem was solved with Python
[Python] Explains how to use the range function with a concrete example
The 16th offline real-time how to write reference problem to solve with Python
[Introduction to Python] How to sort the contents of a list efficiently with list sort
How to fix the initial population with a genetic algorithm using DEAP
The 19th offline real-time how to write reference problem to solve with Python
The 15th offline real-time how to write problem was solved with python
How to calculate the volatility of a brand
How to read a CSV file with Python 2/3
How to share a virtual environment [About requirements.txt]
Feel free to write a test with nose (in the case of + gevent)
How to send a message to LINE with curl
How to publish a blog on Amazon S3 with the static Blog engine'Pelican'for Pythonista
How to draw a 2-axis graph with pyplot
How to develop a cart app with Django
How to make a dictionary with a hierarchical structure.
How to try the friends-of-friends algorithm with pyfof
How to write a ShellScript Bash for statement
Save the object to a file with pickle
How to create a multi-platform app with kivy
[AWS] Wordpress How to deal with "The response is not a correct JSON response"
How to write a named tuple document in 2020
[Go] How to write or call a function
How to Learn Kaldi with the JUST Corpus
I want to write to a file with Python
How to write a ShellScript bash case statement
How to get a list of files in the same directory with python
[Introduction to Python] How to get the index of data with a for statement
How to set a shared folder with the host OS in CentOS7 on VirtualBOX
How to identify the element with the smallest number of characters in a Python list?
A story about how Windows 10 users created an environment to use OpenCV3 with Python 3.5
[Note] How to write QR code and description in the same image with python
A memo on how to overcome the difficult problem of capturing FX with AI
A less likely misunderstanding about how to specify a handler for a zip uploaded with Lambda
How to test the current time with Go (I made a very thin library)
The 15th offline real-time I tried to solve the problem of how to write with python
Read the Python-Markdown source: How to create a parser
How to convert / restore a string with [] in python
How to delete the specified string with the sed command! !! !!
[Python] How to draw a line graph with Matplotlib
[Introduction to Python] How to iterate with the range function?
How to get a logged-in user with Django's forms.py
How to convert a class object to a dictionary with SQLAlchemy
[Python] How to specify the download location with youtube-dl
How to make a shooting game with toio (Part 1)
How to write a list / dictionary type of Python3