Skip to content

API Reference

Debugging tools for Python.

This module provides functions to set up debugging tools like PuDB and Rich Traceback. It checks for the availability of these tools and configures them accordingly.

Importing this module will install the debugging tools based on the configuration. Example usage:

1
2
3
import debug_dojo.install

b()

This will install the debugging tools and put debug breakpoint at this line.

Another way to use this module is to run the desired script or module with the dojo command-line interface.

$ dojo --verbose --config dojo.toml target_script.py --arg_1_for_script value1

Dependency Graph


```mermaid graph TD src.debug_dojo._installers –> src.debug_dojo._compare src.debug_dojo._installers –> src.debug_dojo._config_models src.debug_dojo._cli –> src.debug_dojo._installers src.debug_dojo._cli –> src.debug_dojo._config src.debug_dojo._cli –> src.debug_dojo._config_models src.debug_dojo._config –> src.debug_dojo._config_models src.debug_dojo.install –> src.debug_dojo._config src.debug_dojo.install –> src.debug_dojo._installers src.debug_dojo._config_models src.debug_dojo._compare

```


Module for installing and configuring various debugging tools and features.

This module provides functions to set up different debuggers (PDB, PuDB, IPDB, Debugpy) and to install enhanced debugging features like Rich Traceback, Rich Inspect, Rich Print, and a side-by-side object comparer. These installations are typically driven by the DebugDojoConfig.

install_breakpoint(mnemonic='b')

Inject thebreakpoint() function into builtins under the given mnemonic.

Parameters:

Name Type Description Default
mnemonic str

The name to use for the breakpoint function in builtins. If an empty string, the feature is not installed.

'b'

install_breakpoint() import builtins callable(builtins.b) True

Source code in src/debug_dojo/_installers.py
def install_breakpoint(mnemonic: str = "b") -> None:
    """Inject the`breakpoint()` function into builtins under the given mnemonic.

    Args:
        mnemonic (str): The name to use for the breakpoint function in builtins.
                        If an empty string, the feature is not installed.

    >>> install_breakpoint()
    >>> import builtins
    >>> callable(builtins.b)
    True

    """
    if not mnemonic:
        return

    builtins.__dict__[mnemonic] = breakpoint

install_by_config(config)

Installs all debugging tools and features based on the given configuration.

This is the main entry point for applying debug-dojo settings.

Parameters:

Name Type Description Default
config DebugDojoConfig

The complete debug-dojo configuration object.

required
Source code in src/debug_dojo/_installers.py
def install_by_config(config: DebugDojoConfig) -> None:
    """Installs all debugging tools and features based on the given configuration.

    This is the main entry point for applying `debug-dojo` settings.

    Args:
        config (DebugDojoConfig): The complete debug-dojo configuration object.

    """
    set_debugger(config.debuggers)
    set_exceptions(config.exceptions)
    install_features(config.features)

install_compare(mnemonic='c')

Injects the side-by-side object comparison function into builtins.

Parameters:

Name Type Description Default
mnemonic str

The name to use for the compare function in builtins. If an empty string, the feature is not installed.

'c'

install_compare() import builtins callable(builtins.c) True

Source code in src/debug_dojo/_installers.py
def install_compare(mnemonic: str = "c") -> None:
    """Injects the side-by-side object comparison function into builtins.

    Args:
        mnemonic (str): The name to use for the compare function in builtins.
                        If an empty string, the feature is not installed.

    >>> install_compare()
    >>> import builtins
    >>> callable(builtins.c)
    True

    """
    if not mnemonic:
        return

    builtins.__dict__[mnemonic] = inspect_objects_side_by_side

install_features(features)

Installs debugging features based on the provided configuration.

Parameters:

Name Type Description Default
features FeaturesConfig

Configuration object specifying which features to install and their mnemonics.

required
Source code in src/debug_dojo/_installers.py
def install_features(features: FeaturesConfig) -> None:
    """Installs debugging features based on the provided configuration.

    Args:
        features (FeaturesConfig): Configuration object specifying which features
                                   to install and their mnemonics.

    """
    install_inspect(features.rich_inspect)
    install_rich_print(features.rich_print)
    install_compare(features.comparer)
    install_breakpoint(features.breakpoint)

install_inspect(mnemonic='i')

Injects rich.inspect into builtins under the given mnemonic.

Parameters:

Name Type Description Default
mnemonic str

The name to use for the inspect function in builtins. If an empty string, the feature is not installed.

