diff --git a/jedi/evaluate/__init__.py b/jedi/evaluate/__init__.py index 49ccfdb9..512e097a 100644 --- a/jedi/evaluate/__init__.py +++ b/jedi/evaluate/__init__.py @@ -85,6 +85,18 @@ from jedi.evaluate.syntax_tree import eval_trailer, eval_expr_stmt, \ eval_node, check_tuple_assignments +def execute(context, arguments): + try: + func = context.py__call__ + except AttributeError: + debug.warning("no execution possible %s", context) + return NO_CONTEXTS + else: + context_set = func(arguments) + debug.dbg('execute result: %s in %s', context_set, context) + return context_set + + class Evaluator(object): def __init__(self, project, environment=None, script_path=None): if environment is None: @@ -109,7 +121,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) + plugin_callbacks = plugin_manager.get_callbacks(self) + self.execute = plugin_callbacks.decorate('execute', callback=execute) @property @evaluator_function_cache() diff --git a/jedi/evaluate/base_context.py b/jedi/evaluate/base_context.py index b79f1def..ca2e074c 100644 --- a/jedi/evaluate/base_context.py +++ b/jedi/evaluate/base_context.py @@ -44,26 +44,7 @@ class Context(BaseContext): if self.evaluator.is_analysis: arguments.eval_all() - debug.dbg('execute: %s %s', self, arguments) - from jedi.evaluate import stdlib - try: - # Some stdlib functions like super(), namedtuple(), etc. have been - # hard-coded in Jedi to support them. - return stdlib.execute(self.evaluator, self, arguments) - except stdlib.NotInStdLib: - pass - - 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) + return self.evaluator.execute(self, arguments) def execute_evaluated(self, *value_list): """ diff --git a/jedi/plugins/__init__.py b/jedi/plugins/__init__.py index 12f08032..abbbd151 100644 --- a/jedi/plugins/__init__.py +++ b/jedi/plugins/__init__.py @@ -1,4 +1,4 @@ -from functools import partial +from jedi.plugins.stdlib import StdlibPlugin class _PluginManager(object): @@ -21,23 +21,15 @@ class _PluginManager(object): class _PluginCallbacks(object): def __init__(self, plugins): - plugins = list(plugins) - self.execute = self._wrap(plugins, 'execute') + self._plugins = list(plugins) - 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 + def decorate(self, name, callback): + for plugin in reversed(self._plugins): + # Need to reverse so the first plugin is run first. + callback = getattr(plugin, name)(callback) + return callback -plugin_manager = _PluginManager() +plugin_manager = _PluginManager([ + StdlibPlugin, +]) diff --git a/jedi/plugins/base.py b/jedi/plugins/base.py index fc901416..62288981 100644 --- a/jedi/plugins/base.py +++ b/jedi/plugins/base.py @@ -6,5 +6,8 @@ class BasePlugin(object): # In __init__ you can do some caching. self._evaluator = evaluator - def execute(self, default_callback, arguments): - return default_callback(arguments) + def execute(self, callback): + """ + Decorates the execute(context, arguments) function. + """ + return callback diff --git a/jedi/plugins/stdlib.py b/jedi/plugins/stdlib.py new file mode 100644 index 00000000..c51b9ead --- /dev/null +++ b/jedi/plugins/stdlib.py @@ -0,0 +1,18 @@ +from jedi import debug +from jedi.plugins.base import BasePlugin + + +class StdlibPlugin(BasePlugin): + def execute(self, callback): + def wrapper(context, arguments): + debug.dbg('execute: %s %s', context, arguments) + from jedi.evaluate import stdlib + try: + # Some stdlib functions like super(), namedtuple(), etc. have been + # hard-coded in Jedi to support them. + return stdlib.execute(self._evaluator, context, arguments) + except stdlib.NotInStdLib: + pass + return callback(context, arguments) + + return wrapper