Skip to content

Dataclasses trigger __get__ on unused ClassVar values #144618

@johnslavik

Description

@johnslavik

Bug report

Bug description:

from dataclasses import dataclass
from typing import ClassVar


class Kaboom:
    def __get__(self, inst, owner):
        raise RuntimeError("kaboom!")


@dataclass
class Foo:
    kaboom: ClassVar[Kaboom] = Kaboom()

This kabooms at the point of @dataclass decoration:

❯ ./python t.py
Traceback (most recent call last):
    ...
  File "/home/bswck/Python/cpython/Lib/dataclasses.py", line 833, in _get_field
    default = getattr(cls, a_name, MISSING)
  File "/home/bswck/Python/cpython/t.py", line 7, in __get__
    raise RuntimeError("kaboom!")
RuntimeError: kaboom!

Is this the intended behavior?

It caused a problem for me because I had a descriptor that needed some setup before use.

Workarounds are to (1) not annotate the descriptor (2) delay dataclass decoration.

I realize that class-level descriptors with side effects are a programming smell and that changing this behavior for public fields might be impossible or just not worth it because of backward compatibility.

However, I think we could stop storing (which also means stop exercising the descriptor protocol) defaults of ClassVar pseudo-fields, because they aren't used by dataclasses in any way.

Whether or not it is desired that this is fixed, I'd like this to have a record.
Thanks for considering this issue!

cc @ericvsmith

CPython versions tested on:

CPython main branch

Operating systems tested on:

No response

Linked PRs

Metadata

Metadata

Assignees

No one assigned

    Labels

    3.13bugs and security fixes3.14bugs and security fixes3.15new features, bugs and security fixesstdlibStandard Library Python modules in the Lib/ directorytopic-dataclassestype-bugAn unexpected behavior, bug, or error

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions