Introducing wrapture

Graham Dumpleton has released Wrapture, a new Python library that extends the monkeypatching capabilities of his earlier project, wrapt, to cover testing…

By Vane September 1, 2026 2 min read

Graham Dumpleton has released Wrapture, a new Python library that extends the monkeypatching capabilities of his earlier project, wrapt, to cover testing and tracing simultaneously.

The tool allows developers to wrap any function or method so that all access points are traced or overridden to return different values. It serves as an alternative to unittest.mock and provides a way to implement tracing against existing codebases without modification.

Dumpleton notes the difficulty of the task:

Attaching observation to code you do not control, recording what flows through it, and doing so without disturbing the program being watched, is a problem I have never really stopped thinking about.

Wrapture includes OpenTelemetry support and offers a configuration-based mechanism for adding tracing to existing Python projects. A sample configuration file looks like this:

capture = "summary"

[[observe]]
target = "domain:Calculator"
name = ["outer", "inner"]

[[sink]]
type = "jsonlines"
path = "trace.jsonl"

This is a very young project, only a few weeks old, but it has started promisingly.

Notably, this marks Dumpleton’s first attempt at a large, entirely agent-driven project. He has been clear about the process:

Every line of code and documentation in wrapture was written by an AI assistant working under my direction. I want to be upfront about that, and equally upfront about what it was not. This was not vibe coding, where a one-shot prompt produces a pile of generated code and the person driving hopes for the best because they lack the knowledge to judge what came back. Vibe coding has earned its bad reputation. I engineered wrapture carefully from the start. I have spent a long time in this particular corner of Python and knew exactly what the result needed to be, and the AI was the means of producing it rather than the source of the design.

In a follow-up post, Dumpleton demonstrated the testing patterns supported by the library. One example shows how to stub a method:

def test_stub_with_wrapture():
    with wrapture.binding(
        Gateway, "charge"
    ).on_call.returns({
        "id": "stub", "amount": 0}
    ):
        assert OrderService().place(
            500
        )["id"] == "stub"

Another example shows a test that calls a method and then modifies the return value from the original function:

def test_pinned_result_with_wrapture():
    charge = wrapture.binding(
        Gateway, "charge"
    )
    charge.on_call.transforms_result(
        lambda r: {**r, "id": "ch_TEST"}
    )
    with charge:
        assert OrderService().place(
           500
        ) == {
            "id": "ch_TEST", "amount": 500
        }
Scroll to Top