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

data-export.mddocs/

Data Export and Import

Comprehensive functionality for exporting tree structures to various formats including JSON, dictionaries, and GraphViz DOT files. Enables integration with other systems, data persistence, and visualization workflows.

Capabilities

JSON Export

Export tree structure and data to JSON format for serialization and data exchange.

def to_json(with_data=False, sort=True, reverse=False) -> str:
    """
    Export tree structure to JSON string.
    
    Parameters:
    - with_data: bool, include node data in output
    - sort: bool, sort nodes by tag for consistent output
    - reverse: bool, reverse sort order
    
    Returns:
    str, JSON representation of tree structure
    """

Usage Examples:

# Basic JSON export (structure only)
json_structure = tree.to_json()
print(json_structure)

# Export with node data included
json_with_data = tree.to_json(with_data=True)

# Sorted export for consistent output
json_sorted = tree.to_json(sort=True, reverse=False)

# Save to file
import json
tree_data = json.loads(tree.to_json(with_data=True))
with open("organization.json", "w") as f:
    json.dump(tree_data, f, indent=2)

# Load and process JSON data
import json
json_str = tree.to_json(with_data=True)
parsed_data = json.loads(json_str)
print(f"Root node: {parsed_data}")

Dictionary Export

Convert tree to nested dictionary structure for programmatic manipulation.

def to_dict(nid=None, key=None, sort=True, reverse=False, with_data=False) -> dict:
    """
    Convert tree to nested dictionary representation.
    
    Parameters:
    - nid: str, root node for subtree export (default: entire tree)
    - key: callable, function for sorting nodes (node) -> comparable
    - sort: bool, sort nodes for consistent output
    - reverse: bool, reverse sort order
    - with_data: bool, include node data in output
    
    Returns:
    dict, nested dictionary representation of tree
    """

Usage Examples:

# Export entire tree to dictionary
tree_dict = tree.to_dict()
print(tree_dict)

# Export specific subtree
dept_dict = tree.to_dict(nid="engineering")

# Export with custom sorting
sorted_dict = tree.to_dict(
    key=lambda node: node.tag.lower(),
    sort=True
)

# Export with node data
data_dict = tree.to_dict(with_data=True)

# Process dictionary data
def analyze_tree_dict(tree_dict, level=0):
    """Recursively analyze tree dictionary."""
    indent = "  " * level
    for key, value in tree_dict.items():
        print(f"{indent}{key}")
        if isinstance(value, dict):
            analyze_tree_dict(value, level + 1)

analyze_tree_dict(tree.to_dict())

# Convert to pandas DataFrame for analysis
import pandas as pd

def tree_to_dataframe(tree_dict, parent=None, level=0):
    """Convert tree dictionary to flat DataFrame."""
    rows = []
    for key, children in tree_dict.items():
        row = {"node": key, "parent": parent, "level": level}
        rows.append(row)
        if isinstance(children, dict):
            rows.extend(tree_to_dataframe(children, key, level + 1))
    return rows

df = pd.DataFrame(tree_to_dataframe(tree.to_dict()))
print(df)

GraphViz DOT Export

Export tree to GraphViz DOT format for advanced graph visualization and layout.

def to_graphviz(filename=None, shape="circle", graph="digraph", filter=None, 
               key=None, reverse=False, sorting=True) -> None:
    """
    Export tree to GraphViz DOT format.
    
    Parameters:
    - filename: str, output filename (prints to stdout if None)
    - shape: str, node shape ("circle", "box", "ellipse", etc.)
    - graph: str, graph type ("digraph" or "graph")
    - filter: callable, function to filter nodes (node) -> bool
    - key: callable, function for sorting nodes (node) -> comparable
    - reverse: bool, reverse sort order
    - sorting: bool, enable/disable sorting
    """

Usage Examples:

# Export to GraphViz DOT format
tree.to_graphviz("organization.dot")

# Customize node appearance
tree.to_graphviz("org_boxes.dot", shape="box")

# Create undirected graph
tree.to_graphviz("org_undirected.dot", graph="graph")

# Export with filtering
tree.to_graphviz(
    "managers_only.dot",
    filter=lambda node: node.data and node.data.get("is_manager", False)
)

