From f4cbf616043d843042baa75e5523599e7c3c2954 Mon Sep 17 00:00:00 2001 From: Peter Law Date: Sun, 23 Feb 2020 00:53:41 +0000 Subject: [PATCH] Ensure variadic tuples (Tuple[T, ...]) behave like sequences --- jedi/inference/gradual/annotation.py | 30 ++++++++++++------- .../pep0484_generic_passthroughs.py | 25 +++++++++++++++- 2 files changed, 44 insertions(+), 11 deletions(-) diff --git a/jedi/inference/gradual/annotation.py b/jedi/inference/gradual/annotation.py index 7efff3cd..44f041c5 100644 --- a/jedi/inference/gradual/annotation.py +++ b/jedi/inference/gradual/annotation.py @@ -385,8 +385,6 @@ def _infer_type_vars(annotation_value, value_set, is_class_value=False): ) ) elif annotation_name == 'Tuple': - # TODO: check that this works both for fixed and variadic tuples - # (and maybe for combiantions of those). # TODO: this logic is pretty similar to the general logic below, can # we combine them? @@ -399,20 +397,32 @@ def _infer_type_vars(annotation_value, value_set, is_class_value=False): continue annotation_generics = annotation_value.get_generics() - actual_generics = py_class.get_generics() - for annotation_generics_set, actual_generic_set in zip(annotation_generics, actual_generics): - for nested_annotation_value in annotation_generics_set: + tuple_annotation, = annotation_value.execute_annotation() + # TODO: is can we avoid using this private method? + if tuple_annotation._is_homogenous(): + for nested_annotation_value in annotation_generics[0]: _merge_type_var_dicts( type_var_dict, _infer_type_vars( nested_annotation_value, - actual_generic_set, - # This is a note to ourselves that we - # have already converted the instance - # representation to its class. - is_class_value=True, + value_set.merge_types_of_iterate(), ), ) + else: + actual_generics = py_class.get_generics() + for annotation_generics_set, actual_generic_set in zip(annotation_generics, actual_generics): + for nested_annotation_value in annotation_generics_set: + _merge_type_var_dicts( + type_var_dict, + _infer_type_vars( + nested_annotation_value, + actual_generic_set, + # This is a note to ourselves that we + # have already converted the instance + # representation to its class. + is_class_value=True, + ), + ) elif isinstance(annotation_value, GenericClass): if annotation_name == 'Iterable' and not is_class_value: given = annotation_value.get_generics() diff --git a/test/completion/pep0484_generic_passthroughs.py b/test/completion/pep0484_generic_passthroughs.py index c8a7db7e..3ccdae7a 100644 --- a/test/completion/pep0484_generic_passthroughs.py +++ b/test/completion/pep0484_generic_passthroughs.py @@ -1,5 +1,5 @@ # python >= 3.4 -from typing import Any, Iterable, List, Tuple, TypeVar +from typing import Any, Iterable, List, Sequence, Tuple, TypeVar, Union T = TypeVar('T') U = TypeVar('U') @@ -14,6 +14,9 @@ typed_tuple_str = ('abc',) # type: Tuple[str] untyped_tuple_str_int = ('abc', 4) typed_tuple_str_int = ('abc', 4) # type: Tuple[str, int] +variadic_tuple_str = ('abc',) # type: Tuple[str, ...] +variadic_tuple_str_int = ('abc', 4) # type: Tuple[Union[str, int], ...] + def untyped_passthrough(x): return x @@ -27,6 +30,9 @@ def typed_tuple_generic_passthrough(x: Tuple[T]) -> Tuple[T]: def typed_multi_typed_tuple_generic_passthrough(x: Tuple[T, U]) -> Tuple[U, T]: return x[1], x[0] +def typed_variadic_tuple_generic_passthrough(x: Tuple[T, ...]) -> Sequence[T]: + return x + def typed_iterable_generic_passthrough(x: Iterable[T]) -> Iterable[T]: return x @@ -87,6 +93,23 @@ out_typed[0] out_typed[1] +for j in typed_variadic_tuple_generic_passthrough(untyped_tuple_str_int): + #? str() int() + j + +for k in typed_variadic_tuple_generic_passthrough(typed_tuple_str_int): + #? str() int() + k + +for l in typed_variadic_tuple_generic_passthrough(variadic_tuple_str): + #? str() + l + +for m in typed_variadic_tuple_generic_passthrough(variadic_tuple_str_int): + #? str() int() + m + + for n in typed_fully_generic_passthrough(untyped_list_str): #? str() n