zopefoundation/persistent — pull request #9 by jamadden (2014-03-06 15:26:22+00:00)
Title: Python _p_activate can corrupt non-ghost objects and lead to POSKeyErrors for unsaved objects

Previously, `_p_activate` in the pure-python Persistent object didn't check what the object's state was, only whether it had a jar and OID. It unconditionally called `setstate` on the jar if it had those two things. The C version, in contrast, checks it's state and only unghostifies itself if it is known to be a ghost.

There were two consequences to this behaviour difference. First, if `_p_activate` was ever called more than once on an object that had changes, those changes would get overwritten. Second, if `_p_activate` was called on an object that was newly added to a ZODB connection but not yet committed, ZODB's storage would throw a `POSKeyError` because the OID has only been assigned, it hasn't yet been saved.

It's subtle to see in the diff because it's an indentation difference, but this change makes the Python version also check its state and only unghostify true ghosts.