gh-135228: When @dataclass(slots=True) replaces a dataclass, make the original class collectible (take 2) by JelleZijlstra · Pull Request #137047 · python/cpython

and others added 3 commits

July 23, 2025 08:13
…ke the original class collectible (python#136893)

An interesting hack, but more localized in scope than python#135230.

This may be a breaking change if people intentionally keep the original class around
when using `@dataclass(slots=True)`, and then use `__dict__` or `__weakref__` on the
original class.

Co-authored-by: Alyssa Coghlan <ncoghlan@gmail.com>

JelleZijlstra

serhiy-storchaka

@JelleZijlstra

@JelleZijlstra

encukou

serhiy-storchaka

Co-authored-by: Petr Viktorin <encukou@gmail.com>
Co-authored-by: Serhiy Storchaka <storchaka@gmail.com>

JelleZijlstra

@JelleZijlstra

encukou

@JelleZijlstra

serhiy-storchaka

@JelleZijlstra

serhiy-storchaka

miss-islington pushed a commit to miss-islington/cpython that referenced this pull request

Aug 12, 2025
…ke the original class collectible (take 2) (pythonGH-137047)

Remove the `__dict__` and `__weakref__` descriptors from the original class when creating a dataclass from it.

An interesting hack, but more localized in scope than pythongh-135230.

This may be a breaking change if people intentionally keep the original class around
when using `@dataclass(slots=True)`, and then use `__dict__` or `__weakref__` on the
original class.

(cherry picked from commit 6859b95)

Co-authored-by: Jelle Zijlstra <jelle.zijlstra@gmail.com>
Co-authored-by: Alyssa Coghlan <ncoghlan@gmail.com>
Co-authored-by: Petr Viktorin <encukou@gmail.com>
Co-authored-by: Serhiy Storchaka <storchaka@gmail.com>

hugovk pushed a commit that referenced this pull request

Aug 12, 2025
…ake the original class collectible (take 2) (GH-137047) (#137666)

Co-authored-by: Jelle Zijlstra <jelle.zijlstra@gmail.com>
Co-authored-by: Alyssa Coghlan <ncoghlan@gmail.com>
Co-authored-by: Petr Viktorin <encukou@gmail.com>
Co-authored-by: Serhiy Storchaka <storchaka@gmail.com>

maurycy added a commit to maurycy/cpython that referenced this pull request

Aug 12, 2025

encukou added a commit that referenced this pull request

Aug 18, 2025
…-136966)

This partially reverts #137047, keeping the tests for GC collectability of the
original class that dataclass adds `__slots__` to.
The reference leaks solved there are instead solved by having the `__dict__` &
`__weakref__` descriptors not tied to (and referencing) their class.

Instead, they're shared between all classes that need them (within
an interpreter).
The `__objclass__` ol the descriptors is set to `object`, since these
descriptors work with *any* object. (The appropriate checks were already
made in the get/set code, so the `__objclass__` check was redundant.)

The repr of these descriptors (and any others whose `__objclass__` is `object`)
now doesn't mention the objclass.

This change required adjustment of introspection code that checks
`__objclass__` to determine an object's “own” (i.e. not inherited) `__dict__`.
Third-party code that does similar introspection of the internals will also
need adjusting.


Co-authored-by: Jelle Zijlstra <jelle.zijlstra@gmail.com>

Agent-Hellboy pushed a commit to Agent-Hellboy/cpython that referenced this pull request

Aug 19, 2025
…ke the original class collectible (take 2) (pythonGH-137047)

Remove the `__dict__` and `__weakref__` descriptors from the original class when creating a dataclass from it.

An interesting hack, but more localized in scope than pythongh-135230.

This may be a breaking change if people intentionally keep the original class around
when using `@dataclass(slots=True)`, and then use `__dict__` or `__weakref__` on the
original class.


Co-authored-by: Alyssa Coghlan <ncoghlan@gmail.com>
Co-authored-by: Petr Viktorin <encukou@gmail.com>
Co-authored-by: Serhiy Storchaka <storchaka@gmail.com>

Agent-Hellboy pushed a commit to Agent-Hellboy/cpython that referenced this pull request

Aug 19, 2025
…ct (pythonGH-136966)

This partially reverts python#137047, keeping the tests for GC collectability of the
original class that dataclass adds `__slots__` to.
The reference leaks solved there are instead solved by having the `__dict__` &
`__weakref__` descriptors not tied to (and referencing) their class.

Instead, they're shared between all classes that need them (within
an interpreter).
The `__objclass__` ol the descriptors is set to `object`, since these
descriptors work with *any* object. (The appropriate checks were already
made in the get/set code, so the `__objclass__` check was redundant.)

The repr of these descriptors (and any others whose `__objclass__` is `object`)
now doesn't mention the objclass.

This change required adjustment of introspection code that checks
`__objclass__` to determine an object's “own” (i.e. not inherited) `__dict__`.
Third-party code that does similar introspection of the internals will also
need adjusting.


Co-authored-by: Jelle Zijlstra <jelle.zijlstra@gmail.com>

kumaraditya303 pushed a commit to miss-islington/cpython that referenced this pull request

Sep 9, 2025
…ass, make the original class collectible (take 2) (pythonGH-137047) (python#137666)

Co-authored-by: Jelle Zijlstra <jelle.zijlstra@gmail.com>
Co-authored-by: Alyssa Coghlan <ncoghlan@gmail.com>
Co-authored-by: Petr Viktorin <encukou@gmail.com>
Co-authored-by: Serhiy Storchaka <storchaka@gmail.com>

gpshead added a commit to gpshead/cpython that referenced this pull request

Apr 12, 2026
…_` and `__delattr__` in frozen dataclasses with slots (pythonGH-144021)

pythongh-105936: Properly update closure cells for `__setattr__` and `__delattr__` in frozen dataclasses with slots (pythonGH-144021)
(cherry picked from commit 8a398bf)

The cherry-pick required additional changes beyond the original commit
because 3.13 lacks the `__class__` closure cell fixup machinery that
was added in 3.14 by pythonGH-124455 (pythongh-90562). Specifically:

- Backported `_update_func_cell_for__class__()` helper function and the
  closure fixup loop in `_add_slots()` from pythonGH-124455. Without these,
  renaming the closure variable from `cls` to `__class__` has no effect
  because nothing updates the cell when the class is recreated with slots.
- Changed `_add_slots()` to use `newcls` instead of reusing `cls` for the
  recreated class, so both old and new class references are available for
  the fixup loop.
- Replaced `assertNotHasAttr` with `assertFalse(hasattr(...))` in tests
  (assertNotHasAttr was added in 3.14).
- Dropped `test_original_class_is_gced` additions (that test does not
  exist on 3.13; it was added by pythonGH-137047 for pythongh-135228 which was not
  backported to 3.13).

Co-authored-by: Prometheus3375 <prometheus3375@gmail.com>
Co-authored-by: Sviataslau <35541026+Prometheus3375@users.noreply.github.com>
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>