debug-dojo 0.5.0__tar.gz → 0.7.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.7.0/PKG-INFO +138 -0
- debug_dojo-0.7.0/README.md +105 -0
- debug_dojo-0.7.0/pyproject.toml +87 -0
- {debug_dojo-0.5.0 → debug_dojo-0.7.0}/src/debug_dojo/_cli.py +42 -9
- {debug_dojo-0.5.0 → debug_dojo-0.7.0}/src/debug_dojo/_compare.py +37 -9
- {debug_dojo-0.5.0 → debug_dojo-0.7.0}/src/debug_dojo/_config.py +77 -36
- {debug_dojo-0.5.0 → debug_dojo-0.7.0}/src/debug_dojo/_config_models.py +45 -41
- debug_dojo-0.7.0/src/debug_dojo/_installers.py +271 -0
- debug_dojo-0.7.0/src/debug_dojo.egg-info/PKG-INFO +138 -0
- {debug_dojo-0.5.0 → debug_dojo-0.7.0}/src/debug_dojo.egg-info/SOURCES.txt +4 -1
- debug_dojo-0.7.0/src/debug_dojo.egg-info/requires.txt +9 -0
- debug_dojo-0.7.0/tests/test_compare.py +75 -0
- debug_dojo-0.7.0/tests/test_config.py +81 -0
- debug_dojo-0.7.0/tests/test_installers.py +161 -0
- debug_dojo-0.5.0/PKG-INFO +0 -83
- debug_dojo-0.5.0/README.md +0 -52
- debug_dojo-0.5.0/pyproject.toml +0 -126
- debug_dojo-0.5.0/src/debug_dojo/_installers.py +0 -182
- debug_dojo-0.5.0/src/debug_dojo.egg-info/PKG-INFO +0 -83
- debug_dojo-0.5.0/src/debug_dojo.egg-info/requires.txt +0 -7
- {debug_dojo-0.5.0 → debug_dojo-0.7.0}/LICENSE +0 -0
- {debug_dojo-0.5.0 → debug_dojo-0.7.0}/setup.cfg +0 -0
- {debug_dojo-0.5.0 → debug_dojo-0.7.0}/src/debug_dojo/__init__.py +0 -0
- {debug_dojo-0.5.0 → debug_dojo-0.7.0}/src/debug_dojo/__main__.py +0 -0
- {debug_dojo-0.5.0 → debug_dojo-0.7.0}/src/debug_dojo/install.py +0 -0
- {debug_dojo-0.5.0 → debug_dojo-0.7.0}/src/debug_dojo/py.typed +0 -0
- {debug_dojo-0.5.0 → debug_dojo-0.7.0}/src/debug_dojo.egg-info/dependency_links.txt +0 -0
- {debug_dojo-0.5.0 → debug_dojo-0.7.0}/src/debug_dojo.egg-info/entry_points.txt +0 -0
- {debug_dojo-0.5.0 → debug_dojo-0.7.0}/src/debug_dojo.egg-info/top_level.txt +0 -0
|
@@ -0,0 +1,138 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: debug-dojo
|
|
3
|
+
Version: 0.7.0
|
|
4
|
+
Summary: 🏣 debug dojo, a place for zen debugging
|
|
5
|
+
Author-email: bwrob <bartosz.marcin.wroblewski@gmail.com>
|
|
6
|
+
License-Expression: MIT
|
|
7
|
+
Project-URL: Changelog, https://bwrob.github.io/debug-dojo/changelog/
|
|
8
|
+
Project-URL: Documentation, https://bwrob.github.io/debug-dojo/
|
|
9
|
+
Project-URL: Homepage, https://bwrob.github.io/debug-dojo/
|
|
10
|
+
Project-URL: Source, https://github.com/bwrob/debug-dojo/
|
|
11
|
+
Keywords: debugging,inspection,tools,development
|
|
12
|
+
Classifier: Intended Audience :: Developers
|
|
13
|
+
Classifier: Operating System :: OS Independent
|
|
14
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
15
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
16
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
17
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
18
|
+
Classifier: Programming Language :: Python :: 3.14
|
|
19
|
+
Classifier: Topic :: Software Development :: Debuggers
|
|
20
|
+
Classifier: Topic :: Software Development :: Libraries :: Python Modules
|
|
21
|
+
Requires-Python: <3.15,>=3.10
|
|
22
|
+
Description-Content-Type: text/markdown
|
|
23
|
+
License-File: LICENSE
|
|
24
|
+
Requires-Dist: dacite>=1.0.0
|
|
25
|
+
Requires-Dist: rich>=10.0.0
|
|
26
|
+
Requires-Dist: tomlkit>=0.7.0
|
|
27
|
+
Requires-Dist: typer>=0.3.0
|
|
28
|
+
Provides-Extra: all-debuggers
|
|
29
|
+
Requires-Dist: debugpy>=1.0.0; extra == "all-debuggers"
|
|
30
|
+
Requires-Dist: ipdb>=0.12.0; extra == "all-debuggers"
|
|
31
|
+
Requires-Dist: pudb>=2020.1; extra == "all-debuggers"
|
|
32
|
+
Dynamic: license-file
|
|
33
|
+
|
|
34
|
+
#
|
|
35
|
+
|
|
36
|
+
<p align="center">
|
|
37
|
+
<img src="https://github.com/bwrob/debug-dojo/blob/main/docs/logo/banner.png?raw=true" alt="debug dojo" style="width:100%;"/>
|
|
38
|
+
</p>
|
|
39
|
+
|
|
40
|
+
<p align="center">
|
|
41
|
+
<em>🏣 debug dojo, a place for zen debugging</em>
|
|
42
|
+
</p>
|
|
43
|
+
|
|
44
|
+
<p align="center">
|
|
45
|
+
<a href="https://pypi.org/project/debug-dojo">
|
|
46
|
+
<img src="https://img.shields.io/pypi/v/debug-dojo.svg?style=flat-square" alt="PyPi Version">
|
|
47
|
+
</a>
|
|
48
|
+
<a href="https://pypi.org/pypi/debug-dojo/">
|
|
49
|
+
<img src="https://img.shields.io/pypi/pyversions/debug-dojo.svg?style=flat-square" alt="PyPI pyversions">
|
|
50
|
+
</a>
|
|
51
|
+
<a href="https://pepy.tech/project/debug-dojo">
|
|
52
|
+
<img src="https://static.pepy.tech/badge/debug-dojo/month" alt="downloads">
|
|
53
|
+
</a>
|
|
54
|
+
<a href="https://github.com/bwrob/debug-dojo/blob/main/LICENSE">
|
|
55
|
+
<img src="https://img.shields.io/github/license/bwrob/debug-dojo.svg" alt="license">
|
|
56
|
+
</a>
|
|
57
|
+
<a href="https://results.pre-commit.ci/latest/github/bwrob/debug-dojo/main">
|
|
58
|
+
<img src="https://results.pre-commit.ci/badge/github/bwrob/debug-dojo/main.svg" alt="pre-commit.ci status">
|
|
59
|
+
</a>
|
|
60
|
+
</p>
|
|
61
|
+
|
|
62
|
+
[**debug-dojo**](https://bwrob.github.io/debug-dojo/) is a powerful Python package designed to streamline your debugging workflow directly from the terminal. It integrates seamlessly with popular debuggers and enhances your inspection capabilities with beautiful, readable output.
|
|
63
|
+
|
|
64
|
+
## ✨ Features
|
|
65
|
+
|
|
66
|
+
* **Unified Debugging Interface:** Easily launch your scripts or modules with your preferred debugger (`debugpy`, `pudb`, `pdb`, `ipdb`).
|
|
67
|
+
* **Enhanced Output with Rich:** Leverages [`rich`](https://github.com/Textualize/rich) for stunning, syntax-highlighted code, pretty-printed objects, and improved tracebacks.
|
|
68
|
+
* **Side-by-Side Object Comparison:** Quickly identify differences between two Python objects.
|
|
69
|
+
* **Interactive Object Inspection:** Dive deep into object structures with a powerful `inspect` utility.
|
|
70
|
+
* **Simplified Breakpoints:** Set breakpoints effortlessly with a concise helper function.
|
|
71
|
+
|
|
72
|
+
## 🚀 Installation
|
|
73
|
+
|
|
74
|
+
Install `debug-dojo` using `pip`:
|
|
75
|
+
|
|
76
|
+
```bash
|
|
77
|
+
pip install debug-dojo
|
|
78
|
+
```
|
|
79
|
+
|
|
80
|
+
For full debugger support, you might want to install optional dependencies:
|
|
81
|
+
|
|
82
|
+
```bash
|
|
83
|
+
pip install "debug-dojo[all-debuggers]"
|
|
84
|
+
```
|
|
85
|
+
|
|
86
|
+
## 💻 CLI Usage
|
|
87
|
+
|
|
88
|
+
Run your Python script or module with `debug-dojo`:
|
|
89
|
+
|
|
90
|
+
```console
|
|
91
|
+
dojo my_script.py
|
|
92
|
+
```
|
|
93
|
+
|
|
94
|
+
Specify a debugger, configuration file, or enable verbose output:
|
|
95
|
+
|
|
96
|
+
```console
|
|
97
|
+
dojo --debugger ipdb --config dojo.toml --verbose --module my_module
|
|
98
|
+
```
|
|
99
|
+
|
|
100
|
+
Run an executable command with debugging tools:
|
|
101
|
+
|
|
102
|
+
```console
|
|
103
|
+
dojo --exec pytest
|
|
104
|
+
```
|
|
105
|
+
|
|
106
|
+
## 🐍 Usage in Code
|
|
107
|
+
|
|
108
|
+
Integrate `debug-dojo` directly into your Python code for on-demand debugging and inspection utilities:
|
|
109
|
+
|
|
110
|
+
```python
|
|
111
|
+
import debug_dojo.install
|
|
112
|
+
|
|
113
|
+
# Set a breakpoint and enter the debugger
|
|
114
|
+
# debug_dojo.install.b() # Equivalent to breakpoint()
|
|
115
|
+
|
|
116
|
+
object_1 = {"foo": 1, "bar": 2}
|
|
117
|
+
object_2 = [1, 2, 3]
|
|
118
|
+
|
|
119
|
+
# Pretty print an object with Rich
|
|
120
|
+
debug_dojo.install.p(object_1)
|
|
121
|
+
|
|
122
|
+
# Inspect an object using Rich
|
|
123
|
+
debug_dojo.install.i(object_1)
|
|
124
|
+
|
|
125
|
+
# Compare two objects side-by-side
|
|
126
|
+
debug_dojo.install.c(object_1, object_2)
|
|
127
|
+
|
|
128
|
+
# Enter the debugger (e.g., ipdb, pudb, pdb, debugpy based on config)
|
|
129
|
+
# debug_dojo.install.b()
|
|
130
|
+
```
|
|
131
|
+
|
|
132
|
+
## 📚 Documentation
|
|
133
|
+
|
|
134
|
+
For comprehensive instructions on installation, configuration, advanced usage, and API reference, please visit the [official documentation](https://bwrob.github.io/debug-dojo/).
|
|
135
|
+
|
|
136
|
+
## 🤝 Contributing
|
|
137
|
+
|
|
138
|
+
Contributions are welcome! Please refer to the [development guidelines](https://bwrob.github.io/debug-dojo/development/) for details on how to set up your development environment and submit changes.
|
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
#
|
|
2
|
+
|
|
3
|
+
<p align="center">
|
|
4
|
+
<img src="https://github.com/bwrob/debug-dojo/blob/main/docs/logo/banner.png?raw=true" alt="debug dojo" style="width:100%;"/>
|
|
5
|
+
</p>
|
|
6
|
+
|
|
7
|
+
<p align="center">
|
|
8
|
+
<em>🏣 debug dojo, a place for zen debugging</em>
|
|
9
|
+
</p>
|
|
10
|
+
|
|
11
|
+
<p align="center">
|
|
12
|
+
<a href="https://pypi.org/project/debug-dojo">
|
|
13
|
+
<img src="https://img.shields.io/pypi/v/debug-dojo.svg?style=flat-square" alt="PyPi Version">
|
|
14
|
+
</a>
|
|
15
|
+
<a href="https://pypi.org/pypi/debug-dojo/">
|
|
16
|
+
<img src="https://img.shields.io/pypi/pyversions/debug-dojo.svg?style=flat-square" alt="PyPI pyversions">
|
|
17
|
+
</a>
|
|
18
|
+
<a href="https://pepy.tech/project/debug-dojo">
|
|
19
|
+
<img src="https://static.pepy.tech/badge/debug-dojo/month" alt="downloads">
|
|
20
|
+
</a>
|
|
21
|
+
<a href="https://github.com/bwrob/debug-dojo/blob/main/LICENSE">
|
|
22
|
+
<img src="https://img.shields.io/github/license/bwrob/debug-dojo.svg" alt="license">
|
|
23
|
+
</a>
|
|
24
|
+
<a href="https://results.pre-commit.ci/latest/github/bwrob/debug-dojo/main">
|
|
25
|
+
<img src="https://results.pre-commit.ci/badge/github/bwrob/debug-dojo/main.svg" alt="pre-commit.ci status">
|
|
26
|
+
</a>
|
|
27
|
+
</p>
|
|
28
|
+
|
|
29
|
+
[**debug-dojo**](https://bwrob.github.io/debug-dojo/) is a powerful Python package designed to streamline your debugging workflow directly from the terminal. It integrates seamlessly with popular debuggers and enhances your inspection capabilities with beautiful, readable output.
|
|
30
|
+
|
|
31
|
+
## ✨ Features
|
|
32
|
+
|
|
33
|
+
* **Unified Debugging Interface:** Easily launch your scripts or modules with your preferred debugger (`debugpy`, `pudb`, `pdb`, `ipdb`).
|
|
34
|
+
* **Enhanced Output with Rich:** Leverages [`rich`](https://github.com/Textualize/rich) for stunning, syntax-highlighted code, pretty-printed objects, and improved tracebacks.
|
|
35
|
+
* **Side-by-Side Object Comparison:** Quickly identify differences between two Python objects.
|
|
36
|
+
* **Interactive Object Inspection:** Dive deep into object structures with a powerful `inspect` utility.
|
|
37
|
+
* **Simplified Breakpoints:** Set breakpoints effortlessly with a concise helper function.
|
|
38
|
+
|
|
39
|
+
## 🚀 Installation
|
|
40
|
+
|
|
41
|
+
Install `debug-dojo` using `pip`:
|
|
42
|
+
|
|
43
|
+
```bash
|
|
44
|
+
pip install debug-dojo
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
For full debugger support, you might want to install optional dependencies:
|
|
48
|
+
|
|
49
|
+
```bash
|
|
50
|
+
pip install "debug-dojo[all-debuggers]"
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
## 💻 CLI Usage
|
|
54
|
+
|
|
55
|
+
Run your Python script or module with `debug-dojo`:
|
|
56
|
+
|
|
57
|
+
```console
|
|
58
|
+
dojo my_script.py
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
Specify a debugger, configuration file, or enable verbose output:
|
|
62
|
+
|
|
63
|
+
```console
|
|
64
|
+
dojo --debugger ipdb --config dojo.toml --verbose --module my_module
|
|
65
|
+
```
|
|
66
|
+
|
|
67
|
+
Run an executable command with debugging tools:
|
|
68
|
+
|
|
69
|
+
```console
|
|
70
|
+
dojo --exec pytest
|
|
71
|
+
```
|
|
72
|
+
|
|
73
|
+
## 🐍 Usage in Code
|
|
74
|
+
|
|
75
|
+
Integrate `debug-dojo` directly into your Python code for on-demand debugging and inspection utilities:
|
|
76
|
+
|
|
77
|
+
```python
|
|
78
|
+
import debug_dojo.install
|
|
79
|
+
|
|
80
|
+
# Set a breakpoint and enter the debugger
|
|
81
|
+
# debug_dojo.install.b() # Equivalent to breakpoint()
|
|
82
|
+
|
|
83
|
+
object_1 = {"foo": 1, "bar": 2}
|
|
84
|
+
object_2 = [1, 2, 3]
|
|
85
|
+
|
|
86
|
+
# Pretty print an object with Rich
|
|
87
|
+
debug_dojo.install.p(object_1)
|
|
88
|
+
|
|
89
|
+
# Inspect an object using Rich
|
|
90
|
+
debug_dojo.install.i(object_1)
|
|
91
|
+
|
|
92
|
+
# Compare two objects side-by-side
|
|
93
|
+
debug_dojo.install.c(object_1, object_2)
|
|
94
|
+
|
|
95
|
+
# Enter the debugger (e.g., ipdb, pudb, pdb, debugpy based on config)
|
|
96
|
+
# debug_dojo.install.b()
|
|
97
|
+
```
|
|
98
|
+
|
|
99
|
+
## 📚 Documentation
|
|
100
|
+
|
|
101
|
+
For comprehensive instructions on installation, configuration, advanced usage, and API reference, please visit the [official documentation](https://bwrob.github.io/debug-dojo/).
|
|
102
|
+
|
|
103
|
+
## 🤝 Contributing
|
|
104
|
+
|
|
105
|
+
Contributions are welcome! Please refer to the [development guidelines](https://bwrob.github.io/debug-dojo/development/) for details on how to set up your development environment and submit changes.
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
[project]
|
|
2
|
+
authors = [
|
|
3
|
+
{ name = "bwrob", email = "bartosz.marcin.wroblewski@gmail.com" },
|
|
4
|
+
]
|
|
5
|
+
classifiers = [
|
|
6
|
+
"Intended Audience :: Developers",
|
|
7
|
+
"Operating System :: OS Independent",
|
|
8
|
+
"Programming Language :: Python :: 3.10",
|
|
9
|
+
"Programming Language :: Python :: 3.11",
|
|
10
|
+
"Programming Language :: Python :: 3.12",
|
|
11
|
+
"Programming Language :: Python :: 3.13",
|
|
12
|
+
"Programming Language :: Python :: 3.14",
|
|
13
|
+
"Topic :: Software Development :: Debuggers",
|
|
14
|
+
"Topic :: Software Development :: Libraries :: Python Modules",
|
|
15
|
+
]
|
|
16
|
+
dependencies = [
|
|
17
|
+
"dacite>=1.0.0",
|
|
18
|
+
"rich>=10.0.0",
|
|
19
|
+
"tomlkit>=0.7.0",
|
|
20
|
+
"typer>=0.3.0",
|
|
21
|
+
]
|
|
22
|
+
description = "🏣 debug dojo, a place for zen debugging"
|
|
23
|
+
keywords = [
|
|
24
|
+
"debugging",
|
|
25
|
+
"inspection",
|
|
26
|
+
"tools",
|
|
27
|
+
"development",
|
|
28
|
+
]
|
|
29
|
+
license = 'MIT'
|
|
30
|
+
license-files = ['LICENSE']
|
|
31
|
+
name = "debug-dojo"
|
|
32
|
+
readme = "README.md"
|
|
33
|
+
requires-python = ">=3.10,<3.15"
|
|
34
|
+
version = "0.7.0"
|
|
35
|
+
|
|
36
|
+
[project.urls]
|
|
37
|
+
Changelog = "https://bwrob.github.io/debug-dojo/changelog/"
|
|
38
|
+
Documentation = "https://bwrob.github.io/debug-dojo/"
|
|
39
|
+
Homepage = "https://bwrob.github.io/debug-dojo/"
|
|
40
|
+
Source = "https://github.com/bwrob/debug-dojo/"
|
|
41
|
+
|
|
42
|
+
[project.scripts]
|
|
43
|
+
"dojo" = "debug_dojo._cli:main"
|
|
44
|
+
|
|
45
|
+
[project.optional-dependencies]
|
|
46
|
+
all-debuggers = [
|
|
47
|
+
"debugpy>=1.0.0",
|
|
48
|
+
"ipdb>=0.12.0",
|
|
49
|
+
"pudb>=2020.1",
|
|
50
|
+
]
|
|
51
|
+
|
|
52
|
+
|
|
53
|
+
[dependency-groups]
|
|
54
|
+
|
|
55
|
+
dev = [
|
|
56
|
+
"basedpyright>=1.31.2",
|
|
57
|
+
"coverage>=7.10.4",
|
|
58
|
+
"debug-dojo[all-debuggers]",
|
|
59
|
+
"diff-cover>=9.6.0",
|
|
60
|
+
"poethepoet>=0.37.0",
|
|
61
|
+
"pytest>=8.4.1",
|
|
62
|
+
"pytest-cov>=6.2.1",
|
|
63
|
+
"ruff>=0.12.9",
|
|
64
|
+
"tach>=0.29.0",
|
|
65
|
+
]
|
|
66
|
+
docs = [
|
|
67
|
+
"mkdocs>=1.6.1",
|
|
68
|
+
"mkdocs-git-authors-plugin>=0.10.0",
|
|
69
|
+
"mkdocs-git-committers-plugin-2>=2.5.0",
|
|
70
|
+
"mkdocs-git-revision-date-localized-plugin>=1.4.7",
|
|
71
|
+
"mkdocs-material>=9.6.17",
|
|
72
|
+
"mkdocs-typer2>=0.1.5",
|
|
73
|
+
"mkdocstrings-python>=1.17.0",
|
|
74
|
+
"pymdown-extensions>=10.16.1",
|
|
75
|
+
"typst>=0.14.2",
|
|
76
|
+
]
|
|
77
|
+
|
|
78
|
+
|
|
79
|
+
[tool.uv]
|
|
80
|
+
package = true
|
|
81
|
+
required-version = ">=0.8.0"
|
|
82
|
+
|
|
83
|
+
[tool.uv.workspace]
|
|
84
|
+
members = ["."]
|
|
85
|
+
|
|
86
|
+
[tool.uv.sources]
|
|
87
|
+
debug-dojo = { workspace = true }
|
|
@@ -42,7 +42,20 @@ def __execute_with_debug( # noqa: C901
|
|
|
42
42
|
verbose: bool,
|
|
43
43
|
config: DebugDojoConfig,
|
|
44
44
|
) -> None:
|
|
45
|
-
"""Execute a target script or module with installed debugging tools.
|
|
45
|
+
"""Execute a target script or module with installed debugging tools.
|
|
46
|
+
|
|
47
|
+
Args:
|
|
48
|
+
target_name (str): The name of the script, module, or executable to run.
|
|
49
|
+
target_args (list[str]): Arguments to pass to the target.
|
|
50
|
+
target_mode (ExecMode): The execution mode (FILE, MODULE, or EXECUTABLE).
|
|
51
|
+
verbose (bool): If True, print verbose output.
|
|
52
|
+
config (DebugDojoConfig): The debug-dojo configuration.
|
|
53
|
+
|
|
54
|
+
Raises:
|
|
55
|
+
typer.Exit: If the target file is not found, or if an import error occurs,
|
|
56
|
+
or if the script exits with a non-zero code.
|
|
57
|
+
|
|
58
|
+
"""
|
|
46
59
|
sys.argv = [target_name, *target_args]
|
|
47
60
|
|
|
48
61
|
if verbose:
|
|
@@ -87,12 +100,6 @@ def __execute_with_debug( # noqa: C901
|
|
|
87
100
|
raise typer.Exit(1) from e
|
|
88
101
|
|
|
89
102
|
|
|
90
|
-
def display_config(config: DebugDojoConfig) -> None:
|
|
91
|
-
"""Display the configuration for the debug dojo."""
|
|
92
|
-
rich_print("[blue]Using debug-dojo configuration:[/blue]")
|
|
93
|
-
rich_print(config.model_dump_json(indent=4))
|
|
94
|
-
|
|
95
|
-
|
|
96
103
|
@cli.command(
|
|
97
104
|
help="Run a Python script or module with debugging tools installed.",
|
|
98
105
|
no_args_is_help=True,
|
|
@@ -124,7 +131,33 @@ def run_debug( # noqa: PLR0913
|
|
|
124
131
|
typer.Option("--exec", "-e", help="Run a command"),
|
|
125
132
|
] = False,
|
|
126
133
|
) -> None:
|
|
127
|
-
"""Run
|
|
134
|
+
"""Run a Python script, module, or executable with debug-dojo tools.
|
|
135
|
+
|
|
136
|
+
This command acts as the main entry point for `debug-dojo`, allowing users to
|
|
137
|
+
execute their code while automatically installing and configuring debugging tools
|
|
138
|
+
based on the provided options or configuration file.
|
|
139
|
+
|
|
140
|
+
Args:
|
|
141
|
+
ctx (typer.Context): The Typer context object.
|
|
142
|
+
target_name (str | None): The path to the script, name of the module, or
|
|
143
|
+
name of the executable to run. If not provided,
|
|
144
|
+
the command will exit.
|
|
145
|
+
config_path (Path | None): Path to a custom configuration file
|
|
146
|
+
(e.g., `dojo.toml`).
|
|
147
|
+
debugger (DebuggerType | None): Override the default debugger specified
|
|
148
|
+
in the config.
|
|
149
|
+
verbose (bool): Enable verbose output, showing loaded configuration
|
|
150
|
+
and installation steps.
|
|
151
|
+
module (bool): Treat `target_name` as a Python module to run
|
|
152
|
+
(e.g., `dojo -m my_package.my_module`).
|
|
153
|
+
executable (bool): Treat `target_name` as an executable command to run
|
|
154
|
+
(e.g., `dojo -e pytest`).
|
|
155
|
+
|
|
156
|
+
Raises:
|
|
157
|
+
typer.Exit: If `--module` and `--exec` are used together, or if the target
|
|
158
|
+
cannot be executed, or if an error occurs during execution.
|
|
159
|
+
|
|
160
|
+
"""
|
|
128
161
|
if module and executable:
|
|
129
162
|
rich_print(
|
|
130
163
|
"[red]Error: --module and --command options are mutually exclusive.[/red]"
|
|
@@ -142,7 +175,7 @@ def run_debug( # noqa: PLR0913
|
|
|
142
175
|
config = load_config(config_path, verbose=verbose, debugger=debugger)
|
|
143
176
|
|
|
144
177
|
if verbose:
|
|
145
|
-
|
|
178
|
+
rich_print(f"[blue]Using debug-dojo configuration: {config} [/blue]")
|
|
146
179
|
|
|
147
180
|
if target_name:
|
|
148
181
|
__execute_with_debug(
|
|
@@ -14,8 +14,16 @@ from rich.panel import Panel
|
|
|
14
14
|
from rich.text import Text
|
|
15
15
|
|
|
16
16
|
|
|
17
|
-
def
|
|
18
|
-
"""Extract and format non-callable attributes of an object.
|
|
17
|
+
def get_object_attributes(obj: object) -> list[str]:
|
|
18
|
+
"""Extract and format non-callable attributes of an object.
|
|
19
|
+
|
|
20
|
+
Args:
|
|
21
|
+
obj (object): The object to extract attributes from.
|
|
22
|
+
|
|
23
|
+
Returns:
|
|
24
|
+
list[str]: A list of formatted strings, each representing an attribute.
|
|
25
|
+
|
|
26
|
+
"""
|
|
19
27
|
attributes: list[str] = []
|
|
20
28
|
for attr_name in sorted(dir(obj)):
|
|
21
29
|
# Safely get attribute, returning None if it doesn't exist
|
|
@@ -28,8 +36,16 @@ def _get_object_attributes(obj: object) -> list[str]:
|
|
|
28
36
|
return attributes
|
|
29
37
|
|
|
30
38
|
|
|
31
|
-
def
|
|
32
|
-
"""Extract and format public callable methods of an object.
|
|
39
|
+
def get_object_methods(obj: object) -> list[str]:
|
|
40
|
+
"""Extract and format public callable methods of an object.
|
|
41
|
+
|
|
42
|
+
Args:
|
|
43
|
+
obj (object): The object to extract methods from.
|
|
44
|
+
|
|
45
|
+
Returns:
|
|
46
|
+
list[str]: A list of method names.
|
|
47
|
+
|
|
48
|
+
"""
|
|
33
49
|
methods: list[str] = []
|
|
34
50
|
for method_name in sorted(dir(obj)):
|
|
35
51
|
# Safely get attribute, returning None if it doesn't exist
|
|
@@ -40,11 +56,18 @@ def _get_object_methods(obj: object) -> list[str]:
|
|
|
40
56
|
return methods
|
|
41
57
|
|
|
42
58
|
|
|
43
|
-
def
|
|
59
|
+
def get_simplified_object_info(obj: object) -> list[Text]:
|
|
44
60
|
"""Generate a simplified, Rich-formatted inspection output for an object.
|
|
45
61
|
|
|
46
62
|
Handles basic Python types by displaying their value directly. For other objects, it
|
|
47
63
|
lists their attributes and public methods.
|
|
64
|
+
|
|
65
|
+
Args:
|
|
66
|
+
obj (object): The object to generate info for.
|
|
67
|
+
|
|
68
|
+
Returns:
|
|
69
|
+
list[Text]: A list of Rich Text objects representing the object's information.
|
|
70
|
+
|
|
48
71
|
"""
|
|
49
72
|
info_lines: list[Text] = []
|
|
50
73
|
obj_type: str = type(obj).__name__
|
|
@@ -62,7 +85,7 @@ def _get_simplified_object_info(obj: object) -> list[Text]:
|
|
|
62
85
|
return info_lines
|
|
63
86
|
|
|
64
87
|
# For other objects, list attributes
|
|
65
|
-
attributes =
|
|
88
|
+
attributes = get_object_attributes(obj)
|
|
66
89
|
if attributes:
|
|
67
90
|
info_lines.append(Text("Attributes:", style="bold"))
|
|
68
91
|
info_lines.extend([Text(f" {attr}") for attr in attributes])
|
|
@@ -71,7 +94,7 @@ def _get_simplified_object_info(obj: object) -> list[Text]:
|
|
|
71
94
|
info_lines.append(Text(""))
|
|
72
95
|
|
|
73
96
|
# List methods
|
|
74
|
-
methods =
|
|
97
|
+
methods = get_object_methods(obj)
|
|
75
98
|
if methods:
|
|
76
99
|
info_lines.append(Text("Methods:", style="bold"))
|
|
77
100
|
info_lines.extend([Text(f" {method}()") for method in methods])
|
|
@@ -88,11 +111,16 @@ def inspect_objects_side_by_side(
|
|
|
88
111
|
"""Display two Python objects side-by-side in the terminal using Rich.
|
|
89
112
|
|
|
90
113
|
Showing their attributes and methods in a simplified, aligned format.
|
|
114
|
+
|
|
115
|
+
Args:
|
|
116
|
+
obj1 (object): The first object to display.
|
|
117
|
+
obj2 (object): The second object to display.
|
|
118
|
+
|
|
91
119
|
"""
|
|
92
120
|
main_console: Console = Console()
|
|
93
121
|
|
|
94
|
-
lines1: list[Text] =
|
|
95
|
-
lines2: list[Text] =
|
|
122
|
+
lines1: list[Text] = get_simplified_object_info(obj1)
|
|
123
|
+
lines2: list[Text] = get_simplified_object_info(obj2)
|
|
96
124
|
|
|
97
125
|
# Determine the maximum number of lines to ensure consistent height
|
|
98
126
|
max_lines: int = max(len(lines1), len(lines2))
|
|
@@ -8,39 +8,53 @@ from __future__ import annotations
|
|
|
8
8
|
|
|
9
9
|
from collections.abc import Mapping, Sequence
|
|
10
10
|
from pathlib import Path
|
|
11
|
-
from typing import
|
|
11
|
+
from typing import TypeAlias, cast
|
|
12
12
|
|
|
13
|
-
from
|
|
13
|
+
from dacite import DaciteError, from_dict
|
|
14
14
|
from rich import print as rich_print
|
|
15
15
|
from tomlkit import parse
|
|
16
16
|
from tomlkit.exceptions import TOMLKitError
|
|
17
17
|
from typer import Exit
|
|
18
18
|
|
|
19
19
|
from ._config_models import (
|
|
20
|
+
DACITE_CONFIG,
|
|
20
21
|
DebugDojoConfig,
|
|
21
22
|
DebugDojoConfigV1,
|
|
22
23
|
DebugDojoConfigV2,
|
|
23
24
|
DebuggerType,
|
|
24
25
|
)
|
|
25
26
|
|
|
26
|
-
|
|
27
|
-
Mapping[str, "
|
|
27
|
+
JSON: TypeAlias = (
|
|
28
|
+
Mapping[str, "JSON"] | Sequence["JSON"] | str | int | float | bool | None
|
|
28
29
|
)
|
|
29
30
|
|
|
30
31
|
|
|
31
|
-
def
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
32
|
+
def _validate_model(
|
|
33
|
+
model: type[DebugDojoConfigV1 | DebugDojoConfigV2],
|
|
34
|
+
raw_config: JSON,
|
|
35
|
+
) -> DebugDojoConfigV1 | DebugDojoConfigV2:
|
|
36
|
+
if not isinstance(raw_config, dict):
|
|
37
|
+
msg = "Configuration must be a dictionary."
|
|
38
|
+
raise DaciteError(msg)
|
|
39
|
+
return from_dict(data_class=model, data=raw_config, config=DACITE_CONFIG)
|
|
38
40
|
|
|
39
41
|
|
|
40
|
-
def
|
|
42
|
+
def resolve_config_path(config_path: Path | None) -> Path | None:
|
|
41
43
|
"""Resolve the configuration path.
|
|
42
44
|
|
|
43
45
|
Returning a default if none is provided.
|
|
46
|
+
|
|
47
|
+
Args:
|
|
48
|
+
config_path (Path | None): The explicit path to the configuration file, or None.
|
|
49
|
+
|
|
50
|
+
Returns:
|
|
51
|
+
Path | None: The resolved absolute path to the configuration file, or None if no
|
|
52
|
+
configuration file is found and no explicit path was given.
|
|
53
|
+
|
|
54
|
+
Raises:
|
|
55
|
+
FileNotFoundError: If an explicit `config_path` is provided but the file
|
|
56
|
+
does not exist.
|
|
57
|
+
|
|
44
58
|
"""
|
|
45
59
|
if config_path:
|
|
46
60
|
if not config_path.exists():
|
|
@@ -57,49 +71,66 @@ def __resolve_config_path(config_path: Path | None) -> Path | None:
|
|
|
57
71
|
return None
|
|
58
72
|
|
|
59
73
|
|
|
60
|
-
def
|
|
74
|
+
def load_raw_config(config_path: Path) -> JSON:
|
|
61
75
|
"""Load the Debug Dojo configuration from a file.
|
|
62
76
|
|
|
63
77
|
Currently supports 'dojo.toml' or 'pyproject.toml'. If no path is provided, it
|
|
64
78
|
checks the current directory for these files.
|
|
79
|
+
|
|
80
|
+
Args:
|
|
81
|
+
config_path (Path): The absolute path to the configuration file.
|
|
82
|
+
|
|
83
|
+
Returns:
|
|
84
|
+
JSON: The raw configuration data as a JSON-like dictionary.
|
|
85
|
+
|
|
86
|
+
Raises:
|
|
87
|
+
ValueError: If there is an error parsing the TOML file.
|
|
88
|
+
|
|
65
89
|
"""
|
|
66
90
|
config_str = config_path.read_text(encoding="utf-8")
|
|
67
91
|
|
|
68
92
|
try:
|
|
69
93
|
config_data = parse(config_str).unwrap()
|
|
70
94
|
except TOMLKitError as e:
|
|
71
|
-
msg = f"Error parsing configuration file {config_path.resolve()}
|
|
95
|
+
msg = f"Error parsing configuration file {config_path.resolve()}.."
|
|
72
96
|
raise ValueError(msg) from e
|
|
73
97
|
|
|
98
|
+
if config_path.name != "pyproject.toml":
|
|
99
|
+
return config_data
|
|
100
|
+
|
|
74
101
|
# If config is in [tool.debug_dojo] (pyproject.toml), extract it.
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
except KeyError:
|
|
82
|
-
return {}
|
|
83
|
-
else:
|
|
84
|
-
return dojo_config
|
|
102
|
+
try:
|
|
103
|
+
dojo_config = cast("JSON", config_data["tool"]["debug_dojo"])
|
|
104
|
+
except KeyError:
|
|
105
|
+
return {}
|
|
106
|
+
else:
|
|
107
|
+
return dojo_config
|
|
85
108
|
|
|
86
|
-
return config_data
|
|
87
109
|
|
|
110
|
+
def validated_and_updated_config(raw_config: JSON, *, verbose: bool) -> DebugDojoConfig:
|
|
111
|
+
"""Validate and update the raw configuration to the latest DebugDojoConfig version.
|
|
88
112
|
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
)
|
|
92
|
-
|
|
113
|
+
Args:
|
|
114
|
+
raw_config (JSON): The raw configuration data loaded from a file.
|
|
115
|
+
verbose (bool): If True, print verbose messages during validation and update.
|
|
116
|
+
|
|
117
|
+
Returns:
|
|
118
|
+
DebugDojoConfig: A validated and updated DebugDojoConfig instance.
|
|
119
|
+
|
|
120
|
+
Raises:
|
|
121
|
+
typer.Exit: If the configuration cannot be validated against any known version.
|
|
122
|
+
|
|
123
|
+
"""
|
|
124
|
+
config: DebugDojoConfigV1 | DebugDojoConfigV2 | None = None
|
|
93
125
|
|
|
94
126
|
for model in (DebugDojoConfigV2, DebugDojoConfigV1):
|
|
95
127
|
model_name = model.__name__
|
|
96
128
|
try:
|
|
97
|
-
config = model
|
|
98
|
-
except
|
|
129
|
+
config = _validate_model(model, raw_config)
|
|
130
|
+
except (DaciteError, TypeError, ValueError) as e:
|
|
99
131
|
if verbose:
|
|
100
132
|
msg = (
|
|
101
|
-
f"[yellow]Configuration validation error for {model_name}:\n"
|
|
102
|
-
f"{__filter_pydantic_error_msg(e)}\n\n"
|
|
133
|
+
f"[yellow]Configuration validation error for {model_name}:\n{e}\n\n"
|
|
103
134
|
)
|
|
104
135
|
rich_print(msg)
|
|
105
136
|
else:
|
|
@@ -134,8 +165,18 @@ def load_config(
|
|
|
134
165
|
|
|
135
166
|
If no configuration file is found, it returns a default configuration. If a debugger
|
|
136
167
|
is specified, it overrides the config.
|
|
168
|
+
|
|
169
|
+
Args:
|
|
170
|
+
config_path (Path | None): Optional path to a configuration file.
|
|
171
|
+
verbose (bool): If True, print verbose messages during configuration loading.
|
|
172
|
+
debugger (DebuggerType | None): Optional debugger type to override the default
|
|
173
|
+
debugger specified in the configuration.
|
|
174
|
+
|
|
175
|
+
Returns:
|
|
176
|
+
DebugDojoConfig: The loaded and potentially overridden DebugDojoConfig instance.
|
|
177
|
+
|
|
137
178
|
"""
|
|
138
|
-
resolved_path =
|
|
179
|
+
resolved_path = resolve_config_path(config_path)
|
|
139
180
|
|
|
140
181
|
if verbose:
|
|
141
182
|
if resolved_path:
|
|
@@ -147,8 +188,8 @@ def load_config(
|
|
|
147
188
|
if not resolved_path:
|
|
148
189
|
return DebugDojoConfig()
|
|
149
190
|
|
|
150
|
-
raw_config =
|
|
151
|
-
config =
|
|
191
|
+
raw_config = load_raw_config(resolved_path)
|
|
192
|
+
config = validated_and_updated_config(raw_config, verbose=verbose)
|
|
152
193
|
|
|
153
194
|
# If a debugger is specified, override the config.
|
|
154
195
|
if debugger:
|