Skip to content

Commit

Permalink
Fix setting _p_changed for small pure-Python BTrees.
Browse files Browse the repository at this point in the history
  • Loading branch information
jamadden committed Apr 7, 2015
1 parent b49be3c commit 141c28a
Show file tree
Hide file tree
Showing 4 changed files with 43 additions and 6 deletions.
1 change: 1 addition & 0 deletions .gitignore
Expand Up @@ -16,3 +16,4 @@ coverage.xml
*.egg
dist
.eggs/
.dir-locals.el
15 changes: 10 additions & 5 deletions BTrees/_base.py
Expand Up @@ -883,11 +883,16 @@ def _set(self, key, value=None, ifunset=False):
max_size = self.max_leaf_size
if child.size > max_size:
self._grow(child, index)
elif (grew is not None and
child.__class__ is self._bucket_type and
len(data) == 1 and
child._p_oid is None
):

# If a BTree contains only a single bucket, BTree.__getstate__()
# includes the bucket's entire state, and the bucket doesn't get
# an oid of its own. So if we have a single oid-less bucket that
# changed, it's *our* oid that should be marked as changed -- the
# bucket doesn't have one.
if (grew is not None and
child.__class__ is self._bucket_type and
len(data) == 1 and
child._p_oid is None):
self._p_changed = 1
return result

Expand Down
30 changes: 29 additions & 1 deletion BTrees/tests/common.py
Expand Up @@ -768,7 +768,6 @@ def testPop(self):
# Too many arguments.
self.assertRaises(TypeError, t.pop, 1, 2, 3)


class BTreeTests(MappingBase):
# Tests common to all BTrees

Expand Down Expand Up @@ -1091,6 +1090,35 @@ def testDamagedIterator(self):
self.assertEqual(str(v), str(k[0]))
self._checkIt(t)

def testAddTwoSetsChanged(self):
# A bug in the BTree Python implementation once
# caused adding a second item to a tree to fail
# to set _p_changed (adding the first item sets it because
# the _firstbucket gets set, but the second item only grew the
# existing bucket)
t = self._makeOne()
# Note that for the property to actually hold, we have to fake a
# _p_jar and _p_oid
t._p_oid = b'\0\0\0\0\0'
class Jar(object):
def __init__(self):
self._cache = self
self.registered = None

def mru(self, arg):
pass
def readCurrent(self, arg):
pass
def register(self, arg):
self.registered = arg

t._p_jar = Jar()
t[1] = 3
t._p_changed = False
t._p_jar.registered = None
t[2] = 4
self.assertTrue(t._p_changed)
self.assertEqual(t, t._p_jar.registered)

class NormalSetTests(Base):
# Test common to all set types
Expand Down
3 changes: 3 additions & 0 deletions CHANGES.rst
Expand Up @@ -7,6 +7,9 @@
- Suppress testing 64-bit values in OLBTrees on 32 bit machines.
See: https://github.com/zopefoundation/BTrees/issues/9

- Fix _p_changed for small pure-Python BTrees.
See https://github.com/zopefoundation/BTrees/issues/10


4.1.1 (2014-12-27)
------------------
Expand Down

0 comments on commit 141c28a

Please sign in to comment.