forked from VimPlug/jedi
Start using FileIO in modules
This commit is contained in:
@@ -21,6 +21,7 @@ from jedi.parser_utils import get_executable_nodes
|
||||
from jedi import debug
|
||||
from jedi import settings
|
||||
from jedi import cache
|
||||
from jedi.file_io import KnownContentFileIO
|
||||
from jedi.api import classes
|
||||
from jedi.api import interpreter
|
||||
from jedi.api import helpers
|
||||
@@ -38,8 +39,7 @@ 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
|
||||
from jedi.evaluate.gradual.conversion import try_stubs_to_actual_context_set, \
|
||||
try_stub_to_actual_names
|
||||
from jedi.evaluate.gradual.conversion import try_stub_to_actual_names
|
||||
from jedi.evaluate.gradual.utils import load_proper_stub_module
|
||||
|
||||
# Jedi uses lots and lots of recursion. By setting this a little bit higher, we
|
||||
@@ -164,11 +164,12 @@ class Script(object):
|
||||
names = import_names
|
||||
is_package = is_p
|
||||
|
||||
file_io = KnownContentFileIO(cast_path(self.path), self._code)
|
||||
if self.path is not None and self.path.endswith('.pyi'):
|
||||
# We are in a stub file. Try to load the stub properly.
|
||||
stub_module = load_proper_stub_module(
|
||||
self._evaluator,
|
||||
cast_path(self.path),
|
||||
file_io,
|
||||
names,
|
||||
self._module_node
|
||||
)
|
||||
@@ -179,14 +180,11 @@ class Script(object):
|
||||
names = ('__main__',)
|
||||
|
||||
module = ModuleContext(
|
||||
self._evaluator, self._module_node, cast_path(self.path),
|
||||
self._evaluator, self._module_node, file_io,
|
||||
string_names=names,
|
||||
code_lines=self._code_lines,
|
||||
is_package=is_package,
|
||||
)
|
||||
#module, = try_to_merge_with_stub(
|
||||
# self._evaluator, None, module.string_names, ContextSet([module])
|
||||
#)
|
||||
if names[0] not in ('builtins', '__builtin__', 'typing'):
|
||||
# These modules are essential for Jedi, so don't overwrite them.
|
||||
self._evaluator.module_cache.add(names, ContextSet([module]))
|
||||
@@ -469,7 +467,7 @@ class Interpreter(Script):
|
||||
self._evaluator,
|
||||
self._module_node,
|
||||
self.namespaces,
|
||||
path=self.path,
|
||||
file_io=KnownContentFileIO(self.path, self._code),
|
||||
code_lines=self._code_lines,
|
||||
)
|
||||
|
||||
|
||||
@@ -24,14 +24,14 @@ class MixedModuleContext(Context):
|
||||
# TODO use ContextWrapper!
|
||||
type = 'mixed_module'
|
||||
|
||||
def __init__(self, evaluator, tree_module, namespaces, path, code_lines):
|
||||
def __init__(self, evaluator, tree_module, namespaces, file_io, code_lines):
|
||||
self.evaluator = evaluator
|
||||
self._namespaces = namespaces
|
||||
|
||||
self._namespace_objects = [NamespaceObject(n) for n in namespaces]
|
||||
self._module_context = ModuleContext(
|
||||
evaluator, tree_module,
|
||||
path=path,
|
||||
file_io=file_io,
|
||||
string_names=('__main__',),
|
||||
code_lines=code_lines
|
||||
)
|
||||
|
||||
@@ -11,6 +11,7 @@ from jedi import settings
|
||||
from jedi.evaluate import compiled
|
||||
from jedi.cache import underscore_memoization
|
||||
from jedi.evaluate import imports
|
||||
from jedi.file_io import FileIO
|
||||
from jedi.evaluate.base_context import Context, ContextSet
|
||||
from jedi.evaluate.context import ModuleContext
|
||||
from jedi.evaluate.cache import evaluator_function_cache
|
||||
@@ -140,6 +141,7 @@ def _find_syntax_node_name(evaluator, access_handle):
|
||||
# The path might not exist or be e.g. <stdin>.
|
||||
return None
|
||||
|
||||
file_io = FileIO(path)
|
||||
module_node = _load_module(evaluator, path)
|
||||
|
||||
if inspect.ismodule(python_object):
|
||||
@@ -147,7 +149,7 @@ def _find_syntax_node_name(evaluator, access_handle):
|
||||
# a way to write a module in a module in Python (and also __name__ can
|
||||
# be something like ``email.utils``).
|
||||
code_lines = get_cached_code_lines(evaluator.grammar, path)
|
||||
return module_node, module_node, path, code_lines
|
||||
return module_node, module_node, file_io, code_lines
|
||||
|
||||
try:
|
||||
name_str = python_object.__name__
|
||||
@@ -186,7 +188,7 @@ def _find_syntax_node_name(evaluator, access_handle):
|
||||
# completions at some points but will lead to mostly correct type
|
||||
# inference, because people tend to define a public name in a module only
|
||||
# once.
|
||||
return module_node, names[-1].parent, path, code_lines
|
||||
return module_node, names[-1].parent, file_io, code_lines
|
||||
|
||||
|
||||
@compiled_objects_cache('mixed_cache')
|
||||
@@ -198,7 +200,7 @@ def _create(evaluator, access_handle, parent_context, *args):
|
||||
if result is None:
|
||||
return compiled_object
|
||||
|
||||
module_node, tree_node, path, code_lines = result
|
||||
module_node, tree_node, file_io, code_lines = result
|
||||
|
||||
if parent_context.tree_node.get_root_node() == module_node:
|
||||
module_context = parent_context.get_root_context()
|
||||
@@ -208,7 +210,7 @@ def _create(evaluator, access_handle, parent_context, *args):
|
||||
string_names = tuple(name.split('.'))
|
||||
module_context = ModuleContext(
|
||||
evaluator, module_node,
|
||||
path=path,
|
||||
file_io=file_io,
|
||||
string_names=string_names,
|
||||
code_lines=code_lines,
|
||||
is_package=hasattr(compiled_object, 'py__path__'),
|
||||
|
||||
@@ -173,13 +173,17 @@ class ModuleContext(ModuleMixin, TreeContext):
|
||||
api_type = u'module'
|
||||
parent_context = None
|
||||
|
||||
def __init__(self, evaluator, module_node, path, string_names, code_lines, is_package=False):
|
||||
def __init__(self, evaluator, module_node, file_io, string_names, code_lines, is_package=False):
|
||||
super(ModuleContext, self).__init__(
|
||||
evaluator,
|
||||
parent_context=None,
|
||||
tree_node=module_node
|
||||
)
|
||||
self._path = path
|
||||
self._file_io = file_io
|
||||
if self._file_io is None:
|
||||
self._path = None
|
||||
else:
|
||||
self._path = file_io.path
|
||||
self.string_names = string_names
|
||||
self.code_lines = code_lines
|
||||
self.is_package = is_package
|
||||
|
||||
@@ -4,7 +4,6 @@ import re
|
||||
from jedi.file_io import FileIO
|
||||
from jedi._compatibility import FileNotFoundError, cast_path
|
||||
from jedi.parser_utils import get_cached_code_lines
|
||||
from jedi.evaluate.cache import evaluator_function_cache
|
||||
from jedi.evaluate.base_context import ContextSet
|
||||
from jedi.evaluate.gradual.stub_context import TypingModuleWrapper, StubModuleContext
|
||||
|
||||
@@ -62,11 +61,6 @@ def _get_typeshed_directories(version_info):
|
||||
yield os.path.join(base, check_version)
|
||||
|
||||
|
||||
@evaluator_function_cache()
|
||||
def _load_stub(evaluator, path):
|
||||
return evaluator.parse(file_io=FileIO(path), cache=True, use_latest_grammar=True)
|
||||
|
||||
|
||||
_version_cache = {}
|
||||
|
||||
|
||||
@@ -149,7 +143,12 @@ def _try_to_load_stub(evaluator, import_names, actual_context_set,
|
||||
# foo-stubs
|
||||
for p in sys_path:
|
||||
init = os.path.join(p, *import_names) + '-stubs' + os.path.sep + '__init__.pyi'
|
||||
m = _try_to_load_stub_from_file(evaluator, actual_context_set, init, import_names)
|
||||
m = _try_to_load_stub_from_file(
|
||||
evaluator,
|
||||
actual_context_set,
|
||||
file_io=FileIO(init),
|
||||
import_names=import_names,
|
||||
)
|
||||
if m is not None:
|
||||
return m
|
||||
|
||||
@@ -172,8 +171,8 @@ def _try_to_load_stub(evaluator, import_names, actual_context_set,
|
||||
evaluator,
|
||||
actual_context_set,
|
||||
# The file path should end with .pyi
|
||||
file_path,
|
||||
import_names
|
||||
file_io=FileIO(file_path),
|
||||
import_names=import_names,
|
||||
)
|
||||
if m is not None:
|
||||
return m
|
||||
@@ -202,8 +201,8 @@ def _try_to_load_stub(evaluator, import_names, actual_context_set,
|
||||
m = _try_to_load_stub_from_file(
|
||||
evaluator,
|
||||
actual_context_set,
|
||||
os.path.join(p, *names_for_path) + '.pyi',
|
||||
import_names,
|
||||
file_io=FileIO(os.path.join(p, *names_for_path) + '.pyi'),
|
||||
import_names=import_names,
|
||||
)
|
||||
if m is not None:
|
||||
return m
|
||||
@@ -229,35 +228,44 @@ def _load_from_typeshed(evaluator, actual_context_set, parent_module_context, im
|
||||
if map_ is not None:
|
||||
path = map_.get(import_name)
|
||||
if path is not None:
|
||||
return _try_to_load_stub_from_file(evaluator, actual_context_set, path, import_names)
|
||||
return _try_to_load_stub_from_file(
|
||||
evaluator,
|
||||
actual_context_set,
|
||||
file_io=FileIO(path),
|
||||
import_names=import_names,
|
||||
)
|
||||
|
||||
|
||||
def _try_to_load_stub_from_file(evaluator, actual_context_set, path, import_names):
|
||||
def _try_to_load_stub_from_file(evaluator, actual_context_set, file_io, import_names):
|
||||
try:
|
||||
stub_module_node = _load_stub(evaluator, path)
|
||||
stub_module_node = evaluator.parse(
|
||||
file_io=file_io,
|
||||
cache=True,
|
||||
use_latest_grammar=True
|
||||
)
|
||||
except (OSError, IOError): # IOError is Python 2 only
|
||||
# The file that you're looking for doesn't exist (anymore).
|
||||
return None
|
||||
else:
|
||||
return create_stub_module(
|
||||
evaluator, actual_context_set, stub_module_node, path,
|
||||
evaluator, actual_context_set, stub_module_node, file_io,
|
||||
import_names
|
||||
)
|
||||
|
||||
|
||||
def create_stub_module(evaluator, actual_context_set, stub_module_node, path, import_names):
|
||||
def create_stub_module(evaluator, actual_context_set, stub_module_node, file_io, import_names):
|
||||
if import_names == ('typing',):
|
||||
module_cls = TypingModuleWrapper
|
||||
else:
|
||||
module_cls = StubModuleContext
|
||||
file_name = os.path.basename(path)
|
||||
file_name = os.path.basename(file_io.path)
|
||||
stub_module_context = module_cls(
|
||||
actual_context_set, evaluator, stub_module_node,
|
||||
path=path,
|
||||
file_io=file_io,
|
||||
string_names=import_names,
|
||||
# The code was loaded with latest_grammar, so use
|
||||
# that.
|
||||
code_lines=get_cached_code_lines(evaluator.latest_grammar, path),
|
||||
code_lines=get_cached_code_lines(evaluator.latest_grammar, file_io.path),
|
||||
is_package=file_name == '__init__.pyi',
|
||||
)
|
||||
return stub_module_context
|
||||
|
||||
@@ -3,11 +3,12 @@ import os
|
||||
from jedi.evaluate.gradual.typeshed import TYPESHED_PATH, create_stub_module
|
||||
|
||||
|
||||
def load_proper_stub_module(evaluator, path, import_names, module_node):
|
||||
def load_proper_stub_module(evaluator, file_io, import_names, module_node):
|
||||
"""
|
||||
This function is given a random .pyi file and should return the proper
|
||||
module.
|
||||
"""
|
||||
path = file_io.path
|
||||
assert path.endswith('.pyi')
|
||||
if path.startswith(TYPESHED_PATH):
|
||||
# /foo/stdlib/3/os/__init__.pyi -> stdlib/3/os/__init__
|
||||
@@ -24,7 +25,7 @@ def load_proper_stub_module(evaluator, path, import_names, module_node):
|
||||
return None
|
||||
|
||||
stub = create_stub_module(
|
||||
evaluator, actual_context_set, module_node, path, import_names
|
||||
evaluator, actual_context_set, module_node, file_io, import_names
|
||||
)
|
||||
evaluator.stub_module_cache[import_names] = stub
|
||||
return stub
|
||||
|
||||
@@ -464,7 +464,7 @@ def _load_python_module(evaluator, file_io, sys_path=None,
|
||||
from jedi.evaluate.context import ModuleContext
|
||||
return ModuleContext(
|
||||
evaluator, module_node,
|
||||
path=file_io.path,
|
||||
file_io=file_io,
|
||||
string_names=import_names,
|
||||
code_lines=get_cached_code_lines(evaluator.grammar, file_io.path),
|
||||
is_package=is_package,
|
||||
|
||||
@@ -6,6 +6,7 @@ from jedi.evaluate.base_context import ContextualizedNode
|
||||
from jedi.evaluate.helpers import is_string
|
||||
from jedi.common.utils import traverse_parents
|
||||
from jedi.parser_utils import get_cached_code_lines
|
||||
from jedi.file_io import FileIO
|
||||
from jedi import settings
|
||||
from jedi import debug
|
||||
|
||||
@@ -140,9 +141,10 @@ def discover_buildout_paths(evaluator, script_path):
|
||||
|
||||
|
||||
def _get_paths_from_buildout_script(evaluator, buildout_script_path):
|
||||
file_io = FileIO(buildout_script_path)
|
||||
try:
|
||||
module_node = evaluator.parse(
|
||||
path=buildout_script_path,
|
||||
file_io=file_io,
|
||||
cache=True,
|
||||
cache_path=settings.cache_directory
|
||||
)
|
||||
@@ -152,7 +154,7 @@ def _get_paths_from_buildout_script(evaluator, buildout_script_path):
|
||||
|
||||
from jedi.evaluate.context import ModuleContext
|
||||
module = ModuleContext(
|
||||
evaluator, module_node, buildout_script_path,
|
||||
evaluator, module_node, file_io,
|
||||
string_names=None,
|
||||
code_lines=get_cached_code_lines(evaluator.grammar, buildout_script_path),
|
||||
)
|
||||
|
||||
@@ -437,7 +437,7 @@ def collections_namedtuple(obj, arguments):
|
||||
generated_class = next(module.iter_classdefs())
|
||||
parent_context = ModuleContext(
|
||||
evaluator, module,
|
||||
path=None,
|
||||
file_io=None,
|
||||
string_names=None,
|
||||
code_lines=parso.split_lines(code, keepends=True),
|
||||
)
|
||||
|
||||
Reference in New Issue
Block a user