mirror of
https://github.com/davidhalter/jedi.git
synced 2025-12-15 18:17:07 +08:00
Support passing values through decorators from factories
This builds on the approach taken in https://github.com/davidhalter/jedi/pull/1613 but applies it to type vars themselves so that their type var nature is preserved when a function returns Callable[[T], T] and the T has an upper bound.
This commit is contained in:
@@ -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.base_value import ValueSet, NO_VALUES
|
||||||
from jedi.inference.gradual.base import DefineGenericBaseClass, GenericClass
|
from jedi.inference.gradual.base import DefineGenericBaseClass, GenericClass
|
||||||
from jedi.inference.gradual.generics import TupleGenericManager
|
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.helpers import is_string
|
||||||
from jedi.inference.compiled import builtin_from_name
|
from jedi.inference.compiled import builtin_from_name
|
||||||
from jedi.inference.param import get_executed_param_names
|
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(
|
return ValueSet.from_sets(
|
||||||
v.define_generics(all_type_vars)
|
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
|
for v in result_values
|
||||||
).execute_annotation()
|
).execute_annotation()
|
||||||
|
|
||||||
|
|||||||
@@ -102,7 +102,12 @@ class TypeVar(BaseTypingValue):
|
|||||||
else:
|
else:
|
||||||
if found:
|
if found:
|
||||||
return 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):
|
def execute_annotation(self):
|
||||||
return self._get_classes().execute_annotation()
|
return self._get_classes().execute_annotation()
|
||||||
@@ -122,6 +127,15 @@ class TypeVar(BaseTypingValue):
|
|||||||
return '<%s: %s>' % (self.__class__.__name__, self.py__name__())
|
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):
|
class TypeWrapper(ValueWrapper):
|
||||||
def __init__(self, wrapped_value, original_value):
|
def __init__(self, wrapped_value, original_value):
|
||||||
super(TypeWrapper, self).__init__(wrapped_value)
|
super(TypeWrapper, self).__init__(wrapped_value)
|
||||||
|
|||||||
@@ -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:
|
class class_decorator_factory_bound_callable:
|
||||||
def __call__(self, func: TCallable) -> TCallable:
|
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]):
|
class That(Generic[T]):
|
||||||
def __init__(self, items: List[Tuple[str, T]]) -> None:
|
def __init__(self, items: List[Tuple[str, T]]) -> None:
|
||||||
pass
|
pass
|
||||||
|
|||||||
Reference in New Issue
Block a user