Remove classes from plugins and use decorators instead

This commit is contained in:
Dave Halter
2019-07-16 10:23:19 +02:00
parent 60415033b4
commit 8329e2e969
5 changed files with 69 additions and 94 deletions

View File

@@ -121,7 +121,7 @@ class Evaluator(object):
# Plugin API # Plugin API
from jedi.plugins import plugin_manager from jedi.plugins import plugin_manager
plugin_callbacks = plugin_manager.get_callbacks(self) plugin_callbacks = plugin_manager.get_callbacks()
self.execute = plugin_callbacks.decorate('execute', callback=_execute) self.execute = plugin_callbacks.decorate('execute', callback=_execute)
self._import_module = partial( self._import_module = partial(
plugin_callbacks.decorate( plugin_callbacks.decorate(

View File

@@ -1,5 +1,5 @@
from jedi.plugins.stdlib import StdlibPlugin from jedi.plugins import stdlib
from jedi.plugins.flask import FlaskPlugin from jedi.plugins import flask
class _PluginManager(object): class _PluginManager(object):
@@ -12,12 +12,12 @@ class _PluginManager(object):
""" """
self._registered_plugins.append(plugin_class) self._registered_plugins.append(plugin_class)
def _build_chain(self, evaluator): def _build_chain(self):
for plugin_class in self._registered_plugin_classes: for plugin_class in self._registered_plugin_classes:
yield plugin_class(evaluator) yield plugin_class
def get_callbacks(self, evaluator): def get_callbacks(self):
return _PluginCallbacks(self._build_chain(evaluator)) return _PluginCallbacks(self._build_chain())
class _PluginCallbacks(object): class _PluginCallbacks(object):
@@ -27,11 +27,13 @@ class _PluginCallbacks(object):
def decorate(self, name, callback): def decorate(self, name, callback):
for plugin in reversed(self._plugins): for plugin in reversed(self._plugins):
# Need to reverse so the first plugin is run first. # Need to reverse so the first plugin is run first.
callback = getattr(plugin, name)(callback) try:
func = getattr(plugin, name)
except AttributeError:
pass
else:
callback = func(callback)
return callback return callback
plugin_manager = _PluginManager([ plugin_manager = _PluginManager([stdlib, flask])
StdlibPlugin,
FlaskPlugin,
])

View File

@@ -1,21 +0,0 @@
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, callback):
"""
Decorates the execute(context, arguments) function.
"""
return callback
def import_module(self, callback):
"""
Decorates the
import_module(evaluator, import_path, sys_path, add_error_callback)
function.
"""
return callback

View File

@@ -1,25 +1,21 @@
from jedi.plugins.base import BasePlugin def import_module(callback):
"""
Handle "magic" Flask extension imports:
class FlaskPlugin(BasePlugin): ``flask.ext.foo`` is really ``flask_foo`` or ``flaskext.foo``.
def import_module(self, callback): """
""" def wrapper(evaluator, import_names, module_context, *args, **kwargs):
Handle "magic" Flask extension imports: if len(import_names) == 3 and import_names[:2] == ('flask', 'ext'):
``flask.ext.foo`` is really ``flask_foo`` or ``flaskext.foo``. # New style.
""" ipath = (u'flask_' + import_names[2]),
def wrapper(evaluator, import_names, module_context, *args, **kwargs): context_set = callback(evaluator, ipath, None, *args, **kwargs)
if len(import_names) == 3 and import_names[:2] == ('flask', 'ext'): if context_set:
# New style. return context_set
ipath = (u'flask_' + import_names[2]), context_set = callback(evaluator, (u'flaskext',), None, *args, **kwargs)
context_set = callback(evaluator, ipath, None, *args, **kwargs) return callback(
if context_set: evaluator,
return context_set (u'flaskext', import_names[2]),
context_set = callback(evaluator, (u'flaskext',), None, *args, **kwargs) next(iter(context_set)),
return callback( *args, **kwargs
evaluator, )
(u'flaskext', import_names[2]), return callback(evaluator, import_names, module_context, *args, **kwargs)
next(iter(context_set)), return wrapper
*args, **kwargs
)
return callback(evaluator, import_names, module_context, *args, **kwargs)
return wrapper

View File

@@ -12,7 +12,6 @@ compiled module that returns the types for C-builtins.
import parso import parso
from jedi._compatibility import force_unicode from jedi._compatibility import force_unicode
from jedi.plugins.base import BasePlugin
from jedi import debug from jedi import debug
from jedi.evaluate.helpers import get_str_or_none from jedi.evaluate.helpers import get_str_or_none
from jedi.evaluate.arguments import ValuesArguments, \ from jedi.evaluate.arguments import ValuesArguments, \
@@ -98,45 +97,44 @@ _NAMEDTUPLE_FIELD_TEMPLATE = '''\
''' '''
class StdlibPlugin(BasePlugin): def execute(callback):
def execute(self, callback): def wrapper(context, arguments):
def wrapper(context, arguments): try:
obj_name = context.name.string_name
except AttributeError:
pass
else:
if context.parent_context == context.evaluator.builtins_module:
module_name = 'builtins'
elif context.parent_context is not None and context.parent_context.is_module():
module_name = context.parent_context.py__name__()
else:
return callback(context, arguments=arguments)
if isinstance(context, BoundMethod):
if module_name == 'builtins':
if context.py__name__() == '__get__':
if context.class_context.py__name__() == 'property':
return builtins_property(
context,
arguments=arguments
)
elif context.py__name__() in ('deleter', 'getter', 'setter'):
if context.class_context.py__name__() == 'property':
return ContextSet([context.instance])
return callback(context, arguments=arguments)
# for now we just support builtin functions.
try: try:
obj_name = context.name.string_name func = _implemented[module_name][obj_name]
except AttributeError: except KeyError:
pass pass
else: else:
if context.parent_context == self._evaluator.builtins_module: return func(context, arguments=arguments)
module_name = 'builtins' return callback(context, arguments=arguments)
elif context.parent_context is not None and context.parent_context.is_module():
module_name = context.parent_context.py__name__()
else:
return callback(context, arguments=arguments)
if isinstance(context, BoundMethod): return wrapper
if module_name == 'builtins':
if context.py__name__() == '__get__':
if context.class_context.py__name__() == 'property':
return builtins_property(
context,
arguments=arguments
)
elif context.py__name__() in ('deleter', 'getter', 'setter'):
if context.class_context.py__name__() == 'property':
return ContextSet([context.instance])
return callback(context, arguments=arguments)
# for now we just support builtin functions.
try:
func = _implemented[module_name][obj_name]
except KeyError:
pass
else:
return func(context, arguments=arguments)
return callback(context, arguments=arguments)
return wrapper
def _follow_param(evaluator, arguments, index): def _follow_param(evaluator, arguments, index):