diff --git a/pype/__init__.py b/pype/__init__.py index a5858f49e7..bcbedc9a90 100644 --- a/pype/__init__.py +++ b/pype/__init__.py @@ -3,6 +3,8 @@ import os from pyblish import api as pyblish from avalon import api as avalon from .lib import filter_pyblish_plugins +from pypeapp import config + import logging log = logging.getLogger(__name__) @@ -16,6 +18,51 @@ PLUGINS_DIR = os.path.join(PACKAGE_DIR, "plugins") PUBLISH_PATH = os.path.join(PLUGINS_DIR, "global", "publish") LOAD_PATH = os.path.join(PLUGINS_DIR, "global", "load") +# we are monkey patching `avalon.api.discover()` to allow us to load +# plugin presets on plugins being discovered by avalon. Little bit of +# hacking, but it allows us to add out own features without need +# to modify upstream code. + +_original_discover = avalon.discover + + +def patched_discover(superclass): + """ + Monkey patched version of :func:`avalon.api.discover()`. It allows + us to load presets on plugins being discovered. + """ + # run original discover and get plugins + plugins = _original_discover(superclass) + + # determine host application to use for finding presets + host = avalon.registered_host().__name__.split(".")[-1] + + # map plugin superclass to preset json. Currenly suppoted is load and + # create (avalon.api.Loader and avalon.api.Creator) + plugin_type = "undefined" + if superclass.__name__.split(".")[-1] == "Loader": + plugin_type = "load" + elif superclass.__name__.split(".")[-1] == "Creator": + plugin_type = "create" + + print(">>> trying to find presets for {}:{} ...".format(host, plugin_type)) + try: + config_data = config.get_presets()['plugins'][host][plugin_type] + except KeyError: + print("*** no presets found.") + else: + for plugin in plugins: + if plugin.__name__ in config_data: + print(">>> We have preset for {}".format(plugin.__name__)) + for option, value in config_data[plugin.__name__].items(): + if option == "enabled" and value is False: + setattr(plugin, "active", False) + print(" - is disabled by preset") + else: + setattr(plugin, option, value) + print(" - setting `{}`: `{}`".format(option, value)) + return plugins + def install(): log.info("Registering global plug-ins..") @@ -23,6 +70,9 @@ def install(): pyblish.register_discovery_filter(filter_pyblish_plugins) avalon.register_plugin_path(avalon.Loader, LOAD_PATH) + # apply monkey patched discover to original one + avalon.discover = patched_discover + def uninstall(): log.info("Deregistering global plug-ins..") @@ -30,3 +80,6 @@ def uninstall(): pyblish.deregister_discovery_filter(filter_pyblish_plugins) avalon.deregister_plugin_path(avalon.Loader, LOAD_PATH) log.info("Global plug-ins unregistred") + + # restore original discover + avalon.discover = _original_discover diff --git a/pype/tests/test_avalon_plugin_presets.py b/pype/tests/test_avalon_plugin_presets.py new file mode 100644 index 0000000000..7f023ea358 --- /dev/null +++ b/pype/tests/test_avalon_plugin_presets.py @@ -0,0 +1,40 @@ +import avalon.api as api +import pype + + +class MyTestCreator(api.Creator): + + my_test_property = "A" + + def __init__(self, name, asset, options=None, data=None): + super(MyTestCreator, self).__init__(self, name, asset, + options=None, data=None) + + +# this is hack like no other - we need to inject our own avalon host +# and bypass all its validation. Avalon hosts are modules that needs +# `ls` callable as attribute. Voila: +class Test: + __name__ = "test" + ls = len + + def __call__(self): + pass + + +def test_avalon_plugin_presets(monkeypatch, printer): + + pype.install() + api.register_host(Test()) + api.register_plugin(api.Creator, MyTestCreator) + plugins = api.discover(api.Creator) + printer("Test if we got our test plugin") + assert MyTestCreator in plugins + for p in plugins: + if p.__name__ == "MyTestCreator": + printer("Test if we have overriden existing property") + assert p.my_test_property == "B" + printer("Test if we have overriden superclass property") + assert p.active is False + printer("Test if we have added new property") + assert p.new_property == "new"