sqlalchemy-session-proxy
A lightweight proxy for SQLAlchemy sessions that provides a unified interface over both synchronous (Session) and asynchronous (AsyncSession) usage.
This library allows you to write database-access code that works in both sync and async environments with minimal branching, while still respecting SQLAlchemy’s execution model.
Features
- Unified API for
SessionandAsyncSession - Automatic async detection via
is_async - Explicit dispatching to sync or async implementations
- Async-compatible method signatures for mixed environments
- Fully type-annotated for IDEs and static analysis
- No hidden magic beyond SQLAlchemy’s own async design
Installation
pip install sqlalchemy-session-proxy
Basic Usage
from sqlalchemy.orm import Session
from sqlalchemy.ext.asyncio import AsyncSession
from sqlalchemy_session_proxy.session_proxy import SqlalchemySessionProxy
Synchronous Session
session = Session(...)
proxy = SqlalchemySessionProxy(session)
proxy.add(obj)
proxy.commit()
result = proxy.execute(statement)
Asynchronous Session
async def main():
async_session = AsyncSession(...)
proxy = SqlalchemySessionProxy(async_session)
proxy.add(obj) # NOT awaitable (by SQLAlchemy design)
await proxy.commit() # awaitable
result = await proxy.execute(statement)
⚠️ Important
Some methods (such as
add,add_all,expire) are synchronous by design even when used withAsyncSession. This behavior follows SQLAlchemy’s official API.
Unified Execution Pattern
The following methods automatically dispatch based on the session type:
result = await proxy.execute(stmt)
rows = await proxy.scalars(stmt)
value = await proxy.scalar(stmt)
obj = await proxy.get(User, user_id)
- In sync mode, these methods do not require
await - In async mode, they must be awaited
API Overview
Core Properties
SqlalchemySessionProxy(session).session— underlyingSessionorAsyncSession.is_async—Trueif usingAsyncSession
Method Compatibility Matrix
| Method | Sync | Async | Notes |
|---|---|---|---|
add |
✔️ | ✔️ | Not awaitable |
add_all |
✔️ | ✔️ | Not awaitable |
commit |
✔️ | ✔️ | Awaitable in async |
rollback |
✔️ | ✔️ | Awaitable in async |
close |
✔️ | ✔️ | Awaitable in async |
flush |
✔️ | ✔️ | Awaitable in async |
merge |
✔️ | ✔️ | Awaitable in async |
delete |
✔️ | ✔️ | Awaitable in async |
get |
✔️ | ✔️ | Awaitable in async |
get_one |
✔️ | ✔️ | Awaitable in async |
execute |
✔️ | ✔️ | Awaitable in async |
scalars |
✔️ | ✔️ | Awaitable in async |
scalar |
✔️ | ✔️ | Awaitable in async |
refresh |
✔️ | ✔️ | Awaitable in async |
expire |
✔️ | ✔️ | Not awaitable |
expire_all |
✔️ | ✔️ | Not awaitable |
expunge |
✔️ | ✔️ | Not awaitable |
expunge_all |
✔️ | ✔️ | Not awaitable |
is_modified |
✔️ | ✔️ | Not awaitable |
in_transaction |
✔️ | ✔️ | Not awaitable |
in_nested_transaction |
✔️ | ✔️ | Not awaitable |
query |
✔️ | ❌ | Sync-only (legacy API) |
stream |
❌ | ✔️ | Async-only |
stream_scalars |
❌ | ✔️ | Async-only |
run_sync |
❌ | ✔️ | Async-only |
Notes on query()
-
query()is sync-only -
Calling it on an
AsyncSessionproxy raisesNotImplementedError -
This mirrors SQLAlchemy’s own guidance:
Queryis legacy- Prefer
select()for new code
run_sync
def legacy_fn(session: Session, value: str) -> str:
session.add(MyModel(name=value))
session.flush()
return "ok"
async def main():
async with AsyncSession(engine) as session:
proxy = SqlalchemySessionProxy(session)
result = await proxy.run_sync(legacy_fn, "test")
- Runs synchronous ORM logic inside async code
- Uses SQLAlchemy’s greenlet bridge
- Available only for
AsyncSession
License
Apache-2.0
Author
Tercel (tercel.yi@gmail.com)
Links
Metadata
Release files for sqlalchemy-session-proxy 0.3.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 | |
|---|---|---|---|
| sqlalchemy_session_proxy-0.3.0.tar.gz | 12.4 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| sqlalchemy_session_proxy-0.3.0-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 22.0 kB
Release files / sqlalchemy_session_proxy-0.3.0.tar.gz
| Download URL | sqlalchemy_session_proxy-0.3.0.tar.gz |
|---|---|
| Size | 12.4 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
a8a7eb541d0841939d3484abe85e5422d22779e17bac5425851b1306042453c9
|
|
BLAKE2b-256 checksum How to use checksums |
f919924ab0b4bf7a176075667a9a71d1955ccb8f0cdc73ba7cc010752982b82d
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/6.2.0 CPython/3.12.11
|
Release files / sqlalchemy_session_proxy-0.3.0-py3-none-any.whl
| Download URL | sqlalchemy_session_proxy-0.3.0-py3-none-any.whl |
|---|---|
| Size | 9.7 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
5b4e1bb106b81e6b81b5ea1df330bf0ca4fa6722ce4508af5afd384d06f421c4
|
|
BLAKE2b-256 checksum How to use checksums |
221835912c936a198ad7196dc77e06a1eb26dcade0c14d78967523647fb4ab95
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/6.2.0 CPython/3.12.11
|