Keyboard shortcuts

Press ← or → to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Python Application Driver

RiffDB’s Python package is riffdb-application; application code imports riffdb_application. Wheels use the stable cp313-abi3 interface, so installing a wheel does not require Rust. Building the source distribution requires Rust 1.98.1.

The alpha release matrix is deliberately finite:

PythonPlatformArchitectureStatus
CPython 3.13 or 3.14manylinux 2.28 (glibc)x86_64Supported alpha wheel
CPython 3.13 or 3.14manylinux 2.28 (glibc)aarch64Supported alpha wheel
CPythonmusllinuxx86_64 or aarch64Unsupported
CPythonmacOSx86_64 or arm64Unsupported
CPythonWindowsx86_64 or arm64Unsupported
PyPyAnyAnyUnsupported

Unsupported combinations fail installation; there is no pure-Python transport fallback. The machine-readable source of truth, including the reason for each unsupported family, is release/python/platform-matrix-v1.json in the source distribution repository.

The package is application-only. It exposes generated named queries and typed commands through SyncApplicationTransport and AsyncApplicationTransport. It does not expose Protobuf stubs, kernel requests, administrative RPCs, SQL, or the private native module. Both transports delegate gRPC status validation, request identity, bounded retry, and uncertain-outcome behavior to the stable Rust application client.

The wheel’s in-process PyO3 transport and the local-socket driver use one first-party Rust protocol core. That core alone admits values, applies nesting, collection, string, and frame bounds, constructs typed query and command requests, and classifies public failures. Python keeps its self-contained wheel and does not require riffdb-driverd; it also cannot accept a value the socket driver would reject. One collection is limited to 4,096 values, one string to 262,144 UTF-8 bytes, and enum names use the closed generated-symbol alphabet. Compiled operation schemas may impose stricter limits.

Generated named queries that the compiler proves fully covered negotiate a compact result from the native transport. The generated synchronous and asynchronous decoders validate the exact plan-owned entity, field order, cardinality, row width, enum values, and bounds before constructing the same dataclasses directly. No ordinal or physical-index choice is exposed to Python, and legacy named-record results remain accepted.

AsyncApplicationTransport also backs Application Source V5 generated event iterators and live named-query iterators. Generated delivery types retain the attempt-specific acknowledgement evidence, and live cursors are returned as standard padded Base64 for persistence. See Reactive Application Clients.

Generated synchronous and asynchronous command batch methods accept CommandBatchOptions(concurrency=...) from 1 through 384 and at most 4,096 inputs. Each item remains an ordinary independently authorized and idempotent command; the collection is not one transaction.

Create an application

Build or obtain the matching RiffDB wheel, then create a source-layout project:

export RIFFDB_APPLICATION_WHEEL=/path/to/riffdb_application-0.1.0-cp313-abi3-linux_x86_64.whl
riffdb new my-app --language python
cd my-app
uv sync --locked
PYTHONPATH=src uv run --locked python -m unittest discover -s tests

Installed release bundles place the architecture-matching wheel under public/python; the environment variable is only needed by a source-tree CLI that has no installed bundle. The scaffold copies the wheel into vendor/, pins its SHA-256 in uv.lock, and performs no registry lookup during uv sync --locked.

Run the generated example after deploying and binding its application role:

PYTHONPATH=src uv run --locked python -m my_app \
  http://127.0.0.1:50051 \
  .riffdb/development/credentials/MyAppApplication.credential \
  my_database

riffdb dev --run supplies those same three values as both positional arguments and the runner-owned RIFFDB_ENDPOINT, RIFFDB_CREDENTIAL_FILE, and RIFFDB_DATABASE environment. A runner that accepts both forms must reject a mismatch. Go and TypeScript do not receive these variables because their application process is confined to the private driver-host protocol.

Credentials are Rust-owned, redacted, nonextractable, non-pickleable objects. Use BearerCredential.from_protected_file() for a mode-0600 Linux credential. Use CallMetadata.with_database(DatabaseAlias("my_database")) to select one database before authentication.

For an authenticated remote listener, configure explicit private-CA trust; Python never falls back to native roots or a trust-all mode:

from riffdb_application import SyncApplicationTransport, VerifiedTlsConfig

tls = VerifiedTlsConfig(
    endpoint="https://riffdb.internal:7443",
    trust_root="/run/secrets/riffdb-ca.pem",
    server_name="riffdb.internal",
    pool_connections=4,
    streams_per_connection=64,
)
with SyncApplicationTransport.connect_verified_tls(tls, metadata) as transport:
    client = MyAppClient(transport, AttemptBudget(3))

The asynchronous transport exposes the same verified-TLS constructor. Pool connections are bounded from 1 through 16 and streams per connection from 1 through 256 before native transport work begins.

Existing applications

Application source v1 remains exact and does not gain Python implicitly. Preview the explicit source-only migration:

riffdb application migrate --to v2

Write only the source manifest after review:

riffdb application migrate --to v2 --write
riffdb application lock --write
riffdb application lock --check

The migration command never writes a lock or generated artifact and never contacts a server. Source v2 requires generation.python; lock v2 contains one Python artifact path and digest. Normal lock review remains the only operation that publishes compiler-derived identities and generated bytes.

Direct installation

Install a released wheel with either tool:

python3 -m pip install ./riffdb_application-0.1.0-cp313-abi3-manylinux_2_28_x86_64.whl
uv pip install ./riffdb_application-0.1.0-cp313-abi3-manylinux_2_28_x86_64.whl

Source installation is conventional but compiles the bundled Rust dependency graph:

RUSTUP_TOOLCHAIN=1.98.1 python3 -m pip install ./riffdb_application-0.1.0.tar.gz

Publishing to PyPI is intentionally a separate maintainer action. The POC release pipeline produces and verifies artifacts but holds no upload token.

Maintainers build both wheels and the self-contained source distribution with:

scripts/build-python-distribution dist/python

The build also writes riffdb-python-artifacts-v1.json, a deterministic receipt containing the platform-matrix digest and the name, SHA-256, and byte length of each artifact. The sdist contains only the pinned Rust application-client closure (including the shared driver host and operation registry), required persistent Protobuf fixtures, licenses, and Python package; it does not copy the repository or depend on a checkout. The release checks install the wheel with Rust absent from PATH and install the sdist with Cargo network access disabled.

That command defaults to manylinux_2_28. Local development hosts that are not manylinux build environments can set RIFFDB_PYTHON_COMPATIBILITY=linux for a non-release smoke artifact. The pinned GitHub workflow builds and installs the x86_64 and aarch64 cp313-abi3 wheels on CPython 3.13 and 3.14; it never publishes them. Maintainers can run the same focused checks with:

./scripts/build-python-distributions --check
./scripts/test-python-platform-matrix