API

Powerful and Lightweight Python Tree Data Structure.

Overview

The anytree API is splitted into the following parts:

Classes

class anytree.NodeMixin[source]

Bases: object

The NodeMixin class extends any Python class to a tree node.

The only tree relevant information is the parent attribute. If None the NodeMixin is root node. If set to another node, the NodeMixin becomes the child of it.

>>> class MyBaseClass(object):
...     foo = 4
>>> class MyClass(MyBaseClass, NodeMixin):  # Add Node feature
...     def __init__(self, name, length, width, parent=None):
...         super(MyClass, self).__init__()
...         self.name = name
...         self.length = length
...         self.width = width
...         self.parent = parent
>>> my0 = MyClass('my0', 0, 0)
>>> my1 = MyClass('my1', 1, 0, parent=my0)
>>> my2 = MyClass('my2', 0, 2, parent=my0)
>>> for pre, _, node in RenderTree(my0):
...     treestr = u"%s%s" % (pre, node.name)
...     print(treestr.ljust(8), node.length, node.width)
my0      0 0
├── my1  1 0
└── my2  0 2
parent

Parent Node.

On set, the node is detached from any previous parent node and attached to the new node.

>>> udo = Node("Udo")
>>> marc = Node("Marc")
>>> lian = Node("Lian", parent=marc)
>>> print(RenderTree(udo))
Node('Udo')
>>> print(RenderTree(marc))
Node('Marc')
└── Node('Marc/Lian')

Attach:

>>> marc.parent = udo
>>> print(RenderTree(udo))
Node('Udo')
└── Node('Udo/Marc')
    └── Node('Udo/Marc/Lian')

To make a node to a root node, just set this attribute to None.

children

All child nodes.

>>> dan = Node("Dan")
>>> jet = Node("Jet", parent=dan)
>>> jan = Node("Jan", parent=dan)
>>> joe = Node("Joe", parent=dan)
>>> dan.children
(Node('Dan/Jet'), Node('Dan/Jan'), Node('Dan/Joe'))
path

Path of this Node.

>>> udo = Node("Udo")
>>> marc = Node("Marc", parent=udo)
>>> lian = Node("Lian", parent=marc)
>>> udo.path
(Node('Udo'),)
>>> marc.path
(Node('Udo'), Node('Udo/Marc'))
>>> lian.path
(Node('Udo'), Node('Udo/Marc'), Node('Udo/Marc/Lian'))
anchestors

All parent nodes and their parent nodes.

>>> udo = Node("Udo")
>>> marc = Node("Marc", parent=udo)
>>> lian = Node("Lian", parent=marc)
>>> udo.anchestors
()
>>> marc.anchestors
(Node('Udo'),)
>>> lian.anchestors
(Node('Udo'), Node('Udo/Marc'))
descendants

All child nodes and all their child nodes.

>>> udo = Node("Udo")
>>> marc = Node("Marc", parent=udo)
>>> lian = Node("Lian", parent=marc)
>>> loui = Node("Loui", parent=marc)
>>> udo.descendants
(Node('Udo/Marc'), Node('Udo/Marc/Lian'), Node('Udo/Marc/Loui'))
>>> marc.descendants
(Node('Udo/Marc/Lian'), Node('Udo/Marc/Loui'))
>>> lian.descendants
()
root

Tree Root Node.

>>> udo = Node("Udo")
>>> marc = Node("Marc", parent=udo)
>>> lian = Node("Lian", parent=marc)
>>> udo.root is None
True
>>> marc.root
Node('Udo')
>>> lian.root
Node('Udo')
siblings

Tuple of nodes with the same parent.

>>> udo = Node("Udo")
>>> marc = Node("Marc", parent=udo)
>>> lian = Node("Lian", parent=marc)
>>> loui = Node("Loui", parent=marc)
>>> lazy = Node("Lazy", parent=marc)
>>> udo.siblings
()
>>> marc.siblings
()
>>> lian.siblings
(Node('Udo/Marc/Loui'), Node('Udo/Marc/Lazy'))
>>> loui.siblings
(Node('Udo/Marc/Lian'), Node('Udo/Marc/Lazy'))
is_leaf

