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.4.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.4.0
File Size Uploaded
sustained-2.4.0.tar.gz 119.9 kB Details

Built distribution (wheel)

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

Total release size: 198.4 kB

Release files / sustained-2.4.0.tar.gz

Download URL sustained-2.4.0.tar.gz
Size 119.9 kB
Tags Source
SHA-256 checksum
How to use checksums
2eb5e1ca6fe31b0025ab721a59b2fb3c67173ee12b25aa04b1e7aad002284e03
BLAKE2b-256 checksum
How to use checksums
4db96f07248207742bbc4a364fefd5c22582a4e0f8333424bd18205ef530252b
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.4.0-py3-none-any.whl

Download URL sustained-2.4.0-py3-none-any.whl
Size 78.5 kB
Tags Python 3
SHA-256 checksum
How to use checksums
42b99facf6b992d820572895df89df74e35f9f6c1d4cb4998118b58d1c4295ed
BLAKE2b-256 checksum
How to use checksums
eaa3c7867c447c7b1a12b7a71af9e08019231b3d5b29215f20f809227d492af4
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

This release

2.4.0 This release

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