or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

import-export.mdindex.mdnode-construction.mdpath-resolution.mdsearch.mdtree-iteration.mdtree-rendering.mdutilities.md

import-export.mddocs/

0

# Data Import and Export

1

2

Export tree structures to various formats (dict, JSON, DOT for Graphviz, Mermaid) and import from structured data formats for data exchange, visualization, and interoperability with other systems.

3

4

## Export Capabilities

5

6

### DictExporter - Dictionary Export

7

8

Export tree structures to Python dictionary format for serialization, data processing, or conversion to other formats.

9

10

```python { .api }

11

class DictExporter:

12

"""

13

Export tree to dictionary format.

14

15

Args:

16

dictcls: Dictionary class to use (default dict)

17

attriter: Function to filter/transform node attributes

18

childiter: Function to determine child iteration order (default list)

19

maxlevel: Maximum depth to export (default None - export all)

20

"""

21

def __init__(self, dictcls=dict, attriter=None, childiter=list, maxlevel=None): ...

22

23

def export(self, node): ...

24

```

25

26

**Usage Example:**

27

28

```python

29

from anytree import Node, DictExporter

30

31

# Create tree structure

32

root = Node("Company", founded=2020)

33

engineering = Node("Engineering", parent=root, budget=100000)

34

marketing = Node("Marketing", parent=root, budget=50000)

35

Node("Backend", parent=engineering, team_size=5)

36

Node("Frontend", parent=engineering, team_size=3)

37

38

# Basic dictionary export

39

exporter = DictExporter()

40

data = exporter.export(root)

41

print(data)

42

# {'children': [

43

# {'budget': 100000, 'children': [

44

# {'name': 'Backend', 'team_size': 5},

45

# {'name': 'Frontend', 'team_size': 3}

46

# ], 'name': 'Engineering'},

47

# {'budget': 50000, 'name': 'Marketing'}

48

# ], 'founded': 2020, 'name': 'Company'}

49

50

# Custom attribute filtering

51

def attr_filter(attrs):

52

# Only export specific attributes

53

return [(k, v) for k, v in attrs if k in ['name', 'budget']]

54

55

filtered_exporter = DictExporter(attriter=attr_filter)

56

filtered_data = filtered_exporter.export(root)

57

print(filtered_data) # Only name and budget attributes

58

59

# Limit export depth

60

shallow_exporter = DictExporter(maxlevel=2)

61

shallow_data = shallow_exporter.export(root)

62

print(f"Levels exported: {count_levels(shallow_data)}") # Max 2 levels

63

```

64

65

### JsonExporter - JSON Export

66

67

Export tree structures to JSON format for web APIs, configuration files, or data storage.

68

69

```python { .api }

70

class JsonExporter:

71

"""

72

Export tree to JSON format.

73

74

Args:

75

dictcls: Dictionary class to use (default dict)

76

attriter: Function to filter/transform node attributes

77

childiter: Function to determine child iteration order (default list)

78

maxlevel: Maximum depth to export (default None - export all)

79

**kwargs: Additional arguments passed to json.dumps()

80

"""

81

def __init__(self, dictcls=dict, attriter=None, childiter=list, maxlevel=None, **kwargs): ...

82

83

def export(self, node): ...

84

```

85

86

**Usage Example:**

87

88

```python

89

from anytree import Node, JsonExporter

90

import json

91

92

# Create tree with various data types

93

root = Node("API", version="1.0")

94

users = Node("users", parent=root, endpoints=["GET", "POST", "PUT"])

95

posts = Node("posts", parent=root, endpoints=["GET", "POST"])

96

Node("profile", parent=users, auth_required=True)

97

Node("settings", parent=users, auth_required=True)

98

99

# Basic JSON export

100

exporter = JsonExporter()

101

json_data = exporter.export(root)

102

print(json_data) # JSON string

103

104

# Pretty printed JSON

105

pretty_exporter = JsonExporter(indent=2, sort_keys=True)

106

pretty_json = pretty_exporter.export(root)

107

print(pretty_json)

108

109

# Parse back to dict for verification

110

parsed = json.loads(json_data)

111

print(f"Root name: {parsed['name']}")

112

print(f"Users endpoints: {parsed['children'][0]['endpoints']}")

113

```

114

115

### DotExporter - Graphviz DOT Export