Node has no childrean (External Node).

>>> udo = Node("Udo")
>>> marc = Node("Marc", parent=udo)
>>> lian = Node("Lian", parent=marc)
>>> udo.is_leaf
False
>>> marc.is_leaf
False
>>> lian.is_leaf
True
is_root

Node is tree root.

>>> udo = Node("Udo")
>>> marc = Node("Marc", parent=udo)
>>> lian = Node("Lian", parent=marc)
>>> udo.is_root
True
>>> marc.is_root
False
>>> lian.is_root
False
height

Number of edges on the longest path to a leaf Node.

>>> udo = Node("Udo")
>>> marc = Node("Marc", parent=udo)
>>> lian = Node("Lian", parent=marc)
>>> udo.height
2
>>> marc.height
1
>>> lian.height
0
depth

Number of edges to the root Node.

>>> udo = Node("Udo")
>>> marc = Node("Marc", parent=udo)
>>> lian = Node("Lian", parent=marc)
>>> udo.depth
0
>>> marc.depth
1
>>> lian.depth
2
class anytree.Node(name, parent=None, **kwargs)[source]

Bases: anytree.NodeMixin, object

A simple tree node with a name and any kwargs.

>>> root = Node("root")
>>> s0 = Node("sub0", parent=root)
>>> s0b = Node("sub0B", parent=s0, foo=4, bar=109)
>>> s0a = Node("sub0A", parent=s0)
>>> s1 = Node("sub1", parent=root)
>>> s1a = Node("sub1A", parent=s1)
>>> s1b = Node("sub1B", parent=s1, bar=8)
>>> s1c = Node("sub1C", parent=s1)
>>> s1ca = Node("sub1Ca", parent=s1c)
>>> print(RenderTree(root))
Node('root')
├── Node('root/sub0')
│   ├── Node('root/sub0/sub0B', bar=109, foo=4)
│   └── Node('root/sub0/sub0A')
└── Node('root/sub1')
    ├── Node('root/sub1/sub1A')
    ├── Node('root/sub1/sub1B', bar=8)
    └── Node('root/sub1/sub1C')
        └── Node('root/sub1/sub1C/sub1Ca')
name

Name.

class anytree.PreOrderIter(node)[source]

Bases: object

Iterate over tree applying pre-order strategy starting at node.

>>> f = Node("f")
>>> b = Node("b", parent=f)
>>> a = Node("a", parent=b)
>>> d = Node("d", parent=b)
>>> c = Node("c", parent=d)
>>> e = Node("e", parent=d)
>>> g = Node("g", parent=f)
>>> i = Node("i", parent=g)
>>> h = Node("h", parent=i)
>>> [node.name for node in PreOrderIter(f)]
['f', 'b', 'a', 'd', 'c', 'e', 'g', 'i', 'h']
class anytree.PostOrderIter(node)[source]

Bases: object

Iterate over tree applying post-order strategy starting at node.

>>> f = Node("f")
>>> b = Node("b", parent=f)
>>> a = Node("a", parent=b)
>>> d = Node("d", parent=b)
>>> c = Node("c", parent=d)
>>> e = Node("e", parent=d)
>>> g = Node("g", parent=f)
>>> i = Node("i", parent=g)
>>> h = Node("h", parent=i)
>>> [node.name for node in PostOrderIter(f)]
['a', 'c', 'e', 'd', 'b', 'h', 'i', 'g', 'f']
class anytree.AbstractStyle(vertical, cont, end)[source]

Bases: object

Tree Render Style.

Args:

vertical: Sign for vertical line.

cont: Chars for a continued branch.

end: Chars for the last branch.

empty

Empty string as placeholder.

class anytree.AsciiStyle[source]

Bases: anytree.AbstractStyle

Ascii style.

