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.9.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.9.0
File Size Uploaded
sustained-2.9.0.tar.gz 166.3 kB Details

Built distribution (wheel)

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

Total release size: 266.0 kB

Release files / sustained-2.9.0.tar.gz

Download URL sustained-2.9.0.tar.gz
Size 166.3 kB
Tags Source
SHA-256 checksum
How to use checksums
d9b16586199c07be6c82b7e55e366ce0e2c1bb0a26ae26a1a32dd1dd0a5e59cb
BLAKE2b-256 checksum
How to use checksums
168598d28ce5b41cbd897cef45f8733cf3d3ab7707f047a7fd2639e742c557e4
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.9.0-py3-none-any.whl

Download URL sustained-2.9.0-py3-none-any.whl
Size 99.7 kB
Tags Python 3
SHA-256 checksum
How to use checksums
8ac9eaf5d2969183c91fd572da033b3c434adac550350cebdfa393b95f815ebf
BLAKE2b-256 checksum
How to use checksums
fdcf62b8aaa0255090c4ee19b6a7e5e5a0f5cc0d8fdbbb52e4070883b24e6a12
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

This release

2.9.0 This release

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