diff --git a/.flake8 b/.flake8
deleted file mode 100644
index 47ef7c07fc..0000000000
--- a/.flake8
+++ /dev/null
@@ -1,5 +0,0 @@
-[flake8]
-max-line-length = 88
-select = C,E,F,W,B,B9
-ignore = E203, E501, W503
-exclude = __init__.py
diff --git a/.github/actions/notify-translations/app/translations.yml b/.github/actions/notify-translations/app/translations.yml
index b43aba01d0..4338e1326e 100644
--- a/.github/actions/notify-translations/app/translations.yml
+++ b/.github/actions/notify-translations/app/translations.yml
@@ -18,3 +18,4 @@ uz: 4883
sv: 5146
he: 5157
ta: 5434
+ar: 3349
diff --git a/.github/actions/people/app/main.py b/.github/actions/people/app/main.py
index cdf423b97b..31756a5fcb 100644
--- a/.github/actions/people/app/main.py
+++ b/.github/actions/people/app/main.py
@@ -433,7 +433,7 @@ if __name__ == "__main__":
)
authors = {**issue_authors, **pr_authors}
maintainers_logins = {"tiangolo"}
- bot_names = {"codecov", "github-actions"}
+ bot_names = {"codecov", "github-actions", "pre-commit-ci", "dependabot"}
maintainers = []
for login in maintainers_logins:
user = authors[login]
diff --git a/.github/workflows/build-docs.yml b/.github/workflows/build-docs.yml
index 3052ec1e2b..b9bd521b3f 100644
--- a/.github/workflows/build-docs.yml
+++ b/.github/workflows/build-docs.yml
@@ -36,9 +36,9 @@ jobs:
- uses: actions/upload-artifact@v3
with:
name: docs-zip
- path: ./docs.zip
+ path: ./site/docs.zip
- name: Deploy to Netlify
- uses: nwtgck/actions-netlify@v1.2.4
+ uses: nwtgck/actions-netlify@v2.0.0
with:
publish-dir: './site'
production-branch: master
diff --git a/.github/workflows/preview-docs.yml b/.github/workflows/preview-docs.yml
index 15c59d4bd4..7d31a9c64e 100644
--- a/.github/workflows/preview-docs.yml
+++ b/.github/workflows/preview-docs.yml
@@ -11,21 +11,26 @@ jobs:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
+ - name: Clean site
+ run: |
+ rm -rf ./site
+ mkdir ./site
- name: Download Artifact Docs
- uses: dawidd6/action-download-artifact@v2.24.0
+ uses: dawidd6/action-download-artifact@v2.24.2
with:
github_token: ${{ secrets.GITHUB_TOKEN }}
workflow: build-docs.yml
run_id: ${{ github.event.workflow_run.id }}
name: docs-zip
+ path: ./site/
- name: Unzip docs
run: |
- rm -rf ./site
+ cd ./site
unzip docs.zip
rm -f docs.zip
- name: Deploy to Netlify
id: netlify
- uses: nwtgck/actions-netlify@v1.2.4
+ uses: nwtgck/actions-netlify@v2.0.0
with:
publish-dir: './site'
production-deploy: false
diff --git a/.github/workflows/publish.yml b/.github/workflows/publish.yml
index fe4c5ee86c..8ffb493a4f 100644
--- a/.github/workflows/publish.yml
+++ b/.github/workflows/publish.yml
@@ -18,6 +18,8 @@ jobs:
uses: actions/setup-python@v4
with:
python-version: "3.7"
+ cache: "pip"
+ cache-dependency-path: pyproject.toml
- uses: actions/cache@v3
id: cache
with:
@@ -29,7 +31,7 @@ jobs:
- name: Build distribution
run: python -m build
- name: Publish
- uses: pypa/gh-action-pypi-publish@v1.5.1
+ uses: pypa/gh-action-pypi-publish@v1.5.2
with:
password: ${{ secrets.PYPI_API_TOKEN }}
- name: Dump GitHub context
diff --git a/.github/workflows/smokeshow.yml b/.github/workflows/smokeshow.yml
new file mode 100644
index 0000000000..7559c24c06
--- /dev/null
+++ b/.github/workflows/smokeshow.yml
@@ -0,0 +1,35 @@
+name: Smokeshow
+
+on:
+ workflow_run:
+ workflows: [Test]
+ types: [completed]
+
+permissions:
+ statuses: write
+
+jobs:
+ smokeshow:
+ if: ${{ github.event.workflow_run.conclusion == 'success' }}
+ runs-on: ubuntu-latest
+
+ steps:
+ - uses: actions/setup-python@v4
+ with:
+ python-version: '3.9'
+
+ - run: pip install smokeshow
+
+ - uses: dawidd6/action-download-artifact@v2.24.2
+ with:
+ workflow: test.yml
+ commit: ${{ github.event.workflow_run.head_sha }}
+
+ - run: smokeshow upload coverage-html
+ env:
+ SMOKESHOW_GITHUB_STATUS_DESCRIPTION: Coverage {coverage-percentage}
+ SMOKESHOW_GITHUB_COVERAGE_THRESHOLD: 100
+ SMOKESHOW_GITHUB_CONTEXT: coverage
+ SMOKESHOW_GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
+ SMOKESHOW_GITHUB_PR_HEAD_SHA: ${{ github.event.workflow_run.head_sha }}
+ SMOKESHOW_AUTH_KEY: ${{ secrets.SMOKESHOW_AUTH_KEY }}
diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml
index 3e6225db33..ddc43c942b 100644
--- a/.github/workflows/test.yml
+++ b/.github/workflows/test.yml
@@ -12,7 +12,7 @@ jobs:
runs-on: ubuntu-latest
strategy:
matrix:
- python-version: ["3.7", "3.8", "3.9", "3.10"]
+ python-version: ["3.7", "3.8", "3.9", "3.10", "3.11"]
fail-fast: false
steps:
@@ -21,17 +21,57 @@ jobs:
uses: actions/setup-python@v4
with:
python-version: ${{ matrix.python-version }}
+ cache: "pip"
+ cache-dependency-path: pyproject.toml
- uses: actions/cache@v3
id: cache
with:
path: ${{ env.pythonLocation }}
- key: ${{ runner.os }}-python-${{ env.pythonLocation }}-${{ hashFiles('pyproject.toml') }}-test-v02
+ key: ${{ runner.os }}-python-${{ env.pythonLocation }}-${{ hashFiles('pyproject.toml') }}-test-v03
- name: Install Dependencies
if: steps.cache.outputs.cache-hit != 'true'
run: pip install -e .[all,dev,doc,test]
- name: Lint
run: bash scripts/lint.sh
+ - run: mkdir coverage
- name: Test
run: bash scripts/test.sh
- - name: Upload coverage
- uses: codecov/codecov-action@v3
+ env:
+ COVERAGE_FILE: coverage/.coverage.${{ runner.os }}-py${{ matrix.python-version }}
+ CONTEXT: ${{ runner.os }}-py${{ matrix.python-version }}
+ - name: Store coverage files
+ uses: actions/upload-artifact@v3
+ with:
+ name: coverage
+ path: coverage
+ coverage-combine:
+ needs: [test]
+ runs-on: ubuntu-latest
+
+ steps:
+ - uses: actions/checkout@v3
+
+ - uses: actions/setup-python@v4
+ with:
+ python-version: '3.8'
+ cache: "pip"
+ cache-dependency-path: pyproject.toml
+
+ - name: Get coverage files
+ uses: actions/download-artifact@v3
+ with:
+ name: coverage
+ path: coverage
+
+ - run: pip install coverage[toml]
+
+ - run: ls -la coverage
+ - run: coverage combine coverage
+ - run: coverage report
+ - run: coverage html --show-contexts --title "Coverage for ${{ github.sha }}"
+
+ - name: Store coverage HTML
+ uses: actions/upload-artifact@v3
+ with:
+ name: coverage-html
+ path: htmlcov
diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml
index bd5b8641ad..96f097caa1 100644
--- a/.pre-commit-config.yaml
+++ b/.pre-commit-config.yaml
@@ -12,25 +12,18 @@ repos:
- id: end-of-file-fixer
- id: trailing-whitespace
- repo: https://github.com/asottile/pyupgrade
- rev: v3.1.0
+ rev: v3.2.2
hooks:
- id: pyupgrade
args:
- --py3-plus
- --keep-runtime-typing
-- repo: https://github.com/PyCQA/autoflake
- rev: v1.7.7
+- repo: https://github.com/charliermarsh/ruff-pre-commit
+ rev: v0.0.138
hooks:
- - id: autoflake
+ - id: ruff
args:
- - --recursive
- - --in-place
- - --remove-all-unused-imports
- - --remove-unused-variables
- - --expand-star-imports
- - --exclude
- - __init__.py
- - --remove-duplicate-keys
+ - --fix
- repo: https://github.com/pycqa/isort
rev: 5.10.1
hooks:
diff --git a/README.md b/README.md
index 9d4f1cd902..7c4a6c4b4f 100644
--- a/README.md
+++ b/README.md
@@ -8,8 +8,8 @@
-
-
+
+
@@ -427,7 +427,7 @@ For a more complete example including more features, see the Strawberry and other libraries.
* Many extra features (thanks to Starlette) as:
* **WebSockets**
- * extremely easy tests based on `requests` and `pytest`
+ * extremely easy tests based on HTTPX and `pytest`
* **CORS**
* **Cookie Sessions**
* ...and more.
@@ -447,7 +447,7 @@ Used by Pydantic:
Used by Starlette:
-*
requests - Required if you want to use the `TestClient`.
+* httpx - Required if you want to use the `TestClient`.
* jinja2 - Required if you want to use the default template configuration.
* python-multipart - Required if you want to support form "parsing", with `request.form()`.
* itsdangerous - Required for `SessionMiddleware` support.
diff --git a/docs/az/docs/index.md b/docs/az/docs/index.md
index 3129f9dc6d..282c150322 100644
--- a/docs/az/docs/index.md
+++ b/docs/az/docs/index.md
@@ -446,7 +446,7 @@ Used by Pydantic:
Used by Starlette:
-* requests - Required if you want to use the `TestClient`.
+* httpx - Required if you want to use the `TestClient`.
* jinja2 - Required if you want to use the default template configuration.
* python-multipart - Required if you want to support form "parsing", with `request.form()`.
* itsdangerous - Required for `SessionMiddleware` support.
diff --git a/docs/de/docs/features.md b/docs/de/docs/features.md
index f825472a9a..f281afd1ed 100644
--- a/docs/de/docs/features.md
+++ b/docs/de/docs/features.md
@@ -169,7 +169,7 @@ Mit **FastAPI** bekommen Sie viele von **Starlette**'s Funktionen (da FastAPI nu
* **WebSocket**-Unterstützung.
* Hintergrundaufgaben im selben Prozess.
* Ereignisse für das Starten und Herunterfahren.
-* Testclient basierend auf `requests`.
+* Testclient basierend auf HTTPX.
* **CORS**, GZip, statische Dateien, Antwortfluss.
* **Sitzungs und Cookie** Unterstützung.
* 100% Testabdeckung.
diff --git a/docs/de/docs/index.md b/docs/de/docs/index.md
index 07f51b1be7..68fc8b753a 100644
--- a/docs/de/docs/index.md
+++ b/docs/de/docs/index.md
@@ -445,7 +445,7 @@ Used by Pydantic:
Used by Starlette:
-* requests - Required if you want to use the `TestClient`.
+* httpx - Required if you want to use the `TestClient`.
* jinja2 - Required if you want to use the default template configuration.
* python-multipart - Required if you want to support form "parsing", with `request.form()`.
* itsdangerous - Required for `SessionMiddleware` support.
diff --git a/docs/en/data/github_sponsors.yml b/docs/en/data/github_sponsors.yml
index aaf7c9b80a..1953df801e 100644
--- a/docs/en/data/github_sponsors.yml
+++ b/docs/en/data/github_sponsors.yml
@@ -8,12 +8,15 @@ sponsors:
- login: cryptapi
avatarUrl: https://avatars.githubusercontent.com/u/44925437?u=61369138589bc7fee6c417f3fbd50fbd38286cc4&v=4
url: https://github.com/cryptapi
-- - login: ObliviousAI
+ - login: jrobbins-LiveData
+ avatarUrl: https://avatars.githubusercontent.com/u/79278744?u=bae8175fc3f09db281aca1f97a9ddc1a914a8c4f&v=4
+ url: https://github.com/jrobbins-LiveData
+- - login: nihpo
+ avatarUrl: https://avatars.githubusercontent.com/u/1841030?u=0264956d7580f7e46687a762a7baa629f84cf97c&v=4
+ url: https://github.com/nihpo
+ - login: ObliviousAI
avatarUrl: https://avatars.githubusercontent.com/u/65656077?v=4
url: https://github.com/ObliviousAI
- - login: Lovage-Labs
- avatarUrl: https://avatars.githubusercontent.com/u/71685552?v=4
- url: https://github.com/Lovage-Labs
- login: chaserowbotham
avatarUrl: https://avatars.githubusercontent.com/u/97751084?v=4
url: https://github.com/chaserowbotham
@@ -32,15 +35,24 @@ sponsors:
- login: VincentParedes
avatarUrl: https://avatars.githubusercontent.com/u/103889729?v=4
url: https://github.com/VincentParedes
+- - login: getsentry
+ avatarUrl: https://avatars.githubusercontent.com/u/1396951?v=4
+ url: https://github.com/getsentry
- - login: InesIvanova
avatarUrl: https://avatars.githubusercontent.com/u/22920417?u=409882ec1df6dbd77455788bb383a8de223dbf6f&v=4
url: https://github.com/InesIvanova
-- - login: zopyx
- avatarUrl: https://avatars.githubusercontent.com/u/594239?u=8e5ce882664f47fd61002bed51718c78c3799d24&v=4
- url: https://github.com/zopyx
+- - login: vyos
+ avatarUrl: https://avatars.githubusercontent.com/u/5647000?v=4
+ url: https://github.com/vyos
- login: SendCloud
avatarUrl: https://avatars.githubusercontent.com/u/7831959?v=4
url: https://github.com/SendCloud
+ - login: matallan
+ avatarUrl: https://avatars.githubusercontent.com/u/12107723?v=4
+ url: https://github.com/matallan
+ - login: takashi-yoneya
+ avatarUrl: https://avatars.githubusercontent.com/u/33813153?u=2d0522bceba0b8b69adf1f2db866503bd96f944e&v=4
+ url: https://github.com/takashi-yoneya
- login: mercedes-benz
avatarUrl: https://avatars.githubusercontent.com/u/34240465?v=4
url: https://github.com/mercedes-benz
@@ -56,46 +68,49 @@ sponsors:
- - login: johnadjei
avatarUrl: https://avatars.githubusercontent.com/u/767860?v=4
url: https://github.com/johnadjei
+ - login: gvisniuc
+ avatarUrl: https://avatars.githubusercontent.com/u/1614747?u=502dfdb2b087ddcf5460026297c98c7907bc2795&v=4
+ url: https://github.com/gvisniuc
- login: HiredScore
avatarUrl: https://avatars.githubusercontent.com/u/3908850?v=4
url: https://github.com/HiredScore
- login: Trivie
avatarUrl: https://avatars.githubusercontent.com/u/8161763?v=4
url: https://github.com/Trivie
- - login: wdwinslow
- avatarUrl: https://avatars.githubusercontent.com/u/11562137?u=dc01daafb354135603a263729e3d26d939c0c452&v=4
- url: https://github.com/wdwinslow
+ - login: Lovage-Labs
+ avatarUrl: https://avatars.githubusercontent.com/u/71685552?v=4
+ url: https://github.com/Lovage-Labs
- - login: moellenbeck
avatarUrl: https://avatars.githubusercontent.com/u/169372?v=4
url: https://github.com/moellenbeck
+ - login: AccentDesign
+ avatarUrl: https://avatars.githubusercontent.com/u/2429332?v=4
+ url: https://github.com/AccentDesign
- login: RodneyU215
avatarUrl: https://avatars.githubusercontent.com/u/3329665?u=ec6a9adf8e7e8e306eed7d49687c398608d1604f&v=4
url: https://github.com/RodneyU215
- login: tizz98
avatarUrl: https://avatars.githubusercontent.com/u/5739698?u=f095a3659e3a8e7c69ccd822696990b521ea25f9&v=4
url: https://github.com/tizz98
- - login: Vikka
+ - login: dorianturba
avatarUrl: https://avatars.githubusercontent.com/u/9381120?u=4bfc7032a824d1ed1994aa8256dfa597c8f187ad&v=4
- url: https://github.com/Vikka
+ url: https://github.com/dorianturba
- login: jmaralc
avatarUrl: https://avatars.githubusercontent.com/u/21101214?u=b15a9f07b7cbf6c9dcdbcb6550bbd2c52f55aa50&v=4
url: https://github.com/jmaralc
- - login: takashi-yoneya
- avatarUrl: https://avatars.githubusercontent.com/u/33813153?u=2d0522bceba0b8b69adf1f2db866503bd96f944e&v=4
- url: https://github.com/takashi-yoneya
- login: mainframeindustries
avatarUrl: https://avatars.githubusercontent.com/u/55092103?v=4
url: https://github.com/mainframeindustries
- - login: DelfinaCare
- avatarUrl: https://avatars.githubusercontent.com/u/83734439?v=4
- url: https://github.com/DelfinaCare
- - login: povilasb
avatarUrl: https://avatars.githubusercontent.com/u/1213442?u=b11f58ed6ceea6e8297c9b310030478ebdac894d&v=4
url: https://github.com/povilasb
- login: primer-io
avatarUrl: https://avatars.githubusercontent.com/u/62146168?v=4
url: https://github.com/primer-io
-- - login: A-Edge
+- - login: indeedeng
+ avatarUrl: https://avatars.githubusercontent.com/u/2905043?v=4
+ url: https://github.com/indeedeng
+ - login: A-Edge
avatarUrl: https://avatars.githubusercontent.com/u/59514131?v=4
url: https://github.com/A-Edge
- - login: Kludex
@@ -146,6 +161,12 @@ sponsors:
- login: ltieman
avatarUrl: https://avatars.githubusercontent.com/u/1084689?u=e69b17de17cb3ca141a17daa7ccbe173ceb1eb17&v=4
url: https://github.com/ltieman
+ - login: mrkmcknz
+ avatarUrl: https://avatars.githubusercontent.com/u/1089376?u=2b9b8a8c25c33a4f6c220095638bd821cdfd13a3&v=4
+ url: https://github.com/mrkmcknz
+ - login: coffeewasmyidea
+ avatarUrl: https://avatars.githubusercontent.com/u/1636488?u=8e32a4f200eff54dd79cd79d55d254bfce5e946d&v=4
+ url: https://github.com/coffeewasmyidea
- login: corleyma
avatarUrl: https://avatars.githubusercontent.com/u/2080732?u=aed2ff652294a87d666b1c3f6dbe98104db76d26&v=4
url: https://github.com/corleyma
@@ -161,8 +182,11 @@ sponsors:
- login: Shark009
avatarUrl: https://avatars.githubusercontent.com/u/3163309?u=0c6f4091b0eda05c44c390466199826e6dc6e431&v=4
url: https://github.com/Shark009
+ - login: ColliotL
+ avatarUrl: https://avatars.githubusercontent.com/u/3412402?u=ca64b07ecbef2f9da1cc2cac3f37522aa4814902&v=4
+ url: https://github.com/ColliotL
- login: grillazz
- avatarUrl: https://avatars.githubusercontent.com/u/3415861?u=0b32b7073ae1ab8b7f6d2db0188c2e1e357ff451&v=4
+ avatarUrl: https://avatars.githubusercontent.com/u/3415861?u=453cd1725c8d7fe3e258016bc19cff861d4fcb53&v=4
url: https://github.com/grillazz
- login: dblackrun
avatarUrl: https://avatars.githubusercontent.com/u/3528486?v=4
@@ -183,7 +207,7 @@ sponsors:
avatarUrl: https://avatars.githubusercontent.com/u/3860655?u=f55f47eb2d6a9b495e806ac5a044e3ae01ccc1fa&v=4
url: https://github.com/peterHoburg
- login: jgreys
- avatarUrl: https://avatars.githubusercontent.com/u/4136890?u=b579fd97033269a5e703ab509c7d5478b146cc2d&v=4
+ avatarUrl: https://avatars.githubusercontent.com/u/4136890?u=c66ae617d614f6c886f1f1c1799d22100b3c848d&v=4
url: https://github.com/jgreys
- login: gorhack
avatarUrl: https://avatars.githubusercontent.com/u/4141690?u=ec119ebc4bdf00a7bc84657a71aa17834f4f27f3&v=4
@@ -194,15 +218,18 @@ sponsors:
- login: oliverxchen
avatarUrl: https://avatars.githubusercontent.com/u/4471774?u=534191f25e32eeaadda22dfab4b0a428733d5489&v=4
url: https://github.com/oliverxchen
- - login: CINOAdam
- avatarUrl: https://avatars.githubusercontent.com/u/4728508?u=76ef23f06ae7c604e009873bc27cf0ea9ba738c9&v=4
- url: https://github.com/CINOAdam
+ - login: Rey8d01
+ avatarUrl: https://avatars.githubusercontent.com/u/4836190?u=5942598a23a377602c1669522334ab5ebeaf9165&v=4
+ url: https://github.com/Rey8d01
- login: ScrimForever
avatarUrl: https://avatars.githubusercontent.com/u/5040124?u=091ec38bfe16d6e762099e91309b59f248616a65&v=4
url: https://github.com/ScrimForever
- login: ennui93
avatarUrl: https://avatars.githubusercontent.com/u/5300907?u=5b5452725ddb391b2caaebf34e05aba873591c3a&v=4
url: https://github.com/ennui93
+ - login: ternaus
+ avatarUrl: https://avatars.githubusercontent.com/u/5481618?u=fabc8d75c921b3380126adb5a931c5da6e7db04f&v=4
+ url: https://github.com/ternaus
- login: Yaleesa
avatarUrl: https://avatars.githubusercontent.com/u/6135475?v=4
url: https://github.com/Yaleesa
@@ -216,7 +243,7 @@ sponsors:
avatarUrl: https://avatars.githubusercontent.com/u/6347418?u=98f5918b32e214a168a2f5d59b0b8ebdf57dca0d&v=4
url: https://github.com/pkucmus
- login: s3ich4n
- avatarUrl: https://avatars.githubusercontent.com/u/6926298?u=ba3025d698e1c986655e776ae383a3d60d9d578e&v=4
+ avatarUrl: https://avatars.githubusercontent.com/u/6926298?u=6690c5403bc1d9a1837886defdc5256e9a43b1db&v=4
url: https://github.com/s3ich4n
- login: Rehket
avatarUrl: https://avatars.githubusercontent.com/u/7015688?u=3afb0ba200feebbc7f958950e92db34df2a3c172&v=4
@@ -227,9 +254,12 @@ sponsors:
- login: Shackelford-Arden
avatarUrl: https://avatars.githubusercontent.com/u/7362263?v=4
url: https://github.com/Shackelford-Arden
- - login: Ge0f3
- avatarUrl: https://avatars.githubusercontent.com/u/11887760?u=ccd80f1ac36dcb8517ef5c4e702e8cc5a80cad2f&v=4
- url: https://github.com/Ge0f3
+ - login: wdwinslow
+ avatarUrl: https://avatars.githubusercontent.com/u/11562137?u=dc01daafb354135603a263729e3d26d939c0c452&v=4
+ url: https://github.com/wdwinslow
+ - login: bapi24
+ avatarUrl: https://avatars.githubusercontent.com/u/11890901?u=45cc721d8f66ad2f62b086afc3d4761d0c16b9c6&v=4
+ url: https://github.com/bapi24
- login: svats2k
avatarUrl: https://avatars.githubusercontent.com/u/12378398?u=ecf28c19f61052e664bdfeb2391f8107d137915c&v=4
url: https://github.com/svats2k
@@ -239,18 +269,18 @@ sponsors:
- login: dannywade
avatarUrl: https://avatars.githubusercontent.com/u/13680237?u=418ee985bd41577b20fde81417fb2d901e875e8a&v=4
url: https://github.com/dannywade
+ - login: khadrawy
+ avatarUrl: https://avatars.githubusercontent.com/u/13686061?u=59f25ef42ecf04c22657aac4238ce0e2d3d30304&v=4
+ url: https://github.com/khadrawy
- login: pablonnaoji
avatarUrl: https://avatars.githubusercontent.com/u/15187159?u=afc15bd5a4ba9c5c7206bbb1bcaeef606a0932e0&v=4
url: https://github.com/pablonnaoji
- - login: robintully
- avatarUrl: https://avatars.githubusercontent.com/u/17059673?u=862b9bb01513f5acd30df97433cb97a24dbfb772&v=4
- url: https://github.com/robintully
- login: wedwardbeck
avatarUrl: https://avatars.githubusercontent.com/u/19333237?u=1de4ae2bf8d59eb4c013f21d863cbe0f2010575f&v=4
url: https://github.com/wedwardbeck
- - login: RedCarpetUp
- avatarUrl: https://avatars.githubusercontent.com/u/20360440?v=4
- url: https://github.com/RedCarpetUp
+ - login: m4knV
+ avatarUrl: https://avatars.githubusercontent.com/u/19666130?u=843383978814886be93c137d10d2e20e9f13af07&v=4
+ url: https://github.com/m4knV
- login: Filimoa
avatarUrl: https://avatars.githubusercontent.com/u/21352040?u=75e02d102d2ee3e3d793e555fa5c63045913ccb0&v=4
url: https://github.com/Filimoa
@@ -287,6 +317,9 @@ sponsors:
- login: ProteinQure
avatarUrl: https://avatars.githubusercontent.com/u/33707203?v=4
url: https://github.com/ProteinQure
+ - login: faviasono
+ avatarUrl: https://avatars.githubusercontent.com/u/37707874?u=f0b75ca4248987c08ed8fb8ed682e7e74d5d7091&v=4
+ url: https://github.com/faviasono
- login: ybressler
avatarUrl: https://avatars.githubusercontent.com/u/40807730?u=41e2c00f1eebe3c402635f0325e41b4e6511462c&v=4
url: https://github.com/ybressler
@@ -302,20 +335,17 @@ sponsors:
- login: rafsaf
avatarUrl: https://avatars.githubusercontent.com/u/51059348?u=f8f0d6d6e90fac39fa786228158ba7f013c74271&v=4
url: https://github.com/rafsaf
- - login: yezz123
- avatarUrl: https://avatars.githubusercontent.com/u/52716203?u=636b4f79645176df4527dd45c12d5dbb5a4193cf&v=4
- url: https://github.com/yezz123
- login: dudikbender
avatarUrl: https://avatars.githubusercontent.com/u/53487583?u=494f85229115076121b3639a3806bbac1c6ae7f6&v=4
url: https://github.com/dudikbender
- - login: llamington
- avatarUrl: https://avatars.githubusercontent.com/u/54869395?u=42ea59b76f49449f41a4d106bb65a130797e8d7c&v=4
- url: https://github.com/llamington
+ - login: dazeddd
+ avatarUrl: https://avatars.githubusercontent.com/u/59472056?u=7a1b668449bf8b448db13e4c575576d24d7d658b&v=4
+ url: https://github.com/dazeddd
- login: yakkonaut
avatarUrl: https://avatars.githubusercontent.com/u/60633704?u=90a71fd631aa998ba4a96480788f017c9904e07b&v=4
url: https://github.com/yakkonaut
- login: patsatsia
- avatarUrl: https://avatars.githubusercontent.com/u/61111267?u=419516384f798a35e9d9e2dd81282cc46c151b58&v=4
+ avatarUrl: https://avatars.githubusercontent.com/u/61111267?u=3271b85f7a37b479c8d0ae0a235182e83c166edf&v=4
url: https://github.com/patsatsia
- login: predictionmachine
avatarUrl: https://avatars.githubusercontent.com/u/63719559?v=4
@@ -329,14 +359,23 @@ sponsors:
- login: anthonycepeda
avatarUrl: https://avatars.githubusercontent.com/u/72019805?u=4252c6b6dc5024af502a823a3ac5e7a03a69963f&v=4
url: https://github.com/anthonycepeda
- - login: dotlas
- avatarUrl: https://avatars.githubusercontent.com/u/88832003?v=4
- url: https://github.com/dotlas
+ - login: fpiem
+ avatarUrl: https://avatars.githubusercontent.com/u/77389987?u=f667a25cd4832b28801189013b74450e06cc232c&v=4
+ url: https://github.com/fpiem
+ - login: DelfinaCare
+ avatarUrl: https://avatars.githubusercontent.com/u/83734439?v=4
+ url: https://github.com/DelfinaCare
+ - login: programvx
+ avatarUrl: https://avatars.githubusercontent.com/u/96057906?v=4
+ url: https://github.com/programvx
- login: pyt3h
avatarUrl: https://avatars.githubusercontent.com/u/99658549?v=4
url: https://github.com/pyt3h
+ - login: Dagmaara
+ avatarUrl: https://avatars.githubusercontent.com/u/115501964?v=4
+ url: https://github.com/Dagmaara
- - login: linux-china
- avatarUrl: https://avatars.githubusercontent.com/u/46711?v=4
+ avatarUrl: https://avatars.githubusercontent.com/u/46711?u=cd77c65338b158750eb84dc7ff1acf3209ccfc4f&v=4
url: https://github.com/linux-china
- login: ddanier
avatarUrl: https://avatars.githubusercontent.com/u/113563?u=ed1dc79de72f93bd78581f88ebc6952b62f472da&v=4
@@ -353,15 +392,9 @@ sponsors:
- login: hhatto
avatarUrl: https://avatars.githubusercontent.com/u/150309?u=3e8f63c27bf996bfc68464b0ce3f7a3e40e6ea7f&v=4
url: https://github.com/hhatto
- - login: yourkin
- avatarUrl: https://avatars.githubusercontent.com/u/178984?u=b43a7e5f8818f7d9083d3b110118d9c27d48a794&v=4
- url: https://github.com/yourkin
- login: slafs
avatarUrl: https://avatars.githubusercontent.com/u/210173?v=4
url: https://github.com/slafs
- - login: assem-ch
- avatarUrl: https://avatars.githubusercontent.com/u/315228?u=e0c5ab30726d3243a40974bb9bae327866e42d9b&v=4
- url: https://github.com/assem-ch
- login: adamghill
avatarUrl: https://avatars.githubusercontent.com/u/317045?u=f1349d5ffe84a19f324e204777859fbf69ddf633&v=4
url: https://github.com/adamghill
@@ -419,6 +452,9 @@ sponsors:
- login: pawamoy
avatarUrl: https://avatars.githubusercontent.com/u/3999221?u=b030e4c89df2f3a36bc4710b925bdeb6745c9856&v=4
url: https://github.com/pawamoy
+ - login: nikeee
+ avatarUrl: https://avatars.githubusercontent.com/u/4068864?u=63f8eee593f25138e0f1032ef442e9ad24907d4c&v=4
+ url: https://github.com/nikeee
- login: Alisa-lisa
avatarUrl: https://avatars.githubusercontent.com/u/4137964?u=e7e393504f554f4ff15863a1e01a5746863ef9ce&v=4
url: https://github.com/Alisa-lisa
@@ -426,7 +462,7 @@ sponsors:
avatarUrl: https://avatars.githubusercontent.com/u/4472301?v=4
url: https://github.com/danielunderwood
- login: unredundant
- avatarUrl: https://avatars.githubusercontent.com/u/5607577?u=57dd0023365bec03f4fc566df6b81bc0a264a47d&v=4
+ avatarUrl: https://avatars.githubusercontent.com/u/5607577?u=1ffbf39f5bb8736b75c0d235707d6e8f803725c5&v=4
url: https://github.com/unredundant
- login: Baghdady92
avatarUrl: https://avatars.githubusercontent.com/u/5708590?v=4
@@ -434,6 +470,9 @@ sponsors:
- login: holec
avatarUrl: https://avatars.githubusercontent.com/u/6438041?u=f5af71ec85b3a9d7b8139cb5af0512b02fa9ab1e&v=4
url: https://github.com/holec
+ - login: mattwelke
+ avatarUrl: https://avatars.githubusercontent.com/u/7719209?u=5d963ead289969257190b133250653bd99df06ba&v=4
+ url: https://github.com/mattwelke
- login: hcristea
avatarUrl: https://avatars.githubusercontent.com/u/7814406?u=61d7a4fcf846983a4606788eac25e1c6c1209ba8&v=4
url: https://github.com/hcristea
@@ -470,12 +509,6 @@ sponsors:
- login: logan-connolly
avatarUrl: https://avatars.githubusercontent.com/u/16244943?u=8ae66dfbba936463cc8aa0dd7a6d2b4c0cc757eb&v=4
url: https://github.com/logan-connolly
- - login: sanghunka
- avatarUrl: https://avatars.githubusercontent.com/u/16280020?u=7d8fafd8bfe6d7900bb1e52d5a5d5da0c02bc164&v=4
- url: https://github.com/sanghunka
- - login: stevenayers
- avatarUrl: https://avatars.githubusercontent.com/u/16361214?u=098b797d8d48afb8cd964b717847943b61d24a6d&v=4
- url: https://github.com/stevenayers
- login: cdsre
avatarUrl: https://avatars.githubusercontent.com/u/16945936?v=4
url: https://github.com/cdsre
@@ -494,6 +527,15 @@ sponsors:
- login: fstau
avatarUrl: https://avatars.githubusercontent.com/u/24669867?u=60e7c8c09f8dafabee8fc3edcd6f9e19abbff918&v=4
url: https://github.com/fstau
+ - login: pers0n4
+ avatarUrl: https://avatars.githubusercontent.com/u/24864600?u=444441027bc2c9f9db68e8047d65ff23d25699cf&v=4
+ url: https://github.com/pers0n4
+ - login: SebTota
+ avatarUrl: https://avatars.githubusercontent.com/u/25122511?v=4
+ url: https://github.com/SebTota
+ - login: joerambo
+ avatarUrl: https://avatars.githubusercontent.com/u/26282974?v=4
+ url: https://github.com/joerambo
- login: mertguvencli
avatarUrl: https://avatars.githubusercontent.com/u/29762151?u=16a906d90df96c8cff9ea131a575c4bc171b1523&v=4
url: https://github.com/mertguvencli
@@ -506,6 +548,9 @@ sponsors:
- login: engineerjoe440
avatarUrl: https://avatars.githubusercontent.com/u/33275230?u=eb223cad27017bb1e936ee9b429b450d092d0236&v=4
url: https://github.com/engineerjoe440
+ - login: bnkc
+ avatarUrl: https://avatars.githubusercontent.com/u/34930566?u=20f362505e2a994805233f42e69f9f14b4a9dd0c&v=4
+ url: https://github.com/bnkc
- login: declon
avatarUrl: https://avatars.githubusercontent.com/u/36180226?v=4
url: https://github.com/declon
@@ -563,12 +608,9 @@ sponsors:
- login: pondDevThai
avatarUrl: https://avatars.githubusercontent.com/u/71592181?u=08af9a59bccfd8f6b101de1005aa9822007d0a44&v=4
url: https://github.com/pondDevThai
-- - login: mattwelke
- avatarUrl: https://avatars.githubusercontent.com/u/7719209?u=5d963ead289969257190b133250653bd99df06ba&v=4
- url: https://github.com/mattwelke
- - login: cesarfreire
- avatarUrl: https://avatars.githubusercontent.com/u/21126103?u=5d428f77f9b63c741f0e9ca5e15a689017b66fe8&v=4
- url: https://github.com/cesarfreire
+- - login: wardal
+ avatarUrl: https://avatars.githubusercontent.com/u/15804042?v=4
+ url: https://github.com/wardal
- login: gabrielmbmb
avatarUrl: https://avatars.githubusercontent.com/u/29572918?u=6d1e00b5d558e96718312ff910a2318f47cc3145&v=4
url: https://github.com/gabrielmbmb
@@ -578,6 +620,3 @@ sponsors:
- login: Moises6669
avatarUrl: https://avatars.githubusercontent.com/u/66188523?u=96af25b8d5be9f983cb96e9dd7c605c716caf1f5&v=4
url: https://github.com/Moises6669
- - login: zahariev-webbersof
- avatarUrl: https://avatars.githubusercontent.com/u/68993494?u=b341c94a8aa0624e05e201bcf8ae5b2697e3be2f&v=4
- url: https://github.com/zahariev-webbersof
diff --git a/docs/en/data/people.yml b/docs/en/data/people.yml
index c7354eb44b..51940a6b13 100644
--- a/docs/en/data/people.yml
+++ b/docs/en/data/people.yml
@@ -1,12 +1,12 @@
maintainers:
- login: tiangolo
- answers: 1271
- prs: 338
+ answers: 1837
+ prs: 360
avatarUrl: https://avatars.githubusercontent.com/u/1326112?u=740f11212a731f56798f558ceddb0bd07642afa7&v=4
url: https://github.com/tiangolo
experts:
- login: Kludex
- count: 364
+ count: 374
avatarUrl: https://avatars.githubusercontent.com/u/7353520?u=62adc405ef418f4b6c8caa93d3eb8ab107bc4927&v=4
url: https://github.com/Kludex
- login: dmontagu
@@ -15,24 +15,28 @@ experts:
url: https://github.com/dmontagu
- login: ycd
count: 221
- avatarUrl: https://avatars.githubusercontent.com/u/62724709?u=fa40e037060d62bf82e16b505d870a2866725f38&v=4
+ avatarUrl: https://avatars.githubusercontent.com/u/62724709?u=bba5af018423a2858d49309bed2a899bb5c34ac5&v=4
url: https://github.com/ycd
- login: Mause
count: 207
avatarUrl: https://avatars.githubusercontent.com/u/1405026?v=4
url: https://github.com/Mause
+- login: JarroVGIT
+ count: 192
+ avatarUrl: https://avatars.githubusercontent.com/u/13659033?u=e8bea32d07a5ef72f7dde3b2079ceb714923ca05&v=4
+ url: https://github.com/JarroVGIT
- login: euri10
count: 166
avatarUrl: https://avatars.githubusercontent.com/u/1104190?u=321a2e953e6645a7d09b732786c7a8061e0f8a8b&v=4
url: https://github.com/euri10
-- login: JarroVGIT
- count: 163
- avatarUrl: https://avatars.githubusercontent.com/u/13659033?u=e8bea32d07a5ef72f7dde3b2079ceb714923ca05&v=4
- url: https://github.com/JarroVGIT
- login: phy25
count: 130
avatarUrl: https://avatars.githubusercontent.com/u/331403?v=4
url: https://github.com/phy25
+- login: iudeen
+ count: 87
+ avatarUrl: https://avatars.githubusercontent.com/u/10519440?u=2843b3303282bff8b212dcd4d9d6689452e4470c&v=4
+ url: https://github.com/iudeen
- login: raphaelauv
count: 77
avatarUrl: https://avatars.githubusercontent.com/u/10202690?u=e6f86f5c0c3026a15d6b51792fa3e532b12f1371&v=4
@@ -41,28 +45,24 @@ experts:
count: 71
avatarUrl: https://avatars.githubusercontent.com/u/31127044?u=b0f2c37142f4b762e41ad65dc49581813422bd71&v=4
url: https://github.com/ArcLightSlavik
-- login: iudeen
- count: 65
- avatarUrl: https://avatars.githubusercontent.com/u/10519440?u=2843b3303282bff8b212dcd4d9d6689452e4470c&v=4
- url: https://github.com/iudeen
- login: falkben
- count: 58
+ count: 59
avatarUrl: https://avatars.githubusercontent.com/u/653031?u=0c8d8f33d87f1aa1a6488d3f02105e9abc838105&v=4
url: https://github.com/falkben
+- login: jgould22
+ count: 55
+ avatarUrl: https://avatars.githubusercontent.com/u/4335847?u=ed77f67e0bb069084639b24d812dbb2a2b1dc554&v=4
+ url: https://github.com/jgould22
- login: sm-Fifteen
- count: 49
+ count: 50
avatarUrl: https://avatars.githubusercontent.com/u/516999?u=437c0c5038558c67e887ccd863c1ba0f846c03da&v=4
url: https://github.com/sm-Fifteen
- login: insomnes
count: 46
avatarUrl: https://avatars.githubusercontent.com/u/16958893?u=f8be7088d5076d963984a21f95f44e559192d912&v=4
url: https://github.com/insomnes
-- login: jgould22
- count: 45
- avatarUrl: https://avatars.githubusercontent.com/u/4335847?u=ed77f67e0bb069084639b24d812dbb2a2b1dc554&v=4
- url: https://github.com/jgould22
- login: Dustyposa
- count: 43
+ count: 45
avatarUrl: https://avatars.githubusercontent.com/u/27180793?u=5cf2877f50b3eb2bc55086089a78a36f07042889&v=4
url: https://github.com/Dustyposa
- login: adriangb
@@ -78,17 +78,21 @@ experts:
avatarUrl: https://avatars.githubusercontent.com/u/5167622?u=de8f597c81d6336fcebc37b32dfd61a3f877160c&v=4
url: https://github.com/STeveShary
- login: chbndrhnns
- count: 35
+ count: 36
avatarUrl: https://avatars.githubusercontent.com/u/7534547?v=4
url: https://github.com/chbndrhnns
+- login: frankie567
+ count: 33
+ avatarUrl: https://avatars.githubusercontent.com/u/1144727?u=85c025e3fcc7bd79a5665c63ee87cdf8aae13374&v=4
+ url: https://github.com/frankie567
- login: prostomarkeloff
count: 33
avatarUrl: https://avatars.githubusercontent.com/u/28061158?u=72309cc1f2e04e40fa38b29969cb4e9d3f722e7b&v=4
url: https://github.com/prostomarkeloff
-- login: frankie567
- count: 31
- avatarUrl: https://avatars.githubusercontent.com/u/1144727?u=85c025e3fcc7bd79a5665c63ee87cdf8aae13374&v=4
- url: https://github.com/frankie567
+- login: acidjunk
+ count: 32
+ avatarUrl: https://avatars.githubusercontent.com/u/685002?u=b5094ab4527fc84b006c0ac9ff54367bdebb2267&v=4
+ url: https://github.com/acidjunk
- login: krishnardt
count: 31
avatarUrl: https://avatars.githubusercontent.com/u/31960541?u=47f4829c77f4962ab437ffb7995951e41eeebe9b&v=4
@@ -101,10 +105,6 @@ experts:
count: 29
avatarUrl: https://avatars.githubusercontent.com/u/41326348?u=ba2fda6b30110411ecbf406d187907e2b420ac19&v=4
url: https://github.com/panla
-- login: acidjunk
- count: 27
- avatarUrl: https://avatars.githubusercontent.com/u/685002?u=b5094ab4527fc84b006c0ac9ff54367bdebb2267&v=4
- url: https://github.com/acidjunk
- login: ghandic
count: 25
avatarUrl: https://avatars.githubusercontent.com/u/23500353?u=e2e1d736f924d9be81e8bfc565b6d8836ba99773&v=4
@@ -113,10 +113,18 @@ experts:
count: 25
avatarUrl: https://avatars.githubusercontent.com/u/43723790?u=9bcce836bbce55835291c5b2ac93a4e311f4b3c3&v=4
url: https://github.com/dbanty
+- login: yinziyan1206
+ count: 25
+ avatarUrl: https://avatars.githubusercontent.com/u/37829370?u=da44ca53aefd5c23f346fab8e9fd2e108294c179&v=4
+ url: https://github.com/yinziyan1206
- login: SirTelemak
count: 24
avatarUrl: https://avatars.githubusercontent.com/u/9435877?u=719327b7d2c4c62212456d771bfa7c6b8dbb9eac&v=4
url: https://github.com/SirTelemak
+- login: odiseo0
+ count: 24
+ avatarUrl: https://avatars.githubusercontent.com/u/87550035?u=16f9255804161c6ff3c8b7ef69848f0126bcd405&v=4
+ url: https://github.com/odiseo0
- login: acnebs
count: 22
avatarUrl: https://avatars.githubusercontent.com/u/9054108?u=c27e50269f1ef8ea950cc6f0268c8ec5cebbe9c9&v=4
@@ -129,22 +137,18 @@ experts:
count: 21
avatarUrl: https://avatars.githubusercontent.com/u/565544?v=4
url: https://github.com/chris-allnutt
-- login: odiseo0
- count: 21
- avatarUrl: https://avatars.githubusercontent.com/u/87550035?u=ab724eae71c3fe1cf81e8dc76e73415da926ef7d&v=4
- url: https://github.com/odiseo0
- login: retnikt
count: 19
avatarUrl: https://avatars.githubusercontent.com/u/24581770?v=4
url: https://github.com/retnikt
+- login: rafsaf
+ count: 19
+ avatarUrl: https://avatars.githubusercontent.com/u/51059348?u=f8f0d6d6e90fac39fa786228158ba7f013c74271&v=4
+ url: https://github.com/rafsaf
- login: Hultner
count: 18
avatarUrl: https://avatars.githubusercontent.com/u/2669034?u=115e53df959309898ad8dc9443fbb35fee71df07&v=4
url: https://github.com/Hultner
-- login: rafsaf
- count: 18
- avatarUrl: https://avatars.githubusercontent.com/u/51059348?u=f8f0d6d6e90fac39fa786228158ba7f013c74271&v=4
- url: https://github.com/rafsaf
- login: jorgerpo
count: 17
avatarUrl: https://avatars.githubusercontent.com/u/12537771?u=7444d20019198e34911082780cc7ad73f2b97cb3&v=4
@@ -169,6 +173,10 @@ experts:
count: 15
avatarUrl: https://avatars.githubusercontent.com/u/26334101?u=071c062d2861d3dd127f6b4a5258cd8ef55d4c50&v=4
url: https://github.com/jonatasoli
+- login: mbroton
+ count: 15
+ avatarUrl: https://avatars.githubusercontent.com/u/50829834?u=a48610bf1bffaa9c75d03228926e2eb08a2e24ee&v=4
+ url: https://github.com/mbroton
- login: hellocoldworld
count: 14
avatarUrl: https://avatars.githubusercontent.com/u/47581948?u=3d2186796434c507a6cb6de35189ab0ad27c356f&v=4
@@ -177,10 +185,6 @@ experts:
count: 13
avatarUrl: https://avatars.githubusercontent.com/u/58201?u=dd40d99a3e1935d0b768f122bfe2258d6ea53b2b&v=4
url: https://github.com/haizaar
-- login: yinziyan1206
- count: 13
- avatarUrl: https://avatars.githubusercontent.com/u/37829370?v=4
- url: https://github.com/yinziyan1206
- login: valentin994
count: 13
avatarUrl: https://avatars.githubusercontent.com/u/42819267?u=fdeeaa9242a59b243f8603496b00994f6951d5a2&v=4
@@ -193,35 +197,39 @@ experts:
count: 12
avatarUrl: https://avatars.githubusercontent.com/u/2964996?v=4
url: https://github.com/n8sty
-- login: zoliknemet
- count: 12
- avatarUrl: https://avatars.githubusercontent.com/u/22326718?u=31ba446ac290e23e56eea8e4f0c558aaf0b40779&v=4
- url: https://github.com/zoliknemet
last_month_active:
-- login: JarroVGIT
- count: 27
- avatarUrl: https://avatars.githubusercontent.com/u/13659033?u=e8bea32d07a5ef72f7dde3b2079ceb714923ca05&v=4
- url: https://github.com/JarroVGIT
-- login: iudeen
- count: 16
- avatarUrl: https://avatars.githubusercontent.com/u/10519440?u=2843b3303282bff8b212dcd4d9d6689452e4470c&v=4
- url: https://github.com/iudeen
-- login: mbroton
- count: 6
- avatarUrl: https://avatars.githubusercontent.com/u/50829834?u=a48610bf1bffaa9c75d03228926e2eb08a2e24ee&v=4
- url: https://github.com/mbroton
-- login: csrgxtu
- count: 6
- avatarUrl: https://avatars.githubusercontent.com/u/5053620?u=9655a3e9661492fcdaaf99193eb16d5cbcc3849e&v=4
- url: https://github.com/csrgxtu
-- login: Kludex
- count: 4
- avatarUrl: https://avatars.githubusercontent.com/u/7353520?u=62adc405ef418f4b6c8caa93d3eb8ab107bc4927&v=4
- url: https://github.com/Kludex
- login: jgould22
- count: 3
+ count: 9
avatarUrl: https://avatars.githubusercontent.com/u/4335847?u=ed77f67e0bb069084639b24d812dbb2a2b1dc554&v=4
url: https://github.com/jgould22
+- login: yinziyan1206
+ count: 9
+ avatarUrl: https://avatars.githubusercontent.com/u/37829370?u=da44ca53aefd5c23f346fab8e9fd2e108294c179&v=4
+ url: https://github.com/yinziyan1206
+- login: iudeen
+ count: 8
+ avatarUrl: https://avatars.githubusercontent.com/u/10519440?u=2843b3303282bff8b212dcd4d9d6689452e4470c&v=4
+ url: https://github.com/iudeen
+- login: Kludex
+ count: 5
+ avatarUrl: https://avatars.githubusercontent.com/u/7353520?u=62adc405ef418f4b6c8caa93d3eb8ab107bc4927&v=4
+ url: https://github.com/Kludex
+- login: JarroVGIT
+ count: 5
+ avatarUrl: https://avatars.githubusercontent.com/u/13659033?u=e8bea32d07a5ef72f7dde3b2079ceb714923ca05&v=4
+ url: https://github.com/JarroVGIT
+- login: TheJumpyWizard
+ count: 4
+ avatarUrl: https://avatars.githubusercontent.com/u/90986815?u=67e9c13c9f063dd4313db7beb64eaa2f3a37f1fe&v=4
+ url: https://github.com/TheJumpyWizard
+- login: mbroton
+ count: 3
+ avatarUrl: https://avatars.githubusercontent.com/u/50829834?u=a48610bf1bffaa9c75d03228926e2eb08a2e24ee&v=4
+ url: https://github.com/mbroton
+- login: mateoradman
+ count: 3
+ avatarUrl: https://avatars.githubusercontent.com/u/48420316?u=066f36b8e8e263b0d90798113b0f291d3266db7c&v=4
+ url: https://github.com/mateoradman
top_contributors:
- login: waynerv
count: 25
@@ -231,14 +239,14 @@ top_contributors:
count: 22
avatarUrl: https://avatars.githubusercontent.com/u/41147016?u=55010621aece725aa702270b54fed829b6a1fe60&v=4
url: https://github.com/tokusumi
+- login: jaystone776
+ count: 17
+ avatarUrl: https://avatars.githubusercontent.com/u/11191137?u=299205a95e9b6817a43144a48b643346a5aac5cc&v=4
+ url: https://github.com/jaystone776
- login: dmontagu
count: 16
avatarUrl: https://avatars.githubusercontent.com/u/35119617?u=58ed2a45798a4339700e2f62b2e12e6e54bf0396&v=4
url: https://github.com/dmontagu
-- login: jaystone776
- count: 16
- avatarUrl: https://avatars.githubusercontent.com/u/11191137?u=299205a95e9b6817a43144a48b643346a5aac5cc&v=4
- url: https://github.com/jaystone776
- login: Kludex
count: 15
avatarUrl: https://avatars.githubusercontent.com/u/7353520?u=62adc405ef418f4b6c8caa93d3eb8ab107bc4927&v=4
@@ -255,10 +263,6 @@ top_contributors:
count: 10
avatarUrl: https://avatars.githubusercontent.com/u/16785985?v=4
url: https://github.com/Smlep
-- login: dependabot
- count: 9
- avatarUrl: https://avatars.githubusercontent.com/in/29110?v=4
- url: https://github.com/apps/dependabot
- login: Serrones
count: 8
avatarUrl: https://avatars.githubusercontent.com/u/22691749?u=4795b880e13ca33a73e52fc0ef7dc9c60c8fce47&v=4
@@ -271,6 +275,10 @@ top_contributors:
count: 7
avatarUrl: https://avatars.githubusercontent.com/u/9651103?u=95db33927bbff1ed1c07efddeb97ac2ff33068ed&v=4
url: https://github.com/hard-coders
+- login: rjNemo
+ count: 7
+ avatarUrl: https://avatars.githubusercontent.com/u/56785022?u=d5c3a02567c8649e146fcfc51b6060ccaf8adef8&v=4
+ url: https://github.com/rjNemo
- login: wshayes
count: 5
avatarUrl: https://avatars.githubusercontent.com/u/365303?u=07ca03c5ee811eb0920e633cc3c3db73dbec1aa5&v=4
@@ -285,19 +293,27 @@ top_contributors:
url: https://github.com/Attsun1031
- login: ComicShrimp
count: 5
- avatarUrl: https://avatars.githubusercontent.com/u/43503750?u=b3e4d9a14d9a65d429ce62c566aef73178b7111d&v=4
+ avatarUrl: https://avatars.githubusercontent.com/u/43503750?u=f440bc9062afb3c43b9b9c6cdfdcfe31d58699ef&v=4
url: https://github.com/ComicShrimp
+- login: batlopes
+ count: 5
+ avatarUrl: https://avatars.githubusercontent.com/u/33462923?u=0fb3d7acb316764616f11e4947faf080e49ad8d9&v=4
+ url: https://github.com/batlopes
- login: jekirl
count: 4
avatarUrl: https://avatars.githubusercontent.com/u/2546697?u=a027452387d85bd4a14834e19d716c99255fb3b7&v=4
url: https://github.com/jekirl
+- login: samuelcolvin
+ count: 4
+ avatarUrl: https://avatars.githubusercontent.com/u/4039449?u=807390ba9cfe23906c3bf8a0d56aaca3cf2bfa0d&v=4
+ url: https://github.com/samuelcolvin
- login: jfunez
count: 4
avatarUrl: https://avatars.githubusercontent.com/u/805749?v=4
url: https://github.com/jfunez
- login: ycd
count: 4
- avatarUrl: https://avatars.githubusercontent.com/u/62724709?u=fa40e037060d62bf82e16b505d870a2866725f38&v=4
+ avatarUrl: https://avatars.githubusercontent.com/u/62724709?u=bba5af018423a2858d49309bed2a899bb5c34ac5&v=4
url: https://github.com/ycd
- login: komtaki
count: 4
@@ -307,10 +323,6 @@ top_contributors:
count: 4
avatarUrl: https://avatars.githubusercontent.com/u/3360631?u=5fa1f475ad784d64eb9666bdd43cc4d285dcc773&v=4
url: https://github.com/hitrust
-- login: rjNemo
- count: 4
- avatarUrl: https://avatars.githubusercontent.com/u/56785022?u=d5c3a02567c8649e146fcfc51b6060ccaf8adef8&v=4
- url: https://github.com/rjNemo
- login: lsglucas
count: 4
avatarUrl: https://avatars.githubusercontent.com/u/61513630?u=320e43fe4dc7bc6efc64e9b8f325f8075634fd20&v=4
@@ -319,19 +331,19 @@ top_contributors:
count: 4
avatarUrl: https://avatars.githubusercontent.com/u/79563565?u=1741703bd6c8f491503354b363a86e879b4c1cab&v=4
url: https://github.com/NinaHwang
-- login: pre-commit-ci
- count: 4
- avatarUrl: https://avatars.githubusercontent.com/in/68672?v=4
- url: https://github.com/apps/pre-commit-ci
top_reviewers:
- login: Kludex
- count: 101
+ count: 109
avatarUrl: https://avatars.githubusercontent.com/u/7353520?u=62adc405ef418f4b6c8caa93d3eb8ab107bc4927&v=4
url: https://github.com/Kludex
- login: BilalAlpaslan
- count: 64
+ count: 70
avatarUrl: https://avatars.githubusercontent.com/u/47563997?u=63ed66e304fe8d765762c70587d61d9196e5c82d&v=4
url: https://github.com/BilalAlpaslan
+- login: yezz123
+ count: 59
+ avatarUrl: https://avatars.githubusercontent.com/u/52716203?u=636b4f79645176df4527dd45c12d5dbb5a4193cf&v=4
+ url: https://github.com/yezz123
- login: tokusumi
count: 50
avatarUrl: https://avatars.githubusercontent.com/u/41147016?u=55010621aece725aa702270b54fed829b6a1fe60&v=4
@@ -344,46 +356,46 @@ top_reviewers:
count: 47
avatarUrl: https://avatars.githubusercontent.com/u/59285379?v=4
url: https://github.com/Laineyzhang55
-- login: yezz123
- count: 46
- avatarUrl: https://avatars.githubusercontent.com/u/52716203?u=636b4f79645176df4527dd45c12d5dbb5a4193cf&v=4
- url: https://github.com/yezz123
- login: ycd
count: 45
- avatarUrl: https://avatars.githubusercontent.com/u/62724709?u=fa40e037060d62bf82e16b505d870a2866725f38&v=4
+ avatarUrl: https://avatars.githubusercontent.com/u/62724709?u=bba5af018423a2858d49309bed2a899bb5c34ac5&v=4
url: https://github.com/ycd
- login: cikay
count: 41
avatarUrl: https://avatars.githubusercontent.com/u/24587499?u=e772190a051ab0eaa9c8542fcff1892471638f2b&v=4
url: https://github.com/cikay
+- login: JarroVGIT
+ count: 34
+ avatarUrl: https://avatars.githubusercontent.com/u/13659033?u=e8bea32d07a5ef72f7dde3b2079ceb714923ca05&v=4
+ url: https://github.com/JarroVGIT
- login: AdrianDeAnda
count: 33
avatarUrl: https://avatars.githubusercontent.com/u/1024932?u=b2ea249c6b41ddf98679c8d110d0f67d4a3ebf93&v=4
url: https://github.com/AdrianDeAnda
+- login: iudeen
+ count: 33
+ avatarUrl: https://avatars.githubusercontent.com/u/10519440?u=2843b3303282bff8b212dcd4d9d6689452e4470c&v=4
+ url: https://github.com/iudeen
- login: ArcLightSlavik
count: 31
avatarUrl: https://avatars.githubusercontent.com/u/31127044?u=b0f2c37142f4b762e41ad65dc49581813422bd71&v=4
url: https://github.com/ArcLightSlavik
-- login: JarroVGIT
- count: 31
- avatarUrl: https://avatars.githubusercontent.com/u/13659033?u=e8bea32d07a5ef72f7dde3b2079ceb714923ca05&v=4
- url: https://github.com/JarroVGIT
+- login: komtaki
+ count: 27
+ avatarUrl: https://avatars.githubusercontent.com/u/39375566?u=260ad6b1a4b34c07dbfa728da5e586f16f6d1824&v=4
+ url: https://github.com/komtaki
- login: cassiobotaro
- count: 25
+ count: 26
avatarUrl: https://avatars.githubusercontent.com/u/3127847?u=b0a652331da17efeb85cd6e3a4969182e5004804&v=4
url: https://github.com/cassiobotaro
- login: lsglucas
- count: 24
+ count: 26
avatarUrl: https://avatars.githubusercontent.com/u/61513630?u=320e43fe4dc7bc6efc64e9b8f325f8075634fd20&v=4
url: https://github.com/lsglucas
- login: dmontagu
count: 23
avatarUrl: https://avatars.githubusercontent.com/u/35119617?u=58ed2a45798a4339700e2f62b2e12e6e54bf0396&v=4
url: https://github.com/dmontagu
-- login: komtaki
- count: 21
- avatarUrl: https://avatars.githubusercontent.com/u/39375566?u=260ad6b1a4b34c07dbfa728da5e586f16f6d1824&v=4
- url: https://github.com/komtaki
- login: hard-coders
count: 20
avatarUrl: https://avatars.githubusercontent.com/u/9651103?u=95db33927bbff1ed1c07efddeb97ac2ff33068ed&v=4
@@ -392,6 +404,14 @@ top_reviewers:
count: 19
avatarUrl: https://avatars.githubusercontent.com/u/63915557?u=47debaa860fd52c9b98c97ef357ddcec3b3fb399&v=4
url: https://github.com/0417taehyun
+- login: rjNemo
+ count: 17
+ avatarUrl: https://avatars.githubusercontent.com/u/56785022?u=d5c3a02567c8649e146fcfc51b6060ccaf8adef8&v=4
+ url: https://github.com/rjNemo
+- login: Smlep
+ count: 17
+ avatarUrl: https://avatars.githubusercontent.com/u/16785985?v=4
+ url: https://github.com/Smlep
- login: zy7y
count: 17
avatarUrl: https://avatars.githubusercontent.com/u/67154681?u=5d634834cc514028ea3f9115f7030b99a1f4d5a4&v=4
@@ -404,14 +424,6 @@ top_reviewers:
count: 16
avatarUrl: https://avatars.githubusercontent.com/u/52768429?u=6a3aa15277406520ad37f6236e89466ed44bc5b8&v=4
url: https://github.com/SwftAlpc
-- login: rjNemo
- count: 16
- avatarUrl: https://avatars.githubusercontent.com/u/56785022?u=d5c3a02567c8649e146fcfc51b6060ccaf8adef8&v=4
- url: https://github.com/rjNemo
-- login: Smlep
- count: 16
- avatarUrl: https://avatars.githubusercontent.com/u/16785985?v=4
- url: https://github.com/Smlep
- login: DevDae
count: 16
avatarUrl: https://avatars.githubusercontent.com/u/87962045?u=08e10fa516e844934f4b3fc7c38b33c61697e4a1&v=4
@@ -424,10 +436,10 @@ top_reviewers:
count: 15
avatarUrl: https://avatars.githubusercontent.com/u/63476957?u=6c86e59b48e0394d4db230f37fc9ad4d7e2c27c7&v=4
url: https://github.com/delhi09
-- login: iudeen
- count: 14
- avatarUrl: https://avatars.githubusercontent.com/u/10519440?u=2843b3303282bff8b212dcd4d9d6689452e4470c&v=4
- url: https://github.com/iudeen
+- login: odiseo0
+ count: 15
+ avatarUrl: https://avatars.githubusercontent.com/u/87550035?u=16f9255804161c6ff3c8b7ef69848f0126bcd405&v=4
+ url: https://github.com/odiseo0
- login: sh0nk
count: 13
avatarUrl: https://avatars.githubusercontent.com/u/6478810?u=af15d724875cec682ed8088a86d36b2798f981c0&v=4
@@ -436,10 +448,6 @@ top_reviewers:
count: 12
avatarUrl: https://avatars.githubusercontent.com/u/31848542?u=efb5b45b55584450507834f279ce48d4d64dea2f&v=4
url: https://github.com/RunningIkkyu
-- login: odiseo0
- count: 12
- avatarUrl: https://avatars.githubusercontent.com/u/87550035?u=ab724eae71c3fe1cf81e8dc76e73415da926ef7d&v=4
- url: https://github.com/odiseo0
- login: LorhanSohaky
count: 11
avatarUrl: https://avatars.githubusercontent.com/u/16273730?u=095b66f243a2cd6a0aadba9a095009f8aaf18393&v=4
@@ -462,8 +470,16 @@ top_reviewers:
url: https://github.com/maoyibo
- login: ComicShrimp
count: 10
- avatarUrl: https://avatars.githubusercontent.com/u/43503750?u=b3e4d9a14d9a65d429ce62c566aef73178b7111d&v=4
+ avatarUrl: https://avatars.githubusercontent.com/u/43503750?u=f440bc9062afb3c43b9b9c6cdfdcfe31d58699ef&v=4
url: https://github.com/ComicShrimp
+- login: peidrao
+ count: 10
+ avatarUrl: https://avatars.githubusercontent.com/u/32584628?u=88c2cb42a99e0f50cdeae3606992568184783ee5&v=4
+ url: https://github.com/peidrao
+- login: izaguerreiro
+ count: 9
+ avatarUrl: https://avatars.githubusercontent.com/u/2241504?v=4
+ url: https://github.com/izaguerreiro
- login: graingert
count: 9
avatarUrl: https://avatars.githubusercontent.com/u/413772?u=64b77b6aa405c68a9c6bcf45f84257c66eea5f32&v=4
@@ -480,10 +496,6 @@ top_reviewers:
count: 9
avatarUrl: https://avatars.githubusercontent.com/u/69092910?u=4ac58eab99bd37d663f3d23551df96d4fbdbf760&v=4
url: https://github.com/bezaca
-- login: izaguerreiro
- count: 8
- avatarUrl: https://avatars.githubusercontent.com/u/2241504?v=4
- url: https://github.com/izaguerreiro
- login: raphaelauv
count: 8
avatarUrl: https://avatars.githubusercontent.com/u/10202690?u=e6f86f5c0c3026a15d6b51792fa3e532b12f1371&v=4
@@ -504,6 +516,10 @@ top_reviewers:
count: 8
avatarUrl: https://avatars.githubusercontent.com/u/662249?v=4
url: https://github.com/dimaqq
+- login: Xewus
+ count: 8
+ avatarUrl: https://avatars.githubusercontent.com/u/85196001?u=4bdd4a0300530a504987db27488ba79c37f2fb18&v=4
+ url: https://github.com/Xewus
- login: Serrones
count: 7
avatarUrl: https://avatars.githubusercontent.com/u/22691749?u=4795b880e13ca33a73e52fc0ef7dc9c60c8fce47&v=4
@@ -512,11 +528,3 @@ top_reviewers:
count: 7
avatarUrl: https://avatars.githubusercontent.com/u/21287303?u=b049eac3e51a4c0473c2efe66b4d28a7d8f2b572&v=4
url: https://github.com/jovicon
-- login: ryuckel
- count: 7
- avatarUrl: https://avatars.githubusercontent.com/u/36391432?u=094eec0cfddd5013f76f31e55e56147d78b19553&v=4
- url: https://github.com/ryuckel
-- login: NastasiaSaby
- count: 7
- avatarUrl: https://avatars.githubusercontent.com/u/8245071?u=b3afd005f9e4bf080c219ef61a592b3a8004b764&v=4
- url: https://github.com/NastasiaSaby
diff --git a/docs/en/docs/advanced/async-tests.md b/docs/en/docs/advanced/async-tests.md
index e34f48f173..9b39d70fca 100644
--- a/docs/en/docs/advanced/async-tests.md
+++ b/docs/en/docs/advanced/async-tests.md
@@ -1,6 +1,6 @@
# Async Tests
-You have already seen how to test your **FastAPI** applications using the provided `TestClient`, but with it, you can't test or run any other `async` function in your (synchronous) pytest functions.
+You have already seen how to test your **FastAPI** applications using the provided `TestClient`. Up to now, you have only seen how to write synchronous tests, without using `async` functions.
Being able to use asynchronous functions in your tests could be useful, for example, when you're querying your database asynchronously. Imagine you want to test sending requests to your FastAPI application and then verify that your backend successfully wrote the correct data in the database, while using an async database library.
@@ -8,7 +8,7 @@ Let's look at how we can make that work.
## pytest.mark.anyio
-If we want to call asynchronous functions in our tests, our test functions have to be asynchronous. Anyio provides a neat plugin for this, that allows us to specify that some test functions are to be called asynchronously.
+If we want to call asynchronous functions in our tests, our test functions have to be asynchronous. AnyIO provides a neat plugin for this, that allows us to specify that some test functions are to be called asynchronously.
## HTTPX
@@ -16,13 +16,7 @@ Even if your **FastAPI** application uses normal `def` functions instead of `asy
The `TestClient` does some magic inside to call the asynchronous FastAPI application in your normal `def` test functions, using standard pytest. But that magic doesn't work anymore when we're using it inside asynchronous functions. By running our tests asynchronously, we can no longer use the `TestClient` inside our test functions.
-Luckily there's a nice alternative, called HTTPX.
-
-HTTPX is an HTTP client for Python 3 that allows us to query our FastAPI application similarly to how we did it with the `TestClient`.
-
-If you're familiar with the Requests library, you'll find that the API of HTTPX is almost identical.
-
-The important difference for us is that with HTTPX we are not limited to synchronous, but can also make asynchronous requests.
+The `TestClient` is based on HTTPX, and luckily, we can use it directly to test the API.
## Example
@@ -85,7 +79,7 @@ This is the equivalent to:
response = client.get('/')
```
-that we used to make our requests with the `TestClient`.
+...that we used to make our requests with the `TestClient`.
!!! tip
Note that we're using async/await with the new `AsyncClient` - the request is asynchronous.
diff --git a/docs/en/docs/advanced/middleware.md b/docs/en/docs/advanced/middleware.md
index ed90f29be7..3bf49e3922 100644
--- a/docs/en/docs/advanced/middleware.md
+++ b/docs/en/docs/advanced/middleware.md
@@ -68,7 +68,7 @@ Enforces that all incoming requests have a correctly set `Host` header, in order
The following arguments are supported:
-* `allowed_hosts` - A list of domain names that should be allowed as hostnames. Wildcard domains such as `*.example.com` are supported for matching subdomains to allow any hostname either use `allowed_hosts=["*"]` or omit the middleware.
+* `allowed_hosts` - A list of domain names that should be allowed as hostnames. Wildcard domains such as `*.example.com` are supported for matching subdomains. To allow any hostname either use `allowed_hosts=["*"]` or omit the middleware.
If an incoming request does not validate correctly then a `400` response will be sent.
diff --git a/docs/en/docs/advanced/openapi-callbacks.md b/docs/en/docs/advanced/openapi-callbacks.md
index 656ddbb3f5..71924ce8b2 100644
--- a/docs/en/docs/advanced/openapi-callbacks.md
+++ b/docs/en/docs/advanced/openapi-callbacks.md
@@ -50,7 +50,7 @@ It could be just one or two lines of code, like:
```Python
callback_url = "https://example.com/api/v1/invoices/events/"
-requests.post(callback_url, json={"description": "Invoice paid", "paid": True})
+httpx.post(callback_url, json={"description": "Invoice paid", "paid": True})
```
But possibly the most important part of the callback is making sure that your API user (the external developer) implements the *external API* correctly, according to the data that *your API* is going to send in the request body of the callback, etc.
@@ -64,7 +64,7 @@ This example doesn't implement the callback itself (that could be just a line of
!!! tip
The actual callback is just an HTTP request.
- When implementing the callback yourself, you could use something like HTTPX or Requests.
+ When implementing the callback yourself, you could use something like HTTPX or Requests.
## Write the callback documentation code
diff --git a/docs/en/docs/advanced/websockets.md b/docs/en/docs/advanced/websockets.md
index 0e9bc5b06b..3cf840819f 100644
--- a/docs/en/docs/advanced/websockets.md
+++ b/docs/en/docs/advanced/websockets.md
@@ -112,17 +112,15 @@ In WebSocket endpoints you can import from `fastapi` and use:
They work the same way as for other FastAPI endpoints/*path operations*:
-```Python hl_lines="58-65 68-83"
+```Python hl_lines="66-77 76-91"
{!../../../docs_src/websockets/tutorial002.py!}
```
!!! info
- In a WebSocket it doesn't really make sense to raise an `HTTPException`. So it's better to close the WebSocket connection directly.
+ As this is a WebSocket it doesn't really make sense to raise an `HTTPException`, instead we raise a `WebSocketException`.
You can use a closing code from the valid codes defined in the specification.
- In the future, there will be a `WebSocketException` that you will be able to `raise` from anywhere, and add exception handlers for it. It depends on the PR #527 in Starlette.
-
### Try the WebSockets with dependencies
If your file is named `main.py`, run your application with:
diff --git a/docs/en/docs/alternatives.md b/docs/en/docs/alternatives.md
index bcd406bf9d..0f074ccf32 100644
--- a/docs/en/docs/alternatives.md
+++ b/docs/en/docs/alternatives.md
@@ -367,7 +367,7 @@ It has:
* WebSocket support.
* In-process background tasks.
* Startup and shutdown events.
-* Test client built on requests.
+* Test client built on HTTPX.
* CORS, GZip, Static Files, Streaming responses.
* Session and Cookie support.
* 100% test coverage.
diff --git a/docs/en/docs/features.md b/docs/en/docs/features.md
index 02bb3ac1f2..387ff86c99 100644
--- a/docs/en/docs/features.md
+++ b/docs/en/docs/features.md
@@ -166,7 +166,7 @@ With **FastAPI** you get all of **Starlette**'s features (as FastAPI is just Sta
* **WebSocket** support.
* In-process background tasks.
* Startup and shutdown events.
-* Test client built on `requests`.
+* Test client built on HTTPX.
* **CORS**, GZip, Static Files, Streaming responses.
* **Session and Cookie** support.
* 100% test coverage.
diff --git a/docs/en/docs/help-fastapi.md b/docs/en/docs/help-fastapi.md
index 8d8d708ed9..a7ac9415fc 100644
--- a/docs/en/docs/help-fastapi.md
+++ b/docs/en/docs/help-fastapi.md
@@ -47,7 +47,7 @@ You can:
* Follow me on **GitHub**.
* See other Open Source projects I have created that could help you.
* Follow me to see when I create a new Open Source project.
-* Follow me on **Twitter**.
+* Follow me on **Twitter** or Mastodon.
* Tell me how you use FastAPI (I love to hear that).
* Hear when I make announcements or release new tools.
* You can also follow @fastapi on Twitter (a separate account).
@@ -67,13 +67,54 @@ I love to hear about how **FastAPI** is being used, what you have liked in it, i
* Vote for **FastAPI** in Slant.
* Vote for **FastAPI** in AlternativeTo.
+* Say you use **FastAPI** on StackShare.
## Help others with issues in GitHub
-You can see existing issues and try and help others, most of the times they are questions that you might already know the answer for. 🤓
+You can see existing issues and try and help others, most of the times those issues are questions that you might already know the answer for. 🤓
If you are helping a lot of people with issues, you might become an official [FastAPI Expert](fastapi-people.md#experts){.internal-link target=_blank}. 🎉
+Just remember, the most important point is: try to be kind. People come with their frustrations and in many cases don't ask in the best way, but try as best as you can to be kind. 🤗
+
+The idea is for the **FastAPI** community to be kind and welcoming. At the same time, don't accept bullying or disrespectful behavior towards others. We have to take care of each other.
+
+---
+
+Here's how to help others with issues:
+
+### Understand the question
+
+* Check if you can understand what is the **purpose** and use case of the person asking.
+
+* Then check if the question (the vast majority are questions) is **clear**.
+
+* In many cases the question asked is about an imaginary solution from the user, but there might be a **better** one. If you can understand the problem and use case better, you might be able to suggest a better **alternative solution**.
+
+* If you can't understand the question, ask for more **details**.
+
+### Reproduce the problem
+
+For most of the cases and most of the questions there's something related to the person's **original code**.
+
+In many cases they will only copy a fragment of the code, but that's not enough to **reproduce the problem**.
+
+* You can ask them to provide a minimal, reproducible, example, that you can **copy-paste** and run locally to see the same error or behavior they are seeing, or to understand their use case better.
+
+* If you are feeling too generous, you can try to **create an example** like that yourself, just based on the description of the problem. Just have in mind that this might take a lot of time and it might be better to ask them to clarify the problem first.
+
+### Suggest solutions
+
+* After being able to understand the question, you can give them a possible **answer**.
+
+* In many cases, it's better to understand their **underlying problem or use case**, because there might be a better way to solve it than what they are trying to do.
+
+### Ask to close
+
+If they reply, there's a high chance you would have solved their problem, congrats, **you're a hero**! 🦸
+
+* Now you can ask them, if that solved their problem, to **close the issue**.
+
## Watch the GitHub repository
You can "watch" FastAPI in GitHub (clicking the "watch" button at the top right): https://github.com/tiangolo/fastapi. 👀
@@ -91,6 +132,57 @@ You can
-
-
+
+
@@ -424,7 +424,7 @@ For a more complete example including more features, see the Strawberry and other libraries.
* Many extra features (thanks to Starlette) as:
* **WebSockets**
- * extremely easy tests based on `requests` and `pytest`
+ * extremely easy tests based on HTTPX and `pytest`
* **CORS**
* **Cookie Sessions**
* ...and more.
@@ -444,7 +444,7 @@ Used by Pydantic:
Used by Starlette:
-*
requests - Required if you want to use the `TestClient`.
+* httpx - Required if you want to use the `TestClient`.
* jinja2 - Required if you want to use the default template configuration.
* python-multipart - Required if you want to support form "parsing", with `request.form()`.
* itsdangerous - Required for `SessionMiddleware` support.
diff --git a/docs/en/docs/release-notes.md b/docs/en/docs/release-notes.md
index c6911566aa..b65460294b 100644
--- a/docs/en/docs/release-notes.md
+++ b/docs/en/docs/release-notes.md
@@ -2,6 +2,104 @@
## Latest Changes
+* ⬆ Bump nwtgck/actions-netlify from 1.2.4 to 2.0.0. PR [#5757](https://github.com/tiangolo/fastapi/pull/5757) by [@dependabot[bot]](https://github.com/apps/dependabot).
+* 👷 Refactor CI artifact upload/download for docs previews. PR [#5793](https://github.com/tiangolo/fastapi/pull/5793) by [@tiangolo](https://github.com/tiangolo).
+* ⬆ Bump pypa/gh-action-pypi-publish from 1.5.1 to 1.5.2. PR [#5714](https://github.com/tiangolo/fastapi/pull/5714) by [@dependabot[bot]](https://github.com/apps/dependabot).
+* 👥 Update FastAPI People. PR [#5722](https://github.com/tiangolo/fastapi/pull/5722) by [@github-actions[bot]](https://github.com/apps/github-actions).
+* 🔧 Update sponsors, disable course bundle. PR [#5713](https://github.com/tiangolo/fastapi/pull/5713) by [@tiangolo](https://github.com/tiangolo).
+* ⬆ Update typer[all] requirement from <0.7.0,>=0.6.1 to >=0.6.1,<0.8.0. PR [#5639](https://github.com/tiangolo/fastapi/pull/5639) by [@dependabot[bot]](https://github.com/apps/dependabot).
+
+## 0.88.0
+
+### Upgrades
+
+* ⬆ Bump Starlette to version `0.22.0` to fix bad encoding for query parameters in new `TestClient`. PR [#5659](https://github.com/tiangolo/fastapi/pull/5659) by [@azogue](https://github.com/azogue).
+
+### Docs
+
+* ✏️ Fix typo in docs for `docs/en/docs/advanced/middleware.md`. PR [#5376](https://github.com/tiangolo/fastapi/pull/5376) by [@rifatrakib](https://github.com/rifatrakib).
+
+### Translations
+
+* 🌐 Add Portuguese translation for `docs/pt/docs/deployment/docker.md`. PR [#5663](https://github.com/tiangolo/fastapi/pull/5663) by [@ayr-ton](https://github.com/ayr-ton).
+
+### Internal
+
+* 👷 Tweak build-docs to improve CI performance. PR [#5699](https://github.com/tiangolo/fastapi/pull/5699) by [@tiangolo](https://github.com/tiangolo).
+* ⬆ [pre-commit.ci] pre-commit autoupdate. PR [#5566](https://github.com/tiangolo/fastapi/pull/5566) by [@pre-commit-ci[bot]](https://github.com/apps/pre-commit-ci).
+* ⬆️ Upgrade Ruff. PR [#5698](https://github.com/tiangolo/fastapi/pull/5698) by [@tiangolo](https://github.com/tiangolo).
+* 👷 Remove pip cache for Smokeshow as it depends on a requirements.txt. PR [#5700](https://github.com/tiangolo/fastapi/pull/5700) by [@tiangolo](https://github.com/tiangolo).
+* 💚 Fix pip cache for Smokeshow. PR [#5697](https://github.com/tiangolo/fastapi/pull/5697) by [@tiangolo](https://github.com/tiangolo).
+* 👷 Fix and tweak CI cache handling. PR [#5696](https://github.com/tiangolo/fastapi/pull/5696) by [@tiangolo](https://github.com/tiangolo).
+* 👷 Update `setup-python` action in tests to use new caching feature. PR [#5680](https://github.com/tiangolo/fastapi/pull/5680) by [@madkinsz](https://github.com/madkinsz).
+* ⬆ Bump black from 22.8.0 to 22.10.0. PR [#5569](https://github.com/tiangolo/fastapi/pull/5569) by [@dependabot[bot]](https://github.com/apps/dependabot).
+
+## 0.87.0
+
+Highlights of this release:
+
+* [Upgraded Starlette](https://github.com/encode/starlette/releases/tag/0.21.0)
+ * Now the `TestClient` is based on HTTPX instead of Requests. 🚀
+ * There are some possible **breaking changes** in the `TestClient` usage, but [@Kludex](https://github.com/Kludex) built [bump-testclient](https://github.com/Kludex/bump-testclient) to help you automatize migrating your tests. Make sure you are using Git and that you can undo any unnecessary changes (false positive changes, etc) before using `bump-testclient`.
+* New [WebSocketException (and docs)](https://fastapi.tiangolo.com/advanced/websockets/#using-depends-and-others), re-exported from Starlette.
+* Upgraded and relaxed dependencies for package extras `all` (including new Uvicorn version), when you install `"fastapi[all]"`.
+* New docs about how to [**Help Maintain FastAPI**](https://fastapi.tiangolo.com/help-fastapi/#help-maintain-fastapi).
+
+### Features
+
+* ⬆️ Upgrade and relax dependencies for extras "all". PR [#5634](https://github.com/tiangolo/fastapi/pull/5634) by [@tiangolo](https://github.com/tiangolo).
+* ✨ Re-export Starlette's `WebSocketException` and add it to docs. PR [#5629](https://github.com/tiangolo/fastapi/pull/5629) by [@tiangolo](https://github.com/tiangolo).
+* 📝 Update references to Requests for tests to HTTPX, and add HTTPX to extras. PR [#5628](https://github.com/tiangolo/fastapi/pull/5628) by [@tiangolo](https://github.com/tiangolo).
+* ⬆ Upgrade Starlette to `0.21.0`, including the new [`TestClient` based on HTTPX](https://github.com/encode/starlette/releases/tag/0.21.0). PR [#5471](https://github.com/tiangolo/fastapi/pull/5471) by [@pawelrubin](https://github.com/pawelrubin).
+
+### Docs
+
+* ✏️ Tweak Help FastAPI from PR review after merging. PR [#5633](https://github.com/tiangolo/fastapi/pull/5633) by [@tiangolo](https://github.com/tiangolo).
+* ✏️ Clarify docs on CORS. PR [#5627](https://github.com/tiangolo/fastapi/pull/5627) by [@paxcodes](https://github.com/paxcodes).
+* 📝 Update Help FastAPI: Help Maintain FastAPI. PR [#5632](https://github.com/tiangolo/fastapi/pull/5632) by [@tiangolo](https://github.com/tiangolo).
+
+### Translations
+
+* 🌐 Fix highlight lines for Japanese translation for `docs/tutorial/query-params.md`. PR [#2969](https://github.com/tiangolo/fastapi/pull/2969) by [@ftnext](https://github.com/ftnext).
+* 🌐 Add French translation for `docs/fr/docs/advanced/additional-status-code.md`. PR [#5477](https://github.com/tiangolo/fastapi/pull/5477) by [@axel584](https://github.com/axel584).
+* 🌐 Add Portuguese translation for `docs/pt/docs/tutorial/request-forms-and-files.md`. PR [#5579](https://github.com/tiangolo/fastapi/pull/5579) by [@batlopes](https://github.com/batlopes).
+* 🌐 Add Japanese translation for `docs/ja/docs/advanced/websockets.md`. PR [#4983](https://github.com/tiangolo/fastapi/pull/4983) by [@xryuseix](https://github.com/xryuseix).
+
+### Internal
+
+* ✨ Use Ruff for linting. PR [#5630](https://github.com/tiangolo/fastapi/pull/5630) by [@tiangolo](https://github.com/tiangolo).
+* 🛠 Add Arabic issue number to Notify Translations GitHub Action. PR [#5610](https://github.com/tiangolo/fastapi/pull/5610) by [@tiangolo](https://github.com/tiangolo).
+* ⬆ Bump dawidd6/action-download-artifact from 2.24.1 to 2.24.2. PR [#5609](https://github.com/tiangolo/fastapi/pull/5609) by [@dependabot[bot]](https://github.com/apps/dependabot).
+* ⬆ Bump dawidd6/action-download-artifact from 2.24.0 to 2.24.1. PR [#5603](https://github.com/tiangolo/fastapi/pull/5603) by [@dependabot[bot]](https://github.com/apps/dependabot).
+* 📝 Update coverage badge to use Samuel Colvin's Smokeshow. PR [#5585](https://github.com/tiangolo/fastapi/pull/5585) by [@tiangolo](https://github.com/tiangolo).
+
+## 0.86.0
+
+### Features
+
+* ⬆ Add Python 3.11 to the officially supported versions. PR [#5587](https://github.com/tiangolo/fastapi/pull/5587) by [@tiangolo](https://github.com/tiangolo).
+* ✅ Enable tests for Python 3.11. PR [#4881](https://github.com/tiangolo/fastapi/pull/4881) by [@tiangolo](https://github.com/tiangolo).
+
+### Fixes
+
+* 🐛 Close FormData (uploaded files) after the request is done. PR [#5465](https://github.com/tiangolo/fastapi/pull/5465) by [@adriangb](https://github.com/adriangb).
+
+### Docs
+
+* ✏ Fix typo in `docs/en/docs/tutorial/security/oauth2-jwt.md`. PR [#5584](https://github.com/tiangolo/fastapi/pull/5584) by [@vivekashok1221](https://github.com/vivekashok1221).
+
+### Translations
+
+* 🌐 Update wording in Chinese translation for `docs/zh/docs/python-types.md`. PR [#5416](https://github.com/tiangolo/fastapi/pull/5416) by [@supercaizehua](https://github.com/supercaizehua).
+* 🌐 Add Russian translation for `docs/ru/docs/deployment/index.md`. PR [#5336](https://github.com/tiangolo/fastapi/pull/5336) by [@Xewus](https://github.com/Xewus).
+* 🌐 Update Chinese translation for `docs/tutorial/security/oauth2-jwt.md`. PR [#3846](https://github.com/tiangolo/fastapi/pull/3846) by [@jaystone776](https://github.com/jaystone776).
+
+### Internal
+
+* 👷 Update FastAPI People to exclude bots: pre-commit-ci, dependabot. PR [#5586](https://github.com/tiangolo/fastapi/pull/5586) by [@tiangolo](https://github.com/tiangolo).
+* 🎨 Format OpenAPI JSON in `test_starlette_exception.py`. PR [#5379](https://github.com/tiangolo/fastapi/pull/5379) by [@iudeen](https://github.com/iudeen).
+* 👷 Switch from Codecov to Smokeshow plus pytest-cov to pure coverage for internal tests. PR [#5583](https://github.com/tiangolo/fastapi/pull/5583) by [@tiangolo](https://github.com/tiangolo).
+* 👥 Update FastAPI People. PR [#5571](https://github.com/tiangolo/fastapi/pull/5571) by [@github-actions[bot]](https://github.com/apps/github-actions).
## 0.85.2
diff --git a/docs/en/docs/tutorial/cors.md b/docs/en/docs/tutorial/cors.md
index 4ab3da3b4f..33b11983b3 100644
--- a/docs/en/docs/tutorial/cors.md
+++ b/docs/en/docs/tutorial/cors.md
@@ -57,7 +57,7 @@ The following arguments are supported:
* `allow_origins` - A list of origins that should be permitted to make cross-origin requests. E.g. `['https://example.org', 'https://www.example.org']`. You can use `['*']` to allow any origin.
* `allow_origin_regex` - A regex string to match against origins that should be permitted to make cross-origin requests. e.g. `'https://.*\.example\.org'`.
* `allow_methods` - A list of HTTP methods that should be allowed for cross-origin requests. Defaults to `['GET']`. You can use `['*']` to allow all standard methods.
-* `allow_headers` - A list of HTTP request headers that should be supported for cross-origin requests. Defaults to `[]`. You can use `['*']` to allow all headers. The `Accept`, `Accept-Language`, `Content-Language` and `Content-Type` headers are always allowed for CORS requests.
+* `allow_headers` - A list of HTTP request headers that should be supported for cross-origin requests. Defaults to `[]`. You can use `['*']` to allow all headers. The `Accept`, `Accept-Language`, `Content-Language` and `Content-Type` headers are always allowed for simple CORS requests.
* `allow_credentials` - Indicate that cookies should be supported for cross-origin requests. Defaults to `False`. Also, `allow_origins` cannot be set to `['*']` for credentials to be allowed, origins must be specified.
* `expose_headers` - Indicate any response headers that should be made accessible to the browser. Defaults to `[]`.
* `max_age` - Sets a maximum time in seconds for browsers to cache CORS responses. Defaults to `600`.
diff --git a/docs/en/docs/tutorial/security/oauth2-jwt.md b/docs/en/docs/tutorial/security/oauth2-jwt.md
index 09557f1ac5..41f00fd41e 100644
--- a/docs/en/docs/tutorial/security/oauth2-jwt.md
+++ b/docs/en/docs/tutorial/security/oauth2-jwt.md
@@ -257,7 +257,7 @@ Call the endpoint `/users/me/`, you will get the response as:
-If you open the developer tools, you could see how the data sent and only includes the token, the password is only sent in the first request to authenticate the user and get that access token, but not afterwards:
+If you open the developer tools, you could see how the data sent only includes the token, the password is only sent in the first request to authenticate the user and get that access token, but not afterwards:
diff --git a/docs/en/docs/tutorial/testing.md b/docs/en/docs/tutorial/testing.md
index d2ccd7dc77..be07aab37d 100644
--- a/docs/en/docs/tutorial/testing.md
+++ b/docs/en/docs/tutorial/testing.md
@@ -2,16 +2,16 @@
Thanks to Starlette, testing **FastAPI** applications is easy and enjoyable.
-It is based on Requests, so it's very familiar and intuitive.
+It is based on HTTPX, which in turn is designed based on Requests, so it's very familiar and intuitive.
With it, you can use pytest directly with **FastAPI**.
## Using `TestClient`
!!! info
- To use `TestClient`, first install `requests`.
+ To use `TestClient`, first install `httpx`.
- E.g. `pip install requests`.
+ E.g. `pip install httpx`.
Import `TestClient`.
@@ -19,7 +19,7 @@ Create a `TestClient` by passing your **FastAPI** application to it.
Create functions with a name that starts with `test_` (this is standard `pytest` conventions).
-Use the `TestClient` object the same way as you do with `requests`.
+Use the `TestClient` object the same way as you do with `httpx`.
Write simple `assert` statements with the standard Python expressions that you need to check (again, standard `pytest`).
@@ -130,7 +130,7 @@ You could then update `test_main.py` with the extended tests:
{!> ../../../docs_src/app_testing/app_b/test_main.py!}
```
-Whenever you need the client to pass information in the request and you don't know how to, you can search (Google) how to do it in `requests`.
+Whenever you need the client to pass information in the request and you don't know how to, you can search (Google) how to do it in `httpx`, or even how to do it with `requests`, as HTTPX's design is based on Requests' design.
Then you just do the same in your tests.
@@ -142,7 +142,7 @@ E.g.:
* To pass *headers*, use a `dict` in the `headers` parameter.
* For *cookies*, a `dict` in the `cookies` parameter.
-For more information about how to pass data to the backend (using `requests` or the `TestClient`) check the Requests documentation.
+For more information about how to pass data to the backend (using `httpx` or the `TestClient`) check the HTTPX documentation.
!!! info
Note that the `TestClient` receives data that can be converted to JSON, not Pydantic models.
diff --git a/docs/en/overrides/main.html b/docs/en/overrides/main.html
index c5eb94870d..e9b9f60eb6 100644
--- a/docs/en/overrides/main.html
+++ b/docs/en/overrides/main.html
@@ -22,12 +22,6 @@
-
- requests - Requerido si quieres usar el `TestClient`.
+* httpx - Requerido si quieres usar el `TestClient`.
* jinja2 - Requerido si quieres usar la configuración por defecto de templates.
* python-multipart - Requerido si quieres dar soporte a "parsing" de formularios, con `request.form()`.
* itsdangerous - Requerido para dar soporte a `SessionMiddleware`.
diff --git a/docs/fa/docs/index.md b/docs/fa/docs/index.md
index 0f7cd569ae..dfc4d24e33 100644
--- a/docs/fa/docs/index.md
+++ b/docs/fa/docs/index.md
@@ -421,7 +421,7 @@ item: Item
* قابلیتهای اضافی دیگر (بر اساس Starlette) شامل:
* **وبسوکت**
* **GraphQL**
- * تستهای خودکار آسان مبتنی بر `requests` و `pytest`
+ * تستهای خودکار آسان مبتنی بر HTTPX و `pytest`
* **CORS**
* **Cookie Sessions**
* و موارد بیشمار دیگر.
@@ -441,7 +441,7 @@ item: Item
استفاده شده توسط Starlette:
-* requests - در صورتی که میخواهید از `TestClient` استفاده کنید.
+* HTTPX - در صورتی که میخواهید از `TestClient` استفاده کنید.
* aiofiles - در صورتی که میخواهید از `FileResponse` و `StaticFiles` استفاده کنید.
* jinja2 - در صورتی که بخواهید از پیکربندی پیشفرض برای قالبها استفاده کنید.
* python-multipart - در صورتی که بخواهید با استفاده از `request.form()` از قابلیت "تجزیه (parse)" فرم استفاده کنید.
diff --git a/docs/fr/docs/advanced/additional-responses.md b/docs/fr/docs/advanced/additional-responses.md
new file mode 100644
index 0000000000..35b57594d5
--- /dev/null
+++ b/docs/fr/docs/advanced/additional-responses.md
@@ -0,0 +1,240 @@
+# Réponses supplémentaires dans OpenAPI
+
+!!! Attention
+ Ceci concerne un sujet plutôt avancé.
+
+ Si vous débutez avec **FastAPI**, vous n'en aurez peut-être pas besoin.
+
+Vous pouvez déclarer des réponses supplémentaires, avec des codes HTTP, des types de médias, des descriptions, etc.
+
+Ces réponses supplémentaires seront incluses dans le schéma OpenAPI, elles apparaîtront donc également dans la documentation de l'API.
+
+Mais pour ces réponses supplémentaires, vous devez vous assurer de renvoyer directement une `Response` comme `JSONResponse`, avec votre code HTTP et votre contenu.
+
+## Réponse supplémentaire avec `model`
+
+Vous pouvez ajouter à votre décorateur de *paramètre de chemin* un paramètre `responses`.
+
+Il prend comme valeur un `dict` dont les clés sont des codes HTTP pour chaque réponse, comme `200`, et la valeur de ces clés sont d'autres `dict` avec des informations pour chacun d'eux.
+
+Chacun de ces `dict` de réponse peut avoir une clé `model`, contenant un modèle Pydantic, tout comme `response_model`.
+
+**FastAPI** prendra ce modèle, générera son schéma JSON et l'inclura au bon endroit dans OpenAPI.
+
+Par exemple, pour déclarer une autre réponse avec un code HTTP `404` et un modèle Pydantic `Message`, vous pouvez écrire :
+
+```Python hl_lines="18 22"
+{!../../../docs_src/additional_responses/tutorial001.py!}
+```
+
+!!! Remarque
+ Gardez à l'esprit que vous devez renvoyer directement `JSONResponse`.
+
+!!! Info
+ La clé `model` ne fait pas partie d'OpenAPI.
+
+ **FastAPI** prendra le modèle Pydantic à partir de là, générera le `JSON Schema` et le placera au bon endroit.
+
+ Le bon endroit est :
+
+ * Dans la clé `content`, qui a pour valeur un autre objet JSON (`dict`) qui contient :
+ * Une clé avec le type de support, par ex. `application/json`, qui contient comme valeur un autre objet JSON, qui contient :
+ * Une clé `schema`, qui a pour valeur le schéma JSON du modèle, voici le bon endroit.
+ * **FastAPI** ajoute ici une référence aux schémas JSON globaux à un autre endroit de votre OpenAPI au lieu de l'inclure directement. De cette façon, d'autres applications et clients peuvent utiliser ces schémas JSON directement, fournir de meilleurs outils de génération de code, etc.
+
+Les réponses générées au format OpenAPI pour cette *opération de chemin* seront :
+
+```JSON hl_lines="3-12"
+{
+ "responses": {
+ "404": {
+ "description": "Additional Response",
+ "content": {
+ "application/json": {
+ "schema": {
+ "$ref": "#/components/schemas/Message"
+ }
+ }
+ }
+ },
+ "200": {
+ "description": "Successful Response",
+ "content": {
+ "application/json": {
+ "schema": {
+ "$ref": "#/components/schemas/Item"
+ }
+ }
+ }
+ },
+ "422": {
+ "description": "Validation Error",
+ "content": {
+ "application/json": {
+ "schema": {
+ "$ref": "#/components/schemas/HTTPValidationError"
+ }
+ }
+ }
+ }
+ }
+}
+```
+
+Les schémas sont référencés à un autre endroit du modèle OpenAPI :
+
+```JSON hl_lines="4-16"
+{
+ "components": {
+ "schemas": {
+ "Message": {
+ "title": "Message",
+ "required": [
+ "message"
+ ],
+ "type": "object",
+ "properties": {
+ "message": {
+ "title": "Message",
+ "type": "string"
+ }
+ }
+ },
+ "Item": {
+ "title": "Item",
+ "required": [
+ "id",
+ "value"
+ ],
+ "type": "object",
+ "properties": {
+ "id": {
+ "title": "Id",
+ "type": "string"
+ },
+ "value": {
+ "title": "Value",
+ "type": "string"
+ }
+ }
+ },
+ "ValidationError": {
+ "title": "ValidationError",
+ "required": [
+ "loc",
+ "msg",
+ "type"
+ ],
+ "type": "object",
+ "properties": {
+ "loc": {
+ "title": "Location",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "msg": {
+ "title": "Message",
+ "type": "string"
+ },
+ "type": {
+ "title": "Error Type",
+ "type": "string"
+ }
+ }
+ },
+ "HTTPValidationError": {
+ "title": "HTTPValidationError",
+ "type": "object",
+ "properties": {
+ "detail": {
+ "title": "Detail",
+ "type": "array",
+ "items": {
+ "$ref": "#/components/schemas/ValidationError"
+ }
+ }
+ }
+ }
+ }
+ }
+}
+```
+
+## Types de médias supplémentaires pour la réponse principale
+
+Vous pouvez utiliser ce même paramètre `responses` pour ajouter différents types de médias pour la même réponse principale.
+
+Par exemple, vous pouvez ajouter un type de média supplémentaire `image/png`, en déclarant que votre *opération de chemin* peut renvoyer un objet JSON (avec le type de média `application/json`) ou une image PNG :
+
+```Python hl_lines="19-24 28"
+{!../../../docs_src/additional_responses/tutorial002.py!}
+```
+
+!!! Remarque
+ Notez que vous devez retourner l'image en utilisant directement un `FileResponse`.
+
+!!! Info
+ À moins que vous ne spécifiiez explicitement un type de média différent dans votre paramètre `responses`, FastAPI supposera que la réponse a le même type de média que la classe de réponse principale (par défaut `application/json`).
+
+ Mais si vous avez spécifié une classe de réponse personnalisée avec `None` comme type de média, FastAPI utilisera `application/json` pour toute réponse supplémentaire associée à un modèle.
+
+## Combinaison d'informations
+
+Vous pouvez également combiner des informations de réponse provenant de plusieurs endroits, y compris les paramètres `response_model`, `status_code` et `responses`.
+
+Vous pouvez déclarer un `response_model`, en utilisant le code HTTP par défaut `200` (ou un code personnalisé si vous en avez besoin), puis déclarer des informations supplémentaires pour cette même réponse dans `responses`, directement dans le schéma OpenAPI.
+
+**FastAPI** conservera les informations supplémentaires des `responses` et les combinera avec le schéma JSON de votre modèle.
+
+Par exemple, vous pouvez déclarer une réponse avec un code HTTP `404` qui utilise un modèle Pydantic et a une `description` personnalisée.
+
+Et une réponse avec un code HTTP `200` qui utilise votre `response_model`, mais inclut un `example` personnalisé :
+
+```Python hl_lines="20-31"
+{!../../../docs_src/additional_responses/tutorial003.py!}
+```
+
+Tout sera combiné et inclus dans votre OpenAPI, et affiché dans la documentation de l'API :
+
+
+
+## Combinez les réponses prédéfinies et les réponses personnalisées
+
+Vous voulez peut-être avoir des réponses prédéfinies qui s'appliquent à de nombreux *paramètre de chemin*, mais vous souhaitez les combiner avec des réponses personnalisées nécessaires à chaque *opération de chemin*.
+
+Dans ces cas, vous pouvez utiliser la technique Python "d'affection par décomposition" (appelé _unpacking_ en anglais) d'un `dict` avec `**dict_to_unpack` :
+
+``` Python
+old_dict = {
+ "old key": "old value",
+ "second old key": "second old value",
+}
+new_dict = {**old_dict, "new key": "new value"}
+```
+
+Ici, `new_dict` contiendra toutes les paires clé-valeur de `old_dict` plus la nouvelle paire clé-valeur :
+
+``` Python
+{
+ "old key": "old value",
+ "second old key": "second old value",
+ "new key": "new value",
+}
+```
+
+Vous pouvez utiliser cette technique pour réutiliser certaines réponses prédéfinies dans vos *paramètres de chemin* et les combiner avec des réponses personnalisées supplémentaires.
+
+Par exemple:
+
+```Python hl_lines="13-17 26"
+{!../../../docs_src/additional_responses/tutorial004.py!}
+```
+
+## Plus d'informations sur les réponses OpenAPI
+
+Pour voir exactement ce que vous pouvez inclure dans les réponses, vous pouvez consulter ces sections dans la spécification OpenAPI :
+
+* Objet Responses de OpenAPI , il inclut le `Response Object`.
+* Objet Response de OpenAPI , vous pouvez inclure n'importe quoi directement dans chaque réponse à l'intérieur de votre paramètre `responses`. Y compris `description`, `headers`, `content` (à l'intérieur de cela, vous déclarez différents types de médias et schémas JSON) et `links`.
diff --git a/docs/fr/docs/advanced/additional-status-codes.md b/docs/fr/docs/advanced/additional-status-codes.md
new file mode 100644
index 0000000000..e7b003707b
--- /dev/null
+++ b/docs/fr/docs/advanced/additional-status-codes.md
@@ -0,0 +1,37 @@
+# Codes HTTP supplémentaires
+
+Par défaut, **FastAPI** renverra les réponses à l'aide d'une structure de données `JSONResponse`, en plaçant la réponse de votre *chemin d'accès* à l'intérieur de cette `JSONResponse`.
+
+Il utilisera le code HTTP par défaut ou celui que vous avez défini dans votre *chemin d'accès*.
+
+## Codes HTTP supplémentaires
+
+Si vous souhaitez renvoyer des codes HTTP supplémentaires en plus du code principal, vous pouvez le faire en renvoyant directement une `Response`, comme une `JSONResponse`, et en définissant directement le code HTTP supplémentaire.
+
+Par exemple, disons que vous voulez avoir un *chemin d'accès* qui permet de mettre à jour les éléments et renvoie les codes HTTP 200 "OK" en cas de succès.
+
+Mais vous voulez aussi qu'il accepte de nouveaux éléments. Et lorsque les éléments n'existaient pas auparavant, il les crée et renvoie un code HTTP de 201 "Créé".
+
+Pour y parvenir, importez `JSONResponse` et renvoyez-y directement votre contenu, en définissant le `status_code` que vous souhaitez :
+
+```Python hl_lines="4 25"
+{!../../../docs_src/additional_status_codes/tutorial001.py!}
+```
+
+!!! Attention
+ Lorsque vous renvoyez une `Response` directement, comme dans l'exemple ci-dessus, elle sera renvoyée directement.
+
+ Elle ne sera pas sérialisée avec un modèle.
+
+ Assurez-vous qu'il contient les données souhaitées et que les valeurs soient dans un format JSON valides (si vous utilisez une `JSONResponse`).
+
+!!! note "Détails techniques"
+ Vous pouvez également utiliser `from starlette.responses import JSONResponse`.
+
+ Pour plus de commodités, **FastAPI** fournit les objets `starlette.responses` sous forme d'un alias accessible par `fastapi.responses`. Mais la plupart des réponses disponibles proviennent directement de Starlette. Il en est de même avec l'objet `statut`.
+
+## Documents OpenAPI et API
+
+Si vous renvoyez directement des codes HTTP et des réponses supplémentaires, ils ne seront pas inclus dans le schéma OpenAPI (la documentation de l'API), car FastAPI n'a aucun moyen de savoir à l'avance ce que vous allez renvoyer.
+
+Mais vous pouvez documenter cela dans votre code, en utilisant : [Réponses supplémentaires dans OpenAPI](additional-responses.md){.internal-link target=_blank}.
diff --git a/docs/fr/docs/index.md b/docs/fr/docs/index.md
index 6952044588..e7fb9947d5 100644
--- a/docs/fr/docs/index.md
+++ b/docs/fr/docs/index.md
@@ -426,7 +426,7 @@ For a more complete example including more features, see the requests - Required if you want to use the `TestClient`.
+* HTTPX - Required if you want to use the `TestClient`.
* jinja2 - Required if you want to use the default template configuration.
* python-multipart - Required if you want to support form "parsing", with `request.form()`.
* itsdangerous - Required for `SessionMiddleware` support.
diff --git a/docs/fr/mkdocs.yml b/docs/fr/mkdocs.yml
index 1c4f45682f..7dce4b1276 100644
--- a/docs/fr/mkdocs.yml
+++ b/docs/fr/mkdocs.yml
@@ -67,6 +67,9 @@ nav:
- tutorial/query-params.md
- tutorial/body.md
- tutorial/background-tasks.md
+- Guide utilisateur avancé:
+ - advanced/additional-status-codes.md
+ - advanced/additional-responses.md
- async.md
- Déploiement:
- deployment/index.md
diff --git a/docs/he/docs/index.md b/docs/he/docs/index.md
index fa63d8cb7c..19f2f20413 100644
--- a/docs/he/docs/index.md
+++ b/docs/he/docs/index.md
@@ -445,7 +445,7 @@ item: Item
בשימוש Starlette:
-- requests - דרוש אם ברצונכם להשתמש ב - `TestClient`.
+- httpx - דרוש אם ברצונכם להשתמש ב - `TestClient`.
- jinja2 - דרוש אם ברצונכם להשתמש בברירת המחדל של תצורת הטמפלייטים.
- python-multipart - דרוש אם ברצונכם לתמוך ב "פרסור" טפסים, באצמעות request.form().
- itsdangerous - דרוש אם ברצונכם להשתמש ב - `SessionMiddleware`.
diff --git a/docs/id/docs/index.md b/docs/id/docs/index.md
index 3129f9dc6d..66fc2859e7 100644
--- a/docs/id/docs/index.md
+++ b/docs/id/docs/index.md
@@ -426,7 +426,7 @@ For a more complete example including more features, see the requests - Required if you want to use the `TestClient`.
+* httpx - Required if you want to use the `TestClient`.
* jinja2 - Required if you want to use the default template configuration.
* python-multipart - Required if you want to support form "parsing", with `request.form()`.
* itsdangerous - Required for `SessionMiddleware` support.
diff --git a/docs/it/docs/index.md b/docs/it/docs/index.md
index 852a5e56e8..9d95dd6d72 100644
--- a/docs/it/docs/index.md
+++ b/docs/it/docs/index.md
@@ -423,7 +423,7 @@ For a more complete example including more features, see the requests - Required if you want to use the `TestClient`.
+* httpx - Required if you want to use the `TestClient`.
* jinja2 - Required if you want to use the default template configuration.
* python-multipart - Required if you want to support form "parsing", with `request.form()`.
* itsdangerous - Required for `SessionMiddleware` support.
diff --git a/docs/ja/docs/advanced/websockets.md b/docs/ja/docs/advanced/websockets.md
new file mode 100644
index 0000000000..65e4112a6b
--- /dev/null
+++ b/docs/ja/docs/advanced/websockets.md
@@ -0,0 +1,186 @@
+# WebSocket
+
+**FastAPI**でWebSocketが使用できます。
+
+## `WebSockets`のインストール
+
+まず `WebSockets`のインストールが必要です。
+
+
+
+入力ボックスにメッセージを入力して送信できます。
+
+
+
+そして、 WebSocketを使用した**FastAPI**アプリケーションが応答します。
+
+
+
+複数のメッセージを送信(および受信)できます。
+
+
+
+そして、これらの通信はすべて同じWebSocket接続を使用します。
+
+## 依存関係
+
+WebSocketエンドポイントでは、`fastapi` から以下をインポートして使用できます。
+
+* `Depends`
+* `Security`
+* `Cookie`
+* `Header`
+* `Path`
+* `Query`
+
+これらは、他のFastAPI エンドポイント/*path operation* の場合と同じように機能します。
+
+```Python hl_lines="58-65 68-83"
+{!../../../docs_src/websockets/tutorial002.py!}
+```
+
+!!! info "情報"
+ WebSocket で `HTTPException` を発生させることはあまり意味がありません。したがって、WebSocketの接続を直接閉じる方がよいでしょう。
+
+ クロージングコードは、仕様で定義された有効なコードの中から使用することができます。
+
+ 将来的には、どこからでも `raise` できる `WebSocketException` が用意され、専用の例外ハンドラを追加できるようになる予定です。これは、Starlette の PR #527 に依存するものです。
+
+### 依存関係を用いてWebSocketsを試してみる
+
+ファイル名が `main.py` である場合、以下の方法でアプリケーションを実行します。
+
+
+
+## 切断や複数クライアントへの対応
+
+WebSocket接続が閉じられると、 `await websocket.receive_text()` は例外 `WebSocketDisconnect` を発生させ、この例のようにキャッチして処理することができます。
+
+```Python hl_lines="81-83"
+{!../../../docs_src/websockets/tutorial003.py!}
+```
+
+試してみるには、
+
+* いくつかのブラウザタブでアプリを開きます。
+* それらのタブでメッセージを記入してください。
+* そして、タブのうち1つを閉じてください。
+
+これにより例外 `WebSocketDisconnect` が発生し、他のすべてのクライアントは次のようなメッセージを受信します。
+
+```
+Client #1596980209979 left the chat
+```
+
+!!! tip "豆知識"
+ 上記のアプリは、複数の WebSocket 接続に対してメッセージを処理し、ブロードキャストする方法を示すための最小限のシンプルな例です。
+
+ しかし、すべての接続がメモリ内の単一のリストで処理されるため、プロセスの実行中にのみ機能し、単一のプロセスでのみ機能することに注意してください。
+
+ もしFastAPIと簡単に統合できて、RedisやPostgreSQLなどでサポートされている、より堅牢なものが必要なら、encode/broadcaster を確認してください。
+
+## その他のドキュメント
+
+オプションの詳細については、Starletteのドキュメントを確認してください。
+
+* `WebSocket` クラス
+* クラスベースのWebSocket処理
diff --git a/docs/ja/docs/features.md b/docs/ja/docs/features.md
index 5ea68515da..a40b48cf0e 100644
--- a/docs/ja/docs/features.md
+++ b/docs/ja/docs/features.md
@@ -169,7 +169,7 @@ FastAPIには非常に使いやすく、非常に強力なrequests - 使用 `TestClient` 时安装。
+* httpx - 使用 `TestClient` 时安装。
* jinja2 - 使用默认模板配置时安装。
* python-multipart - 需要通过 `request.form()` 对表单进行「解析」时安装。
* itsdangerous - 需要 `SessionMiddleware` 支持时安装。
diff --git a/docs/zh/docs/python-types.md b/docs/zh/docs/python-types.md
index 67a1612f00..6cdb4b5883 100644
--- a/docs/zh/docs/python-types.md
+++ b/docs/zh/docs/python-types.md
@@ -194,7 +194,7 @@ John Doe
这表示:
-* 变量 `items_t` 是一个 `tuple`,其中的每个元素都是 `int` 类型。
+* 变量 `items_t` 是一个 `tuple`,其中的前两个元素都是 `int` 类型, 最后一个元素是 `str` 类型。
* 变量 `items_s` 是一个 `set`,其中的每个元素都是 `bytes` 类型。
#### 字典
diff --git a/docs/zh/docs/tutorial/security/oauth2-jwt.md b/docs/zh/docs/tutorial/security/oauth2-jwt.md
index 82ef9b897e..054198545e 100644
--- a/docs/zh/docs/tutorial/security/oauth2-jwt.md
+++ b/docs/zh/docs/tutorial/security/oauth2-jwt.md
@@ -1,34 +1,34 @@
-# 使用(哈希)密码和 JWT Bearer 令牌的 OAuth2
+# OAuth2 实现密码哈希与 Bearer JWT 令牌验证
-既然我们已经有了所有的安全流程,就让我们来使用 JWT 令牌和安全哈希密码让应用程序真正地安全吧。
+至此,我们已经编写了所有安全流,本章学习如何使用 JWT 令牌(Token)和安全密码哈希(Hash)实现真正的安全机制。
-你可以在应用程序中真正地使用这些代码,在数据库中保存密码哈希值,等等。
+本章的示例代码真正实现了在应用的数据库中保存哈希密码等功能。
-我们将从上一章结束的位置开始,然后对示例进行扩充。
+接下来,我们紧接上一章,继续完善安全机制。
-## 关于 JWT
+## JWT 简介
-JWT 表示 「JSON Web Tokens」。
+JWT 即**JSON 网络令牌**(JSON Web Tokens)。
-它是一个将 JSON 对象编码为密集且没有空格的长字符串的标准。字符串看起来像这样:
+JWT 是一种将 JSON 对象编码为没有空格,且难以理解的长字符串的标准。JWT 的内容如下所示:
```
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c
```
-它没有被加密,因此任何人都可以从字符串内容中还原数据。
+JWT 字符串没有加密,任何人都能用它恢复原始信息。
-但它经过了签名。因此,当你收到一个由你发出的令牌时,可以校验令牌是否真的由你发出。
+但 JWT 使用了签名机制。接受令牌时,可以用签名校验令牌。
-通过这种方式,你可以创建一个有效期为 1 周的令牌。然后当用户第二天使用令牌重新访问时,你知道该用户仍然处于登入状态。
+使用 JWT 创建有效期为一周的令牌。第二天,用户持令牌再次访问时,仍为登录状态。
-一周后令牌将会过期,用户将不会通过认证,必须再次登录才能获得一个新令牌。而且如果用户(或第三方)试图修改令牌以篡改过期时间,你将因为签名不匹配而能够发觉。
+令牌于一周后过期,届时,用户身份验证就会失败。只有再次登录,才能获得新的令牌。如果用户(或第三方)篡改令牌的过期时间,因为签名不匹配会导致身份验证失败。
-如果你想上手体验 JWT 令牌并了解其工作方式,可访问 https://jwt.io。
+如需深入了解 JWT 令牌,了解它的工作方式,请参阅 https://jwt.io。
## 安装 `python-jose`
-我们需要安装 `python-jose` 以在 Python 中生成和校验 JWT 令牌:
+安装 `python-jose`,在 Python 中生成和校验 JWT 令牌:
-像以前一样对应用程序进行认证。
+用与上一章同样的方式实现应用授权。
使用如下凭证:
-用户名: `johndoe`
-密码: `secret`
+用户名: `johndoe` 密码: `secret`
-!!! check
- 请注意,代码中没有任何地方记录了明文密码 「`secret`」,我们只保存了其哈希值。
+!!! check "检查"
+
+ 注意,代码中没有明文密码**`secret`**,只保存了它的哈希值。
-访问 `/users/me/` 端点,你将获得如下响应:
+调用 `/users/me/` 端点,收到下面的响应:
```JSON
{
@@ -225,41 +229,42 @@ JWT 的规范中提到有一个 `sub` 键,值为该令牌的主题。
-如果你打开开发者工具,将看到数据是如何发送的并且其中仅包含了令牌,只有在第一个请求中发送了密码以校验用户身份并获取该访问令牌,但之后都不会再发送密码:
+打开浏览器的开发者工具,查看数据是怎么发送的,而且数据里只包含了令牌,只有验证用户的第一个请求才发送密码,并获取访问令牌,但之后不会再发送密码:
-!!! note
- 注意请求中的 `Authorization` 首部,其值以 `Bearer` 开头。
+!!! note "笔记"
-## 使用 `scopes` 的进阶用法
+ 注意,请求中 `Authorization` 响应头的值以 `Bearer` 开头。
-OAuth2 具有「作用域」的概念。
+## `scopes` 高级用法
-你可以使用它们向 JWT 令牌添加一组特定的权限。
+OAuth2 支持**`scopes`**(作用域)。
-然后,你可以将此令牌直接提供给用户或第三方,使其在一些限制下与你的 API 进行交互。
+**`scopes`**为 JWT 令牌添加指定权限。
-你可以在之后的**进阶用户指南**中了解如何使用它们以及如何将它们集成到 **FastAPI** 中。
+让持有令牌的用户或第三方在指定限制条件下与 API 交互。
-## 总结
+**高级用户指南**中将介绍如何使用 `scopes`,及如何把 `scopes` 集成至 **FastAPI**。
-通过目前你所看到的,你可以使用像 OAuth2 和 JWT 这样的标准来构建一个安全的 **FastAPI** 应用程序。
+## 小结
-在几乎所有的框架中,处理安全性问题都很容易成为一个相当复杂的话题。
+至此,您可以使用 OAuth2 和 JWT 等标准配置安全的 **FastAPI** 应用。
-许多高度简化了安全流程的软件包不得不在数据模型、数据库和可用功能上做出很多妥协。而这些过于简化流程的软件包中,有些其实隐含了安全漏洞。
+几乎在所有框架中,处理安全问题很快都会变得非常复杂。
+
+有些包为了简化安全流,不得不在数据模型、数据库和功能上做出妥协。而有些过于简化的软件包其实存在了安全隐患。
---
-**FastAPI** 不对任何数据库、数据模型或工具做任何妥协。
+**FastAPI** 不向任何数据库、数据模型或工具做妥协。
-它给了你所有的灵活性来选择最适合你项目的前者。
+开发者可以灵活选择最适合项目的安全机制。
-你可以直接使用许多维护良好且使用广泛的包,如 `passlib` 和 `python-jose`,因为 **FastAPI** 不需要任何复杂的机制来集成外部包。
+还可以直接使用 `passlib` 和 `python-jose` 等维护良好、使用广泛的包,这是因为 **FastAPI** 不需要任何复杂机制,就能集成外部的包。
-但它为你提供了一些工具,在不影响灵活性、健壮性和安全性的前提下,尽可能地简化这个过程。
+而且,**FastAPI** 还提供了一些工具,在不影响灵活、稳定和安全的前提下,尽可能地简化安全机制。
-而且你可以用相对简单的方式使用和实现安全、标准的协议,比如 OAuth2。
+**FastAPI** 还支持以相对简单的方式,使用 OAuth2 等安全、标准的协议。
-你可以在**进阶用户指南**中了解更多关于如何使用 OAuth2 「作用域」的信息,以实现更精细的权限系统,并同样遵循这些标准。带有作用域的 OAuth2 是很多大的认证提供商使用的机制,比如 Facebook、Google、GitHub、微软、Twitter 等,授权第三方应用代表用户与他们的 API 进行交互。
+**高级用户指南**中详细介绍了 OAuth2**`scopes`**的内容,遵循同样的标准,实现更精密的权限系统。OAuth2 的作用域是脸书、谷歌、GitHub、微软、推特等第三方身份验证应用使用的机制,让用户授权第三方应用与 API 交互。
diff --git a/docs_src/security/tutorial005.py b/docs_src/security/tutorial005.py
index ab3af9a6a9..bd0a33581c 100644
--- a/docs_src/security/tutorial005.py
+++ b/docs_src/security/tutorial005.py
@@ -107,7 +107,7 @@ async def get_current_user(
if security_scopes.scopes:
authenticate_value = f'Bearer scope="{security_scopes.scope_str}"'
else:
- authenticate_value = f"Bearer"
+ authenticate_value = "Bearer"
credentials_exception = HTTPException(
status_code=status.HTTP_401_UNAUTHORIZED,
detail="Could not validate credentials",
diff --git a/docs_src/security/tutorial005_py310.py b/docs_src/security/tutorial005_py310.py
index c6a095d2cc..ba756ef4f4 100644
--- a/docs_src/security/tutorial005_py310.py
+++ b/docs_src/security/tutorial005_py310.py
@@ -106,7 +106,7 @@ async def get_current_user(
if security_scopes.scopes:
authenticate_value = f'Bearer scope="{security_scopes.scope_str}"'
else:
- authenticate_value = f"Bearer"
+ authenticate_value = "Bearer"
credentials_exception = HTTPException(
status_code=status.HTTP_401_UNAUTHORIZED,
detail="Could not validate credentials",
diff --git a/docs_src/security/tutorial005_py39.py b/docs_src/security/tutorial005_py39.py
index 38391308af..9e4dbcffba 100644
--- a/docs_src/security/tutorial005_py39.py
+++ b/docs_src/security/tutorial005_py39.py
@@ -107,7 +107,7 @@ async def get_current_user(
if security_scopes.scopes:
authenticate_value = f'Bearer scope="{security_scopes.scope_str}"'
else:
- authenticate_value = f"Bearer"
+ authenticate_value = "Bearer"
credentials_exception = HTTPException(
status_code=status.HTTP_401_UNAUTHORIZED,
detail="Could not validate credentials",
diff --git a/docs_src/websockets/tutorial002.py b/docs_src/websockets/tutorial002.py
index cf5c7e805a..cab749e4db 100644
--- a/docs_src/websockets/tutorial002.py
+++ b/docs_src/websockets/tutorial002.py
@@ -1,6 +1,14 @@
from typing import Union
-from fastapi import Cookie, Depends, FastAPI, Query, WebSocket, status
+from fastapi import (
+ Cookie,
+ Depends,
+ FastAPI,
+ Query,
+ WebSocket,
+ WebSocketException,
+ status,
+)
from fastapi.responses import HTMLResponse
app = FastAPI()
@@ -61,7 +69,7 @@ async def get_cookie_or_token(
token: Union[str, None] = Query(default=None),
):
if session is None and token is None:
- await websocket.close(code=status.WS_1008_POLICY_VIOLATION)
+ raise WebSocketException(code=status.WS_1008_POLICY_VIOLATION)
return session or token
diff --git a/fastapi/__init__.py b/fastapi/__init__.py
index cb1b063aae..037d9804b5 100644
--- a/fastapi/__init__.py
+++ b/fastapi/__init__.py
@@ -1,6 +1,6 @@
"""FastAPI framework, high performance, easy to learn, fast to code, ready for production"""
-__version__ = "0.85.2"
+__version__ = "0.88.0"
from starlette import status as status
@@ -8,6 +8,7 @@ from .applications import FastAPI as FastAPI
from .background import BackgroundTasks as BackgroundTasks
from .datastructures import UploadFile as UploadFile
from .exceptions import HTTPException as HTTPException
+from .exceptions import WebSocketException as WebSocketException
from .param_functions import Body as Body
from .param_functions import Cookie as Cookie
from .param_functions import Depends as Depends
diff --git a/fastapi/dependencies/utils.py b/fastapi/dependencies/utils.py
index 64a6c12765..4c817d5d0b 100644
--- a/fastapi/dependencies/utils.py
+++ b/fastapi/dependencies/utils.py
@@ -105,10 +105,10 @@ def check_file_field(field: ModelField) -> None:
assert parse_options_header
except ImportError:
logger.error(multipart_incorrect_install_error)
- raise RuntimeError(multipart_incorrect_install_error)
+ raise RuntimeError(multipart_incorrect_install_error) from None
except ImportError:
logger.error(multipart_not_installed_error)
- raise RuntimeError(multipart_not_installed_error)
+ raise RuntimeError(multipart_not_installed_error) from None
def get_param_sub_dependant(
@@ -426,21 +426,21 @@ def is_coroutine_callable(call: Callable[..., Any]) -> bool:
return inspect.iscoroutinefunction(call)
if inspect.isclass(call):
return False
- dunder_call = getattr(call, "__call__", None)
+ dunder_call = getattr(call, "__call__", None) # noqa: B004
return inspect.iscoroutinefunction(dunder_call)
def is_async_gen_callable(call: Callable[..., Any]) -> bool:
if inspect.isasyncgenfunction(call):
return True
- dunder_call = getattr(call, "__call__", None)
+ dunder_call = getattr(call, "__call__", None) # noqa: B004
return inspect.isasyncgenfunction(dunder_call)
def is_gen_callable(call: Callable[..., Any]) -> bool:
if inspect.isgeneratorfunction(call):
return True
- dunder_call = getattr(call, "__call__", None)
+ dunder_call = getattr(call, "__call__", None) # noqa: B004
return inspect.isgeneratorfunction(dunder_call)
@@ -724,14 +724,14 @@ def get_body_field(*, dependant: Dependant, name: str) -> Optional[ModelField]:
# in case a sub-dependency is evaluated with a single unique body field
# That is combined (embedded) with other body fields
for param in flat_dependant.body_params:
- setattr(param.field_info, "embed", True)
+ setattr(param.field_info, "embed", True) # noqa: B010
model_name = "Body_" + name
BodyModel: Type[BaseModel] = create_model(model_name)
for f in flat_dependant.body_params:
BodyModel.__fields__[f.name] = f
required = any(True for f in flat_dependant.body_params if f.required)
- BodyFieldInfo_kwargs: Dict[str, Any] = dict(default=None)
+ BodyFieldInfo_kwargs: Dict[str, Any] = {"default": None}
if any(isinstance(f.field_info, params.File) for f in flat_dependant.body_params):
BodyFieldInfo: Type[params.Body] = params.File
elif any(isinstance(f.field_info, params.Form) for f in flat_dependant.body_params):
@@ -740,7 +740,7 @@ def get_body_field(*, dependant: Dependant, name: str) -> Optional[ModelField]:
BodyFieldInfo = params.Body
body_param_media_types = [
- getattr(f.field_info, "media_type")
+ f.field_info.media_type
for f in flat_dependant.body_params
if isinstance(f.field_info, params.Body)
]
diff --git a/fastapi/encoders.py b/fastapi/encoders.py
index 6bde9f4abf..2f95bcbf66 100644
--- a/fastapi/encoders.py
+++ b/fastapi/encoders.py
@@ -157,7 +157,7 @@ def jsonable_encoder(
data = vars(obj)
except Exception as e:
errors.append(e)
- raise ValueError(errors)
+ raise ValueError(errors) from e
return jsonable_encoder(
data,
include=include,
diff --git a/fastapi/exceptions.py b/fastapi/exceptions.py
index 0f50acc6c5..ca097b1cef 100644
--- a/fastapi/exceptions.py
+++ b/fastapi/exceptions.py
@@ -3,6 +3,7 @@ from typing import Any, Dict, Optional, Sequence, Type
from pydantic import BaseModel, ValidationError, create_model
from pydantic.error_wrappers import ErrorList
from starlette.exceptions import HTTPException as StarletteHTTPException
+from starlette.exceptions import WebSocketException as WebSocketException # noqa: F401
class HTTPException(StarletteHTTPException):
diff --git a/fastapi/routing.py b/fastapi/routing.py
index 7caf018b55..9a7d88efc8 100644
--- a/fastapi/routing.py
+++ b/fastapi/routing.py
@@ -3,6 +3,7 @@ import dataclasses
import email.message
import inspect
import json
+from contextlib import AsyncExitStack
from enum import Enum, IntEnum
from typing import (
Any,
@@ -190,6 +191,9 @@ def get_request_handler(
if body_field:
if is_body_form:
body = await request.form()
+ stack = request.scope.get("fastapi_astack")
+ assert isinstance(stack, AsyncExitStack)
+ stack.push_async_callback(body.close)
else:
body_bytes = await request.body()
if body_bytes:
@@ -697,7 +701,7 @@ class APIRouter(routing.Router):
), "A path prefix must not end with '/', as the routes will start with '/'"
else:
for r in router.routes:
- path = getattr(r, "path")
+ path = getattr(r, "path") # noqa: B009
name = getattr(r, "name", "unknown")
if path is not None and not path:
raise Exception(
diff --git a/fastapi/security/api_key.py b/fastapi/security/api_key.py
index bca5c721a6..24ddbf4825 100644
--- a/fastapi/security/api_key.py
+++ b/fastapi/security/api_key.py
@@ -54,7 +54,7 @@ class APIKeyHeader(APIKeyBase):
self.auto_error = auto_error
async def __call__(self, request: Request) -> Optional[str]:
- api_key: str = request.headers.get(self.model.name)
+ api_key = request.headers.get(self.model.name)
if not api_key:
if self.auto_error:
raise HTTPException(
diff --git a/fastapi/security/http.py b/fastapi/security/http.py
index 1b473c69e7..8b677299dd 100644
--- a/fastapi/security/http.py
+++ b/fastapi/security/http.py
@@ -38,7 +38,7 @@ class HTTPBase(SecurityBase):
async def __call__(
self, request: Request
) -> Optional[HTTPAuthorizationCredentials]:
- authorization: str = request.headers.get("Authorization")
+ authorization = request.headers.get("Authorization")
scheme, credentials = get_authorization_scheme_param(authorization)
if not (authorization and scheme and credentials):
if self.auto_error:
@@ -67,7 +67,7 @@ class HTTPBasic(HTTPBase):
async def __call__( # type: ignore
self, request: Request
) -> Optional[HTTPBasicCredentials]:
- authorization: str = request.headers.get("Authorization")
+ authorization = request.headers.get("Authorization")
scheme, param = get_authorization_scheme_param(authorization)
if self.realm:
unauthorized_headers = {"WWW-Authenticate": f'Basic realm="{self.realm}"'}
@@ -113,7 +113,7 @@ class HTTPBearer(HTTPBase):
async def __call__(
self, request: Request
) -> Optional[HTTPAuthorizationCredentials]:
- authorization: str = request.headers.get("Authorization")
+ authorization = request.headers.get("Authorization")
scheme, credentials = get_authorization_scheme_param(authorization)
if not (authorization and scheme and credentials):
if self.auto_error:
@@ -148,7 +148,7 @@ class HTTPDigest(HTTPBase):
async def __call__(
self, request: Request
) -> Optional[HTTPAuthorizationCredentials]:
- authorization: str = request.headers.get("Authorization")
+ authorization = request.headers.get("Authorization")
scheme, credentials = get_authorization_scheme_param(authorization)
if not (authorization and scheme and credentials):
if self.auto_error:
diff --git a/fastapi/security/oauth2.py b/fastapi/security/oauth2.py
index 653c3010e5..eb6b4277cf 100644
--- a/fastapi/security/oauth2.py
+++ b/fastapi/security/oauth2.py
@@ -126,7 +126,7 @@ class OAuth2(SecurityBase):
self.auto_error = auto_error
async def __call__(self, request: Request) -> Optional[str]:
- authorization: str = request.headers.get("Authorization")
+ authorization = request.headers.get("Authorization")
if not authorization:
if self.auto_error:
raise HTTPException(
@@ -157,7 +157,7 @@ class OAuth2PasswordBearer(OAuth2):
)
async def __call__(self, request: Request) -> Optional[str]:
- authorization: str = request.headers.get("Authorization")
+ authorization = request.headers.get("Authorization")
scheme, param = get_authorization_scheme_param(authorization)
if not authorization or scheme.lower() != "bearer":
if self.auto_error:
@@ -200,7 +200,7 @@ class OAuth2AuthorizationCodeBearer(OAuth2):
)
async def __call__(self, request: Request) -> Optional[str]:
- authorization: str = request.headers.get("Authorization")
+ authorization = request.headers.get("Authorization")
scheme, param = get_authorization_scheme_param(authorization)
if not authorization or scheme.lower() != "bearer":
if self.auto_error:
diff --git a/fastapi/security/open_id_connect_url.py b/fastapi/security/open_id_connect_url.py
index dfe9f7b255..393614f7cb 100644
--- a/fastapi/security/open_id_connect_url.py
+++ b/fastapi/security/open_id_connect_url.py
@@ -23,7 +23,7 @@ class OpenIdConnect(SecurityBase):
self.auto_error = auto_error
async def __call__(self, request: Request) -> Optional[str]:
- authorization: str = request.headers.get("Authorization")
+ authorization = request.headers.get("Authorization")
if not authorization:
if self.auto_error:
raise HTTPException(
diff --git a/fastapi/security/utils.py b/fastapi/security/utils.py
index 2da0dd20f3..fa7a450b74 100644
--- a/fastapi/security/utils.py
+++ b/fastapi/security/utils.py
@@ -1,7 +1,9 @@
-from typing import Tuple
+from typing import Optional, Tuple
-def get_authorization_scheme_param(authorization_header_value: str) -> Tuple[str, str]:
+def get_authorization_scheme_param(
+ authorization_header_value: Optional[str],
+) -> Tuple[str, str]:
if not authorization_header_value:
return "", ""
scheme, _, param = authorization_header_value.partition(" ")
diff --git a/fastapi/utils.py b/fastapi/utils.py
index b94dacecc5..b15f6a2cfb 100644
--- a/fastapi/utils.py
+++ b/fastapi/utils.py
@@ -89,7 +89,7 @@ def create_response_field(
except RuntimeError:
raise fastapi.exceptions.FastAPIError(
f"Invalid args for response field! Hint: check that {type_} is a valid pydantic field type"
- )
+ ) from None
def create_cloned_field(
diff --git a/pyproject.toml b/pyproject.toml
index 543ba15c1d..be3080ae83 100644
--- a/pyproject.toml
+++ b/pyproject.toml
@@ -34,11 +34,12 @@ classifiers = [
"Programming Language :: Python :: 3.8",
"Programming Language :: Python :: 3.9",
"Programming Language :: Python :: 3.10",
+ "Programming Language :: Python :: 3.11",
"Topic :: Internet :: WWW/HTTP :: HTTP Servers",
"Topic :: Internet :: WWW/HTTP",
]
dependencies = [
- "starlette==0.20.4",
+ "starlette==0.22.0",
"pydantic >=1.6.2,!=1.7,!=1.7.1,!=1.7.2,!=1.7.3,!=1.8,!=1.8.1,<2.0.0",
]
dynamic = ["version"]
@@ -50,12 +51,11 @@ Documentation = "https://fastapi.tiangolo.com/"
[project.optional-dependencies]
test = [
"pytest >=7.1.3,<8.0.0",
- "pytest-cov >=2.12.0,<5.0.0",
+ "coverage[toml] >= 6.5.0,<7.0",
"mypy ==0.982",
- "flake8 >=3.8.3,<6.0.0",
- "black == 22.8.0",
+ "ruff ==0.0.138",
+ "black == 22.10.0",
"isort >=5.0.6,<6.0.0",
- "requests >=2.24.0,<3.0.0",
"httpx >=0.23.0,<0.24.0",
"email_validator >=1.1.1,<2.0.0",
# TODO: once removing databases from tutorial, upgrade SQLAlchemy
@@ -83,25 +83,24 @@ doc = [
"mkdocs-markdownextradata-plugin >=0.1.7,<0.3.0",
# TODO: upgrade and enable typer-cli once it supports Click 8.x.x
# "typer-cli >=0.0.12,<0.0.13",
- "typer[all] >=0.6.1,<0.7.0",
+ "typer[all] >=0.6.1,<0.8.0",
"pyyaml >=5.3.1,<7.0.0",
]
dev = [
- "autoflake >=1.4.0,<2.0.0",
- "flake8 >=3.8.3,<6.0.0",
+ "ruff ==0.0.138",
"uvicorn[standard] >=0.12.0,<0.19.0",
"pre-commit >=2.17.0,<3.0.0",
]
all = [
- "requests >=2.24.0,<3.0.0",
- "jinja2 >=2.11.2,<4.0.0",
- "python-multipart >=0.0.5,<0.0.6",
- "itsdangerous >=1.1.0,<3.0.0",
- "pyyaml >=5.3.1,<7.0.0",
- "ujson >=4.0.1,!=4.0.2,!=4.1.0,!=4.2.0,!=4.3.0,!=5.0.0,!=5.1.0,<6.0.0",
- "orjson >=3.2.1,<4.0.0",
- "email_validator >=1.1.1,<2.0.0",
- "uvicorn[standard] >=0.12.0,<0.19.0",
+ "httpx >=0.23.0",
+ "jinja2 >=2.11.2",
+ "python-multipart >=0.0.5",
+ "itsdangerous >=1.1.0",
+ "pyyaml >=5.3.1",
+ "ujson >=4.0.1,!=4.0.2,!=4.1.0,!=4.2.0,!=4.3.0,!=5.0.0,!=5.1.0",
+ "orjson >=3.2.1",
+ "email_validator >=1.1.1",
+ "uvicorn[standard] >=0.12.0",
]
[tool.hatch.version]
@@ -136,9 +135,52 @@ filterwarnings = [
# TODO: needed by asyncio in Python 3.9.7 https://bugs.python.org/issue45097, try to remove on 3.9.8
'ignore:The loop argument is deprecated since Python 3\.8, and scheduled for removal in Python 3\.10:DeprecationWarning:asyncio',
'ignore:starlette.middleware.wsgi is deprecated and will be removed in a future release\..*:DeprecationWarning:starlette',
+ # TODO: remove after upgrading HTTPX to a version newer than 0.23.0
+ # Including PR: https://github.com/encode/httpx/pull/2309
+ "ignore:'cgi' is deprecated:DeprecationWarning",
+ # For passlib
+ "ignore:'crypt' is deprecated and slated for removal in Python 3.13:DeprecationWarning",
# see https://trio.readthedocs.io/en/stable/history.html#trio-0-22-0-2022-09-28
"ignore:You seem to already have a custom.*:RuntimeWarning:trio",
"ignore::trio.TrioDeprecationWarning",
# TODO remove pytest-cov
'ignore::pytest.PytestDeprecationWarning:pytest_cov',
]
+
+[tool.coverage.run]
+parallel = true
+source = [
+ "docs_src",
+ "tests",
+ "fastapi"
+]
+context = '${CONTEXT}'
+
+[tool.ruff]
+select = [
+ "E", # pycodestyle errors
+ "W", # pycodestyle warnings
+ "F", # pyflakes
+ # "I", # isort
+ "C", # flake8-comprehensions
+ "B", # flake8-bugbear
+]
+ignore = [
+ "E501", # line too long, handled by black
+ "B008", # do not perform function calls in argument defaults
+ "C901", # too complex
+]
+
+[tool.ruff.per-file-ignores]
+"__init__.py" = ["F401"]
+"docs_src/dependencies/tutorial007.py" = ["F821"]
+"docs_src/dependencies/tutorial008.py" = ["F821"]
+"docs_src/dependencies/tutorial009.py" = ["F821"]
+"docs_src/dependencies/tutorial010.py" = ["F821"]
+"docs_src/custom_response/tutorial007.py" = ["B007"]
+"docs_src/dataclasses/tutorial003.py" = ["I001"]
+"docs_src/path_operation_advanced_configuration/tutorial007.py" = ["B904"]
+"docs_src/custom_request_and_route/tutorial002.py" = ["B904"]
+
+[tool.ruff.isort]
+known-third-party = ["fastapi", "pydantic", "starlette"]
diff --git a/scripts/docs.py b/scripts/docs.py
index d5fbacf59d..e0953b8edb 100644
--- a/scripts/docs.py
+++ b/scripts/docs.py
@@ -284,7 +284,9 @@ def build_all():
continue
langs.append(lang.name)
cpu_count = os.cpu_count() or 1
- with Pool(cpu_count * 2) as p:
+ process_pool_size = cpu_count * 4
+ typer.echo(f"Using process pool size: {process_pool_size}")
+ with Pool(process_pool_size) as p:
p.map(build_lang, langs)
@@ -332,7 +334,7 @@ def serve():
os.chdir("site")
server_address = ("", 8008)
server = HTTPServer(server_address, SimpleHTTPRequestHandler)
- typer.echo(f"Serving at: http://127.0.0.1:8008")
+ typer.echo("Serving at: http://127.0.0.1:8008")
server.serve_forever()
@@ -420,7 +422,7 @@ def get_file_to_nav_map(nav: list) -> Dict[str, Tuple[str, ...]]:
file_to_nav = {}
for item in nav:
if type(item) is str:
- file_to_nav[item] = tuple()
+ file_to_nav[item] = ()
elif type(item) is dict:
item_key = list(item.keys())[0]
sub_nav = item[item_key]
diff --git a/scripts/format.sh b/scripts/format.sh
index ee4fbf1a5b..3ac1fead86 100755
--- a/scripts/format.sh
+++ b/scripts/format.sh
@@ -1,6 +1,6 @@
#!/bin/sh -e
set -x
-autoflake --remove-all-unused-imports --recursive --remove-unused-variables --in-place docs_src fastapi tests scripts --exclude=__init__.py
+ruff fastapi tests docs_src scripts --fix
black fastapi tests docs_src scripts
isort fastapi tests docs_src scripts
diff --git a/scripts/lint.sh b/scripts/lint.sh
index 2e2072cf18..0feb973a87 100755
--- a/scripts/lint.sh
+++ b/scripts/lint.sh
@@ -4,6 +4,6 @@ set -e
set -x
mypy fastapi
-flake8 fastapi tests
+ruff fastapi tests docs_src scripts
black fastapi tests --check
isort fastapi tests docs_src scripts --check-only
diff --git a/scripts/test-cov-html.sh b/scripts/test-cov-html.sh
index 7957277fc3..d1bdfced2a 100755
--- a/scripts/test-cov-html.sh
+++ b/scripts/test-cov-html.sh
@@ -3,4 +3,7 @@
set -e
set -x
-bash scripts/test.sh --cov-report=html ${@}
+bash scripts/test.sh ${@}
+coverage combine
+coverage report --show-missing
+coverage html
diff --git a/scripts/test.sh b/scripts/test.sh
index d445ca1742..62449ea415 100755
--- a/scripts/test.sh
+++ b/scripts/test.sh
@@ -6,4 +6,4 @@ set -x
# Check README.md is up to date
python ./scripts/docs.py verify-readme
export PYTHONPATH=./docs_src
-pytest --cov=fastapi --cov=tests --cov=docs_src --cov-report=term-missing:skip-covered --cov-report=xml tests ${@}
+coverage run -m pytest tests ${@}
diff --git a/scripts/zip-docs.sh b/scripts/zip-docs.sh
index f2b7ba3be3..69315f5ddd 100644
--- a/scripts/zip-docs.sh
+++ b/scripts/zip-docs.sh
@@ -3,7 +3,9 @@
set -x
set -e
+cd ./site
+
if [ -f docs.zip ]; then
rm -rf docs.zip
fi
-zip -r docs.zip ./site
+zip -r docs.zip ./
diff --git a/tests/test_custom_route_class.py b/tests/test_custom_route_class.py
index 1a9ea7199a..2e8d9c6de5 100644
--- a/tests/test_custom_route_class.py
+++ b/tests/test_custom_route_class.py
@@ -110,6 +110,6 @@ def test_route_classes():
for r in app.router.routes:
assert isinstance(r, Route)
routes[r.path] = r
- assert getattr(routes["/a/"], "x_type") == "A"
- assert getattr(routes["/a/b/"], "x_type") == "B"
- assert getattr(routes["/a/b/c/"], "x_type") == "C"
+ assert getattr(routes["/a/"], "x_type") == "A" # noqa: B009
+ assert getattr(routes["/a/b/"], "x_type") == "B" # noqa: B009
+ assert getattr(routes["/a/b/c/"], "x_type") == "C" # noqa: B009
diff --git a/tests/test_datastructures.py b/tests/test_datastructures.py
index 43f1a116cb..2e6217d34e 100644
--- a/tests/test_datastructures.py
+++ b/tests/test_datastructures.py
@@ -1,6 +1,10 @@
+from pathlib import Path
+from typing import List
+
import pytest
-from fastapi import UploadFile
+from fastapi import FastAPI, UploadFile
from fastapi.datastructures import Default
+from fastapi.testclient import TestClient
def test_upload_file_invalid():
@@ -20,3 +24,25 @@ def test_default_placeholder_bool():
placeholder_b = Default("")
assert placeholder_a
assert not placeholder_b
+
+
+def test_upload_file_is_closed(tmp_path: Path):
+ path = tmp_path / "test.txt"
+ path.write_bytes(b"