CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/pypi-treelib

A Python implementation of tree data structure with hierarchical organization and efficient operations for traversal, modification, search, and visualization.

Overview
Eval results
Files

visualization.mddocs/

Tree Visualization and Display

Comprehensive functionality for visualizing and displaying tree structures with customizable formats, line styles, filtering options, and export capabilities. Provides rich text-based tree representations optimized for console output and documentation.

Capabilities

Tree Display

Display tree structure with customizable formatting, filtering, and sorting options.

def show(nid=None, level=ROOT, idhidden=True, filter=None, key=None, 
         reverse=False, line_type="ascii-ex", data_property=None, 
         stdout=True, sorting=True) -> str | None:
    """
    Display tree structure with customizable formatting.
    
    Parameters:
    - nid: str, root node for subtree display (default: entire tree)
    - level: int, starting level for display (ROOT, or specific level)
    - idhidden: bool, hide node identifiers in output
    - filter: callable, function to filter nodes (node) -> bool
    - key: callable, function for sorting nodes (node) -> comparable
    - reverse: bool, reverse sort order
    - line_type: str, line drawing style ("ascii-ex", "ascii-em", etc.)
    - data_property: str, node data property to display
    - stdout: bool, print to console if True, return string if False
    - sorting: bool, enable/disable sorting
    
    Returns:
    str if stdout=False, None if stdout=True
    """

Usage Examples:

# Basic tree display
tree.show()

# Display specific subtree
tree.show(nid="engineering")

# Show with node identifiers
tree.show(idhidden=False)

# Custom line style
tree.show(line_type="ascii-em")

# Display with filtering
tree.show(filter=lambda node: node.is_leaf(tree.identifier))

# Sorted display
tree.show(key=lambda node: node.tag.lower(), reverse=True)

# Show specific data property
tree.show(data_property="role", idhidden=False)

# Get display as string
tree_display = tree.show(stdout=False)
print("Tree structure:")
print(tree_display)

# Combined options
tree.show(
    nid="company",
    idhidden=False,
    line_type="ascii-em",
    key=lambda node: node.tag,
    filter=lambda node: not node.is_leaf(tree.identifier)  # Non-leaf nodes only
)

Line Drawing Styles

Multiple line drawing styles for different visual preferences and contexts.

Available Line Types:

# ASCII Extended (default)
tree.show(line_type="ascii-ex")
# Output:
# Root
# ├── Child A
# │   └── Grandchild
# └── Child B

# ASCII Emphasized
tree.show(line_type="ascii-em")
# Output:
# Root
# +-- Child A
# |   `-- Grandchild
# `-- Child B

# ASCII Expanded Plus
tree.show(line_type="ascii-exr")
# Root
# +-- Child A
# |   +-- Grandchild
# +-- Child B

# ASCII Plus
tree.show(line_type="ascii-emh")
# Root
# +-- Child A
# |   +-- Grandchild
# +-- Child B

# ASCII Dotted
tree.show(line_type="ascii-emv")
# Root
# :-- Child A
# :   :-- Grandchild
# :-- Child B

Usage Examples:

# Compare different styles
styles = ["ascii-ex", "ascii-em", "ascii-exr", "ascii-emh", "ascii-emv"]

for style in styles:
    print(f"\n=== {style.upper()} ===")
    tree.show(line_type=style)

# Choose style based on context
def display_for_context(tree, context="console"):
    """Display tree with appropriate style for context."""
    style_map = {
        "console": "ascii-ex",      # Best for terminal
        "documentation": "ascii-em", # Clean for docs
        "email": "ascii-emh",       # Plain ASCII for email
        "presentation": "ascii-ex"   # Professional look
    }
    
    style = style_map.get(context, "ascii-ex")
    tree.show(line_type=style)

display_for_context(tree, "documentation")

File Output

Save tree visualizations to files for documentation and reporting.

def save2file(filename, nid=None, level=ROOT, idhidden=True, filter=None, 
              key=None, reverse=False, line_type="ascii-ex", 
              data_property=None, sorting=True) -> None:
    """
    Save tree display to file.
    
    Parameters:
    - filename: str, output filename
    - (other parameters same as show() method)
    """

