Skip to main content

iceaxe-sqlite

Python Version Test status

iceaxe-sqlite is a SQLite-focused rewrite of the original iceaxe, which is built around Postgres. The model, query, and data-access conventions from Iceaxe are still extremely effective, so this project keeps those patterns while retargeting them to SQLite.

That split is intentional. Rather than chasing a backend-agnostic API like Peewee or SQLAlchemy, iceaxe-sqlite stays opinionated about the datastore underneath it. The goal is for the ORM surface area to match SQLite itself, so the abstractions stay simple, predictable, and honest about what the database can do.

If you already like the way Iceaxe models tables and fetches data, this package gives you those same conventions in a form designed specifically for SQLite.

Goals are also similar:

  • 🏎️ Performance: We want to exceed or match the fastest ORMs in Python and stay close to raw SQLite query performance.
  • 📝 Typehinting: Everything should be typehinted with expected types. Declare your data as you expect in Python and it should bidirectionally sync to the database.
  • 🪶 SQLite first: Use a small async SQLite backend with no external database server.
  • ⚡ Common things are easy, rare things are possible: 99% of the SQL queries we write are vanilla SELECT/INSERT/UPDATEs. These should be natively supported by your ORM. If you're writing really complex queries, these are better done by hand so you can see exactly what SQL will be run.

The original Iceaxe conventions are used in production at several companies. iceaxe-sqlite is an independent project. It's compatible with the Mountaineer ecosystem, but you can use it in whatever project and web framework you're using.

Installation

Install with uv:

uv add iceaxe-sqlite

Otherwise install with pip:

pip install iceaxe-sqlite

Usage

Define your models as a TableBase subclass:

from iceaxe_sqlite import TableBase

class Person(TableBase):
    id: int
    name: str
    age: int

TableBase is a subclass of Pydantic's BaseModel, so you get all of the validation and Field customization out of the box. We provide our own Field constructor that adds database-specific configuration. For instance, to make the id field a primary key / auto-incrementing you can do:

from iceaxe_sqlite import Field

class Person(TableBase):
    id: int = Field(primary_key=True)
    name: str
    age: int

Okay now you have a model. How do you interact with it?

Databases are based on a few core primitives to insert data, update it, and fetch it out again. To do so you'll need a database connection. The DBConnection is the core class for all ORM actions against the database.

from iceaxe_sqlite import DBConnection, connect

conn = DBConnection(await connect("app.db"))

The Person class currently just lives in memory. To back it with a full database table, we can run raw SQL or run a migration to add it:

await conn.conn.execute(
    """
    CREATE TABLE IF NOT EXISTS person (
        id INTEGER PRIMARY KEY,
        name TEXT NOT NULL,
        age INT NOT NULL
    )
    """
)

Magic Migrations

For local development or side projects, you can use magic_migrate to automatically sync your database schema with your models:

await conn.magic_migrate("my_project")

# Or apply the live schema diff without writing migration files to disk
await conn.magic_migrate("my_project", no_files=True)

This will:

  1. Compare your current database schema against your model definitions
  2. Generate a migration file if changes are detected
  3. Apply all pending migrations

By default, migration files are written to your package's migrations/ folder, giving you a history of schema changes. If you pass no_files=True, Iceaxe skips the file write and applies the schema diff directly to the current database.

Recommended workflow for production:

While magic_migrate is convenient for rapid local iteration, we recommend a more controlled approach before merging to production:

  1. Iterate freely during development using magic_migrate
  2. Before merging, reset your database to the production schema state
  3. Run uv run migrate generate once to generate a single, clean migration file
  4. Commit this migration file with your PR

This ensures your production migrations are clean and reviewable, while still giving you the speed of automatic migrations during development.

Inserting Data

Instantiate object classes as you normally do:

people = [
    Person(name="Alice", age=30),
    Person(name="Bob", age=40),
    Person(name="Charlie", age=50),
]
await conn.insert(people)

print(people[0].id) # 1
print(people[1].id) # 2

Because we're using an auto-incrementing primary key, the id field will be populated after the insert. Iceaxe will automatically update the object in place with the newly assigned value.

Updating data

Now that we have these lovely people, let's modify them.

person = people[0]
person.name = "Blice"

Right now, we have a Python object that's out of state with the database. But that's often okay. We can inspect it and further write logic - it's fully decoupled from the database.

def ensure_b_letter(person: Person):
    if person.name[0].lower() != "b":
        raise ValueError("Name must start with 'B'")

ensure_b_letter(person)

To sync the values back to the database, we can call update:

await conn.update([person])

If we were to query the database directly, we see that the name has been updated:

id | name  | age
----+-------+-----
  1 | Blice |  31
  2 | Bob   |  40
  3 | Charlie | 50

But no other fields have been touched. This lets a potentially concurrent process modify Alice's record - say, updating the age to 31. By the time we update the data, we'll change the name but nothing else. Under the hood we do this by tracking the fields that have been modified in-memory and creating a targeted UPDATE to modify only those values.

Selecting data

