API

Node classes

class littletree.BaseNode(identifier='node', children=(), parent=None)[source]

Bases: Generic[TIdentifier], MutableTree, TreeMixin

A basic tree node that can have a single parent and multiple children.

The BaseNode forms the foundation for building hierarchical tree structures. Each node can be uniquely identified by its name within its parent’s scope and can be navigated via NodePath objects.

Compared to Node this class is more basic and useful for subclassing.

Parameters:
  • identifier (TIdentifier)

  • children (Mapping[TIdentifier, TNode] | Iterable[TNode])

  • parent (TNode | None)

add_child(node, check_loop=True)[source]

Add a single child node.

The child’s parent will be set to this node. A DuplicateChildError is raised if another child with the same name already exists. A DuplicateParentError will be raised if this child already has a parent.

Parameters:
  • node (TNode) – Child to add.

  • check_loop (bool) – Whether to check if adding child results in a loop.

Returns:

property children: ValuesView[TNode]

Children of this node.

clear()[source]

Remove all children.

Return type:

None

copy(_memo=None, keep=None)[source]

Make a shallow copy or deepcopy if memo is passed.

Return type:

TNode

detach()[source]

Remove node from its parent.

This is especially useful when moving the node to a different tree or branch. :return: self

Return type:

TNode

dict_class

alias of dict

property identifier: Any

Key to identify this node. This can not be equal to an identifier of a sibling.

property is_leaf: bool

Whether this node is a leaf (does not have children).

iter_together(other)[source]

Yield all nodes in self with similar nodes in other.

If no equivalent node can be found in other, yield node from self with None

Return type:

Tuple[TNode, TNode | None]

property parent: TNode | None

Parent of this node or None.

property path: NodePath

Path object for access to parent or navigating forward.

pop(identifier)[source]

Remove and return node with identifier or None.

Parameters:

identifier (TIdentifier)

Return type:

TNode | None

remove_child(node)[source]

Remove node from children.

Parameters:

node (TNode)

property root: TNode

Root of tree.

sort_children(key=None, recursive=False, reverse=False)[source]

Sort children

Parameters:
  • key (Callable[[TNode], Any] | None) – Function to sort by. If not given, sort on identifier.

  • recursive (bool) – Whether all descendants should be sorted or just children.

  • reverse (bool) – Whether to sort in reverse order

Return type:

None

update(other, mode='copy', check_loop=True)[source]

Add multiple nodes at once.

This is faster than repeatedly calling setitem when adding many children at once.

About time complexity: Let n be the number of nodes added, d be the depth of the tree, C be copy time:

  • T(n) = O(nC + d) if check_loop and not consume;

  • T(n) = O(n + d) if check_loop and (consume or no child has a parent);

  • T(n) = O(nC) if not check_loop and not consume;

  • T(n) = O(n) if not check_loop and (consume or no child has a parent).

Parameters:
  • other (Mapping[TIdentifier, TNode] | Iterable[TNode] | TNode) –

    Source of other nodes. Other could be:

    • mapping Keys will become new identifiers

    • iterable Nodes will be added

    • node Same as self.update(other.children) but implemented more efficiently.

  • mode (str) –

    How to handle nodes that already have a parent:

    • ”copy”: These nodes will be copied and remain in old tree

    • ”detach”: These nodes will be detached from old tree

  • check_loop (bool) – If True, raises LoopError if a cycle is created.

Returns:

None

Return type:

None

class littletree.Node(data=MISSING, identifier=MISSING, children=(), parent=None)[source]

Bases: BaseNode[TIdentifier], Generic[TIdentifier, TData]

Parameters:
  • data (TData)

  • identifier (TIdentifier)

  • children (Mapping[TIdentifier, TNode] | Iterable[TNode])

  • parent (TNode | None)

compare(other, keep_equal=False)[source]

Compare two trees to one another.

If keep_equal is False (default), all nodes where data is equal will be removed.

