API Reference¶
This is the complete API reference for AlgoTree v1.0+.
Core Classes¶
Node¶
- class AlgoTree.Node(name: str | None = None, parent: Node | None = None, **payload)[source]¶
Bases:
object
A tree node with proper attributes instead of dict inheritance.
This class represents a single node in a tree structure with: - A unique name/identifier - Optional parent reference - List of children - Arbitrary payload data
- add_child(name: str | None = None, **payload) Node [source]¶
Add a child node.
- Parameters:
name – Name for the child node.
**payload – Data for the child node.
- Returns:
The newly created child node.
- find(predicate: Callable[[Node], bool]) Node | None [source]¶
Find first node matching predicate.
- Parameters:
predicate – Function that returns True for matching nodes.
- Returns:
First matching node or None.
- find_all(predicate: Callable[[Node], bool]) List[Node] [source]¶
Find all nodes matching predicate.
- Parameters:
predicate – Function that returns True for matching nodes.
- Returns:
List of matching nodes.
- classmethod from_dict(data: Dict[str, Any], parent: Node | None = None) Node [source]¶
Create tree from nested dictionary representation.
- Parameters:
data – Dictionary with node data and optional ‘children’ key.
parent – Parent node for the created tree.
- Returns:
Root node of created tree.
- property is_leaf: bool¶
Check if this is a leaf node.
- property is_root: bool¶
Check if this is a root node.
- property level: int¶
Get the level (depth) of this node in the tree.
from AlgoTree import Node
# Create nodes
root = Node("root", type="container")
child = root.add_child("child", value=42)
# Access properties
print(root.name) # "root"
print(root.payload) # {"type": "container"}
print(root.children) # [child]
print(root.is_root) # True
print(child.parent) # root
print(child.level) # 1
TreeBuilder¶
- class AlgoTree.TreeBuilder[source]¶
Bases:
object
Fluent API for building trees with method chaining.
Example
- tree = (TreeBuilder()
.root(“company”, type=”corporation”) .child(“engineering”, head=”Alice”)
.child(“frontend”, team_size=5) .sibling(“backend”, team_size=8) .up()
.sibling(“sales”, head=”Bob”) .build())
- child(name: str, **payload) TreeBuilder [source]¶
Add a child to the current node and move to it.
- Parameters:
name – Name for the child node.
**payload – Data for the child node.
- Returns:
Self for method chaining.
- root(name: str, **payload) TreeBuilder [source]¶
Create the root node.
- Parameters:
name – Name for the root node.
**payload – Data for the root node.
- Returns:
Self for method chaining.
- sibling(name: str, **payload) TreeBuilder [source]¶
Add a sibling to the current node.
- Parameters:
name – Name for the sibling node.
**payload – Data for the sibling node.
- Returns:
Self for method chaining.
- to_root() TreeBuilder [source]¶
Move to the root node.
- Returns:
Self for method chaining.
- up(levels: int = 1) TreeBuilder [source]¶
Move up in the tree by specified levels.
- Parameters:
levels – Number of levels to move up. Default is 1.
- Returns:
Self for method chaining.
from AlgoTree import TreeBuilder
tree = (TreeBuilder()
.root("app")
.child("config", debug=True)
.sibling("database", host="localhost")
.up()
.child("modules")
.child("auth")
.sibling("api")
.build())
FluentNode¶
- class AlgoTree.FluentNode(node: Node | List[Node])[source]¶
Bases:
object
Wrapper for Node that provides fluent API for tree operations.
Example
- result = (FluentNode(tree)
.filter(lambda n: n.level <= 2) .map(lambda n: n.payload.get(‘size’, 0)) .where(lambda n: n > 5) .to_list())
- children() FluentNode [source]¶
Get all children of current nodes.
- Returns:
New FluentNode with all children.
- descendants() FluentNode [source]¶
Get all descendants of current nodes.
- Returns:
New FluentNode with all descendants.
- each(action: Callable[[Node], None]) FluentNode [source]¶
Execute an action on each node.
- Parameters:
action – Function to execute on each node.
- Returns:
Self for method chaining.
- filter(predicate: Callable[[Node], bool]) FluentNode [source]¶
Filter nodes by predicate.
- Parameters:
predicate – Function that returns True for nodes to keep.
- Returns:
New FluentNode with filtered nodes.
- leaves() FluentNode [source]¶
Get all leaf nodes from current nodes.
- Returns:
New FluentNode with leaf nodes only.
- map(transform: Callable[[Node], Any]) FluentNode [source]¶
Transform each node’s payload.
- Parameters:
transform – Function to transform each node.
- Returns:
Self for method chaining.
- match(pattern: str | Pattern | dict) FluentNode [source]¶
Find nodes matching a pattern.
- Parameters:
pattern – Pattern to match (string, Pattern object, or dict)
- Returns:
New FluentNode with matching nodes.
- prune(predicate: Callable[[Node], bool]) FluentNode [source]¶
Remove nodes matching predicate.
- Parameters:
predicate – Function that returns True for nodes to remove.
- Returns:
Self for method chaining.
- replace_matches(pattern: str | Pattern | dict, replacement: Node | Callable[[Node], Node]) FluentNode [source]¶
Replace nodes matching a pattern.
- Parameters:
pattern – Pattern to match
replacement – Node or function to generate replacement
- Returns:
Self for method chaining.
- sort(key: Callable[[Node], Any] | None = None, reverse: bool = False) FluentNode [source]¶
Sort children of each node.
- Parameters:
key – Function to extract sort key from each node.
reverse – Whether to sort in reverse order.
- Returns:
Self for method chaining.
- to_dict() dict | List[dict] [source]¶
Convert to dictionary representation.
- Returns:
Dictionary or list of dictionaries.
- where(predicate: Callable[[Node], bool]) FluentNode [source]¶
Filter current nodes by predicate (alias for filter on current set).
- Parameters:
predicate – Function that returns True for nodes to keep.
- Returns:
New FluentNode with filtered nodes.
from AlgoTree import FluentNode
fluent = FluentNode(tree)
# Chain operations
(fluent
.filter(lambda n: n.payload.get("enabled"))
.map(lambda n: {"processed": True})
.each(lambda n: print(n.name)))
Pattern Matching¶
Pattern¶
- class AlgoTree.Pattern(name: str | None = None, attributes: ~typing.Dict[str, ~typing.Any] = <factory>, children: ~typing.List[~AlgoTree.pattern_matcher.Pattern] = <factory>, is_wildcard: bool = False, is_deep_wildcard: bool = False, min_children: int | None = None, max_children: int | None = None, predicate: ~typing.Callable[[~AlgoTree.node.Node], bool] | None = None)[source]¶
Bases:
object
Represents a tree pattern to match against.
Patterns can include: - Exact node matches - Wildcards (*) that match any single node - Deep wildcards (**) that match any subtree - Attribute constraints
- attributes: Dict[str, Any]¶
- static from_dict(pattern_dict: Dict[str, Any]) Pattern [source]¶
Create a pattern from dictionary representation.
Example
- {
“name”: “parent”, “attributes”: {“type”: “container”}, “children”: [
{“name”: “child1”}, {“name”: “*”} # Wildcard child
]
}
- static from_string(pattern_str: str) Pattern [source]¶
Parse a pattern from string notation.
Examples
“root” # Match node named ‘root’ “*” # Match any single node “**” # Match any subtree “node[type=foo]” # Match node with attribute “parent(child1, child2)” # Match parent with specific children “root.branch.leaf” # Dot notation path “app.*.test” # Dot notation with wildcard “root.**.target” # Dot notation with deep wildcard
- is_deep_wildcard: bool = False¶
- is_wildcard: bool = False¶
- max_children: int | None = None¶
- min_children: int | None = None¶
- name: str | None = None¶
PatternMatcher¶
- class AlgoTree.PatternMatcher(match_type: MatchType = MatchType.PARTIAL)[source]¶
Bases:
object
Matches patterns against tree structures.
- find_all(tree: Node, pattern: Pattern) List[Node] [source]¶
Find all nodes in tree that match the pattern.
- Parameters:
tree – Root node of tree to search
pattern – Pattern to match
- Returns:
List of nodes that match the pattern
- find_first(tree: Node, pattern: Pattern) Node | None [source]¶
Find first node that matches the pattern.
- Parameters:
tree – Root node of tree to search
pattern – Pattern to match
- Returns:
First matching node or None
- match(node: Node, pattern: Pattern) bool [source]¶
Check if a node matches a pattern.
- Parameters:
node – Node to match against
pattern – Pattern to match
- Returns:
True if node matches pattern
- replace(tree: Node, pattern: Pattern, replacement: Node | Callable[[Node], Node]) int [source]¶
Replace all nodes matching pattern with replacement.
- Parameters:
tree – Root node of tree
pattern – Pattern to match
replacement – Node or function to generate replacement
- Returns:
Number of replacements made
Pattern Functions¶
- AlgoTree.pattern_match(tree: Node, pattern: str | Dict | Pattern, match_type: MatchType = MatchType.PARTIAL) List[Node] [source]¶
Convenience function to find all matches of a pattern in a tree.
- Parameters:
tree – Tree to search
pattern – Pattern as string, dict, or Pattern object
match_type – Type of matching
- Returns:
List of matching nodes
- AlgoTree.dotmatch(tree: Node, dot_path: str, return_paths: bool = False) List[Node] | List[str] [source]¶
Match nodes using dot notation paths, inspired by dotsuite.
This provides a clean, intuitive way to navigate and match tree paths using dot notation similar to JSONPath or object property access.
- Parameters:
tree – Tree to search
dot_path – Dot notation path (e.g., “root.branch.*.leaf”, “app.**.test”)
return_paths – If True, return dot paths to matches instead of nodes
- Returns:
List of matching nodes or their dot paths
Examples
# Find all test files dotmatch(tree, “src.**.test_*”)
# Find specific path dotmatch(tree, “app.models.user”)
# Find with wildcards dotmatch(tree, “data.*.value”)
# Get paths instead of nodes paths = dotmatch(tree, “**.config”, return_paths=True) # Returns: [“app.config”, “modules.auth.config”, …]
- AlgoTree.dotpluck(tree: Node, *dot_paths: str) List[Any] [source]¶
Extract values from tree using dot notation paths.
Inspired by dotsuite’s dotpluck, this extracts payload values from nodes at specified paths.
- Parameters:
tree – Tree to extract from
*dot_paths – Variable number of dot notation paths
- Returns:
List of values (payload or None for missing paths)
Examples
# Extract multiple values values = dotpluck(tree, “user.name”, “user.age”, “user.email”)
# Extract with wildcards (returns all matching values) values = dotpluck(tree, “users.*.name”)
- AlgoTree.dotexists(tree: Node, dot_path: str) bool [source]¶
Check if a path exists in the tree.
Inspired by dotsuite’s dotexists from the Truth pillar.
- Parameters:
tree – Tree to check
dot_path – Dot notation path
- Returns:
True if path exists, False otherwise
- AlgoTree.dotcount(tree: Node, dot_path: str) int [source]¶
Count nodes matching a path pattern.
- Parameters:
tree – Tree to count in
dot_path – Dot notation path pattern
- Returns:
Number of matching nodes
- AlgoTree.dotfilter(tree: Node, filter_expr: str) List[Node] [source]¶
Filter tree nodes using advanced expressions.
Supports: - Comparison operators: >, <, >=, <=, ==, != - Logical operators: and, or, not - Path expressions: @.property - Functions: contains(), startswith(), endswith()
- Parameters:
tree – Tree to filter
filter_expr – Filter expression
- Returns:
List of matching nodes
Examples
# Size greater than 100 dotfilter(tree, “@.size > 100”)
# Name contains “test” and has children dotfilter(tree, “contains(@.name, ‘test’) and @.children.length > 0”)
Closed Transformations (Tree → Tree)¶
- AlgoTree.dotmod(tree: Node, transformations: Dict[str, Any] | List[Tuple[str, Any]], in_place: bool = False) Node [source]¶
Apply closed tree-to-tree transformations using dot notation paths.
This function modifies nodes in the tree based on dot notation paths, preserving the tree structure (closed transformation).
- Parameters:
tree – Tree to transform
transformations – Either: - Dict mapping dot paths to transformations - List of (dot_path, transformation) tuples
in_place – If True, modify tree in place; otherwise create a copy
- Returns:
Transformed tree (same object if in_place=True, copy otherwise)
- Transformations can be:
Dict: Update node payload with dict contents
Callable: Apply function to node (receives node, returns dict to update payload)
String: Rename the node
None: Clear the payload (but keep the node)
Examples
# Update specific nodes tree = dotmod(tree, {
“app.config”: {“version”: “2.0”, “debug”: False}, “app.database”: {“host”: “localhost”, “port”: 5432}
})
# Rename nodes tree = dotmod(tree, {
“app.oldname”: “newname”
})
# Apply functions tree = dotmod(tree, {
“app.**.file”: lambda n: {“size”: n.payload.get(“size”, 0) * 2}
})
# Multiple transformations to same path pattern tree = dotmod(tree, [
(“app.**.test_*”, lambda n: {“tested”: True}), (“app.**.test_*”, lambda n: {“priority”: “high”})
])
- AlgoTree.dotmap(tree: Node, mapper: Callable[[Node], Dict[str, Any]] | Dict[str, Callable], dot_path: str = '**', in_place: bool = False) Node [source]¶
Map a transformation function over nodes matching a pattern.
This is a convenience function that applies the same transformation to all nodes matching a pattern.
- Parameters:
tree – Tree to transform
mapper – Either: - Function that takes a node and returns dict to update payload - Dict mapping payload keys to transformation functions
dot_path – Pattern to match nodes (default “**” for all nodes)
in_place – If True, modify tree in place
- Returns:
Transformed tree
Examples
# Double all sizes tree = dotmap(tree, lambda n: {“size”: n.payload.get(“size”, 0) * 2})
# Transform specific fields tree = dotmap(tree, {
“size”: lambda v: v * 2, “name”: lambda v: v.upper(), “timestamp”: lambda v: str(v)
})
# Apply only to specific nodes tree = dotmap(tree,
lambda n: {“processed”: True}, dot_path=”app.data.**”)
- AlgoTree.dotprune(tree: Node, condition: str | Callable[[Node], bool], keep_structure: bool = False, in_place: bool = False) Node [source]¶
Prune nodes from tree based on condition.
- Parameters:
tree – Tree to prune
condition – Either: - Dot path pattern of nodes to remove - Predicate function (returns True for nodes to remove)
keep_structure – If True, replace pruned nodes with empty placeholders
in_place – If True, modify tree in place
- Returns:
Pruned tree
Examples
# Remove all test files tree = dotprune(tree, “**.test_*”)
# Remove empty directories tree = dotprune(tree, lambda n: n.payload.get(“type”) == “dir” and len(n.children) == 0)
# Keep structure but clear nodes tree = dotprune(tree, “**.deprecated”, keep_structure=True)
- AlgoTree.dotmerge(tree1: Node, tree2: Node, merge_strategy: str = 'overlay', conflict_resolver: Callable[[Node, Node], Node] | None = None, in_place: bool = False) Node [source]¶
Merge two trees using various strategies.
- Parameters:
tree1 – First tree (base)
tree2 – Second tree (overlay)
merge_strategy – Strategy for merging: - “overlay”: tree2 values override tree1 - “underlay”: tree1 values take precedence - “combine”: merge payloads, keeping both values - “custom”: use conflict_resolver function
conflict_resolver – Function to resolve conflicts (for custom strategy)
in_place – If True, modify tree1 in place
- Returns:
Merged tree
Examples
# Simple overlay merge merged = dotmerge(tree1, tree2, “overlay”)
# Custom conflict resolution def resolver(node1, node2):
# Combine arrays, prefer tree2 for other values merged_payload = {} for key in set(node1.payload.keys()) | set(node2.payload.keys()):
- if key in node1.payload and key in node2.payload:
val1, val2 = node1.payload[key], node2.payload[key] if isinstance(val1, list) and isinstance(val2, list):
merged_payload[key] = val1 + val2
- else:
merged_payload[key] = val2
- elif key in node1.payload:
merged_payload[key] = node1.payload[key]
- else:
merged_payload[key] = node2.payload[key]
return Node(node2.name, **merged_payload)
merged = dotmerge(tree1, tree2, “custom”, conflict_resolver=resolver)
- AlgoTree.dotgraft(tree: Node, graft_point: str, subtree: Node, position: int | str = 'append', in_place: bool = False) Node [source]¶
Graft a subtree onto a tree at specified point(s).
- Parameters:
tree – Tree to graft onto
graft_point – Dot path to graft point(s)
subtree – Subtree to graft
position – Where to add the subtree: - “append”: Add at end of children (default) - “prepend”: Add at beginning of children - int: Insert at specific index - “replace”: Replace existing children
in_place – If True, modify tree in place
- Returns:
Tree with grafted subtree
Examples
# Add new module to app new_module = Node(“auth”, type=”module”) tree = dotgraft(tree, “app.modules”, new_module)
# Insert at specific position tree = dotgraft(tree, “app.modules”, new_module, position=0)
# Replace children tree = dotgraft(tree, “app.old_modules”, new_modules, position=”replace”)
- AlgoTree.dotsplit(tree: Node, split_point: str, include_point: bool = True) Tuple[Node, List[Node]] [source]¶
Split tree at specified point(s), extracting subtrees.
- Parameters:
tree – Tree to split
split_point – Dot path to split point(s)
include_point – If True, include split point in extracted subtrees
- Returns:
Tuple of (modified tree, list of extracted subtrees)
Examples
# Extract all test modules tree, test_modules = dotsplit(tree, “**.tests”)
# Extract but keep the container node tree, extracted = dotsplit(tree, “app.deprecated”, include_point=False)
- AlgoTree.dotflatten(tree: Node, flatten_pattern: str = '**', max_depth: int | None = None) List[Node] [source]¶
Flatten tree structure into a list of nodes.
- Parameters:
tree – Tree to flatten
flatten_pattern – Pattern for nodes to include
max_depth – Maximum depth to flatten to
- Returns:
List of nodes (flattened)
Examples
# Get all nodes as flat list all_nodes = dotflatten(tree)
# Get only file nodes files = dotflatten(tree, “**[type=file]”)
# Flatten only top 3 levels top_nodes = dotflatten(tree, max_depth=3)
- AlgoTree.dotreduce(tree: Node, reducer: Callable[[Any, Node], Any], initial: Any = None, traverse_pattern: str = '**') Any [source]¶
Reduce tree to a single value using a reducer function.
- Parameters:
tree – Tree to reduce
reducer – Function (accumulator, node) -> new_accumulator
initial – Initial value for accumulator
traverse_pattern – Pattern for nodes to include in reduction
- Returns:
Reduced value
Examples
# Sum all sizes total_size = dotreduce(tree,
lambda acc, n: acc + n.payload.get(“size”, 0), initial=0)
# Collect all names names = dotreduce(tree,
lambda acc, n: acc + [n.name], initial=[])
# Find maximum depth max_depth = dotreduce(tree,
lambda acc, n: max(acc, n.level), initial=0)
- AlgoTree.dotannotate(tree: Node, annotator: Callable[[Node], Dict[str, Any]] | Dict[str, Any], annotation_key: str = '_annotation', dot_path: str = '**', in_place: bool = False) Node [source]¶
Add annotations to nodes in the tree.
- Parameters:
tree – Tree to annotate
annotator – Either: - Function that returns annotation dict for each node - Static annotation dict to add to all matching nodes
annotation_key – Key to store annotations under in payload
dot_path – Pattern for nodes to annotate
in_place – If True, modify tree in place
- Returns:
Annotated tree
Examples
# Add computed annotations tree = dotannotate(tree,
- lambda n: {
“depth”: n.level, “has_children”: len(n.children) > 0, “path”: “.”.join(p.name for p in n.get_path())
})
# Add static annotations to specific nodes tree = dotannotate(tree,
{“reviewed”: True, “version”: “1.0”}, dot_path=”**.critical_*”)
- AlgoTree.dotvalidate(tree: Node, validator: Callable[[Node], bool] | Dict[str, Any], dot_path: str = '**', raise_on_invalid: bool = True) bool | List[Node] [source]¶
Validate nodes in the tree against criteria.
- Parameters:
tree – Tree to validate
validator – Either: - Predicate function returning True for valid nodes - Dict of required attributes and values
dot_path – Pattern for nodes to validate
raise_on_invalid – If True, raise exception on first invalid node
- Returns:
List of invalid nodes (empty if all valid) If raise_on_invalid=True: True if all valid (raises otherwise)
- Return type:
If raise_on_invalid=False
Examples
# Validate with function dotvalidate(tree,
lambda n: n.payload.get(“size”, 0) < 1000000, dot_path=”**[type=file]”)
# Validate required attributes dotvalidate(tree,
{“type”: “file”, “tested”: True}, dot_path=”app.src.**”)
# Get list of invalid nodes invalid = dotvalidate(tree,
lambda n: len(n.name) <= 255, raise_on_invalid=False)
- AlgoTree.dotnormalize(tree: Node, normalizer: Callable[[str], str] | None = None, normalize_payload: bool = False, in_place: bool = False) Node [source]¶
Normalize node names and optionally payload keys.
- Parameters:
tree – Tree to normalize
normalizer – Function to normalize names (default: lowercase + underscore)
normalize_payload – If True, also normalize payload keys
in_place – If True, modify tree in place
- Returns:
Normalized tree
Examples
# Default normalization (lowercase, spaces to underscores) tree = dotnormalize(tree)
# Custom normalization tree = dotnormalize(tree,
normalizer=lambda s: s.lower().replace(“-”, “_”))
# Also normalize payload keys tree = dotnormalize(tree, normalize_payload=True)
Open Transformations (Tree → Any)¶
- AlgoTree.dotpipe(tree: Node, *transformers: Callable | Tuple[str, Callable]) Any [source]¶
Pipe tree through a series of transformations.
This is the main function for open transformations - converting trees to any structure through a pipeline of operations.
- Parameters:
tree – Tree to transform
*transformers – Variable number of transformers, each can be: - Callable: Applied to entire result of previous stage - Tuple[str, Callable]: (dot_path, transformer) applies to matched nodes
- Returns:
Result of the final transformation (can be any type)
Examples
# Extract all names as a list names = dotpipe(tree,
lambda t: [n.name for n in t.traverse_preorder()])
# Pipeline of transformations result = dotpipe(tree,
(”**.config”, lambda n: n.payload), # Extract config payloads lambda configs: {c.get(“name”): c for c in configs}, # Dict by name lambda d: list(d.values())) # Back to list
# Convert tree to nested dict data = dotpipe(tree, to_dict)
# Extract and process specific data totals = dotpipe(tree,
(”**[type=file]”, lambda n: n.payload.get(“size”, 0)), sum) # Sum all sizes
- AlgoTree.to_dict(node: Node, include_children: bool = True, include_parent: bool = False, key_mapper: Callable[[str], str] | None = None) Dict[str, Any] [source]¶
Convert tree node to dictionary representation.
- Parameters:
node – Node to convert
include_children – If True, recursively include children
include_parent – If True, include parent reference (careful: can be circular)
key_mapper – Optional function to transform keys
- Returns:
Dictionary representation of the node
Examples
# Simple conversion data = to_dict(tree)
# Without children (just this node) node_data = to_dict(tree, include_children=False)
# With key transformation data = to_dict(tree, key_mapper=str.upper)
- AlgoTree.to_list(node: Node, traverse_order: str = 'preorder', include_data: bool = True) List[str | Dict[str, Any]] [source]¶
Convert tree to flat list representation.
- Parameters:
node – Root node
traverse_order – Traversal order (“preorder”, “postorder”, “levelorder”)
include_data – If True, include full node data; if False, just names
- Returns:
List of nodes (as dicts or names)
Examples
# List of all node names names = to_list(tree, include_data=False)
# List of node data in level order nodes = to_list(tree, traverse_order=”levelorder”)
- AlgoTree.to_paths(node: Node, path_separator: str = '.', include_payload: bool = False) List[str] | Dict[str, Any] [source]¶
Convert tree to path representations.
- Parameters:
node – Root node
path_separator – Separator for path components
include_payload – If True, return dict mapping paths to payloads
- Returns:
List of paths or dict mapping paths to payloads
Examples
# List of all paths paths = to_paths(tree) # [“app”, “app.config”, “app.database”, …]
# Paths with payloads path_data = to_paths(tree, include_payload=True) # {“app”: {…}, “app.config”: {…}, …}
# Using different separator paths = to_paths(tree, path_separator=”/”) # [“app”, “app/config”, “app/database”, …]
- AlgoTree.to_adjacency_list(node: Node) Dict[str, List[str]] [source]¶
Convert tree to adjacency list representation.
- Parameters:
node – Root node
- Returns:
Dictionary mapping node names to lists of child names
Examples
adj = to_adjacency_list(tree) # {“app”: [“config”, “database”], “config”: [], …}
- AlgoTree.to_edge_list(node: Node, include_root: bool = False) List[Tuple[str, str]] [source]¶
Convert tree to edge list representation.
- Parameters:
node – Root node
include_root – If True, include edge from None to root
- Returns:
List of (parent, child) tuples
Examples
edges = to_edge_list(tree) # [(“app”, “config”), (“app”, “database”), …]
- AlgoTree.to_nested_lists(node: Node) List [source]¶
Convert tree to nested list structure (like S-expressions).
- Parameters:
node – Root node
- Returns:
Nested list representation
Examples
nested = to_nested_lists(tree) # [“app”, [“config”], [“database”], [“modules”, [“auth”], [“api”]]]
- AlgoTree.to_table(node: Node, columns: List[str] | None = None, include_path: bool = True) List[Dict[str, Any]] [source]¶
Convert tree to tabular/relational format.
- Parameters:
node – Root node
columns – Specific payload columns to include (None = all)
include_path – If True, include full path to node
- Returns:
List of row dictionaries suitable for DataFrame or CSV
Examples
# Convert to table format rows = to_table(tree, columns=[“type”, “size”, “enabled”])
# Can be used with pandas: # df = pd.DataFrame(rows)
- AlgoTree.dotextract(tree: Node, extractor: Callable[[Node], Any], dot_path: str = '**', flatten: bool = True) List[Any] | Dict[str, Any] [source]¶
Extract data from tree nodes using custom extractor.
- Parameters:
tree – Tree to extract from
extractor – Function to extract data from each node
dot_path – Pattern to match nodes
flatten – If True, return flat list; if False, preserve structure
- Returns:
Extracted data as list or structured dict
Examples
# Extract all sizes sizes = dotextract(tree, lambda n: n.payload.get(“size”))
# Extract node info for files files = dotextract(tree,
lambda n: {“name”: n.name, “size”: n.payload[“size”]}, dot_path=”**[type=file]”)
- AlgoTree.dotcollect(tree: Node, collector: Callable[[Node, Any], Any], initial: Any = None, dot_path: str = '**') Any [source]¶
Collect data from tree using a collector function.
Similar to reduce but more focused on building collections.
- Parameters:
tree – Tree to collect from
collector – Function (node, accumulator) -> new_accumulator
initial – Initial accumulator value
dot_path – Pattern to match nodes
- Returns:
Final collected value
Examples
# Collect into a dict by type by_type = dotcollect(tree,
- lambda n, acc: {
**acc, n.payload.get(“type”, “unknown”):
acc.get(n.payload.get(“type”, “unknown”), []) + [n.name]
}, initial={})
# Collect statistics stats = dotcollect(tree,
- lambda n, acc: {
“count”: acc[“count”] + 1, “total_size”: acc[“total_size”] + n.payload.get(“size”, 0), “max_depth”: max(acc[“max_depth”], n.level)
}, initial={“count”: 0, “total_size”: 0, “max_depth”: 0})
- AlgoTree.dotgroup(tree: Node, grouper: str | Callable[[Node], Any], dot_path: str = '**') Dict[Any, List[Node]] [source]¶
Group tree nodes by a key.
- Parameters:
tree – Tree to group nodes from
grouper – Either: - String: payload key to group by - Callable: function to compute group key
dot_path – Pattern to match nodes
- Returns:
Dictionary mapping group keys to lists of nodes
Examples
# Group by type by_type = dotgroup(tree, “type”)
# Group by custom function by_level = dotgroup(tree, lambda n: n.level)
# Group files by extension by_ext = dotgroup(tree,
lambda n: n.name.split(“.”)[-1] if “.” in n.name else “no_ext”, dot_path=”**[type=file]”)
- AlgoTree.dotpartition(tree: Node, predicate: Callable[[Node], bool], dot_path: str = '**') Tuple[List[Node], List[Node]] [source]¶
Partition nodes into two groups based on predicate.
- Parameters:
tree – Tree to partition
predicate – Function returning True for first group, False for second
dot_path – Pattern to match nodes
- Returns:
Tuple of (matching_nodes, non_matching_nodes)
Examples
# Partition by size large, small = dotpartition(tree, lambda n: n.payload.get(“size”, 0) > 1000)
# Partition enabled/disabled enabled, disabled = dotpartition(tree,
lambda n: n.payload.get(“enabled”, False), dot_path=”app.modules.*”)
- AlgoTree.dotproject(tree: Node, projection: List[str] | Dict[str, str], dot_path: str = '**') List[Dict[str, Any]] [source]¶
Project specific fields from nodes (like SQL SELECT).
- Parameters:
tree – Tree to project from
projection – Either: - List of field names to include - Dict mapping field names to aliases
dot_path – Pattern to match nodes
- Returns:
List of projected dictionaries
Examples
# Select specific fields data = dotproject(tree, [“name”, “size”, “type”])
# With aliases data = dotproject(tree, {
“name”: “file_name”, “size”: “file_size”, “type”: “file_type”
})
Tree DSL Parsing¶
- AlgoTree.parse_tree(text: str, format: str = 'auto') Node [source]¶
Convenience function to parse tree from DSL text.
- Parameters:
text – DSL text to parse.
format – Format to use (‘visual’, ‘indent’, ‘sexpr’, ‘auto’).
- Returns:
Root node of parsed tree.
Examples
# Visual format tree = parse_tree(‘’’
company ├── engineering │ ├── frontend │ └── backend └── sales
‘’’)
# Indent format tree = parse_tree(‘’’
- company
- engineering
frontend backend
sales
‘’’)
# S-expression format tree = parse_tree(‘’’
- (company
- (engineering
(frontend) (backend))
(sales))
‘’’)
Export Functions¶
- class AlgoTree.TreeExporter[source]¶
Bases:
object
Base class for tree exporters.
- static to_ascii(node: Node, style: str = 'ascii') str [source]¶
Export tree to ASCII/Unicode art.
- Parameters:
node – Root node of tree
style – “ascii” for ASCII characters, “unicode” for box drawing
- Returns:
String representation of tree
- static to_dict(node: Node) Dict[str, Any] [source]¶
Export tree to dictionary (already implemented in Node).
- static to_graphviz(node: Node, name: str = 'Tree', node_attr: Callable[[Node], Dict[str, str]] | None = None, edge_attr: Callable[[Node, Node], Dict[str, str]] | None = None, graph_attr: Dict[str, str] | None = None) str [source]¶
Export tree to GraphViz DOT format.
- Parameters:
node – Root node of tree
name – Graph name
node_attr – Function to generate node attributes
edge_attr – Function to generate edge attributes
graph_attr – Graph-level attributes
- Returns:
DOT format string
Example
- dot = TreeExporter.to_graphviz(tree,
node_attr=lambda n: {“label”: f”{n.name}n{n.payload.get(‘size’, ‘’)}”})
- static to_html(node: Node, include_styles: bool = True, collapsible: bool = True) str [source]¶
Export tree to interactive HTML.
- Parameters:
node – Root node of tree
include_styles – Include CSS styles
collapsible – Make tree nodes collapsible
- Returns:
HTML string representation
- static to_mermaid(node: Node, direction: str = 'TD', node_shape: str = 'round', node_text: Callable[[Node], str] | None = None) str [source]¶
Export tree to Mermaid diagram format.
- Parameters:
node – Root node of tree
direction – Graph direction (TD, TB, BT, RL, LR)
node_shape – Shape style (“round”, “square”, “circle”, “rhombus”, “stadium”)
node_text – Function to generate node text
- Returns:
Mermaid format string
Example
- mermaid = TreeExporter.to_mermaid(tree,
node_text=lambda n: f”{n.name}<br/>{n.payload.get(‘type’, ‘’)}”)
- static to_unicode(node: Node) str [source]¶
Export tree to Unicode box drawing (alias for to_ascii with unicode style).
- AlgoTree.export_tree(node: Node, format: str, **kwargs) str [source]¶
Export tree to specified format.
- Parameters:
node – Root node of tree
format – Export format (json, ascii, unicode, graphviz, mermaid, yaml, xml, html)
**kwargs – Format-specific options
- Returns:
String representation in specified format
- AlgoTree.save_tree(node: Node, filepath: str, format: str | None = None, **kwargs)[source]¶
Save tree to file in specified format.
- Parameters:
node – Root node of tree
filepath – Output file path
format – Export format (auto-detected from extension if not specified)
**kwargs – Format-specific options
Visualization¶
- AlgoTree.pretty_tree(node, **kwargs) str [source]¶
Converts a tree to a pretty string representation.
- Parameters:
kwargs – Key-word arguments. See PrettyTree for more details.
- Returns:
A pretty string representation of the tree.
- class AlgoTree.PrettyTree(style: ~typing.Dict[str, str] | None = None, node_name: ~typing.Callable[[~typing.Any], str] = <function PrettyTree.<lambda>>, indent: int = 7, mark: ~typing.List[str] | None = None, node_details: ~typing.Callable[[~typing.Any], ~typing.Any] | None = None)[source]¶
Bases:
object
A class to print a tree in a more readable way.
- default_style = {'child_connector': '├', 'horizontal': '─', 'last_child_connector': '└', 'markers': ['🔵', '🔴', '🟢', '🟣', '🟠', '🟡', '🟤', '⚫', '⚪', '⭕', '🔘'], 'payload_connector': '◄', 'spacer': ' ', 'vertical': '│'}¶