Skip to main content

Async, typed Python data connector for AuraDB and existing databases.

Project description

Aura Connector

A typed async data connector for AuraDB and existing databases.

CI Native PyPI Python License Typed Ruff

Aura Connector is an async, typed Python data connector that gives teams one model and query API across AuraDB, SQLite, PostgreSQL, MySQL/MariaDB, MongoDB, Redis, and an in-memory reference backend. Declare typed models once, compose queries with a fluent, injection-safe builder, and run them against whichever backend you choose by changing only the DSN.

AuraDB remains the native, high-performance backend with the strongest path through the Aura Wire Protocol; the backend adapters make Aura useful immediately with infrastructure you already run. Feature differences between backends are represented honestly through backend capabilities — unsupported features raise a structured error rather than being emulated.

It is useful today with zero setup: the package ships an in-memory reference server and first-class SQLite support, so the examples and the full default test suite run with no external database and no compiler.

import asyncio
from aura import Aura, Model, Field, Vector


class Workspace(Model):
    id: int = Field(primary_key=True)
    name: str


class Document(Model):
    id: int = Field(primary_key=True)
    workspace: Workspace = Field(link=True)
    title: str
    body: str
    embedding: Vector[3]


async def main() -> None:
    async with Aura.connect(
        "aura+memory://localhost/app", models=[Workspace, Document]
    ) as client:
        ws = await client.insert(Workspace(id=1, name="Acme"))
        await client.bulk_insert(
            Document,
            [
                Document(id=1, workspace=ws, title="Refunds", body="...", embedding=[1, 0, 0]),
                Document(id=2, workspace=ws, title="Billing", body="...", embedding=[0, 1, 0]),
            ],
        )

        # Typed, injection-safe query building.
        docs = await (
            client.query(Document)
            .where(Document.title.contains("Refund"))
            .order_by(Document.id.desc())
            .limit(10)
            .all()
        )

        # Vector nearest-neighbour search.
        matches = await (
            client.search(Document)
            .nearest(Document.embedding, [1, 0, 0], metric="cosine")
            .limit(5)
            .all()
        )
        print(docs, matches)


asyncio.run(main())

Why Aura Connector matters

Python data access usually forces a trade. ORMs give you typed models and ergonomics but hide the wire and leak lazy queries. Raw drivers give you control but hand back untyped tuples and string SQL. Vector search lives in yet another SDK with its own client. Aura Connector unifies these behind one typed, async client:

  • One typed client for relational, document, vector, hybrid, and graph access.
  • Async-first. asyncio is the primary execution model, not a wrapper.
  • Explicit relationship loading. No hidden lazy network IO. .include() is required, and accessing an unloaded relationship raises a clear error.
  • Injection-safe by construction. Queries compile to an immutable AST and Query IR, never to concatenated strings.
  • Deterministic binary protocol. Frames are golden-tested, length-bounded, and checksummed.
  • Honest performance. A complete pure-Python core with reproducible benchmarks, plus optional in-repository native acceleration with a fallback that is always available.

Problems it solves

  • Replaces three separate libraries (ORM, driver, vector SDK) with one typed surface.
  • Removes the N+1 surprise by making relationship loading explicit.
  • Keeps queries safe without forcing you to hand-write parameter binding.
  • Makes schema changes reviewable: diff two model versions into a migration plan and gate destructive changes in CI before anything runs.
  • Gives you metrics, latency percentiles, and secret-free query fingerprints in-process, with an optional OpenTelemetry bridge.

How it compares

Tool Typed models Async-native Injection-safe builder Vector fields Wire protocol control
SQLAlchemy yes partial yes via extensions abstracted
Django ORM yes partial yes via extensions abstracted
psycopg / asyncpg no yes (asyncpg) manual binding no low level
Prisma-style clients yes yes yes partial abstracted
Vector database SDKs partial varies no yes per vendor
Aura Connector yes yes yes first-class deterministic, documented

