docs: add v5 migration guide

This commit is contained in:
2026-07-02 13:58:45 -04:00
parent ed0ca7b5dc
commit ba7d841a8b
4 changed files with 151 additions and 5 deletions
+2 -2
View File
@@ -21,7 +21,7 @@ The function creates and manages its own **dedicated session** internally, yield
user.balance += 100 user.balance += 100
# With a custom lock mode # With a custom lock mode
async with lock_tables(session, [Order], mode=LockMode.EXCLUSIVE): async with lock_tables(session=session, tables=[Order], mode=LockMode.EXCLUSIVE):
await process_order(session, order_id) await process_order(session, order_id)
``` ```
@@ -35,6 +35,6 @@ The function creates and manages its own **dedicated session** internally, yield
user.balance += 100 user.balance += 100
# With a custom lock mode # With a custom lock mode
async with lock_tables(session_maker, [Order], mode=LockMode.EXCLUSIVE) as session: async with lock_tables(session_maker=session_maker, tables=[Order], mode=LockMode.EXCLUSIVE) as session:
await process_order(session, order_id) await process_order(session, order_id)
``` ```
+147
View File
@@ -0,0 +1,147 @@
# Migrating to v5.0
This page covers every breaking change introduced in **v5.0** and the steps required to update your code.
---
## Database
`db.py` is now the `db/` package, built around one object, [`Database`](../reference/db.md#fastapi_toolsets.db.Database), that owns the engine and sessionmaker. The free functions that took a `session_maker` you built and passed around yourself are gone from request-handling code; `Database` builds the sessionmaker for you.
### `create_db_dependency` / `create_db_context` removed in favor of `Database`
Build one `Database` with your URL (or an existing `engine=`), then use the instance directly as the FastAPI dependency, and `db.session()` for sessions outside request handlers.
=== "Before (`v4`)"
```python
from sqlalchemy.ext.asyncio import create_async_engine, async_sessionmaker
from fastapi_toolsets.db import create_db_dependency, create_db_context
engine = create_async_engine("postgresql+asyncpg://...")
SessionLocal = async_sessionmaker(engine, expire_on_commit=False)
get_db = create_db_dependency(session_maker=SessionLocal)
get_db_context = create_db_context(session_maker=SessionLocal)
@app.get("/users")
async def list_users(session: AsyncSession = Depends(get_db)):
...
async def seed():
async with get_db_context() as session:
...
```
=== "Now (`v5`)"
```python
from fastapi_toolsets.db import Database
db = Database(url="postgresql+asyncpg://...")
@app.get("/users")
async def list_users(session: AsyncSession = Depends(db)):
...
async def seed():
async with db.session() as session:
...
```
Call `db.install(app)` to also commit before the response is sent (instead of in dependency teardown) and to dispose the engine on shutdown. See [the db module docs](../module/db.md#committing-before-the-response).
### `get_transaction` renamed to `transaction`
Same behavior (savepoint when already in a transaction, new transaction otherwise), new name, same import path.
=== "Before (`v4`)"
```python
from fastapi_toolsets.db import get_transaction
async with get_transaction(session=session):
session.add(model)
```
=== "Now (`v5`)"
```python
from fastapi_toolsets.db import transaction
async with transaction(session=session):
session.add(model)
```
If you have a `Database` instance, `db.begin()` opens a session already inside a transaction:
```python
async with db.begin() as session:
session.add(User(name="ada"))
```
### `lock_tables` is now also a `Database` method
The free `lock_tables(session_maker, tables, ...)` function still exists for callers who manage their own session factory, but prefer `db.lock_tables(tables, ...)`, which drops the `session_maker` argument:
=== "Before (`v4`)"
```python
from fastapi_toolsets.db import lock_tables, LockMode
async with lock_tables(session_maker=session_maker, tables=[Order], mode=LockMode.EXCLUSIVE) as session:
await process_order(session, order_id)
```
=== "Now (`v5`)"
```python
from fastapi_toolsets.db import LockMode
async with db.lock_tables(tables=[Order], mode=LockMode.EXCLUSIVE) as session:
await process_order(session, order_id)
```
### `create_database` and `cleanup_tables` moved to `fastapi_toolsets.db.testing`
=== "Before (`v4`)"
```python
from fastapi_toolsets.db import create_database, cleanup_tables
```
=== "Now (`v5`)"
```python
from fastapi_toolsets.db.testing import create_database, cleanup_tables
```
## Fixtures
### `get_obj_by_attr` / `get_field_by_attr` are now `FixtureRegistry` methods
=== "Before (`v4`)"
```python
from fastapi_toolsets.fixtures import get_obj_by_attr, get_field_by_attr
@fixtures.register(depends_on=["roles"])
def users():
admin_role = get_obj_by_attr(roles, "name", "admin")
return [User(id=1, username="alice", role_id=admin_role.id)]
```
=== "Now (`v5`)"
```python
@fixtures.register(depends_on=["roles"])
def users():
admin_role = fixtures.obj("roles", "name", "admin")
return [User(id=1, username="alice", role_id=admin_role.id)]
```
## Security
The security module has been removed and moved to a dedicated python package: [`fastapi-multiauth`](https://github.com/d3vyce/fastapi-multiauth).
Run `uv add fastapi-multiauth` and replace `from fastapi_toolsets.security import ...` with `from fastapi_multiauth import ...`.
+1 -1
View File
@@ -24,7 +24,7 @@ Configure the CLI in your `pyproject.toml`:
```toml ```toml
[tool.fastapi-toolsets] [tool.fastapi-toolsets]
cli = "myapp.cli:cli" # Custom Typer app custom_cli = "myapp.cli:cli" # Custom Typer app
fixtures = "myapp.fixtures:registry" # FixtureRegistry instance fixtures = "myapp.fixtures:registry" # FixtureRegistry instance
db_context = "myapp.db:db_context" # Async context manager for sessions db_context = "myapp.db:db_context" # Async context manager for sessions
``` ```
+1 -2
View File
@@ -121,7 +121,6 @@ Modules = [
{Models = "module/models.md"}, {Models = "module/models.md"},
{Pytest = "module/pytest.md"}, {Pytest = "module/pytest.md"},
{Schemas = "module/schemas.md"}, {Schemas = "module/schemas.md"},
{Security = "module/security.md"},
] ]
[[project.nav]] [[project.nav]]
@@ -137,7 +136,6 @@ Reference = [
{Models = "reference/models.md"}, {Models = "reference/models.md"},
{Pytest = "reference/pytest.md"}, {Pytest = "reference/pytest.md"},
{Schemas = "reference/schemas.md"}, {Schemas = "reference/schemas.md"},
{Security = "reference/security.md"},
] ]
[[project.nav]] [[project.nav]]
@@ -147,6 +145,7 @@ Examples = [
[[project.nav]] [[project.nav]]
Migration = [ Migration = [
{"v5.0" = "migration/v5.md"},
{"v4.0" = "migration/v4.md"}, {"v4.0" = "migration/v4.md"},
{"v3.0" = "migration/v3.md"}, {"v3.0" = "migration/v3.md"},
{"v2.0" = "migration/v2.md"}, {"v2.0" = "migration/v2.md"},