def launch(self, session, entities, event): time_start = time.time() message = "" # JOB SETTINGS userId = event['source']['user']['id'] user = session.query('User where id is ' + userId).one() job = session.create( 'Job', { 'user': user, 'status': 'running', 'data': json.dumps({'description': 'Sync Ftrack to Avalon.'}) }) session.commit() try: self.log.debug("Preparing entities for synchronization") if entities[0].entity_type.lower() == "project": ft_project_name = entities[0]["full_name"] else: ft_project_name = entities[0]["project"]["full_name"] project_entities = session.query( self.entities_query.format(ft_project_name)).all() ft_project = session.query( self.project_query.format(ft_project_name)).one() entities_by_id = {} entities_by_parent = collections.defaultdict(list) entities_by_id[ft_project["id"]] = ft_project for ent in project_entities: entities_by_id[ent["id"]] = ent entities_by_parent[ent["parent_id"]].append(ent) importable = [] for ent_info in event["data"]["selection"]: ent = entities_by_id[ent_info["entityId"]] for link_ent_info in ent["link"]: link_ent = entities_by_id[link_ent_info["id"]] if (ent.entity_type.lower() in self.ignore_entity_types or link_ent in importable): continue importable.append(link_ent) def add_children(parent_id): ents = entities_by_parent[parent_id] for ent in ents: if ent.entity_type.lower() in self.ignore_entity_types: continue if ent not in importable: importable.append(ent) add_children(ent["id"]) # add children of selection to importable for ent_info in event["data"]["selection"]: add_children(ent_info["entityId"]) # Check names: REGEX in schema/duplicates - raise error if found all_names = [] duplicates = [] for entity in importable: lib.avalon_check_name(entity) if entity.entity_type.lower() == "project": continue if entity['name'] in all_names: duplicates.append("'{}'".format(entity['name'])) else: all_names.append(entity['name']) if len(duplicates) > 0: # TODO Show information to user and return False raise ValueError("Entity name duplication: {}".format( ", ".join(duplicates))) # ----- PROJECT ------ avalon_project = lib.get_avalon_project(ft_project) custom_attributes = lib.get_avalon_attr(session) # Import all entities to Avalon DB for entity in importable: result = lib.import_to_avalon( session=session, entity=entity, ft_project=ft_project, av_project=avalon_project, custom_attributes=custom_attributes) # TODO better error handling # maybe split into critical, warnings and messages? if 'errors' in result and len(result['errors']) > 0: job['status'] = 'failed' session.commit() lib.show_errors(self, event, result['errors']) return { 'success': False, 'message': "Sync to avalon FAILED" } if avalon_project is None: if 'project' in result: avalon_project = result['project'] job['status'] = 'done' session.commit() except ValueError as ve: # TODO remove this part!!!! job['status'] = 'failed' session.commit() message = str(ve) self.log.error('Error during syncToAvalon: {}'.format(message), exc_info=True) except Exception as e: job['status'] = 'failed' session.commit() exc_type, exc_obj, exc_tb = sys.exc_info() fname = os.path.split(exc_tb.tb_frame.f_code.co_filename)[1] log_message = "{}/{}/Line: {}".format(exc_type, fname, exc_tb.tb_lineno) self.log.error('Error during syncToAvalon: {}'.format(log_message), exc_info=True) # TODO add traceback to message and show to user message = ('Unexpected Error' ' - Please check Log for more information') finally: if job['status'] in ['queued', 'running']: job['status'] = 'failed' session.commit() time_end = time.time() self.log.debug("Synchronization took \"{}\"".format( str(time_end - time_start))) if job["status"] != "failed": self.log.debug("Triggering Sync hierarchical attributes") self.trigger_action("sync.hierarchical.attrs", event) if len(message) > 0: message = "Unable to sync: {}".format(message) return {'success': False, 'message': message} return {'success': True, 'message': "Synchronization was successfull"}
def launch(self, session, event): ca_mongoid = lib.get_ca_mongoid() # If mongo_id textfield has changed: RETURN! # - infinite loop for ent in event['data']['entities']: if ent.get('keys') is not None: if ca_mongoid in ent['keys']: return entities = self._get_entities(session, event, self.ignore_entityType) ft_project = None # get project for entity in entities: try: base_proj = entity['link'][0] except Exception: continue ft_project = session.get(base_proj['type'], base_proj['id']) break # check if project is set to auto-sync if (ft_project is None or 'avalon_auto_sync' not in ft_project['custom_attributes'] or ft_project['custom_attributes']['avalon_auto_sync'] is False): return # check if project have Custom Attribute 'avalon_mongo_id' if ca_mongoid not in ft_project['custom_attributes']: message = ( "Custom attribute '{}' for 'Project' is not created" " or don't have set permissions for API").format(ca_mongoid) self.log.warning(message) self.show_message(event, message, False) return # get avalon project if possible import_entities = [] custom_attributes = lib.get_avalon_attr(session) avalon_project = lib.get_avalon_project(ft_project) if avalon_project is None: import_entities.append(ft_project) for entity in entities: if entity.entity_type.lower() in ['task']: entity = entity['parent'] if 'custom_attributes' not in entity: continue if ca_mongoid not in entity['custom_attributes']: message = ("Custom attribute '{}' for '{}' is not created" " or don't have set permissions for API").format( ca_mongoid, entity.entity_type) self.log.warning(message) self.show_message(event, message, False) return if entity not in import_entities: import_entities.append(entity) if len(import_entities) < 1: return try: for entity in import_entities: result = lib.import_to_avalon( session=session, entity=entity, ft_project=ft_project, av_project=avalon_project, custom_attributes=custom_attributes) if 'errors' in result and len(result['errors']) > 0: session.commit() lib.show_errors(self, event, result['errors']) return if avalon_project is None: if 'project' in result: avalon_project = result['project'] except Exception as e: session.reset() # reset session to clear it message = str(e) title = 'Hey You! Unknown Error has been raised! (*look below*)' ftrack_message = ('SyncToAvalon event ended with unexpected error' ' please check log file or contact Administrator' ' for more information.') items = [{ 'type': 'label', 'value': '# Fatal Error' }, { 'type': 'label', 'value': '<p>{}</p>'.format(ftrack_message) }] self.show_interface(items, title, event=event) self.log.error('Fatal error during sync: {}'.format(message), exc_info=True) return
def launch(self, session, entities, event): message = "" # JOB SETTINGS userId = event['source']['user']['id'] user = session.query('User where id is ' + userId).one() job = session.create( 'Job', { 'user': user, 'status': 'running', 'data': json.dumps({'description': 'Sync Ftrack to Avalon.'}) }) session.commit() try: self.importable = [] # get from top entity in hierarchy all parent entities top_entity = entities[0]['link'] if len(top_entity) > 1: for e in top_entity: parent_entity = session.get(e['type'], e['id']) self.importable.append(parent_entity) # get all child entities separately/unique for entity in entities: self.add_childs_to_importable(entity) # Check names: REGEX in schema/duplicates - raise error if found all_names = [] duplicates = [] for entity in self.importable: ftracklib.avalon_check_name(entity) if entity['name'] in all_names: duplicates.append("'{}'".format(e['name'])) else: all_names.append(entity['name']) if len(duplicates) > 0: raise ValueError("Entity name duplication: {}".format( ", ".join(duplicates))) # ----- PROJECT ------ # store Ftrack project- self.importable[0] must be project entity!! ft_project = self.importable[0] avalon_project = ftracklib.get_avalon_project(ft_project) custom_attributes = ftracklib.get_avalon_attr(session) # Import all entities to Avalon DB for entity in self.importable: result = ftracklib.import_to_avalon( session=session, entity=entity, ft_project=ft_project, av_project=avalon_project, custom_attributes=custom_attributes) if 'errors' in result and len(result['errors']) > 0: job['status'] = 'failed' session.commit() ftracklib.show_errors(self, event, result['errors']) return { 'success': False, 'message': "Sync to avalon FAILED" } if avalon_project is None: if 'project' in result: avalon_project = result['project'] job['status'] = 'done' except ValueError as ve: job['status'] = 'failed' message = str(ve) self.log.error('Error during syncToAvalon: {}'.format(message)) except Exception as e: job['status'] = 'failed' exc_type, exc_obj, exc_tb = sys.exc_info() fname = os.path.split(exc_tb.tb_frame.f_code.co_filename)[1] log_message = "{}/{}/Line: {}".format(exc_type, fname, exc_tb.tb_lineno) self.log.error('Error during syncToAvalon: {}'.format(log_message)) message = ('Unexpected Error' ' - Please check Log for more information') finally: if job['status'] in ['queued', 'running']: job['status'] = 'failed' session.commit() if len(message) > 0: message = "Unable to sync: {}".format(message) return {'success': False, 'message': message} return {'success': True, 'message': "Synchronization was successfull"}