# Generate and view GraphViz output
import subprocess
import os

# Export to DOT file
tree.to_graphviz("tree.dot", shape="box")

# Generate SVG using GraphViz
if os.system("which dot") == 0:  # Check if GraphViz installed
    subprocess.run(["dot", "-Tsvg", "tree.dot", "-o", "tree.svg"])
    print("Generated tree.svg")

# Custom DOT generation for complex styling
def custom_graphviz_export(tree, filename):
    """Generate custom DOT file with advanced styling."""
    with open(filename, "w") as f:
        f.write("digraph Tree {\n")
        f.write("  node [fontname=\"Arial\"];\n")
        f.write("  edge [color=gray];\n")
        
        for node_id in tree.expand_tree():
            node = tree[node_id]
            # Custom node styling based on data
            if node.data and node.data.get("role") == "manager":
                style = "filled,style=filled,color=lightblue"
            else:
                style = "filled,style=filled,color=lightgray"
            
            f.write(f'  "{node_id}" [label="{node.tag}",{style}];\n')
            
            # Add edges
            children = tree.children(node_id)
            for child in children:
                f.write(f'  "{node_id}" -> "{child.identifier}";\n')
        
        f.write("}\n")

custom_graphviz_export(tree, "custom_tree.dot")

Tree Construction from Data

Create trees from various data formats and sources.

@classmethod
def from_map(cls, child_parent_dict, id_func=None, data_func=None) -> Tree:
    """
    Create tree from child-parent mapping dictionary.
    
    Parameters:
    - child_parent_dict: dict, mapping of child -> parent relationships
    - id_func: callable, function to generate node identifiers from keys
    - data_func: callable, function to generate node data from keys
    
    Returns:
    Tree, constructed tree object
    """

Usage Examples:

# Create tree from relationship mapping
org_structure = {
    "alice": "engineering",
    "bob": "engineering",
    "carol": "sales",
    "dave": "sales",
    "engineering": "company",
    "sales": "company",
    "company": None  # Root node
}

tree = Tree.from_map(org_structure)

# With custom ID function
file_structure = {
    "/home/user/doc.txt": "/home/user",
    "/home/user/photo.jpg": "/home/user", 
    "/home/user": "/home",
    "/home": None
}

file_tree = Tree.from_map(
    file_structure,
    id_func=lambda path: path.replace("/", "_").strip("_")
)

# With data function
employee_data = {
    "alice": {"role": "engineer", "salary": 120000},
    "bob": {"role": "engineer", "salary": 110000},
    "carol": {"role": "sales", "salary": 95000}
}

org_mapping = {
    "alice": "engineering",
    "bob": "engineering", 
    "carol": "sales",
    "engineering": "company",
    "sales": "company",
    "company": None
}

tree_with_data = Tree.from_map(
    org_mapping,
    data_func=lambda name: employee_data.get(name, {})
)

Data Persistence and Serialization

Save and load tree structures for persistence and backup.

Usage Examples:

import json
import pickle
from datetime import datetime

# JSON persistence
def save_tree_json(tree, filename):
    """Save tree to JSON file with metadata."""
    tree_data = {
        "metadata": {
            "created": datetime.now().isoformat(),
            "node_count": len(tree),
            "tree_depth": tree.depth()
        },
        "structure": json.loads(tree.to_json()),
        "data": {}
    }
    
    # Save node data separately
    for node_id in tree.expand_tree():
        node = tree[node_id]
        if node.data:
            tree_data["data"][node_id] = node.data
    
    with open(filename, "w") as f:
        json.dump(tree_data, f, indent=2)

def load_tree_json(filename):
    """Load tree from JSON file."""
    with open(filename, "r") as f:
        tree_data = json.load(f)
    
    # Reconstruct tree from structure
    # (Implementation would depend on JSON structure format)
    print(f"Loaded tree with {tree_data['metadata']['node_count']} nodes")
    return tree_data

# Binary persistence with pickle
def save_tree_pickle(tree, filename):
    """Save tree using pickle for exact preservation."""
    with open(filename, "wb") as f:
        pickle.dump(tree, f)

def load_tree_pickle(filename):
    """Load tree from pickle file."""
    with open(filename, "rb") as f:
        return pickle.load(f)

