API Reference

nutree.tree module

Declare the Tree class.

MIN_PYTHON_VERSION_INFO = (3, 8)

Minimal Python version that is supported by WsgiDAV

class Tree(name: str | None = None, *, calc_data_id: Callable[[Tree, Any], str | int] | None = None, forward_attrs: bool = False)[source]

Bases: Generic[TData, TNode]

A Tree object is a shallow wrapper around a single, invisible system root node. All visible toplevel nodes are direct children of this root node. Trees expose methods to iterate, search, copy, filter, serialize, etc.

A name string can be passed for enhanced printing.

calc_data_id can be a callback function that calculates data IDs from data objects (by default hash(data) is used).

Set forward_attrs to true, to enable aliasing of node attributes, i.e. make node.data.NAME accessible as node.NAME.
Note: Use with care, see also Forward Attributes (Attribute Aliasing).

DEFAULT_CONNECTOR_STYLE = 'round43'

Default connector prefixes format(style=...) argument.

DEFAULT_KEY_MAP: dict[str, str] = {'data_id': 'i', 'str': 's'}

Default value for save(..., key_map=...) argument.

DEFAULT_VALUE_MAP: dict[str, list[str]] = {}

Default value for save(..., value_map=...) argument.

__contains__(data)[source]

Implement data in tree syntax to check for node existence.

__delitem__(data)[source]

Implement del tree[data] syntax to remove nodes.

__enter__()[source]

Implement with tree: ... syntax to acquire an RLock.

__getitem__(data: object) TNode[source]

Implement tree[data] syntax to lookup a node.

data may be a plain string, data object, data_id, or node_id.

Note: This is a flexible and concise way to access tree nodes. However, find_all() or find_first() may be faster.

AmbiguousMatchError is raised if multiple matches are found. Use find_all() or find_first() instead to resolve this.

__iter__(method: IterMethod = IterMethod.PRE_ORDER) Iterator[TNode]

Implement for node in tree: ... syntax to iterate nodes depth-first.

__len__()[source]

Make len(tree) return the number of nodes (also makes empty trees falsy).

add(child: TNode | Self | TData, *, before: TNode | bool | int | None = None, deep: bool | None = None, data_id: str | int | None = None, node_id=None) TNode[source]

Add a toplevel node (same as shortcut add()).

See Node’s add_child() method for details.

add_child(child: TNode | Self | TData, *, before: TNode | bool | int | None = None, deep: bool | None = None, data_id: str | int | None = None, node_id=None) TNode[source]

Add a toplevel node (same as shortcut add()).

See Node’s add_child() method for details.

classmethod build_random_tree(structure_def: dict) Self[source]

Build a random tree for .

Returns a new Tree instance with random nodes, as defined by structure_def. If called like TypedTree.build_random_tree(structure_def), this method will return a TypedTree instance.

See Generate Random Trees for details.

calc_data_id(data: Any) str | int[source]

Called internally to calculate data_id for a data object.

This value is used to lookup nodes by data, identify clones, and for (de)serialization. It defaults to hash(data) but may be overloaded when the data objects have meaningful keys that should be used instead.

Note: By default, the __hash__() values of str and bytes objects are ‘salted’ with an unpredictable random value. Although they remain constant within an individual Python process, they are not predictable between repeated invocations of Python.

calc_height() int[source]

Return the maximum depth of all nodes.

property children: list[TNode]

Return list of direct child nodes, i.e. toplevel nodes (list may be empty).

clear() None[source]

Remove all nodes from this tree.

copy(*, name: str | None = None, predicate: Callable[[Node], None | bool | IterationControl | type[IterationControl]] | None = None) Self[source]

Return a copy of this tree.

New Tree and Node instances are created. The new nodes reference the original data objects.

predicate may be passed to filter the result, which is equivalent to calling filtered()

See Node’s copy_to() and Iteration Callbacks method for details.

copy_to(target: TNode | Self, *, deep=True) None[source]

Copy this tree’s nodes to another target.

See Node’s copy_to() method for details.

property count: int

Return the total number of nodes.

property count_unique: int

Return the total number of unique nodes.

Multiple references to the same data object (‘clones’) are only counted once. This is different from count(), which returns the number of all nodes.

classmethod deserialize_mapper(parent: Node, data: dict) str | object | None[source]

Used as default mapper argument for load().

diff(other: Self, *, compare: Callable[[Node, Node, Node], bool | Any] | bool = True, ordered=False, reduce=False) Tree[source]

Compare this tree against other and return a merged, annotated copy.

The resulting tree contains a union of all nodes from this and the other tree. Additional metadata is added to the resulting nodes to classify changes from the perspective of this tree. For example a node that only exists in other, will have node.get_meta("dc") == DiffClassification.ADDED defined.

The compare callback can be used to customize the comparison of nodes It should return True if the nodes are considered equal, False otherwise.

If ordered is true, changes in the child order are also considered a change.
If reduce is true, unchanged nodes are removed, leaving a compact tree with only the modifications.

See Diff and Merge for details.

filter(predicate: Callable[[Node], None | bool | IterationControl | type[IterationControl]]) None[source]

In-place removal of unmatching nodes.

See also Iteration Callbacks.

filtered(predicate: Callable[[Node], None | bool | IterationControl | type[IterationControl]]) Self[source]

Return a filtered copy of this tree.

See also Iteration Callbacks.

find(data=None, *, match: str | Callable[[Node], None | bool | IterationControl | type[IterationControl]] | list | tuple | Any | None = None, data_id: str | int | None = None, node_id: int | None = None) TNode | None

Alias for find_first()

find_all(data=None, *, match: str | Callable[[Node], None | bool | IterationControl | type[IterationControl]] | list | tuple | Any | None = None, data_id: str | int | None = None, max_results: int | None = None) list[TNode][source]

Return a list of matching nodes (list may be empty).

See also Node’s find_all() method and Iteration Callbacks.

find_first(data=None, *, match: str | Callable[[Node], None | bool | IterationControl | type[IterationControl]] | list | tuple | Any | None = None, data_id: str | int | None = None, node_id: int | None = None) TNode | None[source]

Return the first matching node or None.

Note that ‘first’ sometimes means ‘one arbitrary’ matching node, which is not neccessarily the first of a specific iteration method. See also Node’s find_first() method and Iteration Callbacks.

first_child() TNode | None[source]

Return the first toplevel node.

format(*, repr: str | Callable[[Node], str] | None = None, style: str | None = None, title: str | bool | None = None, join: str = '\n') str[source]

Return a pretty string representation of the tree hierarchy.

See Node’s format() method for details.

format_iter(*, repr: str | Callable[[Node], str] | None = None, style=None, title=None) Iterator[str][source]

This variant of format() returns a line generator.

classmethod from_dict(obj: list[dict], *, mapper=None) Self[source]

Return a new Tree instance from a list of dicts.

See also to_dict_list() and Node’s find_first() methods, and Iteration Callbacks.

get_random_node() TNode[source]

Return a random node.

Note that there is also IterMethod.RANDOM_ORDER.

get_toplevel_nodes() list[TNode][source]

Return list of direct child nodes, i.e. toplevel nodes (may be empty, alias for children()).

iterator(method: IterMethod = IterMethod.PRE_ORDER) Iterator[TNode][source]

Traverse tree structure and yield nodes.

See Node’s iterator() method for details.

last_child() TNode | None[source]

Return the last toplevel node.

classmethod load(target: IO[str] | str | Path, *, mapper: Callable[[Node, dict], str | object] | None = None, file_meta: dict | None = None, auto_uncompress: bool = True) Self[source]

Create a new Tree instance from a file path or JSON file stream.

If file_meta is a dict, it receives the content if the file’s meta header.

See also save().

name: str

Tree name used for logging

node_factory

alias of Node

print(*, repr: str | Callable[[Node], str] | None = None, style: str | None = None, title: str | bool | None = None, join: str = '\n', file: IO[str] | None = None) None[source]

