Changelog¶
All notable changes to this project will be documented in this file. Please follow the Keep a Changelog standard.
[Unreleased]¶
[9.0.0]¶
Breaking¶
- Cadwyn now requires Python 3.11 or newer. Upgrade Python, or stay on Cadwyn 8.x (#548).
- Cadwyn now requires Pydantic 2.12.0 or newer. Upgrade Pydantic, or stay on Cadwyn 8.x (#570).
- Removed
/changelog,generate_changelog(), andhidden(). Remove their calls and the changelog arguments ofCadwyn(), keeping the instructions that you wrapped inhidden();changelog_url=Noneandinclude_changelog_url_in_schema=Falsestill work with aDeprecationWarninguntil 10.0 (#487). - Removed
Cadwyn(openapi_prefix=...). Set the root path on your server instead (#488). - Removed
Cadwyn(api_version_header_name=...). Pass the same value toapi_version_parameter_name(#550). - Removed
Cadwyn.add_header_versioned_routers(). Put the versions and their changes in aVersionBundle, then include the latest routers withgenerate_and_include_versioned_routers()(#550). - Removed
Version.version_changes,HeadVersion.version_changes, andVersionBundle.version_dates. Usechangesandversion_valuesinstead (#550). - API version headers whose names contain underscores, such as
api_version_parameter_name="api_version", are now validated and documented under that exact name. Invalid versions get a 422 instead of the latest version, and OpenAPI showsapi_versioninstead ofapi-version, which Cadwyn never read, so regenerate clients that sendapi-version(#630). - With path versioning, Cadwyn now reads the API version only from the
{api_version}parameter of the matched route, not from any URL segment that equals a version, such as a tenant ID. Values that aren't one of your versions get a 404 or a rejected WebSocket, and a URL that matches routes of several versions with{api_version}in different positions raisesCadwynError, so check that clients send the version in its route position and keep that position the same across versions.URLVersionManagernow takesapi_version_parameter_nameandversioned_routersinstead ofpossible_version_values(#622). .had(alias=...)and.didnt_have("alias")now also change the validation and serialization aliases that Pydantic derived from the old alias, so older versions use the documented key and reject data with only the old key. Add request and response migrations for the key, or remove the alias change to keep the old key (required inHeadVersion); see alias migrations (#465).- Request and response migrations by schema now also run for that schema as a union member (
Union[A, B],Optional[A]), inAnnotated, and in named type aliases. A migration of the whole union replaces its members' migrations in the same version change. Remove path migrations that now duplicate them, return model objects from such endpoints, and passmigrate_http_errors=Falseto member migrations; see data migrations for the new errors (#530). list[Model]anddict[str, Model]request bodies now keep extra keys, set fields, and aliased values in older versions, and run default factories for unset fields, when Cadwyn can be sure that it's right. Check code that usesmodel_extra,exclude_unset, or stateful factories, and set fields in a request migration if older clients need them; known limitations lists the bodies that keep the old behavior (#566).- Computed fields of request bodies no longer reach
request.bodyor the latest model as input. Compute such values in the migrations that need them, and stop reading them frommodel_extra; responses and models that overridemodel_dump()keep their previous behavior (#570). - Cadwyn no longer parses request bodies as JSON when FastAPI reads them as bytes, e.g. without a
Content-Typeheader, so migrations and body params may now get bytes or defaults. SendContent-Type: application/json, or setstrict_content_type=Falseon the app, router, or route (#531). - When a request body with restored validation aliases fails the latest version's validation, Cadwyn no longer solves the latest dependencies a second time, and
CadwynHeadRequestValidationErrorhas the restored body's errors. Update handlers and tests that read these errors; to get a default that only a custom core schema supplies, delete the rejected value in a request migration (#563). migrate_response_body()now restores validation aliases only when missing keys would certainly fail validation, as routes do, and a restored body that still fails reports its own errors. Set validation keys in response migrations for other cases, and update handlers and tests that check these errors (#565).- Response fields with different validation and serialization aliases, whose default comes only from a custom core schema, now keep their values in
migrate_response_body(), and invalid values raise errors in routes too instead of becoming the default. To get the default, delete such values in a response migration or fromlatest_body(#565). Json[...]fields in supported request bodies now get the string that the client sent, e.g.Json[Any]keeps"123"instead of giving123. Make clients encode such values once instead of twice; migrations that encode values withjson.dumps()keep working, subject to known limitations (#538).- A param or dependency named
body, or named after the body's alias, no longer replaces the request body. Path migrations of affected endpoints with files, forms, or embedded bodies now get the client's body orrequest.form; replace uploads in a request migration, or read the dependency's value explicitly (#526). - On FastAPI 0.158.2+, dependencies and overrides next to an endpoint's form model now get their own form values instead of defaults or 500 errors, including when an optional form model is omitted. Remove workarounds; params that Cadwyn can't give the right value now raise
CadwynError, so use distinct names or aliases, or read the form fromRequest(see known limitations) (#527). - On FastAPI 0.158.2+, dependency form models keep unused
AliasChoiceskeys as extras. Stop sending unused aliases when the model forbids extra fields, or allow extras if you need them (#527). - On FastAPI 0.158.2+, when a request omits an optional form model and other params read the form, those params now get the untouched form values and the keys that a request migration sets, as in plain FastAPI. The model gets the migrated body only if it has fields of the model. Remove lost-value workarounds; a migrated body that isn't a dict, or that has a dict or a nested collection as a value, raises
CadwynError(#529). - On FastAPI 0.153.0+, supported unions of form models keep lists, sets, and tuples from validators or migrations instead of reducing them to one item. Accept the container or select its last item explicitly; conflicting field shapes keep the old behavior before FastAPI 0.161.0 and raise
CadwynErroron newer versions (#532). - Plain enums and flags with
enum(...)instructions now reach endpoints as latest members, including inIterable[...]andGenerator[...]fields, and older enums accept matching latest members. Compare union fields to members rather than raw values, use migrations if you relied on_missing_replacing known members, and useisinstance(member, MyEnum)to tell latest members apart (#521). - Versioned enums now keep aliases,
nonmember()attributes,@memberfunctions, definition order, and custom member attributes, andhad()creates members as the class body does. Send member values, treat@memberfunctions as members, and update OpenAPI snapshots; a custom__new__that can't recreate attributes from the member value now fails at startup, so compute such attributes from the value (see Enum migrations) (#555). enum(MyEnum).had(member=auto())now uses the enum's_generate_next_value_. Pass explicit values to keep the old ones (#554).- When several params read a lazy
IterableorGeneratorrequest field, each now gets all of its items, as in plain FastAPI, instead of the items that the others haven't consumed. A param that reads such a body as another type (e.g.body: dict = Body()) now finds an iterable instead of an iterator at that field, so replacenext(value)withnext(iter(value))(#633). - Type parameters without type args, such as the
Tof a barePageoritem: Tin a non-generic model, now validate and document their bounds, constraints, and defaults with each version's models and enums, so older versions reject latest-only shapes. Add request and response migrations for the outer model or the endpoint; where Cadwyn can't version such a fallback, it raisesSchemaGenerationErrorat startup, so pass explicit type args there (#584). - In older versions, subclasses of bases supplied through
__mro_entries__(e.g.class Child(Alias())) now inherit the versioned copies of their resolved bases, like explicit subclasses. Update their migrations for the older-version fields, and fix rename or deletion instructions that now fail at startup (#588). - Renaming a field now fails at startup when a base or a subclass would keep the old name next to the new one. Rename it in the declaring base and, in the same version, in the subclasses or other bases that keep it, or add the old field with
existed_as()to keep both; see inherited fields (#525, #581). .didnt_existnow fails at startup if the schema would still inherit that field from a base. Delete it from the base in the same version too (#582).- Container defaults and metadata keep their subclass types and attributes, and containers that Cadwyn can't copy safely raise
SchemaGenerationError. Use plain containers for versioned classes or callables, and break cycles through factories (see Defaults) (#564). cadwyn renderhandlesNamedTuple,defaultdict, andCounterdefaults, and raisesCadwynRenderErrorfor defaults that it can't render faithfully. Use a namedField(default_factory=...)for them; nonfinite floats and complex numbers now render as executablefloat(...)andcomplex(...)calls (#590).had(...)now rejects the current object itself even when it is unequal to itself, such as a sharedmath.nan. Remove the redundant instruction (#541).- The
InvalidGenerationInstructionErrorfor ahad(...)that sets a field attribute to its current value now saysof "Model"instead offrom "Model". Update tests that match the old wording (#541). schema(M).validator(M.check_a).didnt_existno longer removes another validator whencheck_aholds a function named like it, such ascheck_bincheck_a = field_validator("a")(check_b). It now removescheck_a, or raisesCadwynStructureErrorif the function backs several validators; then pass the attribute name, e.g.schema(M).validator("check_a").didnt_exist(#133).
Added¶
- FastAPI WebSocket routes now support
endpoint("/ws", ["WEBSOCKET"])with.existed,.didnt_exist, and.had(path=..., name=..., dependencies=...)(#67). - Pass
openapi_customizertoCadwyn()to customize each generated OpenAPI document with its selected version, orNonefor the unversioned document. The callback must be synchronous and return the edited dict or a replacement dict (#255). - Remove a validator assigned as a model attribute, such as
check_x = field_validator("x")(func), withschema(M).validator("check_x").didnt_exist(#133). - Change a model's Pydantic config in older versions with
schema(Model).had(config=ConfigDict(...)). It supports keys such asextra,frozen,title, andvalidate_by_nameon models without subclasses; see Change model configuration (#91). - Pass
run_background_tasks_of_latest_version_dependencies=TruetoCadwyn()orgenerate_versioned_routers()to run tasks added during the latest dependency solve even when the endpoint has noBackgroundTasksparam (#568). - Documented that responses are validated twice: a model object that an endpoint returns runs its validators and
model_post_initagain (#592).
Changed¶
- Type checkers now accept unions in
convert_request_to_next_version_for()andconvert_response_to_previous_version_for()(#530). had(...)instructions now accept distinct values that compare equal, such asTrueand1, instead of rejecting real changes. Unknown objects are compared by identity (see instruction comparisons) (#541).
Deprecated¶
- Dropping the background tasks that dependencies add during the latest dependency solve, when the endpoint has no
BackgroundTasksparam, now warns once per route; 10.0 will run them. Passrun_background_tasks_of_latest_version_dependencies=Truenow, and add each task only whencurrent_dependency_solver == "fastapi"to avoid duplicates; see background tasks (#568).
Fixed¶
typing.get_type_hints()no longer fails ongenerate_versioned_routers()(#614).- Generated WebSocket routes now pick the API version from the header, path, or a constant default with the same rules as HTTP requests, and reject missing or invalid versions before accepting the connection (#67).
- Background tasks can now read
UploadFileparams: Cadwyn closes uploads after the response and its background tasks, including the uploads that migrations add, replace, or remove (#561). - Client disconnects no longer leave uploaded files open on unversioned routes or when a dependency fails before a versioned endpoint runs; see upload cleanup (#594).
- Plain enums and flags with
enum(...)instructions now work in lazyIterableandGeneratorrequest fields without consuming items early, with the same values aslistfields (#591). - Unchanged members of enum copies now keep the attributes and slots set, overwritten, or deleted after construction, such as labels added after class creation or by a metaclass (#589).
- Responses whose validation aliases are restored now run model validators once, avoiding duplicated side effects in routes and
migrate_response_body()(#565). - Supported request and response bodies with versioned plain enums or flags no longer fail with a 500; omitted enum defaults work on FastAPI before 0.148 when that version has the member. See known limitations for strict responses and unsupported containers (#521).
- On FastAPI 0.153.0+, unions of form models no longer fail with a 500 for supported container fields; optional unions also receive their data on 0.161.0+ (#532).
- Models with schema instructions no longer fail to copy annotations such as
Final[int],TypeGuard,TypeIs, orClassVar[Final[...]](#576). - Versioned mixin enums now support
vars()and__dict__, and enums declaring__slots__no longer fail to copy (#555). - In supported request bodies with unchanged schemas,
Json[...]fields accepting strings or string-enum members no longer fail with a 500 (#538).
[8.2.0]¶
Possibly breaking¶
- With FastAPI 0.158.2 or newer, a form field of a dependency override that has the same name as the endpoint's form model param and accepts any value (e.g.
body: Any = Form()next tobody: Annotated[MyModel, Form()]) now gets its own value from the form instead of the whole form model, like in FastAPI itself (#496).
Added¶
- The README and the documentation now link to the author's blog and X.
- Documented how Cadwyn works inside, for contributors, on the new "Architecture" page in the "Theory" section of the documentation (#202).
- Design decisions and trade-offs now lists more known limitations, more rules for changing Cadwyn, and how to check a change (#202).
Fixed¶
- The
cadwyncommand can import modules from the current directory again, socadwyn render module data.schemas --app=main:app --version=...works when run from the folder that containsmain.pyanddata/. Before, it failed withModuleNotFoundErrorunless it was run aspython -m cadwyn. Cadwyn 1.0.2 had fixed this, but later versions stopped putting the current directory onsys.path. - The how-to examples for changing schemas are now tested, which removed their unused imports and added the missing import of the version changes in the "Narrow the type" example.
- Fixed documentation examples that failed or did the opposite of what they described: reversed field renames in the data migration and rename-a-field examples, the
migrate_response_body()call without itsversionsargument, swapped "adding" and "removing" enum member examples, aVersionChangeWithSideEffectsexample withoutinstructions_to_migrate_to_previous_version, ahidden()example that changed path params (which Cadwyn rejects), a "remove a required field" recipe that left HEAD without the default it needs, and missing or wrong imports in several examples. - The examples on the "Version changes", "Changelogs", and "Enum migrations" documentation pages are now tested. This fixed the example of migrating HTTP errors, which changed 400 to 404 instead of changing the latest 404 back to 400, the example of returning an internal representation, which unpacked an object as a dict, and missing imports in the
current_dependency_solverexample. The "Version changes" page also no longer suggests renaming an inherited field in each child schema instead of the parent, which keeps the old field next to the new one. The "Enum migrations" examples now show the enum they change (class MyEnum(str, Enum)). - The code examples on the "Schema migrations", "API version parameter", "Schema generation", "Endpoint migrations", and "Main App" pages are now tested. Examples that could not run now work as written: they no longer import from hypothetical
versionsandmy_versionsmodules or pass...toCadwyn(), and the validator examples no longer have unused imports. The "Schema migrations" page now says to rename an inherited field in the schema that declares it, because renaming it in a subclass keeps the old field next to the new one. Thecadwyn renderexamples on the "Schema generation" page now say to run them from the app's directory. - Fixed documentation claims that contradicted Cadwyn's behavior: that Cadwyn only supports date-based versions, that
api_version_parameter_namedefaults to"X-API-VERSION", that a schema can have bothdefaultanddefault_factory, that validators can reject values withTypeError, and references to thedata.vXXXX_XX_XXpackages that Cadwyn no longer generates. - With FastAPI 0.158.2 or newer, endpoints with an optional form model (e.g.
body: Annotated[Optional[MyModel], Form()] = None) no longer fail with a 500 error in every API version when the request has none of the model's form fields. Request migrations getNoneas the body, and the endpoint gets the param's default (#495). - With FastAPI 0.158.2, endpoints that take a form model no longer fail with a 500 error, and endpoints that take an optional form model now get its form data instead of
None. Cadwyn handled the way FastAPI looks up form models only from FastAPI 0.159.0, while FastAPI changed it in 0.158.2 (#495). - With FastAPI 0.158.2 or newer, a form field or an embedded body param (
Body(embed=True)) of a dependency override that has the same name as the endpoint's form model param (e.g.body: Annotated[MyModel, Form()]in the endpoint andbody: str = Form()in the override) now gets its own value from the form model's data instead of the whole form model, like in FastAPI itself. If the data has no value for it, it gets its default. Before, this failed with a 500 error, or, if the param accepted the form model's data (e.g.body: Any = Form()), gave it the whole form model. Requests in which another param of an override takes the whole body, a required param has no value in the data, or the form has a value for a param that the form model of the request's API version doesn't have a field for (e.g. a field that only newer versions of the model have, or, for a union of form models, a field that only the members that the request doesn't match have), work as before (#496). - With FastAPI 0.161.0 or newer, endpoints that take a union of form models (e.g.
body: Annotated[Union[ModelA, ModelB], Form()]) no longer fail with a 500 error in every API version, including when the models haveset,frozenset, ortuplefields. Endpoints that take an optional union of form models (e.g.body: Annotated[Optional[Union[ModelA, ModelB]], Form()] = None) now get the form data instead ofNone, and no longer fail with a 500 error when the request has none of the models' form fields. Request migrations of these endpoints get the form data of the model that the request matches as the body, orNoneif the request has no form data for the optional union. Requests whose body has a list, set, or tuple in a field that a model of the union takes a single value for (e.g. a field of typeAnythat a validator or a migration fills with a list, or a field that a model which allows extra fields doesn't have) behave as before, because FastAPI would give the field only one of the values. - On Python 3.11 and newer,
enum(...)instructions on aFlagorIntFlagenum no longer make every route and the OpenAPI return a 500 error. The enum of each version has the members of that version, combines them like a hand-written enum, and keeps the enum's boundary (#522). - Request bodies, responses, and fields typed by a native
typealias that refers to itself (Python 3.12+), directly or through other type aliases, no longer fail with a 500 error in every API version when the alias only contains builtin types, such astype JSON = dict[str, JSON] | list[JSON] | str | int | None, and other such aliases. Recursive type aliases that contain anything else, such as models, enums, other classes, forward refs, orAnnotated, still can't be versioned: instead of aRecursionError, the first request now fails with aSchemaGenerationErrorthat names the alias (#524). - With FastAPI 0.158.2 or newer, when a request has none of the fields of an optional form model param without an alias (e.g.
body: Annotated[Optional[MyModel], Form()] = None), or, with FastAPI 0.161.0 or newer, of an optional union of form models, a dict that a request migration sets as the body (e.g.request.body = {"name": "x"}) now reaches the endpoint, the dependencies that declare the same form model under the same param name, and the dependency overrides that declare the same form model. Before, they gotNone, or a 500 error for some unions. A body that the form model rejects now fails with a 500 error, as it does when the form supplies the model. Everything else behaves as before, including a dict with none of the form model's fields (e.g.{}), which gives the param its default, as FastAPI does for a form, a body that isn't a dict or that has a key named like the param (e.g.{"body": {"name": "x"}}), another form model or form field with the same name as the param, a param that gets the whole body (e.g.payload: dict = Body()in an override of a dependency that only the latest version has), a form field that isn't a form model (e.g.x: str = Form("d")in an override), a dependency that declares a form model under another param name, a key that another param reads next to a form model that allows or forbids extra fields, and, for a union, a body with values that FastAPI would change when it validates them as form data (e.g. an empty string, or a one-item list in an extra field) (#529). - Request bodies with
Json[...]fields (e.g.data: Json[dict]), including form models and nested models, no longer fail with a 500 error in the latest API version and in the older versions whose body models are the same as the latest version's. Request migrations still get the parsed values of these fields. If Cadwyn can't be sure that the latest version gets what the client has sent everywhere in the body, the request behaves as before. Known limitations lists these cases (#523).
[8.1.1]¶
Added¶
- The documentation now has a separate version for each Cadwyn release, with a version selector in the header.
latestpoints to the newest release anddevto themainbranch.
Fixed¶
- When the app has a root path (e.g.
--root-path /prefix, or a parent app with a root path that mounts the Cadwyn app), the version links on/docsand/redocno longer repeat the root path (/prefix/prefix/docs?version=...) and lead to a 404 (#501).
[8.1.0]¶
Deprecated¶
- The deprecated changelog (
/changelog,generate_changelog(), andhidden()) will be removed in 9.0. .had(alias=...)and.didnt_have("alias")now warn at startup (FutureWarning) when the field keeps thevalidation_aliasorserialization_aliasthat Pydantic copied from its old alias, and so keeps its old key. Cadwyn 9.0 will change them too (#465).
Added¶
- Documented Cadwyn's design decisions, accepted trade-offs, known limitations, and the rules for changing its behavior in Design decisions and trade-offs (#202).
Fixed¶
- With FastAPI 0.159.0 or newer, endpoints that take a form model (e.g.
body: Annotated[MyModel, Form()]) no longer fail with a 500 error in every API version.
[8.0.0]¶
This release fixes many long-standing bugs, most of them reported by users. Most apps can upgrade without changes. It is a major release because some fixes change wrong behavior that apps or their clients may rely on. Before upgrading, check the Breaking entries and the Upgrade note below. In short:
- Cadwyn now requires Pydantic 2.11.5 or newer.
- Older API versions use their own versions of the models inside generic models such as
Page[Item]. - Older API versions of endpoints with postponed annotations validate request bodies with their own models.
schema(Child).field(...)instructions for inherited fields no longer leak into parent and sibling models.Annotated[T, Depends(f)]dependencies use the versions of models and enums that the request's API version has, in the versions that change them.
Added¶
schema(Model).had(description=...)gives older versions of a model their own OpenAPI description (#168).- Documented how to serve endpoints to requests without an API version, e.g. the OAuth2 token endpoint (#230).
- Documented how to use fastapi-pagination with Cadwyn (#191).
- Documented that request and response migrations only run for the schema that the route uses directly, not for that schema nested in other schemas.
- Documented that computed fields that return versioned models keep the latest versions of these models in older API versions.
Changed¶
- Breaking: Cadwyn now requires Pydantic 2.11.5 or newer.
- Breaking: generic models such as
Page[Item]now use the versioned copies of their type args in requests, responses, and OpenAPI (#416, #420). Older versions validate and serialize these args with their own models, so older clients that relied on the latest models inside generics may need converters for the generics: converters forItemdon't run for the items ofPage[Item]. The OpenAPI names of some generics change, andmigrate_response_bodyno longer accepts instances of the latest models inside them. See Generic models for details. - Breaking:
schema(Child).field(...).had(...)and.didnt_have(...)for an inherited field now change it only inChildand its subclasses, not in its parent and siblings (#466). To keep the old behavior, give the instruction to the parent instead. If a parent renames such a field, the subclass's changes follow the new name only through single, non-generic inheritance.cadwyn rendernow renders each model's own attributes in each version. See Fields that a schema inherits for diamonds and generics. - Breaking: dependencies declared as
Annotated[T, Depends(f)],Annotated[T, Security(f)], orAnnotated[f, Depends()]now use the version's own copy offin the versions that change the models or enums its parameters validate (#467). Requests that relied on the latest dependency can now get a 422, and in these versions the dependency receives the version's copies of models and enums, so compare them by value rather than withisinstanceoris. See Versioned dependencies. - Self-referencing models that don't have, refer to, or pass on any instructions are no longer copied for every version:
generate_versioned_models(versions)[version][Category] is Category. app.dependency_overridesis now FastAPI's plain attribute. Removed the undocumentedcadwyn.applications.FakeDependencyOverridesProviderand theCadwyn.dependency_overridesproperty.- Type checkers now accept assigning an
APIRoutertoapp.router, as in FastAPI. Cadwyn still needs its own router there, so don't replace it.
Deprecated¶
- The
openapi_prefixargument ofCadwyn(). FastAPI 0.145.0 removed it, so on FastAPI 0.145.0 and newer it now raises a clearTypeError, and on older FastAPI it emits aDeprecationWarning. Configure your server's root path instead.
Fixed¶
- Upgrade note: older API versions of endpoints with postponed (
from __future__ import annotations) or quoted request body annotations used the latest models since 6.0.1. Now they use their own models, as documented, so clients that kept sending the latest shape may get a 422. - Fixed apps failing to start, or every request failing with a 500 (
RecursionError), when models refer to themselves, e.g.children: "list[Category]"(#419). Where Cadwyn can't copy such models, it now raises aSchemaGenerationErrorthat names them. See Models that refer to each other. - Fixed responses failing with a 500, and request bodies failing in non-head versions, when a required field validates a different key than it serializes to, e.g.
validation_aliasorserialization_alias(#260, #370). Bodies that worked before are unchanged. - Fixed OpenAPI documenting the API version header as optional when
api_version_default_valueisn't set (#277). - Fixed older API versions adding
"example": {}to the OpenAPI of parameters declared with defaults such as= Query()(#417). - Fixed
Cadwyn()failing on FastAPI 0.145.0 and newer (#462). - Fixed requests without a body failing with a 500 on FastAPI 0.151.0 and newer when the endpoint or its dependencies have embedded optional body params, a
Nonedefault that their type rejects, or a quoted body annotation. - Fixed apps served with
uvicorn module:appreturning a 500 for every request since 7.1.1. - Fixed
Cadwyn(strict_content_type=False)having no effect. - Fixed uploaded files declared as
bytes, in endpoints and dependencies, arriving empty in non-head versions. These versions now hold such uploads in memory twice per request. Dependencies that move an upload only whencurrent_dependency_solveris"fastapi"may now see it moved back to its start; see Dependency re-execution warning. - Fixed embedded request bodies failing in non-head versions when the endpoint has a parameter named
bodyor a body alias that matches another parameter's name. - Fixed enums without enum instructions being copied for every version, which broke strict models.
- Fixed versioned dependencies:
functools.partialdependencies lost their annotations;- dependencies described only by
__signature__lost their parameter types; - async generator dependencies didn't receive exceptions raised after
yield; Depends(scope=...)was lost;app.dependency_overrideswas ignored in older API versions for class instances, bound methods, and partials;- parameter defaults such as
= Query()were shared between versions and apps.
- Fixed startup failures for:
functools.lru_cachedependencies with postponed annotations;- dependency annotations that use names imported under
TYPE_CHECKINGon Python 3.14; - dependency return annotations that only type checkers can evaluate (Cadwyn no longer versions them, like FastAPI).
- Fixed older API versions failing on models that use:
typing.Self;- annotations that can't be rebuilt, such as a bare
CallableorUnpack[Ts]; - default factories without a signature;
- names imported under
TYPE_CHECKINGon Python 3.14; - generic fields that parametrize generics with their own type parameters, e.g.
items: list[Wrapper[T]].
- Fixed
TypeError: unhashable typein older API versions for unhashable request body or response model annotations. - Fixed
schema(...).field(...).didnt_have(...)having no effect ontitle,description,examples, anddeprecateddeclared throughAnnotated[..., Field(...)]. - Fixed
didnt_have("title"),didnt_have("min_length"), anddidnt_have(...)failing withTypeErroronAnnotatedtypes with validators,Len,Strict, orAllowInfNan. - Fixed
had(default=...)andhad(default_factory=...)failing with pydantic'sTypeErrorat startup when they leave a field with both a default and a default factory. Cadwyn now raisesInvalidGenerationInstructionError, and the instruction's value replaces the one fromAnnotated[..., Field(...)]. - Fixed the deprecated
/changelogfailing with a 500 for self-referencing models, and on every call after the first one for instructions on inherited fields. - Fixed type checking with Pydantic 2.14 and ty 0.0.86.
[7.4.0]¶
Fixed¶
- Preserve SQLAlchemy and SQLModel classes during API version generation, fixing startup failures for annotated ORM dependencies. Reject migrations targeting these classes with guidance to use separate Pydantic models, and document this restriction in the schema migrations guide (#410).
[7.3.0]¶
Added¶
- Added native View Transition API animations to documentation navigation, with reduced-motion and unsupported-browser fallbacks.
Changed¶
- Updated Starlette documentation links to the project's current official domain.
Fixed¶
- Restored compatibility with ty 0.0.78 while preserving FastAPI's coroutine detection on every supported Python version.
- Preserved the
classmethodbinding of@field_serializerdecorators during model generation. Previously, such serializers were re-registered as instance methods, shifting their arguments by one and raisingPydanticSerializationErroron every serialization.
[7.2.0]¶
Deprecated¶
- Deprecated changelog generation, including the default
GET /changelogendpoint,Cadwyn.generate_changelog(),cadwyn.hidden(), and thechangelog_urlandinclude_changelog_url_in_schemaconstructor arguments. The feature remains available for backwards compatibility.
[7.1.2]¶
Changed¶
- Simplified contributor setup and development commands (#387)
- Standardized test names around the
what,when, andexpectedconvention and documented test organization (#397) - Expanded Ruff coverage, including return annotations, preview correctness checks, and explicit tracking of reviewed rules
Fixed¶
- Restored compatibility with FastAPI 0.140.2+ after it stopped retaining flattened dependency trees
[7.1.1]¶
Changed¶
- Migrated static type checking from Pyright to ty
Fixed¶
- Return the matched API version in the response header after waterfalling, by @Sanjays2402 (#384)
[7.1.0]¶
Added¶
- Support FastAPI 0.137.1+ included-router trees, including routes added to included routers after inclusion, for Cadwyn's versioned and unversioned routing
[7.0.0]¶
- Breaking change if you relied on lifespan running multiple times: Fixed duplicated lifecycle callbacks in Cadwyn routers, see this issue for more details
- Fixed
Cadwyn.mount()routes, includingStaticFiles, returning 404 instead of being served as unversioned routes (#374)
[6.2.2]¶
[6.2.1]¶
Fixed¶
- Fixed
openapi_tagsto only include tags used by served routes (#368) - Fixed
response_modelnot being respected on routes (#365)
[6.2.0]¶
Added¶
- Added
swagger_js_url,swagger_css_url,swagger_favicon_url,redoc_js_url, andredoc_favicon_urlparameters toCadwynfor customizing docs static asset URLs (#361)
[6.1.1]¶
Fixed¶
- Fixed compatibility with Starlette 1.0.0 which removed the deprecated
TemplateResponse(name, context)calling convention
[6.1.0]¶
Added¶
- Added
formproperty toRequestInfofor reading and modifying multipart/form-encoded fields (strings and file uploads) insideconvert_request_to_next_version_forhandlers (#359)
Fixed¶
- Fixed false
RouterPathParamsModifiedErrorwhen renaming path-versioned endpoints (#357)
[6.0.4]¶
Added¶
- Python 3.14 support (#345)
Fixed¶
- Fixed missing type imports with future annotations in
Dependleading toRecursionErroringenerate_versioned_routersby @Shigerman (#329) - Resolved
'__getitem__' requires a 'typing.Union'error by @ulgens (#336) - Adopted Python 3.14 related union handling changes by @ulgens (#337)
- Adopted Python 3.14 related
http.cookieschanges by @ulgens (#338)
Removed¶
- Python 3.9 support by @ulgens (#342)
[6.0.3]¶
Fixed¶
- Tolerate FastAPI 0.128+ utils removal, restrict fastapi >= 0.128.6 by @shahar1 (#327)
[6.0.2]¶
Fixed¶
- Resolved
...has no attribute '__annotations__'error by @ulgens (#334)
[6.0.1]¶
Fixed¶
- Fixed AttributeError when using callable class dependencies with
from __future__ import annotations. Note that this introduces another problem in python 3.9 in the same case that is currently not yet solved (#321)
[6.0.0]¶
Fixed¶
- Support for FastAPI>=0.128.0+
Removed¶
- Support for FastAPI < 0.128.0 and Pydantic v1
[5.6.2]¶
Fixed¶
- Support for FastAPI 0.126.0+ where
_prepare_response_contentmay return Pydantic model instances instead of dicts, breaking response migrations (#314)
[5.6.1]¶
Fixed¶
- Support for FastAPI 0.121.0
[5.6.0]¶
Added¶
schema(...).had(json_schema_extra=...)support by @csemanish12
[5.5.0]¶
- Fix the rest of the issues from fastapi==0.119.0
[5.4.5]¶
Fixed¶
- Many issues after GenerateJsonSchema getting removed in fastapi==0.119.0
Changed¶
- A lot of documentation improvements by @Shigerman
[5.4.4]¶
Fixed¶
- Fixed KeyError when versioning Pydantic models containing ClassVar annotations
[5.4.3]¶
Fixed¶
- XSS vulnerability in
/docsand/redocendpoints where theversionparameter was not properly sanitized, allowing potential cross-site scripting attacks
[5.4.2]¶
Fixed¶
- Added support for computed fields
[5.4.1]¶
Fixed¶
- Fixed import error in python 3.9 when using typing_extensions==3.14.0
[5.4.0]¶
Added¶
typing_inspectiondependency from pydantic team for complex isinstance checks that must be the same betweentypingandtyping_extensions- Support for
pydantic>=2.12.0FieldInfo refactoring from https://github.com/pydantic/pydantic/pull/11898
[5.3.3]¶
Fixed¶
- Fixed pypi badge link in README
[5.3.2]¶
Fixed¶
- Add support for
pydantic_settings.BaseSettingsin dependencies
[5.3.1]¶
Fixed¶
- Fix invalid content-length header with custom exception handlers (#273)
[5.3.0]¶
Added¶
api_version_titleandapi_version_descriptionarguments toCadwynto allow customizing the API version parameter in the OpenAPI schema
[5.2.2]¶
Fixed¶
- Whenever a route was migrated by path, we used the path and methods of the request. So if the request wanted "/v1/webhook_settings" and we renamed them to "/v1/webhook_subscriptions" -- all migrations for "/v1/webhook_subscriptions" would not get applied to any requests that wanted "/v1/webhook_settings". This effectively means that previously route renamings were incompatible with by path converters. Now we use the head route id instead of the path and methods of the request for matching so we always know which migrations to apply.
[5.2.1]¶
Fixed¶
- #268 A bug where we received 404 for all unversioned routes when a default api version was passed to Cadwyn at initialization
[5.2.0]¶
Removed¶
issubclassdependency
[5.1.4]¶
Fixed¶
- a bug where a custom HTTP exception was not being copied correctly so its unique properties are ignored
[5.1.3]¶
Fixed¶
__doc__attribute is now copied from the original enum to the generated enum- Python 3.12 type aliases and their typing_extensions backports are now supported (including
pydantic.JsonValueand othertyping_extensions.TypeAliasTypeinstances) - The bug when solve_dependencies error on the migration of a request to the latest version responds with a non-json serializable error and cadwyn showed a failed to serialize error instead of the actual error
- Updated minimum FastAPI version to 0.112.4 because embed_body_fields was added in 0.112.4
[5.1.2]¶
Fixed¶
- Generators not being called when FastAPI validates the initial request
Added¶
cadwyn.current_dependency_solverfunction to check whether cadwyn or FastAPI is currently solving dependencies. It can be used as a dependency for versioned endpoints like so:current_dependency_solver: Annotated[Literal["fastapi", "cadwyn"], Depends(current_dependency_solver)]. If your dependency has side effects, you would likely want to only run it once per request. If you want to run it once we migrated the request to the latest version, you should only run it whencurrent_dependency_solveris"cadwyn". If you want your dependency to run at the very beginning of handling the request, you should only run it whencurrent_dependency_solveris"fastapi".
[5.1.1]¶
Fixed¶
- Support for
WithJsonSchemain schema generation
[5.1.0]¶
Added¶
- Support for python 3.9
[5.0.0]¶
Added¶
- Support for URL path version prefixes instead of version headers. You can control it with the
api_version_locationargument ofcadwyn.Cadwyn. - Support for arbitrary strings as versions. You can control the format of the version with the
api_version_formatargument ofcadwyn.Cadwyn. - Extensibility of version picking logic with a new
VersionPickingMiddlewareclass that you can pass to theversioning_middleware_classargument ofcadwyn.Cadwyn. api_version_default_valueargument tocadwyn.Cadwynto set a default version for unversioned requests. It can be a string or an async callable that returns a string.
Changed¶
cadwyn.Version,cadwyn.VersionBundle, andcadwyn.VersionBundle.api_version_varnow store versions as strings instead of dates. Date types can still be passed tocadwyn.Versionbut there is no guarantee that they will be supported in the future. However, ISO dates with a string type are guaranteed to be supported.- Cadwyn's
api_version_header_nameargument is now deprecated in favor ofapi_version_parameter_name cadwyn.Cadwyn.add_header_versioned_routersmethod is now deprecated in favor ofcadwyn.Cadwyn.generate_and_include_versioned_routers. It will be removed in version 6.0.0
Removed¶
HeaderVersioningMiddlewarein favor ofVersionPickingMiddlewarebecause we now support more than just headers
[4.6.0]¶
Added¶
- Support for more field attributes in
schema.had()andschema.didnt_have():field_title_generator,fail_fast,coerce_numbers_to_str,union_mode,allow_mutation,pattern,discriminator - Support for forwardrefs in body fields (for example, when you use
from __future__ import annotationsin the file with your routes) - Support for forwardrefs in route dependencies
[4.5.0]¶
Added¶
check_usageargument to request/response by schema converters. Cadwyn always checks whether a schema mentioned in a converter applies to one or more endpoints to guarantee that the converter will apply to at least one endpoint. Sometimes, however, you do not need this validation. For example, when you use these converters for converting webhook bodies. Settingcheck_usage=Falsemakes it possible to skip the validation
[4.4.5]¶
Fixed¶
- Fix invalid migration of pydantic v1 style root validators when pydantic erases information about their "skip_on_failure" attribute
[4.4.4]¶
Fixed¶
- Type hints for newest pydantic versions
[4.4.3]¶
Changed¶
- Bumped package versions
[4.4.2]¶
Fixed¶
- Non-function (object instances) dependencies not supporting dependency overrides in testing
[4.4.1]¶
Added¶
- Python 3.13 to CI
[4.4.0]¶
Added¶
- Support for webhooks in swagger
- Automatic generation of versioned routes and webhooks upon the first request to Cadwyn. Notice that if you were using some of cadwyn's internal interfaces, this might break your code. If it did, make an issue and let's discuss your use case
[4.3.1]¶
Fixed¶
- Removed typer from main dependencies
[4.3.0]¶
Changed¶
- Migrated from poetry to uv (Contributed by @bastienpo)
- Removed CLI and Uvicorn dependencies from Cadwyn installations by default. Added a
standardextras group to mirror FastAPI (Contributed by @bastienpo)
[4.2.4]¶
Fixed¶
- Background tasks not functioning in versioned endpoints
[4.2.3]¶
Fixed¶
- Added support for
embed_body_fieldsinsolve_dependenciesandcreate_model_fieldin FastAPI. FastAPI has made a breaking change for these interfaces which is why we had to fix it - Fixed invalid imports in quickstart docs
- Fixed default dependencies not including the CLI for FastAPI, thus causing the quickstart docs to be invalid
[4.2.2]¶
Fixed¶
- FastAPI Servers list did not include root path when mounted as a sub-app unless specified directly within the user defined server list (Contributed by @OD-tpeko)
- OpenAPI spec did not include the
summaryfield (Contributed by @OD-tpeko)
[4.2.1]¶
Fixed¶
- Previously the docs were showing wrong versioned doc paths when cadwyn was mounted as a sub-app (Contributed by @OD-tpeko)
[4.2.0]¶
Added¶
- Automatic changelog generation from version changes using
Cadwyn.generate_changelogmethod andGET /changelogendpoint. - Automatic creation of versioned_routers based on the
VersionBundlepassed toCadwynwhich means that all versions mentioned in the version bundle will already be available for routing even without the use ofgenerate_and_include_versioned_routers
Changed¶
- Renamed
Version.version_changestoVersion.changes
Removed¶
regex,include,min_items,max_items, andunique_itemsarguments were removed fromschema(...).field(...).had. Notice that it's not a breaking change for most cases because passing these arguments caused exceptions
[4.1.0]¶
Added¶
- Exposed
cadwyn.generate_versioned_modelsthat allow you to generate pydantic models and enums even without a FastAPI app
[4.0.0]¶
Versions 3.x.x are still supported in terms of bug and security fixes but all the new features will go into versions 4.x.x.
Added¶
- Runtime schema/enum generation
- Support for versions as ISO date strings instead of dates in
cadwyn.migrate_response_bodyandcadwyn.Version
Removed¶
- Pydantic 1 support
- Code generation from everywhere. It is now completely replaced by runtime generation (so schemas/enums are generated in the same manner as endpoints). This allows Cadwyn to version things outside of your project and allows you to pick any project structure unlike codegen that required a single "head" directory with all the versioned modules.
- CLI commands for codegen
cadwyn.mainbecause it is replaced bycadwyn.__init__cadwyn.structure.moduleas it was only necessary in codegencadwyn.VersionBundle.latest_schemas_packageandcadwyn.VersionBundle.head_schemas_package,cadwyn.VersionBundle.versioned_modules,cadwyn.VersionBundle.versioned_directories_with_head,cadwyn.VersionBundle.versioned_directories_without_head, because they were only necessary in code generationcadwyn.Cadwyn.add_unversioned_routersas you can now simply use FastAPI'sinclude_routercadwyn.Cadwyn.add_unversioned_routesas you can now simply use any of FastAPI's methods for adding routes directly to the appcadwyn.Cadwyn.enrich_swaggeras its functionality has been automatedcadwyn.InternalRepresentationOfas it was deprecated previously and is now replaced with HeadVersion migrations
Changed¶
VersionBundle.migrate_response_bodyis no longer a method ofVersionBundleand is now importable directly fromcadwynas a functioncadwyn.structureis no longer recommended to be used directly because everything from it is now available incadwyndirectly
[3.15.8]¶
Fixed¶
- Invalid unparseable JSON response without quotes when the response was a raw string JSONResponse
- An exception raised during codegen if a pydantic model or its parent were created within some indent such as classes defined under if statements
[3.15.7]¶
Fixed¶
- Wrong globals being used for wrapped endpoints in older versions, sometimes causing FastAPI to fail to resolve forward references on endpoint generation (see #192 for more details)
- dependency_overrides not working for old versions of the endpoints because they were wrapped and wraps did not have the same
__hash__and__eq__as the original dependencies
[3.15.6]¶
Added¶
HeadVersionandVersionintocadwyn.__init__so now they are directly importable fromcadwyn
Fixed¶
- Fix dependencies from other libraries not resolving if they use fastapi.Request or fastapi.Response (added svcs-specific test)
- Now a proper exception is used when no dated version was passed into
VersionBundle
[3.15.5]¶
Fixed¶
- Fix dependency overrides not working for versioned routes
[3.15.4]¶
Changed¶
Cadwyn.enrich_swaggeris now completely unnecessary: OpenAPI is now generated at runtime. It also now does not do anything, is deprecated, and will be removed in a future version
Fixed¶
- fastapi-pagination now does not require an explicit call to
Cadwyn.enrich_swagger
[3.15.3]¶
Changed¶
Cadwyn.router.routesnow includes all existing routers within the application instead of just unversioned routes
Fixed¶
- Compatibility with fastapi-pagination
- High cardinality of metrics for routers with path variables in starlette-exporter
[3.15.2]¶
Fixed¶
- OpenAPI not being generated when lifespan was used
[3.15.1]¶
Fixed¶
- Badge links in the readme
[3.15.0]¶
Changed¶
- Optimized the calls to enrich_swagger which now happen on the startup event, once for the whole application
Fixed¶
- Oauth2 authentication parameters did not get passed to swagger
[3.14.0]¶
Added¶
- Current API version to per-version openapi.json
[3.13.0]¶
Added¶
- Validation for path converters to make sure that impossible HTTP methods cannot be used
- Validation for both path and schema converters to make sure that they are used at some point. Otherwise, router generation will raise an error
[3.12.1]¶
Fixed¶
fastapi.Responsesubclasses with non-null bodies and 500 response causing the response to not get returnedfastapi.Responsesubclasses had invalid content length if migration affected it
[3.12.0]¶
Changed¶
- Rewritten header routing logic and structure to support the full feature set of FastAPI
[3.11.1]¶
Fixed¶
- Modules and enums from head versions not being detected and thus causing errors
[3.11.0]¶
Changed¶
- Header router is no longer reliant on the API version header -- now it simply takes the API version from the
VersionBundle.api_version_var, thus making it easy for someone to extend header routing and set their own rules for how the default version is chosen
[3.10.1]¶
Fixed¶
- Previous version introduced a minor breaking change: if any old users depended on the pure
generate_versioned_routersinterface, their work would receive a minor yet simple breaking change.
[3.10.0]¶
Yanked due to a minor breaking change that we fixed in 3.10.1.
Added¶
- The new approach to internal schemas: instead of having them duplicate certain fields from
latest, we introduced a newHEADversion -- the only one the user maintains by hand. All requests get migrated toHEADand latest schemas are generated fromHEAD.cadwyn.structure.HeadVersionwas added to give us the ability to have migrations betweenHEADand latest, thus eliminating the need forInternalRepresentationOfbecause all the used schemas are now the internal representations
Changed¶
latestis now namedheadbecause it no longer represents the newest version. Instead, it is theinternally usedversion and the version that is used for generating all other versions.- the newest version is not aliased from
latestanymore. Instead, it is generated like all the rest - deprecated
InternalRepresentationOfand the concept ofinternal schemasin favor ofHeadVersionmigrations
[3.9.1]¶
Fixed¶
- A broken link to docs in README.md
[3.9.0]¶
Added¶
- Support for getting openapi.json routes using API version headers instead of path query params
[3.8.0]¶
Added¶
- Discord status badge in README
- Logos to existing status badges in README
- An ability to specify multiple schemas when using
convert_request_to_next_version_forandconvert_response_to_next_version_forto be able to migrate multiple types of schemas using the same converter - Redoc support
Removed¶
- Dependency from verselect. Now it is included as a part of Cadwyn
Fixed¶
h11._util.LocalProtocolErrorwhen raisingHTTPException(status_code=500)
[3.7.1]¶
Fixed¶
- Error message for changing path params of an endpoint in an incompatible manner which listed methods instead of path params
Changed¶
- Deprecated
cadwyn generate-code-for-versioned-packagesand addedcadwyn codegeninstead. It doesn't requiretemplate_packageargument anymore and does not have theignore_coverage_for_latest_aliasesargument as we plan to remove this feature in the future. So it only requiresversion_bundle.
[3.7.0]¶
Changed¶
- Deprecated
cadwyn generate-code-for-versioned-packagesand addedcadwyn codegeninstead. It doesn't requiretemplate_packageargument anymore and does not have theignore_coverage_for_latest_aliasesargument as we plan to remove this feature in the future. So it only requiresversion_bundle.
[3.6.6]¶
Fixed¶
- When a class-based dependency from fastapi was used (anything security related), FastAPI had hardcoded
isinstancechecks for it which it used to enrich swagger with functionality. But when the dependencies were wrapped into our function wrappers, these checks stopped passing, thus breaking this functionality in swagger. Now we ignore all dependencies that FastAPI creates. This also introduces a hard-to-solve bug: if FastAPI's class-based security dependency was subclassed and then__call__was overridden with new dependencies that are versioned -- we will not migrate them from version to version. I hope this is an extremely rare use case though. In fact, such use case breaks Liskov Substitution Principle and doesn't make much sense because security classes already includerequestparameter which means that no extra dependencies or parameters are necessary.
[3.6.5]¶
Fixed¶
- When a class-based dependency was used, its dependant was incorrectly generated, causing all affected endpoints to completely stop functioning
[3.6.4] ¶
[3.6.3]¶
Fixed¶
- A rare pydantic 2 bug that caused
BaseModelannotations to be corrupted when new fields were added to the schema
[3.6.2]¶
Fixed¶
- Removed exception when creating
cadwyn.Cadwynwithoutlatest_schemas_packageas it was a minor breaking change
[3.6.0]¶
Added¶
- Add
cadwyn.VersionBundle.migrate_response_bodythat allows us to migrate response bodies outside of routing and FastAPI latest_schemas_packageargument tocadwyn.VersionBundleto support the migration above
Removed¶
Changed¶
- We now raise a 5xx error (
cadwyn.exceptions.CadwynLatestRequestValidationError) whenever a request migration caused our payload to be incompatible with latest request schemas - Deprecated
cadwyn.mainand usecadwyn.applicationsinstead - Deprecated
latest_schemas_packageargument incadwyn.Cadwyn
[3.5.0]¶
Fixed¶
- Previously, Cadwyn did not set the default status code for ResponseInfo
Added¶
- HTTP status error handling in response converters using
convert_response_to_previous_version_for(..., migrate_http_errors=True)
[3.4.4]¶
Fixed¶
- Request and response converters were not applied when path params were present
[3.4.3]¶
Added¶
RouterPathParamsModifiedErroris now raised ifendpoint(...).had(path=...)has different path params than the original route
[3.4.2]¶
Fixed¶
- Fix import aliases in nested
__init__.pyfiles generating incorrectly for latest version
[3.4.1]¶
Fixed¶
- If the endpoint specified a single non-pydantic (list/dict) body parameter, Cadwyn failed to serialize the body
[3.4.0]¶
Added¶
schema(...).validator(...).existedandschema(...).validator(...).didnt_existinstructions for simplistic manipulation of validators- Automatic deletion of validators when the fields they validate get deleted
schema(...).field(...).didnt_havefor unsetting field attributes- Improved support for
typing.Annotatedin schemas - Full preservation of original abstract syntax trees for all field values and annotations
Fixed¶
- If the user wrote a wrong signature in a transformer decorated by
convert_request_to_next_version_fororconvert_response_to_previous_version_for, the text of the error suggested the wrong argument count and names
[3.3.4]¶
Fixed¶
- Added backwards compatibility for FastAPI < 0.106.0
[3.3.3]¶
Fixed¶
- Guaranteed that it is impossible to release cadwyn with the wrong pydantic dependency
[3.3.2]¶
Fixed¶
- Downgrade required version of verselect for backwards compatibility
[3.3.1]¶
Fixed¶
- Removed lazy migrations as they were producing incorrect results when there were no migrations but when there were schema changes
- Added compatibility with fastapi>=0.109.0
[3.3.0]¶
Fixed¶
- If a user used a FastAPI/Starlette
StreamingResponseorFileResponse, we still tried to access itsbodyattribute which caused anAttributeError
[3.2.0]¶
Added¶
- Sponsors section to README and docs, along with Monite as our main and only current sponsor ✨
[3.1.3]¶
Fixed¶
- Switched to
better-ast-commentsbecauseast-commentshad no license listed on pypi (even though its actual license was MIT) which caused some dependency checking tools to report it as unlicensed
[3.1.2]¶
Changed¶
- Migrate from black to ruff-format
Fixed¶
- A rare Pydantic 2 bug in internal body schema handling when it was applied too early, causing partially incomplete data to arrive to the handler
[3.1.1]¶
Fixed¶
- Previously we did not pass
dependency_overrides_provider,response_model_exclude_unsetresponse_model_exclude_defaults, andresponse_model_exclude_nonetofastapiwhich could cause erroneous behaviour during serialization in rare cases.
[3.1.0]¶
Added¶
module(...).had(import_=...)construct for adding imports in older versions- Codegen plugin system that allows easily customizing code generation for any purpose. It also significantly simplifies the core code of code generation
[3.0.2]¶
Fixed¶
- If a user returned a FastAPI/Starlette
Responsewith an empty body, we still tried to serialize it which caused an invalid response body
[Unreleased]¶
[8.1.0]¶
[3.0.0]¶
Added¶
- Pydantic 2 support
- Expanded reference section to docs
- Contributor docs
- Expanded makefile commands
Changed¶
- internal request representation is now done using an annotation
latest_schemas_modulewas renamed tolatest_schemas_packageeverywhereapi_version_varinVersionBundleis now an optional argument instead of a required one
Removed¶
cadwyn.internal_body_representation_ofbecause it is now done using an annotation
[2.3.4]¶
Fixed¶
schema(...).field(...).had(ge=...)for union fields previously raised anAttributeErroron code generation
[2.3.3]¶
Fixed¶
- Field ASTs not preserving the original structure when constrained fields were changed
Added¶
- Support for synchronous endpoints
[2.3.2]¶
Fixed¶
- The bug where fields from parent schemas also appeared in child schemas
[2.3.1]¶
Changed¶
- Migrate from external verselect to stable verselect
[2.3.0]¶
Fixed¶
- Previously whenever we generated routes, we wrapped all endpoints and callbacks in decorators for every version which caused stacktraces to be unnecessarily huge. Now there is only one wrapper for all versions
Added¶
cadwyn.Cadwynclass similar tofastapi.FastAPIthat provides header routing and encapsulates all information about versioned routes- Migrated from
fastapi-header-routingtoverselect cadwyn.routing.VERSION_HEADER_FORMATfromverselect.routing
Changed¶
*versionsargument incadwyn.VersionBundleis now split into a required positional-onlylatest_versionand*other_versionsto make it possible to see an invalid versionless definition statically. Note that it is not a breaking change because the presence of at least one version was also implicitly required before and would produce a failure at runtime
Removed¶
cadwyn.get_cadwyn_dependencyandcadwyn.headerbecause it is fully replaced withverselect
[2.2.0]¶
Added¶
- Validation for the spelling of HTTP methods in
cadwyn.structure.endpoint.
[2.1.0]¶
Added¶
- A prototype of AST-based code generation where we try to keep as much of the old field/annotation structure as possible
[2.0.5]¶
Fixed¶
UploadFileand forms have previously caused exceptions on request migration
[2.0.4]¶
Fixed¶
ContextVar[datetime.date]being incompatible withVersionBundle
[2.0.3]¶
Added¶
- A note into reference docs about the paths specification in CLI
Fixed¶
- Custom body fields created by FastAPI caused an exception. Now they are ignored
[2.0.2]¶
Added¶
- A link to OpenAPI discussion on enum expansion into docs/recipes
- A link to intercom's API versioning article into docs/theory
[2.0.1]¶
Fixed¶
generate_versioned_routersdid not alterAPIRoute.dependant.call,APIRoute.response_field, andAPIRoute.secure_cloned_response_fieldbefore which caused these fields to represent latest version on all generated versions. However, this was only a bug if the routes were later added into the app/router by hand instead of usinginherit_routesoradd_api_route.
[2.0.0]¶
Changed¶
generate_versioned_routersnow accepts only one router instead of a sequence of routers to give us the ability to guarantee that the type of generated routers is the same as the type of the passed router.
[1.4.0]¶
Added¶
- Theory section to docs
[1.3.0]¶
Added¶
- Recipes documentation section
schema(...).field(...).had(name=...)functionality to rename fields
Changed¶
- Tutorial example structure in tests
[1.2.0] - 2023-10-16¶
Added¶
cadwyn.main._Cadwynexperimental private class for automatically adding the header dependency and managing all objects related to versioning
Removed¶
cadwyn.header_routingwhich only had experimental private functions
Fixed¶
- Route callbacks didn't get migrated to versions with their parent routes
[1.1.0] - 2023-10-13¶
Added¶
ignore_coverage_for_latest_aliasesargument togenerate_code_for_versioned_packageswhich controls whether we add "a pragma: no cover" comment to the star imports in the generated version of the latest module. It is True by default.
[1.0.3] - 2023-10-10¶
Fixed¶
- Add back the approach where the first version being an alias to latest in codegen
[1.0.2] - 2023-10-09¶
Fixed¶
- Add current working dir to
sys.pathwhen running code generation through CLI - Use
exclude_unsetwhen migrating the body of a request to make sure that users'exclude_unsetlogic gets preserved
[1.0.1] - 2023-10-09¶
Fixed¶
- Pass first argument in
typer.Argumentto prevent errors on older typer versions
[1.0.0] - 2023-10-09¶
Added¶
- Command-line interface capable of running code-generation and outputting version info
- Internal request schema which gives us all the functionality we could ever need to migrate request bodies forward without any complexity of the prior solution
_get_versioned_routerand experimental header routing with it (by @tikon93). Note that the interface for this feature will change in the future
Changed¶
- Renamed
cadwyn.regenerate_dir_to_all_versionstocadwyn.generate_code_for_versioned_packages - Renamed
cadwyn.generate_all_router_versionstocadwyn.generate_versioned_routers
Removed¶
unionsdirectory and all logic around it (replaced by internal request schema)FillablePrivateAttrand all logic around it (replaced by internal request schema)schema(...).propertyconstructor and all logic around it (replaced by internal request schema)- Special-casing for code generation of package with latest version using star imports from latest (replaced by internal request schema)