diff --git a/pype/lib/__init__.py b/pype/lib/__init__.py index d8ce8badbc..12633959aa 100644 --- a/pype/lib/__init__.py +++ b/pype/lib/__init__.py @@ -21,11 +21,8 @@ from .lib_old import ( get_last_version_from_path, get_avalon_database, set_io_database, - filter_pyblish_plugins, get_subsets, CustomNone, - execute_hook, - PypeHook, get_linked_assets, map_subsets_by_family, BuildWorkfile, @@ -36,3 +33,13 @@ from .lib_old import ( launch_application, ApplicationAction ) + +from .hooks import PypeHook, execute_hook +from .plugin_tools import filter_pyblish_plugins + +__all__ = [ + "PypeHook", + "execute_hook", + + "filter_pyblish_plugins" +] diff --git a/pype/lib/deprecated.py b/pype/lib/deprecated.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/pype/lib/hooks.py b/pype/lib/hooks.py new file mode 100644 index 0000000000..425ad36342 --- /dev/null +++ b/pype/lib/hooks.py @@ -0,0 +1,71 @@ +# -*- coding: utf-8 -*- +"""Package containing code for handling hooks.""" +import os +import sys +import types +import logging +from abc import ABCMeta, abstractmethod + +import six + + +log = logging.getLogger(__name__) + + +@six.add_metaclass(ABCMeta) +class PypeHook: + """Abstract class from all hooks should inherit.""" + + def __init__(self): + """Constructor.""" + pass + + @abstractmethod + def execute(self, *args, **kwargs): + """Abstract execute method.""" + pass + + +def execute_hook(hook, *args, **kwargs): + """Execute hook with arguments. + + This will load hook file, instantiate class and call + :meth:`PypeHook.execute` method on it. Hook must be in a form:: + + $PYPE_SETUP_PATH/repos/pype/path/to/hook.py/HookClass + + This will load `hook.py`, instantiate HookClass and then execute_hook + `execute(*args, **kwargs)` + + Args: + hook (str): path to hook class. + + """ + class_name = hook.split("/")[-1] + + abspath = os.path.join(os.getenv('PYPE_SETUP_PATH'), + 'repos', 'pype', *hook.split("/")[:-1]) + + mod_name, mod_ext = os.path.splitext(os.path.basename(abspath)) + + if not mod_ext == ".py": + return False + + module = types.ModuleType(mod_name) + module.__file__ = abspath + + try: + with open(abspath) as f: + six.exec_(f.read(), module.__dict__) + + sys.modules[abspath] = module + + except Exception as exp: + log.exception("loading hook failed: {}".format(exp), + exc_info=True) + return False + + obj = getattr(module, class_name) + hook_obj = obj() + ret_val = hook_obj.execute(*args, **kwargs) + return ret_val diff --git a/pype/lib/lib_old.py b/pype/lib/lib_old.py index e6de3882e9..08146309cc 100644 --- a/pype/lib/lib_old.py +++ b/pype/lib/lib_old.py @@ -1,6 +1,5 @@ import os import sys -import types import re import uuid import json @@ -11,13 +10,11 @@ import copy import contextlib import subprocess import getpass -import inspect import acre import platform -from abc import ABCMeta, abstractmethod +from pype.lib.hooks import execute_hook from avalon import io, pipeline -import six import avalon.api from ..api import config, Anatomy, Logger @@ -551,53 +548,6 @@ def set_io_database(): io.install() -def filter_pyblish_plugins(plugins): - """ - This servers as plugin filter / modifier for pyblish. It will load plugin - definitions from presets and filter those needed to be excluded. - - :param plugins: Dictionary of plugins produced by :mod:`pyblish-base` - `discover()` method. - :type plugins: Dict - """ - from pyblish import api - - host = api.current_host() - - presets = config.get_presets().get('plugins', {}) - - # iterate over plugins - for plugin in plugins[:]: - # skip if there are no presets to process - if not presets: - continue - - file = os.path.normpath(inspect.getsourcefile(plugin)) - file = os.path.normpath(file) - - # host determined from path - host_from_file = file.split(os.path.sep)[-3:-2][0] - plugin_kind = file.split(os.path.sep)[-2:-1][0] - - try: - config_data = presets[host]["publish"][plugin.__name__] - except KeyError: - try: - config_data = presets[host_from_file][plugin_kind][plugin.__name__] # noqa: E501 - except KeyError: - continue - - for option, value in config_data.items(): - if option == "enabled" and value is False: - log.info('removing plugin {}'.format(plugin.__name__)) - plugins.remove(plugin) - else: - log.info('setting {}:{} on plugin {}'.format( - option, value, plugin.__name__)) - - setattr(plugin, option, value) - - def get_subsets(asset_name, regex_filter=None, version=None, @@ -715,61 +665,6 @@ class CustomNone: return "".format(str(self.identifier)) -def execute_hook(hook, *args, **kwargs): - """ - This will load hook file, instantiate class and call `execute` method - on it. Hook must be in a form: - - `$PYPE_SETUP_PATH/repos/pype/path/to/hook.py/HookClass` - - This will load `hook.py`, instantiate HookClass and then execute_hook - `execute(*args, **kwargs)` - - :param hook: path to hook class - :type hook: str - """ - - class_name = hook.split("/")[-1] - - abspath = os.path.join(os.getenv('PYPE_SETUP_PATH'), - 'repos', 'pype', *hook.split("/")[:-1]) - - mod_name, mod_ext = os.path.splitext(os.path.basename(abspath)) - - if not mod_ext == ".py": - return False - - module = types.ModuleType(mod_name) - module.__file__ = abspath - - try: - with open(abspath) as f: - six.exec_(f.read(), module.__dict__) - - sys.modules[abspath] = module - - except Exception as exp: - log.exception("loading hook failed: {}".format(exp), - exc_info=True) - return False - - obj = getattr(module, class_name) - hook_obj = obj() - ret_val = hook_obj.execute(*args, **kwargs) - return ret_val - - -@six.add_metaclass(ABCMeta) -class PypeHook: - - def __init__(self): - pass - - @abstractmethod - def execute(self, *args, **kwargs): - pass - - def get_linked_assets(asset_entity): """Return linked assets for `asset_entity`.""" inputs = asset_entity["data"].get("inputs", []) diff --git a/pype/lib/plugin_tools.py b/pype/lib/plugin_tools.py new file mode 100644 index 0000000000..066f1ff20a --- /dev/null +++ b/pype/lib/plugin_tools.py @@ -0,0 +1,59 @@ +# -*- coding: utf-8 -*- +"""Avalon/Pyblish plugin tools.""" +import os +import inspect +import logging + +from ..api import config + + +log = logging.getLogger(__name__) + + +def filter_pyblish_plugins(plugins): + """Filter pyblish plugins by presets. + + This servers as plugin filter / modifier for pyblish. It will load plugin + definitions from presets and filter those needed to be excluded. + + Args: + plugins (dict): Dictionary of plugins produced by :mod:`pyblish-base` + `discover()` method. + + """ + from pyblish import api + + host = api.current_host() + + presets = config.get_presets().get('plugins', {}) + + # iterate over plugins + for plugin in plugins[:]: + # skip if there are no presets to process + if not presets: + continue + + file = os.path.normpath(inspect.getsourcefile(plugin)) + file = os.path.normpath(file) + + # host determined from path + host_from_file = file.split(os.path.sep)[-3:-2][0] + plugin_kind = file.split(os.path.sep)[-2:-1][0] + + try: + config_data = presets[host]["publish"][plugin.__name__] + except KeyError: + try: + config_data = presets[host_from_file][plugin_kind][plugin.__name__] # noqa: E501 + except KeyError: + continue + + for option, value in config_data.items(): + if option == "enabled" and value is False: + log.info('removing plugin {}'.format(plugin.__name__)) + plugins.remove(plugin) + else: + log.info('setting {}:{} on plugin {}'.format( + option, value, plugin.__name__)) + + setattr(plugin, option, value)