docs: add migration + fix icon

This commit is contained in:
2026-03-02 11:19:37 -05:00
parent e2df00bd75
commit b6d811cd77
4 changed files with 194 additions and 2 deletions

137
docs/migration/v2.md Normal file
View File

@@ -0,0 +1,137 @@
# Migrating to v2.0
This page covers every breaking change introduced in **v2.0** and the steps required to update your code.
---
## CRUD
### `schema` is now required in `offset_paginate()` and `cursor_paginate()`
Calls that omit `schema` will now raise a `TypeError` at runtime.
Previously `schema` was optional; omitting it returned raw SQLAlchemy model instances inside the response. It is now a required keyword argument and the response always contains serialized schema instances.
=== "Before (`v1`)"
```python
# schema omitted — returned raw model instances
result = await UserCrud.offset_paginate(session, page=1)
result = await UserCrud.cursor_paginate(session, cursor=token)
```
=== "Now (`v2`)"
```python
result = await UserCrud.offset_paginate(session, page=1, schema=UserRead)
result = await UserCrud.cursor_paginate(session, cursor=token, schema=UserRead)
```
### `as_response` removed from `create()`, `get()`, and `update()`
Passing `as_response` to these methods will raise a `TypeError` at runtime.
The `as_response=True` shorthand is replaced by passing a `schema` directly. The return value is a `Response[schema]` when `schema` is provided, or the raw model instance when it is not.
=== "Before (`v1`)"
```python
user = await UserCrud.create(session, data, as_response=True)
user = await UserCrud.get(session, filters, as_response=True)
user = await UserCrud.update(session, data, filters, as_response=True)
```
=== "Now (`v2`)"
```python
user = await UserCrud.create(session, data, schema=UserRead)
user = await UserCrud.get(session, filters, schema=UserRead)
user = await UserCrud.update(session, data, filters, schema=UserRead)
```
### `delete()`: `as_response` renamed and return type changed
`as_response` is gone, and the plain (non-response) call no longer returns `True`.
Two changes were made to `delete()`:
1. The `as_response` parameter is renamed to `return_response`.
2. When called without `return_response=True`, the method now returns `None` on success instead of `True`.
=== "Before (`v1`)"
```python
ok = await UserCrud.delete(session, filters)
if ok: # True on success
...
response = await UserCrud.delete(session, filters, as_response=True)
```
=== "Now (`v2`)"
```python
await UserCrud.delete(session, filters) # returns None
response = await UserCrud.delete(session, filters, return_response=True)
```
### `paginate()` alias removed
Any call to `crud.paginate(...)` will raise `AttributeError` at runtime.
The `paginate` shorthand was an alias for `offset_paginate`. It has been removed; call `offset_paginate` directly.
=== "Before (`v1`)"
```python
result = await UserCrud.paginate(session, page=2, items_per_page=20, schema=UserRead)
```
=== "Now (`v2`)"
```python
result = await UserCrud.offset_paginate(session, page=2, items_per_page=20, schema=UserRead)
```
---
## Exceptions
### Missing `api_error` raises `TypeError` at class definition time
Unfinished or stub exception subclasses that previously compiled fine will now fail on import.
In `v1`, a subclass without `api_error` would only fail when the exception was raised. In `v2`, `__init_subclass__` validates this at class definition time.
=== "Before (`v1`)"
```python
class MyError(ApiException):
pass # fine until raised
```
=== "Now (`v2`)"
```python
class MyError(ApiException):
pass # TypeError: MyError must define an 'api_error' class attribute.
```
For shared base classes that are not meant to be raised directly, use `abstract=True`:
```python
class BillingError(ApiException, abstract=True):
"""Base for all billing-related errors — not raised directly."""
class PaymentRequiredError(BillingError):
api_error = ApiError(code=402, msg="Payment Required", desc="...", err_code="BILLING-402")
```
---
## Schemas
### `Pagination` alias removed
`Pagination` was already deprecated in `v1` and is fully removed in `v2`, you now need to use [`OffsetPagination`](../reference/schemas.md#fastapi_toolsets.schemas.OffsetPagination) or [`CursorPagination`](../reference/schemas.md#fastapi_toolsets.schemas.CursorPagination).

View File

@@ -1,4 +1,4 @@
# `schemas` module # `schemas`
Here's the reference for all response models and types provided by the `schemas` module. Here's the reference for all response models and types provided by the `schemas` module.

View File

@@ -1,7 +1,13 @@
"""Generic async CRUD operations for SQLAlchemy models.""" """Generic async CRUD operations for SQLAlchemy models."""
from ..exceptions import InvalidFacetFilterError, NoSearchableFieldsError from ..exceptions import InvalidFacetFilterError, NoSearchableFieldsError
from ..types import FacetFieldType, JoinType, M2MFieldType, OrderByClause from ..types import (
FacetFieldType,
JoinType,
M2MFieldType,
OrderByClause,
SearchFieldType,
)
from .factory import CrudFactory from .factory import CrudFactory
from .search import SearchConfig, get_searchable_fields from .search import SearchConfig, get_searchable_fields
@@ -15,4 +21,5 @@ __all__ = [
"NoSearchableFieldsError", "NoSearchableFieldsError",
"OrderByClause", "OrderByClause",
"SearchConfig", "SearchConfig",
"SearchFieldType",
] ]

View File

@@ -77,6 +77,10 @@ md_in_html = {}
"pymdownx.tasklist" = {custom_checkbox = true} "pymdownx.tasklist" = {custom_checkbox = true}
"pymdownx.tilde" = {} "pymdownx.tilde" = {}
[project.markdown_extensions.pymdownx.emoji]
emoji_index = "zensical.extensions.emoji.twemoji"
emoji_generator = "zensical.extensions.emoji.to_svg"
[project.markdown_extensions."pymdownx.highlight"] [project.markdown_extensions."pymdownx.highlight"]
anchor_linenums = true anchor_linenums = true
line_spans = "__span" line_spans = "__span"
@@ -95,3 +99,47 @@ permalink = true
[project.markdown_extensions."pymdownx.snippets"] [project.markdown_extensions."pymdownx.snippets"]
base_path = ["."] base_path = ["."]
check_paths = true check_paths = true
[[project.nav]]
Home = "index.md"
[[project.nav]]
Modules = [
{CLI = "module/cli.md"},
{CRUD = "module/crud.md"},
{Database = "module/db.md"},
{Dependencies = "module/dependencies.md"},
{Exceptions = "module/exceptions.md"},
{Fixtures = "module/fixtures.md"},
{Logger = "module/logger.md"},
{Metrics = "module/metrics.md"},
{Pytest = "module/pytest.md"},
{Schemas = "module/schemas.md"},
]
[[project.nav]]
Reference = [
{CLI = "reference/cli.md"},
{CRUD = "reference/crud.md"},
{Database = "reference/db.md"},
{Dependencies = "reference/dependencies.md"},
{Exceptions = "reference/exceptions.md"},
{Fixtures = "reference/fixtures.md"},
{Logger = "reference/logger.md"},
{Metrics = "reference/metrics.md"},
{Pytest = "reference/pytest.md"},
{Schemas = "reference/schemas.md"},
]
[[project.nav]]
Examples = [
{"Pagination & Search" = "examples/pagination-search.md"},
]
[[project.nav]]
Migration = [
{"v2.0" = "migration/v2.md"},
]
[[project.nav]]
"Changelog ↗" = "https://github.com/d3vyce/fastapi-toolsets/releases"