0
# Framework Integration
1
2
Plugin system for framework-specific debugging support including Django templates, Jinja2 templates, and custom debugging extensions. This system provides specialized debugging capabilities for web frameworks, template engines, and other Python frameworks that require custom debugging behavior.
3
4
## Capabilities
5
6
### Django Framework Debugging
7
8
Specialized debugging support for Django web applications, including template debugging, view debugging, and Django-specific breakpoint handling.
9
10
```python { .api }
11
# Django debugging functionality from pydevd_plugins.django_debug
12
13
def add_django_exception_breakpoint(exception_type, notify_on_handled, notify_on_unhandled):
14
"""
15
Add Django-specific exception breakpoint.
16
17
Parameters:
18
- exception_type (str): Django exception type (e.g., 'Http404', 'ValidationError')
19
- notify_on_handled (bool): Break on handled Django exceptions
20
- notify_on_unhandled (bool): Break on unhandled Django exceptions
21
22
Returns:
23
None
24
"""
25
26
def enable_django_template_debugging():
27
"""
28
Enable debugging for Django templates.
29
30
Allows setting breakpoints and stepping through Django template rendering.
31
32
Returns:
33
None
34
"""
35
36
def get_django_frame_locals(frame):
37
"""
38
Extract Django-specific local variables from frame context.
39
40
Parameters:
41
- frame: Python frame object from Django code
42
43
Returns:
44
dict: Django-specific context variables and request information
45
"""
46
```
47
48
### Jinja2 Template Debugging
49
50
Support for debugging Jinja2 templates with template-specific breakpoints and variable inspection.
51
52
```python { .api }
53
# Jinja2 debugging functionality from pydevd_plugins.jinja2_debug
54
55
def enable_jinja2_template_debugging():
56
"""
57
Enable debugging for Jinja2 templates.
58
59
Allows setting breakpoints within template rendering and inspecting
60
template context variables.
61
62
Returns:
63
None
64
"""
65
66
def add_jinja2_template_breakpoint(template_name, line_number):
67
"""
68
Add breakpoint to Jinja2 template.
69
70
Parameters:
71
- template_name (str): Name/path of the Jinja2 template
72
- line_number (int): Line number within the template
73
74
Returns:
75
bool: True if breakpoint was added successfully
76
"""
77
78
def get_jinja2_template_context(frame):
79
"""
80
Extract Jinja2 template context variables from debugging frame.
81
82
Parameters:
83
- frame: Python frame object from Jinja2 template rendering
84
85
Returns:
86
dict: Template context variables and rendering state
87
"""
88
```
89
90
### Line Validation Utilities
91
92
Utilities for validating breakpoint locations within different types of Python code and framework contexts.
93
94
```python { .api }
95
# Line validation from pydevd_plugins.pydevd_line_validation
96
97
def is_valid_breakpoint_line(filename, line_number, framework_type=None):
98
"""
99
Validate if a line is suitable for breakpoint placement.
100
101
Parameters:
102
- filename (str): Source file path
103
- line_number (int): Line number to validate
104
- framework_type (str, optional): Framework type ('django', 'jinja2', 'flask', etc.)
105
106
Returns:
107
bool: True if line can have a breakpoint, False otherwise
108
"""
109
110
def get_valid_breakpoint_lines(filename, start_line=1, end_line=None):
111
"""
112
Get all valid breakpoint lines in a file.
113
114
Parameters:
115
- filename (str): Source file path
116
- start_line (int): Starting line number (default: 1)
117
- end_line (int, optional): Ending line number (default: end of file)
118
119
Returns:
120
list: List of line numbers where breakpoints can be set
121
"""
122
123
def validate_template_breakpoint(template_path, line_number, template_type):
124
"""
125
Validate breakpoint placement in template files.
126
127
Parameters:
128
- template_path (str): Path to template file
129
- line_number (int): Line number in template
130
- template_type (str): Template type ('django', 'jinja2', 'mako', etc.)
131
132
Returns:
133
dict: Validation result with success status and mapped Python line
134
135
Example return:
136
{
137
'valid': True,
138
'python_line': 42, # Corresponding line in compiled template
139
'context': 'template_block',
140
'reason': None # or error message if not valid
141
}
142
"""
143
```
144
145
### Plugin Extension Framework
146
147
Base classes and utilities for creating custom debugging plugins for other frameworks.
148
149
```python { .api }
150
# Extension framework from pydevd_plugins.extensions
151
152
class FrameworkDebugPlugin:
153
"""
154
Base class for framework-specific debugging plugins.
155
"""
156
157
def get_plugin_name(self):
158
"""
159
Get the name of this debugging plugin.
160
161
Returns:
162
str: Plugin name identifier
163
"""
164
165
def can_handle_frame(self, frame):
166
"""
167
Check if this plugin can handle debugging for the given frame.
168
169
Parameters:
170
- frame: Python frame object
171
172
Returns:
173
bool: True if plugin can handle this frame context
174
"""
175
176
def get_frame_variables(self, frame):
177
"""
178
Extract framework-specific variables from frame.
179
180
Parameters:
181
- frame: Python frame object
182
183
Returns:
184
dict: Framework-specific variables and context information
185
"""
186
187
def handle_breakpoint(self, breakpoint, frame):
188
"""
189
Handle breakpoint hit in framework-specific context.
190
191
Parameters:
192
- breakpoint: Breakpoint object
193
- frame: Python frame where breakpoint was hit
194
195
Returns:
196
dict: Framework-specific breakpoint handling result
197
"""
198
199
def get_exception_context(self, exception, frame):
200
"""
201
Get framework-specific context for exception handling.
202
203
Parameters:
204
- exception: Exception instance
205
- frame: Python frame where exception occurred
206
207
Returns:
208
dict: Framework-specific exception context
209
"""
210
211
class TemplateDebugPlugin(FrameworkDebugPlugin):
212
"""
213
Base class for template engine debugging plugins.
214
"""
215
216
def get_template_info(self, frame):
217
"""
218
Extract template information from debugging frame.
219
220
Parameters:
221
- frame: Python frame from template rendering
222
223
Returns:
224
dict: Template information including name, line mapping, and context
225
"""
226
227
def map_template_line_to_python(self, template_path, template_line):
228
"""
229
Map template line number to corresponding Python code line.
230
231
Parameters:
232
- template_path (str): Path to template file
233
- template_line (int): Line number in template
234
235
Returns:
236
int: Corresponding line number in compiled Python code
237
"""
238
```
239
240
## Usage Examples
241
242
### Django Application Debugging
243
244
```python
245
import pydevd
246
from pydevd_plugins import django_debug
247
248
# Set up PyDevD for Django debugging
249
pydevd.settrace('localhost', port=5678)
250
251
# Enable Django-specific debugging features
252
django_debug.enable_django_template_debugging()
253
254
# Add Django exception breakpoints
255
django_debug.add_django_exception_breakpoint(
256
'Http404',
257
notify_on_handled=True,
258
notify_on_unhandled=True
259
)
260
261
django_debug.add_django_exception_breakpoint(
262
'ValidationError',
263
notify_on_handled=False,
264
notify_on_unhandled=True
265
)
266
267
# Your Django application code
268
from django.http import HttpResponse
269
from django.shortcuts import render
270
271
def my_view(request):
272
# This breakpoint will work with Django context
273
context = {'user': request.user, 'data': 'example'}
274
return render(request, 'my_template.html', context)
275
```
276
277
### Jinja2 Template Debugging
278
279
```python
280
import pydevd
281
from pydevd_plugins import jinja2_debug
282
from jinja2 import Environment, FileSystemLoader
283
284
# Set up debugging
285
pydevd.settrace('localhost', port=5678)
286
jinja2_debug.enable_jinja2_template_debugging()
287
288
# Set up Jinja2 environment
289
env = Environment(loader=FileSystemLoader('templates'))
290
291
# Add template breakpoint
292
jinja2_debug.add_jinja2_template_breakpoint('user_profile.html', 15)
293
294
# Render template (will hit breakpoint on line 15)
295
template = env.get_template('user_profile.html')
296
result = template.render(user={'name': 'John', 'age': 30})
297
```
298
299
### Custom Framework Plugin
300
301
```python
302
from pydevd_plugins.extensions import FrameworkDebugPlugin
303
304
class FlaskDebugPlugin(FrameworkDebugPlugin):
305
"""
306
Custom debugging plugin for Flask applications.
307
"""
308
309
def get_plugin_name(self):
310
return "flask_debug"
311
312
def can_handle_frame(self, frame):
313
"""Check if frame is from Flask code."""
314
# Look for Flask-specific variables in frame
315
return 'flask' in frame.f_globals.get('__name__', '') or \
316
'app' in frame.f_locals and hasattr(frame.f_locals['app'], 'config')
317
318
def get_frame_variables(self, frame):
319
"""Extract Flask-specific variables."""
320
flask_vars = {}
321
322
# Extract Flask app context
323
if 'app' in frame.f_locals:
324
app = frame.f_locals['app']
325
flask_vars['flask_app_name'] = getattr(app, 'name', 'unknown')
326
flask_vars['flask_config'] = dict(app.config) if hasattr(app, 'config') else {}
327
328
# Extract request context if available
329
try:
330
from flask import request, g, session
331
flask_vars['request_method'] = request.method
332
flask_vars['request_url'] = request.url
333
flask_vars['request_args'] = dict(request.args)
334
flask_vars['session_data'] = dict(session)
335
flask_vars['g_data'] = dict(g.__dict__)
336
except:
337
pass # Not in request context
338
339
return flask_vars
340
341
def handle_breakpoint(self, breakpoint, frame):
342
"""Handle Flask-specific breakpoint behavior."""
343
flask_context = self.get_frame_variables(frame)
344
345
return {
346
'plugin': self.get_plugin_name(),
347
'context': flask_context,
348
'additional_info': {
349
'route_info': self._get_route_info(frame),
350
'middleware_stack': self._get_middleware_info(frame)
351
}
352
}
353
354
def _get_route_info(self, frame):
355
"""Extract current route information."""
356
try:
357
from flask import request
358
return {
359
'endpoint': request.endpoint,
360
'view_args': request.view_args,
361
'url_rule': str(request.url_rule)
362
}
363
except:
364
return {}
365
366
def _get_middleware_info(self, frame):
367
"""Extract middleware information."""
368
# Implementation would depend on Flask app structure
369
return {}
370
371
# Register the custom plugin
372
flask_plugin = FlaskDebugPlugin()
373
374
# Use in debugging session
375
import pydevd
376
pydevd.settrace('localhost', port=5678)
377
378
# The plugin will automatically be used when debugging Flask code
379
```
380
381
### Template Debugging with Line Validation
382
383
```python
384
from pydevd_plugins.pydevd_line_validation import (
385
is_valid_breakpoint_line,
386
get_valid_breakpoint_lines,
387
validate_template_breakpoint
388
)
389
390
# Validate breakpoints in Python files
391
python_file = '/path/to/views.py'
392
if is_valid_breakpoint_line(python_file, 42, framework_type='django'):
393
print("Line 42 is valid for Django breakpoint")
394
395
# Get all valid breakpoint lines
396
valid_lines = get_valid_breakpoint_lines(python_file, start_line=1, end_line=100)
397
print(f"Valid breakpoint lines: {valid_lines}")
398
399
# Validate template breakpoints
400
template_file = '/path/to/template.html'
401
validation_result = validate_template_breakpoint(
402
template_file,
403
line_number=25,
404
template_type='django'
405
)
406
407
if validation_result['valid']:
408
print(f"Template breakpoint valid, maps to Python line: {validation_result['python_line']}")
409
else:
410
print(f"Template breakpoint invalid: {validation_result['reason']}")
411
```
412
413
### Advanced Framework Integration
414
415
```python
416
import pydevd
417
from pydevd_plugins.extensions import TemplateDebugPlugin
418
419
class CustomTemplateEngine(TemplateDebugPlugin):
420
"""
421
Plugin for a custom template engine.
422
"""
423
424
def get_plugin_name(self):
425
return "custom_template_engine"
426
427
def can_handle_frame(self, frame):
428
"""Check if frame is from our template engine."""
429
return 'CUSTOM_TEMPLATE_MARKER' in frame.f_globals
430
431
def get_template_info(self, frame):
432
"""Extract template information."""
433
return {
434
'template_name': frame.f_globals.get('TEMPLATE_NAME', 'unknown'),
435
'template_line': frame.f_globals.get('TEMPLATE_LINE', 0),
436
'template_context': frame.f_globals.get('TEMPLATE_CONTEXT', {})
437
}
438
439
def map_template_line_to_python(self, template_path, template_line):
440
"""Map template line to Python line."""
441
# Custom mapping logic based on template compilation
442
mapping = self._load_line_mapping(template_path)
443
return mapping.get(template_line, template_line)
444
445
def _load_line_mapping(self, template_path):
446
"""Load line mapping from template compilation metadata."""
447
# Implementation would load mapping from compiled template metadata
448
return {}
449
450
# Set up comprehensive framework debugging
451
pydevd.settrace('localhost', port=5678, suspend=False)
452
453
# Enable multiple framework debugging plugins
454
from pydevd_plugins import django_debug, jinja2_debug
455
456
django_debug.enable_django_template_debugging()
457
jinja2_debug.enable_jinja2_template_debugging()
458
459
# Register custom plugin
460
custom_plugin = CustomTemplateEngine()
461
462
print("Multi-framework debugging enabled")
463
print("- Django template debugging: enabled")
464
print("- Jinja2 template debugging: enabled")
465
print("- Custom template engine: enabled")
466
```
467
468
## Plugin Development Guidelines
469
470
### Creating Framework Plugins
471
472
1. **Inherit from FrameworkDebugPlugin**: Use the base class for consistent interface
473
2. **Frame Detection**: Implement robust `can_handle_frame()` logic
474
3. **Variable Extraction**: Provide meaningful framework-specific variable extraction
475
4. **Error Handling**: Handle framework-specific exceptions gracefully
476
5. **Performance**: Minimize overhead in frame inspection code
477
478
### Template Engine Plugins
479
480
1. **Inherit from TemplateDebugPlugin**: Use template-specific base class
481
2. **Line Mapping**: Implement accurate template-to-Python line mapping
482
3. **Context Extraction**: Extract template context variables effectively
483
4. **Compilation Integration**: Work with template compilation processes
484
5. **Multi-Template Support**: Handle nested and included templates
485
486
### Plugin Registration
487
488
Plugins are typically auto-discovered or manually registered depending on the framework detection logic implemented in the plugin's `can_handle_frame()` method.