mirror of
https://github.com/fastapi/fastapi.git
synced 2026-05-27 17:59:39 -04:00
Compare commits
21 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
2bd97a6013 | ||
|
|
a3558be5f8 | ||
|
|
c9343d2cf0 | ||
|
|
a53efbcae9 | ||
|
|
ad09734fa3 | ||
|
|
57535ef85b | ||
|
|
dbfd55cea3 | ||
|
|
59d4a80fcf | ||
|
|
6cbdde2315 | ||
|
|
1464678ba6 | ||
|
|
1a84bbc00b | ||
|
|
3fdc54edab | ||
|
|
09ba2cec98 | ||
|
|
3e3d38930e | ||
|
|
84f205c8f7 | ||
|
|
7baefe7144 | ||
|
|
2895c51ba8 | ||
|
|
21c46919fc | ||
|
|
8206485753 | ||
|
|
c910e0139f | ||
|
|
063b5bf582 |
27
.github/dependabot.yml
vendored
27
.github/dependabot.yml
vendored
@@ -4,26 +4,47 @@ updates:
|
||||
- package-ecosystem: "github-actions"
|
||||
directory: "/"
|
||||
schedule:
|
||||
interval: "daily"
|
||||
interval: "weekly"
|
||||
cooldown:
|
||||
default-days: 7
|
||||
commit-message:
|
||||
prefix: ⬆
|
||||
labels:
|
||||
- "internal"
|
||||
- "dependencies"
|
||||
- "github_actions"
|
||||
groups:
|
||||
github-actions:
|
||||
patterns:
|
||||
- "*"
|
||||
# Python
|
||||
- package-ecosystem: "uv"
|
||||
directory: "/"
|
||||
schedule:
|
||||
interval: "daily"
|
||||
interval: "weekly"
|
||||
cooldown:
|
||||
default-days: 7
|
||||
commit-message:
|
||||
prefix: ⬆
|
||||
groups:
|
||||
python-packages:
|
||||
dependency-type: "development"
|
||||
patterns:
|
||||
- "*"
|
||||
# pre-commit
|
||||
- package-ecosystem: "pre-commit"
|
||||
directory: "/"
|
||||
schedule:
|
||||
interval: "daily"
|
||||
interval: "weekly"
|
||||
cooldown:
|
||||
default-days: 7
|
||||
commit-message:
|
||||
prefix: ⬆
|
||||
labels:
|
||||
- "internal"
|
||||
- "dependencies"
|
||||
- "pre-commit"
|
||||
groups:
|
||||
pre-commit:
|
||||
patterns:
|
||||
- "*"
|
||||
|
||||
1
.github/workflows/add-to-project.yml
vendored
1
.github/workflows/add-to-project.yml
vendored
@@ -13,6 +13,7 @@ jobs:
|
||||
add-to-project:
|
||||
name: Add to project
|
||||
runs-on: ubuntu-latest
|
||||
timeout-minutes: 5
|
||||
steps:
|
||||
- uses: actions/add-to-project@5afcf98fcd03f1c2f92c3c83f58ae24323cc57fd # v2.0.0
|
||||
with:
|
||||
|
||||
7
.github/workflows/build-docs.yml
vendored
7
.github/workflows/build-docs.yml
vendored
@@ -16,6 +16,7 @@ jobs:
|
||||
# Required permissions
|
||||
permissions:
|
||||
pull-requests: read
|
||||
timeout-minutes: 5
|
||||
# Set job outputs to values from filter step
|
||||
outputs:
|
||||
docs: ${{ steps.filter.outputs.docs }}
|
||||
@@ -42,6 +43,7 @@ jobs:
|
||||
- changes
|
||||
if: ${{ needs.changes.outputs.docs == 'true' }}
|
||||
runs-on: ubuntu-latest
|
||||
timeout-minutes: 5
|
||||
outputs:
|
||||
langs: ${{ steps.show-langs.outputs.langs }}
|
||||
steps:
|
||||
@@ -55,6 +57,8 @@ jobs:
|
||||
- name: Setup uv
|
||||
uses: astral-sh/setup-uv@08807647e7069bb48b6ef5acd8ec9567f424441b # v8.1.0
|
||||
with:
|
||||
# Before upgrading uv version, make sure astral-sh/setup-uv knows its checksum.
|
||||
# See: https://github.com/astral-sh/setup-uv/issues/851#issuecomment-4282017837
|
||||
version: "0.11.4"
|
||||
enable-cache: true
|
||||
cache-dependency-glob: |
|
||||
@@ -73,6 +77,7 @@ jobs:
|
||||
- langs
|
||||
if: ${{ needs.changes.outputs.docs == 'true' }}
|
||||
runs-on: ubuntu-latest
|
||||
timeout-minutes: 7
|
||||
strategy:
|
||||
matrix:
|
||||
lang: ${{ fromJson(needs.langs.outputs.langs) }}
|
||||
@@ -91,6 +96,8 @@ jobs:
|
||||
- name: Setup uv
|
||||
uses: astral-sh/setup-uv@08807647e7069bb48b6ef5acd8ec9567f424441b # v8.1.0
|
||||
with:
|
||||
# Before upgrading uv version, make sure astral-sh/setup-uv knows its checksum.
|
||||
# See: https://github.com/astral-sh/setup-uv/issues/851#issuecomment-4282017837
|
||||
version: "0.11.4"
|
||||
enable-cache: true
|
||||
cache-dependency-glob: |
|
||||
|
||||
2
.github/workflows/contributors.yml
vendored
2
.github/workflows/contributors.yml
vendored
@@ -33,6 +33,8 @@ jobs:
|
||||
- name: Setup uv
|
||||
uses: astral-sh/setup-uv@08807647e7069bb48b6ef5acd8ec9567f424441b # v8.1.0
|
||||
with:
|
||||
# Before upgrading uv version, make sure astral-sh/setup-uv knows its checksum.
|
||||
# See: https://github.com/astral-sh/setup-uv/issues/851#issuecomment-4282017837
|
||||
version: "0.11.4"
|
||||
enable-cache: true
|
||||
cache-dependency-glob: |
|
||||
|
||||
3
.github/workflows/deploy-docs.yml
vendored
3
.github/workflows/deploy-docs.yml
vendored
@@ -16,6 +16,7 @@ jobs:
|
||||
issues: write
|
||||
pull-requests: write
|
||||
statuses: write
|
||||
timeout-minutes: 5
|
||||
steps:
|
||||
- name: Dump GitHub context
|
||||
env:
|
||||
@@ -31,6 +32,8 @@ jobs:
|
||||
- name: Setup uv
|
||||
uses: astral-sh/setup-uv@08807647e7069bb48b6ef5acd8ec9567f424441b # v8.1.0
|
||||
with:
|
||||
# Before upgrading uv version, make sure astral-sh/setup-uv knows its checksum.
|
||||
# See: https://github.com/astral-sh/setup-uv/issues/851#issuecomment-4282017837
|
||||
version: "0.11.4"
|
||||
enable-cache: false
|
||||
- name: Install GitHub Actions dependencies
|
||||
|
||||
1
.github/workflows/detect-conflicts.yml
vendored
1
.github/workflows/detect-conflicts.yml
vendored
@@ -12,6 +12,7 @@ jobs:
|
||||
contents: read
|
||||
pull-requests: write
|
||||
runs-on: ubuntu-latest
|
||||
timeout-minutes: 5
|
||||
steps:
|
||||
- name: Check if PRs have merge conflicts
|
||||
uses: eps1lon/actions-label-merge-conflict@1df065ebe6e3310545d4f4c4e862e43bdca146f0 # v3.0.3
|
||||
|
||||
1
.github/workflows/guard-dependencies.yml
vendored
1
.github/workflows/guard-dependencies.yml
vendored
@@ -15,6 +15,7 @@ permissions:
|
||||
jobs:
|
||||
check-author:
|
||||
runs-on: ubuntu-latest
|
||||
timeout-minutes: 5
|
||||
steps:
|
||||
- name: Check if author is org member or allowed bot
|
||||
uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0
|
||||
|
||||
1
.github/workflows/issue-manager.yml
vendored
1
.github/workflows/issue-manager.yml
vendored
@@ -23,6 +23,7 @@ jobs:
|
||||
permissions:
|
||||
issues: write
|
||||
pull-requests: write
|
||||
timeout-minutes: 5
|
||||
steps:
|
||||
- name: Dump GitHub context
|
||||
env:
|
||||
|
||||
3
.github/workflows/label-approved.yml
vendored
3
.github/workflows/label-approved.yml
vendored
@@ -13,6 +13,7 @@ jobs:
|
||||
runs-on: ubuntu-latest
|
||||
permissions:
|
||||
pull-requests: write
|
||||
timeout-minutes: 7
|
||||
steps:
|
||||
- name: Dump GitHub context
|
||||
env:
|
||||
@@ -28,6 +29,8 @@ jobs:
|
||||
- name: Setup uv
|
||||
uses: astral-sh/setup-uv@08807647e7069bb48b6ef5acd8ec9567f424441b # v8.1.0
|
||||
with:
|
||||
# Before upgrading uv version, make sure astral-sh/setup-uv knows its checksum.
|
||||
# See: https://github.com/astral-sh/setup-uv/issues/851#issuecomment-4282017837
|
||||
version: "0.11.4"
|
||||
enable-cache: true
|
||||
cache-dependency-glob: |
|
||||
|
||||
2
.github/workflows/labeler.yml
vendored
2
.github/workflows/labeler.yml
vendored
@@ -17,6 +17,7 @@ jobs:
|
||||
contents: read
|
||||
pull-requests: write
|
||||
runs-on: ubuntu-latest
|
||||
timeout-minutes: 5
|
||||
steps:
|
||||
- uses: actions/labeler@f27b608878404679385c85cfa523b85ccb86e213 # v6.1.0
|
||||
if: ${{ github.event.action != 'labeled' && github.event.action != 'unlabeled' }}
|
||||
@@ -28,6 +29,7 @@ jobs:
|
||||
permissions:
|
||||
pull-requests: read
|
||||
runs-on: ubuntu-latest
|
||||
timeout-minutes: 5
|
||||
steps:
|
||||
- uses: agilepathway/label-checker@c3d16ad512e7cea5961df85ff2486bb774caf3c5 # v1.6.65
|
||||
with:
|
||||
|
||||
1
.github/workflows/latest-changes.yml
vendored
1
.github/workflows/latest-changes.yml
vendored
@@ -22,6 +22,7 @@ jobs:
|
||||
latest-changes:
|
||||
runs-on: ubuntu-latest
|
||||
if: github.event_name == 'workflow_dispatch' || github.event.pull_request.merged == true
|
||||
timeout-minutes: 5
|
||||
steps:
|
||||
- name: Dump GitHub context
|
||||
env:
|
||||
|
||||
3
.github/workflows/notify-translations.yml
vendored
3
.github/workflows/notify-translations.yml
vendored
@@ -24,6 +24,7 @@ jobs:
|
||||
runs-on: ubuntu-latest
|
||||
permissions:
|
||||
discussions: write
|
||||
timeout-minutes: 5
|
||||
steps:
|
||||
- name: Dump GitHub context
|
||||
env:
|
||||
@@ -39,6 +40,8 @@ jobs:
|
||||
- name: Setup uv
|
||||
uses: astral-sh/setup-uv@08807647e7069bb48b6ef5acd8ec9567f424441b # v8.1.0
|
||||
with:
|
||||
# Before upgrading uv version, make sure astral-sh/setup-uv knows its checksum.
|
||||
# See: https://github.com/astral-sh/setup-uv/issues/851#issuecomment-4282017837
|
||||
version: "0.11.4"
|
||||
enable-cache: true
|
||||
cache-dependency-glob: |
|
||||
|
||||
2
.github/workflows/people.yml
vendored
2
.github/workflows/people.yml
vendored
@@ -33,6 +33,8 @@ jobs:
|
||||
- name: Setup uv
|
||||
uses: astral-sh/setup-uv@08807647e7069bb48b6ef5acd8ec9567f424441b # v8.1.0
|
||||
with:
|
||||
# Before upgrading uv version, make sure astral-sh/setup-uv knows its checksum.
|
||||
# See: https://github.com/astral-sh/setup-uv/issues/851#issuecomment-4282017837
|
||||
version: "0.11.4"
|
||||
enable-cache: true
|
||||
cache-dependency-glob: |
|
||||
|
||||
4
.github/workflows/pre-commit.yml
vendored
4
.github/workflows/pre-commit.yml
vendored
@@ -15,6 +15,7 @@ env:
|
||||
jobs:
|
||||
pre-commit:
|
||||
runs-on: ubuntu-latest
|
||||
timeout-minutes: 5
|
||||
steps:
|
||||
- name: Dump GitHub context
|
||||
env:
|
||||
@@ -48,6 +49,8 @@ jobs:
|
||||
- name: Setup uv
|
||||
uses: astral-sh/setup-uv@08807647e7069bb48b6ef5acd8ec9567f424441b # v8.1.0
|
||||
with:
|
||||
# Before upgrading uv version, make sure astral-sh/setup-uv knows its checksum.
|
||||
# See: https://github.com/astral-sh/setup-uv/issues/851#issuecomment-4282017837
|
||||
version: "0.11.4"
|
||||
cache-dependency-glob: |
|
||||
pyproject.toml
|
||||
@@ -84,6 +87,7 @@ jobs:
|
||||
needs:
|
||||
- pre-commit
|
||||
runs-on: ubuntu-latest
|
||||
timeout-minutes: 5
|
||||
steps:
|
||||
- name: Dump GitHub context
|
||||
env:
|
||||
|
||||
4
.github/workflows/publish.yml
vendored
4
.github/workflows/publish.yml
vendored
@@ -13,6 +13,7 @@ jobs:
|
||||
permissions:
|
||||
id-token: write
|
||||
contents: read
|
||||
timeout-minutes: 5
|
||||
steps:
|
||||
- name: Dump GitHub context
|
||||
env:
|
||||
@@ -28,7 +29,10 @@ jobs:
|
||||
- name: Install uv
|
||||
uses: astral-sh/setup-uv@08807647e7069bb48b6ef5acd8ec9567f424441b # v8.1.0
|
||||
with:
|
||||
# Before upgrading uv version, make sure astral-sh/setup-uv knows its checksum.
|
||||
# See: https://github.com/astral-sh/setup-uv/issues/851#issuecomment-4282017837
|
||||
version: "0.11.4"
|
||||
enable-cache: "false"
|
||||
- name: Build distribution
|
||||
run: uv build
|
||||
- name: Publish
|
||||
|
||||
3
.github/workflows/smokeshow.yml
vendored
3
.github/workflows/smokeshow.yml
vendored
@@ -12,6 +12,7 @@ jobs:
|
||||
runs-on: ubuntu-latest
|
||||
permissions:
|
||||
statuses: write
|
||||
timeout-minutes: 5
|
||||
|
||||
steps:
|
||||
- name: Dump GitHub context
|
||||
@@ -27,6 +28,8 @@ jobs:
|
||||
- name: Setup uv
|
||||
uses: astral-sh/setup-uv@08807647e7069bb48b6ef5acd8ec9567f424441b # v8.1.0
|
||||
with:
|
||||
# Before upgrading uv version, make sure astral-sh/setup-uv knows its checksum.
|
||||
# See: https://github.com/astral-sh/setup-uv/issues/851#issuecomment-4282017837
|
||||
version: "0.11.4"
|
||||
cache-dependency-glob: |
|
||||
pyproject.toml
|
||||
|
||||
3
.github/workflows/sponsors.yml
vendored
3
.github/workflows/sponsors.yml
vendored
@@ -18,6 +18,7 @@ jobs:
|
||||
runs-on: ubuntu-latest
|
||||
permissions:
|
||||
contents: write
|
||||
timeout-minutes: 5
|
||||
steps:
|
||||
- name: Dump GitHub context
|
||||
env:
|
||||
@@ -33,6 +34,8 @@ jobs:
|
||||
- name: Setup uv
|
||||
uses: astral-sh/setup-uv@08807647e7069bb48b6ef5acd8ec9567f424441b # v8.1.0
|
||||
with:
|
||||
# Before upgrading uv version, make sure astral-sh/setup-uv knows its checksum.
|
||||
# See: https://github.com/astral-sh/setup-uv/issues/851#issuecomment-4282017837
|
||||
version: "0.11.4"
|
||||
enable-cache: true
|
||||
cache-dependency-glob: |
|
||||
|
||||
2
.github/workflows/test-redistribute.yml
vendored
2
.github/workflows/test-redistribute.yml
vendored
@@ -14,6 +14,7 @@ permissions: {}
|
||||
jobs:
|
||||
test-redistribute:
|
||||
runs-on: ubuntu-latest
|
||||
timeout-minutes: 5
|
||||
steps:
|
||||
- name: Dump GitHub context
|
||||
env:
|
||||
@@ -57,6 +58,7 @@ jobs:
|
||||
needs:
|
||||
- test-redistribute
|
||||
runs-on: ubuntu-latest
|
||||
timeout-minutes: 5
|
||||
steps:
|
||||
- name: Decide whether the needed jobs succeeded or failed
|
||||
uses: re-actors/alls-green@05ac9388f0aebcb5727afa17fcccfecd6f8ec5fe # v1.2.2
|
||||
|
||||
22
.github/workflows/test.yml
vendored
22
.github/workflows/test.yml
vendored
@@ -25,6 +25,7 @@ jobs:
|
||||
permissions:
|
||||
pull-requests: read
|
||||
# Set job outputs to values from filter step
|
||||
timeout-minutes: 5
|
||||
outputs:
|
||||
src: ${{ steps.filter.outputs.src }}
|
||||
steps:
|
||||
@@ -50,6 +51,7 @@ jobs:
|
||||
needs:
|
||||
- changes
|
||||
if: needs.changes.outputs.src == 'true' || github.ref == 'refs/heads/master'
|
||||
timeout-minutes: 10
|
||||
strategy:
|
||||
matrix:
|
||||
os: [ windows-latest, macos-latest ]
|
||||
@@ -81,6 +83,11 @@ jobs:
|
||||
uv-resolution: highest
|
||||
codspeed: codspeed
|
||||
deprecated-tests: "no-deprecation"
|
||||
- os: ubuntu-latest
|
||||
python-version: "3.13"
|
||||
uv-resolution: highest
|
||||
deprecated-tests: "no-deprecation"
|
||||
without-httpx2: true
|
||||
- os: ubuntu-latest
|
||||
python-version: "3.14"
|
||||
coverage: coverage
|
||||
@@ -113,6 +120,8 @@ jobs:
|
||||
- name: Setup uv
|
||||
uses: astral-sh/setup-uv@08807647e7069bb48b6ef5acd8ec9567f424441b # v8.1.0
|
||||
with:
|
||||
# Before upgrading uv version, make sure astral-sh/setup-uv knows its checksum.
|
||||
# See: https://github.com/astral-sh/setup-uv/issues/851#issuecomment-4282017837
|
||||
version: "0.11.4"
|
||||
enable-cache: true
|
||||
cache-dependency-glob: |
|
||||
@@ -129,15 +138,19 @@ jobs:
|
||||
- name: Install deprecated libraries just for testing
|
||||
if: matrix.deprecated-tests == 'test-deprecation'
|
||||
run: uv pip install orjson ujson
|
||||
- name: Uninstall httpx2 to run tests with httpx
|
||||
if: matrix.without-httpx2 == 'true'
|
||||
run: uv pip uninstall httpx2
|
||||
- name: Reinstall SQLAlchemy without Cython extensions
|
||||
if: matrix.python-version == '3.14t' && matrix.os == 'ubuntu-latest'
|
||||
run: "DISABLE_SQLALCHEMY_CEXT=1 uv pip install --force-reinstall --no-binary :all: sqlalchemy"
|
||||
- run: mkdir coverage
|
||||
- name: Test
|
||||
run: uv run --no-sync bash scripts/test-cov.sh
|
||||
run: uv run --no-sync bash scripts/test-cov.sh $PYTEST_OPTIONS
|
||||
env:
|
||||
COVERAGE_FILE: coverage/.coverage.${{ runner.os }}-py${{ matrix.python-version }}-${{ matrix.deprecated-tests}}
|
||||
CONTEXT: ${{ runner.os }}-py${{ matrix.python-version }}-${{ matrix.deprecated-tests}}
|
||||
PYTEST_OPTIONS: ${{ (matrix.without-httpx2 == 'true') && '-W ignore::UserWarning' || '' }}
|
||||
# Do not store coverage for all possible combinations to avoid file size max errors in Smokeshow
|
||||
- name: Store coverage files
|
||||
if: matrix.coverage == 'coverage'
|
||||
@@ -152,6 +165,7 @@ jobs:
|
||||
- changes
|
||||
if: needs.changes.outputs.src == 'true' || github.ref == 'refs/heads/master'
|
||||
runs-on: ubuntu-latest
|
||||
timeout-minutes: 5
|
||||
env:
|
||||
UV_PYTHON: "3.13"
|
||||
UV_RESOLUTION: highest
|
||||
@@ -170,6 +184,8 @@ jobs:
|
||||
- name: Setup uv
|
||||
uses: astral-sh/setup-uv@08807647e7069bb48b6ef5acd8ec9567f424441b # v8.1.0
|
||||
with:
|
||||
# Before upgrading uv version, make sure astral-sh/setup-uv knows its checksum.
|
||||
# See: https://github.com/astral-sh/setup-uv/issues/851#issuecomment-4282017837
|
||||
version: "0.11.4"
|
||||
enable-cache: true
|
||||
cache-dependency-glob: |
|
||||
@@ -187,6 +203,7 @@ jobs:
|
||||
needs:
|
||||
- test
|
||||
runs-on: ubuntu-latest
|
||||
timeout-minutes: 5
|
||||
steps:
|
||||
- name: Dump GitHub context
|
||||
env:
|
||||
@@ -201,6 +218,8 @@ jobs:
|
||||
- name: Setup uv
|
||||
uses: astral-sh/setup-uv@08807647e7069bb48b6ef5acd8ec9567f424441b # v8.1.0
|
||||
with:
|
||||
# Before upgrading uv version, make sure astral-sh/setup-uv knows its checksum.
|
||||
# See: https://github.com/astral-sh/setup-uv/issues/851#issuecomment-4282017837
|
||||
version: "0.11.4"
|
||||
enable-cache: true
|
||||
cache-dependency-glob: |
|
||||
@@ -232,6 +251,7 @@ jobs:
|
||||
- coverage-combine
|
||||
- benchmark
|
||||
runs-on: ubuntu-latest
|
||||
timeout-minutes: 5
|
||||
steps:
|
||||
- name: Dump GitHub context
|
||||
env:
|
||||
|
||||
3
.github/workflows/topic-repos.yml
vendored
3
.github/workflows/topic-repos.yml
vendored
@@ -13,6 +13,7 @@ jobs:
|
||||
runs-on: ubuntu-latest
|
||||
permissions:
|
||||
contents: write
|
||||
timeout-minutes: 5
|
||||
steps:
|
||||
- name: Dump GitHub context
|
||||
env:
|
||||
@@ -28,6 +29,8 @@ jobs:
|
||||
- name: Setup uv
|
||||
uses: astral-sh/setup-uv@08807647e7069bb48b6ef5acd8ec9567f424441b # v8.1.0
|
||||
with:
|
||||
# Before upgrading uv version, make sure astral-sh/setup-uv knows its checksum.
|
||||
# See: https://github.com/astral-sh/setup-uv/issues/851#issuecomment-4282017837
|
||||
version: "0.11.4"
|
||||
enable-cache: true
|
||||
cache-dependency-glob: |
|
||||
|
||||
4
.github/workflows/translate.yml
vendored
4
.github/workflows/translate.yml
vendored
@@ -60,6 +60,8 @@ jobs:
|
||||
- name: Setup uv
|
||||
uses: astral-sh/setup-uv@08807647e7069bb48b6ef5acd8ec9567f424441b # v8.1.0
|
||||
with:
|
||||
# Before upgrading uv version, make sure astral-sh/setup-uv knows its checksum.
|
||||
# See: https://github.com/astral-sh/setup-uv/issues/851#issuecomment-4282017837
|
||||
version: "0.11.4"
|
||||
cache-dependency-glob: |
|
||||
pyproject.toml
|
||||
@@ -101,6 +103,8 @@ jobs:
|
||||
- name: Setup uv
|
||||
uses: astral-sh/setup-uv@08807647e7069bb48b6ef5acd8ec9567f424441b # v8.1.0
|
||||
with:
|
||||
# Before upgrading uv version, make sure astral-sh/setup-uv knows its checksum.
|
||||
# See: https://github.com/astral-sh/setup-uv/issues/851#issuecomment-4282017837
|
||||
version: "0.11.4"
|
||||
cache-dependency-glob: |
|
||||
pyproject.toml
|
||||
|
||||
24
.github/workflows/zizmor.yml
vendored
Normal file
24
.github/workflows/zizmor.yml
vendored
Normal file
@@ -0,0 +1,24 @@
|
||||
name: Zizmor
|
||||
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- main
|
||||
workflow_dispatch:
|
||||
|
||||
permissions: {}
|
||||
|
||||
jobs:
|
||||
zizmor:
|
||||
name: Run zizmor
|
||||
runs-on: ubuntu-latest
|
||||
timeout-minutes: 5
|
||||
permissions:
|
||||
security-events: write # Required for upload-sarif (used by zizmor-action) to upload SARIF files.
|
||||
steps:
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
|
||||
with:
|
||||
persist-credentials: false
|
||||
- name: Run zizmor
|
||||
uses: zizmorcore/zizmor-action@b1d7e1fb5de872772f31590499237e7cce841e8e # v0.5.3
|
||||
@@ -96,6 +96,6 @@ repos:
|
||||
name: zizmor
|
||||
language: python
|
||||
entry: uv run zizmor .
|
||||
files: ^\.github\/workflows\/
|
||||
files: ^\.github/workflows/|^uv\.lock$
|
||||
require_serial: true
|
||||
pass_filenames: false
|
||||
|
||||
@@ -56,7 +56,6 @@ There are several alternatives, including:
|
||||
* [Hypercorn](https://hypercorn.readthedocs.io/): an ASGI server compatible with HTTP/2 and Trio among other features.
|
||||
* [Daphne](https://github.com/django/daphne): the ASGI server built for Django Channels.
|
||||
* [Granian](https://github.com/emmett-framework/granian): A Rust HTTP server for Python applications.
|
||||
* [NGINX Unit](https://unit.nginx.org/howto/fastapi/): NGINX Unit is a lightweight and versatile web application runtime.
|
||||
|
||||
## Server Machine and Server Program { #server-machine-and-server-program }
|
||||
|
||||
|
||||
@@ -7,6 +7,27 @@ hide:
|
||||
|
||||
## Latest Changes
|
||||
|
||||
### Docs
|
||||
|
||||
* ✏️ Use `Annotated` in inline example in `docs/en/docs/tutorial/body-multiple-params.md`. PR [#15591](https://github.com/fastapi/fastapi/pull/15591) by [@TheArchons](https://github.com/TheArchons).
|
||||
* 📝 Remove "NGINX Unit" from the list of ASGI-servers in docs. PR [#15475](https://github.com/fastapi/fastapi/pull/15475) by [@angryfoxx](https://github.com/angryfoxx).
|
||||
* 📝 Update `docs/en/docs/tutorial/security/oauth2-jwt.md`. PR [#14781](https://github.com/fastapi/fastapi/pull/14781) by [@zadevhub](https://github.com/zadevhub).
|
||||
|
||||
### Internal
|
||||
|
||||
* 🔒️ Improve GitHub actions security. PR [#15607](https://github.com/fastapi/fastapi/pull/15607) by [@YuriiMotov](https://github.com/YuriiMotov).
|
||||
* ⚰️ Remove ruff and coverage ignores for non-existing files. PR [#15610](https://github.com/fastapi/fastapi/pull/15610) by [@YuriiMotov](https://github.com/YuriiMotov).
|
||||
* ✅ Use custom `changing_dir` instead of `CLIRunner.isolated_filesystem` to set working dir. PR [#15616](https://github.com/fastapi/fastapi/pull/15616) by [@YuriiMotov](https://github.com/YuriiMotov).
|
||||
* ✅ Add `httpx2` test dependency to avoid deprecation warning. PR [#15603](https://github.com/fastapi/fastapi/pull/15603) by [@YuriiMotov](https://github.com/YuriiMotov).
|
||||
* ⬆ Bump the python-packages group with 15 updates. PR [#15594](https://github.com/fastapi/fastapi/pull/15594) by [@dependabot[bot]](https://github.com/apps/dependabot).
|
||||
* 👷 Configure Dependabot to group updates and update weekly. PR [#15560](https://github.com/fastapi/fastapi/pull/15560) by [@YuriiMotov](https://github.com/YuriiMotov).
|
||||
|
||||
## 0.136.3 (2026-05-23)
|
||||
|
||||
### Refactors
|
||||
|
||||
* ♻️ Do not accept underscore headers when using `convert_underscores=True` (the default). PR [#15589](https://github.com/fastapi/fastapi/pull/15589) by [@tiangolo](https://github.com/tiangolo).
|
||||
|
||||
## 0.136.2 (2026-05-23)
|
||||
|
||||
### Refactors
|
||||
|
||||
@@ -126,7 +126,7 @@ By default, **FastAPI** will then expect its body directly.
|
||||
But if you want it to expect a JSON with a key `item` and inside of it the model contents, as it does when you declare extra body parameters, you can use the special `Body` parameter `embed`:
|
||||
|
||||
```Python
|
||||
item: Item = Body(embed=True)
|
||||
item: Annotated[Item, Body(embed=True)]
|
||||
```
|
||||
|
||||
as in:
|
||||
|
||||
@@ -18,7 +18,7 @@ eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4
|
||||
|
||||
It is not encrypted, so, anyone could recover the information from the contents.
|
||||
|
||||
But it's signed. So, when you receive a token that you emitted, you can verify that you actually emitted it.
|
||||
But it's signed. So, when you receive a token that you issued, you can verify that it was you who issued it.
|
||||
|
||||
That way, you can create a token with an expiration of, let's say, 1 week. And then when the user comes back the next day with the token, you know that user is still logged in to your system.
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
"""FastAPI framework, high performance, easy to learn, fast to code, ready for production"""
|
||||
|
||||
__version__ = "0.136.2"
|
||||
__version__ = "0.136.3"
|
||||
|
||||
from starlette import status as status
|
||||
|
||||
|
||||
@@ -826,6 +826,10 @@ def request_params_to_args(
|
||||
if value is not None:
|
||||
params_to_process[get_validation_alias(field)] = value
|
||||
processed_keys.add(alias or get_validation_alias(field))
|
||||
# For headers with convert_underscores=True, mark both the converted
|
||||
# header name and the original field alias as processed to avoid
|
||||
# accepting the original alias as an extra header.
|
||||
processed_keys.add(get_validation_alias(field))
|
||||
|
||||
for key in received_params.keys():
|
||||
if key not in processed_keys:
|
||||
|
||||
@@ -146,6 +146,7 @@ docs = [
|
||||
]
|
||||
docs-tests = [
|
||||
"httpx >=0.23.0,<1.0.0",
|
||||
"httpx2>=2.0.0",
|
||||
"ruff >=0.14.14",
|
||||
]
|
||||
github-actions = [
|
||||
@@ -242,7 +243,6 @@ relative_files = true
|
||||
context = '${CONTEXT}'
|
||||
omit = [
|
||||
"tests/benchmarks/*",
|
||||
"docs_src/response_model/tutorial003_04_py39.py",
|
||||
"docs_src/response_model/tutorial003_04_py310.py",
|
||||
"docs_src/dependencies/tutorial013_an_py310.py", # temporary code example?
|
||||
"docs_src/dependencies/tutorial014_an_py310.py", # temporary code example?
|
||||
@@ -279,41 +279,21 @@ ignore = [
|
||||
[tool.ruff.lint.per-file-ignores]
|
||||
"__init__.py" = ["F401"]
|
||||
"docs_src/custom_request_and_route/tutorial002_an_py310.py" = ["B904"]
|
||||
"docs_src/custom_request_and_route/tutorial002_an_py39.py" = ["B904"]
|
||||
"docs_src/custom_request_and_route/tutorial002_py310.py" = ["B904"]
|
||||
"docs_src/custom_request_and_route/tutorial002_py39.py" = ["B904"]
|
||||
"docs_src/custom_response/tutorial007_py310.py" = ["B007"]
|
||||
"docs_src/custom_response/tutorial007_py39.py" = ["B007"]
|
||||
"docs_src/dataclasses/tutorial003_py39.py" = ["I001"]
|
||||
"docs_src/dependencies/tutorial007_py310.py" = ["F821"]
|
||||
"docs_src/dependencies/tutorial007_py39.py" = ["F821"]
|
||||
"docs_src/dependencies/tutorial008_an_py310.py" = ["F821"]
|
||||
"docs_src/dependencies/tutorial008_an_py39.py" = ["F821"]
|
||||
"docs_src/dependencies/tutorial008_py310.py" = ["F821"]
|
||||
"docs_src/dependencies/tutorial008_py39.py" = ["F821"]
|
||||
"docs_src/dependencies/tutorial008b_an_py310.py" = ["B904"]
|
||||
"docs_src/dependencies/tutorial008b_an_py39.py" = ["B904"]
|
||||
"docs_src/dependencies/tutorial008b_py310.py" = ["B904"]
|
||||
"docs_src/dependencies/tutorial008b_py39.py" = ["B904"]
|
||||
"docs_src/dependencies/tutorial009_py310.py" = ["F821"]
|
||||
"docs_src/dependencies/tutorial009_py39.py" = ["F821"]
|
||||
"docs_src/dependencies/tutorial010_py310.py" = ["F821"]
|
||||
"docs_src/dependencies/tutorial010_py39.py" = ["F821"]
|
||||
"docs_src/path_operation_advanced_configuration/tutorial007_pv1_py39.py" = ["B904"]
|
||||
"docs_src/path_operation_advanced_configuration/tutorial007_py310.py" = ["B904"]
|
||||
"docs_src/path_operation_advanced_configuration/tutorial007_py39.py" = ["B904"]
|
||||
"docs_src/query_params_str_validations/tutorial012_an_py310.py" = ["B006"]
|
||||
"docs_src/query_params_str_validations/tutorial012_an_py39.py" = ["B006"]
|
||||
"docs_src/query_params_str_validations/tutorial013_an_py310.py" = ["B006"]
|
||||
"docs_src/query_params_str_validations/tutorial013_an_py39.py" = ["B006"]
|
||||
"docs_src/security/tutorial004_an_py310.py" = ["B904"]
|
||||
"docs_src/security/tutorial004_an_py39.py" = ["B904"]
|
||||
"docs_src/security/tutorial004_py310.py" = ["B904"]
|
||||
"docs_src/security/tutorial004_py39.py" = ["B904"]
|
||||
"docs_src/security/tutorial005_an_py310.py" = ["B904"]
|
||||
"docs_src/security/tutorial005_an_py39.py" = ["B904"]
|
||||
"docs_src/security/tutorial005_py310.py" = ["B904"]
|
||||
"docs_src/security/tutorial005_py39.py" = ["B904"]
|
||||
"docs_src/json_base64_bytes/tutorial001_py310.py" = ["UP012"]
|
||||
"docs_src/stream_json_lines/tutorial001_py310.py" = ["UP028"]
|
||||
"docs_src/stream_data/tutorial001_py310.py" = ["UP028"]
|
||||
|
||||
@@ -1,5 +1,8 @@
|
||||
import os
|
||||
import shutil
|
||||
import sys
|
||||
from collections.abc import Generator
|
||||
from contextlib import contextmanager
|
||||
from pathlib import Path
|
||||
|
||||
import pytest
|
||||
@@ -23,11 +26,20 @@ def pytest_collection_modifyitems(config, items: list[pytest.Item]) -> None:
|
||||
item.add_marker(skip_on_windows)
|
||||
|
||||
|
||||
@contextmanager
|
||||
def changing_dir(directory: str | Path) -> Generator[None, None, None]:
|
||||
initial_dir = os.getcwd()
|
||||
os.chdir(directory)
|
||||
try:
|
||||
yield
|
||||
finally:
|
||||
os.chdir(initial_dir)
|
||||
|
||||
|
||||
@pytest.fixture(name="runner")
|
||||
def get_runner():
|
||||
runner = CliRunner()
|
||||
with runner.isolated_filesystem():
|
||||
yield runner
|
||||
def get_runner(tmp_path: Path):
|
||||
with changing_dir(tmp_path):
|
||||
yield CliRunner()
|
||||
|
||||
|
||||
@pytest.fixture(name="root_dir")
|
||||
|
||||
@@ -11,6 +11,10 @@ class Model(BaseModel):
|
||||
model_config = {"extra": "allow"}
|
||||
|
||||
|
||||
class AuthHeaders(BaseModel):
|
||||
x_user_id: str
|
||||
|
||||
|
||||
@app.get("/query")
|
||||
async def query_model_with_extra(data: Model = Query()):
|
||||
return data
|
||||
@@ -26,6 +30,11 @@ async def cookies_model_with_extra(data: Model = Cookie()):
|
||||
return data
|
||||
|
||||
|
||||
@app.get("/header-requires-hyphen")
|
||||
async def header_model_requires_hyphen(data: AuthHeaders = Header()):
|
||||
return data
|
||||
|
||||
|
||||
def test_query_pass_extra_list():
|
||||
client = TestClient(app)
|
||||
resp = client.get(
|
||||
@@ -91,6 +100,32 @@ def test_header_pass_extra_single():
|
||||
assert resp_json["param2"] == "456"
|
||||
|
||||
|
||||
def test_header_model_prefers_hyphenated_header_with_convert_underscores():
|
||||
client = TestClient(app)
|
||||
|
||||
resp = client.get(
|
||||
"/header-requires-hyphen",
|
||||
headers=[
|
||||
("x-user-id", "hyphenated-value"),
|
||||
("x_user_id", "underscore-value"),
|
||||
],
|
||||
)
|
||||
|
||||
assert resp.status_code == 200
|
||||
assert resp.json() == {"x_user_id": "hyphenated-value"}
|
||||
|
||||
|
||||
def test_header_model_rejects_underscore_header_with_convert_underscores():
|
||||
client = TestClient(app)
|
||||
|
||||
resp = client.get(
|
||||
"/header-requires-hyphen", headers={"x_user_id": "underscore-value"}
|
||||
)
|
||||
|
||||
assert resp.status_code == 422
|
||||
assert resp.json()["detail"][0]["loc"] == ["header", "x_user_id"]
|
||||
|
||||
|
||||
def test_cookie_pass_extra_list():
|
||||
client = TestClient(app)
|
||||
client.cookies = [
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import importlib
|
||||
|
||||
import pytest
|
||||
from dirty_equals import IsOneOf
|
||||
from fastapi.testclient import TestClient
|
||||
from inline_snapshot import snapshot
|
||||
|
||||
@@ -68,7 +69,9 @@ def test_header_param_model_invalid(client: TestClient):
|
||||
"x_tag": [],
|
||||
"host": "testserver",
|
||||
"accept": "*/*",
|
||||
"accept-encoding": "gzip, deflate",
|
||||
"accept-encoding": IsOneOf(
|
||||
"gzip, deflate", "gzip, deflate, zstd"
|
||||
),
|
||||
"connection": "keep-alive",
|
||||
"user-agent": "testclient",
|
||||
},
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import importlib
|
||||
|
||||
import pytest
|
||||
from dirty_equals import IsOneOf
|
||||
from fastapi.testclient import TestClient
|
||||
from inline_snapshot import snapshot
|
||||
|
||||
@@ -66,7 +67,9 @@ def test_header_param_model_no_underscore(client: TestClient):
|
||||
"traceparent": "123",
|
||||
"x_tag": [],
|
||||
"accept": "*/*",
|
||||
"accept-encoding": "gzip, deflate",
|
||||
"accept-encoding": IsOneOf(
|
||||
"gzip, deflate", "gzip, deflate, zstd"
|
||||
),
|
||||
"connection": "keep-alive",
|
||||
"user-agent": "testclient",
|
||||
"save-data": "true",
|
||||
@@ -105,7 +108,9 @@ def test_header_param_model_invalid(client: TestClient):
|
||||
"x_tag": [],
|
||||
"host": "testserver",
|
||||
"accept": "*/*",
|
||||
"accept-encoding": "gzip, deflate",
|
||||
"accept-encoding": IsOneOf(
|
||||
"gzip, deflate", "gzip, deflate, zstd"
|
||||
),
|
||||
"connection": "keep-alive",
|
||||
"user-agent": "testclient",
|
||||
},
|
||||
|
||||
Reference in New Issue
Block a user