The comparison describes design focus, not a benchmark. Each tool above is excellent at its own goals.

What Aura Connector is and is not

It is a production-grade client and connector: model system, query builder, binary protocol, transports, hydration, migrations tooling, observability, and a CLI, with a pure-Python core and optional native acceleration.

It is not a database server. AuraDB server features (storage, distributed transactions, server-side cost-based planning, lock and impact estimation on a live cluster) live in a separate project and are not implemented or claimed here. See AuraDB boundary.

Installation

The base install is dependency-free and includes the AuraDB protocol and in-memory backends. Add an extra for each database backend you want to use:

pip install aura-connector                 # core: AuraDB protocol + in-memory backend
pip install "aura-connector[sqlite]"       # SQLite        (aiosqlite)
pip install "aura-connector[postgres]"     # PostgreSQL    (asyncpg)
pip install "aura-connector[mysql]"        # MySQL/MariaDB (aiomysql)
pip install "aura-connector[mongodb]"      # MongoDB       (motor)
pip install "aura-connector[redis]"        # Redis         (redis.asyncio)
pip install "aura-connector[sql]"          # SQLite + PostgreSQL + MySQL
pip install "aura-connector[all-db]"       # every database driver
pip install "aura-connector[native]"       # + optional native acceleration tooling

Selecting a backend whose driver is not installed raises AuraDriverNotInstalledError with the exact install command. The import package name is aura:

import aura

Development install from a clone:

python -m pip install -e ".[dev,sqlite]"

Requires Python 3.11 or newer. The pure-Python path needs no compiler. Optional native acceleration (CRC32 plus f32 vector packing) lives in this repository under crates/aura_native and is built with maturin (requires a Rust toolchain):

maturin develop --manifest-path crates/aura_native/Cargo.toml --release
aura doctor   # native_acceleration: available

See Native acceleration.

Backends

The DSN scheme selects the backend — nothing else in your code changes:

Scheme(s) Backend Extra
auradb://, auradbs:// AuraDB v0.2.0 server (native AWP 1 over TCP/TLS) — auth + TLS
aura://, auras://, aura+tcp:// AuraDB reference protocol path (bundled; not the v0.2.0 server)
aura+memory://, memory:// In-memory reference engine
sqlite://, sqlite+aiosqlite:// SQLite (first-class local) [sqlite]
postgres://, postgresql://, postgresql+asyncpg:// PostgreSQL [postgres]
mysql://, mariadb://, …+aiomysql:// MySQL / MariaDB [mysql]
mongodb://, mongodb+motor:// MongoDB (document-native) [mongodb]
redis://, redis+asyncio:// Redis (limited key-value / cache) [redis]

See docs/BACKENDS.md and the capability matrix. Summary:

Capability AuraDB Memory SQLite PostgreSQL MySQL MongoDB Redis
CRUD + filters yes yes yes yes yes yes by key
Transactions yes yes yes yes yes no¹ no
Relationships yes yes yes yes yes yes no
JSON / document fields yes yes yes² yes² yes² yes yes
Vector / hybrid search yes yes no no no no³ no
Graph traversal yes yes no no no no no

¹ MongoDB transactions require a replica set. ² SQL backends store JSON/vector fields as JSON text (the documented fallback). ³ MongoDB vector search requires a configured vector index. Unsupported features raise AuraBackendCapabilityError — they are never silently emulated.

Native AuraDB backend (AuraDB v0.2.0)

The auradb:// (plaintext) and auradbs:// (TLS) schemes connect to a running AuraDB v0.2.0 server over the Aura Wire Protocol version 1, including static-token authentication, TLS, and transactions with read-your-writes:

from aura import connect
from aura.config import TokenAuth, TLSConfig

