Rename Red Knot (#17820)

This commit is contained in:
Micha Reiser 2025-05-03 19:49:15 +02:00 committed by GitHub
parent e6a798b962
commit b51c4f82ea
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
1564 changed files with 1598 additions and 1578 deletions

View file

@ -0,0 +1,293 @@
# `typing.dataclass_transform`
```toml
[environment]
python-version = "3.12"
```
`dataclass_transform` is a decorator that can be used to let type checkers know that a function,
class, or metaclass is a `dataclass`-like construct.
## Basic example
```py
from typing_extensions import dataclass_transform
@dataclass_transform()
def my_dataclass[T](cls: type[T]) -> type[T]:
# modify cls
return cls
@my_dataclass
class Person:
name: str
age: int | None = None
Person("Alice", 20)
Person("Bob", None)
Person("Bob")
# error: [missing-argument]
Person()
```
## Decorating decorators that take parameters themselves
If we want our `dataclass`-like decorator to also take parameters, that is also possible:
```py
from typing_extensions import dataclass_transform, Callable
@dataclass_transform()
def versioned_class[T](*, version: int = 1):
def decorator(cls):
# modify cls
return cls
return decorator
@versioned_class(version=2)
class Person:
name: str
age: int | None = None
Person("Alice", 20)
# error: [missing-argument]
Person()
```
We properly type-check the arguments to the decorator:
```py
from typing_extensions import dataclass_transform, Callable
# error: [invalid-argument-type]
@versioned_class(version="a string")
class C:
name: str
```
## Types of decorators
The examples from this section are straight from the Python documentation on
[`typing.dataclass_transform`].
### Decorating a decorator function
```py
from typing_extensions import dataclass_transform
@dataclass_transform()
def create_model[T](cls: type[T]) -> type[T]:
...
return cls
@create_model
class CustomerModel:
id: int
name: str
CustomerModel(id=1, name="Test")
```
### Decorating a metaclass
```py
from typing_extensions import dataclass_transform
@dataclass_transform()
class ModelMeta(type): ...
class ModelBase(metaclass=ModelMeta): ...
class CustomerModel(ModelBase):
id: int
name: str
CustomerModel(id=1, name="Test")
# error: [missing-argument]
CustomerModel()
```
### Decorating a base class
```py
from typing_extensions import dataclass_transform
@dataclass_transform()
class ModelBase: ...
class CustomerModel(ModelBase):
id: int
name: str
# TODO: this is not supported yet
# error: [unknown-argument]
# error: [unknown-argument]
CustomerModel(id=1, name="Test")
```
## Arguments to `dataclass_transform`
### `eq_default`
`eq=True/False` does not have a observable effect (apart from a minor change regarding whether
`other` is positional-only or not, which is not modelled at the moment).
### `order_default`
The `order_default` argument controls whether methods such as `__lt__` are generated by default.
This can be overwritten using the `order` argument to the custom decorator:
```py
from typing_extensions import dataclass_transform
@dataclass_transform()
def normal(*, order: bool = False):
raise NotImplementedError
@dataclass_transform(order_default=False)
def order_default_false(*, order: bool = False):
raise NotImplementedError
@dataclass_transform(order_default=True)
def order_default_true(*, order: bool = True):
raise NotImplementedError
@normal
class Normal:
inner: int
Normal(1) < Normal(2) # error: [unsupported-operator]
@normal(order=True)
class NormalOverwritten:
inner: int
NormalOverwritten(1) < NormalOverwritten(2)
@order_default_false
class OrderFalse:
inner: int
OrderFalse(1) < OrderFalse(2) # error: [unsupported-operator]
@order_default_false(order=True)
class OrderFalseOverwritten:
inner: int
OrderFalseOverwritten(1) < OrderFalseOverwritten(2)
@order_default_true
class OrderTrue:
inner: int
OrderTrue(1) < OrderTrue(2)
@order_default_true(order=False)
class OrderTrueOverwritten:
inner: int
# error: [unsupported-operator]
OrderTrueOverwritten(1) < OrderTrueOverwritten(2)
```
### `kw_only_default`
To do
### `field_specifiers`
To do
## Overloaded dataclass-like decorators
In the case of an overloaded decorator, the `dataclass_transform` decorator can be applied to the
implementation, or to *one* of the overloads.
### Applying `dataclass_transform` to the implementation
```py
from typing_extensions import dataclass_transform, TypeVar, Callable, overload
T = TypeVar("T", bound=type)
@overload
def versioned_class(
cls: T,
*,
version: int = 1,
) -> T: ...
@overload
def versioned_class(
*,
version: int = 1,
) -> Callable[[T], T]: ...
@dataclass_transform()
def versioned_class(
cls: T | None = None,
*,
version: int = 1,
) -> T | Callable[[T], T]:
raise NotImplementedError
@versioned_class
class D1:
x: str
@versioned_class(version=2)
class D2:
x: str
D1("a")
D2("a")
D1(1.2) # error: [invalid-argument-type]
D2(1.2) # error: [invalid-argument-type]
```
### Applying `dataclass_transform` to an overload
```py
from typing_extensions import dataclass_transform, TypeVar, Callable, overload
T = TypeVar("T", bound=type)
@overload
@dataclass_transform()
def versioned_class(
cls: T,
*,
version: int = 1,
) -> T: ...
@overload
def versioned_class(
*,
version: int = 1,
) -> Callable[[T], T]: ...
def versioned_class(
cls: T | None = None,
*,
version: int = 1,
) -> T | Callable[[T], T]:
raise NotImplementedError
@versioned_class
class D1:
x: str
@versioned_class(version=2)
class D2:
x: str
# TODO: these should not be errors
D1("a") # error: [too-many-positional-arguments]
D2("a") # error: [too-many-positional-arguments]
# TODO: these should be invalid-argument-type errors
D1(1.2) # error: [too-many-positional-arguments]
D2(1.2) # error: [too-many-positional-arguments]
```
[`typing.dataclass_transform`]: https://docs.python.org/3/library/typing.html#typing.dataclass_transform