Browse Source

Merge branch 'master' into feat/exception-on-duplicate-path

pull/5595/head
Irfanuddin Shafi Ahmed 1 year ago
committed by GitHub
parent
commit
b8c9000047
No known key found for this signature in database GPG Key ID: 4AEE18F83AFDEB23
  1. 4
      .github/workflows/build-docs.yml
  2. 7
      .github/workflows/latest-changes.yml
  3. 14
      .pre-commit-config.yaml
  4. 4
      README.md
  5. 14
      docs/em/docs/advanced/settings.md
  6. 4
      docs/em/docs/async.md
  7. 2
      docs/em/docs/index.md
  8. 4
      docs/em/docs/tutorial/query-params-str-validations.md
  9. 12
      docs/en/data/sponsors.yml
  10. 3
      docs/en/data/sponsors_badge.yml
  11. 5
      docs/en/docs/advanced/generate-clients.md
  12. 14
      docs/en/docs/advanced/settings.md
  13. 2
      docs/en/docs/alternatives.md
  14. 4
      docs/en/docs/async.md
  15. 4
      docs/en/docs/how-to/custom-docs-ui-assets.md
  16. BIN
      docs/en/docs/img/sponsors/codacy.png
  17. BIN
      docs/en/docs/img/sponsors/reflex-banner.png
  18. BIN
      docs/en/docs/img/sponsors/reflex.png
  19. 1
      docs/en/docs/img/sponsors/scalar-banner.svg
  20. 1
      docs/en/docs/img/sponsors/scalar.svg
  21. 39
      docs/en/docs/release-notes.md
  22. 4
      docs/en/docs/tutorial/query-params-str-validations.md
  23. 18
      docs/en/overrides/main.html
  24. 4
      docs/ru/docs/tutorial/query-params-str-validations.md
  25. 14
      docs/zh/docs/advanced/settings.md
  26. 4
      docs/zh/docs/async.md
  27. 4
      docs_src/custom_docs_ui/tutorial001.py
  28. 2
      docs_src/header_params/tutorial002_an.py
  29. 2
      docs_src/header_params/tutorial002_an_py39.py
  30. 2
      docs_src/query_params_str_validations/tutorial004.py
  31. 2
      docs_src/query_params_str_validations/tutorial004_an.py
  32. 2
      docs_src/query_params_str_validations/tutorial004_an_py310.py
  33. 2
      docs_src/query_params_str_validations/tutorial004_an_py310_regex.py
  34. 2
      docs_src/query_params_str_validations/tutorial004_an_py39.py
  35. 5
      docs_src/query_params_str_validations/tutorial004_py310.py
  36. 2
      docs_src/query_params_str_validations/tutorial008.py
  37. 2
      docs_src/query_params_str_validations/tutorial008_an.py
  38. 2
      docs_src/query_params_str_validations/tutorial008_an_py310.py
  39. 2
      docs_src/query_params_str_validations/tutorial008_an_py39.py
  40. 5
      docs_src/query_params_str_validations/tutorial008_py310.py
  41. 2
      docs_src/query_params_str_validations/tutorial010.py
  42. 2
      docs_src/query_params_str_validations/tutorial010_an.py
  43. 2
      docs_src/query_params_str_validations/tutorial010_an_py310.py
  44. 2
      docs_src/query_params_str_validations/tutorial010_an_py39.py
  45. 5
      docs_src/query_params_str_validations/tutorial010_py310.py
  46. 2
      docs_src/settings/app02/main.py
  47. 2
      docs_src/settings/app02_an/main.py
  48. 2
      docs_src/settings/app02_an_py39/main.py
  49. 2
      docs_src/settings/app03/main.py
  50. 2
      docs_src/settings/app03_an/main.py
  51. 2
      docs_src/settings/app03_an_py39/main.py
  52. 2
      fastapi/__init__.py
  53. 6
      fastapi/_compat.py
  54. 6
      fastapi/applications.py
  55. 4
      fastapi/openapi/docs.py
  56. 2
      fastapi/security/http.py
  57. 4
      fastapi/security/oauth2.py
  58. 3
      fastapi/utils.py
  59. 18
      pyproject.toml
  60. 1
      requirements-docs-tests.txt
  61. 6
      requirements-docs.txt
  62. 2
      requirements-tests.txt
  63. 6
      scripts/docs.py
  64. 2
      scripts/format.sh
  65. 2
      scripts/lint.sh
  66. 4
      scripts/mkdocs_hooks.py
  67. 2
      tests/test_openapi_examples.py
  68. 4
      tests/test_schema_extra_examples.py
  69. 6
      tests/test_tutorial/test_custom_docs_ui/test_tutorial001.py

4
.github/workflows/build-docs.yml

@ -50,7 +50,7 @@ jobs:
run: pip install -r requirements-docs.txt run: pip install -r requirements-docs.txt
# Install MkDocs Material Insiders here just to put it in the cache for the rest of the steps # Install MkDocs Material Insiders here just to put it in the cache for the rest of the steps
- name: Install Material for MkDocs Insiders - name: Install Material for MkDocs Insiders
if: ( github.event_name != 'pull_request' || github.event.pull_request.head.repo.fork == false ) && steps.cache.outputs.cache-hit != 'true' if: ( github.event_name != 'pull_request' || github.secret_source == 'Actions' ) && steps.cache.outputs.cache-hit != 'true'
run: | run: |
pip install git+https://${{ secrets.FASTAPI_MKDOCS_MATERIAL_INSIDERS }}@github.com/squidfunk/mkdocs-material-insiders.git pip install git+https://${{ secrets.FASTAPI_MKDOCS_MATERIAL_INSIDERS }}@github.com/squidfunk/mkdocs-material-insiders.git
pip install git+https://${{ secrets.FASTAPI_MKDOCS_MATERIAL_INSIDERS }}@github.com/pawamoy-insiders/griffe-typing-deprecated.git pip install git+https://${{ secrets.FASTAPI_MKDOCS_MATERIAL_INSIDERS }}@github.com/pawamoy-insiders/griffe-typing-deprecated.git
@ -88,7 +88,7 @@ jobs:
if: steps.cache.outputs.cache-hit != 'true' if: steps.cache.outputs.cache-hit != 'true'
run: pip install -r requirements-docs.txt run: pip install -r requirements-docs.txt
- name: Install Material for MkDocs Insiders - name: Install Material for MkDocs Insiders
if: ( github.event_name != 'pull_request' || github.event.pull_request.head.repo.fork == false ) && steps.cache.outputs.cache-hit != 'true' if: ( github.event_name != 'pull_request' || github.secret_source != 'Actions' ) && steps.cache.outputs.cache-hit != 'true'
run: | run: |
pip install git+https://${{ secrets.FASTAPI_MKDOCS_MATERIAL_INSIDERS }}@github.com/squidfunk/mkdocs-material-insiders.git pip install git+https://${{ secrets.FASTAPI_MKDOCS_MATERIAL_INSIDERS }}@github.com/squidfunk/mkdocs-material-insiders.git
pip install git+https://${{ secrets.FASTAPI_MKDOCS_MATERIAL_INSIDERS }}@github.com/pawamoy-insiders/griffe-typing-deprecated.git pip install git+https://${{ secrets.FASTAPI_MKDOCS_MATERIAL_INSIDERS }}@github.com/pawamoy-insiders/griffe-typing-deprecated.git

7
.github/workflows/latest-changes.yml

@ -34,9 +34,12 @@ jobs:
if: ${{ github.event_name == 'workflow_dispatch' && github.event.inputs.debug_enabled == 'true' }} if: ${{ github.event_name == 'workflow_dispatch' && github.event.inputs.debug_enabled == 'true' }}
with: with:
limit-access-to-actor: true limit-access-to-actor: true
- uses: docker://tiangolo/latest-changes:0.0.3 - uses: docker://tiangolo/latest-changes:0.2.0
# - uses: tiangolo/latest-changes@main
with: with:
token: ${{ secrets.GITHUB_TOKEN }} token: ${{ secrets.GITHUB_TOKEN }}
latest_changes_file: docs/en/docs/release-notes.md latest_changes_file: docs/en/docs/release-notes.md
latest_changes_header: '## Latest Changes\n\n' latest_changes_header: '## Latest Changes'
end_regex: '^## '
debug_logs: true debug_logs: true
label_header_prefix: '### '

14
.pre-commit-config.yaml

@ -13,23 +13,13 @@ repos:
- --unsafe - --unsafe
- id: end-of-file-fixer - id: end-of-file-fixer
- id: trailing-whitespace - id: trailing-whitespace
- repo: https://github.com/asottile/pyupgrade
rev: v3.7.0
hooks:
- id: pyupgrade
args:
- --py3-plus
- --keep-runtime-typing
- repo: https://github.com/charliermarsh/ruff-pre-commit - repo: https://github.com/charliermarsh/ruff-pre-commit
rev: v0.0.275 rev: v0.1.2
hooks: hooks:
- id: ruff - id: ruff
args: args:
- --fix - --fix
- repo: https://github.com/psf/black - id: ruff-format
rev: 23.3.0
hooks:
- id: black
ci: ci:
autofix_commit_msg: 🎨 [pre-commit.ci] Auto format from pre-commit.com hooks autofix_commit_msg: 🎨 [pre-commit.ci] Auto format from pre-commit.com hooks
autoupdate_commit_msg: ⬆ [pre-commit.ci] pre-commit autoupdate autoupdate_commit_msg: ⬆ [pre-commit.ci] pre-commit autoupdate

4
README.md

