Commit 20a7ea71 authored by Kirill Smelkov's avatar Kirill Smelkov

.

parent 7305c503
...@@ -495,7 +495,12 @@ def Restructure(ztree, newStructure): ...@@ -495,7 +495,12 @@ def Restructure(ztree, newStructure):
# AllStructs generates subset of all possible BTree structures for BTrees with # AllStructs generates subset of all possible BTree structures for BTrees with
# specified keys and btree depth up-to maxdepth. Each tree node is split by # specified keys and btree depth up-to maxdepth. Each tree node is split by
# up-to maxsplit points. # up-to maxsplit points.
def AllStructs(keys, maxdepth, maxsplit): # -> i[] of Tree #
# If allowEmptyBuckets=y tree structures with empty buckets are also generated.
# By default, except for empty-tree case, only tree structures with non-empty
# buckets are generated, because ZODB BTree package misbehaves if it finds an
# empty bucket in a trees. ZODB.BTree._check also asserts if bucket is empty.
def AllStructs(keys, maxdepth, maxsplit, allowEmptyBuckets=False): # -> i[] of Tree
assert isinstance(maxdepth, int); assert maxdepth >= 0 assert isinstance(maxdepth, int); assert maxdepth >= 0
assert isinstance(maxsplit, int); assert maxsplit >= 0 assert isinstance(maxsplit, int); assert maxsplit >= 0
ks = set(keys) ks = set(keys)
...@@ -517,11 +522,16 @@ def AllStructs(keys, maxdepth, maxsplit): # -> i[] of Tree ...@@ -517,11 +522,16 @@ def AllStructs(keys, maxdepth, maxsplit): # -> i[] of Tree
klo = 0 klo = 0
khi = 0 khi = 0
for tree in _allStructs(klo, khi, keyv, maxdepth, maxsplit): # the only possible case for empty tree is T/B
if not allowEmptyBuckets:
yield Tree([], Bucket())
return
for tree in _allStructs(klo, khi, keyv, maxdepth, maxsplit, allowEmptyBuckets):
yield tree yield tree
def _allStructs(klo, khi, keyv, maxdepth, maxsplit): def _allStructs(klo, khi, keyv, maxdepth, maxsplit, allowEmptyBuckets):
assert klo <= khi assert klo <= khi
_assertIncv(keyv) _assertIncv(keyv)
if len(keyv) > 0: if len(keyv) > 0:
...@@ -539,8 +549,12 @@ def _allStructs(klo, khi, keyv, maxdepth, maxsplit): ...@@ -539,8 +549,12 @@ def _allStructs(klo, khi, keyv, maxdepth, maxsplit):
# emit Tree -> Buckets # emit Tree -> Buckets
children = [] children = []
for (xlo, xhi) in zip(ksplitv[:-1], ksplitv[1:]): # (klo, s1), (s1, s2), ..., (sN, khi) for (xlo, xhi) in zip(ksplitv[:-1], ksplitv[1:]): # (klo, s1), (s1, s2), ..., (sN, khi)
children.append(Bucket(*_keyvSliceBy(keyv, xlo, xhi))) bkeyv = _keyvSliceBy(keyv, xlo, xhi)
yield Tree(ksplitv[1:-1], *children) # (s1, s2, ..., sN) if len(bkeyv) == 0 and (not allowEmptyBuckets):
break
children.append(Bucket(*bkeyv))
else:
yield Tree(ksplitv[1:-1], *children) # (s1, s2, ..., sN)
# emit Tree -> Trees -> ... # emit Tree -> Trees -> ...
if maxdepth == 0: if maxdepth == 0:
...@@ -548,7 +562,7 @@ def _allStructs(klo, khi, keyv, maxdepth, maxsplit): ...@@ -548,7 +562,7 @@ def _allStructs(klo, khi, keyv, maxdepth, maxsplit):
ichildrenv = [] # of _allStructs for each child link ichildrenv = [] # of _allStructs for each child link
for (xlo, xhi) in zip(ksplitv[:-1], ksplitv[1:]): # (klo, s1), (s1, s2), ..., (sN, khi) for (xlo, xhi) in zip(ksplitv[:-1], ksplitv[1:]): # (klo, s1), (s1, s2), ..., (sN, khi)
ichildrenv.append( _allStructs( ichildrenv.append( _allStructs(
xlo, xhi, _keyvSliceBy(keyv, xlo, xhi), maxdepth - 1, maxsplit)) xlo, xhi, _keyvSliceBy(keyv, xlo, xhi), maxdepth - 1, maxsplit, allowEmptyBuckets))
for children in itertools.product(*ichildrenv): for children in itertools.product(*ichildrenv):
yield Tree(ksplitv[1:-1], *children) # (s1, s2, ..., sN) yield Tree(ksplitv[1:-1], *children) # (s1, s2, ..., sN)
......
...@@ -116,10 +116,14 @@ def test_topoEncoding(): ...@@ -116,10 +116,14 @@ def test_topoEncoding():
def test_allStructs(): def test_allStructs():
T = xbtree.Tree T = xbtree.Tree
B = xbtree.Bucket B = xbtree.Bucket
def X(keys, maxdepth, maxsplit): def X(keys, maxdepth, maxsplit, allowEmptyBuckets=True):
return list(xbtree.AllStructs(keys, maxdepth, maxsplit)) return list(xbtree.AllStructs(keys, maxdepth, maxsplit, allowEmptyBuckets))
def Y(keys, maxdepth, maxsplit):
return X(keys, maxsplit, maxsplit, allowEmptyBuckets=False)
assert X([], 0, 0) == [ T([], B()) ] assert X([], 0, 0) == [ T([], B()) ]
assert Y([], 0, 0) == [ T([], B()) ]
assert X([1], 0, 0) == [ T([], B(1)) ] assert X([1], 0, 0) == [ T([], B(1)) ]
assert X([1,3], 0, 0) == [ T([], B(1,3)) ] assert X([1,3], 0, 0) == [ T([], B(1,3)) ]
......
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