'i'
Source code in src/debug_dojo/_installers.py
def install_inspect(mnemonic: str = "i") -> None:
    """Injects `rich.inspect` into builtins under the given mnemonic.

    Args:
        mnemonic (str): The name to use for the inspect function in builtins.
                        If an empty string, the feature is not installed.

    """
    if not mnemonic:
        return

    from rich import inspect

    def inspect_with_defaults(obj: object, **kwargs: bool) -> None:
        """Inspect an object using Rich's inspect function."""
        if not kwargs:
            kwargs = {"methods": True, "private": True}
        return inspect(obj, console=None, title="", **kwargs)

    builtins.__dict__[mnemonic] = inspect_with_defaults

install_rich_print(mnemonic='p')

Injects rich.print into builtins under the given mnemonic.

Parameters:

Name Type Description Default
mnemonic str

The name to use for the print function in builtins. If an empty string, the feature is not installed.

'p'

install_rich_print() import builtins callable(builtins.p) True p(“test”) test

Source code in src/debug_dojo/_installers.py
def install_rich_print(mnemonic: str = "p") -> None:
    """Injects `rich.print` into builtins under the given mnemonic.

    Args:
        mnemonic (str): The name to use for the print function in builtins.
                        If an empty string, the feature is not installed.

    >>> install_rich_print()
    >>> import builtins
    >>> callable(builtins.p)
    True
    >>> p("test")
    test

    """
    if not mnemonic:
        return

    from rich import print as rich_print

    builtins.__dict__[mnemonic] = rich_print

rich_traceback(*, locals_in_traceback)

Install Rich Traceback for enhanced error reporting.

Parameters:

Name Type Description Default
locals_in_traceback bool

Whether to include local variables in the traceback.

required
Source code in src/debug_dojo/_installers.py
def rich_traceback(*, locals_in_traceback: bool) -> None:
    """Install Rich Traceback for enhanced error reporting.

    Args:
        locals_in_traceback (bool): Whether to include local variables in the traceback.

    """
    from rich import traceback

    _ = traceback.install(show_locals=locals_in_traceback)

set_debugger(config)

Set the default debugger based on the provided configuration.

Parameters:

Name Type Description Default
config DebuggersConfig

Configuration object for debuggers.

required
Source code in src/debug_dojo/_installers.py
def set_debugger(config: DebuggersConfig) -> None:
    """Set the default debugger based on the provided configuration.

    Args:
        config (DebuggersConfig): Configuration object for debuggers.

    """
    debugger = config.default

    if debugger == DebuggerType.PDB:
        use_pdb(config.pdb)
    if debugger == DebuggerType.PUDB:
        use_pudb(config.pudb)
    if debugger == DebuggerType.IPDB:
        use_ipdb(config.ipdb)
    if debugger == DebuggerType.DEBUGPY:
        use_debugpy(config.debugpy)

    sys.ps1 = config.prompt_name

set_exceptions(exceptions)

Configure exception handling based on the provided configuration.

Parameters:

Name Type Description Default
exceptions ExceptionsConfig

Configuration object for exception handling.

required
Source code in src/debug_dojo/_installers.py
def set_exceptions(exceptions: ExceptionsConfig) -> None:
    """Configure exception handling based on the provided configuration.

    Args:
        exceptions (ExceptionsConfig): Configuration object for exception handling.

    """
    if exceptions.rich_traceback:
        rich_traceback(locals_in_traceback=exceptions.locals_in_traceback)

use_debugpy(config)

Set Debugpy as the default debugger.

Configures sys.breakpointhook to use debugpy.breakpoint, sets the PYTHONBREAKPOINT environment variable, and starts a debugpy server waiting for a client connection.

Parameters:

Name Type Description Default
config DebugpyConfig

Configuration for debugpy.

required
Source code in src/debug_dojo/_installers.py
def use_debugpy(config: DebugpyConfig) -> None:
    """Set Debugpy as the default debugger.

    Configures `sys.breakpointhook` to use `debugpy.breakpoint`, sets the
    `PYTHONBREAKPOINT` environment variable, and starts a debugpy server
    waiting for a client connection.

    Args:
        config (DebugpyConfig): Configuration for debugpy.

    """
    try:
        import debugpy
    except ImportError:
        rich_print(_NOT_INSTALLED.format(name="Debugpy"))
        return

    os.environ[BREAKPOINT_ENV_VAR] = config.set_trace_hook
    sys.breakpointhook = debugpy.breakpoint

    launch_config = {
        "name": "debug-dojo",
        "type": "debugpy",
        "request": "attach",
        "connect": {
            "host": config.host,
            "port": config.port,
        },
    }
    rich_print(f"[blue]Connect your VSC debugger to port {config.port}.[/blue]")
    rich_print("[blue]Configuration:[/blue]")
    rich_print(json.dumps(launch_config, indent=4))

    _ = debugpy.listen((config.host, config.port))
    debugpy.wait_for_client()

use_ipdb(config)