>>> tree = Node('apples', identifier='fruit')
>>> other_tree = Node('oranges')
>>> tree.compare(other_tree)
Node({'self': 'apples', 'other': 'oranges'}, identifier='fruit)
Parameters:

other (TNode)

Return type:

TNode | None

copy(memo=None, *, keep=None, deep=False)[source]

Make a shallow copy or deepcopy if memo is passed.

Return type:

TNode

equals(other)[source]

Recursively check if two (sub)trees are the same.

Each node in the subtree must have the same identifier and same data.

Parameters:
  • self (TNode)

  • other (TNode)

Return type:

bool

classmethod from_dict(data, data_field='data', **kwargs)[source]

Import from nested dictionary.

Return type:

TNode

classmethod from_networkx(graph, **kwargs)[source]

Import from networkx graph.

classmethod from_newick(newick, root=None, data_field='data', **kwargs)[source]

Import from newick.

Return type:

TNode

classmethod from_relations(relations, root=None, data_field='data', **kwargs)[source]

Import from parent-child list.

Return type:

TNode

classmethod from_rows(rows, root=None, data_field='data', **kwargs)[source]

Import from list of path-rows.

Return type:

TNode

similar_to(other)[source]

Check if two trees are similar.

Trees are similar if they have the same structure and the same data.

Change from version 0.5.0: - Two trees can now be equal if the roots have a different identifier.

Parameters:
  • self (TNode)

  • other (TNode)

Return type:

bool

to_dict(data_field='data', **kwargs)[source]

Export to nested dictionary.

Return type:

Mapping

to_networkx(**kwargs)[source]

Export to networkx graph.

to_newick(file=None, data_field='data', **kwargs)[source]

Export to newick.

Return type:

str | None

to_relations(data_field='data', **kwargs)[source]

Export to parent-child list.

to_rows(data_field='data', **kwargs)[source]

Export to list of path-rows.

Return type:

Iterator[Mapping]

class littletree.TreeMixin[source]

Bases: Tree

plot(*args, **kwargs)[source]

Plot this tree using matplotlib.

show(*args, **kwargs)[source]

Print this tree. Shortcut for print(tree.to_string()).

to_dot(*args, **kwargs)[source]

Convert tree to dot file.

to_image(*args, **kwargs)[source]

Convert tree to image.

This return bytes. Use to_pillow for an Image abstraction.

to_latex(*args, **kwargs)[source]

Convert tree to latex. Requires the tikz-package if compiling the latex document.

to_mermaid(*args, **kwargs)[source]

Convert tree to mermaid file.

to_pillow(*args, **kwargs)[source]

Convert tree to Pillow / PIL image object.

to_string(*args, **kwargs)[source]

Convert tree to string.

class littletree.basenode.NodePath(node)[source]

Bases: PathView

Parameters:

node (T)

get(path)[source]

Like calling path, but return None if node is missing.

Return type:

TNode | None

create(path)[source]

Like get, but create missing nodes.

Return type:

TNode

glob(path)[source]

Find nodes by globbing patterns.

For example to find all nodes that start with ‘a’:

>>> node.path.glob("**/a*")
Return type:

Iterable[TNode]

Serializers

class littletree.serializers.DictSerializer(factory=None, identifier_name='identifier', children_name='children', fields=(), data_field=None)[source]

Bases: object

Serializer to/from a nested dictionary.

Parameters:
  • factory (Type[TNode])

  • identifier_name (TIdentifier)

  • children_name (str | None)

  • fields (Sequence[str])

  • data_field (str)

from_dict(data)[source]

Load tree from data

Parameters:

data (Mapping) – Dictionary in which tree is stored

Returns:

Root node of new tree

Return type:

TNode

to_dict(tree)[source]

Convert Node to a dictionary.

Parameters:

tree (TNode) – Node to convert

Returns:

Nested dictionary of node and children

Return type:

Mapping

class littletree.serializers.NetworkXSerializer(factory=None, fields=(), data_field=None)[source]

Bases: object

Serializer to/from a networkx graph.

Parameters:
  • factory (Callable[[], TNode])

  • fields (Sequence[str])

  • data_field (str)

class littletree.serializers.NewickSerializer(factory=None, fields=(), data_field=None, dialect=None, **kwargs)[source]

Bases: object

Serialize to/from the newick tree format. A formal description is here: http://biowiki.org/wiki/index.php/Newick_Format

A few dialects are supported (default: safe-nhx):

  • newick is the most basic dialect without extra features

  • nhx enables an extension called New Hampshire X format

    This extension is described here: https://www.cs.mcgill.ca/~birch/doc/forester/NHX.pdf

  • safe-nhx is similar to nhx, but xml-escaping is applied on reserved newick characters

Parameters:
  • factory (Callable[[], TNode])

  • fields (Sequence[str])

  • data_field (str)

  • dialect (str | Dialect | Mapping)

class littletree.serializers.RelationSerializer(factory=None, child_name='identifier', parent_name='parent', fields=(), data_field=None)[source]

Bases: object

Serializes a tree to a list of parent-children relations.

Parameters:
  • factory (Callable[[], TNode])

  • child_name (str)

  • parent_name (str)

  • fields (Sequence[str])

  • data_field (str)

class littletree.serializers.RowSerializer(factory=None, path_name='path', sep='/', fields=(), data_field=None)[source]

Bases: object

Serializes a tree to a list of dicts containing path and data.

Parameters:
  • factory (Callable[[], TNode])

  • path_name (str | Sequence[str] | None)

  • sep (str | None)

  • fields (Sequence[str])

  • data_field (str)

Exceptions

exception littletree.exceptions.TreeException[source]

Bases: Exception

Base tree exceptions.

exception littletree.exceptions.DuplicateParentError(node)[source]

Bases: TreeException

Operation would add multiple parents to a node.

exception littletree.exceptions.DuplicateChildError(node, identifier)[source]

Bases: TreeException

Operation would add multiple children with the same identifier to the same parent.

exception littletree.exceptions.LoopError(node, ancestor)[source]

Bases: TreeException

Operation would create a loop.