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 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%')).
Installation
python3 -m pip install sustained
Local Installation from Source
To install sustained from source for local development:
-
Clone the repository:
git clone https://github.com/wetherc/sustained.git cd sustained
-
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
-
Install pre-commit:
pip install pre-commit
-
Install the Git hooks: From the root of the project directory, run:
pre-commit install
Release files for sustained 2.1.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| sustained-2.1.0.tar.gz | 84.8 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| sustained-2.1.0-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 137.9 kB
Release files / sustained-2.1.0.tar.gz
| Download URL | sustained-2.1.0.tar.gz |
|---|---|
| Size | 84.8 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
eb347f0e0d5c7413a70ea33ff97105c084070916ca8d9e659564d9d7ed13902e
|
|
BLAKE2b-256 checksum How to use checksums |
8d38f883d45becf7f21306da7d0931025650ce98317a51c01537e7d0191eddde
|
| 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.1.0-py3-none-any.whl
| Download URL | sustained-2.1.0-py3-none-any.whl |
|---|---|
| Size | 53.2 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
c40e4a464a799574bdc5b769b8780cc917154242c55dde28acfc72495a111dad
|
|
BLAKE2b-256 checksum How to use checksums |
447570733a6c36e7bf4d4946a144f4204430c013dc85e8060040a0dc97813207
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.14.6
|