Skip to main content
Pre-release

This release is a pre-release and may not be stable for production use.

halfORM

PyPI version Python versions PostgreSQL versions License Tests Coverage Downloads

⚠️ BREAKING CHANGES in v1.0.0

ho_get() is now public and returns a dict directly. It raises NotFoundError (0 rows) or MultipleRowsError (> 1 row) instead of counting first.

Deprecated query-builder setters removed — ho_limit, ho_offset, ho_order_by, ho_distinct no longer exist as setters. Pass these as keyword arguments to ho_select():

# Before (0.x)
rel.ho_limit = 10
rel.ho_order_by = 'name'
list(rel)

# After (1.0)
list(rel.ho_select(limit=10, order_by='name'))

FKEYS_PROPERTIES / FKEYS class attributes removed — use Fkeys only.

ho_cast() now raises CastError if the target is not in the PostgreSQL inheritance hierarchy of the relation.

See CHANGELOG.md for the full list of changes.

halfORM is a database-first ORM for PostgreSQL. Your schema lives in the database; halfORM introspects it at runtime and gives you Python objects to work with your data. No migrations, no code generation.

The central idea: a Relation object is a predicate. It describes the logical condition that rows must satisfy to belong to the relation. Its extension — the set of rows currently satisfying the predicate in the database — is what you read, update, or delete.

Key features

  • Database-first — the schema lives in PostgreSQL, not in Python classes.
  • Predicate model — relations are predicates; set operators (|, &, -) compose them before any SQL is sent.
  • FK navigation — join across tables (and views) by setting FK attributes; explicit Fkeys dict for views where PostgreSQL stores no FK metadata.
  • Sync + async — every executor has an a-prefixed async counterpart (ho_aselect, ho_ainsert, …).
  • Bulk load — ho_copy / ho_acopy for high-throughput inserts via PostgreSQL COPY.
  • No magic — queries are built from the predicate you describe and executed only when you call an executor. ho_mogrify() shows the exact SQL.

Install

pip install half_orm

Requires psycopg 3 (psycopg[binary]).

Configure

# ~/.half_orm/blog
[database]
name     = blog
user     = alice
password = secret
host     = localhost

Usage

from half_orm.model import Model
from half_orm.relation_errors import NotFoundError, MultipleRowsError

blog   = Model('blog')
Post   = blog.get_relation_class('blog.post')
Author = blog.get_relation_class('blog.author')

# Insert — returns the inserted row as a dict
alice = Author(
    first_name='Alice', last_name='Martin', email='alice@example.com'
).ho_insert()

# Query — Author(last_name='Martin') is a predicate, not a query
for row in Author(last_name='Martin').ho_select('id', 'email'):
    print(row)

# Get exactly one row
try:
    author = Author(last_name='Martin').ho_get()
except NotFoundError:
    print("no such author")
except MultipleRowsError:
    print("ambiguous — more than one author named Martin")

# FK navigation — no JOIN written by hand
post = Post(id=1)
post.author_fk.set()                         # join all authors
for row in post.ho_select(json_agg={'author_fk': ['first_name', 'last_name']}):
    print(row['author_fk'])                  # {'first_name': 'Alice', 'last_name': 'Martin'}

# Set operators — compose predicates before hitting the database
recent   = Post(created_at=('>', '2024-01-01'))
featured = Post(featured=True)
combined = recent | featured                 # UNION
print(combined.ho_count())

# Update / delete
Author(id=alice['id']).ho_update(email='alice@newdomain.com')
Author(id=alice['id']).ho_delete()

Documentation

Extensions

Extension Description
half-orm-dev Development tools — half_orm dev project scaffolding, patch management, and schema synchronisation.

License

halfORM is licensed under the GPL-3.0 license.

Metadata

Release files for half-orm 1.0.0rc18

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for half-orm 1.0.0rc18
File Size Uploaded Provenance
half_orm-1.0.0rc18.tar.gz 83.5 kB Without provenance Details

Built distribution (wheel)

Table of built distributions (wheels) for half-orm 1.0.0rc18
File Interpreter ABI Platform
half_orm-1.0.0rc18-py3-none-any.whl Python 3 none any Details

Total release size: 163.2 kB

Release files / half_orm-1.0.0rc18.tar.gz

Download URL half_orm-1.0.0rc18.tar.gz
Size 83.5 kB
Tags Source
SHA-256 checksum
How to use checksums
6fc975a8d2842dde567578aa10bb04a7f494f9f17882100735e234c88ba2959a
BLAKE2b-256 checksum
How to use checksums
137a5c5fb0afea20113ecb7af4138d556eaad0377ee7f7fef0d943520e520c88
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/6.2.0 CPython/3.14.6

Release files / half_orm-1.0.0rc18-py3-none-any.whl

Download URL half_orm-1.0.0rc18-py3-none-any.whl
Size 79.7 kB
Tags Python 3
SHA-256 checksum
How to use checksums
3d209897440a1850def36035d986e66857fa020f63081fc844393d98e687410f
BLAKE2b-256 checksum
How to use checksums
6c8ffacb55f12dc50c11459941e5ba66c22f07f8e6a95cb6fddc3577a67c320f
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/6.2.0 CPython/3.14.6

Security for half-orm 1.0.0rc18

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

No provenance found

None of the files in this release were uploaded with provenance metadata.

A note on package security

PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.

To learn more about protecting yourself from malicious actors, visit our package security documentation.

Release history Release notifications | RSS feed

This release
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