Registry / web-framework / cadwyn

cadwyn

JSON →
library7.2.0pypypi✓ verified 28d ago

Cadwyn is a Python library that provides production-ready, Stripe-like API versioning for FastAPI applications. It allows developers to maintain only the latest version of their API implementation, automatically generating older versions and handling backward compatibility. This approach encapsulates version changes in independent modules, simplifying business logic. The current version is 6.2.0, with an active development and release cadence.

pip install cadwyn
INSTALL
IMPORT
SIG · CADWYN
C
cadwyn
web-frameworkpythonv7.2.0
Install
4.4s avg
Import
1466ms
Disk
32MB
Pass rate
10/ 10
Env Coverage10 / 10
glibc
3.9–3.13
musl
3.9–3.13
Install & Compatibility
Where this runs
tested against v7.2.0 · pip install
no network on importno background threads
Install × environment matrix
Each cell = how many times install + import succeeded across repeated harness runs. Partial = flaky.
glibc = Debian/Ubuntu slim · musl = Alpine Linux
musl
py 3.10–3.95 runs
installs and imports cleanly · install 0.0s · import 1.534s · 33.7MB
glibc
py 3.10–3.95 runs
installs and imports cleanly · install 4.4s · import 1.398s · 33MB
32MB installed
● package 32MB
Code
Verified usage

Verified import paths — ran on the pinned version, not inferred.

Cadwyn
✓ from cadwyn import Cadwyn
VersionedAPIRouter
✓ from cadwyn import VersionedAPIRouter
VersionBundle
✓ from cadwyn import VersionBundle
schema
✓ from cadwyn.structure import schema
VersionChange
✓ from cadwyn.structure import VersionChange

This quickstart demonstrates how to set up a basic FastAPI application with Cadwyn for API versioning. It defines two versions (2024-01-01 and 2023-01-01), with a version change making the `email` field optional in `UserCreateRequest` for the older version. The `Cadwyn` instance handles the generation and inclusion of versioned routers, allowing your core business logic to interact only with the latest schema.

