CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/pypi-anytree

Powerful and Lightweight Python Tree Data Structure with various plugins

Pending

Quality

Pending

Does it follow best practices?

Impact

Pending

No eval scenarios have been run

Overview
Eval results
Files

tree-rendering.mddocs/

Tree Visualization and Rendering

ASCII and Unicode tree rendering with multiple built-in styles for displaying tree structures in console output, documentation, and reports. Provides comprehensive visualization capabilities with customizable formatting.

Capabilities

RenderTree - Tree Visualization

Main class for rendering tree structures as formatted text with various styling options, child ordering control, and depth limits.

class RenderTree:
    """
    Renders tree structure as formatted text.
    
    Args:
        node: Root node to render from
        style: Rendering style (ContStyle, AsciiStyle, etc.)
        childiter: Function to determine child iteration order  
        maxlevel: Maximum depth to render
    """
    def __init__(self, node, style=ContStyle(), childiter=list, maxlevel=None): ...
    
    def __str__(self) -> str: ...
    def __iter__(self) -> Iterator[Row]: ...

Usage Example:

from anytree import Node, RenderTree, AsciiStyle

# Create tree structure
root = Node("Company")
engineering = Node("Engineering", parent=root)
marketing = Node("Marketing", parent=root)
Node("Backend", parent=engineering)
Node("Frontend", parent=engineering)
Node("Content", parent=marketing)

# Basic rendering
print(RenderTree(root))
# Company
# ├── Engineering
# │   ├── Backend
# │   └── Frontend
# └── Marketing
#     └── Content

# ASCII-only rendering
print(RenderTree(root, style=AsciiStyle()))
# Company
# |-- Engineering
# |   |-- Backend
# |   +-- Frontend
# +-- Marketing
#     +-- Content

# With max level limit
print(RenderTree(root, maxlevel=2))
# Company
# ├── Engineering
# └── Marketing

Rendering Styles

Multiple built-in styles for different output requirements and character set compatibility.

ContStyle - Unicode Continuous Lines

Default Unicode style with continuous line characters for modern terminals and documentation.

class ContStyle(AbstractStyle):
    """
    Unicode tree rendering with continuous lines.
    """
    def __init__(self): ...
    
    vertical = "│"
    cont = "├── "
    end = "└── "

AsciiStyle - ASCII-Only Characters

ASCII-compatible style for environments that don't support Unicode characters.

class AsciiStyle(AbstractStyle):
    """
    ASCII-only tree rendering style.
    """
    def __init__(self): ...
    
    vertical = "|"
    cont = "|-- "
    end = "+-- "

ContRoundStyle - Unicode Rounded Corners

Unicode style with rounded corner characters for a softer visual appearance.

class ContRoundStyle(AbstractStyle):
    """
    Unicode tree rendering with rounded corners.
    """
    def __init__(self): ...
    
    vertical = "│"
    cont = "├─ "  
    end = "╰─ "

DoubleStyle - Double Line Characters

Unicode style with double-line characters for emphasis and visual distinction.

class DoubleStyle(AbstractStyle):
    """
    Unicode tree rendering with double lines.
    """
    def __init__(self): ...
    
    vertical = "║"
    cont = "╠══ "
    end = "╚══ "

AbstractStyle - Custom Style Base

Base class for creating custom rendering styles with user-defined characters.

class AbstractStyle:
    """
    Tree Render Style base class.
    
    Args:
        vertical: Sign for vertical line
        cont: Chars for a continued branch  
        end: Chars for the last branch
    """
    def __init__(self, vertical, cont, end): ...
    
    vertical: str
    cont: str
    end: str

Usage Example:

from anytree import Node, RenderTree, AbstractStyle

# Create custom style
class CustomStyle(AbstractStyle):
    def __init__(self):
        super().__init__(
            vertical="▏",
            cont="▣ ",
            end="▣ "
        )

root = Node("root")
Node("child1", parent=root)
Node("child2", parent=root)

print(RenderTree(root, style=CustomStyle()))

Advanced Rendering Features

Custom Child Ordering

Control the order in which child nodes are rendered using the childiter parameter:

from anytree import Node, RenderTree

root = Node("root")
Node("zebra", parent=root)
Node("apple", parent=root)  
Node("beta", parent=root)

# Default order (insertion order)
print("Default order:")
print(RenderTree(root))

# Alphabetical order
print("\nAlphabetical order:")
print(RenderTree(root, childiter=lambda children: sorted(children, key=lambda n: n.name)))

# Reverse order  
print("\nReverse order:")
print(RenderTree(root, childiter=lambda children: reversed(children)))

# Custom sorting (by length)
print("\nBy name length:")
print(RenderTree(root, childiter=lambda children: sorted(children, key=lambda n: len(n.name))))

Depth-Limited Rendering

Render only a specific number of levels to focus on tree structure or handle very deep trees:

from anytree import Node, RenderTree

# Create deep tree
root = Node("Level 0")
current = root
for i in range(1, 6):
    current = Node(f"Level {i}", parent=current)
    Node(f"Side branch {i}", parent=current)