Usage Examples:

# Save basic tree structure
tree.save2file("organization.txt")

# Save with custom formatting
tree.save2file(
    "org_detailed.txt",
    idhidden=False,
    line_type="ascii-em",
    data_property="role"
)

# Save filtered view
tree.save2file(
    "managers_only.txt",
    filter=lambda node: node.data and node.data.get("is_manager", False)
)

# Save subtree
tree.save2file("engineering_dept.txt", nid="engineering")

# Generate multiple report formats
def generate_tree_reports(tree, base_filename):
    """Generate multiple tree visualization reports."""
    reports = {
        "full": {"filter": None, "description": "Complete organization"},
        "managers": {
            "filter": lambda n: n.data and n.data.get("is_manager", False),
            "description": "Management hierarchy"
        },
        "leaves": {
            "filter": lambda n: n.is_leaf(tree.identifier),
            "description": "Individual contributors"
        }
    }
    
    for report_type, config in reports.items():
        filename = f"{base_filename}_{report_type}.txt"
        tree.save2file(
            filename,
            filter=config["filter"],
            idhidden=False
        )
        print(f"Generated {filename}: {config['description']}")

generate_tree_reports(tree, "org_report")

Advanced Display Filtering

Sophisticated filtering and conditional display logic.

Usage Examples:

# Multi-condition filtering
def complex_filter(node):
    """Complex filtering logic."""
    if not node.data:
        return True  # Show nodes without data
    
    # Show if high salary or manager
    salary = node.data.get("salary", 0)
    is_manager = node.data.get("is_manager", False)
    
    return salary > 100000 or is_manager

tree.show(filter=complex_filter)

# Level-based filtering
def show_levels(tree, max_level=2):
    """Show only nodes up to specified level."""
    tree.show(filter=lambda node: tree.level(node.identifier) <= max_level)

show_levels(tree, max_level=3)

# Department-specific views
departments = ["engineering", "sales", "hr"]
for dept in departments:
    if dept in tree:
        print(f"\n=== {dept.upper()} DEPARTMENT ===")
        tree.show(
            nid=dept,
            filter=lambda node: node.identifier != dept  # Exclude dept header
        )

# Dynamic filtering based on node properties
def show_by_role(tree, target_role):
    """Show only nodes with specific role."""
    tree.show(
        filter=lambda node: (
            node.data and 
            node.data.get("role", "").lower() == target_role.lower()
        ),
        key=lambda node: node.tag
    )

show_by_role(tree, "engineer")

Custom Display Formatting

Advanced formatting and customization options.

Usage Examples:

# Display with custom data formatting
def show_with_salary(tree):
    """Display tree with salary information."""
    def format_node_with_salary(node):
        if node.data and "salary" in node.data:
            return f"{node.tag} (${node.data['salary']:,})"
        return node.tag
    
    # Temporarily modify tags for display
    original_tags = {}
    for node_id in tree.expand_tree():
        node = tree[node_id]
        original_tags[node_id] = node.tag
        node.tag = format_node_with_salary(node)
    
    tree.show()
    
    # Restore original tags
    for node_id, original_tag in original_tags.items():
        tree[node_id].tag = original_tag

show_with_salary(tree)

# Create hierarchical summary
def show_summary(tree):
    """Display tree with summary statistics."""
    print("ORGANIZATION SUMMARY")
    print("=" * 50)
    
    for node_id in tree.expand_tree():
        node = tree[node_id]
        level = tree.level(node_id)
        children_count = len(tree.children(node_id))
        
        indent = "  " * level
        summary = f"{indent}{node.tag}"
        
        if children_count > 0:
            summary += f" ({children_count} direct reports)"
        
        if node.data and "salary" in node.data:
            summary += f" - ${node.data['salary']:,}"
        
        print(summary)

show_summary(tree)

