0
# Data Serialization
1
2
Structured data export functionality for converting stack traces and frame information into dictionaries and lists suitable for JSON serialization, programmatic processing, and integration with external systems or APIs.
3
4
## Capabilities
5
6
### Serializer Configuration
7
8
Central serialization class that converts stack traces, exceptions, and frame information into structured data formats (dictionaries and lists) for programmatic processing.
9
10
```python { .api }
11
class Serializer:
12
def __init__(self, *,
13
options: Optional[Options] = None,
14
pygmented: bool = False,
15
show_executing_node: bool = True,
16
pygments_formatter_cls = None,
17
pygments_formatter_kwargs: Optional[dict] = None,
18
pygments_style: str = "monokai",
19
executing_node_modifier: str = "bg:#005080",
20
use_code_qualname: bool = True,
21
strip_leading_indent: bool = True,
22
html: bool = False,
23
chain: bool = True,
24
collapse_repeated_frames: bool = True,
25
show_variables: bool = False):
26
"""
27
Create Serializer for structured data export.
28
29
Args:
30
options: Stack data options for frame analysis
31
pygmented: Whether to include syntax highlighting in output
32
show_executing_node: Whether to mark executing nodes in output
33
pygments_formatter_cls: Custom Pygments formatter class
34
pygments_formatter_kwargs: Arguments for Pygments formatter
35
pygments_style: Pygments style name for syntax highlighting
36
executing_node_modifier: CSS-like modifier for executing node marking
37
use_code_qualname: Whether to use qualified names for code objects
38
strip_leading_indent: Whether to strip leading indentation from source
39
html: Whether to escape HTML characters in output
40
chain: Whether to include exception causes and contexts
41
collapse_repeated_frames: Whether to collapse repeated frames
42
show_variables: Whether to include variable information
43
"""
44
```
45
46
### Exception Serialization
47
48
Functions for converting exceptions and their tracebacks into structured dictionary format suitable for JSON serialization or API responses.
49
50
```python { .api }
51
def format_exception(self, e: Optional[BaseException] = None) -> List[dict]:
52
"""
53
Serialize exception to list of dictionaries.
54
55
Args:
56
e: Exception to serialize (uses sys.exc_info() if None)
57
58
Returns:
59
List of dictionaries containing exception information:
60
- Exception message and type
61
- Traceback frames with source code
62
- Variable information if enabled
63
- Chained exceptions if present
64
"""
65
66
def format_traceback_part(self, e: BaseException) -> dict:
67
"""
68
Serialize single traceback part to dictionary.
69
70
Args:
71
e: Exception containing traceback to serialize
72
73
Returns:
74
Dictionary containing:
75
- exception_type: Exception class name
76
- exception_message: Exception message
77
- frames: List of frame dictionaries
78
- is_cause: Whether this is an exception cause
79
- is_context: Whether this is an exception context
80
"""
81
```
82
83
### Stack Serialization
84
85
Functions for converting stack traces and frame sequences into structured data format for programmatic analysis and processing.
86
87
```python { .api }
88
def format_stack(self, frame_or_tb: Optional[Union[FrameType, TracebackType]] = None) -> List[dict]:
89
"""
90
Serialize stack trace to list of dictionaries.
91
92
Args:
93
frame_or_tb: Frame or traceback to start from (uses current frame if None)
94
95
Returns:
96
List of dictionaries containing stack frame information:
97
- Frame metadata (filename, function, line number)
98
- Source code lines with context
99
- Variable information if enabled
100
- Repeated frame summaries if present
101
"""
102
103
def format_stack_data(self, stack: Iterable[Union[FrameInfo, RepeatedFrames]]) -> Iterable[dict]:
104
"""
105
Serialize stack data objects to dictionaries.
106
107
Args:
108
stack: Iterable of FrameInfo and RepeatedFrames objects
109
110
Yields:
111
Dictionary for each stack element containing:
112
- Frame type (frame or repeated_frames)
113
- Frame information and source code
114
- Variable data if enabled
115
"""
116
```
117
118
### Frame Serialization
119
120
Functions for converting individual stack frames into structured dictionary format with complete metadata and source information.
121
122
```python { .api }
123
def format_frame(self, frame: Union[FrameInfo, FrameType, TracebackType]) -> dict:
124
"""
125
Serialize individual frame to dictionary.
126
127
Args:
128
frame: Frame object to serialize (FrameInfo, FrameType, or TracebackType)
129
130
Returns:
131
Dictionary containing:
132
- filename: Absolute path to source file
133
- function_name: Name of function or method
134
- function_qualname: Qualified name if use_code_qualname is True
135
- lineno: Current line number
136
- lines: List of source line dictionaries
137
- variables: List of variable dictionaries if show_variables is True
138
"""
139
140
def format_repeated_frames(self, repeated_frames: RepeatedFrames) -> dict:
141
"""
142
Serialize repeated frames to dictionary.
143
144
Args:
145
repeated_frames: RepeatedFrames object
146
147
Returns:
148
Dictionary containing:
149
- type: "repeated_frames"
150
- count: Number of repeated frames
151
- description: Brief description of repetition
152
- frames: Sample frame information
153
"""
154
155
def should_include_frame(self, frame_info: FrameInfo) -> bool:
156
"""
157
Determine whether to include frame in output.
158
159
Args:
160
frame_info: FrameInfo object to check
161
162
Returns:
163
Always True (all frames included by default)
164
"""
165
```
166
167
### Line Serialization
168
169
Functions for converting source code lines into structured format with line numbers, content, and metadata.
170
171
```python { .api }
172
def format_lines(self, lines: Iterable[Union[Line, Any]]) -> Iterable[dict]:
173
"""
174
Serialize source lines to dictionaries.
175
176
Args:
177
lines: Iterable of Line objects and other line types
178
179
Yields:
180
Dictionary for each line containing:
181
- line_type: Type of line (source, gap, blank_range)
182
- lineno: Line number for source lines
183
- text: Source code text
184
- is_current: Whether this is the executing line
185
"""
186
187
def format_line(self, line: Line) -> dict:
188
"""
189
Serialize individual source line to dictionary.
190
191
Args:
192
line: Line object to serialize
193
194
Returns:
195
Dictionary containing:
196
- line_type: "source"
197
- lineno: Line number
198
- text: Source code text (processed according to settings)
199
- is_current: Whether this is the currently executing line
200
"""
201
```
202
203
### Variable Serialization
204
205
Functions for converting variable information into structured format with names, values, and type information.
206
207
```python { .api }
208
def format_variables(self, frame_info: FrameInfo) -> Iterable[dict]:
209
"""
210
Serialize variables in frame to dictionaries.
211
212
Args:
213
frame_info: FrameInfo object containing variables
214
215
Yields:
216
Dictionary for each variable containing:
217
- name: Variable name or expression
218
- value: Formatted string representation of value
219
- type: Type name of the value
220
"""
221
222
def format_variable(self, var: Variable) -> dict:
223
"""
224
Serialize individual variable to dictionary.
225
226
Args:
227
var: Variable object to serialize
228
229
Returns:
230
Dictionary containing:
231
- name: Variable name or expression text
232
- value: Formatted string representation
233
- type: Type name of the variable value
234
"""
235
236
def format_variable_part(self, text: str) -> str:
237
"""
238
Format text part of variable display.
239
240
Args:
241
text: Text to format
242
243
Returns:
244
Text with HTML escaping if html=True
245
"""
246
247
def format_variable_value(self, value: Any) -> str:
248
"""
249
Format variable value for display.
250
251
Args:
252
value: Variable value to format
253
254
Returns:
255
String representation of the value
256
"""
257
```
258
259
## Usage Examples
260
261
### Basic Exception Serialization
262
263
```python
264
from stack_data import Serializer
265
import json
266
267
# Create serializer
268
serializer = Serializer()
269
270
try:
271
result = 1 / 0
272
except Exception as e:
273
# Serialize exception to structured data
274
exception_data = serializer.format_exception(e)
275
276
# Convert to JSON
277
json_output = json.dumps(exception_data, indent=2)
278
print(json_output)
279
280
# Access structured data
281
for frame_dict in exception_data:
282
if 'frames' in frame_dict:
283
for frame in frame_dict['frames']:
284
print(f"Function: {frame['function_name']}")
285
print(f"File: {frame['filename']}:{frame['lineno']}")
286
```
287
288
### Stack Serialization with Variables
289
290
```python
291
from stack_data import Serializer, Options
292
293
# Create serializer with variable information
294
serializer = Serializer(
295
show_variables=True, # Include variable data
296
use_code_qualname=True, # Use qualified function names
297
strip_leading_indent=True # Clean up source code
298
)
299
300
import inspect
301
302
def example_function():
303
local_var = "example"
304
frame = inspect.currentframe()
305
306
# Serialize current stack
307
stack_data = serializer.format_stack(frame)
308
309
return stack_data
310
311
# Get serialized stack data
312
data = example_function()
313
314
# Process structured data
315
for frame_dict in data:
316
print(f"Frame: {frame_dict['function_name']}")
317
318
# Access variables if present
319
if 'variables' in frame_dict:
320
for var in frame_dict['variables']:
321
print(f" {var['name']} = {var['value']} ({var['type']})")
322
323
# Access source lines
324
for line in frame_dict['lines']:
325
if line['line_type'] == 'source':
326
marker = ">>> " if line['is_current'] else " "
327
print(f"{marker}{line['lineno']}: {line['text']}")
328
```
329
330
### API Response Format
331
332
```python
333
from stack_data import Serializer
334
import json
335
336
def create_error_response(exception):
337
"""Create API error response with stack data."""
338
339
serializer = Serializer(
340
show_variables=False, # Don't expose variables in API
341
html=True, # Escape HTML for safety
342
chain=True, # Include exception chains
343
collapse_repeated_frames=True # Compact output
344
)
345
346
# Serialize exception
347
stack_data = serializer.format_exception(exception)
348
349
# Create API response format
350
response = {
351
"error": True,
352
"message": str(exception),
353
"type": exception.__class__.__name__,
354
"stack_trace": stack_data,
355
"timestamp": "2023-01-01T00:00:00Z"
356
}
357
358
return response
359
360
# Usage
361
try:
362
# Some operation that fails
363
raise ValueError("Something went wrong")
364
except Exception as e:
365
error_response = create_error_response(e)
366
print(json.dumps(error_response, indent=2))
367
```
368
369
### Custom Data Processing
370
371
```python
372
from stack_data import Serializer, FrameInfo
373
374
class CustomAnalyzer:
375
def __init__(self):
376
self.serializer = Serializer(
377
show_variables=True,
378
pygmented=False, # No highlighting for analysis
379
use_code_qualname=True
380
)
381
382
def analyze_frame(self, frame):
383
"""Extract specific information from frame."""
384
frame_data = self.serializer.format_frame(frame)
385
386
analysis = {
387
"file": frame_data["filename"],
388
"function": frame_data["function_qualname"],
389
"line_count": len([l for l in frame_data["lines"]
390
if l["line_type"] == "source"]),
391
"variable_count": len(frame_data.get("variables", [])),
392
"current_line": frame_data["lineno"]
393
}
394
395
return analysis
396
397
def analyze_exception(self, exception):
398
"""Analyze exception for metrics."""
399
exception_data = self.serializer.format_exception(exception)
400
401
metrics = {
402
"exception_type": exception.__class__.__name__,
403
"frame_count": 0,
404
"unique_files": set(),
405
"functions": []
406
}
407
408
for part in exception_data:
409
if "frames" in part:
410
for frame in part["frames"]:
411
metrics["frame_count"] += 1
412
metrics["unique_files"].add(frame["filename"])
413
metrics["functions"].append(frame["function_name"])
414
415
metrics["unique_files"] = len(metrics["unique_files"])
416
return metrics
417
418
# Usage
419
analyzer = CustomAnalyzer()
420
421
try:
422
result = 1 / 0
423
except Exception as e:
424
metrics = analyzer.analyze_exception(e)
425
print(f"Exception analysis: {metrics}")
426
```
427
428
### HTML-Safe Serialization
429
430
```python
431
from stack_data import Serializer
432
433
# Create HTML-safe serializer
434
html_serializer = Serializer(
435
html=True, # Escape HTML characters
436
pygmented=True, # Include syntax highlighting data
437
show_variables=True, # Include variables (safely escaped)
438
strip_leading_indent=True
439
)
440
441
# Serialize for web display
442
try:
443
user_input = "<script>alert('xss')</script>"
444
eval(user_input) # Dangerous operation
445
except Exception as e:
446
safe_data = html_serializer.format_exception(e)
447
448
# Data is now safe for HTML display
449
for frame_dict in safe_data:
450
if 'frames' in frame_dict:
451
for frame in frame_dict['frames']:
452
# Variables and source code are HTML-escaped
453
for line in frame['lines']:
454
if line['line_type'] == 'source':
455
print(f"Safe HTML: {line['text']}")
456
```
457
458
### Minimal Data Export
459
460
```python
461
from stack_data import Serializer
462
463
# Serializer for minimal data export
464
minimal_serializer = Serializer(
465
show_variables=False, # No variables
466
pygmented=False, # No highlighting
467
show_executing_node=False, # No execution markers
468
strip_leading_indent=True, # Clean source
469
collapse_repeated_frames=True # Compact recursive frames
470
)
471
472
import inspect
473
474
def get_call_stack():
475
"""Get minimal call stack information."""
476
frame = inspect.currentframe()
477
stack_data = minimal_serializer.format_stack(frame)
478
479
# Extract just the essential information
480
call_stack = []
481
for frame_dict in stack_data:
482
if frame_dict.get('type') == 'repeated_frames':
483
call_stack.append({
484
"type": "repeated",
485
"count": frame_dict.get('count', 0),
486
"description": frame_dict.get('description', '')
487
})
488
else:
489
call_stack.append({
490
"type": "frame",
491
"function": frame_dict.get('function_name', ''),
492
"file": frame_dict.get('filename', ''),
493
"line": frame_dict.get('lineno', 0)
494
})
495
496
return call_stack
497
498
# Usage
499
stack = get_call_stack()
500
print(f"Call stack has {len(stack)} entries")
501
```