debug-dojo 0.3.2__tar.gz → 0.4.1__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.2 → debug_dojo-0.4.1}/.gitignore +2 -0
- debug_dojo-0.4.1/PKG-INFO +125 -0
- debug_dojo-0.4.1/README.md +49 -0
- {debug_dojo-0.3.2 → debug_dojo-0.4.1}/pyproject.toml +25 -31
- {debug_dojo-0.3.2 → debug_dojo-0.4.1}/src/debug_dojo/_cli.py +47 -25
- debug_dojo-0.4.1/src/debug_dojo/_config.py +136 -0
- debug_dojo-0.4.1/src/debug_dojo/_config_models.py +138 -0
- {debug_dojo-0.3.2 → debug_dojo-0.4.1}/src/debug_dojo/_installers.py +53 -15
- debug_dojo-0.3.2/HISTORY.md +0 -38
- debug_dojo-0.3.2/LICENSE +0 -21
- debug_dojo-0.3.2/PKG-INFO +0 -178
- debug_dojo-0.3.2/README.md +0 -104
- debug_dojo-0.3.2/src/debug_dojo/_config.py +0 -117
- {debug_dojo-0.3.2 → debug_dojo-0.4.1}/src/debug_dojo/__init__.py +0 -0
- {debug_dojo-0.3.2 → debug_dojo-0.4.1}/src/debug_dojo/__main__.py +0 -0
- {debug_dojo-0.3.2 → debug_dojo-0.4.1}/src/debug_dojo/_compareres.py +0 -0
- {debug_dojo-0.3.2 → debug_dojo-0.4.1}/src/debug_dojo/install.py +0 -0
- {debug_dojo-0.3.2 → debug_dojo-0.4.1}/src/debug_dojo/py.typed +0 -0
|
@@ -0,0 +1,125 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: debug-dojo
|
|
3
|
+
Version: 0.4.1
|
|
4
|
+
Summary: 🏣 Debugging dojo for Python developers
|
|
5
|
+
Project-URL: Homepage, https://bwrob.github.io/debug-dojo/
|
|
6
|
+
Project-URL: Documentation, https://bwrob.github.io/debug-dojo/
|
|
7
|
+
Project-URL: Source, https://github.com/bwrob/debug-dojo/
|
|
8
|
+
Project-URL: Changelog, https://github.com/bwrob/debug-dojo/blob/main/HISTORY.md
|
|
9
|
+
Author-email: bwrob <bartosz.marcin.wroblewski@gmail.com>
|
|
10
|
+
License-Expression: MIT
|
|
11
|
+
Keywords: debugging,inspection,pudb,rich,tools,traceback
|
|
12
|
+
Classifier: Development Status :: 3 - Alpha
|
|
13
|
+
Classifier: Intended Audience :: Developers
|
|
14
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
15
|
+
Classifier: Operating System :: OS Independent
|
|
16
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
17
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
18
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
19
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
20
|
+
Classifier: Topic :: Software Development :: Debuggers
|
|
21
|
+
Classifier: Topic :: Software Development :: Libraries :: Python Modules
|
|
22
|
+
Requires-Python: <3.14,>=3.10
|
|
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
|
+
Description-Content-Type: text/markdown
|
|
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:300px;"/>
|
|
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
|
+
|
|
45
|
+
[**debug-dojo**](https://bwrob.github.io/debug-dojo/) is a Python package providing utilities for enhanced debugging and inspection in the terminal.
|
|
46
|
+
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`.
|
|
47
|
+
|
|
48
|
+
## CLI usage
|
|
49
|
+
|
|
50
|
+
Run your Python script with debugging tools enabled using the `debug-dojo` command:
|
|
51
|
+
|
|
52
|
+
```console
|
|
53
|
+
dojo my_script.py
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
You can optionally set configuration, verbose mode, and specify the debugger type. Both script files and modules are supported:
|
|
57
|
+
|
|
58
|
+
```console
|
|
59
|
+
dojo --debugger ipdb --config dojo.toml --verbose --module my_module
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
## From the code
|
|
63
|
+
|
|
64
|
+
In the `PuDB` style, you can install all debugging tools and enter the debugging mode with a single command:
|
|
65
|
+
|
|
66
|
+
```python
|
|
67
|
+
object_1 = {"foo": 1, "bar": 2}
|
|
68
|
+
object_2 = [1, 2, 3]
|
|
69
|
+
|
|
70
|
+
import debug_dojo.install; b()
|
|
71
|
+
|
|
72
|
+
p(object_1) # Pretty print an object with Rich.
|
|
73
|
+
i(object_1) # Inspect an object using Rich.
|
|
74
|
+
c(object_1, object_2) # Compare two objects side-by-side.
|
|
75
|
+
|
|
76
|
+
```
|
|
77
|
+
|
|
78
|
+
## Documentation
|
|
79
|
+
|
|
80
|
+
For instructions regarding installation, configuration and usage please visit [documentation](https://bwrob.github.io/debug-dojo/).
|
|
81
|
+
# Changelog
|
|
82
|
+
|
|
83
|
+
## v0.4.1 (2025-08-10)
|
|
84
|
+
|
|
85
|
+
*release tag*: [v0.4.1](https://github.com/bwrob/debug-dojo/releases/tag/v0.4.1)
|
|
86
|
+
|
|
87
|
+
- Mkdocs documentation at [debug dojo](https://bwrob.github.io/debug-dojo).
|
|
88
|
+
|
|
89
|
+
## v0.4.0 (2025-08-10)
|
|
90
|
+
|
|
91
|
+
*release tag*: [v0.4.0](https://github.com/bwrob/debug-dojo/releases/tag/v0.4.0)
|
|
92
|
+
|
|
93
|
+
- New configuration model `DebugDojoConfig` for better structure.
|
|
94
|
+
- Added support for `debugger` configuration in `dojo.toml`.
|
|
95
|
+
- Updated `dojo` command to include debugger type in command call.
|
|
96
|
+
- Configuration versioning allows for in-flight migration of old configurations.
|
|
97
|
+
- Improved error handling in configuration loading.
|
|
98
|
+
- Improved catching errors from target execution.
|
|
99
|
+
|
|
100
|
+
## v0.3.2 (2025-07-28)
|
|
101
|
+
|
|
102
|
+
*release tag*: [v0.3.2](https://github.com/bwrob/debug-dojo/releases/tag/v0.3.2)
|
|
103
|
+
|
|
104
|
+
- New logo for the project.
|
|
105
|
+
- Typer used for CLI implementation.
|
|
106
|
+
- Dojo is configured via `dojo.toml` or `pyproject.toml`.
|
|
107
|
+
- Support for `debugpy` and `ipdb` for debugging.
|
|
108
|
+
- Fixed documentation and history.
|
|
109
|
+
|
|
110
|
+
## v0.2.0 (2025-07-20)
|
|
111
|
+
|
|
112
|
+
*release tag*: [v0.2.0](https://github.com/bwrob/debug-dojo/releases/tag/v0.2.0)
|
|
113
|
+
|
|
114
|
+
- Added `dojo` command for easy debugging setup.
|
|
115
|
+
- Added `p()` function for rich printing.
|
|
116
|
+
- Added history file for tracking changes.
|
|
117
|
+
- Moved to `hatch` for building and packaging.
|
|
118
|
+
- Fixed `pyproject.toml` to point to GitHub repository as the homepage.
|
|
119
|
+
|
|
120
|
+
## v0.1.0 (2025-07-19)
|
|
121
|
+
|
|
122
|
+
*release tag*: [v0.1.0](https://github.com/bwrob/debug-dojo/releases/tag/v0.1.0)
|
|
123
|
+
|
|
124
|
+
- Initial module to install debugging tools.
|
|
125
|
+
- Debug mode utilities for PuDB, rich tracebacks, and object inspection.
|
|
@@ -0,0 +1,49 @@
|
|
|
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:300px;"/>
|
|
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
|
+
|
|
14
|
+
[**debug-dojo**](https://bwrob.github.io/debug-dojo/) is a Python package providing utilities for enhanced debugging and inspection in the terminal.
|
|
15
|
+
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`.
|
|
16
|
+
|
|
17
|
+
## CLI usage
|
|
18
|
+
|
|
19
|
+
Run your Python script with debugging tools enabled using the `debug-dojo` command:
|
|
20
|
+
|
|
21
|
+
```console
|
|
22
|
+
dojo my_script.py
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
You can optionally set configuration, verbose mode, and specify the debugger type. Both script files and modules are supported:
|
|
26
|
+
|
|
27
|
+
```console
|
|
28
|
+
dojo --debugger ipdb --config dojo.toml --verbose --module my_module
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
## From the code
|
|
32
|
+
|
|
33
|
+
In the `PuDB` style, you can install all debugging tools and enter the debugging mode with a single command:
|
|
34
|
+
|
|
35
|
+
```python
|
|
36
|
+
object_1 = {"foo": 1, "bar": 2}
|
|
37
|
+
object_2 = [1, 2, 3]
|
|
38
|
+
|
|
39
|
+
import debug_dojo.install; b()
|
|
40
|
+
|
|
41
|
+
p(object_1) # Pretty print an object with Rich.
|
|
42
|
+
i(object_1) # Inspect an object using Rich.
|
|
43
|
+
c(object_1, object_2) # Compare two objects side-by-side.
|
|
44
|
+
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
## Documentation
|
|
48
|
+
|
|
49
|
+
For instructions regarding installation, configuration and usage please visit [documentation](https://bwrob.github.io/debug-dojo/).
|
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
[project]
|
|
2
2
|
name = "debug-dojo"
|
|
3
|
-
description = "
|
|
3
|
+
description = "🏣 Debugging dojo for Python developers"
|
|
4
4
|
authors = [
|
|
5
5
|
{ name = "bwrob", email = "bartosz.marcin.wroblewski@gmail.com" },
|
|
6
6
|
]
|
|
7
|
-
requires-python = ">=3.10"
|
|
7
|
+
requires-python = ">=3.10,<3.14"
|
|
8
8
|
dependencies = [
|
|
9
9
|
"debugpy>=1.8.0",
|
|
10
10
|
"ipdb>=0.13.0",
|
|
@@ -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,26 +36,33 @@
|
|
|
36
36
|
"Topic :: Software Development :: Debuggers",
|
|
37
37
|
"Topic :: Software Development :: Libraries :: Python Modules",
|
|
38
38
|
]
|
|
39
|
-
version = "0.
|
|
39
|
+
version = "0.4.1"
|
|
40
40
|
dynamic = ['readme']
|
|
41
41
|
|
|
42
42
|
[project.urls]
|
|
43
|
-
Homepage = "https://github.
|
|
44
|
-
Documentation = "https://github.
|
|
45
|
-
Source = "https://github.com/bwrob/debug-dojo/
|
|
43
|
+
Homepage = "https://bwrob.github.io/debug-dojo/"
|
|
44
|
+
Documentation = "https://bwrob.github.io/debug-dojo/"
|
|
45
|
+
Source = "https://github.com/bwrob/debug-dojo/"
|
|
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]
|
|
54
52
|
dev = [
|
|
55
|
-
"basedpyright>=1.31.
|
|
56
|
-
"
|
|
57
|
-
"
|
|
58
|
-
"ruff>=0.12.
|
|
53
|
+
"basedpyright>=1.31.2",
|
|
54
|
+
"poethepoet>=0.37.0",
|
|
55
|
+
"pytest>=8.4.1",
|
|
56
|
+
"ruff>=0.12.9",
|
|
57
|
+
]
|
|
58
|
+
docs = [
|
|
59
|
+
"mkdocs>=1.6.1",
|
|
60
|
+
"mkdocs-git-authors-plugin>=0.10.0",
|
|
61
|
+
"mkdocs-git-committers-plugin-2>=2.5.0",
|
|
62
|
+
"mkdocs-git-revision-date-localized-plugin>=1.4.7",
|
|
63
|
+
"mkdocs-material>=9.6.17",
|
|
64
|
+
"mkdocs-typer2>=0.1.5",
|
|
65
|
+
"mkdocstrings-python>=1.17.0",
|
|
59
66
|
]
|
|
60
67
|
|
|
61
68
|
[build-system]
|
|
@@ -65,6 +72,9 @@ version = "0.3.2"
|
|
|
65
72
|
]
|
|
66
73
|
build-backend = "hatchling.build"
|
|
67
74
|
|
|
75
|
+
[tool.uv]
|
|
76
|
+
required-version = ">=0.8.0"
|
|
77
|
+
|
|
68
78
|
[tool.hatch.metadata]
|
|
69
79
|
allow-direct-references = true
|
|
70
80
|
|
|
@@ -73,8 +83,7 @@ version = "0.3.2"
|
|
|
73
83
|
# construct the PyPI readme from README.md and HISTORY.md
|
|
74
84
|
fragments = [
|
|
75
85
|
{ path = 'README.md' },
|
|
76
|
-
{
|
|
77
|
-
{ path = 'HISTORY.md' },
|
|
86
|
+
{ path = './docs/changelog.md' },
|
|
78
87
|
]
|
|
79
88
|
|
|
80
89
|
|
|
@@ -86,22 +95,7 @@ version = "0.3.2"
|
|
|
86
95
|
]
|
|
87
96
|
|
|
88
97
|
[tool.basedpyright]
|
|
89
|
-
typeCheckingMode = "
|
|
98
|
+
typeCheckingMode = "basic"
|
|
90
99
|
pythonVersion = "3.10"
|
|
91
100
|
strict = ["src/debug_dojo/*"]
|
|
92
101
|
ignore = ["examples"]
|
|
93
|
-
|
|
94
|
-
[tool.poe.tasks]
|
|
95
|
-
# Define your tasks here
|
|
96
|
-
lint = "ruff check --fix src"
|
|
97
|
-
format = "ruff format src"
|
|
98
|
-
type-check = "basedpyright"
|
|
99
|
-
code-quality = ["format", "lint", "type-check"]
|
|
100
|
-
publish = [
|
|
101
|
-
"format",
|
|
102
|
-
"lint",
|
|
103
|
-
"type-check",
|
|
104
|
-
{cmd="rm -rf dist"},
|
|
105
|
-
{cmd="uv build"},
|
|
106
|
-
{cmd="uv publish"},
|
|
107
|
-
]
|
|
@@ -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
|
|
@@ -0,0 +1,138 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
from enum import Enum
|
|
4
|
+
|
|
5
|
+
from pydantic import BaseModel, ConfigDict
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
class BaseConfig(BaseModel):
|
|
9
|
+
"""Base configuration class with extra fields forbidden."""
|
|
10
|
+
|
|
11
|
+
model_config = ConfigDict(extra="forbid", validate_assignment=True)
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
class DebuggerType(Enum):
|
|
15
|
+
"""Enum for different types of debuggers."""
|
|
16
|
+
|
|
17
|
+
PDB = "pdb"
|
|
18
|
+
PUDB = "pudb"
|
|
19
|
+
IPDB = "ipdb"
|
|
20
|
+
DEBUGPY = "debugpy"
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
class Features(BaseModel):
|
|
24
|
+
"""Configuration for installing debug features."""
|
|
25
|
+
|
|
26
|
+
model_config = ConfigDict(extra="forbid") # pyright: ignore[reportUnannotatedClassAttribute]
|
|
27
|
+
|
|
28
|
+
rich_inspect: bool = True
|
|
29
|
+
"""Install rich inspect as 'i' for enhanced object inspection."""
|
|
30
|
+
rich_print: bool = True
|
|
31
|
+
"""Install rich print as 'p' for enhanced printing."""
|
|
32
|
+
rich_traceback: bool = True
|
|
33
|
+
"""Install rich traceback for better error reporting."""
|
|
34
|
+
comparer: bool = True
|
|
35
|
+
"""Install comparer as 'c' for side-by-side object comparison."""
|
|
36
|
+
breakpoint: bool = True
|
|
37
|
+
"""Install breakpoint as 'b' for setting breakpoints in code."""
|
|
38
|
+
|
|
39
|
+
|
|
40
|
+
class DebugpyConfig(BaseConfig):
|
|
41
|
+
"""Configuration for debugpy debugger."""
|
|
42
|
+
|
|
43
|
+
port: int = 1992
|
|
44
|
+
"""Port for debugpy debugger."""
|
|
45
|
+
host: str = "localhost"
|
|
46
|
+
"""Host for debugpy debugger."""
|
|
47
|
+
wait_for_client: bool = True
|
|
48
|
+
"""Whether to wait for the client to connect before starting debugging."""
|
|
49
|
+
log_to_file: bool = False
|
|
50
|
+
"""Whether to log debugpy output to a file."""
|
|
51
|
+
|
|
52
|
+
|
|
53
|
+
class IpdbConfig(BaseConfig):
|
|
54
|
+
"""Configuration for ipdb debugger."""
|
|
55
|
+
|
|
56
|
+
context_lines: int = 20
|
|
57
|
+
"""Number of context lines to show in ipdb."""
|
|
58
|
+
|
|
59
|
+
|
|
60
|
+
class DebuggersConfig(BaseConfig):
|
|
61
|
+
"""Configuration for debuggers."""
|
|
62
|
+
|
|
63
|
+
default: DebuggerType = DebuggerType.IPDB
|
|
64
|
+
"""Default debugger to use."""
|
|
65
|
+
prompt_name: str = "debug-dojo> "
|
|
66
|
+
"""Prompt name for the debugger, used in the REPL."""
|
|
67
|
+
debugpy: DebugpyConfig = DebugpyConfig()
|
|
68
|
+
"""Configuration for debugpy debugger."""
|
|
69
|
+
ipdb: IpdbConfig = IpdbConfig()
|
|
70
|
+
"""Configuration for ipdb debugger."""
|
|
71
|
+
|
|
72
|
+
|
|
73
|
+
class ExceptionsConfig(BaseConfig):
|
|
74
|
+
"""Configuration for exceptions handling."""
|
|
75
|
+
|
|
76
|
+
rich_traceback: bool = True
|
|
77
|
+
"""Enable rich traceback for better error reporting."""
|
|
78
|
+
locals_in_traceback: bool = False
|
|
79
|
+
"""Include local variables in traceback."""
|
|
80
|
+
post_mortem: bool = True
|
|
81
|
+
"""Enable post-mortem debugging after an exception."""
|
|
82
|
+
|
|
83
|
+
|
|
84
|
+
class FeaturesConfig(BaseConfig):
|
|
85
|
+
"""Configuration for installing debug features."""
|
|
86
|
+
|
|
87
|
+
rich_inspect: str = "i"
|
|
88
|
+
"""Install rich inspect as 'i' for enhanced object inspection."""
|
|
89
|
+
rich_print: str = "p"
|
|
90
|
+
"""Install rich print as 'p' for enhanced printing."""
|
|
91
|
+
comparer: str = "c"
|
|
92
|
+
"""Install comparer as 'c' for side-by-side object comparison."""
|
|
93
|
+
breakpoint: str = "b"
|
|
94
|
+
"""Install breakpoint as 'b' for setting breakpoints in code."""
|
|
95
|
+
|
|
96
|
+
|
|
97
|
+
class DebugDojoConfigV1(BaseModel):
|
|
98
|
+
"""Configuration for Debug Dojo."""
|
|
99
|
+
|
|
100
|
+
model_config = ConfigDict(extra="forbid") # pyright: ignore[reportUnannotatedClassAttribute]
|
|
101
|
+
|
|
102
|
+
debugger: DebuggerType = DebuggerType.PUDB
|
|
103
|
+
"""The type of debugger to use."""
|
|
104
|
+
features: Features = Features()
|
|
105
|
+
"""Features to install for debugging."""
|
|
106
|
+
|
|
107
|
+
def update(self) -> DebugDojoConfigV2:
|
|
108
|
+
"""Update the configuration to the latest version."""
|
|
109
|
+
v2_exceptions = ExceptionsConfig(
|
|
110
|
+
rich_traceback=self.features.rich_traceback,
|
|
111
|
+
)
|
|
112
|
+
v2_debuggers = DebuggersConfig(default=self.debugger)
|
|
113
|
+
v2_features = FeaturesConfig(
|
|
114
|
+
rich_inspect="i" if self.features.rich_inspect else "",
|
|
115
|
+
rich_print="p" if self.features.rich_print else "",
|
|
116
|
+
comparer="c" if self.features.comparer else "",
|
|
117
|
+
breakpoint="b" if self.features.breakpoint else "",
|
|
118
|
+
)
|
|
119
|
+
return DebugDojoConfigV2(
|
|
120
|
+
exceptions=v2_exceptions,
|
|
121
|
+
debuggers=v2_debuggers,
|
|
122
|
+
features=v2_features,
|
|
123
|
+
)
|
|
124
|
+
|
|
125
|
+
|
|
126
|
+
class DebugDojoConfigV2(BaseModel):
|
|
127
|
+
"""Configuration for Debug Dojo."""
|
|
128
|
+
|
|
129
|
+
model_config = ConfigDict(extra="forbid") # pyright: ignore[reportUnannotatedClassAttribute]
|
|
130
|
+
|
|
131
|
+
exceptions: ExceptionsConfig = ExceptionsConfig()
|
|
132
|
+
debuggers: DebuggersConfig = DebuggersConfig()
|
|
133
|
+
"""Default debugger and configs."""
|
|
134
|
+
features: FeaturesConfig = FeaturesConfig()
|
|
135
|
+
"""Features mnemonics ."""
|
|
136
|
+
|
|
137
|
+
|
|
138
|
+
DebugDojoConfig = DebugDojoConfigV2
|
|
@@ -14,7 +14,13 @@ import sys
|
|
|
14
14
|
from rich import print as rich_print
|
|
15
15
|
|
|
16
16
|
from ._compareres import inspect_objects_side_by_side
|
|
17
|
-
from .
|
|
17
|
+
from ._config_models import (
|
|
18
|
+
DebugDojoConfig,
|
|
19
|
+
DebuggersConfig,
|
|
20
|
+
DebuggerType,
|
|
21
|
+
ExceptionsConfig,
|
|
22
|
+
FeaturesConfig,
|
|
23
|
+
)
|
|
18
24
|
|
|
19
25
|
BREAKPOINT_ENV_VAR = "PYTHONBREAKPOINT"
|
|
20
26
|
|
|
@@ -69,11 +75,11 @@ def _use_debugpy() -> None:
|
|
|
69
75
|
debugpy.wait_for_client()
|
|
70
76
|
|
|
71
77
|
|
|
72
|
-
def _rich_traceback() -> None:
|
|
78
|
+
def _rich_traceback(*, locals_in_traceback: bool) -> None:
|
|
73
79
|
"""Check if Rich Traceback is available and set it as the default."""
|
|
74
80
|
from rich import traceback
|
|
75
81
|
|
|
76
|
-
_ = traceback.install(show_locals=
|
|
82
|
+
_ = traceback.install(show_locals=locals_in_traceback)
|
|
77
83
|
|
|
78
84
|
|
|
79
85
|
def _inspect() -> None:
|
|
@@ -90,49 +96,81 @@ def _inspect() -> None:
|
|
|
90
96
|
|
|
91
97
|
|
|
92
98
|
def _compare() -> None:
|
|
93
|
-
"""Print the object using a custom inspect function.
|
|
99
|
+
"""Print the object using a custom inspect function.
|
|
100
|
+
|
|
101
|
+
>>> _compare()
|
|
102
|
+
>>> import builtins
|
|
103
|
+
>>> callable(builtins.c)
|
|
104
|
+
True
|
|
105
|
+
|
|
106
|
+
"""
|
|
94
107
|
builtins.c = inspect_objects_side_by_side # pyright: ignore[reportAttributeAccessIssue]
|
|
95
108
|
|
|
96
109
|
|
|
97
110
|
def _breakpoint() -> None:
|
|
98
|
-
"""Install the breakpoint function.
|
|
111
|
+
"""Install the breakpoint function.
|
|
112
|
+
|
|
113
|
+
>>> _breakpoint()
|
|
114
|
+
>>> import builtins
|
|
115
|
+
>>> callable(builtins.b)
|
|
116
|
+
True
|
|
117
|
+
|
|
118
|
+
"""
|
|
99
119
|
builtins.b = breakpoint # pyright: ignore[reportAttributeAccessIssue]
|
|
100
120
|
|
|
101
121
|
|
|
102
122
|
def _rich_print() -> None:
|
|
103
|
-
"""Install the print from rich.
|
|
123
|
+
"""Install the print from rich.
|
|
124
|
+
|
|
125
|
+
>>> _rich_print()
|
|
126
|
+
>>> import builtins
|
|
127
|
+
>>> callable(builtins.p)
|
|
128
|
+
True
|
|
129
|
+
>>> p("test")
|
|
130
|
+
test
|
|
131
|
+
|
|
132
|
+
"""
|
|
104
133
|
from rich import print as rich_print
|
|
105
134
|
|
|
106
135
|
builtins.p = rich_print # pyright: ignore[reportAttributeAccessIssue]
|
|
107
136
|
|
|
108
137
|
|
|
109
|
-
def _install_features(features:
|
|
138
|
+
def _install_features(features: FeaturesConfig) -> None:
|
|
110
139
|
"""Install the specified debugging features."""
|
|
111
140
|
if features.rich_inspect:
|
|
112
141
|
_inspect()
|
|
113
142
|
if features.rich_print:
|
|
114
143
|
_rich_print()
|
|
115
|
-
if features.rich_traceback:
|
|
116
|
-
_rich_traceback()
|
|
117
144
|
if features.comparer:
|
|
118
145
|
_compare()
|
|
119
146
|
if features.breakpoint:
|
|
120
147
|
_breakpoint()
|
|
121
148
|
|
|
122
149
|
|
|
123
|
-
def _set_debugger(
|
|
150
|
+
def _set_debugger(debugger_config: DebuggersConfig) -> None:
|
|
124
151
|
"""Set the debugger based on the configuration."""
|
|
152
|
+
debugger = debugger_config.default
|
|
153
|
+
|
|
125
154
|
if debugger == DebuggerType.PDB:
|
|
126
|
-
|
|
155
|
+
_use_pdb()
|
|
127
156
|
if debugger == DebuggerType.PUDB:
|
|
128
|
-
|
|
157
|
+
_use_pudb()
|
|
129
158
|
if debugger == DebuggerType.IPDB:
|
|
130
|
-
|
|
159
|
+
_use_ipdb()
|
|
131
160
|
if debugger == DebuggerType.DEBUGPY:
|
|
132
|
-
|
|
161
|
+
_use_debugpy()
|
|
162
|
+
|
|
163
|
+
sys.ps1 = debugger_config.prompt_name
|
|
164
|
+
|
|
165
|
+
|
|
166
|
+
def _set_exceptions(exceptions: ExceptionsConfig) -> None:
|
|
167
|
+
"""Set the exception handling based on the configuration."""
|
|
168
|
+
if exceptions.rich_traceback:
|
|
169
|
+
_rich_traceback(locals_in_traceback=exceptions.locals_in_traceback)
|
|
133
170
|
|
|
134
171
|
|
|
135
172
|
def install_by_config(config: DebugDojoConfig) -> None:
|
|
136
173
|
"""Install debugging tools."""
|
|
137
|
-
_set_debugger(config.
|
|
174
|
+
_set_debugger(config.debuggers)
|
|
175
|
+
_set_exceptions(config.exceptions)
|
|
138
176
|
_install_features(config.features)
|
debug_dojo-0.3.2/HISTORY.md
DELETED
|
@@ -1,38 +0,0 @@
|
|
|
1
|
-
## v0.3.0 (2025-07-28)
|
|
2
|
-
|
|
3
|
-
*release tag*: [v0.3.2]
|
|
4
|
-
|
|
5
|
-
### What's Changed
|
|
6
|
-
|
|
7
|
-
- New logo for the project.
|
|
8
|
-
- Typer used for CLI implementation.
|
|
9
|
-
- Dojo is configured via `dojo.toml` or `pyproject.toml`.
|
|
10
|
-
- Support for `debugpy` and `ipdb` for debugging.
|
|
11
|
-
|
|
12
|
-
#### Fixes
|
|
13
|
-
|
|
14
|
-
- Fixed documentation and history.
|
|
15
|
-
|
|
16
|
-
## v0.2.0 (2025-07-20)
|
|
17
|
-
|
|
18
|
-
*release tag*: [v0.2.0]
|
|
19
|
-
|
|
20
|
-
### What's Changed
|
|
21
|
-
|
|
22
|
-
- Added `dojo` command for easy debugging setup.
|
|
23
|
-
- Added `p()` function for rich printing.
|
|
24
|
-
- Added history file for tracking changes.
|
|
25
|
-
- Moved to `hatch` for building and packaging.
|
|
26
|
-
|
|
27
|
-
#### Fixes
|
|
28
|
-
|
|
29
|
-
- Fixed `pyproject.toml` to point to GitHub repository as the homepage.
|
|
30
|
-
|
|
31
|
-
## v0.1.0 (2025-07-19)
|
|
32
|
-
|
|
33
|
-
*release tag*: [v0.1.0]
|
|
34
|
-
|
|
35
|
-
### What's Changed
|
|
36
|
-
|
|
37
|
-
- Initial module to install debugging tools.
|
|
38
|
-
- Debug mode utilities for PuDB, rich tracebacks, and object inspection.
|
debug_dojo-0.3.2/LICENSE
DELETED
|
@@ -1,21 +0,0 @@
|
|
|
1
|
-
The MIT License (MIT)
|
|
2
|
-
|
|
3
|
-
Copyright (c) 2025 to bwrob.
|
|
4
|
-
|
|
5
|
-
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
-
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
-
in the Software without restriction, including without limitation the rights
|
|
8
|
-
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
-
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
-
furnished to do so, subject to the following conditions:
|
|
11
|
-
|
|
12
|
-
The above copyright notice and this permission notice shall be included in all
|
|
13
|
-
copies or substantial portions of the Software.
|
|
14
|
-
|
|
15
|
-
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
-
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
-
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
-
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
-
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
-
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
-
SOFTWARE.
|
debug_dojo-0.3.2/PKG-INFO
DELETED
|
@@ -1,178 +0,0 @@
|
|
|
1
|
-
Metadata-Version: 2.4
|
|
2
|
-
Name: debug-dojo
|
|
3
|
-
Version: 0.3.2
|
|
4
|
-
Summary: Debbugging dojo for Python developers
|
|
5
|
-
Project-URL: Homepage, https://github.com/bwrob/debug-dojo
|
|
6
|
-
Project-URL: Documentation, https://github.com/bwrob/debug-dojo/blob/main/README.md
|
|
7
|
-
Project-URL: Source, https://github.com/bwrob/debug-dojo/tree/main/src/debug_dojo
|
|
8
|
-
Project-URL: Changelog, https://github.com/bwrob/debug-dojo/blob/main/HISTORY.md
|
|
9
|
-
Author-email: bwrob <bartosz.marcin.wroblewski@gmail.com>
|
|
10
|
-
License-Expression: MIT
|
|
11
|
-
License-File: LICENSE
|
|
12
|
-
Keywords: debugging,inspection,pudb,rich,tools,traceback
|
|
13
|
-
Classifier: Development Status :: 3 - Alpha
|
|
14
|
-
Classifier: Intended Audience :: Developers
|
|
15
|
-
Classifier: License :: OSI Approved :: MIT License
|
|
16
|
-
Classifier: Operating System :: OS Independent
|
|
17
|
-
Classifier: Programming Language :: Python :: 3.10
|
|
18
|
-
Classifier: Programming Language :: Python :: 3.11
|
|
19
|
-
Classifier: Programming Language :: Python :: 3.12
|
|
20
|
-
Classifier: Programming Language :: Python :: 3.13
|
|
21
|
-
Classifier: Topic :: Software Development :: Debuggers
|
|
22
|
-
Classifier: Topic :: Software Development :: Libraries :: Python Modules
|
|
23
|
-
Requires-Python: >=3.10
|
|
24
|
-
Requires-Dist: debugpy>=1.8.0
|
|
25
|
-
Requires-Dist: ipdb>=0.13.0
|
|
26
|
-
Requires-Dist: pudb>=2020.1
|
|
27
|
-
Requires-Dist: pydantic>=2.11.7
|
|
28
|
-
Requires-Dist: rich>=12.0.0
|
|
29
|
-
Requires-Dist: tomlkit>=0.13.3
|
|
30
|
-
Requires-Dist: typer>=0.15.0
|
|
31
|
-
Description-Content-Type: text/markdown
|
|
32
|
-
|
|
33
|
-
<p align="center">
|
|
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;"/>
|
|
35
|
-
</p>
|
|
36
|
-
|
|
37
|
-
<p align="center">
|
|
38
|
-
<em>debug dojo, a place for zen debugging</em>
|
|
39
|
-
</p>
|
|
40
|
-
|
|
41
|
-
[](https://pypi.org/project/debug-dojo)
|
|
42
|
-
[](https://pypi.org/pypi/debug-dojo/)
|
|
43
|
-
|
|
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`.
|
|
46
|
-
|
|
47
|
-
## Features
|
|
48
|
-
|
|
49
|
-
- **Convenient CLI** Quickly run your code with debugging tools enabled.
|
|
50
|
-
- **Simple API:** Install all tools or only what you need.
|
|
51
|
-
- **Debugger integration:** Quickly enable Debugpy, PuDB, PDB, or IPDB as your default debugger.
|
|
52
|
-
- **Rich tracebacks:** Get readable, colorized tracebacks for easier debugging.
|
|
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`.
|
|
55
|
-
|
|
56
|
-
## Usage
|
|
57
|
-
|
|
58
|
-
### CLI
|
|
59
|
-
|
|
60
|
-
Run your Python script with debugging tools enabled using the `debug-dojo` command:
|
|
61
|
-
|
|
62
|
-
```console
|
|
63
|
-
dojo my_script.py
|
|
64
|
-
```
|
|
65
|
-
|
|
66
|
-
You can optionally set configuration file and verbose mode:
|
|
67
|
-
|
|
68
|
-
```console
|
|
69
|
-
dojo --config dojo.toml --verbose my_script.py
|
|
70
|
-
```
|
|
71
|
-
|
|
72
|
-
### From the code
|
|
73
|
-
|
|
74
|
-
In the `PuDB` style, you can install all debugging tools and enter the debugging mode with a single command:
|
|
75
|
-
|
|
76
|
-
```python
|
|
77
|
-
import debug_dojo.install; b()
|
|
78
|
-
|
|
79
|
-
object_1 = {"foo": 1, "bar": 2}
|
|
80
|
-
object_2 = [1, 2, 3]
|
|
81
|
-
|
|
82
|
-
p(object_1) # Pretty print an object with Rich
|
|
83
|
-
i(object_1) # Inspect an object
|
|
84
|
-
c(object_1, object_2) # Compare two objects side-by-side
|
|
85
|
-
```
|
|
86
|
-
|
|
87
|
-
Where:
|
|
88
|
-
|
|
89
|
-
- `b()` is a builtin-injected function that sets a breakpoint using PuDB's `set_trace()`.
|
|
90
|
-
- `p(object_1)` is pretty printing of an object using Rich.
|
|
91
|
-
- `i(object_1)` to inspect an object using Rich.
|
|
92
|
-
- `c(object_1, object_2)` to compare two objects side-by-side.
|
|
93
|
-
|
|
94
|
-
## Configuration
|
|
95
|
-
|
|
96
|
-
You can configure the debugging tools using a `dojo.toml` or `pyproject.toml` file. The configuration allows you to specify which debugger to use, enable or disable features, and set other options.
|
|
97
|
-
|
|
98
|
-
**Example `dojo.toml`:**
|
|
99
|
-
|
|
100
|
-
```toml
|
|
101
|
-
debugger = "ipdb"
|
|
102
|
-
|
|
103
|
-
[features]
|
|
104
|
-
rich_inspect = true
|
|
105
|
-
rich_print = true
|
|
106
|
-
comparer = false
|
|
107
|
-
```
|
|
108
|
-
|
|
109
|
-
## Installation
|
|
110
|
-
|
|
111
|
-
The package is available on PyPI and can be installed using standard Python package management tools.
|
|
112
|
-
|
|
113
|
-
```console
|
|
114
|
-
pip install debug-dojo
|
|
115
|
-
```
|
|
116
|
-
|
|
117
|
-
You can also use `poetry` or `uv` to add it to your project:
|
|
118
|
-
|
|
119
|
-
```console
|
|
120
|
-
poetry add debug-dojo
|
|
121
|
-
```
|
|
122
|
-
|
|
123
|
-
```console
|
|
124
|
-
uv add debug-dojo
|
|
125
|
-
```
|
|
126
|
-
|
|
127
|
-
Note that dojo most likely will not work when installed via `pipx` or `uvx`, as it relies on the current Python environment dependencies.
|
|
128
|
-
|
|
129
|
-
## Development
|
|
130
|
-
|
|
131
|
-
### Lint and type check
|
|
132
|
-
|
|
133
|
-
```console
|
|
134
|
-
ruff check src/debug_dojo --fix
|
|
135
|
-
basedpyright src/debug_dojo
|
|
136
|
-
```
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
## Changelog
|
|
140
|
-
|
|
141
|
-
## v0.3.0 (2025-07-28)
|
|
142
|
-
|
|
143
|
-
*release tag*: [v0.3.2]
|
|
144
|
-
|
|
145
|
-
### What's Changed
|
|
146
|
-
|
|
147
|
-
- New logo for the project.
|
|
148
|
-
- Typer used for CLI implementation.
|
|
149
|
-
- Dojo is configured via `dojo.toml` or `pyproject.toml`.
|
|
150
|
-
- Support for `debugpy` and `ipdb` for debugging.
|
|
151
|
-
|
|
152
|
-
#### Fixes
|
|
153
|
-
|
|
154
|
-
- Fixed documentation and history.
|
|
155
|
-
|
|
156
|
-
## v0.2.0 (2025-07-20)
|
|
157
|
-
|
|
158
|
-
*release tag*: [v0.2.0]
|
|
159
|
-
|
|
160
|
-
### What's Changed
|
|
161
|
-
|
|
162
|
-
- Added `dojo` command for easy debugging setup.
|
|
163
|
-
- Added `p()` function for rich printing.
|
|
164
|
-
- Added history file for tracking changes.
|
|
165
|
-
- Moved to `hatch` for building and packaging.
|
|
166
|
-
|
|
167
|
-
#### Fixes
|
|
168
|
-
|
|
169
|
-
- Fixed `pyproject.toml` to point to GitHub repository as the homepage.
|
|
170
|
-
|
|
171
|
-
## v0.1.0 (2025-07-19)
|
|
172
|
-
|
|
173
|
-
*release tag*: [v0.1.0]
|
|
174
|
-
|
|
175
|
-
### What's Changed
|
|
176
|
-
|
|
177
|
-
- Initial module to install debugging tools.
|
|
178
|
-
- Debug mode utilities for PuDB, rich tracebacks, and object inspection.
|
debug_dojo-0.3.2/README.md
DELETED
|
@@ -1,104 +0,0 @@
|
|
|
1
|
-
<p align="center">
|
|
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
|
-
</p>
|
|
4
|
-
|
|
5
|
-
<p align="center">
|
|
6
|
-
<em>debug dojo, a place for zen debugging</em>
|
|
7
|
-
</p>
|
|
8
|
-
|
|
9
|
-
[](https://pypi.org/project/debug-dojo)
|
|
10
|
-
[](https://pypi.org/pypi/debug-dojo/)
|
|
11
|
-
|
|
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`.
|
|
14
|
-
|
|
15
|
-
## Features
|
|
16
|
-
|
|
17
|
-
- **Convenient CLI** Quickly run your code with debugging tools enabled.
|
|
18
|
-
- **Simple API:** Install all tools or only what you need.
|
|
19
|
-
- **Debugger integration:** Quickly enable Debugpy, PuDB, PDB, or IPDB as your default debugger.
|
|
20
|
-
- **Rich tracebacks:** Get readable, colorized tracebacks for easier debugging.
|
|
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`.
|
|
23
|
-
|
|
24
|
-
## Usage
|
|
25
|
-
|
|
26
|
-
### CLI
|
|
27
|
-
|
|
28
|
-
Run your Python script with debugging tools enabled using the `debug-dojo` command:
|
|
29
|
-
|
|
30
|
-
```console
|
|
31
|
-
dojo my_script.py
|
|
32
|
-
```
|
|
33
|
-
|
|
34
|
-
You can optionally set configuration file and verbose mode:
|
|
35
|
-
|
|
36
|
-
```console
|
|
37
|
-
dojo --config dojo.toml --verbose my_script.py
|
|
38
|
-
```
|
|
39
|
-
|
|
40
|
-
### From the code
|
|
41
|
-
|
|
42
|
-
In the `PuDB` style, you can install all debugging tools and enter the debugging mode with a single command:
|
|
43
|
-
|
|
44
|
-
```python
|
|
45
|
-
import debug_dojo.install; b()
|
|
46
|
-
|
|
47
|
-
object_1 = {"foo": 1, "bar": 2}
|
|
48
|
-
object_2 = [1, 2, 3]
|
|
49
|
-
|
|
50
|
-
p(object_1) # Pretty print an object with Rich
|
|
51
|
-
i(object_1) # Inspect an object
|
|
52
|
-
c(object_1, object_2) # Compare two objects side-by-side
|
|
53
|
-
```
|
|
54
|
-
|
|
55
|
-
Where:
|
|
56
|
-
|
|
57
|
-
- `b()` is a builtin-injected function that sets a breakpoint using PuDB's `set_trace()`.
|
|
58
|
-
- `p(object_1)` is pretty printing of an object using Rich.
|
|
59
|
-
- `i(object_1)` to inspect an object using Rich.
|
|
60
|
-
- `c(object_1, object_2)` to compare two objects side-by-side.
|
|
61
|
-
|
|
62
|
-
## Configuration
|
|
63
|
-
|
|
64
|
-
You can configure the debugging tools using a `dojo.toml` or `pyproject.toml` file. The configuration allows you to specify which debugger to use, enable or disable features, and set other options.
|
|
65
|
-
|
|
66
|
-
**Example `dojo.toml`:**
|
|
67
|
-
|
|
68
|
-
```toml
|
|
69
|
-
debugger = "ipdb"
|
|
70
|
-
|
|
71
|
-
[features]
|
|
72
|
-
rich_inspect = true
|
|
73
|
-
rich_print = true
|
|
74
|
-
comparer = false
|
|
75
|
-
```
|
|
76
|
-
|
|
77
|
-
## Installation
|
|
78
|
-
|
|
79
|
-
The package is available on PyPI and can be installed using standard Python package management tools.
|
|
80
|
-
|
|
81
|
-
```console
|
|
82
|
-
pip install debug-dojo
|
|
83
|
-
```
|
|
84
|
-
|
|
85
|
-
You can also use `poetry` or `uv` to add it to your project:
|
|
86
|
-
|
|
87
|
-
```console
|
|
88
|
-
poetry add debug-dojo
|
|
89
|
-
```
|
|
90
|
-
|
|
91
|
-
```console
|
|
92
|
-
uv add debug-dojo
|
|
93
|
-
```
|
|
94
|
-
|
|
95
|
-
Note that dojo most likely will not work when installed via `pipx` or `uvx`, as it relies on the current Python environment dependencies.
|
|
96
|
-
|
|
97
|
-
## Development
|
|
98
|
-
|
|
99
|
-
### Lint and type check
|
|
100
|
-
|
|
101
|
-
```console
|
|
102
|
-
ruff check src/debug_dojo --fix
|
|
103
|
-
basedpyright src/debug_dojo
|
|
104
|
-
```
|
|
@@ -1,117 +0,0 @@
|
|
|
1
|
-
from __future__ import annotations
|
|
2
|
-
|
|
3
|
-
from enum import Enum
|
|
4
|
-
from pathlib import Path
|
|
5
|
-
from typing import Any, cast
|
|
6
|
-
|
|
7
|
-
import tomlkit
|
|
8
|
-
from pydantic import BaseModel, ConfigDict
|
|
9
|
-
from rich import print as rich_print
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
class DebuggerType(Enum):
|
|
13
|
-
"""Enum for different types of debuggers."""
|
|
14
|
-
|
|
15
|
-
PDB = "pdb"
|
|
16
|
-
PUDB = "pudb"
|
|
17
|
-
IPDB = "ipdb"
|
|
18
|
-
DEBUGPY = "debugpy"
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
class Features(BaseModel):
|
|
22
|
-
"""Configuration for installing debug features."""
|
|
23
|
-
|
|
24
|
-
model_config = ConfigDict(extra="forbid") # pyright: ignore[reportUnannotatedClassAttribute]
|
|
25
|
-
|
|
26
|
-
rich_inspect: bool = True
|
|
27
|
-
"""Install rich inspect as 'i' for enhanced object inspection."""
|
|
28
|
-
rich_print: bool = True
|
|
29
|
-
"""Install rich print as 'p' for enhanced printing."""
|
|
30
|
-
rich_traceback: bool = True
|
|
31
|
-
"""Install rich traceback for better error reporting."""
|
|
32
|
-
comparer: bool = True
|
|
33
|
-
"""Install comparer as 'c' for side-by-side object comparison."""
|
|
34
|
-
breakpoint: bool = True
|
|
35
|
-
"""Install breakpoint as 'b' for setting breakpoints in code."""
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
class DebugDojoConfig(BaseModel):
|
|
39
|
-
"""Configuration for Debug Dojo."""
|
|
40
|
-
|
|
41
|
-
model_config = ConfigDict(extra="forbid") # pyright: ignore[reportUnannotatedClassAttribute]
|
|
42
|
-
|
|
43
|
-
debugger: DebuggerType = DebuggerType.PUDB
|
|
44
|
-
"""The type of debugger to use."""
|
|
45
|
-
features: Features = Features()
|
|
46
|
-
"""Features to install for debugging."""
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
def resolve_config_path(config_path: Path | None) -> Path | None:
|
|
50
|
-
"""Resolve the configuration path, returning a default if none is provided."""
|
|
51
|
-
if config_path:
|
|
52
|
-
if not config_path.exists():
|
|
53
|
-
msg = f"Configuration file not found:\n{config_path.resolve()}"
|
|
54
|
-
raise FileNotFoundError(msg)
|
|
55
|
-
return config_path
|
|
56
|
-
|
|
57
|
-
# Default configuration path
|
|
58
|
-
for path in (Path("dojo.toml"), Path("pyproject.toml")):
|
|
59
|
-
if path.exists():
|
|
60
|
-
return path
|
|
61
|
-
return None
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
def load_raw_config(
|
|
65
|
-
config_path: Path,
|
|
66
|
-
) -> dict[str, Any]: # pyright: ignore[reportExplicitAny]
|
|
67
|
-
"""Load the Debug Dojo configuration from a file.
|
|
68
|
-
|
|
69
|
-
Currently supports 'dojo.toml' or 'pyproject.toml'.
|
|
70
|
-
If no path is provided, it checks the current directory for these files.
|
|
71
|
-
"""
|
|
72
|
-
with config_path.open("rb") as f:
|
|
73
|
-
config_data = tomlkit.load(f).unwrap()
|
|
74
|
-
|
|
75
|
-
# If config is in [tool.debug_dojo] (pyproject.toml), extract it.
|
|
76
|
-
if config_path.name == "dojo.toml":
|
|
77
|
-
return config_data
|
|
78
|
-
|
|
79
|
-
if config_path.name == "pyproject.toml":
|
|
80
|
-
try:
|
|
81
|
-
dojo_config = cast(
|
|
82
|
-
"dict[str, Any]", # pyright: ignore[reportExplicitAny]
|
|
83
|
-
config_data["tool"]["debug_dojo"],
|
|
84
|
-
)
|
|
85
|
-
except KeyError:
|
|
86
|
-
return {}
|
|
87
|
-
else:
|
|
88
|
-
return dojo_config
|
|
89
|
-
|
|
90
|
-
# If the file is not recognized, raise an error.
|
|
91
|
-
msg = (
|
|
92
|
-
f"Unsupported configuration file: \n{config_path.resolve()}\n"
|
|
93
|
-
"Expected 'dojo.toml' or 'pyproject.toml'."
|
|
94
|
-
)
|
|
95
|
-
raise ValueError(msg)
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
def load_config(
|
|
99
|
-
config_path: Path | None = None,
|
|
100
|
-
*,
|
|
101
|
-
verbose: bool = False,
|
|
102
|
-
) -> DebugDojoConfig:
|
|
103
|
-
"""Load the Debug Dojo configuration and return a DebugDojoConfig instance."""
|
|
104
|
-
resolved_path = resolve_config_path(config_path)
|
|
105
|
-
|
|
106
|
-
if verbose:
|
|
107
|
-
if resolved_path:
|
|
108
|
-
msg = f"Using configuration file: {resolved_path.resolve()}."
|
|
109
|
-
else:
|
|
110
|
-
msg = "No configuration file found, using default settings."
|
|
111
|
-
rich_print(f"[blue]{msg}[/blue]")
|
|
112
|
-
|
|
113
|
-
if not resolved_path:
|
|
114
|
-
return DebugDojoConfig()
|
|
115
|
-
|
|
116
|
-
raw_config = load_raw_config(resolved_path)
|
|
117
|
-
return DebugDojoConfig.model_validate(raw_config)
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|