The Python reference client
nxr.py is the second client of the protocol: a minimal reference implementation on the Python standard library, python3.10+, nothing to install.
It proves the claim the project makes about its own wire format: the protocol is implementable from scratch over bare HTTP, with http.client for the wire and hashlib for the digests.
The authoritative text it follows lives in crates/nexus-raw-core/src/protocol.md.
What it covers
Six verbs over the store: get, put, head, sha, ls, channel get/set.
Deletion is deliberately absent.
The interesting rules are all client-side and all present:
putwrites the bytes, then the.sha256marker of the same name, strictly in that order. A crash between the two leaves a markerless object, which every reader refuses. The marker's name field is the percent-decoded final path segment, refused when it is empty,./.., out of grammar, or.sha256-suffixed.getdownloads the bytes and the sibling and refuses unless the digest matches. Completion is bytes plus the sibling: anything less is an exception, never a silent return.- A 2xx without
Content-Lengthis present-but-unverifiable, never absent (headreportslength=None). - 401/403 fail fast with no retries.
5xx and transport failures retry with backoff (4 attempts, 0.5s x 2^n, capped, jittered).
A retryable status (429 or 5xx) honors its
Retry-Afterpause, clamped to 1..=60 seconds, in place of the backoff. - Redirects are never followed: a 301 surfaces as
HttpErrorwith the status. - The per-operation socket timeout is the stall watchdog: a frozen server aborts the attempt, a slow-but-moving transfer never trips it.
lswalks/service/rest/v1/search/assetswith continuation tokens, capped at 1000 pages, and diagnoses a repository-scoped 400 as "missing or not raw". Withdirectory, it scopes the walk the way a directory listing does: the search asks withq=<directory>/and the client keeps the paths under that whole-segment prefix, so the server's looseqcan only widen the pages, never the answer.- Markers parse strictly (
sha256sum -cshape: LF only, exactly two spaces, 64 lowercase hex, trailing newline), because a loose parse would bless foreign markers. The reference decodes marker bytes as ASCII, one notch stricter than the Rust core's lossy UTF-8: harmless today, since both sides compare digests only, but a porter may loosen it the same way.
Every error is an exception carrying .status (the HTTP status, None for pure transport failures) and .hint (the action line a CLI would print).
Every attempt lands in .requests as a (method, path) pair, the record the conformance suite asserts on.
Run the conformance suite
cargo build -q -p mock-nexus
python3 -m unittest discover clients/python
The suite spawns mock-nexus itself, one process per test on a free port, and reads the scenario list live from mock-nexus --print-scenarios.
To point it at another binary, set MOCK_NEXUS_BIN to the path.
The scenario contract and the skip table
The mock's scenario list is the conformance contract, and the suite refuses to drift from it:
test_unit_every_scenario_is_classified requires every listed scenario to have a test method named test_<scenario with dashes as underscores> or a documented row in SKIP, in both directions.
A scenario added to crates/mock-nexus/src/scenario.rs fails this suite until it is classified, which is the point.
The current skip rows, with the reasons:
| Scenario | Reason |
|---|---|
doc-drift |
The drift toggle is a library-only knob (MockNexus::enable_drift), so the binary serves plain storage. the client-side half, version.json being an ordinary name, is pinned under atomic |
no-service |
The scenario only breaks /service/rest/v1/repositories, and the client has no service-repos surface |
readonly |
The scenario only answers 403 to DELETE, and the client implements no delete |
Lint, types and the suite
The client is gated like the rest of the repository.
just check runs just test-python, which builds the mock binary and runs the suite below, and the prek hooks run ruff (lint plus format check) and ty over the module.
Ruff's width is 120 and E501 is off on purpose: the repository mandates unwrapped sentences in comments and docstrings, and a line-length complaint would fight that rule on exactly those lines.
The configuration lives in pyproject.toml.
Only the shipped module nxr.py is type-checked, the suite is lint-checked, so a loose fixture in a test never blocks a commit.
Porting note
What a real integrator must implement, at minimum, beyond the verbs:
- Basic auth attached to every request, resolved once per invocation.
- The retry classification: retry transport failures and 5xx with bounded backoff, honor
Retry-Afteron any retryable status, never retry 401/403, never follow redirects. - An attempt-level stall bound (a read/write timeout), because a server can hold a connection forever.
- The marker order on upload, the digest check on download, and the strict marker parse.
- The lengthless-answer rule: a 2xx without
Content-Lengthis unverifiable, never empty. Accept-Encoding: identityon every request, unless the client also implements thezstdGET decoding, so digests always describe the stored bytes.
Deliberate simplifications of this reference, safe to outgrow: bodies are held in memory (no streaming, no Range resume, no part files), one connection per attempt (no keep-alive), and TLS is whatever the runtime verifies by default (the protocol's --tls-insecure escape hatch has no equivalent here).
Metadata
Release files for nexus-raw 0.22.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | Provenance | |
|---|---|---|---|---|
| nexus_raw-0.22.0.tar.gz | 20.3 kB | With provenance | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| nexus_raw-0.22.0-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 32.1 kB
Release files / nexus_raw-0.22.0.tar.gz
| Download URL | nexus_raw-0.22.0.tar.gz |
|---|---|
| Size | 20.3 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
416aaaaa8e25c1f5ae2d57f9025e0694099cf3bf6d450fed56bc3d4303eb5c97
|
|
BLAKE2b-256 checksum How to use checksums |
12ab5d6a5bce481f56ad1cd5afe513bad21978dbda6369050213c80395dfb70c
|
| 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 Oct 19, 2026.
Transparency logRelease files / nexus_raw-0.22.0-py3-none-any.whl
| Download URL | nexus_raw-0.22.0-py3-none-any.whl |
|---|---|
| Size | 11.8 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
2e629b3b1235a2a5e3e0698758e2eb99f6189d88c98991678a52713c775f854d
|
|
BLAKE2b-256 checksum How to use checksums |
16818efb0b9aee7a20f5dd3055111c5c3f3d1038b15992f15dcbf4ddbc25a8f4
|
| 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 Oct 19, 2026.
Transparency logSecurity for nexus-raw 0.22.0
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.
Full provenance
All 2 files in this release have been uploaded with provenance metadata.
Attestation for nexus_raw-0.22.0.tar.gz
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 Oct 19, 2026.
Transparency logA note on package security
PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.
To learn more about protecting yourself from malicious actors, visit our package security documentation.