How to add custom entities

pyshotgrid will return any “unknown” entity as “SGEntity” instance to provide minimum functionality in all cases. However sometimes you might want to add or extend some functions on entities to make your live easier. pyshotgrid lets you do that, by registering your custom classes to its setup. Here is an example python script to illustrate what you have to do:

example_custom_entity.py
 1"""
 2Add a custom entity to pyshotgrid.
 3
 4This script illustrates how you can integrate a custom entity into the pyshotgrid universe.
 5
 6Suppose you are using a custom entity called "Episode" which collects shots and sequences in
 7projects. It would be nice if pyshotgrid could reflect that and help you get some information
 8faster. Furthermore it would be nice if the default SGProject class would get an additional
 9function that returns all episodes of the project.
10
11Here is what you have to do:
12"""
13import fnmatch
14
15import pyshotgrid as pysg
16
17
18# Create a class that inherits from "SGEntity" and all the functionality you want to it.
19# In this example we only add a function to get shots from the episode.
20class SGEpisode(pysg.SGEntity):
21    """
22    An instance of this class represents a single Episode entity in Flow Production Tracking.
23    """
24
25    DEFAULT_SG_ENTITY_TYPE = 'CustomProjectEntity01'
26
27    # This is an example implementation of how to retrieve shots from an episode.
28    def shots(self, glob_pattern=None):
29        """
30        :param str|None glob_pattern: A glob to match the shots to return. For example
31                                      `TEST_01_*` would return all shots that start with `TEST_01_`.
32        :return: All the shots from this project.
33        :rtype: list[SGShot]
34        """
35        sg_shots = self.sg.find('Shot',
36                                # NOTE: The "sg_episode" field is only made up and
37                                # could differ from your setup.
38                                [['sg_episode', 'is', self.to_dict()]],
39                                ['code'])
40        if glob_pattern is not None:
41            return [pysg.new_entity(self._sg, sg_shot)
42                    for sg_shot in sg_shots
43                    if fnmatch.fnmatchcase(sg_shot['code'], glob_pattern)]
44        else:
45            return [pysg.new_entity(self._sg, sg_shot) for sg_shot in sg_shots]
46
47
48# To overwrite/add some functionality to one of the default classes you simply inherit from
49# that class and overwrite/add what you deem necessary.
50# In this case we add a very simple function to return all episodes attached to the current project.
51class CustomSGProject(pysg.sg_default_entities.SGProject):
52    """
53    Custom extension of the default SGProject class to provide additional functionality.
54    """
55
56    def episodes(self):
57        """
58        :return: All episodes of this project.
59        :rtype: list[SGEpisode]
60        """
61        # We simple return all entities from the "sg_episodes" field.
62        # NOTE: This field is made up and could differ depending on your setup.
63        return self['sg_episodes'].get()
64
65
66# To let pyshotgrid know about your custom classes you need to register them like so:
67# This will let pyshotgrid return a SGEpisode instance whenever it encounters
68# a "CustomProjectEntity01" entity.
69pysg.register_pysg_class(SGEpisode)
70
71# This will let pyshotgrid return a CustomSGProject instance whenever it encounters
72# "Project" entity and therefore we overwrite the default behaviour for all new Project instances.
73pysg.register_pysg_class(CustomSGProject)
74
75
76# Here is a small example of the above implementations.
77if __name__ == '__main__':
78
79    # connect to a Flow Production Tracking site
80    site = pysg.new_site(base_url='https://example.shotgunstudio.com',
81                         script_name='Some User',
82                         api_key='$ome_password')
83
84    # Get the "test" project
85    project = site.project('test')
86    # Get all episodes of that project.
87    sg_episodes = project.episodes()
88    # List the first shot of the first episode.
89    print(sg_episodes[0].shots()[0])