# Show only first 3 levels
print("First 3 levels:")
print(RenderTree(root, maxlevel=3))

# Show only top 2 levels
print("\nTop 2 levels:")  
print(RenderTree(root, maxlevel=2))

Row-by-Row Processing

Access individual rendered rows for custom processing or formatting:

from anytree import Node, RenderTree, Row

root = Node("Company")
engineering = Node("Engineering", parent=root)
Node("Alice", parent=engineering, role="Engineer")
Node("Bob", parent=engineering, role="Manager")

# Process each row individually
for row in RenderTree(root):
    # row is a Row namedtuple with fields: pre, fill, node
    indent = row.pre
    node = row.node
    fill = row.fill
    
    # Custom formatting
    if hasattr(node, 'role'):
        print(f"{indent}{node.name} ({node.role})")
    else:
        print(f"{indent}{node.name}")

Node Information Display

Include additional node information in rendered output:

from anytree import Node, RenderTree

class InfoNode(Node):
    def __init__(self, name, info=None, **kwargs):
        super().__init__(name, **kwargs)
        self.info = info
    
    def __str__(self):
        if self.info:
            return f"{self.name} [{self.info}]"
        return self.name

root = InfoNode("Company", "Founded 2020")
eng = InfoNode("Engineering", "50 employees", parent=root)
InfoNode("Backend Team", "Python/Django", parent=eng)
InfoNode("Frontend Team", "React/TypeScript", parent=eng)

print(RenderTree(root))
# Company [Founded 2020]
# └── Engineering [50 employees]
#     ├── Backend Team [Python/Django]
#     └── Frontend Team [React/TypeScript]

Style Comparison

Here's how the same tree looks with different styles:

from anytree import Node, RenderTree, AsciiStyle, ContStyle, ContRoundStyle, DoubleStyle

# Create sample tree
root = Node("root")
child1 = Node("child1", parent=root)
child2 = Node("child2", parent=root)
Node("grandchild1", parent=child1)
Node("grandchild2", parent=child1)
Node("grandchild3", parent=child2)

styles = [
    ("ContStyle (default)", ContStyle()),
    ("AsciiStyle", AsciiStyle()),  
    ("ContRoundStyle", ContRoundStyle()),
    ("DoubleStyle", DoubleStyle())
]

for name, style in styles:
    print(f"\n{name}:")
    print(RenderTree(root, style=style))

Output:

ContStyle (default):
root
├── child1
│   ├── grandchild1
│   └── grandchild2
└── child2
    └── grandchild3

AsciiStyle:
root
|-- child1
|   |-- grandchild1
|   +-- grandchild2
+-- child2
    +-- grandchild3

ContRoundStyle:
root
├─ child1
│  ├─ grandchild1
│  ╰─ grandchild2
╰─ child2
   ╰─ grandchild3

DoubleStyle:
root
╠══ child1
║   ╠══ grandchild1
║   ╚══ grandchild2
╚══ child2
    ╚══ grandchild3

Common Use Cases

Documentation Generation

from anytree import Node, RenderTree

def generate_api_tree(modules):
    """Generate API documentation tree"""
    root = Node("API Documentation")
    
    for module_name, functions in modules.items():
        module_node = Node(module_name, parent=root)
        for func_name in functions:
            Node(func_name, parent=module_node)
    
    return RenderTree(root)

modules = {
    "authentication": ["login", "logout", "verify_token"],
    "user_management": ["create_user", "update_user", "delete_user"],
    "data_processing": ["process_csv", "validate_data"]
}

print(generate_api_tree(modules))

File System Visualization

import os
from anytree import Node, RenderTree

def create_file_tree(path, max_depth=3):
    """Create tree representation of file system"""
    def add_path(parent, path, current_depth):
        if current_depth >= max_depth:
            return
            
        try:
            for item in os.listdir(path):
                item_path = os.path.join(path, item)
                node = Node(item, parent=parent)
                
                if os.path.isdir(item_path):
                    add_path(node, item_path, current_depth + 1)
        except PermissionError:
            pass
    
    root = Node(os.path.basename(path) or path)
    add_path(root, path, 0)
    return RenderTree(root)

# Visualize current directory structure
print(create_file_tree(".", max_depth=2))

Organizational Charts

from anytree import Node, RenderTree

class Employee(Node):
    def __init__(self, name, title, parent=None):
        super().__init__(name, parent=parent)
        self.title = title
    
    def __str__(self):
        return f"{self.name} ({self.title})"

# Build org chart
ceo = Employee("Alice Johnson", "CEO")
cto = Employee("Bob Smith", "CTO", parent=ceo)
cfo = Employee("Carol Davis", "CFO", parent=ceo)

Employee("David Wilson", "Senior Engineer", parent=cto)
Employee("Eve Brown", "DevOps Engineer", parent=cto)
Employee("Frank Miller", "Accountant", parent=cfo)

print("Organizational Chart:")
print(RenderTree(ceo))

Install with Tessl CLI

npx tessl i tessl/pypi-anytree

docs

import-export.md

index.md

node-construction.md

path-resolution.md

search.md

tree-iteration.md

tree-rendering.md

utilities.md

tile.json