textual-debugger 0.1.1__tar.gz → 0.1.3__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {textual_debugger-0.1.1 → textual_debugger-0.1.3}/PKG-INFO +130 -31
- {textual_debugger-0.1.1/src/tdb → textual_debugger-0.1.3}/README.md +129 -30
- {textual_debugger-0.1.1 → textual_debugger-0.1.3/src/tdb}/README.md +129 -30
- {textual_debugger-0.1.1 → textual_debugger-0.1.3}/src/tdb/__init__.py +1 -1
- textual_debugger-0.1.3/src/tdb/_timeouts.py +59 -0
- {textual_debugger-0.1.1 → textual_debugger-0.1.3}/src/tdb/app.py +332 -151
- {textual_debugger-0.1.1 → textual_debugger-0.1.3}/src/tdb/app_handlers/dap_events.py +51 -25
- {textual_debugger-0.1.1 → textual_debugger-0.1.3}/src/tdb/app_handlers/inspection.py +194 -44
- textual_debugger-0.1.3/src/tdb/app_handlers/routing.py +194 -0
- textual_debugger-0.1.3/src/tdb/app_handlers/ui_panels.py +63 -0
- {textual_debugger-0.1.1 → textual_debugger-0.1.3}/src/tdb/app_helpers.py +2 -0
- {textual_debugger-0.1.1 → textual_debugger-0.1.3}/src/tdb/breakpoint_hook.py +2 -1
- textual_debugger-0.1.3/src/tdb/cli.py +605 -0
- {textual_debugger-0.1.1 → textual_debugger-0.1.3}/src/tdb/dap/client.py +116 -27
- {textual_debugger-0.1.1 → textual_debugger-0.1.3}/src/tdb/dap/types.py +12 -4
- {textual_debugger-0.1.1 → textual_debugger-0.1.3}/src/tdb/inspection.py +39 -30
- textual_debugger-0.1.3/src/tdb/inspection_full.py +230 -0
- {textual_debugger-0.1.1 → textual_debugger-0.1.3}/src/tdb/keybindings/__init__.py +22 -11
- {textual_debugger-0.1.1 → textual_debugger-0.1.3}/src/tdb/persist.py +73 -39
- {textual_debugger-0.1.1 → textual_debugger-0.1.3}/src/tdb/post_mortem.py +39 -28
- textual_debugger-0.1.3/src/tdb/processes_cache.py +239 -0
- {textual_debugger-0.1.1 → textual_debugger-0.1.3}/src/tdb/server/event_handler.py +9 -6
- {textual_debugger-0.1.1 → textual_debugger-0.1.3}/src/tdb/server/handlers.py +84 -26
- textual_debugger-0.1.3/src/tdb/server/runner.py +132 -0
- textual_debugger-0.1.3/src/tdb/session/child_processes.py +248 -0
- {textual_debugger-0.1.1 → textual_debugger-0.1.3}/src/tdb/session/controller.py +270 -298
- {textual_debugger-0.1.1 → textual_debugger-0.1.3}/src/tdb/session/messages.py +9 -2
- textual_debugger-0.1.3/src/tdb/session/post_mortem_loader.py +78 -0
- {textual_debugger-0.1.1 → textual_debugger-0.1.3}/src/tdb/session/state.py +66 -0
- textual_debugger-0.1.3/src/tdb/session/statement_stepper.py +196 -0
- textual_debugger-0.1.3/src/tdb/session/terminal.py +121 -0
- {textual_debugger-0.1.1 → textual_debugger-0.1.3}/src/tdb/session/textual_handler.py +6 -2
- textual_debugger-0.1.3/src/tdb/source_analysis.py +162 -0
- textual_debugger-0.1.3/src/tdb/widgets/_inspection_modal.py +319 -0
- textual_debugger-0.1.3/src/tdb/widgets/async_tasks_modal.py +318 -0
- {textual_debugger-0.1.1 → textual_debugger-0.1.3}/src/tdb/widgets/breakpoint_view.py +5 -2
- {textual_debugger-0.1.1 → textual_debugger-0.1.3}/src/tdb/widgets/code_view.py +189 -57
- {textual_debugger-0.1.1 → textual_debugger-0.1.3}/src/tdb/widgets/evaluate_console.py +6 -2
- textual_debugger-0.1.3/src/tdb/widgets/full_contents_modal.py +223 -0
- {textual_debugger-0.1.1 → textual_debugger-0.1.3}/src/tdb/widgets/menu_bar.py +14 -5
- {textual_debugger-0.1.1 → textual_debugger-0.1.3}/src/tdb/widgets/modals.py +112 -6
- textual_debugger-0.1.3/src/tdb/widgets/processes_modal.py +276 -0
- {textual_debugger-0.1.1 → textual_debugger-0.1.3}/src/tdb/widgets/stack_view.py +3 -1
- {textual_debugger-0.1.1 → textual_debugger-0.1.3}/src/tdb/widgets/status_bar.py +3 -1
- textual_debugger-0.1.3/src/tdb/widgets/threads_modal.py +154 -0
- textual_debugger-0.1.3/src/tdb/widgets/variable_view.py +179 -0
- {textual_debugger-0.1.1 → textual_debugger-0.1.3}/src/textual_debugger.egg-info/PKG-INFO +130 -31
- {textual_debugger-0.1.1 → textual_debugger-0.1.3}/src/textual_debugger.egg-info/SOURCES.txt +12 -0
- textual_debugger-0.1.1/src/tdb/cli.py +0 -360
- textual_debugger-0.1.1/src/tdb/server/runner.py +0 -89
- textual_debugger-0.1.1/src/tdb/widgets/async_tasks_modal.py +0 -340
- textual_debugger-0.1.1/src/tdb/widgets/processes_modal.py +0 -279
- textual_debugger-0.1.1/src/tdb/widgets/threads_modal.py +0 -244
- textual_debugger-0.1.1/src/tdb/widgets/variable_view.py +0 -97
- {textual_debugger-0.1.1 → textual_debugger-0.1.3}/LICENSE +0 -0
- {textual_debugger-0.1.1 → textual_debugger-0.1.3}/pyproject.toml +0 -0
- {textual_debugger-0.1.1 → textual_debugger-0.1.3}/setup.cfg +0 -0
- {textual_debugger-0.1.1 → textual_debugger-0.1.3}/src/tdb/__main__.py +0 -0
- {textual_debugger-0.1.1 → textual_debugger-0.1.3}/src/tdb/app_handlers/__init__.py +0 -0
- {textual_debugger-0.1.1 → textual_debugger-0.1.3}/src/tdb/dap/__init__.py +0 -0
- {textual_debugger-0.1.1 → textual_debugger-0.1.3}/src/tdb/dap/messages.py +0 -0
- {textual_debugger-0.1.1 → textual_debugger-0.1.3}/src/tdb/dap/protocol.py +0 -0
- {textual_debugger-0.1.1 → textual_debugger-0.1.3}/src/tdb/server/__init__.py +0 -0
- {textual_debugger-0.1.1 → textual_debugger-0.1.3}/src/tdb/server/app.py +0 -0
- {textual_debugger-0.1.1 → textual_debugger-0.1.3}/src/tdb/server/rpc_types.py +0 -0
- {textual_debugger-0.1.1 → textual_debugger-0.1.3}/src/tdb/session/__init__.py +0 -0
- {textual_debugger-0.1.1 → textual_debugger-0.1.3}/src/tdb/session/event_bus.py +0 -0
- {textual_debugger-0.1.1 → textual_debugger-0.1.3}/src/tdb/widgets/__init__.py +0 -0
- {textual_debugger-0.1.1 → textual_debugger-0.1.3}/src/tdb/widgets/console_view.py +0 -0
- {textual_debugger-0.1.1 → textual_debugger-0.1.3}/src/textual_debugger.egg-info/dependency_links.txt +0 -0
- {textual_debugger-0.1.1 → textual_debugger-0.1.3}/src/textual_debugger.egg-info/entry_points.txt +0 -0
- {textual_debugger-0.1.1 → textual_debugger-0.1.3}/src/textual_debugger.egg-info/requires.txt +0 -0
- {textual_debugger-0.1.1 → textual_debugger-0.1.3}/src/textual_debugger.egg-info/top_level.txt +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: textual-debugger
|
|
3
|
-
Version: 0.1.
|
|
3
|
+
Version: 0.1.3
|
|
4
4
|
Summary: A TUI Python debugger based on textual and debugpy
|
|
5
5
|
Author-email: Al Danial <al.danial@gmail.com>
|
|
6
6
|
License: textual-debugger is licensed to you under the MIT/X Consortium license:
|
|
@@ -88,9 +88,9 @@ It specifically supports modules
|
|
|
88
88
|
- `threading` (with a thread inspector)
|
|
89
89
|
- `multiprocessing` / `concurrent.futures` (with automatic child process attachment and a process inspector)
|
|
90
90
|
|
|
91
|
-
- supports remote attachment to
|
|
91
|
+
- supports remote attachment to debugpy-enabled Python programs
|
|
92
92
|
|
|
93
|
-
- includes a JSON-RPC server mode
|
|
93
|
+
- includes a JSON-RPC server mode that enables programmatic debug control, making it suitable for
|
|
94
94
|
automated, headless debugging workflows and AI-assisted debugging
|
|
95
95
|
|
|
96
96
|
- can spawn the debuggee in an external terminal to enable debugging TUI applications
|
|
@@ -164,14 +164,16 @@ tdb my_program.py
|
|
|
164
164
|
# debug with arguments
|
|
165
165
|
tdb my_program.py arg1 arg2
|
|
166
166
|
|
|
167
|
-
# add breakpoints at lines 20 and 35 of `my_program.py` and line 14
|
|
167
|
+
# add breakpoints at lines 20 and 35 of `my_program.py` and line 14
|
|
168
|
+
# of `module.py` (when -k is given, --no-stop-on-entry is set and the
|
|
169
|
+
# program runs to the first breakpoint)
|
|
168
170
|
tdb -k 20 -k 35 -k module.py:14 my_program.py arg1 arg2
|
|
169
171
|
|
|
170
172
|
# use a specific virtualenv
|
|
171
173
|
tdb --python /path/to/venv/bin/python my_program.py
|
|
172
174
|
|
|
173
175
|
# step into, or stop at tracebacks in library code
|
|
174
|
-
tdb --no-just-my-code /path/to/venv/bin/python my_program.py
|
|
176
|
+
tdb --no-just-my-code --python /path/to/venv/bin/python my_program.py
|
|
175
177
|
|
|
176
178
|
# run until first breakpoint or exit
|
|
177
179
|
tdb --no-stop-on-entry my_program.py
|
|
@@ -180,10 +182,20 @@ tdb --no-stop-on-entry my_program.py
|
|
|
180
182
|
tdb --terminal xterm my_program.py
|
|
181
183
|
|
|
182
184
|
# attach to a remote Python program that has a debugpy server on port 5678
|
|
183
|
-
|
|
185
|
+
# (source code is automatically downloaded from the remote host)
|
|
186
|
+
tdb -r remotehost:5678
|
|
184
187
|
|
|
185
|
-
#
|
|
186
|
-
#
|
|
188
|
+
# attach to a remote Python program that has a debugpy server on port 5678
|
|
189
|
+
# and set a breakpoint where tdb and the remote program have the same
|
|
190
|
+
# source code layout
|
|
191
|
+
tdb -r remotehost:5678 -k my_program.py:42
|
|
192
|
+
|
|
193
|
+
# attach to a remote Python program that has a debugpy server on port 5678
|
|
194
|
+
# and set a breakpoint where code on the local host is at a different location
|
|
195
|
+
# than code on the remote host
|
|
196
|
+
tdb -r remotehost:5678 --local-root /my/code/dir --remote-root /app -k my_program.py:42
|
|
197
|
+
|
|
198
|
+
# separate tdb arguments from debuggee arguments with `--`
|
|
187
199
|
tdb --python /path/to/venv/bin/python -- my_program.py -k 17 --max 23.3
|
|
188
200
|
```
|
|
189
201
|
|
|
@@ -197,7 +209,7 @@ python -m tdb my_program.py
|
|
|
197
209
|
|
|
198
210
|
```
|
|
199
211
|
┌─ Header ──────────────────────────────────────────────┐
|
|
200
|
-
├─ Menu Bar (File
|
|
212
|
+
├─ Menu Bar (File / Configure / Help)───────────────────┤
|
|
201
213
|
│ │ │
|
|
202
214
|
│ Code View │ Console View (stdout) │
|
|
203
215
|
│ (source + breakpoints) ├───────────────────────────┤
|
|
@@ -242,7 +254,7 @@ A cursor line (blue) tracks your position; the current execution line is highlig
|
|
|
242
254
|
| Key | Menu |
|
|
243
255
|
|-----|------|
|
|
244
256
|
| `Alt+F` | File (open a different script to debug) |
|
|
245
|
-
| `Alt+C` | Configure (Color Theme, Keybindings) |
|
|
257
|
+
| `Alt+C` | Configure (Color Theme, Keybindings, Step Mode) |
|
|
246
258
|
| `Alt+T` | Threads |
|
|
247
259
|
| `Alt+P` | Processes |
|
|
248
260
|
| `Alt+A` | Async Tasks |
|
|
@@ -268,7 +280,7 @@ Switch from Navigate back to Debug mode with `Escape`.
|
|
|
268
280
|
|
|
269
281
|
> **Note:** Many terminals send the byte sequence `ESC+f` for `Alt+F`, which Textual's
|
|
270
282
|
ANSI parser rewrites to `Ctrl+Right` (the readline "forward-word" convention).
|
|
271
|
-
`tdb` binds both so `Alt+F` works as expected
|
|
283
|
+
`tdb` binds both so `Alt+F` works as expected.
|
|
272
284
|
|
|
273
285
|
### Debugging Controls
|
|
274
286
|
|
|
@@ -277,21 +289,42 @@ those for gdb/pdb, with some aliases and extras thrown in for convenience.
|
|
|
277
289
|
|
|
278
290
|
| Key | Action |
|
|
279
291
|
|-----|--------|
|
|
280
|
-
| `n` | Step over (next
|
|
292
|
+
| `n` | Step over (next statement) |
|
|
281
293
|
| `s` | Step into function call |
|
|
282
294
|
| `o` / `f` / `r` | Step out of current function (also aliased as "finish" and "return") |
|
|
283
295
|
| `c` | Continue execution |
|
|
284
296
|
| `p` | Pause a running program |
|
|
285
297
|
| `t` | Run to cursor position |
|
|
286
298
|
| `u` / `d` | Navigate stack up (caller) / down (callee) |
|
|
299
|
+
| `j` / `k` | Move cursor down / up (with count: `5j`, `10k`) |
|
|
300
|
+
| `G` | Go to last line (with count: `42G` jumps to line 42) |
|
|
301
|
+
| `e` | Re-display the last error (traceback) |
|
|
287
302
|
| `R` | Restart the debug session |
|
|
288
|
-
| `
|
|
303
|
+
| `q q` | Quit |
|
|
304
|
+
| `Ctrl+q` | Quit |
|
|
289
305
|
|
|
290
306
|
> **Note:** `f` ("finish") and `r` ("return") are both aliases for step-out. DAP's only
|
|
291
307
|
"exit-a-function" primitive is `stepOut`, which runs the rest of the current function
|
|
292
308
|
normally and stops at the return point. A true gdb-style immediate-return (skipping
|
|
293
309
|
remaining code in the function without executing side effects) is not supported by DAP/debugpy.
|
|
294
310
|
|
|
311
|
+
**Step granularity (statement vs. line):** by default, `n` (step over) and `s` (step into)
|
|
312
|
+
treat a multi-line source statement as a single step. For example, stepping over
|
|
313
|
+
|
|
314
|
+
```python
|
|
315
|
+
results = await asyncio.gather(
|
|
316
|
+
fetch(1, 2),
|
|
317
|
+
fetch(2, 1),
|
|
318
|
+
fetch(3, 3),
|
|
319
|
+
)
|
|
320
|
+
print(results) # next stop lands here, not on each sub-line above
|
|
321
|
+
```
|
|
322
|
+
|
|
323
|
+
lands on `print(results)`, not on each interior sub-line of the `gather` call. Switch to
|
|
324
|
+
**Line** mode (Configure > Step Mode) to get debugpy's native per-line behavior, which
|
|
325
|
+
stops on each physical line--useful for inspecting how a complex expression is built up.
|
|
326
|
+
The choice is saved to `~/.config/tdb/config.json`.
|
|
327
|
+
|
|
295
328
|
### Breakpoints
|
|
296
329
|
|
|
297
330
|
Click the gutter in the Code View to toggle a breakpoint, or press `b` in Debug mode.
|
|
@@ -316,6 +349,11 @@ The Variable View shows a tree of scopes (Locals, Globals) with all variables in
|
|
|
316
349
|
frame. Expand nodes to drill into complex objects. Children are loaded lazily on demand.
|
|
317
350
|
Variable values can be changed in the Evaluate Console.
|
|
318
351
|
|
|
352
|
+
Double-click a variable, or highlight the variable with the text cursor in
|
|
353
|
+
the Variables View and press `Enter`
|
|
354
|
+
to display that variable in a modal. This simplifies inspection of
|
|
355
|
+
large or deeply nested data structures.
|
|
356
|
+
|
|
319
357
|
### Call Stack
|
|
320
358
|
|
|
321
359
|
The Stack View shows the full call stack. Click a frame to navigate to its source
|
|
@@ -323,7 +361,8 @@ location and inspect its variables.
|
|
|
323
361
|
|
|
324
362
|
### Evaluate Console
|
|
325
363
|
|
|
326
|
-
A REPL at the bottom
|
|
364
|
+
A read-evaluate-print loop (REPL) at the bottom left permits
|
|
365
|
+
interactive evaluation of expressions in the current scope:
|
|
327
366
|
|
|
328
367
|
```
|
|
329
368
|
>>> len(items)
|
|
@@ -349,8 +388,11 @@ The Console View captures stdout (normal text) and stderr (red text) from the de
|
|
|
349
388
|
in real time.
|
|
350
389
|
|
|
351
390
|
If your program prints a lot, or prompts for input, or uses colors or
|
|
352
|
-
terminal control codes,
|
|
353
|
-
with `--terminal` for
|
|
391
|
+
terminal control codes, run the program in an external terminal
|
|
392
|
+
with `--terminal` for a better experience.
|
|
393
|
+
The `--terminal` switch requires a graphical environment and a compatible
|
|
394
|
+
terminal emulator.
|
|
395
|
+
|
|
354
396
|
|
|
355
397
|
### Crash Detection
|
|
356
398
|
|
|
@@ -360,6 +402,9 @@ When the debuggee raises an unhandled exception, `tdb`:
|
|
|
360
402
|
3. Populates the Stack View with the exception's call stack
|
|
361
403
|
4. Lets you press `R` to restart or `Escape` to dismiss
|
|
362
404
|
|
|
405
|
+
> Note: after dismissing the traceback modal, you
|
|
406
|
+
> can display it again by hitting `e` when focus is in the Code View.
|
|
407
|
+
|
|
363
408
|
### Post-Mortem Exception Hook
|
|
364
409
|
|
|
365
410
|
You can have `tdb` pop open automatically when *any* Python program crashes without the
|
|
@@ -368,7 +413,6 @@ need to launch through `tdb` up front. Install the hook once at the top of your
|
|
|
368
413
|
```python
|
|
369
414
|
import sys
|
|
370
415
|
import tdb
|
|
371
|
-
|
|
372
416
|
sys.excepthook = tdb.exception_hook
|
|
373
417
|
```
|
|
374
418
|
|
|
@@ -386,11 +430,11 @@ In post-mortem mode you can:
|
|
|
386
430
|
- Read the full traceback (including chained `cause`/`context` exceptions) in the Console View
|
|
387
431
|
- Jump around the source with the full Code View (syntax highlighting, goto-line, etc.)
|
|
388
432
|
|
|
389
|
-
Stepping,
|
|
390
|
-
interpreter is gone
|
|
433
|
+
Stepping, continue, breakpoints, restart, and the Evaluate View are disabled. The original
|
|
434
|
+
interpreter is gone since the view is a frozen snapshot. Press `q` to exit.
|
|
391
435
|
|
|
392
436
|
The hook is a no-op when stdin/stdout aren't a tty (e.g. when your program is piped or
|
|
393
|
-
run from cron), so it
|
|
437
|
+
run from cron), so it is safe to leave installed in production code. Snapshots are
|
|
394
438
|
written to a temp file that is deleted as soon as `tdb` exits.
|
|
395
439
|
|
|
396
440
|
Snapshot depth / breadth is capped (5 levels, 50 children per container) to keep the
|
|
@@ -401,7 +445,6 @@ memoization.
|
|
|
401
445
|
|
|
402
446
|
`tdb` has an improved implemenation of the standard `breakpoint()` function (or equivalently,
|
|
403
447
|
`pdb.set_trace()`) used to pause at a specific line to inspect, then
|
|
404
|
-
here=
|
|
405
448
|
continuing--use `tdb.breakpoint()`:
|
|
406
449
|
|
|
407
450
|
```python
|
|
@@ -424,7 +467,7 @@ spawns `python -m tdb -r <port>` as a subprocess so the TUI takes over the termi
|
|
|
424
467
|
and pauses the calling thread at the line that called `tdb.breakpoint()` (the hook
|
|
425
468
|
auto-steps out of its own helper so you land in your own frame, not inside
|
|
426
469
|
`breakpoint_hook.py`). Stepping (`n`/`s`/`o`), `continue`, and setting/removing breakpoints
|
|
427
|
-
all work normally; quitting `tdb` (`Ctrl+
|
|
470
|
+
all work normally; quitting `tdb` (`Ctrl+q`) detaches without killing the program, and
|
|
428
471
|
debugpy auto-resumes any threads still paused.
|
|
429
472
|
|
|
430
473
|
This differs from `tdb.exception_hook` in one way:
|
|
@@ -437,6 +480,12 @@ drive the user's program forward.
|
|
|
437
480
|
As with `exception_hook`, the call is a no-op when stdin/stdout aren't a tty, so it's
|
|
438
481
|
safe to leave in code paths that sometimes run headless.
|
|
439
482
|
|
|
483
|
+
Quitting `tdb` while paused in a `tdb.breakpoint()` session detaches the debugger and
|
|
484
|
+
lets the program continue running normally.
|
|
485
|
+
This behavior matches hitting `c` while in a conventional (that is, the Python
|
|
486
|
+
standard library's) `breakpoint()` session.
|
|
487
|
+
If you want to kill the program instead, use `Ctrl+c` in the terminal running the debuggee.
|
|
488
|
+
|
|
440
489
|
### Async Task Inspector
|
|
441
490
|
|
|
442
491
|
For programs using `asyncio`, the menu bar shows an **Async Tasks (N)** label with the count of
|
|
@@ -446,13 +495,17 @@ active tasks (updated each time the program stops). Click it to open a full-scre
|
|
|
446
495
|
primitive (`Lock.acquire`, `Queue.get`, `asyncio.sleep`, …), and coroutine
|
|
447
496
|
- **Right pane**: detail view with full stack trace and an expandable variable tree (same
|
|
448
497
|
as the main Variables View) for the selected task
|
|
449
|
-
- Press `g` to switch the right pane to the **wait graph**
|
|
498
|
+
- Press `g` to switch the right pane to the **wait graph** which is a tree showing
|
|
499
|
+
each blocked
|
|
450
500
|
task, the asyncio primitive it's parked on, and the task(s) holding that primitive.
|
|
451
501
|
Cycles (deadlocks) are highlighted in red both in the task table and as a "Deadlock
|
|
452
502
|
cycles" section at the top of the graph. Selecting a node in the tree highlights the
|
|
453
503
|
corresponding task in the table.
|
|
454
504
|
- Navigate with arrow keys; press `r` to refresh, `Escape` to close
|
|
455
505
|
|
|
506
|
+
> Note: Async task relationships may be directed acyclic graphs (DAGs) rather than trees
|
|
507
|
+
> but I don't know of a way to visualize DAGs in textual.
|
|
508
|
+
|
|
456
509
|
RPC equivalents:
|
|
457
510
|
|
|
458
511
|
```bash
|
|
@@ -564,6 +617,36 @@ All debugging features (breakpoints, stepping, variable inspection, threads, pro
|
|
|
564
617
|
async tasks) work in remote attach mode. The Code View automatically navigates to the
|
|
565
618
|
source file when the program stops.
|
|
566
619
|
|
|
620
|
+
**Mapping remote paths to local copies (`--local-root` / `--remote-root`):** when the
|
|
621
|
+
debuggee lives on another machine, or in a container, or simply in a different directory
|
|
622
|
+
on the same machine, the source paths it reports (and the paths it expects breakpoints
|
|
623
|
+
to refer to) won't match anything on the `tdb` host. To bridge that gap, give `tdb` one
|
|
624
|
+
or more `--local-root` / `--remote-root` pairs. Each `--local-root` points at a local
|
|
625
|
+
directory containing a copy of the code; each `--remote-root` is the corresponding path
|
|
626
|
+
on the debuggee. The two flags must be supplied in equal numbers and are paired in CLI
|
|
627
|
+
order via `zip()`, so the first `--local-root` matches the first `--remote-root`, the
|
|
628
|
+
second matches the second, and so on. `debugpy` then translates paths bidirectionally:
|
|
629
|
+
breakpoints set on a local file land on the matching remote file, and source paths
|
|
630
|
+
returned in stopped-events / stack-traces are rewritten back to the local copy so the
|
|
631
|
+
Code View loads directly from disk (no DAP `source` round-trip needed).
|
|
632
|
+
|
|
633
|
+
These flags are required whenever you want to set a `-k` breakpoint against a remote
|
|
634
|
+
debuggee whose code lives at a different path than your local copy. For example, if the
|
|
635
|
+
remote runs `program.py` at `/path/to/code/program.py` and your local copy is at
|
|
636
|
+
`/local/project/code/program.py`, set a breakpoint at line 321 with:
|
|
637
|
+
|
|
638
|
+
```bash
|
|
639
|
+
tdb -r RHOST:15678 \
|
|
640
|
+
--local-root /local/project/code \
|
|
641
|
+
--remote-root /path/to/code \
|
|
642
|
+
-k program.py:321
|
|
643
|
+
```
|
|
644
|
+
|
|
645
|
+
With `--local-root` set, a relative `-k FILE:LINE` is resolved by searching each
|
|
646
|
+
`--local-root` directory in CLI order (first match wins); absolute paths still work as
|
|
647
|
+
before. Multiple pairs can be supplied to mirror multiple source trees (e.g. an
|
|
648
|
+
application directory and a shared library directory) in one invocation.
|
|
649
|
+
|
|
567
650
|
### External Terminal Support
|
|
568
651
|
|
|
569
652
|
Some Python programs, notably text user interfaces, use terminal control
|
|
@@ -691,22 +774,25 @@ Each is JSON with `event`, `data`, and `timestamp` fields.
|
|
|
691
774
|
## CLI Reference
|
|
692
775
|
|
|
693
776
|
```
|
|
694
|
-
usage: tdb [-h] [-v
|
|
695
|
-
[--no-just-my-code] [--no-subprocess] [--python PYTHON]
|
|
696
|
-
[
|
|
777
|
+
usage: tdb [-h] [-v] [-r [HOST:]PORT] [--cwd CWD] [--no-stop-on-entry]
|
|
778
|
+
[--no-just-my-code] [--no-subprocess] [--python PYTHON] [--pv]
|
|
779
|
+
[--keybindings {default,vim,emacs}]
|
|
697
780
|
[--terminal {xterm,konsole,gnome-terminal,ghostty,kitty,iterm2,warp,wezterm,terminator}]
|
|
698
|
-
[--
|
|
781
|
+
[--local-root PATH] [--remote-root PATH]
|
|
782
|
+
[--server] [--headless] [-k FILE:LINE|LINE] [--server-port SERVER_PORT] [-d] [--doc-text]
|
|
699
783
|
[program] [args ...]
|
|
700
|
-
|
|
701
784
|
```
|
|
702
785
|
|
|
703
786
|
| Flag | Description |
|
|
704
787
|
|------|-------------|
|
|
705
788
|
| `-r HOST:PORT` | Attach to a remote debugpy server |
|
|
706
|
-
|
|
|
707
|
-
| `--
|
|
789
|
+
| `--local-root PATH` | Local directory containing a copy of remote code (repeat to mirror multiple trees). Pair with `--remote-root`; counts must match. Required when `-k` sets a breakpoint against a remote debuggee whose code lives at a different path. |
|
|
790
|
+
| `--remote-root PATH` | Remote directory matched to `--local-root` (same CLI position via `zip()`). |
|
|
791
|
+
| `-k`, `--breakpoint FILE:LINE|LINE` | Set a breakpoint (may be repeated). Passing `-k` implies `--no-stop-on-entry` so the program runs straight to the first breakpoint. |
|
|
792
|
+
| `--no-stop-on-entry` | Do not pause at the first line (default: stop on entry; automatic when `-k` is given) |
|
|
708
793
|
| `--cwd DIR` | Working directory for the debuggee |
|
|
709
794
|
| `--python PATH` | Python interpreter for the debuggee |
|
|
795
|
+
| `--pv` | Shorthand for --python .venv/bin/python |
|
|
710
796
|
| `--no-just-my-code` | Step into stdlib/site-packages code instead of skipping it
|
|
711
797
|
(default: skipped). On uncaught exceptions, the crash modal always shows the full traceback
|
|
712
798
|
including library frames, regardless of this flag. |
|
|
@@ -726,12 +812,25 @@ On Windows, it uses `%APPDATA%\tdb\`.
|
|
|
726
812
|
|
|
727
813
|
| File | Contents |
|
|
728
814
|
|------|----------|
|
|
729
|
-
| `config.json` | User preferences (keybinding scheme) |
|
|
815
|
+
| `config.json` | User preferences (keybinding scheme, color theme, step mode) |
|
|
730
816
|
| `breakpoints.json` | Breakpoints from previous sessions, keyed by project directory |
|
|
731
817
|
|
|
732
818
|
Breakpoints are saved on exit and restored when debugging a program in the same
|
|
733
819
|
directory. Each project's breakpoints are independent.
|
|
734
820
|
|
|
821
|
+
**Step mode** (`step_mode` in `config.json`) controls how `n` (step over) and `s` (step
|
|
822
|
+
into) handle multi-line source statements:
|
|
823
|
+
|
|
824
|
+
| Value | Behavior |
|
|
825
|
+
|-------|----------|
|
|
826
|
+
| `"statement"` (default) | A multi-line statement (e.g. a `gather(...)` call spanning five lines) is one step. The debugger keeps issuing DAP steps until execution leaves the statement, then stops on the next logical line. |
|
|
827
|
+
| `"line"` | debugpy's native per-line behavior (stops on every physical line, including each interior sub-line of a multi-line expression)|
|
|
828
|
+
|
|
829
|
+
Change it from the menu (**Configure > Step Mode**); the choice is saved immediately and
|
|
830
|
+
applies to all future sessions. Breakpoint hits, exceptions, and pauses always interrupt
|
|
831
|
+
a statement step, so a breakpoint set on a sub-line of a multi-line expression still
|
|
832
|
+
fires as expected.
|
|
833
|
+
|
|
735
834
|
## Tech Stack
|
|
736
835
|
|
|
737
836
|
- [textual](https://github.com/Textualize/textual) : TUI framework
|