def main(args): check_thread = None try: server = FtrackServer('event') session = ftrack_api.Session(auto_connect_event_hub=True) check_thread = TimerChecker(server, session) check_thread.start() log.debug("Launching Ftrack Event Legacy Server") server.run_server(session) except Exception as exc: import traceback traceback.print_tb(exc.__traceback__) finally: log_info = True if check_thread is not None: check_thread.stop() check_thread.join() if check_thread.failed: log_info = False if log_info: log.info("Exiting Event server subprocess") return 1
def main(arguments=None): '''Set up logging and register action.''' if arguments is None: arguments = [] parser = argparse.ArgumentParser() # Allow setting of logging level from arguments. loggingLevels = {} for level in (logging.NOTSET, logging.DEBUG, logging.INFO, logging.WARNING, logging.ERROR, logging.CRITICAL): loggingLevels[logging.getLevelName(level).lower()] = level parser.add_argument('-v', '--verbosity', help='Set the logging output verbosity.', choices=loggingLevels.keys(), default='info') namespace = parser.parse_args(arguments) # Set up basic logging logging.basicConfig(level=loggingLevels[namespace.verbosity]) session = ftrack_api.Session() register(session) # Wait for events logging.info( 'Registered actions and listening for events. Use Ctrl-C to abort.') session.event_hub.wait()
def get_file_paths(self, session, event): """Get file paths from selected components.""" link = session.get("Component", list(event["data"]["values"].values()) [0])["version"]["asset"]["parent"]["link"][0] project = session.get(link["type"], link["id"]) os.environ["AVALON_PROJECT"] = project["name"] api.Session["AVALON_PROJECT"] = project["name"] io.install() location = ftrack_api.Session().pick_location() paths = [] for parent_name in sorted(event["data"]["values"].keys()): component = session.get("Component", event["data"]["values"][parent_name]) # Newer publishes have the source referenced in Ftrack. online_source = False for neighbour_component in component["version"]["components"]: if neighbour_component["name"] != "ftrackreview-mp4_src": continue paths.append(location.get_filesystem_path(neighbour_component)) online_source = True if online_source: continue asset = io.find_one({"type": "asset", "name": parent_name}) subset = io.find_one({ "type": "subset", "name": component["version"]["asset"]["name"], "parent": asset["_id"] }) version = io.find_one({ "type": "version", "name": component["version"]["version"], "parent": subset["_id"] }) representation = io.find_one({ "type": "representation", "parent": version["_id"], "name": component["file_type"][1:] }) if representation is None: representation = io.find_one({ "type": "representation", "parent": version["_id"], "name": "preview" }) paths.append(api.get_representation_path(representation)) return paths
def _check_credentials(username=None, apiKey=None): if username and apiKey: _set_env(username, apiKey) try: session = ftrack_api.Session() session.close() except Exception as e: return False return True
def run(self): self.timer_session = ftrack_api.Session(auto_connect_event_hub=True) self.timer_session.event_hub.subscribe( 'topic=ftrack.update and source.user.username={}'.format( self.username), self.event_handler) user_query = 'User where username is "{}"'.format(self.username) self.user = self.timer_session.query(user_query).one() timer_query = 'Timer where user.username is "{}"'.format(self.username) timer = self.timer_session.query(timer_query).first() if timer is not None: self.last_task = timer['context'] self.signal_timer_started.emit( self.get_data_from_task(self.last_task)) self.timer_session.event_hub.wait()
def run_server(self, session=None, load_files=True): if not session: session = ftrack_api.Session(auto_connect_event_hub=True) self.session = session if load_files: paths_str = os.environ.get(self.env_key) if paths_str is None: log.error( ("Env var \"{}\" is not set, \"{}\" server won\'t launch" ).format(self.env_key, self.server_type)) return paths = paths_str.split(os.pathsep) self.set_files(paths) log.info(60 * "*") log.info('Registration of actions/events has finished!') # keep event_hub on session running self.session.event_hub.wait()
def launch(self, session, entities, event): self.interface_messages = {} user = session.query('User where id is "{}"'.format( event['source']['user']['id'])).one() job = session.create( 'Job', { 'user': user, 'status': 'running', 'data': json.dumps( {'description': 'Sync Hierachical attributes'}) }) session.commit() self.log.debug('Job with id "{}" created'.format(job['id'])) process_session = ftrack_api.Session(server_url=session.server_url, api_key=session.api_key, api_user=session.api_user, auto_connect_event_hub=True) try: # Collect hierarchical attrs self.log.debug('Collecting Hierarchical custom attributes started') custom_attributes = {} all_avalon_attr = process_session.query( 'CustomAttributeGroup where name is "avalon"').one() error_key = ( 'Hierarchical attributes with set "default" value (not allowed)' ) for cust_attr in all_avalon_attr[ 'custom_attribute_configurations']: if 'avalon_' in cust_attr['key']: continue if not cust_attr['is_hierarchical']: continue if cust_attr['default']: if error_key not in self.interface_messages: self.interface_messages[error_key] = [] self.interface_messages[error_key].append( cust_attr['label']) self.log.warning( ('Custom attribute "{}" has set default value.' ' This attribute can\'t be synchronized').format( cust_attr['label'])) continue custom_attributes[cust_attr['key']] = cust_attr self.log.debug( 'Collecting Hierarchical custom attributes has finished') if not custom_attributes: msg = 'No hierarchical attributes to sync.' self.log.debug(msg) return {'success': True, 'message': msg} entity = entities[0] if entity.entity_type.lower() == 'project': project_name = entity['full_name'] else: project_name = entity['project']['full_name'] self.db_con.install() self.db_con.Session['AVALON_PROJECT'] = project_name _entities = self._get_entities(event, process_session) for entity in _entities: self.log.debug(30 * '-') self.log.debug('Processing entity "{}"'.format( entity.get('name', entity))) ent_name = entity.get('name', entity) if entity.entity_type.lower() == 'project': ent_name = entity['full_name'] for key in custom_attributes: self.log.debug(30 * '*') self.log.debug( 'Processing Custom attribute key "{}"'.format(key)) # check if entity has that attribute if key not in entity['custom_attributes']: error_key = 'Missing key on entities' if error_key not in self.interface_messages: self.interface_messages[error_key] = [] self.interface_messages[error_key].append( '- key: "{}" - entity: "{}"'.format(key, ent_name)) self.log.error(('- key "{}" not found on "{}"').format( key, entity.get('name', entity))) continue value = self.get_hierarchical_value(key, entity) if value is None: error_key = ( 'Missing value for key on entity' ' and its parents (synchronization was skipped)') if error_key not in self.interface_messages: self.interface_messages[error_key] = [] self.interface_messages[error_key].append( '- key: "{}" - entity: "{}"'.format(key, ent_name)) self.log.warning( ('- key "{}" not set on "{}" or its parents' ).format(key, ent_name)) continue self.update_hierarchical_attribute(entity, key, value) job['status'] = 'done' session.commit() except Exception: self.log.error('Action "{}" failed'.format(self.label), exc_info=True) finally: self.db_con.uninstall() if job['status'] in ('queued', 'running'): job['status'] = 'failed' session.commit() if self.interface_messages: self.show_interface_from_dict(messages=self.interface_messages, title="something went wrong", event=event) return True