Move all the gradual typing stuff into one folder

This commit is contained in:
Dave Halter
2018-12-24 17:40:47 +01:00
parent 025b8bba76
commit e2ab4c060f
14 changed files with 107 additions and 101 deletions

View File

@@ -14,7 +14,7 @@ from jedi.evaluate import imports
from jedi.evaluate import compiled
from jedi.evaluate.imports import ImportName
from jedi.evaluate.context import FunctionExecutionContext
from jedi.plugins.typeshed import StubOnlyModuleContext
from jedi.evaluate.gradual.typeshed import StubOnlyModuleContext
from jedi.api.keywords import KeywordName

View File

@@ -312,7 +312,7 @@ class FunctionExecutionContext(TreeContext):
evaluator = self.evaluator
is_coroutine = self.tree_node.parent.type == 'async_stmt'
is_generator = bool(get_yield_exprs(evaluator, self.tree_node))
from jedi.evaluate.context.typing import AnnotatedSubClass
from jedi.evaluate.gradual.typing import AnnotatedSubClass
if is_coroutine:
if is_generator:

View File

@@ -208,7 +208,7 @@ class Sequence(BuiltinOverwrite, IterableMixin):
@memoize_method
def get_object(self):
from jedi.evaluate.context.typing import AnnotatedSubClass
from jedi.evaluate.gradual.typing import AnnotatedSubClass
klass = compiled.builtin_from_name(self.evaluator, self.array_type)
# TODO is this execute annotation wrong? it returns a context set?!
return AnnotatedSubClass(klass, self._get_generics()).execute_annotation()

View File

@@ -251,7 +251,7 @@ class ClassContext(use_metaclass(CachedMetaClass, ClassMixin, TreeContext)):
)]
def py__getitem__(self, index_context_set, contextualized_node):
from jedi.evaluate.context.typing import AnnotatedClass
from jedi.evaluate.gradual.typing import AnnotatedClass
if not index_context_set:
return ContextSet([self])
return ContextSet(
@@ -264,7 +264,7 @@ class ClassContext(use_metaclass(CachedMetaClass, ClassMixin, TreeContext)):
)
def define_generics(self, type_var_dict):
from jedi.evaluate.context.typing import AnnotatedSubClass
from jedi.evaluate.gradual.typing import AnnotatedSubClass
def remap_type_vars():
for type_var in self.list_type_vars():

View File

