From 8c093ce2adc5220b266cab8b33d5f5e235f980bb Mon Sep 17 00:00:00 2001 From: Jakub Trllo Date: Mon, 26 Nov 2018 14:26:44 +0100 Subject: [PATCH] Creating backup --- pype/ftrack/actions/action_syncToAvalon.py | 57 +++++-------- pype/ftrack/events/event_sync_to_avalon.py | 89 ++++++++++---------- pype/ftrack/events/ftrack_event_handler.py | 1 - pype/ftrack/events/test_event.py | 36 ++++---- pype/ftrack/ftrack_utils.py | 29 ++++++- pype/lib.py | 26 ++++++ pype/utils/__init__.py | 98 ---------------------- pype/utils/lib.py | 96 +++++++++++++++++++++ 8 files changed, 229 insertions(+), 203 deletions(-) diff --git a/pype/ftrack/actions/action_syncToAvalon.py b/pype/ftrack/actions/action_syncToAvalon.py index bdf8649714..0530dde69c 100644 --- a/pype/ftrack/actions/action_syncToAvalon.py +++ b/pype/ftrack/actions/action_syncToAvalon.py @@ -7,10 +7,11 @@ import os import ftrack_api import json import re +from pype import lib from ftrack_action_handler import BaseAction - -from avalon import io, inventory, lib +from avalon import io, inventory from avalon.vendor import toml +from pype.ftrack import ftrack_utils class SyncToAvalon(BaseAction): '''Edit meta data action.''' @@ -27,6 +28,7 @@ class SyncToAvalon(BaseAction): def discover(self, session, entities, event): ''' Validation ''' + discover = False for entity in entities: if entity.entity_type.lower() not in ['task', 'assetversion']: @@ -55,7 +57,7 @@ class SyncToAvalon(BaseAction): print("action <" + self.__class__.__name__ + "> is running") #TODO AVALON_PROJECTS, AVALON_ASSET, AVALON_SILO should be set up otherwise console log shows avalon debug - self.setAvalonAttributes(session) + self.setAvalonAttributes() self.importable = [] # get from top entity in hierarchy all parent entities @@ -107,9 +109,10 @@ class SyncToAvalon(BaseAction): 'success': True, 'message': "Synchronization was successfull" } - def setAvalonAttributes(self, session): + + def setAvalonAttributes(self): self.custom_attributes = [] - all_avalon_attr = session.query('CustomAttributeGroup where name is "avalon"').one() + all_avalon_attr = self.session.query('CustomAttributeGroup where name is "avalon"').one() for cust_attr in all_avalon_attr['custom_attribute_configurations']: if 'avalon_' not in cust_attr['key']: self.custom_attributes.append(cust_attr) @@ -132,28 +135,6 @@ class SyncToAvalon(BaseAction): print("Name of {} was changed to {}".format(input_name, name)) return name - def getConfig(self, entity): - apps = [] - for app in entity['custom_attributes']['applications']: - try: - label = toml.load(lib.which_app(app))['label'] - apps.append({'name':app, 'label':label}) - except Exception as e: - print('Error with application {0} - {1}'.format(app, e)) - - config = { - 'schema': 'avalon-core:config-1.0', - 'tasks': [{'name': ''}], - 'apps': apps, - # TODO redo work!!! - 'template': { - 'workfile': '{asset[name]}_{task[name]}_{version:0>3}<_{comment}>', - 'work': '{root}/{project}/{hierarchy}/{asset}/work/{task}', - 'publish':'{root}/{project}/{hierarchy}/{asset}/publish/{family}/{subset}/v{version}/{projectcode}_{asset}_{subset}_v{version}.{representation}'} - } - return config - - def importToAvalon(self, session, entity): eLinks = [] @@ -170,9 +151,6 @@ class SyncToAvalon(BaseAction): os.environ["AVALON_PROJECT"] = entityProj["full_name"] os.environ["AVALON_ASSET"] = entityProj['full_name'] - # Set project template - template = {"schema": "avalon-core:inventory-1.0"} - # --- Begin: PUSH TO Avalon --- io.install() ## ----- PROJECT ------ @@ -185,25 +163,28 @@ class SyncToAvalon(BaseAction): data['entityType'] = entity_type for cust_attr in self.custom_attributes: + key = cust_attr['key'] if cust_attr['entity_type'].lower() in ['asset']: - data[cust_attr['key']] = entity['custom_attributes'][cust_attr['key']] + data[key] = entity['custom_attributes'][key] elif cust_attr['entity_type'].lower() in ['show'] and entity_type.lower() == 'project': - data[cust_attr['key']] = entity['custom_attributes'][cust_attr['key']] + data[key] = entity['custom_attributes'][key] elif cust_attr['entity_type'].lower() in ['task'] and entity_type.lower() != 'project': # Put space between capitals (e.g. 'AssetBuild' -> 'Asset Build') - entity_type = re.sub(r"(\w)([A-Z])", r"\1 \2", entity_type) + entity_type_full = re.sub(r"(\w)([A-Z])", r"\1 \2", entity_type) # Get object id of entity type - ent_obj_type_id = session.query('ObjectType where name is "{}"'.format(entity_type)).one()['id'] + ent_obj_type_id = session.query('ObjectType where name is "{}"'.format(entity_type_full)).one()['id'] if cust_attr['object_type_id'] == ent_obj_type_id: - data[cust_attr['key']] = entity['custom_attributes'][cust_attr['key']] + data[key] = entity['custom_attributes'][key] - if entity.entity_type.lower() in ['project']: + if entity_type.lower() in ['project']: # Set project Config - config = self.getConfig(entity) + config = ftrack_utils.get_config(entity) + # Set project template + template = lib.get_avalon_project_template_schema() if avalon_project is None: inventory.save(entityProj['full_name'], config, template) @@ -233,7 +214,7 @@ class SyncToAvalon(BaseAction): ## ----- ASSETS ------ # Presets: # TODO how to check if entity is Asset Library or AssetBuild? - if entity.entity_type in ['AssetBuild', 'Library']: + if entity_type in ['AssetBuild', 'Library']: silo = 'Assets' else: silo = 'Film' diff --git a/pype/ftrack/events/event_sync_to_avalon.py b/pype/ftrack/events/event_sync_to_avalon.py index d8ede03503..4c09251b53 100644 --- a/pype/ftrack/events/event_sync_to_avalon.py +++ b/pype/ftrack/events/event_sync_to_avalon.py @@ -1,18 +1,20 @@ import os import sys +import re import ftrack_api from ftrack_event_handler import BaseEvent -from avalon import io, inventory, lib +from pype import lib +from avalon import io, inventory from avalon.vendor import toml -import re from bson.objectid import ObjectId +from pype.ftrack import ftrack_utils class Sync_to_Avalon(BaseEvent): def launch(self, session, entities, event): self.ca_mongoid = 'avalon_mongo_id' - self.proj = None + for entity in entities: try: base_proj = entity['link'][0] @@ -37,12 +39,9 @@ class Sync_to_Avalon(BaseEvent): io.uninstall() self.importEntities = [] - exceptions = ['assetversion', 'job', 'user'] for entity in entities: - if entity.entity_type.lower() in exceptions: - continue - elif entity.entity_type.lower() in ['task']: + if entity.entity_type.lower() in ['task']: entity = entity['parent'] try: mongo_id = entity['custom_attributes'][self.ca_mongoid] @@ -72,46 +71,48 @@ class Sync_to_Avalon(BaseEvent): def importToAvalon(self, entity): data = {} + entity_type = entity.entity_type + type = 'asset' name = entity['name'] silo = 'Film' - if entity.entity_type == 'Project': + if entity_type in ['Project']: type = 'project' name = entity['full_name'] data['code'] = entity['name'] - elif entity.entity_type in ['AssetBuild', 'Library']: + elif entity_type in ['AssetBuild', 'Library']: silo = 'Assets' os.environ["AVALON_ASSET"] = name os.environ["AVALON_SILO"] = silo - entity_type = entity.entity_type - data['ftrackId'] = entity['id'] data['entityType'] = entity_type for cust_attr in self.custom_attributes: + key = cust_attr['key'] if cust_attr['entity_type'].lower() in ['asset']: - data[cust_attr['key']] = entity['custom_attributes'][cust_attr['key']] + data[key] = entity['custom_attributes'][key] elif cust_attr['entity_type'].lower() in ['show'] and entity_type.lower() == 'project': - data[cust_attr['key']] = entity['custom_attributes'][cust_attr['key']] + data[key] = entity['custom_attributes'][key] elif cust_attr['entity_type'].lower() in ['task'] and entity_type.lower() != 'project': # Put space between capitals (e.g. 'AssetBuild' -> 'Asset Build') - entity_type = re.sub(r"(\w)([A-Z])", r"\1 \2", entity_type) + entity_type_full = re.sub(r"(\w)([A-Z])", r"\1 \2", entity_type) # Get object id of entity type - ent_obj_type_id = self.session.query('ObjectType where name is "{}"'.format(entity_type)).one()['id'] + ent_obj_type_id = self.session.query('ObjectType where name is "{}"'.format(entity_type_full)).one()['id'] if cust_attr['object_type_id'] == ent_obj_type_id: - data[cust_attr['key']] = entity['custom_attributes'][cust_attr['key']] + data[key] = entity['custom_attributes'][key] mongo_id = entity['custom_attributes'][self.ca_mongoid] - if entity_type in ['project']: - config = self.getConfig() - template = {"schema": "avalon-core:inventory-1.0"} + if entity_type.lower() in ['project']: + + config = ftrack_utils.get_config(entity) + template = lib.get_avalon_project_template_schema() if self.avalon_project is None: mongo_id = inventory.save(self.proj['full_name'], config, template) @@ -131,6 +132,10 @@ class Sync_to_Avalon(BaseEvent): }}) return + + if self.avalon_project is None: + self.importToAvalon(self.proj) + eLinks = [] for e in entity['link']: tmp = self.session.get(e['type'], e['id']) @@ -161,13 +166,12 @@ class Sync_to_Avalon(BaseEvent): data['visualParent'] = parentId data['hierarchy'] = hierarchy - if self.avalon_project is None: - self.importToAvalon(self.proj) - avalon_asset = io.find_one({'_id': ObjectId(mongo_id)}) if avalon_asset is None: avalon_asset = io.find_one({'type': type, 'name': name}) - if avalon_asset is None: + if avalon_asset is None: + mongo_id = inventory.create_asset(name, silo, data, self.projectId) + elif avalon_asset['name'] != name: mongo_id = inventory.create_asset(name, silo, data, self.projectId) io.update_many( @@ -176,7 +180,7 @@ class Sync_to_Avalon(BaseEvent): 'name':name, 'silo':silo, 'data':data, - 'Parent': self.projectId}}) + 'parent': self.projectId}}) def checkName(self, input_name): @@ -187,27 +191,6 @@ class Sync_to_Avalon(BaseEvent): print("Name of {} was changed to {}".format(input_name, name)) return name - def getConfig(self, entity): - apps = [] - for app in entity['custom_attributes']['applications']: - try: - label = toml.load(lib.which_app(app))['label'] - apps.append({'name':app, 'label':label}) - except Exception as e: - print('Error with application {0} - {1}'.format(app, e)) - - config = { - 'schema': 'avalon-core:config-1.0', - 'tasks': [{'name': ''}], - 'apps': apps, - # TODO redo work!!! - 'template': { - 'workfile': '{asset[name]}_{task[name]}_{version:0>3}<_{comment}>', - 'work': '{root}/{project}/{hierarchy}/{asset}/work/{task}', - 'publish':'{root}/{project}/{hierarchy}/{asset}/publish/{family}/{subset}/v{version}/{projectcode}_{asset}_{subset}_v{version}.{representation}'} - } - return config - def setAvalonAttributes(self): self.custom_attributes = [] all_avalon_attr = self.session.query('CustomAttributeGroup where name is "avalon"').one() @@ -215,6 +198,22 @@ class Sync_to_Avalon(BaseEvent): if 'avalon_' not in cust_attr['key']: self.custom_attributes.append(cust_attr) + def _translate_event(self, session, event): + exceptions = ['assetversion', 'job', 'user', 'reviewsessionobject', 'timer', 'socialfeed', 'timelog'] + _selection = event['data'].get('entities',[]) + + _entities = list() + for entity in _selection: + if entity['entityType'] in exceptions: + continue + _entities.append( + ( + session.get(self._get_entity_type(entity), entity.get('entityId')) + ) + ) + + return [_entities, event] + def register(session, **kw): '''Register plugin. Called when used as an plugin.''' diff --git a/pype/ftrack/events/ftrack_event_handler.py b/pype/ftrack/events/ftrack_event_handler.py index 775d6c07c2..a555a5324a 100644 --- a/pype/ftrack/events/ftrack_event_handler.py +++ b/pype/ftrack/events/ftrack_event_handler.py @@ -59,7 +59,6 @@ class BaseEvent(object): _entities.append( ( session.get(self._get_entity_type(entity), entity.get('entityId')) - # self._get_entity_type(entity), entity.get('entityId') ) ) diff --git a/pype/ftrack/events/test_event.py b/pype/ftrack/events/test_event.py index 7e5fe6d903..bf15928f98 100644 --- a/pype/ftrack/events/test_event.py +++ b/pype/ftrack/events/test_event.py @@ -1,26 +1,26 @@ -# import ftrack_api as local session +import os +import sys import ftrack_api -# -session = ftrack_api.Session() - -# ---------------------------------- +from ftrack_event_handler import BaseEvent -def test_event(event): - '''just a testing event''' +class Test_Event(BaseEvent): - # start of event procedure ---------------------------------- - for entity in event['data'].get('entities', []): - if entity['entityType'] == 'task' and entity['action'] == 'update': + def launch(self, session, entities, event): + '''just a testing event''' + exceptions = ['assetversion', 'job', 'user', 'reviewsessionobject', 'timer', 'socialfeed', 'timelog'] + selection = event['data'].get('entities',[]) + for entity in selection: + if entity['entityType'] in exceptions: + print(100*"*") + print(entity) - print("\n\nevent script: {}".format(__file__)) - # for k in task.keys(): - # print k, task[k] - # print '\n' - # print task['assignments'] +def register(session, **kw): + '''Register plugin. Called when used as an plugin.''' - for e in entity.keys(): - print('{0}: {1}'.format(e, entity[e])) + if not isinstance(session, ftrack_api.session.Session): + return - # end of event procedure ---------------------------------- + event = Test_Event(session) + event.register() diff --git a/pype/ftrack/ftrack_utils.py b/pype/ftrack/ftrack_utils.py index 23531a9fdd..68e83a9e6e 100644 --- a/pype/ftrack/ftrack_utils.py +++ b/pype/ftrack/ftrack_utils.py @@ -2,13 +2,36 @@ import ftrack_api import os +import traceback from pprint import * +from pype import lib +def get_apps(entity): + """ Get apps from project + Requirements: + 'Entity' MUST be object of ftrack entity with entity_type 'Project' + Checking if app from ftrack is available in Templates/bin/{app_name}.toml -def checkLogin(): - # check Environments FTRACK_API_USER, FTRACK_API_KEY - pass + Returns: + Array with dictionaries with app Name and Label + """ + apps = [] + for app in entity['custom_attributes']['applications']: + try: + label = toml.load(lib.which_app(app))['label'] + apps.append({'name':app, 'label':label}) + except Exception as e: + print('Error with application {0} - {1}'.format(app, e)) + return apps +def get_config(self, entity): + config = {} + config['schema'] = lib.get_avalon_project_config_schema() + config['tasks'] = [{'name': ''}] + config['apps'] = get_apps(entity) + config['template'] = lib.get_avalon_project_template() + + return config def checkRegex(): # _handle_result -> would be solution? diff --git a/pype/lib.py b/pype/lib.py index 3ce1441e3d..34bdda2a17 100644 --- a/pype/lib.py +++ b/pype/lib.py @@ -335,3 +335,29 @@ def get_asset_data(asset=None): data = document.get("data", {}) return data + +def get_avalon_project_config_schema(): + schema = 'avalon-core:config-1.0' + return schema + +def get_avalon_project_template_schema(): + schema = {"schema": "avalon-core:inventory-1.0"} + return schema + +def get_avalon_project_template(): + from app.api import Templates + + """Get avalon template + + Returns: + dictionary with templates + """ + template = Templates(type=["anatomy"]) + proj_template = {} + # proj_template['workfile'] = '{asset[name]}_{task[name]}_{version:0>3}<_{comment}>' + # proj_template['work'] = '{root}/{project}/{hierarchy}/{asset}/work/{task}' + # proj_template['publish'] = '{root}/{project}/{hierarchy}/{asset}/publish/{family}/{subset}/v{version}/{projectcode}_{asset}_{subset}_v{version}.{representation}' + proj_template['workfile'] = template.anatomy.avalon.workfile + proj_template['work'] = template.anatomy.avalon.work + proj_template['publish'] = template.anatomy.avalon.publish + return proj_template diff --git a/pype/utils/__init__.py b/pype/utils/__init__.py index 318d875f60..e69de29bb2 100644 --- a/pype/utils/__init__.py +++ b/pype/utils/__init__.py @@ -1,98 +0,0 @@ -from .lib import * - - -def load_capture_preset(path): - import capture_gui - import capture - - path = path - preset = capture_gui.lib.load_json(path) - print preset - - options = dict() - - # CODEC - id = 'Codec' - for key in preset[id]: - options[str(key)] = preset[id][key] - - # GENERIC - id = 'Generic' - for key in preset[id]: - if key.startswith('isolate'): - pass - # options['isolate'] = preset[id][key] - else: - options[str(key)] = preset[id][key] - - # RESOLUTION - id = 'Resolution' - options['height'] = preset[id]['height'] - options['width'] = preset[id]['width'] - - # DISPLAY OPTIONS - id = 'Display Options' - disp_options = {} - for key in preset['Display Options']: - if key.startswith('background'): - disp_options[key] = preset['Display Options'][key] - else: - disp_options['displayGradient'] = True - - options['display_options'] = disp_options - - # VIEWPORT OPTIONS - temp_options = {} - id = 'Renderer' - for key in preset[id]: - temp_options[str(key)] = preset[id][key] - - temp_options2 = {} - id = 'Viewport Options' - light_options = {0: "default", - 1: 'all', - 2: 'selected', - 3: 'flat', - 4: 'nolights'} - for key in preset[id]: - if key == 'high_quality': - temp_options2['multiSampleEnable'] = True - temp_options2['multiSampleCount'] = 4 - temp_options2['textureMaxResolution'] = 512 - temp_options2['enableTextureMaxRes'] = True - - if key == 'alphaCut': - temp_options2['transparencyAlgorithm'] = 5 - temp_options2['transparencyQuality'] = 1 - - if key == 'headsUpDisplay': - temp_options['headsUpDisplay'] = True - - if key == 'displayLights': - temp_options[str(key)] = light_options[preset[id][key]] - else: - temp_options[str(key)] = preset[id][key] - - for key in ['override_viewport_options', 'high_quality', 'alphaCut']: - temp_options.pop(key, None) - - options['viewport_options'] = temp_options - options['viewport2_options'] = temp_options2 - - # use active sound track - scene = capture.parse_active_scene() - options['sound'] = scene['sound'] - cam_options = dict() - cam_options['overscan'] = 1.0 - cam_options['displayFieldChart'] = False - cam_options['displayFilmGate'] = False - cam_options['displayFilmOrigin'] = False - cam_options['displayFilmPivot'] = False - cam_options['displayGateMask'] = False - cam_options['displayResolution'] = False - cam_options['displaySafeAction'] = False - cam_options['displaySafeTitle'] = False - - # options['display_options'] = temp_options - - return options diff --git a/pype/utils/lib.py b/pype/utils/lib.py index 8fdc1a4455..8b7be1a3fe 100644 --- a/pype/utils/lib.py +++ b/pype/utils/lib.py @@ -105,3 +105,99 @@ def filter_instances(context, plugin): instances = pyblish.api.instances_by_plugin(allInstances, plugin) return instances + +def load_capture_preset(path): + import capture_gui + import capture + + path = path + preset = capture_gui.lib.load_json(path) + print preset + + options = dict() + + # CODEC + id = 'Codec' + for key in preset[id]: + options[str(key)] = preset[id][key] + + # GENERIC + id = 'Generic' + for key in preset[id]: + if key.startswith('isolate'): + pass + # options['isolate'] = preset[id][key] + else: + options[str(key)] = preset[id][key] + + # RESOLUTION + id = 'Resolution' + options['height'] = preset[id]['height'] + options['width'] = preset[id]['width'] + + # DISPLAY OPTIONS + id = 'Display Options' + disp_options = {} + for key in preset['Display Options']: + if key.startswith('background'): + disp_options[key] = preset['Display Options'][key] + else: + disp_options['displayGradient'] = True + + options['display_options'] = disp_options + + # VIEWPORT OPTIONS + temp_options = {} + id = 'Renderer' + for key in preset[id]: + temp_options[str(key)] = preset[id][key] + + temp_options2 = {} + id = 'Viewport Options' + light_options = {0: "default", + 1: 'all', + 2: 'selected', + 3: 'flat', + 4: 'nolights'} + for key in preset[id]: + if key == 'high_quality': + temp_options2['multiSampleEnable'] = True + temp_options2['multiSampleCount'] = 4 + temp_options2['textureMaxResolution'] = 512 + temp_options2['enableTextureMaxRes'] = True + + if key == 'alphaCut': + temp_options2['transparencyAlgorithm'] = 5 + temp_options2['transparencyQuality'] = 1 + + if key == 'headsUpDisplay': + temp_options['headsUpDisplay'] = True + + if key == 'displayLights': + temp_options[str(key)] = light_options[preset[id][key]] + else: + temp_options[str(key)] = preset[id][key] + + for key in ['override_viewport_options', 'high_quality', 'alphaCut']: + temp_options.pop(key, None) + + options['viewport_options'] = temp_options + options['viewport2_options'] = temp_options2 + + # use active sound track + scene = capture.parse_active_scene() + options['sound'] = scene['sound'] + cam_options = dict() + cam_options['overscan'] = 1.0 + cam_options['displayFieldChart'] = False + cam_options['displayFilmGate'] = False + cam_options['displayFilmOrigin'] = False + cam_options['displayFilmPivot'] = False + cam_options['displayGateMask'] = False + cam_options['displayResolution'] = False + cam_options['displaySafeAction'] = False + cam_options['displaySafeTitle'] = False + + # options['display_options'] = temp_options + + return options