def testRetAttributeNames( self ): testPairs = [ ( "Asset", "sg_linked_assets", "asset_sg_linked_assets_assets" ), ( "CustomEntity02", "sg_sink_tasks", "custom_entity02_sg_sink_tasks_custom_entity02s" ), ] for ( entityType, attrName, retAttrName ) in testPairs: retAttrNameTest = entityNaming.getReverseAttributeName( entityType, attrName ) self.assertEqual( retAttrNameTest, retAttrName )
def testRetAttributeNames(self): testPairs = [ ("Asset", "sg_linked_assets", "asset_sg_linked_assets_assets"), ("CustomEntity02", "sg_sink_tasks", "custom_entity02_sg_sink_tasks_custom_entity02s"), ] for (entityType, attrName, retAttrName) in testPairs: retAttrNameTest = entityNaming.getReverseAttributeName( entityType, attrName) self.assertEqual(retAttrNameTest, retAttrName)
def testLinkedAsset( self ): self.testasset.assets = [ self.linkedAsset ] self.testasset.save() # get connection objects from source connObj = factories.getConnectionObj( baseObj = self.testasset, linkedObj = self.linkedAsset, attribute = "assets" ) self.assertNotEqual( connObj, None ) # TODO: synch and check if not two connObj # self.assertTrue( self.local2shotgun.connectAndRun(), "synch not successful" ) connObj = factories.getConnectionObj( baseObj = self.testasset, linkedObj = self.linkedAsset, attribute = "assets" ) self.assertNotEqual( type( connObj ), list, "multiple connection objects after synch" ) # get attribute of reverse field reverseAttrName = entityNaming.getReverseAttributeName( "Asset", "assets" ) linkedAsset = factories.getObject( "Asset", local_id = self.linkedAsset.getLocalID() ) retLinks = linkedAsset.getField( reverseAttrName ) self.assertTrue( retLinks != None and self.testasset in retLinks ) # checking sync from shotgun to local self.assertTrue( self.shotgun2local.connectAndRun(), "synch not successful" ) connObj = factories.getConnectionObj( baseObj = self.testasset, linkedObj = self.linkedAsset, attribute = "assets" ) self.assertNotEqual( type( connObj ), list, "multiple connection objects after synch" ) # remove connection self.testasset.assets = [ ] self.testasset.save() connObj = factories.getConnectionObj( baseObj = self.testasset, linkedObj = self.linkedAsset, attribute = "assets" ) self.assertEqual( connObj, None ) linkedAsset = factories.getObject( "Asset", local_id = self.linkedAsset.getLocalID() ) retLinks = linkedAsset.getField( reverseAttrName ) self.assertEqual( retLinks, [] ) self.assertTrue( self.local2shotgun.connectAndRun(), "synch not successful" ) connObj = factories.getConnectionObj( baseObj = self.testasset, linkedObj = self.linkedAsset, attribute = "assets" ) self.assertEqual( connObj, None )
def changeEntity( myObj, changes ): """change entity in local database and add corresponding change-events for shotgun-sync""" # myObj.reload() src = connectors.DatabaseModificator() src.changeInDB( myObj, changes = changes ) for ( key, value ) in changes.iteritems(): if type( value ) == datetime.datetime: changes[key] = value.strftime( "%Y-%m-%d %H:%M:%S" ) if type( value ) == datetime.date: changes[key] = value.strftime( "%Y-%m-%d" ) elif type( value ) == datetime.timedelta: changes[key] = float( value.days ) * 24 + float( value.seconds ) / 3600 elif type( value ) == connectors.PostgresEntityType: changes[key] = value.getShortDict() elif isinstance( value, base_entity.ShotgunBaseEntity ): changes[key] = value.getShortDict() elif type( value ) == type( [] ): changes[key] = [] for entry in value: if isinstance( entry, base_entity.ShotgunBaseEntity ) or type( entry ) == connectors.PostgresEntityType: changes[key].append( entry.getShortDict() ) else: changes[key].append( entry ) attributeName = key fieldValues = value entityType = myObj.getType() connEntityName = entityNaming.getConnectionEntityName( entityType, attributeName ) if connEntityName != None: reverseAttribute = entityNaming.getReverseAttributeName( entityType, attributeName ) linkedEntityType = myObj.shotgun_fields[attributeName]["properties"]["valid_types"]["value"][0] baseEntityType = entityType ( baseAttrName, linkedAttrName ) = entityNaming.getConnectionEntityAttrName( baseEntityType, linkedEntityType, connEntityName ) basePgObj = myObj.getPgObj() # get connections filters = "%s=%s" % ( baseAttrName, "%s" ) filterValues = [ basePgObj ] connections = factories.getObjects( connEntityName, filters, filterValues ) # create new connection entities for linkedDict in changes[key]: linkedPostgresObj = getPgObj( linkedDict ) fieldNames = [ baseAttrName, linkedAttrName ] fieldValues = [ basePgObj, linkedPostgresObj ] # check if existing first connectionExists = False for i in range( len( connections ) ): connection = connections[i] if connection.getRawField( linkedAttrName ) == linkedPostgresObj: connections.remove( connection ) connectionExists = True break if not connectionExists: debug.debug( dict( zip( fieldNames, fieldValues ) ), prefix = "OOOOOOOOO" ) src._addToDatabase( connEntityName, fieldValues, fieldNames ) # setting reverse attribute as well linkedObj = factories.getObject( linkedDict["type"], local_id = linkedDict["__local_id"], remote_id = linkedDict["id"] ) retValues = linkedObj.getRawField( reverseAttribute ) if retValues == None: retValues = [] if basePgObj not in retValues: retValues.append( basePgObj ) src.changeInDB( linkedObj, reverseAttribute, retValues ) # delete unused connection entities for connection in connections: linkedObj = connection.getField( linkedAttrName ) retValues = linkedObj.getRawField( reverseAttribute ) retValues.remove( basePgObj ) src.changeInDB( linkedObj, reverseAttribute, retValues ) src.delete( connection ) _createChangeEvent( src, "change", corr_entity = myObj.getPgObj(), changed_values = json.dumps( changes ) ) return myObj
def changeEntity( myObj, changes ): """change entity in local database and add corresponding change-events for shotgun-sync""" # myObj.reload() src = connectors.DatabaseModificator() src.changeInDB( myObj, changes = changes ) for ( key, value ) in changes.iteritems(): if type( value ) == datetime.datetime: changes[key] = value.strftime( "%Y-%m-%d %H:%M:%S" ) if type( value ) == datetime.date: changes[key] = value.strftime( "%Y-%m-%d" ) elif type( value ) == datetime.timedelta: changes[key] = float( value.days ) * 24 + float( value.seconds ) / 3600 elif type( value ) == connectors.PostgresEntityType: changes[key] = value.getShortDict() elif isinstance( value, base_entity.ShotgunBaseEntity ): changes[key] = value.getShortDict() elif type( value ) == type( [] ): changes[key] = [] for entry in value: if isinstance( entry, base_entity.ShotgunBaseEntity ) or type( entry ) == connectors.PostgresEntityType: changes[key].append( entry.getShortDict() ) else: changes[key].append( entry ) attributeName = key fieldValues = value entityType = myObj.getType() connEntityName = entityNaming.getConnectionEntityName( entityType, attributeName ) if connEntityName != None: reverseAttribute = entityNaming.getReverseAttributeName( entityType, attributeName ) linkedEntityType = myObj.shotgun_fields[attributeName]["properties"]["valid_types"]["value"][0] baseEntityType = entityType ( baseAttrName, linkedAttrName ) = entityNaming.getConnectionEntityAttrName( baseEntityType, linkedEntityType, connEntityName ) basePgObj = myObj.getPgObj() # get connections filters = "%s=%s" % ( baseAttrName, "%s" ) filterValues = [ basePgObj ] connections = factories.getObjects( connEntityName, filters, filterValues ) # create new connection entities for linkedDict in changes[key]: linkedPostgresObj = getPgObj( linkedDict ) fieldNames = [ baseAttrName, linkedAttrName ] fieldValues = [ basePgObj, linkedPostgresObj ] # check if existing first connectionExists = False for i in range( len( connections ) ): connection = connections[i] if connection.getRawField( linkedAttrName ) == linkedPostgresObj: connections.remove( connection ) connectionExists = True break if not connectionExists: debug.debug( dict( zip( fieldNames, fieldValues ) ), prefix = "OOOOOOOOO" ) src._addToDatabase( connEntityName, fieldValues, fieldNames ) # setting reverse attribute as well linkedObj = factories.getObject( linkedDict["type"], local_id = linkedDict["__local_id"], remote_id = linkedDict["id"] ) retValues = linkedObj.getRawField( reverseAttribute ) if retValues == None: retValues = [] if basePgObj not in retValues: retValues.append( basePgObj ) src.changeInDB( linkedObj, reverseAttribute, retValues ) # delete unused connection entities for connection in connections: linkedObj = connection.getField( linkedAttrName ) retValues = linkedObj.getRawField( reverseAttribute ) retValues.remove( basePgObj ) src.changeInDB( linkedObj, reverseAttribute, retValues ) src.delete( connection ) _createChangeEvent( src, "change", corr_entity = myObj.getPgObj(), changed_values = json.dumps( changes ) ) return myObj
def testLinkedAsset(self): self.testasset.assets = [self.linkedAsset] self.testasset.save() # get connection objects from source connObj = factories.getConnectionObj(baseObj=self.testasset, linkedObj=self.linkedAsset, attribute="assets") self.assertNotEqual(connObj, None) # TODO: synch and check if not two connObj # self.assertTrue(self.local2shotgun.connectAndRun(), "synch not successful") connObj = factories.getConnectionObj(baseObj=self.testasset, linkedObj=self.linkedAsset, attribute="assets") self.assertNotEqual(type(connObj), list, "multiple connection objects after synch") # get attribute of reverse field reverseAttrName = entityNaming.getReverseAttributeName( "Asset", "assets") linkedAsset = factories.getObject( "Asset", local_id=self.linkedAsset.getLocalID()) retLinks = linkedAsset.getField(reverseAttrName) self.assertTrue(retLinks != None and self.testasset in retLinks) # checking sync from shotgun to local self.assertTrue(self.shotgun2local.connectAndRun(), "synch not successful") connObj = factories.getConnectionObj(baseObj=self.testasset, linkedObj=self.linkedAsset, attribute="assets") self.assertNotEqual(type(connObj), list, "multiple connection objects after synch") # remove connection self.testasset.assets = [] self.testasset.save() connObj = factories.getConnectionObj(baseObj=self.testasset, linkedObj=self.linkedAsset, attribute="assets") self.assertEqual(connObj, None) linkedAsset = factories.getObject( "Asset", local_id=self.linkedAsset.getLocalID()) retLinks = linkedAsset.getField(reverseAttrName) self.assertEqual(retLinks, []) self.assertTrue(self.local2shotgun.connectAndRun(), "synch not successful") connObj = factories.getConnectionObj(baseObj=self.testasset, linkedObj=self.linkedAsset, attribute="assets") self.assertEqual(connObj, None)
def testAddOutput(self): lastevent = self.sg.find( "EventLogEntry", filters=[], fields=['id', 'event_type', 'attribute_name', 'meta', 'entity'], order=[{ 'column': 'id', 'direction': 'desc' }], filter_operator='all', limit=1)[0] self.lastID = lastevent["id"] data = { "project": { "type": "Project", "id": testProjectID }, "code": "newoutput", "sg_link": { "type": "Task", "id": testTaskID }, } newOutputDict = self.sg.create(InOut().getType(), data, []) self.deleteEntities.append(newOutputDict) newevents = self._getNewEvents() self.assertEqual(newevents[0]["event_type"], "Shotgun_CustomEntity02_New", "event not as expected") self.assertEqual(newevents[1]["event_type"], "Shotgun_CustomEntity02_Change", "event not as expected") self.assertEqual(newevents[2]["event_type"], "Shotgun_CustomEntity02_Change", "event not as expected") self.assertEqual(newevents[3]["event_type"], "Shotgun_CustomEntity02_Change", "event not as expected") self._processEvents(newevents) newOutput = factories.getObject("CustomEntity02", remote_id=newOutputDict["id"]) changedData = { 'sg_sink_tasks': [ { "type": "Task", "id": testTaskID }, { "type": "Task", "id": testTaskID_2 }, ] } self.sg.update(newOutputDict["type"], newOutputDict["id"], changedData) newevents = self._getNewEvents() self.assertEqual(len(newevents), 5) self.assertEqual( newevents[0]["event_type"], "Shotgun_CustomEntity02_sg_sink_tasks_Connection_New") self.assertEqual( newevents[1]["event_type"], "Shotgun_CustomEntity02_sg_sink_tasks_Connection_New") self.assertEqual(newevents[2]["event_type"], "Shotgun_CustomEntity02_Change") self.assertEqual(newevents[3]["event_type"], "Shotgun_Task_Change") self.assertEqual(newevents[4]["event_type"], "Shotgun_Task_Change") self._processEvents(newevents) # check if Connection-Entities are available filters = "custom_entity02=%s and task=ANY(%s)" taskSgObj1 = PostgresEntityType("Task", remote_id=testTaskID) taskSgObj2 = PostgresEntityType("Task", remote_id=testTaskID_2) outputSgObj = PostgresEntityType(newOutputDict["type"], remote_id=newOutputDict["id"]) filterValues = [outputSgObj, [taskSgObj1, taskSgObj2]] connObjs = factories.getObjects( "CustomEntity02_sg_sink_tasks_Connection", filters, filterValues) self.assertEqual( len(connObjs), 2, "no conn-objs: %s" % pprint.pformat(connObjs, indent=2)) # check if return attribute of Task contains this CustomEntity02 retAttr = entityNaming.getReverseAttributeName("CustomEntity02", "sg_sink_tasks") for taskID in [testTaskID, testTaskID_2]: taskTmpObj = factories.getObject("Task", remote_id=taskID) retOutputs = taskTmpObj.__getattribute__(retAttr) self.assertTrue(newOutput in retOutputs) changedData["sg_sink_tasks"] = [] self.sg.update(newOutputDict["type"], newOutputDict["id"], changedData) newevents = self._getNewEvents() # unfortunately there are two events missing: # see: https://support.shotgunsoftware.com/requests/7380 self.assertEqual(len(newevents), 3) self.assertEqual(newevents[0]["event_type"], "Shotgun_CustomEntity02_Change") self.assertEqual(newevents[1]["event_type"], "Shotgun_Task_Change") self.assertEqual(newevents[2]["event_type"], "Shotgun_Task_Change") self._processEvents(newevents) retAttr = entityNaming.getReverseAttributeName("CustomEntity02", "sg_sink_tasks") for taskID in [testTaskID, testTaskID_2]: taskTmpObj = factories.getObject("Task", remote_id=taskID) retOutputs = taskTmpObj.__getattribute__(retAttr) if retOutputs: self.assertFalse(newOutput in retOutputs) # check if Connection-Entities are deleted connObjs = factories.getObjects( "CustomEntity02_sg_sink_tasks_Connection", filters, filterValues) self.assertEqual( len(connObjs), 0, "conn-objs still available: %s" % pprint.pformat(connObjs, indent=2))
def testAddOutput( self ): lastevent = self.sg.find( "EventLogEntry", filters = [], fields = ['id', 'event_type', 'attribute_name', 'meta', 'entity'], order = [{'column':'id', 'direction':'desc'}], filter_operator = 'all', limit = 1 )[0] self.lastID = lastevent["id"] data = { "project": {"type": "Project", "id": testProjectID }, "code": "newoutput", "sg_link": {"type": "Task", "id": testTaskID }, } newOutputDict = self.sg.create( InOut().getType(), data, [] ) self.deleteEntities.append( newOutputDict ) newevents = self._getNewEvents() self.assertEqual( newevents[0]["event_type"], "Shotgun_CustomEntity02_New", "event not as expected" ) self.assertEqual( newevents[1]["event_type"], "Shotgun_CustomEntity02_Change", "event not as expected" ) self.assertEqual( newevents[2]["event_type"], "Shotgun_CustomEntity02_Change", "event not as expected" ) self.assertEqual( newevents[3]["event_type"], "Shotgun_CustomEntity02_Change", "event not as expected" ) self._processEvents( newevents ) newOutput = factories.getObject( "CustomEntity02", remote_id = newOutputDict["id"] ) changedData = { 'sg_sink_tasks': [ { "type": "Task", "id": testTaskID }, { "type": "Task", "id": testTaskID_2 }, ] } self.sg.update( newOutputDict["type"], newOutputDict["id"], changedData ) newevents = self._getNewEvents() self.assertEqual( len( newevents ), 5 ) self.assertEqual( newevents[0]["event_type"], "Shotgun_CustomEntity02_sg_sink_tasks_Connection_New" ) self.assertEqual( newevents[1]["event_type"], "Shotgun_CustomEntity02_sg_sink_tasks_Connection_New" ) self.assertEqual( newevents[2]["event_type"], "Shotgun_CustomEntity02_Change" ) self.assertEqual( newevents[3]["event_type"], "Shotgun_Task_Change" ) self.assertEqual( newevents[4]["event_type"], "Shotgun_Task_Change" ) self._processEvents( newevents ) # check if Connection-Entities are available filters = "custom_entity02=%s and task=ANY(%s)" taskSgObj1 = PostgresEntityType( "Task", remote_id = testTaskID ) taskSgObj2 = PostgresEntityType( "Task", remote_id = testTaskID_2 ) outputSgObj = PostgresEntityType( newOutputDict["type"], remote_id = newOutputDict["id"] ) filterValues = [ outputSgObj, [ taskSgObj1, taskSgObj2 ] ] connObjs = factories.getObjects( "CustomEntity02_sg_sink_tasks_Connection", filters, filterValues ) self.assertEqual( len( connObjs ), 2, "no conn-objs: %s" % pprint.pformat( connObjs, indent = 2 ) ) # check if return attribute of Task contains this CustomEntity02 retAttr = entityNaming.getReverseAttributeName( "CustomEntity02", "sg_sink_tasks" ) for taskID in [ testTaskID, testTaskID_2 ]: taskTmpObj = factories.getObject( "Task", remote_id = taskID ) retOutputs = taskTmpObj.__getattribute__( retAttr ) self.assertTrue( newOutput in retOutputs ) changedData["sg_sink_tasks"] = [] self.sg.update( newOutputDict["type"], newOutputDict["id"], changedData ) newevents = self._getNewEvents() # unfortunately there are two events missing: # see: https://support.shotgunsoftware.com/requests/7380 self.assertEqual( len( newevents ), 3 ) self.assertEqual( newevents[0]["event_type"], "Shotgun_CustomEntity02_Change" ) self.assertEqual( newevents[1]["event_type"], "Shotgun_Task_Change" ) self.assertEqual( newevents[2]["event_type"], "Shotgun_Task_Change" ) self._processEvents( newevents ) retAttr = entityNaming.getReverseAttributeName( "CustomEntity02", "sg_sink_tasks" ) for taskID in [ testTaskID, testTaskID_2 ]: taskTmpObj = factories.getObject( "Task", remote_id = taskID ) retOutputs = taskTmpObj.__getattribute__( retAttr ) if retOutputs: self.assertFalse( newOutput in retOutputs ) # check if Connection-Entities are deleted connObjs = factories.getObjects( "CustomEntity02_sg_sink_tasks_Connection", filters, filterValues ) self.assertEqual( len( connObjs ), 0, "conn-objs still available: %s" % pprint.pformat( connObjs, indent = 2 ) )