Convenience method that simply runs print(self. format()).

root_node_factory

alias of _SystemRootNode

save(target: IO[str] | str | Path, *, compression: bool | int = False, mapper: Callable[[Node, dict], None | dict] | None = None, meta: dict | None = None, key_map: dict[str, str] | bool = True, value_map: dict[str, list[str]] | bool = True) None[source]

Store tree in a compact JSON file stream.

If target is a string, it is interpreted as a file path. Otherwise it must be a file object.

If compression is true, the file is compressed using gzip (zipfile.ZIP_DEFLATED). Other values are: zipfile.ZIP_STORED, zipfile.ZIP_BZIP2, zipfile.ZIP_LZMA. Pass False to disable compression and store as plain json.

See also (De)Serialize and to_list_iter() and load() methods.

classmethod serialize_mapper(node: Node, data: dict) dict | None[source]

Used as default mapper argument for save().

sort(*, key: Callable[[Node], Any] | None = None, reverse=False, deep=True) None[source]

Sort toplevel nodes (optionally recursively).

key defaults to attrgetter("name"), so children are sorted by their string representation.

property system_root: TNode
to_dict_list(*, mapper: Callable[[Node, dict], None | dict] | None = None) list[dict][source]

Call Node’s to_dict() method for all child nodes and return list of results.

to_dot(*, add_root=True, unique_nodes=True, graph_attrs: dict | None = None, node_attrs: dict | None = None, edge_attrs: dict | None = None, node_mapper: Callable[[Node, dict], None | Any] | None = None, edge_mapper: Callable[[Node, dict], None | Any] | None = None) Iterator[str][source]

Generate a DOT formatted graph representation.

See Node’s to_dot() method for details.

to_dotfile(target: IO[str] | str | Path, *, format=None, add_root=True, unique_nodes=True, graph_attrs=None, node_attrs=None, edge_attrs=None, node_mapper=None, edge_mapper=None)[source]

Serialize a DOT formatted graph representation.

Optionally convert to a Graphviz display formats. See Graphs for details.

to_list_iter(*, mapper: Callable[[Node, dict], None | dict] | None = None, key_map: dict[str, str] | None = None, value_map: dict[str, list[str]] | None = None) Iterator[tuple[str | int, dict[str, str | int | float | bool | None] | str | int]][source]

Yield a parent-referencing list of child nodes.

to_mermaid_flowchart(target: IO[str] | str | Path, *, as_markdown: bool = True, direction: Literal['LR', 'RL', 'TB', 'TD', 'BT'] = 'TD', title: str | bool | None = True, format: Literal['svg', 'pdf', 'png'] | None = None, mmdc_options: dict | None = None, add_root: bool = True, unique_nodes: bool = True, headers: Iterable[str] | None = None, root_shape: str | None = None, node_mapper: str | Callable[[Node], str] | None = None, edge_mapper: Callable[[int, Node, int, Node], str] | str | None = None)[source]

Serialize a Mermaid flowchart representation.

Optionally convert to a Graphviz display formats. See Graphs for details.

to_rdf_graph()[source]

Return an instance of rdflib.Graph.

See Graphs for details.

visit(callback: Callable[[Node, Any], None | bool | SkipBranch | StopTraversal | type[SkipBranch] | type[StopTraversal] | type[StopIteration]], *, method: IterMethod = IterMethod.PRE_ORDER, memo: Any = None) Any | None[source]

Call callback(node, memo) for all nodes.

See Node’s visit() method and Iteration Callbacks for details.

nutree.node module

Declare the Node class.

class Node(data: TData, *, parent: Self, data_id: str | int | None = None, node_id: int | None = None, meta: dict | None = None)[source]

Bases: Generic[TData]

A Node represents a single element in the tree. It is a shallow wrapper around a user data instance, that adds navigation, modification, and other functionality.

Node objects are rarely created using this contructor, but indirectly by invoking helper methods like add_child(), etc.

data

is the arbitrary object that this node will hold.

parent

is the parent Node() instance. This node will also inherit the tree reference from it.

data_id

is an optional integer or string that will be used as ID (instead of calculating hash(data)). A tree may contain more than one node with the same data and data_id. In this case we call the nodes ‘clones’.

node_id

is an optional integer, that is used as unique ID for this node. Even ‘clones’ must have unique node IDs. The default is calculated as id(self).

meta

is an optional dictionary. See also get_meta(), set_meta(), update_meta(), and clear_meta().

DEFAULT_RENDER_REPR = '{node.data!r}'

Default value for repr argument when formatting data for print/display.

__eq__(other: Any) bool[source]

Implement node == other syntax to compare embedded data.

If other is a Node instance, self.data == other.data is evaluated. Otherwise self.data == other is compared.

Use node is other syntax instead to check if two nodes are truly identical.

__getattr__(name: str) Any[source]

Implement node.NAME aliasing to node.data.NAME.

See Forward Attributes (Attribute Aliasing).

__iter__(method: IterMethod = IterMethod.PRE_ORDER, *, add_self=False) Iterator[Self]

Implement for subnode in node: ... syntax to iterate descendant nodes.

add(child: Self | Tree | TData, *, before: Self | bool | int | None = None, deep: bool | None = None, data_id: DataIdType | None = None, node_id=None) Self

Alias for add_child()

add_child(child: Self | Tree | TData, *, before: Self | bool | int | None = None, deep: bool | None = None, data_id: DataIdType | None = None, node_id=None) Self[source]

Append or insert a new subnode or branch as child.

If child is an existing Node instance, a copy of this node will be created, that references the same child.data object.
If deep is true, the children are copied recursively.

If child is a Tree, all of its topnodes are added recursively (unless deep is false).

If child is neither a Node nor a Tree, child itself will become the data object of a new node that is added.

The source node may come from the same or from a foreign tree.
Note that adding the same data below one parent is not allowed.

If this node has no children yet, the new node is created as first child. Otherwise, it will be appended to the existing children by default.
The before option may be used to specifiy the position:

  • False, None: append the new node as last child

  • True, 0: prepend the new node as first child

  • <int>: prepend the new node before the existing child with this index

  • <Node>: prepend the new node before this child node

Parameters:
  • child (Node|Tree|TData) – Either an existing Node or a data object.

  • before (bool|int|Node|None) – Optional position.

  • deep (bool) – Copy descendants if any. This argument defaults to false when child is a Node. It defaults to true when child is a Tree.

  • data_id (str|int|None) – Allow to override the new node’s data_id. This argument is only allowed for single nodes, but not for deep copies. Default None will to calculate from hash(node.data).

  • node_id (str|int|None) – Optional custom unique node key (defaults to id(node)) This argument is only allowed for single nodes, but not for deep copies.

Returns:

the new Node instance

append_child(child: Self | Tree | TData, *, deep=None, data_id: DataIdType | None = None, node_id=None)[source]

Append a new subnode.

This is a shortcut for add_child() with before=None.

append_sibling(child: Self | Tree | TData, *, deep=None, data_id: DataIdType | None = None, node_id=None) Self[source]

Add a new node after self.

This method calls add_child() on self.parent.

calc_depth() int[source]

Return the distance to the root node (1 for toplevel nodes).

calc_height() int[source]

Return the maximum depth of all descendants (0 for leaves).

property children: list[Self]

Return list of direct child nodes (list may be empty).

clear_meta(key: str | None = None) None[source]

Reset all metadata or a distinct entry.

copy(*, add_self=True, predicate: PredicateCallbackType | None = None) Tree[TData, Self][source]

Return a new Tree instance from this branch.

See also Iteration Callbacks.

copy_to(target: Self | Tree[TData, Self], *, add_self=True, before: Self | bool | int | None = None, deep: bool = False) Self[source]

Copy this node to another parent and return the new node.

If add_self is set, a copy of this node becomes a child of target. Otherwise copies of all children of this node are created below target.

By default new nodes are appended to existing children. The before argument defines an alternative positioning. It is only available when add_self is true. See add_child() for a description of before.

