Skip to main content

sqlalchemy-libsql-native

SQLAlchemy compatibility DBAPI facade + dialect for remote libSQL (Turso managed libSQL / Hrana).

Note: This repository is a read-only release mirror. Development happens in the private Keelson monorepo; issues are welcome here, but pull requests are not accepted — changes land through the next release.

Wraps the frozen upstream driver (libsql==0.1.11, exact pin) without forking it, and adds the minimal contract SQLAlchemy needs for exception classification and disconnect recovery.

This is a bridge, not a permanent artifact: it exists to make the current frozen driver usable with SQLAlchemy today, and is expected to shrink or retire as upstream grows a real DBAPI surface. Full PEP 249 conformance is not claimed; the goal is limited to making SQLAlchemy's exception-classification and disconnect-recovery machinery work correctly.

Design goals:

  • Raw driver errors (builtins.ValueError) are classified into a PEP 249-shaped exception hierarchy, structured SQLITE_CONSTRAINT* codes taking priority over message text, with an unknown error failing closed to DatabaseError.
  • Hrana stream loss/expiry maps to OperationalError so SQLAlchemy's is_disconnect / pool_pre_ping invalidation and recovery work; nothing else is ever treated as a disconnect.
  • The dialect owns the URL/argument contract and the pool policy (NullPool for remote URLs by default); the adapter never retries on the caller's behalf.
  • Deterministic, self-contained fault injection (no external services beyond Docker) proves the above, including commit ambiguity on a lost commit acknowledgement.

Invariants

  • The package is standalone: no imports from any host application; shipped helpers (sqlalchemy_libsql_native.testing) let downstream test harnesses import them without a dependency on this repo's test-only files.
  • No cloud credentials in this package.
  • Driver is exact-pinned (libsql==0.1.11); supported SQLAlchemy versions are >=2.0.51,<2.1.
  • src/ layout, hatchling build backend, Python >=3.12,<3.13.

Layout

pyproject.toml
src/sqlalchemy_libsql_native/
  __init__.py
  errors.py     # PEP 249-shaped exception hierarchy
  classify.py   # raw builtins.ValueError -> facade exception (structured code first)
  dbapi.py      # ConnectionProxy / CursorProxy facade (connect args, raising attribute boundaries)
  dialect.py    # import_dbapi / create_connect_args / on_connect / is_disconnect / pool policy
  testing.py    # generic Tier 2/3 helpers: local sqld + fault injection + asserts
tests/
  test_errors.py test_classify.py test_dbapi.py test_dialect.py   # Tier 0 unit
  test_file_integration.py                                        # Tier 1 (real driver, file SQLite)
  test_local_sqld_integration.py                                  # Tier 2 (real driver, local Hrana)

Running the tests

Test tiers: Tier 0 — pure-Python unit tests (no driver). Tier 1 — real driver against an embedded file SQLite DB (no network). Tier 2 — real driver against a local libsql-server (Hrana) in Docker. Tier 3 — downstream integration against a real managed deployment; those suites live outside this package but reuse the shipped sqlalchemy_libsql_native.testing helpers.

Tier 0 + Tier 1 (self-contained, no server — always green)

uv sync --group dev
uv run pytest tests/ -q

Tier 0 (classify/errors) is pure Python. Tier 1 exercises the real libsql==0.1.11 driver against an embedded file SQLite DB (no network). Tier 2 below skips with a reason when Docker is unavailable, so this command stays green everywhere.

Tier 2 (local libsql-server / Hrana — needs Docker)

Reproduces the remote transport that file mode cannot: remote constraint classification (a), transparent disconnect recovery (b), and the three fault-injection points. Self-contained (a local server in Docker — no Turso Cloud, no credentials).

# Requires: `docker` on PATH + a running Docker daemon.
uv run pytest tests/test_local_sqld_integration.py -v

The server image is pinned by tag + digest (a moved tag cannot silently change the image):

ghcr.io/tursodatabase/libsql-server:v0.24.32
  @sha256:dedf5273da945d90f3b85fe367ed8f821349117ac2c488bf43c4a6bf9f2123e0

Auxiliary observations:

  • Natural idle stream-expiry (~330–360 s: 10 s expiration + 300 s cleanup) is the slow, non-deterministic counterpart to the deterministic (b) injection. It is opt-in (default-skipped): run with LIBSQL_NATIVE_SLOW_EXPIRY=1.
  • (c) concurrent writes is observation only — success is not asserted; the invariant is only that any surfaced error is facade-classified (never a raw ValueError). On v0.24.32 the collapse surfaces as TRANSACTION_TIMEOUT (→ DatabaseError) / occasionally STREAM_EXPIRED (→ OperationalError).

Commit-response disconnect injection

The "cut at commit response" fault (point="commit_response" in sqlalchemy_libsql_native.testing) runs the real commit first — so the write is durably applied server-side — and only then injects the disconnect, modelling a lost acknowledgement. The Tier 2 test proves the resulting ambiguity concretely: the caller receives a classified OperationalError, yet the row is present when read back through a fresh connection, so "failure" does not mean "rolled back" and a naive retry would double-apply. This is deterministic and self-contained (no extra service). A network-level proxy (Toxiproxy) is documented in testing.py as the higher-fidelity Tier 3 alternative; point="commit" is the complementary request-side loss (fails before the commit reaches the server → not applied). In all cases the connection is invalidated and the adapter does not retry — retry policy is deliberately left to the caller.

Generic test helpers (sqlalchemy_libsql_native.testing)

The sqld launcher, fault injector, and classification asserts live in the shipped package (not tests/) so downstream test harnesses can import them from the installed distribution without a dependency on this repo's test-only files. Key surface: LibsqlServer, fault_injecting_engine, FaultController, docker_available, assert_integrity_surfaced, assert_disconnect_surfaced.

Metadata

Release files for sqlalchemy-libsql-native 0.1.0

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

Source distribution (sdist)

Source distribution for sqlalchemy-libsql-native 0.1.0
File Size Uploaded
sqlalchemy_libsql_native-0.1.0.tar.gz 34.2 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for sqlalchemy-libsql-native 0.1.0
File Interpreter ABI Platform
sqlalchemy_libsql_native-0.1.0-py3-none-any.whl Python 3 none any Details

Total release size: 63.3 kB

Release files / sqlalchemy_libsql_native-0.1.0.tar.gz

Download URL sqlalchemy_libsql_native-0.1.0.tar.gz
Size 34.2 kB
Tags Source
SHA-256 checksum
How to use checksums
f03eba4bf75b9c8c69d6c7e65af833c5b8165f9dc17a7dbd363eff4ede044ca1
BLAKE2b-256 checksum
How to use checksums
f18c7a9768d143149534b92372a935ebf513c7ccf2ecbb6046d204f02731137e
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 Aug 16, 2026.

Transparency log

Release files / sqlalchemy_libsql_native-0.1.0-py3-none-any.whl

Download URL sqlalchemy_libsql_native-0.1.0-py3-none-any.whl
Size 29.2 kB
Tags Python 3
SHA-256 checksum
How to use checksums
b720113b64a22c8aba99c82d00210cb5643aa7a1994fdf5b4547f234f27b12ab
BLAKE2b-256 checksum
How to use checksums
fdfabb5ea6d42c3a9e50546f73044c6170ebf3df3144fdfa94bf5139fc134ba4
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 Aug 16, 2026.

Transparency log

Release history Release notifications | RSS feed

This release

0.1.0 This release

2 release files

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