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
|
||||
|
||||
|
|
@ -115,59 +115,3 @@ P = ParamSpec("P", default=[A, B])
|
|||
class A: ...
|
||||
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