debug-dojo 0.3.1__tar.gz → 0.4.0__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.
- {debug_dojo-0.3.1 → debug_dojo-0.4.0}/.gitignore +1 -0
- {debug_dojo-0.3.1 → debug_dojo-0.4.0}/HISTORY.md +13 -13
- {debug_dojo-0.3.1 → debug_dojo-0.4.0}/PKG-INFO +47 -29
- {debug_dojo-0.3.1 → debug_dojo-0.4.0}/README.md +33 -15
- {debug_dojo-0.3.1 → debug_dojo-0.4.0}/pyproject.toml +19 -12
- {debug_dojo-0.3.1 → debug_dojo-0.4.0}/src/debug_dojo/_cli.py +47 -25
- debug_dojo-0.4.0/src/debug_dojo/_config.py +136 -0
- debug_dojo-0.4.0/src/debug_dojo/_config_models.py +138 -0
- {debug_dojo-0.3.1 → debug_dojo-0.4.0}/src/debug_dojo/_installers.py +27 -12
- debug_dojo-0.3.1/.python-version +0 -1
- debug_dojo-0.3.1/dojo.toml +0 -7
- debug_dojo-0.3.1/examples/test_target.py +0 -24
- debug_dojo-0.3.1/logo/logo_black.png +0 -0
- debug_dojo-0.3.1/logo/logo_white.png +0 -0
- debug_dojo-0.3.1/ruff.toml +0 -19
- debug_dojo-0.3.1/src/debug_dojo/_config.py +0 -117
- debug_dojo-0.3.1/uv.lock +0 -2083
- /debug_dojo-0.3.1/LICENCE → /debug_dojo-0.4.0/LICENSE +0 -0
- {debug_dojo-0.3.1 → debug_dojo-0.4.0}/src/debug_dojo/__init__.py +0 -0
- {debug_dojo-0.3.1 → debug_dojo-0.4.0}/src/debug_dojo/__main__.py +0 -0
- {debug_dojo-0.3.1 → debug_dojo-0.4.0}/src/debug_dojo/_compareres.py +0 -0
- {debug_dojo-0.3.1 → debug_dojo-0.4.0}/src/debug_dojo/install.py +0 -0
- {debug_dojo-0.3.1 → debug_dojo-0.4.0}/src/debug_dojo/py.typed +0 -0
|
@@ -1,37 +1,37 @@
|
|
|
1
|
-
## v0.
|
|
1
|
+
## v0.4.0 (2025-08-10)
|
|
2
2
|
|
|
3
|
-
*release tag*: [v0.
|
|
3
|
+
*release tag*: [v0.4.0]
|
|
4
4
|
|
|
5
|
-
|
|
5
|
+
- New configuration model `DebugDojoConfig` for better structure.
|
|
6
|
+
- Added support for `debugger` configuration in `dojo.toml`.
|
|
7
|
+
- Updated `dojo` command to include debugger type in command call.
|
|
8
|
+
- Configuration versioning allows for in-flight migration of old configurations.
|
|
9
|
+
- Improved error handling in configuration loading.
|
|
10
|
+
- Improved catching errors from target execution.
|
|
11
|
+
|
|
12
|
+
## v0.3.2 (2025-07-28)
|
|
13
|
+
|
|
14
|
+
*release tag*: [v0.3.2]
|
|
6
15
|
|
|
7
16
|
- New logo for the project.
|
|
8
17
|
- Typer used for CLI implementation.
|
|
9
18
|
- Dojo is configured via `dojo.toml` or `pyproject.toml`.
|
|
10
|
-
|
|
11
|
-
#### Fixes
|
|
12
|
-
|
|
19
|
+
- Support for `debugpy` and `ipdb` for debugging.
|
|
13
20
|
- Fixed documentation and history.
|
|
14
21
|
|
|
15
22
|
## v0.2.0 (2025-07-20)
|
|
16
23
|
|
|
17
24
|
*release tag*: [v0.2.0]
|
|
18
25
|
|
|
19
|
-
### What's Changed
|
|
20
|
-
|
|
21
26
|
- Added `dojo` command for easy debugging setup.
|
|
22
27
|
- Added `p()` function for rich printing.
|
|
23
28
|
- Added history file for tracking changes.
|
|
24
29
|
- Moved to `hatch` for building and packaging.
|
|
25
|
-
|
|
26
|
-
#### Fixes
|
|
27
|
-
|
|
28
30
|
- Fixed `pyproject.toml` to point to GitHub repository as the homepage.
|
|
29
31
|
|
|
30
32
|
## v0.1.0 (2025-07-19)
|
|
31
33
|
|
|
32
34
|
*release tag*: [v0.1.0]
|
|
33
35
|
|
|
34
|
-
### What's Changed
|
|
35
|
-
|
|
36
36
|
- Initial module to install debugging tools.
|
|
37
37
|
- Debug mode utilities for PuDB, rich tracebacks, and object inspection.
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: debug-dojo
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.4.0
|
|
4
4
|
Summary: Debbugging dojo for Python developers
|
|
5
5
|
Project-URL: Homepage, https://github.com/bwrob/debug-dojo
|
|
6
6
|
Project-URL: Documentation, https://github.com/bwrob/debug-dojo/blob/main/README.md
|
|
@@ -8,6 +8,7 @@ Project-URL: Source, https://github.com/bwrob/debug-dojo/tree/main/src/debug_doj
|
|
|
8
8
|
Project-URL: Changelog, https://github.com/bwrob/debug-dojo/blob/main/HISTORY.md
|
|
9
9
|
Author-email: bwrob <bartosz.marcin.wroblewski@gmail.com>
|
|
10
10
|
License-Expression: MIT
|
|
11
|
+
License-File: LICENSE
|
|
11
12
|
Keywords: debugging,inspection,pudb,rich,tools,traceback
|
|
12
13
|
Classifier: Development Status :: 3 - Alpha
|
|
13
14
|
Classifier: Intended Audience :: Developers
|
|
@@ -30,7 +31,7 @@ Requires-Dist: typer>=0.15.0
|
|
|
30
31
|
Description-Content-Type: text/markdown
|
|
31
32
|
|
|
32
33
|
<p align="center">
|
|
33
|
-
<img src="https://github.com/bwrob/debug-dojo/blob/main/logo/
|
|
34
|
+
<img src="https://github.com/bwrob/debug-dojo/blob/main/logo/logo_python.png?raw=true" alt="debug dojo" style="width:50%; max-width:300px;"/>
|
|
34
35
|
</p>
|
|
35
36
|
|
|
36
37
|
<p align="center">
|
|
@@ -40,15 +41,17 @@ Description-Content-Type: text/markdown
|
|
|
40
41
|
[](https://pypi.org/project/debug-dojo)
|
|
41
42
|
[](https://pypi.org/pypi/debug-dojo/)
|
|
42
43
|
|
|
43
|
-
**debug-dojo** is a Python package providing utilities for enhanced debugging and inspection in the terminal.
|
|
44
|
+
**debug-dojo** is a Python package providing utilities for enhanced debugging and inspection in the terminal.
|
|
45
|
+
It leverages [`rich`](https://github.com/Textualize/rich) for beautiful output and offers helpers for side-by-side object comparison, improved tracebacks from `rich`, and easy integration with different debuggers -- `debugpy`, `pudb`, `pdb`, and `ipdb`.
|
|
44
46
|
|
|
45
47
|
## Features
|
|
46
48
|
|
|
47
49
|
- **Convenient CLI** Quickly run your code with debugging tools enabled.
|
|
48
50
|
- **Simple API:** Install all tools or only what you need.
|
|
49
|
-
- **Debugger integration:** Quickly enable Debugpy, PuDB, PDB, or IPDB as your default debugger.
|
|
51
|
+
- **Debugger integration:** Quickly enable Debugpy, PuDB, PDB, or IPDB as your default pre-configured debugger.
|
|
50
52
|
- **Rich tracebacks:** Get readable, colorized tracebacks for easier debugging.
|
|
51
53
|
- **Side-by-side object inspection:** Visually compare Python objects, their attributes, and methods in the terminal.
|
|
54
|
+
- **Configuration:** Easily configure the debugging tools using `dojo.toml` or `pyproject.toml`.
|
|
52
55
|
|
|
53
56
|
## Usage
|
|
54
57
|
|
|
@@ -60,10 +63,10 @@ Run your Python script with debugging tools enabled using the `debug-dojo` comma
|
|
|
60
63
|
dojo my_script.py
|
|
61
64
|
```
|
|
62
65
|
|
|
63
|
-
You can optionally set configuration
|
|
66
|
+
You can optionally set configuration, verbose mode, and specify the debugger type. Both script files and modules are supported:
|
|
64
67
|
|
|
65
68
|
```console
|
|
66
|
-
dojo --config dojo.toml --verbose
|
|
69
|
+
dojo --debugger ipdb --config dojo.toml --verbose --module my_module
|
|
67
70
|
```
|
|
68
71
|
|
|
69
72
|
### From the code
|
|
@@ -71,19 +74,18 @@ dojo --config dojo.toml --verbose my_script.py
|
|
|
71
74
|
In the `PuDB` style, you can install all debugging tools and enter the debugging mode with a single command:
|
|
72
75
|
|
|
73
76
|
```python
|
|
74
|
-
import debug_dojo.install; b()
|
|
75
|
-
|
|
76
77
|
object_1 = {"foo": 1, "bar": 2}
|
|
77
78
|
object_2 = [1, 2, 3]
|
|
78
79
|
|
|
80
|
+
import debug_dojo.install; b()
|
|
79
81
|
p(object_1) # Pretty print an object with Rich
|
|
80
|
-
i(object_1) # Inspect an object
|
|
81
|
-
c(object_1, object_2) # Compare two objects side-by-side
|
|
82
82
|
```
|
|
83
83
|
|
|
84
|
-
|
|
84
|
+
### Features in debugging mode
|
|
85
|
+
|
|
86
|
+
The following functions are available in the debugging mode, injected into builtins:
|
|
85
87
|
|
|
86
|
-
- `b()` is a
|
|
88
|
+
- `b()` is a hook that sets a breakpoint using the configured debugger.
|
|
87
89
|
- `p(object_1)` is pretty printing of an object using Rich.
|
|
88
90
|
- `i(object_1)` to inspect an object using Rich.
|
|
89
91
|
- `c(object_1, object_2)` to compare two objects side-by-side.
|
|
@@ -95,12 +97,23 @@ You can configure the debugging tools using a `dojo.toml` or `pyproject.toml` fi
|
|
|
95
97
|
**Example `dojo.toml`:**
|
|
96
98
|
|
|
97
99
|
```toml
|
|
98
|
-
|
|
100
|
+
[debuggers]
|
|
101
|
+
default = "ipdb"
|
|
102
|
+
|
|
103
|
+
debugpy = { port = 1992 }
|
|
104
|
+
ipdb = { context_lines = 20 }
|
|
105
|
+
|
|
106
|
+
[exceptions]
|
|
107
|
+
locals_in_traceback = false
|
|
108
|
+
post_mortem = true
|
|
109
|
+
rich_traceback = true
|
|
99
110
|
|
|
100
111
|
[features]
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
112
|
+
breakpoint = "b"
|
|
113
|
+
# Empty string means disable the feature
|
|
114
|
+
comparer = ""
|
|
115
|
+
rich_inspect = "i"
|
|
116
|
+
rich_print = "p"
|
|
104
117
|
```
|
|
105
118
|
|
|
106
119
|
## Installation
|
|
@@ -130,45 +143,50 @@ Note that dojo most likely will not work when installed via `pipx` or `uvx`, as
|
|
|
130
143
|
```console
|
|
131
144
|
ruff check src/debug_dojo --fix
|
|
132
145
|
basedpyright src/debug_dojo
|
|
146
|
+
|
|
147
|
+
poe code-quality
|
|
133
148
|
```
|
|
134
149
|
|
|
150
|
+
### Tests
|
|
151
|
+
|
|
152
|
+
TBA
|
|
135
153
|
|
|
136
154
|
## Changelog
|
|
137
155
|
|
|
138
|
-
## v0.
|
|
156
|
+
## v0.4.0 (2025-08-10)
|
|
139
157
|
|
|
140
|
-
*release tag*: [v0.
|
|
158
|
+
*release tag*: [v0.4.0]
|
|
141
159
|
|
|
142
|
-
|
|
160
|
+
- New configuration model `DebugDojoConfig` for better structure.
|
|
161
|
+
- Added support for `debugger` configuration in `dojo.toml`.
|
|
162
|
+
- Updated `dojo` command to include debugger type in command call.
|
|
163
|
+
- Configuration versioning allows for in-flight migration of old configurations.
|
|
164
|
+
- Improved error handling in configuration loading.
|
|
165
|
+
- Improved catching errors from target execution.
|
|
166
|
+
|
|
167
|
+
## v0.3.2 (2025-07-28)
|
|
168
|
+
|
|
169
|
+
*release tag*: [v0.3.2]
|
|
143
170
|
|
|
144
171
|
- New logo for the project.
|
|
145
172
|
- Typer used for CLI implementation.
|
|
146
173
|
- Dojo is configured via `dojo.toml` or `pyproject.toml`.
|
|
147
|
-
|
|
148
|
-
#### Fixes
|
|
149
|
-
|
|
174
|
+
- Support for `debugpy` and `ipdb` for debugging.
|
|
150
175
|
- Fixed documentation and history.
|
|
151
176
|
|
|
152
177
|
## v0.2.0 (2025-07-20)
|
|
153
178
|
|
|
154
179
|
*release tag*: [v0.2.0]
|
|
155
180
|
|
|
156
|
-
### What's Changed
|
|
157
|
-
|
|
158
181
|
- Added `dojo` command for easy debugging setup.
|
|
159
182
|
- Added `p()` function for rich printing.
|
|
160
183
|
- Added history file for tracking changes.
|
|
161
184
|
- Moved to `hatch` for building and packaging.
|
|
162
|
-
|
|
163
|
-
#### Fixes
|
|
164
|
-
|
|
165
185
|
- Fixed `pyproject.toml` to point to GitHub repository as the homepage.
|
|
166
186
|
|
|
167
187
|
## v0.1.0 (2025-07-19)
|
|
168
188
|
|
|
169
189
|
*release tag*: [v0.1.0]
|
|
170
190
|
|
|
171
|
-
### What's Changed
|
|
172
|
-
|
|
173
191
|
- Initial module to install debugging tools.
|
|
174
192
|
- Debug mode utilities for PuDB, rich tracebacks, and object inspection.
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
<p align="center">
|
|
2
|
-
<img src="https://github.com/bwrob/debug-dojo/blob/main/logo/
|
|
2
|
+
<img src="https://github.com/bwrob/debug-dojo/blob/main/logo/logo_python.png?raw=true" alt="debug dojo" style="width:50%; max-width:300px;"/>
|
|
3
3
|
</p>
|
|
4
4
|
|
|
5
5
|
<p align="center">
|
|
@@ -9,15 +9,17 @@
|
|
|
9
9
|
[](https://pypi.org/project/debug-dojo)
|
|
10
10
|
[](https://pypi.org/pypi/debug-dojo/)
|
|
11
11
|
|
|
12
|
-
**debug-dojo** is a Python package providing utilities for enhanced debugging and inspection in the terminal.
|
|
12
|
+
**debug-dojo** is a Python package providing utilities for enhanced debugging and inspection in the terminal.
|
|
13
|
+
It leverages [`rich`](https://github.com/Textualize/rich) for beautiful output and offers helpers for side-by-side object comparison, improved tracebacks from `rich`, and easy integration with different debuggers -- `debugpy`, `pudb`, `pdb`, and `ipdb`.
|
|
13
14
|
|
|
14
15
|
## Features
|
|
15
16
|
|
|
16
17
|
- **Convenient CLI** Quickly run your code with debugging tools enabled.
|
|
17
18
|
- **Simple API:** Install all tools or only what you need.
|
|
18
|
-
- **Debugger integration:** Quickly enable Debugpy, PuDB, PDB, or IPDB as your default debugger.
|
|
19
|
+
- **Debugger integration:** Quickly enable Debugpy, PuDB, PDB, or IPDB as your default pre-configured debugger.
|
|
19
20
|
- **Rich tracebacks:** Get readable, colorized tracebacks for easier debugging.
|
|
20
21
|
- **Side-by-side object inspection:** Visually compare Python objects, their attributes, and methods in the terminal.
|
|
22
|
+
- **Configuration:** Easily configure the debugging tools using `dojo.toml` or `pyproject.toml`.
|
|
21
23
|
|
|
22
24
|
## Usage
|
|
23
25
|
|
|
@@ -29,10 +31,10 @@ Run your Python script with debugging tools enabled using the `debug-dojo` comma
|
|
|
29
31
|
dojo my_script.py
|
|
30
32
|
```
|
|
31
33
|
|
|
32
|
-
You can optionally set configuration
|
|
34
|
+
You can optionally set configuration, verbose mode, and specify the debugger type. Both script files and modules are supported:
|
|
33
35
|
|
|
34
36
|
```console
|
|
35
|
-
dojo --config dojo.toml --verbose
|
|
37
|
+
dojo --debugger ipdb --config dojo.toml --verbose --module my_module
|
|
36
38
|
```
|
|
37
39
|
|
|
38
40
|
### From the code
|
|
@@ -40,19 +42,18 @@ dojo --config dojo.toml --verbose my_script.py
|
|
|
40
42
|
In the `PuDB` style, you can install all debugging tools and enter the debugging mode with a single command:
|
|
41
43
|
|
|
42
44
|
```python
|
|
43
|
-
import debug_dojo.install; b()
|
|
44
|
-
|
|
45
45
|
object_1 = {"foo": 1, "bar": 2}
|
|
46
46
|
object_2 = [1, 2, 3]
|
|
47
47
|
|
|
48
|
+
import debug_dojo.install; b()
|
|
48
49
|
p(object_1) # Pretty print an object with Rich
|
|
49
|
-
i(object_1) # Inspect an object
|
|
50
|
-
c(object_1, object_2) # Compare two objects side-by-side
|
|
51
50
|
```
|
|
52
51
|
|
|
53
|
-
|
|
52
|
+
### Features in debugging mode
|
|
54
53
|
|
|
55
|
-
|
|
54
|
+
The following functions are available in the debugging mode, injected into builtins:
|
|
55
|
+
|
|
56
|
+
- `b()` is a hook that sets a breakpoint using the configured debugger.
|
|
56
57
|
- `p(object_1)` is pretty printing of an object using Rich.
|
|
57
58
|
- `i(object_1)` to inspect an object using Rich.
|
|
58
59
|
- `c(object_1, object_2)` to compare two objects side-by-side.
|
|
@@ -64,12 +65,23 @@ You can configure the debugging tools using a `dojo.toml` or `pyproject.toml` fi
|
|
|
64
65
|
**Example `dojo.toml`:**
|
|
65
66
|
|
|
66
67
|
```toml
|
|
67
|
-
|
|
68
|
+
[debuggers]
|
|
69
|
+
default = "ipdb"
|
|
70
|
+
|
|
71
|
+
debugpy = { port = 1992 }
|
|
72
|
+
ipdb = { context_lines = 20 }
|
|
73
|
+
|
|
74
|
+
[exceptions]
|
|
75
|
+
locals_in_traceback = false
|
|
76
|
+
post_mortem = true
|
|
77
|
+
rich_traceback = true
|
|
68
78
|
|
|
69
79
|
[features]
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
80
|
+
breakpoint = "b"
|
|
81
|
+
# Empty string means disable the feature
|
|
82
|
+
comparer = ""
|
|
83
|
+
rich_inspect = "i"
|
|
84
|
+
rich_print = "p"
|
|
73
85
|
```
|
|
74
86
|
|
|
75
87
|
## Installation
|
|
@@ -99,4 +111,10 @@ Note that dojo most likely will not work when installed via `pipx` or `uvx`, as
|
|
|
99
111
|
```console
|
|
100
112
|
ruff check src/debug_dojo --fix
|
|
101
113
|
basedpyright src/debug_dojo
|
|
114
|
+
|
|
115
|
+
poe code-quality
|
|
102
116
|
```
|
|
117
|
+
|
|
118
|
+
### Tests
|
|
119
|
+
|
|
120
|
+
TBA
|
|
@@ -13,7 +13,7 @@
|
|
|
13
13
|
"rich>=12.0.0",
|
|
14
14
|
"tomlkit>=0.13.3",
|
|
15
15
|
"typer>=0.15.0",
|
|
16
|
-
]
|
|
16
|
+
]
|
|
17
17
|
license = 'MIT'
|
|
18
18
|
license-files = ['LICENSE']
|
|
19
19
|
keywords = [
|
|
@@ -36,7 +36,7 @@
|
|
|
36
36
|
"Topic :: Software Development :: Debuggers",
|
|
37
37
|
"Topic :: Software Development :: Libraries :: Python Modules",
|
|
38
38
|
]
|
|
39
|
-
version = "0.
|
|
39
|
+
version = "0.4.0"
|
|
40
40
|
dynamic = ['readme']
|
|
41
41
|
|
|
42
42
|
[project.urls]
|
|
@@ -46,8 +46,6 @@ version = "0.3.1"
|
|
|
46
46
|
Changelog = "https://github.com/bwrob/debug-dojo/blob/main/HISTORY.md"
|
|
47
47
|
|
|
48
48
|
[project.scripts]
|
|
49
|
-
# This defines your command-line script!
|
|
50
|
-
# It points to the 'main' function in your 'cli' module.
|
|
51
49
|
"dojo" = "debug_dojo._cli:main"
|
|
52
50
|
|
|
53
51
|
[dependency-groups]
|
|
@@ -56,7 +54,7 @@ version = "0.3.1"
|
|
|
56
54
|
"jupyter>=1.1.1",
|
|
57
55
|
"poethepoet>=0.36.0",
|
|
58
56
|
"ruff>=0.12.4",
|
|
59
|
-
]
|
|
57
|
+
]
|
|
60
58
|
|
|
61
59
|
[build-system]
|
|
62
60
|
requires = [
|
|
@@ -65,10 +63,6 @@ version = "0.3.1"
|
|
|
65
63
|
]
|
|
66
64
|
build-backend = "hatchling.build"
|
|
67
65
|
|
|
68
|
-
|
|
69
|
-
[tool.hatch.version]
|
|
70
|
-
path = "src/debug_dojo/version.py"
|
|
71
|
-
|
|
72
66
|
[tool.hatch.metadata]
|
|
73
67
|
allow-direct-references = true
|
|
74
68
|
|
|
@@ -81,15 +75,28 @@ version = "0.3.1"
|
|
|
81
75
|
{ path = 'HISTORY.md' },
|
|
82
76
|
]
|
|
83
77
|
|
|
78
|
+
|
|
79
|
+
[tool.hatch.build.targets.sdist]
|
|
80
|
+
include = [
|
|
81
|
+
"/README.md",
|
|
82
|
+
"/HISTORY.md",
|
|
83
|
+
"/src/debug_dojo",
|
|
84
|
+
]
|
|
85
|
+
|
|
84
86
|
[tool.basedpyright]
|
|
85
|
-
typeCheckingMode = "
|
|
87
|
+
typeCheckingMode = "basic"
|
|
86
88
|
pythonVersion = "3.10"
|
|
87
89
|
strict = ["src/debug_dojo/*"]
|
|
88
90
|
ignore = ["examples"]
|
|
89
91
|
|
|
90
92
|
[tool.poe.tasks]
|
|
91
|
-
# Define your tasks here
|
|
92
93
|
lint = "ruff check --fix src"
|
|
93
94
|
format = "ruff format src"
|
|
94
|
-
type-check = "basedpyright"
|
|
95
|
+
type-check = "basedpyright --project pyproject.toml src/debug_dojo"
|
|
95
96
|
code-quality = ["format", "lint", "type-check"]
|
|
97
|
+
publish = [
|
|
98
|
+
"code-quality",
|
|
99
|
+
{ cmd = "rm -rf dist" },
|
|
100
|
+
{ cmd = "uv build" },
|
|
101
|
+
{ cmd = "uv publish" },
|
|
102
|
+
]
|
|
@@ -2,7 +2,6 @@
|
|
|
2
2
|
|
|
3
3
|
from __future__ import annotations
|
|
4
4
|
|
|
5
|
-
import os
|
|
6
5
|
import runpy
|
|
7
6
|
import sys
|
|
8
7
|
from bdb import BdbQuit
|
|
@@ -10,10 +9,9 @@ from pathlib import Path
|
|
|
10
9
|
from typing import Annotated
|
|
11
10
|
|
|
12
11
|
import typer
|
|
13
|
-
from pydantic import ValidationError
|
|
14
12
|
from rich import print as rich_print
|
|
15
13
|
|
|
16
|
-
from ._config import DebugDojoConfig, load_config
|
|
14
|
+
from ._config import DebugDojoConfig, DebuggerType, load_config
|
|
17
15
|
from ._installers import install_by_config
|
|
18
16
|
|
|
19
17
|
cli = typer.Typer(
|
|
@@ -23,11 +21,13 @@ cli = typer.Typer(
|
|
|
23
21
|
)
|
|
24
22
|
|
|
25
23
|
|
|
26
|
-
def execute_with_debug(
|
|
24
|
+
def execute_with_debug( # noqa: C901
|
|
27
25
|
target_name: str,
|
|
28
26
|
target_args: list[str],
|
|
29
27
|
*,
|
|
28
|
+
target_is_module: bool,
|
|
30
29
|
verbose: bool,
|
|
30
|
+
config: DebugDojoConfig,
|
|
31
31
|
) -> None:
|
|
32
32
|
"""Execute a target script or module with installation of debugging tools."""
|
|
33
33
|
sys.argv = [target_name, *target_args]
|
|
@@ -36,21 +36,37 @@ def execute_with_debug(
|
|
|
36
36
|
rich_print(f"[blue]Installing debugging tools for {target_name}.[/blue]")
|
|
37
37
|
rich_print(f"[blue]Arguments for target: {target_args}[/blue]")
|
|
38
38
|
|
|
39
|
-
config = load_config()
|
|
40
39
|
install_by_config(config)
|
|
41
40
|
|
|
42
|
-
if
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
or os.sep in target_name
|
|
46
|
-
):
|
|
41
|
+
if target_is_module:
|
|
42
|
+
runner = runpy.run_module
|
|
43
|
+
else:
|
|
47
44
|
if not Path(target_name).exists():
|
|
48
45
|
sys.exit(1)
|
|
49
46
|
runner = runpy.run_path
|
|
50
|
-
else:
|
|
51
|
-
runner = runpy.run_module
|
|
52
47
|
|
|
53
|
-
|
|
48
|
+
try:
|
|
49
|
+
_ = runner(target_name, run_name="__main__")
|
|
50
|
+
except ImportError as e:
|
|
51
|
+
rich_print(f"[red]Error importing {target_name}:[/red]\n{e}")
|
|
52
|
+
sys.exit(1)
|
|
53
|
+
except BdbQuit:
|
|
54
|
+
rich_print("[red]Debugging session terminated by user.[/red]")
|
|
55
|
+
sys.exit(0)
|
|
56
|
+
except KeyboardInterrupt:
|
|
57
|
+
rich_print("[red]Execution interrupted by user.[/red]")
|
|
58
|
+
sys.exit(0)
|
|
59
|
+
except SystemExit as e:
|
|
60
|
+
if e.code:
|
|
61
|
+
rich_print(f"[red]Script exited with code {e.code}.[/red]")
|
|
62
|
+
except Exception as e: # noqa: BLE001
|
|
63
|
+
rich_print(f"[red]Error while running {target_name}:[/red]\n{e}")
|
|
64
|
+
if config.exceptions.post_mortem:
|
|
65
|
+
import pdb # noqa: PLC0415, T100
|
|
66
|
+
|
|
67
|
+
rich_print("[blue]Entering post-mortem debugging session...[/blue]")
|
|
68
|
+
pdb.post_mortem(e.__traceback__)
|
|
69
|
+
sys.exit(1)
|
|
54
70
|
|
|
55
71
|
|
|
56
72
|
def display_config(config: DebugDojoConfig) -> None:
|
|
@@ -64,36 +80,42 @@ def display_config(config: DebugDojoConfig) -> None:
|
|
|
64
80
|
no_args_is_help=True,
|
|
65
81
|
context_settings={"allow_extra_args": True, "ignore_unknown_options": True},
|
|
66
82
|
)
|
|
67
|
-
def run_debug(
|
|
83
|
+
def run_debug( # noqa: PLR0913
|
|
68
84
|
ctx: typer.Context,
|
|
69
85
|
target_name: Annotated[
|
|
70
86
|
str | None, typer.Argument(help="The target script or module to debug.")
|
|
71
87
|
] = None,
|
|
88
|
+
*,
|
|
72
89
|
config_path: Annotated[
|
|
73
90
|
Path | None, typer.Option("--config", "-c", help="Show configuration")
|
|
74
91
|
] = None,
|
|
75
|
-
|
|
92
|
+
debugger: Annotated[
|
|
93
|
+
DebuggerType | None,
|
|
94
|
+
typer.Option("--debugger", "-d", help="Specify the debugger to use"),
|
|
95
|
+
] = None,
|
|
76
96
|
verbose: Annotated[
|
|
77
97
|
bool,
|
|
78
98
|
typer.Option("--verbose", "-v", is_flag=True, help="Enable verbose output"),
|
|
79
99
|
] = False,
|
|
100
|
+
module: Annotated[
|
|
101
|
+
bool,
|
|
102
|
+
typer.Option("--module", "-m", is_flag=True, help="Run as a module"),
|
|
103
|
+
] = False,
|
|
80
104
|
) -> None:
|
|
81
105
|
"""Run the command-line interface."""
|
|
82
|
-
|
|
83
|
-
config = load_config(config_path, verbose=verbose)
|
|
84
|
-
except ValidationError as e:
|
|
85
|
-
rich_print(f"[red]Configuration error:\n{e}[/red]")
|
|
86
|
-
sys.exit(1)
|
|
106
|
+
config = load_config(config_path, verbose=verbose, debugger=debugger)
|
|
87
107
|
|
|
88
108
|
if verbose:
|
|
89
109
|
display_config(config)
|
|
90
110
|
|
|
91
111
|
if target_name:
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
112
|
+
execute_with_debug(
|
|
113
|
+
target_name=target_name,
|
|
114
|
+
target_is_module=module,
|
|
115
|
+
target_args=ctx.args,
|
|
116
|
+
verbose=verbose,
|
|
117
|
+
config=config,
|
|
118
|
+
)
|
|
97
119
|
|
|
98
120
|
|
|
99
121
|
def main() -> None:
|
|
@@ -0,0 +1,136 @@
|
|
|
1
|
+
"""Debug Dojo configuration module.
|
|
2
|
+
|
|
3
|
+
It includes configurations for different debuggers, exception handling,
|
|
4
|
+
and features that can be enabled or disabled.
|
|
5
|
+
"""
|
|
6
|
+
|
|
7
|
+
from __future__ import annotations
|
|
8
|
+
|
|
9
|
+
import sys
|
|
10
|
+
from pathlib import Path
|
|
11
|
+
from typing import Any, cast
|
|
12
|
+
|
|
13
|
+
from pydantic import ValidationError
|
|
14
|
+
from rich import print as rich_print
|
|
15
|
+
from tomlkit import parse
|
|
16
|
+
from tomlkit.exceptions import TOMLKitError
|
|
17
|
+
|
|
18
|
+
from ._config_models import (
|
|
19
|
+
DebugDojoConfig,
|
|
20
|
+
DebugDojoConfigV1,
|
|
21
|
+
DebugDojoConfigV2,
|
|
22
|
+
DebuggerType,
|
|
23
|
+
)
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
def __filter_pydantic_error_msg(error: ValidationError) -> str:
|
|
27
|
+
"""Filter out specific lines from a Pydantic validation error."""
|
|
28
|
+
return "\n".join(
|
|
29
|
+
line
|
|
30
|
+
for line in str(error).splitlines()
|
|
31
|
+
if not line.startswith("For further information visit")
|
|
32
|
+
)
|
|
33
|
+
|
|
34
|
+
|
|
35
|
+
def resolve_config_path(config_path: Path | None) -> Path | None:
|
|
36
|
+
"""Resolve the configuration path, returning a default if none is provided."""
|
|
37
|
+
if config_path:
|
|
38
|
+
if not config_path.exists():
|
|
39
|
+
msg = f"Configuration file not found:\n{config_path.resolve()}"
|
|
40
|
+
raise FileNotFoundError(msg)
|
|
41
|
+
return config_path.resolve()
|
|
42
|
+
|
|
43
|
+
# Default configuration path
|
|
44
|
+
for path in (Path("dojo.toml"), Path("pyproject.toml")):
|
|
45
|
+
if path.exists():
|
|
46
|
+
return path.resolve()
|
|
47
|
+
return None
|
|
48
|
+
|
|
49
|
+
|
|
50
|
+
def load_raw_config(
|
|
51
|
+
config_path: Path,
|
|
52
|
+
) -> dict[str, Any]: # pyright: ignore[reportExplicitAny]
|
|
53
|
+
"""Load the Debug Dojo configuration from a file.
|
|
54
|
+
|
|
55
|
+
Currently supports 'dojo.toml' or 'pyproject.toml'.
|
|
56
|
+
If no path is provided, it checks the current directory for these files.
|
|
57
|
+
"""
|
|
58
|
+
config_str = config_path.read_text(encoding="utf-8")
|
|
59
|
+
|
|
60
|
+
try:
|
|
61
|
+
config_data = parse(config_str).unwrap()
|
|
62
|
+
except TOMLKitError as e:
|
|
63
|
+
msg = f"Error parsing configuration file {config_path.resolve()}."
|
|
64
|
+
raise ValueError(msg) from e
|
|
65
|
+
|
|
66
|
+
# If config is in [tool.debug_dojo] (pyproject.toml), extract it.
|
|
67
|
+
if config_path.name == "pyproject.toml":
|
|
68
|
+
try:
|
|
69
|
+
dojo_config = cast("dict[str, Any]", config_data["tool"]["debug_dojo"])
|
|
70
|
+
except KeyError:
|
|
71
|
+
return {}
|
|
72
|
+
else:
|
|
73
|
+
return dojo_config
|
|
74
|
+
|
|
75
|
+
return config_data
|
|
76
|
+
|
|
77
|
+
|
|
78
|
+
def load_config( # noqa: C901
|
|
79
|
+
config_path: Path | None = None,
|
|
80
|
+
*,
|
|
81
|
+
verbose: bool = False,
|
|
82
|
+
debugger: DebuggerType | None = None,
|
|
83
|
+
) -> DebugDojoConfig:
|
|
84
|
+
"""Load the Debug Dojo configuration and return a DebugDojoConfig instance."""
|
|
85
|
+
resolved_path = resolve_config_path(config_path)
|
|
86
|
+
|
|
87
|
+
if verbose:
|
|
88
|
+
if resolved_path:
|
|
89
|
+
msg = f"Using configuration file: {resolved_path}."
|
|
90
|
+
else:
|
|
91
|
+
msg = "No configuration file found, using default settings."
|
|
92
|
+
rich_print(f"[blue]{msg}[/blue]")
|
|
93
|
+
|
|
94
|
+
if not resolved_path:
|
|
95
|
+
return DebugDojoConfig()
|
|
96
|
+
|
|
97
|
+
raw_config = load_raw_config(resolved_path)
|
|
98
|
+
|
|
99
|
+
config = None
|
|
100
|
+
for model in (DebugDojoConfigV2, DebugDojoConfigV1):
|
|
101
|
+
model_name = model.__name__
|
|
102
|
+
try:
|
|
103
|
+
config = model.model_validate(raw_config)
|
|
104
|
+
except ValidationError as e:
|
|
105
|
+
if verbose:
|
|
106
|
+
msg = (
|
|
107
|
+
f"[yellow]Configuration validation error for {model_name}:\n"
|
|
108
|
+
f"{__filter_pydantic_error_msg(e)}\n\n"
|
|
109
|
+
f"Please check your configuration file {resolved_path}.[/yellow]"
|
|
110
|
+
)
|
|
111
|
+
rich_print(msg)
|
|
112
|
+
else:
|
|
113
|
+
if verbose or model_name != DebugDojoConfig.__name__:
|
|
114
|
+
msg = (
|
|
115
|
+
f"[blue]Using configuration model: {model_name}.\n"
|
|
116
|
+
f"Current configuration model {DebugDojoConfig.__name__}. [/blue]"
|
|
117
|
+
)
|
|
118
|
+
rich_print(msg)
|
|
119
|
+
break
|
|
120
|
+
|
|
121
|
+
if not config:
|
|
122
|
+
msg = (
|
|
123
|
+
f"[red]Unsupported configuration version in {resolved_path.resolve()}.\n"
|
|
124
|
+
"Please update your configuration file.[/red]"
|
|
125
|
+
)
|
|
126
|
+
rich_print(msg)
|
|
127
|
+
sys.exit(1)
|
|
128
|
+
|
|
129
|
+
while not isinstance(config, DebugDojoConfig):
|
|
130
|
+
config = config.update()
|
|
131
|
+
|
|
132
|
+
# If a debugger is specified, update the config.
|
|
133
|
+
if debugger:
|
|
134
|
+
config.debuggers.default = debugger
|
|
135
|
+
|
|
136
|
+
return config
|