or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

graph-visualization.mdgrowth-analysis.mdindex.mdobject-discovery.mdobject-statistics.mdreference-chains.md

graph-visualization.mddocs/

0

# Graph Visualization

1

2

Generate visual representations of object reference graphs using graphviz. These functions create diagrams showing how objects reference each other, essential for understanding memory layouts, debugging circular references, and visualizing object relationships.

3

4

## Capabilities

5

6

### Backward Reference Visualization

7

8

Generate graphs showing what objects refer to the target objects.

9

10

```python { .api }

11

def show_backrefs(objs, max_depth=3, extra_ignore=(), filter=None, too_many=10, highlight=None, filename=None, extra_info=None, refcounts=False, shortnames=True, output=None, extra_node_attrs=None):

12

"""

13

Generate an object reference graph ending at objs.

14

15

Args:

16

objs: Single object or list of objects to analyze

17

max_depth (int): Maximum graph depth to traverse

18

extra_ignore (tuple): Object IDs to ignore in the graph

19

filter (callable, optional): Function taking object and returning bool; objects returning False are excluded

20

too_many (int): Limit for references per object before truncating

21

highlight (callable, optional): Function taking object and returning bool; matching objects highlighted in blue

22

filename (str, optional): Output file name (.dot, .png, .svg, etc.)

23

extra_info (callable, optional): Function taking object and returning string for extra node information

24

refcounts (bool): Show reference counts in node labels

25

shortnames (bool): Use short class names vs fully qualified names

26

output (file-like, optional): File object to write GraphViz output

27

extra_node_attrs (callable, optional): Function taking object and returning dict of GraphViz node attributes

28

29

Returns:

30

None or graphviz.Source: None for file output, Source object for interactive display

31

32

Note:

33

Shows what refers to the objects. Automatically stops at proper modules to avoid clutter.

34

Cannot specify both filename and output parameters (raises ValueError).

35

"""

36

```

37

38

Usage examples:

39

40

```python

41

import objgraph

42

43

# Basic backref visualization

44

my_object = [1, 2, 3]

45

objgraph.show_backrefs([my_object]) # Interactive display or xdot

46

47

# Save to file

48

objgraph.show_backrefs([my_object], filename='my_backrefs.png')

49

50

# Multiple objects

51

obj1 = {'key': 'value'}

52

obj2 = [1, 2, 3]

53

objgraph.show_backrefs([obj1, obj2], filename='multi_backrefs.png')

54

55

# Advanced filtering

56

def is_interesting(obj):

57

return not isinstance(obj, (str, int, float, bool, type(None)))

58

59

objgraph.show_backrefs([my_object],

60

filter=is_interesting,

61

max_depth=5,

62

filename='filtered_backrefs.png')

63

64

# Highlight specific objects

65

import types

66

objgraph.show_backrefs([my_object],

67

highlight=lambda x: isinstance(x, types.ModuleType),

68

filename='highlighted_backrefs.png')

69

70

# Show reference counts

71

objgraph.show_backrefs([my_object],

72

refcounts=True,

73

filename='refcount_backrefs.png')

74

75

# Fully qualified names

76

objgraph.show_backrefs([my_object],

77

shortnames=False,

78

filename='qualified_backrefs.png')

79

80

# Custom extra info

81

def show_size(obj):

82

if hasattr(obj, '__len__'):

83

return f"size: {len(obj)}"

84

return ""

85

86

objgraph.show_backrefs([my_object],

87

extra_info=show_size,

88

filename='size_info_backrefs.png')

89

90

# Output to file object

91

import io

92

output_buffer = io.StringIO()

93

objgraph.show_backrefs([my_object], output=output_buffer)

94

dot_content = output_buffer.getvalue()

95

96

# Custom node attributes

97

def node_attrs(obj):

98

if isinstance(obj, list):

99

return {'color': 'red', 'style': 'bold'}

100

return {}

101

102

objgraph.show_backrefs([my_object],

103

extra_node_attrs=node_attrs,

104

filename='custom_attrs_backrefs.png')

105

```

106

107

### Forward Reference Visualization

108

109

Generate graphs showing what objects the target objects refer to.

110

111

