From dbb7020a4d98ec994594096f897edaa70c01c67b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebasti=C3=A1n=20Ram=C3=ADrez?= Date: Mon, 3 Nov 2025 10:23:52 +0100 Subject: [PATCH 01/16] =?UTF-8?q?=F0=9F=91=A5=20Update=20FastAPI=20GitHub?= =?UTF-8?q?=20topic=20repositories=20(#14280)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: github-actions --- docs/en/data/topic_repos.yml | 380 +++++++++++++++++------------------ 1 file changed, 190 insertions(+), 190 deletions(-) diff --git a/docs/en/data/topic_repos.yml b/docs/en/data/topic_repos.yml index 9d95fb8b1..1bb6fd70d 100644 --- a/docs/en/data/topic_repos.yml +++ b/docs/en/data/topic_repos.yml @@ -1,81 +1,86 @@ - name: full-stack-fastapi-template html_url: https://github.com/fastapi/full-stack-fastapi-template - stars: 38085 + stars: 38779 owner_login: fastapi owner_html_url: https://github.com/fastapi - name: Hello-Python html_url: https://github.com/mouredev/Hello-Python - stars: 32243 + stars: 32726 owner_login: mouredev owner_html_url: https://github.com/mouredev - name: serve html_url: https://github.com/jina-ai/serve - stars: 21754 + stars: 21779 owner_login: jina-ai owner_html_url: https://github.com/jina-ai - name: HivisionIDPhotos html_url: https://github.com/Zeyi-Lin/HivisionIDPhotos - stars: 19400 + stars: 20028 owner_login: Zeyi-Lin owner_html_url: https://github.com/Zeyi-Lin - name: sqlmodel html_url: https://github.com/fastapi/sqlmodel - stars: 16859 + stars: 17038 owner_login: fastapi owner_html_url: https://github.com/fastapi - name: Douyin_TikTok_Download_API html_url: https://github.com/Evil0ctal/Douyin_TikTok_Download_API - stars: 14452 + stars: 14786 owner_login: Evil0ctal owner_html_url: https://github.com/Evil0ctal - name: fastapi-best-practices html_url: https://github.com/zhanymkanov/fastapi-best-practices - stars: 13613 + stars: 13968 owner_login: zhanymkanov owner_html_url: https://github.com/zhanymkanov +- name: machine-learning-zoomcamp + html_url: https://github.com/DataTalksClub/machine-learning-zoomcamp + stars: 12171 + owner_login: DataTalksClub + owner_html_url: https://github.com/DataTalksClub - name: fastapi_mcp html_url: https://github.com/tadata-org/fastapi_mcp - stars: 10624 + stars: 10976 owner_login: tadata-org owner_html_url: https://github.com/tadata-org - name: awesome-fastapi html_url: https://github.com/mjhea0/awesome-fastapi - stars: 10415 + stars: 10618 owner_login: mjhea0 owner_html_url: https://github.com/mjhea0 -- name: FastUI - html_url: https://github.com/pydantic/FastUI - stars: 8879 - owner_login: pydantic - owner_html_url: https://github.com/pydantic -- name: XHS-Downloader - html_url: https://github.com/JoeanAmier/XHS-Downloader - stars: 8824 - owner_login: JoeanAmier - owner_html_url: https://github.com/JoeanAmier - name: SurfSense html_url: https://github.com/MODSetter/SurfSense - stars: 8257 + stars: 10243 owner_login: MODSetter owner_html_url: https://github.com/MODSetter -- name: FileCodeBox - html_url: https://github.com/vastsa/FileCodeBox - stars: 7367 - owner_login: vastsa - owner_html_url: https://github.com/vastsa +- name: XHS-Downloader + html_url: https://github.com/JoeanAmier/XHS-Downloader + stars: 9062 + owner_login: JoeanAmier + owner_html_url: https://github.com/JoeanAmier +- name: FastUI + html_url: https://github.com/pydantic/FastUI + stars: 8892 + owner_login: pydantic + owner_html_url: https://github.com/pydantic - name: polar html_url: https://github.com/polarsource/polar - stars: 7291 + stars: 8084 owner_login: polarsource owner_html_url: https://github.com/polarsource +- name: FileCodeBox + html_url: https://github.com/vastsa/FileCodeBox + stars: 7494 + owner_login: vastsa + owner_html_url: https://github.com/vastsa - name: nonebot2 html_url: https://github.com/nonebot/nonebot2 - stars: 7065 + stars: 7128 owner_login: nonebot owner_html_url: https://github.com/nonebot - name: hatchet html_url: https://github.com/hatchet-dev/hatchet - stars: 6070 + stars: 6155 owner_login: hatchet-dev owner_html_url: https://github.com/hatchet-dev - name: serge @@ -85,27 +90,27 @@ owner_html_url: https://github.com/serge-chat - name: fastapi-users html_url: https://github.com/fastapi-users/fastapi-users - stars: 5599 + stars: 5683 owner_login: fastapi-users owner_html_url: https://github.com/fastapi-users - name: strawberry html_url: https://github.com/strawberry-graphql/strawberry - stars: 4422 + stars: 4452 owner_login: strawberry-graphql owner_html_url: https://github.com/strawberry-graphql - name: chatgpt-web-share html_url: https://github.com/chatpire/chatgpt-web-share - stars: 4301 + stars: 4296 owner_login: chatpire owner_html_url: https://github.com/chatpire - name: poem html_url: https://github.com/poem-web/poem - stars: 4197 + stars: 4235 owner_login: poem-web owner_html_url: https://github.com/poem-web - name: dynaconf html_url: https://github.com/dynaconf/dynaconf - stars: 4144 + stars: 4174 owner_login: dynaconf owner_html_url: https://github.com/dynaconf - name: atrilabs-engine @@ -115,42 +120,42 @@ owner_html_url: https://github.com/Atri-Labs - name: Kokoro-FastAPI html_url: https://github.com/remsky/Kokoro-FastAPI - stars: 3739 + stars: 3875 owner_login: remsky owner_html_url: https://github.com/remsky - name: logfire html_url: https://github.com/pydantic/logfire - stars: 3614 + stars: 3717 owner_login: pydantic owner_html_url: https://github.com/pydantic - name: LitServe html_url: https://github.com/Lightning-AI/LitServe - stars: 3578 + stars: 3615 owner_login: Lightning-AI owner_html_url: https://github.com/Lightning-AI - name: datamodel-code-generator html_url: https://github.com/koxudaxi/datamodel-code-generator - stars: 3496 + stars: 3554 owner_login: koxudaxi owner_html_url: https://github.com/koxudaxi -- name: farfalle - html_url: https://github.com/rashadphz/farfalle - stars: 3459 - owner_login: rashadphz - owner_html_url: https://github.com/rashadphz -- name: fastapi-admin - html_url: https://github.com/fastapi-admin/fastapi-admin - stars: 3456 - owner_login: fastapi-admin - owner_html_url: https://github.com/fastapi-admin - name: huma html_url: https://github.com/danielgtaylor/huma - stars: 3447 + stars: 3521 owner_login: danielgtaylor owner_html_url: https://github.com/danielgtaylor +- name: fastapi-admin + html_url: https://github.com/fastapi-admin/fastapi-admin + stars: 3497 + owner_login: fastapi-admin + owner_html_url: https://github.com/fastapi-admin +- name: farfalle + html_url: https://github.com/rashadphz/farfalle + stars: 3476 + owner_login: rashadphz + owner_html_url: https://github.com/rashadphz - name: tracecat html_url: https://github.com/TracecatHQ/tracecat - stars: 3254 + stars: 3310 owner_login: TracecatHQ owner_html_url: https://github.com/TracecatHQ - name: opyrator @@ -160,336 +165,331 @@ owner_html_url: https://github.com/ml-tooling - name: docarray html_url: https://github.com/docarray/docarray - stars: 3107 + stars: 3108 owner_login: docarray owner_html_url: https://github.com/docarray - name: fastapi-realworld-example-app html_url: https://github.com/nsidnev/fastapi-realworld-example-app - stars: 2936 + stars: 2945 owner_login: nsidnev owner_html_url: https://github.com/nsidnev - name: uvicorn-gunicorn-fastapi-docker html_url: https://github.com/tiangolo/uvicorn-gunicorn-fastapi-docker - stars: 2804 + stars: 2809 owner_login: tiangolo owner_html_url: https://github.com/tiangolo -- name: best-of-web-python - html_url: https://github.com/ml-tooling/best-of-web-python - stars: 2610 - owner_login: ml-tooling - owner_html_url: https://github.com/ml-tooling +- name: devpush + html_url: https://github.com/hunvreus/devpush + stars: 2784 + owner_login: hunvreus + owner_html_url: https://github.com/hunvreus - name: mcp-context-forge html_url: https://github.com/IBM/mcp-context-forge - stars: 2572 + stars: 2763 owner_login: IBM owner_html_url: https://github.com/IBM +- name: best-of-web-python + html_url: https://github.com/ml-tooling/best-of-web-python + stars: 2630 + owner_login: ml-tooling + owner_html_url: https://github.com/ml-tooling - name: fastapi-react html_url: https://github.com/Buuntu/fastapi-react - stars: 2451 + stars: 2464 owner_login: Buuntu owner_html_url: https://github.com/Buuntu -- name: RasaGPT - html_url: https://github.com/paulpierre/RasaGPT - stars: 2441 - owner_login: paulpierre - owner_html_url: https://github.com/paulpierre - name: FastAPI-template html_url: https://github.com/s3rius/FastAPI-template - stars: 2424 + stars: 2453 owner_login: s3rius owner_html_url: https://github.com/s3rius +- name: RasaGPT + html_url: https://github.com/paulpierre/RasaGPT + stars: 2444 + owner_login: paulpierre + owner_html_url: https://github.com/paulpierre - name: sqladmin html_url: https://github.com/aminalaee/sqladmin - stars: 2357 + stars: 2423 owner_login: aminalaee owner_html_url: https://github.com/aminalaee - name: nextpy html_url: https://github.com/dot-agent/nextpy - stars: 2324 + stars: 2325 owner_login: dot-agent owner_html_url: https://github.com/dot-agent - name: supabase-py html_url: https://github.com/supabase/supabase-py - stars: 2236 + stars: 2292 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: 2210 + stars: 2214 owner_login: codingforentrepreneurs owner_html_url: https://github.com/codingforentrepreneurs +- name: Yuxi-Know + html_url: https://github.com/xerrors/Yuxi-Know + stars: 2212 + owner_login: xerrors + owner_html_url: https://github.com/xerrors - name: langserve html_url: https://github.com/langchain-ai/langserve - stars: 2171 + stars: 2191 owner_login: langchain-ai owner_html_url: https://github.com/langchain-ai - name: fastapi-utils html_url: https://github.com/fastapiutils/fastapi-utils - stars: 2164 + stars: 2185 owner_login: fastapiutils owner_html_url: https://github.com/fastapiutils - name: solara html_url: https://github.com/widgetti/solara - stars: 2102 + stars: 2111 owner_login: widgetti owner_html_url: https://github.com/widgetti -- name: Yuxi-Know - html_url: https://github.com/xerrors/Yuxi-Know - stars: 1995 - owner_login: xerrors - owner_html_url: https://github.com/xerrors - name: mangum html_url: https://github.com/Kludex/mangum - stars: 1989 + stars: 2011 owner_login: Kludex owner_html_url: https://github.com/Kludex -- name: python-week-2022 - html_url: https://github.com/rochacbruno/python-week-2022 - stars: 1816 - owner_login: rochacbruno - owner_html_url: https://github.com/rochacbruno - name: agentkit html_url: https://github.com/BCG-X-Official/agentkit - stars: 1789 + stars: 1826 owner_login: BCG-X-Official owner_html_url: https://github.com/BCG-X-Official +- name: python-week-2022 + html_url: https://github.com/rochacbruno/python-week-2022 + stars: 1815 + owner_login: rochacbruno + owner_html_url: https://github.com/rochacbruno - name: manage-fastapi html_url: https://github.com/ycd/manage-fastapi - stars: 1780 + stars: 1787 owner_login: ycd owner_html_url: https://github.com/ycd - name: ormar html_url: https://github.com/collerek/ormar - stars: 1777 + stars: 1780 owner_login: collerek owner_html_url: https://github.com/collerek +- name: vue-fastapi-admin + html_url: https://github.com/mizhexiaoxiao/vue-fastapi-admin + stars: 1758 + owner_login: mizhexiaoxiao + owner_html_url: https://github.com/mizhexiaoxiao - name: openapi-python-client html_url: https://github.com/openapi-generators/openapi-python-client - stars: 1707 + stars: 1731 owner_login: openapi-generators owner_html_url: https://github.com/openapi-generators - name: piccolo html_url: https://github.com/piccolo-orm/piccolo - stars: 1695 + stars: 1711 owner_login: piccolo-orm owner_html_url: https://github.com/piccolo-orm -- name: vue-fastapi-admin - html_url: https://github.com/mizhexiaoxiao/vue-fastapi-admin - stars: 1695 - owner_login: mizhexiaoxiao - owner_html_url: https://github.com/mizhexiaoxiao - name: fastapi-cache html_url: https://github.com/long2ice/fastapi-cache - stars: 1653 + stars: 1677 owner_login: long2ice owner_html_url: https://github.com/long2ice +- name: slowapi + html_url: https://github.com/laurentS/slowapi + stars: 1669 + owner_login: laurentS + owner_html_url: https://github.com/laurentS - name: langchain-serve html_url: https://github.com/jina-ai/langchain-serve - stars: 1635 + stars: 1632 owner_login: jina-ai owner_html_url: https://github.com/jina-ai - name: termpair html_url: https://github.com/cs01/termpair - stars: 1624 + stars: 1621 owner_login: cs01 owner_html_url: https://github.com/cs01 -- name: slowapi - html_url: https://github.com/laurentS/slowapi - stars: 1620 - owner_login: laurentS - owner_html_url: https://github.com/laurentS +- name: FastAPI-boilerplate + html_url: https://github.com/benavlabs/FastAPI-boilerplate + stars: 1596 + owner_login: benavlabs + owner_html_url: https://github.com/benavlabs - name: coronavirus-tracker-api html_url: https://github.com/ExpDev07/coronavirus-tracker-api - stars: 1576 + stars: 1573 owner_login: ExpDev07 owner_html_url: https://github.com/ExpDev07 - name: fastapi-crudrouter html_url: https://github.com/awtkns/fastapi-crudrouter - stars: 1546 + stars: 1553 owner_login: awtkns owner_html_url: https://github.com/awtkns -- name: FastAPI-boilerplate - html_url: https://github.com/benavlabs/FastAPI-boilerplate - stars: 1516 - owner_login: benavlabs - owner_html_url: https://github.com/benavlabs - name: awesome-fastapi-projects html_url: https://github.com/Kludex/awesome-fastapi-projects - stars: 1481 + stars: 1485 owner_login: Kludex owner_html_url: https://github.com/Kludex - name: fastapi-pagination html_url: https://github.com/uriyyo/fastapi-pagination - stars: 1453 + stars: 1473 owner_login: uriyyo owner_html_url: https://github.com/uriyyo - name: bracket html_url: https://github.com/evroon/bracket - stars: 1415 + stars: 1470 owner_login: evroon owner_html_url: https://github.com/evroon -- name: awesome-python-resources - html_url: https://github.com/DjangoEx/awesome-python-resources - stars: 1413 - owner_login: DjangoEx - owner_html_url: https://github.com/DjangoEx +- name: fastapi-langgraph-agent-production-ready-template + html_url: https://github.com/wassim249/fastapi-langgraph-agent-production-ready-template + stars: 1456 + owner_login: wassim249 + owner_html_url: https://github.com/wassim249 - name: fastapi-boilerplate html_url: https://github.com/teamhide/fastapi-boilerplate - stars: 1406 + stars: 1424 owner_login: teamhide owner_html_url: https://github.com/teamhide -- name: budgetml - html_url: https://github.com/ebhy/budgetml - stars: 1346 - owner_login: ebhy - owner_html_url: https://github.com/ebhy +- name: awesome-python-resources + html_url: https://github.com/DjangoEx/awesome-python-resources + stars: 1420 + owner_login: DjangoEx + owner_html_url: https://github.com/DjangoEx - name: fastapi-amis-admin html_url: https://github.com/amisadmin/fastapi-amis-admin - stars: 1342 + stars: 1363 owner_login: amisadmin owner_html_url: https://github.com/amisadmin -- name: fastapi-langgraph-agent-production-ready-template - html_url: https://github.com/wassim249/fastapi-langgraph-agent-production-ready-template - stars: 1334 - owner_login: wassim249 - owner_html_url: https://github.com/wassim249 +- name: fastcrud + html_url: https://github.com/benavlabs/fastcrud + stars: 1362 + owner_login: benavlabs + owner_html_url: https://github.com/benavlabs +- name: budgetml + html_url: https://github.com/ebhy/budgetml + stars: 1345 + owner_login: ebhy + owner_html_url: https://github.com/ebhy - name: fastapi-tutorial html_url: https://github.com/liaogx/fastapi-tutorial - stars: 1303 + stars: 1315 owner_login: liaogx owner_html_url: https://github.com/liaogx - name: fastapi_best_architecture html_url: https://github.com/fastapi-practices/fastapi_best_architecture - stars: 1276 + stars: 1311 owner_login: fastapi-practices owner_html_url: https://github.com/fastapi-practices -- name: fastcrud - html_url: https://github.com/benavlabs/fastcrud - stars: 1272 - owner_login: benavlabs - owner_html_url: https://github.com/benavlabs - name: fastapi-code-generator html_url: https://github.com/koxudaxi/fastapi-code-generator - stars: 1253 + stars: 1270 owner_login: koxudaxi owner_html_url: https://github.com/koxudaxi - name: prometheus-fastapi-instrumentator html_url: https://github.com/trallnag/prometheus-fastapi-instrumentator - stars: 1246 + stars: 1264 owner_login: trallnag owner_html_url: https://github.com/trallnag -- name: bolt-python - html_url: https://github.com/slackapi/bolt-python - stars: 1221 - owner_login: slackapi - owner_html_url: https://github.com/slackapi - name: bedrock-chat html_url: https://github.com/aws-samples/bedrock-chat - stars: 1220 + stars: 1243 owner_login: aws-samples owner_html_url: https://github.com/aws-samples +- name: bolt-python + html_url: https://github.com/slackapi/bolt-python + stars: 1238 + owner_login: slackapi + owner_html_url: https://github.com/slackapi - name: fastapi_production_template html_url: https://github.com/zhanymkanov/fastapi_production_template - stars: 1202 + stars: 1209 owner_login: zhanymkanov owner_html_url: https://github.com/zhanymkanov - name: fastapi-scaff html_url: https://github.com/atpuxiner/fastapi-scaff - stars: 1193 + stars: 1200 owner_login: atpuxiner owner_html_url: https://github.com/atpuxiner - name: langchain-extract html_url: https://github.com/langchain-ai/langchain-extract - stars: 1164 + stars: 1173 owner_login: langchain-ai owner_html_url: https://github.com/langchain-ai - name: fastapi-alembic-sqlmodel-async html_url: https://github.com/jonra1993/fastapi-alembic-sqlmodel-async - stars: 1149 + stars: 1162 owner_login: jonra1993 owner_html_url: https://github.com/jonra1993 - name: odmantic html_url: https://github.com/art049/odmantic - stars: 1133 + stars: 1137 owner_login: art049 owner_html_url: https://github.com/art049 - name: restish html_url: https://github.com/rest-sh/restish - stars: 1122 + stars: 1129 owner_login: rest-sh owner_html_url: https://github.com/rest-sh -- name: runhouse - html_url: https://github.com/run-house/runhouse - stars: 1047 +- name: kubetorch + html_url: https://github.com/run-house/kubetorch + stars: 1065 owner_login: run-house owner_html_url: https://github.com/run-house - name: flock html_url: https://github.com/Onelevenvy/flock - stars: 1027 + stars: 1039 owner_login: Onelevenvy owner_html_url: https://github.com/Onelevenvy - name: authx html_url: https://github.com/yezz123/authx - stars: 999 + stars: 1017 owner_login: yezz123 owner_html_url: https://github.com/yezz123 - name: autollm html_url: https://github.com/viddexa/autollm - stars: 999 + stars: 997 owner_login: viddexa owner_html_url: https://github.com/viddexa - name: lanarky html_url: https://github.com/ajndkr/lanarky - stars: 995 + stars: 993 owner_login: ajndkr owner_html_url: https://github.com/ajndkr -- name: titiler - html_url: https://github.com/developmentseed/titiler - stars: 952 - owner_login: developmentseed - owner_html_url: https://github.com/developmentseed -- name: energy-forecasting - html_url: https://github.com/iusztinpaul/energy-forecasting - stars: 946 - owner_login: iusztinpaul - owner_html_url: https://github.com/iusztinpaul -- name: secure - html_url: https://github.com/TypeError/secure - stars: 944 - owner_login: TypeError - owner_html_url: https://github.com/TypeError -- name: langcorn - html_url: https://github.com/msoedov/langcorn - stars: 934 - owner_login: msoedov - owner_html_url: https://github.com/msoedov - name: RuoYi-Vue3-FastAPI html_url: https://github.com/insistence/RuoYi-Vue3-FastAPI - stars: 930 + stars: 974 owner_login: insistence owner_html_url: https://github.com/insistence - name: aktools html_url: https://github.com/akfamily/aktools - stars: 916 + stars: 972 owner_login: akfamily owner_html_url: https://github.com/akfamily +- name: titiler + html_url: https://github.com/developmentseed/titiler + stars: 965 + owner_login: developmentseed + owner_html_url: https://github.com/developmentseed +- name: secure + html_url: https://github.com/TypeError/secure + stars: 953 + owner_login: TypeError + owner_html_url: https://github.com/TypeError +- name: energy-forecasting + html_url: https://github.com/iusztinpaul/energy-forecasting + stars: 949 + owner_login: iusztinpaul + owner_html_url: https://github.com/iusztinpaul - name: every-pdf html_url: https://github.com/DDULDDUCK/every-pdf - stars: 907 + stars: 942 owner_login: DDULDDUCK owner_html_url: https://github.com/DDULDDUCK -- name: marker-api - html_url: https://github.com/adithya-s-k/marker-api - stars: 903 - owner_login: adithya-s-k - owner_html_url: https://github.com/adithya-s-k +- name: langcorn + html_url: https://github.com/msoedov/langcorn + stars: 933 + owner_login: msoedov + owner_html_url: https://github.com/msoedov - name: fastapi-observability html_url: https://github.com/blueswen/fastapi-observability - stars: 902 + stars: 923 owner_login: blueswen owner_html_url: https://github.com/blueswen -- name: fastapi-do-zero - html_url: https://github.com/dunossauro/fastapi-do-zero - stars: 900 - owner_login: dunossauro - owner_html_url: https://github.com/dunossauro From f8df43d734c6982c4ad5c6094b05179d0326583b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebasti=C3=A1n=20Ram=C3=ADrez?= Date: Mon, 3 Nov 2025 10:24:09 +0100 Subject: [PATCH 02/16] =?UTF-8?q?=F0=9F=91=A5=20Update=20FastAPI=20People?= =?UTF-8?q?=20-=20Sponsors=20(#14274)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: github-actions --- docs/en/data/github_sponsors.yml | 205 ++++++++++++++++--------------- 1 file changed, 107 insertions(+), 98 deletions(-) diff --git a/docs/en/data/github_sponsors.yml b/docs/en/data/github_sponsors.yml index 7b34719b6..3d8ecdb7a 100644 --- a/docs/en/data/github_sponsors.yml +++ b/docs/en/data/github_sponsors.yml @@ -14,6 +14,9 @@ sponsors: - login: coderabbitai avatarUrl: https://avatars.githubusercontent.com/u/132028505?v=4 url: https://github.com/coderabbitai + - login: greptileai + avatarUrl: https://avatars.githubusercontent.com/u/140149887?v=4 + url: https://github.com/greptileai - login: subtotal avatarUrl: https://avatars.githubusercontent.com/u/176449348?v=4 url: https://github.com/subtotal @@ -41,9 +44,9 @@ sponsors: - login: permitio avatarUrl: https://avatars.githubusercontent.com/u/71775833?v=4 url: https://github.com/permitio -- - login: marvin-robot - avatarUrl: https://avatars.githubusercontent.com/u/41086007?u=b9fcab402d0cd0aec738b6574fe60855cb0cd36d&v=4 - url: https://github.com/marvin-robot +- - login: BoostryJP + avatarUrl: https://avatars.githubusercontent.com/u/57932412?v=4 + url: https://github.com/BoostryJP - login: mercedes-benz avatarUrl: https://avatars.githubusercontent.com/u/34240465?v=4 url: https://github.com/mercedes-benz @@ -53,9 +56,9 @@ sponsors: - login: LambdaTest-Inc avatarUrl: https://avatars.githubusercontent.com/u/171592363?u=96606606a45fa170427206199014f2a5a2a4920b&v=4 url: https://github.com/LambdaTest-Inc - - login: BoostryJP - avatarUrl: https://avatars.githubusercontent.com/u/57932412?v=4 - url: https://github.com/BoostryJP + - login: requestly + avatarUrl: https://avatars.githubusercontent.com/u/12287519?v=4 + url: https://github.com/requestly - login: acsone avatarUrl: https://avatars.githubusercontent.com/u/7601056?v=4 url: https://github.com/acsone @@ -71,27 +74,39 @@ sponsors: - - login: mainframeindustries avatarUrl: https://avatars.githubusercontent.com/u/55092103?v=4 url: https://github.com/mainframeindustries - - login: yasyf - avatarUrl: https://avatars.githubusercontent.com/u/709645?u=f36736b3c6a85f578886ecc42a740e7b436e7a01&v=4 - url: https://github.com/yasyf - - login: alixlahuec avatarUrl: https://avatars.githubusercontent.com/u/29543316?u=44357eb2a93bccf30fb9d389b8befe94a3d00985&v=4 url: https://github.com/alixlahuec + - login: Partho + avatarUrl: https://avatars.githubusercontent.com/u/2034301?u=ce195ac36835cca0cdfe6dd6e897bd38873a1524&v=4 + url: https://github.com/Partho - - login: primer-io avatarUrl: https://avatars.githubusercontent.com/u/62146168?v=4 url: https://github.com/primer-io -- - login: nilslindemann - avatarUrl: https://avatars.githubusercontent.com/u/6892179?u=1dca6a22195d6cd1ab20737c0e19a4c55d639472&v=4 - url: https://github.com/nilslindemann - - login: upciti + - login: xsalagarcia + avatarUrl: https://avatars.githubusercontent.com/u/66035908?v=4 + url: https://github.com/xsalagarcia +- - login: upciti avatarUrl: https://avatars.githubusercontent.com/u/43346262?v=4 url: https://github.com/upciti - - login: thisisfixer - avatarUrl: https://avatars.githubusercontent.com/u/14433035?u=076d52a5b7891c764904af9f462bfb45428e25df&v=4 - url: https://github.com/thisisfixer + - login: GonnaFlyMethod + avatarUrl: https://avatars.githubusercontent.com/u/60840539?u=edf70b373fd4f1a83d3eb7c6802f4b6addb572cf&v=4 + url: https://github.com/GonnaFlyMethod + - login: ChargeStorm + avatarUrl: https://avatars.githubusercontent.com/u/26000165?v=4 + url: https://github.com/ChargeStorm + - login: DanielYang59 + avatarUrl: https://avatars.githubusercontent.com/u/80093591?u=63873f701c7c74aac83c906800a1dddc0bc8c92f&v=4 + url: https://github.com/DanielYang59 + - login: nilslindemann + avatarUrl: https://avatars.githubusercontent.com/u/6892179?u=1dca6a22195d6cd1ab20737c0e19a4c55d639472&v=4 + url: https://github.com/nilslindemann - - login: samuelcolvin avatarUrl: https://avatars.githubusercontent.com/u/4039449?u=42eb3b833047c8c4b4f647a031eaef148c16d93f&v=4 url: https://github.com/samuelcolvin + - login: vincentkoc + avatarUrl: https://avatars.githubusercontent.com/u/25068?u=fbd5b2d51142daa4bdbc21e21953a3b8b8188a4a&v=4 + url: https://github.com/vincentkoc - login: otosky avatarUrl: https://avatars.githubusercontent.com/u/42260747?u=69d089387c743d89427aa4ad8740cfb34045a9e0&v=4 url: https://github.com/otosky @@ -101,6 +116,9 @@ sponsors: - login: roboflow avatarUrl: https://avatars.githubusercontent.com/u/53104118?v=4 url: https://github.com/roboflow + - login: dudikbender + avatarUrl: https://avatars.githubusercontent.com/u/53487583?u=3a57542938ebfd57579a0111db2b297e606d9681&v=4 + url: https://github.com/dudikbender - login: ehaca avatarUrl: https://avatars.githubusercontent.com/u/25950317?u=cec1a3e0643b785288ae8260cc295a85ab344995&v=4 url: https://github.com/ehaca @@ -113,21 +131,15 @@ sponsors: - login: Leay15 avatarUrl: https://avatars.githubusercontent.com/u/32212558?u=c4aa9c1737e515959382a5515381757b1fd86c53&v=4 url: https://github.com/Leay15 - - login: kaoru0310 - avatarUrl: https://avatars.githubusercontent.com/u/80977929?u=1b61d10142b490e56af932ddf08a390fae8ee94f&v=4 - url: https://github.com/kaoru0310 - - login: DelfinaCare - avatarUrl: https://avatars.githubusercontent.com/u/83734439?v=4 - url: https://github.com/DelfinaCare - login: Karine-Bauch avatarUrl: https://avatars.githubusercontent.com/u/90465103?u=7feb1018abb1a5631cfd9a91fea723d1ceb5f49b&v=4 url: https://github.com/Karine-Bauch - login: jugeeem avatarUrl: https://avatars.githubusercontent.com/u/116043716?u=ae590d79c38ac79c91b9c5caa6887d061e865a3d&v=4 url: https://github.com/jugeeem - - login: dudikbender - avatarUrl: https://avatars.githubusercontent.com/u/53487583?u=3a57542938ebfd57579a0111db2b297e606d9681&v=4 - url: https://github.com/dudikbender + - login: connorpark24 + avatarUrl: https://avatars.githubusercontent.com/u/142128990?u=09b84a4beb1f629b77287a837bcf3729785cdd89&v=4 + url: https://github.com/connorpark24 - login: patsatsia avatarUrl: https://avatars.githubusercontent.com/u/61111267?u=3271b85f7a37b479c8d0ae0a235182e83c166edf&v=4 url: https://github.com/patsatsia @@ -140,9 +152,12 @@ sponsors: - login: chickenandstats avatarUrl: https://avatars.githubusercontent.com/u/79477966?u=ae2b894aa954070db1d7830dab99b49eba4e4567&v=4 url: https://github.com/chickenandstats - - login: dodo5522 - avatarUrl: https://avatars.githubusercontent.com/u/1362607?u=9bf1e0e520cccc547c046610c468ce6115bbcf9f&v=4 - url: https://github.com/dodo5522 + - login: kaoru0310 + avatarUrl: https://avatars.githubusercontent.com/u/80977929?u=1b61d10142b490e56af932ddf08a390fae8ee94f&v=4 + url: https://github.com/kaoru0310 + - login: DelfinaCare + avatarUrl: https://avatars.githubusercontent.com/u/83734439?v=4 + url: https://github.com/DelfinaCare - login: knallgelb avatarUrl: https://avatars.githubusercontent.com/u/2358812?u=c48cb6362b309d74cbf144bd6ad3aed3eb443e82&v=4 url: https://github.com/knallgelb @@ -170,9 +185,12 @@ sponsors: - login: Ryandaydev avatarUrl: https://avatars.githubusercontent.com/u/4292423?u=679ff84cb7b988c5795a5fa583857f574a055763&v=4 url: https://github.com/Ryandaydev - - login: vincentkoc - avatarUrl: https://avatars.githubusercontent.com/u/25068?u=fbd5b2d51142daa4bdbc21e21953a3b8b8188a4a&v=4 - url: https://github.com/vincentkoc + - login: jaredtrog + avatarUrl: https://avatars.githubusercontent.com/u/4381365?v=4 + url: https://github.com/jaredtrog + - login: oliverxchen + avatarUrl: https://avatars.githubusercontent.com/u/4471774?u=534191f25e32eeaadda22dfab4b0a428733d5489&v=4 + url: https://github.com/oliverxchen - login: jstanden avatarUrl: https://avatars.githubusercontent.com/u/63288?u=c3658d57d2862c607a0e19c2101c3c51876e36ad&v=4 url: https://github.com/jstanden @@ -197,6 +215,9 @@ sponsors: - login: mintuhouse avatarUrl: https://avatars.githubusercontent.com/u/769950?u=ecfbd79a97d33177e0d093ddb088283cf7fe8444&v=4 url: https://github.com/mintuhouse + - login: dodo5522 + avatarUrl: https://avatars.githubusercontent.com/u/1362607?u=9bf1e0e520cccc547c046610c468ce6115bbcf9f&v=4 + url: https://github.com/dodo5522 - login: wdwinslow avatarUrl: https://avatars.githubusercontent.com/u/11562137?u=371272f2c69e680e0559a7b0a57385e83a5dc728&v=4 url: https://github.com/wdwinslow @@ -212,18 +233,15 @@ sponsors: - login: mjohnsey avatarUrl: https://avatars.githubusercontent.com/u/16784016?u=38fad2e6b411244560b3af99c5f5a4751bc81865&v=4 url: https://github.com/mjohnsey + - login: enguy-hub + avatarUrl: https://avatars.githubusercontent.com/u/16822912?u=2c45f9e7f427b2f2f3b023d7fdb0d44764c92ae8&v=4 + url: https://github.com/enguy-hub - login: ashi-agrawal avatarUrl: https://avatars.githubusercontent.com/u/17105294?u=99c7a854035e5398d8e7b674f2d42baae6c957f8&v=4 url: https://github.com/ashi-agrawal - login: RaamEEIL avatarUrl: https://avatars.githubusercontent.com/u/20320552?v=4 url: https://github.com/RaamEEIL - - login: jaredtrog - avatarUrl: https://avatars.githubusercontent.com/u/4381365?v=4 - url: https://github.com/jaredtrog - - login: oliverxchen - avatarUrl: https://avatars.githubusercontent.com/u/4471774?u=534191f25e32eeaadda22dfab4b0a428733d5489&v=4 - url: https://github.com/oliverxchen - login: ternaus avatarUrl: https://avatars.githubusercontent.com/u/5481618?u=513a26b02a39e7a28d587cd37c6cc877ea368e6e&v=4 url: https://github.com/ternaus @@ -242,7 +260,10 @@ sponsors: - - login: manoelpqueiroz avatarUrl: https://avatars.githubusercontent.com/u/23669137?u=b12e84b28a84369ab5b30bd5a79e5788df5a0756&v=4 url: https://github.com/manoelpqueiroz -- - login: pawamoy +- - login: ceb10n + avatarUrl: https://avatars.githubusercontent.com/u/235213?u=edcce471814a1eba9f0cdaa4cd0de18921a940a6&v=4 + url: https://github.com/ceb10n + - login: pawamoy avatarUrl: https://avatars.githubusercontent.com/u/3999221?u=b030e4c89df2f3a36bc4710b925bdeb6745c9856&v=4 url: https://github.com/pawamoy - login: siavashyj @@ -260,9 +281,9 @@ sponsors: - login: hgalytoby avatarUrl: https://avatars.githubusercontent.com/u/50397689?u=6cc9028f3db63f8f60ad21c17b1ce4b88c4e2e60&v=4 url: https://github.com/hgalytoby - - login: nisutec - avatarUrl: https://avatars.githubusercontent.com/u/25281462?u=e562484c451fdfc59053163f64405f8eb262b8b0&v=4 - url: https://github.com/nisutec + - login: johnl28 + avatarUrl: https://avatars.githubusercontent.com/u/54412955?u=47dd06082d1c39caa90c752eb55566e4f3813957&v=4 + url: https://github.com/johnl28 - login: hoenie-ams avatarUrl: https://avatars.githubusercontent.com/u/25708487?u=cda07434f0509ac728d9edf5e681117c0f6b818b&v=4 url: https://github.com/hoenie-ams @@ -278,33 +299,21 @@ sponsors: - login: petercool avatarUrl: https://avatars.githubusercontent.com/u/37613029?u=75aa8c6729e6e8f85a300561c4dbeef9d65c8797&v=4 url: https://github.com/petercool - - login: JulioPeixoto - avatarUrl: https://avatars.githubusercontent.com/u/96303574?u=27d4614350cae33653f1be35cb47c92a12627ac9&v=4 - url: https://github.com/JulioPeixoto - - login: johnl28 - avatarUrl: https://avatars.githubusercontent.com/u/54412955?u=47dd06082d1c39caa90c752eb55566e4f3813957&v=4 - url: https://github.com/johnl28 - login: PunRabbit avatarUrl: https://avatars.githubusercontent.com/u/70463212?u=1a835cfbc99295a60c8282f6aa6199d1b42241a5&v=4 url: https://github.com/PunRabbit - login: PelicanQ avatarUrl: https://avatars.githubusercontent.com/u/77930606?v=4 url: https://github.com/PelicanQ - - login: miguelgr - avatarUrl: https://avatars.githubusercontent.com/u/1484589?u=54556072b8136efa12ae3b6902032ea2a39ace4b&v=4 - url: https://github.com/miguelgr - - login: WillHogan - avatarUrl: https://avatars.githubusercontent.com/u/1661551?u=8a80356e3e7d5a417157aba7ea565dabc8678327&v=4 - url: https://github.com/WillHogan - login: my3 avatarUrl: https://avatars.githubusercontent.com/u/1825270?v=4 url: https://github.com/my3 - - login: Alisa-lisa - avatarUrl: https://avatars.githubusercontent.com/u/4137964?u=e7e393504f554f4ff15863a1e01a5746863ef9ce&v=4 - url: https://github.com/Alisa-lisa - - login: moonape1226 - avatarUrl: https://avatars.githubusercontent.com/u/8532038?u=d9f8b855a429fff9397c3833c2ff83849ebf989d&v=4 - url: https://github.com/moonape1226 + - login: danielunderwood + avatarUrl: https://avatars.githubusercontent.com/u/4472301?v=4 + url: https://github.com/danielunderwood + - login: rangulvers + avatarUrl: https://avatars.githubusercontent.com/u/5235430?u=e254d4af4ace5a05fa58372ae677c7d26f0d5a53&v=4 + url: https://github.com/rangulvers - login: ddanier avatarUrl: https://avatars.githubusercontent.com/u/113563?u=ed1dc79de72f93bd78581f88ebc6952b62f472da&v=4 url: https://github.com/ddanier @@ -314,24 +323,18 @@ sponsors: - login: slafs avatarUrl: https://avatars.githubusercontent.com/u/210173?v=4 url: https://github.com/slafs - - login: ceb10n - avatarUrl: https://avatars.githubusercontent.com/u/235213?u=edcce471814a1eba9f0cdaa4cd0de18921a940a6&v=4 - url: https://github.com/ceb10n - login: tochikuji avatarUrl: https://avatars.githubusercontent.com/u/851759?v=4 url: https://github.com/tochikuji - - login: xncbf - avatarUrl: https://avatars.githubusercontent.com/u/9462045?u=a80a7bb349555b277645632ed66639ff43400614&v=4 - url: https://github.com/xncbf - - login: DMantis - avatarUrl: https://avatars.githubusercontent.com/u/9536869?u=652dd0d49717803c0cbcbf44f7740e53cf2d4892&v=4 - url: https://github.com/DMantis + - login: miguelgr + avatarUrl: https://avatars.githubusercontent.com/u/1484589?u=54556072b8136efa12ae3b6902032ea2a39ace4b&v=4 + url: https://github.com/miguelgr + - login: WillHogan + avatarUrl: https://avatars.githubusercontent.com/u/1661551?u=8a80356e3e7d5a417157aba7ea565dabc8678327&v=4 + url: https://github.com/WillHogan - login: hard-coders avatarUrl: https://avatars.githubusercontent.com/u/9651103?u=95db33927bbff1ed1c07efddeb97ac2ff33068ed&v=4 url: https://github.com/hard-coders - - login: supdann - avatarUrl: https://avatars.githubusercontent.com/u/9986994?u=9671810f4ae9504c063227fee34fd47567ff6954&v=4 - url: https://github.com/supdann - login: mntolia avatarUrl: https://avatars.githubusercontent.com/u/10390224?v=4 url: https://github.com/mntolia @@ -344,12 +347,9 @@ sponsors: - login: joshuatz avatarUrl: https://avatars.githubusercontent.com/u/17817563?u=f1bf05b690d1fc164218f0b420cdd3acb7913e21&v=4 url: https://github.com/joshuatz - - login: danielunderwood - avatarUrl: https://avatars.githubusercontent.com/u/4472301?v=4 - url: https://github.com/danielunderwood - - login: rangulvers - avatarUrl: https://avatars.githubusercontent.com/u/5235430?u=e254d4af4ace5a05fa58372ae677c7d26f0d5a53&v=4 - url: https://github.com/rangulvers + - login: nisutec + avatarUrl: https://avatars.githubusercontent.com/u/25281462?u=e562484c451fdfc59053163f64405f8eb262b8b0&v=4 + url: https://github.com/nisutec - login: sdevkota avatarUrl: https://avatars.githubusercontent.com/u/5250987?u=4ed9a120c89805a8aefda1cbdc0cf6512e64d1b4&v=4 url: https://github.com/sdevkota @@ -365,39 +365,45 @@ sponsors: - login: harsh183 avatarUrl: https://avatars.githubusercontent.com/u/7780198?v=4 url: https://github.com/harsh183 -- - login: KOZ39 - avatarUrl: https://avatars.githubusercontent.com/u/38822500?u=9dfc0a697df1c9628f08e20dc3fb17b1afc4e5a7&v=4 - url: https://github.com/KOZ39 - - login: rwxd - avatarUrl: https://avatars.githubusercontent.com/u/40308458?u=cd04a39e3655923be4f25c2ba8a5a07b3da3230a&v=4 - url: https://github.com/rwxd - - login: morzan1001 + - login: moonape1226 + avatarUrl: https://avatars.githubusercontent.com/u/8532038?u=d9f8b855a429fff9397c3833c2ff83849ebf989d&v=4 + url: https://github.com/moonape1226 + - login: xncbf + avatarUrl: https://avatars.githubusercontent.com/u/9462045?u=a80a7bb349555b277645632ed66639ff43400614&v=4 + url: https://github.com/xncbf + - login: DMantis + avatarUrl: https://avatars.githubusercontent.com/u/9536869?u=652dd0d49717803c0cbcbf44f7740e53cf2d4892&v=4 + url: https://github.com/DMantis +- - login: morzan1001 avatarUrl: https://avatars.githubusercontent.com/u/47593005?u=c30ab7230f82a12a9b938dcb54f84a996931409a&v=4 url: https://github.com/morzan1001 - - login: azharthegeek - avatarUrl: https://avatars.githubusercontent.com/u/51288109?u=0987b2a9f39c21ccb071b6bdce0fc60d8492f8e8&v=4 - url: https://github.com/azharthegeek - - login: Olegt0rr - avatarUrl: https://avatars.githubusercontent.com/u/25399456?u=3e87b5239a2f4600975ba13be73054f8567c6060&v=4 - url: https://github.com/Olegt0rr - login: larsyngvelundin avatarUrl: https://avatars.githubusercontent.com/u/34173819?u=74958599695bf83ac9f1addd935a51548a10c6b0&v=4 url: https://github.com/larsyngvelundin - login: andrecorumba avatarUrl: https://avatars.githubusercontent.com/u/37807517?u=9b9be3b41da9bda60957da9ef37b50dbf65baa61&v=4 url: https://github.com/andrecorumba - - login: ChenPu2002 - avatarUrl: https://avatars.githubusercontent.com/u/113831763?v=4 - url: https://github.com/ChenPu2002 + - login: KOZ39 + avatarUrl: https://avatars.githubusercontent.com/u/38822500?u=9dfc0a697df1c9628f08e20dc3fb17b1afc4e5a7&v=4 + url: https://github.com/KOZ39 + - login: rwxd + avatarUrl: https://avatars.githubusercontent.com/u/40308458?u=cd04a39e3655923be4f25c2ba8a5a07b3da3230a&v=4 + url: https://github.com/rwxd + - login: hippoley + avatarUrl: https://avatars.githubusercontent.com/u/135493401?u=1164ef48a645a7c12664fabc1638fbb7e1c459b0&v=4 + url: https://github.com/hippoley - login: CoderDeltaLAN avatarUrl: https://avatars.githubusercontent.com/u/152043745?u=4ff541efffb7d134e60c5fcf2dd1e343f90bb782&v=4 url: https://github.com/CoderDeltaLAN - - login: aghents - avatarUrl: https://avatars.githubusercontent.com/u/60949885?u=d8616ddf22cf998a712cdceefd6a0256a178fe9d&v=4 - url: https://github.com/aghents - - login: 0ne-stone + - login: chris1ding1 + avatarUrl: https://avatars.githubusercontent.com/u/194386334?u=5500604b50e35ed8a5aeb82ce34aa5d3ee3f88c7&v=4 + url: https://github.com/chris1ding1 + - login: onestn avatarUrl: https://avatars.githubusercontent.com/u/62360849?u=746dd21c34e7e06eefb11b03e8bb01aaae3c2a4f&v=4 - url: https://github.com/0ne-stone + url: https://github.com/onestn + - login: Rubinskiy + avatarUrl: https://avatars.githubusercontent.com/u/62457878?u=f2e35ed3d196a99cfadb5a29a91950342af07e34&v=4 + url: https://github.com/Rubinskiy - login: nayasinghania avatarUrl: https://avatars.githubusercontent.com/u/74111380?u=752e99a5e139389fdc0a0677122adc08438eb076&v=4 url: https://github.com/nayasinghania @@ -407,6 +413,9 @@ sponsors: - login: andreagrandi avatarUrl: https://avatars.githubusercontent.com/u/636391?u=13d90cb8ec313593a5b71fbd4e33b78d6da736f5&v=4 url: https://github.com/andreagrandi + - login: Olegt0rr + avatarUrl: https://avatars.githubusercontent.com/u/25399456?u=3e87b5239a2f4600975ba13be73054f8567c6060&v=4 + url: https://github.com/Olegt0rr - login: msserpa avatarUrl: https://avatars.githubusercontent.com/u/6334934?u=82c4489eb1559d88d2990d60001901b14f722bbb&v=4 url: https://github.com/msserpa From 940ee0c9c357f749ede6dd0d8d8dde361c1ef883 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Mon, 3 Nov 2025 09:24:17 +0000 Subject: [PATCH 03/16] =?UTF-8?q?=F0=9F=93=9D=20Update=20release=20notes?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit [skip ci] --- docs/en/docs/release-notes.md | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/en/docs/release-notes.md b/docs/en/docs/release-notes.md index 303017d9d..e9c013a7c 100644 --- a/docs/en/docs/release-notes.md +++ b/docs/en/docs/release-notes.md @@ -9,6 +9,7 @@ hide: ### Internal +* 👥 Update FastAPI GitHub topic repositories. PR [#14280](https://github.com/fastapi/fastapi/pull/14280) by [@tiangolo](https://github.com/tiangolo). * ⬆ Bump mkdocs-macros-plugin from 1.4.0 to 1.4.1. PR [#14277](https://github.com/fastapi/fastapi/pull/14277) by [@dependabot[bot]](https://github.com/apps/dependabot). * ⬆ Bump mkdocstrings[python] from 0.26.1 to 0.30.1. PR [#14279](https://github.com/fastapi/fastapi/pull/14279) by [@dependabot[bot]](https://github.com/apps/dependabot). From 566e0d60b29f3fe302c0a8561d108621e496d009 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebasti=C3=A1n=20Ram=C3=ADrez?= Date: Mon, 3 Nov 2025 10:24:36 +0100 Subject: [PATCH 04/16] =?UTF-8?q?=F0=9F=91=A5=20Update=20FastAPI=20People?= =?UTF-8?q?=20-=20Contributors=20and=20Translators=20(#14273)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: github-actions --- docs/en/data/contributors.yml | 52 +++++++++++++------------- docs/en/data/translation_reviewers.yml | 8 ++-- docs/en/data/translators.yml | 12 +++--- 3 files changed, 36 insertions(+), 36 deletions(-) diff --git a/docs/en/data/contributors.yml b/docs/en/data/contributors.yml index c892d8baf..592c79af0 100644 --- a/docs/en/data/contributors.yml +++ b/docs/en/data/contributors.yml @@ -1,11 +1,11 @@ tiangolo: login: tiangolo - count: 782 + count: 794 avatarUrl: https://avatars.githubusercontent.com/u/1326112?u=cb5d06e73a9e1998141b1641aa88e443c6717651&v=4 url: https://github.com/tiangolo dependabot: login: dependabot - count: 117 + count: 126 avatarUrl: https://avatars.githubusercontent.com/in/29110?v=4 url: https://github.com/apps/dependabot alejsdev: @@ -15,7 +15,7 @@ alejsdev: url: https://github.com/alejsdev pre-commit-ci: login: pre-commit-ci - count: 45 + count: 49 avatarUrl: https://avatars.githubusercontent.com/in/68672?v=4 url: https://github.com/apps/pre-commit-ci github-actions: @@ -25,7 +25,7 @@ github-actions: url: https://github.com/apps/github-actions Kludex: login: Kludex - count: 24 + count: 25 avatarUrl: https://avatars.githubusercontent.com/u/7353520?u=df8a3f06ba8f55ae1967a3e2d5ed882903a4e330&v=4 url: https://github.com/Kludex dmontagu: @@ -33,36 +33,36 @@ dmontagu: count: 17 avatarUrl: https://avatars.githubusercontent.com/u/35119617?u=540f30c937a6450812628b9592a1dfe91bbe148e&v=4 url: https://github.com/dmontagu +YuriiMotov: + login: YuriiMotov + count: 15 + avatarUrl: https://avatars.githubusercontent.com/u/109919500?u=b9b13d598dddfab529a52d264df80a900bfe7060&v=4 + url: https://github.com/YuriiMotov +nilslindemann: + login: nilslindemann + count: 14 + avatarUrl: https://avatars.githubusercontent.com/u/6892179?u=1dca6a22195d6cd1ab20737c0e19a4c55d639472&v=4 + url: https://github.com/nilslindemann euri10: login: euri10 count: 13 avatarUrl: https://avatars.githubusercontent.com/u/1104190?u=321a2e953e6645a7d09b732786c7a8061e0f8a8b&v=4 url: https://github.com/euri10 -nilslindemann: - login: nilslindemann +svlandeg: + login: svlandeg count: 13 - avatarUrl: https://avatars.githubusercontent.com/u/6892179?u=1dca6a22195d6cd1ab20737c0e19a4c55d639472&v=4 - url: https://github.com/nilslindemann + avatarUrl: https://avatars.githubusercontent.com/u/8796347?u=556c97650c27021911b0b9447ec55e75987b0e8a&v=4 + url: https://github.com/svlandeg kantandane: login: kantandane count: 13 avatarUrl: https://avatars.githubusercontent.com/u/3978368?u=cccc199291f991a73b1ebba5abc735a948e0bd16&v=4 url: https://github.com/kantandane -svlandeg: - login: svlandeg - count: 11 - avatarUrl: https://avatars.githubusercontent.com/u/8796347?u=556c97650c27021911b0b9447ec55e75987b0e8a&v=4 - url: https://github.com/svlandeg zhaohan-dong: login: zhaohan-dong count: 11 avatarUrl: https://avatars.githubusercontent.com/u/65422392?u=8260f8781f50248410ebfa4c9bf70e143fe5c9f2&v=4 url: https://github.com/zhaohan-dong -YuriiMotov: - login: YuriiMotov - count: 10 - avatarUrl: https://avatars.githubusercontent.com/u/109919500?u=b9b13d598dddfab529a52d264df80a900bfe7060&v=4 - url: https://github.com/YuriiMotov mariacamilagl: login: mariacamilagl count: 9 @@ -158,6 +158,11 @@ prostomarkeloff: count: 3 avatarUrl: https://avatars.githubusercontent.com/u/28061158?u=6918e39a1224194ba636e897461a02a20126d7ad&v=4 url: https://github.com/prostomarkeloff +frankie567: + login: frankie567 + count: 3 + avatarUrl: https://avatars.githubusercontent.com/u/1144727?u=f3e79acfe4ed207e15c2145161a8a9759925fcd2&v=4 + url: https://github.com/frankie567 nsidnev: login: nsidnev count: 3 @@ -191,7 +196,7 @@ Serrones: uriyyo: login: uriyyo count: 3 - avatarUrl: https://avatars.githubusercontent.com/u/32038156?u=0c68019beb28381ce5205a838937c61e0fe3fee2&v=4 + avatarUrl: https://avatars.githubusercontent.com/u/32038156?u=c26ca9b821fcf6499b84db75f553d4980bf8d023&v=4 url: https://github.com/uriyyo andrew222651: login: andrew222651 @@ -261,7 +266,7 @@ Nimitha-jagadeesha: lucaromagnoli: login: lucaromagnoli count: 3 - avatarUrl: https://avatars.githubusercontent.com/u/38782977?u=e66396859f493b4ddcb3a837a1b2b2039c805417&v=4 + avatarUrl: https://avatars.githubusercontent.com/u/38782977?u=15df02e806a2293af40ac619fba11dbe3c0c4fd4&v=4 url: https://github.com/lucaromagnoli salmantec: login: salmantec @@ -328,11 +333,6 @@ svalouch: count: 2 avatarUrl: https://avatars.githubusercontent.com/u/54674660?v=4 url: https://github.com/svalouch -frankie567: - login: frankie567 - count: 2 - avatarUrl: https://avatars.githubusercontent.com/u/1144727?u=f3e79acfe4ed207e15c2145161a8a9759925fcd2&v=4 - url: https://github.com/frankie567 marier-nico: login: marier-nico count: 2 @@ -346,7 +346,7 @@ Dustyposa: aviramha: login: aviramha count: 2 - avatarUrl: https://avatars.githubusercontent.com/u/41201924?u=6883cc4fc13a7b2e60d4deddd4be06f9c5287880&v=4 + avatarUrl: https://avatars.githubusercontent.com/u/41201924?u=ce5d3ea7037c2e6b3f82eff87e2217d4fb63214b&v=4 url: https://github.com/aviramha iwpnd: login: iwpnd diff --git a/docs/en/data/translation_reviewers.yml b/docs/en/data/translation_reviewers.yml index 68ef01f6d..45aa55e5e 100644 --- a/docs/en/data/translation_reviewers.yml +++ b/docs/en/data/translation_reviewers.yml @@ -776,7 +776,7 @@ pablocm83: d2a-raudenaerde: login: d2a-raudenaerde count: 7 - avatarUrl: https://avatars.githubusercontent.com/u/5213150?v=4 + avatarUrl: https://avatars.githubusercontent.com/u/5213150?u=e6d0ef65c571c7e544fc1c7ec151c7c0a72fb6bb&v=4 url: https://github.com/d2a-raudenaerde valentinDruzhinin: login: valentinDruzhinin @@ -1206,7 +1206,7 @@ akagaeng: phamquanganh31101998: login: phamquanganh31101998 count: 3 - avatarUrl: https://avatars.githubusercontent.com/u/43257497?u=36fa4ee689415d869a98453083a7c4213d2136ee&v=4 + avatarUrl: https://avatars.githubusercontent.com/u/43257497?u=6b3419ea9e318c356c42a973fb947682590bd8d3&v=4 url: https://github.com/phamquanganh31101998 peebbv6364: login: peebbv6364 @@ -1806,7 +1806,7 @@ MrL8199: ivintoiu: login: ivintoiu count: 2 - avatarUrl: https://avatars.githubusercontent.com/u/1853336?u=5e3d0977f44661fb9712fa297cc8f7608ea6ce48&v=4 + avatarUrl: https://avatars.githubusercontent.com/u/1853336?u=b537c905ad08b69993de8796fb235c8d4d47f039&v=4 url: https://github.com/ivintoiu TechnoService2: login: TechnoService2 @@ -1841,7 +1841,7 @@ NavesSapnis: eqsdxr: login: eqsdxr count: 2 - avatarUrl: https://avatars.githubusercontent.com/u/157279130?u=58fddf77ed76966eaa8c73eea9bea4bb0c53b673&v=4 + avatarUrl: https://avatars.githubusercontent.com/u/157279130?u=d7aaffb29f542b647cf0f6b0e05722490863658a&v=4 url: https://github.com/eqsdxr syedasamina56: login: syedasamina56 diff --git a/docs/en/data/translators.yml b/docs/en/data/translators.yml index cf61eee8e..a4b87e1bf 100644 --- a/docs/en/data/translators.yml +++ b/docs/en/data/translators.yml @@ -1,6 +1,6 @@ nilslindemann: login: nilslindemann - count: 122 + count: 124 avatarUrl: https://avatars.githubusercontent.com/u/6892179?u=1dca6a22195d6cd1ab20737c0e19a4c55d639472&v=4 url: https://github.com/nilslindemann jaystone776: @@ -103,6 +103,11 @@ pablocm83: count: 8 avatarUrl: https://avatars.githubusercontent.com/u/28315068?u=3310fbb05bb8bfc50d2c48b6cb64ac9ee4a14549&v=4 url: https://github.com/pablocm83 +tiangolo: + login: tiangolo + count: 7 + avatarUrl: https://avatars.githubusercontent.com/u/1326112?u=cb5d06e73a9e1998141b1641aa88e443c6717651&v=4 + url: https://github.com/tiangolo ptt3199: login: ptt3199 count: 7 @@ -118,11 +123,6 @@ batlopes: count: 6 avatarUrl: https://avatars.githubusercontent.com/u/33462923?u=0fb3d7acb316764616f11e4947faf080e49ad8d9&v=4 url: https://github.com/batlopes -tiangolo: - login: tiangolo - count: 6 - avatarUrl: https://avatars.githubusercontent.com/u/1326112?u=cb5d06e73a9e1998141b1641aa88e443c6717651&v=4 - url: https://github.com/tiangolo lucasbalieiro: login: lucasbalieiro count: 6 From 3a223b90737200628d6aaf2b6cdba0944433bae7 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Mon, 3 Nov 2025 09:24:57 +0000 Subject: [PATCH 05/16] =?UTF-8?q?=F0=9F=93=9D=20Update=20release=20notes?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit [skip ci] --- docs/en/docs/release-notes.md | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/en/docs/release-notes.md b/docs/en/docs/release-notes.md index e9c013a7c..a0f870b3b 100644 --- a/docs/en/docs/release-notes.md +++ b/docs/en/docs/release-notes.md @@ -9,6 +9,7 @@ hide: ### Internal +* 👥 Update FastAPI People - Sponsors. PR [#14274](https://github.com/fastapi/fastapi/pull/14274) by [@tiangolo](https://github.com/tiangolo). * 👥 Update FastAPI GitHub topic repositories. PR [#14280](https://github.com/fastapi/fastapi/pull/14280) by [@tiangolo](https://github.com/tiangolo). * ⬆ Bump mkdocs-macros-plugin from 1.4.0 to 1.4.1. PR [#14277](https://github.com/fastapi/fastapi/pull/14277) by [@dependabot[bot]](https://github.com/apps/dependabot). * ⬆ Bump mkdocstrings[python] from 0.26.1 to 0.30.1. PR [#14279](https://github.com/fastapi/fastapi/pull/14279) by [@dependabot[bot]](https://github.com/apps/dependabot). From 425a4c5bb1d1a8e00007e82e5188fc4d30585767 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Mon, 3 Nov 2025 09:25:02 +0000 Subject: [PATCH 06/16] =?UTF-8?q?=F0=9F=93=9D=20Update=20release=20notes?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit [skip ci] --- docs/en/docs/release-notes.md | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/en/docs/release-notes.md b/docs/en/docs/release-notes.md index a0f870b3b..5e6fea9d5 100644 --- a/docs/en/docs/release-notes.md +++ b/docs/en/docs/release-notes.md @@ -9,6 +9,7 @@ hide: ### Internal +* 👥 Update FastAPI People - Contributors and Translators. PR [#14273](https://github.com/fastapi/fastapi/pull/14273) by [@tiangolo](https://github.com/tiangolo). * 👥 Update FastAPI People - Sponsors. PR [#14274](https://github.com/fastapi/fastapi/pull/14274) by [@tiangolo](https://github.com/tiangolo). * 👥 Update FastAPI GitHub topic repositories. PR [#14280](https://github.com/fastapi/fastapi/pull/14280) by [@tiangolo](https://github.com/tiangolo). * ⬆ Bump mkdocs-macros-plugin from 1.4.0 to 1.4.1. PR [#14277](https://github.com/fastapi/fastapi/pull/14277) by [@dependabot[bot]](https://github.com/apps/dependabot). From ac438b99342c859ae0e10f7064021125bd247bf5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebasti=C3=A1n=20Ram=C3=ADrez?= Date: Mon, 3 Nov 2025 11:12:49 +0100 Subject: [PATCH 07/16] =?UTF-8?q?=E2=9C=A8=20Add=20support=20for=20depende?= =?UTF-8?q?ncies=20with=20scopes,=20support=20`scope=3D"request"`=20for=20?= =?UTF-8?q?dependencies=20with=20`yield`=20that=20exit=20before=20the=20re?= =?UTF-8?q?sponse=20is=20sent=20(#14262)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> --- .../dependencies/dependencies-with-yield.md | 45 ++++ docs_src/dependencies/tutorial008e.py | 15 ++ docs_src/dependencies/tutorial008e_an.py | 16 ++ docs_src/dependencies/tutorial008e_an_py39.py | 17 ++ fastapi/dependencies/models.py | 54 ++++- fastapi/dependencies/utils.py | 100 +++++---- fastapi/exceptions.py | 7 + fastapi/param_functions.py | 24 ++- fastapi/params.py | 3 +- fastapi/routing.py | 27 ++- fastapi/types.py | 3 +- tests/test_dependency_yield_scope.py | 184 ++++++++++++++++ .../test_dependency_yield_scope_websockets.py | 201 ++++++++++++++++++ .../test_dependencies/test_tutorial008e.py | 27 +++ 14 files changed, 653 insertions(+), 70 deletions(-) create mode 100644 docs_src/dependencies/tutorial008e.py create mode 100644 docs_src/dependencies/tutorial008e_an.py create mode 100644 docs_src/dependencies/tutorial008e_an_py39.py create mode 100644 tests/test_dependency_yield_scope.py create mode 100644 tests/test_dependency_yield_scope_websockets.py create mode 100644 tests/test_tutorial/test_dependencies/test_tutorial008e.py diff --git a/docs/en/docs/tutorial/dependencies/dependencies-with-yield.md b/docs/en/docs/tutorial/dependencies/dependencies-with-yield.md index adc1afa8d..494c40efa 100644 --- a/docs/en/docs/tutorial/dependencies/dependencies-with-yield.md +++ b/docs/en/docs/tutorial/dependencies/dependencies-with-yield.md @@ -184,6 +184,51 @@ If you raise any exception in the code from the *path operation function*, it wi /// +## Early exit and `scope` { #early-exit-and-scope } + +Normally the exit code of dependencies with `yield` is executed **after the response** is sent to the client. + +But if you know that you won't need to use the dependency after returning from the *path operation function*, you can use `Depends(scope="function")` to tell FastAPI that it should close the dependency after the *path operation function* returns, but **before** the **response is sent**. + +{* ../../docs_src/dependencies/tutorial008e_an_py39.py hl[12,16] *} + +`Depends()` receives a `scope` parameter that can be: + +* `"function"`: start the dependency before the *path operation function* that handles the request, end the dependency after the *path operation function* ends, but **before** the response is sent back to the client. So, the dependency function will be executed **around** the *path operation **function***. +* `"request"`: start the dependency before the *path operation function* 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. + +If not specified and the dependency has `yield`, it will have a `scope` of `"request"` by default. + +### `scope` for sub-dependencies { #scope-for-sub-dependencies } + +When you declare a dependency with a `scope="request"` (the default), any sub-dependency needs to also have a `scope` of `"request"`. + +But a dependency with `scope` of `"function"` can have dependencies with `scope` of `"function"` and `scope` of `"request"`. + +This is because any dependency needs to be able to run its exit code before the sub-dependencies, as it might need to still use them during its exit code. + +```mermaid +sequenceDiagram + +participant client as Client +participant dep_req as Dep scope="request" +participant dep_func as Dep scope="function" +participant operation as Path Operation + + client ->> dep_req: Start request + Note over dep_req: Run code up to yield + dep_req ->> dep_func: Pass dependency + Note over dep_func: Run code up to yield + dep_func ->> operation: Run path operation with dependency + operation ->> dep_func: Return from path operation + Note over dep_func: Run code after yield + Note over dep_func: ✅ Dependency closed + dep_func ->> client: Send response to client + Note over client: Response sent + Note over dep_req: Run code after yield + Note over dep_req: ✅ Dependency closed +``` + ## Dependencies with `yield`, `HTTPException`, `except` and Background Tasks { #dependencies-with-yield-httpexception-except-and-background-tasks } Dependencies with `yield` have evolved over time to cover different use cases and fix some issues. diff --git a/docs_src/dependencies/tutorial008e.py b/docs_src/dependencies/tutorial008e.py new file mode 100644 index 000000000..1ed056e91 --- /dev/null +++ b/docs_src/dependencies/tutorial008e.py @@ -0,0 +1,15 @@ +from fastapi import Depends, FastAPI + +app = FastAPI() + + +def get_username(): + try: + yield "Rick" + finally: + print("Cleanup up before response is sent") + + +@app.get("/users/me") +def get_user_me(username: str = Depends(get_username, scope="function")): + return username diff --git a/docs_src/dependencies/tutorial008e_an.py b/docs_src/dependencies/tutorial008e_an.py new file mode 100644 index 000000000..c8a0af2b3 --- /dev/null +++ b/docs_src/dependencies/tutorial008e_an.py @@ -0,0 +1,16 @@ +from fastapi import Depends, FastAPI +from typing_extensions import Annotated + +app = FastAPI() + + +def get_username(): + try: + yield "Rick" + finally: + print("Cleanup up before response is sent") + + +@app.get("/users/me") +def get_user_me(username: Annotated[str, Depends(get_username, scope="function")]): + return username diff --git a/docs_src/dependencies/tutorial008e_an_py39.py b/docs_src/dependencies/tutorial008e_an_py39.py new file mode 100644 index 000000000..80a44c7e2 --- /dev/null +++ b/docs_src/dependencies/tutorial008e_an_py39.py @@ -0,0 +1,17 @@ +from typing import Annotated + +from fastapi import Depends, FastAPI + +app = FastAPI() + + +def get_username(): + try: + yield "Rick" + finally: + print("Cleanup up before response is sent") + + +@app.get("/users/me") +def get_user_me(username: Annotated[str, Depends(get_username, scope="function")]): + return username diff --git a/fastapi/dependencies/models.py b/fastapi/dependencies/models.py index 418c11725..d6359c0f5 100644 --- a/fastapi/dependencies/models.py +++ b/fastapi/dependencies/models.py @@ -1,8 +1,18 @@ +import inspect +import sys from dataclasses import dataclass, field -from typing import Any, Callable, List, Optional, Sequence, Tuple +from functools import cached_property +from typing import Any, Callable, List, Optional, Sequence, Union from fastapi._compat import ModelField from fastapi.security.base import SecurityBase +from fastapi.types import DependencyCacheKey +from typing_extensions import Literal + +if sys.version_info >= (3, 13): # pragma: no cover + from inspect import iscoroutinefunction +else: # pragma: no cover + from asyncio import iscoroutinefunction @dataclass @@ -31,7 +41,43 @@ class Dependant: security_scopes: Optional[List[str]] = None use_cache: bool = True path: Optional[str] = None - cache_key: Tuple[Optional[Callable[..., Any]], Tuple[str, ...]] = field(init=False) + scope: Union[Literal["function", "request"], None] = None + + @cached_property + def cache_key(self) -> DependencyCacheKey: + return ( + self.call, + tuple(sorted(set(self.security_scopes or []))), + self.computed_scope or "", + ) + + @cached_property + def is_gen_callable(self) -> bool: + if inspect.isgeneratorfunction(self.call): + return True + dunder_call = getattr(self.call, "__call__", None) # noqa: B004 + return inspect.isgeneratorfunction(dunder_call) + + @cached_property + def is_async_gen_callable(self) -> bool: + if inspect.isasyncgenfunction(self.call): + return True + dunder_call = getattr(self.call, "__call__", None) # noqa: B004 + return inspect.isasyncgenfunction(dunder_call) + + @cached_property + def is_coroutine_callable(self) -> bool: + if inspect.isroutine(self.call): + return iscoroutinefunction(self.call) + if inspect.isclass(self.call): + return False + dunder_call = getattr(self.call, "__call__", None) # noqa: B004 + return iscoroutinefunction(dunder_call) - def __post_init__(self) -> None: - self.cache_key = (self.call, tuple(sorted(set(self.security_scopes or [])))) + @cached_property + def computed_scope(self) -> Union[str, None]: + if self.scope: + return self.scope + if self.is_gen_callable or self.is_async_gen_callable: + return "request" + return None diff --git a/fastapi/dependencies/utils.py b/fastapi/dependencies/utils.py index 6477a2cba..c5c6b69bb 100644 --- a/fastapi/dependencies/utils.py +++ b/fastapi/dependencies/utils.py @@ -1,5 +1,4 @@ import inspect -import sys from contextlib import AsyncExitStack, contextmanager from copy import copy, deepcopy from dataclasses import dataclass @@ -55,10 +54,12 @@ from fastapi.concurrency import ( contextmanager_in_threadpool, ) from fastapi.dependencies.models import Dependant, SecurityRequirement +from fastapi.exceptions import DependencyScopeError from fastapi.logger import logger from fastapi.security.base import SecurityBase from fastapi.security.oauth2 import OAuth2, SecurityScopes from fastapi.security.open_id_connect_url import OpenIdConnect +from fastapi.types import DependencyCacheKey from fastapi.utils import create_model_field, get_path_param_names from pydantic import BaseModel from pydantic.fields import FieldInfo @@ -74,15 +75,10 @@ from starlette.datastructures import ( from starlette.requests import HTTPConnection, Request from starlette.responses import Response from starlette.websockets import WebSocket -from typing_extensions import Annotated, get_args, get_origin +from typing_extensions import Annotated, Literal, get_args, get_origin from .. import temp_pydantic_v1_params -if sys.version_info >= (3, 13): # pragma: no cover - from inspect import iscoroutinefunction -else: # pragma: no cover - from asyncio import iscoroutinefunction - multipart_not_installed_error = ( 'Form data requires "python-multipart" to be installed. \n' 'You can install "python-multipart" with: \n\n' @@ -137,14 +133,11 @@ def get_parameterless_sub_dependant(*, depends: params.Depends, path: str) -> De ) -CacheKey = Tuple[Optional[Callable[..., Any]], Tuple[str, ...]] - - def get_flat_dependant( dependant: Dependant, *, skip_repeats: bool = False, - visited: Optional[List[CacheKey]] = None, + visited: Optional[List[DependencyCacheKey]] = None, ) -> Dependant: if visited is None: visited = [] @@ -237,6 +230,7 @@ def get_dependant( name: Optional[str] = None, security_scopes: Optional[List[str]] = None, use_cache: bool = True, + scope: Union[Literal["function", "request"], None] = None, ) -> Dependant: dependant = Dependant( call=call, @@ -244,6 +238,7 @@ def get_dependant( path=path, security_scopes=security_scopes, use_cache=use_cache, + scope=scope, ) path_param_names = get_path_param_names(path) endpoint_signature = get_typed_signature(call) @@ -251,7 +246,7 @@ def get_dependant( if isinstance(call, SecurityBase): use_scopes: List[str] = [] if isinstance(call, (OAuth2, OpenIdConnect)): - use_scopes = security_scopes + use_scopes = security_scopes or use_scopes security_requirement = SecurityRequirement( security_scheme=call, scopes=use_scopes ) @@ -266,6 +261,16 @@ def get_dependant( ) if param_details.depends is not None: assert param_details.depends.dependency + if ( + (dependant.is_gen_callable or dependant.is_async_gen_callable) + and dependant.computed_scope == "request" + and param_details.depends.scope == "function" + ): + assert dependant.call + raise DependencyScopeError( + f'The dependency "{dependant.call.__name__}" has a scope of ' + '"request", it cannot depend on dependencies with scope "function".' + ) use_security_scopes = security_scopes or [] if isinstance(param_details.depends, params.Security): if param_details.depends.scopes: @@ -276,6 +281,7 @@ def get_dependant( name=param_name, security_scopes=use_security_scopes, use_cache=param_details.depends.use_cache, + scope=param_details.depends.scope, ) dependant.dependencies.append(sub_dependant) continue @@ -532,36 +538,14 @@ def add_param_to_fields(*, field: ModelField, dependant: Dependant) -> None: dependant.cookie_params.append(field) -def is_coroutine_callable(call: Callable[..., Any]) -> bool: - if inspect.isroutine(call): - return iscoroutinefunction(call) - if inspect.isclass(call): - return False - dunder_call = getattr(call, "__call__", None) # noqa: B004 - return iscoroutinefunction(dunder_call) - - -def is_async_gen_callable(call: Callable[..., Any]) -> bool: - if inspect.isasyncgenfunction(call): - return True - dunder_call = getattr(call, "__call__", None) # noqa: B004 - return inspect.isasyncgenfunction(dunder_call) - - -def is_gen_callable(call: Callable[..., Any]) -> bool: - if inspect.isgeneratorfunction(call): - return True - dunder_call = getattr(call, "__call__", None) # noqa: B004 - return inspect.isgeneratorfunction(dunder_call) - - -async def solve_generator( - *, call: Callable[..., Any], stack: AsyncExitStack, sub_values: Dict[str, Any] +async def _solve_generator( + *, dependant: Dependant, stack: AsyncExitStack, sub_values: Dict[str, Any] ) -> Any: - if is_gen_callable(call): - cm = contextmanager_in_threadpool(contextmanager(call)(**sub_values)) - elif is_async_gen_callable(call): - cm = asynccontextmanager(call)(**sub_values) + assert dependant.call + if dependant.is_gen_callable: + cm = contextmanager_in_threadpool(contextmanager(dependant.call)(**sub_values)) + elif dependant.is_async_gen_callable: + cm = asynccontextmanager(dependant.call)(**sub_values) return await stack.enter_async_context(cm) @@ -571,7 +555,7 @@ class SolvedDependency: errors: List[Any] background_tasks: Optional[StarletteBackgroundTasks] response: Response - dependency_cache: Dict[Tuple[Callable[..., Any], Tuple[str]], Any] + dependency_cache: Dict[DependencyCacheKey, Any] async def solve_dependencies( @@ -582,10 +566,20 @@ async def solve_dependencies( background_tasks: Optional[StarletteBackgroundTasks] = None, response: Optional[Response] = None, dependency_overrides_provider: Optional[Any] = None, - dependency_cache: Optional[Dict[Tuple[Callable[..., Any], Tuple[str]], Any]] = None, + dependency_cache: Optional[Dict[DependencyCacheKey, Any]] = None, + # TODO: remove this parameter later, no longer used, not removing it yet as some + # people might be monkey patching this function (although that's not supported) async_exit_stack: AsyncExitStack, embed_body_fields: bool, ) -> SolvedDependency: + request_astack = request.scope.get("fastapi_inner_astack") + assert isinstance(request_astack, AsyncExitStack), ( + "fastapi_inner_astack not found in request scope" + ) + function_astack = request.scope.get("fastapi_function_astack") + assert isinstance(function_astack, AsyncExitStack), ( + "fastapi_function_astack not found in request scope" + ) values: Dict[str, Any] = {} errors: List[Any] = [] if response is None: @@ -594,12 +588,8 @@ async def solve_dependencies( response.status_code = None # type: ignore if dependency_cache is None: dependency_cache = {} - sub_dependant: Dependant for sub_dependant in dependant.dependencies: sub_dependant.call = cast(Callable[..., Any], sub_dependant.call) - sub_dependant.cache_key = cast( - Tuple[Callable[..., Any], Tuple[str]], sub_dependant.cache_key - ) call = sub_dependant.call use_sub_dependant = sub_dependant if ( @@ -616,6 +606,7 @@ async def solve_dependencies( call=call, name=sub_dependant.name, security_scopes=sub_dependant.security_scopes, + scope=sub_dependant.scope, ) solved_result = await solve_dependencies( @@ -635,11 +626,18 @@ async def solve_dependencies( continue if sub_dependant.use_cache and sub_dependant.cache_key in dependency_cache: solved = dependency_cache[sub_dependant.cache_key] - elif is_gen_callable(call) or is_async_gen_callable(call): - solved = await solve_generator( - call=call, stack=async_exit_stack, sub_values=solved_result.values + elif ( + use_sub_dependant.is_gen_callable or use_sub_dependant.is_async_gen_callable + ): + use_astack = request_astack + if sub_dependant.scope == "function": + use_astack = function_astack + solved = await _solve_generator( + dependant=use_sub_dependant, + stack=use_astack, + sub_values=solved_result.values, ) - elif is_coroutine_callable(call): + elif use_sub_dependant.is_coroutine_callable: solved = await call(**solved_result.values) else: solved = await run_in_threadpool(call, **solved_result.values) diff --git a/fastapi/exceptions.py b/fastapi/exceptions.py index bb775fcbf..0620428be 100644 --- a/fastapi/exceptions.py +++ b/fastapi/exceptions.py @@ -147,6 +147,13 @@ class FastAPIError(RuntimeError): """ +class DependencyScopeError(FastAPIError): + """ + A dependency declared that it depends on another dependency with an invalid + (narrower) scope. + """ + + class ValidationException(Exception): def __init__(self, errors: Sequence[Any]) -> None: self._errors = errors diff --git a/fastapi/param_functions.py b/fastapi/param_functions.py index f88937e24..e32f75593 100644 --- a/fastapi/param_functions.py +++ b/fastapi/param_functions.py @@ -4,7 +4,7 @@ from annotated_doc import Doc from fastapi import params from fastapi._compat import Undefined from fastapi.openapi.models import Example -from typing_extensions import Annotated, deprecated +from typing_extensions import Annotated, Literal, deprecated _Unset: Any = Undefined @@ -2245,6 +2245,26 @@ def Depends( # noqa: N802 """ ), ] = True, + scope: Annotated[ + Union[Literal["function", "request"], None], + Doc( + """ + Mainly for dependencies with `yield`, define when the dependency function + should start (the code before `yield`) and when it should end (the code + after `yield`). + + * `"function"`: start the dependency before the *path operation function* + that handles the request, end the dependency after the *path operation + function* ends, but **before** the response is sent back to the client. + So, the dependency function will be executed **around** the *path operation + **function***. + * `"request"`: start the dependency before the *path operation function* + 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. + """ + ), + ] = None, ) -> Any: """ Declare a FastAPI dependency. @@ -2275,7 +2295,7 @@ def Depends( # noqa: N802 return commons ``` """ - return params.Depends(dependency=dependency, use_cache=use_cache) + return params.Depends(dependency=dependency, use_cache=use_cache, scope=scope) def Security( # noqa: N802 diff --git a/fastapi/params.py b/fastapi/params.py index 2dc04be14..6a58d5808 100644 --- a/fastapi/params.py +++ b/fastapi/params.py @@ -5,7 +5,7 @@ from typing import Any, Callable, Dict, List, Optional, Sequence, Union from fastapi.openapi.models import Example from pydantic.fields import FieldInfo -from typing_extensions import Annotated, deprecated +from typing_extensions import Annotated, Literal, deprecated from ._compat import ( PYDANTIC_V2, @@ -766,6 +766,7 @@ class File(Form): # type: ignore[misc] class Depends: dependency: Optional[Callable[..., Any]] = None use_cache: bool = True + scope: Union[Literal["function", "request"], None] = None @dataclass diff --git a/fastapi/routing.py b/fastapi/routing.py index 0b59d250a..a8e12eb60 100644 --- a/fastapi/routing.py +++ b/fastapi/routing.py @@ -104,10 +104,11 @@ def request_response( async def app(scope: Scope, receive: Receive, send: Send) -> None: # Starts customization response_awaited = False - async with AsyncExitStack() as stack: - scope["fastapi_inner_astack"] = stack - # Same as in Starlette - response = await f(request) + async with AsyncExitStack() as request_stack: + scope["fastapi_inner_astack"] = request_stack + async with AsyncExitStack() as function_stack: + scope["fastapi_function_astack"] = function_stack + response = await f(request) await response(scope, receive, send) # Continues customization response_awaited = True @@ -140,11 +141,11 @@ def websocket_session( session = WebSocket(scope, receive=receive, send=send) async def app(scope: Scope, receive: Receive, send: Send) -> None: - # Starts customization - async with AsyncExitStack() as stack: - scope["fastapi_inner_astack"] = stack - # Same as in Starlette - await func(session) + async with AsyncExitStack() as request_stack: + scope["fastapi_inner_astack"] = request_stack + async with AsyncExitStack() as function_stack: + scope["fastapi_function_astack"] = function_stack + await func(session) # Same as in Starlette await wrap_app_handling_exceptions(app, session)(scope, receive, send) @@ -479,7 +480,9 @@ class APIWebSocketRoute(routing.WebSocketRoute): self.name = get_name(endpoint) if name is None else name self.dependencies = list(dependencies or []) self.path_regex, self.path_format, self.param_convertors = compile_path(path) - self.dependant = get_dependant(path=self.path_format, call=self.endpoint) + self.dependant = get_dependant( + path=self.path_format, call=self.endpoint, scope="function" + ) for depends in self.dependencies[::-1]: self.dependant.dependencies.insert( 0, @@ -630,7 +633,9 @@ class APIRoute(routing.Route): self.response_fields = {} assert callable(endpoint), "An endpoint must be a callable" - self.dependant = get_dependant(path=self.path_format, call=self.endpoint) + self.dependant = get_dependant( + path=self.path_format, call=self.endpoint, scope="function" + ) for depends in self.dependencies[::-1]: self.dependant.dependencies.insert( 0, diff --git a/fastapi/types.py b/fastapi/types.py index 3205654c7..3f4e81a7c 100644 --- a/fastapi/types.py +++ b/fastapi/types.py @@ -1,6 +1,6 @@ import types from enum import Enum -from typing import Any, Callable, Dict, Set, Type, TypeVar, Union +from typing import Any, Callable, Dict, Optional, Set, Tuple, Type, TypeVar, Union from pydantic import BaseModel @@ -8,3 +8,4 @@ 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] diff --git a/tests/test_dependency_yield_scope.py b/tests/test_dependency_yield_scope.py new file mode 100644 index 000000000..a5227dd7a --- /dev/null +++ b/tests/test_dependency_yield_scope.py @@ -0,0 +1,184 @@ +import json +from typing import Any, Tuple + +import pytest +from fastapi import Depends, FastAPI +from fastapi.exceptions import FastAPIError +from fastapi.responses import StreamingResponse +from fastapi.testclient import TestClient +from typing_extensions import Annotated + + +class Session: + def __init__(self) -> None: + self.open = True + + +def dep_session() -> Any: + s = Session() + yield s + s.open = False + + +SessionFuncDep = Annotated[Session, Depends(dep_session, scope="function")] +SessionRequestDep = Annotated[Session, Depends(dep_session, scope="request")] +SessionDefaultDep = Annotated[Session, Depends(dep_session)] + + +class NamedSession: + def __init__(self, name: str = "default") -> None: + self.name = name + self.open = True + + +def get_named_session(session: SessionRequestDep, session_b: SessionDefaultDep) -> Any: + assert session is session_b + named_session = NamedSession(name="named") + yield named_session, session_b + named_session.open = False + + +NamedSessionsDep = Annotated[Tuple[NamedSession, Session], Depends(get_named_session)] + + +def get_named_func_session(session: SessionFuncDep) -> Any: + named_session = NamedSession(name="named") + yield named_session, session + named_session.open = False + + +def get_named_regular_func_session(session: SessionFuncDep) -> Any: + named_session = NamedSession(name="named") + return named_session, session + + +BrokenSessionsDep = Annotated[ + Tuple[NamedSession, Session], Depends(get_named_func_session) +] +NamedSessionsFuncDep = Annotated[ + Tuple[NamedSession, Session], Depends(get_named_func_session, scope="function") +] + +RegularSessionsDep = Annotated[ + Tuple[NamedSession, Session], Depends(get_named_regular_func_session) +] + +app = FastAPI() + + +@app.get("/function-scope") +def function_scope(session: SessionFuncDep) -> Any: + def iter_data(): + yield json.dumps({"is_open": session.open}) + + return StreamingResponse(iter_data()) + + +@app.get("/request-scope") +def request_scope(session: SessionRequestDep) -> Any: + def iter_data(): + yield json.dumps({"is_open": session.open}) + + return StreamingResponse(iter_data()) + + +@app.get("/two-scopes") +def get_stream_session( + function_session: SessionFuncDep, request_session: SessionRequestDep +) -> Any: + def iter_data(): + yield json.dumps( + {"func_is_open": function_session.open, "req_is_open": request_session.open} + ) + + return StreamingResponse(iter_data()) + + +@app.get("/sub") +def get_sub(sessions: NamedSessionsDep) -> Any: + def iter_data(): + yield json.dumps( + {"named_session_open": sessions[0].open, "session_open": sessions[1].open} + ) + + return StreamingResponse(iter_data()) + + +@app.get("/named-function-scope") +def get_named_function_scope(sessions: NamedSessionsFuncDep) -> Any: + def iter_data(): + yield json.dumps( + {"named_session_open": sessions[0].open, "session_open": sessions[1].open} + ) + + return StreamingResponse(iter_data()) + + +@app.get("/regular-function-scope") +def get_regular_function_scope(sessions: RegularSessionsDep) -> Any: + def iter_data(): + yield json.dumps( + {"named_session_open": sessions[0].open, "session_open": sessions[1].open} + ) + + return StreamingResponse(iter_data()) + + +client = TestClient(app) + + +def test_function_scope() -> None: + response = client.get("/function-scope") + assert response.status_code == 200 + data = response.json() + assert data["is_open"] is False + + +def test_request_scope() -> None: + response = client.get("/request-scope") + assert response.status_code == 200 + data = response.json() + assert data["is_open"] is True + + +def test_two_scopes() -> None: + response = client.get("/two-scopes") + assert response.status_code == 200 + data = response.json() + assert data["func_is_open"] is False + assert data["req_is_open"] is True + + +def test_sub() -> None: + response = client.get("/sub") + assert response.status_code == 200 + data = response.json() + assert data["named_session_open"] is True + assert data["session_open"] is True + + +def test_broken_scope() -> None: + with pytest.raises( + FastAPIError, + match='The dependency "get_named_func_session" has a scope of "request", it cannot depend on dependencies with scope "function"', + ): + + @app.get("/broken-scope") + def get_broken(sessions: BrokenSessionsDep) -> Any: # pragma: no cover + pass + + +def test_named_function_scope() -> None: + response = client.get("/named-function-scope") + assert response.status_code == 200 + data = response.json() + assert data["named_session_open"] is False + assert data["session_open"] is False + + +def test_regular_function_scope() -> None: + response = client.get("/regular-function-scope") + assert response.status_code == 200 + data = response.json() + assert data["named_session_open"] is True + assert data["session_open"] is False diff --git a/tests/test_dependency_yield_scope_websockets.py b/tests/test_dependency_yield_scope_websockets.py new file mode 100644 index 000000000..52a30ae7a --- /dev/null +++ b/tests/test_dependency_yield_scope_websockets.py @@ -0,0 +1,201 @@ +from contextvars import ContextVar +from typing import Any, Dict, Tuple + +import pytest +from fastapi import Depends, FastAPI, WebSocket +from fastapi.exceptions import FastAPIError +from fastapi.testclient import TestClient +from typing_extensions import Annotated + +global_context: ContextVar[Dict[str, Any]] = ContextVar("global_context", default={}) # noqa: B039 + + +class Session: + def __init__(self) -> None: + self.open = True + + +async def dep_session() -> Any: + s = Session() + yield s + s.open = False + global_state = global_context.get() + global_state["session_closed"] = True + + +SessionFuncDep = Annotated[Session, Depends(dep_session, scope="function")] +SessionRequestDep = Annotated[Session, Depends(dep_session, scope="request")] +SessionDefaultDep = Annotated[Session, Depends(dep_session)] + + +class NamedSession: + def __init__(self, name: str = "default") -> None: + self.name = name + self.open = True + + +def get_named_session(session: SessionRequestDep, session_b: SessionDefaultDep) -> Any: + assert session is session_b + named_session = NamedSession(name="named") + yield named_session, session_b + named_session.open = False + global_state = global_context.get() + global_state["named_session_closed"] = True + + +NamedSessionsDep = Annotated[Tuple[NamedSession, Session], Depends(get_named_session)] + + +def get_named_func_session(session: SessionFuncDep) -> Any: + named_session = NamedSession(name="named") + yield named_session, session + named_session.open = False + global_state = global_context.get() + global_state["named_func_session_closed"] = True + + +def get_named_regular_func_session(session: SessionFuncDep) -> Any: + named_session = NamedSession(name="named") + return named_session, session + + +BrokenSessionsDep = Annotated[ + Tuple[NamedSession, Session], Depends(get_named_func_session) +] +NamedSessionsFuncDep = Annotated[ + Tuple[NamedSession, Session], Depends(get_named_func_session, scope="function") +] + +RegularSessionsDep = Annotated[ + Tuple[NamedSession, Session], Depends(get_named_regular_func_session) +] + +app = FastAPI() + + +@app.websocket("/function-scope") +async def function_scope(websocket: WebSocket, session: SessionFuncDep) -> Any: + await websocket.accept() + await websocket.send_json({"is_open": session.open}) + + +@app.websocket("/request-scope") +async def request_scope(websocket: WebSocket, session: SessionRequestDep) -> Any: + await websocket.accept() + await websocket.send_json({"is_open": session.open}) + + +@app.websocket("/two-scopes") +async def get_stream_session( + websocket: WebSocket, + function_session: SessionFuncDep, + request_session: SessionRequestDep, +) -> Any: + await websocket.accept() + await websocket.send_json( + {"func_is_open": function_session.open, "req_is_open": request_session.open} + ) + + +@app.websocket("/sub") +async def get_sub(websocket: WebSocket, sessions: NamedSessionsDep) -> Any: + await websocket.accept() + await websocket.send_json( + {"named_session_open": sessions[0].open, "session_open": sessions[1].open} + ) + + +@app.websocket("/named-function-scope") +async def get_named_function_scope( + websocket: WebSocket, sessions: NamedSessionsFuncDep +) -> Any: + await websocket.accept() + await websocket.send_json( + {"named_session_open": sessions[0].open, "session_open": sessions[1].open} + ) + + +@app.websocket("/regular-function-scope") +async def get_regular_function_scope( + websocket: WebSocket, sessions: RegularSessionsDep +) -> Any: + await websocket.accept() + await websocket.send_json( + {"named_session_open": sessions[0].open, "session_open": sessions[1].open} + ) + + +client = TestClient(app) + + +def test_function_scope() -> None: + global_context.set({}) + global_state = global_context.get() + with client.websocket_connect("/function-scope") as websocket: + data = websocket.receive_json() + assert data["is_open"] is True + assert global_state["session_closed"] is True + + +def test_request_scope() -> None: + global_context.set({}) + global_state = global_context.get() + with client.websocket_connect("/request-scope") as websocket: + data = websocket.receive_json() + assert data["is_open"] is True + assert global_state["session_closed"] is True + + +def test_two_scopes() -> None: + global_context.set({}) + global_state = global_context.get() + with client.websocket_connect("/two-scopes") as websocket: + data = websocket.receive_json() + assert data["func_is_open"] is True + assert data["req_is_open"] is True + assert global_state["session_closed"] is True + + +def test_sub() -> None: + global_context.set({}) + global_state = global_context.get() + with client.websocket_connect("/sub") as websocket: + data = websocket.receive_json() + assert data["named_session_open"] is True + assert data["session_open"] is True + assert global_state["session_closed"] is True + assert global_state["named_session_closed"] is True + + +def test_broken_scope() -> None: + with pytest.raises( + FastAPIError, + match='The dependency "get_named_func_session" has a scope of "request", it cannot depend on dependencies with scope "function"', + ): + + @app.websocket("/broken-scope") + async def get_broken( + websocket: WebSocket, sessions: BrokenSessionsDep + ) -> Any: # pragma: no cover + pass + + +def test_named_function_scope() -> None: + global_context.set({}) + global_state = global_context.get() + with client.websocket_connect("/named-function-scope") as websocket: + data = websocket.receive_json() + assert data["named_session_open"] is True + assert data["session_open"] is True + assert global_state["session_closed"] is True + assert global_state["named_func_session_closed"] is True + + +def test_regular_function_scope() -> None: + global_context.set({}) + global_state = global_context.get() + with client.websocket_connect("/regular-function-scope") as websocket: + data = websocket.receive_json() + assert data["named_session_open"] is True + assert data["session_open"] is True + assert global_state["session_closed"] is True diff --git a/tests/test_tutorial/test_dependencies/test_tutorial008e.py b/tests/test_tutorial/test_dependencies/test_tutorial008e.py new file mode 100644 index 000000000..1ae9ab2cd --- /dev/null +++ b/tests/test_tutorial/test_dependencies/test_tutorial008e.py @@ -0,0 +1,27 @@ +import importlib + +import pytest +from fastapi.testclient import TestClient + +from ...utils import needs_py39 + + +@pytest.fixture( + name="client", + params=[ + "tutorial008e", + "tutorial008e_an", + pytest.param("tutorial008e_an_py39", marks=needs_py39), + ], +) +def get_client(request: pytest.FixtureRequest): + mod = importlib.import_module(f"docs_src.dependencies.{request.param}") + + client = TestClient(mod.app) + return client + + +def test_get_users_me(client: TestClient): + response = client.get("/users/me") + assert response.status_code == 200, response.text + assert response.json() == "Rick" From ad4d8f24ca19bdf224f216a8dca7948935ac8e05 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Mon, 3 Nov 2025 10:13:13 +0000 Subject: [PATCH 08/16] =?UTF-8?q?=F0=9F=93=9D=20Update=20release=20notes?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit [skip ci] --- docs/en/docs/release-notes.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/docs/en/docs/release-notes.md b/docs/en/docs/release-notes.md index 5e6fea9d5..caa7e2187 100644 --- a/docs/en/docs/release-notes.md +++ b/docs/en/docs/release-notes.md @@ -7,6 +7,10 @@ hide: ## Latest Changes +### Features + +* ✨ Add support for dependencies with scopes, support `scope="request"` for dependencies with `yield` that exit before the response is sent. PR [#14262](https://github.com/fastapi/fastapi/pull/14262) by [@tiangolo](https://github.com/tiangolo). + ### Internal * 👥 Update FastAPI People - Contributors and Translators. PR [#14273](https://github.com/fastapi/fastapi/pull/14273) by [@tiangolo](https://github.com/tiangolo). From 36901405559018bd97c1c70eb86748b8b9d67533 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebasti=C3=A1n=20Ram=C3=ADrez?= Date: Mon, 3 Nov 2025 11:19:56 +0100 Subject: [PATCH 09/16] =?UTF-8?q?=F0=9F=93=9D=20Update=20release=20notes?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docs/en/docs/release-notes.md | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/en/docs/release-notes.md b/docs/en/docs/release-notes.md index caa7e2187..93e6d3e12 100644 --- a/docs/en/docs/release-notes.md +++ b/docs/en/docs/release-notes.md @@ -10,6 +10,7 @@ hide: ### Features * ✨ Add support for dependencies with scopes, support `scope="request"` for dependencies with `yield` that exit before the response is sent. PR [#14262](https://github.com/fastapi/fastapi/pull/14262) by [@tiangolo](https://github.com/tiangolo). + * New docs: [Dependencies with `yield` - Early exit and `scope`](https://fastapi.tiangolo.com/tutorial/dependencies/dependencies-with-yield/#early-exit-and-scope). ### Internal From 4efae81a76b809998c12fc0f7e1c172f451cb304 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebasti=C3=A1n=20Ram=C3=ADrez?= Date: Mon, 3 Nov 2025 11:21:36 +0100 Subject: [PATCH 10/16] =?UTF-8?q?=F0=9F=94=96=20Release=20version=200.121.?= =?UTF-8?q?0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docs/en/docs/release-notes.md | 2 ++ fastapi/__init__.py | 2 +- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/docs/en/docs/release-notes.md b/docs/en/docs/release-notes.md index 93e6d3e12..a08aa14fc 100644 --- a/docs/en/docs/release-notes.md +++ b/docs/en/docs/release-notes.md @@ -7,6 +7,8 @@ hide: ## Latest Changes +## 0.121.0 + ### Features * ✨ Add support for dependencies with scopes, support `scope="request"` for dependencies with `yield` that exit before the response is sent. PR [#14262](https://github.com/fastapi/fastapi/pull/14262) by [@tiangolo](https://github.com/tiangolo). diff --git a/fastapi/__init__.py b/fastapi/__init__.py index 93555bfdc..f4a952bf5 100644 --- a/fastapi/__init__.py +++ b/fastapi/__init__.py @@ -1,6 +1,6 @@ """FastAPI framework, high performance, easy to learn, fast to code, ready for production""" -__version__ = "0.120.4" +__version__ = "0.121.0" from starlette import status as status From 289b4aa2faff3bbfa364abbb21fe2b23aebe6270 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebasti=C3=A1n=20Ram=C3=ADrez?= Date: Mon, 3 Nov 2025 14:19:58 +0100 Subject: [PATCH 11/16] =?UTF-8?q?=F0=9F=93=9D=20Upate=20docs=20for=20advan?= =?UTF-8?q?ced=20dependencies=20with=20`yield`,=20noting=20the=20changes?= =?UTF-8?q?=20in=200.121.0,=20adding=20`scope`=20(#14287)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docs/en/docs/advanced/advanced-dependencies.md | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/docs/en/docs/advanced/advanced-dependencies.md b/docs/en/docs/advanced/advanced-dependencies.md index e0404b389..5d6a40f46 100644 --- a/docs/en/docs/advanced/advanced-dependencies.md +++ b/docs/en/docs/advanced/advanced-dependencies.md @@ -70,12 +70,22 @@ If you understood all this, you already know how those utility tools for securit You most probably don't need these technical details. -These details are useful mainly if you had a FastAPI application older than 0.118.0 and you are facing issues with dependencies with `yield`. +These details are useful mainly if you had a FastAPI application older than 0.121.0 and you are facing issues with dependencies with `yield`. /// Dependencies with `yield` have evolved over time to account for the different use cases and to fix some issues, here's a summary of what has changed. +### Dependencies with `yield` and `scope` { #dependencies-with-yield-and-scope } + +In version 0.121.0, FastAPI added support for `Depends(scope="function")` for dependencies with `yield`. + +Using `Depends(scope="function")`, the exit code after `yield` is executed right after the *path operation function* is finished, before the response is sent back to the client. + +And when using `Depends(scope="request")` (the default), the exit code after `yield` is executed after the response is sent. + +You can read more about it in the docs for [Dependencies with `yield` - Early exit and `scope`](../tutorial/dependencies/dependencies-with-yield.md#early-exit-and-scope). + ### Dependencies with `yield` and `StreamingResponse`, Technical Details { #dependencies-with-yield-and-streamingresponse-technical-details } Before FastAPI 0.118.0, if you used a dependency with `yield`, it would run the exit code after the *path operation function* returned but right before sending the response. From b787103226775a4ec328e48241682a34e6b2d217 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Mon, 3 Nov 2025 13:20:34 +0000 Subject: [PATCH 12/16] =?UTF-8?q?=F0=9F=93=9D=20Update=20release=20notes?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit [skip ci] --- docs/en/docs/release-notes.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/docs/en/docs/release-notes.md b/docs/en/docs/release-notes.md index a08aa14fc..24b9f4ca3 100644 --- a/docs/en/docs/release-notes.md +++ b/docs/en/docs/release-notes.md @@ -7,6 +7,10 @@ hide: ## Latest Changes +### Docs + +* 📝 Upate docs for advanced dependencies with `yield`, noting the changes in 0.121.0, adding `scope`. PR [#14287](https://github.com/fastapi/fastapi/pull/14287) by [@tiangolo](https://github.com/tiangolo). + ## 0.121.0 ### Features From 34db1e2e2c153151e8fb66484cbf9f879c12bf4f Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Tue, 4 Nov 2025 09:38:05 +0100 Subject: [PATCH 13/16] =?UTF-8?q?=E2=AC=86=20[pre-commit.ci]=20pre-commit?= =?UTF-8?q?=20autoupdate=20(#14289)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit updates: - [github.com/astral-sh/ruff-pre-commit: v0.14.2 → v0.14.3](https://github.com/astral-sh/ruff-pre-commit/compare/v0.14.2...v0.14.3) Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> --- .pre-commit-config.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 25dcd7b88..8e5eba4c4 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -14,7 +14,7 @@ repos: - id: end-of-file-fixer - id: trailing-whitespace - repo: https://github.com/astral-sh/ruff-pre-commit - rev: v0.14.2 + rev: v0.14.3 hooks: - id: ruff args: From 67c8dfaf0f6baeaa351ce5f8d1bfdafd789e9059 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 4 Nov 2025 09:38:16 +0100 Subject: [PATCH 14/16] =?UTF-8?q?=E2=AC=86=20Bump=20ruff=20from=200.13.2?= =?UTF-8?q?=20to=200.14.3=20(#14276)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Bumps [ruff](https://github.com/astral-sh/ruff) from 0.13.2 to 0.14.3. - [Release notes](https://github.com/astral-sh/ruff/releases) - [Changelog](https://github.com/astral-sh/ruff/blob/main/CHANGELOG.md) - [Commits](https://github.com/astral-sh/ruff/compare/0.13.2...0.14.3) --- updated-dependencies: - dependency-name: ruff dependency-version: 0.14.3 dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- requirements-docs-tests.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/requirements-docs-tests.txt b/requirements-docs-tests.txt index a909d0eef..9350f3ee4 100644 --- a/requirements-docs-tests.txt +++ b/requirements-docs-tests.txt @@ -1,4 +1,4 @@ # For mkdocstrings and tests httpx >=0.23.0,<1.0.0 # For linting and generating docs versions -ruff ==0.13.2 +ruff ==0.14.3 From 4170f621a5b7a14cf95c160d5b8a77fe41d59a62 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Tue, 4 Nov 2025 08:38:34 +0000 Subject: [PATCH 15/16] =?UTF-8?q?=F0=9F=93=9D=20Update=20release=20notes?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit [skip ci] --- docs/en/docs/release-notes.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/docs/en/docs/release-notes.md b/docs/en/docs/release-notes.md index 24b9f4ca3..9394a18dd 100644 --- a/docs/en/docs/release-notes.md +++ b/docs/en/docs/release-notes.md @@ -11,6 +11,10 @@ hide: * 📝 Upate docs for advanced dependencies with `yield`, noting the changes in 0.121.0, adding `scope`. PR [#14287](https://github.com/fastapi/fastapi/pull/14287) by [@tiangolo](https://github.com/tiangolo). +### Internal + +* ⬆ [pre-commit.ci] pre-commit autoupdate. PR [#14289](https://github.com/fastapi/fastapi/pull/14289) by [@pre-commit-ci[bot]](https://github.com/apps/pre-commit-ci). + ## 0.121.0 ### Features From 972a967d5d3fa24d450637c36c6b7ad1f1d8c1b6 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Tue, 4 Nov 2025 08:39:30 +0000 Subject: [PATCH 16/16] =?UTF-8?q?=F0=9F=93=9D=20Update=20release=20notes?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit [skip ci] --- docs/en/docs/release-notes.md | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/en/docs/release-notes.md b/docs/en/docs/release-notes.md index 9394a18dd..9380fb7d4 100644 --- a/docs/en/docs/release-notes.md +++ b/docs/en/docs/release-notes.md @@ -13,6 +13,7 @@ hide: ### Internal +* ⬆ Bump ruff from 0.13.2 to 0.14.3. PR [#14276](https://github.com/fastapi/fastapi/pull/14276) by [@dependabot[bot]](https://github.com/apps/dependabot). * ⬆ [pre-commit.ci] pre-commit autoupdate. PR [#14289](https://github.com/fastapi/fastapi/pull/14289) by [@pre-commit-ci[bot]](https://github.com/apps/pre-commit-ci). ## 0.121.0