diff --git a/CHANGELOG.rst b/CHANGELOG.rst index 55ecbda4..4e2285fb 100644 --- a/CHANGELOG.rst +++ b/CHANGELOG.rst @@ -10,7 +10,9 @@ Unreleased - Removed support for Python 3.8 and 3.9 - Upgraded Typeshed - 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) +++++++++++++++++++ diff --git a/jedi/inference/value/instance.py b/jedi/inference/value/instance.py index fa15d96f..e397773d 100644 --- a/jedi/inference/value/instance.py +++ b/jedi/inference/value/instance.py @@ -17,7 +17,7 @@ from jedi.inference.arguments import ValuesArguments, TreeArgumentsWrapper from jedi.inference.value.function import \ FunctionValue, FunctionMixin, OverloadedFunctionValue, \ 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.parser_utils import function_is_staticmethod, function_is_classmethod @@ -327,7 +327,7 @@ class TreeInstance(_BaseTreeInstance): infer_type_vars_for_execution 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 # control the typeshed code. funcdef = signature.value.tree_node diff --git a/jedi/inference/value/klass.py b/jedi/inference/value/klass.py index 54eabddf..034fe3e5 100644 --- a/jedi/inference/value/klass.py +++ b/jedi/inference/value/klass.py @@ -376,19 +376,8 @@ class ClassMixin: if sigs: return sigs args = ValuesArguments([]) - init_funcs = self.py__call__(args).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": - init_funcs = self.py__call__(args).py__getattribute__('__new__') + instance = self.py__call__(args) + init_funcs = init_or_new_func(instance) dataclass_sigs = self._get_dataclass_transform_signatures() if dataclass_sigs: @@ -481,6 +470,23 @@ class ClassMixin: 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): """ Represent a field declaration on a class with dataclass semantics. diff --git a/test/completion/arrays.py b/test/completion/arrays.py index f4f76e7b..9df9db58 100644 --- a/test/completion/arrays.py +++ b/test/completion/arrays.py @@ -435,9 +435,9 @@ list(set(list(set(a))))[1] list(set(set(a)))[1] # frozenset -##? int() str() +#? int() str() list(frozenset(a))[1] -##? int() str() +#? int() str() list(set(frozenset(a)))[1] # iter diff --git a/test/completion/pep0484_generic_parameters.py b/test/completion/pep0484_generic_parameters.py index 50fdeba1..c4c4765a 100644 --- a/test/completion/pep0484_generic_parameters.py +++ b/test/completion/pep0484_generic_parameters.py @@ -11,6 +11,7 @@ from typing import ( TypeVar, Union, Sequence, + Self, ) K = TypeVar('K') @@ -395,3 +396,11 @@ def generic_func2(arg: T) -> Union[int, str, T]: pass generic_func1(b"hello") #? int() str() bytes() 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 diff --git a/test/static_analysis/comprehensions.py b/test/static_analysis/comprehensions.py index 9b53048c..8701b112 100644 --- a/test/static_analysis/comprehensions.py +++ b/test/static_analysis/comprehensions.py @@ -8,8 +8,6 @@ #! 12 type-error-not-iterable [a for a in 1] -# TODO wrong? -#! 10 type-error-too-many-arguments tuple(str(a) for a in [1]) #! 8 type-error-operation