Set IPDB as the default debugger.

Configures sys.breakpointhook to use ipdb.set_trace, sets the PYTHONBREAKPOINT environment variable, and configures IPDB_CONTEXT_SIZE.

Parameters:

Name Type Description Default
config IpdbConfig

Configuration for IPDB.

required
Source code in src/debug_dojo/_installers.py
def use_ipdb(config: IpdbConfig) -> None:
    """Set IPDB as the default debugger.

    Configures `sys.breakpointhook` to use `ipdb.set_trace`, sets the
    `PYTHONBREAKPOINT` environment variable, and configures `IPDB_CONTEXT_SIZE`.

    Args:
        config (IpdbConfig): Configuration for IPDB.

    """
    try:
        import ipdb  # pyright: ignore[reportMissingTypeStubs]
    except ImportError:
        rich_print(_NOT_INSTALLED.format(name="IPDB"))
        return

    os.environ[BREAKPOINT_ENV_VAR] = config.set_trace_hook
    os.environ[IPDB_CONTEXT_SIZE] = str(config.context_lines)
    sys.breakpointhook = cast("Any", ipdb.set_trace)  # pyright: ignore[reportExplicitAny]

use_pdb(config)

Set PDB as the default debugger.

Configures sys.breakpointhook to use pdb.set_trace and sets the PYTHONBREAKPOINT environment variable.

Parameters:

Name Type Description Default
config PdbConfig

Configuration for PDB.

required
Source code in src/debug_dojo/_installers.py
def use_pdb(config: PdbConfig) -> None:
    """Set PDB as the default debugger.

    Configures `sys.breakpointhook` to use `pdb.set_trace` and sets the
    `PYTHONBREAKPOINT` environment variable.

    Args:
        config (PdbConfig): Configuration for PDB.

    """
    import pdb

    os.environ[BREAKPOINT_ENV_VAR] = config.set_trace_hook
    sys.breakpointhook = cast("Any", pdb.set_trace)  # pyright: ignore[reportExplicitAny]

use_pudb(config)

Set PuDB as the default debugger.

Configures sys.breakpointhook to use pudb.set_trace and sets the PYTHONBREAKPOINT environment variable.

Parameters:

Name Type Description Default
config PudbConfig

Configuration for PuDB.

required
Source code in src/debug_dojo/_installers.py
def use_pudb(config: PudbConfig) -> None:
    """Set PuDB as the default debugger.

    Configures `sys.breakpointhook` to use `pudb.set_trace` and sets the
    `PYTHONBREAKPOINT` environment variable.

    Args:
        config (PudbConfig): Configuration for PuDB.

    """
    try:
        import pudb  # pyright: ignore[reportMissingTypeStubs]
    except ImportError:
        rich_print(_NOT_INSTALLED.format(name="PuDB"))
        return

    os.environ[BREAKPOINT_ENV_VAR] = config.set_trace_hook
    sys.breakpointhook = cast("Any", pudb.set_trace)  # pyright: ignore[reportExplicitAny]

Utilities for side-by-side inspection and comparison of Python objects.

This module provides functions to display attributes and methods of two objects in a visually appealing, side-by-side format in the terminal.

get_object_attributes(obj)

Extract and format non-callable attributes of an object.

Parameters:

Name Type Description Default
obj object

The object to extract attributes from.

required

Returns:

Type Description
list[str]

list[str]: A list of formatted strings, each representing an attribute.

Source code in src/debug_dojo/_compare.py
def get_object_attributes(obj: object) -> list[str]:
    """Extract and format non-callable attributes of an object.

    Args:
        obj (object): The object to extract attributes from.

    Returns:
        list[str]: A list of formatted strings, each representing an attribute.

    """
    return _get_members(
        obj,
        lambda n, v: not n.startswith("__") and not callable(v),  # pyright: ignore[reportAny]
        lambda n, v: f"{n}={v!r}",  # pyright: ignore[reportAny]
    )

get_object_methods(obj)

Extract and format public callable methods of an object.

Parameters:

Name Type Description Default
obj object

The object to extract methods from.

required

Returns:

Type Description
list[str]

list[str]: A list of method names.

Source code in src/debug_dojo/_compare.py
def get_object_methods(obj: object) -> list[str]:
    """Extract and format public callable methods of an object.

    Args:
        obj (object): The object to extract methods from.

    Returns:
        list[str]: A list of method names.

    """
    return _get_members(
        obj,
        lambda n, v: not n.startswith("_") and callable(v),  # pyright: ignore[reportAny]
        lambda n, _v: n,  # pyright: ignore[reportAny]
    )

get_simplified_object_info(obj)

Generate a simplified, Rich-formatted inspection output for an object.

Handles basic Python types by displaying their value directly. For other objects, it lists their attributes and public methods.

Parameters:

Name Type Description Default
obj object

The object to generate info for.

required

Returns:

Type Description
list[Text]

list[Text]: A list of Rich Text objects representing the object’s information.

Source code in src/debug_dojo/_compare.py
def get_simplified_object_info(obj: object) -> list[Text]:
    """Generate a simplified, Rich-formatted inspection output for an object.

    Handles basic Python types by displaying their value directly. For other objects, it
    lists their attributes and public methods.

    Args:
        obj (object): The object to generate info for.

    Returns:
        list[Text]: A list of Rich Text objects representing the object's information.

    """
    info_lines: list[Text] = []
    obj_type: str = type(obj).__name__
    info_lines.append(Text(f"<class '{obj_type}'>", style="cyan bold"))
    info_lines.append(Text(""))

    if _is_basic_type(obj):
        info_lines.extend(_get_basic_info(obj))
        return info_lines

    info_lines.extend(_get_attributes_section(obj))
    info_lines.extend(_get_methods_section(obj))

    return info_lines

inspect_objects_side_by_side(obj1, obj2)

Display two Python objects side-by-side in the terminal using Rich.

Showing their attributes and methods in a simplified, aligned format.

Parameters:

Name Type Description Default
obj1 object

The first object to display.

required
obj2 object

The second object to display.

