Skip to main content

Sustained.py

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

Sustained builds parameterized SQL for the default (ANSI), Postgres, MSSQL, Presto, and DuckDB dialects. It executes queries against any DB-API 2.0 connection or connection pool with transactions, hydrates rows into model instances or DataFrames, writes data with insert(), update(), delete(), upserts, and INSERT ... SELECT, and eager loads relations. Filters compose as typed predicates: User.query().where((User.c.age > 21) & User.c.name.like('A%')). Models declare typed columns and manage their own schema: Migrator.sync(models) diffs the live database, generates the migration, applies it, and down() rolls it back, with destructive changes gated behind explicit opt-ins. Async services run the same queries through driver adapters with await query.arun().

Installation

python3 -m pip install sustained

Local Installation from Source

To install sustained from source for local development:

  1. Clone the repository:

    git clone https://github.com/wetherc/sustained.git
    cd sustained
    
  2. Install in editable mode:

    python3 -m pip install -e .
    

Usage

from sustained import Model, RelationType, create_model

class Person(Model):
    database = 'my_db'
    tableSchema = 'public'
    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


# Build a more complex query with a CTE and a raw join
active_owners = Person.query().select('id').where('status', '=', 'active')

query = (
    Animal.query()
    .with_('active_owners', active_owners)
    .join('active_owners', 'animals.ownerId', '=', 'active_owners.id')
    .select('animals.name')
)

print(query)
# WITH active_owners AS (
#   SELECT id
#   FROM persons
#   WHERE status = 'active'
# )
# SELECT animals.name
# FROM animals
# JOIN active_owners
#   ON animals.ownerId = active_owners.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',)

See the documentation for models, filtering, grouping, relations, and execution guides.

Development

This project uses pre-commit to enforce code quality and run tests before committing code.

Pre-commit Hooks Setup

  1. Install pre-commit:

    pip install pre-commit
    
  2. Install the Git hooks: From the root of the project directory, run:

    pre-commit install
    

Release files for sustained 2.3.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.3.0
File Size Uploaded
sustained-2.3.0.tar.gz 108.0 kB Details

Built distribution (wheel)

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

Total release size: 177.9 kB

Release files / sustained-2.3.0.tar.gz

Download URL sustained-2.3.0.tar.gz
Size 108.0 kB
Tags Source
SHA-256 checksum
How to use checksums
6c9ad1839dc0d3ad1904be9be76e68107df0d7d0a51ea1065fb909f6af0fe5ff
BLAKE2b-256 checksum
How to use checksums
e03fd9af308dafd4c4cf720c8c55eb8c8d1f325f11503d9e17c61d1974ef32ed
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/7.0.0 CPython/3.14.6

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

Download URL sustained-2.3.0-py3-none-any.whl
Size 69.9 kB
Tags Python 3
SHA-256 checksum
How to use checksums
33e86da260ea0cc28d1f085843324d049000393b1e6507a340531ddc7a5752d6
BLAKE2b-256 checksum
How to use checksums
7c22afe88e9aa5caed6c5023d44e9db40fe0740f5fd510f61f172ff32cfbc180
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/7.0.0 CPython/3.14.6

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

2.6.0

2 release files

2.5.0

2 release files

2.4.0

2 release files

This release

2.3.0 This release

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