← Back to index

generics_paramspec_semantics.py

True Positive
False Positive
False Negative
Optional (detected)
Warning or Info
TP: 4
FP: 2
FN: 5
Optional: 1 / 1
1"""
2Tests semantics of ParamSpec.
3"""
4
5# Specification: https://typing.readthedocs.io/en/latest/spec/generics.html#semantics
6
7
8from typing import Callable, Concatenate, Generic, ParamSpec, TypeVar, assert_type
9
10P = ParamSpec("P")
13def changes_return_type_to_str(x: Callable[P, int]) -> Callable[P, str]:
14 raise NotImplementedError
17def returns_int(a: str, b: bool, /) -> int:
18 raise NotImplementedError
21f1 = changes_return_type_to_str(returns_int)
22assert_type(f1, Callable[[str, bool], str])
24v1 = f1("A", True) # OK
25assert_type(v1, str)
26f1(a="A", b=True) # E: positional-only
[positional-only-parameter-as-kwarg] Positional-only parameter 1 (`a`) passed as keyword argument [positional-only-parameter-as-kwarg] Positional-only parameter 2 (`b`) passed as keyword argument
27f1("A", "A") # E: wrong type
[invalid-argument-type] Argument is incorrect: Expected `bool`, found `Literal["A"]`
30def func1(x: Callable[P, int], y: Callable[P, int]) -> Callable[P, bool]:
31 raise NotImplementedError
34def x_y(x: int, y: str) -> int:
35 raise NotImplementedError
38def y_x(y: int, x: str) -> int:
39 raise NotImplementedError
42f2 = func1(x_y, x_y)
43assert_type(f2(1, ""), bool)
44assert_type(f2(y="", x=1), bool)
46f3 = func1(x_y, y_x) # E?: Could return (a: int, b: str, /) -> bool
[invalid-argument-type] Argument to function `func1` is incorrect: Expected `(x: int, y: str) -> int`, found `def y_x(y: int, x: str) -> int`
47# (a callable with two positional-only parameters)
48# This works because both callables have types that are
49# behavioral subtypes of Callable[[int, str], int]
50# Also OK for type checkers to reject this.
53def keyword_only_x(*, x: int) -> int:
54 raise NotImplementedError
57def keyword_only_y(*, y: int) -> int:
58 raise NotImplementedError
61func1(keyword_only_x, keyword_only_y) # E
[invalid-argument-type] Argument to function `func1` is incorrect: Expected `(*, x: int) -> int`, found `def keyword_only_y(*, y: int) -> int`
64U = TypeVar("U")
67class Y(Generic[U, P]):
68 f: Callable[P, str]
69 prop: U
71 def __init__(self, f: Callable[P, str], prop: U) -> None:
72 self.f = f
73 self.prop = prop
76def callback_a(q: int, /) -> str:
77 raise NotImplementedError
80def func(x: int) -> None:
81 y1 = Y(callback_a, x)
82 assert_type(y1, Y[int, [int]])
83 y2 = y1.f
84 assert_type(y2, Callable[[int], str])
87def bar(x: int, *args: bool) -> int:
88 raise NotImplementedError
91def add(x: Callable[P, int]) -> Callable[Concatenate[str, P], bool]:
92 raise NotImplementedError
95a1 = add(bar) # Should return (a: str, /, x: int, *args: bool) -> bool
96assert_type(a1("", 1, False, True), bool)
97assert_type(a1("", x=1), bool)
98a1(1, x=1) # E
Expected a ty diagnostic for this line
101def remove(x: Callable[Concatenate[int, P], int]) -> Callable[P, bool]:
102 raise NotImplementedError
105r1 = remove(bar) # Should return (*args: bool) -> bool
106assert_type(r1(False, True, True), bool)
Unexpected error [missing-argument] No argument provided for required parameter `**kwargs`
107assert_type(r1(), bool)
Unexpected error [missing-argument] No arguments provided for required parameters `*args`, `**kwargs`
108r1(1) # E
[missing-argument] No argument provided for required parameter `**kwargs`
111def transform(
112 x: Callable[Concatenate[int, P], int]
113) -> Callable[Concatenate[str, P], bool]:
114 raise NotImplementedError
117t1 = transform(bar) # Should return (a: str, /, *args: bool) -> bool
118assert_type(t1("", True, False, True), bool)
119assert_type(t1(""), bool)
120t1(1) # E
Expected a ty diagnostic for this line
123def expects_int_first(x: Callable[Concatenate[int, P], int]) -> None:
124 ...
127@expects_int_first # E
Expected a ty diagnostic for this line
128def one(x: str) -> int:
129 raise NotImplementedError
132@expects_int_first # E
Expected a ty diagnostic for this line
133def two(*, x: int) -> int:
134 raise NotImplementedError
137@expects_int_first # E
Expected a ty diagnostic for this line
138def three(**kwargs: int) -> int:
139 raise NotImplementedError
142@expects_int_first # OK
143def four(*args: int) -> int:
144 raise NotImplementedError