@@ -9,7 +9,6 @@ from jedi.evaluate.filters import GlobalNameFilter, ContextNameMixin, \
AbstractNameDefinition, ParserTreeFilter, DictFilter, MergedFilter
from jedi.evaluate import compiled
from jedi.evaluate.base_context import TreeContext
from jedi.evaluate.imports import SubModuleName, infer_import
class _ModuleAttributeName(AbstractNameDefinition):
@@ -84,6 +83,8 @@ class ModuleMixin(object):
Lists modules in the directory of this module (if this module is a
package).
"""
from jedi.evaluate.imports import SubModuleName
names = {}
try:
method = self.py__path__
@@ -120,6 +121,8 @@ class ModuleMixin(object):
# to push the star imports into Evaluator.module_cache, if we reenable this.
@evaluator_method_cache([])
def star_imports(self):
from jedi.evaluate.imports import infer_import
modules = []
for i in self.tree_node.iter_imports():
if i.is_star_import():

View File

@@ -2,7 +2,6 @@ import os
import re
from jedi._compatibility import FileNotFoundError
from jedi.plugins.base import BasePlugin
from jedi.evaluate.cache import evaluator_function_cache
from jedi.cache import memoize_method
from jedi.parser_utils import get_call_signature_for_any, get_cached_code_lines
@@ -15,13 +14,12 @@ from jedi.evaluate.context import ModuleContext, FunctionContext, \
from jedi.evaluate.context.function import FunctionMixin
from jedi.evaluate.context.klass import ClassMixin
from jedi.evaluate.context.module import ModuleMixin
from jedi.evaluate.context.typing import TypingModuleFilterWrapper, \
from jedi.evaluate.gradual.typing import TypingModuleFilterWrapper, \
TypingModuleName
from jedi.evaluate.compiled.context import CompiledName
from jedi.evaluate.utils import to_list, safe_property
from jedi.evaluate.imports import JediImportError
_jedi_path = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
_jedi_path = os.path.dirname(os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
_TYPESHED_PATH = os.path.join(_jedi_path, 'third_party', 'typeshed')
@@ -95,95 +93,97 @@ def _merge_modules(context_set, stub_context):
yield stub_context
class TypeshedPlugin(BasePlugin):
_version_cache = {}
_version_cache = {}
def _cache_stub_file_map(self, version_info):
"""
Returns a map of an importable name in Python to a stub file.
"""
# TODO this caches the stub files indefinitely, maybe use a time cache
# for that?
version = version_info[:2]
def _cache_stub_file_map(version_info):
"""
Returns a map of an importable name in Python to a stub file.
"""
# TODO this caches the stub files indefinitely, maybe use a time cache
# for that?
version = version_info[:2]
try:
return _version_cache[version]
except KeyError:
pass
_version_cache[version] = file_set = \
_merge_create_stub_map(_get_typeshed_directories(version_info))
return file_set
def import_module_decorator(func):
def wrapper(evaluator, import_names, parent_module_context, sys_path):
if import_names == ('_sqlite3',):
# TODO Maybe find a better solution for this?
# The problem is IMO how star imports are priorized and that
# there's no clear ordering.
return NO_CONTEXTS
if import_names == ('os', 'path'):
# This is a huge exception, we follow a nested import
# ``os.path``, because it's a very important one in Python
# that is being achieved by messing with ``sys.modules`` in
# ``os``.
if parent_module_context is None:
parent_module_context, = evaluator.import_module(('os',))
return parent_module_context.py__getattribute__('path')
from jedi.evaluate.imports import JediImportError
try:
return self._version_cache[version]
except KeyError:
pass
context_set = func(
evaluator,
import_names,
parent_module_context,
sys_path
)
except JediImportError:
if import_names == ('typing',):
# TODO this is also quite ugly, please refactor.
context_set = NO_CONTEXTS
else:
raise
self._version_cache[version] = file_set = \
_merge_create_stub_map(_get_typeshed_directories(version_info))
return file_set
import_name = import_names[-1]
map_ = None
if len(import_names) == 1:
map_ = _cache_stub_file_map(evaluator.grammar.version_info)
elif isinstance(parent_module_context, StubModuleContext):
if not parent_module_context.stub_context.is_package():
# Only if it's a package (= a folder) something can be
# imported.
return context_set
path = parent_module_context.stub_context.py__path__()
map_ = _merge_create_stub_map(path)
def import_module(self, callback):
def wrapper(evaluator, import_names, parent_module_context, sys_path):
if import_names == ('_sqlite3',):
# TODO Maybe find a better solution for this?
# The problem is IMO how star imports are priorized and that
# there's no clear ordering.
return NO_CONTEXTS
if import_names == ('os', 'path'):
# This is a huge exception, we follow a nested import
# ``os.path``, because it's a very important one in Python
# that is being achieved by messing with ``sys.modules`` in
# ``os``.
if parent_module_context is None:
parent_module_context, = evaluator.import_module(('os',))
return parent_module_context.py__getattribute__('path')
try:
context_set = callback(
evaluator,
import_names,
parent_module_context,
sys_path
)
except JediImportError:
if import_names == ('typing',):
# TODO this is also quite ugly, please refactor.
context_set = NO_CONTEXTS
if map_ is not None:
path = map_.get(import_name)
if path is not None:
try:
stub_module_node = _load_stub(evaluator, path)
except FileNotFoundError:
# The file has since been removed after looking for it.
# TODO maybe empty cache?
pass
else:
raise
import_name = import_names[-1]
map_ = None
if len(import_names) == 1:
map_ = self._cache_stub_file_map(evaluator.grammar.version_info)
elif isinstance(parent_module_context, StubModuleContext):
if not parent_module_context.stub_context.is_package():
# Only if it's a package (= a folder) something can be
# imported.
return context_set
path = parent_module_context.stub_context.py__path__()
map_ = _merge_create_stub_map(path)
if map_ is not None:
path = map_.get(import_name)
if path is not None:
try:
stub_module_node = _load_stub(evaluator, path)
except FileNotFoundError:
# The file has since been removed after looking for it.
# TODO maybe empty cache?
pass
if import_names == ('typing',):
module_cls = TypingModuleWrapper
else:
if import_names == ('typing',):
module_cls = TypingModuleWrapper
else:
module_cls = StubOnlyModuleContext
stub_module_context = module_cls(
context_set, evaluator, stub_module_node,
path=path,
string_names=import_names,
# The code was loaded with latest_grammar, so use
# that.
code_lines=get_cached_code_lines(evaluator.latest_grammar, path),
)
modules = _merge_modules(context_set, stub_module_context)
return ContextSet(modules)
# If no stub is found, just return the default.
return context_set
return wrapper
module_cls = StubOnlyModuleContext
stub_module_context = module_cls(
context_set, evaluator, stub_module_node,
path=path,
string_names=import_names,
# The code was loaded with latest_grammar, so use
# that.
code_lines=get_cached_code_lines(evaluator.latest_grammar, path),
)
modules = _merge_modules(context_set, stub_module_context)
return ContextSet(modules)
# If no stub is found, just return the default.
return context_set
return wrapper
class StubName(NameWrapper):

View File

@@ -2,6 +2,8 @@
We need to somehow work with the typing objects. Since the typing objects are
pretty bare we need to add all the Jedi customizations to make them work as
contexts.
This file deals with all the typing.py cases.
"""
from jedi._compatibility import unicode, force_unicode
from jedi import debug
@@ -16,7 +18,6 @@ from jedi.evaluate.utils import to_list
from jedi.evaluate.filters import FilterWrapper, NameWrapper, \
AbstractTreeName, AbstractNameDefinition, ContextName
from jedi.evaluate.helpers import is_string
from jedi.evaluate.imports import Importer
from jedi.evaluate.context.klass import ClassMixin
_PROXY_CLASS_TYPES = 'Tuple Generic Protocol Callable Type'.split()
@@ -261,6 +262,8 @@ class TypeAlias(HelperContextMixin):
if self.evaluator.environment.version_info.major == 2 and module_name == 'builtins':
module_name = '__builtin__'
# TODO use evaluator.import_module?
from jedi.evaluate.imports import Importer
module, = Importer(
self.evaluator, [module_name], self.evaluator.builtins_module
).follow()

