A lightweight proxy for SQLAlchemy sessions that seamlessly supports both synchronous (`Session`) and asynchronous (`AsyncSession`) usage. This library provides a unified interface to interact with SQLAlchemy sessions, making it easy to write code that works in both sync and async environments.
Project description
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
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 sqlalchemy_session_proxy-0.3.0.tar.gz.
File metadata
- Download URL: sqlalchemy_session_proxy-0.3.0.tar.gz
- Upload date:
- Size: 12.4 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.12.11
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
a8a7eb541d0841939d3484abe85e5422d22779e17bac5425851b1306042453c9
|
|
| MD5 |
a21f139d1ca6eaca025c6a30443026b9
|
|
| BLAKE2b-256 |
f919924ab0b4bf7a176075667a9a71d1955ccb8f0cdc73ba7cc010752982b82d
|
File details
Details for the file sqlalchemy_session_proxy-0.3.0-py3-none-any.whl.
File metadata
- Download URL: sqlalchemy_session_proxy-0.3.0-py3-none-any.whl
- Upload date:
- Size: 9.7 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.12.11
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
5b4e1bb106b81e6b81b5ea1df330bf0ca4fa6722ce4508af5afd384d06f421c4
|
|
| MD5 |
9f02d82700a479f8e4034f98cb578e0a
|
|
| BLAKE2b-256 |
221835912c936a198ad7196dc77e06a1eb26dcade0c14d78967523647fb4ab95
|