Custom _p_invalidate not called when deleting _p_changed
Affects | Status | Importance | Assigned to | Milestone | |
---|---|---|---|---|---|
ZODB |
Confirmed
|
Low
|
Unassigned |
Bug Description
From persistent/
There are two ways to invalidate an object: call the
_p_invalidate() method (preferred) or delete its _p_changed
attribute.
It turns out that these two are not equivalent when the object has a custom _p_invalidate method. Specifically, the custom _p_invalidate method is never called when you do delete the _p_changed attribute. (Similarly, a custom _p_activate is never called when unghostifying an object, but I don't have a use case for that that isn't already covered by having a custom __setstate__)
Looking at cPersistence.c it is immediately obvious why. The way things are implemented, Persistent.
I think it would be better if that was reversed so Per_set_changed would call the objects (possibly custom) _p_invalidate, which would then set the state and call _p_deactivate itself. This would not only fix the immediate problem, but also make the control flow more obvious. (Modifying _p_changed dispatches to either _p_deactivate or _p_invalidate. _p_invalidate sets state to UPTODATE, calls _p_deactivate, and then forces the object to become a ghost)
Would a patch along those lines be acceptable for 3.10? Or should I rather concentrate on a patch that eliminates all *uses* of "del p._changed" from ZODB (a one-line change in ZODB/Connection
Changed in zodb: | |
status: | Incomplete → New |
status: | New → Confirmed |
I found a workaround that seems to cover most cases. Just override the _p_changed property in your class like this:
class P(persistent. Persistent) :
_p_changed = property(
persistent. Persistent. _p_changed. __get__ ,
persistent. Persistent. _p_changed. __set__ , invalidate( ), /bugs.launchpad .net/zodb/ +bug/586526",
lambda self: self._p_
"Workaround for https:/
)
This should work unless there is code out there that uses persistent. Persistent. _p_changed. __delete_ _ or the c function cPersistence. c:Per_set_ changed directly. I'm guessing there is not a lot of code that uses either.
I'm still interested in working on a patch to fix this, but only if I know that it has a chance.