Skip to main content

Python bindings for the Lora in-memory graph database

Project description

lora-python

Python bindings for the Lora graph engine. Ships both a synchronous PyO3 Database class and an asyncio-compatible AsyncDatabase wrapper that never blocks the event loop.

Package: lora-python.

Install (local dev)

cd crates/bindings/lora-python
python3 -m venv .venv && source .venv/bin/activate
pip install -U pip maturin pytest pytest-asyncio
maturin develop         # builds the Rust extension into the venv
pytest                  # runs the sync + async smoke tests

maturin develop produces a lora_python/_native.<platform>.so inside the package and makes import lora_python work immediately.

Sync usage

from lora_python import Database, is_node

db = Database.create()
db.execute("CREATE (:Person {name: $n, age: $a})", {"n": "Alice", "a": 30})

res = db.execute("MATCH (n:Person) RETURN n")
for row in res["rows"]:
    n = row["n"]
    if is_node(n):
        print(n["properties"]["name"])

Initialization rule:

from lora_python import Database

scratch = Database.create()            # in-memory
persistent = Database.create("app", {"database_dir": "./data"})  # persistent: ./data/app.loradb

If you want persistence, pass a database name and database_dir to Database.create(...) or Database(...).

Explain & Profile

db.explain() and db.profile() are first-class methods alongside db.execute(). They are intentionally separate calls — neither routes through execute() — so plan inspection and runtime metrics must be requested explicitly.

plan = db.explain(
    "MATCH (p:Person) WHERE p.name = $name RETURN p",
    {"name": "Alice"},
)
print(plan["shape"])             # "readOnly"
print(plan["tree"]["operator"])  # top-most operator label

profile = db.profile(
    "MATCH (p:Person) WHERE p.name = $name RETURN p",
    {"name": "Alice"},
)
print(profile["metrics"]["total_elapsed_ns"])
print(profile["metrics"]["per_operator"])  # per-step inclusive timing

explain() never invokes the executor — calling it on a mutating query (CREATE, MERGE, SET, DELETE, REMOVE) leaves the graph untouched.

profile() executes the query for real. Mutating queries produce the same side effects as execute(). Use explain() to inspect a mutating plan without running it.

Async usage (non-blocking)

import asyncio
from lora_python import AsyncDatabase

async def main():
    db = await AsyncDatabase.create()
    await db.execute("CREATE (:Person {name: 'Alice'})")
    r = await db.execute("MATCH (n:Person) RETURN n.name AS name")
    print(r["rows"])

asyncio.run(main())

Async initialization follows the same rule:

db = await AsyncDatabase.create()            # in-memory
db = await AsyncDatabase.create("app", {"database_dir": "./data"})  # persistent: ./data/app.loradb

AsyncDatabase.execute dispatches the query onto the default asyncio thread pool via asyncio.to_thread. The PyO3 Database.execute releases the Python GIL for the duration of engine work, so other coroutines on the event loop can progress while a query runs. A dedicated test proves the event loop continues ticking during a 2 000-node MATCH.

Typed value model

Same conceptual contract as lora-node / lora-wasm:

Python shape Lora value
None, bool, int, float, str scalars
list, dict collections
{"kind": "node", "id", "labels", "properties"} node
{"kind": "relationship", "id", …} relationship
{"kind": "path", "nodes": [...], "rels": [...]} path
{"kind": "date", "iso": "YYYY-MM-DD"} (and time, …) temporal
point dicts — see below point

Points are returned as dicts keyed on their CRS:

SRID Dict
7203 {"kind": "point", "srid": 7203, "crs": "cartesian", "x", "y"}
9157 {"kind": "point", "srid": 9157, "crs": "cartesian-3D", "x", "y", "z"}
4326 {"kind": "point", "srid": 4326, "crs": "WGS-84-2D", "x", "y", "longitude", "latitude"}
4979 {"kind": "point", "srid": 4979, "crs": "WGS-84-3D", "x", "y", "z", "longitude", "latitude", "height"}