@ -48,9 +48,10 @@ The key features are:
<a href="https://cryptapi.io/" target="_blank" title="CryptAPI: Your easy to use, secure and privacy oriented payment gateway."><img src="https://fastapi.tiangolo.com/img/sponsors/cryptapi.svg"></a> <a href="https://cryptapi.io/" target="_blank" title="CryptAPI: Your easy to use, secure and privacy oriented payment gateway."><img src="https://fastapi.tiangolo.com/img/sponsors/cryptapi.svg"></a>
<a href="https://platform.sh/try-it-now/?utm_source=fastapi-signup&utm_medium=banner&utm_campaign=FastAPI-signup-June-2023" target="_blank" title="Build, run and scale your apps on a modern, reliable, and secure PaaS."><img src="https://fastapi.tiangolo.com/img/sponsors/platform-sh.png"></a> <a href="https://platform.sh/try-it-now/?utm_source=fastapi-signup&utm_medium=banner&utm_campaign=FastAPI-signup-June-2023" target="_blank" title="Build, run and scale your apps on a modern, reliable, and secure PaaS."><img src="https://fastapi.tiangolo.com/img/sponsors/platform-sh.png"></a>
<a href="https://www.buildwithfern.com/?utm_source=tiangolo&utm_medium=website&utm_campaign=main-badge" target="_blank" title="Fern | SDKs and API docs"><img src="https://fastapi.tiangolo.com/img/sponsors/fern.svg"></a>
<a href="https://www.porter.run" target="_blank" title="Deploy FastAPI on AWS with a few clicks"><img src="https://fastapi.tiangolo.com/img/sponsors/porter.png"></a> <a href="https://www.porter.run" target="_blank" title="Deploy FastAPI on AWS with a few clicks"><img src="https://fastapi.tiangolo.com/img/sponsors/porter.png"></a>
<a href="https://bump.sh/fastapi?utm_source=fastapi&utm_medium=referral&utm_campaign=sponsor" target="_blank" title="Automate FastAPI documentation generation with Bump.sh"><img src="https://fastapi.tiangolo.com/img/sponsors/bump-sh.svg"></a> <a href="https://bump.sh/fastapi?utm_source=fastapi&utm_medium=referral&utm_campaign=sponsor" target="_blank" title="Automate FastAPI documentation generation with Bump.sh"><img src="https://fastapi.tiangolo.com/img/sponsors/bump-sh.svg"></a>
<a href="https://reflex.dev" target="_blank" title="Reflex"><img src="https://fastapi.tiangolo.com/img/sponsors/reflex.png"></a>
<a href="https://github.com/scalar/scalar/?utm_source=fastapi&utm_medium=website&utm_campaign=main-badge" target="_blank" title="Scalar: Beautiful Open-Source API References from Swagger/OpenAPI files"><img src="https://fastapi.tiangolo.com/img/sponsors/scalar.svg"></a>
<a href="https://www.deta.sh/?ref=fastapi" target="_blank" title="The launchpad for all your (team's) ideas"><img src="https://fastapi.tiangolo.com/img/sponsors/deta.svg"></a> <a href="https://www.deta.sh/?ref=fastapi" target="_blank" title="The launchpad for all your (team's) ideas"><img src="https://fastapi.tiangolo.com/img/sponsors/deta.svg"></a>
<a href="https://training.talkpython.fm/fastapi-courses" target="_blank" title="FastAPI video courses on demand from people you trust"><img src="https://fastapi.tiangolo.com/img/sponsors/talkpython.png"></a> <a href="https://training.talkpython.fm/fastapi-courses" target="_blank" title="FastAPI video courses on demand from people you trust"><img src="https://fastapi.tiangolo.com/img/sponsors/talkpython.png"></a>
<a href="https://testdriven.io/courses/tdd-fastapi/" target="_blank" title="Learn to build high-quality web apps with best practices"><img src="https://fastapi.tiangolo.com/img/sponsors/testdriven.svg"></a> <a href="https://testdriven.io/courses/tdd-fastapi/" target="_blank" title="Learn to build high-quality web apps with best practices"><img src="https://fastapi.tiangolo.com/img/sponsors/testdriven.svg"></a>
@ -59,6 +60,7 @@ The key features are:
<a href="https://databento.com/" target="_blank" title="Pay as you go for market data"><img src="https://fastapi.tiangolo.com/img/sponsors/databento.svg"></a> <a href="https://databento.com/" target="_blank" title="Pay as you go for market data"><img src="https://fastapi.tiangolo.com/img/sponsors/databento.svg"></a>
<a href="https://speakeasyapi.dev?utm_source=fastapi+repo&utm_medium=github+sponsorship" target="_blank" title="SDKs for your API | Speakeasy"><img src="https://fastapi.tiangolo.com/img/sponsors/speakeasy.png"></a> <a href="https://speakeasyapi.dev?utm_source=fastapi+repo&utm_medium=github+sponsorship" target="_blank" title="SDKs for your API | Speakeasy"><img src="https://fastapi.tiangolo.com/img/sponsors/speakeasy.png"></a>
<a href="https://www.svix.com/" target="_blank" title="Svix - Webhooks as a service"><img src="https://fastapi.tiangolo.com/img/sponsors/svix.svg"></a> <a href="https://www.svix.com/" target="_blank" title="Svix - Webhooks as a service"><img src="https://fastapi.tiangolo.com/img/sponsors/svix.svg"></a>
<a href="https://www.codacy.com/?utm_source=github&utm_medium=sponsors&utm_id=pioneers" target="_blank" title="Take code reviews from hours to minutes"><img src="https://fastapi.tiangolo.com/img/sponsors/codacy.png"></a>
<!-- /sponsors --> <!-- /sponsors -->

14
docs/em/docs/advanced/settings.md

@ -221,7 +221,7 @@ $ ADMIN_EMAIL="[email protected]" APP_NAME="ChimichangApp" uvicorn main:app
``` ```
!!! tip !!! tip
👥 🔜 🔬 `@lru_cache()` 🍖. 👥 🔜 🔬 `@lru_cache` 🍖.
🔜 👆 💪 🤔 `get_settings()` 😐 🔢. 🔜 👆 💪 🤔 `get_settings()` 😐 🔢.
@ -254,7 +254,7 @@ $ ADMIN_EMAIL="[email protected]" APP_NAME="ChimichangApp" uvicorn main:app
✋️ 🇨🇻 📁 🚫 🤙 ✔️ ✔️ 👈 ☑ 📁. ✋️ 🇨🇻 📁 🚫 🤙 ✔️ ✔️ 👈 ☑ 📁.
Pydantic ✔️ 🐕‍🦺 👂 ⚪️➡️ 👉 🆎 📁 ⚙️ 🔢 🗃. 👆 💪 ✍ 🌖 <a href="https://pydantic-docs.helpmanual.io/usage/settings/#dotenv-env-support" class="external-link" target="_blank">Pydantic ⚒: 🇨🇻 (.🇨🇻) 🐕‍🦺</a>. Pydantic ✔️ 🐕‍🦺 👂 ⚪️➡️ 👉 🆎 📁 ⚙️ 🔢 🗃. 👆 💪 ✍ 🌖 <a href="https://docs.pydantic.dev/latest/concepts/pydantic_settings/#dotenv-env-support" class="external-link" target="_blank">Pydantic ⚒: 🇨🇻 (.🇨🇻) 🐕‍🦺</a>.
!!! tip !!! tip
👉 👷, 👆 💪 `pip install python-dotenv`. 👉 👷, 👆 💪 `pip install python-dotenv`.
@ -302,7 +302,7 @@ def get_settings():
👥 🔜 ✍ 👈 🎚 🔠 📨, &amp; 👥 🔜 👂 `.env` 📁 🔠 📨. 👶 👶 👥 🔜 ✍ 👈 🎚 🔠 📨, &amp; 👥 🔜 👂 `.env` 📁 🔠 📨. 👶 👶
✋️ 👥 ⚙️ `@lru_cache()` 👨‍🎨 🔛 🔝, `Settings` 🎚 🔜 ✍ 🕴 🕐, 🥇 🕰 ⚫️ 🤙. 👶 👶 ✋️ 👥 ⚙️ `@lru_cache` 👨‍🎨 🔛 🔝, `Settings` 🎚 🔜 ✍ 🕴 🕐, 🥇 🕰 ⚫️ 🤙. 👶 👶
```Python hl_lines="1 10" ```Python hl_lines="1 10"
{!../../../docs_src/settings/app03/main.py!} {!../../../docs_src/settings/app03/main.py!}
@ -312,14 +312,14 @@ def get_settings():
#### `lru_cache` 📡 ℹ #### `lru_cache` 📡 ℹ
`@lru_cache()` 🔀 🔢 ⚫️ 🎀 📨 🎏 💲 👈 📨 🥇 🕰, ↩️ 💻 ⚫️ 🔄, 🛠️ 📟 🔢 🔠 🕰. `@lru_cache` 🔀 🔢 ⚫️ 🎀 📨 🎏 💲 👈 📨 🥇 🕰, ↩️ 💻 ⚫️ 🔄, 🛠️ 📟 🔢 🔠 🕰.
, 🔢 🔛 ⚫️ 🔜 🛠️ 🕐 🔠 🌀 ❌. &amp; ⤴️ 💲 📨 🔠 👈 🌀 ❌ 🔜 ⚙️ 🔄 &amp; 🔄 🕐❔ 🔢 🤙 ⏮️ ⚫️❔ 🎏 🌀 ❌. , 🔢 🔛 ⚫️ 🔜 🛠️ 🕐 🔠 🌀 ❌. &amp; ⤴️ 💲 📨 🔠 👈 🌀 ❌ 🔜 ⚙️ 🔄 &amp; 🔄 🕐❔ 🔢 🤙 ⏮️ ⚫️❔ 🎏 🌀 ❌.
🖼, 🚥 👆 ✔️ 🔢: 🖼, 🚥 👆 ✔️ 🔢:
```Python ```Python
@lru_cache() @lru_cache
def say_hi(name: str, salutation: str = "Ms."): def say_hi(name: str, salutation: str = "Ms."):
return f"Hello {salutation} {name}" return f"Hello {salutation} {name}"
``` ```
@ -371,7 +371,7 @@ participant execute as Execute function
👈 🌌, ⚫️ 🎭 🌖 🚥 ⚫️ 🌐 🔢. ✋️ ⚫️ ⚙️ 🔗 🔢, ⤴️ 👥 💪 🔐 ⚫️ 💪 🔬. 👈 🌌, ⚫️ 🎭 🌖 🚥 ⚫️ 🌐 🔢. ✋️ ⚫️ ⚙️ 🔗 🔢, ⤴️ 👥 💪 🔐 ⚫️ 💪 🔬.
`@lru_cache()` 🍕 `functools` ❔ 🍕 🐍 🐩 🗃, 👆 💪 ✍ 🌅 🔃 ⚫️ <a href="https://docs.python.org/3/library/functools.html#functools.lru_cache" class="external-link" target="_blank">🐍 🩺 `@lru_cache()`</a>. `@lru_cache` 🍕 `functools` ❔ 🍕 🐍 🐩 🗃, 👆 💪 ✍ 🌅 🔃 ⚫️ <a href="https://docs.python.org/3/library/functools.html#functools.lru_cache" class="external-link" target="_blank">🐍 🩺 `@lru_cache`</a>.
## 🌃 ## 🌃
@ -379,4 +379,4 @@ participant execute as Execute function
* ⚙️ 🔗 👆 💪 📉 🔬. * ⚙️ 🔗 👆 💪 📉 🔬.
* 👆 💪 ⚙️ `.env` 📁 ⏮️ ⚫️. * 👆 💪 ⚙️ `.env` 📁 ⏮️ ⚫️.
* ⚙️ `@lru_cache()` ➡️ 👆 ❎ 👂 🇨🇻 📁 🔄 &amp; 🔄 🔠 📨, ⏪ 🤝 👆 🔐 ⚫️ ⏮️ 🔬. * ⚙️ `@lru_cache` ➡️ 👆 ❎ 👂 🇨🇻 📁 🔄 &amp; 🔄 🔠 📨, ⏪ 🤝 👆 🔐 ⚫️ ⏮️ 🔬.

