mirror of
https://github.com/davidhalter/jedi.git
synced 2025-12-06 14:04:26 +08:00
Try to change the module cache
This commit is contained in:
@@ -36,6 +36,7 @@ from jedi.evaluate.sys_path import dotted_path_in_sys_path
|
||||
from jedi.evaluate.filters import TreeNameDefinition, ParamName
|
||||
from jedi.evaluate.syntax_tree import tree_name_to_contexts
|
||||
from jedi.evaluate.context import ModuleContext
|
||||
from jedi.evaluate.base_context import ContextSet
|
||||
from jedi.evaluate.context.iterable import unpack_tuple_to_dict
|
||||
|
||||
# Jedi uses lots and lots of recursion. By setting this a little bit higher, we
|
||||
@@ -143,17 +144,18 @@ class Script(object):
|
||||
debug.reset_time()
|
||||
|
||||
def _get_module(self):
|
||||
name = '__main__'
|
||||
names = ('__main__',)
|
||||
if self.path is not None:
|
||||
import_names = dotted_path_in_sys_path(self._evaluator.get_sys_path(), self.path)
|
||||
if import_names is not None:
|
||||
name = '.'.join(import_names)
|
||||
names = import_names
|
||||
|
||||
module = ModuleContext(
|
||||
self._evaluator, self._module_node, self.path,
|
||||
code_lines=self._code_lines
|
||||
string_names=names,
|
||||
code_lines=self._code_lines,
|
||||
)
|
||||
imports.add_module_to_cache(self._evaluator, name, module)
|
||||
self._evaluator.module_cache.add(names, ContextSet(module))
|
||||
return module
|
||||
|
||||
def __repr__(self):
|
||||
|
||||
@@ -27,6 +27,7 @@ class MixedModuleContext(Context):
|
||||
self.evaluator = evaluator
|
||||
self._namespaces = namespaces
|
||||
|
||||
raise NotImplementedError("module names")
|
||||
self._namespace_objects = [NamespaceObject(n) for n in namespaces]
|
||||
self._module_context = ModuleContext(
|
||||
evaluator, tree_module,
|
||||
|
||||
@@ -62,6 +62,7 @@ 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
|
||||
that are not used are just being ignored.
|
||||
"""
|
||||
from functools import partial
|
||||
|
||||
from parso.python import tree
|
||||
import parso
|
||||
@@ -125,11 +126,24 @@ class Evaluator(object):
|
||||
from jedi.plugins import plugin_manager
|
||||
plugin_callbacks = plugin_manager.get_callbacks(self)
|
||||
self.execute = plugin_callbacks.decorate('execute', callback=_execute)
|
||||
self.import_module = plugin_callbacks.decorate(
|
||||
'import_module',
|
||||
callback=imports.import_module
|
||||
self._import_module = partial(
|
||||
plugin_callbacks.decorate(
|
||||
'import_module',
|
||||
callback=imports.import_module
|
||||
),
|
||||
self,
|
||||
)
|
||||
|
||||
def import_module(self, import_names, parent_module_context, sys_path):
|
||||
try:
|
||||
return ContextSet(self.module_cache.get(import_names))
|
||||
except KeyError:
|
||||
pass
|
||||
|
||||
context_set = self._import_module(import_names, parent_module_context, sys_path)
|
||||
self.module_cache.add(context_set, import_names)
|
||||
return context_set
|
||||
|
||||
@property
|
||||
@evaluator_function_cache()
|
||||
def builtins_module(self):
|
||||
|
||||
@@ -203,6 +203,7 @@ def _create(evaluator, access_handle, parent_context, *args):
|
||||
if parent_context.tree_node.get_root_node() == module_node:
|
||||
module_context = parent_context.get_root_context()
|
||||
else:
|
||||
raise NotImplementedError('module misses string_names arg')
|
||||
module_context = ModuleContext(
|
||||
evaluator, module_node,
|
||||
path=path,
|
||||
|
||||
@@ -42,13 +42,14 @@ class ModuleContext(TreeContext):
|
||||
api_type = u'module'
|
||||
parent_context = None
|
||||
|
||||
def __init__(self, evaluator, module_node, path, code_lines):
|
||||
def __init__(self, evaluator, module_node, path, string_names, code_lines):
|
||||
super(ModuleContext, self).__init__(
|
||||
evaluator,
|
||||
parent_context=None,
|
||||
tree_node=module_node
|
||||
)
|
||||
self._path = path
|
||||
self._string_names = string_names
|
||||
self.code_lines = code_lines
|
||||
|
||||
def get_filters(self, search_global, until_position=None, origin_scope=None):
|
||||
@@ -120,11 +121,7 @@ class ModuleContext(TreeContext):
|
||||
return None
|
||||
|
||||
def py__name__(self):
|
||||
for name, module in self.evaluator.module_cache.iterate_modules_with_names():
|
||||
if module == self and name != '':
|
||||
return name
|
||||
|
||||
return '__main__'
|
||||
return '.'.join(self._string_names)
|
||||
|
||||
def py__file__(self):
|
||||
"""
|
||||
|
||||
@@ -37,16 +37,14 @@ class ModuleCache(object):
|
||||
self._path_cache = {}
|
||||
self._name_cache = {}
|
||||
|
||||
def add(self, module, name):
|
||||
path = module.py__file__()
|
||||
self._path_cache[path] = module
|
||||
self._name_cache[name] = module
|
||||
def add(self, string_names, context_set):
|
||||
#path = module.py__file__()
|
||||
#self._path_cache[path] = context_set
|
||||
if string_names is not None:
|
||||
self._name_cache[string_names] = context_set
|
||||
|
||||
def iterate_modules_with_names(self):
|
||||
return self._name_cache.items()
|
||||
|
||||
def get(self, name):
|
||||
return self._name_cache[name]
|
||||
def get(self, string_names):
|
||||
return self._name_cache[string_names]
|
||||
|
||||
def get_from_path(self, path):
|
||||
return self._path_cache[path]
|
||||
@@ -291,7 +289,6 @@ class Importer(object):
|
||||
try:
|
||||
context_set = ContextSet.from_sets([
|
||||
self._evaluator.import_module(
|
||||
self._evaluator,
|
||||
import_names[:i+1],
|
||||
parent_module_context,
|
||||
self.sys_path_with_modifications(),
|
||||
@@ -410,11 +407,6 @@ def import_module(evaluator, import_names, parent_module_context, sys_path):
|
||||
return ContextSet(module)
|
||||
|
||||
module_name = '.'.join(import_names)
|
||||
try:
|
||||
return ContextSet(evaluator.module_cache.get(module_name))
|
||||
except KeyError:
|
||||
pass
|
||||
|
||||
if parent_module_context is None:
|
||||
debug.dbg('global search_module %s', import_names[-1])
|
||||
# Override the sys.path. It works only good that way.
|
||||
@@ -467,10 +459,6 @@ def _load_module(evaluator, path=None, code=None, sys_path=None,
|
||||
dotted_name = None
|
||||
else:
|
||||
dotted_name = '.'.join(import_names)
|
||||
try:
|
||||
return evaluator.module_cache.get(dotted_name)
|
||||
except KeyError:
|
||||
pass
|
||||
try:
|
||||
return evaluator.module_cache.get_from_path(path)
|
||||
except KeyError:
|
||||
@@ -497,6 +485,7 @@ def _load_module(evaluator, path=None, code=None, sys_path=None,
|
||||
module = ModuleContext(
|
||||
evaluator, module_node,
|
||||
path=path,
|
||||
string_names=import_names,
|
||||
code_lines=get_cached_code_lines(evaluator.grammar, path),
|
||||
)
|
||||
else:
|
||||
@@ -506,23 +495,9 @@ def _load_module(evaluator, path=None, code=None, sys_path=None,
|
||||
# The file might raise an ImportError e.g. and therefore not be
|
||||
# importable.
|
||||
raise JediImportError(import_names)
|
||||
|
||||
if module is not None and dotted_name is not None:
|
||||
add_module_to_cache(evaluator, dotted_name, module, safe=safe_module_name)
|
||||
|
||||
return module
|
||||
|
||||
|
||||
def add_module_to_cache(evaluator, module_name, module, safe=False):
|
||||
if not safe and '.' not in module_name:
|
||||
# We cannot add paths with dots, because that would collide with
|
||||
# the sepatator dots for nested packages. Therefore we return
|
||||
# `__main__` in ModuleWrapper.py__name__(), which is similar to
|
||||
# Python behavior.
|
||||
return
|
||||
evaluator.module_cache.add(module, module_name)
|
||||
|
||||
|
||||
def get_modules_containing_name(evaluator, modules, name):
|
||||
"""
|
||||
Search a name in the directories of modules.
|
||||
@@ -553,6 +528,7 @@ def get_modules_containing_name(evaluator, modules, name):
|
||||
sys_path=e_sys_path,
|
||||
import_names=import_names,
|
||||
)
|
||||
evaluator.module_cache.add(import_names, ContextSet(module))
|
||||
return module
|
||||
|
||||
# skip non python modules
|
||||
|
||||
@@ -151,6 +151,7 @@ def _get_paths_from_buildout_script(evaluator, buildout_script_path):
|
||||
return
|
||||
|
||||
from jedi.evaluate.context import ModuleContext
|
||||
raise NotImplementedError("No module string_names, yet")
|
||||
module = ModuleContext(
|
||||
evaluator, module_node, buildout_script_path,
|
||||
code_lines=get_cached_code_lines(evaluator.grammar, buildout_script_path),
|
||||
|
||||
@@ -289,10 +289,9 @@ def collections_namedtuple(evaluator, obj, arguments):
|
||||
# Parse source code
|
||||
module = evaluator.grammar.parse(code)
|
||||
generated_class = next(module.iter_classdefs())
|
||||
parent_context = ModuleContext(
|
||||
evaluator, module, None,
|
||||
code_lines=parso.split_lines(code, keepends=True),
|
||||
)
|
||||
parent_context = None
|
||||
raise NotImplementedError('TODO implement parent_context')
|
||||
|
||||
return ContextSet(ClassContext(evaluator, parent_context, generated_class))
|
||||
|
||||
|
||||
|
||||
@@ -89,8 +89,9 @@ def _merge_modules(context_set, stub_context):
|
||||
context.evaluator,
|
||||
stub_context,
|
||||
context.tree_node,
|
||||
context._path,
|
||||
context.code_lines
|
||||
path=context._path,
|
||||
string_names=context._string_names,
|
||||
code_lines=context.code_lines
|
||||
)
|
||||
else:
|
||||
# TODO do we want this?
|
||||
@@ -160,7 +161,10 @@ class TypeshedPlugin(BasePlugin):
|
||||
module_cls = StubOnlyModuleContext
|
||||
# TODO use code_lines
|
||||
stub_module_context = module_cls(
|
||||
context_set, evaluator, stub_module_node, path, code_lines=[]
|
||||
context_set, evaluator, stub_module_node,
|
||||
path=path,
|
||||
string_names=import_names,
|
||||
code_lines=[],
|
||||
)
|
||||
modules = _merge_modules(context_set, stub_module_context)
|
||||
return ContextSet.from_iterable(modules)
|
||||
|
||||
Reference in New Issue
Block a user