# Interactive display with user filtering
def interactive_tree_display(tree):
    """Interactive tree display with user-controlled filtering."""
    while True:
        print("\nTree Display Options:")
        print("1. Show full tree")
        print("2. Show by level")
        print("3. Show by role")
        print("4. Show leaves only")
        print("5. Exit")
        
        choice = input("Choose option (1-5): ").strip()
        
        if choice == "1":
            tree.show()
        elif choice == "2":
            max_level = int(input("Enter max level: "))
            tree.show(filter=lambda n: tree.level(n.identifier) <= max_level)
        elif choice == "3":
            role = input("Enter role to filter: ")
            tree.show(filter=lambda n: n.data and role.lower() in n.data.get("role", "").lower())
        elif choice == "4":
            tree.show(filter=lambda n: n.is_leaf(tree.identifier))
        elif choice == "5":
            break
        else:
            print("Invalid choice")

# interactive_tree_display(tree)  # Uncomment for interactive use

Display Constants and Options

Available constants and configuration options for tree display.

ROOT = 0  # Display starting from root level

# Line type options:
# "ascii-ex"  - ASCII Extended (├── └──)
# "ascii-em"  - ASCII Emphasized (+-- `--)  
# "ascii-exr" - ASCII Extended Right (+-- +--)
# "ascii-emh" - ASCII Emphasized Horizontal (+-- +--)
# "ascii-emv" - ASCII Emphasized Vertical (:-- :--)

Performance Optimization for Large Trees

Efficient display strategies for large tree structures.

Usage Examples:

# Lazy display for large trees
def display_large_tree_paginated(tree, page_size=50):
    """Display large tree in pages."""
    all_nodes = list(tree.expand_tree())
    total_pages = (len(all_nodes) + page_size - 1) // page_size
    
    for page in range(total_pages):
        start_idx = page * page_size
        end_idx = min(start_idx + page_size, len(all_nodes))
        page_nodes = set(all_nodes[start_idx:end_idx])
        
        print(f"\n=== Page {page + 1}/{total_pages} ===")
        tree.show(filter=lambda node: node.identifier in page_nodes)
        
        if page < total_pages - 1:
            input("Press Enter for next page...")

# Abbreviated display for overview
def show_tree_summary_levels(tree, max_children_shown=5):
    """Show tree with limited children per node."""
    def limited_children_filter(node):
        parent = tree.parent(node.identifier)
        if parent:
            siblings = tree.children(parent.identifier)
            node_index = next(i for i, sibling in enumerate(siblings) 
                            if sibling.identifier == node.identifier)
            return node_index < max_children_shown
        return True
    
    tree.show(filter=limited_children_filter)
    
    # Show counts of hidden nodes
    for node_id in tree.expand_tree():
        children = tree.children(node_id)
        if len(children) > max_children_shown:
            hidden_count = len(children) - max_children_shown
            level = tree.level(node_id)
            indent = "  " * (level + 1)
            print(f"{indent}... and {hidden_count} more")

show_tree_summary_levels(tree, max_children_shown=3)

# Memory-efficient display streaming
def stream_tree_display(tree, chunk_size=100):
    """Stream tree display for very large trees."""
    nodes_processed = 0
    current_chunk = []
    
    for node_id in tree.expand_tree():
        current_chunk.append(node_id)
        nodes_processed += 1
        
        if len(current_chunk) >= chunk_size:
            # Display current chunk
            chunk_set = set(current_chunk)
            tree.show(filter=lambda node: node.identifier in chunk_set)
            current_chunk = []
            print(f"\n--- Processed {nodes_processed} nodes ---\n")
    
    # Display remaining nodes
    if current_chunk:
        chunk_set = set(current_chunk)
        tree.show(filter=lambda node: node.identifier in chunk_set)

# Usage for large trees
if len(tree) > 1000:
    display_large_tree_paginated(tree)
else:
    tree.show()

Install with Tessl CLI

npx tessl i tessl/pypi-treelib

docs

data-export.md

index.md

tree-construction.md

tree-modification.md

tree-traversal.md

visualization.md

tile.json