Skip to main content

Sustained.py

A Python query builder and lightweight ORM inspired by Objection.js.

You describe a query as chained Python methods. Sustained renders the SQL for your dialect, runs it parameterized against any DB-API 2.0 connection or pool, and hydrates the rows into your model classes.

adults = User.query().where(User.c.age >= 18).orderBy('name').run()

What it does

  • SQL building for the default (ANSI), Postgres, MSSQL, Presto, AWS Athena, and DuckDB dialects: joins, CTEs (including recursive), unions, window functions, CASE expressions, and subqueries. Features a dialect lacks raise DialectError at build time.
  • Safe execution: every statement runs parameterized. Transactions nest through savepoints. update() and delete() refuse to run without a WHERE clause.
  • Writes: insert(), update(), delete(), upserts with onConflict(), INSERT ... SELECT, CTAS, and RETURNING.
  • Typed filters: User.query().where((User.c.age > 21) & User.c.name.like('A%')).
  • Results as model instances, dicts, pandas DataFrames, or pyarrow Tables, with withGraphFetched() eager loading.
  • Schema migrations: models declare typed columns and indexes; Migrator.sync(models) diffs the live database, generates the migration, applies it, and down() rolls it back. Destructive changes are gated behind explicit opt-ins.
  • Rehearsed migrations: sustained rehearse applies every pending migration, runs the down steps back down, and rolls it all back, so a broken or one-way migration shows up before it reaches the real schema.
  • Async: the same queries run through driver adapters (asyncpg, aiosqlite, or any sync driver in a worker thread) with await query.arun().

What it does not do

No lazy loading, no dirty tracking or save(), no identity map, no result caching, no cross-dialect emulation of missing features, and no guessed migrations: drops, renames, and NOT NULL backfills all require explicit opt-ins or hints. Writes and schema changes only happen when you spell them out.

Installation

python3 -m pip install sustained

Usage

from sustained import Model, RelationType

class Person(Model):
    tableName = 'persons'

class Animal(Model):
    tableName = 'animals'
    relationMappings = {
        'owner': {
            'relation': RelationType.BelongsToOneRelation,
            'modelClass': Person,
            'join': {
                'from': 'animals.ownerId',
                'to': 'persons.id'
            }
        }
    }

# Build a query
query = Animal.query().select('animals.name', 'persons.name').leftOuterJoinRelated('owner')

print(query)
# SELECT animals.name, persons.name
# FROM animals
# LEFT OUTER JOIN persons
#   ON animals.ownerId = persons.id


# Execute against any DB-API 2.0 connection
import sqlite3

conn = sqlite3.connect('app.db')
Animal.bind(conn)

# Parameterized execution with model hydration
animals = Animal.query().where('species', '=', 'dog').orderBy('name').run()

# Or take the SQL and parameters and execute them yourself
sql, params = Animal.query().where('species', '=', 'dog').to_sql()
# sql:    "SELECT * FROM animals WHERE species = ?"
# params: ('dog',)

Models can manage their own schema:

from sustained.migrations import Migrator
from sustained.schema import Integer, String, Text

class User(Model):
    tableName = 'users'
    tableColumns = {
        'id': Integer(primary_key=True, autoincrement=True),
        'email': String(120, unique=True, nullable=False),
    }

migrator = Migrator(conn, [])
migrator.sync([User])              # creates the users table

User.tableColumns['bio'] = Text()
migrator.sync([User])              # adds only the bio column
migrator.down()                    # rolls it back

Documentation

The documentation covers models, queries, dialects and drivers, filtering, grouping, relations and joins, execution, pooling, and async, and schema and migrations. The API reference lists every public method by task.

Development

To install from source:

git clone https://github.com/wetherc/sustained.git
cd sustained
python3 -m pip install -e .

This project uses pre-commit to format code, lint, type check, and run the test suite before each commit:

pip install pre-commit
pre-commit install

Release files for sustained 2.10.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 sustained 2.10.0
File Size Uploaded
sustained-2.10.0.tar.gz 183.8 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for sustained 2.10.0
File Interpreter ABI Platform
sustained-2.10.0-py3-none-any.whl Python 3 none any Details

Total release size: 288.7 kB

Release files / sustained-2.10.0.tar.gz

Download URL sustained-2.10.0.tar.gz
Size 183.8 kB
Tags Source
SHA-256 checksum
How to use checksums
01f93e57b4e2d3646a5fd7e9b64ff9547d375f87a6877fc8bd5a74306a53004f
BLAKE2b-256 checksum
How to use checksums
fef8d5463b2b3130d6179212a6b52ddef54275ade0c4ebf159a121b47462b207
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/7.0.0 CPython/3.13.0

Release files / sustained-2.10.0-py3-none-any.whl

Download URL sustained-2.10.0-py3-none-any.whl
Size 105.0 kB
Tags Python 3
SHA-256 checksum
How to use checksums
22e5a6a588a6ab174a241471b04cc3a140aff98f5ae86f9d76e5c28f44e2f161
BLAKE2b-256 checksum
How to use checksums
dcbc6dc135e5960e9926d492a17f535a1551e21c15bcc7d59287f799d4c44920
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/7.0.0 CPython/3.13.0

Release history Release notifications | RSS feed

2.25.0

2 release files

2.24.2

2 release files

2.23.1

2 release files

2.23.0

2 release files

2.22.0

2 release files

2.21.0

2 release files

2.20.0

2 release files

2.19.0

2 release files

2.18.0

2 release files

2.17.0

2 release files

2.16.1

2 release files

2.16.0

2 release files

2.15.0

2 release files

2.14.0

2 release files

2.13.0

2 release files

2.12.0

2 release files

2.11.0

2 release files

This release

2.10.0 This release

2 release files

2.9.0

2 release files

2.8.0

2 release files

2.7.0

2 release files

2.6.0

2 release files

2.5.0

2 release files

2.4.0

2 release files

2.3.0

2 release files

2.2.0

2 release files

2.1.0

2 release files

2.0.0

2 release files

1.1.0

2 release files

1.0.2

2 release files

1.0.1

2 release files

1.0.0

2 release files

0.0.7

2 release files

0.0.6

2 release files

0.0.5

2 release files

0.0.4

2 release files

0.0.3

2 release files

0.0.2

2 release files

0.0.1

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