If deep is set, all descendants are copied recursively.

count_descendants(*, leaves_only=False) int[source]

Return number of descendant nodes, not counting self.

property data: TData

Return the wrapped data instance (use set_data() to modify).

property data_id: str | int

Return the wrapped data instance’s id (use set_data() to modify).

depth() int[source]

Return the distance to the root node (1 for toplevel nodes).

filter(predicate: Callable[[Node], None | bool | IterationControl | type[IterationControl]]) None[source]

In-place removal of mismatching nodes.

See also Iteration Callbacks.

filtered(predicate: PredicateCallbackType) Tree[TData, Self][source]

Return a filtered copy of this node and descendants as tree.

See also Iteration Callbacks.

find(data=None, *, match: str | Callable[[Node], None | bool | IterationControl | type[IterationControl]] | list | tuple | Any | None = None, data_id: str | int | None = None) Self | None

Alias for find_first()

find_all(data=None, *, match: str | Callable[[Node], None | bool | IterationControl | type[IterationControl]] | list | tuple | Any | None = None, data_id: str | int | None = None, add_self=False, max_results: int | None = None) list[Self][source]

Return a list of matching nodes (list may be empty).

See also Iteration Callbacks.

find_first(data=None, *, match: str | Callable[[Node], None | bool | IterationControl | type[IterationControl]] | list | tuple | Any | None = None, data_id: str | int | None = None) Self | None[source]

Return the first matching node or None.

See also Iteration Callbacks.

first_child() Self | None[source]

First direct child node or None if no children exist.

first_sibling() Self[source]

Return first sibling (may be self).

format(*, repr: str | Callable[[Node], str] | None = None, style: str | None = None, add_self=True, join: str = '\n') str[source]

Return a pretty string representation of the node hierarchy.

more

Parameters:
  • repr (str) – A string or callback that defines how the node is rendered after the connector prefixes are generated.

  • style (str) – A string that defines the connector type, e.g. “round42” will produce “│ “, “╰─”, “├─”.

  • add_self (bool) – If false, only the descendants of this node are formatted.

  • join (str) – A string that is used to terminate the single lines. Defaults to “n”, but may be set to “, “ together with style=”list” to create a single line output.

Example

print(node.format(repr=”{node.name}”, style=”round42”))

format_iter(*, repr: str | Callable[[Node], str] | None = None, style: str | None = None, add_self=True) Iterator[str][source]

This variant of format() returns a line generator.

from_dict(obj: list[dict], *, mapper: Callable[[Node, dict], str | object] | None = None) None[source]

Append copies of all source children to self.

get_children() list[Self][source]

Return list of direct child nodes (list may be empty).

get_clones(*, add_self=False) list[Self][source]

Return a list of all nodes that reference the same data if any.

get_common_ancestor(other: Self) Self | None[source]

Return the nearest node that contains self and other (may be None).

get_index() int[source]

Return index in sibling list.

get_meta(key: str, default=None) Any[source]

Return metadata value.

get_parent_list(*, add_self=False, bottom_up=False) list[Self][source]

Return ordered list of all parent nodes.

get_path(*, add_self: bool = True, separator: str = '/', repr: str = '{node.name}') str[source]

Return a breadcrumb string, e.g. ‘/A/a1/a12’.

get_siblings(*, add_self=False) list[Self][source]

Return a list of all sibling entries of self (excluding self) if any.

get_top() Self[source]

Return toplevel ancestor (may be self).

has_children() bool[source]

Return true if this node has one or more children.

is_ancestor_of(other: Self) bool[source]

Return true if this node is a parent, grandparent, … of other.

is_clone() bool[source]

Return true if this node’s data is referenced at least one more time.

is_descendant_of(other: Self) bool[source]

Return true if this node is direct or indirect child of other.

is_first_sibling() bool[source]

Return true if this node is the first sibling, i.e. the first child of its parent.

is_last_sibling() bool[source]

Return true if this node is the last sibling, i.e. the last child of its parent.

is_leaf() bool[source]

Return true if this node is an end node, i.e. has no children.

is_system_root() bool[source]

Return true if this node is the invisible system root _SystemRootNode.

is_top() bool[source]

Return true if this node has no parent.

iterator(method: IterMethod = IterMethod.PRE_ORDER, *, add_self=False) Iterator[Self][source]

Generator that walks the hierarchy.

last_child() Self | None[source]

Last direct child node or None if no children exist.

last_sibling() Self[source]

Return last node, that share own parent (may be self).

property meta: dict | None

Return the node’s metadata dictionary or None if empty.

See also get_meta(), set_meta(), update_meta(), clear_meta().

move_to(new_parent: Self | Tree[TData, Self], *, before: Self | bool | int | None = None)[source]

Move this node to another parent.

By default, the node is appended to existing children. See add_child() for a description of before.

property name: str

String representation of the embedded data object.

next_sibling() Self | None[source]

Return successor or None, if node is last sibling.

property node_id: int

Return the node’s unique key.

property parent: Self | None

Return parent node or None for toplevel nodes.

See also up().

property path: str

All ancestor names including self, starting with and separated by ‘/’.

prepend_child(child: Self | Tree | TData, *, deep=None, data_id: DataIdType | None = None, node_id=None)[source]

Prepend a new subnode.

This is a shortcut for add_child() with before=True.

prepend_sibling(child: Self | Tree | TData, *, deep=None, data_id: DataIdType | None = None, node_id=None) Self[source]

Add a new node before self.

This method calls add_child() on self.parent.

prev_sibling() Self | None[source]

Predecessor or None, if node is first sibling.

remove(*, keep_children=False, with_clones=False) None[source]

Remove this node.

If keep_children is true, all children will be moved one level up, so they become siblings, before this node is removed.

If with_clones is true, all nodes that reference the same data instance are removed as well.

remove_children() None[source]

Remove all children of this node, making it a leaf node.

rename(new_name: str) None[source]

Set self.data to a new string (assuming plain string node).

set_data(data, *, data_id: str | int | None = None, with_clones: bool | None = None) None[source]

Change node’s data and/or data_id and update bookkeeping.

set_meta(key: str, value) None[source]

Set metadata value (pass value None to remove).

sort_children(*, key: Callable[[Node], Any] | None = None, reverse=False, deep=False) None[source]

Sort child nodes.

key defaults to attrgetter("name"), so children are sorted by their string representation.

to_dict(*, mapper: Callable[[Node, dict], None | dict] | None = None) dict[source]

Return a nested dict of this node and its children.

to_dot(*, add_self=False, unique_nodes=True, graph_attrs: dict | None = None, node_attrs: dict | None = None, edge_attrs: dict | None = None, node_mapper: Callable[[Node, dict], None | Any] | None = None, edge_mapper: Callable[[Node, dict], None | Any] | None = None) Iterator[str][source]

Generate a DOT formatted graph representation.

See Graphs for details.

to_list_iter(*, mapper: Callable[[Node, dict], None | dict] | None = None, key_map: dict[str, str] | None = None, value_map: dict[str, list[str]] | None = None) Iterator[tuple[str | int, dict[str, str | int | float | bool | None] | str | int]][source]

Yield children as parent-referencing list.

`py [(parent_key, data)] `

to_mermaid_flowchart(target: IO[str] | str | Path, *, as_markdown: bool = True, direction: Literal['LR', 'RL', 'TB', 'TD', 'BT'] = 'TD', title: str | bool | None = True, format: Literal['svg', 'pdf', 'png'] | None = None, mmdc_options: dict | None = None, add_self: bool = True, unique_nodes: bool = True, headers: Iterable[str] | None = None, root_shape: str | None = None, node_mapper: str | Callable[[Node], str] | None = None, edge_mapper: Callable[[int, Node, int, Node], str] | str | None = None) None[source]

Serialize a Mermaid flowchart representation.

Optionally convert to a Graphviz display formats. See Graphs for details.