To select data, we can use a QueryBuilder. For a shortcut to select query functions, you can also just import select directly. This method takes the desired value parameters and returns a list of the desired objects.

from iceaxe_sqlite import select

query = select(Person).where(Person.name == "Blice", Person.age > 25)
results = await conn.exec(query)

If we inspect the typing of results, we see that it's a list[Person] objects. This matches the typehint of the select function. You can also target columns directly:

query = select((Person.id, Person.name)).where(Person.age > 25)
results = await conn.exec(query)

This will return a list of tuples, where each tuple is the id and name of the person: list[tuple[int, str]].

We support most of the common SQL operations. Just like the results, these are typehinted to their proper types as well. Static typecheckers and your IDE will throw an error if you try to compare a string column to an integer, for instance. A more complex example of a query:

query = select((
    Person.id,
    FavoriteColor,
)).join(
    FavoriteColor,
    Person.id == FavoriteColor.person_id,
).where(
    Person.age > 25,
    Person.name == "Blice",
).order_by(
    Person.age.desc(),
).limit(10)
results = await conn.exec(query)

As expected this will deliver results - and typehint - as a list[tuple[int, FavoriteColor]]

Production

The underlying SQLite connection wrapped by conn stays alive while the DBConnection is in memory. For web apps, create one connection per process or use your framework lifecycle hooks to open and close it deliberately. SQLite serializes writes, so high-write deployments should plan around short transactions and WAL mode when appropriate.

Benchmarking

We have basic benchmarking tests in the __tests__/benchmarks directory. To run them, you'll need to execute the pytest suite:

uv run pytest -m integration_tests

Development

If you update your Cython implementation during development, you'll need to re-compile the Cython code. This can be done with a simple uv sync.

uv sync

Metadata

Release files for iceaxe-sqlite 0.1.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 iceaxe-sqlite 0.1.1
File Size Uploaded
iceaxe_sqlite-0.1.1.tar.gz 223.9 kB Details

Built distributions (wheels)

Table of built distributions (wheels) for iceaxe-sqlite 0.1.1
File
iceaxe_sqlite-0.1.1-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.whl CPython 3.13 CPython 3.13 Linux glibc 2.17+ x86-64 Details
iceaxe_sqlite-0.1.1-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.whl CPython 3.13 CPython 3.13 Linux glibc 2.17+ ARM64 Details
iceaxe_sqlite-0.1.1-cp313-cp313-macosx_11_0_arm64.whl CPython 3.13 CPython 3.13 macOS 11.0+ ARM64 Details
iceaxe_sqlite-0.1.1-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.whl CPython 3.12 CPython 3.12 Linux glibc 2.17+ x86-64 Details
iceaxe_sqlite-0.1.1-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.whl CPython 3.12 CPython 3.12 Linux glibc 2.17+ ARM64 Details
iceaxe_sqlite-0.1.1-cp312-cp312-macosx_11_0_arm64.whl CPython 3.12 CPython 3.12 macOS 11.0+ ARM64 Details
iceaxe_sqlite-0.1.1-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.whl CPython 3.11 CPython 3.11 Linux glibc 2.17+ x86-64 Details
iceaxe_sqlite-0.1.1-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.whl CPython 3.11 CPython 3.11 Linux glibc 2.17+ ARM64 Details
iceaxe_sqlite-0.1.1-cp311-cp311-macosx_11_0_arm64.whl CPython 3.11 CPython 3.11 macOS 11.0+ ARM64 Details

Total release size: 2.9 MB

Release files / iceaxe_sqlite-0.1.1.tar.gz

Download URL iceaxe_sqlite-0.1.1.tar.gz
Size 223.9 kB
Tags Source
SHA-256 checksum
How to use checksums
672188e5a77204324d627858c352c9ec04b3c814cee6dfcf523fb1648f64abad
BLAKE2b-256 checksum
How to use checksums
70c5343b2d68cf350f0f7a5589eeb78f62e7a05cbd0ea5da6ef65ed60120e9f1
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/6.1.0 CPython/3.13.12

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 Apr 25, 2026.

Transparency log

Release files / iceaxe_sqlite-0.1.1-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.whl

Download URL iceaxe_sqlite-0.1.1-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.whl
Size 297.7 kB
Tags CPython 3.13 Linux glibc 2.17+ x86-64
SHA-256 checksum
How to use checksums
ce1f5eee38c3d0ab8883138a3b9470a2fbba68e2811b956bd8cd57921becc1e0
BLAKE2b-256 checksum
How to use checksums
e1ec9e0f9050de06017c4b7d6303b211d9b943c90c6fdd681884512c94a67df5
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/6.1.0 CPython/3.13.12

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 Apr 25, 2026.

Transparency log

Release files / iceaxe_sqlite-0.1.1-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.whl

Download URL iceaxe_sqlite-0.1.1-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.whl
Size 294.6 kB
Tags CPython 3.13 Linux glibc 2.17+ ARM64
SHA-256 checksum
How to use checksums
8b4dd308690ab2879b9734aba286c91815ba9a0beef9adda280e2790475cd64c
BLAKE2b-256 checksum
How to use checksums
74daa99eba3a84f5365d63190fefb6af11b350ef9c20fb5ab0951d1bffe9f08b
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/6.1.0 CPython/3.13.12

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 Apr 25, 2026.

