Skip to content

Commit

Permalink
Ignore __weakref__ in __setstate__ & __getstate__
Browse files Browse the repository at this point in the history
Fixes #311
  • Loading branch information
hynek committed Jan 17, 2018
1 parent 1f0d851 commit 4edcdb0
Show file tree
Hide file tree
Showing 4 changed files with 25 additions and 3 deletions.
1 change: 1 addition & 0 deletions changelog.d/311.change.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
In slots classes, ``__getstate__`` and ``__setstate__`` now ignore the ``__weakref__`` attribute.
1 change: 1 addition & 0 deletions changelog.d/324.change.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
In slots classes, ``__getstate__`` and ``__setstate__`` now ignore the ``__weakref__`` attribute.
12 changes: 9 additions & 3 deletions src/attr/_make.py
Original file line number Diff line number Diff line change
Expand Up @@ -443,20 +443,26 @@ def _create_slots_class(self):
if qualname is not None:
cd["__qualname__"] = qualname

attr_names = tuple(self._attr_names)
# __weakref__ is not writable.
state_attr_names = tuple(
an for an in self._attr_names if an != "__weakref__"
)

def slots_getstate(self):
"""
Automatically created by attrs.
"""
return tuple(getattr(self, name) for name in attr_names)
return tuple(
getattr(self, name)
for name in state_attr_names
)

def slots_setstate(self, state):
"""
Automatically created by attrs.
"""
__bound_setattr = _obj_setattr.__get__(self, Attribute)
for name, value in zip(attr_names, state):
for name, value in zip(state_attr_names, state):
__bound_setattr(name, value)

# slots and frozen require __getstate__/__setstate__ to work
Expand Down
14 changes: 14 additions & 0 deletions tests/test_make.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@

from __future__ import absolute_import, division, print_function

import copy
import inspect
import itertools
import sys
Expand Down Expand Up @@ -1054,3 +1055,16 @@ def fake_meth(self):

assert "42" == rv.__module__ == fake_meth.__module__
assert "23" == rv.__qualname__ == fake_meth.__qualname__

def test_weakref_setstate(self):
"""
__weakref__ is not set on in setstate because it's not writable in
slots classes.
"""
@attr.s(slots=True)
class C(object):
__weakref__ = attr.ib(
init=False, hash=False, repr=False, cmp=False
)

assert C() == copy.deepcopy(C())

0 comments on commit 4edcdb0

Please sign in to comment.