python / python/mypy

Feature request: flag attributes set in `__init__` but not `__setstate__`

Open
#15,797 0 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

feature
Dominant language
Python
Stars
20.6k
Forks
3.3k
PR merge metrics
PR metrics pending

Description

Feature

If an instance attribute is defined in __init__ but its definition is missing from __setstate__, this could cause a crash when an object is deserialized and the attribute is accessed.

Pitch

import pickle

class A:
    """
    Attribute `a` is persistent and serialized.
    Attribute `b` is temporary and not serialized.
    """
    def __init__(self) -> None:
        self.a: int = 1
        self.b: int = 2

    def sum(self) -> int:
        return self.a + self.b

    def __getstate__(self) -> tuple[int]:
        return (self.a,)

    def __setstate__(self, state: tuple[int]) -> None:
        self.a = state[0]
        # BUG: self.b is not set

if __name__ == '__main__':
    a = A()
    print(a.sum())
    b = pickle.loads(pickle.dumps(a))
    print(b.sum())  # AttributeError
$ mypy --version
mypy 1.4.1 (compiled: yes)
$ mypy --strict x.py
Success: no issues found in 1 source file

This bug pattern has bitten me multiple times. Especially in cases where serialization is rare and the test cases that stress class interfaces are not performing deserialization, this bug can make it into releases undetected. This seems like a great candidate for a bug to catch with static analysis. It seems appropriate for mypy because it is in some sense a type bug - if we're using the type model where __init__ is supposed to fully initialize a typed interface, then __setstate__ should do the same.

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start by reproducing the example in x.py with mypy --strict x.py, then inspect how mypy models initialization and serialization methods. Done should mean that the shown missing assignment in __setstate__ produces an appropriate diagnostic while valid temporary attributes remain supported.

Written by the indexing model from the issue text.

Assessment

Tech stack
python
Domain
devtools
Issue type
Feature
Difficulty
5/5
Estimated time
Over a week
Activity status
Stale
Clarity
Mostly clear
Newbie friendliness
35/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.