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.1.tar.gz (88.4 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.1-py3-none-any.whl (9.2 kB view details)

Uploaded Python 3

File details

Details for the file mgf_sqlalchemy-0.1.1.tar.gz.

File metadata

  • Download URL: mgf_sqlalchemy-0.1.1.tar.gz
  • Upload date:
  • Size: 88.4 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.1.tar.gz
Algorithm Hash digest
SHA256 0e32ad706e951222aebb7e8c029624294c0c716f95c38d838cb925b28040a1a7
MD5 30fb563f959005ae4b06a6bb72353c45
BLAKE2b-256 577e533b1a476be2fa776e1aeb67315843835c112089a43e92321b5c84bc2fe5

See more details on using hashes here.

File details

Details for the file mgf_sqlalchemy-0.1.1-py3-none-any.whl.

File metadata

  • Download URL: mgf_sqlalchemy-0.1.1-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.1-py3-none-any.whl
Algorithm Hash digest
SHA256 40e8c55a2bfa0d45f8ae3b5c0cc68a85b13da6fa8bd6ed13e0ed5308a3faae51
MD5 7fafbe311e025eb4bbe1f58347ad7cb2
BLAKE2b-256 0f0b50464b8dc157b0a2381ebf628122ce85d95aa4adedd11e6e9130452caa28

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