to_rdf_graph(*, add_self: bool = True, node_mapper: Callable[[None, None, Node], None | bool] | None = None)[source]

Return an instance of rdflib.Graph.

See Graphs for details.

property tree: Tree[Self]

Return container Tree instance.

up(level: int = 1) Self[source]

Return ancestor node.

Unlike parent(), this method returns the system root node for toplevel nodes.

One use case is method chaining when creating trees:

tree = Tree().add("n1").add("child1").up().add("child2").up(2).add("n2")
update_meta(values: dict, *, replace: bool = False) None[source]

Add values dict to current metadata.

If replace is true, previous metatdata will be cleared.

visit(callback: Callable[[Node, Any], None | bool | SkipBranch | StopTraversal | type[SkipBranch] | type[StopTraversal] | type[StopIteration]], *, add_self=False, method: IterMethod = IterMethod.PRE_ORDER, memo: Any | None = None) None | Any[source]

Call callback(node, memo) for all subnodes.

The callback may return SkipBranch (or an instance thereof) to omit child nodes but continue traversal otherwise. Raising SkipBranch has the same effect.

The callback may return False or StopIteration to immediately interrupt traversal. Raising StopTraversal(value) has the same effect but also allows to specify a return value for the visit method.
See also Iteration Callbacks.

Parameters:
  • callback (function(node, memo)) – Callback function(node, memo)

  • add_self (bool) – If true, this node will also be visited (typically as first call).

  • method (IterMethod) – Traversal method, defaults to pre-order, depth-first search.

  • memo (Any) – This value will be passed to all calls and may be useful to implement caching or collect and return traversal results. If no memo argument is passed, an empty dict is created at start, which has a life-span of the traversal only.

nutree.typed_tree module

Declare the TypedTree class.

final class ANY_KIND[source]

Bases: object

Special argument value for some methods that access child nodes.

class TypedNode(kind: str, data: TData, *, parent: Self, data_id: str | int | None = None, node_id: int | None = None, meta: dict | None = None)[source]

Bases: Node[TData]

A special node variant, derived from Node and used by TypedTree.

In addition to Node, we have a kind member to define the node’s type.

DEFAULT_RENDER_REPR = '{node.kind} {node.data}'

Default value for repr argument when formatting data for print/display.

__eq__(other: Any) bool

Implement node == other syntax to compare embedded data.

If other is a Node instance, self.data == other.data is evaluated. Otherwise self.data == other is compared.

Use node is other syntax instead to check if two nodes are truly identical.

__getattr__(name: str) Any

Implement node.NAME aliasing to node.data.NAME.

See Forward Attributes (Attribute Aliasing).

__iter__(method: IterMethod = IterMethod.PRE_ORDER, *, add_self=False) Iterator[Self]

Generator that walks the hierarchy.

add(child: Self | TypedTree | TData, *, kind: str | None, before: Self | bool | int | None = None, deep: bool | None = None, data_id: str | int | None = None, node_id: int | None = None) Self[source]

Alias for add_child()).

add_child(child: Self | TypedTree | TData, *, kind: str | None, before: Self | bool | int | None = None, deep: bool | None = None, data_id: str | int | None = None, node_id: int | None = None) Self[source]

See …

Parameters:

kind – the type of the new child node. Pass None to use the same type as child (if that is a node) or default to “child”.

See also add_child() method for details.

append_child(child: Self | TypedTree | TData, *, kind: str | None, deep: bool | None = None, data_id: str | int | None = None, node_id: int | None = None)[source]

Append a new subnode.

This is a shortcut for add_child() with before=None.

append_sibling(child: Self | TypedTree | TData, *, kind: str | None, deep: bool | None = None, data_id: str | int | None = None, node_id: int | None = None) Self[source]

Add a new node of same kind after self.

This method calls add_child() on self.parent.

calc_depth() int

Return the distance to the root node (1 for toplevel nodes).

calc_height() int

Return the maximum depth of all descendants (0 for leaves).

property children: list[Self]

Return list of direct child nodes (list may be empty).

clear_meta(key: str | None = None) None

Reset all metadata or a distinct entry.

copy(*, add_self=True, predicate: Callable[[Node], None | bool | IterationControl | type[IterationControl]] | None = None) TypedTree[TData][source]

Return a new Tree instance from this branch.

See also Iteration Callbacks.

copy_to(target: Self | Tree[TData, Self], *, add_self=True, before: Self | bool | int | None = None, deep: bool = False) Self

Copy this node to another parent and return the new node.

If add_self is set, a copy of this node becomes a child of target. Otherwise copies of all children of this node are created below target.

By default new nodes are appended to existing children. The before argument defines an alternative positioning. It is only available when add_self is true. See add_child() for a description of before.

If deep is set, all descendants are copied recursively.

count_descendants(*, leaves_only=False, kind: str | type[~nutree.typed_tree.ANY_KIND] = <class 'nutree.typed_tree.ANY_KIND'>) int[source]

Return number of descendant nodes, not counting self.

property data: TData

Return the wrapped data instance (use set_data() to modify).

property data_id: str | int

Return the wrapped data instance’s id (use set_data() to modify).

depth() int

Return the distance to the root node (1 for toplevel nodes).

filter(predicate: Callable[[Node], None | bool | IterationControl | type[IterationControl]]) None

In-place removal of mismatching nodes.

See also Iteration Callbacks.

filtered(predicate: PredicateCallbackType) Tree[TData, Self]

Return a filtered copy of this node and descendants as tree.

See also Iteration Callbacks.

find(data=None, *, match: str | Callable[[Node], None | bool | IterationControl | type[IterationControl]] | list | tuple | Any | None = None, data_id: str | int | None = None) Self | None

Return the first matching node or None.

See also Iteration Callbacks.

find_all(data=None, *, match: str | Callable[[Node], None | bool | IterationControl | type[IterationControl]] | list | tuple | Any | None = None, data_id: str | int | None = None, add_self=False, max_results: int | None = None) list[Self]

Return a list of matching nodes (list may be empty).

See also Iteration Callbacks.

find_first(data=None, *, match: str | Callable[[Node], None | bool | IterationControl | type[IterationControl]] | list | tuple | Any | None = None, data_id: str | int | None = None) Self | None

Return the first matching node or None.

See also Iteration Callbacks.

first_child(kind: str | type[ANY_KIND]) Self | None[source]

First direct child node or None if no children exist.

first_sibling(*, any_kind=False) Self[source]

Return first sibling of the same kind (may be self).

format(*, repr: str | Callable[[Node], str] | None = None, style: str | None = None, add_self=True, join: str = '\n') str

Return a pretty string representation of the node hierarchy.

more

Parameters:
  • repr (str) – A string or callback that defines how the node is rendered after the connector prefixes are generated.

  • style (str) – A string that defines the connector type, e.g. “round42” will produce “│ “, “╰─”, “├─”.

  • add_self (bool) – If false, only the descendants of this node are formatted.

  • join (str) – A string that is used to terminate the single lines. Defaults to “n”, but may be set to “, “ together with style=”list” to create a single line output.

Example

print(node.format(repr=”{node.name}”, style=”round42”))

format_iter(*, repr: str | Callable[[Node], str] | None = None, style: str | None = None, add_self=True) Iterator[str]

This variant of format() returns a line generator.

from_dict(obj: list[dict], *, mapper: Callable[[Node, dict], str | object] | None = None) None

Append copies of all source children to self.

get_children(kind: str | type[ANY_KIND]) list[Self][source]

Return list of direct child nodes of a given type (list may be empty).

get_clones(*, add_self=False) list[Self]

Return a list of all nodes that reference the same data if any.

get_common_ancestor(other: Self) Self | None

Return the nearest node that contains self and other (may be None).

get_index(*, any_kind=False) int[source]

Return index in sibling list.

get_meta(key: str, default=None) Any

Return metadata value.

get_parent_list(*, add_self=False, bottom_up=False) list[Self]

Return ordered list of all parent nodes.

