0
# Development & Debugging Tools
1
2
Debugging utilities, function introspection, traceback enhancement, garbage collection tools, and development aids. Includes pdb integration, enhanced exception handling, function manipulation utilities, and comprehensive development tooling.
3
4
## Capabilities
5
6
### Debugging Integration
7
8
Integration with Python's pdb debugger for enhanced debugging workflows.
9
10
```python { .api }
11
def pdb_on_signal(signalnum=None):
12
"""
13
Install signal handler to launch pdb breakpoint.
14
15
Parameters:
16
- signalnum (int, optional): Signal number (default: SIGUSR1)
17
18
Returns:
19
None
20
"""
21
22
def pdb_on_exception(limit=100):
23
"""
24
Install handler for post-mortem pdb on unhandled exceptions.
25
26
Parameters:
27
- limit (int): Traceback limit
28
29
Returns:
30
None
31
"""
32
33
def wrap_trace(obj, hook=trace_print_hook, **kwargs):
34
"""
35
Monitor object interactions with custom tracing.
36
37
Parameters:
38
- obj: Object to trace
39
- hook (callable): Trace event handler
40
41
Returns:
42
Wrapped object with tracing
43
"""
44
45
def trace_print_hook(event, label, obj, attr_name, **kwargs):
46
"""
47
Default hook for printing trace events.
48
49
Parameters:
50
- event (str): Event type ('get', 'set', 'call', etc.)
51
- label (str): Trace label
52
- obj: Target object
53
- attr_name (str): Attribute name
54
55
Returns:
56
None
57
"""
58
```
59
60
### Enhanced Traceback Handling
61
62
Comprehensive traceback inspection and formatting utilities.
63
64
```python { .api }
65
class Callpoint:
66
"""Represents a single point in a call stack."""
67
def __init__(self, tb_frame, lineno): ...
68
@property
69
def filename(self): ...
70
@property
71
def lineno(self): ...
72
@property
73
def func_name(self): ...
74
@property
75
def module_name(self): ...
76
def __repr__(self): ...
77
78
class TracebackInfo:
79
"""Enhanced traceback information with additional context."""
80
def __init__(self, tb): ...
81
@property
82
def callpoints(self): ...
83
def format(self): ...
84
def to_dict(self): ...
85
86
class ExceptionInfo:
87
"""Enhanced exception information with formatting."""
88
def __init__(self, exc_type, exc_value, exc_tb): ...
89
@property
90
def exc_type(self): ...
91
@property
92
def exc_msg(self): ...
93
@property
94
def tb_info(self): ...
95
def format(self): ...
96
97
class ContextualCallpoint(Callpoint):
98
"""Callpoint with source code context."""
99
@property
100
def source_lines(self): ...
101
@property
102
def source_context(self): ...
103
104
class ContextualTracebackInfo(TracebackInfo):
105
"""TracebackInfo with source context."""
106
pass
107
108
class ContextualExceptionInfo(ExceptionInfo):
109
"""ExceptionInfo with source context."""
110
pass
111
112
class ParsedException:
113
"""Parsed exception from string representation."""
114
def __init__(self, exc_str): ...
115
@property
116
def exc_type_name(self): ...
117
@property
118
def exc_msg(self): ...
119
120
def format_exception_only(etype, value):
121
"""
122
Format exception without traceback.
123
124
Parameters:
125
- etype (type): Exception type
126
- value (Exception): Exception instance
127
128
Returns:
129
str: Formatted exception string
130
"""
131
132
def print_exception(etype, value, tb, **kwargs):
133
"""
134
Enhanced exception printing.
135
136
Parameters:
137
- etype (type): Exception type
138
- value (Exception): Exception instance
139
- tb: Traceback object
140
141
Returns:
142
None
143
"""
144
145
def fix_print_exception():
146
"""
147
Monkey-patch sys.excepthook with enhanced version.
148
149
Returns:
150
None
151
"""
152
```
153
154
### Function Introspection and Manipulation
155
156
Comprehensive function analysis and manipulation utilities.
157
158
```python { .api }
159
def get_module_callables(mod, ignore=None):
160
"""
161
Get all callable objects from a module.
162
163
Parameters:
164
- mod: Module to inspect
165
- ignore (set, optional): Names to ignore
166
167
Returns:
168
dict: Mapping of names to callable objects
169
"""
170
171
def mro_items(type_obj):
172
"""
173
Get method resolution order as (name, class) pairs.
174
175
Parameters:
176
- type_obj (type): Type to analyze
177
178
Returns:
179
list: List of (method_name, defining_class) tuples
180
"""
181
182
def dir_dict(obj, raise_exc=False):
183
"""
184
Get object's __dict__ with error handling.
185
186
Parameters:
187
- obj: Object to inspect
188
- raise_exc (bool): Raise exceptions on access errors
189
190
Returns:
191
dict: Object's attributes dictionary
192
"""
193
194
def copy_function(orig, copy_dict=True):
195
"""
196
Create copy of function object.
197
198
Parameters:
199
- orig (function): Original function
200
- copy_dict (bool): Copy function's __dict__
201
202
Returns:
203
function: Copied function
204
"""
205
206
def partial_ordering(cls):
207
"""
208
Class decorator to add comparison methods from __lt__.
209
210
Parameters:
211
- cls (type): Class to enhance
212
213
Returns:
214
type: Enhanced class with comparison methods
215
"""
216
217
class FunctionBuilder:
218
"""Programmatically build function signatures and implementations."""
219
def __init__(self, name, doc=None, defaults=None, **kwargs): ...
220
def add_arg(self, name, default=NO_DEFAULT): ...
221
def add_kwarg(self, name, default): ...
222
def compile(self, execdict=None): ...
223
224
def format_invocation(name='', args=(), kwargs=None, **kw):
225
"""
226
Format function call as string.
227
228
Parameters:
229
- name (str): Function name
230
- args (tuple): Positional arguments
231
- kwargs (dict): Keyword arguments
232
233
Returns:
234
str: Formatted function call
235
"""
236
237
def wraps(func, injected=None, expected=None, **kw):
238
"""
239
Enhanced functools.wraps.
240
241
Parameters:
242
- func (callable): Function to wrap
243
- injected (list): Injected argument names
244
- expected (list): Expected argument names
245
246
Returns:
247
callable: Decorator function
248
"""
249
250
def noop(*args, **kwargs):
251
"""
252
No-operation function.
253
254
Parameters:
255
- *args: Any positional arguments (ignored)
256
- **kwargs: Any keyword arguments (ignored)
257
258
Returns:
259
None
260
"""
261
```
262
263
### Garbage Collection Utilities
264
265
Tools for analyzing and controlling garbage collection.
266
267
```python { .api }
268
class GCToggler:
269
"""Context manager to temporarily disable/enable garbage collection."""
270
def __init__(self, enabled=False): ...
271
def __enter__(self): ...
272
def __exit__(self, exc_type, exc_val, exc_tb): ...
273
274
def get_all(type_obj, include_subtypes=True):
275
"""
276
Get all instances of a type from GC.
277
278
Parameters:
279
- type_obj (type): Type to search for
280
- include_subtypes (bool): Include subtype instances
281
282
Returns:
283
list: List of instances found in GC
284
"""
285
```
286
287
## Usage Examples
288
289
```python
290
from boltons.debugutils import pdb_on_signal, pdb_on_exception, wrap_trace
291
from boltons.tbutils import TracebackInfo, ExceptionInfo
292
from boltons.funcutils import FunctionBuilder, get_module_callables
293
from boltons.gcutils import GCToggler, get_all
294
import signal
295
296
# Enhanced debugging setup
297
pdb_on_signal(signal.SIGUSR1) # Send SIGUSR1 to drop into debugger
298
pdb_on_exception() # Auto-debug on unhandled exceptions
299
300
# Trace object interactions
301
class TracedClass:
302
def method(self):
303
return "traced"
304
305
traced_obj = wrap_trace(TracedClass())
306
traced_obj.method() # Prints trace information
307
308
# Enhanced exception handling
309
try:
310
raise ValueError("Something went wrong")
311
except:
312
import sys
313
exc_info = ExceptionInfo(*sys.exc_info())
314
print(exc_info.format()) # Enhanced exception formatting
315
316
# Function analysis
317
import math
318
callables = get_module_callables(math)
319
print(f"Math module has {len(callables)} callable functions")
320
321
# Dynamic function building
322
builder = FunctionBuilder('dynamic_func', doc='Dynamically created function')
323
builder.add_arg('x')
324
builder.add_arg('y', default=10)
325
builder.add_kwarg('multiply', default=True)
326
327
func_code = '''
328
if multiply:
329
return x * y
330
else:
331
return x + y
332
'''
333
334
dynamic_func = builder.compile({'multiply': True})
335
# Now dynamic_func(5, y=3, multiply=False) works
336
337
# Garbage collection analysis
338
class TestClass:
339
pass
340
341
instances = [TestClass() for _ in range(10)]
342
found_instances = get_all(TestClass)
343
print(f"Found {len(found_instances)} TestClass instances in GC")
344
345
# Temporarily disable GC for performance-critical section
346
with GCToggler(enabled=False):
347
# Perform operations without GC interruption
348
heavy_computation()
349
```
350
351
### Advanced Development Tools
352
353
```python
354
from boltons.funcutils import copy_function, format_invocation, wraps
355
from boltons.tbutils import ContextualExceptionInfo
356
357
# Function copying and modification
358
def original_func(x, y=5):
359
\"\"\"Original function docstring.\"\"\"
360
return x + y
361
362
copied_func = copy_function(original_func)
363
copied_func.__name__ = 'modified_func'
364
copied_func.__doc__ = 'Modified function docstring.'
365
366
# Enhanced wrapper with injection
367
@wraps(original_func, injected=['logger'])
368
def logged_wrapper(logger, *args, **kwargs):
369
call_str = format_invocation('original_func', args, kwargs)
370
logger.info(f"Calling: {call_str}")
371
return original_func(*args, **kwargs)
372
373
# Contextual exception analysis
374
try:
375
def problematic_function():
376
x = 1 / 0 # Division by zero
377
return x
378
379
problematic_function()
380
except:
381
import sys
382
ctx_exc_info = ContextualExceptionInfo(*sys.exc_info())
383
384
# Get detailed context with source code
385
formatted = ctx_exc_info.format()
386
print("Detailed exception with source context:")
387
print(formatted)
388
389
# Access individual callpoints with context
390
for callpoint in ctx_exc_info.tb_info.callpoints:
391
if hasattr(callpoint, 'source_context'):
392
print(f"Function: {callpoint.func_name}")
393
print(f"Source context around line {callpoint.lineno}:")
394
for line_no, line in callpoint.source_context:
395
marker = ">>>" if line_no == callpoint.lineno else " "
396
print(f"{marker} {line_no}: {line}")
397
```
398
399
## Types
400
401
```python { .api }
402
# Exception classes
403
class MissingArgument(ValueError):
404
\"\"\"Exception for missing function arguments.\"\"\"
405
pass
406
407
class ExistingArgument(ValueError):
408
\"\"\"Exception for conflicting function arguments.\"\"\"
409
pass
410
411
# Sentinel values
412
NO_DEFAULT = object() # Sentinel for arguments with no default value
413
414
# Trace event types
415
TRACE_EVENTS = {'get', 'set', 'call', 'return', 'exception'}
416
```