116

117

Export tree structures to DOT format for visualization with Graphviz, creating professional tree diagrams and charts.

118

119

```python { .api }

120

class DotExporter:

121

"""

122

Export tree to Graphviz DOT format.

123

124

Args:

125

node: Root node for export

126

graph: Graph type ("digraph" or "graph")

127

name: Graph name

128

options: Global graph options

129

indent: Indentation string

130

nodenamefunc: Function to generate node names

131

nodeattrfunc: Function to generate node attributes

132

edgeattrfunc: Function to generate edge attributes

133

edgetypefunc: Function to determine edge types

134

"""

135

def __init__(self, node, graph="digraph", name="tree", options=None, indent=" ",

136

nodenamefunc=None, nodeattrfunc=None, edgeattrfunc=None, edgetypefunc=None): ...

137

138

def export(self, node): ...

139

def to_dotfile(self, filename): ...

140

def to_picture(self, filename, **kwargs): ...

141

```

142

143

**Usage Example:**

144

145

```python

146

from anytree import Node, DotExporter

147

148

# Create organizational tree

149

root = Node("CEO", title="Chief Executive")

150

cto = Node("CTO", parent=root, title="Chief Technology Officer")

151

cfo = Node("CFO", parent=root, title="Chief Financial Officer")

152

Node("Backend Lead", parent=cto, title="Senior Engineer")

153

Node("Frontend Lead", parent=cto, title="Senior Engineer")

154

Node("Accountant", parent=cfo, title="Financial Analyst")

155

156

# Basic DOT export

157

exporter = DotExporter(root)

158

dot_output = exporter.export(root)

159

print(dot_output)

160

161

# Custom node attributes for styling

162

def node_attr(node):

163

attrs = [f'label="{node.name}\\n{getattr(node, "title", "")}"']

164

if node.name == "CEO":

165

attrs.append('shape=box')

166

attrs.append('style=filled')

167

attrs.append('fillcolor=lightblue')

168

return ", ".join(attrs)

169

170

styled_exporter = DotExporter(root, nodeattrfunc=node_attr)

171

styled_dot = styled_exporter.export(root)

172

173

# Save to file and generate image

174

styled_exporter.to_dotfile("org_chart.dot")

175

styled_exporter.to_picture("org_chart.png", format="png", prog="dot")

176

```

177

178

### UniqueDotExporter - Unique Node DOT Export

179

180

DOT exporter that ensures unique node identifiers, useful for trees with duplicate node names.

181

182

```python { .api }

183

class UniqueDotExporter(DotExporter):

184

"""

185

DOT exporter ensuring unique node identifiers.

186

Handles cases where multiple nodes have the same name.

187

"""

188

def __init__(self, node, **kwargs): ...

189

```

190

191

**Usage Example:**

192

193

```python

194

from anytree import Node, UniqueDotExporter

195

196

# Tree with duplicate names

197

root = Node("Department")

198

team1 = Node("Team", parent=root, location="Building A")

199

team2 = Node("Team", parent=root, location="Building B")

200

Node("Member", parent=team1, employee_id=101)

201

Node("Member", parent=team2, employee_id=102)

202

203

# Regular exporter might have issues with duplicate names

204

unique_exporter = UniqueDotExporter(root)

205

unique_dot = unique_exporter.export(root)

206

print(unique_dot) # Each node gets unique identifier

207

```

208

209

### MermaidExporter - Mermaid Diagram Export

210

211

Export tree structures to Mermaid diagram format for modern web-based visualization and documentation.

212

213

```python { .api }

214

class MermaidExporter:

215

"""

216

Export tree to Mermaid diagram format.

217

218

Args:

219

indent: Indentation string

220

nodenamefunc: Function to generate node names

221

nodeattrfunc: Function to generate node attributes

222

edgeattrfunc: Function to generate edge attributes

223

"""

224

def __init__(self, indent=" ", nodenamefunc=None, nodeattrfunc=None, edgeattrfunc=None): ...

225

226

def export(self, node): ...

227

```

228

229

**Usage Example:**

230

231

