Create nodes as specified in the tree text.
- Compatible with python2,3
- Data can be assigned to nodes
- Convert between text and node objects
- 2019-12-26
- Raspbierry Pi 4 Model B Rev 1.2
- Raspbian buster 10.0 2019-09-26 setup
- bash 5.0.3(1)-release
- Python 2.7.16
- Python 3.7.3
pip install textree
Convert from text to node object.
import textree
tree_text = """
A
A1
A11
A111
A112
A2
B
"""
tree = TexTree()
root = tree.to_node(tree_text)
print(root, root.Name)
for node in tree.Nodes:
print(node.Line)
print(tree.to_text())
Convert between text and objects.
root = tree.to_node(tree_text)
tree.to_text()
Reference and assignment.
node.Name
node.Parent
node.Children
node.Name = 'NewName'
node.Parent = Node('Parent')
node.Children.append(Node('Child'))
Move.
node.to_first()
node.to_last()
node.to_next()
node.to_prev()
Get.
Node.Path.select(root, 'A/A1/A11')
Node.Path.select(A, 'A1/A11')
Insertion / deletion.
node.insert_first(Node('new'))
node.insert_last(Node('new'))
node.insert_next(Node('new'))
node.insert_prev(Node('new'))
node.delete()
Update.
node = Node.Path.select(root, 'A/A1/A11')
node.Name = 'UpdateName'
There are many others. Refer to the code or API list for details.
Attributes can be assigned to the same line.
import textree
tree_text = """
A attrA
A1 attrA1
A11 attrA11
A111 attrA111
A112 attrA112
A2 attrA2
B attrB
"""
tree = TexTree()
root = tree.to_node(tree_text)
print(root, root.Name)
for node in tree.Nodes:
print(node.Name, node,Attr)
Attributes can be assigned to RootNode.
import textree
tree_text = """
<ROOT> root_attr
A attrA
A1 attrA1
A11 attrA11
A111 attrA111
A112 attrA112
A2 attrA2
B attrB
"""
tree = TexTree()
root = tree.to_node(tree_text)
print(root, root.Name, root.Attr)
for node in tree.Nodes:
print(node.Name, node,Attr)
The user can embed the attribute analysis code freely. Of course you can also write code to serialize to text.
The following code gives the node my_name
.
class MyNodeDeserializer(NodeDeserializer):
def deserialize(self, ana, parent, parents=Node):
node = Node(ana.Line, parent=parent)
node.my_name = 'My name is ' + node.Name
return node
tree = TexTree(node_deserializer=MyNodeDeserializer())
root = tree.to_node(tree_text)
for node in tree.Nodes:
print(node.my_name)
class MyNodeAttributeSerializer(NodeAttributeSerializer):
def serialize(self, attr): return 'my_name=' + attr
tree = TexTree(node_deserializer=MyNodeDeserializer(), node_serializer=NodeSerializer(MyNodeAttributeSerializer()))
root = tree.to_node(tree_text)
for node in tree.Nodes:
print(node.my_name)
print(tree.to_text())
tree_text
<ROOT> {"height": 444, "name": " \\" NAME \\" "}
A
a.py
import json, collections
class MyRootAttributeDeserializer(textree.RootAttributeDeserializer):
def deserialize(self, line_attr):
decoder = json.JSONDecoder(object_pairs_hook=collections.OrderedDict)
attr = decoder.decode('{"width":640, "height":480, "name":"new.xcf"}') # default value
if line_attr is None: return attr
inpt = decoder.decode(line_attr)
attr.update(inpt)
return attr
class MyRootAttributeSerializer(textree.RootAttributeSerializer):
def serialize(self, node):
return json.dumps(node.Attr)
tree = TexTree(root_deserializer=textree.RootDeserializer(MyRootAttributeDeserializer()), root_serializer=textree.RootSerializer(MyRootAttributeSerializer()))
tree_text = '<ROOT>\t{"height": 444, "name": " \\" NAME \\" "}\nA'
root = tree.to_node(tree_text)
self.assertEqual(640, root.Attr['width'])
self.assertEqual(444, root.Attr['height'])
self.assertEqual(' " NAME " ', root.Attr['name'])
tree_text
<ROOT> height=444 name=" \" NAME \" "
A
b.py
import json, collections
class MyRootAttributeDeserializer(textree.RootAttributeDeserializer):
def deserialize(self, line_attr):
def parse_kv_pairs(text, item_sep=" ", value_sep="="):
lexer = shlex.shlex(text, posix=True)
lexer.whitespace = item_sep
lexer.wordchars += value_sep
return dict(word.split(value_sep) for word in lexer)
decoder = json.JSONDecoder(object_pairs_hook=collections.OrderedDict)
attr = decoder.decode('{"width":640, "height":480, "name":"new.xcf"}') # default value
if line_attr is None: return attr
inpt = parse_kv_pairs(line_attr)
attr.update(inpt)
attr['width'] = int(attr['width'])
attr['height'] = int(attr['height'])
return attr
class MyRootAttributeSerializer(textree.RootAttributeSerializer):
def serialize(self, attr):
def delete_braces(attr_str):
if '{' == attr_str[0]: attr_str = attr_str[1:]
if '}' == attr_str[-1]: attr_str = attr_str[:-1]
return attr_str
def delete_key_quotes(attr_str):
rmidxs = []
idxs = [i for i, x in enumerate(attr_str) if '=' == x]
for idx in idxs:
if '"' == attr_str[idx-1]:
start_quote_idx = idx-1-1
while -1 < start_quote_idx:
if '"' == attr_str[start_quote_idx]: break
else: start_quote_idx-=1
if -1 < start_quote_idx:
rmidxs.append(start_quote_idx)
rmidxs.append(idx-1)
res = str(attr_str)
diff = 0
for rmidx in rmidxs:
if 0 == rmidx: res = res[rmidx+1-diff:]
elif rmidx == len(attr_str)-1: res = res[:rmidx-diff]
else: res = res[:rmidx-diff] + res[rmidx+1-diff:]
diff+=1
return res
attr_str = json.dumps(attr, False, True, True, True, None, None, (' ','='), "utf-8", None, False)
attr_str = delete_key_quotes(delete_braces(attr_str))
attr_str = attr_str.replace('width=640', '')
attr_str = attr_str.replace('height=480', '')
attr_str = attr_str.replace('name="new.xcf"', '')
return None if attr_str is None else attr_str.strip()
tree = TexTree(root_deserializer=textree.RootDeserializer(attr_des=MyRootAttributeDeserializer()), root_serializer=textree.RootSerializer(attr_ser=MyRootAttributeSerializer()))
tree_text = '<ROOT>\theight=444 name=" \\" NAME \\" "\nA'
root = tree.to_node(tree_text)
self.assertEqual(640, root.Attr['width'])
self.assertEqual(444, root.Attr['height'])
self.assertEqual(' " NAME " ', root.Attr['name'])
self.assertEqual(tree_text, tree.to_text())
- Alpha version. Checking installation
ytyaru
This software is AGPLv3 licensed. (GNU Affero General Public License v3) agpl-3.0