Transparency log

Release files / iceaxe_sqlite-0.1.1-cp313-cp313-macosx_11_0_arm64.whl

Download URL iceaxe_sqlite-0.1.1-cp313-cp313-macosx_11_0_arm64.whl
Size 291.0 kB
Tags CPython 3.13 macOS 11.0+ ARM64
SHA-256 checksum
How to use checksums
03ed690dc2d57a7c8b8e8b258f567f89e0449f2745c4f488d1079fcc296c5224
BLAKE2b-256 checksum
How to use checksums
56ef6eb00a00e82d1e2ac353bf3702a5bf94e8b6b1bc0e76eae0da56f670368c
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/6.1.0 CPython/3.13.12

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 Apr 25, 2026.

Transparency log

Release files / iceaxe_sqlite-0.1.1-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.whl

Download URL iceaxe_sqlite-0.1.1-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.whl
Size 297.6 kB
Tags CPython 3.12 Linux glibc 2.17+ x86-64
SHA-256 checksum
How to use checksums
37df4be1c0f7f17d73e65fe756f9fff95fef3af69b57ceffceea8430da61dfc0
BLAKE2b-256 checksum
How to use checksums
1834633b279cb68452b35c9195ec0607c04b563c53db7115fd291325c9c93e0e
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/6.1.0 CPython/3.13.12

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 Apr 25, 2026.

Transparency log

Release files / iceaxe_sqlite-0.1.1-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.whl

Download URL iceaxe_sqlite-0.1.1-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.whl
Size 294.6 kB
Tags CPython 3.12 Linux glibc 2.17+ ARM64
SHA-256 checksum
How to use checksums
ee1aed7608b3573f3f6002b951858f8dadd5e4c1dd880f9a6e14d2fb6f2be602
BLAKE2b-256 checksum
How to use checksums
03d5c1ab72bb1f9d67f045f16cb07b6d96a40473ea7c9e04672e340df3290ef6
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/6.1.0 CPython/3.13.12

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 Apr 25, 2026.

Transparency log

Release files / iceaxe_sqlite-0.1.1-cp312-cp312-macosx_11_0_arm64.whl

Download URL iceaxe_sqlite-0.1.1-cp312-cp312-macosx_11_0_arm64.whl
Size 291.0 kB
Tags CPython 3.12 macOS 11.0+ ARM64
SHA-256 checksum
How to use checksums
a07c9a28e48db22811e6ab22daf80f35a0ba98c2d70a16ec287694707f76e118
BLAKE2b-256 checksum
How to use checksums
9d63b1c2de8e34f037ead94e41225ebb9ccd56cec578b6b5796727a5f0668341
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/6.1.0 CPython/3.13.12

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 Apr 25, 2026.

Transparency log

Release files / iceaxe_sqlite-0.1.1-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.whl

Download URL iceaxe_sqlite-0.1.1-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.whl
Size 292.9 kB
Tags CPython 3.11 Linux glibc 2.17+ x86-64
SHA-256 checksum
How to use checksums
016f09c5a1118c67b382b4e7df744a368486ba25d9a8853a2f9bac36f3d2452b
BLAKE2b-256 checksum
How to use checksums
af472d0f415e2e53be455cf52e44266a0f14182f973345f6bd5715423c98a3dd
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/6.1.0 CPython/3.13.12

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 Apr 25, 2026.

Transparency log

Release files / iceaxe_sqlite-0.1.1-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.whl

Download URL iceaxe_sqlite-0.1.1-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.whl
Size 290.3 kB
Tags CPython 3.11 Linux glibc 2.17+ ARM64
SHA-256 checksum
How to use checksums
a74a9f7477f5c86557f89e554d5be06128b6ef878bf725ee72d9f1e60a6b48f3
BLAKE2b-256 checksum
How to use checksums
35fcad7166f6bffeb1ee5ed5f9f93d31ff945d687763ac9a92bbc03fbb69d937
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/6.1.0 CPython/3.13.12

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 Apr 25, 2026.

Transparency log

Release files / iceaxe_sqlite-0.1.1-cp311-cp311-macosx_11_0_arm64.whl

Download URL iceaxe_sqlite-0.1.1-cp311-cp311-macosx_11_0_arm64.whl
Size 286.7 kB
Tags CPython 3.11 macOS 11.0+ ARM64
SHA-256 checksum
How to use checksums
af1abf5c54ac21bd76744c37044290eec0f98c6bd5fef2b0925ef52ee068f99e
BLAKE2b-256 checksum
How to use checksums
9591f8339bbab2c7651176bd3c34634453f51c77a0d6bc444c8ea3fbfe8dd5c8
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/6.1.0 CPython/3.13.12

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 Apr 25, 2026.

Transparency log

Release history Release notifications | RSS feed

This release

0.1.1 This release

10 release files

0.1.0

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