cadwyn 5.4.4__tar.gz → 5.5.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.

Potentially problematic release.


This version of cadwyn might be problematic. Click here for more details.

Files changed (163) hide show
  1. {cadwyn-5.4.4 → cadwyn-5.5.0}/CHANGELOG.md +24 -11
  2. {cadwyn-5.4.4 → cadwyn-5.5.0}/PKG-INFO +3 -26
  3. {cadwyn-5.4.4 → cadwyn-5.5.0}/README.md +0 -23
  4. {cadwyn-5.4.4 → cadwyn-5.5.0}/cadwyn/changelogs.py +16 -10
  5. {cadwyn-5.4.4 → cadwyn-5.5.0}/cadwyn/schema_generation.py +1 -1
  6. {cadwyn-5.4.4 → cadwyn-5.5.0}/cadwyn/structure/endpoints.py +1 -1
  7. {cadwyn-5.4.4 → cadwyn-5.5.0}/cadwyn/structure/versions.py +1 -1
  8. {cadwyn-5.4.4 → cadwyn-5.5.0}/docs/concepts/api_version_parameter.md +6 -6
  9. cadwyn-5.5.0/docs/concepts/beware_of_data_versioning.md +9 -0
  10. {cadwyn-5.4.4 → cadwyn-5.5.0}/docs/concepts/changelogs.md +3 -3
  11. {cadwyn-5.4.4 → cadwyn-5.5.0}/docs/concepts/cli.md +2 -2
  12. {cadwyn-5.4.4 → cadwyn-5.5.0}/docs/concepts/endpoint_migrations.md +9 -9
  13. {cadwyn-5.4.4 → cadwyn-5.5.0}/docs/concepts/enum_migrations.md +2 -2
  14. {cadwyn-5.4.4 → cadwyn-5.5.0}/docs/concepts/index.md +2 -2
  15. {cadwyn-5.4.4 → cadwyn-5.5.0}/docs/concepts/main_app.md +4 -4
  16. {cadwyn-5.4.4 → cadwyn-5.5.0}/docs/concepts/methodology.md +2 -2
  17. {cadwyn-5.4.4 → cadwyn-5.5.0}/docs/concepts/schema_generation.md +5 -4
  18. {cadwyn-5.4.4 → cadwyn-5.5.0}/docs/concepts/schema_migrations.md +12 -13
  19. cadwyn-5.5.0/docs/concepts/testing.md +35 -0
  20. {cadwyn-5.4.4 → cadwyn-5.5.0}/docs/concepts/version_changes.md +79 -73
  21. {cadwyn-5.4.4 → cadwyn-5.5.0}/docs/home/CONTRIBUTING.md +0 -1
  22. {cadwyn-5.4.4 → cadwyn-5.5.0}/docs/how_to/change_openapi_schemas/add_field.md +1 -1
  23. {cadwyn-5.4.4 → cadwyn-5.5.0}/docs/how_to/change_openapi_schemas/change_schema_without_endpoint.md +1 -1
  24. {cadwyn-5.4.4 → cadwyn-5.5.0}/docs/how_to/change_openapi_schemas/changing_constraints.md +1 -1
  25. {cadwyn-5.4.4 → cadwyn-5.5.0}/docs/how_to/change_openapi_schemas/remove_field.md +1 -1
  26. {cadwyn-5.4.4 → cadwyn-5.5.0}/docs/quickstart/tutorial.md +5 -5
  27. {cadwyn-5.4.4 → cadwyn-5.5.0}/docs/theory/how_to_build_versioning_framework.md +1 -1
  28. {cadwyn-5.4.4 → cadwyn-5.5.0}/pyproject.toml +3 -3
  29. {cadwyn-5.4.4 → cadwyn-5.5.0}/tests/test_render.py +0 -2
  30. {cadwyn-5.4.4 → cadwyn-5.5.0}/tests/test_router_generation.py +3 -3
  31. {cadwyn-5.4.4 → cadwyn-5.5.0}/tests/test_schema_generation/test_schema_field.py +11 -10
  32. cadwyn-5.5.0/uv.lock +2151 -0
  33. cadwyn-5.4.4/.all-contributorsrc +0 -4
  34. cadwyn-5.4.4/docs/concepts/beware_of_data_versioning.md +0 -9
  35. cadwyn-5.4.4/docs/concepts/testing.md +0 -35
  36. cadwyn-5.4.4/uv.lock +0 -1792
  37. {cadwyn-5.4.4 → cadwyn-5.5.0}/.github/CODE_OF_CONDUCT.md +0 -0
  38. {cadwyn-5.4.4 → cadwyn-5.5.0}/.github/ISSUE_TEMPLATE/bug_report.md +0 -0
  39. {cadwyn-5.4.4 → cadwyn-5.5.0}/.github/ISSUE_TEMPLATE/feature_request.md +0 -0
  40. {cadwyn-5.4.4 → cadwyn-5.5.0}/.github/actions/setup-python-uv/action.yaml +0 -0
  41. {cadwyn-5.4.4 → cadwyn-5.5.0}/.github/workflows/ci.yaml +0 -0
  42. {cadwyn-5.4.4 → cadwyn-5.5.0}/.github/workflows/daily_tests.yaml +0 -0
  43. {cadwyn-5.4.4 → cadwyn-5.5.0}/.github/workflows/publish_docs.yaml +0 -0
  44. {cadwyn-5.4.4 → cadwyn-5.5.0}/.github/workflows/release.yaml +0 -0
  45. {cadwyn-5.4.4 → cadwyn-5.5.0}/.gitignore +0 -0
  46. {cadwyn-5.4.4 → cadwyn-5.5.0}/.pre-commit-config.yaml +0 -0
  47. {cadwyn-5.4.4 → cadwyn-5.5.0}/LICENSE +0 -0
  48. {cadwyn-5.4.4 → cadwyn-5.5.0}/Makefile +0 -0
  49. {cadwyn-5.4.4 → cadwyn-5.5.0}/cadwyn/__init__.py +0 -0
  50. {cadwyn-5.4.4 → cadwyn-5.5.0}/cadwyn/__main__.py +0 -0
  51. {cadwyn-5.4.4 → cadwyn-5.5.0}/cadwyn/_asts.py +0 -0
  52. {cadwyn-5.4.4 → cadwyn-5.5.0}/cadwyn/_importer.py +0 -0
  53. {cadwyn-5.4.4 → cadwyn-5.5.0}/cadwyn/_internal/__init__.py +0 -0
  54. {cadwyn-5.4.4 → cadwyn-5.5.0}/cadwyn/_internal/context_vars.py +0 -0
  55. {cadwyn-5.4.4 → cadwyn-5.5.0}/cadwyn/_render.py +0 -0
  56. {cadwyn-5.4.4 → cadwyn-5.5.0}/cadwyn/_utils.py +0 -0
  57. {cadwyn-5.4.4 → cadwyn-5.5.0}/cadwyn/applications.py +0 -0
  58. {cadwyn-5.4.4 → cadwyn-5.5.0}/cadwyn/dependencies.py +0 -0
  59. {cadwyn-5.4.4 → cadwyn-5.5.0}/cadwyn/exceptions.py +0 -0
  60. {cadwyn-5.4.4 → cadwyn-5.5.0}/cadwyn/middleware.py +0 -0
  61. {cadwyn-5.4.4 → cadwyn-5.5.0}/cadwyn/py.typed +0 -0
  62. {cadwyn-5.4.4 → cadwyn-5.5.0}/cadwyn/route_generation.py +0 -0
  63. {cadwyn-5.4.4 → cadwyn-5.5.0}/cadwyn/routing.py +0 -0
  64. {cadwyn-5.4.4 → cadwyn-5.5.0}/cadwyn/static/__init__.py +0 -0
  65. {cadwyn-5.4.4 → cadwyn-5.5.0}/cadwyn/static/docs.html +0 -0
  66. {cadwyn-5.4.4 → cadwyn-5.5.0}/cadwyn/structure/__init__.py +0 -0
  67. {cadwyn-5.4.4 → cadwyn-5.5.0}/cadwyn/structure/common.py +0 -0
  68. {cadwyn-5.4.4 → cadwyn-5.5.0}/cadwyn/structure/data.py +0 -0
  69. {cadwyn-5.4.4 → cadwyn-5.5.0}/cadwyn/structure/enums.py +0 -0
  70. {cadwyn-5.4.4 → cadwyn-5.5.0}/cadwyn/structure/schemas.py +0 -0
  71. {cadwyn-5.4.4 → cadwyn-5.5.0}/docs/CNAME +0 -0
  72. {cadwyn-5.4.4 → cadwyn-5.5.0}/docs/__init__.py +0 -0
  73. {cadwyn-5.4.4 → cadwyn-5.5.0}/docs/how_to/change_business_logic/index.md +0 -0
  74. {cadwyn-5.4.4 → cadwyn-5.5.0}/docs/how_to/change_endpoints/index.md +0 -0
  75. {cadwyn-5.4.4 → cadwyn-5.5.0}/docs/how_to/change_openapi_schemas/change_field_type.md +0 -0
  76. {cadwyn-5.4.4 → cadwyn-5.5.0}/docs/how_to/change_openapi_schemas/rename_a_field_in_schema.md +0 -0
  77. {cadwyn-5.4.4 → cadwyn-5.5.0}/docs/how_to/index.md +0 -0
  78. {cadwyn-5.4.4 → cadwyn-5.5.0}/docs/how_to/version_with_paths_and_numbers_instead_of_headers_and_dates.md +0 -0
  79. {cadwyn-5.4.4 → cadwyn-5.5.0}/docs/img/dashboard_with_one_version.png +0 -0
  80. {cadwyn-5.4.4 → cadwyn-5.5.0}/docs/img/dashboard_with_two_versions.png +0 -0
  81. {cadwyn-5.4.4 → cadwyn-5.5.0}/docs/img/get_users_endpoint_from_prior_version.png +0 -0
  82. {cadwyn-5.4.4 → cadwyn-5.5.0}/docs/img/logos/cadwyn_icon_transparent.svg +0 -0
  83. {cadwyn-5.4.4 → cadwyn-5.5.0}/docs/img/logos/cadwyn_transparent.svg +0 -0
  84. {cadwyn-5.4.4 → cadwyn-5.5.0}/docs/img/logos/cadwyn_with_background.svg +0 -0
  85. {cadwyn-5.4.4 → cadwyn-5.5.0}/docs/img/simplified_migration_model.png +0 -0
  86. {cadwyn-5.4.4 → cadwyn-5.5.0}/docs/img/unversioned_dashboard.png +0 -0
  87. {cadwyn-5.4.4 → cadwyn-5.5.0}/docs/index.md +0 -0
  88. {cadwyn-5.4.4 → cadwyn-5.5.0}/docs/plugin.py +0 -0
  89. {cadwyn-5.4.4 → cadwyn-5.5.0}/docs/quickstart/setup.md +0 -0
  90. {cadwyn-5.4.4 → cadwyn-5.5.0}/docs/stylesheets/extra.css +0 -0
  91. {cadwyn-5.4.4 → cadwyn-5.5.0}/docs/theory/how_we_got_here.md +0 -0
  92. {cadwyn-5.4.4 → cadwyn-5.5.0}/docs/theory/literature.md +0 -0
  93. {cadwyn-5.4.4 → cadwyn-5.5.0}/docs_src/__init__.py +0 -0
  94. {cadwyn-5.4.4 → cadwyn-5.5.0}/docs_src/how_to/__init__.py +0 -0
  95. {cadwyn-5.4.4 → cadwyn-5.5.0}/docs_src/how_to/change_openapi_schemas/__init__.py +0 -0
  96. {cadwyn-5.4.4 → cadwyn-5.5.0}/docs_src/how_to/change_openapi_schemas/change_schema_without_endpoint/__init__.py +0 -0
  97. {cadwyn-5.4.4 → cadwyn-5.5.0}/docs_src/how_to/change_openapi_schemas/change_schema_without_endpoint/block001.py +0 -0
  98. {cadwyn-5.4.4 → cadwyn-5.5.0}/docs_src/how_to/change_openapi_schemas/change_schema_without_endpoint/block002.py +0 -0
  99. {cadwyn-5.4.4 → cadwyn-5.5.0}/docs_src/how_to/change_openapi_schemas/change_schema_without_endpoint/tests/__init__.py +0 -0
  100. {cadwyn-5.4.4 → cadwyn-5.5.0}/docs_src/how_to/change_openapi_schemas/change_schema_without_endpoint/tests/test_block001.py +0 -0
  101. {cadwyn-5.4.4 → cadwyn-5.5.0}/docs_src/how_to/change_openapi_schemas/change_schema_without_endpoint/tests/test_block002.py +0 -0
  102. {cadwyn-5.4.4 → cadwyn-5.5.0}/docs_src/how_to/version_with_path_and_numbers_instead_of_headers_and_dates/__init__.py +0 -0
  103. {cadwyn-5.4.4 → cadwyn-5.5.0}/docs_src/how_to/version_with_path_and_numbers_instead_of_headers_and_dates/block001.py +0 -0
  104. {cadwyn-5.4.4 → cadwyn-5.5.0}/docs_src/how_to/version_with_path_and_numbers_instead_of_headers_and_dates/tests/__init__.py +0 -0
  105. {cadwyn-5.4.4 → cadwyn-5.5.0}/docs_src/how_to/version_with_path_and_numbers_instead_of_headers_and_dates/tests/test_block_001.py +0 -0
  106. {cadwyn-5.4.4 → cadwyn-5.5.0}/docs_src/quickstart/__init__.py +0 -0
  107. {cadwyn-5.4.4 → cadwyn-5.5.0}/docs_src/quickstart/setup/__init__.py +0 -0
  108. {cadwyn-5.4.4 → cadwyn-5.5.0}/docs_src/quickstart/setup/block001.sh +0 -0
  109. {cadwyn-5.4.4 → cadwyn-5.5.0}/docs_src/quickstart/setup/block002.py +0 -0
  110. {cadwyn-5.4.4 → cadwyn-5.5.0}/docs_src/quickstart/setup/tests/__init__.py +0 -0
  111. {cadwyn-5.4.4 → cadwyn-5.5.0}/docs_src/quickstart/setup/tests/test_block002.py +0 -0
  112. {cadwyn-5.4.4 → cadwyn-5.5.0}/docs_src/quickstart/tutorial/__init__.py +0 -0
  113. {cadwyn-5.4.4 → cadwyn-5.5.0}/docs_src/quickstart/tutorial/block001.py +0 -0
  114. {cadwyn-5.4.4 → cadwyn-5.5.0}/docs_src/quickstart/tutorial/block002.py +0 -0
  115. {cadwyn-5.4.4 → cadwyn-5.5.0}/docs_src/quickstart/tutorial/block003.py +0 -0
  116. {cadwyn-5.4.4 → cadwyn-5.5.0}/docs_src/quickstart/tutorial/tests/__init__.py +0 -0
  117. {cadwyn-5.4.4 → cadwyn-5.5.0}/docs_src/quickstart/tutorial/tests/test_block001.py +0 -0
  118. {cadwyn-5.4.4 → cadwyn-5.5.0}/docs_src/quickstart/tutorial/tests/test_block002.py +0 -0
  119. {cadwyn-5.4.4 → cadwyn-5.5.0}/docs_src/quickstart/tutorial/tests/test_block003.py +0 -0
  120. {cadwyn-5.4.4 → cadwyn-5.5.0}/docs_src/ruff.toml +0 -0
  121. {cadwyn-5.4.4 → cadwyn-5.5.0}/mkdocs.yml +0 -0
  122. {cadwyn-5.4.4 → cadwyn-5.5.0}/ruff.toml +0 -0
  123. {cadwyn-5.4.4 → cadwyn-5.5.0}/scripts/fix_links.py +0 -0
  124. {cadwyn-5.4.4 → cadwyn-5.5.0}/scripts/split_md.py +0 -0
  125. {cadwyn-5.4.4 → cadwyn-5.5.0}/tests/__init__.py +0 -0
  126. {cadwyn-5.4.4 → cadwyn-5.5.0}/tests/_data/__init__.py +0 -0
  127. {cadwyn-5.4.4 → cadwyn-5.5.0}/tests/_data/unversioned_schema_dir/__init__.py +0 -0
  128. {cadwyn-5.4.4 → cadwyn-5.5.0}/tests/_data/unversioned_schema_dir/unversioned_schemas.py +0 -0
  129. {cadwyn-5.4.4 → cadwyn-5.5.0}/tests/_data/unversioned_schemas.py +0 -0
  130. {cadwyn-5.4.4 → cadwyn-5.5.0}/tests/_resources/__init__.py +0 -0
  131. {cadwyn-5.4.4 → cadwyn-5.5.0}/tests/_resources/app_for_testing_routing.py +0 -0
  132. {cadwyn-5.4.4 → cadwyn-5.5.0}/tests/_resources/render/__init__.py +0 -0
  133. {cadwyn-5.4.4 → cadwyn-5.5.0}/tests/_resources/render/classes.py +0 -0
  134. {cadwyn-5.4.4 → cadwyn-5.5.0}/tests/_resources/render/complex/__init__.py +0 -0
  135. {cadwyn-5.4.4 → cadwyn-5.5.0}/tests/_resources/render/complex/classes.py +0 -0
  136. {cadwyn-5.4.4 → cadwyn-5.5.0}/tests/_resources/render/complex/versions.py +0 -0
  137. {cadwyn-5.4.4 → cadwyn-5.5.0}/tests/_resources/render/versions.py +0 -0
  138. {cadwyn-5.4.4 → cadwyn-5.5.0}/tests/_resources/utils.py +0 -0
  139. {cadwyn-5.4.4 → cadwyn-5.5.0}/tests/_resources/versioned_app/__init__.py +0 -0
  140. {cadwyn-5.4.4 → cadwyn-5.5.0}/tests/_resources/versioned_app/app.py +0 -0
  141. {cadwyn-5.4.4 → cadwyn-5.5.0}/tests/_resources/versioned_app/v2021_01_01.py +0 -0
  142. {cadwyn-5.4.4 → cadwyn-5.5.0}/tests/_resources/versioned_app/v2022_01_02.py +0 -0
  143. {cadwyn-5.4.4 → cadwyn-5.5.0}/tests/_resources/versioned_app/webhooks.py +0 -0
  144. {cadwyn-5.4.4 → cadwyn-5.5.0}/tests/conftest.py +0 -0
  145. {cadwyn-5.4.4 → cadwyn-5.5.0}/tests/test_applications.py +0 -0
  146. {cadwyn-5.4.4 → cadwyn-5.5.0}/tests/test_auth_dependencies.py +0 -0
  147. {cadwyn-5.4.4 → cadwyn-5.5.0}/tests/test_changelog.py +0 -0
  148. {cadwyn-5.4.4 → cadwyn-5.5.0}/tests/test_cli.py +0 -0
  149. {cadwyn-5.4.4 → cadwyn-5.5.0}/tests/test_data_migrations.py +0 -0
  150. {cadwyn-5.4.4 → cadwyn-5.5.0}/tests/test_router_generation_with_from_future_annotations.py +0 -0
  151. {cadwyn-5.4.4 → cadwyn-5.5.0}/tests/test_routing.py +0 -0
  152. {cadwyn-5.4.4 → cadwyn-5.5.0}/tests/test_schema_generation/__init__.py +0 -0
  153. {cadwyn-5.4.4 → cadwyn-5.5.0}/tests/test_schema_generation/test_enum.py +0 -0
  154. {cadwyn-5.4.4 → cadwyn-5.5.0}/tests/test_schema_generation/test_schema.py +0 -0
  155. {cadwyn-5.4.4 → cadwyn-5.5.0}/tests/test_schema_generation/test_schema_validator.py +0 -0
  156. {cadwyn-5.4.4 → cadwyn-5.5.0}/tests/test_schema_generation/test_schema_with_future_annotations.py +0 -0
  157. {cadwyn-5.4.4 → cadwyn-5.5.0}/tests/test_structure.py +0 -0
  158. {cadwyn-5.4.4 → cadwyn-5.5.0}/tests/tutorial/__init__.py +0 -0
  159. {cadwyn-5.4.4 → cadwyn-5.5.0}/tests/tutorial/main.py +0 -0
  160. {cadwyn-5.4.4 → cadwyn-5.5.0}/tests/tutorial/test_example.py +0 -0
  161. {cadwyn-5.4.4 → cadwyn-5.5.0}/tests/versioning_styles/__init__.py +0 -0
  162. {cadwyn-5.4.4 → cadwyn-5.5.0}/tests/versioning_styles/test_versioning_formats.py +0 -0
  163. {cadwyn-5.4.4 → cadwyn-5.5.0}/tox.ini +0 -0