required
Source code in src/debug_dojo/_compare.py
def inspect_objects_side_by_side(
    obj1: object,
    obj2: object,
) -> None:
    """Display two Python objects side-by-side in the terminal using Rich.

    Showing their attributes and methods in a simplified, aligned format.

    Args:
        obj1 (object): The first object to display.
        obj2 (object): The second object to display.

    """
    main_console: Console = Console()

    # Get info for both objects
    lines1: list[Text] = get_simplified_object_info(obj1)
    lines2: list[Text] = get_simplified_object_info(obj2)

    # Convert list of Text to a single Renderable for Panel
    inspect_text1: Text = Text("\n").join(lines1)
    inspect_text2: Text = Text("\n").join(lines2)

    # Create Panels for each object's info
    panel1: Panel = Panel(inspect_text1, border_style="green", expand=True)
    panel2: Panel = Panel(inspect_text2, border_style="green", expand=True)

    # Use a Table to display panels side-by-side
    table = Table(show_header=False, show_lines=False, expand=True)
    table.add_column(width=main_console.width // 2 - 1)
    table.add_column(width=main_console.width // 2 - 1)
    table.add_row(panel1, panel2)

    main_console.print(table)

Debug Dojo configuration module.

It includes configurations for different debuggers, exception handling, and features that can be enabled or disabled.

load_config(config_path=None, *, verbose=False, debugger=None)

Load the Debug Dojo configuration.

Return a DebugDojoConfig instance with the loaded configuration.

If no configuration file is found, it returns a default configuration. If a debugger is specified, it overrides the config.

Parameters:

Name Type Description Default
config_path Path | None

Optional path to a configuration file.

None
verbose bool

If True, print verbose messages during configuration loading.

False
debugger DebuggerType | None

Optional debugger type to override the default debugger specified in the configuration.

None

Returns:

Name Type Description
DebugDojoConfig DebugDojoConfig

The loaded and potentially overridden DebugDojoConfig instance.

Source code in src/debug_dojo/_config.py
def load_config(
    config_path: Path | None = None,
    *,
    verbose: bool = False,
    debugger: DebuggerType | None = None,
) -> DebugDojoConfig:
    """Load the Debug Dojo configuration.

    Return a DebugDojoConfig instance with the loaded configuration.

    If no configuration file is found, it returns a default configuration. If a debugger
    is specified, it overrides the config.

    Args:
        config_path (Path | None): Optional path to a configuration file.
        verbose (bool): If True, print verbose messages during configuration loading.
        debugger (DebuggerType | None): Optional debugger type to override the default
                                        debugger specified in the configuration.

    Returns:
        DebugDojoConfig: The loaded and potentially overridden DebugDojoConfig instance.

    """
    resolved_path = resolve_config_path(config_path)

    if verbose:
        if resolved_path:
            msg = f"Using configuration file: {resolved_path}."
        else:
            msg = "No configuration file found, using default settings."
        rich_print(f"[blue]{msg}[/blue]")

    if not resolved_path:
        return DebugDojoConfig()

    raw_config = load_raw_config(resolved_path)
    config = validated_and_updated_config(raw_config, verbose=verbose)

    # If a debugger is specified, override the config.
    if debugger:
        config.debuggers.default = debugger

    return config

load_raw_config(config_path)

Load the Debug Dojo configuration from a file.

Currently supports ‘dojo.toml’ or ‘pyproject.toml’. If no path is provided, it checks the current directory for these files.

Parameters:

Name Type Description Default
config_path Path

The absolute path to the configuration file.

required

Returns:

Name Type Description
JSON JSON

The raw configuration data as a JSON-like dictionary.

Raises:

Type Description
ValueError

If there is an error parsing the TOML file.

Source code in src/debug_dojo/_config.py
def load_raw_config(config_path: Path) -> JSON:
    """Load the Debug Dojo configuration from a file.

    Currently supports 'dojo.toml' or 'pyproject.toml'. If no path is provided, it
    checks the current directory for these files.

    Args:
        config_path (Path): The absolute path to the configuration file.

    Returns:
        JSON: The raw configuration data as a JSON-like dictionary.

    Raises:
        ValueError: If there is an error parsing the TOML file.

    """
    config_str = config_path.read_text(encoding="utf-8")

    try:
        config_data = parse(config_str).unwrap()
    except TOMLKitError as e:
        msg = f"Error parsing configuration file {config_path.resolve()}.."
        raise ValueError(msg) from e

    if config_path.name != "pyproject.toml":
        return config_data

    # If config is in [tool.debug_dojo] (pyproject.toml), extract it.
    try:
        dojo_config = cast("JSON", config_data["tool"]["debug_dojo"])
    except KeyError:
        return {}
    else:
        return dojo_config

resolve_config_path(config_path)

Resolve the configuration path.

Returning a default if none is provided.

Parameters:

Name Type Description Default
config_path Path | None

The explicit path to the configuration file, or None.

required

Returns:

Type Description
Path | None

Path | None: The resolved absolute path to the configuration file, or None if no configuration file is found and no explicit path was given.

Raises:

Type Description
FileNotFoundError

If an explicit config_path is provided but the file does not exist.

Source code in src/debug_dojo/_config.py
def resolve_config_path(config_path: Path | None) -> Path | None:
    """Resolve the configuration path.

    Returning a default if none is provided.

    Args:
        config_path (Path | None): The explicit path to the configuration file, or None.

    Returns:
        Path | None: The resolved absolute path to the configuration file, or None if no
                     configuration file is found and no explicit path was given.

    Raises:
        FileNotFoundError: If an explicit `config_path` is provided but the file
                           does not exist.

    """
    if config_path:
        if not config_path.exists():
            msg = f"Configuration file not found:\n{config_path.resolve()}"
            raise FileNotFoundError(msg)
        return config_path.resolve()

    # Default configuration path
    for path in (Path("dojo.toml"), Path("pyproject.toml")):
        if path.exists():
            return path.resolve()

    # None means - use default config values
    return None

validated_and_updated_config(raw_config, *, verbose)

Validate and update the raw configuration to the latest DebugDojoConfig version.

Parameters:

Name Type Description Default
raw_config JSON

The raw configuration data loaded from a file.

required
verbose bool

If True, print verbose messages during validation and update.

required

Returns:

Name Type Description
DebugDojoConfig DebugDojoConfig

A validated and updated DebugDojoConfig instance.

Raises:

Type Description
Exit

If the configuration cannot be validated against any known version.

Source code in src/debug_dojo/_config.py
def validated_and_updated_config(
    raw_config: JSON,
    *,
    verbose: bool,
) -> DebugDojoConfig:
    """Validate and update the raw configuration to the latest DebugDojoConfig version.

    Args:
        raw_config (JSON): The raw configuration data loaded from a file.
        verbose (bool): If True, print verbose messages during validation and update.

    Returns:
        DebugDojoConfig: A validated and updated DebugDojoConfig instance.

    Raises:
        typer.Exit: If the configuration cannot be validated against any known version.

    """
    config = _try_validate_config(raw_config, verbose=verbose)

    if not config:
        msg = "[red]Unsupported configuration version or error.[/red]"
        rich_print(msg)
        raise Exit(code=1)

    while not isinstance(config, DebugDojoConfig):
        config = config.update()

    return config

Dataclass models for Debug Dojo’s configuration.

This module defines the data structures used to validate and manage the configuration of debug-dojo, including settings for debuggers, exception handling, and features.

DebugDojoConfigV1 dataclass

Legacy configuration for Debug Dojo (version 1).

Source code in src/debug_dojo/_config_models.py
@dataclass
class DebugDojoConfigV1:
    """Legacy configuration for Debug Dojo (version 1)."""

    debugger: DebuggerType = DebuggerType.PUDB
    """The type of debugger to use."""
    features: Features = field(default_factory=Features)
    """Features to install for debugging."""

    def update(self) -> DebugDojoConfigV2:
        """Update the configuration to the latest version."""
        v2_exceptions = ExceptionsConfig(
            rich_traceback=self.features.rich_traceback,
        )
        v2_debuggers = DebuggersConfig(default=self.debugger)
        v2_features = FeaturesConfig(
            rich_inspect="i" if self.features.rich_inspect else "",
            rich_print="p" if self.features.rich_print else "",
            comparer="c" if self.features.comparer else "",
            breakpoint="b" if self.features.breakpoint else "",
        )
        return DebugDojoConfigV2(
            exceptions=v2_exceptions,
            debuggers=v2_debuggers,
            features=v2_features,
        )

debugger = DebuggerType.PUDB class-attribute instance-attribute

The type of debugger to use.

features = field(default_factory=Features) class-attribute instance-attribute

Features to install for debugging.

update()

Update the configuration to the latest version.

Source code in src/debug_dojo/_config_models.py
def update(self) -> DebugDojoConfigV2:
    """Update the configuration to the latest version."""
    v2_exceptions = ExceptionsConfig(
        rich_traceback=self.features.rich_traceback,
    )
    v2_debuggers = DebuggersConfig(default=self.debugger)
    v2_features = FeaturesConfig(
        rich_inspect="i" if self.features.rich_inspect else "",
        rich_print="p" if self.features.rich_print else "",
        comparer="c" if self.features.comparer else "",
        breakpoint="b" if self.features.breakpoint else "",
    )
    return DebugDojoConfigV2(
        exceptions=v2_exceptions,
        debuggers=v2_debuggers,
        features=v2_features,
    )

DebugDojoConfigV2 dataclass

Configuration for Debug Dojo.

Source code in src/debug_dojo/_config_models.py
@dataclass
class DebugDojoConfigV2:
    """Configuration for Debug Dojo."""

    exceptions: ExceptionsConfig = field(default_factory=ExceptionsConfig)
    """Better exception messages."""
    debuggers: DebuggersConfig = field(default_factory=DebuggersConfig)
    """Default debugger and configs."""
    features: FeaturesConfig = field(default_factory=FeaturesConfig)
    """Features mnemonics."""
    gamification: bool = True
    """Enable or disable gamification (Dojo Belts)."""

debuggers = field(default_factory=DebuggersConfig) class-attribute instance-attribute

Default debugger and configs.

exceptions = field(default_factory=ExceptionsConfig) class-attribute instance-attribute

Better exception messages.

features = field(default_factory=FeaturesConfig) class-attribute instance-attribute

Features mnemonics.

gamification = True class-attribute instance-attribute

Enable or disable gamification (Dojo Belts).

DebuggerType

Bases: Enum

Enum for different types of debuggers.

Source code in src/debug_dojo/_config_models.py
class DebuggerType(Enum):
    """Enum for different types of debuggers."""

    DEBUGPY = "debugpy"
    IPDB = "ipdb"
    PDB = "pdb"
    PUDB = "pudb"

DebuggersConfig dataclass

Configuration for debuggers.

Source code in src/debug_dojo/_config_models.py
@dataclass
class DebuggersConfig:
    """Configuration for debuggers."""

    default: DebuggerType = DebuggerType.IPDB
    """Default debugger to use."""
    prompt_name: str = "debug-dojo> "
    """Prompt name for the debugger, used in the REPL."""

    debugpy: DebugpyConfig = field(default_factory=DebugpyConfig)
    """Configuration for debugpy debugger."""
    ipdb: IpdbConfig = field(default_factory=IpdbConfig)
    """Configuration for ipdb debugger."""
    pdb: PdbConfig = field(default_factory=PdbConfig)
    """Configuration for pdb debugger."""
    pudb: PudbConfig = field(default_factory=PudbConfig)
    """Configuration for pudb debugger."""

debugpy = field(default_factory=DebugpyConfig) class-attribute instance-attribute

Configuration for debugpy debugger.

default = DebuggerType.IPDB class-attribute instance-attribute

Default debugger to use.

ipdb = field(default_factory=IpdbConfig) class-attribute instance-attribute

Configuration for ipdb debugger.

pdb = field(default_factory=PdbConfig) class-attribute instance-attribute

Configuration for pdb debugger.

prompt_name = 'debug-dojo> ' class-attribute instance-attribute

Prompt name for the debugger, used in the REPL.

pudb = field(default_factory=PudbConfig) class-attribute instance-attribute

Configuration for pudb debugger.

DebugpyConfig dataclass

Configuration for debugpy debugger.

Source code in src/debug_dojo/_config_models.py
@dataclass
class DebugpyConfig:
    """Configuration for debugpy debugger."""

    host: str = "localhost"
    """Host for debugpy debugger."""
    log_to_file: bool = False
    """Whether to log debugpy output to a file."""
    port: int = 1992
    """Port for debugpy debugger."""
    wait_for_client: bool = True
    """Whether to wait for the client to connect before starting debugging."""

    @property
    def set_trace_hook(self) -> str:
        return "debugpy.breakpoint"

host = 'localhost' class-attribute instance-attribute

Host for debugpy debugger.

log_to_file = False class-attribute instance-attribute

Whether to log debugpy output to a file.

port = 1992 class-attribute instance-attribute

Port for debugpy debugger.

wait_for_client = True class-attribute instance-attribute

Whether to wait for the client to connect before starting debugging.

ExceptionsConfig dataclass

Configuration for exceptions handling.

Source code in src/debug_dojo/_config_models.py
@dataclass
class ExceptionsConfig:
    """Configuration for exceptions handling."""

    locals_in_traceback: bool = False
    """Include local variables in traceback."""
    post_mortem: bool = True
    """Enable post-mortem debugging after an exception."""
    rich_traceback: bool = True
    """Enable rich traceback for better error reporting."""

locals_in_traceback = False class-attribute instance-attribute

Include local variables in traceback.

post_mortem = True class-attribute instance-attribute

Enable post-mortem debugging after an exception.

rich_traceback = True class-attribute instance-attribute

Enable rich traceback for better error reporting.

Features dataclass

Legacy configuration for installing debug features (used in V1 config).

Source code in src/debug_dojo/_config_models.py
@dataclass
class Features:
    """Legacy configuration for installing debug features (used in V1 config)."""

    rich_inspect: bool = True
    """Install rich inspect as 'i' for enhanced object inspection."""
    rich_print: bool = True
    """Install rich print as 'p' for enhanced printing."""
    rich_traceback: bool = True
    """Install rich traceback for better error reporting."""
    comparer: bool = True
    """Install comparer as 'c' for side-by-side object comparison."""
    breakpoint: bool = True
    """Install breakpoint as 'b' for setting breakpoints in code."""

breakpoint = True class-attribute instance-attribute

Install breakpoint as ‘b’ for setting breakpoints in code.

comparer = True class-attribute instance-attribute

Install comparer as ‘c’ for side-by-side object comparison.

rich_inspect = True class-attribute instance-attribute

Install rich inspect as ‘i’ for enhanced object inspection.

rich_print = True class-attribute instance-attribute

Install rich print as ‘p’ for enhanced printing.

rich_traceback = True class-attribute instance-attribute

Install rich traceback for better error reporting.

FeaturesConfig dataclass

Configuration for installing debug features.

Source code in src/debug_dojo/_config_models.py
@dataclass
class FeaturesConfig:
    """Configuration for installing debug features."""

    breakpoint: str = "b"
    """Install breakpoint as 'b' for setting breakpoints in code."""
    comparer: str = "c"
    """Install comparer as 'c' for side-by-side object comparison."""
    rich_inspect: str = "i"
    """Install rich inspect as 'i' for enhanced object inspection."""
    rich_print: str = "p"
    """Install rich print as 'p' for enhanced printing."""

breakpoint = 'b' class-attribute instance-attribute

Install breakpoint as ‘b’ for setting breakpoints in code.

comparer = 'c' class-attribute instance-attribute

Install comparer as ‘c’ for side-by-side object comparison.

rich_inspect = 'i' class-attribute instance-attribute

Install rich inspect as ‘i’ for enhanced object inspection.

rich_print = 'p' class-attribute instance-attribute

Install rich print as ‘p’ for enhanced printing.

IpdbConfig dataclass

Configuration for ipdb debugger.

Source code in src/debug_dojo/_config_models.py
@dataclass
class IpdbConfig:
    """Configuration for ipdb debugger."""

    context_lines: int = 20
    """Number of context lines to show in ipdb."""

    @property
    def set_trace_hook(self) -> str:
        return "ipdb.set_trace"

context_lines = 20 class-attribute instance-attribute

Number of context lines to show in ipdb.

PdbConfig dataclass

Configuration for pdb debugger.

Source code in src/debug_dojo/_config_models.py
@dataclass
class PdbConfig:
    """Configuration for pdb debugger."""

    @property
    def set_trace_hook(self) -> str:
        return "pdb.set_trace"

PudbConfig dataclass

Configuration for pudb debugger.

Source code in src/debug_dojo/_config_models.py
@dataclass
class PudbConfig:
    """Configuration for pudb debugger."""

    @property
    def set_trace_hook(self) -> str:
        return "pudb.set_trace"

Command-line interface for running Python scripts or modules with debugging tools.

belt(config_path=None)

Display the current user’s Dojo Belt status.

Source code in src/debug_dojo/_cli.py
@cli.command(help="Show your current Dojo Belt and stats.")
def belt(
    config_path: Annotated[
        Path | None, typer.Option("--config", "-c", help="Show configuration")
    ] = None,
) -> None:
    """Display the current user's Dojo Belt status."""
    config = load_config(config_path)

    if not config.gamification:
        rich_print("[yellow]Gamification is disabled in your configuration.[/yellow]")
        return

    manager = GamificationManager()
    manager.display_status()

main()

Run the command-line interface.

Source code in src/debug_dojo/_cli.py
def main() -> None:
    """Run the command-line interface."""
    cli()

run_debug(ctx, target_name=None, *, config_path=None, debugger=None, verbose=False, module=False, executable=False)

Run a Python script, module, or executable with debug-dojo tools.

This command acts as the main entry point for debug-dojo, allowing users to execute their code while automatically installing and configuring debugging tools based on the provided options or configuration file.

Parameters:

Name Type Description Default
ctx Context

The Typer context object.

required
target_name str | None

The path to the script, name of the module, or name of the executable to run. If not provided, the command will exit.

None
config_path Path | None

Path to a custom configuration file (e.g., dojo.toml).

None
debugger DebuggerType | None

Override the default debugger specified in the config.

None
verbose bool

Enable verbose output, showing loaded configuration and installation steps.

False
module bool

Treat target_name as a Python module to run (e.g., dojo -m my_package.my_module).

False
executable bool

Treat target_name as an executable command to run (e.g., dojo -e pytest).

False

Raises:

Type Description
Exit

If --module and --exec are used together, or if the target cannot be executed, or if an error occurs during execution.

Source code in src/debug_dojo/_cli.py
@cli.command(
    name="run",
    help="Run a Python script or module with debugging tools installed.",
    no_args_is_help=True,
    context_settings={"allow_extra_args": True, "ignore_unknown_options": True},
)
def run_debug(  # noqa: PLR0913
    ctx: typer.Context,
    target_name: Annotated[
        str | None,
        typer.Argument(help="The target script or module to debug.", metavar="target"),
    ] = None,
    *,
    config_path: Annotated[
        Path | None, typer.Option("--config", "-c", help="Show configuration")
    ] = None,
    debugger: Annotated[
        DebuggerType | None,
        typer.Option("--debugger", "-d", help="Specify the debugger to use"),
    ] = None,
    verbose: Annotated[
        bool,
        typer.Option("--verbose", "-v", help="Enable verbose output"),
    ] = False,
    module: Annotated[
        bool,
        typer.Option("--module", "-m", help="Run a module"),
    ] = False,
    executable: Annotated[
        bool,
        typer.Option("--exec", "-e", help="Run a command"),
    ] = False,
) -> None:
    """Run a Python script, module, or executable with debug-dojo tools.

    This command acts as the main entry point for `debug-dojo`, allowing users to
    execute their code while automatically installing and configuring debugging tools
    based on the provided options or configuration file.

    Args:
        ctx (typer.Context): The Typer context object.
        target_name (str | None): The path to the script, name of the module, or
                                  name of the executable to run. If not provided,
                                  the command will exit.
        config_path (Path | None): Path to a custom configuration file
                                   (e.g., `dojo.toml`).
        debugger (DebuggerType | None): Override the default debugger specified
                                        in the config.
        verbose (bool): Enable verbose output, showing loaded configuration
                        and installation steps.
        module (bool): Treat `target_name` as a Python module to run
                       (e.g., `dojo -m my_package.my_module`).
        executable (bool): Treat `target_name` as an executable command to run
                           (e.g., `dojo -e pytest`).

    Raises:
        typer.Exit: If `--module` and `--exec` are used together, or if the target
                    cannot be executed, or if an error occurs during execution.

    """
    if module and executable:
        rich_print(
            "[red]Error: --module and --command options are mutually exclusive.[/red]"
        )
        raise typer.Exit(1)

    mode = (
        ExecMode.EXECUTABLE
        if executable
        else ExecMode.MODULE
        if module
        else ExecMode.FILE
    )

    config = load_config(config_path, verbose=verbose, debugger=debugger)

    if verbose:
        rich_print(f"[blue]Using debug-dojo configuration: {config} [/blue]")

    if target_name:
        start_time = time.perf_counter()

        execute_with_debug(
            target_name=target_name,
            target_mode=mode,
            target_args=ctx.args,
            verbose=verbose,
            config=config,
        )

        duration = time.perf_counter() - start_time

        # Gamification: Increment session count if enabled
        if config.gamification:
            with contextlib.suppress(Exception):
                command = " ".join(sys.argv)
                GamificationManager().increment_session(
                    duration_seconds=duration,
                    command=command,
                )