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

.

parent 7305c503
......@@ -495,7 +495,12 @@ def Restructure(ztree, newStructure):
# 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
# 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(maxsplit, int); assert maxsplit >= 0
ks = set(keys)
......@@ -517,11 +522,16 @@ def AllStructs(keys, maxdepth, maxsplit): # -> i[] of Tree
klo = 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
def _allStructs(klo, khi, keyv, maxdepth, maxsplit):
def _allStructs(klo, khi, keyv, maxdepth, maxsplit, allowEmptyBuckets):
assert klo <= khi
_assertIncv(keyv)
if len(keyv) > 0:
......@@ -539,7 +549,11 @@ def _allStructs(klo, khi, keyv, maxdepth, maxsplit):
# emit Tree -> Buckets
children = []
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)
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 -> ...
......@@ -548,7 +562,7 @@ def _allStructs(klo, khi, keyv, maxdepth, maxsplit):
ichildrenv = [] # of _allStructs for each child link
for (xlo, xhi) in zip(ksplitv[:-1], ksplitv[1:]): # (klo, s1), (s1, s2), ..., (sN, khi)
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):
yield Tree(ksplitv[1:-1], *children) # (s1, s2, ..., sN)
......
......@@ -116,10 +116,14 @@ def test_topoEncoding():
def test_allStructs():
T = xbtree.Tree
B = xbtree.Bucket
def X(keys, maxdepth, maxsplit):
return list(xbtree.AllStructs(keys, maxdepth, maxsplit))
def X(keys, maxdepth, maxsplit, allowEmptyBuckets=True):
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 Y([], 0, 0) == [ T([], B()) ]
assert X([1], 0, 0) == [ T([], B(1)) ]
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