get_path(*, add_self: bool = True, separator: str = '/', repr: str = '{node.name}') str

Return a breadcrumb string, e.g. ‘/A/a1/a12’.

get_siblings(*, add_self=False, any_kind=False) list[Self][source]

Return a list of all sibling entries of self (excluding self) if any.

get_top() Self

Return toplevel ancestor (may be self).

has_children(kind: str | type[ANY_KIND]) bool[source]

Return true if this node has one or more children.

is_ancestor_of(other: Self) bool

Return true if this node is a parent, grandparent, … of other.

is_clone() bool

Return true if this node’s data is referenced at least one more time.

is_descendant_of(other: Self) bool

Return true if this node is direct or indirect child of other.

is_first_sibling(*, any_kind=False) bool[source]

Return true if this node is the first sibling, i.e. the first child of its parent.

is_last_sibling(*, any_kind=False) bool[source]

Return true if this node is the last sibling, i.e. the last child of this kind of its parent.

is_leaf() bool

Return true if this node is an end node, i.e. has no children.

is_system_root() bool

Return true if this node is the invisible system root _SystemRootNode.

is_top() bool

Return true if this node has no parent.

iterator(method: ~nutree.common.IterMethod = IterMethod.PRE_ORDER, *, add_self=False, kind: str | type[~nutree.typed_tree.ANY_KIND] = <class 'nutree.typed_tree.ANY_KIND'>) Iterator[TypedNode[TData]][source]

Return an iterator that walks the tree in the specified order.

property kind: str
last_child(kind: str | type[ANY_KIND]) Self | None[source]

Last direct child node or None if no children exist.

last_sibling(*, any_kind=False) Self[source]

Return last sibling of the same kind (may be self).

property meta: dict | None

Return the node’s metadata dictionary or None if empty.

See also get_meta(), set_meta(), update_meta(), clear_meta().

move_to(new_parent: Self | Tree[TData, Self], *, before: Self | bool | int | None = None)

Move this node to another parent.

By default, the node is appended to existing children. See add_child() for a description of before.

property name: str

String representation of the embedded data object.

next_sibling(*, any_kind=False) Self | None[source]

Return successor of the same kind or None if node is last sibling.

property node_id: int

Return the node’s unique key.

property parent: Self | None

Return parent node or None for toplevel nodes.

See also up().

property path: str

All ancestor names including self, starting with and separated by ‘/’.

prepend_child(child: Self | TypedTree | TData, *, kind: str | None, deep: bool | None = None, data_id: str | int | None = None, node_id: int | None = None)[source]

Prepend a new subnode.

This is a shortcut for add_child() with before=True.

prepend_sibling(child: Self | TypedTree | TData, *, kind: str | None, deep=None, data_id=None, node_id=None) Self[source]

Add a new node of same kind before self.

This method calls add_child() on self.parent.

prev_sibling(*, any_kind=False) Self | None[source]

Return predecessor of the same kind or None if node is first sibling.

remove(*, keep_children=False, with_clones=False) None

Remove this node.

If keep_children is true, all children will be moved one level up, so they become siblings, before this node is removed.

If with_clones is true, all nodes that reference the same data instance are removed as well.

remove_children() None

Remove all children of this node, making it a leaf node.

rename(new_name: str) None

Set self.data to a new string (assuming plain string node).

set_data(data, *, data_id: str | int | None = None, with_clones: bool | None = None) None

Change node’s data and/or data_id and update bookkeeping.

set_meta(key: str, value) None

Set metadata value (pass value None to remove).

sort_children(*, key: Callable[[Node], Any] | None = None, reverse=False, deep=False) None

Sort child nodes.

key defaults to attrgetter("name"), so children are sorted by their string representation.

to_dict(*, mapper: Callable[[Node, dict], None | dict] | None = None) dict

Return a nested dict of this node and its children.

to_dot(*, add_self=False, unique_nodes=True, graph_attrs: dict | None = None, node_attrs: dict | None = None, edge_attrs: dict | None = None, node_mapper: Callable[[Node, dict], None | Any] | None = None, edge_mapper: Callable[[Node, dict], None | Any] | None = None) Iterator[str][source]

Generate a DOT formatted graph representation.

See Graphs for details.

to_list_iter(*, mapper: Callable[[Node, dict], None | dict] | None = None, key_map: dict[str, str] | None = None, value_map: dict[str, list[str]] | None = None) Iterator[tuple[str | int, dict[str, str | int | float | bool | None] | str | int]]

Yield children as parent-referencing list.

`py [(parent_key, data)] `

to_mermaid_flowchart(target: IO[str] | str | Path, *, as_markdown: bool = True, direction: Literal['LR', 'RL', 'TB', 'TD', 'BT'] = 'TD', title: str | bool | None = True, format: Literal['svg', 'pdf', 'png'] | None = None, mmdc_options: dict | None = None, add_self: bool = True, unique_nodes: bool = True, headers: Iterable[str] | None = None, root_shape: str | None = None, node_mapper: str | Callable[[Node], str] | None = None, edge_mapper: Callable[[int, Node, int, Node], str] | str | None = None) None

Serialize a Mermaid flowchart representation.

Optionally convert to a Graphviz display formats. See Graphs for details.

to_rdf_graph(*, add_self: bool = True, node_mapper: Callable[[None, None, Node], None | bool] | None = None)

Return an instance of rdflib.Graph.

See Graphs for details.

property tree: Tree[Self]

Return container Tree instance.

up(level: int = 1) Self

Return ancestor node.

Unlike parent(), this method returns the system root node for toplevel nodes.

One use case is method chaining when creating trees:

tree = Tree().add("n1").add("child1").up().add("child2").up(2).add("n2")
update_meta(values: dict, *, replace: bool = False) None

Add values dict to current metadata.

If replace is true, previous metatdata will be cleared.

visit(callback: Callable[[Node, Any], None | bool | SkipBranch | StopTraversal | type[SkipBranch] | type[StopTraversal] | type[StopIteration]], *, add_self=False, method: IterMethod = IterMethod.PRE_ORDER, memo: Any | None = None) None | Any

Call callback(node, memo) for all subnodes.

The callback may return SkipBranch (or an instance thereof) to omit child nodes but continue traversal otherwise. Raising SkipBranch has the same effect.

The callback may return False or StopIteration to immediately interrupt traversal. Raising StopTraversal(value) has the same effect but also allows to specify a return value for the visit method.
See also Iteration Callbacks.

Parameters:
  • callback (function(node, memo)) – Callback function(node, memo)

  • add_self (bool) – If true, this node will also be visited (typically as first call).

  • method (IterMethod) – Traversal method, defaults to pre-order, depth-first search.

  • memo (Any) – This value will be passed to all calls and may be useful to implement caching or collect and return traversal results. If no memo argument is passed, an empty dict is created at start, which has a life-span of the traversal only.

class TypedTree(name: str | None = None, *, calc_data_id: Callable[[Tree, Any], str | int] | None = None, forward_attrs: bool = False)[source]

Bases: Tree[TData, TypedNode[TData]]

A special tree variant, derived from Tree, that uses TypedNode objects, which maintain an addition kind attribute.

See Typed Tree for details.

DEFAULT_CHILD_TYPE = 'child'

Default value for add_child when loading.

DEFAULT_CONNECTOR_STYLE = 'round43'

Default connector prefixes format(style=...) argument.

DEFAULT_KEY_MAP: dict[str, str] = {'data_id': 'i', 'kind': 'k', 'str': 's'}

Default value for key_map argument when saving

DEFAULT_VALUE_MAP: dict[str, list[str]] = {}

Default value for value_map argument when saving

__contains__(data)

Implement data in tree syntax to check for node existence.

__delitem__(data)

Implement del tree[data] syntax to remove nodes.

__enter__()

Implement with tree: ... syntax to acquire an RLock.

__getitem__(data: object) TNode

Implement tree[data] syntax to lookup a node.

