voltwire-db-session
A configurable PostgreSQL session factory for Python applications. Wraps SQLAlchemy connection pool setup and pydantic-settings configuration into a single reusable package — install it, point it at your .env, and get sessions.
ORM-agnostic core
DatabaseSessionFactory, RODatabaseSessionFactory, and Session (exported from voltwire.db.session) are Protocols, not concrete classes. TransactionContext and DatabaseAutoConfiguration are written entirely against these interfaces and never import sqlalchemy — only voltwire.db.session.backends.sqlalchemy does. Today that's the only backend (SqlAlchemyDatabaseSessionFactory/SqlAlchemyRODatabaseSessionFactory, built via build_session_factory/build_ro_session_factory), but a future ORM backend only needs to satisfy the same Protocols — no changes required to TransactionContext, DatabaseAutoConfiguration, or downstream packages like voltwire-fastapi-db-txs, which already depend only on the abstraction.
Installation
pip install voltwire-db-session
# or with Poetry:
poetry add voltwire-db-session
A PostgreSQL driver is not included — install whichever you prefer alongside it:
pip install psycopg2-binary # most common
pip install psycopg # psycopg3
Quickstart
from voltwire.db.session import DatabaseSettings, build_session_factory
settings = DatabaseSettings() # reads DB_* vars from .env
factory = build_session_factory(settings)
session = factory.get_session()
try:
result = session.execute(...)
session.commit()
finally:
session.close()
# On app shutdown
factory.close()
Configuration
All settings are loaded from environment variables with a DB_ prefix. By default the library reads from a .env file in the working directory.
Environment variables
| Variable | Default | Description |
|---|---|---|
DB_HOST |
localhost |
Primary database host |
DB_PORT |
5432 |
Database port |
DB_DATABASE |
postgres |
Database name |
DB_USERNAME |
postgres |
Database username |
DB_PASSWORD |
postgres |
Database password |
DB_SCHEMA_NAME |
public |
PostgreSQL schema (used for search_path) |
DB_DRIVER |
psycopg2 |
SQLAlchemy driver name |
DB_RO_HOST |
(unset) | Read-only replica host; falls back to DB_HOST |
DB_POOL_SIZE |
10 |
Minimum connections in pool |
DB_MAX_POOL_SIZE |
20 |
Maximum connections in pool |
DB_POOL_TIMEOUT |
30 |
Seconds to wait for a connection from pool |
DB_POOL_RECYCLE |
299 |
Recycle connections after this many seconds |
DB_APPLICATION_NAME |
app |
Application name reported to PostgreSQL |
Choosing your env file
# Standard .env (default)
settings = DatabaseSettings()
# Custom env file — e.g. .env.local, .env.production
settings = DatabaseSettings.from_env(".env.local")
# No file — reads only from real environment variables
settings = DatabaseSettings.from_env(None)
# No file, with inline overrides
settings = DatabaseSettings.from_env(None, host="db.internal", database="myapp")
Using a different driver
# psycopg3
settings = DatabaseSettings.from_env(".env", driver="psycopg")
# or via env var
# DB_DRIVER=psycopg
The driver value is used as the SQLAlchemy URL scheme: postgresql+{driver}://.... The corresponding package must be installed in your environment.
Read-only replica
from voltwire.db.session import DatabaseSettings, build_ro_session_factory
settings = DatabaseSettings() # set DB_RO_HOST to point at your replica
ro_factory = build_ro_session_factory(settings)
session = ro_factory.get_session() # writes will be rejected by PostgreSQL
If DB_RO_HOST is not set, RODatabaseSessionFactory falls back to the primary host but still enforces read-only mode at the PostgreSQL level.
FastAPI example
from contextlib import asynccontextmanager
from fastapi import FastAPI
from voltwire.db.session import DatabaseSettings, build_session_factory
settings = DatabaseSettings.from_env(".env.local")
@asynccontextmanager
async def lifespan(app: FastAPI):
app.state.db = build_session_factory(settings)
yield
app.state.db.close()
app = FastAPI(lifespan=lifespan)
@app.get("/items")
def list_items():
session = app.state.db.get_session()
try:
return session.execute(...).all()
finally:
session.close()
Logging
The library emits to the voltwire.db.session logger namespace using Python's standard logging module. To activate debug output:
import logging
logging.getLogger("voltwire.db.session").setLevel(logging.DEBUG)
Routing to loguru
If your app uses loguru, intercept stdlib logging once at startup:
import logging
from loguru import logger
class InterceptHandler(logging.Handler):
def emit(self, record: logging.LogRecord) -> None:
logger.opt(depth=6, exception=record.exc_info).log(
record.levelname, record.getMessage()
)
logging.getLogger("voltwire.db.session").addHandler(InterceptHandler())
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 voltwire_db_session-0.0.1.tar.gz.
File metadata
- Download URL: voltwire_db_session-0.0.1.tar.gz
- Upload date:
- Size: 16.1 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via:
uv/0.9.24 {"installer":{"name":"uv","version":"0.9.24","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"macOS","version":null,"id":null,"libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
269c32c93da24da066e8e40cde4cc9d7060fd40790ebfc205c92a6bf0f84cc37
|
|
| MD5 |
ac77d3ab1c17f79db99b761dd6538288
|
|
| BLAKE2b-256 |
8ff43103f28f13368ccc17c183d8dfeb4c84303c6cc66e6fd939926a5ee8a293
|
File details
Details for the file voltwire_db_session-0.0.1-py3-none-any.whl.
File metadata
- Download URL: voltwire_db_session-0.0.1-py3-none-any.whl
- Upload date:
- Size: 14.3 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via:
uv/0.9.24 {"installer":{"name":"uv","version":"0.9.24","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"macOS","version":null,"id":null,"libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
d2159a37bb6ee4640c7821a7f82e6ec86fba5c6b65fea1bab0cd1f551402199e
|
|
| MD5 |
7bc4191d2a67ff7c50e1447e863a7ab5
|
|
| BLAKE2b-256 |
05ea95be120683350cc348037ebf43cc4f9022c248dd6f2a9dea146e950752a4
|