hawkapi-sqlalchemy
SQLAlchemy integration for HawkAPI. Async sessions, multi-database routing (primary/replica/shards), Alembic helpers, and pytest fixtures.
Install
pip install hawkapi-sqlalchemy # SQLite included
pip install 'hawkapi-sqlalchemy[postgres]' # + asyncpg
pip install 'hawkapi-sqlalchemy[mysql]' # + aiomysql
Quickstart
from hawkapi import Depends, HawkAPI
from sqlalchemy.ext.asyncio import AsyncSession
from sqlalchemy.orm import Mapped, mapped_column
from hawkapi_sqlalchemy import Base, TimestampMixin, get_session, init_database
class User(Base, TimestampMixin):
__tablename__ = "users"
id: Mapped[int] = mapped_column(primary_key=True, autoincrement=True)
email: Mapped[str] = mapped_column(unique=True)
app = HawkAPI()
init_database(app, url="postgresql+asyncpg://user:pw@localhost/app")
@app.post("/users")
async def create(email: str, sess: AsyncSession = Depends(get_session)):
sess.add(User(email=email))
await sess.flush()
return {"ok": True}
The get_session dependency opens a fresh session per request, commits on success, and rolls back on exception — no boilerplate.
Multiple databases
from hawkapi_sqlalchemy import DatabaseConfig, init_database, session_for
init_database(
app,
databases={
"primary": DatabaseConfig(url="postgresql+asyncpg://…/primary"),
"replica": DatabaseConfig(url="postgresql+asyncpg://…/replica"),
"analytics": DatabaseConfig(url="postgresql+asyncpg://…/analytics"),
},
)
# DI helpers:
from hawkapi_sqlalchemy import get_session, get_replica_session
get_analytics = session_for("analytics", commit=False)
@app.get("/report")
async def report(sess: AsyncSession = Depends(get_analytics)):
...
get_replica_session falls back to primary if no replica is registered, so you can switch on without changing handlers.
Mixins
from hawkapi_sqlalchemy import Base, TimestampMixin, UUIDMixin
class Doc(Base, UUIDMixin, TimestampMixin):
__tablename__ = "docs"
title: Mapped[str] = mapped_column()
TimestampMixin—created_at/updated_atwith DB-side defaults + Pythononupdate.UUIDMixin— stringidcolumn with auuid4()default.- Prefer
DataclassBaseoverBaseto get SQLAlchemy 2.0's dataclass-style declarative.
Alembic
In your alembic/env.py:
from hawkapi_sqlalchemy.alembic import run_migrations
from myapp.db import Base, settings # your Base + URL
run_migrations(target_metadata=Base.metadata, url=settings.database_url)
That's it — handles both online (live connection) and offline (--sql) modes; uses NullPool for migrations; enables render_as_batch=True automatically for SQLite.
Healthchecks
from hawkapi_sqlalchemy import all_healthy
@app.get("/healthz")
async def healthz():
return await all_healthy(app.state.db)
Returns {"primary": True, "replica": True, ...}.
Testing
import pytest
from hawkapi_sqlalchemy import Base, temporary_database
@pytest.fixture
async def db():
async with temporary_database(Base.metadata) as database:
yield database
async def test_something(db):
async with db.session() as sess:
...
temporary_database creates an in-memory SQLite engine, calls Base.metadata.create_all, yields, then drops the schema and disposes.
DatabaseConfig
DatabaseConfig(
url="postgresql+asyncpg://…",
echo=False,
pool_size=5,
max_overflow=10,
pool_timeout=30.0,
pool_recycle=3600,
pool_pre_ping=True,
connect_args={"server_settings": {"jit": "off"}},
engine_kwargs={...}, # forwarded to create_async_engine
session_kwargs={...}, # forwarded to async_sessionmaker
)
Development
git clone https://github.com/ashimov/hawkapi-sqlalchemy.git
cd hawkapi-sqlalchemy
uv sync --extra dev
uv run pytest -q
uv run ruff check . && uv run ruff format --check .
uv run pyright src/
License
MIT.
Metadata
Release files for hawkapi-sqlalchemy 0.2.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 | |
|---|---|---|---|
| hawkapi_sqlalchemy-0.2.0.tar.gz | 40.1 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| hawkapi_sqlalchemy-0.2.0-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 53.3 kB
Release files / hawkapi_sqlalchemy-0.2.0.tar.gz
| Download URL | hawkapi_sqlalchemy-0.2.0.tar.gz |
|---|---|
| Size | 40.1 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
c64395a0d7a74960ed5ab85ec05e7092cfba3cb2601d163f12e8ef0747e8615b
|
|
BLAKE2b-256 checksum How to use checksums |
46c34e2611bb39f8a1e4d143fddc95f90e5cbbfa6ccacc50b569ede4c01e7317
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/6.1.0 CPython/3.13.12
|
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.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on May 16, 2026.
Transparency logRelease files / hawkapi_sqlalchemy-0.2.0-py3-none-any.whl
| Download URL | hawkapi_sqlalchemy-0.2.0-py3-none-any.whl |
|---|---|
| Size | 13.1 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
13c4576d32e16321dff14b976dea29b26fa1ed491cfb1efb975050a6dc849046
|
|
BLAKE2b-256 checksum How to use checksums |
cea42b5dd5147efc7ed50bc36be096c6a040c1cba11ab70997cb678fc39233b8
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/6.1.0 CPython/3.13.12
|
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.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on May 16, 2026.
Transparency log