Commit a643eb37 authored by Kirill Smelkov's avatar Kirill Smelkov

BTreePy: Reset ._data unconditionally in .clear()

_Tree.clear() is called by _Tree.__setstate__() to reset both .data and
._firstbucket before actually proceeding with setting internal state
with data loaded from database.

However since 0718a45e (Use a Python __reduce__ method to make pickles
match C.) ._data reset became conditional, first checking that ._data is
not already empty.

The .__setstate__() is often called with object being a ghost.  However
ZODB was never promising to keep attributes alive on ghost objects and
in fact attributes kept in __dict__ was always released, but attributes
in slotted variables, probably due to overlook, started to be released
on ghostification only recently:

    https://github.com/zopefoundation/persistent/commit/fe2219f4
    https://github.com/zopefoundation/persistent/pull/44

and that change causes many BTree tests to fail in pure-python part, e.g.:

    ERROR: testGhostUnghost (BTrees.tests.test_IIBTree.IIBTreeTest)
    ----------------------------------------------------------------------
    Traceback (most recent call last):
      File "BTrees/tests/common.py", line 122, in testGhostUnghost
        self.assertEqual(list(root2[i].items()) , list(t.items()))
      File "/home/kirr/src/wendelin/z/persistent/persistent/persistence.py", line 266, in __getattribute__
        oga(self, '_p_activate')()
      File "/home/kirr/src/wendelin/z/persistent/persistent/persistence.py", line 386, in _p_activate
        jar.setstate(self)
      File "/home/kirr/src/wendelin/z/ZODB/src/ZODB/Connection.py", line 771, in setstate
        self._reader.setGhostState(obj, p)
      File "/home/kirr/src/wendelin/z/ZODB/src/ZODB/serialize.py", line 623, in setGhostState
        obj.__setstate__(state)
      File "BTrees/_base.py", line 1069, in __setstate__
        self.clear()
      File "BTrees/_base.py", line 818, in clear
        if self._data:
      File "/home/kirr/src/wendelin/z/persistent/persistent/persistence.py", line 268, in __getattribute__
        return oga(self, name)
    AttributeError: _data

Via unconditionally resetting ._data in clear we can make the problem go away.

After this patch with PURE_PYTHON=1 BTree testsuite is passing fully again.
parent 33ab3d3e
......@@ -815,9 +815,7 @@ class _Tree(_Base):
self._del(self._to_key(key))
def clear(self):
if self._data:
# In the case of __init__, this was already set by __new__
self._data = []
self._data = []
self._firstbucket = None
def __nonzero__(self):
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment