textual-debugger 0.2.2__tar.gz → 0.2.4__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.2.2 → textual_debugger-0.2.4}/PKG-INFO +199 -35
- {textual_debugger-0.2.2/src/tdb → textual_debugger-0.2.4}/README.md +193 -31
- {textual_debugger-0.2.2 → textual_debugger-0.2.4}/pyproject.toml +6 -4
- {textual_debugger-0.2.2 → textual_debugger-0.2.4/src/tdb}/README.md +193 -31
- {textual_debugger-0.2.2 → textual_debugger-0.2.4}/src/tdb/__init__.py +1 -1
- textual_debugger-0.2.4/src/tdb/adapters/bash/__main__.py +23 -0
- textual_debugger-0.2.4/src/tdb/adapters/bash/declares.py +92 -0
- textual_debugger-0.2.4/src/tdb/adapters/bash/server.py +360 -0
- textual_debugger-0.2.4/src/tdb/adapters/bash/session.py +489 -0
- textual_debugger-0.2.4/src/tdb/adapters/bash/tdb_harness.sh +230 -0
- textual_debugger-0.2.4/src/tdb/adapters/perl/Devel/TdbCompile.pm +68 -0
- {textual_debugger-0.2.2 → textual_debugger-0.2.4}/src/tdb/adapters/perl/helpers.pl +42 -1
- {textual_debugger-0.2.2 → textual_debugger-0.2.4}/src/tdb/adapters/perl/server.py +373 -17
- {textual_debugger-0.2.2 → textual_debugger-0.2.4}/src/tdb/adapters/perl/session.py +74 -4
- textual_debugger-0.2.4/src/tdb/adapters/tcsh/__init__.py +7 -0
- textual_debugger-0.2.4/src/tdb/adapters/tcsh/__main__.py +3 -0
- textual_debugger-0.2.4/src/tdb/adapters/tcsh/breakpoints.py +44 -0
- textual_debugger-0.2.4/src/tdb/adapters/tcsh/cli.py +163 -0
- textual_debugger-0.2.4/src/tdb/adapters/tcsh/guardian.py +718 -0
- textual_debugger-0.2.4/src/tdb/adapters/tcsh/inspect.py +187 -0
- textual_debugger-0.2.4/src/tdb/adapters/tcsh/instrumenter.py +354 -0
- textual_debugger-0.2.4/src/tdb/adapters/tcsh/models.py +61 -0
- textual_debugger-0.2.4/src/tdb/adapters/tcsh/protocol.py +68 -0
- textual_debugger-0.2.4/src/tdb/adapters/tcsh/runtime.py +304 -0
- textual_debugger-0.2.4/src/tdb/adapters/tcsh/scanner.py +225 -0
- textual_debugger-0.2.4/src/tdb/adapters/tcsh/server.py +553 -0
- textual_debugger-0.2.4/src/tdb/adapters/tcsh/session.py +1221 -0
- textual_debugger-0.2.4/src/tdb/adapters/tcsh/transport.py +914 -0
- {textual_debugger-0.2.2 → textual_debugger-0.2.4}/src/tdb/app.py +5 -19
- {textual_debugger-0.2.2 → textual_debugger-0.2.4}/src/tdb/app_handlers/dap_events.py +61 -64
- {textual_debugger-0.2.2 → textual_debugger-0.2.4}/src/tdb/app_handlers/ui_panels.py +2 -0
- {textual_debugger-0.2.2 → textual_debugger-0.2.4}/src/tdb/dap/types.py +19 -0
- {textual_debugger-0.2.2 → textual_debugger-0.2.4}/src/tdb/languages/base.py +46 -0
- textual_debugger-0.2.4/src/tdb/languages/bash.py +83 -0
- textual_debugger-0.2.4/src/tdb/languages/errors.py +235 -0
- {textual_debugger-0.2.2 → textual_debugger-0.2.4}/src/tdb/languages/perl.py +4 -1
- {textual_debugger-0.2.2 → textual_debugger-0.2.4}/src/tdb/languages/python.py +2 -1
- {textual_debugger-0.2.2 → textual_debugger-0.2.4}/src/tdb/languages/registry.py +18 -0
- textual_debugger-0.2.4/src/tdb/languages/tcsh.py +101 -0
- {textual_debugger-0.2.2 → textual_debugger-0.2.4}/src/tdb/server/event_handler.py +0 -3
- {textual_debugger-0.2.2 → textual_debugger-0.2.4}/src/tdb/session/controller.py +56 -8
- {textual_debugger-0.2.2 → textual_debugger-0.2.4}/src/tdb/session/state.py +7 -0
- {textual_debugger-0.2.2 → textual_debugger-0.2.4}/src/tdb/session/textual_handler.py +0 -1
- textual_debugger-0.2.4/src/tdb/widgets/__init__.py +0 -0
- {textual_debugger-0.2.2 → textual_debugger-0.2.4}/src/tdb/widgets/async_tasks_modal.py +1 -1
- {textual_debugger-0.2.2 → textual_debugger-0.2.4}/src/tdb/widgets/code_view.py +0 -1
- {textual_debugger-0.2.2 → textual_debugger-0.2.4}/src/tdb/widgets/evaluate_console.py +2 -3
- {textual_debugger-0.2.2 → textual_debugger-0.2.4}/src/tdb/widgets/modals.py +11 -1
- {textual_debugger-0.2.2 → textual_debugger-0.2.4}/src/textual_debugger.egg-info/PKG-INFO +199 -35
- {textual_debugger-0.2.2 → textual_debugger-0.2.4}/src/textual_debugger.egg-info/SOURCES.txt +24 -0
- {textual_debugger-0.2.2 → textual_debugger-0.2.4}/LICENSE +0 -0
- {textual_debugger-0.2.2 → textual_debugger-0.2.4}/setup.cfg +0 -0
- {textual_debugger-0.2.2 → textual_debugger-0.2.4}/src/tdb/__main__.py +0 -0
- {textual_debugger-0.2.2 → textual_debugger-0.2.4}/src/tdb/_timeouts.py +0 -0
- {textual_debugger-0.2.2 → textual_debugger-0.2.4}/src/tdb/adapters/__init__.py +0 -0
- {textual_debugger-0.2.2/src/tdb/adapters/perl → textual_debugger-0.2.4/src/tdb/adapters/bash}/__init__.py +0 -0
- {textual_debugger-0.2.2 → textual_debugger-0.2.4}/src/tdb/adapters/perl/Devel/TdbRemote.pm +0 -0
- {textual_debugger-0.2.2/src/tdb/dap → textual_debugger-0.2.4/src/tdb/adapters/perl}/__init__.py +0 -0
- {textual_debugger-0.2.2 → textual_debugger-0.2.4}/src/tdb/adapters/perl/__main__.py +0 -0
- {textual_debugger-0.2.2 → textual_debugger-0.2.4}/src/tdb/adapters/perl/protocol.py +0 -0
- {textual_debugger-0.2.2 → textual_debugger-0.2.4}/src/tdb/adapters/perl/refs.py +0 -0
- {textual_debugger-0.2.2 → textual_debugger-0.2.4}/src/tdb/app_handlers/__init__.py +0 -0
- {textual_debugger-0.2.2 → textual_debugger-0.2.4}/src/tdb/app_handlers/inspection.py +0 -0
- {textual_debugger-0.2.2 → textual_debugger-0.2.4}/src/tdb/app_handlers/routing.py +0 -0
- {textual_debugger-0.2.2 → textual_debugger-0.2.4}/src/tdb/app_helpers.py +0 -0
- {textual_debugger-0.2.2 → textual_debugger-0.2.4}/src/tdb/breakpoint_hook.py +0 -0
- {textual_debugger-0.2.2 → textual_debugger-0.2.4}/src/tdb/cli.py +0 -0
- {textual_debugger-0.2.2/src/tdb/server → textual_debugger-0.2.4/src/tdb/dap}/__init__.py +0 -0
- {textual_debugger-0.2.2 → textual_debugger-0.2.4}/src/tdb/dap/client.py +0 -0
- {textual_debugger-0.2.2 → textual_debugger-0.2.4}/src/tdb/dap/messages.py +0 -0
- {textual_debugger-0.2.2 → textual_debugger-0.2.4}/src/tdb/dap/protocol.py +0 -0
- {textual_debugger-0.2.2 → textual_debugger-0.2.4}/src/tdb/inspection.py +0 -0
- {textual_debugger-0.2.2 → textual_debugger-0.2.4}/src/tdb/inspection_full.py +0 -0
- {textual_debugger-0.2.2 → textual_debugger-0.2.4}/src/tdb/keybindings/__init__.py +0 -0
- {textual_debugger-0.2.2 → textual_debugger-0.2.4}/src/tdb/languages/__init__.py +0 -0
- {textual_debugger-0.2.2 → textual_debugger-0.2.4}/src/tdb/languages/cpp.py +0 -0
- {textual_debugger-0.2.2 → textual_debugger-0.2.4}/src/tdb/mcp/__init__.py +0 -0
- {textual_debugger-0.2.2 → textual_debugger-0.2.4}/src/tdb/mcp/__main__.py +0 -0
- {textual_debugger-0.2.2 → textual_debugger-0.2.4}/src/tdb/mcp/server.py +0 -0
- {textual_debugger-0.2.2 → textual_debugger-0.2.4}/src/tdb/mcp/session.py +0 -0
- {textual_debugger-0.2.2 → textual_debugger-0.2.4}/src/tdb/persist.py +0 -0
- {textual_debugger-0.2.2 → textual_debugger-0.2.4}/src/tdb/post_mortem.py +0 -0
- {textual_debugger-0.2.2 → textual_debugger-0.2.4}/src/tdb/processes_cache.py +0 -0
- {textual_debugger-0.2.2 → textual_debugger-0.2.4}/src/tdb/replay.py +0 -0
- {textual_debugger-0.2.2/src/tdb/session → textual_debugger-0.2.4/src/tdb/server}/__init__.py +0 -0
- {textual_debugger-0.2.2 → textual_debugger-0.2.4}/src/tdb/server/app.py +0 -0
- {textual_debugger-0.2.2 → textual_debugger-0.2.4}/src/tdb/server/handlers.py +0 -0
- {textual_debugger-0.2.2 → textual_debugger-0.2.4}/src/tdb/server/rpc_types.py +0 -0
- {textual_debugger-0.2.2 → textual_debugger-0.2.4}/src/tdb/server/runner.py +0 -0
- {textual_debugger-0.2.2/src/tdb/widgets → textual_debugger-0.2.4/src/tdb/session}/__init__.py +0 -0
- {textual_debugger-0.2.2 → textual_debugger-0.2.4}/src/tdb/session/child_processes.py +0 -0
- {textual_debugger-0.2.2 → textual_debugger-0.2.4}/src/tdb/session/event_bus.py +0 -0
- {textual_debugger-0.2.2 → textual_debugger-0.2.4}/src/tdb/session/inspect_service.py +0 -0
- {textual_debugger-0.2.2 → textual_debugger-0.2.4}/src/tdb/session/messages.py +0 -0
- {textual_debugger-0.2.2 → textual_debugger-0.2.4}/src/tdb/session/post_mortem_loader.py +0 -0
- {textual_debugger-0.2.2 → textual_debugger-0.2.4}/src/tdb/session/recorder.py +0 -0
- {textual_debugger-0.2.2 → textual_debugger-0.2.4}/src/tdb/session/statement_stepper.py +0 -0
- {textual_debugger-0.2.2 → textual_debugger-0.2.4}/src/tdb/session/terminal.py +0 -0
- {textual_debugger-0.2.2 → textual_debugger-0.2.4}/src/tdb/source_analysis.py +0 -0
- {textual_debugger-0.2.2 → textual_debugger-0.2.4}/src/tdb/widgets/_inspection_modal.py +0 -0
- {textual_debugger-0.2.2 → textual_debugger-0.2.4}/src/tdb/widgets/breakpoint_view.py +0 -0
- {textual_debugger-0.2.2 → textual_debugger-0.2.4}/src/tdb/widgets/console_view.py +0 -0
- {textual_debugger-0.2.2 → textual_debugger-0.2.4}/src/tdb/widgets/full_contents_modal.py +0 -0
- {textual_debugger-0.2.2 → textual_debugger-0.2.4}/src/tdb/widgets/menu_bar.py +0 -0
- {textual_debugger-0.2.2 → textual_debugger-0.2.4}/src/tdb/widgets/processes_modal.py +0 -0
- {textual_debugger-0.2.2 → textual_debugger-0.2.4}/src/tdb/widgets/stack_view.py +0 -0
- {textual_debugger-0.2.2 → textual_debugger-0.2.4}/src/tdb/widgets/status_bar.py +0 -0
- {textual_debugger-0.2.2 → textual_debugger-0.2.4}/src/tdb/widgets/threads_modal.py +0 -0
- {textual_debugger-0.2.2 → textual_debugger-0.2.4}/src/tdb/widgets/variable_view.py +0 -0
- {textual_debugger-0.2.2 → textual_debugger-0.2.4}/src/textual_debugger.egg-info/dependency_links.txt +0 -0
- {textual_debugger-0.2.2 → textual_debugger-0.2.4}/src/textual_debugger.egg-info/entry_points.txt +0 -0
- {textual_debugger-0.2.2 → textual_debugger-0.2.4}/src/textual_debugger.egg-info/requires.txt +0 -0
- {textual_debugger-0.2.2 → textual_debugger-0.2.4}/src/textual_debugger.egg-info/top_level.txt +0 -0
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: textual-debugger
|
|
3
|
-
Version: 0.2.
|
|
4
|
-
Summary: A TUI Python
|
|
3
|
+
Version: 0.2.4
|
|
4
|
+
Summary: A TUI debugger for Python, Perl, and other languages. Based on textual.
|
|
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:
|
|
7
7
|
|
|
@@ -39,11 +39,13 @@ Classifier: Intended Audience :: Developers
|
|
|
39
39
|
Classifier: License :: OSI Approved :: MIT License
|
|
40
40
|
Classifier: Operating System :: POSIX :: Linux
|
|
41
41
|
Classifier: Programming Language :: Python :: 3
|
|
42
|
-
Classifier: Programming Language :: Python :: 3.10
|
|
43
42
|
Classifier: Programming Language :: Python :: 3.11
|
|
44
43
|
Classifier: Programming Language :: Python :: 3.12
|
|
44
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
45
|
+
Classifier: Programming Language :: Python :: 3.14
|
|
46
|
+
Classifier: Programming Language :: Python :: 3.15
|
|
45
47
|
Classifier: Topic :: Software Development :: Debuggers
|
|
46
|
-
Requires-Python: >=3.
|
|
48
|
+
Requires-Python: >=3.11
|
|
47
49
|
Description-Content-Type: text/markdown
|
|
48
50
|
License-File: LICENSE
|
|
49
51
|
Requires-Dist: textual>=8.0.0
|
|
@@ -68,8 +70,12 @@ Dynamic: license-file
|
|
|
68
70
|
|
|
69
71
|
`textual-debugger` (the package) provides `tdb` (the command-line tool and module),
|
|
70
72
|
a full-featured terminal-based debugger for Python and other languages
|
|
71
|
-
with a Debug Adapter Protocol (DAP) implementation.
|
|
72
|
-
`
|
|
73
|
+
with a Debug Adapter Protocol (DAP) implementation. In addition to Python,
|
|
74
|
+
`tdb` comes with built-in support for
|
|
75
|
+
- C and C++ (via `gdb` or `lldb-dap`)
|
|
76
|
+
- Perl (via `perl -d`)
|
|
77
|
+
- Bash (via bash's own `DEBUG` trap; bash ≥ 4.4)
|
|
78
|
+
- Tcsh (via source instrumentation of a stock `tcsh`)
|
|
73
79
|
|
|
74
80
|
`tdb` is built with [textual](https://github.com/Textualize/textual) and speaks
|
|
75
81
|
DAP to a pluggable debug adapter: [debugpy](https://github.com/microsoft/debugpy)
|
|
@@ -90,7 +96,9 @@ MIT License. Copyright 2026 by Al Danial.
|
|
|
90
96
|
`tdb`:
|
|
91
97
|
|
|
92
98
|
- debugs multiple languages through the Debug Adapter Protocol: Python (via `debugpy`,
|
|
93
|
-
the richest feature set)
|
|
99
|
+
the richest feature set), C/C++ (via `gdb -i dap` or `lldb-dap`), Perl (via `perl -d`),
|
|
100
|
+
Bash (via bash's own `DEBUG` trap), and Tcsh (via source instrumentation of a
|
|
101
|
+
stock `tcsh`), with the language
|
|
94
102
|
auto-detected from the target (ref. [Multi-Language Debugging](#multi-language-debugging)).
|
|
95
103
|
|
|
96
104
|
- supports debugging of synchronous, asynchronous, multi-threaded, and multi-process Python code.
|
|
@@ -236,22 +244,26 @@ python -m tdb my_program.py
|
|
|
236
244
|
|
|
237
245
|
## Multi-Language Debugging
|
|
238
246
|
|
|
239
|
-
`tdb` debugs any language that has a Debug Adapter Protocol backend.
|
|
247
|
+
`tdb` debugs any language that has a Debug Adapter Protocol backend. Five
|
|
240
248
|
languages are supported out of the box:
|
|
241
249
|
|
|
242
|
-
| Language | Adapter(s) |
|
|
250
|
+
| Language | Adapter(s) | Dependencies | Feature level |
|
|
243
251
|
|----------|------------|------------------------|---------------|
|
|
244
|
-
| Python | `debugpy` (default) |
|
|
252
|
+
| Python | `debugpy` (default) | Python ≥ 3.11 | everything in this README |
|
|
245
253
|
| C / C++ (any native binary) | `gdb` (default), `lldb-dap` (alternate) | `gdb -i dap` requires GDB ≥ 14; `lldb-dap` ships with LLVM ≥ 17 (e.g. `apt install lldb`) | core debugging: breakpoints, stepping, stack, variables, evaluate console |
|
|
246
|
-
| Perl | perl-tdb (bundled) |
|
|
254
|
+
| Perl | perl-tdb (bundled) | perl ≥ 5.18 on PATH | core debugging + remote attach |
|
|
255
|
+
| Bash | bash-tdb (bundled) | bash ≥ 4.4 on PATH | core debugging (no remote attach) |
|
|
256
|
+
| Tcsh | tcsh-tdb (bundled) | tcsh on PATH | core debugging (no remote attach, no conditional breakpoints, no pause) |
|
|
247
257
|
|
|
248
258
|
### Language detection and selection
|
|
249
259
|
|
|
250
260
|
The language is auto-detected from the debug target:
|
|
251
261
|
|
|
252
|
-
1. File extension: `.py` → Python; `.pl` / `.pm` / `.t` → Perl
|
|
262
|
+
1. File extension: `.py` → Python; `.pl` / `.pm` / `.t` → Perl; `.sh` / `.bash`
|
|
263
|
+
→ Bash; `.csh` / `.tcsh` → Tcsh.
|
|
253
264
|
2. Native executables (ELF, Mach-O, PE magic bytes) → C/C++.
|
|
254
|
-
3. A `#!...python
|
|
265
|
+
3. A `#!...python`, `#!...perl`, `#!...bash`, or `#!...csh`/`#!...tcsh`
|
|
266
|
+
shebang → Python / Perl / Bash / Tcsh respectively.
|
|
255
267
|
4. C/C++/Rust *source* files (`.c`, `.cpp`, `.rs`, …) produce an error with a
|
|
256
268
|
hint: compile with debug info (`g++ -g -O0`) and debug the binary.
|
|
257
269
|
5. Anything else produces an error naming the `--lang` override.
|
|
@@ -283,17 +295,62 @@ conditions and persistence), stepping, continue/pause, run-to-cursor, stack
|
|
|
283
295
|
navigation, variable inspection, the evaluate console, syntax highlighting,
|
|
284
296
|
and the JSON-RPC / MCP programmatic modes.
|
|
285
297
|
|
|
286
|
-
Python-specific features are hidden or return
|
|
298
|
+
Python-specific features are hidden or return "not supported for this
|
|
287
299
|
language" message when debugging other languages: statement-granularity
|
|
288
300
|
stepping (non-Python languages always step per line), the async task /
|
|
289
301
|
process inspectors and wait graph, the evaluate console's trailing-`?` help,
|
|
290
302
|
`--python`/`--pv`, `--no-subprocess`, automatic child-process attachment, and
|
|
291
303
|
the post-mortem / `tdb.breakpoint()` hooks (those hooks live inside Python
|
|
292
304
|
programs by nature). Remote attach (`-r`) also works for Perl (see
|
|
293
|
-
[Perl](#perl)
|
|
294
|
-
for C/C
|
|
305
|
+
[Perl](#perl), `Devel::TdbRemote` in place of `debugpy.listen()`), but not
|
|
306
|
+
for C/C++, Bash, or Tcsh. `--terminal` is
|
|
295
307
|
currently ignored for non-Python targets.
|
|
296
308
|
|
|
309
|
+
**Bash limitations (v1):** the bash adapter uses bash's own `DEBUG` trap and
|
|
310
|
+
has a smaller feature envelope than Python/Perl:
|
|
311
|
+
|
|
312
|
+
- Debuggee code that installs its own `DEBUG` trap clobbers the harness;
|
|
313
|
+
debugging silently degrades to free-running.
|
|
314
|
+
- No stopping inside subshells `(...)`, `$(...)`, or pipeline segments; they
|
|
315
|
+
execute normally.
|
|
316
|
+
- Child bash processes run uninstrumented.
|
|
317
|
+
- Outer-frame locals not inspectable (innermost frame only).
|
|
318
|
+
- Pause is deferred while blocked in an external command.
|
|
319
|
+
- `.sh` files that aren't bash are only diagnosed at launch, by bash itself
|
|
320
|
+
or the harness version check.
|
|
321
|
+
- The `DEBUG` trap never fires on a function-definition line, so a
|
|
322
|
+
breakpoint on a `func() {` line never hits; entry and step-in stops land
|
|
323
|
+
on the first executable line of the function body instead.
|
|
324
|
+
- The debug control channel occupies two inherited file descriptors
|
|
325
|
+
(typically high-numbered). A script that execs redirections onto those
|
|
326
|
+
exact fds (e.g. `exec 63>&-` or reusing them for its own I/O) will
|
|
327
|
+
silently break debugging.
|
|
328
|
+
|
|
329
|
+
See [Bash](#bash) below for launch details.
|
|
330
|
+
|
|
331
|
+
**Tcsh limitations (v1):** tcsh has no debug hooks at all, so the tcsh
|
|
332
|
+
adapter debugs an instrumented temporary *copy* of the script (original
|
|
333
|
+
paths and line numbers are preserved in everything tdb displays):
|
|
334
|
+
|
|
335
|
+
- Conditional breakpoints are not supported; a condition set in the
|
|
336
|
+
Breakpoint View is ignored for tcsh (the breakpoint always stops).
|
|
337
|
+
- No asynchronous pause: a free-running script stops only at the next
|
|
338
|
+
breakpoint (or when it exits).
|
|
339
|
+
- A breakpoint binds to the nearest safe statement at or after the
|
|
340
|
+
requested line; unplaceable breakpoints are reported unverified.
|
|
341
|
+
- Stack frames represent `source`d files, not native call frames, and only
|
|
342
|
+
literal `source` targets resolvable at launch are instrumented (computed
|
|
343
|
+
or `cd`-dependent sources run normally but are atomic to the debugger).
|
|
344
|
+
- All frames show the same live shell state (Shell Variables, Environment,
|
|
345
|
+
Aliases, Arguments). Stock tcsh keeps no per-frame history.
|
|
346
|
+
- Multiple commands on one physical line (`a ; b`), command substitutions,
|
|
347
|
+
and external commands are atomic stepping units.
|
|
348
|
+
- `$0` inside dynamically generated or evaluated text can expose the
|
|
349
|
+
generated copy's path (ordinary lexical `$0` is rewritten correctly).
|
|
350
|
+
- Requires Python ≥ 3.11.
|
|
351
|
+
|
|
352
|
+
See [Tcsh](#tcsh) below for launch details.
|
|
353
|
+
|
|
297
354
|
### C/C++ tips
|
|
298
355
|
|
|
299
356
|
- Compile with `-g` (ideally `-g -O0`). If no breakpoint in a file can be
|
|
@@ -304,7 +361,7 @@ currently ignored for non-Python targets.
|
|
|
304
361
|
variables, and evaluate console remain fully usable.
|
|
305
362
|
- GDB (the default adapter) has the most complete libstdc++
|
|
306
363
|
pretty-printing. `lldb-dap` (via `--adapter lldb-dap`) also debugs
|
|
307
|
-
GCC-built binaries fine
|
|
364
|
+
GCC-built binaries fine. DWARF is compiler-neutral.
|
|
308
365
|
- **GDB evaluate-console quirk:** GDB's DAP treats REPL input as CLI
|
|
309
366
|
commands, so evaluate expressions with an explicit `print`, e.g.
|
|
310
367
|
`print x` rather than bare `x` (bare `x` collides with GDB's
|
|
@@ -312,8 +369,8 @@ currently ignored for non-Python targets.
|
|
|
312
369
|
|
|
313
370
|
### Perl
|
|
314
371
|
|
|
315
|
-
`tdb` bundles its own Perl adapter (`perl-tdb`)
|
|
316
|
-
|
|
372
|
+
`tdb` bundles its own Perl adapter (`perl-tdb`) so only need
|
|
373
|
+
`perl` ≥ 5.18 on `PATH`. It drives stock `perl5db` under the
|
|
317
374
|
hood, so it works with any Perl already on the system.
|
|
318
375
|
|
|
319
376
|
**Launching a script:**
|
|
@@ -322,15 +379,61 @@ hood, so it works with any Perl already on the system.
|
|
|
322
379
|
tdb script.pl
|
|
323
380
|
```
|
|
324
381
|
|
|
382
|
+
**Compile-time code (`BEGIN` blocks):** Perl runs `BEGIN` blocks and the
|
|
383
|
+
`use` statements that are themselves `BEGIN` blocks while it is still
|
|
384
|
+
*compiling* your program, before stock `perl5db` ever stops. `tdb` arms the
|
|
385
|
+
debugger ahead of compilation so that code is debuggable too, which means the
|
|
386
|
+
first stop is the first **compile-time** statement of your file (typically
|
|
387
|
+
`use strict;` near the top) rather than the first runtime statement. Step from
|
|
388
|
+
there and you land inside your `BEGIN` blocks, with the stack and evaluate
|
|
389
|
+
views working normally (local variable listing is limited at a compile-time
|
|
390
|
+
stop); the `Stack` view shows the frame as `main::BEGIN`. Stepping through a
|
|
391
|
+
`use` line takes a few steps (the pragma's
|
|
392
|
+
own compile-time work happens in between) but you are never dragged into
|
|
393
|
+
another module's internals.
|
|
394
|
+
|
|
395
|
+
Two consequences worth knowing:
|
|
396
|
+
|
|
397
|
+
- **Breakpoints are deferred while your program compiles.** During the compile
|
|
398
|
+
phase Perl has only parsed part of your file, so its line table is
|
|
399
|
+
incomplete and a breakpoint can't be verified yet. `tdb` holds such requests
|
|
400
|
+
and, while it single-steps through the rest of compilation, checks each
|
|
401
|
+
compile-time statement it lands on against them. A breakpoint placed
|
|
402
|
+
*inside* a `BEGIN` block fires there directly, on the first run, without
|
|
403
|
+
needing to be stepped into by hand. Conditional breakpoints work the same
|
|
404
|
+
way at compile time; a condition that itself errors behaves exactly like a
|
|
405
|
+
bad condition at runtime in that it does not fire. Two residual caveats: a
|
|
406
|
+
breakpoint on a non-statement line (the `BEGIN {` line itself, or a blank
|
|
407
|
+
line) never fires during the compile phase, since it's never actually
|
|
408
|
+
trapped as a statement; and `hitCondition` (break on the Nth hit) isn't
|
|
409
|
+
honored for a compile-time stop, only a plain `condition`.
|
|
410
|
+
- **Startup is slower for large dependency graphs**, because the debugger is
|
|
411
|
+
active throughout compilation. A script with a big `use` tree takes
|
|
412
|
+
noticeably longer to reach its first stop under `tdb`.
|
|
413
|
+
|
|
414
|
+
**`END` blocks** are entered with **step-in** (`s`). `next` and `continue` run
|
|
415
|
+
straight past them to program termination, which is standard `perl5db`
|
|
416
|
+
behavior, not a `tdb` limitation.
|
|
417
|
+
|
|
418
|
+
**When your program dies:** an uncaught Perl error (`die`, or a fatal runtime
|
|
419
|
+
error such as division by zero) opens the same error modal Python tracebacks
|
|
420
|
+
get: the message, the call stack parsed from Perl's `at FILE line N.` /
|
|
421
|
+
`... called at FILE line N` output, and Code View navigated to the failing
|
|
422
|
+
line. This works for compile-time failures too, including a `die` inside a
|
|
423
|
+
`BEGIN` block that aborts compilation. Press `e` in Code View to re-summon the
|
|
424
|
+
last error. `tdb` also reports the debuggee's real exit status rather than
|
|
425
|
+
assuming success.
|
|
426
|
+
|
|
325
427
|
**Remote attach:** useful when the Perl process is already running (a long-
|
|
326
428
|
lived service, a process started by something other than `tdb`) or lives on
|
|
327
429
|
another host/container. Add three lines to the target program, with the
|
|
328
430
|
`use` line first so the debugger is armed before any of your code compiles:
|
|
329
431
|
|
|
330
432
|
```perl
|
|
331
|
-
use Devel::TdbRemote; #
|
|
433
|
+
use Devel::TdbRemote; # first line of your program
|
|
332
434
|
...
|
|
333
435
|
Devel::TdbRemote::listen(5678); # non-blocking
|
|
436
|
+
print "Waiting for tdb to attach on port 5678\n";
|
|
334
437
|
Devel::TdbRemote::wait_for_client(); # blocks until tdb connects
|
|
335
438
|
```
|
|
336
439
|
|
|
@@ -349,8 +452,8 @@ script controls startup), arm it before Perl even parses your file instead:
|
|
|
349
452
|
environment that launches the debuggee.
|
|
350
453
|
|
|
351
454
|
**Copying the adapter to a remote host:** `Devel::TdbRemote` and its helper
|
|
352
|
-
script are plain files, not a CPAN install
|
|
353
|
-
machine and point `PERL5LIB` at the directory that contains them:
|
|
455
|
+
script are plain files, not a CPAN install. Copy both onto the remote
|
|
456
|
+
machine and point `PERL5LIB` at the directory that contains them, for example:
|
|
354
457
|
|
|
355
458
|
```bash
|
|
356
459
|
# From a checkout or an installed wheel's site-packages/tdb/adapters/perl:
|
|
@@ -360,7 +463,7 @@ export PERL5LIB=/opt/tdb-perl:$PERL5LIB
|
|
|
360
463
|
```
|
|
361
464
|
|
|
362
465
|
(`Devel/TdbRemote.pm` locates `helpers.pl` next to itself at runtime, so keep
|
|
363
|
-
the two files in the same relative layout shown above
|
|
466
|
+
the two files in the same relative layout shown above; `helpers.pl` is a
|
|
364
467
|
sibling of the `Devel/` directory, not inside it.)
|
|
365
468
|
|
|
366
469
|
**PadWalker (optional but recommended):** inspecting lexical (`my`)
|
|
@@ -372,9 +475,68 @@ Install with `cpanm PadWalker` (or your distro's package) for full fidelity.
|
|
|
372
475
|
|
|
373
476
|
**Pause is unavailable in attach mode.** Launch-mode sessions (`tdb
|
|
374
477
|
script.pl`) support pausing a running program at any time. Remote-attach
|
|
375
|
-
sessions don't
|
|
478
|
+
sessions don't. Asynchronous pause (as Python gets via `debugpy`) needs a control channel
|
|
376
479
|
`Devel::TdbRemote` doesn't implement yet; `pause` in attach mode returns a
|
|
377
|
-
|
|
480
|
+
"not available" error instead of hanging.
|
|
481
|
+
|
|
482
|
+
### Bash
|
|
483
|
+
|
|
484
|
+
`tdb` bundles its own bash adapter (`bash-tdb`) so no separate adapter install
|
|
485
|
+
needed, just a `bash` ≥ 4.4 on `PATH`. It drives stock bash's own `DEBUG`
|
|
486
|
+
trap (with `extdebug` for return-value control) under the hood via a small
|
|
487
|
+
harness script sourced through `BASH_ENV`, so it works with any bash already
|
|
488
|
+
on the system.
|
|
489
|
+
|
|
490
|
+
**Launching a script:**
|
|
491
|
+
|
|
492
|
+
```bash
|
|
493
|
+
tdb script.sh
|
|
494
|
+
```
|
|
495
|
+
|
|
496
|
+
Core debugging works as described above (breakpoints, stepping,
|
|
497
|
+
continue/pause, stack, variables, evaluate console), with the v1 caveats
|
|
498
|
+
listed in [What works for non-Python languages](#what-works-for-non-python-languages).
|
|
499
|
+
Most notably, a breakpoint can't be set on a `func() {` line itself (the
|
|
500
|
+
`DEBUG` trap never fires there), stops never land inside subshells or
|
|
501
|
+
pipeline segments, child bash processes run uninstrumented, and only the
|
|
502
|
+
innermost frame's locals are inspectable. There is no remote-attach mode for
|
|
503
|
+
Bash.
|
|
504
|
+
|
|
505
|
+
The Variables view shows three scopes for bash: Locals (innermost frame
|
|
506
|
+
only), Globals (unexported shell variables), and Environment (exported
|
|
507
|
+
variables, both inherited and script-`export`ed).
|
|
508
|
+
|
|
509
|
+
### Tcsh
|
|
510
|
+
|
|
511
|
+
`tdb` bundles its own tcsh adapter (`tcsh-tdb`) so no separate adapter
|
|
512
|
+
is needed, just a stock `tcsh` on `PATH` (or
|
|
513
|
+
`{"adapters": {"tcsh": "/path/to/tcsh"}}` in `config.json`). Stock tcsh has
|
|
514
|
+
no debugger hooks, so the adapter instruments a temporary copy of the script
|
|
515
|
+
(and of any literal `source`d files), runs it with `tcsh -f`, and
|
|
516
|
+
coordinates stops through private FIFOs. tdb always shows the original
|
|
517
|
+
source paths and line numbers; the generated copies are private adapter
|
|
518
|
+
details and are cleaned up when the session ends.
|
|
519
|
+
|
|
520
|
+
**Launching a script:**
|
|
521
|
+
|
|
522
|
+
```bash
|
|
523
|
+
tdb script.csh
|
|
524
|
+
```
|
|
525
|
+
|
|
526
|
+
Core debugging works as described above: line breakpoints, stepping
|
|
527
|
+
(`next` steps over `source`d files, `stepIn` steps into instrumented ones),
|
|
528
|
+
stack navigation across `source` nesting, variable inspection, and the
|
|
529
|
+
evaluate console with the v1 caveats listed in
|
|
530
|
+
[What works for non-Python languages](#what-works-for-non-python-languages),
|
|
531
|
+
most notably: no conditional breakpoints, no pause of a free-running
|
|
532
|
+
script, and stepping is per logical source line.
|
|
533
|
+
|
|
534
|
+
The Variables view shows four scopes for tcsh: Shell Variables (`set`),
|
|
535
|
+
Environment (`setenv`), Aliases, and Arguments (`argv`). All of them show
|
|
536
|
+
the live state of the single tcsh process. The evaluate console executes
|
|
537
|
+
text directly in the paused shell. It can inspect *and mutate* state
|
|
538
|
+
(`set name = value` takes effect immediately), and a syntax error in
|
|
539
|
+
evaluated text can terminate the debuggee; there is no isolation.
|
|
378
540
|
|
|
379
541
|
## Layout
|
|
380
542
|
|
|
@@ -519,8 +681,10 @@ Breakpoints persist across session restarts.
|
|
|
519
681
|
|
|
520
682
|
### Variable Inspection
|
|
521
683
|
|
|
522
|
-
The Variable View shows a tree of scopes
|
|
523
|
-
|
|
684
|
+
The Variable View shows a tree of scopes with all variables in the current frame. The scopes
|
|
685
|
+
themselves are language-dependent: Locals, Globals, plus Environment for bash; Lexicals,
|
|
686
|
+
Globals, Specials for Perl (see the [Bash](#bash) and [Perl](#perl) sections above for
|
|
687
|
+
details). Expand nodes to drill into complex objects. Children are loaded lazily on demand.
|
|
524
688
|
Variable values can be changed in the Evaluate Console.
|
|
525
689
|
|
|
526
690
|
Double-click a variable, or highlight the variable with the text cursor in
|
|
@@ -969,23 +1133,23 @@ Each is JSON with `event`, `data`, and `timestamp` fields.
|
|
|
969
1133
|
## Recording and replaying sessions
|
|
970
1134
|
|
|
971
1135
|
`tdb --record session.jsonl prog.py` runs a normal TUI session and captures
|
|
972
|
-
your debugging actions
|
|
1136
|
+
your debugging actions including breakpoints (including `-k`/`-t` and persisted
|
|
973
1137
|
ones), stepping, continue/pause, Evaluate-console entries, stack-frame
|
|
974
|
-
navigation, variable expansion, restart, quit
|
|
1138
|
+
navigation, variable expansion, restart, quit. The session is
|
|
1139
|
+
written to `session.jsonl` as
|
|
975
1140
|
JSON-RPC commands. Works with launch mode (any language) and `-r`
|
|
976
1141
|
remote attach.
|
|
977
1142
|
|
|
978
1143
|
Replay it two ways:
|
|
979
1144
|
|
|
980
|
-
- `tdb --replay session.jsonl`
|
|
1145
|
+
- `tdb --replay session.jsonl` launches the recorded
|
|
981
1146
|
program headless, feeds every recorded command through the same RPC
|
|
982
1147
|
dispatch `tdb --server` uses, and prints a transcript (recorded time,
|
|
983
1148
|
command, verbatim result, interleaved program output). Exit code 0 iff
|
|
984
1149
|
every command succeeded. Add `--timing` to reproduce the original
|
|
985
1150
|
pacing, `--replay-timeout S` to bound each stop-wait (default 30 s).
|
|
986
1151
|
- Against a live server: start `tdb --server prog.py`, then feed line 2
|
|
987
|
-
onward of the file to `POST /rpc`
|
|
988
|
-
request body:
|
|
1152
|
+
onward of the file to `POST /rpc` . Each line is a valid request body:
|
|
989
1153
|
|
|
990
1154
|
tail -n +2 session.jsonl | while read line; do
|
|
991
1155
|
curl -s -X POST -H 'Content-Type: application/json' \
|
|
@@ -1039,7 +1203,7 @@ client expects to launch servers.
|
|
|
1039
1203
|
| Cluster | Tools |
|
|
1040
1204
|
|---------|-------|
|
|
1041
1205
|
| Lifecycle | `debug_launch`, `debug_attach`, `quit` |
|
|
1042
|
-
| Control | `control(action, timeout_s=30)`
|
|
1206
|
+
| Control | `control(action, timeout_s=30)` where `action ∈ {continue, next, step_in, step_out, pause, wait_for_stop}` |
|
|
1043
1207
|
| Inspection | `inspect(expressions)`, `read_source(file_path)`, `stack_trace()`, `status()`, `get_output()` |
|
|
1044
1208
|
| Breakpoints | `set_breakpoint(spec, condition?, hit_condition?)`, `remove_breakpoint(spec)`, `list_breakpoints()` |
|
|
1045
1209
|
| Differentiators | `threads(thread_id?)`, `tasks(task_name?)`, `processes(name_or_pid?)`, `wait_graph()` |
|
|
@@ -1109,7 +1273,7 @@ usage: tdb [-h] [-v] [-r [HOST:]PORT] [--cwd CWD] [--no-stop-on-entry]
|
|
|
1109
1273
|
| `--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. |
|
|
1110
1274
|
| `--remote-root PATH` | Remote directory matched to `--local-root` (same CLI position via `zip()`). |
|
|
1111
1275
|
| `-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. |
|
|
1112
|
-
| `-t`, `--to-line FILE:LINE|LINE` | Like `-k`, but the breakpoint is not saved to the breakpoints file
|
|
1276
|
+
| `-t`, `--to-line FILE:LINE|LINE` | Like `-k`, but the breakpoint is not saved to the breakpoints file, it just takes you to that spot in the code for this session (may be repeated). |
|
|
1113
1277
|
| `--no-stop-on-entry` | Do not pause at the first line (default: stop on entry; automatic when `-k` is given) |
|
|
1114
1278
|
| `--cwd DIR` | Working directory for the debuggee |
|
|
1115
1279
|
| `--python PATH` | Python interpreter for the debuggee (Python targets only) |
|
|
@@ -1144,7 +1308,7 @@ executable path (`{"adapters": {"lldb-dap": "/opt/llvm/bin/lldb-dap"}}`), and
|
|
|
1144
1308
|
(`{"default_adapters": {"cpp": "lldb-dap"}}`).
|
|
1145
1309
|
|
|
1146
1310
|
**Perl is a special case:** `perl-tdb` is tdb's own bundled adapter (always
|
|
1147
|
-
found
|
|
1311
|
+
found; it's Python code, not an external executable), so
|
|
1148
1312
|
`adapters.perl` doesn't select an adapter binary. Instead it names the
|
|
1149
1313
|
*Perl interpreter* tdb should spawn to run the debuggee:
|
|
1150
1314
|
`{"adapters": {"perl": "/path/to/perl"}}`. Use this when the `perl` on
|