Skip to main content

Modern Python ORM with async support, full type annotations and a generator-expression query DSL

Project description

NextORM

CI PyPI Python License Docs

Modern Python ORM with async support, full type annotations and a generator-expression query DSL.

Features

  • Type-annotated fieldsPK[int], Req[str], Opt[str], Set[T], Single[T]
  • Auto-save sessions — create entities inside db_session and they are committed automatically
  • PonyORM-compatible DSL — generator-expression queries, Entity[pk], Entity.get(), lifecycle hooks
  • Full async supportAsyncDatabase, await db.aselect(...), Entity.aselect(), Entity.aget()
  • Built-in migrations CLInextorm makemigrations / nextorm migrate
  • Three providers — SQLite, PostgreSQL (psycopg3), MariaDB
  • 100% branch coverage enforced in CI

Installation

pip install nextorm[sqlite]        # SQLite (aiosqlite)
pip install nextorm[postgres]      # PostgreSQL (psycopg3)
pip install nextorm[mariadb]       # MariaDB (asyncmy + PyMySQL)
pip install "nextorm[sqlite,postgres,mariadb]"   # all drivers

Quick start

from nextorm import Database, Entity, PK, Req, Opt, Set, Single, db_session

# Define entities — no database coupling required
class Tag(Entity):
    name: Req[str]

class Product(Entity):
    name:  Req[str]
    price: Req[float]
    tags:  Set[Tag]    # many-to-many

# Create and connect the database
db = Database(entities=[Tag, Product])
db.bind("sqlite", ":memory:")
db.generate_mapping(create_tables=True)

# Write — entities are tracked and committed automatically
with db_session:
    t = Tag(name="sale")
    p = Product(name="Widget", price=9.99)
    p.tags.add(t)
# ← INSERT fires here; p.id and t.id are now set

# Read — class-level shortcuts (no explicit db reference needed)
widgets = Product.select().filter(Product.price < 20).fetch_all()
widget  = Product.get(name="Widget")   # None if not found
widget  = Product[1]                   # KeyError if not found

Async quick start

import asyncio
from nextorm import AsyncDatabase, Entity, PK, Req, db_session

class Task(Entity):
    title: Req[str]
    done:  Req[bool]

async def main() -> None:
    db = AsyncDatabase(entities=[Task])
    await db.bind("sqlite", ":memory:")
    await db.generate_mapping(create_tables=True)

    async with db_session:
        Task(title="Buy milk", done=False)

    pending = await Task.aselect().filter(Task.done == False).fetch_all()
    task    = await Task.aget(title="Buy milk")   # None if not found
    print(pending)

asyncio.run(main())

Migrations

nextorm makemigrations   # generate a migration from model changes
nextorm migrate          # apply pending migrations
nextorm showmigrations   # list migration history

Migrating from PonyORM

NextORM's API is intentionally close to PonyORM's. The main differences:

PonyORM NextORM
class Product(db.Entity) class Product(Entity)
Required(str) Req[str]
Optional(str) Opt[str]
PrimaryKey(int, auto=True) PK[int]
Required(Order) (FK side) Single[Order]
Set("Line") (back-reference) Set["Line"]
select(p for p in Product if ...) identical
Product[42] identical
Product.get(name="x") identical
db.save(p) required auto-committed in db_session

See the migration guide for details.

Documentation

Full docs at nextorm.readthedocs.io.

Development

pdm install
pdm test          # run tests
pdm coverage      # tests + branch coverage (must be 100%)
pdm typecheck     # pyright + mypy
pdm lint          # ruff
pdm format        # ruff format
pdm docs-html     # build Sphinx docs

Acknowledgements

NextORM's API design and query DSL are heavily inspired by PonyORM, created by Alexander Kozlovsky, Alexey Malashkevich, and Alexander Tischenko, released under the Apache License 2.0. NextORM is a new, independent implementation and shares no source code with PonyORM.

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

nextorm-0.1.2.tar.gz (212.3 kB view details)

Uploaded Source

Built Distribution

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

nextorm-0.1.2-py3-none-any.whl (126.0 kB view details)

Uploaded Python 3

File details

Details for the file nextorm-0.1.2.tar.gz.

File metadata

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

File hashes

Hashes for nextorm-0.1.2.tar.gz
Algorithm Hash digest
SHA256 8e7c524de7d6e37d81a50b45500fa0218f21d21db2c8e4322a78508f29b3c354
MD5 637f2f75d9cfba471cceda2ca2bf25d8
BLAKE2b-256 f8e0cf1cce7cf2017d291c428809337852ad81c2d62ffe4b14eddaccaf378ece

See more details on using hashes here.

Provenance

The following attestation bundles were made for nextorm-0.1.2.tar.gz:

Publisher: publish.yml on sancode-it/nextorm

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

File details

Details for the file nextorm-0.1.2-py3-none-any.whl.

File metadata

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

File hashes

Hashes for nextorm-0.1.2-py3-none-any.whl
Algorithm Hash digest
SHA256 8139782d990c12e05c0d99762508ccbc1891cbb34bc46deb5695c98b54a4ef60
MD5 3a9cfbb691a84c943df0a2eddc66b06e
BLAKE2b-256 3657c7a339b16e72c750b7f8e748af76a4b2f46d6d564bbe5c1f2ffcb1f22b54

See more details on using hashes here.

Provenance

The following attestation bundles were made for nextorm-0.1.2-py3-none-any.whl:

Publisher: publish.yml on sancode-it/nextorm

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