async with connect(
    "auradbs://db.example.com:7171/app",
    models=[User],
    auth=TokenAuth("my-secret-token"),
    tls=TLSConfig(enabled=True, ca_cert_path="/etc/aura/ca.pem"),
) as client:
    async with client.transaction() as tx:
        await tx.insert(User(id=1, email="ada@example.com"))
        # Read-your-writes: visible inside the transaction, not outside until commit.
        assert await tx.query(User).where(User.id == 1).count() == 1

Compatibility: Aura Connector 0.3.x talks to AuraDB 0.2.x over AWP 1. Aura Connector 0.2.x does not speak the new authenticated, TLS-capable native AWP path and cannot connect to an AuraDB v0.2.0 server — upgrade to 0.3.x. The legacy aura:// schemes use the connector's bundled reference protocol path, not the AuraDB v0.2.0 network server. See docs/AURADB.md.

Quick start

The fastest start needs no external service — SQLite (local) or the in-memory reference engine. Switch to AuraDB or another database by changing only the DSN.

import asyncio
from aura import Aura, Model, Field

class User(Model):
    id: int = Field(primary_key=True)
    email: str = Field(unique=True, index=True)
    display_name: str | None = Field(default=None)

async def main() -> None:
    # SQLite — first-class local backend, no server required.
    async with Aura.connect("sqlite:///app.db", models=[User]) as db:
        await db.insert(User(id=1, email="ada@example.com", display_name="Ada"))
        ada = await db.User.find(id=1)
        print(ada.display_name)

asyncio.run(main())

The same code runs against other backends by changing the DSN:

# PostgreSQL
async with Aura.connect("postgresql://user:pass@localhost:5432/app", models=[User]) as db:
    users = await db.query(User).where(User.email.endswith("@example.com")).all()

# MongoDB (document-native)
async with Aura.connect("mongodb://localhost:27017/app", models=[User]) as db:
    await db.insert(User(id=2, email="grace@example.com"))

# In-memory reference engine (tests, examples, local dev)
async with Aura.connect("aura+memory://localhost/app", models=[User]) as db:
    await db.ping()

# AuraDB — the native, high-performance target (TLS)
async with Aura.connect("auras://cluster:7171/app", models=[User]) as db:
    await db.ping()

Model example

from aura import Model, Field, Vector


class User(Model):
    id: int = Field(primary_key=True)
    email: str = Field(unique=True, index=True)
    display_name: str | None = Field(default=None)
    embedding: Vector[512] | None = None

Query example

cheap = await (
    client.query(Product)
    .where(Product.price_cents < 5000)
    .order_by(Product.price_cents.asc())
    .all()
)

await client.update(Product).where(Product.id == 2).set(price_cents=2499).execute()

total = await client.query(Product).count()
exists = await client.query(Product).where(Product.id == 3).exists()

Vector example

matches = await (
    client.search(Document)
    .nearest(Document.embedding, query_vector, metric="cosine")
    .limit(10)
    .all()
)

Supported metrics are cosine, euclidean, and dot. See Vectors.

Migration example

from aura import diff_schemas, generate_migration, schema_document

plan = generate_migration(old_models, new_models)
print(plan.format())
plan.require_safe()   # raises AuraMigrationError if the plan is destructive

The same gate is available in CI through aura migrate diff --require-safe. See Migrations.

Observability example

async with Client.connect(
    "aura+memory://localhost/shop",
    models=[Product],
    telemetry={"opentelemetry": True, "capture_query_ir": "redacted"},
) as client:
    await client.query(Product).filter(Product.price_cents > 500).all()
    snapshot = client.metrics.snapshot()   # counts, latency p50/p95/p99, bytes, retries

Query fingerprints are stable across bound values and never contain the values themselves. See Observability.

CLI example

The package installs an aura console script for offline, server-independent tasks:

