mirror of
https://github.com/davidhalter/jedi.git
synced 2025-12-06 14:04:26 +08:00
Merge pull request #1553 from PeterJCLaw/generic-tuple-return
Fix construction of nested generic tuple return types
This commit is contained in:
@@ -99,7 +99,7 @@ class DefineGenericBase(LazyValueWrapper):
|
||||
for generic_set in self.get_generics():
|
||||
values = NO_VALUES
|
||||
for generic in generic_set:
|
||||
if isinstance(generic, (GenericClass, TypeVar)):
|
||||
if isinstance(generic, (DefineGenericBase, TypeVar)):
|
||||
result = generic.define_generics(type_var_dict)
|
||||
values |= result
|
||||
if result != ValueSet({generic}):
|
||||
|
||||
@@ -217,9 +217,24 @@ class TypingClassValueWithIndex(_TypingClassMixin, TypingValueWithIndex):
|
||||
|
||||
elif annotation_name == 'Callable':
|
||||
if len(annotation_generics) == 2:
|
||||
return annotation_generics[1].infer_type_vars(
|
||||
value_set.execute_annotation(),
|
||||
)
|
||||
if is_class_value:
|
||||
# This only applies if we are comparing something like
|
||||
# List[Callable[..., T]] with Iterable[Callable[..., T]].
|
||||
# First, Jedi tries to match List/Iterable. After that we
|
||||
# will land here, because is_class_value will be True at
|
||||
# that point. Obviously we also compare below that both
|
||||
# sides are `Callable`.
|
||||
for element in value_set:
|
||||
element_name = element.py__name__()
|
||||
if element_name == 'Callable':
|
||||
merge_type_var_dicts(
|
||||
type_var_dict,
|
||||
merge_pairwise_generics(self, element),
|
||||
)
|
||||
else:
|
||||
return annotation_generics[1].infer_type_vars(
|
||||
value_set.execute_annotation(),
|
||||
)
|
||||
|
||||
elif annotation_name == 'Tuple':
|
||||
tuple_annotation, = self.execute_annotation()
|
||||
|
||||
@@ -206,40 +206,36 @@ for a in list_func_t_to_list_t(12):
|
||||
a
|
||||
|
||||
|
||||
# The following are all actually wrong, however we're mainly testing here that
|
||||
# we don't error when processing invalid values, rather than that we get the
|
||||
# right output.
|
||||
|
||||
x0 = list_func_t_to_list_t(["abc"])[0]
|
||||
#? str()
|
||||
#?
|
||||
x0
|
||||
|
||||
x2 = list_func_t_to_list_t([tpl])[0]
|
||||
#? tuple()
|
||||
#?
|
||||
x2
|
||||
|
||||
x3 = list_func_t_to_list_t([tpl_typed])[0]
|
||||
#? tuple()
|
||||
#?
|
||||
x3
|
||||
|
||||
x4 = list_func_t_to_list_t([collection])[0]
|
||||
#? dict()
|
||||
#?
|
||||
x4
|
||||
|
||||
x5 = list_func_t_to_list_t([collection_typed])[0]
|
||||
#? dict()
|
||||
#?
|
||||
x5
|
||||
|
||||
x6 = list_func_t_to_list_t([custom_generic])[0]
|
||||
#? CustomGeneric()
|
||||
#?
|
||||
x6
|
||||
|
||||
x7 = list_func_t_to_list_t([plain_instance])[0]
|
||||
#? PlainClass()
|
||||
#?
|
||||
x7
|
||||
|
||||
for a in list_func_t_to_list_t([12]):
|
||||
#? int()
|
||||
#?
|
||||
a
|
||||
|
||||
|
||||
|
||||
@@ -6,6 +6,7 @@ from typing import (
|
||||
Iterable,
|
||||
List,
|
||||
Mapping,
|
||||
Tuple,
|
||||
Type,
|
||||
TypeVar,
|
||||
Union,
|
||||
@@ -59,11 +60,32 @@ for b in list_type_t_to_list_t(list_of_int_type):
|
||||
b
|
||||
|
||||
|
||||
def foo(x: T) -> T:
|
||||
# Test construction of nested generic tuple return parameters
|
||||
def list_t_to_list_tuple_t(the_list: List[T]) -> List[Tuple[T]]:
|
||||
return [(x,) for x in the_list]
|
||||
|
||||
|
||||
x1t = list_t_to_list_tuple_t(list_of_ints)[0][0]
|
||||
#? int()
|
||||
x1t
|
||||
|
||||
|
||||
for c1 in list_t_to_list_tuple_t(list_of_ints):
|
||||
#? int()
|
||||
c1[0]
|
||||
|
||||
|
||||
for c2, in list_t_to_list_tuple_t(list_of_ints):
|
||||
#? int()
|
||||
c2
|
||||
|
||||
|
||||
# Test handling of nested callables
|
||||
def foo(x: int) -> int:
|
||||
return x
|
||||
|
||||
|
||||
list_of_funcs = [foo] # type: List[Callable[[T], T]]
|
||||
list_of_funcs = [foo] # type: List[Callable[[int], int]]
|
||||
|
||||
def list_func_t_to_list_func_type_t(the_list: List[Callable[[T], T]]) -> List[Callable[[Type[T]], T]]:
|
||||
def adapt(func: Callable[[T], T]) -> Callable[[Type[T]], T]:
|
||||
@@ -78,6 +100,21 @@ for b in list_func_t_to_list_func_type_t(list_of_funcs):
|
||||
b(int)
|
||||
|
||||
|
||||
def bar(*a, **k) -> int:
|
||||
return len(a) + len(k)
|
||||
|
||||
|
||||
list_of_funcs_2 = [bar] # type: List[Callable[..., int]]
|
||||
|
||||
def list_func_t_passthrough(the_list: List[Callable[..., T]]) -> List[Callable[..., T]]:
|
||||
return the_list
|
||||
|
||||
|
||||
for b in list_func_t_passthrough(list_of_funcs_2):
|
||||
#? int()
|
||||
b(None, x="x")
|
||||
|
||||
|
||||
mapping_int_str = {42: 'a'} # type: Dict[int, str]
|
||||
|
||||
# Test that mappings (that have more than one parameter) are handled
|
||||
|
||||
Reference in New Issue
Block a user