cadwyn 4.4.5__tar.gz → 4.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.
- {cadwyn-4.4.5 → cadwyn-4.5.0}/.github/actions/setup-python-uv/action.yaml +3 -3
- {cadwyn-4.4.5 → cadwyn-4.5.0}/.github/workflows/ci.yaml +31 -15
- {cadwyn-4.4.5 → cadwyn-4.5.0}/.github/workflows/daily_tests.yaml +2 -4
- cadwyn-4.5.0/.github/workflows/validate_links.yaml +25 -0
- {cadwyn-4.4.5 → cadwyn-4.5.0}/CHANGELOG.md +6 -0
- cadwyn-4.5.0/Makefile +11 -0
- {cadwyn-4.4.5 → cadwyn-4.5.0}/PKG-INFO +1 -1
- {cadwyn-4.4.5 → cadwyn-4.5.0}/cadwyn/route_generation.py +7 -0
- {cadwyn-4.4.5 → cadwyn-4.5.0}/cadwyn/schema_generation.py +1 -1
- {cadwyn-4.4.5 → cadwyn-4.5.0}/cadwyn/structure/data.py +17 -5
- {cadwyn-4.4.5 → cadwyn-4.5.0}/docs/how_to/change_openapi_schemas/change_field_type.md +0 -1
- cadwyn-4.5.0/docs/how_to/change_openapi_schemas/change_schema_without_endpoint.md +17 -0
- cadwyn-4.5.0/docs_src/how_to/change_openapi_schemas/change_schema_without_endpoint/block001.py +22 -0
- cadwyn-4.5.0/docs_src/how_to/change_openapi_schemas/change_schema_without_endpoint/block002.py +22 -0
- cadwyn-4.5.0/docs_src/how_to/change_openapi_schemas/change_schema_without_endpoint/tests/test_block001.py +15 -0
- cadwyn-4.5.0/docs_src/how_to/change_openapi_schemas/change_schema_without_endpoint/tests/test_block002.py +14 -0
- cadwyn-4.5.0/docs_src/quickstart/tutorial/tests/test_block003.py +36 -0
- {cadwyn-4.4.5 → cadwyn-4.5.0}/mkdocs.yml +1 -0
- {cadwyn-4.4.5 → cadwyn-4.5.0}/pyproject.toml +6 -2
- {cadwyn-4.4.5 → cadwyn-4.5.0}/ruff.toml +3 -0
- cadwyn-4.5.0/tests/_resources/render/complex/__init__.py +0 -0
- cadwyn-4.5.0/tests/_resources/versioned_app/__init__.py +0 -0
- {cadwyn-4.4.5 → cadwyn-4.5.0}/tests/test_cli.py +2 -10
- cadwyn-4.5.0/tests/test_schema_generation/__init__.py +0 -0
- cadwyn-4.5.0/tests/tutorial/__init__.py +0 -0
- cadwyn-4.5.0/tox.ini +61 -0
- {cadwyn-4.4.5 → cadwyn-4.5.0}/uv.lock +332 -301
- cadwyn-4.4.5/.github/workflows/validate_links.yaml +0 -41
- cadwyn-4.4.5/Makefile +0 -14
- cadwyn-4.4.5/docs_src/quickstart/tutorial/tests/test_block003.py +0 -21
- {cadwyn-4.4.5 → cadwyn-4.5.0}/.github/CODE_OF_CONDUCT.md +0 -0
- {cadwyn-4.4.5 → cadwyn-4.5.0}/.github/ISSUE_TEMPLATE/bug_report.md +0 -0
- {cadwyn-4.4.5 → cadwyn-4.5.0}/.github/ISSUE_TEMPLATE/feature_request.md +0 -0
- {cadwyn-4.4.5 → cadwyn-4.5.0}/.github/workflows/publish_docs.yaml +0 -0
- {cadwyn-4.4.5 → cadwyn-4.5.0}/.github/workflows/release.yaml +0 -0
- {cadwyn-4.4.5 → cadwyn-4.5.0}/.gitignore +0 -0
- {cadwyn-4.4.5 → cadwyn-4.5.0}/.pre-commit-config.yaml +0 -0
- {cadwyn-4.4.5 → cadwyn-4.5.0}/LICENSE +0 -0
- {cadwyn-4.4.5 → cadwyn-4.5.0}/README.md +0 -0
- {cadwyn-4.4.5 → cadwyn-4.5.0}/cadwyn/__init__.py +0 -0
- {cadwyn-4.4.5 → cadwyn-4.5.0}/cadwyn/__main__.py +0 -0
- {cadwyn-4.4.5 → cadwyn-4.5.0}/cadwyn/_asts.py +0 -0
- {cadwyn-4.4.5 → cadwyn-4.5.0}/cadwyn/_importer.py +0 -0
- {cadwyn-4.4.5 → cadwyn-4.5.0}/cadwyn/_render.py +0 -0
- {cadwyn-4.4.5 → cadwyn-4.5.0}/cadwyn/_utils.py +0 -0
- {cadwyn-4.4.5 → cadwyn-4.5.0}/cadwyn/applications.py +0 -0
- {cadwyn-4.4.5 → cadwyn-4.5.0}/cadwyn/changelogs.py +0 -0
- {cadwyn-4.4.5 → cadwyn-4.5.0}/cadwyn/exceptions.py +0 -0
- {cadwyn-4.4.5 → cadwyn-4.5.0}/cadwyn/middleware.py +0 -0
- {cadwyn-4.4.5 → cadwyn-4.5.0}/cadwyn/py.typed +0 -0
- {cadwyn-4.4.5 → cadwyn-4.5.0}/cadwyn/routing.py +0 -0
- {cadwyn-4.4.5 → cadwyn-4.5.0}/cadwyn/static/__init__.py +0 -0
- {cadwyn-4.4.5 → cadwyn-4.5.0}/cadwyn/static/docs.html +0 -0
- {cadwyn-4.4.5 → cadwyn-4.5.0}/cadwyn/structure/__init__.py +0 -0
- {cadwyn-4.4.5 → cadwyn-4.5.0}/cadwyn/structure/common.py +0 -0
- {cadwyn-4.4.5 → cadwyn-4.5.0}/cadwyn/structure/endpoints.py +0 -0
- {cadwyn-4.4.5 → cadwyn-4.5.0}/cadwyn/structure/enums.py +0 -0
- {cadwyn-4.4.5 → cadwyn-4.5.0}/cadwyn/structure/schemas.py +0 -0
- {cadwyn-4.4.5 → cadwyn-4.5.0}/cadwyn/structure/versions.py +0 -0
- {cadwyn-4.4.5 → cadwyn-4.5.0}/docs/CNAME +0 -0
- {cadwyn-4.4.5 → cadwyn-4.5.0}/docs/__init__.py +0 -0
- {cadwyn-4.4.5 → cadwyn-4.5.0}/docs/concepts/api_version_header_and_context_variables.md +0 -0
- {cadwyn-4.4.5 → cadwyn-4.5.0}/docs/concepts/beware_of_data_versioning.md +0 -0
- {cadwyn-4.4.5 → cadwyn-4.5.0}/docs/concepts/changelogs.md +0 -0
- {cadwyn-4.4.5 → cadwyn-4.5.0}/docs/concepts/cli.md +0 -0
- {cadwyn-4.4.5 → cadwyn-4.5.0}/docs/concepts/endpoint_migrations.md +0 -0
- {cadwyn-4.4.5 → cadwyn-4.5.0}/docs/concepts/enum_migrations.md +0 -0
- {cadwyn-4.4.5 → cadwyn-4.5.0}/docs/concepts/index.md +0 -0
- {cadwyn-4.4.5 → cadwyn-4.5.0}/docs/concepts/main_app.md +0 -0
- {cadwyn-4.4.5 → cadwyn-4.5.0}/docs/concepts/methodology.md +0 -0
- {cadwyn-4.4.5 → cadwyn-4.5.0}/docs/concepts/schema_generation.md +0 -0
- {cadwyn-4.4.5 → cadwyn-4.5.0}/docs/concepts/schema_migrations.md +0 -0
- {cadwyn-4.4.5 → cadwyn-4.5.0}/docs/concepts/testing.md +0 -0
- {cadwyn-4.4.5 → cadwyn-4.5.0}/docs/concepts/version_changes.md +0 -0
- {cadwyn-4.4.5 → cadwyn-4.5.0}/docs/home/CONTRIBUTING.md +0 -0
- {cadwyn-4.4.5 → cadwyn-4.5.0}/docs/how_to/change_business_logic/index.md +0 -0
- {cadwyn-4.4.5 → cadwyn-4.5.0}/docs/how_to/change_endpoints/index.md +0 -0
- {cadwyn-4.4.5 → cadwyn-4.5.0}/docs/how_to/change_openapi_schemas/add_field.md +0 -0
- {cadwyn-4.4.5 → cadwyn-4.5.0}/docs/how_to/change_openapi_schemas/changing_constraints.md +0 -0
- {cadwyn-4.4.5 → cadwyn-4.5.0}/docs/how_to/change_openapi_schemas/remove_field.md +0 -0
- {cadwyn-4.4.5 → cadwyn-4.5.0}/docs/how_to/change_openapi_schemas/rename_a_field_in_schema.md +0 -0
- {cadwyn-4.4.5 → cadwyn-4.5.0}/docs/how_to/index.md +0 -0
- {cadwyn-4.4.5 → cadwyn-4.5.0}/docs/img/dashboard_with_one_version.png +0 -0
- {cadwyn-4.4.5 → cadwyn-4.5.0}/docs/img/dashboard_with_two_versions.png +0 -0
- {cadwyn-4.4.5 → cadwyn-4.5.0}/docs/img/get_users_endpoint_from_prior_version.png +0 -0
- {cadwyn-4.4.5 → cadwyn-4.5.0}/docs/img/simplified_migration_model.png +0 -0
- {cadwyn-4.4.5 → cadwyn-4.5.0}/docs/img/sponsor_logos/monite.png +0 -0
- {cadwyn-4.4.5 → cadwyn-4.5.0}/docs/img/unversioned_dashboard.png +0 -0
- {cadwyn-4.4.5 → cadwyn-4.5.0}/docs/index.md +0 -0
- {cadwyn-4.4.5 → cadwyn-4.5.0}/docs/plugin.py +0 -0
- {cadwyn-4.4.5 → cadwyn-4.5.0}/docs/quickstart/setup.md +0 -0
- {cadwyn-4.4.5 → cadwyn-4.5.0}/docs/quickstart/tutorial.md +0 -0
- {cadwyn-4.4.5 → cadwyn-4.5.0}/docs/theory/how_to_build_versioning_framework.md +0 -0
- {cadwyn-4.4.5 → cadwyn-4.5.0}/docs/theory/how_we_got_here.md +0 -0
- {cadwyn-4.4.5 → cadwyn-4.5.0}/docs/theory/literature.md +0 -0
- {cadwyn-4.4.5 → cadwyn-4.5.0}/docs_src/__init__.py +0 -0
- {cadwyn-4.4.5/docs_src/quickstart → cadwyn-4.5.0/docs_src/how_to}/__init__.py +0 -0
- {cadwyn-4.4.5/docs_src/quickstart/setup → cadwyn-4.5.0/docs_src/how_to/change_openapi_schemas}/__init__.py +0 -0
- {cadwyn-4.4.5/docs_src/quickstart/setup/tests → cadwyn-4.5.0/docs_src/how_to/change_openapi_schemas/change_schema_without_endpoint}/__init__.py +0 -0
- {cadwyn-4.4.5/docs_src/quickstart/tutorial → cadwyn-4.5.0/docs_src/how_to/change_openapi_schemas/change_schema_without_endpoint/tests}/__init__.py +0 -0
- {cadwyn-4.4.5/docs_src/quickstart/tutorial/tests → cadwyn-4.5.0/docs_src/quickstart}/__init__.py +0 -0
- {cadwyn-4.4.5/tests/_data → cadwyn-4.5.0/docs_src/quickstart/setup}/__init__.py +0 -0
- {cadwyn-4.4.5 → cadwyn-4.5.0}/docs_src/quickstart/setup/block001.sh +0 -0
- {cadwyn-4.4.5 → cadwyn-4.5.0}/docs_src/quickstart/setup/block002.py +0 -0
- {cadwyn-4.4.5/tests/_resources → cadwyn-4.5.0/docs_src/quickstart/setup/tests}/__init__.py +0 -0
- {cadwyn-4.4.5 → cadwyn-4.5.0}/docs_src/quickstart/setup/tests/test_block002.py +0 -0
- {cadwyn-4.4.5/tests/_resources/render → cadwyn-4.5.0/docs_src/quickstart/tutorial}/__init__.py +0 -0
- {cadwyn-4.4.5 → cadwyn-4.5.0}/docs_src/quickstart/tutorial/block001.py +0 -0
- {cadwyn-4.4.5 → cadwyn-4.5.0}/docs_src/quickstart/tutorial/block002.py +0 -0
- {cadwyn-4.4.5 → cadwyn-4.5.0}/docs_src/quickstart/tutorial/block003.py +0 -0
- {cadwyn-4.4.5/tests/_resources/render/complex → cadwyn-4.5.0/docs_src/quickstart/tutorial/tests}/__init__.py +0 -0
- {cadwyn-4.4.5 → cadwyn-4.5.0}/docs_src/quickstart/tutorial/tests/test_block001.py +0 -0
- {cadwyn-4.4.5 → cadwyn-4.5.0}/docs_src/quickstart/tutorial/tests/test_block002.py +0 -0
- {cadwyn-4.4.5 → cadwyn-4.5.0}/scripts/fix_links.py +0 -0
- {cadwyn-4.4.5 → cadwyn-4.5.0}/scripts/split_md.py +0 -0
- {cadwyn-4.4.5 → cadwyn-4.5.0}/tests/__init__.py +0 -0
- {cadwyn-4.4.5/tests/_resources/versioned_app → cadwyn-4.5.0/tests/_data}/__init__.py +0 -0
- {cadwyn-4.4.5 → cadwyn-4.5.0}/tests/_data/unversioned_schema_dir/__init__.py +0 -0
- {cadwyn-4.4.5 → cadwyn-4.5.0}/tests/_data/unversioned_schema_dir/unversioned_schemas.py +0 -0
- {cadwyn-4.4.5 → cadwyn-4.5.0}/tests/_data/unversioned_schemas.py +0 -0
- {cadwyn-4.4.5/tests/test_schema_generation → cadwyn-4.5.0/tests/_resources}/__init__.py +0 -0
- {cadwyn-4.4.5 → cadwyn-4.5.0}/tests/_resources/app_for_testing_routing.py +0 -0
- {cadwyn-4.4.5/tests/tutorial → cadwyn-4.5.0/tests/_resources/render}/__init__.py +0 -0
- {cadwyn-4.4.5 → cadwyn-4.5.0}/tests/_resources/render/classes.py +0 -0
- {cadwyn-4.4.5 → cadwyn-4.5.0}/tests/_resources/render/complex/classes.py +0 -0
- {cadwyn-4.4.5 → cadwyn-4.5.0}/tests/_resources/render/complex/versions.py +0 -0
- {cadwyn-4.4.5 → cadwyn-4.5.0}/tests/_resources/render/versions.py +0 -0
- {cadwyn-4.4.5 → cadwyn-4.5.0}/tests/_resources/utils.py +0 -0
- {cadwyn-4.4.5 → cadwyn-4.5.0}/tests/_resources/versioned_app/app.py +0 -0
- {cadwyn-4.4.5 → cadwyn-4.5.0}/tests/_resources/versioned_app/v2021_01_01.py +0 -0
- {cadwyn-4.4.5 → cadwyn-4.5.0}/tests/_resources/versioned_app/v2022_01_02.py +0 -0
- {cadwyn-4.4.5 → cadwyn-4.5.0}/tests/_resources/versioned_app/webhooks.py +0 -0
- {cadwyn-4.4.5 → cadwyn-4.5.0}/tests/conftest.py +0 -0
- {cadwyn-4.4.5 → cadwyn-4.5.0}/tests/test_applications.py +0 -0
- {cadwyn-4.4.5 → cadwyn-4.5.0}/tests/test_auth_dependencies.py +0 -0
- {cadwyn-4.4.5 → cadwyn-4.5.0}/tests/test_changelog.py +0 -0
- {cadwyn-4.4.5 → cadwyn-4.5.0}/tests/test_data_migrations.py +0 -0
- {cadwyn-4.4.5 → cadwyn-4.5.0}/tests/test_render.py +0 -0
- {cadwyn-4.4.5 → cadwyn-4.5.0}/tests/test_router_generation.py +0 -0
- {cadwyn-4.4.5 → cadwyn-4.5.0}/tests/test_routing.py +0 -0
- {cadwyn-4.4.5 → cadwyn-4.5.0}/tests/test_schema_generation/test_enum.py +0 -0
- {cadwyn-4.4.5 → cadwyn-4.5.0}/tests/test_schema_generation/test_schema.py +0 -0
- {cadwyn-4.4.5 → cadwyn-4.5.0}/tests/test_schema_generation/test_schema_field.py +0 -0
- {cadwyn-4.4.5 → cadwyn-4.5.0}/tests/test_schema_generation/test_schema_validator.py +0 -0
- {cadwyn-4.4.5 → cadwyn-4.5.0}/tests/test_structure.py +0 -0
- {cadwyn-4.4.5 → cadwyn-4.5.0}/tests/tutorial/main.py +0 -0
- {cadwyn-4.4.5 → cadwyn-4.5.0}/tests/tutorial/test_example.py +0 -0
|
@@ -8,7 +8,7 @@ inputs:
|
|
|
8
8
|
uv-version:
|
|
9
9
|
description: "The uv version to set up"
|
|
10
10
|
required: true
|
|
11
|
-
default: "0.
|
|
11
|
+
default: "0.5.8"
|
|
12
12
|
|
|
13
13
|
runs:
|
|
14
14
|
using: "composite"
|
|
@@ -16,12 +16,12 @@ runs:
|
|
|
16
16
|
- uses: actions/setup-python@v5
|
|
17
17
|
with:
|
|
18
18
|
python-version: ${{ inputs.python-version }}
|
|
19
|
-
- uses: astral-sh/setup-uv@
|
|
19
|
+
- uses: astral-sh/setup-uv@v5
|
|
20
20
|
with:
|
|
21
21
|
version: ${{ inputs.uv-version }}
|
|
22
22
|
enable-cache: true
|
|
23
23
|
cache-dependency-glob: "uv.lock"
|
|
24
24
|
- run: |
|
|
25
25
|
uv sync --frozen --all-extras --dev
|
|
26
|
-
|
|
26
|
+
uv pip install --system tox tox-uv
|
|
27
27
|
shell: bash
|
|
@@ -10,7 +10,7 @@ on:
|
|
|
10
10
|
branches: [main, 3.x.x]
|
|
11
11
|
types: [opened, synchronize]
|
|
12
12
|
paths:
|
|
13
|
-
- ".github/workflows/ci.yaml"
|
|
13
|
+
- ".github/workflows/ci.yaml" # self
|
|
14
14
|
- "**.py"
|
|
15
15
|
- "**.toml"
|
|
16
16
|
- "**.lock"
|
|
@@ -41,13 +41,13 @@ jobs:
|
|
|
41
41
|
- uses: ./.github/actions/setup-python-uv
|
|
42
42
|
with:
|
|
43
43
|
python-version: ${{ matrix.python-version }}
|
|
44
|
-
- run:
|
|
44
|
+
- run: tox run -e py
|
|
45
45
|
- name: Upload coverage results
|
|
46
46
|
uses: actions/upload-artifact@v4
|
|
47
47
|
if: matrix.os == 'ubuntu-latest' # Cross-platform coverage combination doesn't work
|
|
48
48
|
with:
|
|
49
49
|
name: coverage-results-${{ matrix.python-version }}
|
|
50
|
-
path: coverage
|
|
50
|
+
path: .coverage*
|
|
51
51
|
Tutorial-tests:
|
|
52
52
|
runs-on: ubuntu-latest
|
|
53
53
|
name: Tutorial tests
|
|
@@ -58,13 +58,15 @@ jobs:
|
|
|
58
58
|
python-version: "3.10"
|
|
59
59
|
- name: Install cadwyn with instructions from docs
|
|
60
60
|
run: sh docs_src/quickstart/setup/block001.sh
|
|
61
|
-
- run:
|
|
62
|
-
|
|
61
|
+
- run: |
|
|
62
|
+
pip install uv
|
|
63
|
+
uv pip install --system pytest coverage dirty-equals
|
|
64
|
+
coverage run -m pytest docs_src
|
|
63
65
|
- name: Upload coverage results
|
|
64
66
|
uses: actions/upload-artifact@v4
|
|
65
67
|
with:
|
|
66
68
|
name: coverage-results-docs
|
|
67
|
-
path: coverage
|
|
69
|
+
path: .coverage*
|
|
68
70
|
Coverage:
|
|
69
71
|
needs: [Tests, Tutorial-tests]
|
|
70
72
|
runs-on: ubuntu-latest
|
|
@@ -75,32 +77,46 @@ jobs:
|
|
|
75
77
|
with:
|
|
76
78
|
pattern: coverage-results-*
|
|
77
79
|
merge-multiple: true
|
|
78
|
-
path:
|
|
80
|
+
path: .
|
|
79
81
|
- uses: actions/setup-python@v5
|
|
80
82
|
with:
|
|
81
83
|
python-version: "3.10"
|
|
82
|
-
- run:
|
|
83
|
-
|
|
84
|
-
|
|
84
|
+
- run: |
|
|
85
|
+
pip install uv
|
|
86
|
+
uv pip install --system tox tox-uv
|
|
87
|
+
tox run -e coverage_report-ci
|
|
85
88
|
- name: Upload to Codecov
|
|
86
89
|
uses: codecov/codecov-action@v4
|
|
87
90
|
env:
|
|
88
91
|
fail_ci_if_error: true
|
|
89
92
|
CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }}
|
|
90
|
-
- run: coverage report --fail-under=100 --show-missing
|
|
91
93
|
|
|
92
94
|
Lint:
|
|
93
95
|
runs-on: ubuntu-latest
|
|
94
96
|
steps:
|
|
95
97
|
- uses: actions/checkout@v4
|
|
96
|
-
- uses:
|
|
98
|
+
- uses: actions/setup-python@v5
|
|
99
|
+
with:
|
|
100
|
+
python-version: "3.10"
|
|
101
|
+
- run: |
|
|
102
|
+
python -m pip install uv
|
|
103
|
+
uv pip install --system pre-commit pre-commit-uv
|
|
104
|
+
pre-commit run --all-files
|
|
105
|
+
- run: tox run -e docs
|
|
106
|
+
- name: Validate links
|
|
107
|
+
uses: umbrelladocs/action-linkspector@v1
|
|
108
|
+
with:
|
|
109
|
+
reporter: github-pr-review
|
|
110
|
+
filter_mode: diff_context
|
|
111
|
+
fail_level: any
|
|
97
112
|
|
|
98
113
|
Typecheck:
|
|
99
114
|
runs-on: ubuntu-latest
|
|
100
115
|
steps:
|
|
101
116
|
- uses: actions/checkout@v4
|
|
102
117
|
- uses: ./.github/actions/setup-python-uv
|
|
103
|
-
|
|
104
|
-
- uses: jakebailey/pyright-action@v1
|
|
105
118
|
with:
|
|
106
|
-
|
|
119
|
+
# When this version is updated,
|
|
120
|
+
# update the pyright `base_python` version in `tox.ini`, too.
|
|
121
|
+
python-version: "3.10"
|
|
122
|
+
- run: tox run -e pyright
|
|
@@ -21,10 +21,8 @@ jobs:
|
|
|
21
21
|
with:
|
|
22
22
|
python-version: ${{ matrix.python-version }}
|
|
23
23
|
- run: uv sync --refresh --all-extras --dev --upgrade
|
|
24
|
-
- run: pytest .
|
|
25
|
-
-
|
|
26
|
-
with:
|
|
27
|
-
pylance-version: latest-release
|
|
24
|
+
- run: uv run pytest . # We intentionally don't use tox here to run tests "as is"
|
|
25
|
+
- run: uv run pyright --version && uv run pyright .
|
|
28
26
|
|
|
29
27
|
notify-on-failure:
|
|
30
28
|
name: Notify on failure
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
name: Check Markdown links
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
schedule:
|
|
5
|
+
# Run everyday at 9:00 AM
|
|
6
|
+
- cron: "0 9 * * *"
|
|
7
|
+
workflow_dispatch: # Allows manual triggering of the workflow
|
|
8
|
+
|
|
9
|
+
jobs:
|
|
10
|
+
build-docs-to-validate-links:
|
|
11
|
+
runs-on: ubuntu-latest
|
|
12
|
+
steps:
|
|
13
|
+
- uses: actions/checkout@v4
|
|
14
|
+
- uses: ./.github/actions/setup-python-uv
|
|
15
|
+
- run: tox run -e docs
|
|
16
|
+
|
|
17
|
+
markdown-link-check:
|
|
18
|
+
runs-on: ubuntu-latest
|
|
19
|
+
steps:
|
|
20
|
+
- uses: actions/checkout@v4
|
|
21
|
+
- uses: umbrelladocs/action-linkspector@v1
|
|
22
|
+
with:
|
|
23
|
+
reporter: github-check
|
|
24
|
+
filter_mode: nofilter
|
|
25
|
+
fail_level: any
|
|
@@ -5,6 +5,12 @@ Please follow [the Keep a Changelog standard](https://keepachangelog.com/en/1.0.
|
|
|
5
5
|
|
|
6
6
|
## [Unreleased]
|
|
7
7
|
|
|
8
|
+
## [4.5.0]
|
|
9
|
+
|
|
10
|
+
### Added
|
|
11
|
+
|
|
12
|
+
* `check_usage` argument 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. Setting `check_usage=False` makes it possible to skip the validation
|
|
13
|
+
|
|
8
14
|
## [4.4.5]
|
|
9
15
|
|
|
10
16
|
### Fixed
|
cadwyn-4.5.0/Makefile
ADDED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: cadwyn
|
|
3
|
-
Version: 4.
|
|
3
|
+
Version: 4.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
|
|
@@ -221,6 +221,8 @@ class _EndpointTransformer(Generic[_R, _WR]):
|
|
|
221
221
|
|
|
222
222
|
for by_schema_converters in version_change.alter_request_by_schema_instructions.values():
|
|
223
223
|
for by_schema_converter in by_schema_converters:
|
|
224
|
+
if not by_schema_converter.check_usage: # pragma: no cover
|
|
225
|
+
continue
|
|
224
226
|
missing_models = set(by_schema_converter.schemas) - head_request_bodies
|
|
225
227
|
if missing_models:
|
|
226
228
|
raise RouteRequestBySchemaConverterDoesNotApplyToAnythingError(
|
|
@@ -232,6 +234,8 @@ class _EndpointTransformer(Generic[_R, _WR]):
|
|
|
232
234
|
)
|
|
233
235
|
for by_schema_converters in version_change.alter_response_by_schema_instructions.values():
|
|
234
236
|
for by_schema_converter in by_schema_converters:
|
|
237
|
+
if not by_schema_converter.check_usage: # pragma: no cover
|
|
238
|
+
continue
|
|
235
239
|
missing_models = set(by_schema_converter.schemas) - head_response_models
|
|
236
240
|
if missing_models:
|
|
237
241
|
raise RouteResponseBySchemaConverterDoesNotApplyToAnythingError(
|
|
@@ -240,6 +244,9 @@ class _EndpointTransformer(Generic[_R, _WR]):
|
|
|
240
244
|
f"failed to find routes with the following response models: "
|
|
241
245
|
f"{[m.__name__ for m in missing_models]}. "
|
|
242
246
|
f"This means that you are trying to apply this converter to non-existing endpoint(s). "
|
|
247
|
+
"If this is intentional and this converter really does not apply to any endpoints, then "
|
|
248
|
+
"pass check_usage=False argument to "
|
|
249
|
+
f"{version_change.__name__}.{by_schema_converter.transformer.__name__}"
|
|
243
250
|
)
|
|
244
251
|
|
|
245
252
|
def _extract_all_routes_identifiers(
|
|
@@ -86,6 +86,12 @@ class _AlterDataInstruction:
|
|
|
86
86
|
return self.transformer(__request_or_response)
|
|
87
87
|
|
|
88
88
|
|
|
89
|
+
@dataclass
|
|
90
|
+
class _BaseAlterBySchemaInstruction:
|
|
91
|
+
schemas: tuple[Any, ...]
|
|
92
|
+
check_usage: bool = True
|
|
93
|
+
|
|
94
|
+
|
|
89
95
|
##########
|
|
90
96
|
# Requests
|
|
91
97
|
##########
|
|
@@ -97,8 +103,7 @@ class _BaseAlterRequestInstruction(_AlterDataInstruction):
|
|
|
97
103
|
|
|
98
104
|
|
|
99
105
|
@dataclass
|
|
100
|
-
class _AlterRequestBySchemaInstruction(_BaseAlterRequestInstruction):
|
|
101
|
-
schemas: tuple[Any, ...]
|
|
106
|
+
class _AlterRequestBySchemaInstruction(_BaseAlterBySchemaInstruction, _BaseAlterRequestInstruction): ...
|
|
102
107
|
|
|
103
108
|
|
|
104
109
|
@dataclass
|
|
@@ -110,7 +115,10 @@ class _AlterRequestByPathInstruction(_BaseAlterRequestInstruction):
|
|
|
110
115
|
|
|
111
116
|
@overload
|
|
112
117
|
def convert_request_to_next_version_for(
|
|
113
|
-
first_schema: type,
|
|
118
|
+
first_schema: type,
|
|
119
|
+
/,
|
|
120
|
+
*additional_schemas: type,
|
|
121
|
+
check_usage: bool = True,
|
|
114
122
|
) -> "type[staticmethod[_P, None]]": ...
|
|
115
123
|
|
|
116
124
|
|
|
@@ -123,6 +131,7 @@ def convert_request_to_next_version_for(
|
|
|
123
131
|
methods_or_second_schema: list[str] | None | type = None,
|
|
124
132
|
/,
|
|
125
133
|
*additional_schemas: type,
|
|
134
|
+
check_usage: bool = True,
|
|
126
135
|
) -> "type[staticmethod[_P, None]]":
|
|
127
136
|
_validate_decorator_args(schema_or_path, methods_or_second_schema, additional_schemas)
|
|
128
137
|
|
|
@@ -141,6 +150,7 @@ def convert_request_to_next_version_for(
|
|
|
141
150
|
return _AlterRequestBySchemaInstruction(
|
|
142
151
|
schemas=schemas,
|
|
143
152
|
transformer=transformer,
|
|
153
|
+
check_usage=check_usage,
|
|
144
154
|
)
|
|
145
155
|
|
|
146
156
|
return decorator # pyright: ignore[reportReturnType]
|
|
@@ -158,8 +168,7 @@ class _BaseAlterResponseInstruction(_AlterDataInstruction):
|
|
|
158
168
|
|
|
159
169
|
|
|
160
170
|
@dataclass
|
|
161
|
-
class _AlterResponseBySchemaInstruction(_BaseAlterResponseInstruction):
|
|
162
|
-
schemas: tuple[Any, ...]
|
|
171
|
+
class _AlterResponseBySchemaInstruction(_BaseAlterBySchemaInstruction, _BaseAlterResponseInstruction): ...
|
|
163
172
|
|
|
164
173
|
|
|
165
174
|
@dataclass
|
|
@@ -175,6 +184,7 @@ def convert_response_to_previous_version_for(
|
|
|
175
184
|
/,
|
|
176
185
|
*schemas: type,
|
|
177
186
|
migrate_http_errors: bool = False,
|
|
187
|
+
check_usage: bool = True,
|
|
178
188
|
) -> "type[staticmethod[_P, None]]": ...
|
|
179
189
|
|
|
180
190
|
|
|
@@ -194,6 +204,7 @@ def convert_response_to_previous_version_for(
|
|
|
194
204
|
/,
|
|
195
205
|
*additional_schemas: type,
|
|
196
206
|
migrate_http_errors: bool = False,
|
|
207
|
+
check_usage: bool = True,
|
|
197
208
|
) -> "type[staticmethod[_P, None]]":
|
|
198
209
|
_validate_decorator_args(schema_or_path, methods_or_second_schema, additional_schemas)
|
|
199
210
|
|
|
@@ -215,6 +226,7 @@ def convert_response_to_previous_version_for(
|
|
|
215
226
|
schemas=schemas,
|
|
216
227
|
transformer=transformer,
|
|
217
228
|
migrate_http_errors=migrate_http_errors,
|
|
229
|
+
check_usage=check_usage,
|
|
218
230
|
)
|
|
219
231
|
|
|
220
232
|
return decorator # pyright: ignore[reportReturnType]
|
|
@@ -58,7 +58,6 @@ Additional resources:
|
|
|
58
58
|
* <https://github.com/OAI/OpenAPI-Specification/issues/1552>
|
|
59
59
|
* <https://users.rust-lang.org/t/solved-is-adding-an-enum-variant-a-breaking-change/26721/5>
|
|
60
60
|
* <https://github.com/graphql/graphql-js/issues/968>
|
|
61
|
-
* <https://medium.com/@jakob.fiegerl/java-jackson-enum-de-serialization-with-rest-backward-compatibility-9c3ec85ac13d>
|
|
62
61
|
|
|
63
62
|
In these sections, we'll be working with our user's response model: `users.UserResource`. Note that the main theme here is "Will I be able to serialize this change to any of my versions?" as any change to responses can make them incompatible with the data in your database.
|
|
64
63
|
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
# Change a schema that is not used in any endpoint
|
|
2
|
+
|
|
3
|
+
In some situations, we may want to use versioning not just for our openapi schemas and endpoints but also within our code such as when we want to send versioned webhooks to our clients.
|
|
4
|
+
|
|
5
|
+
For example, let's say we want to change the type of an "id" field from integer to string:
|
|
6
|
+
|
|
7
|
+
```python
|
|
8
|
+
{!> ../docs_src/how_to/change_openapi_schemas/change_schema_without_endpoint/block001.py !}
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
Unless there is an endpoint that has `User` as its response_model, this code will end up causing an error when we run our Cadwyn app. This is because Cadwyn tries to make sure that all of your converters apply to at least one endpoint. Otherwise, it would be too easy for you to make a mistake when writing converters for the wrong schemas.
|
|
12
|
+
|
|
13
|
+
To avoid it, set `check_usage=False`:
|
|
14
|
+
|
|
15
|
+
```python hl_lines="21"
|
|
16
|
+
{!> ../docs_src/how_to/change_openapi_schemas/change_schema_without_endpoint/block002.py !}
|
|
17
|
+
```
|
cadwyn-4.5.0/docs_src/how_to/change_openapi_schemas/change_schema_without_endpoint/block001.py
ADDED
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
from pydantic import BaseModel
|
|
2
|
+
|
|
3
|
+
from cadwyn import ResponseInfo, VersionChange, convert_response_to_previous_version_for, schema
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
# User from latest version
|
|
7
|
+
class User(BaseModel):
|
|
8
|
+
id: str
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
class ChangeUserIDToString(VersionChange):
|
|
12
|
+
description = (
|
|
13
|
+
"Change users' ID field to a string to support any kind of ID. "
|
|
14
|
+
"Be careful: if you use a non-integer ID in a new version and "
|
|
15
|
+
"try to get it from the old version, the ID will be zero in response"
|
|
16
|
+
)
|
|
17
|
+
instructions_to_migrate_to_previous_version = [
|
|
18
|
+
schema(User).field("id").had(type=int),
|
|
19
|
+
]
|
|
20
|
+
|
|
21
|
+
@convert_response_to_previous_version_for(User)
|
|
22
|
+
def change_id_to_int(response: ResponseInfo): ...
|
cadwyn-4.5.0/docs_src/how_to/change_openapi_schemas/change_schema_without_endpoint/block002.py
ADDED
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
from pydantic import BaseModel
|
|
2
|
+
|
|
3
|
+
from cadwyn import ResponseInfo, VersionChange, convert_response_to_previous_version_for, schema
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
# User from latest version
|
|
7
|
+
class User(BaseModel):
|
|
8
|
+
id: str
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
class ChangeUserIDToString(VersionChange):
|
|
12
|
+
description = (
|
|
13
|
+
"Change users' ID field to a string to support any kind of ID. "
|
|
14
|
+
"Be careful: if you use a non-integer ID in a new version and "
|
|
15
|
+
"try to get it from the old version, the ID will be zero in response"
|
|
16
|
+
)
|
|
17
|
+
instructions_to_migrate_to_previous_version = [
|
|
18
|
+
schema(User).field("id").had(type=int),
|
|
19
|
+
]
|
|
20
|
+
|
|
21
|
+
@convert_response_to_previous_version_for(User, check_usage=False)
|
|
22
|
+
def change_id_to_int(response: ResponseInfo): ...
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import pytest
|
|
2
|
+
|
|
3
|
+
from cadwyn import Cadwyn, Version, VersionBundle
|
|
4
|
+
from cadwyn.exceptions import RouteResponseBySchemaConverterDoesNotApplyToAnythingError
|
|
5
|
+
from docs_src.how_to.change_openapi_schemas.change_schema_without_endpoint.block001 import (
|
|
6
|
+
ChangeUserIDToString,
|
|
7
|
+
)
|
|
8
|
+
|
|
9
|
+
versions = VersionBundle(Version("2023-04-12", ChangeUserIDToString), Version("2022-11-16"))
|
|
10
|
+
app = Cadwyn(versions=versions)
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
def test__migrate_to_previous_version__without_check_usage_argument__should_raise_error():
|
|
14
|
+
with pytest.raises(RouteResponseBySchemaConverterDoesNotApplyToAnythingError):
|
|
15
|
+
app._cadwyn_initialize()
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
from fastapi.testclient import TestClient
|
|
2
|
+
|
|
3
|
+
from cadwyn import Cadwyn, Version, VersionBundle
|
|
4
|
+
from docs_src.how_to.change_openapi_schemas.change_schema_without_endpoint.block002 import (
|
|
5
|
+
ChangeUserIDToString,
|
|
6
|
+
)
|
|
7
|
+
|
|
8
|
+
versions = VersionBundle(Version("2023-04-12", ChangeUserIDToString), Version("2022-11-16"))
|
|
9
|
+
app = Cadwyn(versions=versions)
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
def test__migrate_to_previous_version__with_check_usage_set_to_false__should_not_raise_error():
|
|
13
|
+
with TestClient(app):
|
|
14
|
+
...
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import pytest
|
|
2
|
+
from dirty_equals import IsUUID
|
|
3
|
+
from fastapi.testclient import TestClient
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
@pytest.fixture
|
|
7
|
+
def client():
|
|
8
|
+
from docs_src.quickstart.tutorial.block003 import app
|
|
9
|
+
|
|
10
|
+
return TestClient(app)
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
def test__basic_post__with_version_2000(client: TestClient):
|
|
14
|
+
response = client.post("/users", json={"address": "123 Example St"}, headers={"x-api-version": "2000-01-01"})
|
|
15
|
+
assert response.status_code == 200, response.json()
|
|
16
|
+
assert response.json() == {"id": IsUUID(4), "address": "123 Example St"}
|
|
17
|
+
|
|
18
|
+
user_id = response.json()["id"]
|
|
19
|
+
|
|
20
|
+
response = client.get(f"/users/{user_id}", headers={"x-api-version": "2000-01-01"})
|
|
21
|
+
assert response.status_code == 200, response.json()
|
|
22
|
+
assert response.json() == {"id": user_id, "address": "123 Example St"}
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
def test__basic_post__with_version_2001(client: TestClient):
|
|
26
|
+
response = client.post(
|
|
27
|
+
"/users", json={"addresses": ["123 John St", "456 Smith St"]}, headers={"x-api-version": "2001-01-01"}
|
|
28
|
+
)
|
|
29
|
+
assert response.status_code == 200, response.json()
|
|
30
|
+
assert response.json() == {"id": IsUUID(4), "addresses": ["123 John St", "456 Smith St"]}
|
|
31
|
+
|
|
32
|
+
user_id = response.json()["id"]
|
|
33
|
+
|
|
34
|
+
response = client.get(f"/users/{user_id}", headers={"x-api-version": "2001-01-01"})
|
|
35
|
+
assert response.status_code == 200, response.json()
|
|
36
|
+
assert response.json() == {"id": user_id, "addresses": ["123 John St", "456 Smith St"]}
|
|
@@ -97,6 +97,7 @@ nav:
|
|
|
97
97
|
- "Rename a field": "how_to/change_openapi_schemas/rename_a_field_in_schema.md"
|
|
98
98
|
- "Change field type": "how_to/change_openapi_schemas/change_field_type.md"
|
|
99
99
|
- "Change field constraints or validators": "how_to/change_openapi_schemas/changing_constraints.md"
|
|
100
|
+
- "Change a schema that is not used in any endpoint": "how_to/change_openapi_schemas/change_schema_without_endpoint.md"
|
|
100
101
|
- "Change business logic": "how_to/change_business_logic/index.md"
|
|
101
102
|
- "Change endpoints": "how_to/change_endpoints/index.md"
|
|
102
103
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
[project]
|
|
2
2
|
name = "cadwyn"
|
|
3
|
-
version = "4.
|
|
3
|
+
version = "4.5.0"
|
|
4
4
|
description = "Production-ready community-driven modern Stripe-like API versioning in FastAPI"
|
|
5
5
|
authors = [{ name = "Stanislav Zmiev", email = "zmievsa@gmail.com" }]
|
|
6
6
|
license = "MIT"
|
|
@@ -64,7 +64,6 @@ standard = ["fastapi[standard]>=0.112.3", "typer>=0.7.0"]
|
|
|
64
64
|
|
|
65
65
|
[tool.uv]
|
|
66
66
|
dev-dependencies = [
|
|
67
|
-
"pdbpp ~=0.10.3",
|
|
68
67
|
"python-multipart >=0.0.6",
|
|
69
68
|
"better-devtools ~=0.13.3",
|
|
70
69
|
"pytest-sugar ~=1.0.0",
|
|
@@ -76,12 +75,15 @@ dev-dependencies = [
|
|
|
76
75
|
"pytest-cov >=4.0.0",
|
|
77
76
|
"dirty-equals >=0.6.0",
|
|
78
77
|
"uvicorn ~=0.23.0",
|
|
78
|
+
# type checking
|
|
79
|
+
"pyright>=1.1.390",
|
|
79
80
|
# docs
|
|
80
81
|
"mkdocs >=1.5.2",
|
|
81
82
|
"mkdocs-material >=9.3.1",
|
|
82
83
|
"mkdocs-simple-hooks >=0.1.5",
|
|
83
84
|
"mdx-include ~=1.4.2",
|
|
84
85
|
"mike >=2.1.2, <3",
|
|
86
|
+
"pdbpp>=0.10.3",
|
|
85
87
|
]
|
|
86
88
|
|
|
87
89
|
[project.urls]
|
|
@@ -99,6 +101,7 @@ parallel = true
|
|
|
99
101
|
branch = true
|
|
100
102
|
|
|
101
103
|
[tool.coverage.report]
|
|
104
|
+
fail_under = 100
|
|
102
105
|
skip_covered = true
|
|
103
106
|
skip_empty = true
|
|
104
107
|
# Taken from https://coverage.readthedocs.io/en/7.1.0/excluding.html#advanced-exclusion
|
|
@@ -119,6 +122,7 @@ exclude_lines = [
|
|
|
119
122
|
"@(typing\\.)?overload",
|
|
120
123
|
"__rich_repr__",
|
|
121
124
|
"__repr__",
|
|
125
|
+
"def .+: \\.\\.\\.",
|
|
122
126
|
]
|
|
123
127
|
omit = ["./docs/plugin.py", "./site/plugin.py", "scripts/*.py"]
|
|
124
128
|
|
|
@@ -127,6 +127,9 @@ ignore = [
|
|
|
127
127
|
"PGH003", # Use specific rule codes when ignoring type issues
|
|
128
128
|
"B008", # Do not perform function call in argument defaults
|
|
129
129
|
]
|
|
130
|
+
"docs_src/**/*" = [
|
|
131
|
+
"RUF012", # Mutable class attributes should be annotated with `typing.ClassVar`
|
|
132
|
+
]
|
|
130
133
|
"cadwyn/_utils.py" = [
|
|
131
134
|
"ERA001", # Found commented-out code (it's not actually commented out. It's just comments)
|
|
132
135
|
]
|
|
File without changes
|
|
File without changes
|
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
import sys
|
|
2
1
|
import textwrap
|
|
3
2
|
|
|
4
3
|
import pytest
|
|
@@ -9,7 +8,7 @@ from cadwyn.__main__ import app
|
|
|
9
8
|
|
|
10
9
|
|
|
11
10
|
def code(c: str) -> str:
|
|
12
|
-
return textwrap.dedent(c.strip())
|
|
11
|
+
return "\n".join(line.rstrip() for line in textwrap.dedent(c.strip()).splitlines())
|
|
13
12
|
|
|
14
13
|
|
|
15
14
|
def test__render_module():
|
|
@@ -70,14 +69,7 @@ def test__render_model__with_syntax_highlighting(): # pragma: no cover
|
|
|
70
69
|
],
|
|
71
70
|
)
|
|
72
71
|
assert result.exit_code == 0
|
|
73
|
-
|
|
74
|
-
if sys.platform.startswith("win32"):
|
|
75
|
-
# Windows rendering is weird
|
|
76
|
-
return
|
|
77
|
-
|
|
78
|
-
assert code(result.stdout) == (
|
|
79
|
-
"1 class A(BaseModel): \n 2 pass"
|
|
80
|
-
)
|
|
72
|
+
assert code(result.stdout) == "1 class A(BaseModel):\n 2 pass"
|
|
81
73
|
|
|
82
74
|
|
|
83
75
|
@pytest.mark.parametrize("arg", ["-V", "--version"])
|
|
File without changes
|
|
File without changes
|
cadwyn-4.5.0/tox.ini
ADDED
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
[tox]
|
|
2
|
+
envlist =
|
|
3
|
+
coverage_erase
|
|
4
|
+
# When updating Python versions, use search-and-replace
|
|
5
|
+
# against the entire list of of versions
|
|
6
|
+
# to ensure consistency throughout this file.
|
|
7
|
+
py{3.13, 3.12, 3.11, 3.10}
|
|
8
|
+
coverage_report
|
|
9
|
+
docs
|
|
10
|
+
pyright
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
[testenv]
|
|
14
|
+
runner = uv-venv-lock-runner
|
|
15
|
+
with_dev = true
|
|
16
|
+
extras =
|
|
17
|
+
standard
|
|
18
|
+
package = wheel
|
|
19
|
+
wheel_build_env = build_wheel
|
|
20
|
+
depends =
|
|
21
|
+
py{3.13, 3.12, 3.11, 3.10}: coverage_erase
|
|
22
|
+
commands = coverage run -m pytest {posargs}
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
[testenv:coverage_erase]
|
|
26
|
+
skip_install = true
|
|
27
|
+
commands = coverage erase
|
|
28
|
+
|
|
29
|
+
|
|
30
|
+
[testenv:coverage_report]
|
|
31
|
+
skip_install = true
|
|
32
|
+
depends =
|
|
33
|
+
py{3.13, 3.12, 3.11, 3.10}
|
|
34
|
+
commands_pre =
|
|
35
|
+
# Ignore the exit code of `coverage combine`
|
|
36
|
+
# (in case the reports are already combined).
|
|
37
|
+
- coverage combine
|
|
38
|
+
commands =
|
|
39
|
+
coverage report --show-missing
|
|
40
|
+
|
|
41
|
+
|
|
42
|
+
[testenv:coverage_report-ci]
|
|
43
|
+
# Inherit everything from the `coverage_report` environment,
|
|
44
|
+
# but generate an XML report and ignore exit codes.
|
|
45
|
+
base = coverage_report
|
|
46
|
+
commands =
|
|
47
|
+
- coverage xml --fail-under=0
|
|
48
|
+
- coverage report --show-missing
|
|
49
|
+
|
|
50
|
+
|
|
51
|
+
[testenv:docs]
|
|
52
|
+
base_python = py3.10
|
|
53
|
+
skip_install = true
|
|
54
|
+
commands = mkdocs build --strict
|
|
55
|
+
|
|
56
|
+
|
|
57
|
+
[testenv:pyright]
|
|
58
|
+
# When the Python version is updated here,
|
|
59
|
+
# update the version used in the CI `Typecheck` job, too.
|
|
60
|
+
base_python = py3.10
|
|
61
|
+
commands = pyright
|