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):
return self
class _MappingBase(_Base):
class _SetBase(_Base):
def setdefault(self, key, value):
return self._set(self._to_key(key), self._to_value(value), True)[1]
#_next = None
def add(self, key):
return self._set(self._to_key(key))[0]
def pop(self, key, default=_marker):
try:
return self._del(self._to_key(key))[1]
except KeyError:
if default is _marker:
raise
return default
insert = add
def update(self, items):
if hasattr(items, 'iteritems'):
items = items.iteritems()
elif hasattr(items, 'items'):
items = items.items()
def remove(self, key):
self._del(self._to_key(key))
set = self.__setitem__
def update(self, items):
add = self.add
for i in items:
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))
add(i)
def _p_resolveConflict(self, s_old, s_com, s_new):
b_old = self.__class__()
......@@ -245,26 +228,20 @@ class _MappingBase(_Base):
def merge_output(it):
result._keys.append(it.key)
result._values.append(it.value)
it.advance()
while i_old.active and i_com.active and i_new.active:
cmp12 = cmp(i_old.key, i_com.key)
cmp13 = cmp(i_old.key, i_new.key)
if cmp12==0:
if cmp13==0:
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)
if cmp12 == 0:
if cmp13 == 0:
result.add(i_old.key)
i_old.advance()
i_com.advance()
i_new.advance()
elif (cmp13 > 0): # insert in new
elif cmp13 > 0: # insert in new
merge_output(i_new)
elif i_old.value == i_com.value: # deleted new
else: # deleted new
if i_new.position == 1:
# Deleted the first item. This will modify the
# parent node, so we don't know if merging will be
......@@ -272,12 +249,10 @@ class _MappingBase(_Base):
raise merge_error(13)
i_old.advance()
i_com.advance()
else:
raise merge_error(2)
elif cmp13 == 0:
if cmp12 > 0: # insert committed
merge_output(i_com)
elif i_old.value == i_new.value: # delete committed
else: # delete committed
if i_com.position == 1:
# Deleted the first item. This will modify the
# parent node, so we don't know if merging will be
......@@ -285,8 +260,6 @@ class _MappingBase(_Base):
raise merge_error(13)
i_old.advance()
i_new.advance()
else:
raise merge_error(3)
else: # both keys changed
cmp23 = cmp(i_com.key, i_new.key)
if cmp23 == 0:
......@@ -314,7 +287,7 @@ class _MappingBase(_Base):
cmp12 = cmp(i_old.key, i_com.key)
if cmp12 > 0: # insert committed
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_com.advance()
else: # dueling deletes or delete and change
......@@ -325,8 +298,7 @@ class _MappingBase(_Base):
cmp13 = cmp(i_old.key, i_new.key)
if cmp13 > 0: # insert new
merge_output(i_new)
elif cmp13 == 0 and (i_old.value == i_new.value):
# deleted in committed
elif cmp13 == 0: # deleted in committed
i_old.advance()
i_new.advance()
else: # dueling deletes or delete and change
......@@ -350,21 +322,38 @@ class _MappingBase(_Base):
return result.__getstate__()
class _SetBase(_Base):
#_next = None
def add(self, key):
return self._set(self._to_key(key))[0]
class _MappingBase(_Base):
insert = add
def setdefault(self, key, value):
return self._set(self._to_key(key), self._to_value(value), True)[1]
def remove(self, key):
self._del(self._to_key(key))
def pop(self, key, default=_marker):
try:
return self._del(self._to_key(key))[1]
except KeyError:
if default is _marker:
raise
return default
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:
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):
b_old = self.__class__()
......@@ -395,20 +384,26 @@ class _SetBase(_Base):
def merge_output(it):
result._keys.append(it.key)
result._values.append(it.value)
it.advance()
while i_old.active and i_com.active and i_new.active:
cmp12 = cmp(i_old.key, i_com.key)
cmp13 = cmp(i_old.key, i_new.key)
if cmp12 == 0:
if cmp13 == 0:
result.add(i_old.key)
if cmp12==0:
if cmp13==0:
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_com.advance()
i_new.advance()
elif cmp13 > 0: # insert in new
elif (cmp13 > 0): # insert in new
merge_output(i_new)
else: # deleted new
elif i_old.value == i_com.value: # deleted new
if i_new.position == 1:
# Deleted the first item. This will modify the
# parent node, so we don't know if merging will be
......@@ -416,10 +411,12 @@ class _SetBase(_Base):
raise merge_error(13)
i_old.advance()
i_com.advance()
else:
raise merge_error(2)
elif cmp13 == 0:
if cmp12 > 0: # insert committed
merge_output(i_com)
else: # delete committed
elif i_old.value == i_new.value: # delete committed
if i_com.position == 1:
# Deleted the first item. This will modify the
# parent node, so we don't know if merging will be
......@@ -427,6 +424,8 @@ class _SetBase(_Base):
raise merge_error(13)
i_old.advance()
i_new.advance()
else:
raise merge_error(3)
else: # both keys changed
cmp23 = cmp(i_com.key, i_new.key)
if cmp23 == 0:
......@@ -454,7 +453,7 @@ class _SetBase(_Base):
cmp12 = cmp(i_old.key, i_com.key)
if cmp12 > 0: # insert committed
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_com.advance()
else: # dueling deletes or delete and change
......@@ -465,7 +464,8 @@ class _SetBase(_Base):
cmp13 = cmp(i_old.key, i_new.key)
if cmp13 > 0: # insert 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_new.advance()
else: # dueling deletes or delete and change
......
......@@ -363,56 +363,13 @@ class Test_BucketBase(unittest.TestCase):
self.assertTrue(key in bucket)
def _assertRaises(self, e_type, checked, *args, **kw):
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):
class Test__SetIteration(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)
from .._base import _SetIteration
return _SetIteration
class Test__SetBase(unittest.TestCase):
......@@ -498,6 +455,51 @@ class Test__SetBase(unittest.TestCase):
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():
return unittest.TestSuite((
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