4
docs/em/docs/async.md

@ -409,11 +409,11 @@ async def read_burgers():
### 🔗 ### 🔗
🎏 ✔ [🔗](/tutorial/dependencies/index.md){.internal-link target=_blank}. 🚥 🔗 🐩 `def` 🔢 ↩️ `async def`, ⚫️ 🏃 🔢 🧵. 🎏 ✔ [🔗](./tutorial/dependencies/index.md){.internal-link target=_blank}. 🚥 🔗 🐩 `def` 🔢 ↩️ `async def`, ⚫️ 🏃 🔢 🧵.
### 🎧-🔗 ### 🎧-🔗
👆 💪 ✔️ 💗 🔗 &amp; [🎧-🔗](/tutorial/dependencies/sub-dependencies.md){.internal-link target=_blank} 🚫 🔠 🎏 (🔢 🔢 🔑), 👫 💪 ✍ ⏮️ `async def` &amp; ⏮️ 😐 `def`. ⚫️ 🔜 👷, &amp; 🕐 ✍ ⏮️ 😐 `def` 🔜 🤙 🔛 🔢 🧵 (⚪️➡️ 🧵) ↩️ ➖ "⌛". 👆 💪 ✔️ 💗 🔗 &amp; [🎧-🔗](./tutorial/dependencies/sub-dependencies.md){.internal-link target=_blank} 🚫 🔠 🎏 (🔢 🔢 🔑), 👫 💪 ✍ ⏮️ `async def` &amp; ⏮️ 😐 `def`. ⚫️ 🔜 👷, &amp; 🕐 ✍ ⏮️ 😐 `def` 🔜 🤙 🔛 🔢 🧵 (⚪️➡️ 🧵) ↩️ ➖ "⌛".
### 🎏 🚙 🔢 ### 🎏 🚙 🔢

2
docs/em/docs/index.md

@ -27,7 +27,7 @@
--- ---
FastAPI 🏛, ⏩ (↕-🎭), 🕸 🛠️ 🏗 🛠️ ⏮️ 🐍 3️⃣.7️⃣ ➕ ⚓️ 🔛 🐩 🐍 🆎 🔑. FastAPI 🏛, ⏩ (↕-🎭), 🕸 🛠️ 🏗 🛠️ ⏮️ 🐍 3️⃣.8️⃣ ➕ ⚓️ 🔛 🐩 🐍 🆎 🔑.
🔑 ⚒: 🔑 ⚒:

4
docs/em/docs/tutorial/query-params-str-validations.md

@ -371,7 +371,7 @@ http://localhost:8000/items/
=== "🐍 3️⃣.1️⃣0️⃣ &amp; 🔛" === "🐍 3️⃣.1️⃣0️⃣ &amp; 🔛"
```Python hl_lines="12" ```Python hl_lines="11"
{!> ../../../docs_src/query_params_str_validations/tutorial008_py310.py!} {!> ../../../docs_src/query_params_str_validations/tutorial008_py310.py!}
``` ```
@ -421,7 +421,7 @@ http://127.0.0.1:8000/items/?item-query=foobaritems
=== "🐍 3️⃣.1️⃣0️⃣ &amp; 🔛" === "🐍 3️⃣.1️⃣0️⃣ &amp; 🔛"
```Python hl_lines="17" ```Python hl_lines="16"
{!> ../../../docs_src/query_params_str_validations/tutorial010_py310.py!} {!> ../../../docs_src/query_params_str_validations/tutorial010_py310.py!}
``` ```

12
docs/en/data/sponsors.yml

@ -5,15 +5,18 @@ gold:
- url: https://platform.sh/try-it-now/?utm_source=fastapi-signup&utm_medium=banner&utm_campaign=FastAPI-signup-June-2023 - url: https://platform.sh/try-it-now/?utm_source=fastapi-signup&utm_medium=banner&utm_campaign=FastAPI-signup-June-2023
title: "Build, run and scale your apps on a modern, reliable, and secure PaaS." title: "Build, run and scale your apps on a modern, reliable, and secure PaaS."
img: https://fastapi.tiangolo.com/img/sponsors/platform-sh.png img: https://fastapi.tiangolo.com/img/sponsors/platform-sh.png
- url: https://www.buildwithfern.com/?utm_source=tiangolo&utm_medium=website&utm_campaign=main-badge
title: Fern | SDKs and API docs
img: https://fastapi.tiangolo.com/img/sponsors/fern.svg
- url: https://www.porter.run - url: https://www.porter.run
title: Deploy FastAPI on AWS with a few clicks title: Deploy FastAPI on AWS with a few clicks
img: https://fastapi.tiangolo.com/img/sponsors/porter.png img: https://fastapi.tiangolo.com/img/sponsors/porter.png
- url: https://bump.sh/fastapi?utm_source=fastapi&utm_medium=referral&utm_campaign=sponsor - url: https://bump.sh/fastapi?utm_source=fastapi&utm_medium=referral&utm_campaign=sponsor
title: Automate FastAPI documentation generation with Bump.sh title: Automate FastAPI documentation generation with Bump.sh
img: https://fastapi.tiangolo.com/img/sponsors/bump-sh.svg img: https://fastapi.tiangolo.com/img/sponsors/bump-sh.svg
- url: https://reflex.dev
title: Reflex
img: https://fastapi.tiangolo.com/img/sponsors/reflex.png
- url: https://github.com/scalar/scalar/?utm_source=fastapi&utm_medium=website&utm_campaign=main-badge
title: "Scalar: Beautiful Open-Source API References from Swagger/OpenAPI files"
img: https://fastapi.tiangolo.com/img/sponsors/scalar.svg
silver: silver:
- url: https://www.deta.sh/?ref=fastapi - url: https://www.deta.sh/?ref=fastapi
title: The launchpad for all your (team's) ideas title: The launchpad for all your (team's) ideas
@ -39,6 +42,9 @@ silver:
- url: https://www.svix.com/ - url: https://www.svix.com/
title: Svix - Webhooks as a service title: Svix - Webhooks as a service
img: https://fastapi.tiangolo.com/img/sponsors/svix.svg img: https://fastapi.tiangolo.com/img/sponsors/svix.svg
- url: https://www.codacy.com/?utm_source=github&utm_medium=sponsors&utm_id=pioneers
title: Take code reviews from hours to minutes
img: https://fastapi.tiangolo.com/img/sponsors/codacy.png
bronze: bronze:
- url: https://www.exoflare.com/open-source/?utm_source=FastAPI&utm_campaign=open_source - url: https://www.exoflare.com/open-source/?utm_source=FastAPI&utm_campaign=open_source
title: Biosecurity risk assessments made easy. title: Biosecurity risk assessments made easy.

3
docs/en/data/sponsors_badge.yml

@ -14,9 +14,12 @@ logins:
- nihpo - nihpo
- armand-sauzay - armand-sauzay
- databento-bot - databento-bot
- databento
- nanram22 - nanram22
- Flint-company - Flint-company
- porter-dev - porter-dev
- fern-api - fern-api
- ndimares - ndimares
- svixhq - svixhq
- Alek99
- codacy

5
docs/en/docs/advanced/generate-clients.md

