diff --git a/README.md b/README.md index 50b97f64e..9f4741877 100644 --- a/README.md +++ b/README.md @@ -53,6 +53,10 @@ Integration and unit tests are provided. ## Changelog +**v3.0.18 - 2015 Mar 13** + + + Add ability to query the per-project visibility status for entities, fields and statuses. (requires Shotgun server >= v5.4.4) + **v3.0.17 - 2014 Jul 10** + Add ability to update last_accessed_by_current_user on Project. diff --git a/setup.py b/setup.py index b4c8b2fc6..3871c16bf 100644 --- a/setup.py +++ b/setup.py @@ -17,7 +17,7 @@ setup( name='shotgun_api3', - version='3.0.17', + version='3.0.18', description='Shotgun Python API ', long_description=readme, author='Shotgun Software', diff --git a/shotgun_api3/shotgun.py b/shotgun_api3/shotgun.py index 4af9729d0..a540a67cb 100755 --- a/shotgun_api3/shotgun.py +++ b/shotgun_api3/shotgun.py @@ -75,7 +75,7 @@ # ---------------------------------------------------------------------------- # Version -__version__ = "3.0.18.dev" +__version__ = "3.0.18" # ---------------------------------------------------------------------------- # Errors @@ -945,23 +945,47 @@ def followers(self, entity): return self._call_rpc('followers', params) - def schema_entity_read(self): + def schema_entity_read(self, project_entity=None): """Gets all active entities defined in the schema. + :param dict project_entity: Optional, if set, each field's visibility is reported accordingly + to the specified project's current visibility settings. + If None, all fields are reported as visible. + :returns: dict of Entity Type to dict containing the display name. """ - return self._call_rpc("schema_entity_read", None) + params = {} + + if project_entity: + params["project"] = project_entity - def schema_read(self): + if params: + return self._call_rpc("schema_entity_read", params) + else: + return self._call_rpc("schema_entity_read", None) + + def schema_read(self, project_entity=None): """Gets the schema for all fields in all entities. + :param dict project_entity: Optional, if set, each field's visibility is reported accordingly + to the specified project's current visibility settings. + If None, all fields are reported as visible. + :returns: nested dicts """ - return self._call_rpc("schema_read", None) + params = {} + + if project_entity: + params["project"] = project_entity - def schema_field_read(self, entity_type, field_name=None): + if params: + return self._call_rpc("schema_read", params) + else: + return self._call_rpc("schema_read", None) + + def schema_field_read(self, entity_type, field_name=None, project_entity=None): """Gets all schema for fields in the specified entity_type or one field. @@ -972,14 +996,20 @@ def schema_field_read(self, entity_type, field_name=None): definition for. If not supplied all fields for the entity type are returned. + :param dict project_entity: Optional, if set, each field's visibility is reported accordingly + to the specified project's current visibility settings. + If None, all fields are reported as visible. + :returns: dict of field name to nested dicts which describe the field """ params = { - "type" : entity_type, + "type": entity_type, } if field_name: params["field_name"] = field_name + if project_entity: + params["project"] = project_entity return self._call_rpc("schema_field_read", params) diff --git a/tests/test_api_long.py b/tests/test_api_long.py index 2938a28a1..bab94af67 100644 --- a/tests/test_api_long.py +++ b/tests/test_api_long.py @@ -6,8 +6,9 @@ import base import random + class TestShotgunApiLong(base.LiveTestBase): - + def test_automated_find(self): """Called find for each entity type and read all fields""" all_entities = self.sg.schema_entity_read().keys() @@ -25,36 +26,35 @@ def test_automated_find(self): if not fields: print "No fields for %s skipping" % (entity_type,) continue - - #trying to use some different code paths to the other find test - #TODO for our test project, we haven't populated these entities.... + + # trying to use some different code paths to the other find test + # TODO for our test project, we haven't populated these entities.... order = [{'field_name': fields.keys()[0], 'direction': direction}] if "project" in fields: filters = [['project', 'is', self.project]] else: filters = [] - records = self.sg.find(entity_type, filters, fields=fields.keys(), + records = self.sg.find(entity_type, filters, fields=fields.keys(), order=order, filter_operator=filter_operator, limit=limit, page=page) - + self.assertTrue(isinstance(records, list)) - + if filter_operator == "all": filter_operator = "any" - else: + else: filter_operator = "all" if direction == "desc": direction = "asc" - else: + else: direction = "desc" limit = (limit % 5) + 1 page = (page % 3) + 1 - def test_schema(self): """Called schema functions""" - + schema = self.sg.schema_entity_read() self.assertTrue(schema, dict) self.assertTrue(len(schema) > 0) @@ -62,20 +62,20 @@ def test_schema(self): schema = self.sg.schema_read() self.assertTrue(schema, dict) self.assertTrue(len(schema) > 0) - + schema = self.sg.schema_field_read("Version") self.assertTrue(schema, dict) self.assertTrue(len(schema) > 0) - + schema = self.sg.schema_field_read("Version", field_name="user") self.assertTrue(schema, dict) self.assertTrue(len(schema) > 0) self.assertTrue("user" in schema) - # An explantion is in order here. the field code that is created in shotgun is based on the human display name + # An explanation is in order here. the field code that is created in shotgun is based on the human display name # that is provided , so for example "Money Count" would generate the field code 'sg_monkey_count' . The field # that is created in this test is retired at the end of the test but when this test is run again against - # the same database ( which happens on our Continous Integration server ) trying to create a new field + # the same database ( which happens on our Continuous Integration server ) trying to create a new field # called "Monkey Count" will now fail due to the new Delete Field Forever features we have added to shotgun # since there will a retired field called sg_monkey_count. The old behavior was to go ahead and create a new # "Monkey Count" field with a field code with an incremented number of the end like sg_monkey_count_1. The new @@ -87,15 +87,44 @@ def test_schema(self): properties = { "description" : "How many monkeys were needed" } new_field_name = self.sg.schema_field_create("Version", "number", human_field_name, properties=properties) - - properties = {"description" : "How many monkeys turned up"} + + properties = {"description": "How many monkeys turned up"} ret_val = self.sg.schema_field_update("Version", - new_field_name, - properties) + new_field_name, + properties) self.assertTrue(ret_val) - + ret_val = self.sg.schema_field_delete("Version", new_field_name) self.assertTrue(ret_val) - -if __name__ == '__main__': + + def test_schema_with_project(self): + """Called schema functions""" + + project_entity = {'type': 'Project', 'id': 0} + schema = self.sg.schema_entity_read(project_entity) + self.assertTrue(schema, dict) + self.assertTrue(len(schema) > 0) + self.assertTrue('Project' in schema) + self.assertTrue('visible' in schema['Project']) + + schema = self.sg.schema_read(project_entity) + self.assertTrue(schema, dict) + self.assertTrue(len(schema) > 0) + self.assertTrue('Version' in schema) + self.assertFalse('visible' in schema.keys()) + + schema = self.sg.schema_field_read('Version', project_entity=project_entity) + self.assertTrue(schema, dict) + self.assertTrue(len(schema) > 0) + self.assertTrue('user' in schema) + self.assertTrue('visible' in schema['user']) + + schema = self.sg.schema_field_read('Version', 'user', project_entity) + self.assertTrue(schema, dict) + self.assertTrue(len(schema) > 0) + self.assertTrue('user' in schema) + self.assertTrue('visible' in schema['user']) + + +if __name__ == '__main__': base.unittest.main()