mirror of https://github.com/astral-sh/ruff
[ty] Split `ParamSpec` mdtests to separate legacy and PEP 695 tests (#21687)
## Summary This is another small refactor for https://github.com/astral-sh/ruff/pull/21445 that splits the single `paramspec.md` into `generics/legacy/paramspec.md` and `generics/pep695/paramspec.md`. ## Test Plan Make sure that all mdtests pass.
This commit is contained in:
parent
ecab623fb2
commit
8795d9f0cb
|
|
@ -1,4 +1,4 @@
|
||||||
# `ParamSpec`
|
# Legacy `ParamSpec`
|
||||||
|
|
||||||
## Definition
|
## Definition
|
||||||
|
|
||||||
|
|
@ -115,59 +115,3 @@ P = ParamSpec("P", default=[A, B])
|
||||||
class A: ...
|
class A: ...
|
||||||
class B: ...
|
class B: ...
|
||||||
```
|
```
|
||||||
|
|
||||||
### PEP 695
|
|
||||||
|
|
||||||
```toml
|
|
||||||
[environment]
|
|
||||||
python-version = "3.12"
|
|
||||||
```
|
|
||||||
|
|
||||||
#### Valid
|
|
||||||
|
|
||||||
```py
|
|
||||||
def foo1[**P]() -> None:
|
|
||||||
reveal_type(P) # revealed: typing.ParamSpec
|
|
||||||
|
|
||||||
def foo2[**P = ...]() -> None:
|
|
||||||
reveal_type(P) # revealed: typing.ParamSpec
|
|
||||||
|
|
||||||
def foo3[**P = [int, str]]() -> None:
|
|
||||||
reveal_type(P) # revealed: typing.ParamSpec
|
|
||||||
|
|
||||||
def foo4[**P, **Q = P]():
|
|
||||||
reveal_type(P) # revealed: typing.ParamSpec
|
|
||||||
reveal_type(Q) # revealed: typing.ParamSpec
|
|
||||||
```
|
|
||||||
|
|
||||||
#### Invalid
|
|
||||||
|
|
||||||
ParamSpec, when defined using the new syntax, does not allow defining bounds or constraints.
|
|
||||||
|
|
||||||
This results in a lot of syntax errors mainly because the AST doesn't accept them in this position.
|
|
||||||
The parser could do a better job in recovering from these errors.
|
|
||||||
|
|
||||||
<!-- blacken-docs:off -->
|
|
||||||
|
|
||||||
```py
|
|
||||||
# error: [invalid-syntax]
|
|
||||||
# error: [invalid-syntax]
|
|
||||||
# error: [invalid-syntax]
|
|
||||||
# error: [invalid-syntax]
|
|
||||||
# error: [invalid-syntax]
|
|
||||||
# error: [invalid-syntax]
|
|
||||||
def foo[**P: int]() -> None:
|
|
||||||
# error: [invalid-syntax]
|
|
||||||
# error: [invalid-syntax]
|
|
||||||
pass
|
|
||||||
```
|
|
||||||
|
|
||||||
<!-- blacken-docs:on -->
|
|
||||||
|
|
||||||
#### Invalid default
|
|
||||||
|
|
||||||
```py
|
|
||||||
# error: [invalid-paramspec]
|
|
||||||
def foo[**P = int]() -> None:
|
|
||||||
pass
|
|
||||||
```
|
|
||||||
|
|
@ -0,0 +1,64 @@
|
||||||
|
# PEP 695 `ParamSpec`
|
||||||
|
|
||||||
|
`ParamSpec` was introduced in Python 3.12 while the support for specifying defaults was added in
|
||||||
|
Python 3.13.
|
||||||
|
|
||||||
|
```toml
|
||||||
|
[environment]
|
||||||
|
python-version = "3.13"
|
||||||
|
```
|
||||||
|
|
||||||
|
## Definition
|
||||||
|
|
||||||
|
```py
|
||||||
|
def foo1[**P]() -> None:
|
||||||
|
reveal_type(P) # revealed: typing.ParamSpec
|
||||||
|
```
|
||||||
|
|
||||||
|
## Bounds and constraints
|
||||||
|
|
||||||
|
`ParamSpec`, when defined using the new syntax, does not allow defining bounds or constraints.
|
||||||
|
|
||||||
|
TODO: This results in a lot of syntax errors mainly because the AST doesn't accept them in this
|
||||||
|
position. The parser could do a better job in recovering from these errors.
|
||||||
|
|
||||||
|
<!-- blacken-docs:off -->
|
||||||
|
|
||||||
|
```py
|
||||||
|
# error: [invalid-syntax]
|
||||||
|
# error: [invalid-syntax]
|
||||||
|
# error: [invalid-syntax]
|
||||||
|
# error: [invalid-syntax]
|
||||||
|
# error: [invalid-syntax]
|
||||||
|
# error: [invalid-syntax]
|
||||||
|
def foo[**P: int]() -> None:
|
||||||
|
# error: [invalid-syntax]
|
||||||
|
# error: [invalid-syntax]
|
||||||
|
pass
|
||||||
|
```
|
||||||
|
|
||||||
|
<!-- blacken-docs:on -->
|
||||||
|
|
||||||
|
## Default
|
||||||
|
|
||||||
|
The default value for a `ParamSpec` can be either a list of types, `...`, or another `ParamSpec`.
|
||||||
|
|
||||||
|
```py
|
||||||
|
def foo2[**P = ...]() -> None:
|
||||||
|
reveal_type(P) # revealed: typing.ParamSpec
|
||||||
|
|
||||||
|
def foo3[**P = [int, str]]() -> None:
|
||||||
|
reveal_type(P) # revealed: typing.ParamSpec
|
||||||
|
|
||||||
|
def foo4[**P, **Q = P]():
|
||||||
|
reveal_type(P) # revealed: typing.ParamSpec
|
||||||
|
reveal_type(Q) # revealed: typing.ParamSpec
|
||||||
|
```
|
||||||
|
|
||||||
|
Other values are invalid.
|
||||||
|
|
||||||
|
```py
|
||||||
|
# error: [invalid-paramspec]
|
||||||
|
def foo[**P = int]() -> None:
|
||||||
|
pass
|
||||||
|
```
|
||||||
Loading…
Reference in New Issue