diff --git a/jedi/inference/gradual/annotation.py b/jedi/inference/gradual/annotation.py index 7311bfb5..2ad8f979 100644 --- a/jedi/inference/gradual/annotation.py +++ b/jedi/inference/gradual/annotation.py @@ -14,7 +14,7 @@ from jedi.inference.cache import inference_state_method_cache from jedi.inference.base_value import ValueSet, NO_VALUES from jedi.inference.gradual.base import DefineGenericBaseClass, GenericClass from jedi.inference.gradual.generics import TupleGenericManager -from jedi.inference.gradual.type_var import TypeVar +from jedi.inference.gradual.type_var import TypeVar, TypeVarWrapper from jedi.inference.helpers import is_string from jedi.inference.compiled import builtin_from_name from jedi.inference.param import get_executed_param_names @@ -281,7 +281,8 @@ def infer_return_for_callable(arguments, param_values, result_values): return ValueSet.from_sets( v.define_generics(all_type_vars) - if isinstance(v, (DefineGenericBaseClass, TypeVar)) else ValueSet({v}) + if isinstance(v, (DefineGenericBaseClass, TypeVar, TypeVarWrapper)) + else ValueSet({v}) for v in result_values ).execute_annotation() diff --git a/jedi/inference/gradual/type_var.py b/jedi/inference/gradual/type_var.py index 502eaf1f..04dce8ab 100644 --- a/jedi/inference/gradual/type_var.py +++ b/jedi/inference/gradual/type_var.py @@ -102,7 +102,12 @@ class TypeVar(BaseTypingValue): else: if found: return found - return self._get_classes() or ValueSet({self}) + + classes = self._get_classes() + if not classes: + return ValueSet({self}) + + return ValueSet(TypeVarWrapper(cls, self) for cls in classes) def execute_annotation(self): return self._get_classes().execute_annotation() @@ -122,6 +127,15 @@ class TypeVar(BaseTypingValue): return '<%s: %s>' % (self.__class__.__name__, self.py__name__()) +class TypeVarWrapper(ValueWrapper): + def __init__(self, wrapped_value, original_value): + super(TypeVarWrapper, self).__init__(wrapped_value) + self._original_value = original_value + + def define_generics(self, type_var_dict): + return self._original_value.define_generics(type_var_dict) + + class TypeWrapper(ValueWrapper): def __init__(self, wrapped_value, original_value): super(TypeWrapper, self).__init__(wrapped_value) diff --git a/test/completion/pep0484_generic_passthroughs.py b/test/completion/pep0484_generic_passthroughs.py index 31a289c5..63692051 100644 --- a/test/completion/pep0484_generic_passthroughs.py +++ b/test/completion/pep0484_generic_passthroughs.py @@ -250,6 +250,28 @@ is_decorated_by_class_decorator_factory(the_par ) +def decorator_factory_plain() -> Callable[[T], T]: + pass + +#? Callable() +decorator_factory_plain() + +#? +decorator_factory_plain()() + +#? int() +decorator_factory_plain()(42) + +is_decorated_by_plain_factory = decorator_factory_plain()(will_be_decorated) + +#? will_be_decorated +is_decorated_by_plain_factory + +#? ['the_param='] +is_decorated_by_plain_factory(the_par +) + + class class_decorator_factory_bound_callable: def __call__(self, func: TCallable) -> TCallable: ... @@ -270,6 +292,25 @@ is_decorated_by_class_bound_factory(the_par ) +def decorator_factory_bound_callable() -> Callable[[TCallable], TCallable]: + pass + +#? Callable() +decorator_factory_bound_callable() + +#? Callable() +decorator_factory_bound_callable()() + +is_decorated_by_bound_factory = decorator_factory_bound_callable()(will_be_decorated) + +#? will_be_decorated +is_decorated_by_bound_factory + +#? ['the_param='] +is_decorated_by_bound_factory(the_par +) + + class That(Generic[T]): def __init__(self, items: List[Tuple[str, T]]) -> None: pass