From 2b8ff908c060fe6c3f5877ef3ecb3399253ba6ea Mon Sep 17 00:00:00 2001 From: Milan Kolar Date: Tue, 30 Oct 2018 15:15:10 +0100 Subject: [PATCH] remove action handler from vendor --- .../actions}/action.py | 0 pype/ftrack/actions/action_Apps.py | 2 +- .../actions/action_createCustomAttributes.py | 2 +- pype/ftrack/actions/action_killRunningJobs.py | 4 +- pype/ftrack/actions/action_syncToAvalon.py | 2 +- pype/ftrack/actions/action_test.py | 2 +- .../actions/ftrack_action_handler.py} | 228 ++++++++++++++++++ pype/vendor/ftrack_action_handler/__init__.py | 4 - pype/vendor/ftrack_action_handler/_version.py | 1 - 9 files changed, 234 insertions(+), 11 deletions(-) rename pype/{vendor/ftrack_action_handler => ftrack/actions}/action.py (100%) rename pype/{vendor/ftrack_action_handler/appaction.py => ftrack/actions/ftrack_action_handler.py} (57%) delete mode 100644 pype/vendor/ftrack_action_handler/__init__.py delete mode 100644 pype/vendor/ftrack_action_handler/_version.py diff --git a/pype/vendor/ftrack_action_handler/action.py b/pype/ftrack/actions/action.py similarity index 100% rename from pype/vendor/ftrack_action_handler/action.py rename to pype/ftrack/actions/action.py diff --git a/pype/ftrack/actions/action_Apps.py b/pype/ftrack/actions/action_Apps.py index 0e79b4c0d4..6b0a5e4cc7 100644 --- a/pype/ftrack/actions/action_Apps.py +++ b/pype/ftrack/actions/action_Apps.py @@ -2,7 +2,7 @@ import os import logging import toml import ftrack_api -from ftrack_action_handler.appaction import AppAction +from ftrack_action_handler import AppAction from avalon import io, lib diff --git a/pype/ftrack/actions/action_createCustomAttributes.py b/pype/ftrack/actions/action_createCustomAttributes.py index d0d538d9de..9133709c13 100644 --- a/pype/ftrack/actions/action_createCustomAttributes.py +++ b/pype/ftrack/actions/action_createCustomAttributes.py @@ -6,7 +6,7 @@ import logging import os import json import ftrack_api -from ftrack_action_handler.action import BaseAction +from ftrack_action_handler import BaseAction from avalon import io, inventory, lib from avalon.vendor import toml diff --git a/pype/ftrack/actions/action_killRunningJobs.py b/pype/ftrack/actions/action_killRunningJobs.py index 20bd2eee38..450788df0e 100644 --- a/pype/ftrack/actions/action_killRunningJobs.py +++ b/pype/ftrack/actions/action_killRunningJobs.py @@ -6,7 +6,7 @@ import logging import datetime import ftrack_api -from ftrack_action_handler.action import BaseAction +from ftrack_action_handler import BaseAction class JobKiller(BaseAction): @@ -96,7 +96,7 @@ def main(arguments=None): logging.basicConfig(level=loggingLevels[namespace.verbosity]) session = ftrack_api.Session() - + register(session) # Wait for events diff --git a/pype/ftrack/actions/action_syncToAvalon.py b/pype/ftrack/actions/action_syncToAvalon.py index dd8b096ca8..f7e389a16b 100644 --- a/pype/ftrack/actions/action_syncToAvalon.py +++ b/pype/ftrack/actions/action_syncToAvalon.py @@ -6,7 +6,7 @@ import logging import os import json import ftrack_api -from ftrack_action_handler.action import BaseAction +from ftrack_action_handler import BaseAction from avalon import io, inventory, lib from avalon.vendor import toml diff --git a/pype/ftrack/actions/action_test.py b/pype/ftrack/actions/action_test.py index 7123422cc8..a5eca5dfac 100644 --- a/pype/ftrack/actions/action_test.py +++ b/pype/ftrack/actions/action_test.py @@ -8,7 +8,7 @@ import os import json import ftrack_api -from ftrack_action_handler.action import BaseAction +from ftrack_action_handler import BaseAction from avalon import io, inventory, schema from avalon.vendor import toml diff --git a/pype/vendor/ftrack_action_handler/appaction.py b/pype/ftrack/actions/ftrack_action_handler.py similarity index 57% rename from pype/vendor/ftrack_action_handler/appaction.py rename to pype/ftrack/actions/ftrack_action_handler.py index 5b71bbddd3..992b455e5b 100644 --- a/pype/vendor/ftrack_action_handler/appaction.py +++ b/pype/ftrack/actions/ftrack_action_handler.py @@ -295,3 +295,231 @@ class AppAction(object): ) return result + + +class BaseAction(object): + '''Custom Action base class + + `label` a descriptive string identifing your action. + + `varaint` To group actions together, give them the same + label and specify a unique variant per action. + + `identifier` a unique identifier for your action. + + `description` a verbose descriptive text for you action + + ''' + label = None + variant = None + identifier = None + description = None + icon = None + + def __init__(self, session): + '''Expects a ftrack_api.Session instance''' + + self.logger = logging.getLogger( + '{0}.{1}'.format(__name__, self.__class__.__name__) + ) + + if self.label is None: + raise ValueError( + 'Action missing label.' + ) + + elif self.identifier is None: + raise ValueError( + 'Action missing identifier.' + ) + + self._session = session + + @property + def session(self): + '''Return current session.''' + return self._session + + def register(self): + '''Registers the action, subscribing the the discover and launch topics.''' + self.session.event_hub.subscribe( + 'topic=ftrack.action.discover', self._discover + ) + + self.session.event_hub.subscribe( + 'topic=ftrack.action.launch and data.actionIdentifier={0}'.format( + self.identifier + ), + self._launch + ) + + def _discover(self, event): + args = self._translate_event( + self.session, event + ) + + accepts = self.discover( + self.session, *args + ) + + if accepts: + return { + 'items': [{ + 'label': self.label, + 'variant': self.variant, + 'description': self.description, + 'actionIdentifier': self.identifier, + 'icon': self.icon, + }] + } + + def discover(self, session, entities, event): + '''Return true if we can handle the selected entities. + + *session* is a `ftrack_api.Session` instance + + + *entities* is a list of tuples each containing the entity type and the entity id. + If the entity is a hierarchical you will always get the entity + type TypedContext, once retrieved through a get operation you + will have the "real" entity type ie. example Shot, Sequence + or Asset Build. + + *event* the unmodified original event + + ''' + + return False + + def _translate_event(self, session, event): + '''Return *event* translated structure to be used with the API.''' + + _selection = event['data'].get('selection', []) + + _entities = list() + for entity in _selection: + _entities.append( + ( + self._get_entity_type(entity), entity.get('entityId') + ) + ) + + return [ + _entities, + event + ] + + def _get_entity_type(self, entity): + '''Return translated entity type tht can be used with API.''' + # Get entity type and make sure it is lower cased. Most places except + # the component tab in the Sidebar will use lower case notation. + entity_type = entity.get('entityType').replace('_', '').lower() + + for schema in self.session.schemas: + alias_for = schema.get('alias_for') + + if ( + alias_for and isinstance(alias_for, str) and + alias_for.lower() == entity_type + ): + return schema['id'] + + for schema in self.session.schemas: + if schema['id'].lower() == entity_type: + return schema['id'] + + raise ValueError( + 'Unable to translate entity type: {0}.'.format(entity_type) + ) + + def _launch(self, event): + args = self._translate_event( + self.session, event + ) + + interface = self._interface( + self.session, *args + ) + + if interface: + return interface + + response = self.launch( + self.session, *args + ) + + return self._handle_result( + self.session, response, *args + ) + + def launch(self, session, entities, event): + '''Callback method for the custom action. + + return either a bool ( True if successful or False if the action failed ) + or a dictionary with they keys `message` and `success`, the message should be a + string and will be displayed as feedback to the user, success should be a bool, + True if successful or False if the action failed. + + *session* is a `ftrack_api.Session` instance + + *entities* is a list of tuples each containing the entity type and the entity id. + If the entity is a hierarchical you will always get the entity + type TypedContext, once retrieved through a get operation you + will have the "real" entity type ie. example Shot, Sequence + or Asset Build. + + *event* the unmodified original event + + ''' + raise NotImplementedError() + + def _interface(self, *args): + interface = self.interface(*args) + + if interface: + return { + 'items': interface + } + + def interface(self, session, entities, event): + '''Return a interface if applicable or None + + *session* is a `ftrack_api.Session` instance + + *entities* is a list of tuples each containing the entity type and the entity id. + If the entity is a hierarchical you will always get the entity + type TypedContext, once retrieved through a get operation you + will have the "real" entity type ie. example Shot, Sequence + or Asset Build. + + *event* the unmodified original event + ''' + return None + + def _handle_result(self, session, result, entities, event): + '''Validate the returned result from the action callback''' + if isinstance(result, bool): + result = { + 'success': result, + 'message': ( + '{0} launched successfully.'.format( + self.label + ) + ) + } + + elif isinstance(result, dict): + for key in ('success', 'message'): + if key in result: + continue + + raise KeyError( + 'Missing required key: {0}.'.format(key) + ) + + else: + self.logger.error( + 'Invalid result type must be bool or dictionary!' + ) + + return result diff --git a/pype/vendor/ftrack_action_handler/__init__.py b/pype/vendor/ftrack_action_handler/__init__.py deleted file mode 100644 index 54b1761f13..0000000000 --- a/pype/vendor/ftrack_action_handler/__init__.py +++ /dev/null @@ -1,4 +0,0 @@ -# :coding: utf-8 -# :copyright: Copyright (c) 2017 ftrack - -from ._version import __version__ diff --git a/pype/vendor/ftrack_action_handler/_version.py b/pype/vendor/ftrack_action_handler/_version.py deleted file mode 100644 index 8ce9b3623b..0000000000 --- a/pype/vendor/ftrack_action_handler/_version.py +++ /dev/null @@ -1 +0,0 @@ -__version__ = '0.1.3'