forked from VimPlug/jedi
Implement support for TypeVar inference for __new__
This commit is contained in:
+3
-1
@@ -10,7 +10,9 @@ Unreleased
|
|||||||
- Removed support for Python 3.8 and 3.9
|
- Removed support for Python 3.8 and 3.9
|
||||||
- Upgraded Typeshed
|
- Upgraded Typeshed
|
||||||
- Better support for Final/ClassVar
|
- Better support for Final/ClassVar
|
||||||
- ``__new__`` is now also recognized as a signature
|
- ``__new__`` is now also recognized as a signature and TypeVar inference
|
||||||
|
- Support for ``Self``
|
||||||
|
- Support for ``TypeAlias``, generics for ``type[...]`` and ``tuple[...]``
|
||||||
|
|
||||||
0.19.2 (2024-11-10)
|
0.19.2 (2024-11-10)
|
||||||
+++++++++++++++++++
|
+++++++++++++++++++
|
||||||
|
|||||||
@@ -17,7 +17,7 @@ from jedi.inference.arguments import ValuesArguments, TreeArgumentsWrapper
|
|||||||
from jedi.inference.value.function import \
|
from jedi.inference.value.function import \
|
||||||
FunctionValue, FunctionMixin, OverloadedFunctionValue, \
|
FunctionValue, FunctionMixin, OverloadedFunctionValue, \
|
||||||
BaseFunctionExecutionContext, FunctionExecutionContext, FunctionNameInClass
|
BaseFunctionExecutionContext, FunctionExecutionContext, FunctionNameInClass
|
||||||
from jedi.inference.value.klass import ClassFilter
|
from jedi.inference.value.klass import ClassFilter, init_or_new_func
|
||||||
from jedi.inference.value.dynamic_arrays import get_dynamic_array_instance
|
from jedi.inference.value.dynamic_arrays import get_dynamic_array_instance
|
||||||
from jedi.parser_utils import function_is_staticmethod, function_is_classmethod
|
from jedi.parser_utils import function_is_staticmethod, function_is_classmethod
|
||||||
|
|
||||||
@@ -327,7 +327,7 @@ class TreeInstance(_BaseTreeInstance):
|
|||||||
infer_type_vars_for_execution
|
infer_type_vars_for_execution
|
||||||
|
|
||||||
args = InstanceArguments(self, self._arguments)
|
args = InstanceArguments(self, self._arguments)
|
||||||
for signature in self.class_value.py__getattribute__('__init__').get_signatures():
|
for signature in init_or_new_func(self.class_value).get_signatures():
|
||||||
# Just take the first result, it should always be one, because we
|
# Just take the first result, it should always be one, because we
|
||||||
# control the typeshed code.
|
# control the typeshed code.
|
||||||
funcdef = signature.value.tree_node
|
funcdef = signature.value.tree_node
|
||||||
|
|||||||
@@ -376,19 +376,8 @@ class ClassMixin:
|
|||||||
if sigs:
|
if sigs:
|
||||||
return sigs
|
return sigs
|
||||||
args = ValuesArguments([])
|
args = ValuesArguments([])
|
||||||
init_funcs = self.py__call__(args).py__getattribute__('__init__')
|
instance = self.py__call__(args)
|
||||||
if len(init_funcs) == 1:
|
init_funcs = init_or_new_func(instance)
|
||||||
init = next(iter(init_funcs))
|
|
||||||
try:
|
|
||||||
class_context = init.class_context
|
|
||||||
except AttributeError:
|
|
||||||
pass
|
|
||||||
else:
|
|
||||||
# In the case where we are on object.__init__, we try to use
|
|
||||||
# __new__.
|
|
||||||
if class_context.get_root_context().is_builtins_module() \
|
|
||||||
and init.class_context.name.string_name == "object":
|
|
||||||
init_funcs = self.py__call__(args).py__getattribute__('__new__')
|
|
||||||
|
|
||||||
dataclass_sigs = self._get_dataclass_transform_signatures()
|
dataclass_sigs = self._get_dataclass_transform_signatures()
|
||||||
if dataclass_sigs:
|
if dataclass_sigs:
|
||||||
@@ -481,6 +470,23 @@ class ClassMixin:
|
|||||||
return ValueSet({self})
|
return ValueSet({self})
|
||||||
|
|
||||||
|
|
||||||
|
def init_or_new_func(value):
|
||||||
|
init_funcs = value.py__getattribute__('__init__')
|
||||||
|
if len(init_funcs) == 1:
|
||||||
|
init = next(iter(init_funcs))
|
||||||
|
try:
|
||||||
|
class_context = init.class_context
|
||||||
|
except AttributeError:
|
||||||
|
pass
|
||||||
|
else:
|
||||||
|
# In the case where we are on object.__init__, we try to use
|
||||||
|
# __new__.
|
||||||
|
if class_context.get_root_context().is_builtins_module() \
|
||||||
|
and init.class_context.name.string_name == "object":
|
||||||
|
return value.py__getattribute__('__new__')
|
||||||
|
return init_funcs
|
||||||
|
|
||||||
|
|
||||||
class DataclassParamName(BaseTreeParamName):
|
class DataclassParamName(BaseTreeParamName):
|
||||||
"""
|
"""
|
||||||
Represent a field declaration on a class with dataclass semantics.
|
Represent a field declaration on a class with dataclass semantics.
|
||||||
|
|||||||
@@ -435,9 +435,9 @@ list(set(list(set(a))))[1]
|
|||||||
list(set(set(a)))[1]
|
list(set(set(a)))[1]
|
||||||
|
|
||||||
# frozenset
|
# frozenset
|
||||||
##? int() str()
|
#? int() str()
|
||||||
list(frozenset(a))[1]
|
list(frozenset(a))[1]
|
||||||
##? int() str()
|
#? int() str()
|
||||||
list(set(frozenset(a)))[1]
|
list(set(frozenset(a)))[1]
|
||||||
|
|
||||||
# iter
|
# iter
|
||||||
|
|||||||
@@ -11,6 +11,7 @@ from typing import (
|
|||||||
TypeVar,
|
TypeVar,
|
||||||
Union,
|
Union,
|
||||||
Sequence,
|
Sequence,
|
||||||
|
Self,
|
||||||
)
|
)
|
||||||
|
|
||||||
K = TypeVar('K')
|
K = TypeVar('K')
|
||||||
@@ -395,3 +396,11 @@ def generic_func2(arg: T) -> Union[int, str, T]: pass
|
|||||||
generic_func1(b"hello")
|
generic_func1(b"hello")
|
||||||
#? int() str() bytes()
|
#? int() str() bytes()
|
||||||
generic_func2(b"hello")
|
generic_func2(b"hello")
|
||||||
|
|
||||||
|
class CustomGeneric2(Generic[T_co]):
|
||||||
|
val: T_co
|
||||||
|
def __init__(cls, val: T_co) -> Self:
|
||||||
|
raise NotImplementedError
|
||||||
|
|
||||||
|
#? int()
|
||||||
|
CustomGeneric2(1).val
|
||||||
|
|||||||
@@ -8,8 +8,6 @@
|
|||||||
#! 12 type-error-not-iterable
|
#! 12 type-error-not-iterable
|
||||||
[a for a in 1]
|
[a for a in 1]
|
||||||
|
|
||||||
# TODO wrong?
|
|
||||||
#! 10 type-error-too-many-arguments
|
|
||||||
tuple(str(a) for a in [1])
|
tuple(str(a) for a in [1])
|
||||||
|
|
||||||
#! 8 type-error-operation
|
#! 8 type-error-operation
|
||||||
|
|||||||
Reference in New Issue
Block a user