cadwyn 5.0.0__tar.gz → 5.1.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.
- {cadwyn-5.0.0 → cadwyn-5.1.0}/.github/workflows/ci.yaml +10 -6
- {cadwyn-5.0.0 → cadwyn-5.1.0}/CHANGELOG.md +6 -0
- {cadwyn-5.0.0 → cadwyn-5.1.0}/PKG-INFO +4 -3
- {cadwyn-5.0.0 → cadwyn-5.1.0}/cadwyn/_asts.py +10 -7
- {cadwyn-5.0.0 → cadwyn-5.1.0}/cadwyn/_render.py +7 -7
- {cadwyn-5.0.0 → cadwyn-5.1.0}/cadwyn/_utils.py +25 -2
- {cadwyn-5.0.0 → cadwyn-5.1.0}/cadwyn/applications.py +34 -32
- {cadwyn-5.0.0 → cadwyn-5.1.0}/cadwyn/changelogs.py +182 -181
- {cadwyn-5.0.0 → cadwyn-5.1.0}/cadwyn/middleware.py +7 -7
- {cadwyn-5.0.0 → cadwyn-5.1.0}/cadwyn/route_generation.py +10 -9
- {cadwyn-5.0.0 → cadwyn-5.1.0}/cadwyn/routing.py +2 -2
- {cadwyn-5.0.0 → cadwyn-5.1.0}/cadwyn/schema_generation.py +114 -46
- {cadwyn-5.0.0 → cadwyn-5.1.0}/cadwyn/structure/common.py +5 -3
- {cadwyn-5.0.0 → cadwyn-5.1.0}/cadwyn/structure/data.py +10 -7
- {cadwyn-5.0.0 → cadwyn-5.1.0}/cadwyn/structure/endpoints.py +24 -21
- {cadwyn-5.0.0 → cadwyn-5.1.0}/cadwyn/structure/enums.py +13 -7
- {cadwyn-5.0.0 → cadwyn-5.1.0}/cadwyn/structure/schemas.py +63 -53
- {cadwyn-5.0.0 → cadwyn-5.1.0}/cadwyn/structure/versions.py +50 -40
- {cadwyn-5.0.0 → cadwyn-5.1.0}/pyproject.toml +4 -3
- {cadwyn-5.0.0 → cadwyn-5.1.0}/ruff.toml +1 -1
- {cadwyn-5.0.0 → cadwyn-5.1.0}/tests/_resources/render/complex/classes.py +2 -2
- {cadwyn-5.0.0 → cadwyn-5.1.0}/tests/_resources/render/complex/versions.py +10 -0
- {cadwyn-5.0.0 → cadwyn-5.1.0}/tests/conftest.py +11 -12
- {cadwyn-5.0.0 → cadwyn-5.1.0}/tests/test_changelog.py +4 -4
- {cadwyn-5.0.0 → cadwyn-5.1.0}/tests/test_data_migrations.py +12 -12
- {cadwyn-5.0.0 → cadwyn-5.1.0}/tests/test_render.py +9 -2
- {cadwyn-5.0.0 → cadwyn-5.1.0}/tests/test_router_generation.py +14 -13
- {cadwyn-5.0.0 → cadwyn-5.1.0}/tests/test_schema_generation/test_schema_field.py +11 -11
- {cadwyn-5.0.0 → cadwyn-5.1.0}/tests/test_structure.py +18 -13
- {cadwyn-5.0.0 → cadwyn-5.1.0}/tox.ini +6 -15
- {cadwyn-5.0.0 → cadwyn-5.1.0}/uv.lock +126 -2
- {cadwyn-5.0.0 → cadwyn-5.1.0}/.github/CODE_OF_CONDUCT.md +0 -0
- {cadwyn-5.0.0 → cadwyn-5.1.0}/.github/ISSUE_TEMPLATE/bug_report.md +0 -0
- {cadwyn-5.0.0 → cadwyn-5.1.0}/.github/ISSUE_TEMPLATE/feature_request.md +0 -0
- {cadwyn-5.0.0 → cadwyn-5.1.0}/.github/actions/setup-python-uv/action.yaml +0 -0
- {cadwyn-5.0.0 → cadwyn-5.1.0}/.github/workflows/daily_tests.yaml +0 -0
- {cadwyn-5.0.0 → cadwyn-5.1.0}/.github/workflows/publish_docs.yaml +0 -0
- {cadwyn-5.0.0 → cadwyn-5.1.0}/.github/workflows/release.yaml +0 -0
- {cadwyn-5.0.0 → cadwyn-5.1.0}/.gitignore +0 -0
- {cadwyn-5.0.0 → cadwyn-5.1.0}/.pre-commit-config.yaml +0 -0
- {cadwyn-5.0.0 → cadwyn-5.1.0}/LICENSE +0 -0
- {cadwyn-5.0.0 → cadwyn-5.1.0}/Makefile +0 -0
- {cadwyn-5.0.0 → cadwyn-5.1.0}/README.md +0 -0
- {cadwyn-5.0.0 → cadwyn-5.1.0}/cadwyn/__init__.py +0 -0
- {cadwyn-5.0.0 → cadwyn-5.1.0}/cadwyn/__main__.py +0 -0
- {cadwyn-5.0.0 → cadwyn-5.1.0}/cadwyn/_importer.py +0 -0
- {cadwyn-5.0.0 → cadwyn-5.1.0}/cadwyn/exceptions.py +0 -0
- {cadwyn-5.0.0 → cadwyn-5.1.0}/cadwyn/py.typed +0 -0
- {cadwyn-5.0.0 → cadwyn-5.1.0}/cadwyn/static/__init__.py +0 -0
- {cadwyn-5.0.0 → cadwyn-5.1.0}/cadwyn/static/docs.html +0 -0
- {cadwyn-5.0.0 → cadwyn-5.1.0}/cadwyn/structure/__init__.py +0 -0
- {cadwyn-5.0.0 → cadwyn-5.1.0}/docs/CNAME +0 -0
- {cadwyn-5.0.0 → cadwyn-5.1.0}/docs/__init__.py +0 -0
- {cadwyn-5.0.0 → cadwyn-5.1.0}/docs/concepts/api_version_parameter_and_context_variables.md +0 -0
- {cadwyn-5.0.0 → cadwyn-5.1.0}/docs/concepts/beware_of_data_versioning.md +0 -0
- {cadwyn-5.0.0 → cadwyn-5.1.0}/docs/concepts/changelogs.md +0 -0
- {cadwyn-5.0.0 → cadwyn-5.1.0}/docs/concepts/cli.md +0 -0
- {cadwyn-5.0.0 → cadwyn-5.1.0}/docs/concepts/endpoint_migrations.md +0 -0
- {cadwyn-5.0.0 → cadwyn-5.1.0}/docs/concepts/enum_migrations.md +0 -0
- {cadwyn-5.0.0 → cadwyn-5.1.0}/docs/concepts/index.md +0 -0
- {cadwyn-5.0.0 → cadwyn-5.1.0}/docs/concepts/main_app.md +0 -0
- {cadwyn-5.0.0 → cadwyn-5.1.0}/docs/concepts/methodology.md +0 -0
- {cadwyn-5.0.0 → cadwyn-5.1.0}/docs/concepts/schema_generation.md +0 -0
- {cadwyn-5.0.0 → cadwyn-5.1.0}/docs/concepts/schema_migrations.md +0 -0
- {cadwyn-5.0.0 → cadwyn-5.1.0}/docs/concepts/testing.md +0 -0
- {cadwyn-5.0.0 → cadwyn-5.1.0}/docs/concepts/version_changes.md +0 -0
- {cadwyn-5.0.0 → cadwyn-5.1.0}/docs/concepts/where_to_put_the_version_and_how_to_format_it.md +0 -0
- {cadwyn-5.0.0 → cadwyn-5.1.0}/docs/home/CONTRIBUTING.md +0 -0
- {cadwyn-5.0.0 → cadwyn-5.1.0}/docs/how_to/change_business_logic/index.md +0 -0
- {cadwyn-5.0.0 → cadwyn-5.1.0}/docs/how_to/change_endpoints/index.md +0 -0
- {cadwyn-5.0.0 → cadwyn-5.1.0}/docs/how_to/change_openapi_schemas/add_field.md +0 -0
- {cadwyn-5.0.0 → cadwyn-5.1.0}/docs/how_to/change_openapi_schemas/change_field_type.md +0 -0
- {cadwyn-5.0.0 → cadwyn-5.1.0}/docs/how_to/change_openapi_schemas/change_schema_without_endpoint.md +0 -0
- {cadwyn-5.0.0 → cadwyn-5.1.0}/docs/how_to/change_openapi_schemas/changing_constraints.md +0 -0
- {cadwyn-5.0.0 → cadwyn-5.1.0}/docs/how_to/change_openapi_schemas/remove_field.md +0 -0
- {cadwyn-5.0.0 → cadwyn-5.1.0}/docs/how_to/change_openapi_schemas/rename_a_field_in_schema.md +0 -0
- {cadwyn-5.0.0 → cadwyn-5.1.0}/docs/how_to/index.md +0 -0
- {cadwyn-5.0.0 → cadwyn-5.1.0}/docs/how_to/version_with_paths_and_numbers_instead_of_headers_and_dates.md +0 -0
- {cadwyn-5.0.0 → cadwyn-5.1.0}/docs/img/dashboard_with_one_version.png +0 -0
- {cadwyn-5.0.0 → cadwyn-5.1.0}/docs/img/dashboard_with_two_versions.png +0 -0
- {cadwyn-5.0.0 → cadwyn-5.1.0}/docs/img/get_users_endpoint_from_prior_version.png +0 -0
- {cadwyn-5.0.0 → cadwyn-5.1.0}/docs/img/simplified_migration_model.png +0 -0
- {cadwyn-5.0.0 → cadwyn-5.1.0}/docs/img/sponsor_logos/monite.png +0 -0
- {cadwyn-5.0.0 → cadwyn-5.1.0}/docs/img/unversioned_dashboard.png +0 -0
- {cadwyn-5.0.0 → cadwyn-5.1.0}/docs/index.md +0 -0
- {cadwyn-5.0.0 → cadwyn-5.1.0}/docs/plugin.py +0 -0
- {cadwyn-5.0.0 → cadwyn-5.1.0}/docs/quickstart/setup.md +0 -0
- {cadwyn-5.0.0 → cadwyn-5.1.0}/docs/quickstart/tutorial.md +0 -0
- {cadwyn-5.0.0 → cadwyn-5.1.0}/docs/theory/how_to_build_versioning_framework.md +0 -0
- {cadwyn-5.0.0 → cadwyn-5.1.0}/docs/theory/how_we_got_here.md +0 -0
- {cadwyn-5.0.0 → cadwyn-5.1.0}/docs/theory/literature.md +0 -0
- {cadwyn-5.0.0 → cadwyn-5.1.0}/docs_src/__init__.py +0 -0
- {cadwyn-5.0.0 → cadwyn-5.1.0}/docs_src/how_to/__init__.py +0 -0
- {cadwyn-5.0.0 → cadwyn-5.1.0}/docs_src/how_to/change_openapi_schemas/__init__.py +0 -0
- {cadwyn-5.0.0 → cadwyn-5.1.0}/docs_src/how_to/change_openapi_schemas/change_schema_without_endpoint/__init__.py +0 -0
- {cadwyn-5.0.0 → cadwyn-5.1.0}/docs_src/how_to/change_openapi_schemas/change_schema_without_endpoint/block001.py +0 -0
- {cadwyn-5.0.0 → cadwyn-5.1.0}/docs_src/how_to/change_openapi_schemas/change_schema_without_endpoint/block002.py +0 -0
- {cadwyn-5.0.0 → cadwyn-5.1.0}/docs_src/how_to/change_openapi_schemas/change_schema_without_endpoint/tests/__init__.py +0 -0
- {cadwyn-5.0.0 → cadwyn-5.1.0}/docs_src/how_to/change_openapi_schemas/change_schema_without_endpoint/tests/test_block001.py +0 -0
- {cadwyn-5.0.0 → cadwyn-5.1.0}/docs_src/how_to/change_openapi_schemas/change_schema_without_endpoint/tests/test_block002.py +0 -0
- {cadwyn-5.0.0 → cadwyn-5.1.0}/docs_src/how_to/version_with_path_and_numbers_instead_of_headers_and_dates/__init__.py +0 -0
- {cadwyn-5.0.0 → cadwyn-5.1.0}/docs_src/how_to/version_with_path_and_numbers_instead_of_headers_and_dates/block001.py +0 -0
- {cadwyn-5.0.0 → cadwyn-5.1.0}/docs_src/how_to/version_with_path_and_numbers_instead_of_headers_and_dates/tests/__init__.py +0 -0
- {cadwyn-5.0.0 → cadwyn-5.1.0}/docs_src/how_to/version_with_path_and_numbers_instead_of_headers_and_dates/tests/test_block_001.py +0 -0
- {cadwyn-5.0.0 → cadwyn-5.1.0}/docs_src/quickstart/__init__.py +0 -0
- {cadwyn-5.0.0 → cadwyn-5.1.0}/docs_src/quickstart/setup/__init__.py +0 -0
- {cadwyn-5.0.0 → cadwyn-5.1.0}/docs_src/quickstart/setup/block001.sh +0 -0
- {cadwyn-5.0.0 → cadwyn-5.1.0}/docs_src/quickstart/setup/block002.py +0 -0
- {cadwyn-5.0.0 → cadwyn-5.1.0}/docs_src/quickstart/setup/tests/__init__.py +0 -0
- {cadwyn-5.0.0 → cadwyn-5.1.0}/docs_src/quickstart/setup/tests/test_block002.py +0 -0
- {cadwyn-5.0.0 → cadwyn-5.1.0}/docs_src/quickstart/tutorial/__init__.py +0 -0
- {cadwyn-5.0.0 → cadwyn-5.1.0}/docs_src/quickstart/tutorial/block001.py +0 -0
- {cadwyn-5.0.0 → cadwyn-5.1.0}/docs_src/quickstart/tutorial/block002.py +0 -0
- {cadwyn-5.0.0 → cadwyn-5.1.0}/docs_src/quickstart/tutorial/block003.py +0 -0
- {cadwyn-5.0.0 → cadwyn-5.1.0}/docs_src/quickstart/tutorial/tests/__init__.py +0 -0
- {cadwyn-5.0.0 → cadwyn-5.1.0}/docs_src/quickstart/tutorial/tests/test_block001.py +0 -0
- {cadwyn-5.0.0 → cadwyn-5.1.0}/docs_src/quickstart/tutorial/tests/test_block002.py +0 -0
- {cadwyn-5.0.0 → cadwyn-5.1.0}/docs_src/quickstart/tutorial/tests/test_block003.py +0 -0
- {cadwyn-5.0.0 → cadwyn-5.1.0}/docs_src/ruff.toml +0 -0
- {cadwyn-5.0.0 → cadwyn-5.1.0}/mkdocs.yml +0 -0
- {cadwyn-5.0.0 → cadwyn-5.1.0}/scripts/fix_links.py +0 -0
- {cadwyn-5.0.0 → cadwyn-5.1.0}/scripts/split_md.py +0 -0
- {cadwyn-5.0.0 → cadwyn-5.1.0}/tests/__init__.py +0 -0
- {cadwyn-5.0.0 → cadwyn-5.1.0}/tests/_data/__init__.py +0 -0
- {cadwyn-5.0.0 → cadwyn-5.1.0}/tests/_data/unversioned_schema_dir/__init__.py +0 -0
- {cadwyn-5.0.0 → cadwyn-5.1.0}/tests/_data/unversioned_schema_dir/unversioned_schemas.py +0 -0
- {cadwyn-5.0.0 → cadwyn-5.1.0}/tests/_data/unversioned_schemas.py +0 -0
- {cadwyn-5.0.0 → cadwyn-5.1.0}/tests/_resources/__init__.py +0 -0
- {cadwyn-5.0.0 → cadwyn-5.1.0}/tests/_resources/app_for_testing_routing.py +0 -0
- {cadwyn-5.0.0 → cadwyn-5.1.0}/tests/_resources/render/__init__.py +0 -0
- {cadwyn-5.0.0 → cadwyn-5.1.0}/tests/_resources/render/classes.py +0 -0
- {cadwyn-5.0.0 → cadwyn-5.1.0}/tests/_resources/render/complex/__init__.py +0 -0
- {cadwyn-5.0.0 → cadwyn-5.1.0}/tests/_resources/render/versions.py +0 -0
- {cadwyn-5.0.0 → cadwyn-5.1.0}/tests/_resources/utils.py +0 -0
- {cadwyn-5.0.0 → cadwyn-5.1.0}/tests/_resources/versioned_app/__init__.py +0 -0
- {cadwyn-5.0.0 → cadwyn-5.1.0}/tests/_resources/versioned_app/app.py +0 -0
- {cadwyn-5.0.0 → cadwyn-5.1.0}/tests/_resources/versioned_app/v2021_01_01.py +0 -0
- {cadwyn-5.0.0 → cadwyn-5.1.0}/tests/_resources/versioned_app/v2022_01_02.py +0 -0
- {cadwyn-5.0.0 → cadwyn-5.1.0}/tests/_resources/versioned_app/webhooks.py +0 -0
- {cadwyn-5.0.0 → cadwyn-5.1.0}/tests/test_applications.py +0 -0
- {cadwyn-5.0.0 → cadwyn-5.1.0}/tests/test_auth_dependencies.py +0 -0
- {cadwyn-5.0.0 → cadwyn-5.1.0}/tests/test_cli.py +0 -0
- {cadwyn-5.0.0 → cadwyn-5.1.0}/tests/test_router_generation_with_from_future_annotations.py +0 -0
- {cadwyn-5.0.0 → cadwyn-5.1.0}/tests/test_routing.py +0 -0
- {cadwyn-5.0.0 → cadwyn-5.1.0}/tests/test_schema_generation/__init__.py +0 -0
- {cadwyn-5.0.0 → cadwyn-5.1.0}/tests/test_schema_generation/test_enum.py +0 -0
- {cadwyn-5.0.0 → cadwyn-5.1.0}/tests/test_schema_generation/test_schema.py +0 -0
- {cadwyn-5.0.0 → cadwyn-5.1.0}/tests/test_schema_generation/test_schema_validator.py +0 -0
- {cadwyn-5.0.0 → cadwyn-5.1.0}/tests/tutorial/__init__.py +0 -0
- {cadwyn-5.0.0 → cadwyn-5.1.0}/tests/tutorial/main.py +0 -0
- {cadwyn-5.0.0 → cadwyn-5.1.0}/tests/tutorial/test_example.py +0 -0
- {cadwyn-5.0.0 → cadwyn-5.1.0}/tests/versioning_styles/__init__.py +0 -0
- {cadwyn-5.0.0 → cadwyn-5.1.0}/tests/versioning_styles/test_versioning_formats.py +0 -0
|
@@ -22,6 +22,8 @@ jobs:
|
|
|
22
22
|
fail-fast: true
|
|
23
23
|
matrix:
|
|
24
24
|
include:
|
|
25
|
+
- os: ubuntu-latest
|
|
26
|
+
python-version: "3.9"
|
|
25
27
|
- os: ubuntu-latest
|
|
26
28
|
python-version: "3.10"
|
|
27
29
|
- os: ubuntu-latest
|
|
@@ -48,6 +50,7 @@ jobs:
|
|
|
48
50
|
with:
|
|
49
51
|
name: coverage-results-${{ matrix.python-version }}
|
|
50
52
|
path: .coverage*
|
|
53
|
+
include-hidden-files: true
|
|
51
54
|
Tutorial-tests:
|
|
52
55
|
runs-on: ubuntu-latest
|
|
53
56
|
name: Tutorial tests
|
|
@@ -67,6 +70,7 @@ jobs:
|
|
|
67
70
|
with:
|
|
68
71
|
name: coverage-results-docs
|
|
69
72
|
path: .coverage*
|
|
73
|
+
include-hidden-files: true
|
|
70
74
|
Coverage:
|
|
71
75
|
needs: [Tests, Tutorial-tests]
|
|
72
76
|
runs-on: ubuntu-latest
|
|
@@ -80,13 +84,13 @@ jobs:
|
|
|
80
84
|
path: .
|
|
81
85
|
- uses: actions/setup-python@v5
|
|
82
86
|
with:
|
|
83
|
-
python-version: "3.
|
|
87
|
+
python-version: "3.12"
|
|
84
88
|
- run: |
|
|
85
89
|
pip install uv
|
|
86
90
|
uv pip install --system tox tox-uv
|
|
87
|
-
tox run -e coverage_report
|
|
91
|
+
tox run -e coverage_report
|
|
88
92
|
- name: Upload to Codecov
|
|
89
|
-
uses: codecov/codecov-action@
|
|
93
|
+
uses: codecov/codecov-action@v5
|
|
90
94
|
env:
|
|
91
95
|
fail_ci_if_error: true
|
|
92
96
|
CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }}
|
|
@@ -97,7 +101,7 @@ jobs:
|
|
|
97
101
|
- uses: actions/checkout@v4
|
|
98
102
|
- uses: actions/setup-python@v5
|
|
99
103
|
with:
|
|
100
|
-
python-version: "3.
|
|
104
|
+
python-version: "3.12"
|
|
101
105
|
- run: |
|
|
102
106
|
python -m pip install uv
|
|
103
107
|
uv pip install --system pre-commit pre-commit-uv
|
|
@@ -111,7 +115,7 @@ jobs:
|
|
|
111
115
|
with:
|
|
112
116
|
# When this version is updated,
|
|
113
117
|
# update the pyright `base_python` version in `tox.ini`, too.
|
|
114
|
-
python-version: "3.
|
|
118
|
+
python-version: "3.12"
|
|
115
119
|
- run: tox run -e docs
|
|
116
120
|
- name: Validate links
|
|
117
121
|
uses: umbrelladocs/action-linkspector@v1
|
|
@@ -128,5 +132,5 @@ jobs:
|
|
|
128
132
|
with:
|
|
129
133
|
# When this version is updated,
|
|
130
134
|
# update the pyright `base_python` version in `tox.ini`, too.
|
|
131
|
-
python-version: "3.
|
|
135
|
+
python-version: "3.12"
|
|
132
136
|
- run: tox run -e pyright
|
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: cadwyn
|
|
3
|
-
Version: 5.
|
|
3
|
+
Version: 5.1.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
|
|
7
7
|
Author-email: Stanislav Zmiev <zmievsa@gmail.com>
|
|
8
8
|
License-Expression: MIT
|
|
9
9
|
License-File: LICENSE
|
|
10
|
-
Keywords: api,api-versioning,code-generation,fastapi,hints,json-schema,pydantic,python,python310,python311,python312,python313,stripe,versioning
|
|
10
|
+
Keywords: api,api-versioning,code-generation,fastapi,hints,json-schema,pydantic,python,python310,python311,python312,python313,python39,stripe,versioning
|
|
11
11
|
Classifier: Development Status :: 5 - Production/Stable
|
|
12
12
|
Classifier: Environment :: Web Environment
|
|
13
13
|
Classifier: Framework :: AsyncIO
|
|
@@ -20,6 +20,7 @@ Classifier: License :: OSI Approved :: MIT License
|
|
|
20
20
|
Classifier: Operating System :: OS Independent
|
|
21
21
|
Classifier: Programming Language :: Python
|
|
22
22
|
Classifier: Programming Language :: Python :: 3
|
|
23
|
+
Classifier: Programming Language :: Python :: 3.9
|
|
23
24
|
Classifier: Programming Language :: Python :: 3.10
|
|
24
25
|
Classifier: Programming Language :: Python :: 3.11
|
|
25
26
|
Classifier: Programming Language :: Python :: 3.12
|
|
@@ -32,7 +33,7 @@ Classifier: Topic :: Software Development :: Libraries
|
|
|
32
33
|
Classifier: Topic :: Software Development :: Libraries :: Application Frameworks
|
|
33
34
|
Classifier: Topic :: Software Development :: Libraries :: Python Modules
|
|
34
35
|
Classifier: Typing :: Typed
|
|
35
|
-
Requires-Python: >=3.
|
|
36
|
+
Requires-Python: >=3.9
|
|
36
37
|
Requires-Dist: backports-strenum<2,>=1.3.1; python_version < '3.11'
|
|
37
38
|
Requires-Dist: fastapi>=0.112.3
|
|
38
39
|
Requires-Dist: issubclass>=0.1.2
|
|
@@ -2,10 +2,11 @@ import ast
|
|
|
2
2
|
import inspect
|
|
3
3
|
from collections.abc import Callable
|
|
4
4
|
from enum import Enum, auto
|
|
5
|
-
from types import GenericAlias, LambdaType
|
|
5
|
+
from types import GenericAlias, LambdaType
|
|
6
6
|
from typing import ( # noqa: UP035
|
|
7
7
|
Any,
|
|
8
8
|
List,
|
|
9
|
+
Union,
|
|
9
10
|
cast,
|
|
10
11
|
get_args,
|
|
11
12
|
get_origin,
|
|
@@ -17,6 +18,7 @@ from cadwyn._utils import PlainRepr, UnionType
|
|
|
17
18
|
from cadwyn.exceptions import InvalidGenerationInstructionError
|
|
18
19
|
|
|
19
20
|
_LambdaFunctionName = (lambda: None).__name__ # pragma: no branch
|
|
21
|
+
NoneType = type(None)
|
|
20
22
|
|
|
21
23
|
|
|
22
24
|
# A parent type of typing._GenericAlias
|
|
@@ -25,17 +27,18 @@ _BaseGenericAlias = cast(type, type(List[int])).mro()[1] # noqa: UP006
|
|
|
25
27
|
# type(list[int]) and type(List[int]) are different which is why we have to do this.
|
|
26
28
|
# Please note that this problem is much wider than just lists which is why we use typing._BaseGenericAlias
|
|
27
29
|
# instead of typing._GenericAlias.
|
|
28
|
-
GenericAliasUnion = GenericAlias
|
|
30
|
+
GenericAliasUnion = Union[GenericAlias, _BaseGenericAlias]
|
|
31
|
+
GenericAliasUnionArgs = get_args(GenericAliasUnion)
|
|
29
32
|
|
|
30
33
|
|
|
31
34
|
def get_fancy_repr(value: Any) -> Any:
|
|
32
35
|
if isinstance(value, annotated_types.GroupedMetadata) and hasattr(type(value), "__dataclass_fields__"):
|
|
33
36
|
return transform_grouped_metadata(value)
|
|
34
|
-
if isinstance(value, list
|
|
37
|
+
if isinstance(value, (list, tuple, set, frozenset)):
|
|
35
38
|
return transform_collection(value)
|
|
36
39
|
if isinstance(value, dict):
|
|
37
40
|
return transform_dict(value)
|
|
38
|
-
if isinstance(value,
|
|
41
|
+
if isinstance(value, GenericAliasUnionArgs):
|
|
39
42
|
return transform_generic_alias(value)
|
|
40
43
|
if value is None or value is NoneType:
|
|
41
44
|
return transform_none(value)
|
|
@@ -46,7 +49,7 @@ def get_fancy_repr(value: Any) -> Any:
|
|
|
46
49
|
if isinstance(value, auto): # pragma: no cover # it works but we no longer use auto
|
|
47
50
|
return transform_auto(value)
|
|
48
51
|
if isinstance(value, UnionType):
|
|
49
|
-
return transform_union(value)
|
|
52
|
+
return transform_union(value) # pragma: no cover
|
|
50
53
|
if isinstance(value, LambdaType) and _LambdaFunctionName == value.__name__:
|
|
51
54
|
return transform_lambda(value)
|
|
52
55
|
if inspect.isfunction(value):
|
|
@@ -72,7 +75,7 @@ def transform_grouped_metadata(value: "annotated_types.GroupedMetadata"):
|
|
|
72
75
|
)
|
|
73
76
|
|
|
74
77
|
|
|
75
|
-
def transform_collection(value: list
|
|
78
|
+
def transform_collection(value: Union[list, tuple, set, frozenset]) -> Any:
|
|
76
79
|
return PlainRepr(value.__class__(map(get_fancy_repr, value)))
|
|
77
80
|
|
|
78
81
|
|
|
@@ -102,7 +105,7 @@ def transform_auto(_: auto) -> Any: # pragma: no cover # it works but we no lon
|
|
|
102
105
|
return PlainRepr("auto()")
|
|
103
106
|
|
|
104
107
|
|
|
105
|
-
def transform_union(value: UnionType) -> Any:
|
|
108
|
+
def transform_union(value: UnionType) -> Any: # pragma: no cover
|
|
106
109
|
return "typing.Union[" + (", ".join(get_fancy_repr(a) for a in get_args(value))) + "]"
|
|
107
110
|
|
|
108
111
|
|
|
@@ -2,7 +2,7 @@ import ast
|
|
|
2
2
|
import inspect
|
|
3
3
|
import textwrap
|
|
4
4
|
from enum import Enum
|
|
5
|
-
from typing import TYPE_CHECKING
|
|
5
|
+
from typing import TYPE_CHECKING, Union
|
|
6
6
|
|
|
7
7
|
import typer
|
|
8
8
|
from issubclass import issubclass as lenient_issubclass
|
|
@@ -30,7 +30,7 @@ def render_module_by_path(module_path: str, app_path: str, version: str):
|
|
|
30
30
|
attributes_to_alter = [
|
|
31
31
|
name
|
|
32
32
|
for name, value in module.__dict__.items()
|
|
33
|
-
if lenient_issubclass(value, Enum
|
|
33
|
+
if lenient_issubclass(value, (Enum, BaseModel)) and value.__module__ == module.__name__
|
|
34
34
|
]
|
|
35
35
|
|
|
36
36
|
try:
|
|
@@ -53,12 +53,12 @@ def render_module_by_path(module_path: str, app_path: str, version: str):
|
|
|
53
53
|
|
|
54
54
|
def render_model_by_path(model_path: str, app_path: str, version: str) -> str:
|
|
55
55
|
# cadwyn render model schemas:MySchema --app=run:app --version=2000-01-01
|
|
56
|
-
model: type[BaseModel
|
|
56
|
+
model: type[Union[BaseModel, Enum]] = import_attribute_from_string(model_path)
|
|
57
57
|
app: Cadwyn = import_attribute_from_string(app_path)
|
|
58
58
|
return render_model(model, app.versions, version)
|
|
59
59
|
|
|
60
60
|
|
|
61
|
-
def render_model(model: type[BaseModel
|
|
61
|
+
def render_model(model: type[Union[BaseModel, Enum]], versions: VersionBundle, version: str) -> str:
|
|
62
62
|
try:
|
|
63
63
|
original_cls_node = ast.parse(textwrap.dedent(inspect.getsource(model))).body[0]
|
|
64
64
|
except (OSError, SyntaxError, ValueError): # pragma: no cover
|
|
@@ -71,7 +71,7 @@ def render_model(model: type[BaseModel | Enum], versions: VersionBundle, version
|
|
|
71
71
|
|
|
72
72
|
|
|
73
73
|
def _render_model_from_ast(
|
|
74
|
-
model_ast: ast.ClassDef, model: type[BaseModel
|
|
74
|
+
model_ast: ast.ClassDef, model: type[Union[BaseModel, Enum]], versions: VersionBundle, version: str
|
|
75
75
|
):
|
|
76
76
|
versioned_models = generate_versioned_models(versions)
|
|
77
77
|
generator = versioned_models[version]
|
|
@@ -97,7 +97,7 @@ def _render_enum_model(wrapper: _EnumWrapper, original_cls_node: ast.ClassDef):
|
|
|
97
97
|
]
|
|
98
98
|
|
|
99
99
|
old_body = [
|
|
100
|
-
n for n in original_cls_node.body if not isinstance(n, ast.AnnAssign
|
|
100
|
+
n for n in original_cls_node.body if not isinstance(n, (ast.AnnAssign, ast.Assign, ast.Pass, ast.Constant))
|
|
101
101
|
]
|
|
102
102
|
docstring = pop_docstring_from_cls_body(old_body)
|
|
103
103
|
|
|
@@ -130,7 +130,7 @@ def _render_pydantic_model(wrapper: _PydanticModelWrapper, original_cls_node: as
|
|
|
130
130
|
n
|
|
131
131
|
for n in original_cls_node.body
|
|
132
132
|
if not (
|
|
133
|
-
isinstance(n, ast.AnnAssign
|
|
133
|
+
isinstance(n, (ast.AnnAssign, ast.Assign, ast.Pass, ast.Constant))
|
|
134
134
|
or (isinstance(n, ast.FunctionDef) and n.name in wrapper.validators)
|
|
135
135
|
)
|
|
136
136
|
]
|
|
@@ -1,10 +1,11 @@
|
|
|
1
|
+
import sys
|
|
1
2
|
from collections.abc import Callable
|
|
2
3
|
from typing import TYPE_CHECKING, Any, Generic, TypeVar, Union
|
|
3
4
|
|
|
4
5
|
from pydantic._internal._decorators import unwrap_wrapped_function
|
|
5
6
|
|
|
6
7
|
Sentinel: Any = object()
|
|
7
|
-
|
|
8
|
+
|
|
8
9
|
_T = TypeVar("_T", bound=Callable)
|
|
9
10
|
|
|
10
11
|
|
|
@@ -12,6 +13,28 @@ _P_T = TypeVar("_P_T")
|
|
|
12
13
|
_P_R = TypeVar("_P_R")
|
|
13
14
|
|
|
14
15
|
|
|
16
|
+
if sys.version_info >= (3, 10):
|
|
17
|
+
UnionType = type(int | str) | type(Union[int, str])
|
|
18
|
+
DATACLASS_SLOTS: dict[str, Any] = {"slots": True}
|
|
19
|
+
ZIP_STRICT_TRUE: dict[str, Any] = {"strict": True}
|
|
20
|
+
ZIP_STRICT_FALSE: dict[str, Any] = {"strict": False}
|
|
21
|
+
DATACLASS_KW_ONLY: dict[str, Any] = {"kw_only": True}
|
|
22
|
+
else:
|
|
23
|
+
UnionType = type(Union[int, str])
|
|
24
|
+
DATACLASS_SLOTS: dict[str, Any] = {}
|
|
25
|
+
DATACLASS_KW_ONLY: dict[str, Any] = {}
|
|
26
|
+
ZIP_STRICT_TRUE: dict[str, Any] = {}
|
|
27
|
+
ZIP_STRICT_FALSE: dict[str, Any] = {}
|
|
28
|
+
|
|
29
|
+
|
|
30
|
+
def get_name_of_function_wrapped_in_pydantic_validator(func: Any) -> str:
|
|
31
|
+
if hasattr(func, "wrapped"):
|
|
32
|
+
return get_name_of_function_wrapped_in_pydantic_validator(func.wrapped)
|
|
33
|
+
if hasattr(func, "__func__"):
|
|
34
|
+
return get_name_of_function_wrapped_in_pydantic_validator(func.__func__)
|
|
35
|
+
return func.__name__
|
|
36
|
+
|
|
37
|
+
|
|
15
38
|
class classproperty(Generic[_P_T, _P_R]): # noqa: N801
|
|
16
39
|
def __init__(self, func: Callable[[_P_T], _P_R]) -> None:
|
|
17
40
|
super().__init__()
|
|
@@ -49,7 +72,7 @@ if TYPE_CHECKING:
|
|
|
49
72
|
|
|
50
73
|
else:
|
|
51
74
|
|
|
52
|
-
def lenient_issubclass(cls: type, other: T
|
|
75
|
+
def lenient_issubclass(cls: type, other: Union[T, tuple[T, ...]]) -> bool:
|
|
53
76
|
try:
|
|
54
77
|
return issubclass(cls, other)
|
|
55
78
|
except TypeError: # pragma: no cover
|
|
@@ -4,7 +4,7 @@ from collections.abc import Awaitable, Callable, Coroutine, Sequence
|
|
|
4
4
|
from datetime import date
|
|
5
5
|
from logging import getLogger
|
|
6
6
|
from pathlib import Path
|
|
7
|
-
from typing import TYPE_CHECKING, Annotated, Any, cast
|
|
7
|
+
from typing import TYPE_CHECKING, Annotated, Any, Union, cast
|
|
8
8
|
|
|
9
9
|
import fastapi
|
|
10
10
|
from fastapi import APIRouter, FastAPI, HTTPException, routing
|
|
@@ -26,7 +26,7 @@ from starlette.routing import BaseRoute, Route
|
|
|
26
26
|
from starlette.types import Lifespan
|
|
27
27
|
from typing_extensions import Self, assert_never, deprecated
|
|
28
28
|
|
|
29
|
-
from cadwyn._utils import same_definition_as_in
|
|
29
|
+
from cadwyn._utils import DATACLASS_SLOTS, same_definition_as_in
|
|
30
30
|
from cadwyn.changelogs import CadwynChangelogResource, _generate_changelog
|
|
31
31
|
from cadwyn.exceptions import CadwynStructureError
|
|
32
32
|
from cadwyn.middleware import (
|
|
@@ -48,7 +48,7 @@ CURR_DIR = Path(__file__).resolve()
|
|
|
48
48
|
logger = getLogger(__name__)
|
|
49
49
|
|
|
50
50
|
|
|
51
|
-
@dataclasses.dataclass(
|
|
51
|
+
@dataclasses.dataclass(**DATACLASS_SLOTS)
|
|
52
52
|
class FakeDependencyOverridesProvider:
|
|
53
53
|
dependency_overrides: dict[Callable[..., Any], Callable[..., Any]]
|
|
54
54
|
|
|
@@ -61,7 +61,7 @@ class Cadwyn(FastAPI):
|
|
|
61
61
|
*,
|
|
62
62
|
versions: VersionBundle,
|
|
63
63
|
api_version_header_name: Annotated[
|
|
64
|
-
str
|
|
64
|
+
Union[str, None],
|
|
65
65
|
deprecated(
|
|
66
66
|
"api_version_header_name is deprecated and will be removed in the future. "
|
|
67
67
|
"Use api_version_parameter_name instead."
|
|
@@ -70,49 +70,51 @@ class Cadwyn(FastAPI):
|
|
|
70
70
|
api_version_location: APIVersionLocation = "custom_header",
|
|
71
71
|
api_version_format: APIVersionFormat = "date",
|
|
72
72
|
api_version_parameter_name: str = "x-api-version",
|
|
73
|
-
api_version_default_value: str
|
|
73
|
+
api_version_default_value: Union[str, None, Callable[[Request], Awaitable[str]]] = None,
|
|
74
74
|
versioning_middleware_class: type[VersionPickingMiddleware] = VersionPickingMiddleware,
|
|
75
|
-
changelog_url: str
|
|
75
|
+
changelog_url: Union[str, None] = "/changelog",
|
|
76
76
|
include_changelog_url_in_schema: bool = True,
|
|
77
77
|
debug: bool = False,
|
|
78
78
|
title: str = "FastAPI",
|
|
79
|
-
summary: str
|
|
79
|
+
summary: Union[str, None] = None,
|
|
80
80
|
description: str = "",
|
|
81
81
|
version: str = "0.1.0",
|
|
82
|
-
openapi_url: str
|
|
83
|
-
openapi_tags: list[dict[str, Any]]
|
|
84
|
-
servers: list[dict[str, str
|
|
85
|
-
dependencies: Sequence[Depends]
|
|
82
|
+
openapi_url: Union[str, None] = "/openapi.json",
|
|
83
|
+
openapi_tags: Union[list[dict[str, Any]], None] = None,
|
|
84
|
+
servers: Union[list[dict[str, Union[str, Any]]], None] = None,
|
|
85
|
+
dependencies: Union[Sequence[Depends], None] = None,
|
|
86
86
|
default_response_class: type[Response] = JSONResponse,
|
|
87
87
|
redirect_slashes: bool = True,
|
|
88
|
-
routes: list[BaseRoute]
|
|
89
|
-
docs_url: str
|
|
90
|
-
redoc_url: str
|
|
91
|
-
swagger_ui_oauth2_redirect_url: str
|
|
92
|
-
swagger_ui_init_oauth: dict[str, Any]
|
|
93
|
-
middleware: Sequence[Middleware]
|
|
88
|
+
routes: Union[list[BaseRoute], None] = None,
|
|
89
|
+
docs_url: Union[str, None] = "/docs",
|
|
90
|
+
redoc_url: Union[str, None] = "/redoc",
|
|
91
|
+
swagger_ui_oauth2_redirect_url: Union[str, None] = "/docs/oauth2-redirect",
|
|
92
|
+
swagger_ui_init_oauth: Union[dict[str, Any], None] = None,
|
|
93
|
+
middleware: Union[Sequence[Middleware], None] = None,
|
|
94
94
|
exception_handlers: (
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
95
|
+
Union[
|
|
96
|
+
dict[
|
|
97
|
+
Union[int, type[Exception]],
|
|
98
|
+
Callable[[Request, Any], Coroutine[Any, Any, Response]],
|
|
99
|
+
],
|
|
100
|
+
None,
|
|
98
101
|
]
|
|
99
|
-
| None
|
|
100
102
|
) = None,
|
|
101
|
-
on_startup: Sequence[Callable[[], Any]]
|
|
102
|
-
on_shutdown: Sequence[Callable[[], Any]]
|
|
103
|
-
lifespan: Lifespan[Self]
|
|
104
|
-
terms_of_service: str
|
|
105
|
-
contact: dict[str, str
|
|
106
|
-
license_info: dict[str, str
|
|
103
|
+
on_startup: Union[Sequence[Callable[[], Any]], None] = None,
|
|
104
|
+
on_shutdown: Union[Sequence[Callable[[], Any]], None] = None,
|
|
105
|
+
lifespan: Union[Lifespan[Self], None] = None,
|
|
106
|
+
terms_of_service: Union[str, None] = None,
|
|
107
|
+
contact: Union[dict[str, Union[str, Any]], None] = None,
|
|
108
|
+
license_info: Union[dict[str, Union[str, Any]], None] = None,
|
|
107
109
|
openapi_prefix: str = "",
|
|
108
110
|
root_path: str = "",
|
|
109
111
|
root_path_in_servers: bool = True,
|
|
110
|
-
responses: dict[int
|
|
111
|
-
callbacks: list[BaseRoute]
|
|
112
|
-
webhooks: APIRouter
|
|
113
|
-
deprecated: bool
|
|
112
|
+
responses: Union[dict[Union[int, str], dict[str, Any]], None] = None,
|
|
113
|
+
callbacks: Union[list[BaseRoute], None] = None,
|
|
114
|
+
webhooks: Union[APIRouter, None] = None,
|
|
115
|
+
deprecated: Union[bool, None] = None,
|
|
114
116
|
include_in_schema: bool = True,
|
|
115
|
-
swagger_ui_parameters: dict[str, Any]
|
|
117
|
+
swagger_ui_parameters: Union[dict[str, Any], None] = None,
|
|
116
118
|
generate_unique_id_function: Callable[[routing.APIRoute], str] = Default( # noqa: B008
|
|
117
119
|
generate_unique_id
|
|
118
120
|
),
|