scripts: Changed most tree renderers to be pseudo-standalone
I'm trying to avoid having classes with different implementations across scripts, as it makes updating things error-prone, but at same time copying all the tree renderers to all dbg scripts would be a bit much. Monkey-patching the TreeArt class in relevant scripts seems like a reasonable compromise.
This commit is contained in:
+136
-132
@@ -1516,151 +1516,155 @@ class TreeArt:
|
|||||||
|
|
||||||
return '%s ' % ''.join(trunk)
|
return '%s ' % ''.join(trunk)
|
||||||
|
|
||||||
# some more renderers
|
# some more renderers
|
||||||
|
|
||||||
# render a btree rbyd tree for debugging
|
# render a btree rbyd tree for debugging
|
||||||
@classmethod
|
@classmethod
|
||||||
def _frombtreertree(cls, btree, *,
|
def _treeartfrombtreertree(cls, btree, *,
|
||||||
depth=None,
|
depth=None,
|
||||||
inner=False,
|
inner=False,
|
||||||
**args):
|
**args):
|
||||||
# precompute rbyd trees so we know the max depth at each layer
|
# precompute rbyd trees so we know the max depth at each layer
|
||||||
# to nicely align trees
|
# to nicely align trees
|
||||||
rtrees = {}
|
rtrees = {}
|
||||||
rdepths = {}
|
rdepths = {}
|
||||||
for bid, rbyd, path in btree.traverse(path=True, depth=depth):
|
for bid, rbyd, path in btree.traverse(path=True, depth=depth):
|
||||||
if not rbyd:
|
if not rbyd:
|
||||||
continue
|
continue
|
||||||
|
|
||||||
rtree = cls.fromrbyd(rbyd, **args)
|
rtree = cls.fromrbyd(rbyd, **args)
|
||||||
rtrees[rbyd] = rtree
|
rtrees[rbyd] = rtree
|
||||||
rdepths[len(path)] = max(rdepths.get(len(path), 0), rtree.depth)
|
rdepths[len(path)] = max(rdepths.get(len(path), 0), rtree.depth)
|
||||||
|
|
||||||
# map rbyd branches into our btree space
|
# map rbyd branches into our btree space
|
||||||
tree = set()
|
tree = set()
|
||||||
for bid, rbyd, path in btree.traverse(path=True, depth=depth):
|
for bid, rbyd, path in btree.traverse(path=True, depth=depth):
|
||||||
if not rbyd:
|
if not rbyd:
|
||||||
continue
|
continue
|
||||||
|
|
||||||
# yes we can find new rbyds if disk is being mutated, just
|
# yes we can find new rbyds if disk is being mutated, just
|
||||||
# ignore these
|
# ignore these
|
||||||
if rbyd not in rtrees:
|
if rbyd not in rtrees:
|
||||||
continue
|
continue
|
||||||
|
|
||||||
rtree = rtrees[rbyd]
|
rtree = rtrees[rbyd]
|
||||||
rz = max((t.z+1 for t in rtree), default=0)
|
rz = max((t.z+1 for t in rtree), default=0)
|
||||||
d = sum(rdepths[d]+1 for d in range(len(path)))
|
d = sum(rdepths[d]+1 for d in range(len(path)))
|
||||||
|
|
||||||
# map into our btree space
|
# map into our btree space
|
||||||
for t in rtree:
|
for t in rtree:
|
||||||
# note we adjust our bid to be left-leaning, this allows
|
|
||||||
# a global order and makes tree rendering quite a bit easier
|
|
||||||
a_rid, a_tag = t.a
|
|
||||||
b_rid, b_tag = t.b
|
|
||||||
_, (_, a_w, _) = rbyd.lookupnext(a_rid)
|
|
||||||
_, (_, b_w, _) = rbyd.lookupnext(b_rid)
|
|
||||||
tree.add(cls.Branch(
|
|
||||||
(bid-(rbyd.weight-1)+a_rid-(a_w-1), len(path), a_tag),
|
|
||||||
(bid-(rbyd.weight-1)+b_rid-(b_w-1), len(path), b_tag),
|
|
||||||
d + rdepths[len(path)]-rz + t.z,
|
|
||||||
t.color))
|
|
||||||
|
|
||||||
# connect rbyd branches to rbyd roots
|
|
||||||
if path:
|
|
||||||
l_bid, l_rbyd, l_rid, l_name = path[-1]
|
|
||||||
l_branch = l_rbyd.lookup(l_rid, TAG_BRANCH, 0x3)
|
|
||||||
|
|
||||||
if rtree:
|
|
||||||
r_rid, r_tag = min(rtree, key=lambda t: t.z).a
|
|
||||||
_, (_, r_w, _) = rbyd.lookupnext(r_rid)
|
|
||||||
else:
|
|
||||||
r_rid, (r_tag, r_w, _) = rbyd.lookupnext(-1)
|
|
||||||
|
|
||||||
tree.add(cls.Branch(
|
|
||||||
(l_bid-(l_name.weight-1), len(path)-1, l_branch.tag),
|
|
||||||
(bid-(rbyd.weight-1)+r_rid-(r_w-1), len(path), r_tag),
|
|
||||||
d-1))
|
|
||||||
|
|
||||||
# remap branches to leaves if we aren't showing inner branches
|
|
||||||
if not inner:
|
|
||||||
# step through each btree layer backwards
|
|
||||||
b_depth = max((t.a[1]+1 for t in tree), default=0)
|
|
||||||
|
|
||||||
for d in reversed(range(b_depth-1)):
|
|
||||||
# find bid ranges at this level
|
|
||||||
bids = set()
|
|
||||||
for t in tree:
|
|
||||||
if t.b[1] == d:
|
|
||||||
bids.add(t.b[0])
|
|
||||||
bids = sorted(bids)
|
|
||||||
|
|
||||||
# find the best root for each bid range
|
|
||||||
roots = {}
|
|
||||||
for i in range(len(bids)):
|
|
||||||
for t in tree:
|
|
||||||
if (t.a[1] > d
|
|
||||||
and t.a[0] >= bids[i]
|
|
||||||
and (i == len(bids)-1 or t.a[0] < bids[i+1])
|
|
||||||
and (bids[i] not in roots
|
|
||||||
or t < roots[bids[i]])):
|
|
||||||
roots[bids[i]] = t
|
|
||||||
|
|
||||||
# remap branches to leaf-roots
|
|
||||||
tree = {t.map(
|
|
||||||
lambda x: x[1] == d and x[0] in roots,
|
|
||||||
lambda x: roots[x[0]].a)
|
|
||||||
for t in tree}
|
|
||||||
|
|
||||||
return cls(tree)
|
|
||||||
|
|
||||||
# render a btree btree tree for debugging
|
|
||||||
@classmethod
|
|
||||||
def _frombtreebtree(cls, btree, *,
|
|
||||||
depth=None,
|
|
||||||
inner=False,
|
|
||||||
**args):
|
|
||||||
# find all branches
|
|
||||||
tree = set()
|
|
||||||
root = None
|
|
||||||
branches = {}
|
|
||||||
for bid, name, path in btree.bids(
|
|
||||||
path=True,
|
|
||||||
depth=depth):
|
|
||||||
# create branch for each jump in path
|
|
||||||
#
|
|
||||||
# note we adjust our bid to be left-leaning, this allows
|
# note we adjust our bid to be left-leaning, this allows
|
||||||
# a global order and makes tree rendering quite a bit easier
|
# a global order and makes tree rendering quite a bit easier
|
||||||
a = root
|
a_rid, a_tag = t.a
|
||||||
for d, (bid_, rbyd_, rid_, name_) in enumerate(path):
|
b_rid, b_tag = t.b
|
||||||
# map into our btree space
|
_, (_, a_w, _) = rbyd.lookupnext(a_rid)
|
||||||
bid__ = bid_-(name_.weight-1)
|
_, (_, b_w, _) = rbyd.lookupnext(b_rid)
|
||||||
b = (bid__, d, name_.tag)
|
tree.add(cls.Branch(
|
||||||
|
(bid-(rbyd.weight-1)+a_rid-(a_w-1), len(path), a_tag),
|
||||||
|
(bid-(rbyd.weight-1)+b_rid-(b_w-1), len(path), b_tag),
|
||||||
|
d + rdepths[len(path)]-rz + t.z,
|
||||||
|
t.color))
|
||||||
|
|
||||||
# remap branches to leaves if we aren't showing inner
|
# connect rbyd branches to rbyd roots
|
||||||
# branches
|
if path:
|
||||||
if not inner:
|
l_bid, l_rbyd, l_rid, l_name = path[-1]
|
||||||
if b not in branches:
|
l_branch = l_rbyd.lookup(l_rid, TAG_BRANCH, 0x3)
|
||||||
bid_, rbyd_, rid_, name_ = path[-1]
|
|
||||||
bid__ = bid_-(name_.weight-1)
|
|
||||||
branches[b] = (bid__, len(path)-1, name_.tag)
|
|
||||||
b = branches[b]
|
|
||||||
|
|
||||||
# render the root path on first rid, this is arbitrary
|
if rtree:
|
||||||
if root is None:
|
r_rid, r_tag = min(rtree, key=lambda t: t.z).a
|
||||||
root, a = b, b
|
_, (_, r_w, _) = rbyd.lookupnext(r_rid)
|
||||||
|
else:
|
||||||
|
r_rid, (r_tag, r_w, _) = rbyd.lookupnext(-1)
|
||||||
|
|
||||||
tree.add(cls.Branch(a, b, d))
|
tree.add(cls.Branch(
|
||||||
a = b
|
(l_bid-(l_name.weight-1), len(path)-1, l_branch.tag),
|
||||||
|
(bid-(rbyd.weight-1)+r_rid-(r_w-1), len(path), r_tag),
|
||||||
|
d-1))
|
||||||
|
|
||||||
return cls(tree)
|
# remap branches to leaves if we aren't showing inner branches
|
||||||
|
if not inner:
|
||||||
|
# step through each btree layer backwards
|
||||||
|
b_depth = max((t.a[1]+1 for t in tree), default=0)
|
||||||
|
|
||||||
# render a btree tree for debugging
|
for d in reversed(range(b_depth-1)):
|
||||||
@classmethod
|
# find bid ranges at this level
|
||||||
def frombtree(cls, btree, **args):
|
bids = set()
|
||||||
if args.get('tree_btree'):
|
for t in tree:
|
||||||
return cls._frombtreebtree(btree, **args)
|
if t.b[1] == d:
|
||||||
else:
|
bids.add(t.b[0])
|
||||||
return cls._frombtreertree(btree, **args)
|
bids = sorted(bids)
|
||||||
|
|
||||||
|
# find the best root for each bid range
|
||||||
|
roots = {}
|
||||||
|
for i in range(len(bids)):
|
||||||
|
for t in tree:
|
||||||
|
if (t.a[1] > d
|
||||||
|
and t.a[0] >= bids[i]
|
||||||
|
and (i == len(bids)-1 or t.a[0] < bids[i+1])
|
||||||
|
and (bids[i] not in roots
|
||||||
|
or t < roots[bids[i]])):
|
||||||
|
roots[bids[i]] = t
|
||||||
|
|
||||||
|
# remap branches to leaf-roots
|
||||||
|
tree = {t.map(
|
||||||
|
lambda x: x[1] == d and x[0] in roots,
|
||||||
|
lambda x: roots[x[0]].a)
|
||||||
|
for t in tree}
|
||||||
|
|
||||||
|
return cls(tree)
|
||||||
|
|
||||||
|
# render a btree btree tree for debugging
|
||||||
|
@classmethod
|
||||||
|
def _treeartfrombtreebtree(cls, btree, *,
|
||||||
|
depth=None,
|
||||||
|
inner=False,
|
||||||
|
**args):
|
||||||
|
# find all branches
|
||||||
|
tree = set()
|
||||||
|
root = None
|
||||||
|
branches = {}
|
||||||
|
for bid, name, path in btree.bids(
|
||||||
|
path=True,
|
||||||
|
depth=depth):
|
||||||
|
# create branch for each jump in path
|
||||||
|
#
|
||||||
|
# note we adjust our bid to be left-leaning, this allows
|
||||||
|
# a global order and makes tree rendering quite a bit easier
|
||||||
|
a = root
|
||||||
|
for d, (bid_, rbyd_, rid_, name_) in enumerate(path):
|
||||||
|
# map into our btree space
|
||||||
|
bid__ = bid_-(name_.weight-1)
|
||||||
|
b = (bid__, d, name_.tag)
|
||||||
|
|
||||||
|
# remap branches to leaves if we aren't showing inner
|
||||||
|
# branches
|
||||||
|
if not inner:
|
||||||
|
if b not in branches:
|
||||||
|
bid_, rbyd_, rid_, name_ = path[-1]
|
||||||
|
bid__ = bid_-(name_.weight-1)
|
||||||
|
branches[b] = (bid__, len(path)-1, name_.tag)
|
||||||
|
b = branches[b]
|
||||||
|
|
||||||
|
# render the root path on first rid, this is arbitrary
|
||||||
|
if root is None:
|
||||||
|
root, a = b, b
|
||||||
|
|
||||||
|
tree.add(cls.Branch(a, b, d))
|
||||||
|
a = b
|
||||||
|
|
||||||
|
return cls(tree)
|
||||||
|
|
||||||
|
# render a btree tree for debugging
|
||||||
|
@classmethod
|
||||||
|
def treeartfrombtree(cls, btree, **args):
|
||||||
|
if args.get('tree_btree'):
|
||||||
|
return cls._frombtreebtree(btree, **args)
|
||||||
|
else:
|
||||||
|
return cls._frombtreertree(btree, **args)
|
||||||
|
|
||||||
|
TreeArt._frombtreertree = _treeartfrombtreertree
|
||||||
|
TreeArt._frombtreebtree = _treeartfrombtreebtree
|
||||||
|
TreeArt.frombtree = treeartfrombtree
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
+158
-152
@@ -3750,174 +3750,180 @@ class TreeArt:
|
|||||||
|
|
||||||
# some more renderers
|
# some more renderers
|
||||||
|
|
||||||
# render a btree rbyd tree for debugging
|
# render a btree rbyd tree for debugging
|
||||||
@classmethod
|
@classmethod
|
||||||
def _frombtreertree(cls, btree, *,
|
def _treeartfrombtreertree(cls, btree, *,
|
||||||
depth=None,
|
depth=None,
|
||||||
inner=False,
|
inner=False,
|
||||||
**args):
|
**args):
|
||||||
# precompute rbyd trees so we know the max depth at each layer
|
# precompute rbyd trees so we know the max depth at each layer
|
||||||
# to nicely align trees
|
# to nicely align trees
|
||||||
rtrees = {}
|
rtrees = {}
|
||||||
rdepths = {}
|
rdepths = {}
|
||||||
for bid, rbyd, path in btree.traverse(path=True, depth=depth):
|
for bid, rbyd, path in btree.traverse(path=True, depth=depth):
|
||||||
if not rbyd:
|
if not rbyd:
|
||||||
continue
|
continue
|
||||||
|
|
||||||
rtree = cls.fromrbyd(rbyd, **args)
|
rtree = cls.fromrbyd(rbyd, **args)
|
||||||
rtrees[rbyd] = rtree
|
rtrees[rbyd] = rtree
|
||||||
rdepths[len(path)] = max(rdepths.get(len(path), 0), rtree.depth)
|
rdepths[len(path)] = max(rdepths.get(len(path), 0), rtree.depth)
|
||||||
|
|
||||||
# map rbyd branches into our btree space
|
# map rbyd branches into our btree space
|
||||||
tree = set()
|
tree = set()
|
||||||
for bid, rbyd, path in btree.traverse(path=True, depth=depth):
|
for bid, rbyd, path in btree.traverse(path=True, depth=depth):
|
||||||
if not rbyd:
|
if not rbyd:
|
||||||
continue
|
continue
|
||||||
|
|
||||||
# yes we can find new rbyds if disk is being mutated, just
|
# yes we can find new rbyds if disk is being mutated, just
|
||||||
# ignore these
|
# ignore these
|
||||||
if rbyd not in rtrees:
|
if rbyd not in rtrees:
|
||||||
continue
|
continue
|
||||||
|
|
||||||
rtree = rtrees[rbyd]
|
rtree = rtrees[rbyd]
|
||||||
rz = max((t.z+1 for t in rtree), default=0)
|
rz = max((t.z+1 for t in rtree), default=0)
|
||||||
d = sum(rdepths[d]+1 for d in range(len(path)))
|
d = sum(rdepths[d]+1 for d in range(len(path)))
|
||||||
|
|
||||||
# map into our btree space
|
# map into our btree space
|
||||||
for t in rtree:
|
for t in rtree:
|
||||||
# note we adjust our bid to be left-leaning, this allows
|
|
||||||
# a global order and makes tree rendering quite a bit easier
|
|
||||||
a_rid, a_tag = t.a
|
|
||||||
b_rid, b_tag = t.b
|
|
||||||
_, (_, a_w, _) = rbyd.lookupnext(a_rid)
|
|
||||||
_, (_, b_w, _) = rbyd.lookupnext(b_rid)
|
|
||||||
tree.add(cls.Branch(
|
|
||||||
(bid-(rbyd.weight-1)+a_rid-(a_w-1), len(path), a_tag),
|
|
||||||
(bid-(rbyd.weight-1)+b_rid-(b_w-1), len(path), b_tag),
|
|
||||||
d + rdepths[len(path)]-rz + t.z,
|
|
||||||
t.color))
|
|
||||||
|
|
||||||
# connect rbyd branches to rbyd roots
|
|
||||||
if path:
|
|
||||||
l_bid, l_rbyd, l_rid, l_name = path[-1]
|
|
||||||
l_branch = l_rbyd.lookup(l_rid, TAG_BRANCH, 0x3)
|
|
||||||
|
|
||||||
if rtree:
|
|
||||||
r_rid, r_tag = min(rtree, key=lambda t: t.z).a
|
|
||||||
_, (_, r_w, _) = rbyd.lookupnext(r_rid)
|
|
||||||
else:
|
|
||||||
r_rid, (r_tag, r_w, _) = rbyd.lookupnext(-1)
|
|
||||||
|
|
||||||
tree.add(cls.Branch(
|
|
||||||
(l_bid-(l_name.weight-1), len(path)-1, l_branch.tag),
|
|
||||||
(bid-(rbyd.weight-1)+r_rid-(r_w-1), len(path), r_tag),
|
|
||||||
d-1))
|
|
||||||
|
|
||||||
# remap branches to leaves if we aren't showing inner branches
|
|
||||||
if not inner:
|
|
||||||
# step through each btree layer backwards
|
|
||||||
b_depth = max((t.a[1]+1 for t in tree), default=0)
|
|
||||||
|
|
||||||
for d in reversed(range(b_depth-1)):
|
|
||||||
# find bid ranges at this level
|
|
||||||
bids = set()
|
|
||||||
for t in tree:
|
|
||||||
if t.b[1] == d:
|
|
||||||
bids.add(t.b[0])
|
|
||||||
bids = sorted(bids)
|
|
||||||
|
|
||||||
# find the best root for each bid range
|
|
||||||
roots = {}
|
|
||||||
for i in range(len(bids)):
|
|
||||||
for t in tree:
|
|
||||||
if (t.a[1] > d
|
|
||||||
and t.a[0] >= bids[i]
|
|
||||||
and (i == len(bids)-1 or t.a[0] < bids[i+1])
|
|
||||||
and (bids[i] not in roots
|
|
||||||
or t < roots[bids[i]])):
|
|
||||||
roots[bids[i]] = t
|
|
||||||
|
|
||||||
# remap branches to leaf-roots
|
|
||||||
tree = {t.map(
|
|
||||||
lambda x: x[1] == d and x[0] in roots,
|
|
||||||
lambda x: roots[x[0]].a)
|
|
||||||
for t in tree}
|
|
||||||
|
|
||||||
return cls(tree)
|
|
||||||
|
|
||||||
# render a btree btree tree for debugging
|
|
||||||
@classmethod
|
|
||||||
def _frombtreebtree(cls, btree, *,
|
|
||||||
depth=None,
|
|
||||||
inner=False,
|
|
||||||
**args):
|
|
||||||
# find all branches
|
|
||||||
tree = set()
|
|
||||||
root = None
|
|
||||||
branches = {}
|
|
||||||
for bid, name, path in btree.bids(
|
|
||||||
path=True,
|
|
||||||
depth=depth):
|
|
||||||
# create branch for each jump in path
|
|
||||||
#
|
|
||||||
# note we adjust our bid to be left-leaning, this allows
|
# note we adjust our bid to be left-leaning, this allows
|
||||||
# a global order and makes tree rendering quite a bit easier
|
# a global order and makes tree rendering quite a bit easier
|
||||||
a = root
|
a_rid, a_tag = t.a
|
||||||
for d, (bid_, rbyd_, rid_, name_) in enumerate(path):
|
b_rid, b_tag = t.b
|
||||||
# map into our btree space
|
_, (_, a_w, _) = rbyd.lookupnext(a_rid)
|
||||||
bid__ = bid_-(name_.weight-1)
|
_, (_, b_w, _) = rbyd.lookupnext(b_rid)
|
||||||
b = (bid__, d, name_.tag)
|
tree.add(cls.Branch(
|
||||||
|
(bid-(rbyd.weight-1)+a_rid-(a_w-1), len(path), a_tag),
|
||||||
|
(bid-(rbyd.weight-1)+b_rid-(b_w-1), len(path), b_tag),
|
||||||
|
d + rdepths[len(path)]-rz + t.z,
|
||||||
|
t.color))
|
||||||
|
|
||||||
# remap branches to leaves if we aren't showing inner
|
# connect rbyd branches to rbyd roots
|
||||||
# branches
|
if path:
|
||||||
if not inner:
|
l_bid, l_rbyd, l_rid, l_name = path[-1]
|
||||||
if b not in branches:
|
l_branch = l_rbyd.lookup(l_rid, TAG_BRANCH, 0x3)
|
||||||
bid_, rbyd_, rid_, name_ = path[-1]
|
|
||||||
bid__ = bid_-(name_.weight-1)
|
|
||||||
branches[b] = (bid__, len(path)-1, name_.tag)
|
|
||||||
b = branches[b]
|
|
||||||
|
|
||||||
# render the root path on first rid, this is arbitrary
|
if rtree:
|
||||||
if root is None:
|
r_rid, r_tag = min(rtree, key=lambda t: t.z).a
|
||||||
root, a = b, b
|
_, (_, r_w, _) = rbyd.lookupnext(r_rid)
|
||||||
|
else:
|
||||||
|
r_rid, (r_tag, r_w, _) = rbyd.lookupnext(-1)
|
||||||
|
|
||||||
tree.add(cls.Branch(a, b, d))
|
tree.add(cls.Branch(
|
||||||
a = b
|
(l_bid-(l_name.weight-1), len(path)-1, l_branch.tag),
|
||||||
|
(bid-(rbyd.weight-1)+r_rid-(r_w-1), len(path), r_tag),
|
||||||
|
d-1))
|
||||||
|
|
||||||
return cls(tree)
|
# remap branches to leaves if we aren't showing inner branches
|
||||||
|
if not inner:
|
||||||
|
# step through each btree layer backwards
|
||||||
|
b_depth = max((t.a[1]+1 for t in tree), default=0)
|
||||||
|
|
||||||
# render a btree tree for debugging
|
for d in reversed(range(b_depth-1)):
|
||||||
@classmethod
|
# find bid ranges at this level
|
||||||
def frombtree(cls, btree, **args):
|
bids = set()
|
||||||
if args.get('tree_btree'):
|
for t in tree:
|
||||||
return cls._frombtreebtree(btree, **args)
|
if t.b[1] == d:
|
||||||
else:
|
bids.add(t.b[0])
|
||||||
return cls._frombtreertree(btree, **args)
|
bids = sorted(bids)
|
||||||
|
|
||||||
# render a file tree for debugging
|
# find the best root for each bid range
|
||||||
@classmethod
|
roots = {}
|
||||||
def fromfile(cls, file, **args):
|
for i in range(len(bids)):
|
||||||
tree = cls.frombtree(file.bshrub, **args)
|
for t in tree:
|
||||||
t_depth = tree.depth
|
if (t.a[1] > d
|
||||||
|
and t.a[0] >= bids[i]
|
||||||
|
and (i == len(bids)-1 or t.a[0] < bids[i+1])
|
||||||
|
and (bids[i] not in roots
|
||||||
|
or t < roots[bids[i]])):
|
||||||
|
roots[bids[i]] = t
|
||||||
|
|
||||||
# connect bptr tags to bptrs
|
# remap branches to leaf-roots
|
||||||
tree = set(tree)
|
tree = {t.map(
|
||||||
bptrs = {}
|
lambda x: x[1] == d and x[0] in roots,
|
||||||
for pos, data, path in file.datas(
|
lambda x: roots[x[0]].a)
|
||||||
path=True,
|
for t in tree}
|
||||||
depth=args.get('depth')):
|
|
||||||
if isinstance(data, Bptr):
|
|
||||||
a = (pos, len(path)-1, data.tag)
|
|
||||||
b = (pos, len(path), data.tag)
|
|
||||||
bptrs[a] = b
|
|
||||||
tree.add(cls.Branch(a, b, t_depth))
|
|
||||||
|
|
||||||
# if we're not showing inner branches, nudge bptr tags to
|
return cls(tree)
|
||||||
# their bptrs
|
|
||||||
if not args.get('inner'):
|
|
||||||
tree = {t.map(lambda x: bptrs.get(x, x)) for t in tree}
|
|
||||||
|
|
||||||
return cls(tree)
|
# render a btree btree tree for debugging
|
||||||
|
@classmethod
|
||||||
|
def _treeartfrombtreebtree(cls, btree, *,
|
||||||
|
depth=None,
|
||||||
|
inner=False,
|
||||||
|
**args):
|
||||||
|
# find all branches
|
||||||
|
tree = set()
|
||||||
|
root = None
|
||||||
|
branches = {}
|
||||||
|
for bid, name, path in btree.bids(
|
||||||
|
path=True,
|
||||||
|
depth=depth):
|
||||||
|
# create branch for each jump in path
|
||||||
|
#
|
||||||
|
# note we adjust our bid to be left-leaning, this allows
|
||||||
|
# a global order and makes tree rendering quite a bit easier
|
||||||
|
a = root
|
||||||
|
for d, (bid_, rbyd_, rid_, name_) in enumerate(path):
|
||||||
|
# map into our btree space
|
||||||
|
bid__ = bid_-(name_.weight-1)
|
||||||
|
b = (bid__, d, name_.tag)
|
||||||
|
|
||||||
|
# remap branches to leaves if we aren't showing inner
|
||||||
|
# branches
|
||||||
|
if not inner:
|
||||||
|
if b not in branches:
|
||||||
|
bid_, rbyd_, rid_, name_ = path[-1]
|
||||||
|
bid__ = bid_-(name_.weight-1)
|
||||||
|
branches[b] = (bid__, len(path)-1, name_.tag)
|
||||||
|
b = branches[b]
|
||||||
|
|
||||||
|
# render the root path on first rid, this is arbitrary
|
||||||
|
if root is None:
|
||||||
|
root, a = b, b
|
||||||
|
|
||||||
|
tree.add(cls.Branch(a, b, d))
|
||||||
|
a = b
|
||||||
|
|
||||||
|
return cls(tree)
|
||||||
|
|
||||||
|
# render a btree tree for debugging
|
||||||
|
@classmethod
|
||||||
|
def treeartfrombtree(cls, btree, **args):
|
||||||
|
if args.get('tree_btree'):
|
||||||
|
return cls._frombtreebtree(btree, **args)
|
||||||
|
else:
|
||||||
|
return cls._frombtreertree(btree, **args)
|
||||||
|
|
||||||
|
TreeArt._frombtreertree = _treeartfrombtreertree
|
||||||
|
TreeArt._frombtreebtree = _treeartfrombtreebtree
|
||||||
|
TreeArt.frombtree = treeartfrombtree
|
||||||
|
|
||||||
|
# render a file tree for debugging
|
||||||
|
@classmethod
|
||||||
|
def treeartfromfile(cls, file, **args):
|
||||||
|
tree = cls.frombtree(file.bshrub, **args)
|
||||||
|
t_depth = tree.depth
|
||||||
|
|
||||||
|
# connect bptr tags to bptrs
|
||||||
|
tree = set(tree)
|
||||||
|
bptrs = {}
|
||||||
|
for pos, data, path in file.datas(
|
||||||
|
path=True,
|
||||||
|
depth=args.get('depth')):
|
||||||
|
if isinstance(data, Bptr):
|
||||||
|
a = (pos, len(path)-1, data.tag)
|
||||||
|
b = (pos, len(path), data.tag)
|
||||||
|
bptrs[a] = b
|
||||||
|
tree.add(cls.Branch(a, b, t_depth))
|
||||||
|
|
||||||
|
# if we're not showing inner branches, nudge bptr tags to
|
||||||
|
# their bptrs
|
||||||
|
if not args.get('inner'):
|
||||||
|
tree = {t.map(lambda x: bptrs.get(x, x)) for t in tree}
|
||||||
|
|
||||||
|
return cls(tree)
|
||||||
|
|
||||||
|
TreeArt.fromfile = treeartfromfile
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
+314
-306
@@ -2433,342 +2433,350 @@ class TreeArt:
|
|||||||
|
|
||||||
return '%s ' % ''.join(trunk)
|
return '%s ' % ''.join(trunk)
|
||||||
|
|
||||||
# some more renderers
|
# some more renderers
|
||||||
|
|
||||||
# render a btree rbyd tree for debugging
|
# render a btree rbyd tree for debugging
|
||||||
@classmethod
|
@classmethod
|
||||||
def _frombtreertree(cls, btree, *,
|
def _treeartfrombtreertree(cls, btree, *,
|
||||||
depth=None,
|
depth=None,
|
||||||
inner=False,
|
inner=False,
|
||||||
**args):
|
**args):
|
||||||
# precompute rbyd trees so we know the max depth at each layer
|
# precompute rbyd trees so we know the max depth at each layer
|
||||||
# to nicely align trees
|
# to nicely align trees
|
||||||
rtrees = {}
|
rtrees = {}
|
||||||
rdepths = {}
|
rdepths = {}
|
||||||
for bid, rbyd, path in btree.traverse(path=True, depth=depth):
|
for bid, rbyd, path in btree.traverse(path=True, depth=depth):
|
||||||
if not rbyd:
|
if not rbyd:
|
||||||
continue
|
continue
|
||||||
|
|
||||||
rtree = cls.fromrbyd(rbyd, **args)
|
rtree = cls.fromrbyd(rbyd, **args)
|
||||||
rtrees[rbyd] = rtree
|
rtrees[rbyd] = rtree
|
||||||
rdepths[len(path)] = max(rdepths.get(len(path), 0), rtree.depth)
|
rdepths[len(path)] = max(rdepths.get(len(path), 0), rtree.depth)
|
||||||
|
|
||||||
# map rbyd branches into our btree space
|
# map rbyd branches into our btree space
|
||||||
tree = set()
|
tree = set()
|
||||||
for bid, rbyd, path in btree.traverse(path=True, depth=depth):
|
for bid, rbyd, path in btree.traverse(path=True, depth=depth):
|
||||||
if not rbyd:
|
if not rbyd:
|
||||||
continue
|
continue
|
||||||
|
|
||||||
# yes we can find new rbyds if disk is being mutated, just
|
# yes we can find new rbyds if disk is being mutated, just
|
||||||
# ignore these
|
# ignore these
|
||||||
if rbyd not in rtrees:
|
if rbyd not in rtrees:
|
||||||
continue
|
continue
|
||||||
|
|
||||||
rtree = rtrees[rbyd]
|
rtree = rtrees[rbyd]
|
||||||
rz = max((t.z+1 for t in rtree), default=0)
|
rz = max((t.z+1 for t in rtree), default=0)
|
||||||
d = sum(rdepths[d]+1 for d in range(len(path)))
|
d = sum(rdepths[d]+1 for d in range(len(path)))
|
||||||
|
|
||||||
# map into our btree space
|
# map into our btree space
|
||||||
for t in rtree:
|
for t in rtree:
|
||||||
# note we adjust our bid to be left-leaning, this allows
|
|
||||||
# a global order and makes tree rendering quite a bit easier
|
|
||||||
a_rid, a_tag = t.a
|
|
||||||
b_rid, b_tag = t.b
|
|
||||||
_, (_, a_w, _) = rbyd.lookupnext(a_rid)
|
|
||||||
_, (_, b_w, _) = rbyd.lookupnext(b_rid)
|
|
||||||
tree.add(cls.Branch(
|
|
||||||
(bid-(rbyd.weight-1)+a_rid-(a_w-1), len(path), a_tag),
|
|
||||||
(bid-(rbyd.weight-1)+b_rid-(b_w-1), len(path), b_tag),
|
|
||||||
d + rdepths[len(path)]-rz + t.z,
|
|
||||||
t.color))
|
|
||||||
|
|
||||||
# connect rbyd branches to rbyd roots
|
|
||||||
if path:
|
|
||||||
l_bid, l_rbyd, l_rid, l_name = path[-1]
|
|
||||||
l_branch = l_rbyd.lookup(l_rid, TAG_BRANCH, 0x3)
|
|
||||||
|
|
||||||
if rtree:
|
|
||||||
r_rid, r_tag = min(rtree, key=lambda t: t.z).a
|
|
||||||
_, (_, r_w, _) = rbyd.lookupnext(r_rid)
|
|
||||||
else:
|
|
||||||
r_rid, (r_tag, r_w, _) = rbyd.lookupnext(-1)
|
|
||||||
|
|
||||||
tree.add(cls.Branch(
|
|
||||||
(l_bid-(l_name.weight-1), len(path)-1, l_branch.tag),
|
|
||||||
(bid-(rbyd.weight-1)+r_rid-(r_w-1), len(path), r_tag),
|
|
||||||
d-1))
|
|
||||||
|
|
||||||
# remap branches to leaves if we aren't showing inner branches
|
|
||||||
if not inner:
|
|
||||||
# step through each btree layer backwards
|
|
||||||
b_depth = max((t.a[1]+1 for t in tree), default=0)
|
|
||||||
|
|
||||||
for d in reversed(range(b_depth-1)):
|
|
||||||
# find bid ranges at this level
|
|
||||||
bids = set()
|
|
||||||
for t in tree:
|
|
||||||
if t.b[1] == d:
|
|
||||||
bids.add(t.b[0])
|
|
||||||
bids = sorted(bids)
|
|
||||||
|
|
||||||
# find the best root for each bid range
|
|
||||||
roots = {}
|
|
||||||
for i in range(len(bids)):
|
|
||||||
for t in tree:
|
|
||||||
if (t.a[1] > d
|
|
||||||
and t.a[0] >= bids[i]
|
|
||||||
and (i == len(bids)-1 or t.a[0] < bids[i+1])
|
|
||||||
and (bids[i] not in roots
|
|
||||||
or t < roots[bids[i]])):
|
|
||||||
roots[bids[i]] = t
|
|
||||||
|
|
||||||
# remap branches to leaf-roots
|
|
||||||
tree = {t.map(
|
|
||||||
lambda x: x[1] == d and x[0] in roots,
|
|
||||||
lambda x: roots[x[0]].a)
|
|
||||||
for t in tree}
|
|
||||||
|
|
||||||
return cls(tree)
|
|
||||||
|
|
||||||
# render a btree btree tree for debugging
|
|
||||||
@classmethod
|
|
||||||
def _frombtreebtree(cls, btree, *,
|
|
||||||
depth=None,
|
|
||||||
inner=False,
|
|
||||||
**args):
|
|
||||||
# find all branches
|
|
||||||
tree = set()
|
|
||||||
root = None
|
|
||||||
branches = {}
|
|
||||||
for bid, name, path in btree.bids(
|
|
||||||
path=True,
|
|
||||||
depth=depth):
|
|
||||||
# create branch for each jump in path
|
|
||||||
#
|
|
||||||
# note we adjust our bid to be left-leaning, this allows
|
# note we adjust our bid to be left-leaning, this allows
|
||||||
# a global order and makes tree rendering quite a bit easier
|
# a global order and makes tree rendering quite a bit easier
|
||||||
a = root
|
a_rid, a_tag = t.a
|
||||||
for d, (bid_, rbyd_, rid_, name_) in enumerate(path):
|
b_rid, b_tag = t.b
|
||||||
# map into our btree space
|
_, (_, a_w, _) = rbyd.lookupnext(a_rid)
|
||||||
bid__ = bid_-(name_.weight-1)
|
_, (_, b_w, _) = rbyd.lookupnext(b_rid)
|
||||||
b = (bid__, d, name_.tag)
|
tree.add(cls.Branch(
|
||||||
|
(bid-(rbyd.weight-1)+a_rid-(a_w-1), len(path), a_tag),
|
||||||
|
(bid-(rbyd.weight-1)+b_rid-(b_w-1), len(path), b_tag),
|
||||||
|
d + rdepths[len(path)]-rz + t.z,
|
||||||
|
t.color))
|
||||||
|
|
||||||
# remap branches to leaves if we aren't showing inner
|
# connect rbyd branches to rbyd roots
|
||||||
# branches
|
if path:
|
||||||
if not inner:
|
l_bid, l_rbyd, l_rid, l_name = path[-1]
|
||||||
if b not in branches:
|
l_branch = l_rbyd.lookup(l_rid, TAG_BRANCH, 0x3)
|
||||||
bid_, rbyd_, rid_, name_ = path[-1]
|
|
||||||
bid__ = bid_-(name_.weight-1)
|
|
||||||
branches[b] = (bid__, len(path)-1, name_.tag)
|
|
||||||
b = branches[b]
|
|
||||||
|
|
||||||
# render the root path on first rid, this is arbitrary
|
if rtree:
|
||||||
if root is None:
|
r_rid, r_tag = min(rtree, key=lambda t: t.z).a
|
||||||
root, a = b, b
|
_, (_, r_w, _) = rbyd.lookupnext(r_rid)
|
||||||
|
else:
|
||||||
|
r_rid, (r_tag, r_w, _) = rbyd.lookupnext(-1)
|
||||||
|
|
||||||
tree.add(cls.Branch(a, b, d))
|
tree.add(cls.Branch(
|
||||||
a = b
|
(l_bid-(l_name.weight-1), len(path)-1, l_branch.tag),
|
||||||
|
(bid-(rbyd.weight-1)+r_rid-(r_w-1), len(path), r_tag),
|
||||||
|
d-1))
|
||||||
|
|
||||||
return cls(tree)
|
# remap branches to leaves if we aren't showing inner branches
|
||||||
|
if not inner:
|
||||||
|
# step through each btree layer backwards
|
||||||
|
b_depth = max((t.a[1]+1 for t in tree), default=0)
|
||||||
|
|
||||||
# render a btree tree for debugging
|
for d in reversed(range(b_depth-1)):
|
||||||
@classmethod
|
# find bid ranges at this level
|
||||||
def frombtree(cls, btree, **args):
|
bids = set()
|
||||||
if args.get('tree_btree'):
|
for t in tree:
|
||||||
return cls._frombtreebtree(btree, **args)
|
if t.b[1] == d:
|
||||||
|
bids.add(t.b[0])
|
||||||
|
bids = sorted(bids)
|
||||||
|
|
||||||
|
# find the best root for each bid range
|
||||||
|
roots = {}
|
||||||
|
for i in range(len(bids)):
|
||||||
|
for t in tree:
|
||||||
|
if (t.a[1] > d
|
||||||
|
and t.a[0] >= bids[i]
|
||||||
|
and (i == len(bids)-1 or t.a[0] < bids[i+1])
|
||||||
|
and (bids[i] not in roots
|
||||||
|
or t < roots[bids[i]])):
|
||||||
|
roots[bids[i]] = t
|
||||||
|
|
||||||
|
# remap branches to leaf-roots
|
||||||
|
tree = {t.map(
|
||||||
|
lambda x: x[1] == d and x[0] in roots,
|
||||||
|
lambda x: roots[x[0]].a)
|
||||||
|
for t in tree}
|
||||||
|
|
||||||
|
return cls(tree)
|
||||||
|
|
||||||
|
# render a btree btree tree for debugging
|
||||||
|
@classmethod
|
||||||
|
def _treeartfrombtreebtree(cls, btree, *,
|
||||||
|
depth=None,
|
||||||
|
inner=False,
|
||||||
|
**args):
|
||||||
|
# find all branches
|
||||||
|
tree = set()
|
||||||
|
root = None
|
||||||
|
branches = {}
|
||||||
|
for bid, name, path in btree.bids(
|
||||||
|
path=True,
|
||||||
|
depth=depth):
|
||||||
|
# create branch for each jump in path
|
||||||
|
#
|
||||||
|
# note we adjust our bid to be left-leaning, this allows
|
||||||
|
# a global order and makes tree rendering quite a bit easier
|
||||||
|
a = root
|
||||||
|
for d, (bid_, rbyd_, rid_, name_) in enumerate(path):
|
||||||
|
# map into our btree space
|
||||||
|
bid__ = bid_-(name_.weight-1)
|
||||||
|
b = (bid__, d, name_.tag)
|
||||||
|
|
||||||
|
# remap branches to leaves if we aren't showing inner
|
||||||
|
# branches
|
||||||
|
if not inner:
|
||||||
|
if b not in branches:
|
||||||
|
bid_, rbyd_, rid_, name_ = path[-1]
|
||||||
|
bid__ = bid_-(name_.weight-1)
|
||||||
|
branches[b] = (bid__, len(path)-1, name_.tag)
|
||||||
|
b = branches[b]
|
||||||
|
|
||||||
|
# render the root path on first rid, this is arbitrary
|
||||||
|
if root is None:
|
||||||
|
root, a = b, b
|
||||||
|
|
||||||
|
tree.add(cls.Branch(a, b, d))
|
||||||
|
a = b
|
||||||
|
|
||||||
|
return cls(tree)
|
||||||
|
|
||||||
|
# render a btree tree for debugging
|
||||||
|
@classmethod
|
||||||
|
def treeartfrombtree(cls, btree, **args):
|
||||||
|
if args.get('tree_btree'):
|
||||||
|
return cls._frombtreebtree(btree, **args)
|
||||||
|
else:
|
||||||
|
return cls._frombtreertree(btree, **args)
|
||||||
|
|
||||||
|
TreeArt._frombtreertree = _treeartfrombtreertree
|
||||||
|
TreeArt._frombtreebtree = _treeartfrombtreebtree
|
||||||
|
TreeArt.frombtree = treeartfrombtree
|
||||||
|
|
||||||
|
# render an mtree tree for debugging
|
||||||
|
@classmethod
|
||||||
|
def _treeartfrommtreertree(cls, mtree, *,
|
||||||
|
depth=None,
|
||||||
|
inner=False,
|
||||||
|
**args):
|
||||||
|
# precompute rbyd trees so we know the max depth at each layer
|
||||||
|
# to nicely align trees
|
||||||
|
rtrees = {}
|
||||||
|
rdepths = {}
|
||||||
|
for mdir, path in mtree.traverse(path=True, depth=depth):
|
||||||
|
if isinstance(mdir, Mdir):
|
||||||
|
if not mdir:
|
||||||
|
continue
|
||||||
|
rbyd = mdir.rbyd
|
||||||
else:
|
else:
|
||||||
return cls._frombtreertree(btree, **args)
|
bid, rbyd = mdir
|
||||||
|
if not rbyd:
|
||||||
# render an mtree tree for debugging
|
|
||||||
@classmethod
|
|
||||||
def _frommtreertree(cls, mtree, *,
|
|
||||||
depth=None,
|
|
||||||
inner=False,
|
|
||||||
**args):
|
|
||||||
# precompute rbyd trees so we know the max depth at each layer
|
|
||||||
# to nicely align trees
|
|
||||||
rtrees = {}
|
|
||||||
rdepths = {}
|
|
||||||
for mdir, path in mtree.traverse(path=True, depth=depth):
|
|
||||||
if isinstance(mdir, Mdir):
|
|
||||||
if not mdir:
|
|
||||||
continue
|
|
||||||
rbyd = mdir.rbyd
|
|
||||||
else:
|
|
||||||
bid, rbyd = mdir
|
|
||||||
if not rbyd:
|
|
||||||
continue
|
|
||||||
|
|
||||||
rtree = cls.fromrbyd(rbyd, **args)
|
|
||||||
rtrees[rbyd] = rtree
|
|
||||||
rdepths[len(path)] = max(rdepths.get(len(path), 0), rtree.depth)
|
|
||||||
|
|
||||||
# map rbyd branches into our mtree space
|
|
||||||
tree = set()
|
|
||||||
branches = {}
|
|
||||||
for mdir, path in mtree.traverse(path=True, depth=depth):
|
|
||||||
if isinstance(mdir, Mdir):
|
|
||||||
if not mdir:
|
|
||||||
continue
|
|
||||||
rbyd = mdir.rbyd
|
|
||||||
else:
|
|
||||||
bid, rbyd = mdir
|
|
||||||
if not rbyd:
|
|
||||||
continue
|
|
||||||
|
|
||||||
# yes we can find new rbyds if disk is being mutated, just
|
|
||||||
# ignore these
|
|
||||||
if rbyd not in rtrees:
|
|
||||||
continue
|
continue
|
||||||
|
|
||||||
rtree = rtrees[rbyd]
|
rtree = cls.fromrbyd(rbyd, **args)
|
||||||
rz = max((t.z+1 for t in rtree), default=0)
|
rtrees[rbyd] = rtree
|
||||||
d = sum(rdepths[d]+1 for d, p in enumerate(path))
|
rdepths[len(path)] = max(rdepths.get(len(path), 0), rtree.depth)
|
||||||
|
|
||||||
# map into our mtree space
|
# map rbyd branches into our mtree space
|
||||||
for t in rtree:
|
tree = set()
|
||||||
# note we adjust our mid/bid to be left-leaning, this allows
|
branches = {}
|
||||||
# a global order and makes tree rendering quite a bit easier
|
for mdir, path in mtree.traverse(path=True, depth=depth):
|
||||||
#
|
if isinstance(mdir, Mdir):
|
||||||
# we also need to give btree nodes mrid=-1 so they come
|
if not mdir:
|
||||||
# before and mrid=-1 mdir attrs
|
continue
|
||||||
a_rid, a_tag = t.a
|
rbyd = mdir.rbyd
|
||||||
b_rid, b_tag = t.b
|
else:
|
||||||
_, (_, a_w, _) = rbyd.lookupnext(a_rid)
|
bid, rbyd = mdir
|
||||||
_, (_, b_w, _) = rbyd.lookupnext(b_rid)
|
if not rbyd:
|
||||||
if isinstance(mdir, Mdir):
|
continue
|
||||||
a_mid = mtree.mid(mdir.mid, a_rid)
|
|
||||||
b_mid = mtree.mid(mdir.mid, b_rid)
|
|
||||||
else:
|
|
||||||
a_mid = mtree.mid(bid-(rbyd.weight-1)+a_rid-(a_w-1), -1)
|
|
||||||
b_mid = mtree.mid(bid-(rbyd.weight-1)+b_rid-(b_w-1), -1)
|
|
||||||
|
|
||||||
tree.add(cls.Branch(
|
# yes we can find new rbyds if disk is being mutated, just
|
||||||
(a_mid, len(path), a_tag),
|
# ignore these
|
||||||
(b_mid, len(path), b_tag),
|
if rbyd not in rtrees:
|
||||||
d + rdepths[len(path)]-rz + t.z,
|
continue
|
||||||
t.color))
|
|
||||||
|
|
||||||
# connect rbyd branches to rbyd roots
|
rtree = rtrees[rbyd]
|
||||||
if path:
|
rz = max((t.z+1 for t in rtree), default=0)
|
||||||
# figure out branch mid/attr
|
d = sum(rdepths[d]+1 for d, p in enumerate(path))
|
||||||
if isinstance(path[-1][1], Mdir):
|
|
||||||
l_mid, l_mdir, l_name = path[-1]
|
|
||||||
l_branch = (l_mdir.lookup(l_mid, TAG_MROOT, 0x3)
|
|
||||||
or l_mdir.lookup(l_mid, TAG_MTREE, 0x3))
|
|
||||||
else:
|
|
||||||
l_bid, l_rbyd, l_rid, l_name = path[-1]
|
|
||||||
l_mid = mtree.mid(l_bid-(l_name.weight-1), -1)
|
|
||||||
l_branch = (l_rbyd.lookup(l_rid, TAG_BRANCH, 0x3)
|
|
||||||
or l_rbyd.lookup(l_rid, TAG_MDIR, 0x3))
|
|
||||||
|
|
||||||
# figure out root mid/rattr
|
# map into our mtree space
|
||||||
if rtree:
|
for t in rtree:
|
||||||
r_rid, r_tag = min(rtree, key=lambda t: t.z).a
|
|
||||||
_, (_, r_w, _) = rbyd.lookupnext(r_rid)
|
|
||||||
else:
|
|
||||||
r_rid, (r_tag, r_w, _) = rbyd.lookupnext(-1)
|
|
||||||
|
|
||||||
if isinstance(mdir, Mdir):
|
|
||||||
r_mid = mtree.mid(mdir.mid, r_rid)
|
|
||||||
else:
|
|
||||||
r_mid = mtree.mid(bid-(rbyd.weight-1)+r_rid-(r_w-1), -1)
|
|
||||||
|
|
||||||
tree.add(cls.Branch(
|
|
||||||
(l_mid, len(path)-1, l_branch.tag),
|
|
||||||
(r_mid, len(path), r_tag),
|
|
||||||
d-1))
|
|
||||||
|
|
||||||
# remap branches to leaves if we aren't showing inner branches
|
|
||||||
if not inner:
|
|
||||||
# step through each btree layer backwards
|
|
||||||
b_depth = max((t.a[1]+1 for t in tree), default=0)
|
|
||||||
|
|
||||||
for d in reversed(range(len(mtree.mrootchain), b_depth-1)):
|
|
||||||
# find mid ranges at this level
|
|
||||||
mids = set()
|
|
||||||
for t in tree:
|
|
||||||
if t.b[1] == d:
|
|
||||||
mids.add(t.b[0])
|
|
||||||
mids = sorted(mids)
|
|
||||||
|
|
||||||
# find the best root for each mid range
|
|
||||||
roots = {}
|
|
||||||
for i in range(len(mids)):
|
|
||||||
for t in tree:
|
|
||||||
if (t.a[1] > d
|
|
||||||
and t.a[0] >= mids[i]
|
|
||||||
and (i == len(mids)-1 or t.a[0] < mids[i+1])
|
|
||||||
and (mids[i] not in roots
|
|
||||||
or t < roots[mids[i]])):
|
|
||||||
roots[mids[i]] = t
|
|
||||||
|
|
||||||
# remap branches to leaf-roots
|
|
||||||
tree = {t.map(
|
|
||||||
lambda x: x[1] == d and x[0] in roots,
|
|
||||||
lambda x: roots[x[0]].a)
|
|
||||||
for t in tree}
|
|
||||||
|
|
||||||
return cls(tree)
|
|
||||||
|
|
||||||
# render an mtree tree for debugging
|
|
||||||
@classmethod
|
|
||||||
def _frommtreebtree(cls, mtree, *,
|
|
||||||
depth=None,
|
|
||||||
inner=False,
|
|
||||||
**args):
|
|
||||||
tree = set()
|
|
||||||
root = None
|
|
||||||
branches = {}
|
|
||||||
for mid, mdir, name, path in mtree.mids(
|
|
||||||
mdirs_only=False,
|
|
||||||
path=True,
|
|
||||||
depth=depth):
|
|
||||||
# create branch for each jump in path
|
|
||||||
#
|
|
||||||
# note we adjust our mid/bid to be left-leaning, this allows
|
# note we adjust our mid/bid to be left-leaning, this allows
|
||||||
# a global order and makes tree rendering quite a bit easier
|
# a global order and makes tree rendering quite a bit easier
|
||||||
#
|
#
|
||||||
# we also need to give btree nodes mrid=-1 so they come
|
# we also need to give btree nodes mrid=-1 so they come
|
||||||
# before and mrid=-1 mdir attrs
|
# before and mrid=-1 mdir attrs
|
||||||
a = root
|
a_rid, a_tag = t.a
|
||||||
for d, p in enumerate(path):
|
b_rid, b_tag = t.b
|
||||||
# map into our mtree space
|
_, (_, a_w, _) = rbyd.lookupnext(a_rid)
|
||||||
if isinstance(p[1], Mdir):
|
_, (_, b_w, _) = rbyd.lookupnext(b_rid)
|
||||||
mid_, mdir_, name_ = p
|
if isinstance(mdir, Mdir):
|
||||||
else:
|
a_mid = mtree.mid(mdir.mid, a_rid)
|
||||||
bid_, rbyd_, rid_, name_ = p
|
b_mid = mtree.mid(mdir.mid, b_rid)
|
||||||
mid_ = mtree.mid(bid_-(name_.weight-1), -1)
|
else:
|
||||||
b = (mid_, d, name_.tag)
|
a_mid = mtree.mid(bid-(rbyd.weight-1)+a_rid-(a_w-1), -1)
|
||||||
|
b_mid = mtree.mid(bid-(rbyd.weight-1)+b_rid-(b_w-1), -1)
|
||||||
|
|
||||||
# remap branches to leaves if we aren't showing inner
|
tree.add(cls.Branch(
|
||||||
# branches
|
(a_mid, len(path), a_tag),
|
||||||
if not inner:
|
(b_mid, len(path), b_tag),
|
||||||
if b not in branches:
|
d + rdepths[len(path)]-rz + t.z,
|
||||||
if isinstance(path[-1][1], Mdir):
|
t.color))
|
||||||
mid_, mdir_, name_ = path[-1]
|
|
||||||
else:
|
|
||||||
bid_, rbyd_, rid_, name_ = path[-1]
|
|
||||||
mid_ = mtree.mid(bid_-(name_.weight-1), -1)
|
|
||||||
branches[b] = (mid_, len(path)-1, name_.tag)
|
|
||||||
b = branches[b]
|
|
||||||
|
|
||||||
# render the root path on first rid, this is arbitrary
|
# connect rbyd branches to rbyd roots
|
||||||
if root is None:
|
if path:
|
||||||
root, a = b, b
|
# figure out branch mid/attr
|
||||||
|
if isinstance(path[-1][1], Mdir):
|
||||||
|
l_mid, l_mdir, l_name = path[-1]
|
||||||
|
l_branch = (l_mdir.lookup(l_mid, TAG_MROOT, 0x3)
|
||||||
|
or l_mdir.lookup(l_mid, TAG_MTREE, 0x3))
|
||||||
|
else:
|
||||||
|
l_bid, l_rbyd, l_rid, l_name = path[-1]
|
||||||
|
l_mid = mtree.mid(l_bid-(l_name.weight-1), -1)
|
||||||
|
l_branch = (l_rbyd.lookup(l_rid, TAG_BRANCH, 0x3)
|
||||||
|
or l_rbyd.lookup(l_rid, TAG_MDIR, 0x3))
|
||||||
|
|
||||||
tree.add(cls.Branch(a, b, d))
|
# figure out root mid/rattr
|
||||||
a = b
|
if rtree:
|
||||||
|
r_rid, r_tag = min(rtree, key=lambda t: t.z).a
|
||||||
|
_, (_, r_w, _) = rbyd.lookupnext(r_rid)
|
||||||
|
else:
|
||||||
|
r_rid, (r_tag, r_w, _) = rbyd.lookupnext(-1)
|
||||||
|
|
||||||
return cls(tree)
|
if isinstance(mdir, Mdir):
|
||||||
|
r_mid = mtree.mid(mdir.mid, r_rid)
|
||||||
|
else:
|
||||||
|
r_mid = mtree.mid(bid-(rbyd.weight-1)+r_rid-(r_w-1), -1)
|
||||||
|
|
||||||
# render an mtree tree for debugging
|
tree.add(cls.Branch(
|
||||||
@classmethod
|
(l_mid, len(path)-1, l_branch.tag),
|
||||||
def frommtree(cls, mtree, **args):
|
(r_mid, len(path), r_tag),
|
||||||
if args.get('tree_btree'):
|
d-1))
|
||||||
return cls._frommtreebtree(mtree, **args)
|
|
||||||
else:
|
# remap branches to leaves if we aren't showing inner branches
|
||||||
return cls._frommtreertree(mtree, **args)
|
if not inner:
|
||||||
|
# step through each btree layer backwards
|
||||||
|
b_depth = max((t.a[1]+1 for t in tree), default=0)
|
||||||
|
|
||||||
|
for d in reversed(range(len(mtree.mrootchain), b_depth-1)):
|
||||||
|
# find mid ranges at this level
|
||||||
|
mids = set()
|
||||||
|
for t in tree:
|
||||||
|
if t.b[1] == d:
|
||||||
|
mids.add(t.b[0])
|
||||||
|
mids = sorted(mids)
|
||||||
|
|
||||||
|
# find the best root for each mid range
|
||||||
|
roots = {}
|
||||||
|
for i in range(len(mids)):
|
||||||
|
for t in tree:
|
||||||
|
if (t.a[1] > d
|
||||||
|
and t.a[0] >= mids[i]
|
||||||
|
and (i == len(mids)-1 or t.a[0] < mids[i+1])
|
||||||
|
and (mids[i] not in roots
|
||||||
|
or t < roots[mids[i]])):
|
||||||
|
roots[mids[i]] = t
|
||||||
|
|
||||||
|
# remap branches to leaf-roots
|
||||||
|
tree = {t.map(
|
||||||
|
lambda x: x[1] == d and x[0] in roots,
|
||||||
|
lambda x: roots[x[0]].a)
|
||||||
|
for t in tree}
|
||||||
|
|
||||||
|
return cls(tree)
|
||||||
|
|
||||||
|
# render an mtree tree for debugging
|
||||||
|
@classmethod
|
||||||
|
def _treeartfrommtreebtree(cls, mtree, *,
|
||||||
|
depth=None,
|
||||||
|
inner=False,
|
||||||
|
**args):
|
||||||
|
tree = set()
|
||||||
|
root = None
|
||||||
|
branches = {}
|
||||||
|
for mid, mdir, name, path in mtree.mids(
|
||||||
|
mdirs_only=False,
|
||||||
|
path=True,
|
||||||
|
depth=depth):
|
||||||
|
# create branch for each jump in path
|
||||||
|
#
|
||||||
|
# note we adjust our mid/bid to be left-leaning, this allows
|
||||||
|
# a global order and makes tree rendering quite a bit easier
|
||||||
|
#
|
||||||
|
# we also need to give btree nodes mrid=-1 so they come
|
||||||
|
# before and mrid=-1 mdir attrs
|
||||||
|
a = root
|
||||||
|
for d, p in enumerate(path):
|
||||||
|
# map into our mtree space
|
||||||
|
if isinstance(p[1], Mdir):
|
||||||
|
mid_, mdir_, name_ = p
|
||||||
|
else:
|
||||||
|
bid_, rbyd_, rid_, name_ = p
|
||||||
|
mid_ = mtree.mid(bid_-(name_.weight-1), -1)
|
||||||
|
b = (mid_, d, name_.tag)
|
||||||
|
|
||||||
|
# remap branches to leaves if we aren't showing inner
|
||||||
|
# branches
|
||||||
|
if not inner:
|
||||||
|
if b not in branches:
|
||||||
|
if isinstance(path[-1][1], Mdir):
|
||||||
|
mid_, mdir_, name_ = path[-1]
|
||||||
|
else:
|
||||||
|
bid_, rbyd_, rid_, name_ = path[-1]
|
||||||
|
mid_ = mtree.mid(bid_-(name_.weight-1), -1)
|
||||||
|
branches[b] = (mid_, len(path)-1, name_.tag)
|
||||||
|
b = branches[b]
|
||||||
|
|
||||||
|
# render the root path on first rid, this is arbitrary
|
||||||
|
if root is None:
|
||||||
|
root, a = b, b
|
||||||
|
|
||||||
|
tree.add(cls.Branch(a, b, d))
|
||||||
|
a = b
|
||||||
|
|
||||||
|
return cls(tree)
|
||||||
|
|
||||||
|
# render an mtree tree for debugging
|
||||||
|
@classmethod
|
||||||
|
def treeartfrommtree(cls, mtree, **args):
|
||||||
|
if args.get('tree_btree'):
|
||||||
|
return cls._frommtreebtree(mtree, **args)
|
||||||
|
else:
|
||||||
|
return cls._frommtreertree(mtree, **args)
|
||||||
|
|
||||||
|
TreeArt._frommtreertree = _treeartfrommtreertree
|
||||||
|
TreeArt._frommtreebtree = _treeartfrommtreebtree
|
||||||
|
TreeArt.frommtree = treeartfrommtree
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user