Constructors and guards are exported from lora_python.types: date, time, localtime, datetime, localdatetime, duration, cartesian, cartesian_3d, wgs84, wgs84_3d, is_node, is_relationship, is_path, is_point, is_temporal.

distance() on WGS-84-3D points ignores height — see functions reference for the full spatial reference and known limitations.

Errors

  • LoraError — base class
  • LoraQueryError — parse / analyze / execute failure
  • InvalidParamsError — a parameter value couldn't be mapped

All three are available as lora_python.LoraError, etc.

Persistence

Database.create("app", {"database_dir": "./data"}), Database("app", {"database_dir": "./data"}), and await AsyncDatabase.create("app", {"database_dir": "./data"}) open or create an archive-backed persistent database at ./data/app.loradb. Reopening the same path replays committed writes before returning the handle.

Call db.close() / await db.close() before reopening the same archive inside one process.

For explicit WAL directories with managed snapshots, use open_wal:

db = Database.open_wal(
    "./data/wal",
    {
        "snapshot_dir": "./data/snapshots",
        "snapshot_every_commits": 1000,
        "snapshot_keep_old": 2,
    },
)

snapshot_options accepts the same compression/encryption options as save_snapshot.

Snapshots accept the same broad shapes in sync and async APIs:

import io
from lora_python import Database

db = Database.create()
db.execute("CREATE (:Person {name: 'Alice'})")

meta = db.save_snapshot("./graph.lorasnap")   # path / PathLike
raw = db.save_snapshot("binary")              # bytes
text = db.save_snapshot("base64")             # base64 str
buf = io.BytesIO()
meta = db.save_snapshot(buf)                  # binary writer

db.load_snapshot("./graph.lorasnap")
db.load_snapshot(raw)
db.load_snapshot(io.BytesIO(buf.getvalue()))
db.load_snapshot(text, format="base64")

Architecture

lora-database (Rust)
   └── lora-python (crate, cdylib)             <- PyO3 bindings
          ├── Database (sync, releases the GIL)
          └── python/lora_python/
                 ├── _async.py  AsyncDatabase via asyncio.to_thread
                 └── types.py   typed dicts + constructors + guards

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

lora_python-0.14.0.tar.gz (771.1 kB view details)

Uploaded Source

Built Distributions

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

lora_python-0.14.0-cp38-abi3-win_amd64.whl (2.6 MB view details)

Uploaded CPython 3.8+Windows x86-64

lora_python-0.14.0-cp38-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl (3.0 MB view details)

Uploaded CPython 3.8+manylinux: glibc 2.17+ x86-64

lora_python-0.14.0-cp38-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl (2.8 MB view details)

Uploaded CPython 3.8+manylinux: glibc 2.17+ ARM64

lora_python-0.14.0-cp38-abi3-macosx_11_0_arm64.whl (2.6 MB view details)

Uploaded CPython 3.8+macOS 11.0+ ARM64

lora_python-0.14.0-cp38-abi3-macosx_10_12_x86_64.whl (2.9 MB view details)

Uploaded CPython 3.8+macOS 10.12+ x86-64

File details

Details for the file lora_python-0.14.0.tar.gz.

File metadata

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

File hashes

Hashes for lora_python-0.14.0.tar.gz
Algorithm Hash digest
SHA256 90c237bfa3c963e9356db543eea340388e1daf1c0d2f6731f6c62a25b8c441c4
MD5 264cef4e1217f254ab193131d0b390ff
BLAKE2b-256 8d31bac30cd314f2f114e41c651dc28599a1a48bdd89cfdd58c744177ba3d5ae

See more details on using hashes here.

Provenance

The following attestation bundles were made for lora_python-0.14.0.tar.gz:

Publisher: packages-release.yml on lora-db/lora

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

File details