```python { .api }

112

def show_refs(objs, max_depth=3, extra_ignore=(), filter=None, too_many=10, highlight=None, filename=None, extra_info=None, refcounts=False, shortnames=True, output=None, extra_node_attrs=None):

113

"""

114

Generate an object reference graph starting at objs.

115

116

Args:

117

objs: Single object or list of objects to analyze

118

max_depth (int): Maximum graph depth to traverse

119

extra_ignore (tuple): Object IDs to ignore in the graph

120

filter (callable, optional): Function taking object and returning bool; objects returning False are excluded

121

too_many (int): Limit for references per object before truncating

122

highlight (callable, optional): Function taking object and returning bool; matching objects highlighted in blue

123

filename (str, optional): Output file name (.dot, .png, .svg, etc.)

124

extra_info (callable, optional): Function taking object and returning string for extra node information

125

refcounts (bool): Show reference counts in node labels

126

shortnames (bool): Use short class names vs fully qualified names

127

output (file-like, optional): File object to write GraphViz output

128

extra_node_attrs (callable, optional): Function taking object and returning dict of GraphViz node attributes

129

130

Returns:

131

None or graphviz.Source: None for file output, Source object for interactive display

132

133

Note:

134

Shows what the objects refer to. Follows references from modules (unlike show_backrefs).

135

Cannot specify both filename and output parameters (raises ValueError).

136

"""

137

```

138

139

Usage examples:

140

141

```python

142

import objgraph

143

144

# Basic forward reference visualization

145

class MyClass:

146

def __init__(self):

147

self.data = [1, 2, 3]

148

self.info = {'status': 'active'}

149

150

obj = MyClass()

151

objgraph.show_refs([obj], filename='forward_refs.png')

152

153

# Show what a complex object contains

154

complex_structure = {

155

'lists': [[1, 2], [3, 4], [5, 6]],

156

'nested': {'inner': {'deep': 'value'}},

157

'function': lambda x: x * 2

158

}

159

objgraph.show_refs([complex_structure],

160

max_depth=4,

161

filename='complex_refs.png')

162

163

# Filter out built-in types

164

def is_custom(obj):

165

return not isinstance(obj, (str, int, float, bool, type(None)))

166

167

objgraph.show_refs([obj],

168

filter=is_custom,

169

filename='custom_only_refs.png')

170

171

# Highlight containers

172

objgraph.show_refs([obj],

173

highlight=lambda x: hasattr(x, '__len__'),

174

filename='highlighted_containers.png')

175

176

# Limit references to avoid cluttered graphs

177

large_object = {'key_' + str(i): f'value_{i}' for i in range(100)}

178

objgraph.show_refs([large_object],

179

too_many=5, # Only show first 5 references

180

filename='limited_refs.png')

181

```

182

183

### Reference Chain Visualization

184

185

Display specific reference chains found with find_ref_chain or find_backref_chain.

186

187

```python { .api }

188

def show_chain(*chains, **kw):

189

"""

190

Show a chain (or several chains) of object references.

191

192

Args:

193

*chains: One or more reference chains (lists of objects)

194

backrefs (bool, keyword): If True, trace backwards; if False, trace forwards (default: True)

195

highlight (callable, keyword): Function taking object and returning bool for highlighting

196

extra_info (callable, keyword): Function taking object and returning string for extra info

197

refcounts (bool, keyword): Show reference counts in node labels

198

shortnames (bool, keyword): Use short class names vs fully qualified names

199

filename (str, keyword): Output file name (.dot, .png, .svg, etc.)

200

output (file-like, keyword): File object to write GraphViz output to

201

202

Returns:

203

None or graphviz.Source: None for file output, Source object for interactive display

204

205

Note:

206

Useful with find_ref_chain() or find_backref_chain().

207

Filters the graph to show only objects in the provided chains.

208

"""

209

```

210

211

Usage examples:

212

213

```python

214

import objgraph

215

216

# Find and visualize a chain

217

my_object = [1, 2, 3]

218

globals()['my_global'] = my_object # Ensure it's reachable from a module

219

220

chain = objgraph.find_backref_chain(my_object, objgraph.is_proper_module)

221

objgraph.show_chain(chain, filename='backref_chain.png')

222

223

# Multiple chains

224

obj1 = [1, 2, 3]

225

obj2 = {'key': 'value'}

226

globals()['obj1'] = obj1

227

globals()['obj2'] = obj2

228

229

chain1 = objgraph.find_backref_chain(obj1, objgraph.is_proper_module)

230

chain2 = objgraph.find_backref_chain(obj2, objgraph.is_proper_module)

231

objgraph.show_chain(chain1, chain2, filename='multiple_chains.png')

232

233

# Forward chain visualization

234

target_obj = [1, 2, 3]

235

container = {'target': target_obj}

236

forward_chain = objgraph.find_ref_chain(container, lambda x: isinstance(x, list))

237

objgraph.show_chain(forward_chain, backrefs=False, filename='forward_chain.png')

238

239

# Chain with highlighting

240

objgraph.show_chain(chain,

241

highlight=lambda x: isinstance(x, dict),

242

filename='highlighted_chain.png')

243

244

# Chain with extra info

245

def show_type_and_size(obj):

246

type_name = type(obj).__name__

247

if hasattr(obj, '__len__'):

248

return f"{type_name} (size: {len(obj)})"

249

return type_name

250

251

objgraph.show_chain(chain,

252

extra_info=show_type_and_size,

253

filename='detailed_chain.png')

254

```

