From a6e7878258322a6c3c41f454dbff3d5616686650 Mon Sep 17 00:00:00 2001 From: dieter Date: Sat, 7 Nov 2020 00:08:46 +0100 Subject: [PATCH 1/4] fix persistency bug in the Python version --- BTrees/_base.py | 1 + CHANGES.rst | 3 +++ 2 files changed, 4 insertions(+) diff --git a/BTrees/_base.py b/BTrees/_base.py index b42ee83..e7dd815 100644 --- a/BTrees/_base.py +++ b/BTrees/_base.py @@ -1050,6 +1050,7 @@ def _del(self, key): self._firstbucket = child._next removed_first_bucket = True del data[index] + self._p_changed = True return removed_first_bucket, value diff --git a/CHANGES.rst b/CHANGES.rst index b2d1d31..566ee46 100644 --- a/CHANGES.rst +++ b/CHANGES.rst @@ -5,6 +5,9 @@ 4.7.3 (unreleased) ================== +- Fix persistency bug in the Python version + (`#118 https://github.com/zopefoundation/BTrees/issues/118`_). + - Fix ``Tree.__setstate__`` to no longer accept children besides tree or bucket types to prevent crashes. See `PR 143 `_ for details. From 578d301bf6e54110602c8622b9ffb3a0e6db2db9 Mon Sep 17 00:00:00 2001 From: dieter Date: Sat, 7 Nov 2020 06:42:49 +0100 Subject: [PATCH 2/4] fix broken link syntax in `CHANGES.rst` --- CHANGES.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGES.rst b/CHANGES.rst index 566ee46..c881835 100644 --- a/CHANGES.rst +++ b/CHANGES.rst @@ -6,7 +6,7 @@ ================== - Fix persistency bug in the Python version - (`#118 https://github.com/zopefoundation/BTrees/issues/118`_). + (`#118 `_). - Fix ``Tree.__setstate__`` to no longer accept children besides tree or bucket types to prevent crashes. See `PR 143 From 40ebe529fee173efdd794ee1b46a597682154c7b Mon Sep 17 00:00:00 2001 From: dieter Date: Mon, 9 Nov 2020 09:56:41 +0100 Subject: [PATCH 3/4] add test -- correctly works in isolation but not when activated via `tox` --- BTrees/tests/common.py | 29 +++++++++++--------- BTrees/tests/testPersistency.py | 47 +++++++++++++++++++++++++++++++++ tox.ini | 2 +- 3 files changed, 65 insertions(+), 13 deletions(-) create mode 100644 BTrees/tests/testPersistency.py diff --git a/BTrees/tests/common.py b/BTrees/tests/common.py index 1267704..1f0e3ad 100644 --- a/BTrees/tests/common.py +++ b/BTrees/tests/common.py @@ -91,24 +91,14 @@ class SignedMixin(object): KEY_RANDRANGE_ARGS = (-2000, 2001) -class Base(SignedMixin): - # Tests common to all types: sets, buckets, and BTrees +class ZODBAccess(object): db = None - def _getTargetClass(self): - raise NotImplementedError("subclass should return the target type") - - def _makeOne(self): - return self._getTargetClass()() - - def setUp(self): - super(Base, self).setUp() - _skip_if_pure_py_and_py_test(self) - def tearDown(self): if self.db is not None: self.db.close() + del self.db def _getRoot(self): from ZODB import DB @@ -131,6 +121,21 @@ def _closeRoot(self, root): transaction.abort() root._p_jar.close() + +class Base(ZODBAccess, SignedMixin): + # Tests common to all types: sets, buckets, and BTrees + + def _getTargetClass(self): + raise NotImplementedError("subclass should return the target type") + + def _makeOne(self): + return self._getTargetClass()() + + def setUp(self): + super(Base, self).setUp() + _skip_if_pure_py_and_py_test(self) + + def testPersistentSubclass(self): # Can we subclass this and Persistent? # https://github.com/zopefoundation/BTrees/issues/78 diff --git a/BTrees/tests/testPersistency.py b/BTrees/tests/testPersistency.py new file mode 100644 index 0000000..4b36554 --- /dev/null +++ b/BTrees/tests/testPersistency.py @@ -0,0 +1,47 @@ +############################################################################## +# +# Copyright (c) 2020 Zope Foundation and Contributors. +# All Rights Reserved. +# +# This software is subject to the provisions of the Zope Public License, +# Version 2.1 (ZPL). A copy of the ZPL should accompany this distribution. +# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED +# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS +# FOR A PARTICULAR PURPOSE +# +############################################################################## + +from unittest import TestCase + +from ..OOBTree import OOBTree, OOBTreePy +from .common import _skip_wo_ZODB, ZODBAccess + + +BUCKET_SIZE = OOBTreePy.max_leaf_size + + +class TestPersistency(ZODBAccess, TestCase): + @_skip_wo_ZODB + def test_empty_bucket_persistency(self): + from transaction import commit + root = self._getRoot() + try: + # tree with 3 buckets (internal implementation details) + tree = OOBTree( + dict((i, i) for i in range(3 * BUCKET_SIZE // 2 + 2))) + root["tree"] = tree + commit() + # almost clear the second bucket keeping the last element + for i in range(BUCKET_SIZE // 2, BUCKET_SIZE - 1): + del tree[i] + commit() + del tree[BUCKET_SIZE - 1] # remove the last element + commit() + tree._check() + tree._p_deactivate() + tree._check() # fails in case of bad persistency + finally: + self._closeRoot(root) + + diff --git a/tox.ini b/tox.ini index e4cf67a..2d07252 100644 --- a/tox.ini +++ b/tox.ini @@ -3,7 +3,7 @@ envlist = # Jython support pending 2.7 support, due 2012-07-15 or so. See: # http://fwierzbicki.blogspot.com/2012/03/adconion-to-fund-jython-27.html # py27,jython,pypy,coverage,docs - py27,py27-pure,py35,py35-pure,py36,py37,py38,pypy,pypy3,w_zodb,coverage,docs + py27,py27-pure,py35,py35-pure,py36,py37,py38,pypy,pypy3,w_zodb,w_zodb-pure,coverage,docs [testenv] usedevelop = true From 159fb2261d1aafafb961e51c94a7f5f3152e595e Mon Sep 17 00:00:00 2001 From: dieter Date: Mon, 9 Nov 2020 11:58:15 +0100 Subject: [PATCH 4/4] `tox` workaround: env `w_zodb-pure` does not inherit settings of env `w_zodb` -- copy them explicitly --- tox.ini | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/tox.ini b/tox.ini index 2d07252..72890d2 100644 --- a/tox.ini +++ b/tox.ini @@ -29,6 +29,12 @@ basepython = deps = ZODB +[testenv:w_zodb-pure] +basepython = + python2.7 +deps = + ZODB + [testenv:coverage] basepython = python3.6