fastapi-router-versioning 0.2.6__tar.gz → 0.3.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.
- {fastapi_router_versioning-0.2.6 → fastapi_router_versioning-0.3.0}/.github/dependabot.yml +2 -19
- fastapi_router_versioning-0.3.0/.github/workflows/bump-pre-commit-hooks.yml +67 -0
- {fastapi_router_versioning-0.2.6 → fastapi_router_versioning-0.3.0}/.github/workflows/create-draft-release.yml +3 -3
- {fastapi_router_versioning-0.2.6 → fastapi_router_versioning-0.3.0}/.github/workflows/labeler.yml +1 -1
- {fastapi_router_versioning-0.2.6 → fastapi_router_versioning-0.3.0}/.github/workflows/latest-changes.yml +1 -1
- {fastapi_router_versioning-0.2.6 → fastapi_router_versioning-0.3.0}/.github/workflows/pre-commit.yml +3 -3
- {fastapi_router_versioning-0.2.6 → fastapi_router_versioning-0.3.0}/.github/workflows/prepare-release.yml +3 -3
- {fastapi_router_versioning-0.2.6 → fastapi_router_versioning-0.3.0}/.github/workflows/publish.yml +3 -3
- {fastapi_router_versioning-0.2.6 → fastapi_router_versioning-0.3.0}/.github/workflows/test-redistribute.yml +3 -3
- {fastapi_router_versioning-0.2.6 → fastapi_router_versioning-0.3.0}/.github/workflows/test.yml +6 -6
- {fastapi_router_versioning-0.2.6 → fastapi_router_versioning-0.3.0}/.github/workflows/zizmor.yml +2 -2
- {fastapi_router_versioning-0.2.6 → fastapi_router_versioning-0.3.0}/.pre-commit-config.yaml +1 -1
- {fastapi_router_versioning-0.2.6 → fastapi_router_versioning-0.3.0}/PKG-INFO +53 -58
- {fastapi_router_versioning-0.2.6 → fastapi_router_versioning-0.3.0}/README.md +52 -57
- {fastapi_router_versioning-0.2.6 → fastapi_router_versioning-0.3.0}/RELEASE_NOTES.md +21 -0
- {fastapi_router_versioning-0.2.6 → fastapi_router_versioning-0.3.0}/examples/mounted_subapps_app.py +2 -4
- fastapi_router_versioning-0.3.0/examples/validation_override_integration_app.py +56 -0
- {fastapi_router_versioning-0.2.6 → fastapi_router_versioning-0.3.0}/fastapi_router_versioning/__init__.py +1 -1
- {fastapi_router_versioning-0.2.6 → fastapi_router_versioning-0.3.0}/fastapi_router_versioning/versioner.py +0 -99
- {fastapi_router_versioning-0.2.6 → fastapi_router_versioning-0.3.0}/pyproject.toml +1 -0
- {fastapi_router_versioning-0.2.6 → fastapi_router_versioning-0.3.0}/tests/test_versioner.py +7 -330
- {fastapi_router_versioning-0.2.6 → fastapi_router_versioning-0.3.0}/uv.lock +250 -232
- fastapi_router_versioning-0.2.6/examples/validation_error_code_app.py +0 -57
- fastapi_router_versioning-0.2.6/examples/validation_error_code_custom_handler_app.py +0 -70
- {fastapi_router_versioning-0.2.6 → fastapi_router_versioning-0.3.0}/.github/labeler.yml +0 -0
- {fastapi_router_versioning-0.2.6 → fastapi_router_versioning-0.3.0}/.github/workflows/detect-conflicts.yml +0 -0
- {fastapi_router_versioning-0.2.6 → fastapi_router_versioning-0.3.0}/.github/workflows/guard-dependencies.yml +0 -0
- {fastapi_router_versioning-0.2.6 → fastapi_router_versioning-0.3.0}/.gitignore +0 -0
- {fastapi_router_versioning-0.2.6 → fastapi_router_versioning-0.3.0}/.python-version +0 -0
- {fastapi_router_versioning-0.2.6 → fastapi_router_versioning-0.3.0}/LICENSE +0 -0
- {fastapi_router_versioning-0.2.6 → fastapi_router_versioning-0.3.0}/examples/calver_app.py +0 -0
- {fastapi_router_versioning-0.2.6 → fastapi_router_versioning-0.3.0}/examples/download_static_assets.py +0 -0
- {fastapi_router_versioning-0.2.6 → fastapi_router_versioning-0.3.0}/examples/multi_router_app.py +0 -0
- {fastapi_router_versioning-0.2.6 → fastapi_router_versioning-0.3.0}/examples/openapi_hook_app.py +0 -0
- {fastapi_router_versioning-0.2.6 → fastapi_router_versioning-0.3.0}/examples/self_hosted_docs_app.py +0 -0
- {fastapi_router_versioning-0.2.6 → fastapi_router_versioning-0.3.0}/examples/semver_app.py +0 -0
- {fastapi_router_versioning-0.2.6 → fastapi_router_versioning-0.3.0}/examples/semver_major_only_app.py +0 -0
- {fastapi_router_versioning-0.2.6 → fastapi_router_versioning-0.3.0}/examples/webhook_versioning_app.py +0 -0
- {fastapi_router_versioning-0.2.6 → fastapi_router_versioning-0.3.0}/fastapi_router_versioning/py.typed +0 -0
- {fastapi_router_versioning-0.2.6 → fastapi_router_versioning-0.3.0}/scripts/format.sh +0 -0
- {fastapi_router_versioning-0.2.6 → fastapi_router_versioning-0.3.0}/scripts/lint.sh +0 -0
- {fastapi_router_versioning-0.2.6 → fastapi_router_versioning-0.3.0}/scripts/prepare_release.py +0 -0
- {fastapi_router_versioning-0.2.6 → fastapi_router_versioning-0.3.0}/scripts/test-cov-html.sh +0 -0
- {fastapi_router_versioning-0.2.6 → fastapi_router_versioning-0.3.0}/scripts/test-cov.sh +0 -0
- {fastapi_router_versioning-0.2.6 → fastapi_router_versioning-0.3.0}/scripts/test.sh +0 -0
- {fastapi_router_versioning-0.2.6 → fastapi_router_versioning-0.3.0}/tests/__init__.py +0 -0
- {fastapi_router_versioning-0.2.6 → fastapi_router_versioning-0.3.0}/tests/test_calver.py +0 -0
- {fastapi_router_versioning-0.2.6 → fastapi_router_versioning-0.3.0}/tests/test_fastapi_integration.py +0 -0
- {fastapi_router_versioning-0.2.6 → fastapi_router_versioning-0.3.0}/tests/test_prepare_release.py +0 -0
- {fastapi_router_versioning-0.2.6 → fastapi_router_versioning-0.3.0}/tests/test_semver.py +0 -0
|
@@ -4,7 +4,7 @@ updates:
|
|
|
4
4
|
- package-ecosystem: "github-actions"
|
|
5
5
|
directory: "/"
|
|
6
6
|
schedule:
|
|
7
|
-
interval: "
|
|
7
|
+
interval: "monthly"
|
|
8
8
|
cooldown:
|
|
9
9
|
default-days: 7
|
|
10
10
|
commit-message:
|
|
@@ -21,7 +21,7 @@ updates:
|
|
|
21
21
|
- package-ecosystem: "uv"
|
|
22
22
|
directory: "/"
|
|
23
23
|
schedule:
|
|
24
|
-
interval: "
|
|
24
|
+
interval: "monthly"
|
|
25
25
|
cooldown:
|
|
26
26
|
default-days: 7
|
|
27
27
|
commit-message:
|
|
@@ -31,20 +31,3 @@ updates:
|
|
|
31
31
|
dependency-type: "development"
|
|
32
32
|
patterns:
|
|
33
33
|
- "*"
|
|
34
|
-
# pre-commit
|
|
35
|
-
- package-ecosystem: "pre-commit"
|
|
36
|
-
directory: "/"
|
|
37
|
-
schedule:
|
|
38
|
-
interval: "weekly"
|
|
39
|
-
cooldown:
|
|
40
|
-
default-days: 7
|
|
41
|
-
commit-message:
|
|
42
|
-
prefix: ⬆
|
|
43
|
-
labels:
|
|
44
|
-
- "internal"
|
|
45
|
-
- "dependencies"
|
|
46
|
-
- "pre-commit"
|
|
47
|
-
groups:
|
|
48
|
-
pre-commit:
|
|
49
|
-
patterns:
|
|
50
|
-
- "*"
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
name: Bump pre-commit hooks
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
schedule:
|
|
5
|
+
- cron: "0 12 1 * *"
|
|
6
|
+
workflow_dispatch:
|
|
7
|
+
|
|
8
|
+
permissions: {}
|
|
9
|
+
|
|
10
|
+
jobs:
|
|
11
|
+
bump-pre-commit-hooks:
|
|
12
|
+
if: github.repository_owner == 'mat81black'
|
|
13
|
+
runs-on: ubuntu-latest
|
|
14
|
+
timeout-minutes: 10
|
|
15
|
+
steps:
|
|
16
|
+
- name: Dump GitHub context
|
|
17
|
+
env:
|
|
18
|
+
GITHUB_CONTEXT: ${{ toJson(github) }}
|
|
19
|
+
run: echo "$GITHUB_CONTEXT"
|
|
20
|
+
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
|
|
21
|
+
with:
|
|
22
|
+
token: ${{ secrets.FASTAPI_ROUTER_VERSIONING_LATEST_CHANGES }}
|
|
23
|
+
persist-credentials: true
|
|
24
|
+
- name: Set up Python
|
|
25
|
+
uses: actions/setup-python@5fda3b95a4ea91299a34e894583c3862153e4b97 # v7.0.0
|
|
26
|
+
with:
|
|
27
|
+
python-version-file: ".python-version"
|
|
28
|
+
- name: Setup uv
|
|
29
|
+
uses: astral-sh/setup-uv@c771a70e6277c0a99b617c7a806ffedaca235ff9 # v9.0.0
|
|
30
|
+
with:
|
|
31
|
+
# Before upgrading uv version, make sure astral-sh/setup-uv knows its checksum.
|
|
32
|
+
# See: https://github.com/astral-sh/setup-uv/issues/851#issuecomment-4282017837
|
|
33
|
+
version: "0.11.18"
|
|
34
|
+
cache-dependency-glob: |
|
|
35
|
+
pyproject.toml
|
|
36
|
+
uv.lock
|
|
37
|
+
- name: Bump pre-commit hooks
|
|
38
|
+
run: uv run prek auto-update --freeze --cooldown-days 7
|
|
39
|
+
- name: Create pull request
|
|
40
|
+
env:
|
|
41
|
+
GH_TOKEN: ${{ secrets.FASTAPI_ROUTER_VERSIONING_LATEST_CHANGES }}
|
|
42
|
+
BASE_BRANCH: ${{ github.event.repository.default_branch }}
|
|
43
|
+
run: |
|
|
44
|
+
set -euo pipefail
|
|
45
|
+
if git diff --quiet; then
|
|
46
|
+
echo "No pre-commit hook updates available"
|
|
47
|
+
exit 0
|
|
48
|
+
fi
|
|
49
|
+
git config user.name "github-actions[bot]"
|
|
50
|
+
git config user.email "github-actions[bot]@users.noreply.github.com"
|
|
51
|
+
branch="bump-pre-commit-hooks"
|
|
52
|
+
git switch -C "$branch"
|
|
53
|
+
git add .pre-commit-config.yaml
|
|
54
|
+
git commit -m "⬆ Bump pre-commit hooks"
|
|
55
|
+
git push --force origin "$branch"
|
|
56
|
+
if [ -z "$(gh pr list --head "$branch" --state open --json number --jq '.[].number')" ]; then
|
|
57
|
+
gh pr create \
|
|
58
|
+
--base "$BASE_BRANCH" \
|
|
59
|
+
--head "$branch" \
|
|
60
|
+
--title "⬆ Bump pre-commit hooks" \
|
|
61
|
+
--body "Bump pre-commit hook versions via \`prek auto-update --freeze --cooldown-days 7\`." \
|
|
62
|
+
--label internal \
|
|
63
|
+
--label dependencies \
|
|
64
|
+
--label pre-commit
|
|
65
|
+
else
|
|
66
|
+
echo "PR for \"$branch\" already open; branch updated in place."
|
|
67
|
+
fi
|
|
@@ -22,16 +22,16 @@ jobs:
|
|
|
22
22
|
env:
|
|
23
23
|
GITHUB_CONTEXT: ${{ toJson(github) }}
|
|
24
24
|
run: echo "$GITHUB_CONTEXT"
|
|
25
|
-
- uses: actions/checkout@
|
|
25
|
+
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
|
|
26
26
|
with:
|
|
27
27
|
ref: ${{ github.event.repository.default_branch }}
|
|
28
28
|
persist-credentials: true
|
|
29
29
|
- name: Set up Python
|
|
30
|
-
uses: actions/setup-python@
|
|
30
|
+
uses: actions/setup-python@5fda3b95a4ea91299a34e894583c3862153e4b97 # v7.0.0
|
|
31
31
|
with:
|
|
32
32
|
python-version-file: ".python-version"
|
|
33
33
|
- name: Install uv
|
|
34
|
-
uses: astral-sh/setup-uv@
|
|
34
|
+
uses: astral-sh/setup-uv@c771a70e6277c0a99b617c7a806ffedaca235ff9 # v9.0.0
|
|
35
35
|
with:
|
|
36
36
|
# Before upgrading uv version, make sure astral-sh/setup-uv knows its checksum.
|
|
37
37
|
# See: https://github.com/astral-sh/setup-uv/issues/851#issuecomment-4282017837
|
{fastapi_router_versioning-0.2.6 → fastapi_router_versioning-0.3.0}/.github/workflows/labeler.yml
RENAMED
|
@@ -19,7 +19,7 @@ jobs:
|
|
|
19
19
|
runs-on: ubuntu-latest
|
|
20
20
|
timeout-minutes: 5
|
|
21
21
|
steps:
|
|
22
|
-
- uses: actions/labeler@
|
|
22
|
+
- uses: actions/labeler@bf12e9b00b37c5c0ca2b87b79b2daf7891dbda13 # v7.0.0
|
|
23
23
|
if: ${{ github.event.action != 'labeled' && github.event.action != 'unlabeled' }}
|
|
24
24
|
- run: echo "Done adding labels"
|
|
25
25
|
# Run this after labeler applied labels
|
|
@@ -28,7 +28,7 @@ jobs:
|
|
|
28
28
|
env:
|
|
29
29
|
GITHUB_CONTEXT: ${{ toJson(github) }}
|
|
30
30
|
run: echo "$GITHUB_CONTEXT"
|
|
31
|
-
- uses: actions/checkout@
|
|
31
|
+
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
|
|
32
32
|
with:
|
|
33
33
|
ref: ${{ github.event.repository.default_branch }}
|
|
34
34
|
# To allow latest-changes to commit to the main branch
|
{fastapi_router_versioning-0.2.6 → fastapi_router_versioning-0.3.0}/.github/workflows/pre-commit.yml
RENAMED
|
@@ -18,19 +18,19 @@ jobs:
|
|
|
18
18
|
run: echo "$GITHUB_CONTEXT"
|
|
19
19
|
|
|
20
20
|
- name: Checkout code
|
|
21
|
-
uses: actions/checkout@
|
|
21
|
+
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
|
|
22
22
|
with:
|
|
23
23
|
persist-credentials: false
|
|
24
24
|
# Full history required for --from-ref/--to-ref diff in prek
|
|
25
25
|
fetch-depth: 0
|
|
26
26
|
|
|
27
27
|
- name: Set up Python
|
|
28
|
-
uses: actions/setup-python@
|
|
28
|
+
uses: actions/setup-python@5fda3b95a4ea91299a34e894583c3862153e4b97 # v7.0.0
|
|
29
29
|
with:
|
|
30
30
|
python-version-file: ".python-version"
|
|
31
31
|
|
|
32
32
|
- name: Setup uv
|
|
33
|
-
uses: astral-sh/setup-uv@
|
|
33
|
+
uses: astral-sh/setup-uv@c771a70e6277c0a99b617c7a806ffedaca235ff9 # v9.0.0
|
|
34
34
|
with:
|
|
35
35
|
# Before upgrading uv version, make sure astral-sh/setup-uv knows its checksum.
|
|
36
36
|
# See: https://github.com/astral-sh/setup-uv/issues/851#issuecomment-4282017837
|
|
@@ -34,16 +34,16 @@ jobs:
|
|
|
34
34
|
env:
|
|
35
35
|
GITHUB_CONTEXT: ${{ toJson(github) }}
|
|
36
36
|
run: echo "$GITHUB_CONTEXT"
|
|
37
|
-
- uses: actions/checkout@
|
|
37
|
+
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
|
|
38
38
|
with:
|
|
39
39
|
token: ${{ secrets.FASTAPI_ROUTER_VERSIONING_LATEST_CHANGES }} # zizmor: ignore[secrets-outside-env]
|
|
40
40
|
persist-credentials: true
|
|
41
41
|
- name: Set up Python
|
|
42
|
-
uses: actions/setup-python@
|
|
42
|
+
uses: actions/setup-python@5fda3b95a4ea91299a34e894583c3862153e4b97 # v7.0.0
|
|
43
43
|
with:
|
|
44
44
|
python-version-file: ".python-version"
|
|
45
45
|
- name: Install uv
|
|
46
|
-
uses: astral-sh/setup-uv@
|
|
46
|
+
uses: astral-sh/setup-uv@c771a70e6277c0a99b617c7a806ffedaca235ff9 # v9.0.0
|
|
47
47
|
with:
|
|
48
48
|
# Before upgrading uv version, make sure astral-sh/setup-uv knows its checksum.
|
|
49
49
|
# See: https://github.com/astral-sh/setup-uv/issues/851#issuecomment-4282017837
|
{fastapi_router_versioning-0.2.6 → fastapi_router_versioning-0.3.0}/.github/workflows/publish.yml
RENAMED
|
@@ -20,15 +20,15 @@ jobs:
|
|
|
20
20
|
env:
|
|
21
21
|
GITHUB_CONTEXT: ${{ toJson(github) }}
|
|
22
22
|
run: echo "$GITHUB_CONTEXT"
|
|
23
|
-
- uses: actions/checkout@
|
|
23
|
+
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
|
|
24
24
|
with:
|
|
25
25
|
persist-credentials: false
|
|
26
26
|
- name: Set up Python
|
|
27
|
-
uses: actions/setup-python@
|
|
27
|
+
uses: actions/setup-python@5fda3b95a4ea91299a34e894583c3862153e4b97 # v7.0.0
|
|
28
28
|
with:
|
|
29
29
|
python-version-file: ".python-version"
|
|
30
30
|
- name: Install uv
|
|
31
|
-
uses: astral-sh/setup-uv@
|
|
31
|
+
uses: astral-sh/setup-uv@c771a70e6277c0a99b617c7a806ffedaca235ff9 # v9.0.0
|
|
32
32
|
with:
|
|
33
33
|
# Before upgrading uv version, make sure astral-sh/setup-uv knows its checksum.
|
|
34
34
|
# See: https://github.com/astral-sh/setup-uv/issues/851#issuecomment-4282017837
|
|
@@ -18,7 +18,7 @@ jobs:
|
|
|
18
18
|
outputs:
|
|
19
19
|
src: ${{ steps.filter.outputs.src }}
|
|
20
20
|
steps:
|
|
21
|
-
- uses: actions/checkout@
|
|
21
|
+
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
|
|
22
22
|
with:
|
|
23
23
|
persist-credentials: false
|
|
24
24
|
- uses: dorny/paths-filter@7b450fff21473bca461d4b92ce414b9d0420d706 # v4.0.2
|
|
@@ -46,11 +46,11 @@ jobs:
|
|
|
46
46
|
env:
|
|
47
47
|
GITHUB_CONTEXT: ${{ toJson(github) }}
|
|
48
48
|
run: echo "$GITHUB_CONTEXT"
|
|
49
|
-
- uses: actions/checkout@
|
|
49
|
+
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
|
|
50
50
|
with:
|
|
51
51
|
persist-credentials: false
|
|
52
52
|
- name: Set up Python
|
|
53
|
-
uses: actions/setup-python@
|
|
53
|
+
uses: actions/setup-python@5fda3b95a4ea91299a34e894583c3862153e4b97 # v7.0.0
|
|
54
54
|
with:
|
|
55
55
|
python-version-file: ".python-version"
|
|
56
56
|
- name: Install build dependencies
|
{fastapi_router_versioning-0.2.6 → fastapi_router_versioning-0.3.0}/.github/workflows/test.yml
RENAMED
|
@@ -26,7 +26,7 @@ jobs:
|
|
|
26
26
|
outputs:
|
|
27
27
|
src: ${{ steps.filter.outputs.src }}
|
|
28
28
|
steps:
|
|
29
|
-
- uses: actions/checkout@
|
|
29
|
+
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
|
|
30
30
|
with:
|
|
31
31
|
persist-credentials: false
|
|
32
32
|
# For pull requests it's not necessary to checkout the code but for the main branch it is
|
|
@@ -72,17 +72,17 @@ jobs:
|
|
|
72
72
|
GITHUB_CONTEXT: ${{ toJson(github) }}
|
|
73
73
|
run: echo "$GITHUB_CONTEXT"
|
|
74
74
|
|
|
75
|
-
- uses: actions/checkout@
|
|
75
|
+
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
|
|
76
76
|
with:
|
|
77
77
|
persist-credentials: false
|
|
78
78
|
|
|
79
79
|
- name: Set up Python
|
|
80
|
-
uses: actions/setup-python@
|
|
80
|
+
uses: actions/setup-python@5fda3b95a4ea91299a34e894583c3862153e4b97 # v7.0.0
|
|
81
81
|
with:
|
|
82
82
|
python-version: ${{ matrix.python-version }}
|
|
83
83
|
|
|
84
84
|
- name: Setup uv
|
|
85
|
-
uses: astral-sh/setup-uv@
|
|
85
|
+
uses: astral-sh/setup-uv@c771a70e6277c0a99b617c7a806ffedaca235ff9 # v9.0.0
|
|
86
86
|
with:
|
|
87
87
|
# Before upgrading uv version, make sure astral-sh/setup-uv knows its checksum.
|
|
88
88
|
# See: https://github.com/astral-sh/setup-uv/issues/851#issuecomment-4282017837
|
|
@@ -130,12 +130,12 @@ jobs:
|
|
|
130
130
|
GITHUB_CONTEXT: ${{ toJson(github) }}
|
|
131
131
|
run: echo "$GITHUB_CONTEXT"
|
|
132
132
|
|
|
133
|
-
- uses: actions/checkout@
|
|
133
|
+
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
|
|
134
134
|
with:
|
|
135
135
|
persist-credentials: false
|
|
136
136
|
|
|
137
137
|
- name: Setup uv
|
|
138
|
-
uses: astral-sh/setup-uv@
|
|
138
|
+
uses: astral-sh/setup-uv@c771a70e6277c0a99b617c7a806ffedaca235ff9 # v9.0.0
|
|
139
139
|
with:
|
|
140
140
|
# Before upgrading uv version, make sure astral-sh/setup-uv knows its checksum.
|
|
141
141
|
# See: https://github.com/astral-sh/setup-uv/issues/851#issuecomment-4282017837
|
{fastapi_router_versioning-0.2.6 → fastapi_router_versioning-0.3.0}/.github/workflows/zizmor.yml
RENAMED
|
@@ -18,8 +18,8 @@ jobs:
|
|
|
18
18
|
security-events: write # Required for upload-sarif (used by zizmor-action) to upload SARIF files.
|
|
19
19
|
steps:
|
|
20
20
|
- name: Checkout repository
|
|
21
|
-
uses: actions/checkout@
|
|
21
|
+
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
|
|
22
22
|
with:
|
|
23
23
|
persist-credentials: false
|
|
24
24
|
- name: Run zizmor
|
|
25
|
-
uses: zizmorcore/zizmor-action@
|
|
25
|
+
uses: zizmorcore/zizmor-action@6599ee8b7a49aef6a770f63d261d214911a7ce02 # v0.6.0
|
|
@@ -15,7 +15,7 @@ repos:
|
|
|
15
15
|
- id: trailing-whitespace
|
|
16
16
|
|
|
17
17
|
- repo: https://github.com/crate-ci/typos
|
|
18
|
-
rev:
|
|
18
|
+
rev: bee27e3a4fd1ea2111cf90ab89cd076c870fce14 # frozen: v1.48.0
|
|
19
19
|
hooks:
|
|
20
20
|
- id: typos
|
|
21
21
|
args: [ --force-exclude ]
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: fastapi-router-versioning
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.3.0
|
|
4
4
|
Summary: Router-based API versioning for FastAPI, with per-version docs and a declarative route lifecycle.
|
|
5
5
|
Project-URL: Homepage, https://github.com/mat81black/fastapi-router-versioning
|
|
6
6
|
Project-URL: Repository, https://github.com/mat81black/fastapi-router-versioning
|
|
@@ -49,7 +49,6 @@ Running multiple API versions side by side usually means duplicating routers, ha
|
|
|
49
49
|
- **Latest alias**: expose the newest version under a fixed `/latest` prefix clients can pin to
|
|
50
50
|
- **Self-hosted docs assets**: point Swagger UI and ReDoc at your own JS/CSS for air-gapped deployments
|
|
51
51
|
- **Reverse proxy and sub-app aware**: doc URLs pick up the ASGI `root_path` at request time
|
|
52
|
-
- **Configurable validation error status**: swap FastAPI's default `422` for any code, applied consistently to runtime responses and every OpenAPI schema, including the app's own root schema
|
|
53
52
|
- **Route composition support**: works across nested routers, WebSockets, `Depends`, and OpenAPI Callbacks
|
|
54
53
|
|
|
55
54
|
---
|
|
@@ -154,6 +153,15 @@ def legacy_route():
|
|
|
154
153
|
A route without `@api_version` isn't excluded, it falls back to `default_version`
|
|
155
154
|
(`(1, 0)` for SemVer, `"1"` for CalVer, unless overridden).
|
|
156
155
|
|
|
156
|
+
FastAPI's own `deprecated=True` (set directly on a route, or inherited from
|
|
157
|
+
`APIRouter(deprecated=True)`) is preserved as-is: `RouterVersioner` copies it into every
|
|
158
|
+
version unconditionally, on top of whatever `deprecate_in` computes. `deprecate_in` only
|
|
159
|
+
ever turns deprecation *on* for versions at or after its boundary, it never turns off a
|
|
160
|
+
`deprecated=True` that was already set natively. If you set both on the same route, it
|
|
161
|
+
shows as deprecated in every version, including ones before `deprecate_in`'s boundary.
|
|
162
|
+
Use one or the other: `deprecated=True` for an unconditional, version-independent flag,
|
|
163
|
+
`deprecate_in` for a per-version lifecycle.
|
|
164
|
+
|
|
157
165
|
---
|
|
158
166
|
|
|
159
167
|
## `RouterVersioner` reference
|
|
@@ -180,8 +188,6 @@ A route without `@api_version` isn't excluded, it falls back to `default_version
|
|
|
180
188
|
| `redoc_js_url` | `str \| None` | FastAPI CDN | Custom URL for the ReDoc JS bundle |
|
|
181
189
|
| `redoc_favicon_url` | `str \| None` | FastAPI favicon | Custom URL for the ReDoc favicon |
|
|
182
190
|
| `redoc_with_google_fonts` | `bool` | `True` | Set `False` to stop ReDoc from loading Google Fonts |
|
|
183
|
-
| `validation_error_code` | `int` | `422` | Status code returned for request validation errors; also replaces the `422` entry everywhere it appears in the OpenAPI schema, root schema included |
|
|
184
|
-
| `handle_validation_exceptions` | `bool` | `True` | Set `False` to only patch the schema and register your own `RequestValidationError` handler |
|
|
185
191
|
|
|
186
192
|
`.versionize()` returns the list of versions it activated. It can only be called once per
|
|
187
193
|
instance; a second call raises `RuntimeError`, since it mutates the live FastAPI app in a way
|
|
@@ -290,6 +296,41 @@ RouterVersioner(
|
|
|
290
296
|
).versionize()
|
|
291
297
|
```
|
|
292
298
|
|
|
299
|
+
### Custom validation error status code
|
|
300
|
+
|
|
301
|
+
Changing FastAPI's default `422` for request validation errors is not something
|
|
302
|
+
`RouterVersioner` does itself: it's a separate, general-purpose concern, handled by the
|
|
303
|
+
[fastapi-validation-override](https://pypi.org/project/fastapi-validation-override/) package.
|
|
304
|
+
`openapi_hook` is the integration point: it lets you re-apply the same patch to every
|
|
305
|
+
per-version schema that `RouterVersioner` generates, so all of them, root schema included,
|
|
306
|
+
stay consistent.
|
|
307
|
+
|
|
308
|
+
```bash
|
|
309
|
+
uv add fastapi-validation-override
|
|
310
|
+
```
|
|
311
|
+
|
|
312
|
+
```python
|
|
313
|
+
from fastapi_validation_override import override_validation_error, patch_422_responses
|
|
314
|
+
|
|
315
|
+
# 1. Registers the runtime handler and patches the app's own root /openapi.json.
|
|
316
|
+
override_validation_error(app, status_code=400)
|
|
317
|
+
|
|
318
|
+
# 2. Re-applies the same patch to each version's own schema.
|
|
319
|
+
def versioning_openapi_hook(schema: dict, version: tuple[int, int]) -> dict:
|
|
320
|
+
return patch_422_responses(schema, "400")
|
|
321
|
+
|
|
322
|
+
RouterVersioner(
|
|
323
|
+
app=app,
|
|
324
|
+
routers=router,
|
|
325
|
+
version_format=VersionFormat.SEMVER,
|
|
326
|
+
openapi_hook=versioning_openapi_hook,
|
|
327
|
+
).versionize()
|
|
328
|
+
# Validation failures now return 400, both at runtime and in every schema
|
|
329
|
+
# (root, and every /vX_Y/openapi.json)
|
|
330
|
+
```
|
|
331
|
+
|
|
332
|
+
See [`examples/validation_override_integration_app.py`](https://github.com/mat81black/fastapi-router-versioning/blob/main/examples/validation_override_integration_app.py).
|
|
333
|
+
|
|
293
334
|
### OpenAPI Callbacks and Webhooks
|
|
294
335
|
|
|
295
336
|
Route-level **Callbacks** need no special handling: a `callbacks=[...]` argument on a route
|
|
@@ -373,63 +414,18 @@ RouterVersioner(
|
|
|
373
414
|
[`examples/download_static_assets.py`](https://github.com/mat81black/fastapi-router-versioning/blob/main/examples/download_static_assets.py) downloads the required files in one step;
|
|
374
415
|
[`examples/self_hosted_docs_app.py`](https://github.com/mat81black/fastapi-router-versioning/blob/main/examples/self_hosted_docs_app.py) wires them into a full app.
|
|
375
416
|
|
|
376
|
-
### Validation error status code
|
|
377
|
-
|
|
378
|
-
`validation_error_code` changes what FastAPI returns for a failed request body/query/path
|
|
379
|
-
validation, `422` by default, both at runtime and in the schema:
|
|
380
|
-
|
|
381
|
-
```python
|
|
382
|
-
RouterVersioner(
|
|
383
|
-
app=app,
|
|
384
|
-
routers=router,
|
|
385
|
-
version_format=VersionFormat.SEMVER,
|
|
386
|
-
validation_error_code=400,
|
|
387
|
-
).versionize()
|
|
388
|
-
# Validation failures now return 400; every 422 entry in the schema becomes 400
|
|
389
|
-
```
|
|
390
|
-
|
|
391
|
-
Set `handle_validation_exceptions=False` to keep the schema change while writing your own
|
|
392
|
-
response body:
|
|
393
|
-
|
|
394
|
-
```python
|
|
395
|
-
from fastapi import Request
|
|
396
|
-
from fastapi.exceptions import RequestValidationError
|
|
397
|
-
from fastapi.responses import JSONResponse
|
|
398
|
-
|
|
399
|
-
@app.exception_handler(RequestValidationError)
|
|
400
|
-
async def my_handler(request: Request, exc: RequestValidationError) -> JSONResponse:
|
|
401
|
-
return JSONResponse(status_code=400, content={"errors": exc.errors()})
|
|
402
|
-
|
|
403
|
-
RouterVersioner(
|
|
404
|
-
app=app,
|
|
405
|
-
routers=router,
|
|
406
|
-
version_format=VersionFormat.SEMVER,
|
|
407
|
-
validation_error_code=400,
|
|
408
|
-
handle_validation_exceptions=False, # schema updated; the handler above owns the response
|
|
409
|
-
).versionize()
|
|
410
|
-
```
|
|
411
|
-
|
|
412
|
-
This also patches the app's own root `/docs`, `/redoc`, and `/openapi.json`, not just the
|
|
413
|
-
versioned ones, so there's nothing left showing the stale `422`.
|
|
414
|
-
|
|
415
417
|
Sharing one app across several `RouterVersioner` instances only makes sense for one reason:
|
|
416
418
|
mixing `version_format` values, SemVer for one group of routes and CalVer for another, on
|
|
417
419
|
the same app. Splitting modules that share a `version_format` doesn't need a second instance;
|
|
418
420
|
pass them all to one `RouterVersioner` via `routers=[...]` instead (see
|
|
419
421
|
[`multi_router_app.py`](https://github.com/mat81black/fastapi-router-versioning/blob/main/examples/multi_router_app.py)).
|
|
420
|
-
If you do share an app across instances,
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
router, so a mismatch raises `RuntimeError` when the second instance is constructed rather
|
|
425
|
-
than silently keeping whichever handler was registered first.
|
|
426
|
-
- Every instance needs its own `prefix_format`/`latest_prefix`. Two instances that resolve to
|
|
427
|
-
the same prefix would otherwise overwrite each other's docs/openapi routes at the same
|
|
428
|
-
path; this raises `RuntimeError` too.
|
|
422
|
+
If you do share an app across instances, one rule is enforced for you: every instance needs
|
|
423
|
+
its own `prefix_format`/`latest_prefix`. Two instances that resolve to the same prefix would
|
|
424
|
+
otherwise overwrite each other's docs/openapi routes at the same path; this raises
|
|
425
|
+
`RuntimeError`.
|
|
429
426
|
|
|
430
|
-
For modules that genuinely don't need to coordinate at all,
|
|
431
|
-
|
|
432
|
-
section).
|
|
427
|
+
For modules that genuinely don't need to coordinate at all, mount them as separate FastAPI
|
|
428
|
+
sub-applications instead (next section).
|
|
433
429
|
|
|
434
430
|
### Reverse proxy and sub-application mounting
|
|
435
431
|
|
|
@@ -444,7 +440,7 @@ parent.mount("/api", app) # root_path="/api" is injected per request
|
|
|
444
440
|
|
|
445
441
|
A mounted sub-application is a separate `FastAPI()` instance with its own `app.state`, so a
|
|
446
442
|
`RouterVersioner` attached to it is entirely independent from one attached to the parent, or
|
|
447
|
-
to another sub-application, no
|
|
443
|
+
to another sub-application, no prefix coordination needed.
|
|
448
444
|
See [`examples/mounted_subapps_app.py`](https://github.com/mat81black/fastapi-router-versioning/blob/main/examples/mounted_subapps_app.py).
|
|
449
445
|
|
|
450
446
|
### Callback hook
|
|
@@ -477,9 +473,8 @@ RouterVersioner(
|
|
|
477
473
|
| [`multi_router_app.py`](https://github.com/mat81black/fastapi-router-versioning/blob/main/examples/multi_router_app.py) | Several routers versioned together under one instance |
|
|
478
474
|
| [`self_hosted_docs_app.py`](https://github.com/mat81black/fastapi-router-versioning/blob/main/examples/self_hosted_docs_app.py) | Swagger UI and ReDoc served from local static assets |
|
|
479
475
|
| [`openapi_hook_app.py`](https://github.com/mat81black/fastapi-router-versioning/blob/main/examples/openapi_hook_app.py) | Per-version OpenAPI schema edits via `openapi_hook` |
|
|
480
|
-
| [`validation_error_code_app.py`](https://github.com/mat81black/fastapi-router-versioning/blob/main/examples/validation_error_code_app.py) | `400` instead of `422`, handled automatically by `RouterVersioner` |
|
|
481
|
-
| [`validation_error_code_custom_handler_app.py`](https://github.com/mat81black/fastapi-router-versioning/blob/main/examples/validation_error_code_custom_handler_app.py) | Same, but with `handle_validation_exceptions=False` and a custom handler |
|
|
482
476
|
| [`mounted_subapps_app.py`](https://github.com/mat81black/fastapi-router-versioning/blob/main/examples/mounted_subapps_app.py) | Independently versioned modules as separate `app.mount()` sub-applications |
|
|
477
|
+
| [`validation_override_integration_app.py`](https://github.com/mat81black/fastapi-router-versioning/blob/main/examples/validation_override_integration_app.py) | Custom validation error status code via `fastapi-validation-override` and `openapi_hook` |
|
|
483
478
|
|
|
484
479
|
---
|
|
485
480
|
|
|
@@ -18,7 +18,6 @@ Running multiple API versions side by side usually means duplicating routers, ha
|
|
|
18
18
|
- **Latest alias**: expose the newest version under a fixed `/latest` prefix clients can pin to
|
|
19
19
|
- **Self-hosted docs assets**: point Swagger UI and ReDoc at your own JS/CSS for air-gapped deployments
|
|
20
20
|
- **Reverse proxy and sub-app aware**: doc URLs pick up the ASGI `root_path` at request time
|
|
21
|
-
- **Configurable validation error status**: swap FastAPI's default `422` for any code, applied consistently to runtime responses and every OpenAPI schema, including the app's own root schema
|
|
22
21
|
- **Route composition support**: works across nested routers, WebSockets, `Depends`, and OpenAPI Callbacks
|
|
23
22
|
|
|
24
23
|
---
|
|
@@ -123,6 +122,15 @@ def legacy_route():
|
|
|
123
122
|
A route without `@api_version` isn't excluded, it falls back to `default_version`
|
|
124
123
|
(`(1, 0)` for SemVer, `"1"` for CalVer, unless overridden).
|
|
125
124
|
|
|
125
|
+
FastAPI's own `deprecated=True` (set directly on a route, or inherited from
|
|
126
|
+
`APIRouter(deprecated=True)`) is preserved as-is: `RouterVersioner` copies it into every
|
|
127
|
+
version unconditionally, on top of whatever `deprecate_in` computes. `deprecate_in` only
|
|
128
|
+
ever turns deprecation *on* for versions at or after its boundary, it never turns off a
|
|
129
|
+
`deprecated=True` that was already set natively. If you set both on the same route, it
|
|
130
|
+
shows as deprecated in every version, including ones before `deprecate_in`'s boundary.
|
|
131
|
+
Use one or the other: `deprecated=True` for an unconditional, version-independent flag,
|
|
132
|
+
`deprecate_in` for a per-version lifecycle.
|
|
133
|
+
|
|
126
134
|
---
|
|
127
135
|
|
|
128
136
|
## `RouterVersioner` reference
|
|
@@ -149,8 +157,6 @@ A route without `@api_version` isn't excluded, it falls back to `default_version
|
|
|
149
157
|
| `redoc_js_url` | `str \| None` | FastAPI CDN | Custom URL for the ReDoc JS bundle |
|
|
150
158
|
| `redoc_favicon_url` | `str \| None` | FastAPI favicon | Custom URL for the ReDoc favicon |
|
|
151
159
|
| `redoc_with_google_fonts` | `bool` | `True` | Set `False` to stop ReDoc from loading Google Fonts |
|
|
152
|
-
| `validation_error_code` | `int` | `422` | Status code returned for request validation errors; also replaces the `422` entry everywhere it appears in the OpenAPI schema, root schema included |
|
|
153
|
-
| `handle_validation_exceptions` | `bool` | `True` | Set `False` to only patch the schema and register your own `RequestValidationError` handler |
|
|
154
160
|
|
|
155
161
|
`.versionize()` returns the list of versions it activated. It can only be called once per
|
|
156
162
|
instance; a second call raises `RuntimeError`, since it mutates the live FastAPI app in a way
|
|
@@ -259,6 +265,41 @@ RouterVersioner(
|
|
|
259
265
|
).versionize()
|
|
260
266
|
```
|
|
261
267
|
|
|
268
|
+
### Custom validation error status code
|
|
269
|
+
|
|
270
|
+
Changing FastAPI's default `422` for request validation errors is not something
|
|
271
|
+
`RouterVersioner` does itself: it's a separate, general-purpose concern, handled by the
|
|
272
|
+
[fastapi-validation-override](https://pypi.org/project/fastapi-validation-override/) package.
|
|
273
|
+
`openapi_hook` is the integration point: it lets you re-apply the same patch to every
|
|
274
|
+
per-version schema that `RouterVersioner` generates, so all of them, root schema included,
|
|
275
|
+
stay consistent.
|
|
276
|
+
|
|
277
|
+
```bash
|
|
278
|
+
uv add fastapi-validation-override
|
|
279
|
+
```
|
|
280
|
+
|
|
281
|
+
```python
|
|
282
|
+
from fastapi_validation_override import override_validation_error, patch_422_responses
|
|
283
|
+
|
|
284
|
+
# 1. Registers the runtime handler and patches the app's own root /openapi.json.
|
|
285
|
+
override_validation_error(app, status_code=400)
|
|
286
|
+
|
|
287
|
+
# 2. Re-applies the same patch to each version's own schema.
|
|
288
|
+
def versioning_openapi_hook(schema: dict, version: tuple[int, int]) -> dict:
|
|
289
|
+
return patch_422_responses(schema, "400")
|
|
290
|
+
|
|
291
|
+
RouterVersioner(
|
|
292
|
+
app=app,
|
|
293
|
+
routers=router,
|
|
294
|
+
version_format=VersionFormat.SEMVER,
|
|
295
|
+
openapi_hook=versioning_openapi_hook,
|
|
296
|
+
).versionize()
|
|
297
|
+
# Validation failures now return 400, both at runtime and in every schema
|
|
298
|
+
# (root, and every /vX_Y/openapi.json)
|
|
299
|
+
```
|
|
300
|
+
|
|
301
|
+
See [`examples/validation_override_integration_app.py`](https://github.com/mat81black/fastapi-router-versioning/blob/main/examples/validation_override_integration_app.py).
|
|
302
|
+
|
|
262
303
|
### OpenAPI Callbacks and Webhooks
|
|
263
304
|
|
|
264
305
|
Route-level **Callbacks** need no special handling: a `callbacks=[...]` argument on a route
|
|
@@ -342,63 +383,18 @@ RouterVersioner(
|
|
|
342
383
|
[`examples/download_static_assets.py`](https://github.com/mat81black/fastapi-router-versioning/blob/main/examples/download_static_assets.py) downloads the required files in one step;
|
|
343
384
|
[`examples/self_hosted_docs_app.py`](https://github.com/mat81black/fastapi-router-versioning/blob/main/examples/self_hosted_docs_app.py) wires them into a full app.
|
|
344
385
|
|
|
345
|
-
### Validation error status code
|
|
346
|
-
|
|
347
|
-
`validation_error_code` changes what FastAPI returns for a failed request body/query/path
|
|
348
|
-
validation, `422` by default, both at runtime and in the schema:
|
|
349
|
-
|
|
350
|
-
```python
|
|
351
|
-
RouterVersioner(
|
|
352
|
-
app=app,
|
|
353
|
-
routers=router,
|
|
354
|
-
version_format=VersionFormat.SEMVER,
|
|
355
|
-
validation_error_code=400,
|
|
356
|
-
).versionize()
|
|
357
|
-
# Validation failures now return 400; every 422 entry in the schema becomes 400
|
|
358
|
-
```
|
|
359
|
-
|
|
360
|
-
Set `handle_validation_exceptions=False` to keep the schema change while writing your own
|
|
361
|
-
response body:
|
|
362
|
-
|
|
363
|
-
```python
|
|
364
|
-
from fastapi import Request
|
|
365
|
-
from fastapi.exceptions import RequestValidationError
|
|
366
|
-
from fastapi.responses import JSONResponse
|
|
367
|
-
|
|
368
|
-
@app.exception_handler(RequestValidationError)
|
|
369
|
-
async def my_handler(request: Request, exc: RequestValidationError) -> JSONResponse:
|
|
370
|
-
return JSONResponse(status_code=400, content={"errors": exc.errors()})
|
|
371
|
-
|
|
372
|
-
RouterVersioner(
|
|
373
|
-
app=app,
|
|
374
|
-
routers=router,
|
|
375
|
-
version_format=VersionFormat.SEMVER,
|
|
376
|
-
validation_error_code=400,
|
|
377
|
-
handle_validation_exceptions=False, # schema updated; the handler above owns the response
|
|
378
|
-
).versionize()
|
|
379
|
-
```
|
|
380
|
-
|
|
381
|
-
This also patches the app's own root `/docs`, `/redoc`, and `/openapi.json`, not just the
|
|
382
|
-
versioned ones, so there's nothing left showing the stale `422`.
|
|
383
|
-
|
|
384
386
|
Sharing one app across several `RouterVersioner` instances only makes sense for one reason:
|
|
385
387
|
mixing `version_format` values, SemVer for one group of routes and CalVer for another, on
|
|
386
388
|
the same app. Splitting modules that share a `version_format` doesn't need a second instance;
|
|
387
389
|
pass them all to one `RouterVersioner` via `routers=[...]` instead (see
|
|
388
390
|
[`multi_router_app.py`](https://github.com/mat81black/fastapi-router-versioning/blob/main/examples/multi_router_app.py)).
|
|
389
|
-
If you do share an app across instances,
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
router, so a mismatch raises `RuntimeError` when the second instance is constructed rather
|
|
394
|
-
than silently keeping whichever handler was registered first.
|
|
395
|
-
- Every instance needs its own `prefix_format`/`latest_prefix`. Two instances that resolve to
|
|
396
|
-
the same prefix would otherwise overwrite each other's docs/openapi routes at the same
|
|
397
|
-
path; this raises `RuntimeError` too.
|
|
391
|
+
If you do share an app across instances, one rule is enforced for you: every instance needs
|
|
392
|
+
its own `prefix_format`/`latest_prefix`. Two instances that resolve to the same prefix would
|
|
393
|
+
otherwise overwrite each other's docs/openapi routes at the same path; this raises
|
|
394
|
+
`RuntimeError`.
|
|
398
395
|
|
|
399
|
-
For modules that genuinely don't need to coordinate at all,
|
|
400
|
-
|
|
401
|
-
section).
|
|
396
|
+
For modules that genuinely don't need to coordinate at all, mount them as separate FastAPI
|
|
397
|
+
sub-applications instead (next section).
|
|
402
398
|
|
|
403
399
|
### Reverse proxy and sub-application mounting
|
|
404
400
|
|
|
@@ -413,7 +409,7 @@ parent.mount("/api", app) # root_path="/api" is injected per request
|
|
|
413
409
|
|
|
414
410
|
A mounted sub-application is a separate `FastAPI()` instance with its own `app.state`, so a
|
|
415
411
|
`RouterVersioner` attached to it is entirely independent from one attached to the parent, or
|
|
416
|
-
to another sub-application, no
|
|
412
|
+
to another sub-application, no prefix coordination needed.
|
|
417
413
|
See [`examples/mounted_subapps_app.py`](https://github.com/mat81black/fastapi-router-versioning/blob/main/examples/mounted_subapps_app.py).
|
|
418
414
|
|
|
419
415
|
### Callback hook
|
|
@@ -446,9 +442,8 @@ RouterVersioner(
|
|
|
446
442
|
| [`multi_router_app.py`](https://github.com/mat81black/fastapi-router-versioning/blob/main/examples/multi_router_app.py) | Several routers versioned together under one instance |
|
|
447
443
|
| [`self_hosted_docs_app.py`](https://github.com/mat81black/fastapi-router-versioning/blob/main/examples/self_hosted_docs_app.py) | Swagger UI and ReDoc served from local static assets |
|
|
448
444
|
| [`openapi_hook_app.py`](https://github.com/mat81black/fastapi-router-versioning/blob/main/examples/openapi_hook_app.py) | Per-version OpenAPI schema edits via `openapi_hook` |
|
|
449
|
-
| [`validation_error_code_app.py`](https://github.com/mat81black/fastapi-router-versioning/blob/main/examples/validation_error_code_app.py) | `400` instead of `422`, handled automatically by `RouterVersioner` |
|
|
450
|
-
| [`validation_error_code_custom_handler_app.py`](https://github.com/mat81black/fastapi-router-versioning/blob/main/examples/validation_error_code_custom_handler_app.py) | Same, but with `handle_validation_exceptions=False` and a custom handler |
|
|
451
445
|
| [`mounted_subapps_app.py`](https://github.com/mat81black/fastapi-router-versioning/blob/main/examples/mounted_subapps_app.py) | Independently versioned modules as separate `app.mount()` sub-applications |
|
|
446
|
+
| [`validation_override_integration_app.py`](https://github.com/mat81black/fastapi-router-versioning/blob/main/examples/validation_override_integration_app.py) | Custom validation error status code via `fastapi-validation-override` and `openapi_hook` |
|
|
452
447
|
|
|
453
448
|
---
|
|
454
449
|
|