```python

232

from anytree import Node, MermaidExporter

233

234

# Create process flow tree

235

root = Node("Start")

236

decision = Node("Decision", parent=root)

237

path_a = Node("Path A", parent=decision)

238

path_b = Node("Path B", parent=decision)

239

Node("End A", parent=path_a)

240

Node("End B", parent=path_b)

241

242

# Export to Mermaid format

243

exporter = MermaidExporter()

244

mermaid_output = exporter.export(root)

245

print(mermaid_output)

246

# graph TD

247

# Start --> Decision

248

# Decision --> "Path A"

249

# Decision --> "Path B"

250

# "Path A" --> "End A"

251

# "Path B" --> "End B"

252

253

# Custom node attributes

254

def node_attr(node):

255

if "End" in node.name:

256

return "shape=circle"

257

elif node.name == "Decision":

258

return "shape=diamond"

259

return ""

260

261

styled_exporter = MermaidExporter(nodeattrfunc=node_attr)

262

styled_mermaid = styled_exporter.export(root)

263

```

264

265

## Import Capabilities

266

267

### DictImporter - Dictionary Import

268

269

Import tree structures from Python dictionary format, useful for deserializing exported data or creating trees from configuration files.

270

271

```python { .api }

272

class DictImporter:

273

"""

274

Import tree from dictionary format.

275

276

Args:

277

nodecls: Node class to use for imported nodes (default AnyNode)

278

childiter: Attribute name for children list (default "children")

279

"""

280

def __init__(self, nodecls=AnyNode, childiter="children"): ...

281

282

def import_(self, data): ...

283

```

284

285

**Usage Example:**

286

287

```python

288

from anytree import DictImporter, RenderTree

289

290

# Dictionary data (e.g., from JSON file or API)

291

tree_data = {

292

"name": "Company",

293

"founded": 2020,

294

"children": [

295

{

296

"name": "Engineering",

297

"budget": 100000,

298

"children": [

299

{"name": "Backend", "team_size": 5},

300

{"name": "Frontend", "team_size": 3}

301

]

302

},

303

{

304

"name": "Marketing",

305

"budget": 50000,

306

"children": []

307

}

308

]

309

}

310

311

# Import dictionary to tree

312

importer = DictImporter()

313

root = importer.import_(tree_data)

314

315

print(RenderTree(root))

316

# AnyNode(founded=2020, name='Company')

317

# ├── AnyNode(budget=100000, name='Engineering')

318

# │ ├── AnyNode(name='Backend', team_size=5)

319

# │ └── AnyNode(name='Frontend', team_size=3)

320

# └── AnyNode(budget=50000, name='Marketing')

321

322

# Access imported attributes

323

print(f"Company founded: {root.founded}")

324

engineering = root.children[0]

325

print(f"Engineering budget: ${engineering.budget}")

326

```

327

328

### JsonImporter - JSON Import

329

330

Import tree structures from JSON format, combining JSON parsing with dictionary import for direct JSON-to-tree conversion.

331

332

```python { .api }

333

class JsonImporter:

334

"""

335

Import tree from JSON format.

336

337

Args:

338

nodecls: Node class to use for imported nodes (default AnyNode)

339

childiter: Attribute name for children list (default "children")

340

"""

341

def __init__(self, nodecls=AnyNode, childiter="children"): ...

342

343

def import_(self, data): ...

344

```

345

346

**Usage Example:**

347

348

```python

349

from anytree import JsonImporter, Node, RenderTree

350

import json

351

352

# JSON string (e.g., from file or API response)

353

json_data = '''

354

{

355

"name": "Project",

356

"version": "1.0.0",

357

"children": [

358

{

359

"name": "src",

360

"type": "directory",

361

"children": [

362

{"name": "main.py", "type": "file", "size": 1024},

363

{"name": "utils.py", "type": "file", "size": 512}

364

]

365

},

366

{

367

"name": "tests",

368

"type": "directory",

369

"children": [

370

{"name": "test_main.py", "type": "file", "size": 256}

371

]

372

}

373

]

374

}

375

'''

376

377

# Import JSON to tree

378

importer = JsonImporter()

379

root = importer.import_(json_data)

380

381

print(RenderTree(root))

382

# AnyNode(name='Project', version='1.0.0')

383

# ├── AnyNode(name='src', type='directory')

384

# │ ├── AnyNode(name='main.py', size=1024, type='file')

385

# │ └── AnyNode(name='utils.py', size=512, type='file')

386

# └── AnyNode(name='tests', type='directory')

387

# └── AnyNode(name='test_main.py', size=256, type='file')

388

389

# Custom node class

390

class FileNode(Node):

391

def __str__(self):

392

if self.type == "file":

393

return f"{self.name} ({self.size} bytes)"

394

return self.name

395

396

custom_importer = JsonImporter(nodecls=FileNode)

397

custom_root = custom_importer.import_(json_data)

398

print(RenderTree(custom_root))

399

```

