Skip to main content

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

PyPI Python

Sibling of mgf-common under the mgf.* namespace. Houses the async-SQLAlchemy helpers that previously lived under mgf.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

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

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

mgf_sqlalchemy-0.1.0.tar.gz (88.1 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

mgf_sqlalchemy-0.1.0-py3-none-any.whl (9.2 kB view details)

Uploaded Python 3

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

Hashes for mgf_sqlalchemy-0.1.0.tar.gz
Algorithm Hash digest
SHA256 e7688e8472a40d441568796f70480d331baddac38cd17737fc5c796f2dc0cc62
MD5 85096387da5853f92fc9a52b59dcbb58
BLAKE2b-256 c3666a04ee600862524f5d6735f30287bccf97889f34787eef247340ff544eef

See more details on using hashes here.

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

Hashes for mgf_sqlalchemy-0.1.0-py3-none-any.whl
Algorithm Hash digest
SHA256 be3dda61202c3e54e82effa2359fd4d82287228255166f734203069cac3273e7
MD5 840b7a79f397d67a4a5f386e22b8b651
BLAKE2b-256 59d0e884b67aa16d150b87a0040d3d90fdae9ef3f6004e21cb0fc8eebc5db4da

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page