aura version
aura doctor                                            # environment, deps, native status
aura schema compile --app myapp.models --out schema.json
aura migrate diff --from old.json --to myapp.models --require-safe
aura explain file query-ir.json                        # client-side static plan
aura bench local --iterations 20000                    # in-process micro-benchmarks
aura generate stubs --models myapp/models.py           # faithful .pyi from models

See CLI.

Native acceleration

The pure-Python core is the complete, benchmarked baseline and is always available. An optional in-repository Rust/PyO3 extension accelerates two byte-exact hot paths (frame CRC32 and fixed-dimension f32 vector packing) when built and installed. The public API and all observable behaviour are identical with or without it, parity is enforced by tests, and AURA_DISABLE_NATIVE=1 forces the pure-Python path.

No zero-copy behaviour is claimed, and the native path is not always faster: in the included benchmark, CRC32 through the native path can be slower than Python's optimized zlib routine on some inputs, while vector packing is faster. Measure on your own hardware. See Native acceleration.

AuraDB boundary

This package is the client and connector. AuraDB server features are a separate future project. Operations that require a live cluster (applying migrations, server-side cost estimation, distributed transaction coordination) fail with a structured error rather than pretending to succeed. See AuraDB boundary.

Documentation

Benchmarks

The benchmarks/ directory contains real, in-process micro-benchmarks for protocol encode/decode, model hydration, Query IR construction, vector serialization, an end-to-end round trip through the reference transport, and pure-Python versus native acceleration. They print measured timings on your machine:

python benchmarks/bench_protocol.py
python benchmarks/bench_native_acceleration.py

Numbers vary by hardware. The benchmarks contain no precomputed or fabricated results.

Testing

python -m pytest -vv

The suite is deterministic and requires no external services. It covers models, fields, vectors, schema generation, the query builder, protocol frames and golden bytes, transports, client lifecycle, hydration, errors, migrations, observability, typing, and example smoke tests. See Testing.

Security

The client validates and length-bounds every protocol frame, fails closed on protocol errors, never embeds secrets in errors or logs, and redacts credentials in configuration repr. To report a vulnerability, see SECURITY.md.

Contributing

Contributions are welcome. See CONTRIBUTING.md for setup, the dev and native build, test commands, and code style. Please also read our Code of Conduct.

License

Apache-2.0. See LICENSE.

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

aura_connector-0.3.0.tar.gz (137.2 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

aura_connector-0.3.0-py3-none-any.whl (125.0 kB view details)

Uploaded Python 3

File details

Details for the file aura_connector-0.3.0.tar.gz.

File metadata

  • Download URL: aura_connector-0.3.0.tar.gz
  • Upload date:
  • Size: 137.2 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for aura_connector-0.3.0.tar.gz
Algorithm Hash digest
SHA256 9dda33e43f088cd6504b598ddce3ba0989831935979d7d570997729383252fd8
MD5 fea4398bd74843cea890d66f9e62a3bb
BLAKE2b-256 22df891fe96bf6c744c2d561fc55820aa00132c63d6e1ebe8a0f29abbb3ffce5

See more details on using hashes here.

Provenance

The following attestation bundles were made for aura_connector-0.3.0.tar.gz:

Publisher: publish.yml on Ohswedd/aura-connector

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file aura_connector-0.3.0-py3-none-any.whl.

File metadata

  • Download URL: aura_connector-0.3.0-py3-none-any.whl
  • Upload date:
  • Size: 125.0 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for aura_connector-0.3.0-py3-none-any.whl
Algorithm Hash digest
SHA256 d874bb3c6ff4d8694be27c723468e812f999ef157909cdf526942974532c9d56
MD5 ff9f6c9843f3fd9fd8bc12dd40cc2620
BLAKE2b-256 a221cc0f4745d011f20b1d46b235fcccb07d5273924602ed8c368a70dddd13d2

See more details on using hashes here.

Provenance

The following attestation bundles were made for aura_connector-0.3.0-py3-none-any.whl:

Publisher: publish.yml on Ohswedd/aura-connector

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page