← Back to index

constructors_call_new.py

True Positive
False Positive
False Negative
Optional (detected)
Warning or Info
TP: 2
FP: 6
FN: 0
Optional: 0 / 0
1"""
2Tests the evaluation of calls to constructors when there is a __new__
3method defined.
4"""
5
6# Specification: https://typing.readthedocs.io/en/latest/spec/constructors.html#new-method
7
8
9from typing import Any, Generic, NoReturn, Self, TypeVar, assert_type
11T = TypeVar("T")
14class Class1(Generic[T]):
15 def __new__(cls, x: T) -> Self:
16 return super().__new__(cls)
19assert_type(Class1[int](1), Class1[int])
20assert_type(Class1[float](1), Class1[float])
21Class1[int](1.0) # E
[invalid-argument-type] Argument to function `__new__` is incorrect: Expected `int`, found `float`
23assert_type(Class1(1), Class1[int])
24assert_type(Class1(1.0), Class1[float])
27class Class2(Generic[T]):
28 def __new__(cls, *args, **kwargs) -> Self:
29 return super().__new__(cls)
31 def __init__(self, x: T) -> None:
32 pass
35assert_type(Class2(1), Class2[int])
36assert_type(Class2(""), Class2[str])
39class Class3:
40 def __new__(cls) -> int:
41 return 0
43 # In this case, the __init__ method should not be considered
44 # by the type checker when evaluating a constructor call.
45 def __init__(self, x: int):
46 pass
49assert_type(Class3(), int)
Unexpected error [type-assertion-failure] Type `int` does not match asserted type `Class3` [missing-argument] No argument provided for required parameter `x` of bound method `__init__`
51# > For purposes of this test, an explicit return type of Any (or a union
52# > containing Any) should be treated as a type that is not an instance of
53# > the class being constructed.
56class Class4:
57 def __new__(cls) -> "Class4 | Any":
58 return 0
60 def __init__(self, x: int):
61 pass
64assert_type(Class4(), Class4 | Any)
Unexpected error [type-assertion-failure] Type `Class4 | Any` does not match asserted type `Class4` [missing-argument] No argument provided for required parameter `x` of bound method `__init__`
67class Class5:
68 def __new__(cls) -> NoReturn:
69 raise NotImplementedError
71 def __init__(self, x: int):
72 pass
75try:
76 assert_type(Class5(), NoReturn)
Unexpected error [type-assertion-failure] Type `Never` does not match asserted type `Class5` [missing-argument] No argument provided for required parameter `x` of bound method `__init__`
77except:
78 pass
81class Class6:
82 def __new__(cls) -> "int | Class6":
83 return 0
85 def __init__(self, x: int):
86 pass
89assert_type(Class6(), int | Class6)
Unexpected error [type-assertion-failure] Type `int | Class6` does not match asserted type `Class6` [missing-argument] No argument provided for required parameter `x` of bound method `__init__`
91# > If the return type of __new__ is not annotated, a type checker may assume
92# > that the return type is Self and proceed with the assumption that the
93# > __init__ method will be called.
96class Class7:
97 def __new__(cls, *args, **kwargs):
98 return super().__new__(cls, *args, **kwargs)
100 def __init__(self, x: int):
101 pass
104assert_type(Class7(1), Class7)
107# > If the class is generic, it is possible for a __new__ method to override
108# > the specialized class type and return a class instance that is specialized
109# > with different type arguments.
112class Class8(Generic[T]):
113 def __new__(cls, *args, **kwargs) -> "Class8[list[T]]":
114 raise NotImplementedError
117assert_type(Class8[int](), Class8[list[int]])
Unexpected error [type-assertion-failure] Type `Class8[list[int]]` does not match asserted type `Class8[int]`
118assert_type(Class8[str](), Class8[list[str]])
Unexpected error [type-assertion-failure] Type `Class8[list[str]]` does not match asserted type `Class8[str]`
121# > If the cls parameter within the __new__ method is not annotated,
122# > type checkers should infer a type of type[Self].
125class Class9(Generic[T]):
126 def __new__(cls, *args, **kwargs) -> Self:
127 raise NotImplementedError
130class Class10(Class9[int]):
131 pass
134c10: Class9[int] = Class10()
136# > Regardless of whether the type of the cls parameter is explicit or
137# > inferred, the type checker should bind the class being constructed to
138# > the cls parameter and report any type errors that arise during binding.
141class Class11(Generic[T]):
142 def __new__(cls: "type[Class11[int]]") -> "Class11[int]":
143 raise NotImplementedError
146Class11() # OK
147Class11[int]() # OK
148Class11[str]() # E
[invalid-argument-type] Argument to function `__new__` is incorrect: Expected `type[Class11[int]]`, found `<class 'Class11[str]'>`