What is PEP 681?
PEP 681: Data Class Transforms (Python 3.11) adds typing.dataclass_transform, a decorator a library applies to its own base class, metaclass, or decorator to tell type checkers “classes built with this behave like dataclasses.” It is the reason pydantic models and attrs classes get a checked __init__ in your editor without any checker-specific plugin.
Why did type checkers need a marker?
Libraries like pydantic and attrs generate __init__, __eq__, and friends at runtime from a class’s annotations. A static checker never sees those generated methods, so without help it thinks User(name="ada") is calling a constructor that takes no arguments.
Checkers special-cased @dataclasses.dataclass itself, and the rest of the ecosystem ran on per-library plugins: pydantic v1 shipped a mypy plugin, attrs support was hardcoded into mypy. Every new dataclass-like library started invisible to every checker. PEP 681, which grew out of Pyright’s dataclass_transform experiment, replaces that with one declaration the library makes about itself.
How does the marker work?
dataclass_transform does nothing at runtime. It only tells checkers to synthesize dataclass-style methods for classes built with the marked construct:
from typing import dataclass_transform
@dataclass_transform()
def model(cls):
return cls # the real library generates __init__ and friends here
@model
class User:
name: str
age: int
User(name="ada", age=36) # ok: the checker synthesized __init__
User(name="ada") # errormypy reports the last line as Missing positional argument "age" in call to "User", even though the toy model decorator generates nothing. The marker takes parameters such as kw_only_default and field_specifiers that describe how the library differs from dataclasses.dataclass; the dataclass_transform documentation lists them.
If you expected the marker to generate a working __init__ at runtime, that’s the most common misreading of this PEP. The library still writes the runtime machinery; the marker only describes it to checkers.
Who relies on it?
pydantic v2 applies dataclass_transform to the metaclass behind BaseModel, and attrs applies it to attrs.define in its type stubs. The PEP’s motivation section names attrs, pydantic, SQLAlchemy, and Django models as the dataclass-like patterns it was designed for. When completion and argument checking work on a pydantic model in VS Code, this marker is what’s powering it.
Where do you get it?
dataclass_transform lives in typing from Python 3.11 and in typing_extensions for older versions. Type checkers treat the two spellings identically, so libraries import it from typing_extensions to keep supporting older Pythons.
Learn More
- PEP 681: Data Class Transforms
- typing.dataclass_transform documentation
- What is PEP 695? covers declaring generics for dataclass-like builders
- What is PEP 612? covers the matching mechanism for decorators