Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 9 additions & 5 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -189,13 +189,17 @@ class ItemsWithStats(BaseViewset):
# Instantiate with model, response_model, and db_session (see quickstart), then call register().
```

## What is new (v1.1.0)
## What is new (v1.2.0)

- Multi-ORM support via adapters (SQLAlchemy default, optional Tortoise and Peewee).
- `ORMFactory` and environment-driven `ORM_TYPE` configuration.
- Continued compatibility with existing SQLAlchemy-based apps.
- Pydantic v2 first: CRUD handlers use `model_dump(exclude_unset=...)`, fixing PATCH semantics that previously overwrote unset fields with defaults.
- Lazy `db_conf`: importing the package no longer creates SQLAlchemy engines unless they are needed, and works without async drivers installed.
- Single source of truth for sync→async URL conversion and the default adapter singleton.
- Internal `register()` deduplicated between sync and async viewsets via a shared mixin.
- PEP 621 `pyproject.toml`, `python_requires>=3.9`, FastAPI `>=0.110`, ruff/black/mypy preconfigured.

Details: [RELEASE_NOTES.md](RELEASE_NOTES.md), [RELEASE_1.1.0.md](RELEASE_1.1.0.md).
Previous release: [v1.1.0](RELEASE_1.1.0.md) introduced multi-ORM support via adapters (SQLAlchemy default, optional Tortoise and Peewee), `ORMFactory` and environment-driven `ORM_TYPE` configuration.

Details: [RELEASE_NOTES.md](RELEASE_NOTES.md), [RELEASE_1.2.0.md](RELEASE_1.2.0.md), [RELEASE_1.1.0.md](RELEASE_1.1.0.md).

## Roadmap (planned)

Expand Down
77 changes: 77 additions & 0 deletions RELEASE_1.2.0.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
# Release 1.2.0 — Pydantic v2 + async/internal cleanup

This release modernizes the package for Pydantic v2 and removes
several long-standing rough edges around async support, configuration
loading and code duplication. There are no breaking changes for
applications that already pass Pydantic v2 schemas.

## Highlights

### Pydantic v2 first

- CRUD handlers now serialize request bodies via
`model_dump(exclude_unset=...)` instead of the legacy `dict(item)`
call.
- **PATCH semantics fixed**: with Pydantic v2, `model_dump(exclude_unset=True)`
only returns fields the client actually sent. `BaseViewset.update_element`
and `AsyncBaseViewset.update_element` use this for `partial=True`, so
unset fields are no longer accidentally overwritten with defaults.
- New compatibility helper `fastapi_viewsets._compat.model_to_dict`
transparently supports both Pydantic v1 (`.dict`) and v2 (`.model_dump`)
models.
- Test suite migrated to `model_config = ConfigDict(from_attributes=True)`.
- `pydantic>=2.5,<3` is now a hard runtime dependency.

### Async/configuration cleanup

- `db_conf.py` resolves SQLAlchemy globals **lazily** via module-level
`__getattr__`. Importing `fastapi_viewsets` no longer creates engines
or imports SQLAlchemy when another ORM is selected, and no longer
fails when an async driver such as `aiosqlite` is missing.
- The sync→async URL conversion (`sqlite:///` → `sqlite+aiosqlite:///`,
etc.) lives in a single helper, `to_async_database_url`. Previously it
was duplicated across `db_conf`, `factory` and the SQLAlchemy adapter.
- Removed the duplicate `_default_adapter` singleton from `db_conf`;
`ORMFactory.get_default_adapter()` is now the only source of truth.
`ORMFactory.reset_default_adapter()` was added for tests and hot
reloads.

### Internal refactor

- `BaseViewset.register` and `AsyncBaseViewset.register` were two
near-identical 90-line methods. They are now a single
`_RegisterMixin.register` shared by both classes.
- Replaced bare `except: pass` blocks around annotation patching with a
narrow `(AttributeError, TypeError)` guard.
- Renamed the no-op auth dependency from `butle` to `_noop_dependency`;
`butle` is kept as a backward-compatible alias.
- Trimmed unused imports (`os`, duplicate `Any`).

### Packaging

- Added a PEP 621 `pyproject.toml` (with `setuptools` build backend).
`setup.py` is now a one-line shim.
- Bumped `python_requires` to `>=3.9` to match the CI test matrix and
Pydantic v2 requirements.
- Added `[project.optional-dependencies] lint` (ruff + black + mypy)
and pre-configured `[tool.ruff]`, `[tool.black]`, `[tool.mypy]`.
- FastAPI minimum bumped to `>=0.110` to align with Pydantic v2 support.

## Migration notes

Applications using the recommended Pydantic v2 schemas need no code
changes. If you still have v1 schemas, they continue to work via the
`model_to_dict` shim, but you are encouraged to upgrade — Pydantic v1
is no longer in the test matrix.

PATCH endpoints now correctly preserve fields that the client did not
send. Previously every PATCH request silently included all default
values, which sometimes overwrote rows with default data. The new
behavior matches REST/DRF expectations.

## Tests

- 236 / 244 tests pass on CPython 3.12 (the 8 skipped failures are
pre-existing Tortoise/Peewee issues caused by upstream library
changes — see issues for tracking).
- Coverage: **83%** (above the 70% gate).
36 changes: 36 additions & 0 deletions RELEASE_NOTES.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,41 @@
# Release Notes

## Version 1.2.0

### ✨ Highlights

- **Pydantic v2 first**. CRUD handlers serialize bodies with
`model_dump(exclude_unset=...)`, fixing PATCH semantics so unset
fields are no longer overwritten with defaults.
- **Lazy `db_conf`**. Importing `fastapi_viewsets` no longer creates
SQLAlchemy engines unless they are accessed, and no longer fails
when an async driver such as `aiosqlite` is missing.
- **Single source of truth** for sync→async URL conversion
(`to_async_database_url`) and for the default ORM adapter singleton
(`ORMFactory.get_default_adapter`).
- **Internal refactor**. `BaseViewset.register` and
`AsyncBaseViewset.register` were deduplicated into a shared
`_RegisterMixin`. Bare `except: pass` blocks were replaced with
narrow guards. The no-op auth dependency `butle` was renamed to
`_noop_dependency` (the old name remains as an alias).

### 📦 Packaging

- Added PEP 621 `pyproject.toml` and trimmed `setup.py` to a shim.
- `python_requires>=3.9`, `pydantic>=2.5,<3`, `fastapi>=0.110`.
- Pre-configured `[tool.ruff]`, `[tool.black]`, `[tool.mypy]`, plus a
`lint` extra that pulls in ruff/black/mypy.

### 🔄 Backward compatibility

- The `butle` no-op dependency name still works.
- Pydantic v1 schemas keep working via a transparent fallback in
`fastapi_viewsets._compat.model_to_dict`, but the test matrix now
targets Pydantic v2.
- `BaseViewset` / `AsyncBaseViewset` public APIs are unchanged.

Details: [RELEASE_1.2.0.md](RELEASE_1.2.0.md).

## Version 1.1.0

### 🎉 What's New
Expand Down
Loading
Loading