@@ -5,6 +5,20 @@ Please follow [the Keep a Changelog standard](https://keepachangelog.com/en/1.0.
5
5
 
6
6
  ## [Unreleased]
7
7
 
8
+ ## [5.5.0]
9
+
10
+ * Fix the rest of the issues from fastapi==0.119.0
11
+
12
+ ## [5.4.5]
13
+
14
+ ### Fixed
15
+
16
+ * Many issues after GenerateJsonSchema getting removed in fastapi==0.119.0
17
+
18
+ ### Changed
19
+
20
+ * A lot of documentation improvements by @Shigerman
21
+
8
22
  ## [5.4.4]
9
23
 
10
24
  ### Fixed
@@ -33,9 +47,8 @@ Please follow [the Keep a Changelog standard](https://keepachangelog.com/en/1.0.
33
47
 
34
48
  ### Added
35
49
 
36
- - `typing_inspection` dependency from pydantic team for complex isinstance checks that must be the same between `typing` and `typing_extensions`
37
- - Support for `pydantic>=2.12.0` FieldInfo refactoring from https://github.com/pydantic/pydantic/pull/11898
38
-
50
+ * `typing_inspection` dependency from pydantic team for complex isinstance checks that must be the same between `typing` and `typing_extensions`
51
+ * Support for `pydantic>=2.12.0` FieldInfo refactoring from <https://github.com/pydantic/pydantic/pull/11898>
39
52
 
40
53
  ## [5.3.3]
41
54
 
@@ -92,17 +105,17 @@ Please follow [the Keep a Changelog standard](https://keepachangelog.com/en/1.0.
92
105
  * `__doc__` attribute is now copied from the original enum to the generated enum
93
106
  * Python 3.12 type aliases and their typing_extensions backports are now supported (including `pydantic.JsonValue` and other `typing_extensions.TypeAliasType` instances)
94
107
  * 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
95
- * Updated minimum fastapi version to 0.112.4 because embed_body_fields was added in 0.112.4
108
+ * Updated minimum FastAPI version to 0.112.4 because embed_body_fields was added in 0.112.4
96
109
 
97
110
  ## [5.1.2]
98
111
 
99
112
  ### Fixed
100
113
 
101
- * Generators not being called when fastapi validates the initial request
114
+ * Generators not being called when FastAPI validates the initial request
102
115
 
103
116
  ### Added
104
117
 
105
- * `cadwyn.current_dependency_solver` function 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 when `current_dependency_solver` is `"cadwyn"`. If you want your dependency to run at the very beginning of handling the request, you should only run it when `current_dependency_solver` is `"fastapi"`.
118
+ * `cadwyn.current_dependency_solver` function 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 when `current_dependency_solver` is `"cadwyn"`. If you want your dependency to run at the very beginning of handling the request, you should only run it when `current_dependency_solver` is `"fastapi"`.
106
119
 
107
120
  ## [5.1.1]
108
121
 
@@ -309,7 +322,7 @@ Versions 3.x.x are still supported in terms of bug and security fixes but all th
309
322
 
310
323
  ### Changed
311
324
 
312
- * `Cadwyn.enrich_swagger` is 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
325
+ * `Cadwyn.enrich_swagger` is 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
313
326
 
314
327
  ### Fixed
315
328
 
@@ -330,7 +343,7 @@ Versions 3.x.x are still supported in terms of bug and security fixes but all th
330
343
 
331
344
  ### Fixed
332
345
 
333
- * Openapi not being generated when lifespan was used
346
+ * OpenAPI not being generated when lifespan was used
334
347
 
335
348
  ## [3.15.1]
336
349
 
@@ -455,7 +468,7 @@ Versions 3.x.x are still supported in terms of bug and security fixes but all th
455
468
 
456
469
  ### Fixed
457
470
 
458
- * When a class-based dependency from **fastapi** was used (anything security related), FastAPI had hardcoded `isinstance` checks 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 include `request` parameter which means that no extra dependencies or parameters are necessary.
471
+ * When a class-based dependency from **fastapi** was used (anything security related), FastAPI had hardcoded `isinstance` checks 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 include `request` parameter which means that no extra dependencies or parameters are necessary.
459
472
 
460
473
  ## [3.6.5]
461
474
 
@@ -713,13 +726,13 @@ Versions 3.x.x are still supported in terms of bug and security fixes but all th
713
726
 
714
727
  ### Fixed
715
728
 
716
- * Custom body fields created by fastapi caused an exception. Now they are ignored
729
+ * Custom body fields created by FastAPI caused an exception. Now they are ignored
717
730
 
718
731
  ## [2.0.2]
719
732
 
720
733
  ### Added
721
734
 
722
- * A link to openapi discussion on enum expansion into docs/recipes
735
+ * A link to OpenAPI discussion on enum expansion into docs/recipes
723
736
  * A link to intercom's API versioning article into docs/theory
724
737
 
725
738
  ## [2.0.1]
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: cadwyn
3
- Version: 5.4.4
3
+ Version: 5.5.0
4
4
  Summary: Production-ready community-driven modern Stripe-like API versioning in FastAPI
5
5
  Project-URL: Source code, https://github.com/zmievsa/cadwyn
6
6
  Project-URL: Documentation, https://docs.cadwyn.dev
@@ -35,14 +35,14 @@ Classifier: Topic :: Software Development :: Libraries :: Python Modules
35
35
  Classifier: Typing :: Typed
36
36
  Requires-Python: >=3.9
37
37
  Requires-Dist: backports-strenum<2,>=1.3.1; python_version < '3.11'
38
- Requires-Dist: fastapi>=0.112.4
38
+ Requires-Dist: fastapi>=0.119.0
39
39
  Requires-Dist: jinja2>=3.1.2
40
40
  Requires-Dist: pydantic>=2.11.0
41
41
  Requires-Dist: starlette>=0.30.0
42
42
  Requires-Dist: typing-extensions>=4.8.0
43
43
  Requires-Dist: typing-inspection>=0.4.0
44
44
  Provides-Extra: standard
45
- Requires-Dist: fastapi[standard]>=0.112.3; extra == 'standard'
45
+ Requires-Dist: fastapi[standard]>=0.119.0; extra == 'standard'
46
46
  Requires-Dist: typer>=0.7.0; extra == 'standard'
47
47
  Description-Content-Type: text/markdown
48
48
 
@@ -88,26 +88,3 @@ The [documentation](https://docs.cadwyn.dev) has everything you need to succeed.
88
88
  ## Sponsors
89
89
 
90
90
  These are our gorgeous sponsors. They are using Cadwyn and are sponsoring it through various means. Contact [me](https://github.com/zmievsa) if you would like to become one, too!
91
-
92
- ## Contributors
93
-
94
- <details>
95
-
96
- <summary>Thanks goes to these wonderful people:</summary>
97
- <a href="https://allcontributors.org/docs/en/emoji-key">Emoji Key </a>
98
-
99
- <!-- ALL-CONTRIBUTORS-LIST:START - Do not remove or modify this section -->
100
- <!-- prettier-ignore-start -->
101
- <!-- markdownlint-disable -->
102
-
103
- <!-- markdownlint-restore -->
104
- <!-- prettier-ignore-end -->
105
-
106
- <!-- ALL-CONTRIBUTORS-LIST:END -->
107
-
108
- This project follows the [all-contributors](https://github.com/all-contributors/all-contributors) specification.
109
- Contributions are welcome!
110
-
111
- </details>
112
-
113
- <!-- contributors-end -->
@@ -40,26 +40,3 @@ The [documentation](https://docs.cadwyn.dev) has everything you need to succeed.
40
40
  ## Sponsors
41
41
 
42
42
  These are our gorgeous sponsors. They are using Cadwyn and are sponsoring it through various means. Contact [me](https://github.com/zmievsa) if you would like to become one, too!
43
-
44
- ## Contributors
45
-
46
- <details>
47
-
48
- <summary>Thanks goes to these wonderful people:</summary>
49
- <a href="https://allcontributors.org/docs/en/emoji-key">Emoji Key </a>
50
-
51
- <!-- ALL-CONTRIBUTORS-LIST:START - Do not remove or modify this section -->
52
- <!-- prettier-ignore-start -->
53
- <!-- markdownlint-disable -->
54
-
55
- <!-- markdownlint-restore -->
56
- <!-- prettier-ignore-end -->
57
-
58
- <!-- ALL-CONTRIBUTORS-LIST:END -->
59
-
60
- This project follows the [all-contributors](https://github.com/all-contributors/all-contributors) specification.
61
- Contributions are welcome!
62
-
63
- </details>
64
-
65
- <!-- contributors-end -->
@@ -5,12 +5,10 @@ from logging import getLogger
5
5
  from typing import Any, Literal, TypeVar, Union, cast, get_args
6
6
 
7
7
  from fastapi._compat import (
8
- GenerateJsonSchema,
9
- ModelField,
10
8
  get_compat_model_name_map,
11
9
  get_definitions,
12
10
  )
13
- from fastapi.openapi.constants import REF_TEMPLATE
11
+ from fastapi._compat.v2 import ModelField
14
12
  from fastapi.openapi.utils import (
15
13
  get_fields_from_routes,
16
14
  get_openapi,
@@ -92,7 +90,7 @@ def _generate_changelog(versions: VersionBundle, router: _RootCadwynAPIRouter) -
92
90
  version_change,
93
91
  generator_from_newer_version,
94
92
  generator_from_older_version,
95
- schemas_from_older_version,
93
+ schemas_from_older_version, # pyright: ignore[reportArgumentType]
96
94
  cast("list[APIRoute]", routes_from_newer_version),
97
95
  )
98
96
  if changelog_entry is not None: # pragma: no branch # This should never happen
@@ -120,7 +118,7 @@ def _get_affected_model_names(
120
118
  FieldDidntHaveInstruction,
121
119
  ],
122
120
  generator_from_newer_version: SchemaGenerator,
123
- schemas_from_last_version: list[ModelField],
121
+ schemas_from_last_version: "list[ModelField]",
124
122
  ):
125
123
  changed_model = generator_from_newer_version._get_wrapper_for_model(instruction.schema)
126
124
  annotations = [model.field_info.annotation for model in schemas_from_last_version]
@@ -159,11 +157,19 @@ def _get_openapi_representation_of_a_field(model: type[BaseModel], field_name: s
159
157
  class CadwynDummyModelForRepresentation(BaseModel):
160
158
  my_field: model
161
159
 
162
- model_name_map = get_compat_model_name_map([CadwynDummyModelForRepresentation.model_fields["my_field"]])
163
- schema_generator = GenerateJsonSchema(ref_template=REF_TEMPLATE)
160
+ model_name_map = get_compat_model_name_map(
161
+ [
162
+ CadwynDummyModelForRepresentation.model_fields["my_field"], # pyright: ignore[reportArgumentType]
163
+ ]
164
+ )
165
+
164
166
  _, definitions = get_definitions(
165
- fields=[ModelField(CadwynDummyModelForRepresentation.model_fields["my_field"], "my_field")],
166
- schema_generator=schema_generator,
167
+ fields=[
168
+ ModelField(
169
+ CadwynDummyModelForRepresentation.model_fields["my_field"],
170
+ "my_field",
171
+ ), # pyright: ignore[reportArgumentType]
172
+ ],
167
173
  model_name_map=model_name_map,
168
174
  separate_input_output_schemas=False,
169
175
  )
@@ -315,7 +321,7 @@ def _convert_version_change_instruction_to_changelog_entry( # noqa: C901
315
321
  version_change: type[VersionChange],
316
322
  generator_from_newer_version: SchemaGenerator,
317
323
  generator_from_older_version: SchemaGenerator,
318
- schemas_from_older_version: list[ModelField],
324
+ schemas_from_older_version: "list[ModelField]",
319
325
  routes_from_newer_version: list[APIRoute],
320
326
  ):
321
327
  if isinstance(instruction, EndpointDidntExistInstruction):
@@ -541,7 +541,7 @@ class _AsyncGeneratorCallableWrapper(_CallableWrapper):
541
541
  class _AnnotationTransformer:
542
542
  def __init__(self, generator: "SchemaGenerator") -> None:
543
543
  # This cache is not here for speeding things up. It's for preventing the creation of copies of the same object
544
- # because such copies could produce weird behaviors at runtime, especially if you/fastapi do any comparisons.
544
+ # because such copies could produce weird behaviors at runtime, especially if you/FastAPI do any comparisons.
545
545
  # It's defined here and not on the method because of this: https://youtu.be/sVjtp6tGo0g
546
546
  self.generator = generator
547
547
  # TODO: Rewrite this to memoize
@@ -18,7 +18,7 @@ HTTP_METHODS = {"GET", "POST", "PUT", "PATCH", "DELETE", "OPTIONS", "HEAD"}
18
18
 
19
19
  @dataclass(**DATACLASS_SLOTS)
20
20
  class EndpointAttributesPayload:
21
- # Fastapi API routes also have "endpoint" and "dependency_overrides_provider" fields.
21
+ # FastAPI API routes also have "endpoint" and "dependency_overrides_provider" fields.
22
22
  # We do not use them because:
23
23
  # 1. "endpoint" must not change -- otherwise this versioning is doomed
24
24
  # 2. "dependency_overrides_provider" is taken from router's attributes
@@ -694,7 +694,7 @@ class VersionBundle:
694
694
  # We use this instead of `.body()` to automatically guess body type and load the correct body, even if it's a form
695
695
  async def _get_body(
696
696
  request: FastapiRequest, body_field: Union[ModelField, None], exit_stack: AsyncExitStack
697
- ): # pragma: no cover # This is from fastapi
697
+ ): # pragma: no cover # This is from FastAPI
698
698
  is_body_form = body_field and isinstance(body_field.field_info, params.Form)
699
699
  try:
700
700
  body: Any = None
@@ -63,7 +63,7 @@ app = Cadwyn(
63
63
  )
64
64
  ```
65
65
 
66
- In which case only dates will be accepted as valid versions.
66
+ In the example above only dates will be accepted as valid versions.
67
67
 
68
68
  You can also use an arbitrary string:
69
69
 
@@ -80,21 +80,21 @@ app = Cadwyn(
80
80
  )
81
81
  ```
82
82
 
83
- In which case any string will be accepted as a valid version. Notice how they do not have to be sortable or even ordered. Cadwyn will assume that their actual order is the same as the order of the versions in the `VersionBundle`.
83
+ In the example above any string will be accepted as a valid version. Arbitrary strings can be used, Cadwyn will not sort them. Cadwyn will assume their actual order matches the order of the versions in the `VersionBundle`.
84
84
 
85
85
  ### API Version waterfalling
86
86
 
87
87
  For historical reasons, date-based routing also supports waterfalling the requests to the closest earlier version of the API if the request date parameter doesn't match any of the versions exactly.
88
88
 
89
- If the app has two versions: 2022-01-02 and 2022-01-05, and the request date parameter is 2022-01-03, then the request will be routed to 2022-01-02 version as it the closest version, but lower than the request date parameter.
89
+ If the app has two versions: 2022-01-02 and 2022-01-05, and the request date parameter is 2022-01-03, then the request will be routed to the 2022-01-02 version, as it is the closest version, but lower than the request date parameter.
90
90
 
91
- Exact match is always preferred over partial match and a request will never be matched to the higher versioned route.
91
+ An exact match is always preferred to a partial match and a request will never be matched to the higher-versioned route.
92
92
 
93
- We implement routing like this because Cadwyn was born in a microservice architecture and it is extremely convenient to have waterfalling there. For example, imagine that you have two Cadwyn services: Payables and Receivables, each defining its own API versions. Payables service might contain 10 versions while receivables service might contain only 2 versions because it didn't need as many breaking changes. If a client requests a version that does not exist in receivables -- we will just waterfall to some earlier version, making receivables behavior consistent even if API keeps getting new versions.
93
+ We implement routing like this because Cadwyn was born in a microservice architecture and it is extremely convenient to have waterfalling there. For example, imagine that you have two Cadwyn services: Payables and Receivables, each defining its own API versions. Payables service might contain 10 versions while Receivables service might contain only 2 versions because it didn't need as many breaking changes. If a client requests a version that does not exist in Receivables, we will just waterfall to some earlier version, making Receivables behavior consistent even if API keeps getting new versions.
94
94
 
95
95
  ## API Version Parameter Title and Description
96
96
 
97
- You can pass a title and/or a description to `Cadwyn` constructor. They are equivalent to passing `title` and `description` to `fastapi.Path` or `fastapi.Header` constructors.
97
+ You can pass a title and/or a description to the `Cadwyn` constructor. It is equivalent to passing `title` and `description` to `fastapi.Path` or `fastapi.Header` constructors.
98
98
 
99
99
  ```python
100
100
  app = Cadwyn(
@@ -0,0 +1,9 @@
1
+ # Beware of data versioning
2
+
3
+ Oftentimes you will want to introduce a breaking change where one of the following is true:
4
+
5
+ * Old data cannot be automatically converted to the structure of the new response
6
+ * New response cannot be automatically migrated to an older response
7
+ * Old request cannot be automatically converted to the HEAD request
8
+
9
+ This means that you are not versioning your API, you are versioning your **data**. This cannot be solved by an API versioning framework. It also makes it incredibly hard to version as you now cannot guarantee compatibility between versions. Avoid this at all costs -- all your API versions must be compatible between each other. Data versioning is not a result of a complicated use case, it is a result of **errors** when divising a new version. I am yet to meet a single case where data versioning is the right way to solve an API versioning problem.
@@ -27,11 +27,11 @@ class CompletelyHiddenVersionChange(VersionChange):
27
27
 
28
28
  ## Customizing changelog endpoint
29
29
 
30
- Just pass the `changelog_url` argument to `Cadwyn` and a `GET` to this url will start returning the changelog for all versions based on the contents of your `VersionBundle`.
30
+ The changelog endpoint name can be customized by specifying a new name via the `changelog_url` argument to the `Cadwyn()` constructor. Accessing this url via the `GET` request will return the changelog for all versions based on the content of your `VersionBundle`.
31
31
 
32
- If you want to hide the changelog endpoint, pass `include_changelog_url_in_schema=False` to `Cadwyn`.
32
+ If you want to hide the changelog endpoint, pass `include_changelog_url_in_schema=False` to `Cadwyn()`.
33
33
 
34
- If you want to delete the changelog endpoint, pass `changelog_url=None` to `Cadwyn`.
34
+ If you want to delete the changelog endpoint, pass `changelog_url=None` to `Cadwyn()`.
35
35
 
36
36
  ## Changelog structure and entry types
37
37
 
@@ -1,7 +1,7 @@
1
1
  # CLI
2
2
 
3
- Cadwyn has an optional CLI interface that can be installed with `pip install 'cadwyn[standard]'`.
4
- You can run `cadwyn --version` to check current version of Cadwyn.
3
+ Cadwyn has an optional CLI that can be installed with `pip install 'cadwyn[standard]'`.
4
+ You can run `cadwyn --version` to check the current version of Cadwyn.
5
5
 
6
6
  Its main purpose is [rendering generated schemas](./schema_generation.md#rendering-schemas).
7
7
 
@@ -1,8 +1,8 @@
1
1
  # Endpoint migrations
2
2
 
3
- Note that the `endpoint(...)` constructor contains a second argument that describes the methods of the endpoints you would like to edit. If you have two routes for a single endpoint and you put both of their methods into the instruction -- both of them are going to be changed as you would expect.
3
+ Note that the `endpoint(...)` constructor contains a second argument that describes the methods of the endpoints you would like to edit. If you have two routes for a single endpoint and you put both of their methods into the instruction -- as expected, both of them will be changed.
4
4
 
5
- ## Defining endpoints that didn't exist in new versions
5
+ ## Defining endpoints that didn't exist for new versions
6
6
 
7
7
  If you had an endpoint in an old version **but want to delete it in a new version**, you must still define it as usual with all your other endpoints but mark it as deleted.
8
8
 
@@ -43,7 +43,7 @@ class MyChange(VersionChange):
43
43
 
44
44
  ## Changing endpoint attributes
45
45
 
46
- If you want to change any attribute of your endpoint in a new version, you can return the attribute's value in all older versions like so:
46
+ If you want to change any attribute of your endpoint in a new version, you can return the attribute's value in all older versions like this:
47
47
 
48
48
  ```python
49
49
  from cadwyn import VersionChange, endpoint
@@ -64,11 +64,11 @@ However, you only need to have a migration if it is a breaking change for your u
64
64
 
65
65
  Note that changing endpoint `dependencies` is only going to affect the initial validation. So Cadwyn will take your altered dependencies and run them on each request to the endpoint but ultimately your endpoint code is always going to use the HEAD version of your dependencies. So be careful.
66
66
 
67
- Note also that if some of your dependencies were added at app/router level -- they **are** going to be overwritten by this instruction. Most of the time it is rather safe, however, as all the necessary dependencies will still run on HEAD version.
67
+ Also note that if some of your dependencies were added at app/router level, they **are** going to be overwritten by this instruction. Most of the time it is rather safe, however, as all the necessary dependencies will still run on HEAD version.
68
68
 
69
69
  ## Dealing with endpoint duplicates
70
70
 
71
- Sometimes, when you're doing some advanced changes in between versions, you will need to rewrite your endpoint function entirely. So essentially you'd have the following structure:
71
+ Sometimes, when you're doing some advanced changes in between versions, you need to rewrite your endpoint function entirely. So essentially you'd have the following structure:
72
72
 
73
73
  ```python
74
74
  from fastapi.params import Param
@@ -92,7 +92,7 @@ def get_users_by_name(user_name: Annotated[str, Param()]):
92
92
  """Do some logic with user_name"""
93
93
  ```
94
94
 
95
- As you see, these two functions have the same methods and paths. And when you have many versions, you can have even more functions like these two. So how do we ask cadwyn to restore only one of them and delete the other one?
95
+ As you see, these two functions have the same parameters and path decorators. And when you have many versions, you can have even more functions like these two. So how do we ask cadwyn to restore only one of them and delete the other one?
96
96
 
97
97
  ```python
98
98
  from cadwyn import VersionChange, endpoint
@@ -104,8 +104,8 @@ class UseParamsInsteadOfHeadersForUserNameFiltering(VersionChange):
104
104
  "because using headers is a bad API practice in such scenarios."
105
105
  )
106
106
  instructions_to_migrate_to_previous_version = (
107
- # We need to specify the name, otherwise, we will encounter an exception due to having two identical endpoints
108
- # with the same path and method
107
+ # We need to specify the name, otherwise, we will encounter an exception due to
108
+ # having two identical endpoints with the same parameters and path decorators
109
109
  endpoint(
110
110
  "/users",
111
111
  ["GET"],
@@ -117,4 +117,4 @@ class UseParamsInsteadOfHeadersForUserNameFiltering(VersionChange):
117
117
  )
118
118
  ```
119
119
 
120
- So by using a more concrete `func_name`, we are capable to distinguish between different functions that affect the same routes.
120
+ So by using a more concrete `func_name`, we are able to distinguish between different functions that affect the same routes.
@@ -1,10 +1,10 @@
1
1
  # Enum migrations
2
2
 
3
- All of the following instructions affect only openapi schemas and their initial validation. All of your incoming requests will still be converted into your HEAD schemas.
3
+ All of the following instructions affect only OpenAPI schemas and their initial validation. All of your incoming requests will still be converted into your HEAD schemas.
4
4
 
5
5
  ## Adding enum members
6
6
 
7
- Note that adding enum members **can** be a breaking change unlike adding optional fields to a schema. For example, if I return a list of entities, each of which has some type, and I add a new type -- then my client's code is likely to break.
7
+ Note that adding enum members **can** be a breaking change unlike adding optional fields to a schema. For example, if I return a list of entities, each of which has some type, and I add a new type, then my client's code is likely to break.
8
8
 
9
9
  So I suggest adding enum members in new versions as well.
10
10
 
@@ -1,8 +1,8 @@
1
1
  # Concepts
2
2
 
3
- This section covers the entirety of features and their rationale in Cadwyn. It can also be used as a reference documentation until we have a proper one. First, let's talk about the reasons for using Cadwyn at all.
3
+ This section covers the entirety of features and their rationale in Cadwyn. It can also be used as reference documentation until we have a proper one. First, let's talk about the reasons for using Cadwyn at all.
4
4
 
5
- Cadwyn aims to be the most accurate and sophisticated API Versioning model out there. First of all, you maintain **zero** duplicated code yourself. Usually, in API versioning you [would need to](../theory/how_we_got_here.md) duplicate and maintain at least some layer of your application. It could be the database, business logic, schemas, and endpoints. Cadwyn allows you to duplicate none of that. Internally, it duplicates endpoints and schemas at runtime but none of it becomes your tech debt, none of it becomes your code to support. If you test rigorously, then only [some small subset of your tests](./testing.md) will need to be duplicated when existing functionality is changed between versions.
5
+ Cadwyn aims to be the most accurate and sophisticated API Versioning model out there. First of all, you maintain **zero** duplicated code yourself. Usually, in API versioning you [would need to](../theory/how_we_got_here.md) duplicate and maintain at least some layer of your application. It could be the database, business logic, schemas, and endpoints. With Cadwyn you avoid duplicating any of that. Internally, it duplicates endpoints and schemas at runtime but none of it becomes your tech debt, none of it becomes your code to support. If you test rigorously, then only [some small subset of your tests](./testing.md) will need to be duplicated when existing functionality is changed between versions.
6
6
 
7
7
  You define your database, business logic, routes, and schemas only once. Then, whenever you release a new API version, you use Cadwyn's [version change DSL](./version_changes.md#version-changes) to describe how to convert your app to the previous version. So your business logic and database stay intact and always represent the latest version while the version changes make sure that your clients can continue using the previous versions without ever needing to update their code.
8
8
 
@@ -1,11 +1,11 @@
1
1
  # Main App
2
2
 
3
- Cadwyn's standard usage is done with a single customized FastAPI app: `cadwyn.Cadwyn`. It accepts all the same arguments as `FastAPI` three more keyword-only arguments:
3
+ Cadwyn's standard usage involves a single customized FastAPI app: `cadwyn.Cadwyn`. It accepts all the same arguments as `FastAPI` does and two more keyword-only arguments:
4
4
 
5
5
  * Required `versions: VersionBundle` describes [all versions](./version_changes.md#versionbundle) within your application
6
6
  * Optional `api_version_parameter_name: str = "x_api_version"` is the parameter that Cadwyn will use for [routing](#routing) to different API versions of your app
7
7
 
8
- After you have defined a main app, you can add versioned API routers to it using `Cadwyn.generate_and_include_versioned_routers(*routers)`
8
+ After you have defined the main app, you can add versioned API routers to it using `Cadwyn.generate_and_include_versioned_routers(*routers)`
9
9
 
10
10
  ```python
11
11
  from cadwyn import VersionedAPIRouter, Cadwyn
@@ -33,9 +33,9 @@ That's it! `generate_and_include_versioned_routers` will generate all versions o
33
33
 
34
34
  ## Routing
35
35
 
36
- Cadwyn is built on header-based routing. First, we route requests to the appropriate API version based on the version header (`x-api-version` by default). Then we route by the appropriate url path and method. Currently, Cadwyn only works with ISO date-based versions (such as `2022-11-16`). If the user sends an incorrect API version, Cadwyn picks up the closest lower applicable version. For example, `2022-11-16` in request can be matched by `2022-11-15` and `2000-01-01` but cannot be matched by `2022-11-17`.
36
+ Cadwyn is built on header-based routing. First, we route requests to the appropriate API version based on the version header (`x-api-version` by default). Then we route by the appropriate url path and method. Currently, Cadwyn only works with ISO date-based versions (such as `2022-11-16`). If the user sends a date that does not have an exact match, Cadwyn picks up the closest lower applicable version. For example, `2022-11-16` in request can be matched by `2022-11-15` and `2000-01-01` but cannot be matched by `2022-11-17`.
37
37
 
38
- However, header-based routing is only the standard way to use Cadwyn. If you want to use any other sort of routing, you can use Cadwyn directly through `cadwyn.generate_versioned_routers` or subclass `cadwyn.Cadwyn` to use a different router and middleware. Just remember to update the `VersionBundle.api_version_var` variable each time you route some request to a version. This variable allows Cadwyn to do [side effects](./version_changes.md#version-changes-with-side-effects) and [data migrations](./version_changes.md#data-migrations).
38
+ However, header-based routing is the default way to use Cadwyn. If you want to use any other form of routing, you can use Cadwyn directly through `cadwyn.generate_versioned_routers` or subclass `cadwyn.Cadwyn` to use a different router and middleware. Just remember to update the `VersionBundle.api_version_var` variable each time you route some request to a version. This variable allows Cadwyn to do [side effects](./version_changes.md#version-changes-with-side-effects) and [data migrations](./version_changes.md#data-migrations).
39
39
 
40
40
  ### VersionedAPIRouter
41
41
 
@@ -2,12 +2,12 @@
2
2
 
3
3
  Cadwyn implements a methodology that is based on the following set of principles:
4
4
 
5
- * Each version is made up of "version changes" or "compatibility gates" which describe **independent atomic** differences between it and previous version
5
+ * Each version consists of "version changes" or "compatibility gates" which describe **independent, atomic** differences from the previous version
6
6
  * We make a new version if and only if we have breaking changes
7
7
  * Versions must have little to no effect on the business logic
8
8
  * Versions **must always** be compatible in terms of data
9
9
  * Creating new versions is avoided at all costs
10
- * Any backwards compatible features must be backported to all compatible versions
10
+ * Any backward-compatible features must be backported to all compatible versions
11
11
 
12
12
  These rules give us an ability to have a large number of self-documenting versions while encapsulating their complexity in small version change classes, providing a consistent and stable experience to our users.
13
13
 
@@ -4,13 +4,13 @@ Cadwyn automatically generates versioned schemas and everything related to them
4
4
 
5
5
  ## Rendering schemas
6
6
 
7
- When you have many versions and many schemas, it is quite hard to know what validators, fields, and other attributes are defined on each schema in any concrete version. To combat this problem, we have a way to **render** the generated pydantic models and enums to code using the command-line interface.
7
+ When you have many versions and schemas, it is quite challenging to know what validators, fields, and other attributes are defined on each schema in any specific version. To address this issue, there is a way to **render** the generated pydantic models and enums as code using the command-line interface.
8
8
 
9
- **NOTICE** that `cadwyn render` does not promise to render correct schemas. It is going to be a very close approximation which should be enough for the cases where humans check the schemas by hand. However, it is not yet ready to be used for full blown code generation. For example, it doesn't handle schema renamings in class `__bases__` yet.
9
+ **NOTICE** that `cadwyn render` does not guarantee rendering correct schemas. It is going to be a close enough approximation for manual validation. However, it is not yet ready to be used for production code generation. For example, it doesn't handle schema renamings in class `__bases__` yet.
10
10
 
11
11
  ### Rendering a module
12
12
 
13
- Here's how you would render the entire module with your schemas:
13
+ Here's a way to render the entire module with the schemas:
14
14
 
15
15
  ```bash
16
16
  cadwyn render module data.schemas --app=main:app --version=2024-05-26
@@ -20,7 +20,7 @@ This command will print to stdout what the schemas would look like in version 20
20
20
 
21
21
  ### Rendering a single model
22
22
 
23
- Here's how you would render a single pydantic model or enum with your schemas:
23
+ Here's a way to render a single pydantic model or enum with the schemas:
24
24
 
25
25
  ```bash
26
26
  cadwyn render model data.schemas:UserCreateRequest --app=main:app --version=2024-05-26
@@ -34,6 +34,7 @@ Cadwyn is capable of generating versioned schemas from its version changes even
34
34
 
35
35
  ```python
36
36
  import cadwyn
37
+ from cadwyn.schema_generation import generate_versioned_models
37
38
  from my_versions import version_bundle, MyVersionedSchema
38
39
 
39
40
  schema_generators = generate_versioned_models(version_bundle)
@@ -1,14 +1,14 @@
1
1
  # Schema migrations
2
2
 
3
- All of the following instructions affect only openapi schemas and their initial validation. All of your incoming requests will still be converted into your HEAD schemas.
3
+ All of the following instructions affect only OpenAPI schemas and their initial validation. All of your incoming requests will still be converted into your HEAD schemas.
4
4
 
5
- Please note that you only need to have a migration if it is a breaking change for your users. The scenarios below only describe "what you can do" but not "what you should do". For the "should", please refer to the [how-to docs](../how_to/change_openapi_schemas/add_field.md).
5
+ Please note that you only need to have a migration if it is a breaking change for your users. The scenarios below only describe "what you can do" but not "what you should do". For the "should" part, please refer to the [how-to docs](../how_to/change_openapi_schemas/add_field.md).
6
6
 
7
7
  ## Add a field to the older version
8
8
 
9
9
  ```python
10
- from pydantic import Field
11
10
  from cadwyn import VersionChange, schema
11
+ from pydantic import Field
12
12
 
13
13
 
14
14
  class MyChange(VersionChange):
@@ -35,7 +35,7 @@ class MyChange(VersionChange):
35
35
 
36
36
  ## Change a field in the older version
37
37
 
38
- If you would like to set a description or any other attribute of a field, you would do:
38
+ The following code allows to set an attribute of a field, such as a description:
39
39
 
40
40
  ```python
41
41
  from cadwyn import VersionChange, schema
@@ -48,7 +48,7 @@ class MyChange(VersionChange):
48
48
  )
49
49
  ```
50
50
 
51
- and if you would like to unset any attribute of a field as if it was never passed, you would do:
51
+ The following code allows to un-set an attribute of a field, as if it never existed:
52
52
 
53
53
  ```python
54
54
  from cadwyn import VersionChange, schema
@@ -65,23 +65,23 @@ class MyChange(VersionChange):
65
65
 
66
66
  If you add `default` or `default_factory` into the old version of a schema -- it will not manifest in code automatically. Instead, you should add both the `default` or `default_factory`, and then also add the default value using a request migration.
67
67
 
68
- This happens because of how Cadwyn works with pydantic and sadly cannot be changed:
68
+ The reason for such behaviour is the way how Cadwyn works with pydantic and unfortunately this cannot be changed:
69
69
 
70
70
  Cadwyn:
71
71
 
72
- 1. Receives the request of some version `V`
72
+ 1. Receives a request for API version `V`
73
73
  2. Validates the request using the schemas from `V`
74
74
  3. Marshalls the unmarshalled request body into a raw data structure using `BaseModel.dict` (`BaseModel.model_dump` in Pydantic v2) using **exclude_unset=True**
75
75
  4. Passes the request through all request migrations from `V` to `latest`
76
76
  5. Validates the request using `latest` schemas
77
77
 
78
- The part that causes the aforementioned problem is our usage of `exclude_unset=True`. Sadly, when we use it, all default fields do not get set so `latest` does not receive them. And if `latest` does not have the same defaults (for example, if the field has no default and is required in `latest`), then an error will occur. If we used `exclude_unset=False`, then `exclude_unset` would lose all its purpose for the users of our library so we cannot abandon it. Instead, you should set all extra on step 4 in your request migrations.
78
+ The part that causes the aforementioned problem is cadwyn's usage of `exclude_unset=True`. Unfortunately, when we use it, all default fields do not get set, so `latest` does not receive them. And if `latest` does not have the same defaults (for example, if the field has no default and is required in `latest`), then an error will occur. If we used `exclude_unset=False`, then `exclude_unset` would lose all its purpose for the users of our library so we cannot give it up. Instead, you should set all extras on step 4 in your request migrations.
79
79
 
80
80
  ## Add a validator to the older version
81
81
 
82
82
  ```python
83
- from pydantic import Field, field_validator
84
83
  from cadwyn import VersionChange, schema
84
+ from pydantic import Field, field_validator
85
85
 
86
86
 
87
87
  @field_validator("foo")
@@ -101,8 +101,8 @@ class MyChange(VersionChange):
101
101
  ## Remove a validator from the older version
102
102
 
103
103
  ```python
104
- from pydantic import Field, validator
105
104
  from cadwyn import VersionChange, schema
105
+ from pydantic import Field, validator
106
106
 
107
107
 
108
108
  class MyChange(VersionChange):
@@ -114,7 +114,8 @@ class MyChange(VersionChange):
114
114
 
115
115
  ## Rename a schema in the older version
116
116
 
117
- If you wish to rename your schema to make sure that its name is different in openapi.json:
117
+ The following code allows to replace all schema name occurrences with the new one to make sure that the name is different in openapi.json:
118
+
118
119
 
119
120
  ```python
120
121
  from cadwyn import VersionChange, schema
@@ -126,5 +127,3 @@ class MyChange(VersionChange):
126
127
  schema(MySchema).had(name="OtherSchema"),
127
128
  )
128
129
  ```
129
-
130
- which will replace all references to this schema with the new name.