Skip to main content

A lightweight, async-ready ORM for SQLite

Project description

Obele

Obele is a lightweight SQLite ORM and key-value store for modern Python applications. It keeps a small, Django-like API for models and queries while supporting both synchronous code and native asyncio workflows.

Highlights

  • Sync and async APIs for models, queries, raw SQL, search, and KV operations.
  • Async SQLite integration through the bundled obele.asqlite bridge.
  • Thread-safe SQLite connection management with transactions, savepoints, scoped database bindings, WAL mode, and query logging.
  • Declarative models with field validation, foreign keys, reverse relations, mixins, signals, pagination, and FTS5 search indexes.
  • Persistent dict-like KVStore with namespaces, TTL, atomic operations, range/prefix/scan queries, serializers, and async methods.

Requirements

  • Python 3.13 or newer.
  • SQLite with FTS5 enabled for full-text search features.

Obele has no required runtime dependencies outside the Python standard library.

Installation

pip install obele

For local development:

git clone https://github.com/ichinga-samuel/obele.git
cd obele
python -m pip install -e ".[dev]"
pytest -q

Quickstart

import asyncio
from obele import Database, Model, TextField, IntegerField

Database.configure("app.sqlite3")

class User(Model):
    table_name = "users"
    name = TextField()
    age = IntegerField(nullable=True)

async def main():
    await User.acreate_table()

    await User.acreate(name="Alice", age=30)
    await User.acreate(name="Bob", age=25)

    users = await User.filter(age__gte=18).order_by("name").aall()
    for user in users:
        print(user.name, user.age)

    await Database.aclose_all()

asyncio.run(main())

The same API is available synchronously by omitting the a prefix:

User.create_table()
User.create(name="Ada", age=36)
adults = User.filter(age__gte=18).all()

Direct SQL

Use Database helpers when you need lower-level access:

cursor = Database.execute(
    "INSERT INTO users (name, age) VALUES (?, ?)",
    ["Grace", 40],
)
print(cursor.lastrowid)

row = Database.fetchone("SELECT name FROM users WHERE id = ?", [cursor.lastrowid])

Async helpers use the bundled async SQLite connection and return async cursors:

cursor = await Database.aexecute(
    "INSERT INTO users (name, age) VALUES (?, ?)",
    ["Linus", 33],
)
await cursor.close()

row = await Database.afetchone("SELECT name FROM users WHERE age > ?", [30])

Transactions And Scoped Databases

with Database.transaction():
    User.create(name="One")
    User.create(name="Two")

async with Database.transaction():
    await User.acreate(name="Async One")
    await User.acreate(name="Async Two")

Use scoped bindings for tests, tenants, or short-lived alternate databases:

with Database.using("tenant.sqlite3"):
    User.create_table()
    User.create(name="Tenant User")

Key-Value Store

from obele import KVStore

settings = KVStore("settings", key_type=str, namespace="app")
settings["theme"] = "dark"
settings.set("session", {"user_id": 1}, ttl=3600)

print(settings["theme"])
print(settings.prefix("sess"))

Async KV methods are prefixed with a:

await settings.aset("feature:search", True)
enabled = await settings.aget("feature:search")

Documentation

To preview the docs locally:

mkdocs serve

Testing

The test suite is organized by public behavior and uses the local checkout by default via pyproject.toml.

pytest -q

Current suite coverage includes ORM CRUD, queries, async behavior, direct database access, FTS search, pagination, signals, field types, and KVStore features.

License

Obele is released under the MIT License. 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

obele-0.1.0.tar.gz (90.1 kB view details)

Uploaded Source

Built Distribution

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

obele-0.1.0-py3-none-any.whl (70.7 kB view details)

Uploaded Python 3

File details

Details for the file obele-0.1.0.tar.gz.

File metadata

  • Download URL: obele-0.1.0.tar.gz
  • Upload date:
  • Size: 90.1 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: uv/0.9.5

File hashes

Hashes for obele-0.1.0.tar.gz
Algorithm Hash digest
SHA256 f17b3b36f8e693ef2951f68d7e6dfd083ad6ebfa86ae37dfd102577ed2d325d3
MD5 d31650a8be2b4768a045cf04f31e56a9
BLAKE2b-256 ec7571e7d5bd3d70c149c0db01c4fc70d922891ed33745cb5ebfcb67ea14bbbf

See more details on using hashes here.

File details

Details for the file obele-0.1.0-py3-none-any.whl.

File metadata

  • Download URL: obele-0.1.0-py3-none-any.whl
  • Upload date:
  • Size: 70.7 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: uv/0.9.5

File hashes

Hashes for obele-0.1.0-py3-none-any.whl
Algorithm Hash digest
SHA256 b78025f32a7b9fcfe617079c4835fcf432c70507b98366415215c6a5f9ce349d
MD5 f7d3e63643a597763d00b13de8029c70
BLAKE2b-256 85b92e5d7e66c164fbaf1143394e72f39e17892b48e94a2b0e59692fe16972a2

See more details on using hashes here.

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