View File

@@ -30,6 +30,7 @@ from jedi.evaluate.utils import unite
from jedi.evaluate.cache import evaluator_method_cache
from jedi.evaluate.filters import AbstractNameDefinition
from jedi.evaluate.base_context import ContextSet, NO_CONTEXTS
from jedi.evaluate.gradual.typeshed import import_module_decorator
class ModuleCache(object):
@@ -387,6 +388,7 @@ class JediImportError(Exception):
self.import_names = import_names
@import_module_decorator
def import_module(evaluator, import_names, parent_module_context, sys_path):
"""
This method is very similar to importlib's `_gcd_import`.

View File

@@ -26,7 +26,7 @@ from parso import ParserSyntaxError, parse
from jedi._compatibility import force_unicode
from jedi.evaluate.cache import evaluator_method_cache
from jedi.evaluate.base_context import ContextSet, NO_CONTEXTS
from jedi.evaluate.context.typing import TypeVar, AnnotatedClass, \
from jedi.evaluate.gradual.typing import TypeVar, AnnotatedClass, \
AbstractAnnotatedClass
from jedi.evaluate.helpers import is_string
from jedi import debug

View File

@@ -25,6 +25,7 @@ from jedi.evaluate.finder import NameFinder
from jedi.evaluate.helpers import is_string, is_literal, is_number, is_compiled
from jedi.evaluate.compiled.access import COMPARISON_OPERATORS
from jedi.evaluate.cache import evaluator_method_cache
from jedi.evaluate.gradual.typeshed import VersionInfo
def _limit_context_infers(func):
@@ -495,7 +496,6 @@ def _eval_comparison_part(evaluator, context, left, operator, right):
bool_ = operation(left, right)
return ContextSet([_bool_to_context(evaluator, bool_)])
from jedi.plugins.typeshed import VersionInfo
if isinstance(left, VersionInfo):
version_info = _get_tuple_ints(right)
if version_info is not None:

View File

@@ -1,5 +1,4 @@
from jedi.plugins.stdlib import StdlibPlugin
from jedi.plugins.typeshed import TypeshedPlugin
from jedi.plugins.flask import FlaskPlugin
@@ -35,5 +34,4 @@ class _PluginCallbacks(object):
plugin_manager = _PluginManager([
StdlibPlugin,
FlaskPlugin,
TypeshedPlugin,
])

View File

@@ -9,7 +9,7 @@ from pytest import raises
from parso import cache
from jedi import preload_module
from jedi.plugins import typeshed
from jedi.evaluate.gradual import typeshed
def test_preload_modules():

View File

@@ -1,6 +1,6 @@
import os
from jedi.plugins import typeshed
from jedi.evaluate.gradual import typeshed
from jedi.evaluate.context import TreeInstance, BoundMethod, FunctionContext
from parso.utils import PythonVersionInfo
from jedi.evaluate.filters import TreeNameDefinition

View File

@@ -3,7 +3,7 @@ import pytest
from jedi import settings
from jedi.evaluate.filters import ContextName
from jedi.evaluate.compiled import CompiledContextName
from jedi.plugins.typeshed import StubOnlyModuleContext
from jedi.evaluate.gradual.typeshed import StubOnlyModuleContext
@pytest.fixture()