400

401

## Advanced Import/Export Patterns

402

403

### Round-trip Conversion

404

405

Export and re-import data to verify integrity:

406

407

```python

408

from anytree import Node, DictExporter, DictImporter, RenderTree

409

410

# Original tree

411

original = Node("root")

412

Node("child1", parent=original, value=42)

413

Node("child2", parent=original, value=24)

414

415

print("Original:")

416

print(RenderTree(original))

417

418

# Export to dict

419

exporter = DictExporter()

420

data = exporter.export(original)

421

422

# Import back from dict

423

importer = DictImporter()

424

restored = importer.import_(data)

425

426

print("\nRestored:")

427

print(RenderTree(restored))

428

429

# Verify integrity

430

def tree_equals(node1, node2):

431

if node1.name != node2.name:

432

return False

433

if len(node1.children) != len(node2.children):

434

return False

435

return all(tree_equals(c1, c2) for c1, c2 in zip(node1.children, node2.children))

436

437

print(f"Trees equal: {tree_equals(original, restored)}")

438

```

439

440

### Custom Attribute Handling

441

442

Control which attributes are exported and how they're processed:

443

444

```python

445

from anytree import Node, DictExporter, DictImporter

446

447

class CustomNode(Node):

448

def __init__(self, name, **kwargs):

449

# Separate public and private attributes

450

super().__init__(name)

451

self.public_data = {}

452

self.private_data = {}

453

454

for key, value in kwargs.items():

455

if key.startswith('_'):

456

self.private_data[key] = value

457

else:

458

self.public_data[key] = value

459

460

# Create tree with mixed attributes

461

root = CustomNode("root", config="public", _secret="private")

462

child = CustomNode("child", parent=root, setting="visible", _internal="hidden")

463

464

# Export only public attributes

465

def public_attrs_only(attrs):

466

return [(k, v) for k, v in attrs if not k.startswith('_') and k != 'private_data']

467

468

exporter = DictExporter(attriter=public_attrs_only)

469

public_data = exporter.export(root)

470

print("Public data only:", public_data)

471

```

472

473

### Batch Processing

474

475

Process multiple trees or large datasets efficiently:

476

477

```python

478

from anytree import Node, JsonExporter, JsonImporter

479

import json

480

481

def process_tree_batch(tree_list, output_file):

482

"""Export multiple trees to single JSON file"""

483

exporter = JsonExporter()

484

batch_data = []

485

486

for tree in tree_list:

487

tree_data = json.loads(exporter.export(tree))

488

batch_data.append(tree_data)

489

490

with open(output_file, 'w') as f:

491

json.dump(batch_data, f, indent=2)

492

493

def import_tree_batch(input_file):

494

"""Import multiple trees from JSON file"""

495

importer = JsonImporter()

496

497

with open(input_file, 'r') as f:

498

batch_data = json.load(f)

499

500

trees = []

501

for tree_data in batch_data:

502

tree_json = json.dumps(tree_data)

503

tree = importer.import_(tree_json)

504

trees.append(tree)

505

506

return trees

507

508

# Example usage

509

trees = [

510

Node("Tree1", children=[Node("A"), Node("B")]),

511

Node("Tree2", children=[Node("X"), Node("Y")]),

512

]

513

514

process_tree_batch(trees, "trees.json")

515

restored_trees = import_tree_batch("trees.json")

516

```

517

518

### Legacy Format Support

519

520

Handle different data formats and schemas:

521

522

```python

523

from anytree import DictImporter, Node

524

525

class LegacyImporter(DictImporter):

526

"""Import from legacy format with different field names"""

527

528

def import_(self, data):

529

# Convert legacy format to standard format

530

converted = self._convert_legacy_format(data)

531

return super().import_(converted)

532

533

def _convert_legacy_format(self, node_data):

534

"""Convert old field names to new format"""

535

if isinstance(node_data, dict):

536

converted = {}

537

538

# Map old field names to new ones

539

field_mapping = {

540

'title': 'name',

541

'subnodes': 'children',

542

'properties': 'attributes'

543

}

544

545

for old_key, value in node_data.items():

546

new_key = field_mapping.get(old_key, old_key)

547

548

if new_key == 'children' and isinstance(value, list):

549

converted[new_key] = [self._convert_legacy_format(child) for child in value]

550

else:

551

converted[new_key] = value

552

553

return converted

554

return node_data

555

556

# Legacy data format

557

legacy_data = {

558

"title": "Old Root",

559

"properties": {"version": "1.0"},

560

"subnodes": [

561

{"title": "Old Child 1", "properties": {"type": "folder"}},

562

{"title": "Old Child 2", "properties": {"type": "file"}}

563

]

564

}

565

566

# Import using legacy converter

567

legacy_importer = LegacyImporter()

568

tree = legacy_importer.import_(legacy_data)

569

print(f"Imported root: {tree.name}") # "Old Root"

570

```

571

572

## Visualization Integration

573

574

### Graphviz Integration

575

576

Generate publication-quality diagrams:

577

578

```python

579

from anytree import Node, DotExporter

580

import subprocess

581

582

def create_org_chart():

583

# Create organizational structure

584

ceo = Node("Alice Johnson", title="CEO", level="C-Level")

585

cto = Node("Bob Smith", parent=ceo, title="CTO", level="C-Level")

586

cfo = Node("Carol Davis", parent=ceo, title="CFO", level="C-Level")

587

588

# Engineering team

589

senior_eng = Node("David Wilson", parent=cto, title="Senior Engineer", level="Senior")

590

junior_eng = Node("Eve Brown", parent=cto, title="Junior Engineer", level="Junior")

591

592

# Finance team

593

accountant = Node("Frank Miller", parent=cfo, title="Accountant", level="Associate")

594

595

return ceo

596

597

def generate_styled_chart(root, filename):

598

def node_attrs(node):

599

attrs = [f'label="{node.name}\\n{node.title}"']

600

601

# Color by level

602

colors = {

603

"C-Level": "lightblue",

604

"Senior": "lightgreen",

605

"Junior": "lightyellow",

606

"Associate": "lightpink"

607

}

608

609

if hasattr(node, 'level'):

610

attrs.append(f'fillcolor={colors.get(node.level, "white")}')

611

attrs.append('style=filled')

612

613

return ", ".join(attrs)

614

615

exporter = DotExporter(root,

616

nodeattrfunc=node_attrs,

617

options=['rankdir=TB', 'node [shape=box]'])

618

619

# Generate PNG

620

exporter.to_picture(f"{filename}.png", format="png", prog="dot")

621

622

# Generate SVG for web use

623

exporter.to_picture(f"{filename}.svg", format="svg", prog="dot")

624

625

# Create and export chart

626

org_root = create_org_chart()

627

generate_styled_chart(org_root, "org_chart")

628

```

629

630

### Web Integration

631

632

Export for web-based visualization:

633

634

```python

635

from anytree import Node, JsonExporter

636

import json

637

638

def create_interactive_data(root):

639

"""Prepare tree data for D3.js or similar libraries"""

640

641

def add_ui_attributes(attrs):

642

# Add attributes needed for interactive visualization

643

enhanced = list(attrs)

644

enhanced.extend([

645

('id', f"node_{hash(attrs)}"),

646

('collapsed', False),

647

('selected', False)

648

])

649

return enhanced

650

651

exporter = JsonExporter(attriter=add_ui_attributes, indent=2)

652

json_data = exporter.export(root)

653

654

# Wrap in format expected by visualization libraries

655

wrapped_data = {

656

"version": "1.0",

657

"tree": json.loads(json_data),

658

"metadata": {

659

"node_count": len(list(root.descendants)) + 1,

660

"max_depth": root.height,

661

"created": "2024-01-01T00:00:00Z"

662

}

663

}

664

665

return json.dumps(wrapped_data, indent=2)

666

667

# Generate interactive data

668

tree_root = Node("Interactive Root")

669

Node("Branch 1", parent=tree_root, category="primary")

670

Node("Branch 2", parent=tree_root, category="secondary")

671

672

interactive_json = create_interactive_data(tree_root)

673

print(interactive_json)

674

```