Details for the file lora_python-0.14.0-cp38-abi3-win_amd64.whl.

File metadata

  • Download URL: lora_python-0.14.0-cp38-abi3-win_amd64.whl
  • Upload date:
  • Size: 2.6 MB
  • Tags: CPython 3.8+, Windows x86-64
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for lora_python-0.14.0-cp38-abi3-win_amd64.whl
Algorithm Hash digest
SHA256 2d507f5eb8c7dde2e06967662e72040efd9e8fbef0f7e96a72a556cbd8d0ed26
MD5 6570cb3eb095a2e2087c4b8225bee4da
BLAKE2b-256 48ea25fccb2e07937ed1735a377ff70ec80682be3bde3b7fc74fa2cbfe1728a2

See more details on using hashes here.

Provenance

The following attestation bundles were made for lora_python-0.14.0-cp38-abi3-win_amd64.whl:

Publisher: packages-release.yml on lora-db/lora

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

File details

Details for the file lora_python-0.14.0-cp38-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl.

File metadata

File hashes

Hashes for lora_python-0.14.0-cp38-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
Algorithm Hash digest
SHA256 d7321eb702dcaddfbe73089dfa20ca519000384e39251e79bda887ada913de62
MD5 60f2a0e1cd8321270f93126ad70a5bb2
BLAKE2b-256 33235d50c91fa601c18d13ac26134b1f207481e4c2d41f61cb7de2f76e3f5198

See more details on using hashes here.

Provenance

The following attestation bundles were made for lora_python-0.14.0-cp38-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl:

Publisher: packages-release.yml on lora-db/lora

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

File details

Details for the file lora_python-0.14.0-cp38-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl.

File metadata

File hashes

Hashes for lora_python-0.14.0-cp38-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl
Algorithm Hash digest
SHA256 9ca5c46ae1db8efb504ad74b8c0c1dcef6d34c15645cb53c10199afa649ed513
MD5 8cad4f69df37a9ef7c6d6333e86e5a94
BLAKE2b-256 ed4c38a12b23e52256dc0edd8cd5bd97ae8c898bf73da1b17211005f95e88a62

See more details on using hashes here.

Provenance

The following attestation bundles were made for lora_python-0.14.0-cp38-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl:

Publisher: packages-release.yml on lora-db/lora

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

File details

Details for the file lora_python-0.14.0-cp38-abi3-macosx_11_0_arm64.whl.

File metadata

File hashes

Hashes for lora_python-0.14.0-cp38-abi3-macosx_11_0_arm64.whl
Algorithm Hash digest
SHA256 ab43d0f1e144b74eaf4883099899009a301d7f301420cffecf3e925017d048a5
MD5 140f22e7c3be55d25b5cf92ae355a8e3
BLAKE2b-256 c41b7ed830e0afd98c642a3c4c7048ad24d5dbcc72267bc9e26e9ebb803e8e86

See more details on using hashes here.

Provenance

The following attestation bundles were made for lora_python-0.14.0-cp38-abi3-macosx_11_0_arm64.whl:

Publisher: packages-release.yml on lora-db/lora

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

File details

Details for the file lora_python-0.14.0-cp38-abi3-macosx_10_12_x86_64.whl.

File metadata

File hashes

Hashes for lora_python-0.14.0-cp38-abi3-macosx_10_12_x86_64.whl
Algorithm Hash digest
SHA256 3f86765a75b5fa42e78214259adce098507c0fb63d4974bca088d630ae6cdfdb
MD5 33982894a07b91ac4b2a48a5a3fe86b6
BLAKE2b-256 5cb2de351f947c5f76f53812f3cbc61ead1650cc1a485854ca3063b83bb12514

See more details on using hashes here.

Provenance

The following attestation bundles were made for lora_python-0.14.0-cp38-abi3-macosx_10_12_x86_64.whl:

Publisher: packages-release.yml on lora-db/lora

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