Skip to content

fix(slots): preserve __dict__ state when pickling slotted classes - #1643

Open
saadkhantareen wants to merge 1 commit into
python-attrs:mainfrom
saadkhantareen:fix/preserve-dict-state-when-pickling-slotted-classes
Open

saadkhantareen wants to merge 1 commit into
python-attrs:mainfrom
saadkhantareen:fix/preserve-dict-state-when-pickling-slotted-classes

Conversation

@saadkhantareen

Copy link
Copy Markdown

Summary

A slotted attrs class that inherits from a non-slotted class has an instance __dict__, but the generated __getstate__ / __setstate__ only handled the attrs fields.
Any additional state stored in that __dict__ -- for example an attribute set in __attrs_post_init__ or by a mixin -- was silently dropped when the instance was pickled (which also breaks multiprocessing, as reported in #1020) or copied.

This change makes the generated state handling preserve that __dict__ state, mirroring what object.__getstate__() returns for such classes, while keeping the existing state format.

Changes

  • src/attr/_make.py: in _ClassBuilder._make_getstate_setstate(), slots_getstate now merges entries from the instance __dict__ that are not attrs fields into the returned state dict (attrs fields take precedence). slots_setstate restores those extra entries into the instance __dict__ when the instance has one. Instances without a __dict__ ignore extra keys as before, so unpickling after an attribute was removed from a slotted class keeps working, and both the pre-22.2.0 tuple state format and the current dict format remain readable.
  • tests/test_slots.py: added a slotted subclass of a non-slotted attrs class whose __attrs_post_init__ stores an extra attribute in __dict__, with regression tests covering a pickle round-trip for every protocol and copy.copy.
  • changelog.d/1020.change.md: added a news fragment.

Tests

  • PYTHONPATH=src python -m pytest tests/test_slots.py -q -- 59 passed, 1 skipped
  • PYTHONPATH=src python -m pytest tests/test_dunders.py tests/test_funcs.py -q -- 152 passed
  • ruff format --check src/attr/_make.py tests/test_slots.py and ruff check src/attr/_make.py tests/test_slots.py -- clean

Fixes #1020

Pull Request Checklist

  • I acknowledge this project's AI policy.
  • This pull request is not from my main branch.
  • There's tests for all new and changed code.
  • Changes or additions to public APIs are reflected in our type stubs (files ending in .pyi).
    • ...and used in the stub test file typing_tests/baseline.py or, if necessary, typing_tests/mypy.py.
    • If they've been added to attr/__init__.pyi, they've also been re-imported in attrs/__init__.pyi.
  • The documentation has been updated.
    • New functions/classes have to be added to docs/api.rst by hand.
    • Changes to the signatures of @attr.s() and @attrs.define() have to be added by hand too.
    • Changed/added classes/methods/functions have appropriate versionadded, versionchanged, or deprecated directives.
    • Documentation in .rst and .md files is written using semantic newlines.
  • Changes have news fragments in changelog.d.

Copilot AI balanced review requested due to automatic review settings October 15, 2026 10:11

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot was unable to review this pull request because the user who requested the review has reached their quota limit.

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Mixed inheritance between slotted and non slotted classes leads to issues with parallelisation.

2 participants