Skip to main content
Pre-release

This release is a pre-release and may not be stable for production use.

wrapture

Trace assertions without instrumenting your code.

Tests Documentation

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: early development. The monkey patching and unit testing layers are implemented; the tracing and profiling layers are designed but not built. Nothing is published to PyPI yet.

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.

Thirty seconds of it

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, four uses, in increasing order of machinery:

  1. 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.

  2. 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 Mock, which fabricates values and cannot see calls an object makes to itself, wrapture watches the real code run. 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.

  3. 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.

  4. Targeted profiling. Use a binding as a scope within which CPython's own profiling machinery is active, so you can profile one subsystem of a live process instead of everything.

The distinction that matters: most tracing and profiling 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.mock records a flat call list, with no nesting and no return values, and a patched call returns a fabricated MagicMock rather than running the real code.
  • Span-assertion tools (logfire.testing, OpenTelemetry's InMemorySpanExporter) require the code to already be instrumented.
  • sys.settrace tools (hunter, snoop) give a firehose with no assertion API.
  • cProfile cannot scope to a subsystem in a live process, and 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 replacement for unittest.mock. It complements mocking where code has seams; it exists for the code that doesn't.
  • Not a sampling profiler. py-spy and austin do that better and without distortion.
  • 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.

Requirements

  • Python 3.12+
  • wrapt 2.4.0+

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

wrapture-1.0.0.dev1.tar.gz (70.6 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

wrapture-1.0.0.dev1-py3-none-any.whl (41.9 kB view details)

Uploaded Python 3

File details

Details for the file wrapture-1.0.0.dev1.tar.gz.

File metadata

  • Download URL: wrapture-1.0.0.dev1.tar.gz
  • Upload date:
  • Size: 70.6 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/7.0.0 CPython/3.13.14

File hashes

Hashes for wrapture-1.0.0.dev1.tar.gz
Algorithm Hash digest
SHA256 2151881a4f942f4ffc50c4129077c5e65dafb9a227f34ac8c09fa9c2d74915da
MD5 8b8bf98d3ec5fb50b77520d5f2329a50
BLAKE2b-256 1ae066367164f9a4489ad60f18eef0493957bdf13c41c3ee3b2c16701a9801ef

See more details on using hashes here.

Provenance

The following attestation bundles were made for wrapture-1.0.0.dev1.tar.gz:

Publisher: build-test-release.yml on GrahamDumpleton/wrapture

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file wrapture-1.0.0.dev1-py3-none-any.whl.

File metadata

  • Download URL: wrapture-1.0.0.dev1-py3-none-any.whl
  • Upload date:
  • Size: 41.9 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/7.0.0 CPython/3.13.14

File hashes

Hashes for wrapture-1.0.0.dev1-py3-none-any.whl
Algorithm Hash digest
SHA256 580575b3ced50f6831f291ad3376c72fe058244a98063c9a06e6eda52608e898
MD5 b5919ebf304400734c4fd8eb4c9e433e
BLAKE2b-256 d9337cae018792b796922aa5c6d6c793c9aa9b13474c995b4c4c26724fd6a8fb

See more details on using hashes here.

Provenance

The following attestation bundles were made for wrapture-1.0.0.dev1-py3-none-any.whl:

Publisher: build-test-release.yml on GrahamDumpleton/wrapture

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page