255

256

## Output Formats and Viewing

257

258

objgraph supports multiple output formats and viewing methods:

259

260

### File Formats

261

262

```python

263

# PNG images (most common)

264

objgraph.show_backrefs([obj], filename='graph.png')

265

266

# SVG for scalable graphics

267

objgraph.show_backrefs([obj], filename='graph.svg')

268

269

# PDF for high-quality printing

270

objgraph.show_backrefs([obj], filename='graph.pdf')

271

272

# Raw GraphViz DOT format

273

objgraph.show_backrefs([obj], filename='graph.dot')

274

275

# Format determined by extension

276

objgraph.show_backrefs([obj], filename='graph.jpg') # JPEG

277

```

278

279

### Interactive Viewing

280

281

```python

282

# Automatic viewing (tries xdot, then generates PNG)

283

objgraph.show_backrefs([obj])

284

285

# IPython/Jupyter inline display

286

# (returns graphviz.Source object when IS_INTERACTIVE=True)

287

result = objgraph.show_backrefs([obj])

288

# result can be displayed inline in notebooks

289

```

290

291

## Common Workflows

292

293

### Memory Leak Visualization

294

295

```python

296

import objgraph

297

import gc

298

299

# Find objects that might be leaking

300

gc.collect()

301

before_count = objgraph.count('MyClass')

302

303

# Run code that might create objects

304

for i in range(100):

305

# some_operation_that_might_leak()

306

pass

307

308

gc.collect()

309

after_count = objgraph.count('MyClass')

310

311

if after_count > before_count:

312

print(f"Potential leak: {after_count - before_count} new MyClass objects")

313

314

# Get some instances to investigate

315

instances = objgraph.by_type('MyClass')

316

recent_instances = instances[before_count:before_count + 5] # First 5 new ones

317

318

# Show what keeps them alive

319

objgraph.show_backrefs(recent_instances,

320

max_depth=5,

321

filename='potential_leak.png')

322

```

323

324

### Complex Object Structure Analysis

325

326

```python

327

import objgraph

328

329

# Analyze a complex data structure

330

class Node:

331

def __init__(self, value):

332

self.value = value

333

self.children = []

334

self.metadata = {}

335

336

def add_child(self, child):

337

self.children.append(child)

338

child.metadata['parent'] = self

339

340

# Create complex structure

341

root = Node("root")

342

for i in range(3):

343

child = Node(f"child_{i}")

344

root.add_child(child)

345

for j in range(2):

346

grandchild = Node(f"grandchild_{i}_{j}")

347

child.add_child(grandchild)

348

349

# Visualize the structure

350

objgraph.show_refs([root],

351

max_depth=4,

352

highlight=lambda x: isinstance(x, Node),

353

extra_info=lambda x: getattr(x, 'value', ''),

354

filename='tree_structure.png')

355

356

# Show what keeps leaf nodes alive

357

leaf_nodes = [node for node in objgraph.by_type('Node')

358

if not node.children]

359

objgraph.show_backrefs(leaf_nodes[:2], # First 2 leaf nodes

360

filename='leaf_backrefs.png')

361

```

362

363

### Circular Reference Detection

364

365

```python

366

import objgraph

367

368

# Create circular references

369

class CircularA:

370

def __init__(self):

371

self.ref_to_b = None

372

373

class CircularB:

374

def __init__(self):

375

self.ref_to_a = None

376

377

# Create the cycle

378

a = CircularA()

379

b = CircularB()

380

a.ref_to_b = b

381

b.ref_to_a = a

382

383

# Visualize the circular reference

384

objgraph.show_refs([a],

385

max_depth=3,

386

highlight=lambda x: isinstance(x, (CircularA, CircularB)),

387

filename='circular_refs.png')

388

389

# Also show backrefs to see the complete cycle

390

objgraph.show_backrefs([a],

391

max_depth=3,

392

highlight=lambda x: isinstance(x, (CircularA, CircularB)),

393

filename='circular_backrefs.png')

394

```