diff --git a/jedi/inference/base_value.py b/jedi/inference/base_value.py index a7127546..b666f99b 100644 --- a/jedi/inference/base_value.py +++ b/jedi/inference/base_value.py @@ -170,6 +170,9 @@ class Value(HelperValueMixin, BaseValue): def is_bound_method(self): return False + def is_builtins_module(self): + return False + def py__bool__(self): """ Since Wrapper is a super class for classes, functions and modules, diff --git a/jedi/inference/finder.py b/jedi/inference/finder.py index 9a306e07..ce6c9ef7 100644 --- a/jedi/inference/finder.py +++ b/jedi/inference/finder.py @@ -64,7 +64,7 @@ class NameFinder(object): return NO_VALUES return self._found_predefined_types - types = self._names_to_types(names, attribute_lookup) + types = self._names_to_types(names) if not names and self._analysis_errors and not types \ and not (isinstance(self._name, tree.Name) and @@ -184,7 +184,7 @@ class NameFinder(object): inst.get_function_slot_names(u'__getattribute__')) return inst.execute_function_slots(names, name) - def _names_to_types(self, names, attribute_lookup): + def _names_to_types(self, names): values = ValueSet.from_sets(name.infer() for name in names) debug.dbg('finder._names_to_types: %s -> %s', names, values) diff --git a/jedi/inference/gradual/typing.py b/jedi/inference/gradual/typing.py index c6071252..74035703 100644 --- a/jedi/inference/gradual/typing.py +++ b/jedi/inference/gradual/typing.py @@ -20,6 +20,7 @@ from jedi.inference.names import NameWrapper, AbstractTreeName, \ AbstractNameDefinition, ValueName from jedi.inference.helpers import is_string from jedi.inference.value.klass import ClassMixin, ClassFilter +from jedi.inference.context import ClassContext _PROXY_CLASS_TYPES = 'Tuple Generic Protocol Callable Type'.split() _TYPE_ALIAS_TYPES = { @@ -549,21 +550,23 @@ class TypeVarFilter(object): return [] -class AbstractAnnotatedClass(ClassMixin, ValueWrapper): - def get_type_var_filter(self): - return TypeVarFilter(self.get_generics(), self.list_type_vars()) - +class AnnotatedClassContext(ClassContext): def get_filters(self, *args, **kwargs): - filters = super(AbstractAnnotatedClass, self).get_filters( + filters = super(AnnotatedClassContext, self).get_filters( *args, **kwargs ) for f in filters: yield f - if search_global: - # The type vars can only be looked up if it's a global search and - # not a direct lookup on the class. - yield self.get_type_var_filter() + # The type vars can only be looked up if it's a global search and + # not a direct lookup on the class. + yield self._value.get_type_var_filter() + + + +class AbstractAnnotatedClass(ClassMixin, ValueWrapper): + def get_type_var_filter(self): + return TypeVarFilter(self.get_generics(), self.list_type_vars()) def is_same_class(self, other): if not isinstance(other, AbstractAnnotatedClass): @@ -623,6 +626,9 @@ class AbstractAnnotatedClass(ClassMixin, ValueWrapper): generics=tuple(new_generics) )]) + def as_context(self): + return AnnotatedClassContext(self) + def __repr__(self): return '<%s: %s%s>' % ( self.__class__.__name__, diff --git a/jedi/inference/syntax_tree.py b/jedi/inference/syntax_tree.py index 6d1a2f76..8ea441c8 100644 --- a/jedi/inference/syntax_tree.py +++ b/jedi/inference/syntax_tree.py @@ -75,7 +75,7 @@ def infer_node(context, element): if typ in ('name', 'number', 'string', 'atom', 'strings', 'keyword', 'fstring'): return infer_atom(context, element) elif typ == 'lambdef': - return ValueSet([FunctionValue.from_value(context, element)]) + return ValueSet([FunctionValue.from_context(context, element)]) elif typ == 'expr_stmt': return infer_expr_stmt(context, element) elif typ in ('power', 'atom_expr'): @@ -571,8 +571,7 @@ def tree_name_to_values(inference_state, context, tree_name): node = tree_name.parent if node.type == 'global_stmt': c = context.create_context(tree_name) - raise NotImplementedError - finder = NameFinder(inference_state, value, value, tree_name.value) + finder = NameFinder(inference_state, c, c, tree_name.value) filters = finder.get_global_filters() # For global_stmt lookups, we only need the first possible scope, # which means the function itself. @@ -642,7 +641,7 @@ def _apply_decorators(context, node): tree_node=node ) else: - decoratee_value = FunctionValue.from_value(context, node) + decoratee_value = FunctionValue.from_context(context, node) initial = values = ValueSet([decoratee_value]) for dec in reversed(node.get_decorators()): debug.dbg('decorator: %s %s', dec, values, color="MAGENTA") diff --git a/jedi/inference/value/function.py b/jedi/inference/value/function.py index 8c81c602..f5a9a23a 100644 --- a/jedi/inference/value/function.py +++ b/jedi/inference/value/function.py @@ -16,6 +16,7 @@ from jedi.inference.base_value import ValueualizedNode, NO_VALUES, \ ValueSet, TreeValue, ValueWrapper from jedi.inference.lazy_value import LazyKnownValues, LazyKnownValue, \ LazyTreeValue +from jedi.inference.context import AbstractContext from jedi.inference.value import iterable from jedi import parser_utils from jedi.inference.parser_cache import get_yield_exprs @@ -90,7 +91,7 @@ class FunctionMixin(object): if arguments is None: arguments = AnonymousArguments() - return FunctionExecutionContext(self.inference_state, self.parent_context, self, arguments) + return FunctionExecutionContext(self, arguments) def get_signatures(self): return [TreeSignature(f) for f in self.get_signature_functions()] @@ -101,25 +102,25 @@ class FunctionValue(use_metaclass(CachedMetaClass, FunctionMixin, FunctionAndCla return True @classmethod - def from_value(cls, value, tree_node): + def from_context(cls, context, tree_node): def create(tree_node): - if value.is_class(): + if context.is_class(): return MethodValue( - value.inference_state, - value, + context.inference_state, + context, parent_context=parent_context, tree_node=tree_node ) else: return cls( - value.inference_state, + context.inference_state, parent_context=parent_context, tree_node=tree_node ) - overloaded_funcs = list(_find_overload_functions(value, tree_node)) + overloaded_funcs = list(_find_overload_functions(context, tree_node)) - parent_context = value + parent_context = context while parent_context.is_class() or parent_context.is_instance(): parent_context = parent_context.parent_context @@ -160,15 +161,11 @@ class MethodValue(FunctionValue): return names + (self.py__name__(),) -class FunctionExecutionContext(TreeValue): +class FunctionExecutionContext(AbstractContext): function_execution_filter = FunctionExecutionFilter - def __init__(self, inference_state, parent_context, function_value, var_args): - super(FunctionExecutionContext, self).__init__( - inference_state, - parent_context, - function_value.tree_node, - ) + def __init__(self, function_value, var_args): + super(FunctionExecutionContext, self).__init__(function_value) self.function_value = function_value self.var_args = var_args diff --git a/jedi/inference/value/instance.py b/jedi/inference/value/instance.py index f4d3ac39..bb4c0d28 100644 --- a/jedi/inference/value/instance.py +++ b/jedi/inference/value/instance.py @@ -190,7 +190,7 @@ class AbstractInstanceValue(Value): for name in self.get_function_slot_names(u'__init__'): # TODO is this correct? I think we need to check for functions. if isinstance(name, LazyInstanceClassName): - function = FunctionValue.from_value( + function = FunctionValue.from_context( self.parent_context, name.tree_name.parent ) @@ -207,7 +207,7 @@ class AbstractInstanceValue(Value): else: parent_context = self.create_instance_value(class_value, scope) if scope.type == 'funcdef': - func = FunctionValue.from_value( + func = FunctionValue.from_context( parent_context, scope, ) diff --git a/jedi/plugins/stdlib.py b/jedi/plugins/stdlib.py index 3d5e3be7..d92b518e 100644 --- a/jedi/plugins/stdlib.py +++ b/jedi/plugins/stdlib.py @@ -114,10 +114,11 @@ def execute(callback): except AttributeError: pass else: - if value.parent_context.is_builtins_module(): + p = value.parent_context + if p is not None and p.is_builtins_module(): module_name = 'builtins' - elif value.parent_context is not None and value.parent_context.is_module(): - module_name = value.parent_context.py__name__() + elif p is not None and p.is_module(): + module_name = p.py__name__() else: return call() diff --git a/test/run.py b/test/run.py index 40abb8ce..0c29fea3 100755 --- a/test/run.py +++ b/test/run.py @@ -224,14 +224,15 @@ class IntegrationTestCase(object): string = match.group(0) parser = grammar36.parse(string, start_symbol='eval_input', error_recovery=False) parser_utils.move(parser.get_root_node(), self.line_nr) - element = parser.get_root_node() + node = parser.get_root_node() module_context = script._get_module_context() user_context = get_user_context(module_context, (self.line_nr, 0)) - if user_context._value.api_type == 'function': - user_context = user_context.get_function_execution() - element.parent = user_context.tree_node + # TODO needed? + #if user_context._value.api_type == 'function': + # user_context = user_context.get_function_execution() + node.parent = user_context.tree_node results = convert_values( - inference_state.infer_element(user_context, element), + user_context.infer_node(node), ) if not results: raise Exception('Could not resolve %s on line %s'