>>> root = Node("root")
>>> s0 = Node("sub0", parent=root)
>>> s0b = Node("sub0B", parent=s0)
>>> s0a = Node("sub0A", parent=s0)
>>> s1 = Node("sub1", parent=root)
>>> print(RenderTree(root, style=AsciiStyle()))
Node('root')
|-- Node('root/sub0')
|   |-- Node('root/sub0/sub0B')
|   +-- Node('root/sub0/sub0A')
+-- Node('root/sub1')
class anytree.ContStyle[source]

Bases: anytree.AbstractStyle

Continued style, without gaps.

>>> root = Node("root")
>>> s0 = Node("sub0", parent=root)
>>> s0b = Node("sub0B", parent=s0)
>>> s0a = Node("sub0A", parent=s0)
>>> s1 = Node("sub1", parent=root)
>>> print(RenderTree(root, style=ContStyle()))
Node('root')
├── Node('root/sub0')
│   ├── Node('root/sub0/sub0B')
│   └── Node('root/sub0/sub0A')
└── Node('root/sub1')
class anytree.ContRoundStyle[source]

Bases: anytree.AbstractStyle

Continued style, without gaps, round edges.

>>> root = Node("root")
>>> s0 = Node("sub0", parent=root)
>>> s0b = Node("sub0B", parent=s0)
>>> s0a = Node("sub0A", parent=s0)
>>> s1 = Node("sub1", parent=root)
>>> print(RenderTree(root, style=ContRoundStyle()))
Node('root')
├── Node('root/sub0')
│   ├── Node('root/sub0/sub0B')
│   ╰── Node('root/sub0/sub0A')
╰── Node('root/sub1')
class anytree.DoubleStyle[source]

Bases: anytree.AbstractStyle

Double line style, without gaps.

>>> root = Node("root")
>>> s0 = Node("sub0", parent=root)
>>> s0b = Node("sub0B", parent=s0)
>>> s0a = Node("sub0A", parent=s0)
>>> s1 = Node("sub1", parent=root)
>>> print(RenderTree(root, style=DoubleStyle))
Node('root')
╠══ Node('root/sub0')
║   ╠══ Node('root/sub0/sub0B')
║   ╚══ Node('root/sub0/sub0A')
╚══ Node('root/sub1')
class anytree.RenderTree(node, style=ContStyle(), childiter=<type 'list'>)[source]

Bases: object

Render tree starting at node.

Keyword Args:

style (AbstractStyle): Render Style.

childiter: Child iterator.

RenderTree is an iterator, returning a tuple with 3 items:

pre
tree prefix.
fill
filling for multiline entries.
node
NodeMixin object.

It is up to the user to assemble these parts to a whole.

>>> root = Node("root", lines=["c0fe", "c0de"])
>>> s0 = Node("sub0", parent=root, lines=["ha", "ba"])
>>> s0b = Node("sub0B", parent=s0, lines=["1", "2", "3"])
>>> s0a = Node("sub0A", parent=s0, lines=["a", "b"])
>>> s1 = Node("sub1", parent=root, lines=["Z"])

Simple one line:

>>> for pre, _, node in RenderTree(root):
...     print("%s%s" % (pre, node.name))
root
├── sub0
│   ├── sub0B
│   └── sub0A
└── sub1

Multiline:

>>> for pre, fill, node in RenderTree(root):
...     print("%s%s" % (pre, node.lines[0]))
...     for line in node.lines[1:]:
...         print("%s%s" % (fill, line))
c0fe
c0de
├── ha
│   ba
│   ├── 1
│   │   2
│   │   3
│   └── a
│       b
└── Z

The childiter is responsible for iterating over child nodes at the same level. An reversed order can be achived by using reversed.

>>> for pre, _, node in RenderTree(root, childiter=reversed):
...     print("%s%s" % (pre, node.name))
root
├── sub1
└── sub0
    ├── sub0A
    └── sub0B

Or writing your own sort function:

>>> def mysort(items):
...     return sorted(items, key=lambda item: item.name)
>>> for pre, _, node in RenderTree(root, childiter=mysort):
...     print("%s%s" % (pre, node.name))
root
├── sub0
│   ├── sub0A
│   └── sub0B
└── sub1
exception anytree.LoopError[source]

Bases: exceptions.RuntimeError

Tree contains infinite loop.