or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

core-debugging.mdfile-system.mdframework-integration.mdindex.mdinteractive-console.mdipython-integration.mdprocess-attachment.mdprogrammatic-api.md

framework-integration.mddocs/

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.