Merged in feature/PYPE-220/specify-loaded-pyblish-plugins (pull request #185)

feat(pyblish): adding ability to filter and modify plugins based on presets

Approved-by: Milan Kolar <milan@orbi.tools>
This commit is contained in:
Ondřej Samohel 2019-07-09 11:42:04 +00:00 committed by Milan Kolar
commit e7f082a225
7 changed files with 190 additions and 0 deletions

15
.gitignore vendored
View file

@ -12,3 +12,18 @@ __pycache__/
# Editor backup files #
#######################
*~
# Unit test / coverage reports
##############################
htmlcov/
.tox/
.nox/
.coverage
.coverage.*
/coverage
.cache
nosetests.xml
coverage.xml
*.cover
.hypothesis/
.pytest_cache/

0
pype/.coveragerc Normal file
View file

View file

@ -2,6 +2,7 @@ import os
from pyblish import api as pyblish
from avalon import api as avalon
from .lib import filter_pyblish_plugins
import logging
log = logging.getLogger(__name__)
@ -22,10 +23,12 @@ LOAD_PATH = os.path.join(PLUGINS_DIR, "global", "load")
def install():
log.info("Registering global plug-ins..")
pyblish.register_plugin_path(PUBLISH_PATH)
pyblish.register_discovery_filter(filter_pyblish_plugins)
avalon.register_plugin_path(avalon.Loader, LOAD_PATH)
def uninstall():
log.info("Deregistering global plug-ins..")
pyblish.deregister_plugin_path(PUBLISH_PATH)
pyblish.deregister_discovery_filter(filter_pyblish_plugins)
avalon.deregister_plugin_path(avalon.Loader, LOAD_PATH)
log.info("Global plug-ins unregistred")

View file

@ -478,3 +478,35 @@ def get_presets_path():
path_items = [templates, 'presets']
filepath = os.path.sep.join(path_items)
return filepath
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 pypeapp import config
from pyblish import api
host = api.current_host()
# iterate over plugins
for plugin in plugins[:]:
try:
config_data = config.get_presets()['plugins'][host]["publish"][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)

0
pype/tests/__init__.py Normal file
View file

80
pype/tests/lib.py Normal file
View file

@ -0,0 +1,80 @@
import os
import sys
import shutil
import tempfile
import contextlib
import pyblish
import pyblish.cli
import pyblish.plugin
from pyblish.vendor import six
# Setup
HOST = 'python'
FAMILY = 'test.family'
REGISTERED = pyblish.plugin.registered_paths()
PACKAGEPATH = pyblish.lib.main_package_path()
ENVIRONMENT = os.environ.get("PYBLISHPLUGINPATH", "")
PLUGINPATH = os.path.join(PACKAGEPATH, '..', 'tests', 'plugins')
def setup():
pyblish.plugin.deregister_all_paths()
def setup_empty():
"""Disable all plug-ins"""
setup()
pyblish.plugin.deregister_all_plugins()
pyblish.plugin.deregister_all_paths()
pyblish.plugin.deregister_all_hosts()
pyblish.plugin.deregister_all_callbacks()
pyblish.plugin.deregister_all_targets()
pyblish.api.deregister_all_discovery_filters()
def teardown():
"""Restore previously REGISTERED paths"""
pyblish.plugin.deregister_all_paths()
for path in REGISTERED:
pyblish.plugin.register_plugin_path(path)
os.environ["PYBLISHPLUGINPATH"] = ENVIRONMENT
pyblish.api.deregister_all_plugins()
pyblish.api.deregister_all_hosts()
pyblish.api.deregister_all_discovery_filters()
pyblish.api.deregister_test()
pyblish.api.__init__()
@contextlib.contextmanager
def captured_stdout():
"""Temporarily reassign stdout to a local variable"""
try:
sys.stdout = six.StringIO()
yield sys.stdout
finally:
sys.stdout = sys.__stdout__
@contextlib.contextmanager
def captured_stderr():
"""Temporarily reassign stderr to a local variable"""
try:
sys.stderr = six.StringIO()
yield sys.stderr
finally:
sys.stderr = sys.__stderr__
@contextlib.contextmanager
def tempdir():
"""Provide path to temporary directory"""
try:
tempdir = tempfile.mkdtemp()
yield tempdir
finally:
shutil.rmtree(tempdir)

View file

@ -0,0 +1,60 @@
from . import lib
import pyblish.api
import pyblish.util
import pyblish.plugin
from pype.lib import filter_pyblish_plugins
import os
def test_pyblish_plugin_filter_modifier(printer, monkeypatch):
"""
Test if pyblish filter can filter and modify plugins on-the-fly.
"""
lib.setup_empty()
monkeypatch.setitem(os.environ, 'PYBLISHPLUGINPATH', '')
plugins = pyblish.api.registered_plugins()
printer("Test if we have no registered plugins")
assert len(plugins) == 0
paths = pyblish.api.registered_paths()
printer("Test if we have no registered plugin paths")
print(paths)
class MyTestPlugin(pyblish.api.InstancePlugin):
my_test_property = 1
label = "Collect Renderable Camera(s)"
hosts = ["test"]
families = ["default"]
pyblish.api.register_host("test")
pyblish.api.register_plugin(MyTestPlugin)
pyblish.api.register_discovery_filter(filter_pyblish_plugins)
plugins = pyblish.api.discover()
printer("Test if only one plugin was discovered")
assert len(plugins) == 1
printer("Test if properties are modified correctly")
assert plugins[0].label == "loaded from preset"
assert plugins[0].families == ["changed", "by", "preset"]
assert plugins[0].optional is True
lib.teardown()
def test_pyblish_plugin_filter_removal(monkeypatch):
""" Test that plugin can be removed by filter """
lib.setup_empty()
monkeypatch.setitem(os.environ, 'PYBLISHPLUGINPATH', '')
plugins = pyblish.api.registered_plugins()
class MyTestRemovedPlugin(pyblish.api.InstancePlugin):
my_test_property = 1
label = "Collect Renderable Camera(s)"
hosts = ["test"]
families = ["default"]
pyblish.api.register_host("test")
pyblish.api.register_plugin(MyTestRemovedPlugin)
pyblish.api.register_discovery_filter(filter_pyblish_plugins)
plugins = pyblish.api.discover()
assert len(plugins) == 0