PDB Invocation and Wrapping

Purpose

This subtopic addresses the integration of Python's built-in debugger, **pdb**, within pytest's test execution environment by wrapping pdb classes and managing input/output capturing during debugging sessions. Its goal is to ensure that when a user invokes the debugger—either automatically on test failures or manually via command line options—pytest properly suspends output capturing, presents clear debugging prompts, and handles pdb commands gracefully without interfering with pytest’s internal state or test output.

Unlike the parent topic that broadly covers pdb integration and command line control, this subtopic specifically focuses on the underlying mechanics of invoking pdb, wrapping pdb classes to extend behavior, and managing IO capturing so that interactive debugging sessions work seamlessly within pytest’s capturing and reporting framework.

Functionality

Wrapping pdb Classes for Enhanced Behavior

This wrapping ensures that pdb debugging sessions respect pytest's output capturing and lifecycle, providing a smooth user experience.

Managing IO Capturing During Debugging

Invocation Hooks and Session Control

Example Code Snippet: Wrapping pdb class

def _get_pdb_wrapper_class(cls, pdb_cls, capman: CaptureManager | None):
    class PytestPdbWrapper(pdb_cls):
        _pytest_capman = capman
        _continued = False

        def do_continue(self, arg):
            ret = super().do_continue(arg)
            if cls._recursive_debug == 0:
                # Resume capturing output after continue
                if self._pytest_capman:
                    self._pytest_capman.resume()
            return ret

        def do_quit(self, arg):
            ret = super().do_quit(arg)
            if cls._recursive_debug == 0:
                outcomes.exit("Quitting debugger")
            return ret
    return PytestPdbWrapper

This snippet shows how the wrapper intercepts `continue` and `quit` commands to integrate with pytest’s capture manager and test lifecycle.

Integration

Diagram

sequenceDiagram
    participant User
    participant Pytest CLI
    participant PluginManager
    participant pytestPDB
    participant CaptureManager
    participant pdb

    User->>Pytest CLI: Run tests with --pdb or --trace
    Pytest CLI->>PluginManager: Register PdbInvoke or PdbTrace plugin
    PluginManager->>pytestPDB: Initialize with config and capture manager
    pytestPDB->>CaptureManager: Suspend capturing for pdb session
    pytestPDB->>pdb: Import and wrap pdb class (PytestPdbWrapper)
    User->>pdb: Interact with pdb session (commands like continue, quit)
    pdb->>pytestPDB: On continue, call do_continue override
    pytestPDB->>CaptureManager: Resume capturing output
    pdb->>pytestPDB: On quit, raise exit outcome to end test run

This sequence diagram visualizes the key flow of invoking pdb within pytest, highlighting how capturing is managed and how pdb is wrapped and controlled.


By wrapping pdb and managing IO capturing, pytest ensures that debugging sessions integrate smoothly into test runs, preserving output consistency and providing users with an interactive debugging experience tailored for automated testing workflows.