Skip to main content

nimax

CI codecov PyPI

Record and replay niquests HTTP and WebSocket interactions in pytest.

nimax is a VCR-style cassette library built natively for niquests — supporting lazy responses, multiplexed connections, AsyncSession, and WebSockets. It is to niquests what betamax is to requests.

Installation

pip install nimax

Quick start

Automatic fixture

nimax registers a nimax_session pytest fixture automatically. Use it instead of niquests.Session() in your tests:

def test_my_api(nimax_session):
    resp = nimax_session.get("https://api.example.com/users")
    assert resp.status_code == 200

On the first run nimax records the real HTTP response to a cassette file under cassettes/<test_module>/<test_name>.json. Subsequent runs replay from the cassette — no network required.

Async sessions

import pytest
import niquests


async def test_async(nimax_session):
    async with niquests.AsyncSession() as session:
        with NimaxRecorder(session).use_cassette("my_cassette.json"):
            resp = await session.get("https://api.example.com/data")
            assert resp.status_code == 200

Programmatic API

import niquests
from nimax import NimaxRecorder, RecordMode


def test_programmatic(tmp_path):
    session = niquests.Session()
    cassette_path = tmp_path / "my_cassette.json"
    with NimaxRecorder(session).use_cassette(cassette_path, record_mode=RecordMode.ONCE):
        resp = session.get("https://api.example.com/users")
        assert resp.status_code == 200

Record modes

Mode Behaviour
once Record on first run, replay on subsequent runs (default)
none Never record — raise an error if no matching interaction exists
new_episodes Replay existing interactions; record any unmatched requests
all Always record, overwriting the cassette each run

WebSocket support

WebSocket connections opened through a cassette-backed session are recorded and replayed automatically, alongside HTTP interactions, in the same cassette file:

def test_ws_echo(nimax_session):
    resp = nimax_session.get("wss://echo.example.com")
    resp.extension.send_payload('{"id": "1", "op": "ping"}')
    reply = resp.extension.next_payload()

On replay, a recv frame only releases once the real send_payload() call it depends on has actually happened — matching how a real socket can't deliver a response before its triggering request went out. By default this is tracked by position (send count) in the recorded log, which is correct as long as your live send order doesn't diverge from the recorded order.

Correlating responses by id

If your protocol embeds a correlation id in its messages (e.g. JSON-RPC-style {"id": ..., ...}) and you dispatch responses from a background reader task — so concurrent, in-flight requests can legitimately resolve out of order — pass ws_id_extractor to correlate replay by that id instead of by position:

with NimaxRecorder(session).use_cassette("my_cassette.json", ws_id_extractor="id"):
    ...

ws_id_extractor accepts:

  • A dotted JSON path string, e.g. "id" or "params.id" for a nested field.
  • A callable (payload: str | bytes) -> Any | None for anything else (non-JSON protocols, custom shapes).

A message whose id doesn't resolve (e.g. valid JSON with no id field) falls back to the position-based gate. A payload the extractor can't parse at all (e.g. malformed JSON when JSON was expected) raises — that means the extractor doesn't match the actual protocol, which is worth surfacing rather than silently ignoring.

Placeholders

Scrub sensitive values (tokens, API keys) from cassettes before they are written:

from nimax import Placeholder

recorder = NimaxRecorder(
    session,
    placeholders=[
        Placeholder(placeholder="<AUTH_TOKEN>", replace="Bearer secret123"),
    ],
)

Custom matchers and serializers

from nimax import BaseMatcher, NimaxRecorder


class BodyMatcher(BaseMatcher):
    name = "body"

    def match(self, recorded: dict, live: object) -> bool:
        return recorded.get("body") == live.body  # type: ignore[union-attr]


NimaxRecorder.register_matcher(BodyMatcher)

YAML cassettes are supported out of the box — use a .yaml extension for the cassette path.

Requirements

  • Python ≥ 3.11
  • niquests ≥ 3
  • pytest ≥ 8
  • PyYAML ≥ 6

License

MIT

Metadata

Release files for nimax 1.1.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for nimax 1.1.0
File Size Uploaded
nimax-1.1.0.tar.gz 30.0 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for nimax 1.1.0
File Interpreter ABI Platform
nimax-1.1.0-py3-none-any.whl Python 3 none any Details

Total release size: 50.3 kB

Release files / nimax-1.1.0.tar.gz

Download URL nimax-1.1.0.tar.gz
Size 30.0 kB
Tags Source
SHA-256 checksum
How to use checksums
751e8d50303da4cfe3268e3a9e49ff5e50f2d9dbf0556662eea87bd0346a18ab
BLAKE2b-256 checksum
How to use checksums
e591ce362ebd357410ecc4a63e1f3c89fef37ae6612072d502a07d8d05b32665
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Sep 16, 2026.

Transparency log

Release files / nimax-1.1.0-py3-none-any.whl

Download URL nimax-1.1.0-py3-none-any.whl
Size 20.3 kB
Tags Python 3
SHA-256 checksum
How to use checksums
ae4c09dee876ed5169c4c017b16201f549554f3d4918f7fd484fefe7b8aa830e
BLAKE2b-256 checksum
How to use checksums
339d67dbe5770c37de4bf2cc431033f7539cd6b23f5229e00c375ce053b7c819
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Sep 16, 2026.

Transparency log

Release history Release notifications | RSS feed

1.1.1

2 release files

This release

1.1.0 This release

2 release files

1.0.0

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page