Skip to content

Commit

Permalink
If the python version of Persistent had __setstate__ called with a di…
Browse files Browse the repository at this point in the history
…ctionary containing exactly two items, it would fail at idict.update(inst_dict) with 'ValueError: sequence of pairs expected' due to incorrect tuple unpacking. Do what the C version does and check for a tuple explicitly.
  • Loading branch information
jamadden committed Feb 18, 2014
1 parent 690441d commit dfc9823
Show file tree
Hide file tree
Showing 2 changed files with 17 additions and 9 deletions.
4 changes: 2 additions & 2 deletions persistent/persistence.py
Original file line number Diff line number Diff line change
Expand Up @@ -288,9 +288,9 @@ def __getstate__(self):
def __setstate__(self, state):
""" See IPersistent.
"""
try:
if isinstance(state,tuple):
inst_dict, slots = state
except:
else:
inst_dict, slots = state, ()
idict = getattr(self, '__dict__', None)
if inst_dict is not None:
Expand Down
22 changes: 15 additions & 7 deletions persistent/tests/test_persistence.py
Original file line number Diff line number Diff line change
Expand Up @@ -111,7 +111,7 @@ def test_assign_p_oid_w_valid_oid(self):
from persistent.timestamp import _makeOctets
OID = _makeOctets('\x01' * 8)
inst = self._makeOne()
inst._p_oid = OID
inst._p_oid = OID
self.assertEqual(inst._p_oid, OID)
inst._p_oid = OID # reassign only same OID

Expand Down Expand Up @@ -174,15 +174,15 @@ def test_assign_p_serial_w_valid_serial(self):
from persistent.timestamp import _makeOctets
SERIAL = _makeOctets('\x01' * 8)
inst = self._makeOne()
inst._p_serial = SERIAL
inst._p_serial = SERIAL
self.assertEqual(inst._p_serial, SERIAL)

def test_delete_p_serial(self):
from persistent.timestamp import _makeOctets
from persistent.persistence import _INITIAL_SERIAL
SERIAL = _makeOctets('\x01' * 8)
inst = self._makeOne()
inst._p_serial = SERIAL
inst._p_serial = SERIAL
self.assertEqual(inst._p_serial, SERIAL)
del(inst._p_serial)
self.assertEqual(inst._p_serial, _INITIAL_SERIAL)
Expand Down Expand Up @@ -789,6 +789,14 @@ class Derived(self._getTargetClass()):
inst.__setstate__({'baz': 'bam'})
self.assertEqual(inst.__dict__, {'baz': 'bam'})

def test___setstate___nonempty_derived_w_dict_w_two_keys(self):
class Derived(self._getTargetClass()):
pass
inst = Derived()
inst.foo = 'bar'
inst.__setstate__({'baz': 'bam', 'biz': 'boz'})
self.assertEqual(inst.__dict__, {'baz': 'bam', 'biz': 'boz'})

def test___setstate___derived_w_slots(self):
class Derived(self._getTargetClass()):
__slots__ = ('foo', '_p_baz', '_v_qux')
Expand Down Expand Up @@ -937,7 +945,7 @@ def test__p_activate_from_unsaved(self):
def test__p_activate_from_ghost(self):
inst, jar, OID = self._makeOneWithJar()
inst._p_deactivate()
inst._p_activate()
inst._p_activate()
self.assertEqual(inst._p_status, 'saved')

def test__p_activate_from_saved(self):
Expand Down Expand Up @@ -1253,7 +1261,7 @@ def inc(self):
def test__ancient_dict_layout_bug(self):
# We once had a bug in the `Persistent` class that calculated an
# incorrect offset for the ``__dict__`` attribute. It assigned
# ``__dict__`` and ``_p_jar`` to the same location in memory.
# ``__dict__`` and ``_p_jar`` to the same location in memory.
# This is a simple test to make sure they have different locations.
class P(self._getTargetClass()):
def __init__(self):
Expand Down Expand Up @@ -1319,7 +1327,7 @@ def _checkMRU(self, jar, value):

def _clearMRU(self, jar):
jar._cache._mru[:] = []

_add_to_suite = [PyPersistentTests]

if not os.environ.get('PURE_PYTHON'):
Expand All @@ -1336,7 +1344,7 @@ def _getTargetClass(self):

def _checkMRU(self, jar, value):
pass # Figure this out later

def _clearMRU(self, jar):
pass # Figure this out later

Expand Down

0 comments on commit dfc9823

Please sign in to comment.