Skip to content

Commit

Permalink
The pure-Python Persistent class no longer calls subclass's __setattr…
Browse files Browse the repository at this point in the history
…__ at instance creation time, just like the C version.
  • Loading branch information
jamadden committed Feb 24, 2014
1 parent bf4fd8f commit 85eae63
Show file tree
Hide file tree
Showing 3 changed files with 20 additions and 5 deletions.
3 changes: 3 additions & 0 deletions CHANGES.rst
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,9 @@
4.0.8 (Unreleased)
------------------

- The pure-Python ``Persistent`` class no longer calls subclass's
``__setattr__`` at instance creation time. (PR #8)

- Make it possible to delete ``_p_jar`` / ``_p_oid`` of a pure-Python
``Persistent`` object which has been removed from the jar's cache
(fixes aborting a ZODB Connection that has added objects). (PR #7)
Expand Down
14 changes: 9 additions & 5 deletions persistent/persistence.py
Original file line number Diff line number Diff line change
Expand Up @@ -53,11 +53,15 @@ class Persistent(object):

def __new__(cls, *args, **kw):
inst = super(Persistent, cls).__new__(cls)
inst.__jar = None
inst.__oid = None
inst.__serial = None
inst.__flags = None
inst.__size = 0
# We bypass the __setattr__ implementation of this object
# at __new__ time, just like the C implementation does. This
# makes us compatible with subclasses that want to access
# properties like _p_changed in their setattr implementation
_OSA(inst, '_Persistent__jar', None)
_OSA(inst, '_Persistent__oid', None)
_OSA(inst, '_Persistent__serial', None)
_OSA(inst, '_Persistent__flags', None)
_OSA(inst, '_Persistent__size', 0)
return inst

# _p_jar: see IPersistent.
Expand Down
8 changes: 8 additions & 0 deletions persistent/tests/test_persistence.py
Original file line number Diff line number Diff line change
Expand Up @@ -1325,6 +1325,14 @@ class mixed1(alternate, self._getTargetClass()):
class mixed2(self._getTargetClass(), alternate):
pass

def test_setattr_in_subclass_is_not_called_creating_an_instance(self):
class subclass(self._getTargetClass()):
_v_setattr_called = False
def __setattr__(self, name, value):
object.__setattr__(self, '_v_setattr_called', True)
super(subclass,self).__setattr__(name, value)
inst = subclass()
self.assertEqual(object.__getattribute__(inst,'_v_setattr_called'), False)

class PyPersistentTests(unittest.TestCase, _Persistent_Base):

Expand Down

0 comments on commit 85eae63

Please sign in to comment.