textual-debugger 0.1.1__tar.gz → 0.1.2__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.2}/PKG-INFO +42 -8
- {textual_debugger-0.1.1/src/tdb → textual_debugger-0.1.2}/README.md +41 -7
- {textual_debugger-0.1.1 → textual_debugger-0.1.2/src/tdb}/README.md +41 -7
- {textual_debugger-0.1.1 → textual_debugger-0.1.2}/src/tdb/__init__.py +1 -1
- textual_debugger-0.1.2/src/tdb/_timeouts.py +59 -0
- {textual_debugger-0.1.1 → textual_debugger-0.1.2}/src/tdb/app.py +189 -146
- {textual_debugger-0.1.1 → textual_debugger-0.1.2}/src/tdb/app_handlers/dap_events.py +40 -23
- {textual_debugger-0.1.1 → textual_debugger-0.1.2}/src/tdb/app_handlers/inspection.py +152 -45
- textual_debugger-0.1.2/src/tdb/app_handlers/routing.py +194 -0
- textual_debugger-0.1.2/src/tdb/app_handlers/ui_panels.py +53 -0
- {textual_debugger-0.1.1 → textual_debugger-0.1.2}/src/tdb/app_helpers.py +2 -0
- {textual_debugger-0.1.1 → textual_debugger-0.1.2}/src/tdb/breakpoint_hook.py +2 -1
- {textual_debugger-0.1.1 → textual_debugger-0.1.2}/src/tdb/cli.py +176 -61
- {textual_debugger-0.1.1 → textual_debugger-0.1.2}/src/tdb/dap/client.py +61 -27
- {textual_debugger-0.1.1 → textual_debugger-0.1.2}/src/tdb/dap/types.py +12 -4
- {textual_debugger-0.1.1 → textual_debugger-0.1.2}/src/tdb/inspection.py +39 -30
- {textual_debugger-0.1.1 → textual_debugger-0.1.2}/src/tdb/keybindings/__init__.py +20 -11
- {textual_debugger-0.1.1 → textual_debugger-0.1.2}/src/tdb/persist.py +73 -39
- {textual_debugger-0.1.1 → textual_debugger-0.1.2}/src/tdb/post_mortem.py +39 -28
- textual_debugger-0.1.2/src/tdb/processes_cache.py +239 -0
- {textual_debugger-0.1.1 → textual_debugger-0.1.2}/src/tdb/server/event_handler.py +9 -6
- {textual_debugger-0.1.1 → textual_debugger-0.1.2}/src/tdb/server/handlers.py +84 -26
- {textual_debugger-0.1.1 → textual_debugger-0.1.2}/src/tdb/server/runner.py +8 -2
- textual_debugger-0.1.2/src/tdb/session/child_processes.py +248 -0
- {textual_debugger-0.1.1 → textual_debugger-0.1.2}/src/tdb/session/controller.py +220 -297
- {textual_debugger-0.1.1 → textual_debugger-0.1.2}/src/tdb/session/messages.py +9 -2
- textual_debugger-0.1.2/src/tdb/session/post_mortem_loader.py +78 -0
- {textual_debugger-0.1.1 → textual_debugger-0.1.2}/src/tdb/session/state.py +66 -0
- textual_debugger-0.1.2/src/tdb/session/statement_stepper.py +196 -0
- textual_debugger-0.1.2/src/tdb/session/terminal.py +121 -0
- {textual_debugger-0.1.1 → textual_debugger-0.1.2}/src/tdb/session/textual_handler.py +6 -2
- textual_debugger-0.1.2/src/tdb/source_analysis.py +162 -0
- textual_debugger-0.1.2/src/tdb/widgets/_inspection_modal.py +319 -0
- textual_debugger-0.1.2/src/tdb/widgets/async_tasks_modal.py +318 -0
- {textual_debugger-0.1.1 → textual_debugger-0.1.2}/src/tdb/widgets/breakpoint_view.py +5 -2
- {textual_debugger-0.1.1 → textual_debugger-0.1.2}/src/tdb/widgets/code_view.py +164 -56
- {textual_debugger-0.1.1 → textual_debugger-0.1.2}/src/tdb/widgets/evaluate_console.py +6 -2
- {textual_debugger-0.1.1 → textual_debugger-0.1.2}/src/tdb/widgets/menu_bar.py +14 -5
- {textual_debugger-0.1.1 → textual_debugger-0.1.2}/src/tdb/widgets/modals.py +112 -6
- textual_debugger-0.1.2/src/tdb/widgets/processes_modal.py +276 -0
- {textual_debugger-0.1.1 → textual_debugger-0.1.2}/src/tdb/widgets/stack_view.py +3 -1
- {textual_debugger-0.1.1 → textual_debugger-0.1.2}/src/tdb/widgets/status_bar.py +3 -1
- textual_debugger-0.1.2/src/tdb/widgets/threads_modal.py +154 -0
- {textual_debugger-0.1.1 → textual_debugger-0.1.2}/src/tdb/widgets/variable_view.py +3 -6
- {textual_debugger-0.1.1 → textual_debugger-0.1.2}/src/textual_debugger.egg-info/PKG-INFO +42 -8
- {textual_debugger-0.1.1 → textual_debugger-0.1.2}/src/textual_debugger.egg-info/SOURCES.txt +10 -0
- 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 → textual_debugger-0.1.2}/LICENSE +0 -0
- {textual_debugger-0.1.1 → textual_debugger-0.1.2}/pyproject.toml +0 -0
- {textual_debugger-0.1.1 → textual_debugger-0.1.2}/setup.cfg +0 -0
- {textual_debugger-0.1.1 → textual_debugger-0.1.2}/src/tdb/__main__.py +0 -0
- {textual_debugger-0.1.1 → textual_debugger-0.1.2}/src/tdb/app_handlers/__init__.py +0 -0
- {textual_debugger-0.1.1 → textual_debugger-0.1.2}/src/tdb/dap/__init__.py +0 -0
- {textual_debugger-0.1.1 → textual_debugger-0.1.2}/src/tdb/dap/messages.py +0 -0
- {textual_debugger-0.1.1 → textual_debugger-0.1.2}/src/tdb/dap/protocol.py +0 -0
- {textual_debugger-0.1.1 → textual_debugger-0.1.2}/src/tdb/server/__init__.py +0 -0
- {textual_debugger-0.1.1 → textual_debugger-0.1.2}/src/tdb/server/app.py +0 -0
- {textual_debugger-0.1.1 → textual_debugger-0.1.2}/src/tdb/server/rpc_types.py +0 -0
- {textual_debugger-0.1.1 → textual_debugger-0.1.2}/src/tdb/session/__init__.py +0 -0
- {textual_debugger-0.1.1 → textual_debugger-0.1.2}/src/tdb/session/event_bus.py +0 -0
- {textual_debugger-0.1.1 → textual_debugger-0.1.2}/src/tdb/widgets/__init__.py +0 -0
- {textual_debugger-0.1.1 → textual_debugger-0.1.2}/src/tdb/widgets/console_view.py +0 -0
- {textual_debugger-0.1.1 → textual_debugger-0.1.2}/src/textual_debugger.egg-info/dependency_links.txt +0 -0
- {textual_debugger-0.1.1 → textual_debugger-0.1.2}/src/textual_debugger.egg-info/entry_points.txt +0 -0
- {textual_debugger-0.1.1 → textual_debugger-0.1.2}/src/textual_debugger.egg-info/requires.txt +0 -0
- {textual_debugger-0.1.1 → textual_debugger-0.1.2}/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.2
|
|
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:
|
|
@@ -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
|
|
@@ -242,7 +244,7 @@ A cursor line (blue) tracks your position; the current execution line is highlig
|
|
|
242
244
|
| Key | Menu |
|
|
243
245
|
|-----|------|
|
|
244
246
|
| `Alt+F` | File (open a different script to debug) |
|
|
245
|
-
| `Alt+C` | Configure (Color Theme, Keybindings) |
|
|
247
|
+
| `Alt+C` | Configure (Color Theme, Keybindings, Step Mode) |
|
|
246
248
|
| `Alt+T` | Threads |
|
|
247
249
|
| `Alt+P` | Processes |
|
|
248
250
|
| `Alt+A` | Async Tasks |
|
|
@@ -277,13 +279,15 @@ those for gdb/pdb, with some aliases and extras thrown in for convenience.
|
|
|
277
279
|
|
|
278
280
|
| Key | Action |
|
|
279
281
|
|-----|--------|
|
|
280
|
-
| `n` | Step over (next
|
|
282
|
+
| `n` | Step over (next statement) |
|
|
281
283
|
| `s` | Step into function call |
|
|
282
284
|
| `o` / `f` / `r` | Step out of current function (also aliased as "finish" and "return") |
|
|
283
285
|
| `c` | Continue execution |
|
|
284
286
|
| `p` | Pause a running program |
|
|
285
287
|
| `t` | Run to cursor position |
|
|
286
288
|
| `u` / `d` | Navigate stack up (caller) / down (callee) |
|
|
289
|
+
| `j` / `k` | Move cursor down / up (with count: `5j`, `10k`) |
|
|
290
|
+
| `G` | Go to last line (with count: `42G` jumps to line 42) |
|
|
287
291
|
| `R` | Restart the debug session |
|
|
288
292
|
| `Ctrl+Q` | Quit |
|
|
289
293
|
|
|
@@ -292,6 +296,23 @@ those for gdb/pdb, with some aliases and extras thrown in for convenience.
|
|
|
292
296
|
normally and stops at the return point. A true gdb-style immediate-return (skipping
|
|
293
297
|
remaining code in the function without executing side effects) is not supported by DAP/debugpy.
|
|
294
298
|
|
|
299
|
+
**Step granularity (statement vs. line):** by default, `n` (step over) and `s` (step into)
|
|
300
|
+
treat a multi-line source statement as a single step. For example, stepping over
|
|
301
|
+
|
|
302
|
+
```python
|
|
303
|
+
results = await asyncio.gather(
|
|
304
|
+
fetch(1, 2),
|
|
305
|
+
fetch(2, 1),
|
|
306
|
+
fetch(3, 3),
|
|
307
|
+
)
|
|
308
|
+
print(results) # next stop lands here, not on each sub-line above
|
|
309
|
+
```
|
|
310
|
+
|
|
311
|
+
lands on `print(results)`, not on each interior sub-line of the `gather` call. Switch to
|
|
312
|
+
**Line** mode (Configure > Step Mode) to get debugpy's native per-line behavior, which
|
|
313
|
+
stops on each physical line — useful for inspecting how a complex expression is built up.
|
|
314
|
+
The choice is saved to `~/.config/tdb/config.json`.
|
|
315
|
+
|
|
295
316
|
### Breakpoints
|
|
296
317
|
|
|
297
318
|
Click the gutter in the Code View to toggle a breakpoint, or press `b` in Debug mode.
|
|
@@ -703,8 +724,8 @@ usage: tdb [-h] [-v/--version] [-r [HOST:]PORT] [--cwd CWD] [--no-stop-on-entry]
|
|
|
703
724
|
| Flag | Description |
|
|
704
725
|
|------|-------------|
|
|
705
726
|
| `-r HOST:PORT` | Attach to a remote debugpy server |
|
|
706
|
-
| `-k`, `--breakpoint FILE:LINE|LINE` | Set a breakpoint (may be repeated) |
|
|
707
|
-
| `--no-stop-on-entry` | Do not pause at the first line (default: stop on entry) |
|
|
727
|
+
| `-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. |
|
|
728
|
+
| `--no-stop-on-entry` | Do not pause at the first line (default: stop on entry; automatic when `-k` is given) |
|
|
708
729
|
| `--cwd DIR` | Working directory for the debuggee |
|
|
709
730
|
| `--python PATH` | Python interpreter for the debuggee |
|
|
710
731
|
| `--no-just-my-code` | Step into stdlib/site-packages code instead of skipping it
|
|
@@ -726,12 +747,25 @@ On Windows, it uses `%APPDATA%\tdb\`.
|
|
|
726
747
|
|
|
727
748
|
| File | Contents |
|
|
728
749
|
|------|----------|
|
|
729
|
-
| `config.json` | User preferences (keybinding scheme) |
|
|
750
|
+
| `config.json` | User preferences (keybinding scheme, color theme, step mode) |
|
|
730
751
|
| `breakpoints.json` | Breakpoints from previous sessions, keyed by project directory |
|
|
731
752
|
|
|
732
753
|
Breakpoints are saved on exit and restored when debugging a program in the same
|
|
733
754
|
directory. Each project's breakpoints are independent.
|
|
734
755
|
|
|
756
|
+
**Step mode** (`step_mode` in `config.json`) controls how `n` (step over) and `s` (step
|
|
757
|
+
into) handle multi-line source statements:
|
|
758
|
+
|
|
759
|
+
| Value | Behavior |
|
|
760
|
+
|-------|----------|
|
|
761
|
+
| `"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. |
|
|
762
|
+
| `"line"` | debugpy's native per-line behavior — stops on every physical line, including each interior sub-line of a multi-line expression. |
|
|
763
|
+
|
|
764
|
+
Change it from the menu (**Configure > Step Mode**); the choice is saved immediately and
|
|
765
|
+
applies to all future sessions. Breakpoint hits, exceptions, and pauses always interrupt
|
|
766
|
+
a statement step, so a breakpoint set on a sub-line of a multi-line expression still
|
|
767
|
+
fires as expected.
|
|
768
|
+
|
|
735
769
|
## Tech Stack
|
|
736
770
|
|
|
737
771
|
- [textual](https://github.com/Textualize/textual) : TUI framework
|
|
@@ -99,14 +99,16 @@ tdb my_program.py
|
|
|
99
99
|
# debug with arguments
|
|
100
100
|
tdb my_program.py arg1 arg2
|
|
101
101
|
|
|
102
|
-
# add breakpoints at lines 20 and 35 of `my_program.py` and line 14
|
|
102
|
+
# add breakpoints at lines 20 and 35 of `my_program.py` and line 14
|
|
103
|
+
# of `module.py` (when -k is given, --no-stop-on-entry is set and the
|
|
104
|
+
# program runs to the first breakpoint)
|
|
103
105
|
tdb -k 20 -k 35 -k module.py:14 my_program.py arg1 arg2
|
|
104
106
|
|
|
105
107
|
# use a specific virtualenv
|
|
106
108
|
tdb --python /path/to/venv/bin/python my_program.py
|
|
107
109
|
|
|
108
110
|
# step into, or stop at tracebacks in library code
|
|
109
|
-
tdb --no-just-my-code /path/to/venv/bin/python my_program.py
|
|
111
|
+
tdb --no-just-my-code --python /path/to/venv/bin/python my_program.py
|
|
110
112
|
|
|
111
113
|
# run until first breakpoint or exit
|
|
112
114
|
tdb --no-stop-on-entry my_program.py
|
|
@@ -177,7 +179,7 @@ A cursor line (blue) tracks your position; the current execution line is highlig
|
|
|
177
179
|
| Key | Menu |
|
|
178
180
|
|-----|------|
|
|
179
181
|
| `Alt+F` | File (open a different script to debug) |
|
|
180
|
-
| `Alt+C` | Configure (Color Theme, Keybindings) |
|
|
182
|
+
| `Alt+C` | Configure (Color Theme, Keybindings, Step Mode) |
|
|
181
183
|
| `Alt+T` | Threads |
|
|
182
184
|
| `Alt+P` | Processes |
|
|
183
185
|
| `Alt+A` | Async Tasks |
|
|
@@ -212,13 +214,15 @@ those for gdb/pdb, with some aliases and extras thrown in for convenience.
|
|
|
212
214
|
|
|
213
215
|
| Key | Action |
|
|
214
216
|
|-----|--------|
|
|
215
|
-
| `n` | Step over (next
|
|
217
|
+
| `n` | Step over (next statement) |
|
|
216
218
|
| `s` | Step into function call |
|
|
217
219
|
| `o` / `f` / `r` | Step out of current function (also aliased as "finish" and "return") |
|
|
218
220
|
| `c` | Continue execution |
|
|
219
221
|
| `p` | Pause a running program |
|
|
220
222
|
| `t` | Run to cursor position |
|
|
221
223
|
| `u` / `d` | Navigate stack up (caller) / down (callee) |
|
|
224
|
+
| `j` / `k` | Move cursor down / up (with count: `5j`, `10k`) |
|
|
225
|
+
| `G` | Go to last line (with count: `42G` jumps to line 42) |
|
|
222
226
|
| `R` | Restart the debug session |
|
|
223
227
|
| `Ctrl+Q` | Quit |
|
|
224
228
|
|
|
@@ -227,6 +231,23 @@ those for gdb/pdb, with some aliases and extras thrown in for convenience.
|
|
|
227
231
|
normally and stops at the return point. A true gdb-style immediate-return (skipping
|
|
228
232
|
remaining code in the function without executing side effects) is not supported by DAP/debugpy.
|
|
229
233
|
|
|
234
|
+
**Step granularity (statement vs. line):** by default, `n` (step over) and `s` (step into)
|
|
235
|
+
treat a multi-line source statement as a single step. For example, stepping over
|
|
236
|
+
|
|
237
|
+
```python
|
|
238
|
+
results = await asyncio.gather(
|
|
239
|
+
fetch(1, 2),
|
|
240
|
+
fetch(2, 1),
|
|
241
|
+
fetch(3, 3),
|
|
242
|
+
)
|
|
243
|
+
print(results) # next stop lands here, not on each sub-line above
|
|
244
|
+
```
|
|
245
|
+
|
|
246
|
+
lands on `print(results)`, not on each interior sub-line of the `gather` call. Switch to
|
|
247
|
+
**Line** mode (Configure > Step Mode) to get debugpy's native per-line behavior, which
|
|
248
|
+
stops on each physical line — useful for inspecting how a complex expression is built up.
|
|
249
|
+
The choice is saved to `~/.config/tdb/config.json`.
|
|
250
|
+
|
|
230
251
|
### Breakpoints
|
|
231
252
|
|
|
232
253
|
Click the gutter in the Code View to toggle a breakpoint, or press `b` in Debug mode.
|
|
@@ -638,8 +659,8 @@ usage: tdb [-h] [-v/--version] [-r [HOST:]PORT] [--cwd CWD] [--no-stop-on-entry]
|
|
|
638
659
|
| Flag | Description |
|
|
639
660
|
|------|-------------|
|
|
640
661
|
| `-r HOST:PORT` | Attach to a remote debugpy server |
|
|
641
|
-
| `-k`, `--breakpoint FILE:LINE|LINE` | Set a breakpoint (may be repeated) |
|
|
642
|
-
| `--no-stop-on-entry` | Do not pause at the first line (default: stop on entry) |
|
|
662
|
+
| `-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. |
|
|
663
|
+
| `--no-stop-on-entry` | Do not pause at the first line (default: stop on entry; automatic when `-k` is given) |
|
|
643
664
|
| `--cwd DIR` | Working directory for the debuggee |
|
|
644
665
|
| `--python PATH` | Python interpreter for the debuggee |
|
|
645
666
|
| `--no-just-my-code` | Step into stdlib/site-packages code instead of skipping it
|
|
@@ -661,12 +682,25 @@ On Windows, it uses `%APPDATA%\tdb\`.
|
|
|
661
682
|
|
|
662
683
|
| File | Contents |
|
|
663
684
|
|------|----------|
|
|
664
|
-
| `config.json` | User preferences (keybinding scheme) |
|
|
685
|
+
| `config.json` | User preferences (keybinding scheme, color theme, step mode) |
|
|
665
686
|
| `breakpoints.json` | Breakpoints from previous sessions, keyed by project directory |
|
|
666
687
|
|
|
667
688
|
Breakpoints are saved on exit and restored when debugging a program in the same
|
|
668
689
|
directory. Each project's breakpoints are independent.
|
|
669
690
|
|
|
691
|
+
**Step mode** (`step_mode` in `config.json`) controls how `n` (step over) and `s` (step
|
|
692
|
+
into) handle multi-line source statements:
|
|
693
|
+
|
|
694
|
+
| Value | Behavior |
|
|
695
|
+
|-------|----------|
|
|
696
|
+
| `"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. |
|
|
697
|
+
| `"line"` | debugpy's native per-line behavior — stops on every physical line, including each interior sub-line of a multi-line expression. |
|
|
698
|
+
|
|
699
|
+
Change it from the menu (**Configure > Step Mode**); the choice is saved immediately and
|
|
700
|
+
applies to all future sessions. Breakpoint hits, exceptions, and pauses always interrupt
|
|
701
|
+
a statement step, so a breakpoint set on a sub-line of a multi-line expression still
|
|
702
|
+
fires as expected.
|
|
703
|
+
|
|
670
704
|
## Tech Stack
|
|
671
705
|
|
|
672
706
|
- [textual](https://github.com/Textualize/textual) : TUI framework
|
|
@@ -99,14 +99,16 @@ tdb my_program.py
|
|
|
99
99
|
# debug with arguments
|
|
100
100
|
tdb my_program.py arg1 arg2
|
|
101
101
|
|
|
102
|
-
# add breakpoints at lines 20 and 35 of `my_program.py` and line 14
|
|
102
|
+
# add breakpoints at lines 20 and 35 of `my_program.py` and line 14
|
|
103
|
+
# of `module.py` (when -k is given, --no-stop-on-entry is set and the
|
|
104
|
+
# program runs to the first breakpoint)
|
|
103
105
|
tdb -k 20 -k 35 -k module.py:14 my_program.py arg1 arg2
|
|
104
106
|
|
|
105
107
|
# use a specific virtualenv
|
|
106
108
|
tdb --python /path/to/venv/bin/python my_program.py
|
|
107
109
|
|
|
108
110
|
# step into, or stop at tracebacks in library code
|
|
109
|
-
tdb --no-just-my-code /path/to/venv/bin/python my_program.py
|
|
111
|
+
tdb --no-just-my-code --python /path/to/venv/bin/python my_program.py
|
|
110
112
|
|
|
111
113
|
# run until first breakpoint or exit
|
|
112
114
|
tdb --no-stop-on-entry my_program.py
|
|
@@ -177,7 +179,7 @@ A cursor line (blue) tracks your position; the current execution line is highlig
|
|
|
177
179
|
| Key | Menu |
|
|
178
180
|
|-----|------|
|
|
179
181
|
| `Alt+F` | File (open a different script to debug) |
|
|
180
|
-
| `Alt+C` | Configure (Color Theme, Keybindings) |
|
|
182
|
+
| `Alt+C` | Configure (Color Theme, Keybindings, Step Mode) |
|
|
181
183
|
| `Alt+T` | Threads |
|
|
182
184
|
| `Alt+P` | Processes |
|
|
183
185
|
| `Alt+A` | Async Tasks |
|
|
@@ -212,13 +214,15 @@ those for gdb/pdb, with some aliases and extras thrown in for convenience.
|
|
|
212
214
|
|
|
213
215
|
| Key | Action |
|
|
214
216
|
|-----|--------|
|
|
215
|
-
| `n` | Step over (next
|
|
217
|
+
| `n` | Step over (next statement) |
|
|
216
218
|
| `s` | Step into function call |
|
|
217
219
|
| `o` / `f` / `r` | Step out of current function (also aliased as "finish" and "return") |
|
|
218
220
|
| `c` | Continue execution |
|
|
219
221
|
| `p` | Pause a running program |
|
|
220
222
|
| `t` | Run to cursor position |
|
|
221
223
|
| `u` / `d` | Navigate stack up (caller) / down (callee) |
|
|
224
|
+
| `j` / `k` | Move cursor down / up (with count: `5j`, `10k`) |
|
|
225
|
+
| `G` | Go to last line (with count: `42G` jumps to line 42) |
|
|
222
226
|
| `R` | Restart the debug session |
|
|
223
227
|
| `Ctrl+Q` | Quit |
|
|
224
228
|
|
|
@@ -227,6 +231,23 @@ those for gdb/pdb, with some aliases and extras thrown in for convenience.
|
|
|
227
231
|
normally and stops at the return point. A true gdb-style immediate-return (skipping
|
|
228
232
|
remaining code in the function without executing side effects) is not supported by DAP/debugpy.
|
|
229
233
|
|
|
234
|
+
**Step granularity (statement vs. line):** by default, `n` (step over) and `s` (step into)
|
|
235
|
+
treat a multi-line source statement as a single step. For example, stepping over
|
|
236
|
+
|
|
237
|
+
```python
|
|
238
|
+
results = await asyncio.gather(
|
|
239
|
+
fetch(1, 2),
|
|
240
|
+
fetch(2, 1),
|
|
241
|
+
fetch(3, 3),
|
|
242
|
+
)
|
|
243
|
+
print(results) # next stop lands here, not on each sub-line above
|
|
244
|
+
```
|
|
245
|
+
|
|
246
|
+
lands on `print(results)`, not on each interior sub-line of the `gather` call. Switch to
|
|
247
|
+
**Line** mode (Configure > Step Mode) to get debugpy's native per-line behavior, which
|
|
248
|
+
stops on each physical line — useful for inspecting how a complex expression is built up.
|
|
249
|
+
The choice is saved to `~/.config/tdb/config.json`.
|
|
250
|
+
|
|
230
251
|
### Breakpoints
|
|
231
252
|
|
|
232
253
|
Click the gutter in the Code View to toggle a breakpoint, or press `b` in Debug mode.
|
|
@@ -638,8 +659,8 @@ usage: tdb [-h] [-v/--version] [-r [HOST:]PORT] [--cwd CWD] [--no-stop-on-entry]
|
|
|
638
659
|
| Flag | Description |
|
|
639
660
|
|------|-------------|
|
|
640
661
|
| `-r HOST:PORT` | Attach to a remote debugpy server |
|
|
641
|
-
| `-k`, `--breakpoint FILE:LINE|LINE` | Set a breakpoint (may be repeated) |
|
|
642
|
-
| `--no-stop-on-entry` | Do not pause at the first line (default: stop on entry) |
|
|
662
|
+
| `-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. |
|
|
663
|
+
| `--no-stop-on-entry` | Do not pause at the first line (default: stop on entry; automatic when `-k` is given) |
|
|
643
664
|
| `--cwd DIR` | Working directory for the debuggee |
|
|
644
665
|
| `--python PATH` | Python interpreter for the debuggee |
|
|
645
666
|
| `--no-just-my-code` | Step into stdlib/site-packages code instead of skipping it
|
|
@@ -661,12 +682,25 @@ On Windows, it uses `%APPDATA%\tdb\`.
|
|
|
661
682
|
|
|
662
683
|
| File | Contents |
|
|
663
684
|
|------|----------|
|
|
664
|
-
| `config.json` | User preferences (keybinding scheme) |
|
|
685
|
+
| `config.json` | User preferences (keybinding scheme, color theme, step mode) |
|
|
665
686
|
| `breakpoints.json` | Breakpoints from previous sessions, keyed by project directory |
|
|
666
687
|
|
|
667
688
|
Breakpoints are saved on exit and restored when debugging a program in the same
|
|
668
689
|
directory. Each project's breakpoints are independent.
|
|
669
690
|
|
|
691
|
+
**Step mode** (`step_mode` in `config.json`) controls how `n` (step over) and `s` (step
|
|
692
|
+
into) handle multi-line source statements:
|
|
693
|
+
|
|
694
|
+
| Value | Behavior |
|
|
695
|
+
|-------|----------|
|
|
696
|
+
| `"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. |
|
|
697
|
+
| `"line"` | debugpy's native per-line behavior — stops on every physical line, including each interior sub-line of a multi-line expression. |
|
|
698
|
+
|
|
699
|
+
Change it from the menu (**Configure > Step Mode**); the choice is saved immediately and
|
|
700
|
+
applies to all future sessions. Breakpoint hits, exceptions, and pauses always interrupt
|
|
701
|
+
a statement step, so a breakpoint set on a sub-line of a multi-line expression still
|
|
702
|
+
fires as expected.
|
|
703
|
+
|
|
670
704
|
## Tech Stack
|
|
671
705
|
|
|
672
706
|
- [textual](https://github.com/Textualize/textual) : TUI framework
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
"""Centralized timeout constants (seconds).
|
|
2
|
+
|
|
3
|
+
Reasoning per constant lives beside its value so the "why this number?"
|
|
4
|
+
question doesn't require reading commit history or guessing. Group by
|
|
5
|
+
subsystem; alphabetize within group.
|
|
6
|
+
|
|
7
|
+
Bare integers/floats for wall-clock seconds. Always pass to
|
|
8
|
+
`asyncio.wait_for(..., timeout=X)` (or equivalent). Don't multiply
|
|
9
|
+
these together to derive new timeouts — add a new named constant.
|
|
10
|
+
"""
|
|
11
|
+
|
|
12
|
+
from __future__ import annotations
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
# --- DAP protocol round-trips --------------------------------------------
|
|
16
|
+
# debugpy is normally fast (single-digit ms) but some requests block on the
|
|
17
|
+
# debuggee's main thread (e.g. evaluate during a long sync call). 30s gives
|
|
18
|
+
# headroom for those without hanging a user-typed step forever.
|
|
19
|
+
DAP_REQUEST = 30.0
|
|
20
|
+
"""Default per-request timeout for `DAPClient._send`."""
|
|
21
|
+
|
|
22
|
+
# Child-process DAPClient disconnect runs in parallel with the parent's
|
|
23
|
+
# `disconnect(terminate=True)`. debugpy cascades termination from the
|
|
24
|
+
# parent, so the per-child handshake is cleanup, not load-bearing — keep
|
|
25
|
+
# it short so multi-process quit doesn't pile up 8 × 30s waits.
|
|
26
|
+
DAP_DISCONNECT_CHILD = 1.0
|
|
27
|
+
"""Wait for one child DAP session to acknowledge disconnect."""
|
|
28
|
+
|
|
29
|
+
# Parent disconnect is also bounded. The parent's `disconnect` is what
|
|
30
|
+
# actually kills the debuggee in non-remote-attach mode, so we wait a
|
|
31
|
+
# bit longer than children — but still capped to keep quit snappy.
|
|
32
|
+
DAP_DISCONNECT_PARENT = 2.0
|
|
33
|
+
"""Wait for the parent DAP session to acknowledge disconnect."""
|
|
34
|
+
|
|
35
|
+
# Time to wait for debugpy to emit `initialized` after launch/attach.
|
|
36
|
+
# Cold debugpy start (no compiled cache, large dependency graph) can
|
|
37
|
+
# take ~1-3s on modest machines; 10s is comfortable padding.
|
|
38
|
+
DAP_INITIALIZED = 10.0
|
|
39
|
+
"""Wait for `initialized` event after launch / attach."""
|
|
40
|
+
|
|
41
|
+
# Time to wait for a `stopped` event after launch with `stop_on_entry=True`.
|
|
42
|
+
# Same shape as DAP_INITIALIZED — we just need debugpy to reach line 1.
|
|
43
|
+
DAP_STOP_ON_ENTRY = 10.0
|
|
44
|
+
"""Wait for the first `stopped` event when stop_on_entry is set."""
|
|
45
|
+
|
|
46
|
+
# Child-process attach handshake: after a `debugpyAttach` reverse event,
|
|
47
|
+
# the child opens its DAP socket and we connect + initialize. 30s allows
|
|
48
|
+
# for slow forkserver starts on Linux (Python 3.14 default).
|
|
49
|
+
DAP_CHILD_ATTACH = 30.0
|
|
50
|
+
"""End-to-end timeout for connecting + initializing a child DAP session."""
|
|
51
|
+
|
|
52
|
+
|
|
53
|
+
# --- RPC handler waits ---------------------------------------------------
|
|
54
|
+
# Step / continue can run a long tail in multi-process programs: after
|
|
55
|
+
# releasing all breakpoint hits, the remainder of the script may run for
|
|
56
|
+
# many seconds before `terminated` arrives. 30s wasn't enough; 10 min is
|
|
57
|
+
# arbitrary-but-comfortable for typical interactive sessions.
|
|
58
|
+
RPC_STEP_WAIT = 600.0
|
|
59
|
+
"""How long the RPC `_step_action` blocks awaiting the next stop."""
|