sgsession¶

This Python package is a wrapper around shotgun_api3 for Shotgun which provides a local data cache and some additional intelligence on top of bare entities.
This has been crafted to mimick the normal interface, and graft extra features on top. Howveer, this is not a drop-in replacement for the normal API. While any individual entity in isolation should behave in the same way as with the normal API, the entities are linked behind the scenes and so complex behaviour is likely to break.
Contents¶
Overview¶
Getting Started¶
All you must do to start using sgsession
is to construct a Session
with an existing Shotgun instance:
>>> from shotgun_api3 import Shotgun
>>> from sgsession import Session
>>> session = Session(Shotgun(*shotgun_args))
From then on you can use the session
as you would have used the Shotgun instance itself.
The Entity¶
The primary representation of Shotgun entities is the Entity
class, which extends the familiar dictionary with more Shotgun specific methods and a link back to the session for fetching more fields, parents, etc..
Instance Sharing¶
The same Entity
instance will always be returned for the same conceptual instance. E.g.:
>>> a = session.find_one('Task', [('code', 'is', 'AA_001')])
>>> b = session.find_one('Task', [('code', 'is', 'AA_001')])
>>> a is b
True
Caching, Merging, and Backrefs¶
Entities will be cached for the lifetime of their Session
, and any new information about them will be merged in as it is encountered.
For example, fields fetched in subsequent queries to the server will be availible on earlier found entities:
>>> a = session.find_one('Task', [('code', 'is', 'AA_001')])
>>> 'sg_status_list' in a
False
>>> b = session.find_one('Task', [('code', 'is', 'AA_001')], ['sg_status_list'])
>>> a['sg_status_list']
'fin'
Deep-linked fields will also be merged into the main scope of the linked entities for easy referral:
>>> x = session.find_one('Task', [], ['entity.Shot.code'])
>>> x['entity']['code']
'AA_001'
Links to other entities will automatically populate backrefs on the remote side of the link, allowing for entities to easily find there they have been linked from:
>>> task = session.find_one('Task', [], ['entity'])
>>> shot = task['entity']
>>> task in shot.backrefs[('Task', 'entity')]
True
Important Fields¶
Several fields will always be queried for whenever you operate on entities. These include Shot.code
, Task.step
, and project
on many types. When availible, deep-linked fields will also be fetched, including Task.entity.Shot.code
, so even single simple queries will return lots of related data:
>>> x = session.find_one('Task', [])
>>> x.pprint()
Task:456 at 0x101577a20; {
entity = Shot:234 at 0x101541a80; {
code = 'AA_001'
name = 'AA_001'
project = Project:123 at 0x101561f30; {
name = 'Demo Project'
}
}
project = Project:123 at 0x101561f30; ...
sg_status_list = 'fin'
step = Step:345 at 0x10155b5e0; {
code = 'Matchmove'
entity_type = 'Shot'
name = 'Matchmove'
short_name = 'Matchmove'
}
}
Brace Expansion¶
During a find
or find_one
, return fields can be specified with brace
expansions to allow for a more compact representation of complex links:
>>> session.find('Task', [], ['entity.{Asset,Shot}.{name,code}'])
Efficient Heirarchies¶
Ever have a list of tasks that you need to know the full heirarchy for all the way up to the project? With any number of tasks, you can get all of the important fields for the full heirarchy in no more than 3 requests:
>>> tasks = session.find('Task', some_filters)
>>> all_entities = session.fetch_heirarchy(tasks)
all_entities
is a list of every entity above those tasks, and every entity has been linked and backreffed to each other.
sgsession.Session
¶
The Session is a wrapper around a Shotgun instance, proxying requests to the server and applying additional logic on top of it. The Session instance is designed to be used for a single task and then discarded, since it makes the assumption that entity relationships do not change.
While not fully documented below, this object will proxy all attributes to the underlying Shotgun instance, so you can treat this as you would a Shotgun instance.
-
class
sgsession.session.
Session
(shotgun=None, schema=None, *args, **kwargs)¶ Shotgun wrapper.
Parameters: shotgun – A Shotgun instance to wrap, or the name to be passed to shotgun_api3_registry.connect()
in order to construct one.If passed a name, the remaining args and kwargs will also be passed to the api registry connector.
If passed a descendant of
shotgun_api3.Shotgun
(or one is constructed via the registry), it will be wrapped in aShotgunPool
so that it becomes thread-safe. Any other objects (e.g. mock servers) are used unmodified.
Entity Control¶
-
Session.
merge
(data, over=None, created_at=None, resolve=True)¶ Import data containing raw entities into the session.
This will effectively return a copy of any nested structure of lists, tuples, and dicts, while converting any dicts which look like entities into an
Entity
. The returned structure is a copy of the original.Parameters: Returns: The
Entity
. This will not be a new instance if the entity was already in the session, but it will have all the newly merged data in it.
-
Session.
get
(*args, **kwargs)¶ Get one entity by type and ID.
Parameters:
-
Session.
filter_exists
(*args, **kwargs)¶ Return the subset of given entities which exist (non-retired).
Parameters: Returns set: The entities which exist, or aren’t sure about.
This will handle multiple entity-types in multiple requests.
Fetching Fields¶
-
Session.
fetch
(*args, **kwargs)¶ Fetch the named fields on the given entities.
Parameters: This will safely handle multiple entitiy types at the same time, and by default will only make requests of the server if some of the data does not already exist.
Note
This does not assert that all “important” fields exist. See
fetch_core()
.
-
Session.
fetch_core
(*args, **kwargs)¶ Assert all “important” fields exist, and fetch them if they do not.
Parameters: to_fetch (list) – The entities to get the core fields on. - This will populate all important fields, and important fields on linked
- entities.
-
Session.
fetch_backrefs
(*args, **kwargs)¶ Fetch requested backrefs on the given entities.
Parameters: # Find all tasks which refer to this shot. >>> session.fetch_backrefs([shot], 'Task', 'entity')
-
Session.
fetch_heirarchy
(*args, **kwargs)¶ Populate the parents as far up as we can go, and return all involved.
With (new-ish) arbitrarily-deep-links on Shotgun, this method could be made quite a bit more effiecient, since it should be able to request the entire heirarchy for any given type at once.
See
parent_fields
.
Importance Controls¶
These class attributes control which fields are considered “important”, which types are potentially linked to by various fields, and which types are considered the parent of other types.
-
Session.
important_fields_for_all
= ['updated_at']¶
-
Session.
important_fields
= {'Project': ['name'], 'Step': ['code', 'short_name', 'entity_type'], 'Task': ['step', 'content'], 'Shot': ['code'], 'Asset': ['code', 'sg_asset_type'], 'Sequence': ['code'], 'Version': ['code', 'sg_task'], 'HumanUser': ['firstname', 'lastname', 'email', 'login'], 'PublishEvent': ['code', 'sg_type', 'sg_version']}¶
-
Session.
important_links
= {'PublishEvent': {'project': ['Project'], 'sg_link': ['Task']}, 'Task': {'project': ['Project'], 'step': ['Step'], 'entity': ['Asset', 'Shot']}, 'Shot': {'project': ['Project'], 'sg_sequence': ['Sequence']}, 'Asset': {'project': ['Project']}, 'Sequence': {'project': ['Project']}}¶
-
Session.
parent_fields
= {'Task': 'entity', 'Shot': 'sg_sequence', 'Sequence': 'project', 'Project': None, 'Version': 'entity', 'Asset': 'project', 'PublishEvent': 'sg_link'}¶
Wrapped Methods¶
-
Session.
create
(*args, **kwargs)¶ Create an entity of the given type and data.
Returns: The new Entity
.
-
Session.
update
(*args, **kwargs)¶ Update the given entity with the given fields.
Todo
Add this to the Entity.
-
Session.
delete
(*args, **kwargs)¶ Delete one entity.
Warning
This session will not forget about the deleted entity, and all links from other entities will remain intact.
-
Session.
batch
(*args, **kwargs)¶ Perform a series of requests in a transaction.
sgsession.Entity
¶
-
class
sgsession.entity.
Entity
(type_, id_, session)¶ A Shotgun entity.
This behaves much like the
dict
the Shotgun API normally returns does, but understands the links bettween entities in its associated session.
Entity Management¶
-
Entity.
as_dict
()¶ Return the entity and all linked entities as pure
dict
.The first reference to an entity will have all availible fields, and any subsequent ones will be the minimal representation. This is the ideal format for serialization and remerging into a session.
-
Entity.
pprint
(backrefs=None, depth=0)¶ Print this entity, all links and optional backrefs.
-
Entity.
exists
(*args, **kwargs)¶ Determine if this entity still exists (non-retired) on the server.
Parameters: Returns bool: True/False if it is known to exist or not, and None if we do not know.
See
Session.filter_exists()
for the bulk version.
Retrieving Data¶
-
Entity.
get
(*args, **kwargs)¶ Get field value(s) if they exist, otherwise a default.
Parameters: - fields – A
str
field name or collection ofstr
field names. - default – Default value to return when field does not exist.
If passed a single field name as a
str
, return the coresponding value. If passed field names as a list or tuple, return a tuple of coresponding values.- fields – A
-
Entity.
fetch
(*args, **kwargs)¶ Get field value(s), automatically fetching them from the server.
Parameters: - fields – A
str
field name or collection ofstr
field names. - default – Default value to return when field does not exist.
- force (bool) – Force an update from the server, otherwise only query they server if fields have been requested that we do not already have.
If passed a single field name as a
str
, return the coresponding value. If passed field names as a list or tuple, return a tuple of coresponding values.See
Session.fetch()
for the bulk version.- fields – A
-
Entity.
fetch_core
(*args, **kwargs)¶ Assert that all “important” fields exist on this Entity.
See
Session.fetch_core()
for the bulk version.
-
Entity.
fetch_backrefs
(*args, **kwargs)¶ Fetch all backrefs to this Entity from the given type and field.
See
Session.fetch_backrefs()
for the bulk version.
-
Entity.
fetch_heirarchy
(*args, **kwargs)¶ Fetch the full upward heirarchy (toward the Project) from the server.
See
Session.fetch_heirarchy()
for the bulk version.
Heirarchy¶
-
Entity.
parent
(*args, **kwargs)¶ Get the parent of this Entity, automatically fetching from the server.
-
Entity.
project
(*args, **kwargs)¶ Get the project of this Entity, automatically fetching from the server.
Depending on what part of the heirarchy is already loaded, many more entities will have their Project fetched by this single call.
sgsession.ShotgunPool
¶
A wrapper around shotgun_api3
to allow for parallel requests.
The standard Shotgun API uses a connection object that serialized requests. Therefore, efficient usage in a multi-threaded environment is tricker than it could be. Ergo, this module was concieved.
ShotgunPool
is a connection pool that creates fresh Shotgun instances
when needed, and recycles old ones after use. It proxies attributes and
methods to the managed instances. An actual Shotgun instance should never leak
out of this object, so even passing around bound methods from this object
should be safe.
E.g.:
>>> # Construct and wrap a Shotgun instance.
>>> shotgun = Shotgun(...)
>>> shotgun = ShotgunPool(shotgun)
>>>
>>> # Use it like normal, except in parallel.
>>> shotgun.find('Task', ...)
-
class
sgsession.pool.
ShotgunPool
(prototype, *args, **kwargs)¶ Shotgun connection pool.
Parameters: prototype – Shotgun instance to use as a prototype, OR the base_url
to be used to construct a prototype.If passed a
base_url
, the remaining args and kwargs will be passed to the Shotgun constructor for creation of a prototype.The
config
object of the prototype will be shared amoung all Shotgun instances created; changing the settings on one Shotgun instance (or this object) will affect all other instances.