data may be a plain string, data object, data_id, or node_id.

Note: This is a flexible and concise way to access tree nodes. However, find_all() or find_first() may be faster.

AmbiguousMatchError is raised if multiple matches are found. Use find_all() or find_first() instead to resolve this.

__iter__(method: IterMethod = IterMethod.PRE_ORDER) Iterator[TNode]

Traverse tree structure and yield nodes.

See Node’s iterator() method for details.

__len__()

Make len(tree) return the number of nodes (also makes empty trees falsy).

add(child: TypedNode[TData] | Self | TData, *, kind: str | None, before: TypedNode[TData] | bool | int | None = None, deep: bool | None = None, data_id: str | int | None = None, node_id: int | None = None) TypedNode[TData][source]

Alias for shortcut add_child()).

See Node’s add_child() method for details.

add_child(child: TypedNode[TData] | Self | TData, *, kind: str | None, before: TypedNode[TData] | bool | int | None = None, deep: bool | None = None, data_id: str | int | None = None, node_id: int | None = None) TypedNode[TData][source]

Add a toplevel node (same as shortcut add()).

See Node’s add_child() method for details.

classmethod build_random_tree(structure_def: dict) Self

Build a random tree for .

Returns a new Tree instance with random nodes, as defined by structure_def. If called like TypedTree.build_random_tree(structure_def), this method will return a TypedTree instance.

See Generate Random Trees for details.

calc_data_id(data: Any) str | int

Called internally to calculate data_id for a data object.

This value is used to lookup nodes by data, identify clones, and for (de)serialization. It defaults to hash(data) but may be overloaded when the data objects have meaningful keys that should be used instead.

Note: By default, the __hash__() values of str and bytes objects are ‘salted’ with an unpredictable random value. Although they remain constant within an individual Python process, they are not predictable between repeated invocations of Python.

calc_height() int

Return the maximum depth of all nodes.

property children: list[TNode]

Return list of direct child nodes, i.e. toplevel nodes (list may be empty).

clear() None

Remove all nodes from this tree.

copy(*, name: str | None = None, predicate: Callable[[Node], None | bool | IterationControl | type[IterationControl]] | None = None) Self

Return a copy of this tree.

New Tree and Node instances are created. The new nodes reference the original data objects.

predicate may be passed to filter the result, which is equivalent to calling filtered()

See Node’s copy_to() and Iteration Callbacks method for details.

copy_to(target: TNode | Self, *, deep=True) None

Copy this tree’s nodes to another target.

See Node’s copy_to() method for details.

property count: int

Return the total number of nodes.

count_descendants(*, leaves_only=False, kind: str | type[~nutree.typed_tree.ANY_KIND] = <class 'nutree.typed_tree.ANY_KIND'>) int[source]

Return number of nodes, optionally restricted to type.

property count_unique: int

Return the total number of unique nodes.

Multiple references to the same data object (‘clones’) are only counted once. This is different from count(), which returns the number of all nodes.

classmethod deserialize_mapper(parent: Node, data: dict) str | object | None[source]

Used as default mapper argument for load().

diff(other: Self, *, compare: Callable[[Node, Node, Node], bool | Any] | bool = True, ordered=False, reduce=False) Tree

Compare this tree against other and return a merged, annotated copy.

The resulting tree contains a union of all nodes from this and the other tree. Additional metadata is added to the resulting nodes to classify changes from the perspective of this tree. For example a node that only exists in other, will have node.get_meta("dc") == DiffClassification.ADDED defined.

The compare callback can be used to customize the comparison of nodes It should return True if the nodes are considered equal, False otherwise.

If ordered is true, changes in the child order are also considered a change.
If reduce is true, unchanged nodes are removed, leaving a compact tree with only the modifications.

See Diff and Merge for details.

filter(predicate: Callable[[Node], None | bool | IterationControl | type[IterationControl]]) None

In-place removal of unmatching nodes.

See also Iteration Callbacks.

filtered(predicate: Callable[[Node], None | bool | IterationControl | type[IterationControl]]) Self

Return a filtered copy of this tree.

See also Iteration Callbacks.

find(data=None, *, match: str | Callable[[Node], None | bool | IterationControl | type[IterationControl]] | list | tuple | Any | None = None, data_id: str | int | None = None, node_id: int | None = None) TNode | None

Return the first matching node or None.

Note that ‘first’ sometimes means ‘one arbitrary’ matching node, which is not neccessarily the first of a specific iteration method. See also Node’s find_first() method and Iteration Callbacks.

find_all(data=None, *, match: str | Callable[[Node], None | bool | IterationControl | type[IterationControl]] | list | tuple | Any | None = None, data_id: str | int | None = None, max_results: int | None = None) list[TNode]

Return a list of matching nodes (list may be empty).

See also Node’s find_all() method and Iteration Callbacks.

find_first(data=None, *, match: str | Callable[[Node], None | bool | IterationControl | type[IterationControl]] | list | tuple | Any | None = None, data_id: str | int | None = None, node_id: int | None = None) TNode | None

Return the first matching node or None.

Note that ‘first’ sometimes means ‘one arbitrary’ matching node, which is not neccessarily the first of a specific iteration method. See also Node’s find_first() method and Iteration Callbacks.

first_child(kind: str | type[ANY_KIND]) TypedNode[TData] | None[source]

Return the first toplevel node.

format(*, repr: str | Callable[[Node], str] | None = None, style: str | None = None, title: str | bool | None = None, join: str = '\n') str

Return a pretty string representation of the tree hierarchy.

See Node’s format() method for details.

format_iter(*, repr: str | Callable[[Node], str] | None = None, style=None, title=None) Iterator[str]

This variant of format() returns a line generator.

classmethod from_dict(obj: list[dict], *, mapper=None) Self

Return a new Tree instance from a list of dicts.

See also to_dict_list() and Node’s find_first() methods, and Iteration Callbacks.

get_random_node() TNode

Return a random node.

Note that there is also IterMethod.RANDOM_ORDER.

get_toplevel_nodes() list[TNode]

Return list of direct child nodes, i.e. toplevel nodes (may be empty, alias for children()).

iter_by_type(kind: str | type[ANY_KIND]) Iterator[TypedNode[TData]][source]

@deprecated: Use iterator() with kind argument instead.

iterator(method: ~nutree.common.IterMethod = IterMethod.PRE_ORDER, *, kind: str | type[~nutree.typed_tree.ANY_KIND] = <class 'nutree.typed_tree.ANY_KIND'>) Iterator[TypedNode[TData]][source]

Traverse tree structure and yield nodes.

See Node’s iterator() method for details.

last_child(kind: str | type[ANY_KIND]) TypedNode[TData] | None[source]

Return the last toplevel node.

classmethod load(target: IO[str] | str | Path, *, mapper: Callable[[Node, dict], str | object] | None = None, file_meta: dict | None = None) Self[source]

Create a new TypedTree instance from a JSON file stream.

See also Tree’s save() and load() methods.

name: str

Tree name used for logging

node_factory

alias of TypedNode

print(*, repr: str | Callable[[Node], str] | None = None, style: str | None = None, title: str | bool | None = None, join: str = '\n', file: IO[str] | None = None) None

Convenience method that simply runs print(self. format()).

root_node_factory

alias of _SystemRootTypedNode

save(target: IO[str] | str | Path, *, mapper: Callable[[Node, dict], None | dict] | None = None, meta: dict | None = None, key_map: dict[str, str] | bool = True, value_map: dict[str, list[str]] | bool = True) None[source]

Store tree in a compact JSON file stream.

See also (De)Serialize and to_list_iter() and load() methods.

classmethod serialize_mapper(node: Node, data: dict) dict | None

Used as default mapper argument for save().

sort(*, key: Callable[[Node], Any] | None = None, reverse=False, deep=True) None

Sort toplevel nodes (optionally recursively).

key defaults to attrgetter("name"), so children are sorted by their string representation.

