Extract data from python stack frames and tracebacks for informative displays
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.
Central serialization class that converts stack traces, exceptions, and frame information into structured data formats (dictionaries and lists) for programmatic processing.
class Serializer:
def __init__(self, *,
options: Optional[Options] = None,
pygmented: bool = False,
show_executing_node: bool = True,
pygments_formatter_cls = None,
pygments_formatter_kwargs: Optional[dict] = None,
pygments_style: str = "monokai",
executing_node_modifier: str = "bg:#005080",
use_code_qualname: bool = True,
strip_leading_indent: bool = True,
html: bool = False,
chain: bool = True,
collapse_repeated_frames: bool = True,
show_variables: bool = False):
"""
Create Serializer for structured data export.
Args:
options: Stack data options for frame analysis
pygmented: Whether to include syntax highlighting in output
show_executing_node: Whether to mark executing nodes in output
pygments_formatter_cls: Custom Pygments formatter class
pygments_formatter_kwargs: Arguments for Pygments formatter
pygments_style: Pygments style name for syntax highlighting
executing_node_modifier: CSS-like modifier for executing node marking
use_code_qualname: Whether to use qualified names for code objects
strip_leading_indent: Whether to strip leading indentation from source
html: Whether to escape HTML characters in output
chain: Whether to include exception causes and contexts
collapse_repeated_frames: Whether to collapse repeated frames
show_variables: Whether to include variable information
"""Functions for converting exceptions and their tracebacks into structured dictionary format suitable for JSON serialization or API responses.
def format_exception(self, e: Optional[BaseException] = None) -> List[dict]:
"""
Serialize exception to list of dictionaries.
Args:
e: Exception to serialize (uses sys.exc_info() if None)
Returns:
List of dictionaries containing exception information:
- Exception message and type
- Traceback frames with source code
- Variable information if enabled
- Chained exceptions if present
"""
def format_traceback_part(self, e: BaseException) -> dict:
"""
Serialize single traceback part to dictionary.
Args:
e: Exception containing traceback to serialize
Returns:
Dictionary containing:
- exception_type: Exception class name
- exception_message: Exception message
- frames: List of frame dictionaries
- is_cause: Whether this is an exception cause
- is_context: Whether this is an exception context
"""Functions for converting stack traces and frame sequences into structured data format for programmatic analysis and processing.
def format_stack(self, frame_or_tb: Optional[Union[FrameType, TracebackType]] = None) -> List[dict]:
"""
Serialize stack trace to list of dictionaries.
Args:
frame_or_tb: Frame or traceback to start from (uses current frame if None)
Returns:
List of dictionaries containing stack frame information:
- Frame metadata (filename, function, line number)
- Source code lines with context
- Variable information if enabled
- Repeated frame summaries if present
"""
def format_stack_data(self, stack: Iterable[Union[FrameInfo, RepeatedFrames]]) -> Iterable[dict]:
"""
Serialize stack data objects to dictionaries.
Args:
stack: Iterable of FrameInfo and RepeatedFrames objects
Yields:
Dictionary for each stack element containing:
- Frame type (frame or repeated_frames)
- Frame information and source code
- Variable data if enabled
"""Functions for converting individual stack frames into structured dictionary format with complete metadata and source information.
def format_frame(self, frame: Union[FrameInfo, FrameType, TracebackType]) -> dict:
"""
Serialize individual frame to dictionary.
Args:
frame: Frame object to serialize (FrameInfo, FrameType, or TracebackType)
Returns:
Dictionary containing:
- filename: Absolute path to source file
- function_name: Name of function or method
- function_qualname: Qualified name if use_code_qualname is True
- lineno: Current line number
- lines: List of source line dictionaries
- variables: List of variable dictionaries if show_variables is True
"""
def format_repeated_frames(self, repeated_frames: RepeatedFrames) -> dict:
"""
Serialize repeated frames to dictionary.
Args:
repeated_frames: RepeatedFrames object
Returns:
Dictionary containing:
- type: "repeated_frames"
- count: Number of repeated frames
- description: Brief description of repetition
- frames: Sample frame information
"""
def should_include_frame(self, frame_info: FrameInfo) -> bool:
"""
Determine whether to include frame in output.
Args:
frame_info: FrameInfo object to check
Returns:
Always True (all frames included by default)
"""Functions for converting source code lines into structured format with line numbers, content, and metadata.
def format_lines(self, lines: Iterable[Union[Line, Any]]) -> Iterable[dict]:
"""
Serialize source lines to dictionaries.
Args:
lines: Iterable of Line objects and other line types
Yields:
Dictionary for each line containing:
- line_type: Type of line (source, gap, blank_range)
- lineno: Line number for source lines
- text: Source code text
- is_current: Whether this is the executing line
"""
def format_line(self, line: Line) -> dict:
"""
Serialize individual source line to dictionary.
Args:
line: Line object to serialize
Returns:
Dictionary containing:
- line_type: "source"
- lineno: Line number
- text: Source code text (processed according to settings)
- is_current: Whether this is the currently executing line
"""Functions for converting variable information into structured format with names, values, and type information.
def format_variables(self, frame_info: FrameInfo) -> Iterable[dict]:
"""
Serialize variables in frame to dictionaries.
Args:
frame_info: FrameInfo object containing variables
Yields:
Dictionary for each variable containing:
- name: Variable name or expression
- value: Formatted string representation of value
- type: Type name of the value
"""
def format_variable(self, var: Variable) -> dict:
"""
Serialize individual variable to dictionary.
Args:
var: Variable object to serialize
Returns:
Dictionary containing:
- name: Variable name or expression text
- value: Formatted string representation
- type: Type name of the variable value
"""
def format_variable_part(self, text: str) -> str:
"""
Format text part of variable display.
Args:
text: Text to format
Returns:
Text with HTML escaping if html=True
"""
def format_variable_value(self, value: Any) -> str:
"""
Format variable value for display.
Args:
value: Variable value to format
Returns:
String representation of the value
"""from stack_data import Serializer
import json
# Create serializer
serializer = Serializer()
try:
result = 1 / 0
except Exception as e:
# Serialize exception to structured data
exception_data = serializer.format_exception(e)
# Convert to JSON
json_output = json.dumps(exception_data, indent=2)
print(json_output)
# Access structured data
for frame_dict in exception_data:
if 'frames' in frame_dict:
for frame in frame_dict['frames']:
print(f"Function: {frame['function_name']}")
print(f"File: {frame['filename']}:{frame['lineno']}")from stack_data import Serializer, Options
# Create serializer with variable information
serializer = Serializer(
show_variables=True, # Include variable data
use_code_qualname=True, # Use qualified function names
strip_leading_indent=True # Clean up source code
)
import inspect
def example_function():
local_var = "example"
frame = inspect.currentframe()
# Serialize current stack
stack_data = serializer.format_stack(frame)
return stack_data
# Get serialized stack data
data = example_function()
# Process structured data
for frame_dict in data:
print(f"Frame: {frame_dict['function_name']}")
# Access variables if present
if 'variables' in frame_dict:
for var in frame_dict['variables']:
print(f" {var['name']} = {var['value']} ({var['type']})")
# Access source lines
for line in frame_dict['lines']:
if line['line_type'] == 'source':
marker = ">>> " if line['is_current'] else " "
print(f"{marker}{line['lineno']}: {line['text']}")from stack_data import Serializer
import json
def create_error_response(exception):
"""Create API error response with stack data."""
serializer = Serializer(
show_variables=False, # Don't expose variables in API
html=True, # Escape HTML for safety
chain=True, # Include exception chains
collapse_repeated_frames=True # Compact output
)
# Serialize exception
stack_data = serializer.format_exception(exception)
# Create API response format
response = {
"error": True,
"message": str(exception),
"type": exception.__class__.__name__,
"stack_trace": stack_data,
"timestamp": "2023-01-01T00:00:00Z"
}
return response
# Usage
try:
# Some operation that fails
raise ValueError("Something went wrong")
except Exception as e:
error_response = create_error_response(e)
print(json.dumps(error_response, indent=2))from stack_data import Serializer, FrameInfo
class CustomAnalyzer:
def __init__(self):
self.serializer = Serializer(
show_variables=True,
pygmented=False, # No highlighting for analysis
use_code_qualname=True
)
def analyze_frame(self, frame):
"""Extract specific information from frame."""
frame_data = self.serializer.format_frame(frame)
analysis = {
"file": frame_data["filename"],
"function": frame_data["function_qualname"],
"line_count": len([l for l in frame_data["lines"]
if l["line_type"] == "source"]),
"variable_count": len(frame_data.get("variables", [])),
"current_line": frame_data["lineno"]
}
return analysis
def analyze_exception(self, exception):
"""Analyze exception for metrics."""
exception_data = self.serializer.format_exception(exception)
metrics = {
"exception_type": exception.__class__.__name__,
"frame_count": 0,
"unique_files": set(),
"functions": []
}
for part in exception_data:
if "frames" in part:
for frame in part["frames"]:
metrics["frame_count"] += 1
metrics["unique_files"].add(frame["filename"])
metrics["functions"].append(frame["function_name"])
metrics["unique_files"] = len(metrics["unique_files"])
return metrics
# Usage
analyzer = CustomAnalyzer()
try:
result = 1 / 0
except Exception as e:
metrics = analyzer.analyze_exception(e)
print(f"Exception analysis: {metrics}")from stack_data import Serializer
# Create HTML-safe serializer
html_serializer = Serializer(
html=True, # Escape HTML characters
pygmented=True, # Include syntax highlighting data
show_variables=True, # Include variables (safely escaped)
strip_leading_indent=True
)
# Serialize for web display
try:
user_input = "<script>alert('xss')</script>"
eval(user_input) # Dangerous operation
except Exception as e:
safe_data = html_serializer.format_exception(e)
# Data is now safe for HTML display
for frame_dict in safe_data:
if 'frames' in frame_dict:
for frame in frame_dict['frames']:
# Variables and source code are HTML-escaped
for line in frame['lines']:
if line['line_type'] == 'source':
print(f"Safe HTML: {line['text']}")from stack_data import Serializer
# Serializer for minimal data export
minimal_serializer = Serializer(
show_variables=False, # No variables
pygmented=False, # No highlighting
show_executing_node=False, # No execution markers
strip_leading_indent=True, # Clean source
collapse_repeated_frames=True # Compact recursive frames
)
import inspect
def get_call_stack():
"""Get minimal call stack information."""
frame = inspect.currentframe()
stack_data = minimal_serializer.format_stack(frame)
# Extract just the essential information
call_stack = []
for frame_dict in stack_data:
if frame_dict.get('type') == 'repeated_frames':
call_stack.append({
"type": "repeated",
"count": frame_dict.get('count', 0),
"description": frame_dict.get('description', '')
})
else:
call_stack.append({
"type": "frame",
"function": frame_dict.get('function_name', ''),
"file": frame_dict.get('filename', ''),
"line": frame_dict.get('lineno', 0)
})
return call_stack
# Usage
stack = get_call_stack()
print(f"Call stack has {len(stack)} entries")Install with Tessl CLI
npx tessl i tessl/pypi-stack-data