# What is PEP 681?


[PEP 681: Data Class Transforms](https://peps.python.org/pep-0681/) (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](https://pydevtools.com/handbook/reference/mypy.md). Every new dataclass-like library started invisible to every checker. PEP 681, which grew out of [Pyright](https://pydevtools.com/handbook/reference/pyright.md)'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:

```python
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")          # error
```

mypy 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](https://docs.python.org/3/library/typing.html#typing.dataclass_transform) 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](https://peps.python.org/pep-0681/)
- [typing.dataclass_transform documentation](https://docs.python.org/3/library/typing.html#typing.dataclass_transform)
- [What is PEP 695?](https://pydevtools.com/handbook/explanation/what-is-pep-695.md) covers declaring generics for dataclass-like builders
- [What is PEP 612?](https://pydevtools.com/handbook/explanation/what-is-pep-612.md) covers the matching mechanism for decorators
