Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

add support to register plugins by module path #373

Open
wants to merge 4 commits into
base: master
Choose a base branch
from
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
123 changes: 81 additions & 42 deletions pyblish/plugin.py
Original file line number Diff line number Diff line change
Expand Up @@ -1321,69 +1321,108 @@ def discover(type=None, regex=None, paths=None):
# Include plug-ins from registered paths
for path in paths or plugin_paths():
path = os.path.normpath(path)
if not os.path.isdir(path):

if not os.path.exists(path):
continue

for fname in os.listdir(path):
if fname.startswith("_"):
continue
# check if folder or file
if os.path.isdir(path):
file_paths = [os.path.join(path, fname) for fname in os.listdir(path)]
elif os.path.isfile(path):
# todo check if valid path?
file_paths = [path]

abspath = os.path.join(path, fname)
# register plugins from modules in folder
for abspath in file_paths:

if not os.path.isfile(abspath):
continue
module = _valid_plugin_module(abspath)

mod_name, mod_ext = os.path.splitext(fname)
if module:
plugins_in_module = plugins_from_module(module)
_register_plugins_helper(plugins_in_module, plugin_names, plugins, module=module)

if not mod_ext == ".py":
continue
# Include plug-ins from registration.
# Directly registered plug-ins take precedence.
_register_plugins_helper(registered_plugins(), plugin_names, plugins, module=None)

module = types.ModuleType(mod_name)
module.__file__ = abspath
plugins = list(plugins.values())
sort(plugins) # In-place

try:
with open(abspath, "rb") as f:
six.exec_(f.read(), module.__dict__)
# In-place user-defined filter
for filter_ in _registered_plugin_filters:
filter_(plugins)

# Store reference to original module, to avoid
# garbage collection from collecting it's global
# imports, such as `import os`.
sys.modules[abspath] = module
return plugins

except Exception as err:
log.debug("Skipped: \"%s\" (%s)", mod_name, err)
continue

for plugin in plugins_from_module(module):
if not ALLOW_DUPLICATES and plugin.__name__ in plugin_names:
log.debug("Duplicate plug-in found: %s", plugin)
continue
def _valid_plugin_module(abspath):
"""load any"""

plugin_names.append(plugin.__name__)
if '/' in abspath:
split_char = '/'
elif '\\' in abspath:
split_char = '\\'
path, fname = abspath.rsplit(split_char, 1)

plugin.__module__ = module.__file__
key = "{0}.{1}".format(plugin.__module__, plugin.__name__)
plugins[key] = plugin
if fname.startswith("_"):
log.debug('Skipped: private module: "%s"', fname)
return

# Include plug-ins from registration.
# Directly registered plug-ins take precedence.
for plugin in registered_plugins():
if not os.path.isfile(abspath):
log.debug('Skipped: "%s" is not a file', abspath)
return

mod_name, mod_ext = os.path.splitext(fname)

if not mod_ext == ".py":
log.debug('Skipped: "%s" is not a python file', fname)
return

module = types.ModuleType(mod_name)
module.__file__ = abspath

try:
with open(abspath, "rb") as f:
six.exec_(f.read(), module.__dict__)

# Store reference to original module, to avoid
# garbage collection from collecting it's global
# imports, such as `import os`.
sys.modules[abspath] = module

except Exception as err:
log.debug("Skipped: \"%s\" (%s)", mod_name, err)
return

return module


def _register_plugins_helper(plugins_to_register, plugin_names, plugins, module=None):
"""
add the plugin to the dict with the correct key
append the plugin name to plugin_names

arguments:
plugins_to_register: new plugins to register
plugin_names: list of plugin names to append to
plugins: dict of registered plugins

module=None: optional module when importing a plugin from a module instead of a file
"""
for plugin in plugins_to_register:
if not ALLOW_DUPLICATES and plugin.__name__ in plugin_names:
log.debug("Duplicate plug-in found: %s", plugin)
continue

plugin_names.append(plugin.__name__)

plugins[plugin.__name__] = plugin
if module:
plugin.__module__ = module.__file__
key = "{0}.{1}".format(plugin.__module__, plugin.__name__)
else:
key = plugin.__name__

plugins = list(plugins.values())
sort(plugins) # In-place

# In-place user-defined filter
for filter_ in _registered_plugin_filters:
filter_(plugins)

return plugins
plugins[key] = plugin


def plugins_from_module(module):
Expand Down