Commit d66be83a authored by Tres Seaver's avatar Tres Seaver

Reorder to test sets before mappings.

parent 1c5fb3c2
...@@ -183,38 +183,21 @@ class _SetIteration(object): ...@@ -183,38 +183,21 @@ class _SetIteration(object):
return self return self
class _MappingBase(_Base): class _SetBase(_Base):
def setdefault(self, key, value): #_next = None
return self._set(self._to_key(key), self._to_value(value), True)[1] def add(self, key):
return self._set(self._to_key(key))[0]
def pop(self, key, default=_marker): insert = add
try:
return self._del(self._to_key(key))[1]
except KeyError:
if default is _marker:
raise
return default
def update(self, items): def remove(self, key):
if hasattr(items, 'iteritems'): self._del(self._to_key(key))
items = items.iteritems()
elif hasattr(items, 'items'):
items = items.items()
set = self.__setitem__ def update(self, items):
add = self.add
for i in items: for i in items:
set(*i) add(i)
def __setitem__(self, key, value):
# Enforce test that key has non-default comparison.
if ( getattr(key, '__lt__', None) is None and
getattr(key, '__cmp__', None) is None):
raise TypeError("Can't use default __cmp__")
self._set(self._to_key(key), self._to_value(value))
def __delitem__(self, key):
self._del(self._to_key(key))
def _p_resolveConflict(self, s_old, s_com, s_new): def _p_resolveConflict(self, s_old, s_com, s_new):
b_old = self.__class__() b_old = self.__class__()
...@@ -245,26 +228,20 @@ class _MappingBase(_Base): ...@@ -245,26 +228,20 @@ class _MappingBase(_Base):
def merge_output(it): def merge_output(it):
result._keys.append(it.key) result._keys.append(it.key)
result._values.append(it.value)
it.advance() it.advance()
while i_old.active and i_com.active and i_new.active: while i_old.active and i_com.active and i_new.active:
cmp12 = cmp(i_old.key, i_com.key) cmp12 = cmp(i_old.key, i_com.key)
cmp13 = cmp(i_old.key, i_new.key) cmp13 = cmp(i_old.key, i_new.key)
if cmp12==0: if cmp12 == 0:
if cmp13==0: if cmp13 == 0:
if i_com.value == i_old.value: result.add(i_old.key)
result[i_old.key] = i_new.value
elif i_new.value == i_old.value:
result[i_old.key] = i_com.value
else:
raise merge_error(1)
i_old.advance() i_old.advance()
i_com.advance() i_com.advance()
i_new.advance() i_new.advance()
elif (cmp13 > 0): # insert in new elif cmp13 > 0: # insert in new
merge_output(i_new) merge_output(i_new)
elif i_old.value == i_com.value: # deleted new else: # deleted new
if i_new.position == 1: if i_new.position == 1:
# Deleted the first item. This will modify the # Deleted the first item. This will modify the
# parent node, so we don't know if merging will be # parent node, so we don't know if merging will be
...@@ -272,12 +249,10 @@ class _MappingBase(_Base): ...@@ -272,12 +249,10 @@ class _MappingBase(_Base):
raise merge_error(13) raise merge_error(13)
i_old.advance() i_old.advance()
i_com.advance() i_com.advance()
else:
raise merge_error(2)
elif cmp13 == 0: elif cmp13 == 0:
if cmp12 > 0: # insert committed if cmp12 > 0: # insert committed
merge_output(i_com) merge_output(i_com)
elif i_old.value == i_new.value: # delete committed else: # delete committed
if i_com.position == 1: if i_com.position == 1:
# Deleted the first item. This will modify the # Deleted the first item. This will modify the
# parent node, so we don't know if merging will be # parent node, so we don't know if merging will be
...@@ -285,8 +260,6 @@ class _MappingBase(_Base): ...@@ -285,8 +260,6 @@ class _MappingBase(_Base):
raise merge_error(13) raise merge_error(13)
i_old.advance() i_old.advance()
i_new.advance() i_new.advance()
else:
raise merge_error(3)
else: # both keys changed else: # both keys changed
cmp23 = cmp(i_com.key, i_new.key) cmp23 = cmp(i_com.key, i_new.key)
if cmp23 == 0: if cmp23 == 0:
...@@ -314,7 +287,7 @@ class _MappingBase(_Base): ...@@ -314,7 +287,7 @@ class _MappingBase(_Base):
cmp12 = cmp(i_old.key, i_com.key) cmp12 = cmp(i_old.key, i_com.key)
if cmp12 > 0: # insert committed if cmp12 > 0: # insert committed
merge_output(i_com) merge_output(i_com)
elif cmp12 == 0 and (i_old.value == i_com.value): # del in new elif cmp12 == 0: # del in new
i_old.advance() i_old.advance()
i_com.advance() i_com.advance()
else: # dueling deletes or delete and change else: # dueling deletes or delete and change
...@@ -325,8 +298,7 @@ class _MappingBase(_Base): ...@@ -325,8 +298,7 @@ class _MappingBase(_Base):
cmp13 = cmp(i_old.key, i_new.key) cmp13 = cmp(i_old.key, i_new.key)
if cmp13 > 0: # insert new if cmp13 > 0: # insert new
merge_output(i_new) merge_output(i_new)
elif cmp13 == 0 and (i_old.value == i_new.value): elif cmp13 == 0: # deleted in committed
# deleted in committed
i_old.advance() i_old.advance()
i_new.advance() i_new.advance()
else: # dueling deletes or delete and change else: # dueling deletes or delete and change
...@@ -350,21 +322,38 @@ class _MappingBase(_Base): ...@@ -350,21 +322,38 @@ class _MappingBase(_Base):
return result.__getstate__() return result.__getstate__()
class _SetBase(_Base): class _MappingBase(_Base):
#_next = None
def add(self, key):
return self._set(self._to_key(key))[0]
insert = add def setdefault(self, key, value):
return self._set(self._to_key(key), self._to_value(value), True)[1]
def remove(self, key): def pop(self, key, default=_marker):
self._del(self._to_key(key)) try:
return self._del(self._to_key(key))[1]
except KeyError:
if default is _marker:
raise
return default
def update(self, items): def update(self, items):
add = self.add if hasattr(items, 'iteritems'):
items = items.iteritems()
elif hasattr(items, 'items'):
items = items.items()
set = self.__setitem__
for i in items: for i in items:
add(i) set(*i)
def __setitem__(self, key, value):
# Enforce test that key has non-default comparison.
if ( getattr(key, '__lt__', None) is None and
getattr(key, '__cmp__', None) is None):
raise TypeError("Can't use default __cmp__")
self._set(self._to_key(key), self._to_value(value))
def __delitem__(self, key):
self._del(self._to_key(key))
def _p_resolveConflict(self, s_old, s_com, s_new): def _p_resolveConflict(self, s_old, s_com, s_new):
b_old = self.__class__() b_old = self.__class__()
...@@ -395,20 +384,26 @@ class _SetBase(_Base): ...@@ -395,20 +384,26 @@ class _SetBase(_Base):
def merge_output(it): def merge_output(it):
result._keys.append(it.key) result._keys.append(it.key)
result._values.append(it.value)
it.advance() it.advance()
while i_old.active and i_com.active and i_new.active: while i_old.active and i_com.active and i_new.active:
cmp12 = cmp(i_old.key, i_com.key) cmp12 = cmp(i_old.key, i_com.key)
cmp13 = cmp(i_old.key, i_new.key) cmp13 = cmp(i_old.key, i_new.key)
if cmp12 == 0: if cmp12==0:
if cmp13 == 0: if cmp13==0:
result.add(i_old.key) if i_com.value == i_old.value:
result[i_old.key] = i_new.value
elif i_new.value == i_old.value:
result[i_old.key] = i_com.value
else:
raise merge_error(1)
i_old.advance() i_old.advance()
i_com.advance() i_com.advance()
i_new.advance() i_new.advance()
elif cmp13 > 0: # insert in new elif (cmp13 > 0): # insert in new
merge_output(i_new) merge_output(i_new)
else: # deleted new elif i_old.value == i_com.value: # deleted new
if i_new.position == 1: if i_new.position == 1:
# Deleted the first item. This will modify the # Deleted the first item. This will modify the
# parent node, so we don't know if merging will be # parent node, so we don't know if merging will be
...@@ -416,10 +411,12 @@ class _SetBase(_Base): ...@@ -416,10 +411,12 @@ class _SetBase(_Base):
raise merge_error(13) raise merge_error(13)
i_old.advance() i_old.advance()
i_com.advance() i_com.advance()
else:
raise merge_error(2)
elif cmp13 == 0: elif cmp13 == 0:
if cmp12 > 0: # insert committed if cmp12 > 0: # insert committed
merge_output(i_com) merge_output(i_com)
else: # delete committed elif i_old.value == i_new.value: # delete committed
if i_com.position == 1: if i_com.position == 1:
# Deleted the first item. This will modify the # Deleted the first item. This will modify the
# parent node, so we don't know if merging will be # parent node, so we don't know if merging will be
...@@ -427,6 +424,8 @@ class _SetBase(_Base): ...@@ -427,6 +424,8 @@ class _SetBase(_Base):
raise merge_error(13) raise merge_error(13)
i_old.advance() i_old.advance()
i_new.advance() i_new.advance()
else:
raise merge_error(3)
else: # both keys changed else: # both keys changed
cmp23 = cmp(i_com.key, i_new.key) cmp23 = cmp(i_com.key, i_new.key)
if cmp23 == 0: if cmp23 == 0:
...@@ -454,7 +453,7 @@ class _SetBase(_Base): ...@@ -454,7 +453,7 @@ class _SetBase(_Base):
cmp12 = cmp(i_old.key, i_com.key) cmp12 = cmp(i_old.key, i_com.key)
if cmp12 > 0: # insert committed if cmp12 > 0: # insert committed
merge_output(i_com) merge_output(i_com)
elif cmp12 == 0: # del in new elif cmp12 == 0 and (i_old.value == i_com.value): # del in new
i_old.advance() i_old.advance()
i_com.advance() i_com.advance()
else: # dueling deletes or delete and change else: # dueling deletes or delete and change
...@@ -465,7 +464,8 @@ class _SetBase(_Base): ...@@ -465,7 +464,8 @@ class _SetBase(_Base):
cmp13 = cmp(i_old.key, i_new.key) cmp13 = cmp(i_old.key, i_new.key)
if cmp13 > 0: # insert new if cmp13 > 0: # insert new
merge_output(i_new) merge_output(i_new)
elif cmp13 == 0: # deleted in committed elif cmp13 == 0 and (i_old.value == i_new.value):
# deleted in committed
i_old.advance() i_old.advance()
i_new.advance() i_new.advance()
else: # dueling deletes or delete and change else: # dueling deletes or delete and change
......
...@@ -363,56 +363,13 @@ class Test_BucketBase(unittest.TestCase): ...@@ -363,56 +363,13 @@ class Test_BucketBase(unittest.TestCase):
self.assertTrue(key in bucket) self.assertTrue(key in bucket)
def _assertRaises(self, e_type, checked, *args, **kw): class Test__SetIteration(unittest.TestCase):
try:
checked(*args, **kw)
except e_type as e:
return e
self.fail("Didn't raise: %s" % e_type.__name__)
class Test__MappingBase(unittest.TestCase):
assertRaises = _assertRaises assertRaises = _assertRaises
def _getTargetClass(self): def _getTargetClass(self):
from .._base import _MappingBase from .._base import _SetIteration
return _MappingBase return _SetIteration
def _makeOne(self):
class _TestMapping(self._getTargetClass()):
_values = None
def __setstate__(self, state):
state, self._next = state
self._keys = []
self._values = []
for i in range(len(state) // 2):
self._keys.append(state[i])
self._values.append(state[i+1])
def clear(self):
self._keys, self._values, self._next = [], [], None
def iteritems(self):
return iter(zip(self._keys, self._values))
return _TestMapping()
def test__p_resolveConflict_delete_first_new(self):
from ..Interfaces import BTreesConflictError
bucket = self._makeOne()
s_old = (['a', 0, 'b', 1], None)
s_com = (['a', 1, 'b', 2, 'c', 3], None)
s_new = (['b', 4], None)
e = self.assertRaises(BTreesConflictError,
bucket._p_resolveConflict, s_old, s_com, s_new)
self.assertEqual(e.reason, 2)
def test__p_resolveConflict_delete_first_committed(self):
from ..Interfaces import BTreesConflictError
bucket = self._makeOne()
s_old = (['a', 0, 'b', 1], None)
s_com = (['b', 4], None)
s_new = (['a', 1, 'b', 2, 'c', 3], None)
e = self.assertRaises(BTreesConflictError,
bucket._p_resolveConflict, s_old, s_com, s_new)
self.assertEqual(e.reason, 3)
class Test__SetBase(unittest.TestCase): class Test__SetBase(unittest.TestCase):
...@@ -498,6 +455,51 @@ class Test__SetBase(unittest.TestCase): ...@@ -498,6 +455,51 @@ class Test__SetBase(unittest.TestCase):
self.assertEqual(e.reason, 13) self.assertEqual(e.reason, 13)
class Test__MappingBase(unittest.TestCase):
assertRaises = _assertRaises
def _getTargetClass(self):
from .._base import _MappingBase
return _MappingBase
def _makeOne(self):
class _TestMapping(self._getTargetClass()):
_values = None
def __setstate__(self, state):
state, self._next = state
self._keys = []
self._values = []
for i in range(len(state) // 2):
self._keys.append(state[i])
self._values.append(state[i+1])
def clear(self):
self._keys, self._values, self._next = [], [], None
def iteritems(self):
return iter(zip(self._keys, self._values))
return _TestMapping()
def test__p_resolveConflict_delete_first_new(self):
from ..Interfaces import BTreesConflictError
bucket = self._makeOne()
s_old = (['a', 0, 'b', 1], None)
s_com = (['a', 1, 'b', 2, 'c', 3], None)
s_new = (['b', 4], None)
e = self.assertRaises(BTreesConflictError,
bucket._p_resolveConflict, s_old, s_com, s_new)
self.assertEqual(e.reason, 2)
def test__p_resolveConflict_delete_first_committed(self):
from ..Interfaces import BTreesConflictError
bucket = self._makeOne()
s_old = (['a', 0, 'b', 1], None)
s_com = (['b', 4], None)
s_new = (['a', 1, 'b', 2, 'c', 3], None)
e = self.assertRaises(BTreesConflictError,
bucket._p_resolveConflict, s_old, s_com, s_new)
self.assertEqual(e.reason, 3)
def test_suite(): def test_suite():
return unittest.TestSuite(( return unittest.TestSuite((
unittest.makeSuite(Test_BucketBase), unittest.makeSuite(Test_BucketBase),
......
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