2Tests the conversion of constructors into Callable types.
5# Specification: https://typing.readthedocs.io/en/latest/spec/constructors.html#converting-a-constructor-to-callable
26def accepts_callable(cb: Callable[P, R]) -> Callable[P, R]:
31 def __init__(self, x: int) -> None:
35r1 = accepts_callable(Class1)
36reveal_type(r1) # `def (x: int) -> Class1`
[revealed-type] Revealed type: `(x: int) -> Class1`
37assert_type(r1(1), Class1)
[missing-argument] No argument provided for required parameter `x`
[missing-argument] No argument provided for required parameter `x`
[unknown-argument] Argument `y` does not match any known parameter
43 """No __new__ or __init__"""
48r2 = accepts_callable(Class2)
49reveal_type(r2) # `def () -> Class2`
[revealed-type] Revealed type: `() -> Class2`
50assert_type(r2(), Class2)
[too-many-positional-arguments] Too many positional arguments: expected 0, got 1
55 """__new__ and __init__"""
57 def __new__(cls, *args, **kwargs) -> Self:
58 raise NotImplementedError
60 def __init__(self, x: int) -> None: ...
63r3 = accepts_callable(Class3)
64reveal_type(r3) # `def (x: int) -> Class3`
[revealed-type] Revealed type: `(...) -> Class3`
65assert_type(r3(3), Class3)
Expected a ty diagnostic for this line
Expected a ty diagnostic for this line
Expected a ty diagnostic for this line
72 """__new__ but no __init__"""
74 def __new__(cls, x: int) -> int:
75 raise NotImplementedError
78r4 = accepts_callable(Class4)
79reveal_type(r4) # `def (x: int) -> int`
[revealed-type] Revealed type: `(x: int) -> int`
80assert_type(r4(1), int)
[missing-argument] No argument provided for required parameter `x`
[missing-argument] No argument provided for required parameter `x`
[unknown-argument] Argument `y` does not match any known parameter
86 def __call__(cls, *args: Any, **kwargs: Any) -> NoReturn:
87 raise NotImplementedError("Class not constructable")
90class Class5(metaclass=Meta1):
91 """Custom metaclass that overrides type.__call__"""
93 def __new__(cls, *args: Any, **kwargs: Any) -> Self:
94 """This __new__ is ignored for purposes of conversion"""
95 return super().__new__(cls)
98r5 = accepts_callable(Class5)
99reveal_type(r5) # `def (*args: Any, **kwargs: Any) -> NoReturn`
[revealed-type] Revealed type: `(...) -> Unknown`
102 assert_type(r5(), NoReturn)
Unexpected error
[type-assertion-failure] Type `Never` does not match asserted type `Unknown`
107 assert_type(r5(1, x=1), NoReturn)
Unexpected error
[type-assertion-failure] Type `Never` does not match asserted type `Unknown`
112class Class6Proxy: ...
116 """__new__ that causes __init__ to be ignored"""
118 def __new__(cls) -> Class6Proxy:
121 def __init__(self, x: int) -> None:
122 """This __init__ is ignored for purposes of conversion"""
126r6 = accepts_callable(Class6)
127reveal_type(r6) # `def () -> Class6Proxy`
[revealed-type] Revealed type: `() -> Class6Proxy`
128assert_type(r6(), Class6Proxy)
[too-many-positional-arguments] Too many positional arguments: expected 0, got 1
133 """__new__ that causes __init__ to be ignored via Any"""
135 def __new__(cls) -> Any:
136 return super().__new__(cls)
138 def __init__(self, x: int) -> None:
139 """This __init__ is ignored for purposes of conversion"""
143r6_any = accepts_callable(Class6Any)
Unexpected error
[invalid-argument-type] Argument to function `accepts_callable` is incorrect: Expected `() -> Any | Class6Any`, found `<class 'Class6Any'>`
144reveal_type(r6_any) # `def () -> Any`
[revealed-type] Revealed type: `() -> Any | Class6Any`
145assert_type(r6_any(), Any)
Unexpected error
[type-assertion-failure] Type `Any` does not match asserted type `Any | Class6Any`
[too-many-positional-arguments] Too many positional arguments: expected 0, got 1
148# > If the __init__ or __new__ method is overloaded, the callable type should
149# > be synthesized from the overloads. The resulting callable type itself will
153class Class7(Generic[T]):
155 def __init__(self: "Class7[int]", x: int) -> None: ...
157 def __init__(self: "Class7[str]", x: str) -> None: ...
158 def __init__(self, x: int | str) -> None:
162r7 = accepts_callable(Class7)
[revealed-type] Revealed type: `Overload[[T](x: int) -> Class7[int] | Class7[str], [T](x: str) -> Class7[int] | Class7[str]]`
165) # overload of `def (x: int) -> Class7[int]` and `def (x: str) -> Class7[str]`
166assert_type(r7(0), Class7[int])
Unexpected error
[type-assertion-failure] Type `Class7[int]` does not match asserted type `Class7[int] | Class7[str]`
167assert_type(r7(""), Class7[str])
Unexpected error
[type-assertion-failure] Type `Class7[str]` does not match asserted type `Class7[int] | Class7[str]`
170# > If the class is generic, the synthesized callable should include any
171# > class-scoped type parameters that appear within the signature, but these
172# > type parameters should be converted to function-scoped type parameters
173# > for the callable. Any function-scoped type parameters in the __init__
174# > or __new__ method should also be included as function-scoped type parameters
175# > in the synthesized callable.
178class Class8(Generic[T]):
179 def __new__(cls, x: list[T], y: list[T]) -> Self:
180 return super().__new__(cls)
183r8 = accepts_callable(Class8)
184reveal_type(r8) # `def [T] (x: list[T], y: list[T]) -> Class8[T]`
[revealed-type] Revealed type: `[T](x: list[T], y: list[T]) -> Class8[T]`
185assert_type(r8([""], [""]), Class8[str])
Unexpected error
[type-assertion-failure] Type `Class8[str]` does not match asserted type `Class8[Unknown | str]`
Expected a ty diagnostic for this line
190 def __init__(self, x: list[T], y: list[T]) -> None:
194r9 = accepts_callable(Class9)
195reveal_type(r9) # `def [T] (x: list[T], y: list[T]) -> Class9`
[revealed-type] Revealed type: `[T](x: list[T], y: list[T]) -> Class9`
196assert_type(r9([""], [""]), Class9)
Expected a ty diagnostic for this line