Exemple #1
0
    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
Exemple #3
0
    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"}