QIR Formatter
qir-formatter is a Rust-backed Python library for rendering execution results into the
QIR labeled output schema.
It accepts shot-oriented result data in the internal USER:<TYPE>:<TAG> form
and emits the text format expected by tools that consume labeled QIR output.
Installation
pip install qir-formatter
Rust consumers can add the crate from crates.io:
cargo add qir-formatter --rename qir_formatter
The release workflow builds native wheels for standard (GIL-enabled) CPython 3.10 and newer on:
- Linux x86-64 and ARM64 (manylinux2014, glibc 2.17 or newer)
- macOS Intel and Apple Silicon
- Windows x86-64
Installing a matching wheel does not require Rust. Other targets, including Alpine/musl, Windows ARM64, and 32-bit platforms, do not have prebuilt wheels; installation falls back to the source distribution and requires Rust 1.85 or newer and a platform C/C++ build toolchain. Source builds on these targets are not tested by the release workflow. Free-threaded Python and alternative Python implementations are not covered by the wheel matrix.
Every wheel is installed and checked with the Python compatibility tests before publishing.
Usage
The formatter operates on a list of shots, where each shot is a list of
(name, value) tuples. User-facing values should use the
USER:<TYPE>:<TAG> naming convention.
from qir_formatter import QirLabeledFormatter, QsysShots
results: QsysShots = [
[
("USER:INT:shots", 42),
("USER:BOOL:accepted", 1),
("USER:RESULT_ARRAY:bits", [1, 0, 1]),
]
]
attributes = {
"qir_profiles": "base_profile",
"required_num_qubits": "3",
"required_num_results": "3",
}
output = QirLabeledFormatter().qir_labeled_output(results, attributes)
print(output)
This produces:
HEADER schema_id labeled
HEADER schema_version 2.1
START
METADATA entry_point
METADATA qir_profiles base_profile
METADATA required_num_qubits 3
METADATA required_num_results 3
OUTPUT INT 42 shots
OUTPUT BOOL true accepted
OUTPUT RESULT_ARRAY 101 bits
END 0
Only USER records are emitted. Known raw types currently map to the labeled
QIR schema as follows:
INTandUINTbecomeINTFLOATbecomesDOUBLEBOOLbecomesBOOLRESULTbecomesRESULTRESULT_ARRAYbecomesRESULT_ARRAYQIRARRAYbecomesARRAYQIRTUPLEbecomesTUPLE
Malformed values are skipped rather than raising, which makes the formatter
safe to use on partially clean result streams. Integer records use the signed
64-bit domain defined by the QIR record-output ABI. Python integers outside
-(2**63) through 2**63 - 1 are malformed and are skipped with a warning.
Rust API
src/labeled_formatter.rs is the single formatting implementation. It exposes
the formatter's validation, header/footer, value, shot, and complete-output
methods with typed Rust inputs. Writer methods append to a concrete QirOutput
buffer containing text and a malformed-value count. Floats use Rust's standard
formatting, not Python's exact decimal notation.
The published package uses a hyphenated crates.io name. Consumers can rename the dependency to give the library an idiomatic crate name:
[dependencies]
qir_formatter = { package = "qir-formatter", version = "0.3" }
use qir_formatter::{
QShotValType, QirLabeledFormatter, QirMetadata, QsysShotItemValue, QsysShots,
};
let results: QsysShots = vec![vec![(
"USER:INT:answer".into(),
QsysShotItemValue::Scalar(QShotValType::Int(42)),
)]];
let output = QirLabeledFormatter::new().qir_labeled_output(&results, &QirMetadata::new());
assert!(output.contains("OUTPUT\tINT\t42\tanswer\n"));
Malformed-value warnings use Rust's log crate with debug-formatted context.
The calling application configures the logger. The Python adapter also emits
the original plain warning through Python's logging module.
src/python.rs only adapts Python inputs, return values, text writers, and
logging. It does not build QIR records or dispatch through Python formatter
methods. The unchanged Python tests define the compatibility target; Python
subclass/override hooks and weak references are not supported. Output is buffered
before being passed to a Python writer.
The core has no Python dependency and can be tested independently:
cargo test
Development
The primary contributor workflow uses uv and a Rust toolchain. The package is
built as a PyO3 extension with Maturin; its public Python imports are unchanged.
uv sync --all-groups
Optional local environment files such as devenv.* and .envrc are kept for
maintainer convenience, but they are not required to build or test the project.
Pull requests should keep changes focused, include tests when behavior changes,
and use the conventional-commit title format already enforced by the repo, for
example fix: handle malformed result arrays or docs: expand README usage example.
Linting
uv run ruff format --check src tests
uv run ruff check src tests
uv run ty check src tests
Testing
cargo test
uv run pytest
The Python compatibility suite in tests/ is a permanent release gate for the
public bindings and verifies them against the original Python behavior. It
complements the Rust unit tests and should remain in CI. Both suites share the
fixtures in src/tests/data/ and run in CI. After editing Rust source, rebuild
the extension with uv sync --all-groups --reinstall-package qir-formatter
before running pytest.
The private extension stub is generated from the PyO3 declarations. Regenerate it after changing the Python binding surface:
uv run maturin generate-stubs --locked --out src
The normal check script regenerates the stub and fails in CI if the committed file is stale. Release wheels package the checked generated stub and exercise it through the installed-wheel tests.
Dependency Audit
uv audit --locked --preview-features audit
This scans pinned dependencies directly from uv.lock. The repo also
configures uv with a 7-day dependency cooldown so routine resolution avoids
newly uploaded packages while the ecosystem has time to surface supply-chain
issues.
Git Hooks
The repo includes a prek configuration in .pre-commit-config.yaml.
uvx prek install
uvx prek run --all-files
This runs ruff formatting and lint fixes, a ty type-check pass, and a small
set of builtin file hygiene checks before commit.
Support
For bug reports, feature requests, or questions about the public package, open an issue in the GitHub repository.
Release files for qir-formatter 0.3.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 | |
|---|---|---|---|
| qir_formatter-0.3.0.tar.gz | 53.7 kB | Details |
Built distributions (wheels)
| File | Reset | |||
|---|---|---|---|---|
| qir_formatter-0.3.0-cp310-abi3-win_amd64.whl | CPython 3.10 | abi3 | Windows x86-64 | Details |
| qir_formatter-0.3.0-cp310-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl | CPython 3.10 | abi3 | Linux glibc 2.17+ x86-64 | Details |
| qir_formatter-0.3.0-cp310-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl | CPython 3.10 | abi3 | Linux glibc 2.17+ ARM64 | Details |
| qir_formatter-0.3.0-cp310-abi3-macosx_11_0_arm64.whl | CPython 3.10 | abi3 | macOS 11.0+ ARM64 | Details |
| qir_formatter-0.3.0-cp310-abi3-macosx_10_12_x86_64.whl | CPython 3.10 | abi3 | macOS 10.12+ x86-64 | Details |
Total release size: 1.3 MB
Release files / qir_formatter-0.3.0.tar.gz
| Download URL | qir_formatter-0.3.0.tar.gz |
|---|---|
| Size | 53.7 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
b335e7c58bf68a32dd4fe5de6727dc9bc05510368a23ea9bb5b1a96a08aaea1d
|
|
BLAKE2b-256 checksum How to use checksums |
a27c92616774a27ea9f4a329d0ba9c51a447df7c50cffb2ce807fda10070a9b3
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
uv/0.12.18 {"installer":{"name":"uv","version":"0.12.18","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}
|
Release files / qir_formatter-0.3.0-cp310-abi3-win_amd64.whl
| Download URL | qir_formatter-0.3.0-cp310-abi3-win_amd64.whl |
|---|---|
| Size | 170.9 kB |
| Tags | CPython 3.10 Windows x86-64 abi3 |
|
SHA-256 checksum How to use checksums |
26b1437c7038ef9408c6e65fbab60fa5df0d3cd4d6602ffbe5a6f9f69b266985
|
|
BLAKE2b-256 checksum How to use checksums |
57b9eb3d26f40f0a32a7c02bb2c06bb17bb1240a4ddf6cfb3d4f34f25b9488bc
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
uv/0.12.18 {"installer":{"name":"uv","version":"0.12.18","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}
|
Release files / qir_formatter-0.3.0-cp310-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
| Download URL | qir_formatter-0.3.0-cp310-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl |
|---|---|
| Size | 276.3 kB |
| Tags | CPython 3.10 Linux glibc 2.17+ x86-64 abi3 |
|
SHA-256 checksum How to use checksums |
fa3449048614b4328f414b71252ee51c049a7e786b8f82e28a184b03eeadfe8b
|
|
BLAKE2b-256 checksum How to use checksums |
0ab77c3252a02d1442c5638d27521444d96857633216d750eb3be996884d6122
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
uv/0.12.18 {"installer":{"name":"uv","version":"0.12.18","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}
|
Release files / qir_formatter-0.3.0-cp310-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl
| Download URL | qir_formatter-0.3.0-cp310-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl |
|---|---|
| Size | 261.7 kB |
| Tags | CPython 3.10 Linux glibc 2.17+ ARM64 abi3 |
|
SHA-256 checksum How to use checksums |
5eb17d1e61a09e4f40dd744761ab7bdaa308630ac31f9797773644fd41f784ae
|
|
BLAKE2b-256 checksum How to use checksums |
a98ffff6e11c69275b1c18de6a8ff8ad084da1f11dbd69812daa2aa5836cc25d
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
uv/0.12.18 {"installer":{"name":"uv","version":"0.12.18","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}
|
Release files / qir_formatter-0.3.0-cp310-abi3-macosx_11_0_arm64.whl
| Download URL | qir_formatter-0.3.0-cp310-abi3-macosx_11_0_arm64.whl |
|---|---|
| Size | 246.8 kB |
| Tags | CPython 3.10 abi3 macOS 11.0+ ARM64 |
|
SHA-256 checksum How to use checksums |
f8c6dd036c88071090ce67a9ec7fcb0694e1bba4fe21a1f480bc58ab04b702fb
|
|
BLAKE2b-256 checksum How to use checksums |
7c1fbe41b9b6f7c204de872ce0a96016733de592b738c5bce9bdce23b796ec9b
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
uv/0.12.18 {"installer":{"name":"uv","version":"0.12.18","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}
|
Release files / qir_formatter-0.3.0-cp310-abi3-macosx_10_12_x86_64.whl
| Download URL | qir_formatter-0.3.0-cp310-abi3-macosx_10_12_x86_64.whl |
|---|---|
| Size | 248.3 kB |
| Tags | CPython 3.10 abi3 macOS 10.12+ x86-64 |
|
SHA-256 checksum How to use checksums |
c53cb72b047b39c34cd3667b8e77a11a0bae8950139d3a7c530b1f5f1b38133d
|
|
BLAKE2b-256 checksum How to use checksums |
690a96a721692a85110dab6c6a173038658606a9ba934f1860aee04dc425c6be
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
uv/0.12.18 {"installer":{"name":"uv","version":"0.12.18","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}
|