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.
  • 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.6.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.6.0
File Size Uploaded
sustained-2.6.0.tar.gz 145.0 kB Details

Built distribution (wheel)

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

Total release size: 233.8 kB

Release files / sustained-2.6.0.tar.gz

Download URL sustained-2.6.0.tar.gz
Size 145.0 kB
Tags Source
SHA-256 checksum
How to use checksums
1728135f969e0a726b00883191fe5fab1c42a910829b7743a807fdd50d35859d
BLAKE2b-256 checksum
How to use checksums
fb2168152afeaa18613f1292c8285e05105ee2d96dfd96c3b3b0a39a6a30ecc9
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.6.0-py3-none-any.whl

Download URL sustained-2.6.0-py3-none-any.whl
Size 88.8 kB
Tags Python 3
SHA-256 checksum
How to use checksums
f456bb6335a77dd4f6e3e695688996f246a846ca57ae4d5bf8ba778d8774d36b
BLAKE2b-256 checksum
How to use checksums
90db96bb1ed9c0f471924e80c36eb4f3d35205065b5ec13cddf68e040ded8fa5
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

2.10.0

2 release files

2.9.0

2 release files

2.8.0

2 release files

2.7.0

2 release files

This release

2.6.0 This release

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