diff --git a/jedi/evaluate/__init__.py b/jedi/evaluate/__init__.py index 01081a3a..49ccfdb9 100644 --- a/jedi/evaluate/__init__.py +++ b/jedi/evaluate/__init__.py @@ -108,6 +108,8 @@ class Evaluator(object): self.reset_recursion_limitations() self.allow_different_encoding = True + from jedi.plugins import plugin_manager + self.plugin_callbacks = plugin_manager.get_callbacks(self) @property @evaluator_function_cache() diff --git a/jedi/evaluate/base_context.py b/jedi/evaluate/base_context.py index 3f0a198c..b79f1def 100644 --- a/jedi/evaluate/base_context.py +++ b/jedi/evaluate/base_context.py @@ -53,17 +53,17 @@ class Context(BaseContext): except stdlib.NotInStdLib: pass - try: - func = self.py__call__ - except AttributeError: - debug.warning("no execution possible %s", self) - return NO_CONTEXTS - else: - context_set = func(arguments) - debug.dbg('execute result: %s in %s', context_set, self) - return context_set - - return self.evaluator.execute(self, arguments) + def default(arguments): + try: + func = self.py__call__ + except AttributeError: + debug.warning("no execution possible %s", self) + return NO_CONTEXTS + else: + context_set = func(arguments) + debug.dbg('execute result: %s in %s', context_set, self) + return context_set + return self.evaluator.plugin_callbacks.execute(default, arguments) def execute_evaluated(self, *value_list): """ diff --git a/jedi/plugins/__init__.py b/jedi/plugins/__init__.py new file mode 100644 index 00000000..12f08032 --- /dev/null +++ b/jedi/plugins/__init__.py @@ -0,0 +1,43 @@ +from functools import partial + + +class _PluginManager(object): + def __init__(self, registered_plugin_classes=()): + self._registered_plugin_classes = list(registered_plugin_classes) + + def register(self, plugin_class): + """ + Makes it possible to register your plugin. + """ + self._registered_plugins.append(plugin_class) + + def _build_chain(self, evaluator): + for plugin_class in self._registered_plugin_classes: + yield plugin_class(evaluator) + + def get_callbacks(self, evaluator): + return _PluginCallbacks(self._build_chain(evaluator)) + + +class _PluginCallbacks(object): + def __init__(self, plugins): + plugins = list(plugins) + self.execute = self._wrap(plugins, 'execute') + + def _wrap(self, plugins, name): + if not plugins: + def default_callback(callback, *args, **kwargs): + return callback(*args, **kwargs) + + return default_callback + + func = None + for plugin in plugins: + if func is None: + func = getattr(plugin, name) + else: + func = partial(getattr(plugin, name), func) + return func + + +plugin_manager = _PluginManager() diff --git a/jedi/plugins/base.py b/jedi/plugins/base.py new file mode 100644 index 00000000..fc901416 --- /dev/null +++ b/jedi/plugins/base.py @@ -0,0 +1,10 @@ +class BasePlugin(object): + """ + Plugins are created each time an evaluator is created. + """ + def __init__(self, evaluator): + # In __init__ you can do some caching. + self._evaluator = evaluator + + def execute(self, default_callback, arguments): + return default_callback(arguments)