import datetime from fastapi import FastAPI from pydantic import BaseModel, Field from cadwyn import Cadwyn, VersionBundle, VersionedAPIRouter from cadwyn.structure import VersionChange, schema # 1. Define your schemas in the 'latest' version class UserCreateRequest(BaseModel): name: str email: str class UserResource(BaseModel): id: int name: str email: str # 2. Define your API versions # Use ISO date strings for versions for future compatibility (v6.x+) VERSION_2024_01_01 = datetime.date(2024, 1, 1) VERSION_2023_01_01 = datetime.date(2023, 1, 1) # 3. Define version changes class ChangeEmailFieldToOptional(VersionChange): description = 'Make email field optional in UserCreateRequest' version = VERSION_2023_01_01 @schema(UserCreateRequest).alter def alter_user_create_request(cls): cls.email = Field(default=None, union_of=[cls.email, type(None)]) # 4. Create a VersionBundle version_bundle = VersionBundle( latest_version=VERSION_2024_01_01, old_versions=[VERSION_2023_01_01], version_changes=[ChangeEmailFieldToOptional], ) # 5. Initialize Cadwyn and the versioned router app = FastAPI() cadwyn_app = Cadwyn( versions=version_bundle, api_version_header_name='x-api-version', latest_schemas_package=__name__, old_versions_package=__name__ ) # Use a standard FastAPI router but include it via Cadwyn router = VersionedAPIRouter(version_bundle=version_bundle) @router.post('/users', response_model=UserResource) async def create_user(user: UserCreateRequest): # Business logic always works with the latest schema return {"id": 1, "name": user.name, "email": user.email} @router.get('/users/{user_id}', response_model=UserResource) async def get_user(user_id: int): return {"id": user_id, "name": "John Doe", "email": "john.doe@example.com"} # Cadwyn generates and includes versioned routes cadwyn_app.generate_and_include_versioned_routers(app, router) # To run: uvicorn your_module_name:app --reload # Test with curl -H 'x-api-version: 2024-01-01' -X POST -H 'Content-Type: application/json' -d '{"name": "Alice", "email": "alice@example.com"}' http://localhost:8000/users # Test with curl -H 'x-api-version: 2023-01-01' -X POST -H 'Content-Type: application/json' -d '{"name": "Bob"}' http://localhost:8000/users
cadwyn --version
Debug
Known issues
breakingCadwyn v6.0.0 removed support for FastAPI versions older than 0.128.0 and Pydantic v1. Ensure your FastAPI and Pydantic installations meet the new minimum requirements.
fix
Upgrade FastAPI to 0.128.0 or newer and Pydantic to v2.x (if not already using it). Ensure your project's `requires_python` is `>=3.10`.
affects: >=6.0.0
breakingPython 3.9 support was removed in Cadwyn v6.0.3. Projects using older Python versions will not be compatible with recent Cadwyn releases.
fix
Upgrade your Python environment to 3.10 or higher.
affects: >=6.0.3
deprecatedThe `api_version_header_name` argument in `Cadwyn` is deprecated in favor of `api_version_parameter_name`. Also, `cadwyn.Cadwyn.add_header_versioned_routers` is deprecated and likely removed in favor of `generate_and_include_versioned_routers`.
fix
Use `api_version_parameter_name` for configuring how Cadwyn extracts the API version. Replace `add_header_versioned_routers` with `generate_and_include_versioned_routers`.
affects: >=5.x, <=6.2.0 (deprecation); >=6.0.0 (removal of old method)
gotchaCadwyn v6.x+ stores versions as strings (preferably ISO dates) internally. While date types can still be passed to `cadwyn.Version`, string types (like 'YYYY-MM-DD') are guaranteed to be supported in the future.
fix
When defining your versions, prefer using string representations of dates (e.g., '2024-01-01') instead of `datetime.date` objects, or ensure any `datetime.date` objects are handled consistently as Cadwyn converts them internally.
affects: >=6.0.0
gotchaCadwyn aims to eliminate explicit version checks in business logic. Directly checking `api_version_var.get() >= date(...)` is discouraged and often indicates a missing or incorrectly applied version change.
fix
Instead of direct version checks, define appropriate `VersionChange` objects to transform schemas and routes. This keeps your business logic version-agnostic. Refer to Cadwyn's documentation on version changes for better patterns.
affects: All versions
gotchaCadwyn does not automatically edit Python import statements when generating schemas. If you import from versioned code within other versioned code, use relative imports to ensure they resolve correctly after code generation.
fix
Use relative imports (e.g., `from . import some_module`) for any internal module imports within your versioned schemas or routes to maintain correct references across generated versions.
affects: All versions
breakingThe method `.alter` used for defining schema version changes has been removed or significantly changed. `AlterSchemaInstructionFactory` objects no longer have an `alter` attribute, leading to an `AttributeError` when attempting to use the old syntax.
fix
Consult the Cadwyn documentation for the correct and current API to define `VersionChange` objects and apply schema transformations. The syntax for altering schemas has likely been updated to use different methods or decorators.
affects: >=6.0.0
Errors
Common errors & fixes
fastapi.exceptions.FastAPIError: Invalid args for response field! Hint: check that <pydantic.types.JsonValue object at 0x...> is a valid Pydantic field type.
The `pydantic.JsonValue` type, when used as a direct type annotation in request body models, requires Pydantic 2.0+ and often Python 3.12+ for full compatibility, leading to validation errors in older environments.
fix
For Python versions older than 3.12 or Pydantic versions below 2.0, use `typing.Union[dict, list, str, int, float, bool, None]` or a custom `Annotated` type instead of `JsonValue` in your Pydantic models. Alternatively, upgrade Python to 3.12+ and Pydantic to 2.0+.
RuntimeError: No matching endpoint found for migration defined for version 'YYYY-MM-DD' and path '/your/api/path'.
A migration function was defined to operate on a specific API endpoint, but Cadwyn could not find a corresponding endpoint at the specified path and version in the `VersionedAPIRouter`. This usually occurs if the endpoint was removed, renamed, or its path changed without the migration being updated accordingly.
fix
Verify that the path and HTTP method used in your migration decorator (e.g., `@router.patch('/your/api/path')`) precisely match an existing endpoint in the `HeadVersion` or the target past version. If the endpoint was intentionally altered, adjust your migration to reflect these changes, potentially using `RemoveEndpoint` or `MoveEndpoint` migration types.
HTTP 400 Bad Request: The requested API version 'YYYY-MM-DD' is not registered.
The client attempted to access an API version (specified via header or query parameter) that has not been explicitly defined or included in your Cadwyn application's `VersionBundle`.
fix
Ensure that all supported API versions are correctly listed in the `VersionBundle` when initializing your Cadwyn application. For example: `app = Cadwyn(versions=VersionBundle(HeadVersion(), Version('2024-01-01'), Version('2023-01-01'))`. Also, verify the client is sending a valid and correctly formatted version string.
Upgrade
Version history
7.2.0latest on PyPI · released Jul 29, 2026
Audit
Dependencies
fastapirequiredCadwyn is built on and extends FastAPI for API versioning functionality.
pydanticrequiredCadwyn leverages Pydantic for defining API schemas and data validation.
Agent activity
20 hits · last 30 days
node
18
OpenAI (training)
1
Resources
cadwyn — pip install cadwyn · libregistry