Skip to content

Commit 67a6ad7

Browse files
authored
Turn on ParamSpec semanal by default (#10883)
This PR does not mean mypy supports PEP 612, but it does do enough to unblock #10862 mypy should now treat Callable[P, T] as Callable[..., T] and the code paths with incomplete support will no longer crash (but will not do what you'd want) Co-authored-by: hauntsaninja <>
1 parent 805bbde commit 67a6ad7

10 files changed

+39
-18
lines changed

Diff for: mypy/applytype.py

+3-1
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
from mypy.expandtype import expand_type
66
from mypy.types import (
77
Type, TypeVarId, TypeVarType, CallableType, AnyType, PartialType, get_proper_types,
8-
TypeVarDef, TypeVarLikeDef, ProperType
8+
TypeVarDef, TypeVarLikeDef, ProperType, ParamSpecDef
99
)
1010
from mypy.nodes import Context
1111

@@ -19,6 +19,8 @@ def get_target_type(
1919
skip_unsatisfied: bool
2020
) -> Optional[Type]:
2121
# TODO(shantanu): fix for ParamSpecDef
22+
if isinstance(tvar, ParamSpecDef):
23+
return None
2224
assert isinstance(tvar, TypeVarDef)
2325
values = get_proper_types(tvar.values)
2426
if values:

Diff for: mypy/checkexpr.py

+3-1
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@
1818
Type, AnyType, CallableType, Overloaded, NoneType, TypeGuardType, TypeVarDef,
1919
TupleType, TypedDictType, Instance, TypeVarType, ErasedType, UnionType,
2020
PartialType, DeletedType, UninhabitedType, TypeType, TypeOfAny, LiteralType, LiteralValue,
21-
is_named_instance, FunctionLike,
21+
is_named_instance, FunctionLike, ParamSpecDef,
2222
StarType, is_optional, remove_optional, is_generic_instance, get_proper_type, ProperType,
2323
get_proper_types, flatten_nested_unions
2424
)
@@ -4481,6 +4481,8 @@ def merge_typevars_in_callables_by_name(
44814481
name = tvdef.fullname
44824482
if name not in unique_typevars:
44834483
# TODO(shantanu): fix for ParamSpecDef
4484+
if isinstance(tvdef, ParamSpecDef):
4485+
continue
44844486
assert isinstance(tvdef, TypeVarDef)
44854487
unique_typevars[name] = TypeVarType(tvdef)
44864488
variables.append(tvdef)

Diff for: mypy/expandtype.py

+4-1
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,8 @@
55
NoneType, TypeVarType, Overloaded, TupleType, TypedDictType, UnionType,
66
ErasedType, PartialType, DeletedType, UninhabitedType, TypeType, TypeVarId,
77
FunctionLike, TypeVarDef, LiteralType, get_proper_type, ProperType,
8-
TypeAliasType)
8+
TypeAliasType, ParamSpecDef
9+
)
910

1011

1112
def expand_type(typ: Type, env: Mapping[TypeVarId, Type]) -> Type:
@@ -41,6 +42,8 @@ def freshen_function_type_vars(callee: F) -> F:
4142
tvmap: Dict[TypeVarId, Type] = {}
4243
for v in callee.variables:
4344
# TODO(shantanu): fix for ParamSpecDef
45+
if isinstance(v, ParamSpecDef):
46+
continue
4447
assert isinstance(v, TypeVarDef)
4548
tvdef = TypeVarDef.new_unification_variable(v)
4649
tvdefs.append(tvdef)

Diff for: mypy/main.py