property system_root: TNode
to_dict_list(*, mapper: Callable[[Node, dict], None | dict] | None = None) list[dict]

Call Node’s to_dict() method for all child nodes and return list of results.

to_dot(*, add_root=True, unique_nodes=True, graph_attrs: dict | None = None, node_attrs: dict | None = None, edge_attrs: dict | None = None, node_mapper: Callable[[Node, dict], None | Any] | None = None, edge_mapper: Callable[[Node, dict], None | Any] | None = None) Iterator[str]

Generate a DOT formatted graph representation.

See Node’s to_dot() method for details.

to_dotfile(target: IO[str] | str | Path, *, format=None, add_root=True, unique_nodes=True, graph_attrs=None, node_attrs=None, edge_attrs=None, node_mapper=None, edge_mapper=None)

Serialize a DOT formatted graph representation.

Optionally convert to a Graphviz display formats. See Graphs for details.

to_list_iter(*, mapper: Callable[[Node, dict], None | dict] | None = None, key_map: dict[str, str] | None = None, value_map: dict[str, list[str]] | None = None) Iterator[tuple[str | int, dict[str, str | int | float | bool | None] | str | int]]

Yield a parent-referencing list of child nodes.

to_mermaid_flowchart(target: IO[str] | str | Path, *, as_markdown: bool = True, direction: Literal['LR', 'RL', 'TB', 'TD', 'BT'] = 'TD', title: str | bool | None = True, format: Literal['svg', 'pdf', 'png'] | None = None, mmdc_options: dict | None = None, add_root: bool = True, unique_nodes: bool = True, headers: Iterable[str] | None = None, root_shape: str | None = None, node_mapper: str | Callable[[Node], str] | None = None, edge_mapper: Callable[[int, Node, int, Node], str] | str | None = None)

Serialize a Mermaid flowchart representation.

Optionally convert to a Graphviz display formats. See Graphs for details.

to_rdf_graph()

Return an instance of rdflib.Graph.

See Graphs for details.

visit(callback: Callable[[Node, Any], None | bool | SkipBranch | StopTraversal | type[SkipBranch] | type[StopTraversal] | type[StopIteration]], *, method: IterMethod = IterMethod.PRE_ORDER, memo: Any = None) Any | None

Call callback(node, memo) for all nodes.

See Node’s visit() method and Iteration Callbacks for details.

nutree.common module

Functions and declarations used by the nutree.tree and nutree.node modules.

exception AmbiguousMatchError[source]

Bases: TreeError

Thrown when a single-value lookup found multiple matches.

add_note()

Exception.add_note(note) – add a note to the exception

args
CONNECTORS = {'ascii11': (' ', '|', '`', '-'), 'ascii21': ('  ', '| ', '` ', '- '), 'ascii22': ('  ', '| ', '`-', '+-'), 'ascii32': ('   ', '|  ', '`- ', '+- '), 'ascii42': ('    ', ' |  ', ' `- ', ' +- '), 'ascii43': ('    ', '|   ', '`-- ', '+-- '), 'lines11': (' ', '│', '└', '├'), 'lines21': ('  ', '│ ', '└ ', '├ '), 'lines22': ('  ', '│ ', '└─', '├─'), 'lines32': ('   ', '│  ', '└─ ', '├─ '), 'lines32c': (' ', '│', '└─ ', '├─ ', '└┬ ', '├┬ '), 'lines42': ('    ', '   ', ' └─ ', ' ├─ '), 'lines43': ('    ', '│   ', '└── ', '├── '), 'lines43c': ('  ', '│ ', '└── ', '├── ', '└─┬ ', '├─┬ '), 'lines43r': ('    ', '   ', ' └──', ' ├──'), 'round11': (' ', '│', '╰', '├'), 'round21': ('  ', '│ ', '╰ ', '├ '), 'round22': ('  ', '│ ', '╰─', '├─'), 'round32': ('   ', '│  ', '╰─ ', '├─ '), 'round32c': (' ', '│', '╰─ ', '├─ ', '╰┬ ', '├┬ '), 'round42': ('    ', '   ', ' ╰─ ', ' ├─ '), 'round43': ('    ', '│   ', '╰── ', '├── '), 'round43c': ('  ', '│ ', '╰── ', '├── ', '╰─┬ ', '├─┬ '), 'round43r': ('    ', '   ', ' ╰──', ' ├──'), 'space1': (' ', ' ', ' ', ' '), 'space2': ('  ', '  ', '  ', '  '), 'space3': ('   ', '   ', '   ', '   '), 'space4': ('    ', ' |  ', '    ', '    ')}

Node connector prefixes, for use with format(style=...) argument.

CalcIdCallbackType

Type of Tree(..., calc_data_id)`

alias of Callable[[Tree, Any], str | int]

DataIdType

Type of Node.data_id

alias of str | int

DeserializeMapperType

Callback for tree.load()

alias of Callable[[Node, dict], str | object]

class DictWrapper(dict_inst: dict | None = None, **values)[source]

Bases: object

Wrap a Python dict so it can be added to the tree.

Makes the dict hashable and comparable with ==, so it can be used added to the tree and can be checked for modifications during tree diffing.

Initialized with a dictionary of values. The values can be accessed via the node.data attribute like node.data[“KEY”].

See Dictionaries (DictWrapper) for details.

__getitem__(key)[source]

Allow to access values as items.

E.g. foo = node.data["foo"] instead of `` foo = node.data._dict[“foo”]``.

__setitem__(key, value)[source]

Allow to access values as items.

Example:

`node.data["foo"] = 1` instead of `node.data._dict["foo"] = 1`.
classmethod deserialize_mapper(nutree_node: Node, data: dict) str | object[source]

Serialize the data object to a dictionary.

Example:

tree = Tree.load(file_path, mapper=DictWrapper.deserialize_mapper)
classmethod serialize_mapper(nutree_node: Node, data: dict) None | dict[source]

Serialize the data object to a dictionary.

Example:

tree.save(file_path, mapper=DictWrapper.serialize_mapper)
FILE_FORMAT_VERSION: str = '1.0'

File format version used by tree.save() as meta.$format_version

FlatJsonDictType

A dict of scalar values

alias of dict[str, str | int | float | bool | None]

class IterMethod(value, names=<not given>, *values, module=None, qualname=None, type=None, start=1, boundary=None)[source]

Bases: Enum

Traversal order.

LEVEL_ORDER = 'level'

Breadth-first (aka level-order)

LEVEL_ORDER_RTL = 'level_rtl'

Breadth-first (aka level-order) right-to-left

POST_ORDER = 'post'

Depth-first, post-order

PRE_ORDER = 'pre'

Depth-first, pre-order

RANDOM_ORDER = 'random'

Random order traversal

UNORDERED = 'unordered'

Fastest traversal in unpredictable order. It may appear to be the order of node insertion, but do not rely on this!

ZIGZAG = 'zigzag'

ZigZag order

ZIGZAG_RTL = 'zigzag_rtl'

ZigZag order

classmethod __contains__(value)

Return True if value is in cls.

value is in cls if: 1) value is a member of cls, or 2) value is the value of one of the cls’s members.

classmethod __getitem__(name)

Return the member matching name.

classmethod __iter__()

Return members in definition order.

classmethod __len__()

Return the number of members (no aliases)

exception IterationControl[source]

Bases: Exception

Common base class for tree iteration controls.

add_note()

Exception.add_note(note) – add a note to the exception

args
KeyMapType

Type of tree.save(..., key_map)

alias of dict[str, str]

MapperCallbackType

Generic callback for tree.to_dot(), …

alias of Callable[[Node, dict], None | Any]

MatchArgumentType

alias of str | Callable[[Node], None | bool | IterationControl | type[IterationControl]] | list | tuple | Any

PYTHON_VERSION = '3.12.7'

Currently used Python version as string

PredicateCallbackType

Generic callback for tree.filter(), tree.copy(), …

alias of Callable[[Node], None | bool | IterationControl | type[IterationControl]]

ROOT_DATA_ID: str = '__root__'

Used as ID for the system root node

ReprArgType

Type of format(..., repr=)`