# Usage
save_tree_json(tree, "organization.json")
save_tree_pickle(tree, "organization.pkl")

loaded_tree = load_tree_pickle("organization.pkl")

Format Conversion and Integration

Convert between different tree formats and integrate with external systems.

Usage Examples:

# Convert to networkx graph
try:
    import networkx as nx
    
    def tree_to_networkx(tree):
        """Convert treelib Tree to networkx DiGraph."""
        G = nx.DiGraph()
        
        for node_id in tree.expand_tree():
            node = tree[node_id]
            G.add_node(node_id, 
                      tag=node.tag, 
                      data=node.data)
            
            parent = tree.parent(node_id)
            if parent:
                G.add_edge(parent.identifier, node_id)
        
        return G
    
    nx_graph = tree_to_networkx(tree)
    print(f"NetworkX graph with {nx_graph.number_of_nodes()} nodes")
    
except ImportError:
    print("NetworkX not available")

# Export to CSV for spreadsheet analysis
import csv

def tree_to_csv(tree, filename):
    """Export tree to CSV with hierarchical information."""
    with open(filename, "w", newline="") as f:
        writer = csv.writer(f)
        writer.writerow(["node_id", "tag", "parent_id", "level", "is_leaf", "data"])
        
        for node_id in tree.expand_tree():
            node = tree[node_id]
            parent = tree.parent(node_id)
            parent_id = parent.identifier if parent else None
            
            writer.writerow([
                node_id,
                node.tag,
                parent_id,
                tree.level(node_id),
                node.is_leaf(tree.identifier),
                str(node.data) if node.data else ""
            ])

tree_to_csv(tree, "organization.csv")

# Import from external hierarchical data
def import_from_filesystem(root_path):
    """Create tree from filesystem structure."""
    import os
    
    tree = Tree()
    tree.create_node(root_path, root_path)
    
    def add_directory_tree(parent_path, parent_id):
        try:
            for item in os.listdir(parent_path):
                item_path = os.path.join(parent_path, item)
                item_id = item_path
                
                if os.path.isdir(item_path):
                    tree.create_node(f"📁 {item}", item_id, parent=parent_id)
                    add_directory_tree(item_path, item_id)
                else:
                    tree.create_node(f"📄 {item}", item_id, parent=parent_id)
        except PermissionError:
            pass  # Skip inaccessible directories
    
    add_directory_tree(root_path, root_path)
    return tree

# Usage
fs_tree = import_from_filesystem("/tmp")
fs_tree.show()

Advanced Export Patterns

Sophisticated export scenarios for complex use cases.

Usage Examples:

# Multi-format export pipeline
def export_tree_all_formats(tree, base_filename):
    """Export tree to multiple formats."""
    formats = {
        "json": lambda: tree.to_json(with_data=True),
        "dict": lambda: str(tree.to_dict(with_data=True)),
        "dot": lambda: tree.to_graphviz(f"{base_filename}.dot")
    }
    
    results = {}
    for fmt, export_func in formats.items():
        try:
            if fmt == "dot":
                export_func()  # Writes to file
                results[fmt] = f"{base_filename}.dot"
            else:
                content = export_func()
                filename = f"{base_filename}.{fmt}"
                with open(filename, "w") as f:
                    f.write(content)
                results[fmt] = filename
        except Exception as e:
            results[fmt] = f"Error: {e}"
    
    return results

# Incremental export for large trees
def export_tree_incremental(tree, chunk_size=1000):
    """Export large tree in chunks."""
    all_nodes = list(tree.expand_tree())
    chunks = [all_nodes[i:i+chunk_size] for i in range(0, len(all_nodes), chunk_size)]
    
    for i, chunk in enumerate(chunks):
        chunk_data = {}
        for node_id in chunk:
            node = tree[node_id]
            chunk_data[node_id] = {
                "tag": node.tag,
                "data": node.data,
                "parent": tree.parent(node_id).identifier if tree.parent(node_id) else None
            }
        
        with open(f"tree_chunk_{i}.json", "w") as f:
            json.dump(chunk_data, f, indent=2)
    
    print(f"Exported {len(chunks)} chunks")

# Usage
export_results = export_tree_all_formats(tree, "organization")
print("Export results:", export_results)

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