diff --git a/jedi/evaluate/arguments.py b/jedi/evaluate/arguments.py index 6faae67d..ae4e58c9 100644 --- a/jedi/evaluate/arguments.py +++ b/jedi/evaluate/arguments.py @@ -159,7 +159,7 @@ class AnonymousArguments(AbstractArguments): execution_context.evaluator, execution_context, execution_context.tree_node - ) + ), [] def __repr__(self): return '%s()' % self.__class__.__name__ diff --git a/jedi/evaluate/context/instance.py b/jedi/evaluate/context/instance.py index 2d97fbb8..9c71d0b4 100644 --- a/jedi/evaluate/context/instance.py +++ b/jedi/evaluate/context/instance.py @@ -27,6 +27,9 @@ class InstanceExecutedParam(object): def infer(self): return ContextSet(self._instance) + def matches_signature(self): + return True + class AnonymousInstanceArguments(AnonymousArguments): def __init__(self, instance): @@ -42,14 +45,14 @@ class AnonymousInstanceArguments(AnonymousArguments): if len(tree_params) == 1: # If the only param is self, we don't need to try to find # executions of this function, we have all the params already. - return [self_param] + return [self_param], [] executed_params = list(search_params( execution_context.evaluator, execution_context, execution_context.tree_node )) executed_params[0] = self_param - return [], executed_params + return executed_params, [] class AbstractInstanceContext(Context): @@ -263,7 +266,7 @@ class TreeInstance(AbstractInstanceContext): @evaluator_method_cache() def get_annotated_class_object(self): - from jedi.evaluate.pep0484 import define_type_vars_for_execution + from jedi.evaluate import pep0484 for func in self._get_annotation_init_functions(): # Just take the first result, it should always be one, because we @@ -274,13 +277,12 @@ class TreeInstance(AbstractInstanceContext): # First check if the signature even matches, if not we don't # need to infer anything. continue - context_set = define_type_vars_for_execution( - ContextSet(self.class_context), - execution, - self.class_context.list_type_vars() + + all_annotations = pep0484.py__annotations__(execution.tree_node) + return pep0484.define_type_vars( + self.class_context, + pep0484.infer_type_vars_for_execution(execution, all_annotations), ) - if context_set: - return next(iter(context_set)) return self.class_context def _get_annotation_init_functions(self): diff --git a/jedi/evaluate/context/klass.py b/jedi/evaluate/context/klass.py index 66fe225d..de199e43 100644 --- a/jedi/evaluate/context/klass.py +++ b/jedi/evaluate/context/klass.py @@ -261,20 +261,16 @@ class ClassContext(use_metaclass(CachedMetaClass, TreeContext)): return self.name.string_name def py__getitem__(self, index_context_set, contextualized_node): - from jedi.evaluate.context.typing import TypingClassMixin, AnnotatedClass - #from pprint import pprint - for cls in py__mro__(self): - if isinstance(cls, TypingClassMixin): - # TODO get the right classes. - return ContextSet.from_iterable( - AnnotatedClass( - self.evaluator, - self.parent_context, - self.tree_node, - index_context, - context_of_index=contextualized_node.context, - ) - for index_context in index_context_set - ) - - return super(ClassContext, self).py__getitem__(index_context_set, contextualized_node) + from jedi.evaluate.context.typing import AnnotatedClass + if not index_context_set: + return ContextSet(self) + return ContextSet.from_iterable( + AnnotatedClass( + self.evaluator, + self.parent_context, + self.tree_node, + index_context, + context_of_index=contextualized_node.context, + ) + for index_context in index_context_set + ) diff --git a/jedi/evaluate/context/typing.py b/jedi/evaluate/context/typing.py index 7b3f5408..5f13a038 100644 --- a/jedi/evaluate/context/typing.py +++ b/jedi/evaluate/context/typing.py @@ -406,7 +406,7 @@ class TypeVar(_BaseTypingContext): return ContextSet.from_sets( l.infer() for l in self._constraints_lazy_contexts ) - debug.warning('Tried to infer the TypeVar %r without a given type', self._var_name) + debug.warning('Tried to infer the TypeVar %s without a given type', self._var_name) return NO_CONTEXTS @property diff --git a/jedi/evaluate/param.py b/jedi/evaluate/param.py index 65bd71e3..23a4190b 100644 --- a/jedi/evaluate/param.py +++ b/jedi/evaluate/param.py @@ -69,7 +69,7 @@ def get_executed_params_and_issues(execution_context, var_args): _add_argument_issue( default_param_context, 'type-error-too-many-arguments', - lazy_context, + argument, message=m ) ) diff --git a/jedi/evaluate/pep0484.py b/jedi/evaluate/pep0484.py index 70c90afd..bdaee016 100644 --- a/jedi/evaluate/pep0484.py +++ b/jedi/evaluate/pep0484.py @@ -221,23 +221,34 @@ def infer_return_types(function_execution_context): if not unknown_type_vars: return context.eval_node(annotation).execute_annotation() - return define_type_vars_for_execution( - context.eval_node(annotation), - function_execution_context, - unknown_type_vars, + annotations_contexts = context.eval_node(annotation) + type_var_dict = infer_type_vars_for_execution(function_execution_context, all_annotations) + + def remap_type_vars(context, type_var_dict): + """ + The TypeVars in the resulting classes have sometimes different names + and we need to check for that, e.g. a signature can be: + + def iter(iterable: Iterable[_T]) -> Iterator[_T]: ... + + However, the iterator is defined as Iterator[_T_co], which means it has + a different type var name. + """ + if isinstance(context, ClassContext): + return { + to.py__name__(): type_var_dict.get(from_.py__name__(), NO_CONTEXTS) + for from_, to in zip(unknown_type_vars, context.list_type_vars()) + } + return type_var_dict + return ContextSet.from_iterable( + define_type_vars( + annotation_context, + remap_type_vars(annotation_context, type_var_dict), + ) for annotation_context in annotations_contexts ).execute_annotation() -def define_type_vars_for_execution(to_define_contexts, execution_context, - unknown_type_vars): - all_annotations = py__annotations__(execution_context.tree_node) - return _define_type_vars( - to_define_contexts, - _infer_type_vars_for_execution(execution_context, all_annotations), - ) - - -def _infer_type_vars_for_execution(execution_context, annotation_dict): +def infer_type_vars_for_execution(execution_context, annotation_dict): """ Some functions use type vars that are not defined by the class, but rather only defined in the function. See for example `iter`. In those cases we @@ -277,26 +288,19 @@ def _infer_type_vars_for_execution(execution_context, annotation_dict): return annotation_variable_results -def _define_type_vars(annotation_contexts, type_var_dict): +def define_type_vars(annotation_context, type_var_dict): def remap_type_vars(cls): for type_var in cls.list_type_vars(): yield type_var_dict.get(type_var.py__name__(), NO_CONTEXTS) - if not type_var_dict: - return annotation_contexts - - context_set = ContextSet() - for annotation_context in annotation_contexts: - if isinstance(annotation_context, ClassContext): - context_set |= ContextSet.from_iterable([ - AnnotatedSubClass( - annotation_context.evaluator, - annotation_context.parent_context, - annotation_context.tree_node, - given_types=tuple(remap_type_vars(annotation_context)) - ) - ]) - return context_set + if type_var_dict and isinstance(annotation_context, ClassContext): + return AnnotatedSubClass( + annotation_context.evaluator, + annotation_context.parent_context, + annotation_context.tree_node, + given_types=tuple(remap_type_vars(annotation_context)) + ) + return annotation_context def _merge_type_var_dicts(base_dict, new_dict): diff --git a/test/completion/arrays.py b/test/completion/arrays.py index 4f5c8e70..3b4f3725 100644 --- a/test/completion/arrays.py +++ b/test/completion/arrays.py @@ -273,9 +273,9 @@ d.values()[0] x, = d.values() #? int() str() x -#? int() +#? int() str() d['a'] -#? int() None +#? int() str() None d.get('a') # -----------------