Refactor the plugin registry

This commit is contained in:
Dave Halter
2019-07-16 12:48:54 +02:00
parent 8329e2e969
commit dea887d27d
6 changed files with 66 additions and 53 deletions
+3
View File
@@ -42,3 +42,6 @@ from jedi.api.environment import find_virtualenvs, find_system_environments, \
get_default_environment, InvalidPythonEnvironment, create_environment, \ get_default_environment, InvalidPythonEnvironment, create_environment, \
get_system_environment get_system_environment
from jedi.api.exceptions import InternalError from jedi.api.exceptions import InternalError
# Finally load the internal plugins. This is only internal.
from jedi.plugins import registry
del registry
+12 -24
View File
@@ -62,8 +62,6 @@ I need to mention now that lazy evaluation is really good because it
only *evaluates* what needs to be *evaluated*. All the statements and modules only *evaluates* what needs to be *evaluated*. All the statements and modules
that are not used are just being ignored. that are not used are just being ignored.
""" """
from functools import partial
from parso.python import tree from parso.python import tree
import parso import parso
from parso import python_bytes_to_unicode from parso import python_bytes_to_unicode
@@ -84,14 +82,7 @@ from jedi.evaluate.context import ClassContext, FunctionContext, \
from jedi.evaluate.context.iterable import CompForContext from jedi.evaluate.context.iterable import CompForContext
from jedi.evaluate.syntax_tree import eval_trailer, eval_expr_stmt, \ from jedi.evaluate.syntax_tree import eval_trailer, eval_expr_stmt, \
eval_node, check_tuple_assignments eval_node, check_tuple_assignments
from jedi.plugins import plugin_manager
def _execute(context, arguments):
debug.dbg('execute: %s %s', context, arguments)
with debug.increase_indent_cm():
context_set = context.py__call__(arguments=arguments)
debug.dbg('execute result: %s in %s', context_set, context)
return context_set
class Evaluator(object): class Evaluator(object):
@@ -119,24 +110,21 @@ class Evaluator(object):
self.reset_recursion_limitations() self.reset_recursion_limitations()
self.allow_different_encoding = True self.allow_different_encoding = True
# Plugin API
from jedi.plugins import plugin_manager
plugin_callbacks = plugin_manager.get_callbacks()
self.execute = plugin_callbacks.decorate('execute', callback=_execute)
self._import_module = partial(
plugin_callbacks.decorate(
'import_module',
callback=imports.import_module
),
self,
)
def import_module(self, import_names, parent_module_context=None, def import_module(self, import_names, parent_module_context=None,
sys_path=None, prefer_stubs=True): sys_path=None, prefer_stubs=True):
if sys_path is None: if sys_path is None:
sys_path = self.get_sys_path() sys_path = self.get_sys_path()
return self._import_module(import_names, parent_module_context, return imports.import_module(self, import_names, parent_module_context,
sys_path, prefer_stubs=prefer_stubs) sys_path, prefer_stubs=prefer_stubs)
@staticmethod
@plugin_manager.decorate()
def execute(context, arguments):
debug.dbg('execute: %s %s', context, arguments)
with debug.increase_indent_cm():
context_set = context.py__call__(arguments=arguments)
debug.dbg('execute result: %s in %s', context_set, context)
return context_set
@property @property
@evaluator_function_cache() @evaluator_function_cache()
+2
View File
@@ -1,5 +1,6 @@
import os import os
import re import re
from functools import wraps
from jedi.file_io import FileIO from jedi.file_io import FileIO
from jedi._compatibility import FileNotFoundError, cast_path from jedi._compatibility import FileNotFoundError, cast_path
@@ -87,6 +88,7 @@ def _cache_stub_file_map(version_info):
def import_module_decorator(func): def import_module_decorator(func):
@wraps(func)
def wrapper(evaluator, import_names, parent_module_context, sys_path, prefer_stubs): def wrapper(evaluator, import_names, parent_module_context, sys_path, prefer_stubs):
try: try:
python_context_set = evaluator.module_cache.get(import_names) python_context_set = evaluator.module_cache.get(import_names)
+3 -1
View File
@@ -21,7 +21,7 @@ from jedi._compatibility import (FileNotFoundError, ImplicitNSInfo,
force_unicode, unicode) force_unicode, unicode)
from jedi import debug from jedi import debug
from jedi import settings from jedi import settings
from jedi.file_io import KnownContentFileIO, FolderIO, FileIO from jedi.file_io import KnownContentFileIO, FileIO
from jedi.parser_utils import get_cached_code_lines from jedi.parser_utils import get_cached_code_lines
from jedi.evaluate import sys_path from jedi.evaluate import sys_path
from jedi.evaluate import helpers from jedi.evaluate import helpers
@@ -33,6 +33,7 @@ from jedi.evaluate.names import ImportName, SubModuleName
from jedi.evaluate.base_context import ContextSet, NO_CONTEXTS from jedi.evaluate.base_context import ContextSet, NO_CONTEXTS
from jedi.evaluate.gradual.typeshed import import_module_decorator from jedi.evaluate.gradual.typeshed import import_module_decorator
from jedi.evaluate.context.module import iter_module_names from jedi.evaluate.context.module import iter_module_names
from jedi.plugins import plugin_manager
class ModuleCache(object): class ModuleCache(object):
@@ -371,6 +372,7 @@ class Importer(object):
return names return names
@plugin_manager.decorate()
@import_module_decorator @import_module_decorator
def import_module(evaluator, import_names, parent_module_context, sys_path): def import_module(evaluator, import_names, parent_module_context, sys_path):
""" """
+36 -28
View File
@@ -1,39 +1,47 @@
from jedi.plugins import stdlib from functools import wraps
from jedi.plugins import flask
class _PluginManager(object): class _PluginManager(object):
def __init__(self, registered_plugin_classes=()): def __init__(self):
self._registered_plugin_classes = list(registered_plugin_classes) self._registered_plugins = []
self._cached_base_callbacks = {}
self._built_functions = {}
def register(self, plugin_class): def register(self, *plugins):
""" """
Makes it possible to register your plugin. Makes it possible to register your plugin.
""" """
self._registered_plugins.append(plugin_class) self._registered_plugins.extend(plugins)
self._build_functions()
def _build_chain(self): def decorate(self):
for plugin_class in self._registered_plugin_classes: def decorator(callback):
yield plugin_class @wraps(callback)
def wrapper(*args, **kwargs):
return built_functions[name](*args, **kwargs)
def get_callbacks(self): name = callback.__name__
return _PluginCallbacks(self._build_chain())
assert name not in self._built_functions
built_functions = self._built_functions
built_functions[name] = callback
self._cached_base_callbacks[name] = callback
return wrapper
return decorator
def _build_functions(self):
for name, callback in self._cached_base_callbacks.items():
for plugin in reversed(self._registered_plugins):
# Need to reverse so the first plugin is run first.
try:
func = getattr(plugin, name)
except AttributeError:
pass
else:
callback = func(callback)
self._built_functions[name] = callback
class _PluginCallbacks(object): plugin_manager = _PluginManager()
def __init__(self, plugins):
self._plugins = list(plugins)
def decorate(self, name, callback):
for plugin in reversed(self._plugins):
# Need to reverse so the first plugin is run first.
try:
func = getattr(plugin, name)
except AttributeError:
pass
else:
callback = func(callback)
return callback
plugin_manager = _PluginManager([stdlib, flask])
+10
View File
@@ -0,0 +1,10 @@
"""
This is not a plugin, this is just the place were plugins are registered.
"""
from jedi.plugins import stdlib
from jedi.plugins import flask
from jedi.plugins import plugin_manager
plugin_manager.register(stdlib, flask)