Skip to content

Frozen dataclasses with slots cannot override __getstate__ or __setstate__ #104035

Description

@drhagen

You are supposed to be able to override how pickle pickles an object with __getstate__ and __setstate__. However, these methods are ignored in a dataclass when specifying both frozen=True and slots=True.

See this example:

import pickle
from dataclasses import dataclass


@dataclass(frozen=True, slots=True)
class Foo:
    bar: int

    def __getstate__(self):
        print("getstate")
        return {"bar": self.bar}

    def __setstate__(self, state):
        print("setstate")
        object.__setattr__(self, "bar", state["bar"])

b = pickle.dumps(Foo(1))
foo = pickle.loads(b)

The expected "getstate" and "setstate" lines are never printed because the supplied methods are never called. If either frozen or slots is removed, the expected lines are printed.

From the source code, it is pretty clear why this is happening. If frozen and slots are both True, then special versions of __getstate__ and __setstate__ are unconditionally attached to the dataclass. The dataclass decorator should probably treat this way that it does other methods—only add a method if it is not already present.

Linked PRs

Activity

  1. added
    type-bugAn unexpected behavior, bug, or error
    on May 1, 2023
  2. ericvsmith commented on May 1, 2023

    @ericvsmith
    Member

    It does seem reasonable to ignore __getstate__ and __setstate__ if they're already set. Have you tested this? And in particular, does it break any existing tests?

  3. added
    stdlibStandard Library Python modules in the Lib/ directory
    on May 1, 2023
  4. added a commit that references this issue on May 1, 2023
  5. sobolevn commented on May 1, 2023

    @sobolevn
    Member

    Oh, I just went for fixing this in #104041 :)

    New logic will allow users to customize __getstate__ and __setstate__ method.
    Thanks a lot, @drhagen for finding this :)

    It is funny that I've spent the whole day optimizing these two in #103032, but I haven't seen this! 👍

  6. added a commit that references this issue on May 1, 2023
  7. added a commit that references this issue on May 1, 2023
  8. added a commit that references this issue on May 1, 2023
  9. added a commit that references this issue on May 1, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    stdlibStandard Library Python modules in the Lib/ directorytype-bugAn unexpected behavior, bug, or error

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions