Async SQLAlchemy helpers for mgf-common consumers — typed engine factory, sessionmaker, Postgres RLS tenant-scoping. Sibling of mgf-common under the mgf.* namespace.
Project description
mgf-sqlalchemy — async SQLAlchemy helpers for mgf-common consumers
Sibling of
mgf-commonunder themgf.*namespace. Houses the async-SQLAlchemy helpers that previously lived undermgf.common.db.*— extracted at mgf-common v0.30 / mgf-sqlalchemy v0.1 per the federation split plan.
What this provides
| Submodule | What |
|---|---|
mgf.sqlalchemy |
create_engine — async SQLAlchemy engine factory with production-leaning pool defaults (pool_pre_ping, pool_recycle, sane pool_size/max_overflow). SQLite-aware (skips pool kwargs that StaticPool/NullPool reject). create_sessionmaker — async sessionmaker factory with SQLAlchemy 2's recommended expire_on_commit=False default. tenant_session — context manager for Postgres RLS multi-tenancy (SET LOCAL app.current_tenant = '<uuid>'); UUID-validated to prevent SQL injection. |
FastAPI helpers live elsewhere. The get_session
FastAPI-Depends generator and the setup_db lifespan helper that
previously co-located with these in mgf-common moved to
mgf.fastapi.db in
mgf-fastapi v0.2.0 (which depends on mgf-sqlalchemy via its
[sqlalchemy] extra). This sibling stays framework-agnostic — no
Starlette / no FastAPI in the dependency graph.
Install
pip install mgf-sqlalchemy
# Or with the test extra (aiosqlite for in-memory SQLite tests):
pip install 'mgf-sqlalchemy[test]'
Pulls in mgf-common + sqlalchemy[asyncio] automatically. Production
consumers also need an async driver of their own (asyncpg / aiomysql /
asyncmy); we don't pin one — the consumer picks based on their
database.
Quick start
import asyncio
from mgf.sqlalchemy import create_engine, create_sessionmaker
async def main() -> None:
engine = create_engine(
"postgresql+asyncpg://user:pass@localhost/myapp",
echo=False,
)
sessionmaker = create_sessionmaker(engine)
try:
async with sessionmaker() as session:
from sqlalchemy import text
row = (await session.execute(text("SELECT 1"))).scalar_one()
print(row)
finally:
await engine.dispose()
asyncio.run(main())
Postgres RLS multi-tenancy
from uuid import UUID
from mgf.sqlalchemy import tenant_session
tenant_id = UUID("550e8400-e29b-41d4-a716-446655440000")
async with sessionmaker() as session:
async with tenant_session(session, tenant_id) as scoped:
# Every query on `scoped` (same session, just tenant-scoped)
# gets `app.current_tenant` set in the current transaction.
# RLS policies in your schema can read from
# `current_setting('app.current_tenant')`.
rows = await scoped.execute(text("SELECT ..."))
FastAPI integration
The FastAPI-shaped helpers (request-scoped session injection + lifespan) live in mgf-fastapi:
# pyproject.toml
dependencies = [
"mgf-common>=0.30,<0.31",
"mgf-sqlalchemy>=0.1,<0.2",
"mgf-fastapi[sqlalchemy]>=0.2,<0.3",
]
from typing import Annotated
from contextlib import asynccontextmanager
from fastapi import FastAPI, Depends
from sqlalchemy.ext.asyncio import AsyncSession
from mgf.fastapi.db import get_session, setup_db
@asynccontextmanager
async def lifespan(app: FastAPI):
async with setup_db(app, database_url="postgresql+asyncpg://..."):
yield
app = FastAPI(lifespan=lifespan)
@app.get("/users")
async def list_users(
session: Annotated[AsyncSession, Depends(get_session)],
) -> list[dict]:
...
Documentation
docs/recipes/sqlalchemy.md— full async-SQLAlchemy walkthrough.docs/cutover/v0.1.0.md— maiden voyage migration story (the v0.30 split + the get_session/setup_db relocation to mgf-fastapi).PUBLIC_API.md— full public surface contract.CHANGELOG.md— release history.
For the federation-wide engineering standards (DESIGN_PRINCIPLES,
ERROR_HANDLING, SECURITY, etc.) see
mgf-common/docs/standards/.
This sibling inherits them by reference; the standards
source-of-truth lives in mgf-common.
Status
🚧 Experimental — every public name is experimental per AP-09.
Promotion to stable happens release-by-release as consumer feedback
in mgf-common/FEEDBACK.md
converges. The 0.x window applies. Pin tightly:
mgf-sqlalchemy = ">=0.X.0,<0.Y".
Cross-references
- Filing process for sharp edges: open an entry on
mgf-common/FEEDBACK.mdwith[mgf-sqlalchemy]prefix, OR file directly on this repo's Issues → maintainer mirrors into the canonical FEEDBACK.md. - Federation pattern:
mgf-common/docs/design/federation.md. - The split that created this sibling:
mgf-common/docs/release/federation_roadmap.md. - Companion sibling:
mgf-alembic— async-aware alembic env.py helper (paired ship at v0.30; depends on this sibling).
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file mgf_sqlalchemy-0.1.0.tar.gz.
File metadata
- Download URL: mgf_sqlalchemy-0.1.0.tar.gz
- Upload date:
- Size: 88.1 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: uv/0.10.8 {"installer":{"name":"uv","version":"0.10.8","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
e7688e8472a40d441568796f70480d331baddac38cd17737fc5c796f2dc0cc62
|
|
| MD5 |
85096387da5853f92fc9a52b59dcbb58
|
|
| BLAKE2b-256 |
c3666a04ee600862524f5d6735f30287bccf97889f34787eef247340ff544eef
|
File details
Details for the file mgf_sqlalchemy-0.1.0-py3-none-any.whl.
File metadata
- Download URL: mgf_sqlalchemy-0.1.0-py3-none-any.whl
- Upload date:
- Size: 9.2 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: uv/0.10.8 {"installer":{"name":"uv","version":"0.10.8","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
be3dda61202c3e54e82effa2359fd4d82287228255166f734203069cac3273e7
|
|
| MD5 |
840b7a79f397d67a4a5f386e22b8b651
|
|
| BLAKE2b-256 |
59d0e884b67aa16d150b87a0040d3d90fdae9ef3f6004e21cb0fc8eebc5db4da
|