debug-dojo 0.4.0__tar.gz → 0.5.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.4.0 → debug_dojo-0.5.0}/LICENSE +2 -2
- debug_dojo-0.5.0/PKG-INFO +83 -0
- debug_dojo-0.5.0/README.md +52 -0
- debug_dojo-0.5.0/pyproject.toml +126 -0
- debug_dojo-0.5.0/setup.cfg +4 -0
- {debug_dojo-0.4.0 → debug_dojo-0.5.0}/src/debug_dojo/_cli.py +53 -17
- debug_dojo-0.4.0/src/debug_dojo/_compareres.py → debug_dojo-0.5.0/src/debug_dojo/_compare.py +7 -30
- {debug_dojo-0.4.0 → debug_dojo-0.5.0}/src/debug_dojo/_config.py +60 -39
- {debug_dojo-0.4.0 → debug_dojo-0.5.0}/src/debug_dojo/_config_models.py +47 -14
- {debug_dojo-0.4.0 → debug_dojo-0.5.0}/src/debug_dojo/_installers.py +76 -47
- debug_dojo-0.5.0/src/debug_dojo.egg-info/PKG-INFO +83 -0
- debug_dojo-0.5.0/src/debug_dojo.egg-info/SOURCES.txt +18 -0
- debug_dojo-0.5.0/src/debug_dojo.egg-info/dependency_links.txt +1 -0
- debug_dojo-0.5.0/src/debug_dojo.egg-info/entry_points.txt +2 -0
- debug_dojo-0.5.0/src/debug_dojo.egg-info/requires.txt +7 -0
- debug_dojo-0.5.0/src/debug_dojo.egg-info/top_level.txt +1 -0
- debug_dojo-0.4.0/.gitignore +0 -208
- debug_dojo-0.4.0/HISTORY.md +0 -37
- debug_dojo-0.4.0/PKG-INFO +0 -192
- debug_dojo-0.4.0/README.md +0 -120
- debug_dojo-0.4.0/pyproject.toml +0 -102
- {debug_dojo-0.4.0 → debug_dojo-0.5.0}/src/debug_dojo/__init__.py +0 -0
- {debug_dojo-0.4.0 → debug_dojo-0.5.0}/src/debug_dojo/__main__.py +0 -0
- {debug_dojo-0.4.0 → debug_dojo-0.5.0}/src/debug_dojo/install.py +0 -0
- {debug_dojo-0.4.0 → debug_dojo-0.5.0}/src/debug_dojo/py.typed +0 -0
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
The MIT License (MIT)
|
|
1
|
+
# The MIT License (MIT)
|
|
2
2
|
|
|
3
3
|
Copyright (c) 2025 to bwrob.
|
|
4
4
|
|
|
@@ -18,4 +18,4 @@ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
|
18
18
|
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
19
|
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
20
|
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
-
SOFTWARE.
|
|
21
|
+
SOFTWARE.
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: debug-dojo
|
|
3
|
+
Version: 0.5.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: Topic :: Software Development :: Debuggers
|
|
19
|
+
Classifier: Topic :: Software Development :: Libraries :: Python Modules
|
|
20
|
+
Requires-Python: <3.14,>=3.10
|
|
21
|
+
Description-Content-Type: text/markdown
|
|
22
|
+
License-File: LICENSE
|
|
23
|
+
Requires-Dist: debugpy>=1.8.0
|
|
24
|
+
Requires-Dist: ipdb>=0.13.0
|
|
25
|
+
Requires-Dist: pudb>=2020.1
|
|
26
|
+
Requires-Dist: pydantic>=2.11.7
|
|
27
|
+
Requires-Dist: rich>=12.0.0
|
|
28
|
+
Requires-Dist: tomlkit>=0.13.3
|
|
29
|
+
Requires-Dist: typer>=0.15.0
|
|
30
|
+
Dynamic: license-file
|
|
31
|
+
|
|
32
|
+
# debug dojo
|
|
33
|
+
|
|
34
|
+
<p align="center">
|
|
35
|
+
<img src="https://github.com/bwrob/debug-dojo/blob/main/docs/logo/logo_python.png?raw=true" alt="debug dojo" style="width:50%; max-width:350px;"/>
|
|
36
|
+
</p>
|
|
37
|
+
|
|
38
|
+
<p align="center">
|
|
39
|
+
<em>🏣 debug dojo, a place for zen debugging</em>
|
|
40
|
+
</p>
|
|
41
|
+
|
|
42
|
+
[](https://pypi.org/project/debug-dojo)
|
|
43
|
+
[](https://pypi.org/pypi/debug-dojo/)
|
|
44
|
+
[](https://pepy.tech/project/debug-dojo)
|
|
45
|
+
[](https://github.com/bwrob/debug-dojo/blob/main/LICENSE)
|
|
46
|
+
[](https://results.pre-commit.ci/latest/github/bwrob/debug-dojo/main)
|
|
47
|
+
|
|
48
|
+
[**debug-dojo**](https://bwrob.github.io/debug-dojo/) is a Python package providing utilities for enhanced debugging and inspection in the terminal.
|
|
49
|
+
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`.
|
|
50
|
+
|
|
51
|
+
## CLI usage
|
|
52
|
+
|
|
53
|
+
Run your Python script with debugging tools enabled using the `debug-dojo` command:
|
|
54
|
+
|
|
55
|
+
```console
|
|
56
|
+
dojo my_script.py
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
You can optionally set configuration, verbose mode, and specify the debugger type. Both script files and modules are supported:
|
|
60
|
+
|
|
61
|
+
```console
|
|
62
|
+
dojo --debugger ipdb --config dojo.toml --verbose --module my_module
|
|
63
|
+
```
|
|
64
|
+
|
|
65
|
+
## From the code
|
|
66
|
+
|
|
67
|
+
In the `PuDB` style, you can install all debugging tools and enter the debugging mode with a single command:
|
|
68
|
+
|
|
69
|
+
```python
|
|
70
|
+
object_1 = {"foo": 1, "bar": 2}
|
|
71
|
+
object_2 = [1, 2, 3]
|
|
72
|
+
|
|
73
|
+
import debug_dojo.install; b()
|
|
74
|
+
|
|
75
|
+
p(object_1) # Pretty print an object with Rich.
|
|
76
|
+
i(object_1) # Inspect an object using Rich.
|
|
77
|
+
c(object_1, object_2) # Compare two objects side-by-side.
|
|
78
|
+
|
|
79
|
+
```
|
|
80
|
+
|
|
81
|
+
## Documentation
|
|
82
|
+
|
|
83
|
+
For instructions regarding installation, configuration and usage please visit [documentation](https://bwrob.github.io/debug-dojo/).
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
# debug dojo
|
|
2
|
+
|
|
3
|
+
<p align="center">
|
|
4
|
+
<img src="https://github.com/bwrob/debug-dojo/blob/main/docs/logo/logo_python.png?raw=true" alt="debug dojo" style="width:50%; max-width:350px;"/>
|
|
5
|
+
</p>
|
|
6
|
+
|
|
7
|
+
<p align="center">
|
|
8
|
+
<em>🏣 debug dojo, a place for zen debugging</em>
|
|
9
|
+
</p>
|
|
10
|
+
|
|
11
|
+
[](https://pypi.org/project/debug-dojo)
|
|
12
|
+
[](https://pypi.org/pypi/debug-dojo/)
|
|
13
|
+
[](https://pepy.tech/project/debug-dojo)
|
|
14
|
+
[](https://github.com/bwrob/debug-dojo/blob/main/LICENSE)
|
|
15
|
+
[](https://results.pre-commit.ci/latest/github/bwrob/debug-dojo/main)
|
|
16
|
+
|
|
17
|
+
[**debug-dojo**](https://bwrob.github.io/debug-dojo/) is a Python package providing utilities for enhanced debugging and inspection in the terminal.
|
|
18
|
+
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`.
|
|
19
|
+
|
|
20
|
+
## CLI usage
|
|
21
|
+
|
|
22
|
+
Run your Python script with debugging tools enabled using the `debug-dojo` command:
|
|
23
|
+
|
|
24
|
+
```console
|
|
25
|
+
dojo my_script.py
|
|
26
|
+
```
|
|
27
|
+
|
|
28
|
+
You can optionally set configuration, verbose mode, and specify the debugger type. Both script files and modules are supported:
|
|
29
|
+
|
|
30
|
+
```console
|
|
31
|
+
dojo --debugger ipdb --config dojo.toml --verbose --module my_module
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
## From the code
|
|
35
|
+
|
|
36
|
+
In the `PuDB` style, you can install all debugging tools and enter the debugging mode with a single command:
|
|
37
|
+
|
|
38
|
+
```python
|
|
39
|
+
object_1 = {"foo": 1, "bar": 2}
|
|
40
|
+
object_2 = [1, 2, 3]
|
|
41
|
+
|
|
42
|
+
import debug_dojo.install; b()
|
|
43
|
+
|
|
44
|
+
p(object_1) # Pretty print an object with Rich.
|
|
45
|
+
i(object_1) # Inspect an object using Rich.
|
|
46
|
+
c(object_1, object_2) # Compare two objects side-by-side.
|
|
47
|
+
|
|
48
|
+
```
|
|
49
|
+
|
|
50
|
+
## Documentation
|
|
51
|
+
|
|
52
|
+
For instructions regarding installation, configuration and usage please visit [documentation](https://bwrob.github.io/debug-dojo/).
|
|
@@ -0,0 +1,126 @@
|
|
|
1
|
+
[project]
|
|
2
|
+
authors = [ { name = "bwrob", email = "bartosz.marcin.wroblewski@gmail.com" } ]
|
|
3
|
+
classifiers = [
|
|
4
|
+
"Intended Audience :: Developers",
|
|
5
|
+
"Operating System :: OS Independent",
|
|
6
|
+
"Programming Language :: Python :: 3.10",
|
|
7
|
+
"Programming Language :: Python :: 3.11",
|
|
8
|
+
"Programming Language :: Python :: 3.12",
|
|
9
|
+
"Programming Language :: Python :: 3.13",
|
|
10
|
+
"Topic :: Software Development :: Debuggers",
|
|
11
|
+
"Topic :: Software Development :: Libraries :: Python Modules",
|
|
12
|
+
]
|
|
13
|
+
dependencies = [
|
|
14
|
+
"debugpy>=1.8.0",
|
|
15
|
+
"ipdb>=0.13.0",
|
|
16
|
+
"pudb>=2020.1",
|
|
17
|
+
"pydantic>=2.11.7",
|
|
18
|
+
"rich>=12.0.0",
|
|
19
|
+
"tomlkit>=0.13.3",
|
|
20
|
+
"typer>=0.15.0",
|
|
21
|
+
]
|
|
22
|
+
description = "🏣 debug dojo, a place for zen debugging"
|
|
23
|
+
keywords = [ "debugging", "inspection", "tools", "development" ]
|
|
24
|
+
license = 'MIT'
|
|
25
|
+
license-files = [ 'LICENSE' ]
|
|
26
|
+
name = "debug-dojo"
|
|
27
|
+
readme = "README.md"
|
|
28
|
+
requires-python = ">=3.10,<3.14"
|
|
29
|
+
version = "0.5.0"
|
|
30
|
+
|
|
31
|
+
[project.urls]
|
|
32
|
+
Changelog = "https://bwrob.github.io/debug-dojo/changelog/"
|
|
33
|
+
Documentation = "https://bwrob.github.io/debug-dojo/"
|
|
34
|
+
Homepage = "https://bwrob.github.io/debug-dojo/"
|
|
35
|
+
Source = "https://github.com/bwrob/debug-dojo/"
|
|
36
|
+
|
|
37
|
+
[project.scripts]
|
|
38
|
+
"dojo" = "debug_dojo._cli:main"
|
|
39
|
+
|
|
40
|
+
|
|
41
|
+
[dependency-groups]
|
|
42
|
+
|
|
43
|
+
dev = [
|
|
44
|
+
"basedpyright>=1.31.2",
|
|
45
|
+
"coverage>=7.10.4",
|
|
46
|
+
"poethepoet>=0.37.0",
|
|
47
|
+
"pytest>=8.4.1",
|
|
48
|
+
"ruff>=0.12.9",
|
|
49
|
+
]
|
|
50
|
+
docs = [
|
|
51
|
+
"mkdocs>=1.6.1",
|
|
52
|
+
"mkdocs-git-authors-plugin>=0.10.0",
|
|
53
|
+
"mkdocs-git-committers-plugin-2>=2.5.0",
|
|
54
|
+
"mkdocs-git-revision-date-localized-plugin>=1.4.7",
|
|
55
|
+
"mkdocs-material>=9.6.17",
|
|
56
|
+
"mkdocs-typer2>=0.1.5",
|
|
57
|
+
"mkdocstrings-python>=1.17.0",
|
|
58
|
+
]
|
|
59
|
+
|
|
60
|
+
|
|
61
|
+
[tool.uv]
|
|
62
|
+
default-groups = "all"
|
|
63
|
+
package = true
|
|
64
|
+
required-version = ">=0.8.0"
|
|
65
|
+
|
|
66
|
+
|
|
67
|
+
[tool.basedpyright]
|
|
68
|
+
ignore = [ "examples", "tests/assets" ]
|
|
69
|
+
pythonVersion = "3.10"
|
|
70
|
+
strict = [ "src/debug_dojo/*" ]
|
|
71
|
+
typeCheckingMode = "all"
|
|
72
|
+
|
|
73
|
+
|
|
74
|
+
[tool.ruff]
|
|
75
|
+
line-length = 88
|
|
76
|
+
target-version = "py310"
|
|
77
|
+
|
|
78
|
+
[tool.ruff.lint]
|
|
79
|
+
exclude = [ "examples" ]
|
|
80
|
+
ignore = [ "COM", "D203", "D211", "D213" ]
|
|
81
|
+
select = [ "ALL" ]
|
|
82
|
+
|
|
83
|
+
[tool.ruff.lint.per-file-ignores]
|
|
84
|
+
"examples/*" = [ "INP001" ]
|
|
85
|
+
"examples/test_target.py" = [ "F821" ]
|
|
86
|
+
"src/debug_dojo/_installers.py" = [ "PLC0415", "T100" ]
|
|
87
|
+
"tests/*" = [ "S101", "T201" ]
|
|
88
|
+
"tests/assets/*" = [ "T201", "INP001", "F821" ]
|
|
89
|
+
|
|
90
|
+
[tool.ruff.format]
|
|
91
|
+
docstring-code-format = true
|
|
92
|
+
|
|
93
|
+
|
|
94
|
+
[tool.poe.tasks]
|
|
95
|
+
|
|
96
|
+
format = { cmd = "ruff format --diff --config=pyproject.toml", help = "Check code formatting using ruff." }
|
|
97
|
+
lint = { cmd = "uv run ruff check --config=pyproject.toml", help = "Check code rules using ruff." }
|
|
98
|
+
precommit = { cmd = "pre-commit run --all-files", help = "Run all code quality checks." }
|
|
99
|
+
test = { cmd = "pytest --verbose --doctest-modules", help = "Run tests using pytest." }
|
|
100
|
+
type-check = { cmd = "basedpyright", help = "Check static typing using basedpyright." }
|
|
101
|
+
|
|
102
|
+
[tool.poe.tasks.code-quality]
|
|
103
|
+
help = "Run all code quality checks."
|
|
104
|
+
ignore_fail = "return_non_zero"
|
|
105
|
+
sequence = [ "fix", "precommit", "format", "lint", "type-check" ]
|
|
106
|
+
|
|
107
|
+
[tool.poe.tasks.fix]
|
|
108
|
+
default_item_type = "cmd"
|
|
109
|
+
help = "Code quality fixes using ruff."
|
|
110
|
+
ignore_fail = "return_non_zero"
|
|
111
|
+
sequence = [
|
|
112
|
+
"ruff check --fix --unsafe-fixes --config=pyproject.toml",
|
|
113
|
+
"ruff format --config=pyproject.toml",
|
|
114
|
+
]
|
|
115
|
+
|
|
116
|
+
[tool.poe.tasks.publish]
|
|
117
|
+
sequence = [
|
|
118
|
+
"code-quality",
|
|
119
|
+
{ cmd = "rm -rf dist" },
|
|
120
|
+
{ cmd = "uv build" },
|
|
121
|
+
{ cmd = "uv publish" },
|
|
122
|
+
]
|
|
123
|
+
|
|
124
|
+
[tool.docformatter]
|
|
125
|
+
black = true
|
|
126
|
+
non-cap = [ "dojo" ]
|
|
@@ -4,16 +4,29 @@ from __future__ import annotations
|
|
|
4
4
|
|
|
5
5
|
import runpy
|
|
6
6
|
import sys
|
|
7
|
+
import traceback
|
|
7
8
|
from bdb import BdbQuit
|
|
9
|
+
from enum import Enum
|
|
8
10
|
from pathlib import Path
|
|
11
|
+
from shutil import which
|
|
9
12
|
from typing import Annotated
|
|
10
13
|
|
|
11
14
|
import typer
|
|
12
15
|
from rich import print as rich_print
|
|
13
16
|
|
|
14
|
-
from ._config import
|
|
17
|
+
from ._config import load_config
|
|
18
|
+
from ._config_models import DebugDojoConfig, DebuggerType # noqa: TC001
|
|
15
19
|
from ._installers import install_by_config
|
|
16
20
|
|
|
21
|
+
|
|
22
|
+
class ExecMode(Enum):
|
|
23
|
+
"""Execution mode for the target."""
|
|
24
|
+
|
|
25
|
+
FILE = "file"
|
|
26
|
+
MODULE = "module"
|
|
27
|
+
EXECUTABLE = "executable"
|
|
28
|
+
|
|
29
|
+
|
|
17
30
|
cli = typer.Typer(
|
|
18
31
|
name="debug_dojo",
|
|
19
32
|
help="Run a Python script or module with debugging tools installed.",
|
|
@@ -21,15 +34,15 @@ cli = typer.Typer(
|
|
|
21
34
|
)
|
|
22
35
|
|
|
23
36
|
|
|
24
|
-
def
|
|
37
|
+
def __execute_with_debug( # noqa: C901
|
|
25
38
|
target_name: str,
|
|
26
39
|
target_args: list[str],
|
|
27
40
|
*,
|
|
28
|
-
|
|
41
|
+
target_mode: ExecMode,
|
|
29
42
|
verbose: bool,
|
|
30
43
|
config: DebugDojoConfig,
|
|
31
44
|
) -> None:
|
|
32
|
-
"""Execute a target script or module with
|
|
45
|
+
"""Execute a target script or module with installed debugging tools."""
|
|
33
46
|
sys.argv = [target_name, *target_args]
|
|
34
47
|
|
|
35
48
|
if verbose:
|
|
@@ -38,35 +51,40 @@ def execute_with_debug( # noqa: C901
|
|
|
38
51
|
|
|
39
52
|
install_by_config(config)
|
|
40
53
|
|
|
41
|
-
if
|
|
54
|
+
if target_mode is ExecMode.MODULE:
|
|
42
55
|
runner = runpy.run_module
|
|
43
56
|
else:
|
|
57
|
+
if target_mode is ExecMode.EXECUTABLE:
|
|
58
|
+
target_name = which(target_name) or target_name
|
|
59
|
+
|
|
44
60
|
if not Path(target_name).exists():
|
|
45
|
-
|
|
61
|
+
raise typer.Exit(1)
|
|
62
|
+
|
|
46
63
|
runner = runpy.run_path
|
|
47
64
|
|
|
48
65
|
try:
|
|
49
66
|
_ = runner(target_name, run_name="__main__")
|
|
50
67
|
except ImportError as e:
|
|
51
68
|
rich_print(f"[red]Error importing {target_name}:[/red]\n{e}")
|
|
52
|
-
|
|
69
|
+
raise typer.Exit(1) from e
|
|
53
70
|
except BdbQuit:
|
|
54
71
|
rich_print("[red]Debugging session terminated by user.[/red]")
|
|
55
|
-
|
|
72
|
+
raise typer.Exit(0) from None
|
|
56
73
|
except KeyboardInterrupt:
|
|
57
74
|
rich_print("[red]Execution interrupted by user.[/red]")
|
|
58
|
-
|
|
75
|
+
raise typer.Exit(0) from None
|
|
59
76
|
except SystemExit as e:
|
|
60
77
|
if e.code:
|
|
61
78
|
rich_print(f"[red]Script exited with code {e.code}.[/red]")
|
|
62
|
-
except Exception as e:
|
|
79
|
+
except Exception as e:
|
|
63
80
|
rich_print(f"[red]Error while running {target_name}:[/red]\n{e}")
|
|
81
|
+
rich_print(traceback.format_exc())
|
|
64
82
|
if config.exceptions.post_mortem:
|
|
65
|
-
import
|
|
83
|
+
import ipdb # pyright: ignore[reportMissingTypeStubs] # noqa: PLC0415, T100
|
|
66
84
|
|
|
67
85
|
rich_print("[blue]Entering post-mortem debugging session...[/blue]")
|
|
68
|
-
|
|
69
|
-
|
|
86
|
+
ipdb.post_mortem(e.__traceback__) # pyright: ignore[reportUnknownMemberType]
|
|
87
|
+
raise typer.Exit(1) from e
|
|
70
88
|
|
|
71
89
|
|
|
72
90
|
def display_config(config: DebugDojoConfig) -> None:
|
|
@@ -95,23 +113,41 @@ def run_debug( # noqa: PLR0913
|
|
|
95
113
|
] = None,
|
|
96
114
|
verbose: Annotated[
|
|
97
115
|
bool,
|
|
98
|
-
typer.Option("--verbose", "-v",
|
|
116
|
+
typer.Option("--verbose", "-v", help="Enable verbose output"),
|
|
99
117
|
] = False,
|
|
100
118
|
module: Annotated[
|
|
101
119
|
bool,
|
|
102
|
-
typer.Option("--module", "-m",
|
|
120
|
+
typer.Option("--module", "-m", help="Run a module"),
|
|
121
|
+
] = False,
|
|
122
|
+
executable: Annotated[
|
|
123
|
+
bool,
|
|
124
|
+
typer.Option("--exec", "-e", help="Run a command"),
|
|
103
125
|
] = False,
|
|
104
126
|
) -> None:
|
|
105
127
|
"""Run the command-line interface."""
|
|
128
|
+
if module and executable:
|
|
129
|
+
rich_print(
|
|
130
|
+
"[red]Error: --module and --command options are mutually exclusive.[/red]"
|
|
131
|
+
)
|
|
132
|
+
raise typer.Exit(1)
|
|
133
|
+
|
|
134
|
+
mode = (
|
|
135
|
+
ExecMode.EXECUTABLE
|
|
136
|
+
if executable
|
|
137
|
+
else ExecMode.MODULE
|
|
138
|
+
if module
|
|
139
|
+
else ExecMode.FILE
|
|
140
|
+
)
|
|
141
|
+
|
|
106
142
|
config = load_config(config_path, verbose=verbose, debugger=debugger)
|
|
107
143
|
|
|
108
144
|
if verbose:
|
|
109
145
|
display_config(config)
|
|
110
146
|
|
|
111
147
|
if target_name:
|
|
112
|
-
|
|
148
|
+
__execute_with_debug(
|
|
113
149
|
target_name=target_name,
|
|
114
|
-
|
|
150
|
+
target_mode=mode,
|
|
115
151
|
target_args=ctx.args,
|
|
116
152
|
verbose=verbose,
|
|
117
153
|
config=config,
|
debug_dojo-0.4.0/src/debug_dojo/_compareres.py → debug_dojo-0.5.0/src/debug_dojo/_compare.py
RENAMED
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
"""Utilities for side-by-side inspection and comparison of Python objects
|
|
1
|
+
"""Utilities for side-by-side inspection and comparison of Python objects.
|
|
2
2
|
|
|
3
|
-
This module provides functions to display attributes and methods of two objects
|
|
4
|
-
|
|
3
|
+
This module provides functions to display attributes and methods of two objects in a
|
|
4
|
+
visually appealing, side-by-side format in the terminal.
|
|
5
5
|
"""
|
|
6
6
|
|
|
7
7
|
from __future__ import annotations
|
|
@@ -15,15 +15,7 @@ from rich.text import Text
|
|
|
15
15
|
|
|
16
16
|
|
|
17
17
|
def _get_object_attributes(obj: object) -> list[str]:
|
|
18
|
-
"""Extract and format non-callable attributes of an object.
|
|
19
|
-
|
|
20
|
-
Args:
|
|
21
|
-
obj: The object to inspect.
|
|
22
|
-
|
|
23
|
-
Returns:
|
|
24
|
-
A list of strings, each representing an attribute in 'name=value' format.
|
|
25
|
-
|
|
26
|
-
"""
|
|
18
|
+
"""Extract and format non-callable attributes of an object."""
|
|
27
19
|
attributes: list[str] = []
|
|
28
20
|
for attr_name in sorted(dir(obj)):
|
|
29
21
|
# Safely get attribute, returning None if it doesn't exist
|
|
@@ -37,15 +29,7 @@ def _get_object_attributes(obj: object) -> list[str]:
|
|
|
37
29
|
|
|
38
30
|
|
|
39
31
|
def _get_object_methods(obj: object) -> list[str]:
|
|
40
|
-
"""Extract and format public callable methods of an object.
|
|
41
|
-
|
|
42
|
-
Args:
|
|
43
|
-
obj: The object to inspect.
|
|
44
|
-
|
|
45
|
-
Returns:
|
|
46
|
-
A list of strings, each representing a method name.
|
|
47
|
-
|
|
48
|
-
"""
|
|
32
|
+
"""Extract and format public callable methods of an object."""
|
|
49
33
|
methods: list[str] = []
|
|
50
34
|
for method_name in sorted(dir(obj)):
|
|
51
35
|
# Safely get attribute, returning None if it doesn't exist
|
|
@@ -59,15 +43,8 @@ def _get_object_methods(obj: object) -> list[str]:
|
|
|
59
43
|
def _get_simplified_object_info(obj: object) -> list[Text]:
|
|
60
44
|
"""Generate a simplified, Rich-formatted inspection output for an object.
|
|
61
45
|
|
|
62
|
-
Handles basic Python types by displaying their value directly. For other
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
Args:
|
|
66
|
-
obj: The object to generate info for.
|
|
67
|
-
|
|
68
|
-
Returns:
|
|
69
|
-
A list of Rich Text objects, each representing a line of information.
|
|
70
|
-
|
|
46
|
+
Handles basic Python types by displaying their value directly. For other objects, it
|
|
47
|
+
lists their attributes and public methods.
|
|
71
48
|
"""
|
|
72
49
|
info_lines: list[Text] = []
|
|
73
50
|
obj_type: str = type(obj).__name__
|
|
@@ -1,19 +1,20 @@
|
|
|
1
1
|
"""Debug Dojo configuration module.
|
|
2
2
|
|
|
3
|
-
It includes configurations for different debuggers, exception handling,
|
|
4
|
-
|
|
3
|
+
It includes configurations for different debuggers, exception handling, and features
|
|
4
|
+
that can be enabled or disabled.
|
|
5
5
|
"""
|
|
6
6
|
|
|
7
7
|
from __future__ import annotations
|
|
8
8
|
|
|
9
|
-
import
|
|
9
|
+
from collections.abc import Mapping, Sequence
|
|
10
10
|
from pathlib import Path
|
|
11
|
-
from typing import Any, cast
|
|
11
|
+
from typing import Any, TypeAlias, cast
|
|
12
12
|
|
|
13
13
|
from pydantic import ValidationError
|
|
14
14
|
from rich import print as rich_print
|
|
15
15
|
from tomlkit import parse
|
|
16
16
|
from tomlkit.exceptions import TOMLKitError
|
|
17
|
+
from typer import Exit
|
|
17
18
|
|
|
18
19
|
from ._config_models import (
|
|
19
20
|
DebugDojoConfig,
|
|
@@ -22,6 +23,10 @@ from ._config_models import (
|
|
|
22
23
|
DebuggerType,
|
|
23
24
|
)
|
|
24
25
|
|
|
26
|
+
JSON_ro: TypeAlias = (
|
|
27
|
+
Mapping[str, "JSON_ro"] | Sequence["JSON_ro"] | str | int | float | bool | None
|
|
28
|
+
)
|
|
29
|
+
|
|
25
30
|
|
|
26
31
|
def __filter_pydantic_error_msg(error: ValidationError) -> str:
|
|
27
32
|
"""Filter out specific lines from a Pydantic validation error."""
|
|
@@ -32,8 +37,11 @@ def __filter_pydantic_error_msg(error: ValidationError) -> str:
|
|
|
32
37
|
)
|
|
33
38
|
|
|
34
39
|
|
|
35
|
-
def
|
|
36
|
-
"""Resolve the configuration path
|
|
40
|
+
def __resolve_config_path(config_path: Path | None) -> Path | None:
|
|
41
|
+
"""Resolve the configuration path.
|
|
42
|
+
|
|
43
|
+
Returning a default if none is provided.
|
|
44
|
+
"""
|
|
37
45
|
if config_path:
|
|
38
46
|
if not config_path.exists():
|
|
39
47
|
msg = f"Configuration file not found:\n{config_path.resolve()}"
|
|
@@ -44,16 +52,16 @@ def resolve_config_path(config_path: Path | None) -> Path | None:
|
|
|
44
52
|
for path in (Path("dojo.toml"), Path("pyproject.toml")):
|
|
45
53
|
if path.exists():
|
|
46
54
|
return path.resolve()
|
|
55
|
+
|
|
56
|
+
# None means - use default config values
|
|
47
57
|
return None
|
|
48
58
|
|
|
49
59
|
|
|
50
|
-
def
|
|
51
|
-
config_path: Path,
|
|
52
|
-
) -> dict[str, Any]: # pyright: ignore[reportExplicitAny]
|
|
60
|
+
def __load_raw_config(config_path: Path) -> JSON_ro:
|
|
53
61
|
"""Load the Debug Dojo configuration from a file.
|
|
54
62
|
|
|
55
|
-
Currently supports 'dojo.toml' or 'pyproject.toml'.
|
|
56
|
-
|
|
63
|
+
Currently supports 'dojo.toml' or 'pyproject.toml'. If no path is provided, it
|
|
64
|
+
checks the current directory for these files.
|
|
57
65
|
"""
|
|
58
66
|
config_str = config_path.read_text(encoding="utf-8")
|
|
59
67
|
|
|
@@ -66,7 +74,10 @@ def load_raw_config(
|
|
|
66
74
|
# If config is in [tool.debug_dojo] (pyproject.toml), extract it.
|
|
67
75
|
if config_path.name == "pyproject.toml":
|
|
68
76
|
try:
|
|
69
|
-
dojo_config = cast(
|
|
77
|
+
dojo_config = cast(
|
|
78
|
+
"dict[str, Any]", # pyright: ignore[reportExplicitAny]
|
|
79
|
+
config_data["tool"]["debug_dojo"],
|
|
80
|
+
)
|
|
70
81
|
except KeyError:
|
|
71
82
|
return {}
|
|
72
83
|
else:
|
|
@@ -75,28 +86,11 @@ def load_raw_config(
|
|
|
75
86
|
return config_data
|
|
76
87
|
|
|
77
88
|
|
|
78
|
-
def
|
|
79
|
-
|
|
80
|
-
*,
|
|
81
|
-
verbose: bool = False,
|
|
82
|
-
debugger: DebuggerType | None = None,
|
|
89
|
+
def __validated_and_updated_config(
|
|
90
|
+
raw_config: JSON_ro, *, verbose: bool
|
|
83
91
|
) -> 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
92
|
config = None
|
|
93
|
+
|
|
100
94
|
for model in (DebugDojoConfigV2, DebugDojoConfigV1):
|
|
101
95
|
model_name = model.__name__
|
|
102
96
|
try:
|
|
@@ -106,7 +100,6 @@ def load_config( # noqa: C901
|
|
|
106
100
|
msg = (
|
|
107
101
|
f"[yellow]Configuration validation error for {model_name}:\n"
|
|
108
102
|
f"{__filter_pydantic_error_msg(e)}\n\n"
|
|
109
|
-
f"Please check your configuration file {resolved_path}.[/yellow]"
|
|
110
103
|
)
|
|
111
104
|
rich_print(msg)
|
|
112
105
|
else:
|
|
@@ -119,17 +112,45 @@ def load_config( # noqa: C901
|
|
|
119
112
|
break
|
|
120
113
|
|
|
121
114
|
if not config:
|
|
122
|
-
msg =
|
|
123
|
-
f"[red]Unsupported configuration version in {resolved_path.resolve()}.\n"
|
|
124
|
-
"Please update your configuration file.[/red]"
|
|
125
|
-
)
|
|
115
|
+
msg = "[red]Unsupported configuration version or error.[/red]"
|
|
126
116
|
rich_print(msg)
|
|
127
|
-
|
|
117
|
+
raise Exit(code=1)
|
|
128
118
|
|
|
129
119
|
while not isinstance(config, DebugDojoConfig):
|
|
130
120
|
config = config.update()
|
|
131
121
|
|
|
132
|
-
|
|
122
|
+
return config
|
|
123
|
+
|
|
124
|
+
|
|
125
|
+
def load_config(
|
|
126
|
+
config_path: Path | None = None,
|
|
127
|
+
*,
|
|
128
|
+
verbose: bool = False,
|
|
129
|
+
debugger: DebuggerType | None = None,
|
|
130
|
+
) -> DebugDojoConfig:
|
|
131
|
+
"""Load the Debug Dojo configuration.
|
|
132
|
+
|
|
133
|
+
Return a DebugDojoConfig instance with the loaded configuration.
|
|
134
|
+
|
|
135
|
+
If no configuration file is found, it returns a default configuration. If a debugger
|
|
136
|
+
is specified, it overrides the config.
|
|
137
|
+
"""
|
|
138
|
+
resolved_path = __resolve_config_path(config_path)
|
|
139
|
+
|
|
140
|
+
if verbose:
|
|
141
|
+
if resolved_path:
|
|
142
|
+
msg = f"Using configuration file: {resolved_path}."
|
|
143
|
+
else:
|
|
144
|
+
msg = "No configuration file found, using default settings."
|
|
145
|
+
rich_print(f"[blue]{msg}[/blue]")
|
|
146
|
+
|
|
147
|
+
if not resolved_path:
|
|
148
|
+
return DebugDojoConfig()
|
|
149
|
+
|
|
150
|
+
raw_config = __load_raw_config(resolved_path)
|
|
151
|
+
config = __validated_and_updated_config(raw_config, verbose=verbose)
|
|
152
|
+
|
|
153
|
+
# If a debugger is specified, override the config.
|
|
133
154
|
if debugger:
|
|
134
155
|
config.debuggers.default = debugger
|
|
135
156
|
|