-2
Original file line numberDiff line numberDiff line change
@@ -852,8 +852,6 @@ def add_invertible_flag(flag: str,
852852
# Must be followed by another flag or by '--' (and then only file args may follow).
853853
parser.add_argument('--cache-map', nargs='+', dest='special-opts:cache_map',
854854
help=argparse.SUPPRESS)
855-
# PEP 612 support is a work in progress, hide it from users
856-
parser.add_argument('--wip-pep-612', action="store_true", help=argparse.SUPPRESS)
857855

858856
# options specifying code to check
859857
code_group = parser.add_argument_group(

Diff for: mypy/options.py

-3
Original file line numberDiff line numberDiff line change
@@ -242,9 +242,6 @@ def __init__(self) -> None:
242242
# mypy. (Like mypyc.)
243243
self.preserve_asts = False
244244

245-
# PEP 612 support is a work in progress, hide it from users
246-
self.wip_pep_612 = False
247-
248245
# Paths of user plugins
249246
self.plugins: List[str] = []
250247

Diff for: mypy/semanal.py

-2
Original file line numberDiff line numberDiff line change
@@ -3151,8 +3151,6 @@ def process_paramspec_declaration(self, s: AssignmentStmt) -> bool:
31513151
In the future, ParamSpec may accept bounds and variance arguments, in which
31523152
case more aggressive sharing of code with process_typevar_declaration should be pursued.
31533153
"""
3154-
if not self.options.wip_pep_612:
3155-
return False
31563154
call = self.get_typevarlike_declaration(
31573155
s, ("typing_extensions.ParamSpec", "typing.ParamSpec")
31583156
)

Diff for: mypy/typeops.py

+3-1
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@
1414
TupleType, Instance, FunctionLike, Type, CallableType, TypeVarDef, TypeVarLikeDef, Overloaded,
1515
TypeVarType, UninhabitedType, FormalArgument, UnionType, NoneType, TypedDictType,
1616
AnyType, TypeOfAny, TypeType, ProperType, LiteralType, get_proper_type, get_proper_types,
17-
copy_type, TypeAliasType, TypeQuery
17+
copy_type, TypeAliasType, TypeQuery, ParamSpecDef
1818
)
1919
from mypy.nodes import (
2020
FuncBase, FuncItem, OverloadedFuncDef, TypeInfo, ARG_STAR, ARG_STAR2, ARG_POS,
@@ -512,6 +512,8 @@ def true_or_false(t: Type) -> ProperType:
512512

513513
def erase_def_to_union_or_bound(tdef: TypeVarLikeDef) -> Type:
514514
# TODO(shantanu): fix for ParamSpecDef
515+
if isinstance(tdef, ParamSpecDef):
516+
return AnyType(TypeOfAny.from_error)
515517
assert isinstance(tdef, TypeVarDef)
516518
if tdef.values:
517519
return make_simplified_union(tdef.values)

Diff for: test-data/unit/check-parameter-specification.test

+23-2
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,9 @@
11
[case testBasicParamSpec]
2-
# flags: --wip-pep-612
32
from typing_extensions import ParamSpec
43
P = ParamSpec('P')
54
[builtins fixtures/tuple.pyi]
65

76
[case testParamSpecLocations]
8-
# flags: --wip-pep-612
97
from typing import Callable, List
108
from typing_extensions import ParamSpec, Concatenate
119
P = ParamSpec('P')
@@ -29,3 +27,26 @@ def foo5(x: Callable[[int, str], P]) -> None: ... # E: Invalid location for Par
2927
def foo6(x: Callable[[P], int]) -> None: ... # E: Invalid location for ParamSpec "P" \
3028
# N: You can use ParamSpec as the first argument to Callable, e.g., 'Callable[P, int]'
3129
[builtins fixtures/tuple.pyi]
30+
31+
[case testParamSpecTemporaryAnyBehaviour]
32+
# This is a test of mypy's temporary behaviour in lieu of full support for ParamSpec
33+
from typing import Callable, List, Iterator, TypeVar
34+
from typing_extensions import ParamSpec
35+
P = ParamSpec('P')
36+
T = TypeVar('T')
37+
38+
def changes_return_type_to_str(x: Callable[P, int]) -> Callable[P, str]: ...
39+
40+
def returns_int(a: str, b: bool) -> int: ...
41+
42+
reveal_type(changes_return_type_to_str(returns_int)) # N: Revealed type is "def (*Any, **Any) -> builtins.str"
43+
44+
def tmpcontextmanagerlike(x: Callable[P, Iterator[T]]) -> Callable[P, List[T]]: ...
45+
46+
@tmpcontextmanagerlike
47+
def whatever(x: int) -> Iterator[int]:
48+
yield x
49+
50+
reveal_type(whatever) # N: Revealed type is "def (*Any, **Any) -> builtins.list[builtins.int*]"
51+
reveal_type(whatever(217)) # N: Revealed type is "builtins.list[builtins.int*]"
52+
[builtins fixtures/tuple.pyi]

Diff for: test-data/unit/semanal-errors.test

-1
Original file line numberDiff line numberDiff line change
@@ -1426,7 +1426,6 @@ def g() -> None:
14261426
[out]
14271427

14281428
[case testParamSpec]
1429-
# flags: --wip-pep-612
14301429
from typing_extensions import ParamSpec
14311430

14321431
TParams = ParamSpec('TParams')

Diff for: test-data/unit/semanal-types.test

+3-4
Original file line numberDiff line numberDiff line change
@@ -1500,12 +1500,11 @@ MypyFile:1(
15001500

15011501

15021502
[case testParamSpec]
1503-
# flags: --wip-pep-612
15041503
from typing import ParamSpec
15051504
P = ParamSpec("P")
15061505
[out]
15071506
MypyFile:1(
1508-
ImportFrom:2(typing, [ParamSpec])
1509-
AssignmentStmt:3(
1507+
ImportFrom:1(typing, [ParamSpec])
1508+
AssignmentStmt:2(
15101509
NameExpr(P* [__main__.P])
1511-
ParamSpecExpr:3()))
1510+
ParamSpecExpr:2()))

0 commit comments

Comments
 (0)