Skip to main content

murr-python

Async Python client for murr, a RocksDB-based NVMe/S3 cache for AI inference workloads.

The client is pure Python: it talks to a murr server over HTTP, with Arrow IPC for data and JSON for schemas. Version 0.3.1 of the client needs a server of version 0.3.1 or newer, which is where reads became sparse.

Install

pip install murr

Quickstart

Start a server:

docker run -p 8080:8080 ghcr.io/murrdb/murr:0.3.1

and then:

import asyncio

import pyarrow as pa
from murr.client import Client, ColumnSchema, DType, TableSchema


async def main():
    async with Client("http://localhost:8080") as db:
        await db.create_table("docs", TableSchema(columns={
            "id":       ColumnSchema(dtype=DType.UTF8, nullable=False, key=True),
            "score":    ColumnSchema(dtype=DType.FLOAT32),
            "category": ColumnSchema(dtype=DType.UTF8),
        }))

        await db.write("docs", pa.table({
            "id":       ["doc_1", "doc_2", "doc_3"],
            "score":    pa.array([0.95, 0.72, 0.68], pa.float32()),
            "category": ["ml", "infra", "ops"],
        }))

        result = await db.read("docs", {"id": ["doc_3", "nope", "doc_1"]}, columns=["score", "category"])
        print(result.to_pandas())


asyncio.run(main())

# Output: only found keys come back, _idx is the position of the key in the request
#    _idx  score category
# 0     0   0.68      ops
# 1     2   0.95       ml

read returns a pyarrow.Table with an _idx column and then the requested columns, one row per key which was found. A missing key has no row, and rows come in no particular order: _idx (uint32, exported as IDX_COLUMN) is the position of the row's key in the request, so join on it.

API

Method What it does
create_table(name, schema) Create a table
drop_table(name) Drop a table
list_tables() All tables as {name: TableSchema}
get_schema(name) Schema of one table
write(table, data) Write a pa.Table or pa.RecordBatch
read(table, keys, columns) Read columns for the keys which are found
compact(table) Compact a table, returns when it is done

All methods are coroutines. There is no blocking client: wrap a call in asyncio.run if you need one.

Schemas

A column has a dtype, and optional nullable (default True), key (default False) and strict (default True) flags. Supported dtypes are utf8, bool, int8 to int64, uint8 to uint64, float32 and float64.

A table needs at least one key column. Key columns must be nullable=False and of a utf8 or integer dtype. The column name _idx is reserved for the read result. Several key columns form a compound key:

schema = TableSchema(columns={
    "user":  ColumnSchema(dtype=DType.UTF8,  nullable=False, key=True),
    "item":  ColumnSchema(dtype=DType.INT64, nullable=False, key=True),
    "score": ColumnSchema(dtype=DType.FLOAT64),
})

await db.create_table("ratings", schema)
await db.read("ratings", {"user": ["u1", "u2"], "item": [1, 7]}, columns=["score"])

Keys

Keys go to the server as an Arrow table with one column per key column. Pass a pa.Table, a pa.RecordBatch, or a {name: values} mapping which is turned into a table with pa.table().

The server widens types (an int32 array is fine for an int64 key) but never narrows them. Python ints become int64, so a narrower key column needs a typed array:

await db.read("events", {"id": pa.array([1, 2], pa.int32())}, columns=["flag"])

The same holds for writes, with one addition: writing float64 values into a float32 column rounds them, and is only accepted for a column created with strict=False.

Errors

Server errors are raised as subclasses of MurrError, which carries the HTTP status_code and the server message:

Exception When
TableNotFoundError the table does not exist
TableAlreadyExistsError create_table for an existing name
InvalidRequestError bad schema, wrong key types, unknown column
ServerError the server failed to process the request

Development

uv sync --extra dev
uv run pytest tests/ -v

The tests start ghcr.io/murrdb/murr:0.3.1 in Docker through testcontainers. Set MURR_IMAGE to test against another image, or MURR_ENDPOINT to use a server which is already running.

Releases

Set version in pyproject.toml and push a matching v<version> tag, like v0.3.1. The release workflow runs the tests, checks that the tag matches the package version, publishes the sdist and wheel to PyPI, and then creates a GitHub release.

License

Apache-2.0.

Metadata

Release files for murr 0.3.1

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

Source distribution (sdist)

Source distribution for murr 0.3.1
File Size Uploaded Provenance Actions
murr-0.3.1.tar.gz 54.5 kB Without provenance Details for murr-0.3.1.tar.gz

Built distribution (wheel)

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

Total release size: 65.8 kB

Release files / murr-0.3.1.tar.gz

Download URL murr-0.3.1.tar.gz
Size 54.5 kB
Tags Source
SHA-256 checksum
How to use checksums
99f6876c723246e6b14f768afab321c71f079fe18f23c9d5204f519bd4fbda47
BLAKE2b-256 checksum
How to use checksums
5846fff5294449bd99ba960e08d049e131a3303e438d2e28dde71f362cc8cc29
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via uv/0.12.23 {"installer":{"name":"uv","version":"0.12.23","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 / murr-0.3.1-py3-none-any.whl

Download URL murr-0.3.1-py3-none-any.whl
Size 11.3 kB
Tags Python 3
SHA-256 checksum
How to use checksums
81b5e46ab032c9b63367caba92d30e389e9ab4b7785f431959462f08f14a07b4
BLAKE2b-256 checksum
How to use checksums
b371fdc65b0bea6ab7e89a1de549374ff472914be0249800aae4e75e42e929a3
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via uv/0.12.23 {"installer":{"name":"uv","version":"0.12.23","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}

Security for murr 0.3.1

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.

No provenance found

None of the files in this release were uploaded with provenance metadata.

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

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