Skip to content

PEP 749 support #1450

@Tinche

Description

@Tinche

attrs doesn't currently support PEP 749 annotations.

On Python 3.14, this works:

class A:
    b: B


class B:
    pass

If we try using attrs, it doesn't:

from attrs import define

@define
class A:
    b: B


class B:
    pass
Traceback (most recent call last):
  File "/Users/tintvrtkovic/pg/attrs/a01.py", line 6, in <module>
    @define
     ^^^^^^
  File "/Users/tintvrtkovic/pg/attrs/src/attr/_next_gen.py", line 409, in define
    return wrap(maybe_cls)
  File "/Users/tintvrtkovic/pg/attrs/src/attr/_next_gen.py", line 400, in wrap
    return do_it(cls, True)
  File "/Users/tintvrtkovic/pg/attrs/src/attr/_next_gen.py", line 346, in do_it
    return attrs(
        maybe_cls=cls,
    ...<20 lines>...
        match_args=match_args,
    )
  File "/Users/tintvrtkovic/pg/attrs/src/attr/_make.py", line 1554, in attrs
    return wrap(maybe_cls)
  File "/Users/tintvrtkovic/pg/attrs/src/attr/_make.py", line 1452, in wrap
    builder = _ClassBuilder(
        cls,
    ...<18 lines>...
        field_transformer,
    )
  File "/Users/tintvrtkovic/pg/attrs/src/attr/_make.py", line 679, in __init__
    attrs, base_attrs, base_map = _transform_attrs(
                                  ~~~~~~~~~~~~~~~~^
        cls,
        ^^^^
    ...<4 lines>...
        field_transformer,
        ^^^^^^^^^^^^^^^^^^
    )
    ^
  File "/Users/tintvrtkovic/pg/attrs/src/attr/_make.py", line 390, in _transform_attrs
    anns = _get_annotations(cls)
  File "/Users/tintvrtkovic/.local/share/uv/python/cpython-3.14.0b1-macos-aarch64-none/lib/python3.14/annotationlib.py", line 862, in get_annotations
    ann = _get_dunder_annotations(obj)
  File "/Users/tintvrtkovic/.local/share/uv/python/cpython-3.14.0b1-macos-aarch64-none/lib/python3.14/annotationlib.py", line 1014, in _get_dunder_annotations
    ann = getattr(obj, "__annotations__", None)
  File "/Users/tintvrtkovic/pg/attrs/a01.py", line 8, in __annotate__
    b: B
       ^
NameError: name 'B' is not defined

This is because we eagerly evaluate annotations; this cannot work with forward references (which is the entire point of the new handling of annotations).

Dataclasses work:

from dataclasses import dataclass


@dataclass
class A:
    b: B


class B:
    pass

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions