From abd401f86361db3d3aa4c17d372c28f3bdb84cb4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=2E=20Fernando=20S=C3=A1nchez?= Date: Tue, 2 Jan 2018 11:56:55 +0100 Subject: [PATCH] Enhance plugin metaclass * Change names of plugins to avoid repetitions (we may have to revert this) * Make subprocess log private --- example-plugins/dummy_plugin/dummy_noinfo.py | 4 ++-- example-plugins/noop/noop_plugin.py | 2 +- senpy/plugins/__init__.py | 18 +++++++++++++++--- 3 files changed, 18 insertions(+), 6 deletions(-) diff --git a/example-plugins/dummy_plugin/dummy_noinfo.py b/example-plugins/dummy_plugin/dummy_noinfo.py index 0a653e2..5a46c95 100644 --- a/example-plugins/dummy_plugin/dummy_noinfo.py +++ b/example-plugins/dummy_plugin/dummy_noinfo.py @@ -1,7 +1,7 @@ from senpy.plugins import SentimentPlugin -class DummyPlugin(SentimentPlugin): +class DummyNoInfo(SentimentPlugin): description = 'This is a dummy self-contained plugin' author = '@balkian' @@ -23,5 +23,5 @@ class DummyPlugin(SentimentPlugin): if __name__ == '__main__': - d = DummyPlugin() + d = DummyNoInfo() d.test() diff --git a/example-plugins/noop/noop_plugin.py b/example-plugins/noop/noop_plugin.py index ba851b5..8fd9b56 100644 --- a/example-plugins/noop/noop_plugin.py +++ b/example-plugins/noop/noop_plugin.py @@ -1,5 +1,5 @@ from senpy.plugins import SentimentPlugin -class DummyPlugin(SentimentPlugin): +class NoOp(SentimentPlugin): import noop diff --git a/senpy/plugins/__init__.py b/senpy/plugins/__init__.py index a14d7ae..135cd77 100644 --- a/senpy/plugins/__init__.py +++ b/senpy/plugins/__init__.py @@ -23,6 +23,7 @@ logger = logging.getLogger(__name__) class PluginMeta(models.BaseMeta): + _classes = {} def __new__(mcs, name, bases, attrs, **kwargs): plugin_type = [] @@ -30,7 +31,16 @@ class PluginMeta(models.BaseMeta): plugin_type += bases[0].plugin_type plugin_type.append(name) attrs['plugin_type'] = plugin_type - return super(PluginMeta, mcs).__new__(mcs, name, bases, attrs) + cls = super(PluginMeta, mcs).__new__(mcs, name, bases, attrs) + if name in mcs._classes: + raise Exception(('The type of plugin {} already exists. ' + 'Please, choose a different name').format(name)) + mcs._classes[name] = cls + return cls + + @classmethod + def for_type(cls, ptype): + return cls._classes[ptype] class Plugin(with_metaclass(PluginMeta, models.Plugin)): @@ -234,7 +244,7 @@ def load_module(name, root=None): return tmp -def log_subprocess_output(process): +def _log_subprocess_output(process): for line in iter(process.stdout.readline, b''): logger.info('%r', line) for line in iter(process.stderr.readline, b''): @@ -253,7 +263,7 @@ def install_deps(*plugins): process = subprocess.Popen(pip_args, stdout=subprocess.PIPE, stderr=subprocess.PIPE) - log_subprocess_output(process) + _log_subprocess_output(process) exitcode = process.wait() installed = True if exitcode != 0: @@ -289,6 +299,8 @@ def load_plugin_from_info(info, root=None, validator=validate_info, install=True cls = None if '@type' not in info: cls = get_plugin_class(tmp) + else: + cls = PluginMeta.from_type(info['@type']) if not cls: raise Exception("No valid plugin for: {}".format(module)) return cls(info=info, *args, **kwargs)