alias of str | Callable[[Node], str]

exception SelectBranch[source]

Bases: IterationControl

Raised or returned by traversal callbacks to unconditionally accept all descendants.

add_note()

Exception.add_note(note) – add a note to the exception

args
SerializeMapperType

Callback for tree.save()

alias of Callable[[Node, dict], None | dict]

exception SkipBranch(*, and_self=None)[source]

Bases: IterationControl

Raised or returned by traversal callbacks to skip the current node’s descendants.

If and_self is true, some iterators will consider the node itself, but still skip the descendants. For example copy() and find_all(). If and_self is false, some iterators will consider the node’s children only.

add_note()

Exception.add_note(note) – add a note to the exception

args
SortKeyType

Callback for tree.sort(key=…)

alias of Callable[[Node], Any]

exception StopTraversal(value=None)[source]

Bases: IterationControl

Raised or returned by traversal callbacks to stop iteration.

Optionally, a return value may be passed. Note that if a callback returns False, this will be converted to a StopTraversal(None) exception.

add_note()

Exception.add_note(note) – add a note to the exception

args
TraversalCallbackType

alias of Callable[[Node, Any], None | bool | SkipBranch | StopTraversal | type[SkipBranch] | type[StopTraversal] | type[StopIteration]]

exception TreeError[source]

Bases: RuntimeError

Base class for all nutree errors.

add_note()

Exception.add_note(note) – add a note to the exception

args
exception UniqueConstraintError[source]

Bases: TreeError

Thrown when trying to add the same node_id to the same parent

add_note()

Exception.add_note(note) – add a note to the exception

args
ValueDictMapType

0, ‘dept’: 1}}`

Type:

E.g. `{‘t’

Type:

{‘person’

alias of dict[str, dict[str, int]]

ValueMapType

Type of tree.save(..., value_map) E.g. {‘t’: [‘person’, ‘dept’]}

alias of dict[str, list[str]]

call_mapper(fn: MapperCallbackType | None, node: Node, data: dict) Any[source]

Call the function and normalize result and exceptions.

Handles MapperCallbackType: Call fn(node, data) if defined and return the result. If fn is undefined or returns None, return data.

call_predicate(fn: Callable, node: Node) IterationControl | None | Any[source]

Call the function and normalize result and exceptions.

Handles PredicateCallbackType: Call fn(node) and converts all raised IterationControl responses to a canonical result.

call_traversal_cb(fn: TraversalCallbackType, node: Node, memo: Any) Literal[False] | None[source]

Call the function and handle result and exceptions.

This method calls fn(node, memo) and converts all returned or raised IterationControl responses to a canonical result:

Handles TraversalCallbackType

  • Return False if the method returns SkipBranch or an instance of SkipBranch.

  • Raise StopTraversal(value) if the method returns False, StopTraversal, or an instance of StopTraversal.

  • If a form of StopIteration is returned, we treat as StopTraversal, but emit a warning.

  • Other return values are ignored and converted to None.

check_python_version(min_version: tuple[str | int, str | int]) bool[source]

Check for deprecated Python version.

get_version() str[source]
open_as_compressed_output_stream(path: str | Path, *, compression: bool | int = True, encoding: str = 'utf8') Iterator[IO[str]][source]

Open a file for writing, ZIP-compressing if requested.

Example:

with open_as_compressed_stream("/path/to/foo.nutree") as fp:
    fp:
        print(line)
open_as_uncompressed_input_stream(path: str | Path, *, encoding: str = 'utf8', auto_uncompress: bool = True) Iterator[IO[str]][source]

Open a file for reading, decompressing if necessary.

Decompression is done by checking for the magic header (independent of the file extension).

Example:

with open_as_uncompressed_stream("/path/to/foo.nutree") as fp:
    for line in fp:
        print(line)

nutree.tree_generator module

Implements a generator that creates a random tree structure from a specification.

See Generate Random Trees for details.

class BlindTextRandomizer(*, sentence_count: int | tuple = (2, 6), dialect: str = 'ipsum', entropy: int = 2, keep_first: bool = False, words_per_sentence: int | tuple = (3, 15), probability: float = 1.0)[source]

Bases: Randomizer

A randomizer class that generates a random lorem ipsum text value from a template.

Uses the [fabulist](https://github.com/mar10/fabulist/) library to generate text values.

Parameters:
  • sentence_count (int | tuple, optional) – The number of sentences to generate. Defaults to (2, 6).

  • dialect (str, optional) – The dialect of the text. Defaults to “ipsum”.

  • entropy (int, optional) – The entropy of the text. Defaults to 2.

  • keep_first (bool, optional) – If True, keep the first sentence. Defaults to False.

  • words_per_sentence (int | tuple, optional) – The number of words per sentence. Defaults to (3, 15).

  • probability (float, optional) – The probability of generating a value. Defaults to 1.0.

generate() Any[source]
class DateRangeRandomizer(min_dt: date, max_dt: date | int, *, as_js_stamp=True, probability: float = 1.0)[source]

Bases: Randomizer

A randomizer class that generates random dates within a specified range.

Parameters:
  • min_dt (date) – The minimum date of the range.

  • max_dt (date | int) – The maximum date of the range. Pass an integer to specify the number of days from min_dt.

  • as_js_stamp (bool, optional) – If True, return the date as a JavaScript timestamp. Defaults to True.

  • probability (float, optional) – The probability of generating a value. Defaults to 1.0.

Examples

>>> DateRangeRandomizer(date(2020, 1, 1), date(2020, 12, 31)).generate()
datetime.date(2020, 3, 7)
>>> DateRangeRandomizer(date(2020, 1, 1), 365).generate()
generate() date | float | None[source]
class Randomizer(*, probability: float = 1.0)[source]

Bases: ABC

Abstract base class for randomizers.

Parameters:

probability (float, optional) – The probability of using the randomizer. Must be in the range [0.0, 1.0]. Defaults to 1.0.

abstract generate() Any[source]
class RangeRandomizer(min_val: float | int, max_val: float | int, *, probability: float = 1.0, none_value: Any = None)[source]

Bases: Randomizer

A randomizer class that generates random values within a specified range.

Parameters:
  • min_val (float| int) – The minimum value of the range.

  • max_val (float| int) – The maximum value of the range.

  • probability (float, optional) – The probability of generating a value. Defaults to 1.0.

  • none_value (Any, optional) – The value to return when skipping generation. Defaults to None.

Returns:

Union[float, int, None]

The generated random value, or none_value

if generation is skipped.

generate() float | int | Any | None[source]
class SampleRandomizer(sample_list: Sequence, *, counts=None, probability: float = 1.0)[source]

Bases: Randomizer

A randomizer class that generates a random value from a sample list.

generate() Any[source]
class SparseBoolRandomizer(*, probability: float)[source]

Bases: ValueRandomizer

A randomizer class that generates a boolean value with a given probability. If the value is False, it is returned as None.

generate() Any
class TextRandomizer(template: str | list[str], *, probability: float = 1.0)[source]

Bases: Randomizer

A randomizer class that generates a random string value from a Fabulist template.

Uses the [fabulist](https://github.com/mar10/fabulist/) library to generate text values.

Parameters:
  • template (str | list) – A template string or list of strings.

  • probability (float, optional) – The probability of generating a value. Defaults to 1.0.

generate() Any[source]
class ValueRandomizer(value: Any, *, probability: float)[source]

Bases: Randomizer

A randomizer class that generates a fixed value with a given probability.

Parameters:
  • value (Any) – The value to generate.

  • probability (float) – The probability of generating a value [0.0 .. 1.0].

generate() Any[source]
build_random_tree(*, tree_class: type[Tree[Any, Any]], structure_def: dict) Tree[source]

Return a nutree.TypedTree with random data from a specification. See Generate Random Trees for details.