This release is a pre-release and may not be stable for production use.
wrapture
Wrap anything, capture everything, change nothing.
wrapture (wrapt + capture) is a Python library for attaching bindings to
arbitrary call sites, without modifying the code being observed, and doing
something useful with what flows through them.
It is a sibling project to wrapt and autowrapt, building on the safe monkey-patching machinery wrapt provides.
Status: stabilising ahead of 1.0.0. The feature set is complete for a first release and pre-releases are published to PyPI. Until 1.0.0 is final, a plain
pip install wrapturepicks up the latest pre-release automatically, so there is no need to pin a specific version. The API is being exercised and tidied rather than extended, so small changes are still possible before 1.0.0.
Installation
wrapture is on PyPI:
$ pip install wrapture
or with uv:
$ uv add wrapture
Documentation
Full documentation is at wrapture.readthedocs.io.
Start with the getting started
page: everything on it can be pasted into a Python interpreter. Coming
from unittest.mock? There is a
comparison page
mapping each mock idiom to its wrapture counterpart. After that, the
worked examples, starting with
testing code that calls external services,
each take one question you might arrive with and answer it end to end.
At a glance
None of the classes below import wrapture or know they are observed:
place = wrapture.binding(OrderService, "place")
charge = wrapture.binding(Gateway, "charge")
record = wrapture.binding(Ledger, "record")
with wrapture.timeline(place, charge, record) as tape:
OrderService().place(500)
print(tape.tree())
OrderService.place(amount=500) -> {'id': 'ch_500', 'amount': 500}
Gateway.charge(amount=500, currency='USD') -> {'id': 'ch_500', 'amount': 500}
Ledger.record(entry={'id': 'ch_500', 'amount': 500}) -> 'led_ch_500'
The same bindings intervene as well as observe: stub a result, inject a failure, or transform one argument while the real code keeps running.
What it does
One mechanism, three uses, in increasing order of machinery:
-
Monkey patching. A clean lifecycle and behaviour vocabulary over wrapt's
wrap_object(). Point at a method by name and stub it, fail it, transform its arguments or result, or wrap it with a decorator, then remove it again, with honest reporting if something else displaced the patch in the meantime. Useful entirely on its own, with nothing else switched on. -
Unit testing. Observe and assert on how calls actually flowed through a real call graph (nesting, ordering, arguments and return values) and optionally intervene (stub, transform, fail-inject). Unlike a
unittest.mockMock, which fabricates values and cannot see calls an object makes to itself, wrapture watches the real code run, and when a test must supply a stand-in it provides strict, recorded ones:stub()for a callable, spec-requiredmock()for a collaborator. This makes it possible to test code with no injectable seams at all, and to assert on what didn't happen on an error path: inject a gateway timeout, then verify the ledger was not written, the receipt was not sent, and the compensating refund was issued. -
Ad-hoc tracing. Attach bindings to a running application, including one you cannot modify or redeploy, and emit a structured, nested trace to process or chart elsewhere. Name a handful of methods and a call tree appears; no code changes required: with a
wrapture.tomlnaming the methods and a sink,python -m wrapture manage.py runservertraces the application untouched. With autowrapt installed, not even the launcher is needed:AUTOWRAPT_BOOTSTRAP=wrapturein the environment applies the same config at interpreter startup, so the program starts with plainpython.
The distinction that matters: most tracing tools either need the code to have been written with them in mind, or can only be switched on for the whole program at once. wrapture needs neither: you point at a method by name and a trace appears.
Why
No single existing tool covers "point at arbitrary methods, get a structured nested trace, assert on it or export it, in tests or in production":
unittest.mockrecords a flat call list, with no nesting and no return values, and a patched call returns a fabricatedMagicMockrather than running the real code.- Span-assertion tools (
logfire.testing, OpenTelemetry'sInMemorySpanExporter) require the code to already be instrumented. sys.settracetools (hunter,snoop) give a firehose with no assertion API.- APM agents are all-or-nothing products rather than a toolkit.
wrapture fills that gap: a targeted call tree with normalized arguments and return values, produced by naming the methods you care about, usable as a testing assertion library, a tracing tool, or both at once.
What it is not
- Not a fabrication tool. There is no spec-less
Mock()here by design; stand-ins are strict and built from named specs, andunittest.mockremains the tool for invented objects. - Not a production APM. It is a toolkit that APM-like things could be built on.
- Not an OpenTelemetry competitor. It should emit to OTel, not replace it.
How it was built
wrapture's code and documentation were written by an AI assistant under the direction of Graham Dumpleton, the author of wrapt, through a long process of specification, layered implementation, and validation against real-world test suites. How wrapture was built explains the process and the thinking.
Requirements
- Python 3.12+
- wrapt 2.4.0+
Issues
Bug reports and feature requests go to the issue tracker. Include the wrapture and Python versions and, where you can, a small binding that reproduces the problem.
License
BSD 2-Clause. See LICENSE.
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file wrapture-1.0.0a1.tar.gz.
File metadata
- Download URL: wrapture-1.0.0a1.tar.gz
- Upload date:
- Size: 262.0 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via:
twine/7.0.0 CPython/3.13.14
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
3625f9160a9f9afdf67bfa5f9a001ea89f65519251c295a2f59a2a01717398c4
|
|
| MD5 |
c6be9d0687158cc1608b38b57766613e
|
|
| BLAKE2b-256 |
015e3ce622a1a595b42431a3cf22d762887279e84a279f5e0787790c4700fbe1
|
Provenance
The following attestation bundles were made for wrapture-1.0.0a1.tar.gz:
Publisher:
build-test-release.yml on GrahamDumpleton/wrapture
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
wrapture-1.0.0a1.tar.gz -
Subject digest:
3625f9160a9f9afdf67bfa5f9a001ea89f65519251c295a2f59a2a01717398c4 - Sigstore transparency entry: 2543530025
- Sigstore integration time:
-
Permalink:
GrahamDumpleton/wrapture@655b17d0502fc6ddd66daa9f69f5dc675249a78e -
Branch / Tag:
refs/tags/1.0.0a1 - Owner: https://github.com/GrahamDumpleton
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
build-test-release.yml@655b17d0502fc6ddd66daa9f69f5dc675249a78e -
Trigger Event:
push
-
Statement type:
File details
Details for the file wrapture-1.0.0a1-py3-none-any.whl.
File metadata
- Download URL: wrapture-1.0.0a1-py3-none-any.whl
- Upload date:
- Size: 164.1 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via:
twine/7.0.0 CPython/3.13.14
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
da4a4c37f29061d7b6bb19ba32b4859991e962a87cbc554522a33d4d2067c44a
|
|
| MD5 |
22a5e65816154c199b73263cd11a5530
|
|
| BLAKE2b-256 |
d5d8be6f0fb1bfee8597f60708a283c5d8ca3c93b8da629d17b2dbd5965a030c
|
Provenance
The following attestation bundles were made for wrapture-1.0.0a1-py3-none-any.whl:
Publisher:
build-test-release.yml on GrahamDumpleton/wrapture
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
wrapture-1.0.0a1-py3-none-any.whl -
Subject digest:
da4a4c37f29061d7b6bb19ba32b4859991e962a87cbc554522a33d4d2067c44a - Sigstore transparency entry: 2543530175
- Sigstore integration time:
-
Permalink:
GrahamDumpleton/wrapture@655b17d0502fc6ddd66daa9f69f5dc675249a78e -
Branch / Tag:
refs/tags/1.0.0a1 - Owner: https://github.com/GrahamDumpleton
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
build-test-release.yml@655b17d0502fc6ddd66daa9f69f5dc675249a78e -
Trigger Event:
push
-
Statement type: