Browse Source

Merge branch 'master' into fix/issue-10127-response-dependency-annotation

pull/14794/head
Motov Yurii 5 months ago
committed by GitHub
parent
commit
3724bfff80
No known key found for this signature in database GPG Key ID: B5690EEEBB952194
  1. 32
      .github/workflows/test.yml
  2. 7
      .pre-commit-config.yaml
  3. 18
      README.md
  4. 18
      docs/en/data/contributors.yml
  5. 336
      docs/en/data/topic_repos.yml
  6. 114
      docs/en/data/translation_reviewers.yml
  7. 43
      docs/en/data/translators.yml
  8. 20
      docs/en/docs/advanced/wsgi.md
  9. 6
      docs/en/docs/contributing.md
  10. 4
      docs/en/docs/deployment/docker.md
  11. 18
      docs/en/docs/index.md
  12. 8
      docs/en/docs/reference/middleware.md
  13. 2
      docs/en/docs/reference/request.md
  14. 2
      docs/en/docs/reference/response.md
  15. 2
      docs/en/docs/reference/responses.md
  16. 2
      docs/en/docs/reference/security/index.md
  17. 24
      docs/en/docs/reference/websockets.md
  18. 37
      docs/en/docs/release-notes.md
  19. 11
      docs/en/docs/translation-banner.md
  20. 7
      docs/en/docs/tutorial/body-multiple-params.md
  21. 4
      docs/en/docs/tutorial/path-operation-configuration.md
  22. 11
      docs/ru/docs/translation-banner.md
  23. 80
      docs/uk/docs/alternatives.md
  24. 108
      docs/uk/docs/fastapi-cli.md
  25. 138
      docs/uk/docs/features.md
  26. 6
      docs_src/app_testing/app_b_an_py310/main.py
  27. 6
      docs_src/app_testing/app_b_an_py39/main.py
  28. 6
      docs_src/app_testing/app_b_py310/main.py
  29. 6
      docs_src/app_testing/app_b_py39/main.py
  30. 4
      docs_src/body_updates/tutorial002_py310.py
  31. 4
      docs_src/body_updates/tutorial002_py39.py
  32. 2
      docs_src/metadata/tutorial001_1_py39.py
  33. 4
      docs_src/path_operation_advanced_configuration/tutorial004_py310.py
  34. 4
      docs_src/path_operation_advanced_configuration/tutorial004_py39.py
  35. 4
      docs_src/path_operation_configuration/tutorial001_py310.py
  36. 4
      docs_src/path_operation_configuration/tutorial001_py39.py
  37. 4
      docs_src/path_operation_configuration/tutorial002_py310.py
  38. 4
      docs_src/path_operation_configuration/tutorial002_py39.py
  39. 3
      docs_src/path_operation_configuration/tutorial003_py310.py
  40. 3
      docs_src/path_operation_configuration/tutorial003_py39.py
  41. 4
      docs_src/path_operation_configuration/tutorial004_py310.py
  42. 4
      docs_src/path_operation_configuration/tutorial004_py39.py
  43. 3
      docs_src/path_operation_configuration/tutorial005_py310.py
  44. 3
      docs_src/path_operation_configuration/tutorial005_py39.py
  45. 4
      docs_src/security/tutorial004_an_py310.py
  46. 4
      docs_src/security/tutorial004_an_py39.py
  47. 4
      docs_src/security/tutorial004_py310.py
  48. 4
      docs_src/security/tutorial004_py39.py
  49. 4
      docs_src/security/tutorial005_an_py310.py
  50. 4
      docs_src/security/tutorial005_an_py39.py
  51. 4
      docs_src/security/tutorial005_py310.py
  52. 4
      docs_src/security/tutorial005_py39.py
  53. 2
      docs_src/wsgi/tutorial001_py39.py
  54. 4
      fastapi/_compat/shared.py
  55. 8
      fastapi/_compat/v2.py
  56. 7
      fastapi/applications.py
  57. 13
      fastapi/dependencies/utils.py
  58. 4
      fastapi/encoders.py
  59. 10
      fastapi/exceptions.py
  60. 4
      fastapi/middleware/wsgi.py
  61. 31
      fastapi/openapi/docs.py
  62. 3
      fastapi/openapi/utils.py
  63. 94
      fastapi/param_functions.py
  64. 30
      fastapi/security/oauth2.py
  65. 2
      fastapi/security/utils.py
  66. 2
      fastapi/types.py
  67. 2
      fastapi/utils.py
  68. 12
      pyproject.toml
  69. 30
      scripts/mkdocs_hooks.py
  70. 28
      scripts/translate.py
  71. 123
      tests/test_additional_responses_union_duplicate_anyof.py
  72. 20
      tests/test_invalid_sequence_param.py
  73. 6
      tests/test_security_http_base.py
  74. 6
      tests/test_security_oauth2_authorization_code_bearer.py
  75. 30
      tests/test_stringified_annotation_dependency_py314.py
  76. 10
      tests/test_tutorial/test_dependencies/test_tutorial008.py
  77. 2
      tests/test_tutorial/test_metadata/test_tutorial001_1.py
  78. 4
      tests/utils.py
  79. 114
      uv.lock

32
.github/workflows/test.yml

@ -16,7 +16,35 @@ env:
UV_NO_SYNC: true
jobs:
changes:
runs-on: ubuntu-latest
# Required permissions
permissions:
pull-requests: read
# Set job outputs to values from filter step
outputs:
src: ${{ steps.filter.outputs.src }}
steps:
- uses: actions/checkout@v6
# For pull requests it's not necessary to checkout the code but for the main branch it is
- uses: dorny/paths-filter@v3
id: filter
with:
filters: |
src:
- .github/workflows/test.yml
- docs_src/**
- fastapi/**
- scripts/**
- tests/**
- .python-version
- pyproject.toml
- uv.lock
test:
needs:
- changes
if: needs.changes.outputs.src == 'true'
strategy:
matrix:
os: [ windows-latest, macos-latest ]
@ -91,7 +119,8 @@ jobs:
include-hidden-files: true
coverage-combine:
needs: [test]
needs:
- test
runs-on: ubuntu-latest
steps:
- name: Dump GitHub context
@ -143,3 +172,4 @@ jobs:
uses: re-actors/alls-green@release/v1
with:
jobs: ${{ toJSON(needs) }}
allowed-skips: coverage-combine,test

7
.pre-commit-config.yaml

@ -30,6 +30,13 @@ repos:
language: unsupported
types: [python]
- id: local-mypy
name: mypy check
entry: uv run mypy fastapi
require_serial: true
language: unsupported
pass_filenames: false
- id: add-permalinks-pages
language: unsupported
name: add-permalinks-pages

18
README.md

@ -164,8 +164,6 @@ $ pip install "fastapi[standard]"
Create a file `main.py` with:
```Python
from typing import Union
from fastapi import FastAPI
app = FastAPI()
@ -177,7 +175,7 @@ def read_root():
@app.get("/items/{item_id}")
def read_item(item_id: int, q: Union[str, None] = None):
def read_item(item_id: int, q: str | None = None):
return {"item_id": item_id, "q": q}
```
@ -186,9 +184,7 @@ def read_item(item_id: int, q: Union[str, None] = None):
If your code uses `async` / `await`, use `async def`:
```Python hl_lines="9 14"
from typing import Union
```Python hl_lines="7 12"
from fastapi import FastAPI
app = FastAPI()
@ -200,7 +196,7 @@ async def read_root():
@app.get("/items/{item_id}")
async def read_item(item_id: int, q: Union[str, None] = None):
async def read_item(item_id: int, q: str | None = None):
return {"item_id": item_id, "q": q}
```
@ -291,9 +287,7 @@ Now modify the file `main.py` to receive a body from a `PUT` request.
Declare the body using standard Python types, thanks to Pydantic.
```Python hl_lines="4 9-12 25-27"
from typing import Union
```Python hl_lines="2 7-10 23-25"
from fastapi import FastAPI
from pydantic import BaseModel
@ -303,7 +297,7 @@ app = FastAPI()
class Item(BaseModel):
name: str
price: float
is_offer: Union[bool, None] = None
is_offer: bool | None = None
@app.get("/")
@ -312,7 +306,7 @@ def read_root():
@app.get("/items/{item_id}")
def read_item(item_id: int, q: Union[str, None] = None):
def read_item(item_id: int, q: str | None = None):
return {"item_id": item_id, "q": q}

18
docs/en/data/contributors.yml

@ -1,17 +1,17 @@
tiangolo:
login: tiangolo
count: 857
count: 871
avatarUrl: https://avatars.githubusercontent.com/u/1326112?u=cb5d06e73a9e1998141b1641aa88e443c6717651&v=4
url: https://github.com/tiangolo
dependabot:
login: dependabot
count: 130
count: 133
avatarUrl: https://avatars.githubusercontent.com/in/29110?v=4
url: https://github.com/apps/dependabot
alejsdev:
login: alejsdev
count: 53
avatarUrl: https://avatars.githubusercontent.com/u/90076947?u=85ceac49fb87138aebe8d663912e359447329090&v=4
avatarUrl: https://avatars.githubusercontent.com/u/90076947?u=0facffe3abf87f57a1f05fa773d1119cc5c2f6a5&v=4
url: https://github.com/alejsdev
pre-commit-ci:
login: pre-commit-ci
@ -20,8 +20,8 @@ pre-commit-ci:
url: https://github.com/apps/pre-commit-ci
YuriiMotov:
login: YuriiMotov
count: 36
avatarUrl: https://avatars.githubusercontent.com/u/109919500?u=b9b13d598dddfab529a52d264df80a900bfe7060&v=4
count: 38
avatarUrl: https://avatars.githubusercontent.com/u/109919500?u=bc48be95c429989224786106b027f3c5e40cc354&v=4
url: https://github.com/YuriiMotov
github-actions:
login: github-actions
@ -40,7 +40,7 @@ dmontagu:
url: https://github.com/dmontagu
svlandeg:
login: svlandeg
count: 16
count: 17
avatarUrl: https://avatars.githubusercontent.com/u/8796347?u=556c97650c27021911b0b9447ec55e75987b0e8a&v=4
url: https://github.com/svlandeg
nilslindemann:
@ -126,7 +126,7 @@ hitrust:
ShahriyarR:
login: ShahriyarR
count: 4
avatarUrl: https://avatars.githubusercontent.com/u/3852029?u=631b2ae59360ab380c524b32bc3d245aff1165af&v=4
avatarUrl: https://avatars.githubusercontent.com/u/3852029?u=2dc6402d9053ee53f7afc407089cbab21c68f21d&v=4
url: https://github.com/ShahriyarR
adriangb:
login: adriangb
@ -266,7 +266,7 @@ Nimitha-jagadeesha:
lucaromagnoli:
login: lucaromagnoli
count: 3
avatarUrl: https://avatars.githubusercontent.com/u/38782977?u=15df02e806a2293af40ac619fba11dbe3c0c4fd4&v=4
avatarUrl: https://avatars.githubusercontent.com/u/38782977?u=a09a2e916625fa035f9dfa25ebc58e07aac8ec36&v=4
url: https://github.com/lucaromagnoli
salmantec:
login: salmantec
@ -521,7 +521,7 @@ s111d:
estebanx64:
login: estebanx64
count: 2
avatarUrl: https://avatars.githubusercontent.com/u/10840422?u=1900887aeed268699e5ea6f3fb7db614f7b77cd3&v=4
avatarUrl: https://avatars.githubusercontent.com/u/10840422?u=812422ae5d6a4bc5ff331c901fc54f9ab3cecf5c&v=4
url: https://github.com/estebanx64
ndimares:
login: ndimares

336
docs/en/data/topic_repos.yml

@ -1,176 +1,181 @@
- name: full-stack-fastapi-template
html_url: https://github.com/fastapi/full-stack-fastapi-template
stars: 40334
stars: 41312
owner_login: fastapi
owner_html_url: https://github.com/fastapi
- name: Hello-Python
html_url: https://github.com/mouredev/Hello-Python
stars: 33628
stars: 34206
owner_login: mouredev
owner_html_url: https://github.com/mouredev
- name: serve
html_url: https://github.com/jina-ai/serve
stars: 21817
stars: 21832
owner_login: jina-ai
owner_html_url: https://github.com/jina-ai
- name: HivisionIDPhotos
html_url: https://github.com/Zeyi-Lin/HivisionIDPhotos
stars: 20409
stars: 20661
owner_login: Zeyi-Lin
owner_html_url: https://github.com/Zeyi-Lin
- name: sqlmodel
html_url: https://github.com/fastapi/sqlmodel
stars: 17415
stars: 17567
owner_login: fastapi
owner_html_url: https://github.com/fastapi
- name: fastapi-best-practices
html_url: https://github.com/zhanymkanov/fastapi-best-practices
stars: 15776
stars: 16291
owner_login: zhanymkanov
owner_html_url: https://github.com/zhanymkanov
- name: Douyin_TikTok_Download_API
html_url: https://github.com/Evil0ctal/Douyin_TikTok_Download_API
stars: 15588
stars: 16132
owner_login: Evil0ctal
owner_html_url: https://github.com/Evil0ctal
- name: machine-learning-zoomcamp
html_url: https://github.com/DataTalksClub/machine-learning-zoomcamp
stars: 12447
owner_login: DataTalksClub
owner_html_url: https://github.com/DataTalksClub
- name: SurfSense
html_url: https://github.com/MODSetter/SurfSense
stars: 12128
stars: 12723
owner_login: MODSetter
owner_html_url: https://github.com/MODSetter
- name: machine-learning-zoomcamp
html_url: https://github.com/DataTalksClub/machine-learning-zoomcamp
stars: 12575
owner_login: DataTalksClub
owner_html_url: https://github.com/DataTalksClub
- name: fastapi_mcp
html_url: https://github.com/tadata-org/fastapi_mcp
stars: 11326
stars: 11478
owner_login: tadata-org
owner_html_url: https://github.com/tadata-org
- name: awesome-fastapi
html_url: https://github.com/mjhea0/awesome-fastapi
stars: 10901
stars: 11018
owner_login: mjhea0
owner_html_url: https://github.com/mjhea0
- name: XHS-Downloader
html_url: https://github.com/JoeanAmier/XHS-Downloader
stars: 9584
stars: 9938
owner_login: JoeanAmier
owner_html_url: https://github.com/JoeanAmier
- name: polar
html_url: https://github.com/polarsource/polar
stars: 8951
stars: 9348
owner_login: polarsource
owner_html_url: https://github.com/polarsource
- name: FastUI
html_url: https://github.com/pydantic/FastUI
stars: 8934
stars: 8949
owner_login: pydantic
owner_html_url: https://github.com/pydantic
- name: FileCodeBox
html_url: https://github.com/vastsa/FileCodeBox
stars: 7934
stars: 8060
owner_login: vastsa
owner_html_url: https://github.com/vastsa
- name: nonebot2
html_url: https://github.com/nonebot/nonebot2
stars: 7248
stars: 7311
owner_login: nonebot
owner_html_url: https://github.com/nonebot
- name: hatchet
html_url: https://github.com/hatchet-dev/hatchet
stars: 6392
stars: 6479
owner_login: hatchet-dev
owner_html_url: https://github.com/hatchet-dev
- name: fastapi-users
html_url: https://github.com/fastapi-users/fastapi-users
stars: 5899
stars: 5970
owner_login: fastapi-users
owner_html_url: https://github.com/fastapi-users
- name: serge
html_url: https://github.com/serge-chat/serge
stars: 5754
stars: 5751
owner_login: serge-chat
owner_html_url: https://github.com/serge-chat
- name: strawberry
html_url: https://github.com/strawberry-graphql/strawberry
stars: 4577
stars: 4598
owner_login: strawberry-graphql
owner_html_url: https://github.com/strawberry-graphql
- name: devpush
html_url: https://github.com/hunvreus/devpush
stars: 4407
owner_login: hunvreus
owner_html_url: https://github.com/hunvreus
- name: Kokoro-FastAPI
html_url: https://github.com/remsky/Kokoro-FastAPI
stars: 4359
owner_login: remsky
owner_html_url: https://github.com/remsky
- name: poem
html_url: https://github.com/poem-web/poem
stars: 4303
stars: 4337
owner_login: poem-web
owner_html_url: https://github.com/poem-web
- name: chatgpt-web-share
html_url: https://github.com/chatpire/chatgpt-web-share
stars: 4287
stars: 4279
owner_login: chatpire
owner_html_url: https://github.com/chatpire
- name: dynaconf
html_url: https://github.com/dynaconf/dynaconf
stars: 4221
stars: 4244
owner_login: dynaconf
owner_html_url: https://github.com/dynaconf
- name: Kokoro-FastAPI
html_url: https://github.com/remsky/Kokoro-FastAPI
stars: 4181
owner_login: remsky
owner_html_url: https://github.com/remsky
- name: Yuxi-Know
html_url: https://github.com/xerrors/Yuxi-Know
stars: 4154
owner_login: xerrors
owner_html_url: https://github.com/xerrors
- name: atrilabs-engine
html_url: https://github.com/Atri-Labs/atrilabs-engine
stars: 4090
stars: 4086
owner_login: Atri-Labs
owner_html_url: https://github.com/Atri-Labs
- name: devpush
html_url: https://github.com/hunvreus/devpush
stars: 4037
owner_login: hunvreus
owner_html_url: https://github.com/hunvreus
- name: logfire
html_url: https://github.com/pydantic/logfire
stars: 3896
stars: 3975
owner_login: pydantic
owner_html_url: https://github.com/pydantic
- name: LitServe
html_url: https://github.com/Lightning-AI/LitServe
stars: 3756
stars: 3797
owner_login: Lightning-AI
owner_html_url: https://github.com/Lightning-AI
- name: huma
html_url: https://github.com/danielgtaylor/huma
stars: 3702
stars: 3785
owner_login: danielgtaylor
owner_html_url: https://github.com/danielgtaylor
- name: Yuxi-Know
html_url: https://github.com/xerrors/Yuxi-Know
stars: 3680
owner_login: xerrors
owner_html_url: https://github.com/xerrors
- name: datamodel-code-generator
html_url: https://github.com/koxudaxi/datamodel-code-generator
stars: 3675
stars: 3731
owner_login: koxudaxi
owner_html_url: https://github.com/koxudaxi
- name: fastapi-admin
html_url: https://github.com/fastapi-admin/fastapi-admin
stars: 3659
stars: 3697
owner_login: fastapi-admin
owner_html_url: https://github.com/fastapi-admin
- name: farfalle
html_url: https://github.com/rashadphz/farfalle
stars: 3497
stars: 3506
owner_login: rashadphz
owner_html_url: https://github.com/rashadphz
- name: tracecat
html_url: https://github.com/TracecatHQ/tracecat
stars: 3421
stars: 3458
owner_login: TracecatHQ
owner_html_url: https://github.com/TracecatHQ
- name: mcp-context-forge
html_url: https://github.com/IBM/mcp-context-forge
stars: 3216
owner_login: IBM
owner_html_url: https://github.com/IBM
- name: opyrator
html_url: https://github.com/ml-tooling/opyrator
stars: 3136
stars: 3134
owner_login: ml-tooling
owner_html_url: https://github.com/ml-tooling
- name: docarray
@ -180,316 +185,311 @@
owner_html_url: https://github.com/docarray
- name: fastapi-realworld-example-app
html_url: https://github.com/nsidnev/fastapi-realworld-example-app
stars: 3051
stars: 3072
owner_login: nsidnev
owner_html_url: https://github.com/nsidnev
- name: mcp-context-forge
html_url: https://github.com/IBM/mcp-context-forge
stars: 3034
owner_login: IBM
owner_html_url: https://github.com/IBM
- name: uvicorn-gunicorn-fastapi-docker
html_url: https://github.com/tiangolo/uvicorn-gunicorn-fastapi-docker
stars: 2904
stars: 2908
owner_login: tiangolo
owner_html_url: https://github.com/tiangolo
- name: FastAPI-template
html_url: https://github.com/s3rius/FastAPI-template
stars: 2680
stars: 2728
owner_login: s3rius
owner_html_url: https://github.com/s3rius
- name: best-of-web-python
html_url: https://github.com/ml-tooling/best-of-web-python
stars: 2662
stars: 2686
owner_login: ml-tooling
owner_html_url: https://github.com/ml-tooling
- name: YC-Killer
html_url: https://github.com/sahibzada-allahyar/YC-Killer
stars: 2614
stars: 2648
owner_login: sahibzada-allahyar
owner_html_url: https://github.com/sahibzada-allahyar
- name: sqladmin
html_url: https://github.com/aminalaee/sqladmin
stars: 2587
stars: 2637
owner_login: aminalaee
owner_html_url: https://github.com/aminalaee
- name: fastapi-react
html_url: https://github.com/Buuntu/fastapi-react
stars: 2566
stars: 2573
owner_login: Buuntu
owner_html_url: https://github.com/Buuntu
- name: RasaGPT
html_url: https://github.com/paulpierre/RasaGPT
stars: 2456
stars: 2460
owner_login: paulpierre
owner_html_url: https://github.com/paulpierre
- name: supabase-py
html_url: https://github.com/supabase/supabase-py
stars: 2394
stars: 2428
owner_login: supabase
owner_html_url: https://github.com/supabase
- name: 30-Days-of-Python
html_url: https://github.com/codingforentrepreneurs/30-Days-of-Python
stars: 2347
owner_login: codingforentrepreneurs
owner_html_url: https://github.com/codingforentrepreneurs
- name: nextpy
html_url: https://github.com/dot-agent/nextpy
stars: 2338
stars: 2337
owner_login: dot-agent
owner_html_url: https://github.com/dot-agent
- name: fastapi-utils
html_url: https://github.com/fastapiutils/fastapi-utils
stars: 2289
stars: 2299
owner_login: fastapiutils
owner_html_url: https://github.com/fastapiutils
- name: langserve
html_url: https://github.com/langchain-ai/langserve
stars: 2234
stars: 2255
owner_login: langchain-ai
owner_html_url: https://github.com/langchain-ai
- name: 30-Days-of-Python
html_url: https://github.com/codingforentrepreneurs/30-Days-of-Python
stars: 2232
owner_login: codingforentrepreneurs
owner_html_url: https://github.com/codingforentrepreneurs
- name: NoteDiscovery
html_url: https://github.com/gamosoft/NoteDiscovery
stars: 2182
owner_login: gamosoft
owner_html_url: https://github.com/gamosoft
- name: solara
html_url: https://github.com/widgetti/solara
stars: 2141
stars: 2154
owner_login: widgetti
owner_html_url: https://github.com/widgetti
- name: mangum
html_url: https://github.com/Kludex/mangum
stars: 2046
stars: 2071
owner_login: Kludex
owner_html_url: https://github.com/Kludex
- name: fastapi_best_architecture
html_url: https://github.com/fastapi-practices/fastapi_best_architecture
stars: 1963
stars: 2036
owner_login: fastapi-practices
owner_html_url: https://github.com/fastapi-practices
- name: NoteDiscovery
html_url: https://github.com/gamosoft/NoteDiscovery
stars: 1943
owner_login: gamosoft
owner_html_url: https://github.com/gamosoft
- name: agentkit
html_url: https://github.com/BCG-X-Official/agentkit
stars: 1936
owner_login: BCG-X-Official
owner_html_url: https://github.com/BCG-X-Official
- name: vue-fastapi-admin
html_url: https://github.com/mizhexiaoxiao/vue-fastapi-admin
stars: 1909
stars: 1983
owner_login: mizhexiaoxiao
owner_html_url: https://github.com/mizhexiaoxiao
- name: manage-fastapi
html_url: https://github.com/ycd/manage-fastapi
stars: 1887
owner_login: ycd
owner_html_url: https://github.com/ycd
- name: agentkit
html_url: https://github.com/BCG-X-Official/agentkit
stars: 1941
owner_login: BCG-X-Official
owner_html_url: https://github.com/BCG-X-Official
- name: fastapi-langgraph-agent-production-ready-template
html_url: https://github.com/wassim249/fastapi-langgraph-agent-production-ready-template
stars: 1920
owner_login: wassim249
owner_html_url: https://github.com/wassim249
- name: openapi-python-client
html_url: https://github.com/openapi-generators/openapi-python-client
stars: 1879
stars: 1900
owner_login: openapi-generators
owner_html_url: https://github.com/openapi-generators
- name: manage-fastapi
html_url: https://github.com/ycd/manage-fastapi
stars: 1894
owner_login: ycd
owner_html_url: https://github.com/ycd
- name: slowapi
html_url: https://github.com/laurentS/slowapi
stars: 1845
stars: 1891
owner_login: laurentS
owner_html_url: https://github.com/laurentS
- name: piccolo
html_url: https://github.com/piccolo-orm/piccolo
stars: 1843
stars: 1854
owner_login: piccolo-orm
owner_html_url: https://github.com/piccolo-orm
- name: fastapi-cache
html_url: https://github.com/long2ice/fastapi-cache
stars: 1816
owner_login: long2ice
owner_html_url: https://github.com/long2ice
- name: python-week-2022
html_url: https://github.com/rochacbruno/python-week-2022
stars: 1813
owner_login: rochacbruno
owner_html_url: https://github.com/rochacbruno
- name: fastapi-cache
html_url: https://github.com/long2ice/fastapi-cache
stars: 1805
owner_login: long2ice
owner_html_url: https://github.com/long2ice
- name: ormar
html_url: https://github.com/collerek/ormar
stars: 1785
stars: 1797
owner_login: collerek
owner_html_url: https://github.com/collerek
- name: fastapi-langgraph-agent-production-ready-template
html_url: https://github.com/wassim249/fastapi-langgraph-agent-production-ready-template
stars: 1780
owner_login: wassim249
owner_html_url: https://github.com/wassim249
- name: FastAPI-boilerplate
html_url: https://github.com/benavlabs/FastAPI-boilerplate
stars: 1734
stars: 1792
owner_login: benavlabs
owner_html_url: https://github.com/benavlabs
- name: termpair
html_url: https://github.com/cs01/termpair
stars: 1724
stars: 1727
owner_login: cs01
owner_html_url: https://github.com/cs01
- name: fastapi-crudrouter
html_url: https://github.com/awtkns/fastapi-crudrouter
stars: 1671
stars: 1677
owner_login: awtkns
owner_html_url: https://github.com/awtkns
- name: langchain-serve
html_url: https://github.com/jina-ai/langchain-serve
stars: 1633
stars: 1634
owner_login: jina-ai
owner_html_url: https://github.com/jina-ai
- name: fastapi-pagination
html_url: https://github.com/uriyyo/fastapi-pagination
stars: 1588
stars: 1607
owner_login: uriyyo
owner_html_url: https://github.com/uriyyo
- name: awesome-fastapi-projects
html_url: https://github.com/Kludex/awesome-fastapi-projects
stars: 1583
stars: 1592
owner_login: Kludex
owner_html_url: https://github.com/Kludex
- name: coronavirus-tracker-api
html_url: https://github.com/ExpDev07/coronavirus-tracker-api
stars: 1571
owner_login: ExpDev07
owner_html_url: https://github.com/ExpDev07
- name: bracket
html_url: https://github.com/evroon/bracket
stars: 1549
stars: 1580
owner_login: evroon
owner_html_url: https://github.com/evroon
- name: coronavirus-tracker-api
html_url: https://github.com/ExpDev07/coronavirus-tracker-api
stars: 1570
owner_login: ExpDev07
owner_html_url: https://github.com/ExpDev07
- name: fastapi-amis-admin
html_url: https://github.com/amisadmin/fastapi-amis-admin
stars: 1491
stars: 1512
owner_login: amisadmin
owner_html_url: https://github.com/amisadmin
- name: fastapi-boilerplate
html_url: https://github.com/teamhide/fastapi-boilerplate
stars: 1452
owner_login: teamhide
owner_html_url: https://github.com/teamhide
- name: fastcrud
html_url: https://github.com/benavlabs/fastcrud
stars: 1452
stars: 1471
owner_login: benavlabs
owner_html_url: https://github.com/benavlabs
- name: fastapi-boilerplate
html_url: https://github.com/teamhide/fastapi-boilerplate
stars: 1461
owner_login: teamhide
owner_html_url: https://github.com/teamhide
- name: awesome-python-resources
html_url: https://github.com/DjangoEx/awesome-python-resources
stars: 1430
stars: 1435
owner_login: DjangoEx
owner_html_url: https://github.com/DjangoEx
- name: prometheus-fastapi-instrumentator
html_url: https://github.com/trallnag/prometheus-fastapi-instrumentator
stars: 1399
stars: 1417
owner_login: trallnag
owner_html_url: https://github.com/trallnag
- name: fastapi-code-generator
html_url: https://github.com/koxudaxi/fastapi-code-generator
stars: 1371
stars: 1382
owner_login: koxudaxi
owner_html_url: https://github.com/koxudaxi
- name: fastapi-scaff
html_url: https://github.com/atpuxiner/fastapi-scaff
stars: 1367
owner_login: atpuxiner
owner_html_url: https://github.com/atpuxiner
- name: fastapi-tutorial
html_url: https://github.com/liaogx/fastapi-tutorial
stars: 1346
stars: 1360
owner_login: liaogx
owner_html_url: https://github.com/liaogx
- name: budgetml
html_url: https://github.com/ebhy/budgetml
stars: 1345
stars: 1343
owner_login: ebhy
owner_html_url: https://github.com/ebhy
- name: fastapi-scaff
html_url: https://github.com/atpuxiner/fastapi-scaff
stars: 1331
owner_login: atpuxiner
owner_html_url: https://github.com/atpuxiner
- name: bolt-python
html_url: https://github.com/slackapi/bolt-python
stars: 1266
stars: 1276
owner_login: slackapi
owner_html_url: https://github.com/slackapi
- name: bedrock-chat
html_url: https://github.com/aws-samples/bedrock-chat
stars: 1266
stars: 1268
owner_login: aws-samples
owner_html_url: https://github.com/aws-samples
- name: fastapi-alembic-sqlmodel-async
html_url: https://github.com/jonra1993/fastapi-alembic-sqlmodel-async
stars: 1260
owner_login: jonra1993
owner_html_url: https://github.com/jonra1993
html_url: https://github.com/vargasjona/fastapi-alembic-sqlmodel-async
stars: 1265
owner_login: vargasjona
owner_html_url: https://github.com/vargasjona
- name: fastapi_production_template
html_url: https://github.com/zhanymkanov/fastapi_production_template
stars: 1222
stars: 1227
owner_login: zhanymkanov
owner_html_url: https://github.com/zhanymkanov
- name: langchain-extract
html_url: https://github.com/langchain-ai/langchain-extract
stars: 1179
owner_login: langchain-ai
owner_html_url: https://github.com/langchain-ai
- name: restish
html_url: https://github.com/rest-sh/restish
stars: 1152
stars: 1200
owner_login: rest-sh
owner_html_url: https://github.com/rest-sh
- name: langchain-extract
html_url: https://github.com/langchain-ai/langchain-extract
stars: 1183
owner_login: langchain-ai
owner_html_url: https://github.com/langchain-ai
- name: odmantic
html_url: https://github.com/art049/odmantic
stars: 1143
stars: 1162
owner_login: art049
owner_html_url: https://github.com/art049
- name: authx
html_url: https://github.com/yezz123/authx
stars: 1128
owner_login: yezz123
owner_html_url: https://github.com/yezz123
- name: SAG
html_url: https://github.com/Zleap-AI/SAG
stars: 1104
owner_login: Zleap-AI
owner_html_url: https://github.com/Zleap-AI
- name: aktools
html_url: https://github.com/akfamily/aktools
stars: 1072
stars: 1155
owner_login: akfamily
owner_html_url: https://github.com/akfamily
- name: RuoYi-Vue3-FastAPI
html_url: https://github.com/insistence/RuoYi-Vue3-FastAPI
stars: 1063
stars: 1155
owner_login: insistence
owner_html_url: https://github.com/insistence
- name: authx
html_url: https://github.com/yezz123/authx
stars: 1142
owner_login: yezz123
owner_html_url: https://github.com/yezz123
- name: SAG
html_url: https://github.com/Zleap-AI/SAG
stars: 1110
owner_login: Zleap-AI
owner_html_url: https://github.com/Zleap-AI
- name: flock
html_url: https://github.com/Onelevenvy/flock
stars: 1059
stars: 1069
owner_login: Onelevenvy
owner_html_url: https://github.com/Onelevenvy
- name: fastapi-observability
html_url: https://github.com/blueswen/fastapi-observability
stars: 1046
stars: 1063
owner_login: blueswen
owner_html_url: https://github.com/blueswen
- name: enterprise-deep-research
html_url: https://github.com/SalesforceAIResearch/enterprise-deep-research
stars: 1019
stars: 1061
owner_login: SalesforceAIResearch
owner_html_url: https://github.com/SalesforceAIResearch
- name: titiler
html_url: https://github.com/developmentseed/titiler
stars: 1016
stars: 1039
owner_login: developmentseed
owner_html_url: https://github.com/developmentseed
- name: every-pdf
html_url: https://github.com/DDULDDUCK/every-pdf
stars: 1004
stars: 1017
owner_login: DDULDDUCK
owner_html_url: https://github.com/DDULDDUCK
- name: autollm
html_url: https://github.com/viddexa/autollm
stars: 1003
stars: 1005
owner_login: viddexa
owner_html_url: https://github.com/viddexa
- name: lanarky
html_url: https://github.com/ajndkr/lanarky
stars: 996
stars: 995
owner_login: ajndkr
owner_html_url: https://github.com/ajndkr

114
docs/en/data/translation_reviewers.yml

@ -10,12 +10,12 @@ Xewus:
url: https://github.com/Xewus
sodaMelon:
login: sodaMelon
count: 127
count: 128
avatarUrl: https://avatars.githubusercontent.com/u/66295123?u=be939db90f1119efee9e6110cc05066ff1f40f00&v=4
url: https://github.com/sodaMelon
ceb10n:
login: ceb10n
count: 117
count: 119
avatarUrl: https://avatars.githubusercontent.com/u/235213?u=edcce471814a1eba9f0cdaa4cd0de18921a940a6&v=4
url: https://github.com/ceb10n
tokusumi:
@ -25,7 +25,7 @@ tokusumi:
url: https://github.com/tokusumi
hard-coders:
login: hard-coders
count: 96
count: 102
avatarUrl: https://avatars.githubusercontent.com/u/9651103?u=78d12d1acdf853c817700145e73de7fd9e5d068b&v=4
url: https://github.com/hard-coders
hasansezertasan:
@ -50,7 +50,7 @@ AlertRED:
url: https://github.com/AlertRED
tiangolo:
login: tiangolo
count: 73
count: 78
avatarUrl: https://avatars.githubusercontent.com/u/1326112?u=cb5d06e73a9e1998141b1641aa88e443c6717651&v=4
url: https://github.com/tiangolo
Alexandrhub:
@ -58,26 +58,31 @@ Alexandrhub:
count: 68
avatarUrl: https://avatars.githubusercontent.com/u/119126536?u=9fc0d48f3307817bafecc5861eb2168401a6cb04&v=4
url: https://github.com/Alexandrhub
cassiobotaro:
login: cassiobotaro
count: 64
avatarUrl: https://avatars.githubusercontent.com/u/3127847?u=a08022b191ddbd0a6159b2981d9d878b6d5bb71f&v=4
url: https://github.com/cassiobotaro
waynerv:
login: waynerv
count: 63
avatarUrl: https://avatars.githubusercontent.com/u/39515546?u=ec35139777597cdbbbddda29bf8b9d4396b429a9&v=4
url: https://github.com/waynerv
cassiobotaro:
login: cassiobotaro
count: 62
avatarUrl: https://avatars.githubusercontent.com/u/3127847?u=a08022b191ddbd0a6159b2981d9d878b6d5bb71f&v=4
url: https://github.com/cassiobotaro
nilslindemann:
login: nilslindemann
count: 61
avatarUrl: https://avatars.githubusercontent.com/u/6892179?u=1dca6a22195d6cd1ab20737c0e19a4c55d639472&v=4
url: https://github.com/nilslindemann
mattwang44:
login: mattwang44
count: 61
avatarUrl: https://avatars.githubusercontent.com/u/24987826?u=58e37fb3927b9124b458945ac4c97aa0f1062d85&v=4
url: https://github.com/mattwang44
nilslindemann:
login: nilslindemann
count: 59
avatarUrl: https://avatars.githubusercontent.com/u/6892179?u=1dca6a22195d6cd1ab20737c0e19a4c55d639472&v=4
url: https://github.com/nilslindemann
YuriiMotov:
login: YuriiMotov
count: 56
avatarUrl: https://avatars.githubusercontent.com/u/109919500?u=bc48be95c429989224786106b027f3c5e40cc354&v=4
url: https://github.com/YuriiMotov
Laineyzhang55:
login: Laineyzhang55
count: 48
@ -88,26 +93,21 @@ Kludex:
count: 47
avatarUrl: https://avatars.githubusercontent.com/u/7353520?u=df8a3f06ba8f55ae1967a3e2d5ed882903a4e330&v=4
url: https://github.com/Kludex
YuriiMotov:
login: YuriiMotov
count: 46
avatarUrl: https://avatars.githubusercontent.com/u/109919500?u=b9b13d598dddfab529a52d264df80a900bfe7060&v=4
url: https://github.com/YuriiMotov
komtaki:
login: komtaki
count: 45
avatarUrl: https://avatars.githubusercontent.com/u/39375566?u=260ad6b1a4b34c07dbfa728da5e586f16f6d1824&v=4
url: https://github.com/komtaki
svlandeg:
login: svlandeg
count: 43
avatarUrl: https://avatars.githubusercontent.com/u/8796347?u=556c97650c27021911b0b9447ec55e75987b0e8a&v=4
url: https://github.com/svlandeg
rostik1410:
login: rostik1410
count: 42
avatarUrl: https://avatars.githubusercontent.com/u/11443899?u=e26a635c2ba220467b308a326a579b8ccf4a8701&v=4
url: https://github.com/rostik1410
svlandeg:
login: svlandeg
count: 42
avatarUrl: https://avatars.githubusercontent.com/u/8796347?u=556c97650c27021911b0b9447ec55e75987b0e8a&v=4
url: https://github.com/svlandeg
alperiox:
login: alperiox
count: 42
@ -136,7 +136,7 @@ JavierSanchezCastro:
alejsdev:
login: alejsdev
count: 37
avatarUrl: https://avatars.githubusercontent.com/u/90076947?u=85ceac49fb87138aebe8d663912e359447329090&v=4
avatarUrl: https://avatars.githubusercontent.com/u/90076947?u=0facffe3abf87f57a1f05fa773d1119cc5c2f6a5&v=4
url: https://github.com/alejsdev
mezgoodle:
login: mezgoodle
@ -383,6 +383,11 @@ Joao-Pedro-P-Holanda:
count: 16
avatarUrl: https://avatars.githubusercontent.com/u/110267046?u=331bd016326dac4cf3df4848f6db2dbbf8b5f978&v=4
url: https://github.com/Joao-Pedro-P-Holanda
maru0123-2004:
login: maru0123-2004
count: 16
avatarUrl: https://avatars.githubusercontent.com/u/43961566?u=16ed8603a4d6a4665cb6c53a7aece6f31379b769&v=4
url: https://github.com/maru0123-2004
JaeHyuckSa:
login: JaeHyuckSa
count: 16
@ -418,11 +423,6 @@ mattkoehne:
count: 14
avatarUrl: https://avatars.githubusercontent.com/u/80362153?v=4
url: https://github.com/mattkoehne
maru0123-2004:
login: maru0123-2004
count: 14
avatarUrl: https://avatars.githubusercontent.com/u/43961566?u=16ed8603a4d6a4665cb6c53a7aece6f31379b769&v=4
url: https://github.com/maru0123-2004
jovicon:
login: jovicon
count: 13
@ -458,6 +458,11 @@ wesinalves:
count: 13
avatarUrl: https://avatars.githubusercontent.com/u/13563128?u=9eb17ed50645dd684bfec47e75dba4e9772ec9c1&v=4
url: https://github.com/wesinalves
andersonrocha0:
login: andersonrocha0
count: 13
avatarUrl: https://avatars.githubusercontent.com/u/22346169?u=93a1359c8c5461d894802c0cc65bcd09217e7a02&v=4
url: https://github.com/andersonrocha0
NastasiaSaby:
login: NastasiaSaby
count: 12
@ -471,7 +476,7 @@ oandersonmagalhaes:
mkdir700:
login: mkdir700
count: 12
avatarUrl: https://avatars.githubusercontent.com/u/56359329?u=3d6ea8714f5000829b60dcf7b13a75b1e73aaf47&v=4
avatarUrl: https://avatars.githubusercontent.com/u/56359329?u=818e5f4b4dcc1a6ffb3e5aaa08fd827e5a726dfd&v=4
url: https://github.com/mkdir700
batlopes:
login: batlopes
@ -493,11 +498,6 @@ KaniKim:
count: 12
avatarUrl: https://avatars.githubusercontent.com/u/19832624?u=296dbdd490e0eb96e3d45a2608c065603b17dc31&v=4
url: https://github.com/KaniKim
andersonrocha0:
login: andersonrocha0
count: 12
avatarUrl: https://avatars.githubusercontent.com/u/22346169?u=93a1359c8c5461d894802c0cc65bcd09217e7a02&v=4
url: https://github.com/andersonrocha0
gitgernit:
login: gitgernit
count: 12
@ -558,6 +558,11 @@ Zhongheng-Cheng:
count: 11
avatarUrl: https://avatars.githubusercontent.com/u/95612344?u=a0f7730a3cc7486827965e01a119ad610bda4b0a&v=4
url: https://github.com/Zhongheng-Cheng
Pyth3rEx:
login: Pyth3rEx
count: 11
avatarUrl: https://avatars.githubusercontent.com/u/26427764?u=087724f74d813c95925d51e354554bd4b6d6bb60&v=4
url: https://github.com/Pyth3rEx
mariacamilagl:
login: mariacamilagl
count: 10
@ -611,7 +616,7 @@ socket-socket:
nick-cjyx9:
login: nick-cjyx9
count: 10
avatarUrl: https://avatars.githubusercontent.com/u/119087246?u=7227a2de948c68fb8396d5beff1ee5b0e057c42e&v=4
avatarUrl: https://avatars.githubusercontent.com/u/119087246?u=3d51dcbd79222ecb6538642f31dc7c8bb708d191&v=4
url: https://github.com/nick-cjyx9
marcelomarkus:
login: marcelomarkus
@ -683,11 +688,6 @@ Yarous:
count: 9
avatarUrl: https://avatars.githubusercontent.com/u/61277193?u=5b462347458a373b2d599c6f416d2b75eddbffad&v=4
url: https://github.com/Yarous
Pyth3rEx:
login: Pyth3rEx
count: 9
avatarUrl: https://avatars.githubusercontent.com/u/26427764?u=087724f74d813c95925d51e354554bd4b6d6bb60&v=4
url: https://github.com/Pyth3rEx
dimaqq:
login: dimaqq
count: 8
@ -736,7 +736,7 @@ minaton-ru:
sungchan1:
login: sungchan1
count: 8
avatarUrl: https://avatars.githubusercontent.com/u/28076127?u=a816d86ef3e60450a7225f128caf9a394c9320f9&v=4
avatarUrl: https://avatars.githubusercontent.com/u/28076127?u=fadbf24840186aca639d344bb3e0ecf7ff3441cf&v=4
url: https://github.com/sungchan1
Serrones:
login: Serrones
@ -761,7 +761,7 @@ anthonycepeda:
fabioueno:
login: fabioueno
count: 7
avatarUrl: https://avatars.githubusercontent.com/u/14273852?u=edd700982b16317ac6ebfd24c47bc0029b21d360&v=4
avatarUrl: https://avatars.githubusercontent.com/u/14273852?u=a3d546449cdc96621c32bcc26cf74be6e4390209&v=4
url: https://github.com/fabioueno
cfraboulet:
login: cfraboulet
@ -793,6 +793,11 @@ Zerohertz:
count: 7
avatarUrl: https://avatars.githubusercontent.com/u/42334717?u=5ebf4d33e73b1ad373154f6cdee44f7cab4d05ba&v=4
url: https://github.com/Zerohertz
EdmilsonRodrigues:
login: EdmilsonRodrigues
count: 7
avatarUrl: https://avatars.githubusercontent.com/u/62777025?u=217d6f3cd6cc750bb8818a3af7726c8d74eb7c2d&v=4
url: https://github.com/EdmilsonRodrigues
deniscapeto:
login: deniscapeto
count: 6
@ -1028,11 +1033,6 @@ devluisrodrigues:
count: 5
avatarUrl: https://avatars.githubusercontent.com/u/21125286?v=4
url: https://github.com/11kkw
EdmilsonRodrigues:
login: EdmilsonRodrigues
count: 5
avatarUrl: https://avatars.githubusercontent.com/u/62777025?u=217d6f3cd6cc750bb8818a3af7726c8d74eb7c2d&v=4
url: https://github.com/EdmilsonRodrigues
lpdswing:
login: lpdswing
count: 4
@ -1178,6 +1178,11 @@ SBillion:
count: 4
avatarUrl: https://avatars.githubusercontent.com/u/1070649?u=3ab493dfc88b39da0eb1600e3b8e7df1c90a5dee&v=4
url: https://github.com/SBillion
seuthootDev:
login: seuthootDev
count: 4
avatarUrl: https://avatars.githubusercontent.com/u/175179350?u=7c2cbc48ab43b52e0c86592111d92e013d72ea4d&v=4
url: https://github.com/seuthootDev
tyronedamasceno:
login: tyronedamasceno
count: 3
@ -1266,7 +1271,7 @@ rafsaf:
frnsimoes:
login: frnsimoes
count: 3
avatarUrl: https://avatars.githubusercontent.com/u/66239468?u=fd8d408946633acc4bea057c207e6c0833871527&v=4
avatarUrl: https://avatars.githubusercontent.com/u/66239468?u=cba345870d8d6b25dd6d56ee18f7120581e3c573&v=4
url: https://github.com/frnsimoes
lieryan:
login: lieryan
@ -1593,6 +1598,11 @@ ayr-ton:
count: 2
avatarUrl: https://avatars.githubusercontent.com/u/1090517?u=5cf70a0e0f0dbf084e074e494aa94d7c91a46ba6&v=4
url: https://github.com/ayr-ton
Kadermiyanyedi:
login: Kadermiyanyedi
count: 2
avatarUrl: https://avatars.githubusercontent.com/u/48386782?u=e34f31bf50a8ed8d37fbfa4f301b0c190b1b4b86&v=4
url: https://github.com/Kadermiyanyedi
raphaelauv:
login: raphaelauv
count: 2
@ -1831,7 +1841,7 @@ EgorOnishchuk:
iamantonreznik:
login: iamantonreznik
count: 2
avatarUrl: https://avatars.githubusercontent.com/u/112612414?u=bf6de9a1ab17326fe14de0709719fff3826526d0&v=4
avatarUrl: https://avatars.githubusercontent.com/u/112612414?u=b9ba8d9b4d3940198bc3a4353dfce70c044a39b1&v=4
url: https://github.com/iamantonreznik
Azazul123:
login: Azazul123
@ -1851,7 +1861,7 @@ NavesSapnis:
isgin01:
login: isgin01
count: 2
avatarUrl: https://avatars.githubusercontent.com/u/157279130?u=ddffde10876b50f35dc90d1337f507a630530a6a&v=4
avatarUrl: https://avatars.githubusercontent.com/u/157279130?u=16d6466476cf7dbc55a4cd575b6ea920ebdd81e1&v=4
url: https://github.com/isgin01
syedasamina56:
login: syedasamina56

43
docs/en/data/translators.yml

@ -8,9 +8,14 @@ jaystone776:
count: 46
avatarUrl: https://avatars.githubusercontent.com/u/11191137?u=299205a95e9b6817a43144a48b643346a5aac5cc&v=4
url: https://github.com/jaystone776
tiangolo:
login: tiangolo
count: 31
avatarUrl: https://avatars.githubusercontent.com/u/1326112?u=cb5d06e73a9e1998141b1641aa88e443c6717651&v=4
url: https://github.com/tiangolo
ceb10n:
login: ceb10n
count: 29
count: 30
avatarUrl: https://avatars.githubusercontent.com/u/235213?u=edcce471814a1eba9f0cdaa4cd0de18921a940a6&v=4
url: https://github.com/ceb10n
valentinDruzhinin:
@ -28,11 +33,6 @@ SwftAlpc:
count: 23
avatarUrl: https://avatars.githubusercontent.com/u/52768429?u=6a3aa15277406520ad37f6236e89466ed44bc5b8&v=4
url: https://github.com/SwftAlpc
tiangolo:
login: tiangolo
count: 22
avatarUrl: https://avatars.githubusercontent.com/u/1326112?u=cb5d06e73a9e1998141b1641aa88e443c6717651&v=4
url: https://github.com/tiangolo
hasansezertasan:
login: hasansezertasan
count: 22
@ -43,16 +43,16 @@ waynerv:
count: 20
avatarUrl: https://avatars.githubusercontent.com/u/39515546?u=ec35139777597cdbbbddda29bf8b9d4396b429a9&v=4
url: https://github.com/waynerv
hard-coders:
login: hard-coders
count: 16
avatarUrl: https://avatars.githubusercontent.com/u/9651103?u=78d12d1acdf853c817700145e73de7fd9e5d068b&v=4
url: https://github.com/hard-coders
AlertRED:
login: AlertRED
count: 16
avatarUrl: https://avatars.githubusercontent.com/u/15695000?u=f5a4944c6df443030409c88da7d7fa0b7ead985c&v=4
url: https://github.com/AlertRED
hard-coders:
login: hard-coders
count: 15
avatarUrl: https://avatars.githubusercontent.com/u/9651103?u=78d12d1acdf853c817700145e73de7fd9e5d068b&v=4
url: https://github.com/hard-coders
Joao-Pedro-P-Holanda:
login: Joao-Pedro-P-Holanda
count: 14
@ -108,6 +108,11 @@ pablocm83:
count: 8
avatarUrl: https://avatars.githubusercontent.com/u/28315068?u=3310fbb05bb8bfc50d2c48b6cb64ac9ee4a14549&v=4
url: https://github.com/pablocm83
YuriiMotov:
login: YuriiMotov
count: 8
avatarUrl: https://avatars.githubusercontent.com/u/109919500?u=bc48be95c429989224786106b027f3c5e40cc354&v=4
url: https://github.com/YuriiMotov
ptt3199:
login: ptt3199
count: 7
@ -133,11 +138,6 @@ Alexandrhub:
count: 6
avatarUrl: https://avatars.githubusercontent.com/u/119126536?u=9fc0d48f3307817bafecc5861eb2168401a6cb04&v=4
url: https://github.com/Alexandrhub
YuriiMotov:
login: YuriiMotov
count: 6
avatarUrl: https://avatars.githubusercontent.com/u/109919500?u=b9b13d598dddfab529a52d264df80a900bfe7060&v=4
url: https://github.com/YuriiMotov
Serrones:
login: Serrones
count: 5
@ -291,7 +291,7 @@ hsuanchi:
alejsdev:
login: alejsdev
count: 3
avatarUrl: https://avatars.githubusercontent.com/u/90076947?u=85ceac49fb87138aebe8d663912e359447329090&v=4
avatarUrl: https://avatars.githubusercontent.com/u/90076947?u=0facffe3abf87f57a1f05fa773d1119cc5c2f6a5&v=4
url: https://github.com/alejsdev
riroan:
login: riroan
@ -361,7 +361,7 @@ Rishat-F:
ruzia:
login: ruzia
count: 3
avatarUrl: https://avatars.githubusercontent.com/u/24503?v=4
avatarUrl: https://avatars.githubusercontent.com/u/24503?u=abce66d26c9611818720f11e6ae6773a6e0928f8&v=4
url: https://github.com/ruzia
izaguerreiro:
login: izaguerreiro
@ -413,6 +413,11 @@ ayr-ton:
count: 2
avatarUrl: https://avatars.githubusercontent.com/u/1090517?u=5cf70a0e0f0dbf084e074e494aa94d7c91a46ba6&v=4
url: https://github.com/ayr-ton
Kadermiyanyedi:
login: Kadermiyanyedi
count: 2
avatarUrl: https://avatars.githubusercontent.com/u/48386782?u=e34f31bf50a8ed8d37fbfa4f301b0c190b1b4b86&v=4
url: https://github.com/Kadermiyanyedi
KdHyeon0661:
login: KdHyeon0661
count: 2
@ -461,7 +466,7 @@ ArtemKhymenko:
hasnatsajid:
login: hasnatsajid
count: 2
avatarUrl: https://avatars.githubusercontent.com/u/86589885?u=6668823c3b029bfecf10a8918ed3af1aafb8b15e&v=4
avatarUrl: https://avatars.githubusercontent.com/u/86589885?v=4
url: https://github.com/hasnatsajid
alperiox:
login: alperiox

20
docs/en/docs/advanced/wsgi.md

@ -6,13 +6,29 @@ For that, you can use the `WSGIMiddleware` and use it to wrap your WSGI applicat
## Using `WSGIMiddleware` { #using-wsgimiddleware }
You need to import `WSGIMiddleware`.
/// info
This requires installing `a2wsgi` for example with `pip install a2wsgi`.
///
You need to import `WSGIMiddleware` from `a2wsgi`.
Then wrap the WSGI (e.g. Flask) app with the middleware.
And then mount that under a path.
{* ../../docs_src/wsgi/tutorial001_py39.py hl[2:3,3] *}
{* ../../docs_src/wsgi/tutorial001_py39.py hl[1,3,23] *}
/// note
Previously, it was recommended to use `WSGIMiddleware` from `fastapi.middleware.wsgi`, but it is now deprecated.
It’s advised to use the `a2wsgi` package instead. The usage remains the same.
Just ensure that you have the `a2wsgi` package installed and import `WSGIMiddleware` correctly from `a2wsgi`.
///
## Check it { #check-it }

6
docs/en/docs/contributing.md

@ -13,7 +13,7 @@ Create a virtual environment and install the required packages with <a href="htt
<div class="termy">
```console
$ uv sync
$ uv sync --extra all
---> 100%
```
@ -32,9 +32,9 @@ That way, you don't have to "install" your local version to be able to test ever
/// note | Technical Details
This only happens when you install using `uv sync` instead of running `pip install fastapi` directly.
This only happens when you install using `uv sync --extra all` instead of running `pip install fastapi` directly.
That is because `uv sync` will install the local version of FastAPI in "editable" mode by default.
That is because `uv sync --extra all` will install the local version of FastAPI in "editable" mode by default.
///

4
docs/en/docs/deployment/docker.md

@ -145,8 +145,6 @@ There are other formats and tools to define and install package dependencies.
* Create a `main.py` file with:
```Python
from typing import Union
from fastapi import FastAPI
app = FastAPI()
@ -158,7 +156,7 @@ def read_root():
@app.get("/items/{item_id}")
def read_item(item_id: int, q: Union[str, None] = None):
def read_item(item_id: int, q: str | None = None):
return {"item_id": item_id, "q": q}
```

18
docs/en/docs/index.md

@ -161,8 +161,6 @@ $ pip install "fastapi[standard]"
Create a file `main.py` with:
```Python
from typing import Union
from fastapi import FastAPI
app = FastAPI()
@ -174,7 +172,7 @@ def read_root():
@app.get("/items/{item_id}")
def read_item(item_id: int, q: Union[str, None] = None):
def read_item(item_id: int, q: str | None = None):
return {"item_id": item_id, "q": q}
```
@ -183,9 +181,7 @@ def read_item(item_id: int, q: Union[str, None] = None):
If your code uses `async` / `await`, use `async def`:
```Python hl_lines="9 14"
from typing import Union
```Python hl_lines="7 12"
from fastapi import FastAPI
app = FastAPI()
@ -197,7 +193,7 @@ async def read_root():
@app.get("/items/{item_id}")
async def read_item(item_id: int, q: Union[str, None] = None):
async def read_item(item_id: int, q: str | None = None):
return {"item_id": item_id, "q": q}
```
@ -288,9 +284,7 @@ Now modify the file `main.py` to receive a body from a `PUT` request.
Declare the body using standard Python types, thanks to Pydantic.
```Python hl_lines="4 9-12 25-27"
from typing import Union
```Python hl_lines="2 7-10 23-25"
from fastapi import FastAPI
from pydantic import BaseModel
@ -300,7 +294,7 @@ app = FastAPI()
class Item(BaseModel):
name: str
price: float
is_offer: Union[bool, None] = None
is_offer: bool | None = None
@app.get("/")
@ -309,7 +303,7 @@ def read_root():
@app.get("/items/{item_id}")
def read_item(item_id: int, q: Union[str, None] = None):
def read_item(item_id: int, q: str | None = None):
return {"item_id": item_id, "q": q}

8
docs/en/docs/reference/middleware.md

@ -35,11 +35,3 @@ It can be imported from `fastapi`:
```python
from fastapi.middleware.trustedhost import TrustedHostMiddleware
```
::: fastapi.middleware.wsgi.WSGIMiddleware
It can be imported from `fastapi`:
```python
from fastapi.middleware.wsgi import WSGIMiddleware
```

2
docs/en/docs/reference/request.md

@ -2,6 +2,8 @@
You can declare a parameter in a *path operation function* or dependency to be of type `Request` and then you can access the raw request object directly, without any validation, etc.
Read more about it in the [FastAPI docs about using Request directly](https://fastapi.tiangolo.com/advanced/using-request-directly/)
You can import it directly from `fastapi`:
```python

2
docs/en/docs/reference/response.md

@ -4,6 +4,8 @@ You can declare a parameter in a *path operation function* or dependency to be o
You can also use it directly to create an instance of it and return it from your *path operations*.
Read more about it in the [FastAPI docs about returning a custom Response](https://fastapi.tiangolo.com/advanced/response-directly/#returning-a-custom-response)
You can import it directly from `fastapi`:
```python

2
docs/en/docs/reference/responses.md

@ -56,6 +56,8 @@ There are a couple of custom FastAPI response classes, you can use them to optim
## Starlette Responses
You can read more about all of them in the [FastAPI docs for Custom Response](https://fastapi.tiangolo.com/advanced/custom-response/) and in the [Starlette docs about Responses](https://starlette.dev/responses/).
::: fastapi.responses.FileResponse
options:
members:

2
docs/en/docs/reference/security/index.md

@ -28,6 +28,8 @@ from fastapi.security import (
)
```
Read more about them in the [FastAPI docs about Security](https://fastapi.tiangolo.com/tutorial/security/).
## API Key Security Schemes
::: fastapi.security.APIKeyCookie

24
docs/en/docs/reference/websockets.md

@ -2,6 +2,8 @@
When defining WebSockets, you normally declare a parameter of type `WebSocket` and with it you can read data from the client and send data to it.
Read more about it in the [FastAPI docs for WebSockets](https://fastapi.tiangolo.com/advanced/websockets/)
It is provided directly by Starlette, but you can import it from `fastapi`:
```python
@ -44,16 +46,6 @@ When you want to define dependencies that should be compatible with both HTTP an
- send_json
- close
When a client disconnects, a `WebSocketDisconnect` exception is raised, you can catch it.
You can import it directly form `fastapi`:
```python
from fastapi import WebSocketDisconnect
```
::: fastapi.WebSocketDisconnect
## WebSockets - additional classes
Additional classes for handling WebSockets.
@ -66,4 +58,16 @@ from fastapi.websockets import WebSocketDisconnect, WebSocketState
::: fastapi.websockets.WebSocketDisconnect
When a client disconnects, a `WebSocketDisconnect` exception is raised, you can catch it.
You can import it directly form `fastapi`:
```python
from fastapi import WebSocketDisconnect
```
Read more about it in the [FastAPI docs for WebSockets](https://fastapi.tiangolo.com/advanced/websockets/#handling-disconnections-and-multiple-clients)
::: fastapi.websockets.WebSocketState
`WebSocketState` is an enumeration of the possible states of a WebSocket connection.

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

@ -7,8 +7,33 @@ hide:
## Latest Changes
### Features
* ✨ Add `viewport` meta tag to improve Swagger UI on mobile devices. PR [#14777](https://github.com/fastapi/fastapi/pull/14777) by [@Joab0](https://github.com/Joab0).
* 🚸 Improve error message for invalid query parameter type annotations. PR [#14479](https://github.com/fastapi/fastapi/pull/14479) by [@retwish](https://github.com/retwish).
### Fixes
* 🐛 Fix TYPE_CHECKING annotations for Python 3.14 (PEP 649). PR [#14789](https://github.com/fastapi/fastapi/pull/14789) by [@mgu](https://github.com/mgu).
* 🐛 Strip whitespaces from `Authorization` header credentials. PR [#14786](https://github.com/fastapi/fastapi/pull/14786) by [@WaveTheory1](https://github.com/WaveTheory1).
* 🐛 Fix OpenAPI duplication of `anyOf` refs for app-level responses with specified `content` and `model` as `Union`. PR [#14463](https://github.com/fastapi/fastapi/pull/14463) by [@DJMcoder](https://github.com/DJMcoder).
### Refactors
* 🎨 Tweak types for mypy. PR [#14816](https://github.com/fastapi/fastapi/pull/14816) by [@tiangolo](https://github.com/tiangolo).
* 🏷️ Re-export `IncEx` type from Pydantic instead of duplicating it. PR [#14641](https://github.com/fastapi/fastapi/pull/14641) by [@mvanderlee](https://github.com/mvanderlee).
* 💡 Update comment for Pydantic internals. PR [#14814](https://github.com/fastapi/fastapi/pull/14814) by [@tiangolo](https://github.com/tiangolo).
### Docs
* 📝 Fix typing issue in `docs_src/app_testing/app_b` code example. PR [#14573](https://github.com/fastapi/fastapi/pull/14573) by [@timakaa](https://github.com/timakaa).
* 📝 Fix example of license identifier in documentation. PR [#14492](https://github.com/fastapi/fastapi/pull/14492) by [@johnson-earls](https://github.com/johnson-earls).
* 📝 Add banner to translated pages. PR [#14809](https://github.com/fastapi/fastapi/pull/14809) by [@YuriiMotov](https://github.com/YuriiMotov).
* 📝 Add links to related sections of docs to docstrings. PR [#14776](https://github.com/fastapi/fastapi/pull/14776) by [@YuriiMotov](https://github.com/YuriiMotov).
* 📝 Update embedded code examples to Python 3.10 syntax. PR [#14758](https://github.com/fastapi/fastapi/pull/14758) by [@YuriiMotov](https://github.com/YuriiMotov).
* 📝 Fix dependency installation command in `docs/en/docs/contributing.md`. PR [#14757](https://github.com/fastapi/fastapi/pull/14757) by [@YuriiMotov](https://github.com/YuriiMotov).
* 📝 Use return type annotation instead of `response_model` when possible. PR [#14753](https://github.com/fastapi/fastapi/pull/14753) by [@YuriiMotov](https://github.com/YuriiMotov).
* 📝 Use `WSGIMiddleware` from `a2wsgi` instead of deprecated `fastapi.middleware.wsgi.WSGIMiddleware`. PR [#14756](https://github.com/fastapi/fastapi/pull/14756) by [@YuriiMotov](https://github.com/YuriiMotov).
* 📝 Fix minor typos in release notes. PR [#14780](https://github.com/fastapi/fastapi/pull/14780) by [@whyvineet](https://github.com/whyvineet).
* 🐛 Fix copy button in custom.js. PR [#14722](https://github.com/fastapi/fastapi/pull/14722) by [@fcharrier](https://github.com/fcharrier).
* 📝 Add contribution instructions about LLM generated code and comments and automated tools for PRs. PR [#14706](https://github.com/fastapi/fastapi/pull/14706) by [@tiangolo](https://github.com/tiangolo).
@ -19,6 +44,7 @@ hide:
### Translations
* 🌐 Update translations for uk (update outdated, found by fixer tool). PR [#14739](https://github.com/fastapi/fastapi/pull/14739) by [@YuriiMotov](https://github.com/YuriiMotov).
* 🌐 Update translations for tr (update-outdated). PR [#14745](https://github.com/fastapi/fastapi/pull/14745) by [@tiangolo](https://github.com/tiangolo).
* 🌐 Update `llm-prompt.md` for Korean language. PR [#14763](https://github.com/fastapi/fastapi/pull/14763) by [@seuthootDev](https://github.com/seuthootDev).
* 🌐 Update translations for ko (update outdated, found by fixer tool). PR [#14738](https://github.com/fastapi/fastapi/pull/14738) by [@YuriiMotov](https://github.com/YuriiMotov).
@ -40,6 +66,17 @@ hide:
### Internal
* 🔨 Update translation script to retry if LLM-response doesn't pass validation with Translation Fixer tool. PR [#14749](https://github.com/fastapi/fastapi/pull/14749) by [@YuriiMotov](https://github.com/YuriiMotov).
* 👷 Run tests only on relevant code changes (not on docs). PR [#14813](https://github.com/fastapi/fastapi/pull/14813) by [@tiangolo](https://github.com/tiangolo).
* 👷 Run mypy by pre-commit. PR [#14806](https://github.com/fastapi/fastapi/pull/14806) by [@YuriiMotov](https://github.com/YuriiMotov).
* ⬆ Bump ruff from 0.14.3 to 0.14.14. PR [#14798](https://github.com/fastapi/fastapi/pull/14798) by [@dependabot[bot]](https://github.com/apps/dependabot).
* ⬆ Bump pyasn1 from 0.6.1 to 0.6.2. PR [#14804](https://github.com/fastapi/fastapi/pull/14804) by [@dependabot[bot]](https://github.com/apps/dependabot).
* ⬆ Bump sqlmodel from 0.0.27 to 0.0.31. PR [#14802](https://github.com/fastapi/fastapi/pull/14802) by [@dependabot[bot]](https://github.com/apps/dependabot).
* ⬆ Bump mkdocs-macros-plugin from 1.4.1 to 1.5.0. PR [#14801](https://github.com/fastapi/fastapi/pull/14801) by [@dependabot[bot]](https://github.com/apps/dependabot).
* ⬆ Bump gitpython from 3.1.45 to 3.1.46. PR [#14800](https://github.com/fastapi/fastapi/pull/14800) by [@dependabot[bot]](https://github.com/apps/dependabot).
* ⬆ Bump typer from 0.16.0 to 0.21.1. PR [#14799](https://github.com/fastapi/fastapi/pull/14799) by [@dependabot[bot]](https://github.com/apps/dependabot).
* 👥 Update FastAPI GitHub topic repositories. PR [#14803](https://github.com/fastapi/fastapi/pull/14803) by [@tiangolo](https://github.com/tiangolo).
* 👥 Update FastAPI People - Contributors and Translators. PR [#14796](https://github.com/fastapi/fastapi/pull/14796) by [@tiangolo](https://github.com/tiangolo).
* 🔧 Ensure that an edit to `uv.lock` gets the `internal` label. PR [#14759](https://github.com/fastapi/fastapi/pull/14759) by [@svlandeg](https://github.com/svlandeg).
* 🔧 Update sponsors: remove Requestly. PR [#14735](https://github.com/fastapi/fastapi/pull/14735) by [@tiangolo](https://github.com/tiangolo).
* 🔧 Update sponsors, LambdaTest changes to TestMu AI. PR [#14734](https://github.com/fastapi/fastapi/pull/14734) by [@tiangolo](https://github.com/tiangolo).

11
docs/en/docs/translation-banner.md

@ -0,0 +1,11 @@
/// details | 🌐 Translation by AI and humans
This translation was made by AI guided by humans. 🤝
It could have mistakes of misunderstanding the original meaning, or looking unnatural, etc. 🤖
You can improve this translation by [helping us guide the AI LLM better](https://fastapi.tiangolo.com/contributing/#translations).
[English version](ENGLISH_VERSION_URL)
///

7
docs/en/docs/tutorial/body-multiple-params.md

@ -103,15 +103,16 @@ Of course, you can also declare additional query parameters whenever you need, a
As, by default, singular values are interpreted as query parameters, you don't have to explicitly add a `Query`, you can just do:
```Python
q: Union[str, None] = None
q: str | None = None
```
Or in Python 3.10 and above:
Or in Python 3.9:
```Python
q: str | None = None
q: Union[str, None] = None
```
For example:
{* ../../docs_src/body_multiple_params/tutorial004_an_py310.py hl[28] *}

4
docs/en/docs/tutorial/path-operation-configuration.md

@ -52,7 +52,7 @@ In these cases, it could make sense to store the tags in an `Enum`.
You can add a `summary` and `description`:
{* ../../docs_src/path_operation_configuration/tutorial003_py310.py hl[18:19] *}
{* ../../docs_src/path_operation_configuration/tutorial003_py310.py hl[17:18] *}
## Description from docstring { #description-from-docstring }
@ -70,7 +70,7 @@ It will be used in the interactive docs:
You can specify the response description with the parameter `response_description`:
{* ../../docs_src/path_operation_configuration/tutorial005_py310.py hl[19] *}
{* ../../docs_src/path_operation_configuration/tutorial005_py310.py hl[18] *}
/// info

11
docs/ru/docs/translation-banner.md

@ -0,0 +1,11 @@
/// details | 🌐 Перевод выполнен с помощью ИИ и людей
Этот перевод был сделан ИИ под руководством людей. 🤝
В нем могут быть ошибки из-за неправильного понимания оригинального смысла или неестественности и т. д. 🤖
Вы можете улучшить этот перевод, [помогая нам лучше направлять ИИ LLM](https://fastapi.tiangolo.com/ru/contributing/#translations).
[Английская версия](ENGLISH_VERSION_URL)
///

80
docs/uk/docs/alternatives.md

@ -1,8 +1,8 @@
# Альтернативи, натхнення та порівняння
# Альтернативи, натхнення та порівняння { #alternatives-inspiration-and-comparisons }
Що надихнуло на створення **FastAPI**, який він у порінянні з іншими альтернативами та чого він у них навчився.
Що надихнуло **FastAPI**, як він порівнюється з альтернативами та чого він у них навчився.
## Вступ
## Вступ { #intro }
**FastAPI** не існувало б, якби не попередні роботи інших.
@ -12,17 +12,17 @@
Але в якийсь момент не було іншого виходу, окрім створення чогось, що надавало б усі ці функції, взявши найкращі ідеї з попередніх інструментів і поєднавши їх найкращим чином, використовуючи мовні функції, які навіть не були доступні раніше (Python 3.6+ підказки типів).
## Попередні інструменти
## Попередні інструменти { #previous-tools }
### <a href="https://www.djangoproject.com/" class="external-link" target="_blank">Django</a>
### <a href="https://www.djangoproject.com/" class="external-link" target="_blank">Django</a> { #django }
Це найпопулярніший фреймворк Python, який користується широкою довірою. Він використовується для створення таких систем, як Instagram.
Він відносно тісно пов’язаний з реляційними базами даних (наприклад, MySQL або PostgreSQL), тому мати базу даних NoSQL (наприклад, Couchbase, MongoDB, Cassandra тощо) як основний механізм зберігання не дуже просто.
Він був створений для створення HTML у серверній частині, а не для створення API, які використовуються сучасним інтерфейсом (як-от React, Vue.js і Angular) або іншими системами (як-от <abbr title="Internet of Things">IoT</abbr > пристрої), які спілкуються з ним.
Він був створений для створення HTML у серверній частині, а не для створення API, які використовуються сучасним інтерфейсом (як-от React, Vue.js і Angular) або іншими системами (як-от <abbr title="Internet of Things - Інтернет речей">IoT</abbr> пристрої), які спілкуються з ним.
### <a href="https://www.django-rest-framework.org/" class="external-link" target="_blank">Django REST Framework</a>
### <a href="https://www.django-rest-framework.org/" class="external-link" target="_blank">Django REST Framework</a> { #django-rest-framework }
Фреймворк Django REST був створений як гнучкий інструментарій для створення веб-інтерфейсів API використовуючи Django в основі, щоб покращити його можливості API.
@ -42,7 +42,7 @@ Django REST Framework створив Том Крісті. Той самий тв
///
### <a href="https://flask.palletsprojects.com" class="external-link" target="_blank">Flask</a>
### <a href="https://flask.palletsprojects.com" class="external-link" target="_blank">Flask</a> { #flask }
Flask — це «мікрофреймворк», він не включає інтеграцію бази даних, а також багато речей, які за замовчуванням є в Django.
@ -64,7 +64,7 @@ Flask — це «мікрофреймворк», він не включає ін
///
### <a href="https://requests.readthedocs.io" class="external-link" target="_blank">Requests</a>
### <a href="https://requests.readthedocs.io" class="external-link" target="_blank">Requests</a> { #requests }
**FastAPI** насправді не є альтернативою **Requests**. Сфера їх застосування дуже різна.
@ -88,12 +88,12 @@ Requests мають дуже простий та інтуїтивно зрозу
response = requests.get("http://example.com/some/url")
```
Відповідна операція *роуту* API FastAPI може виглядати так:
Відповідна операція шляху API FastAPI може виглядати так:
```Python hl_lines="1"
@app.get("/some/url")
def read_url():
return {"message": "Hello World"}
return {"message": "Hello World"}
```
Зверніть увагу на схожість у `requests.get(...)` і `@app.get(...)`.
@ -101,12 +101,12 @@ def read_url():
/// check | Надихнуло **FastAPI** на
* Майте простий та інтуїтивно зрозумілий API.
* Використовуйте імена (операції) методів HTTP безпосередньо, простим та інтуїтивно зрозумілим способом.
* Розумні параметри за замовчуванням, але потужні налаштування.
* Використовуйте імена (операції) методів HTTP безпосередньо, простим та інтуїтивно зрозумілим способом.
* Розумні параметри за замовчуванням, але потужні налаштування.
///
### <a href="https://swagger.io/" class="external-link" target="_blank">Swagger</a> / <a href="https://github.com/OAI /OpenAPI-Specification/" class="external-link" target="_blank">OpenAPI</a>
### <a href="https://swagger.io/" class="external-link" target="_blank">Swagger</a> / <a href="https://github.com/OAI/OpenAPI-Specification/" class="external-link" target="_blank">OpenAPI</a> { #swagger-openapi }
Головною функцією, яку я хотів від Django REST Framework, була автоматична API документація.
@ -124,18 +124,18 @@ def read_url():
Інтегрувати інструменти інтерфейсу на основі стандартів:
* <a href="https://github.com/swagger-api/swagger-ui" class="external-link" target="_blank">Інтерфейс Swagger</a>
* <a href="https://github.com/Rebilly/ReDoc" class="external-link" target="_blank">ReDoc</a>
* <a href="https://github.com/swagger-api/swagger-ui" class="external-link" target="_blank">Інтерфейс Swagger</a>
* <a href="https://github.com/Rebilly/ReDoc" class="external-link" target="_blank">ReDoc</a>
Ці два було обрано через те, що вони досить популярні та стабільні, але, виконавши швидкий пошук, ви можете знайти десятки додаткових альтернативних інтерфейсів для OpenAPI (які можна використовувати з **FastAPI**).
///
### Фреймворки REST для Flask
### Фреймворки REST для Flask { #flask-rest-frameworks }
Існує кілька фреймворків Flask REST, але, витративши час і роботу на їх дослідження, я виявив, що багато з них припинено або залишено, з кількома постійними проблемами, які зробили їх непридатними.
### <a href="https://marshmallow.readthedocs.io/en/stable/" class="external-link" target="_blank">Marshmallow</a>
### <a href="https://marshmallow.readthedocs.io/en/stable/" class="external-link" target="_blank">Marshmallow</a> { #marshmallow }
Однією з головних функцій, необхідних для систем API, є "<abbr title="також звана marshalling, conversion">серіалізація</abbr>", яка бере дані з коду (Python) і перетворює їх на щось, що можна надіслати через мережу. Наприклад, перетворення об’єкта, що містить дані з бази даних, на об’єкт JSON. Перетворення об’єктів `datetime` на строки тощо.
@ -153,7 +153,7 @@ Marshmallow створено для забезпечення цих функці
///
### <a href="https://webargs.readthedocs.io/en/latest/" class="external-link" target="_blank">Webargs</a>
### <a href="https://webargs.readthedocs.io/en/latest/" class="external-link" target="_blank">Webargs</a> { #webargs }
Іншою важливою функцією, необхідною для API, є <abbr title="читання та перетворення даних Python">аналіз</abbr> даних із вхідних запитів.
@ -175,7 +175,7 @@ Webargs був створений тими ж розробниками Marshmall
///
### <a href="https://apispec.readthedocs.io/en/stable/" class="external-link" target="_blank">APISpec</a>
### <a href="https://apispec.readthedocs.io/en/stable/" class="external-link" target="_blank">APISpec</a> { #apispec }
Marshmallow і Webargs забезпечують перевірку, аналіз і серіалізацію як плагіни.
@ -205,7 +205,7 @@ APISpec був створений тими ж розробниками Marshmall
///
### <a href="https://flask-apispec.readthedocs.io/en/latest/" class="external-link" target="_blank">Flask-apispec</a>
### <a href="https://flask-apispec.readthedocs.io/en/latest/" class="external-link" target="_blank">Flask-apispec</a> { #flask-apispec }
Це плагін Flask, який об’єднує Webargs, Marshmallow і APISpec.
@ -237,13 +237,13 @@ Flask-apispec був створений тими ж розробниками Mar
///
### <a href="https://nestjs.com/" class="external-link" target="_blank">NestJS</a> (та <a href="https://angular.io/ " class="external-link" target="_blank">Angular</a>)
### <a href="https://nestjs.com/" class="external-link" target="_blank">NestJS</a> (та <a href="https://angular.io/" class="external-link" target="_blank">Angular</a>) { #nestjs-and-angular }
Це навіть не Python, NestJS — це фреймворк NodeJS JavaScript (TypeScript), натхненний Angular.
Це досягає чогось подібного до того, що можна зробити з Flask-apispec.
Він має інтегровану систему впровадження залежностей, натхненну Angular two. Він потребує попередньої реєстрації «injectables» (як і всі інші системи впровадження залежностей, які я знаю), тому це збільшує багатослівність та повторення коду.
Він має інтегровану систему впровадження залежностей, натхненну Angular 2. Він потребує попередньої реєстрації «injectables» (як і всі інші системи впровадження залежностей, які я знаю), тому це збільшує багатослівність та повторення коду.
Оскільки параметри описані за допомогою типів TypeScript (подібно до підказок типу Python), підтримка редактора досить хороша.
@ -259,7 +259,7 @@ Flask-apispec був створений тими ж розробниками Mar
///
### <a href="https://sanic.readthedocs.io/en/latest/" class="external-link" target="_blank">Sanic</a>
### <a href="https://sanic.readthedocs.io/en/latest/" class="external-link" target="_blank">Sanic</a> { #sanic }
Це був один із перших надзвичайно швидких фреймворків Python на основі `asyncio`. Він був дуже схожий на Flask.
@ -279,7 +279,7 @@ Flask-apispec був створений тими ж розробниками Mar
///
### <a href="https://falconframework.org/" class="external-link" target="_blank">Falcon</a>
### <a href="https://falconframework.org/" class="external-link" target="_blank">Falcon</a> { #falcon }
Falcon — ще один високопродуктивний фреймворк Python, він розроблений як мінімальний і працює як основа інших фреймворків, таких як Hug.
@ -297,7 +297,7 @@ Falcon — ще один високопродуктивний фреймворк
///
### <a href="https://moltenframework.com/" class="external-link" target="_blank">Molten</a>
### <a href="https://moltenframework.com/" class="external-link" target="_blank">Molten</a> { #molten }
Я відкрив для себе Molten на перших етапах створення **FastAPI**. І він має досить схожі ідеї:
@ -321,7 +321,7 @@ Falcon — ще один високопродуктивний фреймворк
///
### <a href="https://github.com/hugapi/hug" class="external-link" target="_blank">Hug</a>
### <a href="https://github.com/hugapi/hug" class="external-link" target="_blank">Hug</a> { #hug }
Hug був одним із перших фреймворків, який реалізував оголошення типів параметрів API за допомогою підказок типу Python. Це була чудова ідея, яка надихнула інші інструменти зробити те саме.
@ -351,7 +351,7 @@ Hug надихнув частину APIStar і був одним із найбі
///
### <a href="https://github.com/encode/apistar" class="external-link" target="_blank">APIStar</a> (<= 0,5)
### <a href="https://github.com/encode/apistar" class="external-link" target="_blank">APIStar</a> (<= 0,5) { #apistar-0-5 }
Безпосередньо перед тим, як вирішити створити **FastAPI**, я знайшов сервер **APIStar**. Він мав майже все, що я шукав, і мав чудовий дизайн.
@ -379,9 +379,9 @@ Hug надихнув частину APIStar і був одним із найбі
APIStar створив Том Крісті. Той самий хлопець, який створив:
* Django REST Framework
* Starlette (на якому базується **FastAPI**)
* Uvicorn (використовується Starlette і **FastAPI**)
* Django REST Framework
* Starlette (на якому базується **FastAPI**)
* Uvicorn (використовується Starlette і **FastAPI**)
///
@ -393,13 +393,15 @@ APIStar створив Том Крісті. Той самий хлопець, я
І після тривалого пошуку подібної структури та тестування багатьох різних альтернатив, APIStar став найкращим доступним варіантом.
Потім APIStar перестав існувати як сервер, і було створено Starlette, який став новою кращою основою для такої системи. Це стало останнім джерелом натхнення для створення **FastAPI**. Я вважаю **FastAPI** «духовним спадкоємцем» APIStar, удосконалюючи та розширюючи функції, систему введення тексту та інші частини на основі досвіду, отриманого від усіх цих попередніх інструментів.
Потім APIStar перестав існувати як сервер, і було створено Starlette, який став новою кращою основою для такої системи. Це стало останнім джерелом натхнення для створення **FastAPI**.
Я вважаю **FastAPI** «духовним спадкоємцем» APIStar, удосконалюючи та розширюючи функції, систему типізації та інші частини на основі досвіду, отриманого від усіх цих попередніх інструментів.
///
## Використовується **FastAPI**
## Використовується **FastAPI** { #used-by-fastapi }
### <a href="https://docs.pydantic.dev/" class="external-link" target="_blank">Pydantic</a>
### <a href="https://docs.pydantic.dev/" class="external-link" target="_blank">Pydantic</a> { #pydantic }
Pydantic — це бібліотека для визначення перевірки даних, серіалізації та документації (за допомогою схеми JSON) на основі підказок типу Python.
@ -415,9 +417,9 @@ Pydantic — це бібліотека для визначення переві
///
### <a href="https://www.starlette.dev/" class="external-link" target="_blank">Starlette</a>
### <a href="https://www.starlette.dev/" class="external-link" target="_blank">Starlette</a> { #starlette }
Starlette — це легкий фреймворк/набір інструментів <abbr title="The new standard for build asynchronous Python web">ASGI</abbr>, який ідеально підходить для створення високопродуктивних asyncio сервісів.
Starlette — це легкий фреймворк/набір інструментів <abbr title="Новий стандарт для створення асинхронних Python вебзастосунків">ASGI</abbr>, який ідеально підходить для створення високопродуктивних asyncio сервісів.
Він дуже простий та інтуїтивно зрозумілий. Його розроблено таким чином, щоб його можна було легко розширювати та мати модульні компоненти.
@ -460,7 +462,7 @@ ASGI — це новий «стандарт», який розробляєтьс
///
### <a href="https://www.uvicorn.dev/" class="external-link" target="_blank">Uvicorn</a>
### <a href="https://www.uvicorn.dev/" class="external-link" target="_blank">Uvicorn</a> { #uvicorn }
Uvicorn — це блискавичний сервер ASGI, побудований на uvloop і httptools.
@ -472,12 +474,12 @@ Uvicorn — це блискавичний сервер ASGI, побудован
Основний веб-сервер для запуску програм **FastAPI**.
Ви можете поєднати його з Gunicorn, щоб мати асинхронний багатопроцесний сервер.
Ви також можете використати параметр командного рядка `--workers`, щоб мати асинхронний багатопроцесний сервер.
Додаткову інформацію див. у розділі [Розгортання](deployment/index.md){.internal-link target=_blank}.
///
## Орієнтири та швидкість
## Орієнтири та швидкість { #benchmarks-and-speed }
Щоб зрозуміти, порівняти та побачити різницю між Uvicorn, Starlette і FastAPI, перегляньте розділ про [Бенчмарки](benchmarks.md){.internal-link target=_blank}.

108
docs/uk/docs/fastapi-cli.md

@ -1,83 +1,75 @@
# FastAPI CLI
# FastAPI CLI { #fastapi-cli }
**FastAPI CLI** це програма командного рядка, яку Ви можете використовувати, щоб обслуговувати Ваш додаток FastAPI, керувати Вашими FastApi проектами, тощо.
**FastAPI CLI** це програма командного рядка, яку ви можете використовувати, щоб обслуговувати ваш застосунок FastAPI, керувати вашим проєктом FastAPI тощо.
Коли Ви встановлюєте FastApi (тобто виконуєте `pip install "fastapi[standard]"`), Ви також встановлюєте пакунок `fastapi-cli`, цей пакунок надає команду `fastapi` в терміналі.
Коли ви встановлюєте FastAPI (наприклад, за допомогою `pip install "fastapi[standard]"`), він включає пакет під назвою `fastapi-cli`, цей пакет надає команду `fastapi` у терміналі.
Для запуску Вашого FastAPI проекту для розробки, Ви можете скористатись командою `fastapi dev`:
Щоб запустити ваш застосунок FastAPI для розробки, ви можете використати команду `fastapi dev`:
<div class="termy">
```console
$ <font color="#4E9A06">fastapi</font> dev <u style="text-decoration-style:single">main.py</u>
<font color="#3465A4">INFO </font> Using path <font color="#3465A4">main.py</font>
<font color="#3465A4">INFO </font> Resolved absolute path <font color="#75507B">/home/user/code/awesomeapp/</font><font color="#AD7FA8">main.py</font>
<font color="#3465A4">INFO </font> Searching for package file structure from directories with <font color="#3465A4">__init__.py</font> files
<font color="#3465A4">INFO </font> Importing from <font color="#75507B">/home/user/code/</font><font color="#AD7FA8">awesomeapp</font>
╭─ <font color="#8AE234"><b>Python module file</b></font> ─╮
│ │
│ 🐍 main.py │
│ │
╰──────────────────────╯
<font color="#3465A4">INFO </font> Importing module <font color="#4E9A06">main</font>
<font color="#3465A4">INFO </font> Found importable FastAPI app
╭─ <font color="#8AE234"><b>Importable FastAPI app</b></font> ─╮
│ │
<span style="background-color:#272822"><font color="#FF4689">from</font></span><span style="background-color:#272822"><font color="#F8F8F2"> main </font></span><span style="background-color:#272822"><font color="#FF4689">import</font></span><span style="background-color:#272822"><font color="#F8F8F2"> app</font></span><span style="background-color:#272822"> </span>
│ │
╰──────────────────────────╯
<font color="#3465A4">INFO </font> Using import string <font color="#8AE234"><b>main:app</b></font>
<span style="background-color:#C4A000"><font color="#2E3436">╭────────── FastAPI CLI - Development mode ───────────╮</font></span>
<span style="background-color:#C4A000"><font color="#2E3436">│ │</font></span>
<span style="background-color:#C4A000"><font color="#2E3436">│ Serving at: http://127.0.0.1:8000 │</font></span>
<span style="background-color:#C4A000"><font color="#2E3436">│ │</font></span>
<span style="background-color:#C4A000"><font color="#2E3436">│ API docs: http://127.0.0.1:8000/docs │</font></span>
<span style="background-color:#C4A000"><font color="#2E3436">│ │</font></span>
<span style="background-color:#C4A000"><font color="#2E3436">│ Running in development mode, for production use: │</font></span>
<span style="background-color:#C4A000"><font color="#2E3436">│ │</font></span>
<span style="background-color:#C4A000"><font color="#2E3436"></font></span><span style="background-color:#C4A000"><font color="#555753"><b>fastapi run</b></font></span><span style="background-color:#C4A000"><font color="#2E3436"></font></span>
<span style="background-color:#C4A000"><font color="#2E3436">│ │</font></span>
<span style="background-color:#C4A000"><font color="#2E3436">╰─────────────────────────────────────────────────────╯</font></span>
<font color="#4E9A06">INFO</font>: Will watch for changes in these directories: [&apos;/home/user/code/awesomeapp&apos;]
<font color="#4E9A06">INFO</font>: Uvicorn running on <b>http://127.0.0.1:8000</b> (Press CTRL+C to quit)
<font color="#4E9A06">INFO</font>: Started reloader process [<font color="#34E2E2"><b>2265862</b></font>] using <font color="#34E2E2"><b>WatchFiles</b></font>
<font color="#4E9A06">INFO</font>: Started server process [<font color="#06989A">2265873</font>]
<font color="#4E9A06">INFO</font>: Waiting for application startup.
<font color="#4E9A06">INFO</font>: Application startup complete.
$ <font color="#4E9A06">fastapi</font> dev <u style="text-decoration-style:solid">main.py</u>
<span style="background-color:#009485"><font color="#D3D7CF"> FastAPI </font></span> Starting development server 🚀
Searching for package file structure from directories with
<font color="#3465A4">__init__.py</font> files
Importing from <font color="#75507B">/home/user/code/</font><font color="#AD7FA8">awesomeapp</font>
<span style="background-color:#007166"><font color="#D3D7CF"> module </font></span> 🐍 main.py
<span style="background-color:#007166"><font color="#D3D7CF"> code </font></span> Importing the FastAPI app object from the module with the
following code:
<u style="text-decoration-style:solid">from </u><u style="text-decoration-style:solid"><b>main</b></u><u style="text-decoration-style:solid"> import </u><u style="text-decoration-style:solid"><b>app</b></u>
<span style="background-color:#007166"><font color="#D3D7CF"> app </font></span> Using import string: <font color="#3465A4">main:app</font>
<span style="background-color:#007166"><font color="#D3D7CF"> server </font></span> Server started at <font color="#729FCF"><u style="text-decoration-style:solid">http://127.0.0.1:8000</u></font>
<span style="background-color:#007166"><font color="#D3D7CF"> server </font></span> Documentation at <font color="#729FCF"><u style="text-decoration-style:solid">http://127.0.0.1:8000/docs</u></font>
<span style="background-color:#007166"><font color="#D3D7CF"> tip </font></span> Running in development mode, for production use:
<b>fastapi run</b>
Logs:
<span style="background-color:#007166"><font color="#D3D7CF"> INFO </font></span> Will watch for changes in these directories:
<b>[</b><font color="#4E9A06">&apos;/home/user/code/awesomeapp&apos;</font><b>]</b>
<span style="background-color:#007166"><font color="#D3D7CF"> INFO </font></span> Uvicorn running on <font color="#729FCF"><u style="text-decoration-style:solid">http://127.0.0.1:8000</u></font> <b>(</b>Press CTRL+C to
quit<b>)</b>
<span style="background-color:#007166"><font color="#D3D7CF"> INFO </font></span> Started reloader process <b>[</b><font color="#34E2E2"><b>383138</b></font><b>]</b> using WatchFiles
<span style="background-color:#007166"><font color="#D3D7CF"> INFO </font></span> Started server process <b>[</b><font color="#34E2E2"><b>383153</b></font><b>]</b>
<span style="background-color:#007166"><font color="#D3D7CF"> INFO </font></span> Waiting for application startup.
<span style="background-color:#007166"><font color="#D3D7CF"> INFO </font></span> Application startup complete.
```
</div>
Програма командного рядка `fastapi` це **FastAPI CLI**.
Програма командного рядка під назвою `fastapi` — це **FastAPI CLI**.
FastAPI CLI приймає шлях до Вашої Python програми (напр. `main.py`) і автоматично виявляє екземпляр `FastAPI` (зазвичай названий `app`), обирає коректний процес імпорту, а потім обслуговує його.
FastAPI CLI бере шлях до вашої Python-програми (наприклад, `main.py`) і автоматично виявляє екземпляр `FastAPI` (зазвичай з назвою `app`), визначає правильний процес імпорту, а потім обслуговує його.
Натомість, для запуску у продакшн використовуйте `fastapi run`. 🚀
Натомість, для продакшн ви використали б `fastapi run`. 🚀
Всередині **FastAPI CLI** використовує <a href="https://www.uvicorn.dev" class="external-link" target="_blank">Uvicorn</a>, високопродуктивний, production-ready, ASGI cервер. 😎
Внутрішньо **FastAPI CLI** використовує <a href="https://www.uvicorn.dev" class="external-link" target="_blank">Uvicorn</a>, високопродуктивний, production-ready, ASGI сервер. 😎
## `fastapi dev`
## `fastapi dev` { #fastapi-dev }
Використання `fastapi dev` ініціює режим розробки.
Запуск `fastapi dev` ініціює режим розробки.
За замовчуванням, **автоматичне перезавантаження** увімкнене, автоматично перезавантажуючи сервер кожного разу, коли Ви змінюєте Ваш код. Це ресурсо-затратно, та може бути менш стабільним, ніж коли воно вимкнене. Ви повинні використовувати його тільки під час розробки. Воно також слухає IP-адресу `127.0.0.1`, що є IP Вашого девайсу для самостійної комунікації з самим собою (`localhost`).
За замовчуванням **auto-reload** увімкнено, і сервер автоматично перезавантажується, коли ви вносите зміни у ваш код. Це ресурсоємно та може бути менш стабільним, ніж коли його вимкнено. Вам слід використовувати це лише для розробки. Також він слухає IP-адресу `127.0.0.1`, яка є IP-адресою для того, щоб ваша машина могла взаємодіяти лише сама з собою (`localhost`).
## `fastapi run`
## `fastapi run` { #fastapi-run }
Виконання `fastapi run` запустить FastAPI у продакшн-режимі за замовчуванням.
Виконання `fastapi run` за замовчуванням запускає FastAPI у продакшн-режимі.
За замовчуванням, **автоматичне перезавантаження** вимкнене. Воно також прослуховує IP-адресу `0.0.0.0`, що означає всі доступні IP адреси, тим самим даючи змогу будь-кому комунікувати з девайсом. Так Ви зазвичай будете запускати його у продакшн, наприклад у контейнері.
За замовчуванням **auto-reload** вимкнено. Також він слухає IP-адресу `0.0.0.0`, що означає всі доступні IP-адреси, таким чином він буде публічно доступним для будь-кого, хто може взаємодіяти з машиною. Зазвичай саме так ви запускатимете його в продакшн, наприклад у контейнері.
В більшості випадків Ви можете (і маєте) мати "termination proxy", який обробляє HTTPS для Вас, це залежить від способу розгортання вашого додатку, Ваш провайдер може зробити це для Вас, або Вам потрібно налаштувати його самостійно.
У більшості випадків ви (і вам слід) матимете «termination proxy», який обробляє HTTPS для вас зверху; це залежатиме від того, як ви розгортаєте ваш застосунок: ваш провайдер може зробити це за вас, або вам може знадобитися налаштувати це самостійно.
/// tip
/// tip | Порада
Ви можете дізнатись більше про це у [документації про розгортування](deployment/index.md){.internal-link target=_blank}.
Ви можете дізнатися більше про це в [документації з розгортання](deployment/index.md){.internal-link target=_blank}.
///

138
docs/uk/docs/features.md

@ -1,21 +1,21 @@
# Функціональні можливості
# Функціональні можливості { #features }
## Функціональні можливості FastAPI
## Функціональні можливості FastAPI { #fastapi-features }
**FastAPI** надає вам такі можливості:
### Використання відкритих стандартів
### На основі відкритих стандартів { #based-on-open-standards }
* <a href="https://github.com/OAI/OpenAPI-Specification" class="external-link" target="_blank"><strong>OpenAPI</strong></a> для створення API, включаючи оголошення <abbr title="також відомі як: endpoints, маршрути">шляхів</abbr>, <abbr title="також відомі як HTTP-методи, наприклад, POST, GET, PUT, DELETE">операцій</abbr>, параметрів, тіл запитів, безпеки тощо.
* Автоматична документація моделей даних за допомогою <a href="https://json-schema.org/" class="external-link" target="_blank"><strong>JSON Schema</strong></a> (оскільки OpenAPI базується саме на JSON Schema).
* Розроблено на основі цих стандартів після ретельного аналізу, а не як додатковий рівень поверх основної архітектури.
* Це також дає змогу автоматично **генерувати код клієнта** багатьма мовами.
* Це також дає змогу використовувати автоматичну **генерацію клієнтського коду** багатьма мовами.
### Автоматична генерація документації
### Автоматична документація { #automatic-docs }
Інтерактивна документація API та вебінтерфейс для його дослідження. Оскільки фреймворк базується на OpenAPI, є кілька варіантів, два з яких включені за замовчуванням.
Інтерактивна документація API та вебінтерфейси для його дослідження. Оскільки фреймворк базується на OpenAPI, є кілька варіантів, 2 з яких включені за замовчуванням.
* <a href="https://github.com/swagger-api/swagger-ui" class="external-link" target="_blank"><strong>Swagger UI</strong></a>дозволяє інтерактивно переглядати API, викликати та тестувати його прямо у браузері.
* <a href="https://github.com/swagger-api/swagger-ui" class="external-link" target="_blank"><strong>Swagger UI</strong></a>з інтерактивним дослідженням, викликом і тестуванням вашого API прямо з браузера.
![Swagger UI interaction](https://fastapi.tiangolo.com/img/index/index-03-swagger-02.png)
@ -23,23 +23,25 @@
![ReDoc](https://fastapi.tiangolo.com/img/index/index-06-redoc-02.png)
### Тільки сучасний Python
### Лише сучасний Python { #just-modern-python }
FastAPI використовує стандартні **типи Python** (завдяки Pydantic). Вам не потрібно вивчати новий синтаксис — лише стандартний сучасний Python.
Усе базується на стандартних оголошеннях **типів Python** (завдяки Pydantic). Жодного нового синтаксису для вивчення. Лише стандартний сучасний Python.
Якщо вам потрібне коротке нагадування про використання типів у Python (навіть якщо ви не використовуєте FastAPI), перегляньте короткий підручник: [Вступ до типів Python](python-types.md){.internal-link target=_blank}.
Якщо вам потрібно 2-хвилинне нагадування про те, як використовувати типи Python (навіть якщо ви не використовуєте FastAPI), перегляньте короткий підручник: [Типи Python](python-types.md){.internal-link target=_blank}.
Ось приклад стандартного Python-коду з типами:
Ви пишете стандартний Python з типами:
```Python
from datetime import date
from pydantic import BaseModel
# Оголошення змінної як str
# з підтримкою автодоповнення у редакторі
# Оголосіть змінну як str
# та отримайте підтримку редактора всередині функції
def main(user_id: str):
return user_id
# Модель Pydantic
class User(BaseModel):
id: int
@ -47,7 +49,7 @@ class User(BaseModel):
joined: date
```
Приклад використання цієї моделі:
Далі це можна використовувати так:
```Python
my_user: User = User(id=3, name="John Doe", joined="2018-07-19")
@ -65,19 +67,21 @@ my_second_user: User = User(**second_user_data)
`**second_user_data` означає:
Передати ключі та значення словника `second_user_data` як аргументи у вигляді "ключ-значення", еквівалентно `User(id=4, name="Mary", joined="2018-11-30")`.
Передати ключі та значення словника `second_user_data` безпосередньо як аргументи у вигляді «ключ-значення», еквівалентно: `User(id=4, name="Mary", joined="2018-11-30")`
///
### Підтримка редакторів (IDE)
### Підтримка редакторів (IDE) { #editor-support }
Фреймворк спроєктований так, щоб бути легким і інтуїтивно зрозумілим. Усі рішення тестувалися у різних редакторах ще до початку розробки, щоб забезпечити найкращий досвід програмування.
Увесь фреймворк спроєктовано так, щоб ним було легко та інтуїтивно користуватися; усі рішення тестувалися у кількох редакторах ще до початку розробки, щоб забезпечити найкращий досвід розробки.
За результатами опитувань розробників Python <a href="https://www.jetbrains.com/research/python-developers-survey-2017/#tools-and-features" class="external-link" target="_blank">однією з найпопулярніших функцій є "автодоповнення"</a>.
З опитувань розробників Python зрозуміло <a href="https://www.jetbrains.com/research/python-developers-survey-2017/#tools-and-features" class="external-link" target="_blank">що однією з найуживаніших функцій є «автодоповнення»</a>.
**FastAPI** повністю підтримує автодоповнення у всіх місцях, тому вам рідко доведеться повертатися до документації.
Увесь фреймворк **FastAPI** побудований так, щоб це забезпечити. Автодоповнення працює всюди.
Приклад автодоповнення у редакторах:
Вам рідко доведеться повертатися до документації.
Ось як ваш редактор може вам допомогти:
* у <a href="https://code.visualstudio.com/" class="external-link" target="_blank">Visual Studio Code</a>:
@ -87,17 +91,25 @@ my_second_user: User = User(**second_user_data)
![editor support](https://fastapi.tiangolo.com/img/pycharm-completion.png)
### Короткий код
FastAPI має розумні налаштування **за замовчуванням**, але всі параметри можна налаштовувати відповідно до ваших потреб. Однак за замовчуванням все "просто працює".
Ви отримаєте автодоповнення в коді, який раніше могли вважати навіть неможливим. Наприклад, для ключа `price` всередині JSON body (який міг бути вкладеним), що надходить із запиту.
Більше не доведеться вводити неправильні назви ключів, постійно повертатися до документації або прокручувати вгору-вниз, щоб знайти, чи ви зрештою використали `username` чи `user_name`.
### Короткий код { #short }
FastAPI має розумні **налаштування за замовчуванням** для всього, з можливістю конфігурації всюди. Усі параметри можна точно налаштувати під ваші потреби та визначити потрібний вам API.
Але за замовчуванням усе **«просто працює»**.
### Валідація { #validation }
### Валідація
* Підтримка валідації для більшості (або всіх?) **типів даних Python**, зокрема:
* JSON-об'єктів (`dict`).
* JSON-списків (`list`) з визначенням типів елементів.
* Рядків (`str`) із мінімальною та максимальною довжиною.
* Чисел (`int`, `float`) з обмеженнями мінімальних та максимальних значень тощо.
* JSON-масивів (`list`) із визначенням типів елементів.
* Полів-рядків (`str`) із визначенням мінімальної та максимальної довжини.
* Чисел (`int`, `float`) з мінімальними та максимальними значеннями тощо.
* Валідація складніших типів, таких як:
* Валідація для більш екзотичних типів, як-от:
* URL.
* Email.
* UUID.
@ -105,55 +117,55 @@ FastAPI має розумні налаштування **за замовчува
Уся валідація виконується через надійний та перевірений **Pydantic**.
### Безпека та автентифікація
### Безпека та автентифікація { #security-and-authentication }
**FastAPI** підтримує вбудовану автентифікацію та авторизацію, без прив’язки до конкретних баз даних чи моделей даних.
Інтегровані безпека та автентифікація. Без жодних компромісів із базами даних чи моделями даних.
Підтримуються всі схеми безпеки OpenAPI, включаючи:
Підтримуються всі схеми безпеки, визначені в OpenAPI, включно з:
* HTTP Basic.
* **OAuth2** (також із підтримкою **JWT-токенів**). Див. підручник: [OAuth2 із JWT](tutorial/security/oauth2-jwt.md){.internal-link target=_blank}.
* **OAuth2** (також із підтримкою **JWT tokens**). Перегляньте підручник: [OAuth2 із JWT](tutorial/security/oauth2-jwt.md){.internal-link target=_blank}.
* Ключі API в:
* Заголовках.
* Параметрах запиту.
* Cookies тощо.
А також усі можливості безпеки від Starlette (зокрема **сесійні cookies**).
А також усі можливості безпеки від Starlette (зокрема **session cookies**).
Усі вони створені як багаторазові інструменти та компоненти, які легко інтегруються з вашими системами, сховищами даних, реляційними та NoSQL базами даних тощо.
Усе це зроблено як багаторазові інструменти та компоненти, які легко інтегруються з вашими системами, сховищами даних, реляційними та NoSQL базами даних тощо.
### Впровадження залежностей
### Впровадження залежностей { #dependency-injection }
**FastAPI** містить надзвичайно просту у використанні, але потужну систему впровадження залежностей.
FastAPI містить надзвичайно просту у використанні, але надзвичайно потужну систему <abbr title='також відоме як: "components", "resources", "services", "providers"'><strong>Dependency Injection</strong></abbr>.
* Залежності можуть мати власні залежності, утворюючи ієрархію або **"граф залежностей"**.
* Усі залежності автоматично керуються фреймворком.
* Усі залежності можуть отримувати дані з запитів і розширювати **обмеження операції за шляхом** та автоматичну документацію.
* **Автоматична валідація** навіть для параметрів *операцій шляху*, визначених у залежностях.
* Підтримка складних систем автентифікації користувачів, **з'єднань із базами даних** тощо.
* **Жодних обмежень** щодо використання баз даних, фронтендів тощо, але водночас проста інтеграція з усіма ними.
* Навіть залежності можуть мати власні залежності, утворюючи ієрархію або **«граф» залежностей**.
* Усе **автоматично обробляється** фреймворком.
* Усі залежності можуть вимагати дані із запитів і **розширювати обмеження операції шляху** та автоматичну документацію.
* **Автоматична валідація** навіть для параметрів *операції шляху*, визначених у залежностях.
* Підтримка складних систем автентифікації користувачів, **підключень до баз даних** тощо.
* **Жодних компромісів** із базами даних, фронтендами тощо. Але проста інтеграція з усіма ними.
### Немає обмежень на "плагіни"
### Необмежені «плагіни» { #unlimited-plug-ins }
Або іншими словами, вони не потрібні – просто імпортуйте та використовуйте необхідний код.
Інакше кажучи, вони не потрібні — імпортуйте та використовуйте код, який вам потрібен.
Будь-яка інтеграція спроєктована настільки просто (з використанням залежностей), що ви можете створити "плагін" для свого застосунку всього у 2 рядках коду, використовуючи ту саму структуру та синтаксис, що й для ваших *операцій шляху*.
Будь-яка інтеграція спроєктована так, щоб її було дуже просто використовувати (із залежностями), тож ви можете створити «плагін» для свого застосунку у 2 рядках коду, використовуючи ту саму структуру та синтаксис, що й для ваших *операцій шляху*.
### Протестовано
### Протестовано { #tested }
* 100% <abbr title="Обсяг коду, що автоматично тестується">покриття тестами</abbr>.
* 100% <abbr title="Анотації типів у Python, завдяки яким ваш редактор і зовнішні інструменти можуть надавати кращу підтримку">анотована типами</abbr> кодова база.
* Використовується у робочих середовищах.
* Використовується в production-застосунках.
## Можливості Starlette
## Можливості Starlette { #starlette-features }
**FastAPI** повністю сумісний із (та побудований на основі) <a href="https://www.starlette.dev/" class="external-link" target="_blank"><strong>Starlette</strong></a>. Тому будь-який додатковий код Starlette, який ви маєте, також працюватиме.
**FastAPI** фактично є підкласом **Starlette**. Тому, якщо ви вже знайомі зі Starlette або використовуєте його, більшість функціональності працюватиме так само.
`FastAPI` фактично є підкласом `Starlette`. Тому, якщо ви вже знайомі зі Starlette або використовуєте його, більшість функціональності працюватиме так само.
З **FastAPI** ви отримуєте всі можливості **Starlette** (адже FastAPI — це, по суті, Starlette на стероїдах):
З **FastAPI** ви отримуєте всі можливості **Starlette** (адже FastAPI — це просто Starlette на стероїдах):
* Разюча продуктивність. Це <a href="https://github.com/encode/starlette#performance" class="external-link" target="_blank">один із найшвидших фреймворків на Python</a>, на рівні з **NodeJS** і **Go**.
* Разюча продуктивність. Це <a href="https://github.com/encode/starlette#performance" class="external-link" target="_blank">один із найшвидших доступних Python-фреймворків, на рівні з **NodeJS** і **Go**</a>.
* Підтримка **WebSocket**.
* Фонові задачі у процесі.
* Події запуску та завершення роботи.
@ -163,27 +175,27 @@ FastAPI має розумні налаштування **за замовчува
* 100% покриття тестами.
* 100% анотована типами кодова база.
## Можливості Pydantic
## Можливості Pydantic { #pydantic-features }
**FastAPI** повністю сумісний із (та побудований на основі) <a href="https://docs.pydantic.dev/" class="external-link" target="_blank"><strong>Pydantic</strong></a>. Тому будь-який додатковий код Pydantic, який ви маєте, також працюватиме.
Включаючи зовнішні бібліотеки, побудовані також на Pydantic, такі як <abbr title="Object-Relational Mapper">ORM</abbr>, <abbr title="Object-Document Mapper">ODM</abbr> для баз даних.
Включно із зовнішніми бібліотеками, які також базуються на Pydantic, як-от <abbr title="Object-Relational Mapper - Об'єктно-реляційний відображувач">ORM</abbr>, <abbr title="Object-Document Mapper - Об'єктно-документний відображувач">ODM</abbr> для баз даних.
Це також означає, що в багатьох випадках ви можете передати той самий об'єкт, який отримуєте з запиту, **безпосередньо в базу даних**, оскільки все автоматично перевіряється.
Це також означає, що в багатьох випадках ви можете передати той самий об'єкт, який отримуєте із запиту, **безпосередньо в базу даних**, оскільки все автоматично перевіряється.
Те ж саме відбувається й у зворотному напрямку — у багатьох випадках ви можете просто передати об'єкт, який отримуєте з бази даних, **безпосередньо клієнту**.
Те саме застосовується й у зворотному напрямку — у багатьох випадках ви можете просто передати об'єкт, який отримуєте з бази даних, **безпосередньо клієнту**.
З **FastAPI** ви отримуєте всі можливості **Pydantic** (адже FastAPI базується на Pydantic для обробки всіх даних):
* **Ніякої плутанини** :
* Не потрібно вчити нову мову для визначення схем.
* **Ніякої плутанини**:
* Не потрібно вчити нову мікромову для визначення схем.
* Якщо ви знаєте типи Python, ви знаєте, як використовувати Pydantic.
* Легко працює з вашим **<abbr title="Інтегроване середовище розробки, схоже на редактор коду">IDE</abbr>/<abbr title="Програма, яка перевіряє помилки в коді">лінтером</abbr>/мозком**:
* Оскільки структури даних Pydantic є просто екземплярами класів, які ви визначаєте; автодоповнення, лінтинг, mypy і ваша інтуїція повинні добре працювати з вашими перевіреними даними.
* Валідація **складних структур**:
* Використання ієрархічних моделей Pydantic. Python `typing`, `List` і `Dict` тощо.
* Валідатори дозволяють чітко і просто визначати, перевіряти й документувати складні схеми даних у вигляді JSON-схеми.
* Ви можете мати глибоко **вкладені JSON об'єкти** та перевірити та анотувати їх всі.
* Легко працює з вашим **<abbr title="Integrated Development Environment - Інтегроване середовище розробки: схоже на код-редактор">IDE</abbr>/<abbr title="Програма, що перевіряє код на помилки">linter</abbr>/мозком**:
* Оскільки структури даних pydantic є просто екземплярами класів, які ви визначаєте; автодоповнення, лінтинг, mypy і ваша інтуїція повинні добре працювати з вашими перевіреними даними.
* Валідує **складні структури**:
* Використання ієрархічних моделей Pydantic, Python `typing`’s `List` і `Dict` тощо.
* Валідатори дають змогу складні схеми даних чітко й просто визначати, перевіряти й документувати як JSON Schema.
* Ви можете мати глибоко **вкладені JSON** об'єкти, і всі вони будуть валідовані та анотовані.
* **Розширюваність**:
* Pydantic дозволяє визначати користувацькі типи даних або розширювати валідацію методами в моделі декоратором `validator`.
* Pydantic дозволяє визначати користувацькі типи даних або ви можете розширити валідацію методами в моделі, позначеними декоратором validator.
* 100% покриття тестами.

6
docs_src/app_testing/app_b_an_py310/main.py

@ -28,11 +28,11 @@ async def read_main(item_id: str, x_token: Annotated[str, Header()]):
return fake_db[item_id]
@app.post("/items/", response_model=Item)
async def create_item(item: Item, x_token: Annotated[str, Header()]):
@app.post("/items/")
async def create_item(item: Item, x_token: Annotated[str, Header()]) -> Item:
if x_token != fake_secret_token:
raise HTTPException(status_code=400, detail="Invalid X-Token header")
if item.id in fake_db:
raise HTTPException(status_code=409, detail="Item already exists")
fake_db[item.id] = item
fake_db[item.id] = item.model_dump()
return item

6
docs_src/app_testing/app_b_an_py39/main.py

@ -28,11 +28,11 @@ async def read_main(item_id: str, x_token: Annotated[str, Header()]):
return fake_db[item_id]
@app.post("/items/", response_model=Item)
async def create_item(item: Item, x_token: Annotated[str, Header()]):
@app.post("/items/")
async def create_item(item: Item, x_token: Annotated[str, Header()]) -> Item:
if x_token != fake_secret_token:
raise HTTPException(status_code=400, detail="Invalid X-Token header")
if item.id in fake_db:
raise HTTPException(status_code=409, detail="Item already exists")
fake_db[item.id] = item
fake_db[item.id] = item.model_dump()
return item

6
docs_src/app_testing/app_b_py310/main.py

@ -26,11 +26,11 @@ async def read_main(item_id: str, x_token: str = Header()):
return fake_db[item_id]
@app.post("/items/", response_model=Item)
async def create_item(item: Item, x_token: str = Header()):
@app.post("/items/")
async def create_item(item: Item, x_token: str = Header()) -> Item:
if x_token != fake_secret_token:
raise HTTPException(status_code=400, detail="Invalid X-Token header")
if item.id in fake_db:
raise HTTPException(status_code=409, detail="Item already exists")
fake_db[item.id] = item
fake_db[item.id] = item.model_dump()
return item

6
docs_src/app_testing/app_b_py39/main.py

@ -28,11 +28,11 @@ async def read_main(item_id: str, x_token: str = Header()):
return fake_db[item_id]
@app.post("/items/", response_model=Item)
async def create_item(item: Item, x_token: str = Header()):
@app.post("/items/")
async def create_item(item: Item, x_token: str = Header()) -> Item:
if x_token != fake_secret_token:
raise HTTPException(status_code=400, detail="Invalid X-Token header")
if item.id in fake_db:
raise HTTPException(status_code=409, detail="Item already exists")
fake_db[item.id] = item
fake_db[item.id] = item.model_dump()
return item

4
docs_src/body_updates/tutorial002_py310.py

@ -25,8 +25,8 @@ async def read_item(item_id: str):
return items[item_id]
@app.patch("/items/{item_id}", response_model=Item)
async def update_item(item_id: str, item: Item):
@app.patch("/items/{item_id}")
async def update_item(item_id: str, item: Item) -> Item:
stored_item_data = items[item_id]
stored_item_model = Item(**stored_item_data)
update_data = item.model_dump(exclude_unset=True)

4
docs_src/body_updates/tutorial002_py39.py

@ -27,8 +27,8 @@ async def read_item(item_id: str):
return items[item_id]
@app.patch("/items/{item_id}", response_model=Item)
async def update_item(item_id: str, item: Item):
@app.patch("/items/{item_id}")
async def update_item(item_id: str, item: Item) -> Item:
stored_item_data = items[item_id]
stored_item_model = Item(**stored_item_data)
update_data = item.model_dump(exclude_unset=True)

2
docs_src/metadata/tutorial001_1_py39.py

@ -28,7 +28,7 @@ app = FastAPI(
},
license_info={
"name": "Apache 2.0",
"identifier": "MIT",
"identifier": "Apache-2.0",
},
)

4
docs_src/path_operation_advanced_configuration/tutorial004_py310.py

@ -12,8 +12,8 @@ class Item(BaseModel):
tags: set[str] = set()
@app.post("/items/", response_model=Item, summary="Create an item")
async def create_item(item: Item):
@app.post("/items/", summary="Create an item")
async def create_item(item: Item) -> Item:
"""
Create an item with all the information:

4
docs_src/path_operation_advanced_configuration/tutorial004_py39.py

@ -14,8 +14,8 @@ class Item(BaseModel):
tags: set[str] = set()
@app.post("/items/", response_model=Item, summary="Create an item")
async def create_item(item: Item):
@app.post("/items/", summary="Create an item")
async def create_item(item: Item) -> Item:
"""
Create an item with all the information:

4
docs_src/path_operation_configuration/tutorial001_py310.py

@ -12,6 +12,6 @@ class Item(BaseModel):
tags: set[str] = set()
@app.post("/items/", response_model=Item, status_code=status.HTTP_201_CREATED)
async def create_item(item: Item):
@app.post("/items/", status_code=status.HTTP_201_CREATED)
async def create_item(item: Item) -> Item:
return item

4
docs_src/path_operation_configuration/tutorial001_py39.py

@ -14,6 +14,6 @@ class Item(BaseModel):
tags: set[str] = set()
@app.post("/items/", response_model=Item, status_code=status.HTTP_201_CREATED)
async def create_item(item: Item):
@app.post("/items/", status_code=status.HTTP_201_CREATED)
async def create_item(item: Item) -> Item:
return item

4
docs_src/path_operation_configuration/tutorial002_py310.py

@ -12,8 +12,8 @@ class Item(BaseModel):
tags: set[str] = set()
@app.post("/items/", response_model=Item, tags=["items"])
async def create_item(item: Item):
@app.post("/items/", tags=["items"])
async def create_item(item: Item) -> Item:
return item

4
docs_src/path_operation_configuration/tutorial002_py39.py

@ -14,8 +14,8 @@ class Item(BaseModel):
tags: set[str] = set()
@app.post("/items/", response_model=Item, tags=["items"])
async def create_item(item: Item):
@app.post("/items/", tags=["items"])
async def create_item(item: Item) -> Item:
return item

3
docs_src/path_operation_configuration/tutorial003_py310.py

@ -14,9 +14,8 @@ class Item(BaseModel):
@app.post(
"/items/",
response_model=Item,
summary="Create an item",
description="Create an item with all the information, name, description, price, tax and a set of unique tags",
)
async def create_item(item: Item):
async def create_item(item: Item) -> Item:
return item

3
docs_src/path_operation_configuration/tutorial003_py39.py

@ -16,9 +16,8 @@ class Item(BaseModel):
@app.post(
"/items/",
response_model=Item,
summary="Create an item",
description="Create an item with all the information, name, description, price, tax and a set of unique tags",
)
async def create_item(item: Item):
async def create_item(item: Item) -> Item:
return item

4
docs_src/path_operation_configuration/tutorial004_py310.py

@ -12,8 +12,8 @@ class Item(BaseModel):
tags: set[str] = set()
@app.post("/items/", response_model=Item, summary="Create an item")
async def create_item(item: Item):
@app.post("/items/", summary="Create an item")
async def create_item(item: Item) -> Item:
"""
Create an item with all the information:

4
docs_src/path_operation_configuration/tutorial004_py39.py

@ -14,8 +14,8 @@ class Item(BaseModel):
tags: set[str] = set()
@app.post("/items/", response_model=Item, summary="Create an item")
async def create_item(item: Item):
@app.post("/items/", summary="Create an item")
async def create_item(item: Item) -> Item:
"""
Create an item with all the information:

3
docs_src/path_operation_configuration/tutorial005_py310.py

@ -14,11 +14,10 @@ class Item(BaseModel):
@app.post(
"/items/",
response_model=Item,
summary="Create an item",
response_description="The created item",
)
async def create_item(item: Item):
async def create_item(item: Item) -> Item:
"""
Create an item with all the information:

3
docs_src/path_operation_configuration/tutorial005_py39.py

@ -16,11 +16,10 @@ class Item(BaseModel):
@app.post(
"/items/",
response_model=Item,
summary="Create an item",
response_description="The created item",
)
async def create_item(item: Item):
async def create_item(item: Item) -> Item:
"""
Create an item with all the information:

4
docs_src/security/tutorial004_an_py310.py

@ -133,10 +133,10 @@ async def login_for_access_token(
return Token(access_token=access_token, token_type="bearer")
@app.get("/users/me/", response_model=User)
@app.get("/users/me/")
async def read_users_me(
current_user: Annotated[User, Depends(get_current_active_user)],
):
) -> User:
return current_user

4
docs_src/security/tutorial004_an_py39.py

@ -133,10 +133,10 @@ async def login_for_access_token(
return Token(access_token=access_token, token_type="bearer")
@app.get("/users/me/", response_model=User)
@app.get("/users/me/")
async def read_users_me(
current_user: Annotated[User, Depends(get_current_active_user)],
):
) -> User:
return current_user

4
docs_src/security/tutorial004_py310.py

@ -130,8 +130,8 @@ async def login_for_access_token(
return Token(access_token=access_token, token_type="bearer")
@app.get("/users/me/", response_model=User)
async def read_users_me(current_user: User = Depends(get_current_active_user)):
@app.get("/users/me/")
async def read_users_me(current_user: User = Depends(get_current_active_user)) -> User:
return current_user

4
docs_src/security/tutorial004_py39.py

@ -131,8 +131,8 @@ async def login_for_access_token(
return Token(access_token=access_token, token_type="bearer")
@app.get("/users/me/", response_model=User)
async def read_users_me(current_user: User = Depends(get_current_active_user)):
@app.get("/users/me/")
async def read_users_me(current_user: User = Depends(get_current_active_user)) -> User:
return current_user

4
docs_src/security/tutorial005_an_py310.py

@ -160,10 +160,10 @@ async def login_for_access_token(
return Token(access_token=access_token, token_type="bearer")
@app.get("/users/me/", response_model=User)
@app.get("/users/me/")
async def read_users_me(
current_user: Annotated[User, Depends(get_current_active_user)],
):
) -> User:
return current_user

4
docs_src/security/tutorial005_an_py39.py

@ -160,10 +160,10 @@ async def login_for_access_token(
return Token(access_token=access_token, token_type="bearer")
@app.get("/users/me/", response_model=User)
@app.get("/users/me/")
async def read_users_me(
current_user: Annotated[User, Depends(get_current_active_user)],
):
) -> User:
return current_user

4
docs_src/security/tutorial005_py310.py

@ -159,8 +159,8 @@ async def login_for_access_token(
return Token(access_token=access_token, token_type="bearer")
@app.get("/users/me/", response_model=User)
async def read_users_me(current_user: User = Depends(get_current_active_user)):
@app.get("/users/me/")
async def read_users_me(current_user: User = Depends(get_current_active_user)) -> User:
return current_user

4
docs_src/security/tutorial005_py39.py

@ -160,8 +160,8 @@ async def login_for_access_token(
return Token(access_token=access_token, token_type="bearer")
@app.get("/users/me/", response_model=User)
async def read_users_me(current_user: User = Depends(get_current_active_user)):
@app.get("/users/me/")
async def read_users_me(current_user: User = Depends(get_current_active_user)) -> User:
return current_user

2
docs_src/wsgi/tutorial001_py39.py

@ -1,5 +1,5 @@
from a2wsgi import WSGIMiddleware
from fastapi import FastAPI
from fastapi.middleware.wsgi import WSGIMiddleware
from flask import Flask, request
from markupsafe import escape

4
fastapi/_compat/shared.py

@ -17,7 +17,7 @@ from pydantic.version import VERSION as PYDANTIC_VERSION
from starlette.datastructures import UploadFile
from typing_extensions import get_args, get_origin
# Copy from Pydantic v2, compatible with v1
# Copy from Pydantic: pydantic/_internal/_typing_extra.py
if sys.version_info < (3, 10):
WithArgsTypes: tuple[Any, ...] = (typing._GenericAlias, types.GenericAlias) # type: ignore[attr-defined]
else:
@ -45,7 +45,7 @@ sequence_types = tuple(sequence_annotation_to_type.keys())
Url: type[Any]
# Copy of Pydantic v2, compatible with v1
# Copy of Pydantic: pydantic/_internal/_utils.py
def lenient_issubclass(
cls: Any, class_or_tuple: Union[type[Any], tuple[type[Any], ...], None]
) -> bool:

8
fastapi/_compat/v2.py

@ -477,7 +477,7 @@ def get_model_fields(model: type[BaseModel]) -> list[ModelField]:
@lru_cache
def get_cached_model_fields(model: type[BaseModel]) -> list[ModelField]:
return get_model_fields(model) # type: ignore[return-value]
return get_model_fields(model)
# Duplicate of several schema functions from Pydantic v1 to make them compatible with
@ -500,13 +500,13 @@ def get_model_name_map(unique_models: TypeModelSet) -> dict[TypeModelOrEnum, str
def get_compat_model_name_map(fields: list[ModelField]) -> ModelNameMap:
all_flat_models = set()
all_flat_models: TypeModelSet = set()
v2_model_fields = [field for field in fields if isinstance(field, ModelField)]
v2_flat_models = get_flat_models_from_fields(v2_model_fields, known_models=set())
all_flat_models = all_flat_models.union(v2_flat_models) # type: ignore[arg-type]
all_flat_models = all_flat_models.union(v2_flat_models)
model_name_map = get_model_name_map(all_flat_models) # type: ignore[arg-type]
model_name_map = get_model_name_map(all_flat_models)
return model_name_map

7
fastapi/applications.py

@ -672,7 +672,7 @@ class FastAPI(Starlette):
in the autogenerated OpenAPI using the `root_path`.
Read more about it in the
[FastAPI docs for Behind a Proxy](https://fastapi.tiangolo.com/advanced/behind-a-proxy/#disable-automatic-server-from-root_path).
[FastAPI docs for Behind a Proxy](https://fastapi.tiangolo.com/advanced/behind-a-proxy/#disable-automatic-server-from-root-path).
**Example**
@ -739,7 +739,7 @@ class FastAPI(Starlette):
It will be added to the generated OpenAPI (e.g. visible at `/docs`).
Read more about it in the
[FastAPI docs for Path Operation Configuration](https://fastapi.tiangolo.com/tutorial/path-operation-configuration/).
[FastAPI docs for Path Operation Configuration](https://fastapi.tiangolo.com/tutorial/path-operation-configuration/#deprecate-a-path-operation).
"""
),
] = None,
@ -812,6 +812,9 @@ class FastAPI(Starlette):
In this case, there would be two different schemas, one for input and
another one for output.
Read more about it in the
[FastAPI docs about how to separate schemas for input and output](https://fastapi.tiangolo.com/how-to/separate-openapi-schemas)
"""
),
] = True,

13
fastapi/dependencies/utils.py

@ -204,7 +204,12 @@ def _get_signature(call: Callable[..., Any]) -> inspect.Signature:
except NameError:
# Handle type annotations with if TYPE_CHECKING, not used by FastAPI
# e.g. dependency return types
signature = inspect.signature(call)
if sys.version_info >= (3, 14):
from annotationlib import Format
signature = inspect.signature(call, annotation_format=Format.FORWARDREF)
else:
signature = inspect.signature(call)
else:
signature = inspect.signature(call)
return signature
@ -399,7 +404,7 @@ def analyze_param(
if isinstance(fastapi_annotation, FieldInfo):
# Copy `field_info` because we mutate `field_info.default` below.
field_info = copy_field_info(
field_info=fastapi_annotation, # type: ignore[arg-type]
field_info=fastapi_annotation,
annotation=use_annotation,
)
assert (
@ -433,7 +438,7 @@ def analyze_param(
"Cannot specify FastAPI annotations in `Annotated` and default value"
f" together for {param_name!r}"
)
field_info = value # type: ignore[assignment]
field_info = value
if isinstance(field_info, FieldInfo):
field_info.annotation = type_annotation
@ -520,7 +525,7 @@ def analyze_param(
# For Pydantic v1
and getattr(field, "shape", 1) == 1
)
)
), f"Query parameter {param_name!r} must be one of the supported types"
return ParamDetails(type_annotation=type_annotation, depends=depends, field=field)

4
fastapi/encoders.py

@ -219,9 +219,9 @@ def jsonable_encoder(
if isinstance(obj, encoder_type):
return encoder_instance(obj)
if include is not None and not isinstance(include, (set, dict)):
include = set(include)
include = set(include) # type: ignore[assignment]
if exclude is not None and not isinstance(exclude, (set, dict)):
exclude = set(exclude)
exclude = set(exclude) # type: ignore[assignment]
if isinstance(obj, BaseModel):
obj_dict = obj.model_dump(
mode="json",

10
fastapi/exceptions.py

@ -49,6 +49,9 @@ class HTTPException(StarletteHTTPException):
Doc(
"""
HTTP status code to send to the client.
Read more about it in the
[FastAPI docs for Handling Errors](https://fastapi.tiangolo.com/tutorial/handling-errors/#use-httpexception)
"""
),
],
@ -58,6 +61,9 @@ class HTTPException(StarletteHTTPException):
"""
Any data to be sent to the client in the `detail` key of the JSON
response.
Read more about it in the
[FastAPI docs for Handling Errors](https://fastapi.tiangolo.com/tutorial/handling-errors/#use-httpexception)
"""
),
] = None,
@ -66,6 +72,10 @@ class HTTPException(StarletteHTTPException):
Doc(
"""
Any headers to send to the client in the response.
Read more about it in the
[FastAPI docs for Handling Errors](https://fastapi.tiangolo.com/tutorial/handling-errors/#add-custom-headers)
"""
),
] = None,

4
fastapi/middleware/wsgi.py

@ -1 +1,3 @@
from starlette.middleware.wsgi import WSGIMiddleware as WSGIMiddleware # noqa
from starlette.middleware.wsgi import (
WSGIMiddleware as WSGIMiddleware,
) # pragma: no cover # noqa

31
fastapi/openapi/docs.py

@ -33,6 +33,9 @@ def get_swagger_ui_html(
This is normally done automatically by FastAPI using the default URL
`/openapi.json`.
Read more about it in the
[FastAPI docs for Conditional OpenAPI](https://fastapi.tiangolo.com/how-to/conditional-openapi/#conditional-openapi-from-settings-and-env-vars)
"""
),
],
@ -41,6 +44,9 @@ def get_swagger_ui_html(
Doc(
"""
The HTML `<title>` content, normally shown in the browser tab.
Read more about it in the
[FastAPI docs for Custom Docs UI Static Assets](https://fastapi.tiangolo.com/how-to/custom-docs-ui-assets/)
"""
),
],
@ -51,6 +57,9 @@ def get_swagger_ui_html(
The URL to use to load the Swagger UI JavaScript.
It is normally set to a CDN URL.
Read more about it in the
[FastAPI docs for Custom Docs UI Static Assets](https://fastapi.tiangolo.com/how-to/custom-docs-ui-assets/)
"""
),
] = "https://cdn.jsdelivr.net/npm/swagger-ui-dist@5/swagger-ui-bundle.js",
@ -61,6 +70,9 @@ def get_swagger_ui_html(
The URL to use to load the Swagger UI CSS.
It is normally set to a CDN URL.
Read more about it in the
[FastAPI docs for Custom Docs UI Static Assets](https://fastapi.tiangolo.com/how-to/custom-docs-ui-assets/)
"""
),
] = "https://cdn.jsdelivr.net/npm/swagger-ui-dist@5/swagger-ui.css",
@ -77,6 +89,9 @@ def get_swagger_ui_html(
Doc(
"""
The OAuth2 redirect URL, it is normally automatically handled by FastAPI.
Read more about it in the
[FastAPI docs for Custom Docs UI Static Assets](https://fastapi.tiangolo.com/how-to/custom-docs-ui-assets/)
"""
),
] = None,
@ -85,6 +100,9 @@ def get_swagger_ui_html(
Doc(
"""
A dictionary with Swagger UI OAuth2 initialization configurations.
Read more about the available configuration options in the
[Swagger UI docs](https://swagger.io/docs/open-source-tools/swagger-ui/usage/oauth2/).
"""
),
] = None,
@ -95,6 +113,9 @@ def get_swagger_ui_html(
Configuration parameters for Swagger UI.
It defaults to [swagger_ui_default_parameters][fastapi.openapi.docs.swagger_ui_default_parameters].
Read more about it in the
[FastAPI docs about how to Configure Swagger UI](https://fastapi.tiangolo.com/how-to/configure-swagger-ui/).
"""
),
] = None,
@ -118,6 +139,7 @@ def get_swagger_ui_html(
<!DOCTYPE html>
<html>
<head>
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link type="text/css" rel="stylesheet" href="{swagger_css_url}">
<link rel="shortcut icon" href="{swagger_favicon_url}">
<title>{title}</title>
@ -168,6 +190,9 @@ def get_redoc_html(
This is normally done automatically by FastAPI using the default URL
`/openapi.json`.
Read more about it in the
[FastAPI docs for Conditional OpenAPI](https://fastapi.tiangolo.com/how-to/conditional-openapi/#conditional-openapi-from-settings-and-env-vars)
"""
),
],
@ -176,6 +201,9 @@ def get_redoc_html(
Doc(
"""
The HTML `<title>` content, normally shown in the browser tab.
Read more about it in the
[FastAPI docs for Custom Docs UI Static Assets](https://fastapi.tiangolo.com/how-to/custom-docs-ui-assets/)
"""
),
],
@ -186,6 +214,9 @@ def get_redoc_html(
The URL to use to load the ReDoc JavaScript.
It is normally set to a CDN URL.
Read more about it in the
[FastAPI docs for Custom Docs UI Static Assets](https://fastapi.tiangolo.com/how-to/custom-docs-ui-assets/)
"""
),
] = "https://cdn.jsdelivr.net/npm/redoc@2/bundles/redoc.standalone.js",

3
fastapi/openapi/utils.py

@ -1,3 +1,4 @@
import copy
import http.client
import inspect
import warnings
@ -377,7 +378,7 @@ def get_openapi_path(
additional_status_code,
additional_response,
) in route.responses.items():
process_response = additional_response.copy()
process_response = copy.deepcopy(additional_response)
process_response.pop("model", None)
status_code_key = str(additional_status_code).upper()
if status_code_key == "DEFAULT":

94
fastapi/param_functions.py

@ -79,6 +79,9 @@ def Path( # noqa: N802
Doc(
"""
Human-readable title.
Read more about it in the
[FastAPI docs for Path Parameters and Numeric Validations](https://fastapi.tiangolo.com/tutorial/path-params-numeric-validations/#declare-metadata)
"""
),
] = None,
@ -96,6 +99,9 @@ def Path( # noqa: N802
"""
Greater than. If set, value must be greater than this. Only applicable to
numbers.
Read more about it in the
[FastAPI docs about Path parameters numeric validations](https://fastapi.tiangolo.com/tutorial/path-params-numeric-validations/#number-validations-greater-than-and-less-than-or-equal)
"""
),
] = None,
@ -105,6 +111,9 @@ def Path( # noqa: N802
"""
Greater than or equal. If set, value must be greater than or equal to
this. Only applicable to numbers.
Read more about it in the
[FastAPI docs about Path parameters numeric validations](https://fastapi.tiangolo.com/tutorial/path-params-numeric-validations/#number-validations-greater-than-and-less-than-or-equal)
"""
),
] = None,
@ -113,6 +122,9 @@ def Path( # noqa: N802
Doc(
"""
Less than. If set, value must be less than this. Only applicable to numbers.
Read more about it in the
[FastAPI docs about Path parameters numeric validations](https://fastapi.tiangolo.com/tutorial/path-params-numeric-validations/#number-validations-greater-than-and-less-than-or-equal)
"""
),
] = None,
@ -122,6 +134,9 @@ def Path( # noqa: N802
"""
Less than or equal. If set, value must be less than or equal to this.
Only applicable to numbers.
Read more about it in the
[FastAPI docs about Path parameters numeric validations](https://fastapi.tiangolo.com/tutorial/path-params-numeric-validations/#number-validations-greater-than-and-less-than-or-equal)
"""
),
] = None,
@ -213,6 +228,9 @@ def Path( # noqa: N802
Doc(
"""
Example values for this field.
Read more about it in the
[FastAPI docs for Declare Request Example Data](https://fastapi.tiangolo.com/tutorial/schema-extra-example/)
"""
),
] = None,
@ -343,6 +361,9 @@ def Query( # noqa: N802
Doc(
"""
Default value if the parameter field is not set.
Read more about it in the
[FastAPI docs about Query parameters](https://fastapi.tiangolo.com/tutorial/query-params-str-validations/#alternative-old-query-as-the-default-value)
"""
),
] = Undefined,
@ -367,6 +388,9 @@ def Query( # noqa: N802
This will be used to extract the data and for the generated OpenAPI.
It is particularly useful when you can't use the name you want because it
is a Python reserved keyword or similar.
Read more about it in the
[FastAPI docs about Query parameters](https://fastapi.tiangolo.com/tutorial/query-params-str-validations/#alias-parameters)
"""
),
] = None,
@ -402,6 +426,9 @@ def Query( # noqa: N802
Doc(
"""
Human-readable title.
Read more about it in the
[FastAPI docs about Query parameters](https://fastapi.tiangolo.com/tutorial/query-params-str-validations/#declare-more-metadata)
"""
),
] = None,
@ -410,6 +437,9 @@ def Query( # noqa: N802
Doc(
"""
Human-readable description.
Read more about it in the
[FastAPI docs about Query parameters](https://fastapi.tiangolo.com/tutorial/query-params-str-validations/#declare-more-metadata)
"""
),
] = None,
@ -419,6 +449,9 @@ def Query( # noqa: N802
"""
Greater than. If set, value must be greater than this. Only applicable to
numbers.
Read more about it in the
[FastAPI docs about Path parameters numeric validations](https://fastapi.tiangolo.com/tutorial/path-params-numeric-validations/#number-validations-greater-than-and-less-than-or-equal)
"""
),
] = None,
@ -428,6 +461,9 @@ def Query( # noqa: N802
"""
Greater than or equal. If set, value must be greater than or equal to
this. Only applicable to numbers.
Read more about it in the
[FastAPI docs about Path parameters numeric validations](https://fastapi.tiangolo.com/tutorial/path-params-numeric-validations/#number-validations-greater-than-and-less-than-or-equal)
"""
),
] = None,
@ -436,6 +472,9 @@ def Query( # noqa: N802
Doc(
"""
Less than. If set, value must be less than this. Only applicable to numbers.
Read more about it in the
[FastAPI docs about Path parameters numeric validations](https://fastapi.tiangolo.com/tutorial/path-params-numeric-validations/#number-validations-greater-than-and-less-than-or-equal)
"""
),
] = None,
@ -445,6 +484,9 @@ def Query( # noqa: N802
"""
Less than or equal. If set, value must be less than or equal to this.
Only applicable to numbers.
Read more about it in the
[FastAPI docs about Path parameters numeric validations](https://fastapi.tiangolo.com/tutorial/path-params-numeric-validations/#number-validations-greater-than-and-less-than-or-equal)
"""
),
] = None,
@ -453,6 +495,9 @@ def Query( # noqa: N802
Doc(
"""
Minimum length for strings.
Read more about it in the
[FastAPI docs about Query parameters](https://fastapi.tiangolo.com/tutorial/query-params-str-validations/)
"""
),
] = None,
@ -461,6 +506,9 @@ def Query( # noqa: N802
Doc(
"""
Maximum length for strings.
Read more about it in the
[FastAPI docs about Query parameters](https://fastapi.tiangolo.com/tutorial/query-params-str-validations/)
"""
),
] = None,
@ -469,6 +517,9 @@ def Query( # noqa: N802
Doc(
"""
RegEx pattern for strings.
Read more about it in the
[FastAPI docs about Query parameters](https://fastapi.tiangolo.com/tutorial/query-params-str-validations/#add-regular-expressions
"""
),
] = None,
@ -536,6 +587,9 @@ def Query( # noqa: N802
Doc(
"""
Example values for this field.
Read more about it in the
[FastAPI docs for Declare Request Example Data](https://fastapi.tiangolo.com/tutorial/schema-extra-example/)
"""
),
] = None,
@ -570,6 +624,9 @@ def Query( # noqa: N802
Mark this parameter field as deprecated.
It will affect the generated OpenAPI (e.g. visible at `/docs`).
Read more about it in the
[FastAPI docs about Query parameters](https://fastapi.tiangolo.com/tutorial/query-params-str-validations/#deprecating-parameters)
"""
),
] = None,
@ -581,6 +638,9 @@ def Query( # noqa: N802
You probably don't need it, but it's available.
This affects the generated OpenAPI (e.g. visible at `/docs`).
Read more about it in the
[FastAPI docs about Query parameters](https://fastapi.tiangolo.com/tutorial/query-params-str-validations/#exclude-parameters-from-openapi
"""
),
] = True,
@ -849,6 +909,9 @@ def Header( # noqa: N802
Doc(
"""
Example values for this field.
Read more about it in the
[FastAPI docs for Declare Request Example Data](https://fastapi.tiangolo.com/tutorial/schema-extra-example/)
"""
),
] = None,
@ -1152,6 +1215,9 @@ def Cookie( # noqa: N802
Doc(
"""
Example values for this field.
Read more about it in the
[FastAPI docs for Declare Request Example Data](https://fastapi.tiangolo.com/tutorial/schema-extra-example/)
"""
),
] = None,
@ -1477,6 +1543,9 @@ def Body( # noqa: N802
Doc(
"""
Example values for this field.
Read more about it in the
[FastAPI docs for Declare Request Example Data](https://fastapi.tiangolo.com/tutorial/schema-extra-example/)
"""
),
] = None,
@ -1790,6 +1859,9 @@ def Form( # noqa: N802
Doc(
"""
Example values for this field.
Read more about it in the
[FastAPI docs for Declare Request Example Data](https://fastapi.tiangolo.com/tutorial/schema-extra-example/)
"""
),
] = None,
@ -2102,6 +2174,9 @@ def File( # noqa: N802
Doc(
"""
Example values for this field.
Read more about it in the
[FastAPI docs for Declare Request Example Data](https://fastapi.tiangolo.com/tutorial/schema-extra-example/)
"""
),
] = None,
@ -2215,6 +2290,9 @@ def Depends( # noqa: N802
Don't call it directly, FastAPI will call it for you, just pass the object
directly.
Read more about it in the
[FastAPI docs for Dependencies](https://fastapi.tiangolo.com/tutorial/dependencies/)
"""
),
] = None,
@ -2230,6 +2308,9 @@ def Depends( # noqa: N802
Set `use_cache` to `False` to disable this behavior and ensure the
dependency is called again (if declared more than once) in the same request.
Read more about it in the
[FastAPI docs about sub-dependencies](https://fastapi.tiangolo.com/tutorial/dependencies/sub-dependencies/#using-the-same-dependency-multiple-times)
"""
),
] = True,
@ -2250,6 +2331,9 @@ def Depends( # noqa: N802
that handles the request (similar to when using `"function"`), but end
**after** the response is sent back to the client. So, the dependency
function will be executed **around** the **request** and response cycle.
Read more about it in the
[FastAPI docs for FastAPI Dependencies with yield](https://fastapi.tiangolo.com/tutorial/dependencies/dependencies-with-yield/#early-exit-and-scope)
"""
),
] = None,
@ -2295,6 +2379,9 @@ def Security( # noqa: N802
Don't call it directly, FastAPI will call it for you, just pass the object
directly.
Read more about it in the
[FastAPI docs for Dependencies](https://fastapi.tiangolo.com/tutorial/dependencies/)
"""
),
] = None,
@ -2312,7 +2399,9 @@ def Security( # noqa: N802
These scopes are integrated with OpenAPI (and the API docs at `/docs`).
So they are visible in the OpenAPI specification.
)
Read more about it in the
[FastAPI docs about OAuth2 scopes](https://fastapi.tiangolo.com/advanced/security/oauth2-scopes/)
"""
),
] = None,
@ -2327,6 +2416,9 @@ def Security( # noqa: N802
Set `use_cache` to `False` to disable this behavior and ensure the
dependency is called again (if declared more than once) in the same request.
Read more about it in the
[FastAPI docs about sub-dependencies](https://fastapi.tiangolo.com/tutorial/dependencies/sub-dependencies/#using-the-same-dependency-multiple-times)
"""
),
] = True,

30
fastapi/security/oauth2.py

@ -68,6 +68,9 @@ class OAuth2PasswordRequestForm:
"password". Nevertheless, this dependency class is permissive and
allows not passing it. If you want to enforce it, use instead the
`OAuth2PasswordRequestFormStrict` dependency.
Read more about it in the
[FastAPI docs for Simple OAuth2 with Password and Bearer](https://fastapi.tiangolo.com/tutorial/security/simple-oauth2/).
"""
),
] = None,
@ -78,6 +81,9 @@ class OAuth2PasswordRequestForm:
"""
`username` string. The OAuth2 spec requires the exact field name
`username`.
Read more about it in the
[FastAPI docs for Simple OAuth2 with Password and Bearer](https://fastapi.tiangolo.com/tutorial/security/simple-oauth2/).
"""
),
],
@ -88,6 +94,9 @@ class OAuth2PasswordRequestForm:
"""
`password` string. The OAuth2 spec requires the exact field name
`password`.
Read more about it in the
[FastAPI docs for Simple OAuth2 with Password and Bearer](https://fastapi.tiangolo.com/tutorial/security/simple-oauth2/).
"""
),
],
@ -112,6 +121,9 @@ class OAuth2PasswordRequestForm:
* `users:read`
* `profile`
* `openid`
Read more about it in the
[FastAPI docs for Simple OAuth2 with Password and Bearer](https://fastapi.tiangolo.com/tutorial/security/simple-oauth2/).
"""
),
] = "",
@ -222,6 +234,9 @@ class OAuth2PasswordRequestFormStrict(OAuth2PasswordRequestForm):
"password". This dependency is strict about it. If you want to be
permissive, use instead the `OAuth2PasswordRequestForm` dependency
class.
Read more about it in the
[FastAPI docs for Simple OAuth2 with Password and Bearer](https://fastapi.tiangolo.com/tutorial/security/simple-oauth2/).
"""
),
],
@ -232,6 +247,9 @@ class OAuth2PasswordRequestFormStrict(OAuth2PasswordRequestForm):
"""
`username` string. The OAuth2 spec requires the exact field name
`username`.
Read more about it in the
[FastAPI docs for Simple OAuth2 with Password and Bearer](https://fastapi.tiangolo.com/tutorial/security/simple-oauth2/).
"""
),
],
@ -242,6 +260,9 @@ class OAuth2PasswordRequestFormStrict(OAuth2PasswordRequestForm):
"""
`password` string. The OAuth2 spec requires the exact field name
`password`.
Read more about it in the
[FastAPI docs for Simple OAuth2 with Password and Bearer](https://fastapi.tiangolo.com/tutorial/security/simple-oauth2/).
"""
),
],
@ -266,6 +287,9 @@ class OAuth2PasswordRequestFormStrict(OAuth2PasswordRequestForm):
* `users:read`
* `profile`
* `openid`
Read more about it in the
[FastAPI docs for Simple OAuth2 with Password and Bearer](https://fastapi.tiangolo.com/tutorial/security/simple-oauth2/).
"""
),
] = "",
@ -423,6 +447,9 @@ class OAuth2PasswordBearer(OAuth2):
"""
The URL to obtain the OAuth2 token. This would be the *path operation*
that has `OAuth2PasswordRequestForm` as a dependency.
Read more about it in the
[FastAPI docs for Simple OAuth2 with Password and Bearer](https://fastapi.tiangolo.com/tutorial/security/simple-oauth2/).
"""
),
],
@ -442,6 +469,9 @@ class OAuth2PasswordBearer(OAuth2):
"""
The OAuth2 scopes that would be required by the *path operations* that
use this dependency.
Read more about it in the
[FastAPI docs for Simple OAuth2 with Password and Bearer](https://fastapi.tiangolo.com/tutorial/security/simple-oauth2/).
"""
),
] = None,

2
fastapi/security/utils.py

@ -7,4 +7,4 @@ def get_authorization_scheme_param(
if not authorization_header_value:
return "", ""
scheme, _, param = authorization_header_value.partition(" ")
return scheme, param
return scheme, param.strip()

2
fastapi/types.py

@ -3,9 +3,9 @@ from enum import Enum
from typing import Any, Callable, Optional, TypeVar, Union
from pydantic import BaseModel
from pydantic.main import IncEx as IncEx
DecoratedCallable = TypeVar("DecoratedCallable", bound=Callable[..., Any])
UnionType = getattr(types, "UnionType", Union)
ModelNameMap = dict[Union[type[BaseModel], type[Enum]], str]
IncEx = Union[set[int], set[str], dict[int, Any], dict[str, Any]]
DependencyCacheKey = tuple[Optional[Callable[..., Any]], tuple[str, ...], str]

2
fastapi/utils.py

@ -90,7 +90,7 @@ def create_model_field(
field_info = field_info or FieldInfo(annotation=type_, default=default, alias=alias)
kwargs = {"mode": mode, "name": name, "field_info": field_info}
try:
return v2.ModelField(**kwargs) # type: ignore[return-value,arg-type]
return v2.ModelField(**kwargs) # type: ignore[arg-type]
except PydanticSchemaGenerationError:
raise fastapi.exceptions.FastAPIError(
_invalid_args_message.format(type_=type_)

12
pyproject.toml

@ -140,18 +140,18 @@ docs = [
"jieba==0.42.1",
"markdown-include-variants==0.0.8",
"mdx-include>=1.4.1,<2.0.0",
"mkdocs-macros-plugin==1.4.1",
"mkdocs-macros-plugin==1.5.0",
"mkdocs-material==9.7.0",
"mkdocs-redirects>=1.2.1,<1.3.0",
"mkdocstrings[python]==0.30.1",
"pillow==11.3.0",
"python-slugify==8.0.4",
"pyyaml>=5.3.1,<7.0.0",
"typer==0.16.0",
"typer==0.21.1",
]
docs-tests = [
"httpx>=0.23.0,<1.0.0",
"ruff==0.14.3",
"ruff==0.14.14",
]
github-actions = [
"httpx>=0.27.0,<1.0.0",
@ -174,13 +174,14 @@ tests = [
"pytest>=7.1.3,<9.0.0",
"pytest-codspeed==4.2.0",
"pyyaml>=5.3.1,<7.0.0",
"sqlmodel==0.0.27",
"sqlmodel==0.0.31",
"strawberry-graphql>=0.200.0,<1.0.0",
"types-orjson==3.6.2",
"types-ujson==5.10.0.20240515",
"a2wsgi>=1.9.0,<=2.0.0",
]
translations = [
"gitpython==3.1.45",
"gitpython==3.1.46",
"pydantic-ai==0.4.10",
"pygithub==2.8.1",
]
@ -231,7 +232,6 @@ xfail_strict = true
junit_family = "xunit2"
filterwarnings = [
"error",
'ignore:starlette.middleware.wsgi is deprecated and will be removed in a future release\..*:DeprecationWarning:starlette',
# 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",
# TODO: remove after upgrading SQLAlchemy to a version that includes the following changes

30
scripts/mkdocs_hooks.py

@ -26,6 +26,17 @@ def get_missing_translation_content(docs_dir: str) -> str:
return missing_translation_path.read_text(encoding="utf-8")
@lru_cache
def get_translation_banner_content(docs_dir: str) -> str:
docs_dir_path = Path(docs_dir)
translation_banner_path = docs_dir_path / "translation-banner.md"
if not translation_banner_path.is_file():
translation_banner_path = (
docs_dir_path.parent.parent / "en" / "docs" / "translation-banner.md"
)
return translation_banner_path.read_text(encoding="utf-8")
@lru_cache
def get_mkdocs_material_langs() -> list[str]:
material_path = Path(material.__file__).parent
@ -151,4 +162,21 @@ def on_page_markdown(
if markdown.startswith("#"):
header, _, body = markdown.partition("\n\n")
return f"{header}\n\n{missing_translation_content}\n\n{body}"
return markdown
docs_dir_path = Path(config.docs_dir)
en_docs_dir_path = docs_dir_path.parent.parent / "en/docs"
if docs_dir_path == en_docs_dir_path:
return markdown
# For translated pages add translation banner
translation_banner_content = get_translation_banner_content(config.docs_dir)
en_url = "https://fastapi.tiangolo.com/" + page.url.lstrip("/")
translation_banner_content = translation_banner_content.replace(
"ENGLISH_VERSION_URL", en_url
)
header = ""
body = markdown
if markdown.startswith("#"):
header, _, body = markdown.partition("\n\n")
return f"{header}\n\n{translation_banner_content}\n\n{body}"

28
scripts/translate.py

@ -10,6 +10,7 @@ from typing import Annotated
import git
import typer
import yaml
from doc_parsing_utils import check_translation
from github import Github
from pydantic_ai import Agent
from rich import print
@ -119,9 +120,30 @@ def translate_page(
]
)
prompt = "\n\n".join(prompt_segments)
print(f"Running agent for {out_path}")
result = agent.run_sync(prompt)
out_content = f"{result.output.strip()}\n"
MAX_ATTEMPTS = 3
for attempt_no in range(1, MAX_ATTEMPTS + 1):
print(f"Running agent for {out_path} (attempt {attempt_no}/{MAX_ATTEMPTS})")
result = agent.run_sync(prompt)
out_content = f"{result.output.strip()}\n"
try:
check_translation(
doc_lines=out_content.splitlines(),
en_doc_lines=original_content.splitlines(),
lang_code=language,
auto_fix=False,
path=str(out_path),
)
break # Exit loop if no errors
except ValueError as e:
print(
f"Translation check failed on attempt {attempt_no}/{MAX_ATTEMPTS}: {e}"
)
continue # Retry if not reached max attempts
else: # Max retry attempts reached
print(f"Translation failed for {out_path} after {MAX_ATTEMPTS} attempts")
raise typer.Exit(code=1)
print(f"Saving translation to {out_path}")
out_path.write_text(out_content, encoding="utf-8", newline="\n")

123
tests/test_additional_responses_union_duplicate_anyof.py

@ -0,0 +1,123 @@
"""
Regression test: Ensure app-level responses with Union models and content/examples
don't accumulate duplicate $ref entries in anyOf arrays.
See https://github.com/fastapi/fastapi/pull/14463
"""
from typing import Union
from fastapi import FastAPI
from fastapi.testclient import TestClient
from pydantic import BaseModel
class ModelA(BaseModel):
a: str
class ModelB(BaseModel):
b: str
app = FastAPI(
responses={
500: {
"model": Union[ModelA, ModelB],
"content": {"application/json": {"examples": {"Case A": {"value": "a"}}}},
}
}
)
@app.get("/route1")
async def route1():
pass # pragma: no cover
@app.get("/route2")
async def route2():
pass # pragma: no cover
client = TestClient(app)
def test_openapi_schema():
response = client.get("/openapi.json")
assert response.status_code == 200, response.text
assert response.json() == {
"openapi": "3.1.0",
"info": {"title": "FastAPI", "version": "0.1.0"},
"paths": {
"/route1": {
"get": {
"summary": "Route1",
"operationId": "route1_route1_get",
"responses": {
"200": {
"description": "Successful Response",
"content": {"application/json": {"schema": {}}},
},
"500": {
"description": "Internal Server Error",
"content": {
"application/json": {
"schema": {
"anyOf": [
{"$ref": "#/components/schemas/ModelA"},
{"$ref": "#/components/schemas/ModelB"},
],
"title": "Response 500 Route1 Route1 Get",
},
"examples": {"Case A": {"value": "a"}},
}
},
},
},
}
},
"/route2": {
"get": {
"summary": "Route2",
"operationId": "route2_route2_get",
"responses": {
"200": {
"description": "Successful Response",
"content": {"application/json": {"schema": {}}},
},
"500": {
"description": "Internal Server Error",
"content": {
"application/json": {
"schema": {
"anyOf": [
{"$ref": "#/components/schemas/ModelA"},
{"$ref": "#/components/schemas/ModelB"},
],
"title": "Response 500 Route2 Route2 Get",
},
"examples": {"Case A": {"value": "a"}},
}
},
},
},
}
},
},
"components": {
"schemas": {
"ModelA": {
"properties": {"a": {"type": "string", "title": "A"}},
"type": "object",
"required": ["a"],
"title": "ModelA",
},
"ModelB": {
"properties": {"b": {"type": "string", "title": "B"}},
"type": "object",
"required": ["b"],
"title": "ModelB",
},
}
},
}

20
tests/test_invalid_sequence_param.py

@ -6,7 +6,10 @@ from pydantic import BaseModel
def test_invalid_sequence():
with pytest.raises(AssertionError):
with pytest.raises(
AssertionError,
match="Query parameter 'q' must be one of the supported types",
):
app = FastAPI()
class Item(BaseModel):
@ -18,7 +21,10 @@ def test_invalid_sequence():
def test_invalid_tuple():
with pytest.raises(AssertionError):
with pytest.raises(
AssertionError,
match="Query parameter 'q' must be one of the supported types",
):
app = FastAPI()
class Item(BaseModel):
@ -30,7 +36,10 @@ def test_invalid_tuple():
def test_invalid_dict():
with pytest.raises(AssertionError):
with pytest.raises(
AssertionError,
match="Query parameter 'q' must be one of the supported types",
):
app = FastAPI()
class Item(BaseModel):
@ -42,7 +51,10 @@ def test_invalid_dict():
def test_invalid_simple_dict():
with pytest.raises(AssertionError):
with pytest.raises(
AssertionError,
match="Query parameter 'q' must be one of the supported types",
):
app = FastAPI()
class Item(BaseModel):

6
tests/test_security_http_base.py

@ -21,6 +21,12 @@ def test_security_http_base():
assert response.json() == {"scheme": "Other", "credentials": "foobar"}
def test_security_http_base_with_whitespaces():
response = client.get("/users/me", headers={"Authorization": "Other foobar "})
assert response.status_code == 200, response.text
assert response.json() == {"scheme": "Other", "credentials": "foobar"}
def test_security_http_base_no_credentials():
response = client.get("/users/me")
assert response.status_code == 401, response.text

6
tests/test_security_oauth2_authorization_code_bearer.py

@ -37,6 +37,12 @@ def test_token():
assert response.json() == {"token": "testtoken"}
def test_token_with_whitespaces():
response = client.get("/items", headers={"Authorization": "Bearer testtoken "})
assert response.status_code == 200, response.text
assert response.json() == {"token": "testtoken"}
def test_openapi_schema():
response = client.get("/openapi.json")
assert response.status_code == 200, response.text

30
tests/test_stringified_annotation_dependency_py314.py

@ -0,0 +1,30 @@
from typing import TYPE_CHECKING, Annotated
from fastapi import Depends, FastAPI
from fastapi.testclient import TestClient
from .utils import needs_py314
if TYPE_CHECKING: # pragma: no cover
class DummyUser: ...
@needs_py314
def test_stringified_annotation():
# python3.14: Use forward reference without "from __future__ import annotations"
async def get_current_user() -> DummyUser | None:
return None
app = FastAPI()
client = TestClient(app)
@app.get("/")
async def get(
current_user: Annotated[DummyUser | None, Depends(get_current_user)],
) -> str:
return "hello world"
response = client.get("/")
assert response.status_code == 200

10
tests/test_tutorial/test_dependencies/test_tutorial008.py

@ -1,4 +1,5 @@
import importlib
import sys
from types import ModuleType
from typing import Annotated, Any
from unittest.mock import Mock, patch
@ -12,8 +13,13 @@ from fastapi.testclient import TestClient
name="module",
params=[
"tutorial008_py39",
# Fails with `NameError: name 'DepA' is not defined`
pytest.param("tutorial008_an_py39", marks=pytest.mark.xfail),
pytest.param(
"tutorial008_an_py39",
marks=pytest.mark.xfail(
sys.version_info < (3, 14),
reason="Fails with `NameError: name 'DepA' is not defined`",
),
),
],
)
def get_module(request: pytest.FixtureRequest):

2
tests/test_tutorial/test_metadata/test_tutorial001_1.py

@ -28,7 +28,7 @@ def test_openapi_schema():
},
"license": {
"name": "Apache 2.0",
"identifier": "MIT",
"identifier": "Apache-2.0",
},
"version": "0.0.1",
},

4
tests/utils.py

@ -6,8 +6,8 @@ needs_py39 = pytest.mark.skipif(sys.version_info < (3, 9), reason="requires pyth
needs_py310 = pytest.mark.skipif(
sys.version_info < (3, 10), reason="requires python3.10+"
)
needs_py_lt_314 = pytest.mark.skipif(
sys.version_info >= (3, 14), reason="requires python3.13-"
needs_py314 = pytest.mark.skipif(
sys.version_info < (3, 14), reason="requires python3.14+"
)

114
uv.lock

@ -7,6 +7,18 @@ resolution-markers = [
"python_full_version < '3.10'",
]
[[package]]
name = "a2wsgi"
version = "1.10.10"
source = { registry = "https://pypi.org/simple" }
dependencies = [
{ name = "typing-extensions", marker = "python_full_version < '3.11'" },
]
sdist = { url = "https://files.pythonhosted.org/packages/9a/cb/822c56fbea97e9eee201a2e434a80437f6750ebcb1ed307ee3a0a7505b14/a2wsgi-1.10.10.tar.gz", hash = "sha256:a5bcffb52081ba39df0d5e9a884fc6f819d92e3a42389343ba77cbf809fe1f45", size = 18799, upload-time = "2025-06-18T09:00:10.843Z" }
wheels = [
{ url = "https://files.pythonhosted.org/packages/02/d5/349aba3dc421e73cbd4958c0ce0a4f1aa3a738bc0d7de75d2f40ed43a535/a2wsgi-1.10.10-py3-none-any.whl", hash = "sha256:d2b21379479718539dc15fce53b876251a0efe7615352dfe49f6ad1bc507848d", size = 17389, upload-time = "2025-06-18T09:00:09.676Z" },
]
[[package]]
name = "ag-ui-protocol"
version = "0.1.10"
@ -1058,6 +1070,7 @@ standard-no-fastapi-cloud-cli = [
[package.dev-dependencies]
dev = [
{ name = "a2wsgi" },
{ name = "anyio", extra = ["trio"] },
{ name = "black" },
{ name = "cairosvg" },
@ -1131,6 +1144,7 @@ github-actions = [
{ name = "smokeshow" },
]
tests = [
{ name = "a2wsgi" },
{ name = "anyio", extra = ["trio"] },
{ name = "coverage", version = "7.10.7", source = { registry = "https://pypi.org/simple" }, extra = ["toml"], marker = "python_full_version < '3.10'" },
{ name = "coverage", version = "7.13.1", source = { registry = "https://pypi.org/simple" }, extra = ["toml"], marker = "python_full_version >= '3.10'" },
@ -1197,13 +1211,14 @@ provides-extras = ["standard", "standard-no-fastapi-cloud-cli", "all"]
[package.metadata.requires-dev]
dev = [
{ name = "a2wsgi", specifier = ">=1.9.0,<=2.0.0" },
{ name = "anyio", extras = ["trio"], specifier = ">=3.2.1,<5.0.0" },
{ name = "black", specifier = "==25.1.0" },
{ name = "cairosvg", specifier = "==2.8.2" },
{ name = "coverage", extras = ["toml"], specifier = ">=6.5.0,<8.0" },
{ name = "dirty-equals", specifier = "==0.9.0" },
{ name = "flask", specifier = ">=1.1.2,<4.0.0" },
{ name = "gitpython", specifier = "==3.1.45" },
{ name = "gitpython", specifier = "==3.1.46" },
{ name = "griffe-typingdoc", specifier = "==0.3.0" },
{ name = "griffe-warnings-deprecated", specifier = "==1.1.0" },
{ name = "httpx", specifier = ">=0.23.0,<1.0.0" },
@ -1211,7 +1226,7 @@ dev = [
{ name = "jieba", specifier = "==0.42.1" },
{ name = "markdown-include-variants", specifier = "==0.0.8" },
{ name = "mdx-include", specifier = ">=1.4.1,<2.0.0" },
{ name = "mkdocs-macros-plugin", specifier = "==1.4.1" },
{ name = "mkdocs-macros-plugin", specifier = "==1.5.0" },
{ name = "mkdocs-material", specifier = "==9.7.0" },
{ name = "mkdocs-redirects", specifier = ">=1.2.1,<1.3.0" },
{ name = "mkdocstrings", extras = ["python"], specifier = "==0.30.1" },
@ -1227,10 +1242,10 @@ dev = [
{ name = "pytest-codspeed", specifier = "==4.2.0" },
{ name = "python-slugify", specifier = "==8.0.4" },
{ name = "pyyaml", specifier = ">=5.3.1,<7.0.0" },
{ name = "ruff", specifier = "==0.14.3" },
{ name = "sqlmodel", specifier = "==0.0.27" },
{ name = "ruff", specifier = "==0.14.14" },
{ name = "sqlmodel", specifier = "==0.0.31" },
{ name = "strawberry-graphql", specifier = ">=0.200.0,<1.0.0" },
{ name = "typer", specifier = "==0.16.0" },
{ name = "typer", specifier = "==0.21.1" },
{ name = "types-orjson", specifier = "==3.6.2" },
{ name = "types-ujson", specifier = "==5.10.0.20240515" },
]
@ -1243,19 +1258,19 @@ docs = [
{ name = "jieba", specifier = "==0.42.1" },
{ name = "markdown-include-variants", specifier = "==0.0.8" },
{ name = "mdx-include", specifier = ">=1.4.1,<2.0.0" },
{ name = "mkdocs-macros-plugin", specifier = "==1.4.1" },
{ name = "mkdocs-macros-plugin", specifier = "==1.5.0" },
{ name = "mkdocs-material", specifier = "==9.7.0" },
{ name = "mkdocs-redirects", specifier = ">=1.2.1,<1.3.0" },
{ name = "mkdocstrings", extras = ["python"], specifier = "==0.30.1" },
{ name = "pillow", specifier = "==11.3.0" },
{ name = "python-slugify", specifier = "==8.0.4" },
{ name = "pyyaml", specifier = ">=5.3.1,<7.0.0" },
{ name = "ruff", specifier = "==0.14.3" },
{ name = "typer", specifier = "==0.16.0" },
{ name = "ruff", specifier = "==0.14.14" },
{ name = "typer", specifier = "==0.21.1" },
]
docs-tests = [
{ name = "httpx", specifier = ">=0.23.0,<1.0.0" },
{ name = "ruff", specifier = "==0.14.3" },
{ name = "ruff", specifier = "==0.14.14" },
]
github-actions = [
{ name = "httpx", specifier = ">=0.27.0,<1.0.0" },
@ -1266,6 +1281,7 @@ github-actions = [
{ name = "smokeshow", specifier = ">=0.5.0" },
]
tests = [
{ name = "a2wsgi", specifier = ">=1.9.0,<=2.0.0" },
{ name = "anyio", extras = ["trio"], specifier = ">=3.2.1,<5.0.0" },
{ name = "coverage", extras = ["toml"], specifier = ">=6.5.0,<8.0" },
{ name = "dirty-equals", specifier = "==0.9.0" },
@ -1278,14 +1294,14 @@ tests = [
{ name = "pytest", specifier = ">=7.1.3,<9.0.0" },
{ name = "pytest-codspeed", specifier = "==4.2.0" },
{ name = "pyyaml", specifier = ">=5.3.1,<7.0.0" },
{ name = "ruff", specifier = "==0.14.3" },
{ name = "sqlmodel", specifier = "==0.0.27" },
{ name = "ruff", specifier = "==0.14.14" },
{ name = "sqlmodel", specifier = "==0.0.31" },
{ name = "strawberry-graphql", specifier = ">=0.200.0,<1.0.0" },
{ name = "types-orjson", specifier = "==3.6.2" },
{ name = "types-ujson", specifier = "==5.10.0.20240515" },
]
translations = [
{ name = "gitpython", specifier = "==3.1.45" },
{ name = "gitpython", specifier = "==3.1.46" },
{ name = "pydantic-ai", specifier = "==0.4.10" },
{ name = "pygithub", specifier = "==2.8.1" },
]
@ -1632,15 +1648,15 @@ wheels = [
[[package]]
name = "gitpython"
version = "3.1.45"
version = "3.1.46"
source = { registry = "https://pypi.org/simple" }
dependencies = [
{ name = "gitdb" },
{ name = "typing-extensions", marker = "python_full_version < '3.10'" },
]
sdist = { url = "https://files.pythonhosted.org/packages/9a/c8/dd58967d119baab745caec2f9d853297cec1989ec1d63f677d3880632b88/gitpython-3.1.45.tar.gz", hash = "sha256:85b0ee964ceddf211c41b9f27a49086010a190fd8132a24e21f362a4b36a791c", size = 215076, upload-time = "2025-07-24T03:45:54.871Z" }
sdist = { url = "https://files.pythonhosted.org/packages/df/b5/59d16470a1f0dfe8c793f9ef56fd3826093fc52b3bd96d6b9d6c26c7e27b/gitpython-3.1.46.tar.gz", hash = "sha256:400124c7d0ef4ea03f7310ac2fbf7151e09ff97f2a3288d64a440c584a29c37f", size = 215371, upload-time = "2026-01-01T15:37:32.073Z" }
wheels = [
{ url = "https://files.pythonhosted.org/packages/01/61/d4b89fec821f72385526e1b9d9a3a0385dda4a72b206d28049e2c7cd39b8/gitpython-3.1.45-py3-none-any.whl", hash = "sha256:8908cb2e02fb3b93b7eb0f2827125cb699869470432cc885f019b8fd0fccff77", size = 208168, upload-time = "2025-07-24T03:45:52.517Z" },
{ url = "https://files.pythonhosted.org/packages/6a/09/e21df6aef1e1ffc0c816f0522ddc3f6dcded766c3261813131c78a704470/gitpython-3.1.46-py3-none-any.whl", hash = "sha256:79812ed143d9d25b6d176a10bb511de0f9c67b1fa641d82097b0ab90398a2058", size = 208620, upload-time = "2026-01-01T15:37:30.574Z" },
]
[[package]]
@ -2652,7 +2668,7 @@ wheels = [
[[package]]
name = "mkdocs-macros-plugin"
version = "1.4.1"
version = "1.5.0"
source = { registry = "https://pypi.org/simple" }
dependencies = [
{ name = "hjson" },
@ -2667,9 +2683,9 @@ dependencies = [
{ name = "termcolor", version = "3.1.0", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.10'" },
{ name = "termcolor", version = "3.3.0", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.10'" },
]
sdist = { url = "https://files.pythonhosted.org/packages/1b/42/bb2ceed148c77f82b57c6d3b7f584f0f34ababf7a9a8ff85809380d1f400/mkdocs_macros_plugin-1.4.1.tar.gz", hash = "sha256:55a9c93871e3744cdeb0736316783d60830a6d5d97b1132364e6b491607f2332", size = 35094, upload-time = "2025-10-25T12:37:20.689Z" }
sdist = { url = "https://files.pythonhosted.org/packages/92/15/e6a44839841ebc9c5872fa0e6fad1c3757424e4fe026093b68e9f386d136/mkdocs_macros_plugin-1.5.0.tar.gz", hash = "sha256:12aa45ce7ecb7a445c66b9f649f3dd05e9b92e8af6bc65e4acd91d26f878c01f", size = 37730, upload-time = "2025-11-13T08:08:55.545Z" }
wheels = [
{ url = "https://files.pythonhosted.org/packages/93/ec/e6e96a7ae8df414f03f43681821234b0d3b86666f7b91f70ab26775a8809/mkdocs_macros_plugin-1.4.1-py3-none-any.whl", hash = "sha256:5a9e483f6056fe7ad0923802affe699233ca468672e20a9640dba237165b3240", size = 40155, upload-time = "2025-10-25T12:37:19.417Z" },
{ url = "https://files.pythonhosted.org/packages/51/62/9fffba5bb9ed3d31a932ad35038ba9483d59850256ee0fea7f1187173983/mkdocs_macros_plugin-1.5.0-py3-none-any.whl", hash = "sha256:c10fabd812bf50f9170609d0ed518e54f1f0e12c334ac29141723a83c881dd6f", size = 44626, upload-time = "2025-11-13T08:08:53.878Z" },
]
[[package]]
@ -3238,11 +3254,11 @@ argon2 = [
[[package]]
name = "pyasn1"
version = "0.6.1"
version = "0.6.2"
source = { registry = "https://pypi.org/simple" }
sdist = { url = "https://files.pythonhosted.org/packages/ba/e9/01f1a64245b89f039897cb0130016d79f77d52669aae6ee7b159a6c4c018/pyasn1-0.6.1.tar.gz", hash = "sha256:6f580d2bdd84365380830acf45550f2511469f673cb4a5ae3857a3170128b034", size = 145322, upload-time = "2024-09-10T22:41:42.55Z" }
sdist = { url = "https://files.pythonhosted.org/packages/fe/b6/6e630dff89739fcd427e3f72b3d905ce0acb85a45d4ec3e2678718a3487f/pyasn1-0.6.2.tar.gz", hash = "sha256:9b59a2b25ba7e4f8197db7686c09fb33e658b98339fadb826e9512629017833b", size = 146586, upload-time = "2026-01-16T18:04:18.534Z" }
wheels = [
{ url = "https://files.pythonhosted.org/packages/c8/f1/d6a797abb14f6283c0ddff96bbdd46937f64122b8c925cab503dd37f8214/pyasn1-0.6.1-py3-none-any.whl", hash = "sha256:0d632f46f2ba09143da3a8afe9e33fb6f92fa2320ab7e886e2d0f7672af84629", size = 83135, upload-time = "2024-09-11T16:00:36.122Z" },
{ url = "https://files.pythonhosted.org/packages/44/b5/a96872e5184f354da9c84ae119971a0a4c221fe9b27a4d94bd43f2596727/pyasn1-0.6.2-py3-none-any.whl", hash = "sha256:1eb26d860996a18e9b6ed05e7aae0e9fc21619fcee6af91cca9bad4fbea224bf", size = 83371, upload-time = "2026-01-16T18:04:17.174Z" },
]
[[package]]
@ -4248,28 +4264,28 @@ wheels = [
[[package]]
name = "ruff"
version = "0.14.3"
source = { registry = "https://pypi.org/simple" }
sdist = { url = "https://files.pythonhosted.org/packages/75/62/50b7727004dfe361104dfbf898c45a9a2fdfad8c72c04ae62900224d6ecf/ruff-0.14.3.tar.gz", hash = "sha256:4ff876d2ab2b161b6de0aa1f5bd714e8e9b4033dc122ee006925fbacc4f62153", size = 5558687, upload-time = "2025-10-31T00:26:26.878Z" }
wheels = [
{ url = "https://files.pythonhosted.org/packages/ce/8e/0c10ff1ea5d4360ab8bfca4cb2c9d979101a391f3e79d2616c9bf348cd26/ruff-0.14.3-py3-none-linux_armv6l.whl", hash = "sha256:876b21e6c824f519446715c1342b8e60f97f93264012de9d8d10314f8a79c371", size = 12535613, upload-time = "2025-10-31T00:25:44.302Z" },
{ url = "https://files.pythonhosted.org/packages/d3/c8/6724f4634c1daf52409fbf13fefda64aa9c8f81e44727a378b7b73dc590b/ruff-0.14.3-py3-none-macosx_10_12_x86_64.whl", hash = "sha256:b6fd8c79b457bedd2abf2702b9b472147cd860ed7855c73a5247fa55c9117654", size = 12855812, upload-time = "2025-10-31T00:25:47.793Z" },
{ url = "https://files.pythonhosted.org/packages/de/03/db1bce591d55fd5f8a08bb02517fa0b5097b2ccabd4ea1ee29aa72b67d96/ruff-0.14.3-py3-none-macosx_11_0_arm64.whl", hash = "sha256:71ff6edca490c308f083156938c0c1a66907151263c4abdcb588602c6e696a14", size = 11944026, upload-time = "2025-10-31T00:25:49.657Z" },
{ url = "https://files.pythonhosted.org/packages/0b/75/4f8dbd48e03272715d12c87dc4fcaaf21b913f0affa5f12a4e9c6f8a0582/ruff-0.14.3-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:786ee3ce6139772ff9272aaf43296d975c0217ee1b97538a98171bf0d21f87ed", size = 12356818, upload-time = "2025-10-31T00:25:51.949Z" },
{ url = "https://files.pythonhosted.org/packages/ec/9b/506ec5b140c11d44a9a4f284ea7c14ebf6f8b01e6e8917734a3325bff787/ruff-0.14.3-py3-none-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:cd6291d0061811c52b8e392f946889916757610d45d004e41140d81fb6cd5ddc", size = 12336745, upload-time = "2025-10-31T00:25:54.248Z" },
{ url = "https://files.pythonhosted.org/packages/c7/e1/c560d254048c147f35e7f8131d30bc1f63a008ac61595cf3078a3e93533d/ruff-0.14.3-py3-none-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:a497ec0c3d2c88561b6d90f9c29f5ae68221ac00d471f306fa21fa4264ce5fcd", size = 13101684, upload-time = "2025-10-31T00:25:56.253Z" },
{ url = "https://files.pythonhosted.org/packages/a5/32/e310133f8af5cd11f8cc30f52522a3ebccc5ea5bff4b492f94faceaca7a8/ruff-0.14.3-py3-none-manylinux_2_17_ppc64.manylinux2014_ppc64.whl", hash = "sha256:e231e1be58fc568950a04fbe6887c8e4b85310e7889727e2b81db205c45059eb", size = 14535000, upload-time = "2025-10-31T00:25:58.397Z" },
{ url = "https://files.pythonhosted.org/packages/a2/a1/7b0470a22158c6d8501eabc5e9b6043c99bede40fa1994cadf6b5c2a61c7/ruff-0.14.3-py3-none-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:469e35872a09c0e45fecf48dd960bfbce056b5db2d5e6b50eca329b4f853ae20", size = 14156450, upload-time = "2025-10-31T00:26:00.889Z" },
{ url = "https://files.pythonhosted.org/packages/0a/96/24bfd9d1a7f532b560dcee1a87096332e461354d3882124219bcaff65c09/ruff-0.14.3-py3-none-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:3d6bc90307c469cb9d28b7cfad90aaa600b10d67c6e22026869f585e1e8a2db0", size = 13568414, upload-time = "2025-10-31T00:26:03.291Z" },
{ url = "https://files.pythonhosted.org/packages/a7/e7/138b883f0dfe4ad5b76b58bf4ae675f4d2176ac2b24bdd81b4d966b28c61/ruff-0.14.3-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0e2f8a0bbcffcfd895df39c9a4ecd59bb80dca03dc43f7fb63e647ed176b741e", size = 13315293, upload-time = "2025-10-31T00:26:05.708Z" },
{ url = "https://files.pythonhosted.org/packages/33/f4/c09bb898be97b2eb18476b7c950df8815ef14cf956074177e9fbd40b7719/ruff-0.14.3-py3-none-manylinux_2_31_riscv64.whl", hash = "sha256:678fdd7c7d2d94851597c23ee6336d25f9930b460b55f8598e011b57c74fd8c5", size = 13539444, upload-time = "2025-10-31T00:26:08.09Z" },
{ url = "https://files.pythonhosted.org/packages/9c/aa/b30a1db25fc6128b1dd6ff0741fa4abf969ded161599d07ca7edd0739cc0/ruff-0.14.3-py3-none-musllinux_1_2_aarch64.whl", hash = "sha256:1ec1ac071e7e37e0221d2f2dbaf90897a988c531a8592a6a5959f0603a1ecf5e", size = 12252581, upload-time = "2025-10-31T00:26:10.297Z" },
{ url = "https://files.pythonhosted.org/packages/da/13/21096308f384d796ffe3f2960b17054110a9c3828d223ca540c2b7cc670b/ruff-0.14.3-py3-none-musllinux_1_2_armv7l.whl", hash = "sha256:afcdc4b5335ef440d19e7df9e8ae2ad9f749352190e96d481dc501b753f0733e", size = 12307503, upload-time = "2025-10-31T00:26:12.646Z" },
{ url = "https://files.pythonhosted.org/packages/cb/cc/a350bac23f03b7dbcde3c81b154706e80c6f16b06ff1ce28ed07dc7b07b0/ruff-0.14.3-py3-none-musllinux_1_2_i686.whl", hash = "sha256:7bfc42f81862749a7136267a343990f865e71fe2f99cf8d2958f684d23ce3dfa", size = 12675457, upload-time = "2025-10-31T00:26:15.044Z" },
{ url = "https://files.pythonhosted.org/packages/cb/76/46346029fa2f2078826bc88ef7167e8c198e58fe3126636e52f77488cbba/ruff-0.14.3-py3-none-musllinux_1_2_x86_64.whl", hash = "sha256:a65e448cfd7e9c59fae8cf37f9221585d3354febaad9a07f29158af1528e165f", size = 13403980, upload-time = "2025-10-31T00:26:17.81Z" },
{ url = "https://files.pythonhosted.org/packages/9f/a4/35f1ef68c4e7b236d4a5204e3669efdeefaef21f0ff6a456792b3d8be438/ruff-0.14.3-py3-none-win32.whl", hash = "sha256:f3d91857d023ba93e14ed2d462ab62c3428f9bbf2b4fbac50a03ca66d31991f7", size = 12500045, upload-time = "2025-10-31T00:26:20.503Z" },
{ url = "https://files.pythonhosted.org/packages/03/15/51960ae340823c9859fb60c63301d977308735403e2134e17d1d2858c7fb/ruff-0.14.3-py3-none-win_amd64.whl", hash = "sha256:d7b7006ac0756306db212fd37116cce2bd307e1e109375e1c6c106002df0ae5f", size = 13594005, upload-time = "2025-10-31T00:26:22.533Z" },
{ url = "https://files.pythonhosted.org/packages/b7/73/4de6579bac8e979fca0a77e54dec1f1e011a0d268165eb8a9bc0982a6564/ruff-0.14.3-py3-none-win_arm64.whl", hash = "sha256:26eb477ede6d399d898791d01961e16b86f02bc2486d0d1a7a9bb2379d055dc1", size = 12590017, upload-time = "2025-10-31T00:26:24.52Z" },
version = "0.14.14"
source = { registry = "https://pypi.org/simple" }
sdist = { url = "https://files.pythonhosted.org/packages/2e/06/f71e3a86b2df0dfa2d2f72195941cd09b44f87711cb7fa5193732cb9a5fc/ruff-0.14.14.tar.gz", hash = "sha256:2d0f819c9a90205f3a867dbbd0be083bee9912e170fd7d9704cc8ae45824896b", size = 4515732, upload-time = "2026-01-22T22:30:17.527Z" }
wheels = [
{ url = "https://files.pythonhosted.org/packages/d2/89/20a12e97bc6b9f9f68343952da08a8099c57237aef953a56b82711d55edd/ruff-0.14.14-py3-none-linux_armv6l.whl", hash = "sha256:7cfe36b56e8489dee8fbc777c61959f60ec0f1f11817e8f2415f429552846aed", size = 10467650, upload-time = "2026-01-22T22:30:08.578Z" },
{ url = "https://files.pythonhosted.org/packages/a3/b1/c5de3fd2d5a831fcae21beda5e3589c0ba67eec8202e992388e4b17a6040/ruff-0.14.14-py3-none-macosx_10_12_x86_64.whl", hash = "sha256:6006a0082336e7920b9573ef8a7f52eec837add1265cc74e04ea8a4368cd704c", size = 10883245, upload-time = "2026-01-22T22:30:04.155Z" },
{ url = "https://files.pythonhosted.org/packages/b8/7c/3c1db59a10e7490f8f6f8559d1db8636cbb13dccebf18686f4e3c9d7c772/ruff-0.14.14-py3-none-macosx_11_0_arm64.whl", hash = "sha256:026c1d25996818f0bf498636686199d9bd0d9d6341c9c2c3b62e2a0198b758de", size = 10231273, upload-time = "2026-01-22T22:30:34.642Z" },
{ url = "https://files.pythonhosted.org/packages/a1/6e/5e0e0d9674be0f8581d1f5e0f0a04761203affce3232c1a1189d0e3b4dad/ruff-0.14.14-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f666445819d31210b71e0a6d1c01e24447a20b85458eea25a25fe8142210ae0e", size = 10585753, upload-time = "2026-01-22T22:30:31.781Z" },
{ url = "https://files.pythonhosted.org/packages/23/09/754ab09f46ff1884d422dc26d59ba18b4e5d355be147721bb2518aa2a014/ruff-0.14.14-py3-none-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:3c0f18b922c6d2ff9a5e6c3ee16259adc513ca775bcf82c67ebab7cbd9da5bc8", size = 10286052, upload-time = "2026-01-22T22:30:24.827Z" },
{ url = "https://files.pythonhosted.org/packages/c8/cc/e71f88dd2a12afb5f50733851729d6b571a7c3a35bfdb16c3035132675a0/ruff-0.14.14-py3-none-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:1629e67489c2dea43e8658c3dba659edbfd87361624b4040d1df04c9740ae906", size = 11043637, upload-time = "2026-01-22T22:30:13.239Z" },
{ url = "https://files.pythonhosted.org/packages/67/b2/397245026352494497dac935d7f00f1468c03a23a0c5db6ad8fc49ca3fb2/ruff-0.14.14-py3-none-manylinux_2_17_ppc64.manylinux2014_ppc64.whl", hash = "sha256:27493a2131ea0f899057d49d303e4292b2cae2bb57253c1ed1f256fbcd1da480", size = 12194761, upload-time = "2026-01-22T22:30:22.542Z" },
{ url = "https://files.pythonhosted.org/packages/5b/06/06ef271459f778323112c51b7587ce85230785cd64e91772034ddb88f200/ruff-0.14.14-py3-none-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:01ff589aab3f5b539e35db38425da31a57521efd1e4ad1ae08fc34dbe30bd7df", size = 12005701, upload-time = "2026-01-22T22:30:20.499Z" },
{ url = "https://files.pythonhosted.org/packages/41/d6/99364514541cf811ccc5ac44362f88df66373e9fec1b9d1c4cc830593fe7/ruff-0.14.14-py3-none-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:1cc12d74eef0f29f51775f5b755913eb523546b88e2d733e1d701fe65144e89b", size = 11282455, upload-time = "2026-01-22T22:29:59.679Z" },
{ url = "https://files.pythonhosted.org/packages/ca/71/37daa46f89475f8582b7762ecd2722492df26421714a33e72ccc9a84d7a5/ruff-0.14.14-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:bb8481604b7a9e75eff53772496201690ce2687067e038b3cc31aaf16aa0b974", size = 11215882, upload-time = "2026-01-22T22:29:57.032Z" },
{ url = "https://files.pythonhosted.org/packages/2c/10/a31f86169ec91c0705e618443ee74ede0bdd94da0a57b28e72db68b2dbac/ruff-0.14.14-py3-none-manylinux_2_31_riscv64.whl", hash = "sha256:14649acb1cf7b5d2d283ebd2f58d56b75836ed8c6f329664fa91cdea19e76e66", size = 11180549, upload-time = "2026-01-22T22:30:27.175Z" },
{ url = "https://files.pythonhosted.org/packages/fd/1e/c723f20536b5163adf79bdd10c5f093414293cdf567eed9bdb7b83940f3f/ruff-0.14.14-py3-none-musllinux_1_2_aarch64.whl", hash = "sha256:e8058d2145566510790eab4e2fad186002e288dec5e0d343a92fe7b0bc1b3e13", size = 10543416, upload-time = "2026-01-22T22:30:01.964Z" },
{ url = "https://files.pythonhosted.org/packages/3e/34/8a84cea7e42c2d94ba5bde1d7a4fae164d6318f13f933d92da6d7c2041ff/ruff-0.14.14-py3-none-musllinux_1_2_armv7l.whl", hash = "sha256:e651e977a79e4c758eb807f0481d673a67ffe53cfa92209781dfa3a996cf8412", size = 10285491, upload-time = "2026-01-22T22:30:29.51Z" },
{ url = "https://files.pythonhosted.org/packages/55/ef/b7c5ea0be82518906c978e365e56a77f8de7678c8bb6651ccfbdc178c29f/ruff-0.14.14-py3-none-musllinux_1_2_i686.whl", hash = "sha256:cc8b22da8d9d6fdd844a68ae937e2a0adf9b16514e9a97cc60355e2d4b219fc3", size = 10733525, upload-time = "2026-01-22T22:30:06.499Z" },
{ url = "https://files.pythonhosted.org/packages/6a/5b/aaf1dfbcc53a2811f6cc0a1759de24e4b03e02ba8762daabd9b6bd8c59e3/ruff-0.14.14-py3-none-musllinux_1_2_x86_64.whl", hash = "sha256:16bc890fb4cc9781bb05beb5ab4cd51be9e7cb376bf1dd3580512b24eb3fda2b", size = 11315626, upload-time = "2026-01-22T22:30:36.848Z" },
{ url = "https://files.pythonhosted.org/packages/2c/aa/9f89c719c467dfaf8ad799b9bae0df494513fb21d31a6059cb5870e57e74/ruff-0.14.14-py3-none-win32.whl", hash = "sha256:b530c191970b143375b6a68e6f743800b2b786bbcf03a7965b06c4bf04568167", size = 10502442, upload-time = "2026-01-22T22:30:38.93Z" },
{ url = "https://files.pythonhosted.org/packages/87/44/90fa543014c45560cae1fffc63ea059fb3575ee6e1cb654562197e5d16fb/ruff-0.14.14-py3-none-win_amd64.whl", hash = "sha256:3dde1435e6b6fe5b66506c1dff67a421d0b7f6488d466f651c07f4cab3bf20fd", size = 11630486, upload-time = "2026-01-22T22:30:10.852Z" },
{ url = "https://files.pythonhosted.org/packages/9e/6a/40fee331a52339926a92e17ae748827270b288a35ef4a15c9c8f2ec54715/ruff-0.14.14-py3-none-win_arm64.whl", hash = "sha256:56e6981a98b13a32236a72a8da421d7839221fa308b223b9283312312e5ac76c", size = 10920448, upload-time = "2026-01-22T22:30:15.417Z" },
]
[[package]]
@ -4415,15 +4431,15 @@ wheels = [
[[package]]
name = "sqlmodel"
version = "0.0.27"
version = "0.0.31"
source = { registry = "https://pypi.org/simple" }
dependencies = [
{ name = "pydantic" },
{ name = "sqlalchemy" },
]
sdist = { url = "https://files.pythonhosted.org/packages/90/5a/693d90866233e837d182da76082a6d4c2303f54d3aaaa5c78e1238c5d863/sqlmodel-0.0.27.tar.gz", hash = "sha256:ad1227f2014a03905aef32e21428640848ac09ff793047744a73dfdd077ff620", size = 118053, upload-time = "2025-10-08T16:39:11.938Z" }
sdist = { url = "https://files.pythonhosted.org/packages/56/b8/e7cd6def4a773f25d6e29ffce63ccbfd6cf9488b804ab6fb9b80d334b39d/sqlmodel-0.0.31.tar.gz", hash = "sha256:2d41a8a9ee05e40736e2f9db8ea28cbfe9b5d4e5a18dd139e80605025e0c516c", size = 94952, upload-time = "2025-12-28T12:35:01.436Z" }
wheels = [
{ url = "https://files.pythonhosted.org/packages/8c/92/c35e036151fe53822893979f8a13e6f235ae8191f4164a79ae60a95d66aa/sqlmodel-0.0.27-py3-none-any.whl", hash = "sha256:667fe10aa8ff5438134668228dc7d7a08306f4c5c4c7e6ad3ad68defa0e7aa49", size = 29131, upload-time = "2025-10-08T16:39:10.917Z" },
{ url = "https://files.pythonhosted.org/packages/6c/72/5aa5be921800f6418a949a73c9bb7054890881143e6bc604a93d228a95a3/sqlmodel-0.0.31-py3-none-any.whl", hash = "sha256:6d946d56cac4c2db296ba1541357cee2e795d68174e2043cd138b916794b1513", size = 27093, upload-time = "2025-12-28T12:35:00.108Z" },
]
[[package]]
@ -4737,7 +4753,7 @@ wheels = [
[[package]]
name = "typer"
version = "0.16.0"
version = "0.21.1"
source = { registry = "https://pypi.org/simple" }
dependencies = [
{ name = "click", version = "8.1.8", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.10'" },
@ -4746,9 +4762,9 @@ dependencies = [
{ name = "shellingham" },
{ name = "typing-extensions" },
]
sdist = { url = "https://files.pythonhosted.org/packages/c5/8c/7d682431efca5fd290017663ea4588bf6f2c6aad085c7f108c5dbc316e70/typer-0.16.0.tar.gz", hash = "sha256:af377ffaee1dbe37ae9440cb4e8f11686ea5ce4e9bae01b84ae7c63b87f1dd3b", size = 102625, upload-time = "2025-05-26T14:30:31.824Z" }
sdist = { url = "https://files.pythonhosted.org/packages/36/bf/8825b5929afd84d0dabd606c67cd57b8388cb3ec385f7ef19c5cc2202069/typer-0.21.1.tar.gz", hash = "sha256:ea835607cd752343b6b2b7ce676893e5a0324082268b48f27aa058bdb7d2145d", size = 110371, upload-time = "2026-01-06T11:21:10.989Z" }
wheels = [
{ url = "https://files.pythonhosted.org/packages/76/42/3efaf858001d2c2913de7f354563e3a3a2f0decae3efe98427125a8f441e/typer-0.16.0-py3-none-any.whl", hash = "sha256:1f79bed11d4d02d4310e3c1b7ba594183bcedb0ac73b27a9e5f28f6fb5b98855", size = 46317, upload-time = "2025-05-26T14:30:30.523Z" },
{ url = "https://files.pythonhosted.org/packages/a0/1d/d9257dd49ff2ca23ea5f132edf1281a0c4f9de8a762b9ae399b670a59235/typer-0.21.1-py3-none-any.whl", hash = "sha256:7985e89081c636b88d172c2ee0cfe33c253160994d47bdfdc302defd7d1f1d01", size = 47381, upload-time = "2026-01-06T11:21:09.824Z" },
]
[[package]]

Loading…
Cancel
Save