@ -20,10 +20,9 @@ Some of them also ✨ [**sponsor FastAPI**](../help-fastapi.md#sponsor-the-autho
And it shows their true commitment to FastAPI and its **community** (you), as they not only want to provide you a **good service** but also want to make sure you have a **good and healthy framework**, FastAPI. 🙇 And it shows their true commitment to FastAPI and its **community** (you), as they not only want to provide you a **good service** but also want to make sure you have a **good and healthy framework**, FastAPI. 🙇
You might want to try their services and follow their guides: For example, you might want to try <a href="https://speakeasyapi.dev/?utm_source=fastapi+repo&utm_medium=github+sponsorship" class="external-link" target="_blank">Speakeasy</a>.
* <a href="https://www.buildwithfern.com/?utm_source=tiangolo&utm_medium=website&utm_campaign=docs-generate-clients" class="external-link" target="_blank">Fern</a> There are also several other companies offering similar services that you can search and find online. 🤓
* <a href="https://speakeasyapi.dev/?utm_source=fastapi+repo&utm_medium=github+sponsorship" class="external-link" target="_blank">Speakeasy</a>
## Generate a TypeScript Frontend Client ## Generate a TypeScript Frontend Client

14
docs/en/docs/advanced/settings.md

@ -276,7 +276,7 @@ Now we create a dependency that returns a new `config.Settings()`.
``` ```
!!! tip !!! tip
We'll discuss the `@lru_cache()` in a bit. We'll discuss the `@lru_cache` in a bit.
For now you can assume `get_settings()` is a normal function. For now you can assume `get_settings()` is a normal function.
@ -326,7 +326,7 @@ This practice is common enough that it has a name, these environment variables a
But a dotenv file doesn't really have to have that exact filename. But a dotenv file doesn't really have to have that exact filename.
Pydantic has support for reading from these types of files using an external library. You can read more at <a href="https://pydantic-docs.helpmanual.io/usage/settings/#dotenv-env-support" class="external-link" target="_blank">Pydantic Settings: Dotenv (.env) support</a>. Pydantic has support for reading from these types of files using an external library. You can read more at <a href="https://docs.pydantic.dev/latest/concepts/pydantic_settings/#dotenv-env-support" class="external-link" target="_blank">Pydantic Settings: Dotenv (.env) support</a>.
!!! tip !!! tip
For this to work, you need to `pip install python-dotenv`. For this to work, you need to `pip install python-dotenv`.
@ -388,7 +388,7 @@ def get_settings():
we would create that object for each request, and we would be reading the `.env` file for each request. ⚠️ we would create that object for each request, and we would be reading the `.env` file for each request. ⚠️
But as we are using the `@lru_cache()` decorator on top, the `Settings` object will be created only once, the first time it's called. ✔️ But as we are using the `@lru_cache` decorator on top, the `Settings` object will be created only once, the first time it's called. ✔️
=== "Python 3.9+" === "Python 3.9+"
@ -415,14 +415,14 @@ Then for any subsequent calls of `get_settings()` in the dependencies for the ne
#### `lru_cache` Technical Details #### `lru_cache` Technical Details
`@lru_cache()` modifies the function it decorates to return the same value that was returned the first time, instead of computing it again, executing the code of the function every time. `@lru_cache` modifies the function it decorates to return the same value that was returned the first time, instead of computing it again, executing the code of the function every time.
So, the function below it will be executed once for each combination of arguments. And then the values returned by each of those combinations of arguments will be used again and again whenever the function is called with exactly the same combination of arguments. So, the function below it will be executed once for each combination of arguments. And then the values returned by each of those combinations of arguments will be used again and again whenever the function is called with exactly the same combination of arguments.
For example, if you have a function: For example, if you have a function:
```Python ```Python
@lru_cache() @lru_cache
def say_hi(name: str, salutation: str = "Ms."): def say_hi(name: str, salutation: str = "Ms."):
return f"Hello {salutation} {name}" return f"Hello {salutation} {name}"
``` ```
@ -474,7 +474,7 @@ In the case of our dependency `get_settings()`, the function doesn't even take a
That way, it behaves almost as if it was just a global variable. But as it uses a dependency function, then we can override it easily for testing. That way, it behaves almost as if it was just a global variable. But as it uses a dependency function, then we can override it easily for testing.
`@lru_cache()` is part of `functools` which is part of Python's standard library, you can read more about it in the <a href="https://docs.python.org/3/library/functools.html#functools.lru_cache" class="external-link" target="_blank">Python docs for `@lru_cache()`</a>. `@lru_cache` is part of `functools` which is part of Python's standard library, you can read more about it in the <a href="https://docs.python.org/3/library/functools.html#functools.lru_cache" class="external-link" target="_blank">Python docs for `@lru_cache`</a>.
## Recap ## Recap
@ -482,4 +482,4 @@ You can use Pydantic Settings to handle the settings or configurations for your
* By using a dependency you can simplify testing. * By using a dependency you can simplify testing.
* You can use `.env` files with it. * You can use `.env` files with it.
* Using `@lru_cache()` lets you avoid reading the dotenv file again and again for each request, while allowing you to override it during testing. * Using `@lru_cache` lets you avoid reading the dotenv file again and again for each request, while allowing you to override it during testing.

2
docs/en/docs/alternatives.md

@ -119,8 +119,6 @@ That's why when talking about version 2.0 it's common to say "Swagger", and for
These two were chosen for being fairly popular and stable, but doing a quick search, you could find dozens of additional alternative user interfaces for OpenAPI (that you can use with **FastAPI**). These two were chosen for being fairly popular and stable, but doing a quick search, you could find dozens of additional alternative user interfaces for OpenAPI (that you can use with **FastAPI**).
For example, you could try <a href="https://www.buildwithfern.com/?utm_source=tiangolo&utm_medium=website&utm_campaign=docs-alternatives" class="external-link" target="_blank">Fern</a> which is also a FastAPI sponsor. 😎🎉
### Flask REST frameworks ### Flask REST frameworks
There are several Flask REST frameworks, but after investing the time and work into investigating them, I found that many are discontinued or abandoned, with several standing issues that made them unfit. There are several Flask REST frameworks, but after investing the time and work into investigating them, I found that many are discontinued or abandoned, with several standing issues that made them unfit.

4
docs/en/docs/async.md

@ -409,11 +409,11 @@ Still, in both situations, chances are that **FastAPI** will [still be faster](/
### Dependencies ### Dependencies
The same applies for [dependencies](/tutorial/dependencies/index.md){.internal-link target=_blank}. If a dependency is a standard `def` function instead of `async def`, it is run in the external threadpool. The same applies for [dependencies](./tutorial/dependencies/index.md){.internal-link target=_blank}. If a dependency is a standard `def` function instead of `async def`, it is run in the external threadpool.
### Sub-dependencies ### Sub-dependencies
You can have multiple dependencies and [sub-dependencies](/tutorial/dependencies/sub-dependencies.md){.internal-link target=_blank} requiring each other (as parameters of the function definitions), some of them might be created with `async def` and some with normal `def`. It would still work, and the ones created with normal `def` would be called on an external thread (from the threadpool) instead of being "awaited". You can have multiple dependencies and [sub-dependencies](./tutorial/dependencies/sub-dependencies.md){.internal-link target=_blank} requiring each other (as parameters of the function definitions), some of them might be created with `async def` and some with normal `def`. It would still work, and the ones created with normal `def` would be called on an external thread (from the threadpool) instead of being "awaited".
### Other utility functions ### Other utility functions

4
docs/en/docs/how-to/custom-docs-ui-assets.md

@ -96,8 +96,8 @@ You can probably right-click each link and select an option similar to `Save lin
**Swagger UI** uses the files: **Swagger UI** uses the files:
* <a href="https://cdn.jsdelivr.net/npm/swagger-ui-dist@5/swagger-ui-bundle.js" class="external-link" target="_blank">`swagger-ui-bundle.js`</a> * <a href="https://cdn.jsdelivr.net/npm/swagger-ui-dist@5.9.0/swagger-ui-bundle.js" class="external-link" target="_blank">`swagger-ui-bundle.js`</a>
* <a href="https://cdn.jsdelivr.net/npm/swagger-ui-dist@5/swagger-ui.css" class="external-link" target="_blank">`swagger-ui.css`</a> * <a href="https://cdn.jsdelivr.net/npm/swagger-ui-dist@5.9.0/swagger-ui.css" class="external-link" target="_blank">`swagger-ui.css`</a>
And **ReDoc** uses the file: And **ReDoc** uses the file:

BIN
docs/en/docs/img/sponsors/codacy.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 30 KiB

BIN
docs/en/docs/img/sponsors/reflex-banner.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.0 KiB

BIN
docs/en/docs/img/sponsors/reflex.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 11 KiB

1
docs/en/docs/img/sponsors/scalar-banner.svg

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 6.4 KiB

1
docs/en/docs/img/sponsors/scalar.svg

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 36 KiB

39
docs/en/docs/release-notes.md

@ -7,9 +7,26 @@ hide:
## Latest Changes ## Latest Changes
* 🔧 Add `CITATION.cff` file for academic citations. PR [#10496](https://github.com/tiangolo/fastapi/pull/10496) by [@tiangolo](https://github.com/tiangolo). * 🔧 Update sponsors, add Scalar. PR [#10728](https://github.com/tiangolo/fastapi/pull/10728) by [@tiangolo](https://github.com/tiangolo).
### Internal
* 🔧 Update sponsors, remove Fern. PR [#10729](https://github.com/tiangolo/fastapi/pull/10729) by [@tiangolo](https://github.com/tiangolo).
* 🔧 Update sponsors, add Codacy. PR [#10677](https://github.com/tiangolo/fastapi/pull/10677) by [@tiangolo](https://github.com/tiangolo).
* 🔧 Update sponsors, add Reflex. PR [#10676](https://github.com/tiangolo/fastapi/pull/10676) by [@tiangolo](https://github.com/tiangolo).
* 📝 Update release notes, move and check latest-changes. PR [#10588](https://github.com/tiangolo/fastapi/pull/10588) by [@tiangolo](https://github.com/tiangolo).
* 👷 Upgrade latest-changes GitHub Action. PR [#10587](https://github.com/tiangolo/fastapi/pull/10587) by [@tiangolo](https://github.com/tiangolo).
## 0.104.1
### Fixes
* 📌 Pin Swagger UI version to 5.9.0 temporarily to handle a bug crashing it in 5.9.1. PR [#10529](https://github.com/tiangolo/fastapi/pull/10529) by [@alejandraklachquin](https://github.com/alejandraklachquin).
* This is not really a bug in FastAPI but in Swagger UI, nevertheless pinning the version will work while a solution is found on the [Swagger UI side](https://github.com/swagger-api/swagger-ui/issues/9337).
### Docs
* 📝 Update data structure and render for external-links. PR [#10495](https://github.com/tiangolo/fastapi/pull/10495) by [@tiangolo](https://github.com/tiangolo). * 📝 Update data structure and render for external-links. PR [#10495](https://github.com/tiangolo/fastapi/pull/10495) by [@tiangolo](https://github.com/tiangolo).
* 🐛 Fix overriding MKDocs theme lang in hook. PR [#10490](https://github.com/tiangolo/fastapi/pull/10490) by [@tiangolo](https://github.com/tiangolo).
* ✏️ Fix link to SPDX license identifier in `docs/en/docs/tutorial/metadata.md`. PR [#10433](https://github.com/tiangolo/fastapi/pull/10433) by [@worldworm](https://github.com/worldworm). * ✏️ Fix link to SPDX license identifier in `docs/en/docs/tutorial/metadata.md`. PR [#10433](https://github.com/tiangolo/fastapi/pull/10433) by [@worldworm](https://github.com/worldworm).
* 📝 Update example validation error from Pydantic v1 to match Pydantic v2 in `docs/en/docs/tutorial/path-params.md`. PR [#10043](https://github.com/tiangolo/fastapi/pull/10043) by [@giuliowaitforitdavide](https://github.com/giuliowaitforitdavide). * 📝 Update example validation error from Pydantic v1 to match Pydantic v2 in `docs/en/docs/tutorial/path-params.md`. PR [#10043](https://github.com/tiangolo/fastapi/pull/10043) by [@giuliowaitforitdavide](https://github.com/giuliowaitforitdavide).
* ✏️ Fix typos in emoji docs and in some source examples. PR [#10438](https://github.com/tiangolo/fastapi/pull/10438) by [@afuetterer](https://github.com/afuetterer). * ✏️ Fix typos in emoji docs and in some source examples. PR [#10438](https://github.com/tiangolo/fastapi/pull/10438) by [@afuetterer](https://github.com/afuetterer).
@ -17,8 +34,24 @@ hide:
* ✏️ Fix typos and rewordings in `docs/en/docs/tutorial/body-nested-models.md`. PR [#10468](https://github.com/tiangolo/fastapi/pull/10468) by [@yogabonito](https://github.com/yogabonito). * ✏️ Fix typos and rewordings in `docs/en/docs/tutorial/body-nested-models.md`. PR [#10468](https://github.com/tiangolo/fastapi/pull/10468) by [@yogabonito](https://github.com/yogabonito).
* 📝 Update docs, remove references to removed `pydantic.Required` in `docs/en/docs/tutorial/query-params-str-validations.md`. PR [#10469](https://github.com/tiangolo/fastapi/pull/10469) by [@yogabonito](https://github.com/yogabonito). * 📝 Update docs, remove references to removed `pydantic.Required` in `docs/en/docs/tutorial/query-params-str-validations.md`. PR [#10469](https://github.com/tiangolo/fastapi/pull/10469) by [@yogabonito](https://github.com/yogabonito).
* ✏️ Fix typo in `docs/en/docs/reference/index.md`. PR [#10467](https://github.com/tiangolo/fastapi/pull/10467) by [@tarsil](https://github.com/tarsil). * ✏️ Fix typo in `docs/en/docs/reference/index.md`. PR [#10467](https://github.com/tiangolo/fastapi/pull/10467) by [@tarsil](https://github.com/tarsil).
* 🔥 Drop/close Gitter chat. Questions should go to GitHub Discussions, free conversations to Discord.. PR [#10485](https://github.com/tiangolo/fastapi/pull/10485) by [@tiangolo](https://github.com/tiangolo).
* 🔥 Remove unnecessary duplicated docstrings. PR [#10484](https://github.com/tiangolo/fastapi/pull/10484) by [@tiangolo](https://github.com/tiangolo). * 🔥 Remove unnecessary duplicated docstrings. PR [#10484](https://github.com/tiangolo/fastapi/pull/10484) by [@tiangolo](https://github.com/tiangolo).
### Internal
* ✏️ Update Pydantic links to dotenv support. PR [#10511](https://github.com/tiangolo/fastapi/pull/10511) by [@White-Mask](https://github.com/White-Mask).
* ✏️ Update links in `docs/en/docs/async.md` and `docs/zh/docs/async.md` to make them relative. PR [#10498](https://github.com/tiangolo/fastapi/pull/10498) by [@hasnatsajid](https://github.com/hasnatsajid).
* ✏️ Fix links in `docs/em/docs/async.md`. PR [#10507](https://github.com/tiangolo/fastapi/pull/10507) by [@hasnatsajid](https://github.com/hasnatsajid).
* ✏️ Fix typo in `docs/em/docs/index.md`, Python 3.8. PR [#10521](https://github.com/tiangolo/fastapi/pull/10521) by [@kerriop](https://github.com/kerriop).
* ⬆ Bump pillow from 9.5.0 to 10.1.0. PR [#10446](https://github.com/tiangolo/fastapi/pull/10446) by [@dependabot[bot]](https://github.com/apps/dependabot).
* ⬆ Update mkdocs-material requirement from <9.0.0,>=8.1.4 to >=8.1.4,<10.0.0. PR [#5862](https://github.com/tiangolo/fastapi/pull/5862) by [@dependabot[bot]](https://github.com/apps/dependabot).
* ⬆ Bump mkdocs-material from 9.1.21 to 9.4.7. PR [#10545](https://github.com/tiangolo/fastapi/pull/10545) by [@dependabot[bot]](https://github.com/apps/dependabot).
* 👷 Install MkDocs Material Insiders only when secrets are available, for Dependabot. PR [#10544](https://github.com/tiangolo/fastapi/pull/10544) by [@tiangolo](https://github.com/tiangolo).
* 🔧 Update sponsors badges, Databento. PR [#10519](https://github.com/tiangolo/fastapi/pull/10519) by [@tiangolo](https://github.com/tiangolo).
* 👷 Adopt Ruff format. PR [#10517](https://github.com/tiangolo/fastapi/pull/10517) by [@tiangolo](https://github.com/tiangolo).
* 🔧 Add `CITATION.cff` file for academic citations. PR [#10496](https://github.com/tiangolo/fastapi/pull/10496) by [@tiangolo](https://github.com/tiangolo).
* 🐛 Fix overriding MKDocs theme lang in hook. PR [#10490](https://github.com/tiangolo/fastapi/pull/10490) by [@tiangolo](https://github.com/tiangolo).
* 🔥 Drop/close Gitter chat. Questions should go to GitHub Discussions, free conversations to Discord.. PR [#10485](https://github.com/tiangolo/fastapi/pull/10485) by [@tiangolo](https://github.com/tiangolo).
## 0.104.0 ## 0.104.0
## Features ## Features

4
docs/en/docs/tutorial/query-params-str-validations.md

@ -737,7 +737,7 @@ And a `description`:
!!! tip !!! tip
Prefer to use the `Annotated` version if possible. Prefer to use the `Annotated` version if possible.
```Python hl_lines="12" ```Python hl_lines="11"
{!> ../../../docs_src/query_params_str_validations/tutorial008_py310.py!} {!> ../../../docs_src/query_params_str_validations/tutorial008_py310.py!}
``` ```
@ -835,7 +835,7 @@ Then pass the parameter `deprecated=True` to `Query`:
!!! tip !!! tip
Prefer to use the `Annotated` version if possible. Prefer to use the `Annotated` version if possible.
```Python hl_lines="17" ```Python hl_lines="16"
{!> ../../../docs_src/query_params_str_validations/tutorial010_py310.py!} {!> ../../../docs_src/query_params_str_validations/tutorial010_py310.py!}
``` ```

18
docs/en/overrides/main.html

@ -34,12 +34,6 @@
<img class="sponsor-image" src="/img/sponsors/platform-sh-banner.png" /> <img class="sponsor-image" src="/img/sponsors/platform-sh-banner.png" />
</a> </a>
</div> </div>
<div class="item">
<a title="Fern | SDKs and API docs" style="display: block; position: relative;" href="https://www.buildwithfern.com/?utm_source=tiangolo&utm_medium=website&utm_campaign=top-banner" target="_blank">
<span class="sponsor-badge">sponsor</span>
<img class="sponsor-image" src="/img/sponsors/fern-banner.svg" />
</a>
</div>
<div class="item"> <div class="item">
<a title="Deploy FastAPI on AWS with a few clicks" style="display: block; position: relative;" href="https://www.porter.run" target="_blank"> <a title="Deploy FastAPI on AWS with a few clicks" style="display: block; position: relative;" href="https://www.porter.run" target="_blank">
<span class="sponsor-badge">sponsor</span> <span class="sponsor-badge">sponsor</span>
@ -52,6 +46,18 @@
<img class="sponsor-image" src="/img/sponsors/bump-sh-banner.svg" /> <img class="sponsor-image" src="/img/sponsors/bump-sh-banner.svg" />
</a> </a>
</div> </div>
<div class="item">
<a title="Reflex" style="display: block; position: relative;" href="https://reflex.dev" target="_blank">
<span class="sponsor-badge">sponsor</span>
<img class="sponsor-image" src="/img/sponsors/reflex-banner.png" />
</a>
</div>
<div class="item">
<a title="Scalar: Beautiful Open-Source API References from Swagger/OpenAPI files" style="display: block; position: relative;" href="https://github.com/scalar/scalar/?utm_source=fastapi&utm_medium=website&utm_campaign=top-banner" target="_blank">
<span class="sponsor-badge">sponsor</span>
<img class="sponsor-image" src="/img/sponsors/scalar-banner.svg" />
</a>
</div>
</div> </div>
</div> </div>
{% endblock %} {% endblock %}

4
docs/ru/docs/tutorial/query-params-str-validations.md

@ -741,7 +741,7 @@ http://localhost:8000/items/
!!! tip "Подсказка" !!! tip "Подсказка"
Рекомендуется использовать версию с `Annotated` если возможно. Рекомендуется использовать версию с `Annotated` если возможно.
```Python hl_lines="12" ```Python hl_lines="11"
{!> ../../../docs_src/query_params_str_validations/tutorial008_py310.py!} {!> ../../../docs_src/query_params_str_validations/tutorial008_py310.py!}
``` ```
@ -839,7 +839,7 @@ http://127.0.0.1:8000/items/?item-query=foobaritems
!!! tip "Подсказка" !!! tip "Подсказка"
Рекомендуется использовать версию с `Annotated` если возможно. Рекомендуется использовать версию с `Annotated` если возможно.
```Python hl_lines="17" ```Python hl_lines="16"
{!> ../../../docs_src/query_params_str_validations/tutorial010_py310.py!} {!> ../../../docs_src/query_params_str_validations/tutorial010_py310.py!}
``` ```

14
docs/zh/docs/advanced/settings.md

@ -239,7 +239,7 @@ $ ADMIN_EMAIL="[email protected]" APP_NAME="ChimichangApp"uvicorn main:app
``` ```
!!! tip !!! tip
我们稍后会讨论 `@lru_cache()` 我们稍后会讨论 `@lru_cache`
目前,您可以将 `get_settings()` 视为普通函数。 目前,您可以将 `get_settings()` 视为普通函数。
@ -289,7 +289,7 @@ $ ADMIN_EMAIL="[email protected]" APP_NAME="ChimichangApp"uvicorn main:app
但是,dotenv 文件实际上不一定要具有确切的文件名。 但是,dotenv 文件实际上不一定要具有确切的文件名。
Pydantic 支持使用外部库从这些类型的文件中读取。您可以在<a href="https://pydantic-docs.helpmanual.io/usage/settings/#dotenv-env-support" class="external-link" target="_blank">Pydantic 设置: Dotenv (.env) 支持</a>中阅读更多相关信息。 Pydantic 支持使用外部库从这些类型的文件中读取。您可以在<a href="https://docs.pydantic.dev/latest/concepts/pydantic_settings/#dotenv-env-support" class="external-link" target="_blank">Pydantic 设置: Dotenv (.env) 支持</a>中阅读更多相关信息。
!!! tip !!! tip
要使其工作,您需要执行 `pip install python-dotenv` 要使其工作,您需要执行 `pip install python-dotenv`
@ -337,7 +337,7 @@ def get_settings():
我们将为每个请求创建该对象,并且将在每个请求中读取 `.env` 文件。 ⚠️ 我们将为每个请求创建该对象,并且将在每个请求中读取 `.env` 文件。 ⚠️
但是,由于我们在顶部使用了 `@lru_cache()` 装饰器,因此只有在第一次调用它时,才会创建 `Settings` 对象一次。 ✔️ 但是,由于我们在顶部使用了 `@lru_cache` 装饰器,因此只有在第一次调用它时,才会创建 `Settings` 对象一次。 ✔️
=== "Python 3.9+" === "Python 3.9+"
@ -364,13 +364,13 @@ def get_settings():
#### `lru_cache` 技术细节 #### `lru_cache` 技术细节
`@lru_cache()` 修改了它所装饰的函数,以返回第一次返回的相同值,而不是再次计算它,每次都执行函数的代码。 `@lru_cache` 修改了它所装饰的函数,以返回第一次返回的相同值,而不是再次计算它,每次都执行函数的代码。
因此,下面的函数将对每个参数组合执行一次。然后,每个参数组合返回的值将在使用完全相同的参数组合调用函数时再次使用。 因此,下面的函数将对每个参数组合执行一次。然后,每个参数组合返回的值将在使用完全相同的参数组合调用函数时再次使用。
例如,如果您有一个函数: 例如,如果您有一个函数:
```Python ```Python
@lru_cache() @lru_cache
def say_hi(name: str, salutation: str = "Ms."): def say_hi(name: str, salutation: str = "Ms."):
return f"Hello {salutation} {name}" return f"Hello {salutation} {name}"
``` ```
@ -422,7 +422,7 @@ participant execute as Execute function
这样,它的行为几乎就像是一个全局变量。但是由于它使用了依赖项函数,因此我们可以轻松地进行测试时的覆盖。 这样,它的行为几乎就像是一个全局变量。但是由于它使用了依赖项函数,因此我们可以轻松地进行测试时的覆盖。
`@lru_cache()``functools` 的一部分,它是 Python 标准库的一部分,您可以在<a href="https://docs.python.org/3/library/functools.html#functools.lru_cache" class="external-link" target="_blank">Python 文档中了解有关 `@lru_cache()` 的更多信息</a> `@lru_cache``functools` 的一部分,它是 Python 标准库的一部分,您可以在<a href="https://docs.python.org/3/library/functools.html#functools.lru_cache" class="external-link" target="_blank">Python 文档中了解有关 `@lru_cache` 的更多信息</a>
## 小结 ## 小结
@ -430,4 +430,4 @@ participant execute as Execute function
* 通过使用依赖项,您可以简化测试。 * 通过使用依赖项,您可以简化测试。
* 您可以使用 `.env` 文件。 * 您可以使用 `.env` 文件。
* 使用 `@lru_cache()` 可以避免为每个请求重复读取 dotenv 文件,同时允许您在测试时进行覆盖。 * 使用 `@lru_cache` 可以避免为每个请求重复读取 dotenv 文件,同时允许您在测试时进行覆盖。

4
docs/zh/docs/async.md

@ -409,11 +409,11 @@ Starlette (和 **FastAPI**) 是基于 <a href="https://anyio.readthedocs.io/
### 依赖 ### 依赖
这同样适用于[依赖](/tutorial/dependencies/index.md){.internal-link target=_blank}。如果一个依赖是标准的 `def` 函数而不是 `async def`,它将被运行在外部线程池中。 这同样适用于[依赖](./tutorial/dependencies/index.md){.internal-link target=_blank}。如果一个依赖是标准的 `def` 函数而不是 `async def`,它将被运行在外部线程池中。
### 子依赖 ### 子依赖
你可以拥有多个相互依赖的依赖以及[子依赖](/tutorial/dependencies/sub-dependencies.md){.internal-link target=_blank} (作为函数的参数),它们中的一些可能是通过 `async def` 声明,也可能是通过 `def` 声明。它们仍然可以正常工作,这些通过 `def` 声明的函数将会在外部线程中调用(来自线程池),而不是"被等待"。 你可以拥有多个相互依赖的依赖以及[子依赖](./tutorial/dependencies/sub-dependencies.md){.internal-link target=_blank} (作为函数的参数),它们中的一些可能是通过 `async def` 声明,也可能是通过 `def` 声明。它们仍然可以正常工作,这些通过 `def` 声明的函数将会在外部线程中调用(来自线程池),而不是"被等待"。
### 其他函数 ### 其他函数

4
docs_src/custom_docs_ui/tutorial001.py

@ -14,8 +14,8 @@ async def custom_swagger_ui_html():
openapi_url=app.openapi_url, openapi_url=app.openapi_url,
title=app.title + " - Swagger UI", title=app.title + " - Swagger UI",
oauth2_redirect_url=app.swagger_ui_oauth2_redirect_url, oauth2_redirect_url=app.swagger_ui_oauth2_redirect_url,
swagger_js_url="https://unpkg.com/swagger-ui-dist@5/swagger-ui-bundle.js", swagger_js_url="https://unpkg.com/swagger-ui-dist@5.9.0/swagger-ui-bundle.js",
swagger_css_url="https://unpkg.com/swagger-ui-dist@5/swagger-ui.css", swagger_css_url="https://unpkg.com/swagger-ui-dist@5.9.0/swagger-ui.css",
) )

2
docs_src/header_params/tutorial002_an.py

@ -10,6 +10,6 @@ app = FastAPI()
async def read_items( async def read_items(
strange_header: Annotated[ strange_header: Annotated[
Union[str, None], Header(convert_underscores=False) Union[str, None], Header(convert_underscores=False)
] = None ] = None,
): ):
return {"strange_header": strange_header} return {"strange_header": strange_header}

2
docs_src/header_params/tutorial002_an_py39.py

@ -9,6 +9,6 @@ app = FastAPI()
async def read_items( async def read_items(
strange_header: Annotated[ strange_header: Annotated[
Union[str, None], Header(convert_underscores=False) Union[str, None], Header(convert_underscores=False)
] = None ] = None,
): ):
return {"strange_header": strange_header} return {"strange_header": strange_header}

2
docs_src/query_params_str_validations/tutorial004.py

@ -9,7 +9,7 @@ app = FastAPI()
async def read_items( async def read_items(
q: Union[str, None] = Query( q: Union[str, None] = Query(
default=None, min_length=3, max_length=50, pattern="^fixedquery$" default=None, min_length=3, max_length=50, pattern="^fixedquery$"
) ),
): ):
results = {"items": [{"item_id": "Foo"}, {"item_id": "Bar"}]} results = {"items": [{"item_id": "Foo"}, {"item_id": "Bar"}]}
if q: if q:

2
docs_src/query_params_str_validations/tutorial004_an.py

@ -10,7 +10,7 @@ app = FastAPI()
async def read_items( async def read_items(
q: Annotated[ q: Annotated[
Union[str, None], Query(min_length=3, max_length=50, pattern="^fixedquery$") Union[str, None], Query(min_length=3, max_length=50, pattern="^fixedquery$")
] = None ] = None,
): ):
results = {"items": [{"item_id": "Foo"}, {"item_id": "Bar"}]} results = {"items": [{"item_id": "Foo"}, {"item_id": "Bar"}]}
if q: if q:

2
docs_src/query_params_str_validations/tutorial004_an_py310.py

@ -9,7 +9,7 @@ app = FastAPI()
async def read_items( async def read_items(
q: Annotated[ q: Annotated[
str | None, Query(min_length=3, max_length=50, pattern="^fixedquery$") str | None, Query(min_length=3, max_length=50, pattern="^fixedquery$")
] = None ] = None,
): ):
results = {"items": [{"item_id": "Foo"}, {"item_id": "Bar"}]} results = {"items": [{"item_id": "Foo"}, {"item_id": "Bar"}]}
if q: if q:

2
docs_src/query_params_str_validations/tutorial004_an_py310_regex.py

@ -9,7 +9,7 @@ app = FastAPI()
async def read_items( async def read_items(
q: Annotated[ q: Annotated[
str | None, Query(min_length=3, max_length=50, regex="^fixedquery$") str | None, Query(min_length=3, max_length=50, regex="^fixedquery$")
] = None ] = None,
): ):
results = {"items": [{"item_id": "Foo"}, {"item_id": "Bar"}]} results = {"items": [{"item_id": "Foo"}, {"item_id": "Bar"}]}
if q: if q:

2
docs_src/query_params_str_validations/tutorial004_an_py39.py

@ -9,7 +9,7 @@ app = FastAPI()
async def read_items( async def read_items(
q: Annotated[ q: Annotated[
Union[str, None], Query(min_length=3, max_length=50, pattern="^fixedquery$") Union[str, None], Query(min_length=3, max_length=50, pattern="^fixedquery$")
] = None ] = None,
): ):
results = {"items": [{"item_id": "Foo"}, {"item_id": "Bar"}]} results = {"items": [{"item_id": "Foo"}, {"item_id": "Bar"}]}
if q: if q:

5
docs_src/query_params_str_validations/tutorial004_py310.py

@ -5,8 +5,9 @@ app = FastAPI()
@app.get("/items/") @app.get("/items/")
async def read_items( async def read_items(
q: str q: str | None = Query(
| None = Query(default=None, min_length=3, max_length=50, pattern="^fixedquery$") default=None, min_length=3, max_length=50, pattern="^fixedquery$"
),
): ):
results = {"items": [{"item_id": "Foo"}, {"item_id": "Bar"}]} results = {"items": [{"item_id": "Foo"}, {"item_id": "Bar"}]}
if q: if q:

2
docs_src/query_params_str_validations/tutorial008.py

@ -12,7 +12,7 @@ async def read_items(
title="Query string", title="Query string",
description="Query string for the items to search in the database that have a good match", description="Query string for the items to search in the database that have a good match",
min_length=3, min_length=3,
) ),
): ):
results = {"items": [{"item_id": "Foo"}, {"item_id": "Bar"}]} results = {"items": [{"item_id": "Foo"}, {"item_id": "Bar"}]}
if q: if q:

2
docs_src/query_params_str_validations/tutorial008_an.py

@ -15,7 +15,7 @@ async def read_items(
description="Query string for the items to search in the database that have a good match", description="Query string for the items to search in the database that have a good match",
min_length=3, min_length=3,
), ),
] = None ] = None,
): ):
results = {"items": [{"item_id": "Foo"}, {"item_id": "Bar"}]} results = {"items": [{"item_id": "Foo"}, {"item_id": "Bar"}]}
if q: if q:

2
docs_src/query_params_str_validations/tutorial008_an_py310.py

@ -14,7 +14,7 @@ async def read_items(
description="Query string for the items to search in the database that have a good match", description="Query string for the items to search in the database that have a good match",
min_length=3, min_length=3,
), ),
] = None ] = None,
): ):
results = {"items": [{"item_id": "Foo"}, {"item_id": "Bar"}]} results = {"items": [{"item_id": "Foo"}, {"item_id": "Bar"}]}
if q: if q:

2
docs_src/query_params_str_validations/tutorial008_an_py39.py

@ -14,7 +14,7 @@ async def read_items(
description="Query string for the items to search in the database that have a good match", description="Query string for the items to search in the database that have a good match",
min_length=3, min_length=3,
), ),
] = None ] = None,
): ):
results = {"items": [{"item_id": "Foo"}, {"item_id": "Bar"}]} results = {"items": [{"item_id": "Foo"}, {"item_id": "Bar"}]}
if q: if q:

5
docs_src/query_params_str_validations/tutorial008_py310.py

@ -5,13 +5,12 @@ app = FastAPI()
@app.get("/items/") @app.get("/items/")
async def read_items( async def read_items(
q: str q: str | None = Query(
| None = Query(
default=None, default=None,
title="Query string", title="Query string",
description="Query string for the items to search in the database that have a good match", description="Query string for the items to search in the database that have a good match",
min_length=3, min_length=3,
) ),
): ):
results = {"items": [{"item_id": "Foo"}, {"item_id": "Bar"}]} results = {"items": [{"item_id": "Foo"}, {"item_id": "Bar"}]}
if q: if q:

2
docs_src/query_params_str_validations/tutorial010.py

@ -16,7 +16,7 @@ async def read_items(
max_length=50, max_length=50,
pattern="^fixedquery$", pattern="^fixedquery$",
deprecated=True, deprecated=True,
) ),
): ):
results = {"items": [{"item_id": "Foo"}, {"item_id": "Bar"}]} results = {"items": [{"item_id": "Foo"}, {"item_id": "Bar"}]}
if q: if q:

2
docs_src/query_params_str_validations/tutorial010_an.py

@ -19,7 +19,7 @@ async def read_items(
pattern="^fixedquery$", pattern="^fixedquery$",
deprecated=True, deprecated=True,
), ),
] = None ] = None,
): ):
results = {"items": [{"item_id": "Foo"}, {"item_id": "Bar"}]} results = {"items": [{"item_id": "Foo"}, {"item_id": "Bar"}]}
if q: if q:

2
docs_src/query_params_str_validations/tutorial010_an_py310.py

@ -18,7 +18,7 @@ async def read_items(
pattern="^fixedquery$", pattern="^fixedquery$",
deprecated=True, deprecated=True,
), ),
] = None ] = None,
): ):
results = {"items": [{"item_id": "Foo"}, {"item_id": "Bar"}]} results = {"items": [{"item_id": "Foo"}, {"item_id": "Bar"}]}
if q: if q:

2
docs_src/query_params_str_validations/tutorial010_an_py39.py

@ -18,7 +18,7 @@ async def read_items(
pattern="^fixedquery$", pattern="^fixedquery$",
deprecated=True, deprecated=True,
), ),
] = None ] = None,
): ):
results = {"items": [{"item_id": "Foo"}, {"item_id": "Bar"}]} results = {"items": [{"item_id": "Foo"}, {"item_id": "Bar"}]}
if q: if q:

5
docs_src/query_params_str_validations/tutorial010_py310.py

@ -5,8 +5,7 @@ app = FastAPI()
@app.get("/items/") @app.get("/items/")
async def read_items( async def read_items(
q: str q: str | None = Query(
| None = Query(
default=None, default=None,
alias="item-query", alias="item-query",
title="Query string", title="Query string",
@ -15,7 +14,7 @@ async def read_items(
max_length=50, max_length=50,
pattern="^fixedquery$", pattern="^fixedquery$",
deprecated=True, deprecated=True,
) ),
): ):
results = {"items": [{"item_id": "Foo"}, {"item_id": "Bar"}]} results = {"items": [{"item_id": "Foo"}, {"item_id": "Bar"}]}
if q: if q:

2
docs_src/settings/app02/main.py

@ -7,7 +7,7 @@ from .config import Settings
app = FastAPI() app = FastAPI()
@lru_cache() @lru_cache
def get_settings(): def get_settings():
return Settings() return Settings()

2
docs_src/settings/app02_an/main.py

@ -8,7 +8,7 @@ from .config import Settings
app = FastAPI() app = FastAPI()
@lru_cache() @lru_cache
def get_settings(): def get_settings():
return Settings() return Settings()

2
docs_src/settings/app02_an_py39/main.py

@ -8,7 +8,7 @@ from .config import Settings
app = FastAPI() app = FastAPI()
@lru_cache() @lru_cache
def get_settings(): def get_settings():
return Settings() return Settings()

2
docs_src/settings/app03/main.py

@ -7,7 +7,7 @@ from . import config
app = FastAPI() app = FastAPI()
@lru_cache() @lru_cache
def get_settings(): def get_settings():
return config.Settings() return config.Settings()

2
docs_src/settings/app03_an/main.py

@ -8,7 +8,7 @@ from . import config
app = FastAPI() app = FastAPI()
@lru_cache() @lru_cache
def get_settings(): def get_settings():
return config.Settings() return config.Settings()

2
docs_src/settings/app03_an_py39/main.py

@ -8,7 +8,7 @@ from . import config
app = FastAPI() app = FastAPI()
@lru_cache() @lru_cache
def get_settings(): def get_settings():
return config.Settings() return config.Settings()

2
fastapi/__init__.py

@ -1,6 +1,6 @@
"""FastAPI framework, high performance, easy to learn, fast to code, ready for production""" """FastAPI framework, high performance, easy to learn, fast to code, ready for production"""
__version__ = "0.104.0" __version__ = "0.104.1"
from starlette import status as status from starlette import status as status

6
fastapi/_compat.py

@ -197,9 +197,9 @@ if PYDANTIC_V2:
if "$ref" not in json_schema: if "$ref" not in json_schema:
# TODO remove when deprecating Pydantic v1 # TODO remove when deprecating Pydantic v1
# Ref: https://github.com/pydantic/pydantic/blob/d61792cc42c80b13b23e3ffa74bc37ec7c77f7d1/pydantic/schema.py#L207 # Ref: https://github.com/pydantic/pydantic/blob/d61792cc42c80b13b23e3ffa74bc37ec7c77f7d1/pydantic/schema.py#L207
json_schema[ json_schema["title"] = (
"title" field.field_info.title or field.alias.title().replace("_", " ")
] = field.field_info.title or field.alias.title().replace("_", " ") )
return json_schema return json_schema
def get_compat_model_name_map(fields: List[ModelField]) -> ModelNameMap: def get_compat_model_name_map(fields: List[ModelField]) -> ModelNameMap:

6
fastapi/applications.py

@ -896,9 +896,7 @@ class FastAPI(Starlette):
[FastAPI docs for OpenAPI Webhooks](https://fastapi.tiangolo.com/advanced/openapi-webhooks/). [FastAPI docs for OpenAPI Webhooks](https://fastapi.tiangolo.com/advanced/openapi-webhooks/).
""" """
), ),
] = ( ] = webhooks or routing.APIRouter()
webhooks or routing.APIRouter()
)
self.root_path = root_path or openapi_prefix self.root_path = root_path or openapi_prefix
self.state: Annotated[ self.state: Annotated[
State, State,
@ -951,7 +949,7 @@ class FastAPI(Starlette):
) )
self.exception_handlers: Dict[ self.exception_handlers: Dict[
Any, Callable[[Request, Any], Union[Response, Awaitable[Response]]] Any, Callable[[Request, Any], Union[Response, Awaitable[Response]]]
] = ({} if exception_handlers is None else dict(exception_handlers)) ] = {} if exception_handlers is None else dict(exception_handlers)
self.exception_handlers.setdefault(HTTPException, http_exception_handler) self.exception_handlers.setdefault(HTTPException, http_exception_handler)
self.exception_handlers.setdefault( self.exception_handlers.setdefault(
RequestValidationError, request_validation_exception_handler RequestValidationError, request_validation_exception_handler

4
fastapi/openapi/docs.py

@ -53,7 +53,7 @@ def get_swagger_ui_html(
It is normally set to a CDN URL. It is normally set to a CDN URL.
""" """
), ),
] = "https://cdn.jsdelivr.net/npm/swagger-ui-dist@5/swagger-ui-bundle.js", ] = "https://cdn.jsdelivr.net/npm/swagger-ui-dist@5.9.0/swagger-ui-bundle.js",
swagger_css_url: Annotated[ swagger_css_url: Annotated[
str, str,
Doc( Doc(
@ -63,7 +63,7 @@ def get_swagger_ui_html(
It is normally set to a CDN URL. It is normally set to a CDN URL.
""" """
), ),
] = "https://cdn.jsdelivr.net/npm/swagger-ui-dist@5/swagger-ui.css", ] = "https://cdn.jsdelivr.net/npm/swagger-ui-dist@5.9.0/swagger-ui.css",
swagger_favicon_url: Annotated[ swagger_favicon_url: Annotated[
str, str,
Doc( Doc(

2
fastapi/security/http.py

@ -210,7 +210,7 @@ class HTTPBasic(HTTPBase):
try: try:
data = b64decode(param).decode("ascii") data = b64decode(param).decode("ascii")
except (ValueError, UnicodeDecodeError, binascii.Error): except (ValueError, UnicodeDecodeError, binascii.Error):
raise invalid_user_credentials_exc raise invalid_user_credentials_exc # noqa: B904
username, separator, password = data.partition(":") username, separator, password = data.partition(":")
if not separator: if not separator:
raise invalid_user_credentials_exc raise invalid_user_credentials_exc

4
fastapi/security/oauth2.py

@ -626,9 +626,7 @@ class SecurityScopes:
The list of all the scopes required by dependencies. The list of all the scopes required by dependencies.
""" """
), ),
] = ( ] = scopes or []
scopes or []
)
self.scope_str: Annotated[ self.scope_str: Annotated[
str, str,
Doc( Doc(

3
fastapi/utils.py

@ -152,7 +152,8 @@ def create_cloned_field(
] ]
if field.key_field: # type: ignore[attr-defined] if field.key_field: # type: ignore[attr-defined]
new_field.key_field = create_cloned_field( # type: ignore[attr-defined] new_field.key_field = create_cloned_field( # type: ignore[attr-defined]
field.key_field, cloned_types=cloned_types # type: ignore[attr-defined] field.key_field, # type: ignore[attr-defined]
cloned_types=cloned_types,
) )
new_field.validators = field.validators # type: ignore[attr-defined] new_field.validators = field.validators # type: ignore[attr-defined]
new_field.pre_validators = field.pre_validators # type: ignore[attr-defined] new_field.pre_validators = field.pre_validators # type: ignore[attr-defined]

18
pyproject.toml

@ -130,11 +130,13 @@ select = [
"I", # isort "I", # isort
"C", # flake8-comprehensions "C", # flake8-comprehensions
"B", # flake8-bugbear "B", # flake8-bugbear
"UP", # pyupgrade
] ]
ignore = [ ignore = [
"E501", # line too long, handled by black "E501", # line too long, handled by black
"B008", # do not perform function calls in argument defaults "B008", # do not perform function calls in argument defaults
"C901", # too complex "C901", # too complex
"W191", # indentation contains tabs
] ]
[tool.ruff.per-file-ignores] [tool.ruff.per-file-ignores]
@ -154,6 +156,22 @@ ignore = [
"docs_src/query_params_str_validations/tutorial012_an_py39.py" = ["B006"] "docs_src/query_params_str_validations/tutorial012_an_py39.py" = ["B006"]
"docs_src/query_params_str_validations/tutorial013_an.py" = ["B006"] "docs_src/query_params_str_validations/tutorial013_an.py" = ["B006"]
"docs_src/query_params_str_validations/tutorial013_an_py39.py" = ["B006"] "docs_src/query_params_str_validations/tutorial013_an_py39.py" = ["B006"]
"docs_src/security/tutorial004.py" = ["B904"]
"docs_src/security/tutorial004_an.py" = ["B904"]
"docs_src/security/tutorial004_an_py310.py" = ["B904"]
"docs_src/security/tutorial004_an_py39.py" = ["B904"]
"docs_src/security/tutorial004_py310.py" = ["B904"]
"docs_src/security/tutorial005.py" = ["B904"]
"docs_src/security/tutorial005_an.py" = ["B904"]
"docs_src/security/tutorial005_an_py310.py" = ["B904"]
"docs_src/security/tutorial005_an_py39.py" = ["B904"]
"docs_src/security/tutorial005_py310.py" = ["B904"]
"docs_src/security/tutorial005_py39.py" = ["B904"]
[tool.ruff.isort] [tool.ruff.isort]
known-third-party = ["fastapi", "pydantic", "starlette"] known-third-party = ["fastapi", "pydantic", "starlette"]
[tool.ruff.pyupgrade]
# Preserve types, even if a file imports `from __future__ import annotations`.
keep-runtime-typing = true

1
requirements-docs-tests.txt

@ -1,3 +1,2 @@
# For mkdocstrings and tests # For mkdocstrings and tests
httpx >=0.23.0,<0.25.0 httpx >=0.23.0,<0.25.0
black == 23.3.0

6
requirements-docs.txt

@ -1,6 +1,6 @@
-e . -e .
-r requirements-docs-tests.txt -r requirements-docs-tests.txt
mkdocs-material==9.1.21 mkdocs-material==9.4.7
mdx-include >=1.4.1,<2.0.0 mdx-include >=1.4.1,<2.0.0
mkdocs-markdownextradata-plugin >=0.1.7,<0.3.0 mkdocs-markdownextradata-plugin >=0.1.7,<0.3.0
mkdocs-redirects>=1.2.1,<1.3.0 mkdocs-redirects>=1.2.1,<1.3.0
@ -10,8 +10,10 @@ pyyaml >=5.3.1,<7.0.0
# For Material for MkDocs, Chinese search # For Material for MkDocs, Chinese search
jieba==0.42.1 jieba==0.42.1
# For image processing by Material for MkDocs # For image processing by Material for MkDocs
pillow==9.5.0 pillow==10.1.0
# For image processing by Material for MkDocs # For image processing by Material for MkDocs
cairosvg==2.7.0 cairosvg==2.7.0
mkdocstrings[python]==0.23.0 mkdocstrings[python]==0.23.0
griffe-typingdoc==0.2.2 griffe-typingdoc==0.2.2
# For griffe, it formats with black
black==23.3.0

2
requirements-tests.txt

@ -4,7 +4,7 @@ pydantic-settings >=2.0.0
pytest >=7.1.3,<8.0.0 pytest >=7.1.3,<8.0.0
coverage[toml] >= 6.5.0,< 8.0 coverage[toml] >= 6.5.0,< 8.0
mypy ==1.4.1 mypy ==1.4.1
ruff ==0.0.275 ruff ==0.1.2
email_validator >=1.1.1,<3.0.0 email_validator >=1.1.1,<3.0.0
dirty-equals ==0.6.0 dirty-equals ==0.6.0
# TODO: once removing databases from tutorial, upgrade SQLAlchemy # TODO: once removing databases from tutorial, upgrade SQLAlchemy

6
scripts/docs.py

@ -36,7 +36,7 @@ site_path = Path("site").absolute()
build_site_path = Path("site_build").absolute() build_site_path = Path("site_build").absolute()
@lru_cache() @lru_cache
def is_mkdocs_insiders() -> bool: def is_mkdocs_insiders() -> bool:
version = metadata.version("mkdocs-material") version = metadata.version("mkdocs-material")
return "insiders" in version return "insiders" in version
@ -104,7 +104,7 @@ def new_lang(lang: str = typer.Argument(..., callback=lang_callback)):
def build_lang( def build_lang(
lang: str = typer.Argument( lang: str = typer.Argument(
..., callback=lang_callback, autocompletion=complete_existing_lang ..., callback=lang_callback, autocompletion=complete_existing_lang
) ),
) -> None: ) -> None:
""" """
Build the docs for a language. Build the docs for a language.
@ -251,7 +251,7 @@ def serve() -> None:
def live( def live(
lang: str = typer.Argument( lang: str = typer.Argument(
None, callback=lang_callback, autocompletion=complete_existing_lang None, callback=lang_callback, autocompletion=complete_existing_lang
) ),
) -> None: ) -> None:
""" """
Serve with livereload a docs site for a specific language. Serve with livereload a docs site for a specific language.

2
scripts/format.sh

@ -2,4 +2,4 @@
set -x set -x
ruff fastapi tests docs_src scripts --fix ruff fastapi tests docs_src scripts --fix
black fastapi tests docs_src scripts ruff format fastapi tests docs_src scripts

2
scripts/lint.sh

@ -5,4 +5,4 @@ set -x
mypy fastapi mypy fastapi
ruff fastapi tests docs_src scripts ruff fastapi tests docs_src scripts
black fastapi tests --check ruff format fastapi tests --check

4
scripts/mkdocs_hooks.py

@ -14,14 +14,14 @@ non_traslated_sections = [
] ]
@lru_cache() @lru_cache
def get_missing_translation_content(docs_dir: str) -> str: def get_missing_translation_content(docs_dir: str) -> str:
docs_dir_path = Path(docs_dir) docs_dir_path = Path(docs_dir)
missing_translation_path = docs_dir_path.parent.parent / "missing-translation.md" missing_translation_path = docs_dir_path.parent.parent / "missing-translation.md"
return missing_translation_path.read_text(encoding="utf-8") return missing_translation_path.read_text(encoding="utf-8")
@lru_cache() @lru_cache
def get_mkdocs_material_langs() -> List[str]: def get_mkdocs_material_langs() -> List[str]:
material_path = Path(material.__file__).parent material_path = Path(material.__file__).parent
material_langs_path = material_path / "templates" / "partials" / "languages" material_langs_path = material_path / "templates" / "partials" / "languages"

2
tests/test_openapi_examples.py

@ -28,7 +28,7 @@ def examples(
"value": {"data": "Data in Body examples, example2"}, "value": {"data": "Data in Body examples, example2"},
}, },
}, },
) ),
): ):
return item return item

4
tests/test_schema_extra_examples.py

@ -40,7 +40,7 @@ def create_app():
{"data": "Data in Body examples, example1"}, {"data": "Data in Body examples, example1"},
{"data": "Data in Body examples, example2"}, {"data": "Data in Body examples, example2"},
], ],
) ),
): ):
return item return item
@ -54,7 +54,7 @@ def create_app():
{"data": "examples example_examples 1"}, {"data": "examples example_examples 1"},
{"data": "examples example_examples 2"}, {"data": "examples example_examples 2"},
], ],
) ),
): ):
return item return item

6
tests/test_tutorial/test_custom_docs_ui/test_tutorial001.py

@ -20,8 +20,10 @@ def client():
def test_swagger_ui_html(client: TestClient): def test_swagger_ui_html(client: TestClient):
response = client.get("/docs") response = client.get("/docs")
assert response.status_code == 200, response.text assert response.status_code == 200, response.text
assert "https://unpkg.com/swagger-ui-dist@5/swagger-ui-bundle.js" in response.text assert (
assert "https://unpkg.com/swagger-ui-dist@5/swagger-ui.css" in response.text "https://unpkg.com/[email protected]/swagger-ui-bundle.js" in response.text
)
assert "https://unpkg.com/[email protected]/swagger-ui.css" in response.text
def test_swagger_ui_oauth2_redirect_html(client: TestClient): def test_swagger_ui_oauth2_redirect_html(client: TestClient):

Loading…
Cancel
Save