diff --git a/jedi/evaluate/gradual/stub_context.py b/jedi/evaluate/gradual/stub_context.py new file mode 100644 index 00000000..9915ed14 --- /dev/null +++ b/jedi/evaluate/gradual/stub_context.py @@ -0,0 +1,384 @@ +from jedi.cache import memoize_method +from jedi.parser_utils import get_call_signature_for_any +from jedi.evaluate.utils import safe_property +from jedi.evaluate.base_context import ContextWrapper +from jedi.evaluate.context.function import FunctionMixin, FunctionContext, MethodContext +from jedi.evaluate.context.klass import ClassMixin, ClassContext +from jedi.evaluate.context.module import ModuleMixin, ModuleContext +from jedi.evaluate.base_context import iterator_to_context_set +from jedi.evaluate.filters import ParserTreeFilter, \ + NameWrapper, AbstractFilter, TreeNameDefinition +from jedi.evaluate.compiled.context import CompiledName +from jedi.evaluate.utils import to_list +from jedi.evaluate.gradual.typing import TypingModuleFilterWrapper, TypingModuleName + + +class _StubContextFilterMixin(object): + def get_filters(self, search_global=False, until_position=None, + origin_scope=None, **kwargs): + filters = self._wrapped_context.get_filters( + search_global, until_position, origin_scope, **kwargs + ) + yield self.stub_context.get_stub_only_filter( + parent_context=self, + # Take the first filter, which is here to filter module contents + # and wrap it. + non_stub_filters=[next(filters)], + search_global=search_global, + until_position=until_position, + origin_scope=origin_scope, + ) + for f in filters: + yield f + + +class StubModuleContext(_StubContextFilterMixin, ModuleMixin, ContextWrapper): + def __init__(self, context, stub_context): + super(StubModuleContext, self).__init__(context) + self.stub_context = stub_context + + +class StubClassContext(_StubContextFilterMixin, ClassMixin, ContextWrapper): + def __init__(self, parent_context, actual_context, stub_context): + super(StubClassContext, self).__init__(actual_context) + self.parent_context = parent_context + self.stub_context = stub_context + + def __getattribute__(self, name): + if name in ('py__getitem__', 'py__simple_getitem__', 'py__bases__', + 'execute_annotation', 'list_type_vars', 'get_signatures'): + # getitem is always done in the stub class. + return getattr(self.stub_context, name) + return super(StubClassContext, self).__getattribute__(name) + + def define_generics(self, type_var_dict): + if not type_var_dict: + return self + return self.stub_context.define_generics(type_var_dict) + + +class StubFunctionContext(FunctionMixin, ContextWrapper): + def __init__(self, parent_context, actual_context, stub_context): + super(StubFunctionContext, self).__init__(actual_context) + self.parent_context = parent_context + self.stub_context = stub_context + + def get_function_execution(self, arguments=None): + return self.stub_context.get_function_execution(arguments) + + def get_signatures(self): + return self.stub_context.get_signatures() + + +class StubMethodContext(StubFunctionContext): + """ + Both of the stub context and the actual context are a stub method. + """ + @safe_property + def class_context(self): + return StubClassContext.create_cached( + self.evaluator, + self.parent_context, + actual_context=self._wrapped_context.class_context, + stub_context=self.stub_context.class_context + ) + + +class _StubOnlyContextMixin(object): + _add_non_stubs_in_filter = False + + def _get_stub_only_filters(self, **filter_kwargs): + return [StubOnlyFilter( + self.evaluator, + context=self, + **filter_kwargs + )] + + def get_stub_only_filter(self, parent_context, non_stub_filters, **filter_kwargs): + # Here we remap the names from stubs to the actual module. This is + # important if type inferences is needed in that module. + return StubFilter( + parent_context, + non_stub_filters, + self._get_stub_only_filters(**filter_kwargs), + add_non_stubs=self._add_non_stubs_in_filter, + ) + + def _get_base_filters(self, filters, search_global=False, + until_position=None, origin_scope=None): + next(filters) # Ignore the first filter and replace it with our own + yield self.get_stub_only_filter( + parent_context=self, + non_stub_filters=list(self._get_first_non_stub_filters()), + search_global=search_global, + until_position=until_position, + origin_scope=origin_scope, + ) + + for f in filters: + yield f + + +class StubOnlyModuleContext(_StubOnlyContextMixin, ModuleContext): + _add_non_stubs_in_filter = True + + def __init__(self, non_stub_context_set, *args, **kwargs): + super(StubOnlyModuleContext, self).__init__(*args, **kwargs) + self.non_stub_context_set = non_stub_context_set + + def _get_first_non_stub_filters(self): + for context in self.non_stub_context_set: + yield next(context.get_filters(search_global=False)) + + def _get_stub_only_filters(self, search_global, **filter_kwargs): + stub_filters = super(StubOnlyModuleContext, self)._get_stub_only_filters( + search_global=search_global, **filter_kwargs + ) + stub_filters += self.iter_star_filters(search_global=search_global) + return stub_filters + + def get_filters(self, search_global=False, until_position=None, + origin_scope=None, **kwargs): + filters = super(StubOnlyModuleContext, self).get_filters( + search_global, until_position, origin_scope, **kwargs + ) + for f in self._get_base_filters(filters, search_global, until_position, origin_scope): + yield f + + +class StubOnlyClass(_StubOnlyContextMixin, ClassMixin, ContextWrapper): + pass + + +class _CompiledStubContext(ContextWrapper): + def __init__(self, stub_context, compiled_context): + super(_CompiledStubContext, self).__init__(stub_context) + self._compiled_context = compiled_context + + def py__doc__(self, include_call_signature=False): + doc = self._compiled_context.py__doc__() + if include_call_signature: + call_sig = get_call_signature_for_any(self._wrapped_context.tree_node) + if call_sig is not None: + doc = call_sig + '\n\n' + doc + return doc + + +class CompiledStubFunction(_CompiledStubContext): + pass + + +class CompiledStubClass(_StubOnlyContextMixin, _CompiledStubContext, ClassMixin): + def _get_first_non_stub_filters(self): + yield next(self._compiled_context.get_filters(search_global=False)) + + def get_filters(self, search_global=False, until_position=None, + origin_scope=None, **kwargs): + filters = self._wrapped_context.get_filters( + search_global, until_position, origin_scope, **kwargs + ) + for f in self._get_base_filters(filters, search_global, until_position, origin_scope): + yield f + + +class TypingModuleWrapper(StubOnlyModuleContext): + # TODO should use this instead of the isinstance check + def get_filterss(self, *args, **kwargs): + filters = super(TypingModuleWrapper, self).get_filters(*args, **kwargs) + yield TypingModuleFilterWrapper(next(filters)) + for f in filters: + yield f + + +class StubName(NameWrapper): + """ + This name is only here to mix stub names with non-stub names. The idea is + that the user can goto the actual name, but end up on the definition of the + stub when inferring types. + """ + def __init__(self, parent_context, non_stub_name, stub_name): + super(StubName, self).__init__(non_stub_name) + self.parent_context = parent_context + self._stub_name = stub_name + + @memoize_method + @iterator_to_context_set + def infer(self): + stub_contexts = self._stub_name.infer() + if not stub_contexts: + for c in self._wrapped_name.infer(): + yield c + return + + typ = self._wrapped_name.tree_name.parent.type + if typ in ('classdef', 'funcdef'): + actual_context, = self._wrapped_name.infer() + for stub_context in stub_contexts: + if isinstance(stub_context, MethodContext): + assert isinstance(actual_context, MethodContext) + cls = StubMethodContext + elif isinstance(stub_context, FunctionContext): + cls = StubFunctionContext + elif isinstance(stub_context, StubOnlyClass): + cls = StubClassContext + else: + yield stub_context + continue + yield cls.create_cached( + actual_context.evaluator, + self.parent_context, + actual_context, + stub_context, + ) + else: + for c in stub_contexts: + yield c + + +class CompiledStubName(NameWrapper): + def __init__(self, parent_context, compiled_name, stub_name): + super(CompiledStubName, self).__init__(stub_name) + self.parent_context = parent_context + self._compiled_name = compiled_name + + @memoize_method + @iterator_to_context_set + def infer(self): + compiled_contexts = self._compiled_name.infer() + stub_contexts = self._wrapped_name.infer() + + if not compiled_contexts: + for c in stub_contexts: + yield c + + for actual_context in compiled_contexts: + for stub_context in stub_contexts: + if isinstance(stub_context, _CompiledStubContext): + # It's already a stub context, e.g. bytes in Python 2 + # behaves this way. + yield stub_context + elif stub_context.is_class(): + assert not isinstance(stub_context, CompiledStubClass), \ + "%s and %s" % (self._wrapped_name, self._compiled_name) + yield CompiledStubClass.create_cached( + stub_context.evaluator, stub_context, actual_context) + elif stub_context.is_function(): + yield CompiledStubFunction.create_cached( + stub_context.evaluator, stub_context, actual_context) + else: + yield stub_context + if not stub_contexts: + yield actual_context + + +class StubOnlyName(TreeNameDefinition): + def infer(self): + inferred = super(StubOnlyName, self).infer() + if self.string_name == 'version_info' and self.get_root_context().py__name__() == 'sys': + return [VersionInfo(c) for c in inferred] + + return [ + StubOnlyClass.create_cached(c.evaluator, c) if isinstance(c, ClassContext) else c + for c in inferred + ] + + +class StubOnlyFilter(ParserTreeFilter): + name_class = StubOnlyName + + def __init__(self, *args, **kwargs): + self._search_global = kwargs.pop('search_global') # Python 2 :/ + super(StubOnlyFilter, self).__init__(*args, **kwargs) + + def _is_name_reachable(self, name): + if not super(StubOnlyFilter, self)._is_name_reachable(name): + return False + + if not self._search_global: + # Imports in stub files are only public if they have an "as" + # export. + definition = name.get_definition() + if definition.type in ('import_from', 'import_name'): + if name.parent.type not in ('import_as_name', 'dotted_as_name'): + return False + n = name.value + if n.startswith('_') and not (n.startswith('__') and n.endswith('__')): + return False + return True + + +class StubFilter(AbstractFilter): + """ + Merging names from stubs and non-stubs. + """ + def __init__(self, parent_context, non_stub_filters, stub_filters, add_non_stubs): + self._parent_context = parent_context + self._non_stub_filters = non_stub_filters + self._stub_filters = stub_filters + self._add_non_stubs = add_non_stubs + + def get(self, name): + non_stub_names = self._get_names_from_filters(self._non_stub_filters, name) + stub_names = self._get_names_from_filters(self._stub_filters, name) + return self._merge_names(non_stub_names, stub_names) + + def values(self): + name_dict = {} + for non_stub_filter in self._non_stub_filters: + for name in non_stub_filter.values(): + name_dict.setdefault(name.string_name, []).append(name) + + # Try to match the names of stubs with non-stubs. If there's no + # match, just use the stub name. The user will be directed there + # for all API accesses. Otherwise the user will be directed to the + # non-stub positions (see StubName). + for stub_filter in self._stub_filters: + for stub_name in stub_filter.values(): + merged_names = self._merge_names( + names=name_dict.get(stub_name.string_name), + stub_names=[stub_name] + ) + for merged_name in merged_names: + yield merged_name + + def _get_names_from_filters(self, filters, string_name): + return [ + name + for filter in filters + for name in filter.get(string_name) + ] + + @to_list + def _merge_names(self, names, stub_names): + if not stub_names: + if self._add_non_stubs: + return names + return [] + if not names: + if isinstance(self._stub_filters[0].context, TypingModuleWrapper): + return [TypingModuleName(n) for n in stub_names] + return stub_names + + result = [] + # The names are contained in both filters. + for name in names: + for stub_name in stub_names: + if isinstance(self._stub_filters[0].context, TypingModuleWrapper): + stub_name = TypingModuleName(stub_name) + + if isinstance(name, CompiledName): + result.append(CompiledStubName(self._parent_context, name, stub_name)) + else: + result.append(StubName(self._parent_context, name, stub_name)) + return result + + def __repr__(self): + return '%s(%s, %s)' % ( + self.__class__.__name__, + self._non_stub_filters, + self._stub_filters, + ) + + +class VersionInfo(ContextWrapper): + pass diff --git a/jedi/evaluate/gradual/typeshed.py b/jedi/evaluate/gradual/typeshed.py index 1b026cc1..06b1ca3b 100644 --- a/jedi/evaluate/gradual/typeshed.py +++ b/jedi/evaluate/gradual/typeshed.py @@ -2,22 +2,12 @@ import os import re from jedi._compatibility import FileNotFoundError +from jedi.parser_utils import get_cached_code_lines 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 -from jedi.evaluate.base_context import ContextSet, iterator_to_context_set, \ - ContextWrapper, NO_CONTEXTS -from jedi.evaluate.filters import ParserTreeFilter, \ - NameWrapper, AbstractFilter, TreeNameDefinition -from jedi.evaluate.context import ModuleContext, FunctionContext, \ - MethodContext, ClassContext -from jedi.evaluate.context.function import FunctionMixin -from jedi.evaluate.context.klass import ClassMixin -from jedi.evaluate.context.module import ModuleMixin -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.base_context import ContextSet, NO_CONTEXTS +from jedi.evaluate.context import ModuleContext +from jedi.evaluate.gradual.stub_context import StubModuleContext, \ + TypingModuleWrapper, StubOnlyModuleContext _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') @@ -184,374 +174,3 @@ def import_module_decorator(func): # If no stub is found, just return the default. return context_set return wrapper - - -class StubName(NameWrapper): - """ - This name is only here to mix stub names with non-stub names. The idea is - that the user can goto the actual name, but end up on the definition of the - stub when inferring types. - """ - def __init__(self, parent_context, non_stub_name, stub_name): - super(StubName, self).__init__(non_stub_name) - self.parent_context = parent_context - self._stub_name = stub_name - - @memoize_method - @iterator_to_context_set - def infer(self): - stub_contexts = self._stub_name.infer() - if not stub_contexts: - for c in self._wrapped_name.infer(): - yield c - return - - typ = self._wrapped_name.tree_name.parent.type - if typ in ('classdef', 'funcdef'): - actual_context, = self._wrapped_name.infer() - for stub_context in stub_contexts: - if isinstance(stub_context, MethodContext): - assert isinstance(actual_context, MethodContext) - cls = StubMethodContext - elif isinstance(stub_context, FunctionContext): - cls = StubFunctionContext - elif isinstance(stub_context, StubOnlyClass): - cls = StubClassContext - else: - yield stub_context - continue - yield cls.create_cached( - actual_context.evaluator, - self.parent_context, - actual_context, - stub_context, - ) - else: - for c in stub_contexts: - yield c - - -class CompiledStubName(NameWrapper): - def __init__(self, parent_context, compiled_name, stub_name): - super(CompiledStubName, self).__init__(stub_name) - self.parent_context = parent_context - self._compiled_name = compiled_name - - @memoize_method - @iterator_to_context_set - def infer(self): - compiled_contexts = self._compiled_name.infer() - stub_contexts = self._wrapped_name.infer() - - if not compiled_contexts: - for c in stub_contexts: - yield c - - for actual_context in compiled_contexts: - for stub_context in stub_contexts: - if isinstance(stub_context, _CompiledStubContext): - # It's already a stub context, e.g. bytes in Python 2 - # behaves this way. - yield stub_context - elif stub_context.is_class(): - assert not isinstance(stub_context, CompiledStubClass), \ - "%s and %s" % (self._wrapped_name, self._compiled_name) - yield CompiledStubClass.create_cached( - stub_context.evaluator, stub_context, actual_context) - elif stub_context.is_function(): - yield CompiledStubFunction.create_cached( - stub_context.evaluator, stub_context, actual_context) - else: - yield stub_context - if not stub_contexts: - yield actual_context - - -class VersionInfo(ContextWrapper): - pass - - -class StubOnlyName(TreeNameDefinition): - def infer(self): - inferred = super(StubOnlyName, self).infer() - if self.string_name == 'version_info' and self.get_root_context().py__name__() == 'sys': - return [VersionInfo(c) for c in inferred] - - return [ - StubOnlyClass.create_cached(c.evaluator, c) if isinstance(c, ClassContext) else c - for c in inferred - ] - - -class StubOnlyFilter(ParserTreeFilter): - name_class = StubOnlyName - - def __init__(self, *args, **kwargs): - self._search_global = kwargs.pop('search_global') # Python 2 :/ - super(StubOnlyFilter, self).__init__(*args, **kwargs) - - def _is_name_reachable(self, name): - if not super(StubOnlyFilter, self)._is_name_reachable(name): - return False - - if not self._search_global: - # Imports in stub files are only public if they have an "as" - # export. - definition = name.get_definition() - if definition.type in ('import_from', 'import_name'): - if name.parent.type not in ('import_as_name', 'dotted_as_name'): - return False - n = name.value - if n.startswith('_') and not (n.startswith('__') and n.endswith('__')): - return False - return True - - -class StubFilter(AbstractFilter): - """ - Merging names from stubs and non-stubs. - """ - def __init__(self, parent_context, non_stub_filters, stub_filters, add_non_stubs): - self._parent_context = parent_context - self._non_stub_filters = non_stub_filters - self._stub_filters = stub_filters - self._add_non_stubs = add_non_stubs - - def get(self, name): - non_stub_names = self._get_names_from_filters(self._non_stub_filters, name) - stub_names = self._get_names_from_filters(self._stub_filters, name) - return self._merge_names(non_stub_names, stub_names) - - def values(self): - name_dict = {} - for non_stub_filter in self._non_stub_filters: - for name in non_stub_filter.values(): - name_dict.setdefault(name.string_name, []).append(name) - - # Try to match the names of stubs with non-stubs. If there's no - # match, just use the stub name. The user will be directed there - # for all API accesses. Otherwise the user will be directed to the - # non-stub positions (see StubName). - for stub_filter in self._stub_filters: - for stub_name in stub_filter.values(): - merged_names = self._merge_names( - names=name_dict.get(stub_name.string_name), - stub_names=[stub_name] - ) - for merged_name in merged_names: - yield merged_name - - def _get_names_from_filters(self, filters, string_name): - return [ - name - for filter in filters - for name in filter.get(string_name) - ] - - @to_list - def _merge_names(self, names, stub_names): - if not stub_names: - if self._add_non_stubs: - return names - return [] - if not names: - if isinstance(self._stub_filters[0].context, TypingModuleWrapper): - return [TypingModuleName(n) for n in stub_names] - return stub_names - - result = [] - # The names are contained in both filters. - for name in names: - for stub_name in stub_names: - if isinstance(self._stub_filters[0].context, TypingModuleWrapper): - stub_name = TypingModuleName(stub_name) - - if isinstance(name, CompiledName): - result.append(CompiledStubName(self._parent_context, name, stub_name)) - else: - result.append(StubName(self._parent_context, name, stub_name)) - return result - - def __repr__(self): - return '%s(%s, %s)' % ( - self.__class__.__name__, - self._non_stub_filters, - self._stub_filters, - ) - - -class _StubContextFilterMixin(object): - def get_filters(self, search_global=False, until_position=None, - origin_scope=None, **kwargs): - filters = self._wrapped_context.get_filters( - search_global, until_position, origin_scope, **kwargs - ) - yield self.stub_context.get_stub_only_filter( - parent_context=self, - # Take the first filter, which is here to filter module contents - # and wrap it. - non_stub_filters=[next(filters)], - search_global=search_global, - until_position=until_position, - origin_scope=origin_scope, - ) - for f in filters: - yield f - - -class StubModuleContext(_StubContextFilterMixin, ModuleMixin, ContextWrapper): - def __init__(self, context, stub_context): - super(StubModuleContext, self).__init__(context) - self.stub_context = stub_context - - -class StubClassContext(_StubContextFilterMixin, ClassMixin, ContextWrapper): - def __init__(self, parent_context, actual_context, stub_context): - super(StubClassContext, self).__init__(actual_context) - self.parent_context = parent_context - self.stub_context = stub_context - - def __getattribute__(self, name): - if name in ('py__getitem__', 'py__simple_getitem__', 'py__bases__', - 'execute_annotation', 'list_type_vars', 'get_signatures'): - # getitem is always done in the stub class. - return getattr(self.stub_context, name) - return super(StubClassContext, self).__getattribute__(name) - - def define_generics(self, type_var_dict): - if not type_var_dict: - return self - return self.stub_context.define_generics(type_var_dict) - - -class StubFunctionContext(FunctionMixin, ContextWrapper): - def __init__(self, parent_context, actual_context, stub_context): - super(StubFunctionContext, self).__init__(actual_context) - self.parent_context = parent_context - self.stub_context = stub_context - - def get_function_execution(self, arguments=None): - return self.stub_context.get_function_execution(arguments) - - def get_signatures(self): - return self.stub_context.get_signatures() - - -class StubMethodContext(StubFunctionContext): - """ - Both of the stub context and the actual context are a stub method. - """ - @safe_property - def class_context(self): - return StubClassContext.create_cached( - self.evaluator, - self.parent_context, - actual_context=self._wrapped_context.class_context, - stub_context=self.stub_context.class_context - ) - - -class _StubOnlyContextMixin(object): - _add_non_stubs_in_filter = False - - def _get_stub_only_filters(self, **filter_kwargs): - return [StubOnlyFilter( - self.evaluator, - context=self, - **filter_kwargs - )] - - def get_stub_only_filter(self, parent_context, non_stub_filters, **filter_kwargs): - # Here we remap the names from stubs to the actual module. This is - # important if type inferences is needed in that module. - return StubFilter( - parent_context, - non_stub_filters, - self._get_stub_only_filters(**filter_kwargs), - add_non_stubs=self._add_non_stubs_in_filter, - ) - - def _get_base_filters(self, filters, search_global=False, - until_position=None, origin_scope=None): - next(filters) # Ignore the first filter and replace it with our own - yield self.get_stub_only_filter( - parent_context=self, - non_stub_filters=list(self._get_first_non_stub_filters()), - search_global=search_global, - until_position=until_position, - origin_scope=origin_scope, - ) - - for f in filters: - yield f - - -class StubOnlyModuleContext(_StubOnlyContextMixin, ModuleContext): - _add_non_stubs_in_filter = True - - def __init__(self, non_stub_context_set, *args, **kwargs): - super(StubOnlyModuleContext, self).__init__(*args, **kwargs) - self.non_stub_context_set = non_stub_context_set - - def _get_first_non_stub_filters(self): - for context in self.non_stub_context_set: - yield next(context.get_filters(search_global=False)) - - def _get_stub_only_filters(self, search_global, **filter_kwargs): - stub_filters = super(StubOnlyModuleContext, self)._get_stub_only_filters( - search_global=search_global, **filter_kwargs - ) - stub_filters += self.iter_star_filters(search_global=search_global) - return stub_filters - - def get_filters(self, search_global=False, until_position=None, - origin_scope=None, **kwargs): - filters = super(StubOnlyModuleContext, self).get_filters( - search_global, until_position, origin_scope, **kwargs - ) - for f in self._get_base_filters(filters, search_global, until_position, origin_scope): - yield f - - -class StubOnlyClass(_StubOnlyContextMixin, ClassMixin, ContextWrapper): - pass - - -class _CompiledStubContext(ContextWrapper): - def __init__(self, stub_context, compiled_context): - super(_CompiledStubContext, self).__init__(stub_context) - self._compiled_context = compiled_context - - def py__doc__(self, include_call_signature=False): - doc = self._compiled_context.py__doc__() - if include_call_signature: - call_sig = get_call_signature_for_any(self._wrapped_context.tree_node) - if call_sig is not None: - doc = call_sig + '\n\n' + doc - return doc - - -class CompiledStubFunction(_CompiledStubContext): - pass - - -class CompiledStubClass(_StubOnlyContextMixin, _CompiledStubContext, ClassMixin): - def _get_first_non_stub_filters(self): - yield next(self._compiled_context.get_filters(search_global=False)) - - def get_filters(self, search_global=False, until_position=None, - origin_scope=None, **kwargs): - filters = self._wrapped_context.get_filters( - search_global, until_position, origin_scope, **kwargs - ) - for f in self._get_base_filters(filters, search_global, until_position, origin_scope): - yield f - - -class TypingModuleWrapper(StubOnlyModuleContext): - # TODO should use this instead of the isinstance check - def get_filterss(self, *args, **kwargs): - filters = super(TypingModuleWrapper, self).get_filters(*args, **kwargs) - yield TypingModuleFilterWrapper(next(filters)) - for f in filters: - yield f diff --git a/jedi/evaluate/syntax_tree.py b/jedi/evaluate/syntax_tree.py index 81593e2e..8ab7ff91 100644 --- a/jedi/evaluate/syntax_tree.py +++ b/jedi/evaluate/syntax_tree.py @@ -24,7 +24,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 +from jedi.evaluate.gradual.stub_context import VersionInfo from jedi.evaluate.gradual import annotation diff --git a/test/test_plugin/test_stub.py b/test/test_plugin/test_stub.py index fee99f3f..c7c2d33c 100644 --- a/test/test_plugin/test_stub.py +++ b/test/test_plugin/test_stub.py @@ -1,6 +1,6 @@ import os -from jedi.evaluate.gradual import typeshed +from jedi.evaluate.gradual import typeshed, stub_context from jedi.evaluate.context import TreeInstance, BoundMethod, FunctionContext from parso.utils import PythonVersionInfo from jedi.evaluate.filters import TreeNameDefinition @@ -48,7 +48,7 @@ def test_function(Script, environment): # it's for now a FunctionContext. expected = FunctionContext else: - expected = typeshed.StubFunctionContext + expected = stub_context.StubFunctionContext code = 'import threading; threading.current_thread' def_, = Script(code).goto_definitions() @@ -58,10 +58,10 @@ def test_function(Script, environment): def_, = Script(code + '()').goto_definitions() context = def_._name._context assert isinstance(context, TreeInstance) - assert isinstance(context.class_context, typeshed.StubOnlyClass), context + assert isinstance(context.class_context, stub_context.StubOnlyClass), context def_, = Script('import threading; threading.Thread').goto_definitions() - assert isinstance(def_._name._context, typeshed.StubClassContext), def_ + assert isinstance(def_._name._context, stub_context.StubClassContext), def_ def test_keywords_variable(Script): @@ -75,20 +75,20 @@ def test_keywords_variable(Script): def test_class(Script): def_, = Script('import threading; threading.Thread').goto_definitions() context = def_._name._context - assert isinstance(context, typeshed.StubClassContext), context + assert isinstance(context, stub_context.StubClassContext), context def test_instance(Script): def_, = Script('import threading; threading.Thread()').goto_definitions() context = def_._name._context assert isinstance(context, TreeInstance) - assert isinstance(context.class_context, typeshed.StubClassContext), context + assert isinstance(context.class_context, stub_context.StubClassContext), context def test_class_function(Script): def_, = Script('import threading; threading.Thread.getName').goto_definitions() context = def_._name._context - assert isinstance(context, typeshed.StubFunctionContext), context + assert isinstance(context, stub_context.StubFunctionContext), context def test_method(Script): @@ -96,7 +96,7 @@ def test_method(Script): def_, = Script(code).goto_definitions() context = def_._name._context assert isinstance(context, BoundMethod), context - assert isinstance(context._wrapped_context, typeshed.StubFunctionContext), context + assert isinstance(context._wrapped_context, stub_context.StubFunctionContext), context def_, = Script(code + '()').goto_definitions() context = def_._name._context @@ -130,7 +130,7 @@ def test_sys_getwindowsversion(Script, environment): def test_sys_hexversion(Script): script = Script('import sys; sys.hexversion') def_, = script.completions() - assert isinstance(def_._name, typeshed.CompiledStubName), def_._name + assert isinstance(def_._name, stub_context.CompiledStubName), def_._name assert isinstance(def_._name._wrapped_name, TreeNameDefinition) assert typeshed._TYPESHED_PATH in def_.module_path def_, = script.goto_definitions()