From da508e9dce85874d654eb10472b090f573de97fe Mon Sep 17 00:00:00 2001 From: Mohammad <116789737+Mohammad222PR@users.noreply.github.com> Date: Fri, 25 Jul 2025 12:57:03 +0330 Subject: [PATCH 01/60] =?UTF-8?q?=F0=9F=8C=90=20Add=20Persian=20translatio?= =?UTF-8?q?n=20for=20`docs/fa/docs/environment-variables.md`=20(#13923)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 🌐 Add Persian translation for docs/fa/docs/environment-variables.md --- docs/fa/docs/environment-variables.md | 298 ++++++++++++++++++++++++++ 1 file changed, 298 insertions(+) create mode 100644 docs/fa/docs/environment-variables.md diff --git a/docs/fa/docs/environment-variables.md b/docs/fa/docs/environment-variables.md new file mode 100644 index 000000000..75309ce1f --- /dev/null +++ b/docs/fa/docs/environment-variables.md @@ -0,0 +1,298 @@ +# متغیرهای محیطی + +/// tip + +اگه از قبل می‌دونی متغیرهای محیطی چی هستن و چطور ازشون استفاده می‌شه، می‌تونی این بخش رو رد کنی. + +/// + +یه متغیر محیطی (که بهش "**env var**" هم می‌گن) یه متغیریه که **خارج** از کد پایتون، توی **سیستم‌عامل** زندگی می‌کنه و می‌تونه توسط کد پایتونت (یا برنامه‌های دیگه) خونده بشه. + +متغیرهای محیطی می‌تونن برای مدیریت **تنظیمات** برنامه، به‌عنوان بخشی از **نصب** پایتون و غیره مفید باشن. + +## ساخت و استفاده از متغیرهای محیطی + +می‌تونی متغیرهای محیطی رو توی **شل (ترمینال)** **بسازی** و ازشون استفاده کنی، بدون اینکه به پایتون نیاز داشته باشی: + +//// tab | لینوکس، مک‌اواس، ویندوز بش + +
+ +```console +// می‌تونی یه متغیر محیطی به اسم MY_NAME بسازی با +$ export MY_NAME="Wade Wilson" + +// بعد می‌تونی با برنامه‌های دیگه ازش استفاده کنی، مثل +$ echo "Hello $MY_NAME" + +Hello Wade Wilson +``` + +
+ +//// + +//// tab | ویندوز پاورشل + +
+ +```console +// یه متغیر محیطی به اسم MY_NAME بساز +$ $Env:MY_NAME = "Wade Wilson" + +// با برنامه‌های دیگه ازش استفاده کن، مثل +$ echo "Hello $Env:MY_NAME" + +Hello Wade Wilson +``` + +
+ +//// + +## خوندن متغیرهای محیطی توی پایتون + +می‌تونی متغیرهای محیطی رو **خارج** از پایتون، توی ترمینال (یا با هر روش دیگه) بسازی، و بعد توی **پایتون** اونا رو بخونی. + +مثلاً می‌تونی یه فایل `main.py` داشته باشی با: + +```Python hl_lines="3" +import os + +name = os.getenv("MY_NAME", "World") +print(f"Hello {name} from Python") +``` + +/// tip + +آرگومان دوم `os.getenv()` مقدار پیش‌فرضیه که برمی‌گردونه. + +اگه ندی، به‌صورت پیش‌فرض `None` هست، اینجا ما `"World"` رو به‌عنوان مقدار پیش‌فرض گذاشتیم. + +/// + +بعد می‌تونی اون برنامه پایتون رو صدا کنی: + +//// tab | لینوکس، مک‌اواس، ویندوز بش + +
+ +```console +// اینجا هنوز متغیر محیطی رو تنظیم نکردیم +$ python main.py + +// چون متغیر محیطی رو تنظیم نکردیم، مقدار پیش‌فرض رو می‌گیریم + +Hello World from Python + +// ولی اگه اول یه متغیر محیطی بسازیم +$ export MY_NAME="Wade Wilson" + +// و بعد دوباره برنامه رو صدا کنیم +$ python main.py + +// حالا می‌تونه متغیر محیطی رو بخونه + +Hello Wade Wilson from Python +``` + +
+ +//// + +//// tab | ویندوز پاورشل + +
+ +```console +// اینجا هنوز متغیر محیطی رو تنظیم نکردیم +$ python main.py + +// چون متغیر محیطی رو تنظیم نکردیم، مقدار پیش‌فرض رو می‌گیریم + +Hello World from Python + +// ولی اگه اول یه متغیر محیطی بسازیم +$ $Env:MY_NAME = "Wade Wilson" + +// و بعد دوباره برنامه رو صدا کنیم +$ python main.py + +// حالا می‌تونه متغیر محیطی رو بخونه + +Hello Wade Wilson from Python +``` + +
+ +//// + +چون متغیرهای محیطی می‌تونن خارج از کد تنظیم بشن، ولی کد می‌تونه اونا رو بخونه، و لازم نیست با بقیه فایل‌ها ذخیره (کمیتی به `git`) بشن، معمولاً برای پیکربندی یا **تنظیمات** استفاده می‌شن. + +همچنین می‌تونی یه متغیر محیطی رو فقط برای **یه اجرای خاص برنامه** بسازی، که فقط برای اون برنامه و فقط برای مدت زمان اجراش در دسترسه. + +برای این کار، درست قبل از خود برنامه، توی همون خط بسازش: + +
+ +```console +// یه متغیر محیطی MY_NAME رو توی خط برای این اجرای برنامه بساز +$ MY_NAME="Wade Wilson" python main.py + +// حالا می‌تونه متغیر محیطی رو بخونه + +Hello Wade Wilson from Python + +// متغیر محیطی بعدش دیگه وجود نداره +$ python main.py + +Hello World from Python +``` + +
+ +/// tip + +می‌تونی بیشتر در موردش توی برنامه دوازده‌فاکتوری: پیکربندی بخونی. + +/// + +## نوع‌ها و اعتبارسنجی + +این متغیرهای محیطی فقط می‌تونن **رشته‌های متنی** رو نگه دارن، چون خارج از پایتون هستن و باید با برنامه‌های دیگه و بقیه سیستم (و حتی سیستم‌عامل‌های مختلف مثل لینوکس، ویندوز، مک‌اواس) سازگار باشن. + +یعنی **هر مقداری** که توی پایتون از یه متغیر محیطی خونده می‌شه یه `str` هست، و هر تبدیل به نوع دیگه یا هر اعتبارسنجی باید توی کد انجام بشه. + +توی [راهنمای کاربر پیشرفته - تنظیمات و متغیرهای محیطی](./advanced/settings.md){.internal-link target=_blank} بیشتر در مورد استفاده از متغیرهای محیطی برای مدیریت **تنظیمات برنامه** یاد می‌گیری. + +## متغیر محیطی `PATH` + +یه متغیر محیطی **خاص** به اسم **`PATH`** وجود داره که سیستم‌عامل‌ها (لینوکس، مک‌اواس، ویندوز) ازش برای پیدا کردن برنامه‌هایی که قراره اجرا بشن استفاده می‌کنن. + +مقدار متغیر `PATH` یه رشته طولانی از پوشه‌هاست که توی لینوکس و مک‌اواس با دونقطه `:` و توی ویندوز با نقطه‌ویرگول `;` از هم جدا شدن. + +مثلاً، متغیر محیطی `PATH` می‌تونه اینجوری باشه: + +//// tab | لینوکس، مک‌اواس + +```plaintext +/usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbin +``` + +یعنی سیستم باید دنبال برنامه‌ها توی این پوشه‌ها بگرده: + +* `/usr/local/bin` +* `/usr/bin` +* `/bin` +* `/usr/sbin` +* `/sbin` + +//// + +//// tab | ویندوز + +```plaintext +C:\Program Files\Python312\Scripts;C:\Program Files\Python312;C:\Windows\System32 +``` + +یعنی سیستم باید دنبال برنامه‌ها توی این پوشه‌ها بگرده: + +* `C:\Program Files\Python312\Scripts` +* `C:\Program Files\Python312` +* `C:\Windows\System32` + +//// + +وقتی یه **دستور** توی ترمینال تایپ می‌کنی، سیستم‌عامل **دنبال** برنامه توی **هر کدوم از این پوشه‌ها** که توی متغیر محیطی `PATH` لیست شدن می‌گرده. + +مثلاً، وقتی توی ترمینال `python` تایپ می‌کنی، سیستم‌عامل دنبال یه برنامه به اسم `python` توی **اولین پوشه** توی اون لیست می‌گرده. + +اگه پیداش کنه، **استفاده‌ش می‌کنه**. وگرنه توی **پوشه‌های بعدی** دنبالش می‌گرده. + +### نصب پایتون و به‌روزرسانی `PATH` + +وقتی پایتون رو نصب می‌کنی، ممکنه ازت بپرسن آیا می‌خوای متغیر محیطی `PATH` رو به‌روزرسانی کنی. + +//// tab | لینوکس، مک‌اواس + +فرض کن پایتون رو نصب کردی و توی یه پوشه `/opt/custompython/bin` قرار گرفته. + +اگه بگی بله برای به‌روزرسانی متغیر محیطی `PATH`، نصاب `/opt/custompython/bin` رو به متغیر محیطی `PATH` اضافه می‌کنه. + +ممکنه اینجوری بشه: + +```plaintext +/usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbin:/opt/custompython/bin +``` + +این‌جوری، وقتی توی ترمینال `python` تایپ می‌کنی، سیستم برنامه پایتون رو توی `/opt/custompython/bin` (آخرین پوشه) پیدا می‌کنه و از اون استفاده می‌کنه. + +//// + +//// tab | ویندوز + +فرض کن پایتون رو نصب کردی و توی یه پوشه `C:\opt\custompython\bin` قرار گرفته. + +اگه بگی بله برای به‌روزرسانی متغیر محیطی `PATH`، نصاب `C:\opt\custompython\bin` رو به متغیر محیطی `PATH` اضافه می‌کنه. + +```plaintext +C:\Program Files\Python312\Scripts;C:\Program Files\Python312;C:\Windows\System32;C:\opt\custompython\bin +``` + +این‌جوری، وقتی توی ترمینال `python` تایپ می‌کنی، سیستم برنامه پایتون رو توی `C:\opt\custompython\bin` (آخرین پوشه) پیدا می‌کنه و از اون استفاده می‌کنه. + +//// + +پس، اگه تایپ کنی: + +
+ +```console +$ python +``` + +
+ +//// tab | لینوکس، مک‌اواس + +سیستم برنامه `python` رو توی `/opt/custompython/bin` **پیدا** می‌کنه و اجراش می‌کنه. + +تقریباً معادل اینه که تایپ کنی: + +
+ +```console +$ /opt/custompython/bin/python +``` + +
+ +//// + +//// tab | ویندوز + +سیستم برنامه `python` رو توی `C:\opt\custompython\bin\python` **پیدا** می‌کنه و اجراش می‌کنه. + +تقریباً معادل اینه که تایپ کنی: + +
+ +```console +$ C:\opt\custompython\bin\python +``` + +
+ +//// + +این اطلاعات وقتی در مورد [محیط‌های مجازی](virtual-environments.md){.internal-link target=_blank} یاد می‌گیری به‌دردت می‌خوره. + +## نتیجه‌گیری + +با این باید یه درک پایه‌ای از **متغیرهای محیطی** و نحوه استفاده‌شون توی پایتون داشته باشی. + +می‌تونی بیشتر در موردشون توی ویکی‌پدیا برای متغیر محیطی بخونی. + +توی خیلی موارد مشخص نیست که متغیرهای محیطی چطور می‌تونن فوری مفید و کاربردی باشن. ولی توی موقعیت‌های مختلف توسعه مدام پیداشون می‌شه، پس خوبه که در موردشون بدونی. + +مثلاً، توی بخش بعدی در مورد [محیط‌های مجازی](virtual-environments.md) به این اطلاعات نیاز داری. From 4ca93aea04bf289cedb4dc0d922c97f2e99399d9 Mon Sep 17 00:00:00 2001 From: github-actions Date: Fri, 25 Jul 2025 09:27:24 +0000 Subject: [PATCH 02/60] =?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 42f9c5c2c..e198e9437 100644 --- a/docs/en/docs/release-notes.md +++ b/docs/en/docs/release-notes.md @@ -9,6 +9,7 @@ hide: ### Translations +* 🌐 Add Persian translation for `docs/fa/docs/environment-variables.md`. PR [#13923](https://github.com/fastapi/fastapi/pull/13923) by [@Mohammad222PR](https://github.com/Mohammad222PR). * 🌐 Add Persian translation for `docs/fa/docs/python-types.md`. PR [#13524](https://github.com/fastapi/fastapi/pull/13524) by [@Mohammad222PR](https://github.com/Mohammad222PR). * 🌐 Update Portuguese Translation for `docs/pt/docs/project-generation.md`. PR [#13875](https://github.com/fastapi/fastapi/pull/13875) by [@EdmilsonRodrigues](https://github.com/EdmilsonRodrigues). * 🌐 Add Persian translation for `docs/fa/docs/async.md`. PR [#13541](https://github.com/fastapi/fastapi/pull/13541) by [@Mohammad222PR](https://github.com/Mohammad222PR). From e4453a850d794fd211eb3741c85cf3bec320c871 Mon Sep 17 00:00:00 2001 From: Koyo Miyazaki <82708304+KoyoMiyazaki@users.noreply.github.com> Date: Sat, 26 Jul 2025 19:48:11 +0900 Subject: [PATCH 03/60] =?UTF-8?q?=F0=9F=93=9D=20Fix=20highlight=20line=20i?= =?UTF-8?q?n=20`docs/ja/docs/tutorial/body.md`=20(#13927)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit fix highlight line in docs/ja/docs/tutorial/body.md --- docs/ja/docs/tutorial/body.md | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/docs/ja/docs/tutorial/body.md b/docs/ja/docs/tutorial/body.md index 8376959d5..1298eec7e 100644 --- a/docs/ja/docs/tutorial/body.md +++ b/docs/ja/docs/tutorial/body.md @@ -22,7 +22,7 @@ GET リクエストでボディを送信することは、仕様では未定義 ます初めに、 `pydantic` から `BaseModel` をインポートする必要があります: -{* ../../docs_src/body/tutorial001.py hl[2] *} +{* ../../docs_src/body/tutorial001.py hl[4] *} ## データモデルの作成 @@ -30,7 +30,7 @@ GET リクエストでボディを送信することは、仕様では未定義 すべての属性にpython標準の型を使用します: -{* ../../docs_src/body/tutorial001.py hl[5:9] *} +{* ../../docs_src/body/tutorial001.py hl[7:11] *} クエリパラメータの宣言と同様に、モデル属性がデフォルト値をもつとき、必須な属性ではなくなります。それ以外は必須になります。オプショナルな属性にしたい場合は `None` を使用してください。 @@ -58,7 +58,7 @@ GET リクエストでボディを送信することは、仕様では未定義 *パスオペレーション* に加えるために、パスパラメータやクエリパラメータと同じ様に宣言します: -{* ../../docs_src/body/tutorial001.py hl[16] *} +{* ../../docs_src/body/tutorial001.py hl[18] *} ...そして、作成したモデル `Item` で型を宣言します。 @@ -125,7 +125,7 @@ GET リクエストでボディを送信することは、仕様では未定義 関数内部で、モデルの全ての属性に直接アクセスできます: -{* ../../docs_src/body/tutorial002.py hl[19] *} +{* ../../docs_src/body/tutorial002.py hl[21] *} ## リクエストボディ + パスパラメータ @@ -133,7 +133,7 @@ GET リクエストでボディを送信することは、仕様では未定義 **FastAPI** はパスパラメータである関数パラメータは**パスから受け取り**、Pydanticモデルによって宣言された関数パラメータは**リクエストボディから受け取る**ということを認識します。 -{* ../../docs_src/body/tutorial003.py hl[15:16] *} +{* ../../docs_src/body/tutorial003.py hl[17:18] *} ## リクエストボディ + パスパラメータ + クエリパラメータ @@ -141,7 +141,7 @@ GET リクエストでボディを送信することは、仕様では未定義 **FastAPI** はそれぞれを認識し、適切な場所からデータを取得します。 -{* ../../docs_src/body/tutorial004.py hl[16] *} +{* ../../docs_src/body/tutorial004.py hl[18] *} 関数パラメータは以下の様に認識されます: From 106a4338db8d546f3a6bf817e237331297e7f797 Mon Sep 17 00:00:00 2001 From: github-actions Date: Sat, 26 Jul 2025 10:48:36 +0000 Subject: [PATCH 04/60] =?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 e198e9437..d5186aad3 100644 --- a/docs/en/docs/release-notes.md +++ b/docs/en/docs/release-notes.md @@ -9,6 +9,7 @@ hide: ### Translations +* 📝 Fix highlight line in `docs/ja/docs/tutorial/body.md`. PR [#13927](https://github.com/fastapi/fastapi/pull/13927) by [@KoyoMiyazaki](https://github.com/KoyoMiyazaki). * 🌐 Add Persian translation for `docs/fa/docs/environment-variables.md`. PR [#13923](https://github.com/fastapi/fastapi/pull/13923) by [@Mohammad222PR](https://github.com/Mohammad222PR). * 🌐 Add Persian translation for `docs/fa/docs/python-types.md`. PR [#13524](https://github.com/fastapi/fastapi/pull/13524) by [@Mohammad222PR](https://github.com/Mohammad222PR). * 🌐 Update Portuguese Translation for `docs/pt/docs/project-generation.md`. PR [#13875](https://github.com/fastapi/fastapi/pull/13875) by [@EdmilsonRodrigues](https://github.com/EdmilsonRodrigues). From 54c7c34b25e9c71d218f4a01095520bc2b582b24 Mon Sep 17 00:00:00 2001 From: Chih-Hsuan Yen <1937689+yan12125@users.noreply.github.com> Date: Sat, 26 Jul 2025 18:49:23 +0800 Subject: [PATCH 05/60] =?UTF-8?q?=E2=AC=86=20Update=20httpx=20requirement?= =?UTF-8?q?=20to=20>=3D0.23.0,<0.29.0=20(#13114)?= 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> --- requirements-docs-tests.txt | 2 +- requirements-github-actions.txt | 2 +- .../test_custom_request_and_route/test_tutorial002.py | 8 +++++--- 3 files changed, 7 insertions(+), 5 deletions(-) diff --git a/requirements-docs-tests.txt b/requirements-docs-tests.txt index 71f4a7ab9..e7684a2e3 100644 --- a/requirements-docs-tests.txt +++ b/requirements-docs-tests.txt @@ -1,4 +1,4 @@ # For mkdocstrings and tests -httpx >=0.23.0,<0.28.0 +httpx >=0.23.0,<0.29.0 # For linting and generating docs versions ruff ==0.11.2 diff --git a/requirements-github-actions.txt b/requirements-github-actions.txt index 920aefea6..f807d06a8 100644 --- a/requirements-github-actions.txt +++ b/requirements-github-actions.txt @@ -1,6 +1,6 @@ PyGithub>=2.3.0,<3.0.0 pydantic>=2.5.3,<3.0.0 pydantic-settings>=2.1.0,<3.0.0 -httpx>=0.27.0,<0.28.0 +httpx>=0.27.0,<0.29.0 pyyaml >=5.3.1,<7.0.0 smokeshow diff --git a/tests/test_tutorial/test_custom_request_and_route/test_tutorial002.py b/tests/test_tutorial/test_custom_request_and_route/test_tutorial002.py index 6f7355aaa..647f1c5dd 100644 --- a/tests/test_tutorial/test_custom_request_and_route/test_tutorial002.py +++ b/tests/test_tutorial/test_custom_request_and_route/test_tutorial002.py @@ -1,4 +1,4 @@ -from dirty_equals import IsDict +from dirty_equals import IsDict, IsOneOf from fastapi.testclient import TestClient from docs_src.custom_request_and_route.tutorial002 import app @@ -24,14 +24,16 @@ def test_exception_handler_body_access(): "input": {"numbers": [1, 2, 3]}, } ], - "body": '{"numbers": [1, 2, 3]}', + # httpx 0.28.0 switches to compact JSON https://github.com/encode/httpx/issues/3363 + "body": IsOneOf('{"numbers": [1, 2, 3]}', '{"numbers":[1,2,3]}'), } } ) | IsDict( # TODO: remove when deprecating Pydantic v1 { "detail": { - "body": '{"numbers": [1, 2, 3]}', + # httpx 0.28.0 switches to compact JSON https://github.com/encode/httpx/issues/3363 + "body": IsOneOf('{"numbers": [1, 2, 3]}', '{"numbers":[1,2,3]}'), "errors": [ { "loc": ["body"], From bfbed308699d6f8204411e5bbaaa084b6e779c30 Mon Sep 17 00:00:00 2001 From: github-actions Date: Sat, 26 Jul 2025 10:49:51 +0000 Subject: [PATCH 06/60] =?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 d5186aad3..c75a8b574 100644 --- a/docs/en/docs/release-notes.md +++ b/docs/en/docs/release-notes.md @@ -18,6 +18,7 @@ hide: ### Internal +* ⬆ Update httpx requirement to >=0.23.0,<0.29.0. PR [#13114](https://github.com/fastapi/fastapi/pull/13114) by [@yan12125](https://github.com/yan12125). * 🔧 Update sponsors: Add Mobb. PR [#13916](https://github.com/fastapi/fastapi/pull/13916) by [@tiangolo](https://github.com/tiangolo). * 👥 Update FastAPI People - Experts. PR [#13889](https://github.com/fastapi/fastapi/pull/13889) by [@tiangolo](https://github.com/tiangolo). * 🔨 Update FastAPI People sleep interval, use external settings. PR [#13888](https://github.com/fastapi/fastapi/pull/13888) by [@tiangolo](https://github.com/tiangolo). From fcdd5031e1b150952bd70ea8d1ea805d5f1014c6 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Sat, 26 Jul 2025 12:51:31 +0200 Subject: [PATCH 07/60] =?UTF-8?q?=E2=AC=86=20[pre-commit.ci]=20pre-commit?= =?UTF-8?q?=20autoupdate=20(#13894)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit updates: - [github.com/astral-sh/ruff-pre-commit: v0.12.2 → v0.12.4](https://github.com/astral-sh/ruff-pre-commit/compare/v0.12.2...v0.12.4) 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 680cafce9..e461b0133 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.12.2 + rev: v0.12.4 hooks: - id: ruff args: From 8bfc783194bdfc2142ac716ae208c735e1862c81 Mon Sep 17 00:00:00 2001 From: github-actions Date: Sat, 26 Jul 2025 10:51:53 +0000 Subject: [PATCH 08/60] =?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 c75a8b574..d5730e247 100644 --- a/docs/en/docs/release-notes.md +++ b/docs/en/docs/release-notes.md @@ -18,6 +18,7 @@ hide: ### Internal +* ⬆ [pre-commit.ci] pre-commit autoupdate. PR [#13894](https://github.com/fastapi/fastapi/pull/13894) by [@pre-commit-ci[bot]](https://github.com/apps/pre-commit-ci). * ⬆ Update httpx requirement to >=0.23.0,<0.29.0. PR [#13114](https://github.com/fastapi/fastapi/pull/13114) by [@yan12125](https://github.com/yan12125). * 🔧 Update sponsors: Add Mobb. PR [#13916](https://github.com/fastapi/fastapi/pull/13916) by [@tiangolo](https://github.com/tiangolo). * 👥 Update FastAPI People - Experts. PR [#13889](https://github.com/fastapi/fastapi/pull/13889) by [@tiangolo](https://github.com/tiangolo). From 2013336d65e1b7ac25aa3a4b130d41b6b2ac31f4 Mon Sep 17 00:00:00 2001 From: Edmilson Monteiro Rodrigues Neto Date: Sat, 26 Jul 2025 12:16:39 +0100 Subject: [PATCH 09/60] =?UTF-8?q?=20=F0=9F=8C=90=20Update=20Portuguese=20T?= =?UTF-8?q?ranslation=20for=20`docs/pt/docs/async.md`=20(#13863)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docs/pt/docs/async.md | 207 ++++++++++++++++++++++-------------------- 1 file changed, 108 insertions(+), 99 deletions(-) diff --git a/docs/pt/docs/async.md b/docs/pt/docs/async.md index 0d6bdbf0e..4425eba77 100644 --- a/docs/pt/docs/async.md +++ b/docs/pt/docs/async.md @@ -40,7 +40,7 @@ def results(): --- -Se sua aplicação (de alguma forma) não tem que se comunicar com nada mais e tem que esperar que o respondam, use `async def`. +Se sua aplicação (de alguma forma) não tem que se comunicar com nada mais e esperar que o respondam, use `async def`. --- @@ -52,7 +52,7 @@ Se você simplesmente não sabe, use apenas `def`. De qualquer forma, em ambos os casos acima, FastAPI irá trabalhar assincronamente e ser extremamente rápido. -Seguindo os passos acima, ele será capaz de fazer algumas otimizações de performance. +Mas, seguindo os passos acima, ele será capaz de fazer algumas otimizações de performance. ## Detalhes Técnicos @@ -66,36 +66,36 @@ Vamos ver aquela frase por partes na seção abaixo: ## Código assíncrono -Código assíncrono apenas significa que a linguagem 💬 tem um jeito de dizer para o computador / programa 🤖 que em certo ponto, ele 🤖 terá que esperar por *algo* para finalizar em outro lugar. Vamos dizer que esse *algo* seja chamado "arquivo lento" 📝. +Código assíncrono apenas significa que a linguagem 💬 tem um jeito de dizer para o computador / programa 🤖 que em certo ponto do código, ele 🤖 terá que esperar *algo* finalizar em outro lugar. Vamos dizer que esse *algo* seja chamado "arquivo lento" 📝. -Então, durante esse tempo, o computador pode ir e fazer outro trabalho, enquanto o "arquivo lento" 📝 termine. +Então, durante esse tempo, o computador pode ir e fazer outro trabalho, enquanto o "arquivo lento" 📝 termina. -Então o computador / programa 🤖 irá voltar toda hora que tiver uma chance porquê ele ainda está esperando o "arquivo lento", ou ele 🤖 nunca irá terminar todo o trabalho que tem até esse ponto. E ele 🤖 irá ver se alguma das tarefas que estava esperando já terminaram, fazendo o que quer que tinham que fazer. +Então o computador / programa 🤖 irá voltar sempre que tiver uma chance, seja porque ele está esperando novamente, ou quando ele 🤖 terminar todo o trabalho que tem até esse ponto. E ele 🤖 irá ver se alguma das tarefas que estava esperando já terminaram de fazer o que quer que tinham que fazer. -Depois, ele 🤖 pega a primeira tarefa para finalizar (vamos dizer, nosso "arquivo lento" 📝) e continua o que ele tem que fazer com isso. +Depois, ele 🤖 pega a primeira tarefa para finalizar (vamos dizer, nosso "arquivo lento" 📝) e continua o que tem que fazer com ela. -Esse "esperar por algo" normalmente se refere a operações I/O que são relativamente "lentas" (comparadas a velocidade do processador e da memória RAM), como esperar por: +Esse "esperar por algo" normalmente se refere a operações I/O que são relativamente "lentas" (comparadas à velocidade do processador e da memória RAM), como esperar por: * dados do cliente para serem enviados através da rede -* dados enviados pelo seu programa para serem recebidos pelo clente através da rede -* conteúdo de um arquivo no disco pra ser lido pelo sistema e entregar ao seu programa +* dados enviados pelo seu programa serem recebidos pelo clente através da rede +* conteúdo de um arquivo no disco ser lido pelo sistema e entregue ao seu programa * conteúdo que seu programa deu ao sistema para ser escrito no disco -* uma operação remota API -* uma operação no banco de dados para finalizar -* uma solicitação no banco de dados esperando o retorno do resultado +* uma operação em uma API remota +* uma operação no banco de dados finalizar +* uma solicitação no banco de dados retornar o resultado * etc. -Enquanto o tempo de execução é consumido mais pela espera das operações I/O, essas operações são chamadas de operações "limitadas por I/O". +Quanto o tempo de execução é consumido majoritariamente pela espera de operações I/O, essas operações são chamadas operações "limitadas por I/O". -Isso é chamado de "assíncrono" porquê o computador / programa não tem que ser "sincronizado" com a tarefa lenta, esperando pelo exato momento que a tarefa finalize, enquanto não faz nada, para ser capaz de pegar o resultado da tarefa e dar continuidade ao trabalho. +Isso é chamado de "assíncrono" porque o computador / programa não tem que ser "sincronizado" com a tarefa lenta, esperando pelo momento exato em que a tarefa finaliza, enquanto não faz nada, para ser capaz de pegar o resultado da tarefa e dar continuidade ao trabalho. -Ao invés disso, sendo um sistema "assíncrono", uma vez finalizada, a tarefa pode esperar um pouco (alguns microssegundos) para que o computador / programa finalize o que quer que esteja fazendo,e então volte para pegar o resultado e continue trabalhando com ele. +Ao invés disso, sendo um sistema "assíncrono", uma vez finalizada, a tarefa pode esperar na fila um pouco (alguns microssegundos) para que o computador / programa finalize o que quer que esteja fazendo, e então volte para pegar o resultado e continue trabalhando com ele. -Para "síncrono" (contrário de "assíncrono") também é utilizado o termo "sequencial", porquê o computador / programa segue todos os passos, na sequência, antes de trocar para uma tarefa diferente, mesmo se alguns passos envolvam esperar. +Para "síncrono" (contrário de "assíncrono") também é utilizado o termo "sequencial", porquê o computador / programa segue todos os passos, em sequência, antes de trocar para uma tarefa diferente, mesmo se alguns passos envolvam esperar. ### Concorrência e hambúrgueres -Essa idéia de código **assíncrono** descrito acima é algo às vezes chamado de **"concorrência"**. E é diferente de **"paralelismo"**. +Essa idéia de código **assíncrono** descrita acima é às vezes chamado de **"concorrência"**. Isso é diferente de **"paralelismo"**. **Concorrência** e **paralelismo** ambos são relacionados a "diferentes coisas acontecendo mais ou menos ao mesmo tempo". @@ -105,117 +105,115 @@ Para ver essa diferença, imagine a seguinte história sobre hambúrgueres: ### Hambúrgueres concorrentes -Você vai com seu _crush_ :heart_eyes: na lanchonete, fica na fila enquanto o caixa pega os pedidos das pessoas na sua frente. +Você vai com seu _crush_ na lanchonete, e fica na fila enquanto o caixa pega os pedidos das pessoas na sua frente. 😍 -Então chega a sua vez, você pede dois saborosos hambúrgueres para você e seu _crush_ :heart_eyes:. +Então chega a sua vez, você pede dois saborosos hambúrgueres para você e seu _crush_. 🍔🍔 -Você paga. +O caixa diz alguma coisa para o cozinheiro na cozinha para que eles saivam que têm que preparar seus hambúrgueres (mesmo que ele esteja atualmente preparando os lanches dos outros clientes). -O caixa diz alguma coisa para o cara na cozinha para que ele tenha que preparar seus hambúrgueres (mesmo embora ele esteja preparando os lanches dos outros clientes). +Você paga. 💸 O caixa te entrega seu número de chamada. -Enquanto você espera, você vai com seu _crush_ :heart_eyes: e pega uma mesa, senta e conversa com seu _crush_ :heart_eyes: por um bom tempo (como seus hambúrgueres são muito saborosos, leva um tempo para serem preparados). +Enquanto você espera, você vai com seu _crush_ e pega uma mesa, senta e conversa com seu _crush_ por um bom tempo (já que seus hambúrgueres são muito saborosos, e leva um tempo para serem preparados). -Enquanto você está sentado na mesa com seu _crush_ :heart_eyes:, esperando os hambúrgueres, você pode gastar o tempo admirando como lindo, maravilhoso e esperto é seu _crush_ :heart_eyes:. +Já que você está sentado na mesa com seu _crush_, esperando os hambúrgueres, você pode passar esse tempo admirando o quão lindo, maravilhoso e esperto é seu _crush_ ✨😍✨. -Enquanto espera e conversa com seu _crush_ :heart_eyes:, de tempos em tempos, você verifica o número de chamada exibido no balcão para ver se já é sua vez. +Enquanto espera e conversa com seu _crush_, de tempos em tempos, você verifica o número da chamada exibido no balcão para ver se já é sua vez. -Então a certo ponto, é finalmente sua vez. Você vai no balcão, pega seus hambúrgueres e volta para a mesa. +Então em algum momento, é finalmente sua vez. Você vai ao balcão, pega seus hambúrgueres e volta para a mesa. -Você e seu _crush_ :heart_eyes: comem os hambúrgueres e aproveitam o tempo. +Você e seu _crush_ comem os hambúrgueres e aproveitam o tempo. ✨ --- -Imagine que você seja o computador / programa nessa história. +Imagine que você seja o computador / programa nessa história. -Enquanto você está na fila, tranquilo, esperando por sua vez, não está fazendo nada "produtivo". Mas a fila é rápida porquê o caixa só está pegando os pedidos, então está tudo bem. +Enquanto você está na fila, você está somente ocioso 😴, esperando por sua vez, sem fazer nada muito "produtivo". Mas a fila é rápida porque o caixa só está pegando os pedidos (não os preparando), então está tudo bem. -Então, quando é sua vez, você faz o trabalho "produtivo" de verdade, você processa o menu, decide o que quer, pega a escolha de seu _crush_ :heart_eyes:, paga, verifica se entregou o valor correto em dinheiro ou cartão de crédito, verifica se foi cobrado corretamente, verifica se seu pedido está correto etc. +Então, quando é sua vez, você faz trabalho realmente "produtivo", você processa o menu, decide o que quer, pega a escolha de seu _crush_, paga, verifica se entregou o cartão ou a cédula correta, verifica se foi cobrado corretamente, verifica se seu pedido está correto etc. -Mas então, embora você ainda não tenha os hambúrgueres, seu trabalho no caixa está "pausado", porquê você tem que esperar seus hambúrgueres estarem prontos. +Mas então, embora você ainda não tenha os hambúrgueres, seu trabalho no caixa está "pausado" ⏸, porque você tem que esperar 🕙 seus hambúrgueres ficarem prontos. -Mas enquanto você se afasta do balcão e senta na mesa com o número da sua chamada, você pode trocar sua atenção para seu _crush_ :heart_eyes:, e "trabalhar" nisso. Então você está novamente fazendo algo muito "produtivo", como flertar com seu _crush_ :heart_eyes:. +Contudo, à medida que você se afasta do balcão e senta na mesa, com um número para sua chamada, você pode trocar 🔀 sua atenção para seu _crush_, e "trabalhar" ⏯ 🤓 nisso. Então você está novamente fazendo algo muito "produtivo", como flertar com seu _crush_ 😍. -Então o caixa diz que "seus hambúrgueres estão prontos" colocando seu número no balcão, mas você não corre que nem um maluco imediatamente quando o número exibido é o seu. Você sabe que ninguém irá roubar seus hambúrgueres porquê você tem o número de chamada, e os outros tem os números deles. +Então o caixa 💁 diz que "seus hambúrgueres estão prontos" colocando seu número no balcão, mas você não corre que nem um maluco imediatamente quando o número exibido é o seu. Você sabe que ninguém irá roubar seus hambúrgueres porque você tem o seu número da chamada, e os outros têm os deles. -Então você espera que seu _crush_ :heart_eyes: termine a história que estava contando (terminar o trabalho atual / tarefa sendo processada), sorri gentilmente e diz que você está indo buscar os hambúrgueres. +Então você espera seu _crush_ terminar a história que estava contando (terminar o trabalho atual ⏯ / tarefa sendo processada 🤓), sorri gentilmente e diz que você está indo buscar os hambúrgueres. -Então você vai no balcão, para a tarefa inicial que agora está finalizada, pega os hambúrgueres, e leva para a mesa. Isso finaliza esse passo / tarefa da interação com o balcão. Agora é criada uma nova tarefa, "comer hambúrgueres", mas a tarefa anterior, "pegar os hambúrgueres" já está finalizada. +Então você vai ao balcão 🔀, para a tarefa inicial que agora está finalizada⏯, pega os hambúrgueres, agradece, e leva-os para a mesa. Isso finaliza esse passo / tarefa da interação com o balcão ⏹. Isso, por sua vez, cria uma nova tarefa, a de "comer hambúrgueres" 🔀 ⏯, mas a tarefa anterior de "pegar os hambúrgueres" já está finalizada ⏹. ### Hambúrgueres paralelos -Você vai com seu _crush_ :heart_eyes: em uma lanchonete paralela. +Agora vamos imaginar que esses não são "Hambúrgueres Concorrentes", e sim "Hambúrgueres Paralelos" -Você fica na fila enquanto alguns (vamos dizer 8) caixas pegam os pedidos das pessoas na sua frente. +Você vai com seu _crush_ na lanchonete paralela. -Todo mundo antes de você está esperando pelos hambúrgueres estarem prontos antes de deixar o caixa porquê cada um dos 8 caixas vai e prepara o hambúrguer antes de pegar o próximo pedido. +Você fica na fila enquanto vários (vamos dizer 8) caixas que também são cozinheiros pegam os pedidos das pessoas na sua frente. -Então é finalmente sua vez, e pede 2 hambúrgueres muito saborosos para você e seu _crush_ :heart_eyes:. +Todo mundo na sua frente está esperando seus hambúrgueres ficarem prontos antes de deixar o caixa porque cada um dos 8 caixas vai e prepara o hambúrguer logo após receber o pedido, antes de pegar o próximo pedido. -Você paga. +Então é finalmente sua vez, você pede 2 hambúrgueres muito saborosos para você e seu _crush_. + +Você paga 💸. O caixa vai para a cozinha. -Você espera, na frente do balcão, para que ninguém pegue seus hambúrgueres antes de você, já que não tem números de chamadas. +Você espera, na frente do balcão 🕙, para que ninguém pegue seus hambúrgueres antes de você, já que não tem números de chamadas. -Enquanto você e seu _crush_ :heart_eyes: estão ocupados não permitindo que ninguém passe a frente e pegue seus hambúrgueres assim que estiverem prontos, você não pode dar atenção ao seu _crush_ :heart_eyes:. +Como você e seu _crush_ estão ocupados não permitindo que ninguém passe na frente e pegue seus hambúrgueres assim que estiverem prontos, você não pode dar atenção ao seu _crush_. 😞 -Isso é trabalho "síncrono", você está "sincronizado" com o caixa / cozinheiro. Você tem que esperar e estar lá no exato momento que o caixa / cozinheiro terminar os hambúrgueres e dá-los a você, ou então, outro alguém pode pegá-los. +Isso é trabalho "síncrono", você está "sincronizado" com o caixa / cozinheiro👨‍🍳. Você tem que esperar 🕙 e estar lá no exato momento que o caixa / cozinheiro 👨‍🍳 terminar os hambúrgueres e os der a você, ou então, outro alguém pode pegá-los. -Então seu caixa / cozinheiro finalmente volta com seus hambúrgueres, depois de um longo tempo esperando por eles em frente ao balcão. +Então seu caixa / cozinheiro 👨‍🍳 finalmente volta com seus hambúrgueres, depois de um longo tempo esperando 🕙 por eles em frente ao balcão. -Você pega seus hambúrgueres e vai para a mesa com seu _crush_ :heart_eyes:. +Você pega seus hambúrgueres e vai para a mesa com seu _crush_. -Vocês comem os hambúrgueres, e o trabalho está terminado. +Vocês comem os hambúrgueres, e o trabalho está terminado. ⏹ -Não houve muita conversa ou flerte já que a maior parte do tempo foi gasto esperando os lanches na frente do balcão. +Não houve muita conversa ou flerte já que a maior parte do tempo foi gasto esperando 🕙 na frente do balcão. 😞 --- -Nesse cenário dos hambúrgueres paralelos, você é um computador / programa com dois processadores (você e seu _crush_ :heart_eyes:), ambos esperando e dedicando a atenção de estar "esperando no balcão" por um bom tempo. +Nesse cenário dos hambúrgueres paralelos, você é um computador / programa com dois processadores (você e seu _crush_), ambos esperando 🕙 e dedicando sua atenção ⏯ "esperando no balcão" 🕙 por um bom tempo. -A lanchonete paralela tem 8 processadores (caixas / cozinheiros). Enquanto a lanchonete dos hambúrgueres concorrentes tinham apenas 2 (um caixa e um cozinheiro). +A lanchonete paralela tem 8 processadores (caixas / cozinheiros), enquanto a lanchonete dos hambúrgueres concorrentes tinha apenas 2 (um caixa e um cozinheiro). -Ainda assim, a última experiência não foi a melhor. +Ainda assim, a experiência final não foi a melhor. 😞 --- -Essa poderia ser a história paralela equivalente aos hambúrgueres. +Essa seria o equivalente paralelo à histório dos hambúrgueres. 🍔 Para um exemplo "mais real", imagine um banco. -Até recentemente, a maioria dos bancos tinha muitos caixas e uma grande fila. +Até recentemente, a maioria dos bancos tinham muitos caixas 👨‍💼👨‍💼👨‍💼👨‍💼 e uma grande fila 🕙🕙🕙🕙🕙🕙🕙🕙. -Todos os caixas fazendo todo o trabalho, um cliente após o outro. +Todos os caixas fazendo todo o trabalho, um cliente após o outro 👨‍💼⏯. -E você tinha que esperar na fila por um longo tempo ou poderia perder a vez. +E você tinha que esperar 🕙 na fila por um longo tempo ou poderia perder a vez. -Você provavelmente não gostaria de levar seu _crush_ :heart_eyes: com você para um rolezinho no banco. +Você provavelmente não gostaria de levar seu _crush_ 😍 com você para um rolezinho no banco 🏦. ### Conclusão dos hambúrgueres -Nesse cenário dos "hambúrgueres com seu _crush_ :heart_eyes:", como tem muita espera, faz mais sentido ter um sistema concorrente. +Nesse cenário dos "hambúrgueres com seu _crush_", como tem muita espera, faz mais sentido ter um sistema concorrente ⏸🔀⏯. Esse é o caso da maioria das aplicações web. -Geralmente são muitos usuários, e seu servidor está esperando pelas suas conexões não tão boas para enviar as requisições. - -E então esperando novamente pelas respostas voltarem. - -Essa "espera" é medida em microssegundos, e ainda assim, somando tudo, é um monte de espera no final. +Muitos, muitos usuários, mas seu servidor está esperando 🕙 pela sua conexão não tão boa enviar suas requisições. -Por isso que faz muito mais sentido utilizar código assíncrono para APIs web. +E então esperando 🕙 novamente as respostas voltarem. -A maioria dos frameworks Python existentes mais populares (incluindo Flask e Django) foram criados antes que os novos recursos assíncronos existissem em Python. Então, os meios que eles podem ser colocados em produção para suportar execução paralela mais a forma antiga de execução assíncrona não são tão poderosos quanto as novas capacidades. +Essa "espera" 🕙 é medida em microssegundos, mas ainda assim, somando tudo, é um monte de espera no final. -Mesmo embora a especificação principal para web assíncrono em Python (ASGI) foi desenvolvida no Django, para adicionar suporte para WebSockets. +Por isso que faz bastante sentido utilizar código assíncrono ⏸🔀⏯ para APIs web. -Esse tipo de assincronicidade é o que fez NodeJS popular (embora NodeJS não seja paralelo) e que essa seja a força do Go como uma linguagem de programa. +Esse tipo de assincronicidade é o que fez NodeJS popular (embora NodeJS não seja paralelo) e essa é a força do Go como uma linguagem de programação. E esse é o mesmo nível de performance que você tem com o **FastAPI**. -E como você pode ter paralelismo e sincronicidade ao mesmo tempo, você tem uma maior performance do que a maioria dos frameworks NodeJS testados e lado a lado com Go, que é uma linguagem compilada próxima ao C (tudo graças ao Starlette). +E como você pode ter paralelismo e assincronicidade ao mesmo tempo, você tem uma maior performance do que a maioria dos frameworks NodeJS testados e lado a lado com Go, que é uma linguagem compilada, mais próxima ao C (tudo graças ao Starlette). ### Concorrência é melhor que paralelismo? @@ -225,64 +223,64 @@ Concorrência é diferente de paralelismo. E é melhor em cenários **específic Então, para equilibrar tudo, imagine a seguinte historinha: -> Você tem que limpar uma grande casa suja. +> Você tem que limpar uma casa grande e suja. *Sim, essa é toda a história*. --- -Não há espera em lugar algum, apenas um monte de trabalho para ser feito, em múltiplos cômodos da casa. +Não há espera 🕙 em lugar algum, apenas um monte de trabalho para ser feito, em múltiplos cômodos da casa. -Você poderia ter chamadas como no exemplo dos hambúrgueres, primeiro a sala de estar, então a cozinha, mas você não está esperando por nada, apenas limpar e limpar, as chamadas não afetariam em nada. +Você poderia ter turnos como no exemplo dos hambúrgueres, primeiro a sala de estar, então a cozinha, mas como você não está esperando por nada, apenas limpando e limpando, as chamadas não afetariam em nada. -Levaria o mesmo tempo para finalizar com ou sem chamadas (concorrência) e você teria feito o mesmo tanto de trabalho. +Levaria o mesmo tempo para finalizar com ou sem turnos (concorrência) e você teria feito o mesmo tanto de trabalho. Mas nesse caso, se você trouxesse os 8 ex-caixas / cozinheiros / agora-faxineiros, e cada um deles (mais você) pudessem dividir a casa para limpá-la, vocês fariam toda a limpeza em **paralelo**, com a ajuda extra, e terminariam muito mais cedo. Nesse cenário, cada um dos faxineiros (incluindo você) poderia ser um processador, fazendo a sua parte do trabalho. -E a maior parte do tempo de execução é tomada por trabalho (ao invés de ficar esperando), e o trabalho em um computador é feito pela CPU, que podem gerar problemas que são chamados de "limite de CPU". +E a maior parte do tempo de execução é tomada por trabalho real (ao invés de ficar esperando), e o trabalho em um computador é feito pela CPU. Eles chamam esses problemas de "limitados por CPU". --- -Exemplos comuns de limite de CPU são coisas que exigem processamento matemático complexo. +Exemplos comuns de operações limitadas por CPU são coisas que exigem processamento matemático complexo. Por exemplo: * **Processamento de áudio** ou **imagem** -* **Visão do Computador**: uma imagem é composta por milhões de pixels, cada pixel tem 3 valores (cores, processamento que normalmente exige alguma computação em todos esses pixels ao mesmo tempo) +* **Visão Computacional**: uma imagem é composta por milhões de pixels, cada pixel tem 3 valores / cores, processar isso normalmente exige alguma computação em todos esses pixels ao mesmo tempo -* **Machine Learning**: Normalmente exige muita multiplicação de matrizes e vetores. Pense numa grande folha de papel com números e multiplicando todos eles juntos e ao mesmo tempo. +* **Machine Learning**: Normalmente exige muita multiplicação de matrizes e vetores. Pense numa grande planilha com números e em multiplicar todos eles juntos e ao mesmo tempo. -* **Deep Learning**: Esse é um subcampo do Machine Learning, então o mesmo se aplica. A diferença é que não há apenas uma grande folha de papel com números para multiplicar, mas um grande conjunto de folhas de papel, e em muitos casos, você utiliza um processador especial para construir e/ou usar modelos. +* **Deep Learning**: Esse é um subcampo do Machine Learning, então, o mesmo se aplica. A diferença é que não há apenas uma grande planilha com números para multiplicar, mas um grande conjunto delas, e em muitos casos, você utiliza um processador especial para construir e/ou usar esses modelos. ### Concorrência + Paralelismo: Web + Machine learning Com **FastAPI** você pode levar a vantagem da concorrência que é muito comum para desenvolvimento web (o mesmo atrativo de NodeJS). -Mas você também pode explorar os benefícios do paralelismo e multiprocessamento (tendo múltiplos processadores rodando em paralelo) para trabalhos pesados que geram **limite de CPU** como aqueles em sistemas de Machine Learning. +Mas você também pode explorar os benefícios do paralelismo e multiprocessamento (tendo múltiplos processadores rodando em paralelo) para trabalhos **limitados por CPU** como aqueles em sistemas de Machine Learning. -Isso, mais o simples fato que Python é a principal linguagem para **Data Science**, Machine Learning e especialmente Deep Learning, faz do FastAPI uma ótima escolha para APIs web e aplicações com Data Science / Machine Learning (entre muitas outras). +Isso, somado ao simples fato que Python é a principal linguagem para **Data Science**, Machine Learning e especialmente Deep Learning, faz do FastAPI uma ótima escolha para APIs web e aplicações com Data Science / Machine Learning (entre muitas outras). Para ver como alcançar esse paralelismo em produção veja a seção sobre [Deployment](deployment/index.md){.internal-link target=_blank}. ## `async` e `await` -Versões modernas do Python tem um modo muito intuitivo para definir código assíncrono. Isso faz parecer normal o código "sequencial" e fazer o "esperar" para você nos momentos certos. +Versões modernas do Python têm um modo muito intuitivo para definir código assíncrono. Isso faz parecer do mesmo jeito do código normal "sequencial" e fazer a "espera" para você nos momentos certos. -Quando tem uma operação que exigirá espera antes de dar os resultados e tem suporte para esses recursos Python, você pode escrever assim: +Quando tem uma operação que exigirá espera antes de dar os resultados e tem suporte para esses novos recursos do Python, você pode escrever assim: ```Python burgers = await get_burgers(2) ``` -A chave aqui é o `await`. Ele diz ao Python que ele tem que esperar por `get_burgers(2)` para finalizar suas coisas antes de armazenar os resultados em `burgers`. Com isso, o Python saberá que ele pode ir e fazer outras coisas nesse meio tempo (como receber outra requisição). +A chave aqui é o `await`. Ele diz ao Python que ele tem que esperar por `get_burgers(2)` finalizar suas coisas 🕙 antes de armazenar os resultados em `burgers`. Com isso, o Python saberá que ele pode ir e fazer outras coisas 🔀 ⏯ nesse meio tempo (como receber outra requisição). Para o `await` funcionar, tem que estar dentro de uma função que suporte essa assincronicidade. Para fazer isso, apenas declare a função com `async def`: ```Python hl_lines="1" async def get_burgers(number: int): - # Fazer alguma coisa assíncrona para criar os hambúrgueres + # Faz alguma coisa assíncrona para criar os hambúrgueres return burgers ``` @@ -295,9 +293,9 @@ def get_sequential_burgers(number: int): return burgers ``` -Com `async def`, o Python sabe que, dentro dessa função, tem que estar ciente das expressões `await`, e que isso pode "pausar" a execução dessa função, e poderá fazer outra coisa antes de voltar. +Com `async def`, o Python sabe que, dentro dessa função, ele deve estar ciente das expressões `await`, e que isso poderá "pausar" ⏸ a execução dessa função, e ir fazer outra coisa 🔀 antes de voltar. -Quando você quiser chamar uma função `async def`, você tem que "esperar". Então, isso não funcionará: +Quando você quiser chamar uma função `async def`, você tem que "esperar" ela. Então, isso não funcionará: ```Python # Isso não irá funcionar, porquê get_burgers foi definido com: async def @@ -319,13 +317,24 @@ async def read_burgers(): Você deve ter observado que `await` pode ser usado somente dentro de funções definidas com `async def`. -Mas ao mesmo tempo, funções definidas com `async def` tem que ser aguardadas. Então, funções com `async def` pdem ser chamadas somente dentro de funções definidas com `async def` também. +Mas ao mesmo tempo, funções definidas com `async def` têm que ser "aguardadas". Então, funções com `async def` pdem ser chamadas somente dentro de funções definidas com `async def` também. Então, sobre o ovo e a galinha, como você chama a primeira função async? Se você estivar trabalhando com **FastAPI** não terá que se preocupar com isso, porquê essa "primeira" função será a sua *função de operação de rota*, e o FastAPI saberá como fazer a coisa certa. -Mas se você quiser usar `async` / `await` sem FastAPI, verifique a documentação oficial Python. +Mas se você quiser usar `async` / `await` sem FastAPI, você também pode fazê-lo. + +### Escreva seu próprio código assíncrono + +Starlette (e **FastAPI**) são baseados no AnyIO, o que o torna compatível com ambos o asyncio da biblioteca padrão do Python, e o Trio. + +Em particular, você pode usar diretamente o AnyIO para seus casos de uso avançados de concorrência que requerem padrões mais avançados no seu próprio código. + +E até se você não estiver utilizando FastAPI, você também pode escrever suas próprias aplicações assíncronas com o AnyIO por ser altamente compatível e ganhar seus benefícios (e.g. *concorrência estruturada*). + +Eu criei outra biblioteca em cima do AnyIO, como uma fina camada acima, para melhorar um pouco as anotações de tipo e obter melhor **autocompletar**, **erros de linha**, etc. Ela também possui uma introdução amigável e um tutorial para ajudar você a **entender** e escrever **seu próprio código async**: Asyncer. Seria particularmente útil se você precisar **combinar código async com código regular** (bloqueador/síncrono). + ### Outras formas de código assíncrono @@ -337,25 +346,25 @@ Essa mesma sintaxe (ou quase a mesma) foi também incluída recentemente em vers Mas antes disso, controlar código assíncrono era bem mais complexo e difícil. -Nas versões anteriores do Python, você poderia utilizar threads ou Gevent. Mas o código é um pouco mais complexo de entender, debugar, e pensar sobre. +Nas versões anteriores do Python, você poderia utilizar threads ou Gevent. Mas o código é bem mais complexo de entender, debugar, e pensar sobre. -Nas versões anteriores do NodeJS / Navegador JavaScript, você poderia utilizar "callbacks". O que leva ao inferno do callback. +Nas versões anteriores do NodeJS / Navegador JavaScript, você utilizaria "callbacks". O que leva ao inferno do callback. ## Corrotinas -**Corrotina** é apenas um jeito bonitinho para a coisa que é retornada de uma função `async def`. O Python sabe que é uma função que pode começar e terminar em algum ponto, mas que pode ser pausada internamente também, sempre que tiver um `await` dentro dela. +**Corrotina** é apenas um jeito bonitinho para a coisa que é retornada de uma função `async def`. O Python sabe que é algo como uma função, que pode começar e que vai terminar em algum ponto, mas que pode ser pausada ⏸ internamente também, sempre que tiver um `await` dentro dela. -Mas toda essa funcionalidade de código assíncrono com `async` e `await` é muitas vezes resumida como "corrotina". É comparável ao principal recurso chave do Go, a "Gorotina". +Mas toda essa funcionalidade de código assíncrono com `async` e `await` é muitas vezes resumida como usando "corrotinas". É comparável ao principal recurso chave do Go, a "Gorrotina". ## Conclusão -Vamos ver a mesma frase com o conteúdo cima: +Vamos ver a mesma frase de cima: -> Versões modernas do Python tem suporte para **"código assíncrono"** usando algo chamado **"corrotinas"**, com sintaxe **`async` e `await`**. +> Versões modernas do Python têm suporte para **"código assíncrono"** usando algo chamado **"corrotinas"**, com sintaxe **`async` e `await`**. -Isso pode fazer mais sentido agora. +Isso pode fazer mais sentido agora. ✨ -Tudo isso é o que deixa o FastAPI poderoso (através do Starlette) e que o faz ter uma performance impressionante. +Tudo isso é o que empodera o FastAPI (através do Starlette) e que o faz ter uma performance tão impressionante. ## Detalhes muito técnicos @@ -365,25 +374,25 @@ Você pode provavelmente pular isso. Esses são detalhes muito técnicos de como **FastAPI** funciona por baixo do capô. -Se você tem algum conhecimento técnico (corrotinas, threads, blocking etc) e está curioso sobre como o FastAPI controla o `async def` vs normal `def`, vá em frente. +Se você tem certo conhecimento técnico (corrotinas, threads, blocking etc) e está curioso sobre como o FastAPI controla o `async def` vs normal `def`, vá em frente. /// ### Funções de operação de rota -Quando você declara uma *função de operação de rota* com `def` normal ao invés de `async def`, ela é rodada em uma threadpool externa que então é aguardada, ao invés de ser chamada diretamente (ela poderia bloquear o servidor). +Quando você declara uma *função de operação de rota* com `def` normal ao invés de `async def`, ela é rodada em uma threadpool externa que é então aguardada, ao invés de ser chamada diretamente (já que ela bloquearia o servidor). -Se você está chegando de outro framework assíncrono que não faz o trabalho descrito acima e você está acostumado a definir triviais *funções de operação de rota* com simples `def` para ter um mínimo ganho de performance (cerca de 100 nanosegundos), por favor observe que no **FastAPI** o efeito pode ser bem o oposto. Nesses casos, é melhor usar `async def` a menos que suas *funções de operação de rota* utilizem código que performem bloqueamento IO. +Se você está chegando de outro framework assíncrono que não funciona como descrito acima e você está acostumado a definir *funções de operação de rota* triviais somente de computação com simples `def` para ter um mínimo ganho de performance (cerca de 100 nanosegundos), por favor observe que no **FastAPI** o efeito pode ser bem o oposto. Nesses casos, é melhor usar `async def` a menos que suas *funções de operação de rota* utilizem código que performe bloqueamento IO. -Ainda, em ambas as situações, as chances são que o **FastAPI** será [ainda mais rápido](index.md#performance){.internal-link target=_blank} do que (ou ao menos comparável a) seus frameworks antecessores. +Ainda, em ambas as situações, as chances são que o **FastAPI** [ainda será mais rápido](index.md#performance){.internal-link target=_blank} do que (ou ao menos comparável a) seu framework anterior. ### Dependências -O mesmo se aplica para as dependências. Se uma dependência tem as funções com padrão `def` ao invés de `async def`, ela é rodada no threadpool externo. +O mesmo se aplica para as [dependências](tutorial/dependencies/index.md){.internal-link target=_blank}. Se uma dependência tem as funções com padrão `def` ao invés de `async def`, ela é rodada no threadpool externo. ### Sub-dependências -Você pode ter múltiplas dependências e sub-dependências exigindo uma a outra (como parâmetros de definições de funções), algumas delas podem ser criadas com `async def` e algumas com `def` normal. Isso ainda poderia funcionar, e aquelas criadas com `def` podem ser chamadas em uma thread externa ao invés de serem "aguardadas". +Você pode ter múltiplas dependências e [sub-dependências](tutorial/dependencies/sub-dependencies.md){.internal-link target=_blank} requisitando uma à outra (como parâmetros de definições de funções), algumas delas podem ser criadas com `async def` e algumas com `def` normal. Isso ainda funcionaria, e aquelas criadas com `def` normal seriam chamadas em uma thread externa (do threadpool) ao invés de serem "aguardadas". ### Outras funções de utilidade @@ -395,6 +404,6 @@ Se sua função de utilidade é uma função normal com `def`, ela será chamada --- -Novamente, esses são detalhes muito técnicos que provavelmente possam ser úteis caso você esteja procurando por eles. +Novamente, esses são detalhes muito técnicos que provavelmente seriam úteis caso você esteja procurando por eles. Caso contrário, você deve ficar bem com as dicas da seção acima: Com pressa?. From 89b4d1f076be7f7b30447344ef33cc895dade875 Mon Sep 17 00:00:00 2001 From: github-actions Date: Sat, 26 Jul 2025 11:17:02 +0000 Subject: [PATCH 10/60] =?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 d5730e247..a6a68584a 100644 --- a/docs/en/docs/release-notes.md +++ b/docs/en/docs/release-notes.md @@ -9,6 +9,7 @@ hide: ### Translations +* 🌐 Update Portuguese Translation for `docs/pt/docs/async.md`. PR [#13863](https://github.com/fastapi/fastapi/pull/13863) by [@EdmilsonRodrigues](https://github.com/EdmilsonRodrigues). * 📝 Fix highlight line in `docs/ja/docs/tutorial/body.md`. PR [#13927](https://github.com/fastapi/fastapi/pull/13927) by [@KoyoMiyazaki](https://github.com/KoyoMiyazaki). * 🌐 Add Persian translation for `docs/fa/docs/environment-variables.md`. PR [#13923](https://github.com/fastapi/fastapi/pull/13923) by [@Mohammad222PR](https://github.com/Mohammad222PR). * 🌐 Add Persian translation for `docs/fa/docs/python-types.md`. PR [#13524](https://github.com/fastapi/fastapi/pull/13524) by [@Mohammad222PR](https://github.com/Mohammad222PR). From 3d60b5e23e878ca28e823fa65b06d67de95a6588 Mon Sep 17 00:00:00 2001 From: Alejandra <90076947+alejsdev@users.noreply.github.com> Date: Sat, 26 Jul 2025 13:35:42 +0200 Subject: [PATCH 11/60] =?UTF-8?q?=F0=9F=93=9D=20Add=20discussion=20templat?= =?UTF-8?q?e=20for=20new=20language=20translation=20requests=20(#13535)?= 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> Co-authored-by: Sebastián Ramírez --- .github/DISCUSSION_TEMPLATE/translations.yml | 45 ++++++++++++++++++++ docs/en/docs/contributing.md | 37 +++++++++++----- 2 files changed, 72 insertions(+), 10 deletions(-) create mode 100644 .github/DISCUSSION_TEMPLATE/translations.yml diff --git a/.github/DISCUSSION_TEMPLATE/translations.yml b/.github/DISCUSSION_TEMPLATE/translations.yml new file mode 100644 index 000000000..16e304d99 --- /dev/null +++ b/.github/DISCUSSION_TEMPLATE/translations.yml @@ -0,0 +1,45 @@ +labels: [lang-all] +body: + - type: markdown + attributes: + value: | + Thanks for your interest in helping translate the FastAPI docs! 🌍 + + Please follow these instructions carefully to propose a new language translation. 🙏 + + This structured process helps ensure translations can be properly maintained long-term. + - type: checkboxes + id: checks + attributes: + label: Initial Checks + description: Please confirm and check all the following options. + options: + - label: I checked that this language is not already being translated in FastAPI docs. + required: true + - label: I searched existing discussions to ensure no one else proposed this language. + required: true + - label: I am a native speaker of the language I want to help translate. + required: true + - type: input + id: language + attributes: + label: Target Language + description: What language do you want to translate the FastAPI docs into? + placeholder: e.g. Latin + validations: + required: true + - type: textarea + id: additional_info + attributes: + label: Additional Information + description: Any other relevant information about your translation proposal + - type: markdown + attributes: + value: | + Translations are automatized with AI and then reviewed by native speakers. 🤖 🙋 + + This allows us to keep them consistent and up-to-date. + + If there are several native speakers commenting on this discussion and + committing to help review new translations, the FastAPI team will review it + and potentially make it an official translation. 😎 diff --git a/docs/en/docs/contributing.md b/docs/en/docs/contributing.md index 91c39c927..2583fd1fb 100644 --- a/docs/en/docs/contributing.md +++ b/docs/en/docs/contributing.md @@ -315,30 +315,47 @@ Now you can translate it all and see how it looks as you save the file. Some of these files are updated very frequently and a translation would always be behind, or they include the main content from English source files, etc. +#### Request a New Language + +Let's say that you want to request translations for a language that is not yet translated, not even some pages. For example, Latin. + +If there is no discussion for that language, you can start by requesting the new language. For that, you can follow these steps: + +* Create a new discussion following the template. +* Get a few native speakers to comment on the discussion and commit to help review translations for that language. + +Once there are several people in the discussion, the FastAPI team can evaluate it and can make it an official translation. + +Then the docs will be automatically translated using AI, and the team of native speakers can review the translation, and help tweak the AI prompts. + +Once there's a new translation, for example if docs are updated or there's a new section, there will be a comment in the same discussion with the link to the new translation to review. + #### New Language -Let's say that you want to add translations for a language that is not yet translated, not even some pages. +/// note -Let's say you want to add translations for Creole, and it's not yet there in the docs. +These steps will be performed by the FastAPI team. + +/// -Checking the link from above, the code for "Creole" is `ht`. +Checking the link from above (List of ISO 639-1 codes), you can see that the 2-letter code for Latin is `la`. -The next step is to run the script to generate a new translation directory: +Now you can create a new directory for the new language, running the following script:
```console // Use the command new-lang, pass the language code as a CLI argument -$ python ./scripts/docs.py new-lang ht +$ python ./scripts/docs.py new-lang la -Successfully initialized: docs/ht +Successfully initialized: docs/la ```
-Now you can check in your code editor the newly created directory `docs/ht/`. +Now you can check in your code editor the newly created directory `docs/la/`. -That command created a file `docs/ht/mkdocs.yml` with a simple config that inherits everything from the `en` version: +That command created a file `docs/la/mkdocs.yml` with a simple config that inherits everything from the `en` version: ```yaml INHERIT: ../en/mkdocs.yml @@ -350,11 +367,11 @@ You could also simply create that file with those contents manually. /// -That command also created a dummy file `docs/ht/index.md` for the main page, you can start by translating that one. +That command also created a dummy file `docs/la/index.md` for the main page, you can start by translating that one. You can continue with the previous instructions for an "Existing Language" for that process. -You can make the first pull request with those two files, `docs/ht/mkdocs.yml` and `docs/ht/index.md`. 🎉 +You can make the first pull request with those two files, `docs/la/mkdocs.yml` and `docs/la/index.md`. 🎉 #### Preview the result From d67f092db84c7c5cb7b882aa1e25c8a10b6727b6 Mon Sep 17 00:00:00 2001 From: github-actions Date: Sat, 26 Jul 2025 11:36:02 +0000 Subject: [PATCH 12/60] =?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 a6a68584a..0e5fa6303 100644 --- a/docs/en/docs/release-notes.md +++ b/docs/en/docs/release-notes.md @@ -7,6 +7,10 @@ hide: ## Latest Changes +### Docs + +* 📝 Add discussion template for new language translation requests. PR [#13535](https://github.com/fastapi/fastapi/pull/13535) by [@alejsdev](https://github.com/alejsdev). + ### Translations * 🌐 Update Portuguese Translation for `docs/pt/docs/async.md`. PR [#13863](https://github.com/fastapi/fastapi/pull/13863) by [@EdmilsonRodrigues](https://github.com/EdmilsonRodrigues). From ae02be90b6857cac1a00ea47c154457effcdcb5d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebasti=C3=A1n=20Ram=C3=ADrez?= Date: Sat, 26 Jul 2025 20:57:50 +0200 Subject: [PATCH 13/60] =?UTF-8?q?=F0=9F=94=A8=20Update=20translations=20sc?= =?UTF-8?q?ript=20to=20remove=20old=20(removed)=20files=20(#13928)?= 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> --- docs/es/llm-prompt.md | 50 ----------------------- scripts/translate.py | 93 +++++++++++++++++++++++++++++++++++++++---- 2 files changed, 86 insertions(+), 57 deletions(-) diff --git a/docs/es/llm-prompt.md b/docs/es/llm-prompt.md index 3340dbc99..936ed9bba 100644 --- a/docs/es/llm-prompt.md +++ b/docs/es/llm-prompt.md @@ -4,56 +4,6 @@ Use the informal grammar (use "tú" instead of "usted"). For instructions or titles in imperative, keep them in imperative, for example "Edit it" to "Edítalo". -There are special blocks of notes, tips and others that look like: - -/// note - -To translate it, keep the same line and add the translation after a vertical bar: - -/// note | Nota - -Some examples: - -Source: - -/// tip - -Result: - -/// tip | Consejo - -Source: - -/// details | Preview - -Result: - -/// details | Vista previa - -Source: - -/// warning - -Result: - -/// warning | Advertencia - -Source: - -/// info - -Result: - -/// info | Información - -Source: - -/// note | Technical Details - -Result: - -/// note | Detalles Técnicos - --- For the next terms, use the following translations: diff --git a/scripts/translate.py b/scripts/translate.py index 9a2136d1b..09533747b 100644 --- a/scripts/translate.py +++ b/scripts/translate.py @@ -5,6 +5,7 @@ from typing import Iterable import typer import yaml from pydantic_ai import Agent +from rich import print non_translated_sections = ( "reference/", @@ -28,8 +29,38 @@ The content is written in markdown, write the translation in markdown as well. D When there's an example of code, the console or a terminal, normally surrounded by triple backticks and a keyword like "console" or "bash" (e.g. ```console), do not translate the content, keep the original in English. The original content will be surrounded by triple percentage signs (%) and you should translate it to the target language. Do not include the triple percentage signs in the translation. + +There are special blocks of notes, tips and others that look like: + +/// note + +To translate it, keep the same line and add the translation after a vertical bar. + +For example, if you were translating to Spanish, you would write: + +/// note | Nota + +Some examples in Spanish: + +Source: + +/// tip + +Result: + +/// tip | Consejo + +Source: + +/// details | Preview + +Result: + +/// details | Vista previa """ +app = typer.Typer() + @lru_cache def get_langs() -> dict[str, str]: @@ -46,6 +77,17 @@ def generate_lang_path(*, lang: str, path: Path) -> Path: return out_path +def generate_en_path(*, lang: str, path: Path) -> Path: + en_docs_path = Path("docs/en/docs") + assert not str(path).startswith(str(en_docs_path)), ( + f"Path must not be inside {en_docs_path}" + ) + lang_docs_path = Path(f"docs/{lang}/docs") + out_path = Path(str(path).replace(str(lang_docs_path), str(en_docs_path))) + return out_path + + +@app.command() def translate_page(*, lang: str, path: Path) -> None: langs = get_langs() language = langs[lang] @@ -68,8 +110,8 @@ def translate_page(*, lang: str, path: Path) -> None: agent = Agent("openai:gpt-4o") prompt_segments = [ - lang_prompt_content, general_prompt, + lang_prompt_content, ] if old_translation: prompt_segments.extend( @@ -119,6 +161,7 @@ def iter_paths_to_translate() -> Iterable[Path]: yield path +@app.command() def translate_all(lang: str) -> None: paths_to_process: list[Path] = [] for path in iter_paths_to_translate(): @@ -151,12 +194,48 @@ def translate_all(lang: str) -> None: print(f"Done translating: {p}") -def main(*, lang: str, path: Path = None) -> None: - if path: - translate_page(lang=lang, path=path) - else: - translate_all(lang=lang) +@app.command() +def list_removable(lang: str) -> list[Path]: + removable_paths: list[Path] = [] + lang_paths = Path(f"docs/{lang}").rglob("*.md") + for path in lang_paths: + en_path = generate_en_path(lang=lang, path=path) + if not en_path.exists(): + removable_paths.append(path) + print(removable_paths) + return removable_paths + + +@app.command() +def list_all_removable() -> list[Path]: + all_removable_paths: list[Path] = [] + langs = get_langs() + for lang in langs: + if lang == "en": + continue + removable_paths = list_removable(lang) + all_removable_paths.extend(removable_paths) + print(all_removable_paths) + return all_removable_paths + + +@app.command() +def remove_removable(lang: str) -> None: + removable_paths = list_removable(lang) + for path in removable_paths: + path.unlink() + print(f"Removed: {path}") + print("Done removing all removable paths") + + +@app.command() +def remove_all_removable() -> None: + all_removable = list_all_removable() + for removable_path in all_removable: + removable_path.unlink() + print(f"Removed: {removable_path}") + print("Done removing all removable paths") if __name__ == "__main__": - typer.run(main) + app() From 4f0aae9d237059c48aace9cc222f62e3ef4f2ee5 Mon Sep 17 00:00:00 2001 From: github-actions Date: Sat, 26 Jul 2025 18:58:14 +0000 Subject: [PATCH 14/60] =?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 0e5fa6303..3b94dfd8f 100644 --- a/docs/en/docs/release-notes.md +++ b/docs/en/docs/release-notes.md @@ -23,6 +23,7 @@ hide: ### Internal +* 🔨 Update translations script to remove old (removed) files. PR [#13928](https://github.com/fastapi/fastapi/pull/13928) by [@tiangolo](https://github.com/tiangolo). * ⬆ [pre-commit.ci] pre-commit autoupdate. PR [#13894](https://github.com/fastapi/fastapi/pull/13894) by [@pre-commit-ci[bot]](https://github.com/apps/pre-commit-ci). * ⬆ Update httpx requirement to >=0.23.0,<0.29.0. PR [#13114](https://github.com/fastapi/fastapi/pull/13114) by [@yan12125](https://github.com/yan12125). * 🔧 Update sponsors: Add Mobb. PR [#13916](https://github.com/fastapi/fastapi/pull/13916) by [@tiangolo](https://github.com/tiangolo). From adc328e258d00c5717070a103626cb48a03abecf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebasti=C3=A1n=20Ram=C3=ADrez?= Date: Sat, 26 Jul 2025 23:19:05 +0200 Subject: [PATCH 15/60] =?UTF-8?q?=F0=9F=94=A8=20Refactor=20translate=20scr?= =?UTF-8?q?ipt=20with=20extra=20feedback=20(prints)=20(#13932)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- scripts/translate.py | 20 +++++++++++++------- 1 file changed, 13 insertions(+), 7 deletions(-) diff --git a/scripts/translate.py b/scripts/translate.py index 09533747b..6af12dc98 100644 --- a/scripts/translate.py +++ b/scripts/translate.py @@ -106,7 +106,9 @@ def translate_page(*, lang: str, path: Path) -> None: original_content = path.read_text() old_translation: str | None = None if out_path.exists(): + print(f"Found existing translation: {out_path}") old_translation = out_path.read_text() + print(f"Translating {path} to {lang} ({language})") agent = Agent("openai:gpt-4o") prompt_segments = [ @@ -131,13 +133,14 @@ def translate_page(*, lang: str, path: Path) -> None: ] ) prompt = "\n\n".join(prompt_segments) - + print(f"Running agent for {out_path}") result = agent.run_sync(prompt) out_content = f"{result.data.strip()}\n" + print(f"Saving translation to {out_path}") out_path.write_text(out_content) -def iter_paths_to_translate() -> Iterable[Path]: +def iter_all_en_paths() -> Iterable[Path]: """ Iterate on the markdown files to translate in order of priority. """ @@ -161,13 +164,16 @@ def iter_paths_to_translate() -> Iterable[Path]: yield path -@app.command() -def translate_all(lang: str) -> None: - paths_to_process: list[Path] = [] - for path in iter_paths_to_translate(): +def iter_en_paths_to_translate() -> Iterable[Path]: + for path in iter_all_en_paths(): if str(path).replace("docs/en/docs/", "").startswith(non_translated_sections): continue - paths_to_process.append(path) + yield path + + +@app.command() +def translate_all(lang: str) -> None: + paths_to_process = list(iter_en_paths_to_translate()) print("Original paths:") for p in paths_to_process: print(f" - {p}") From 4c40b484f1a6ecea0921dc58292c3f733ddf5d9b Mon Sep 17 00:00:00 2001 From: github-actions Date: Sat, 26 Jul 2025 21:19:29 +0000 Subject: [PATCH 16/60] =?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 3b94dfd8f..56c325977 100644 --- a/docs/en/docs/release-notes.md +++ b/docs/en/docs/release-notes.md @@ -23,6 +23,7 @@ hide: ### Internal +* 🔨 Refactor translate script with extra feedback (prints). PR [#13932](https://github.com/fastapi/fastapi/pull/13932) by [@tiangolo](https://github.com/tiangolo). * 🔨 Update translations script to remove old (removed) files. PR [#13928](https://github.com/fastapi/fastapi/pull/13928) by [@tiangolo](https://github.com/tiangolo). * ⬆ [pre-commit.ci] pre-commit autoupdate. PR [#13894](https://github.com/fastapi/fastapi/pull/13894) by [@pre-commit-ci[bot]](https://github.com/apps/pre-commit-ci). * ⬆ Update httpx requirement to >=0.23.0,<0.29.0. PR [#13114](https://github.com/fastapi/fastapi/pull/13114) by [@yan12125](https://github.com/yan12125). From 273b06adab5fd527492ff9ed3f98cfa653d10002 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebasti=C3=A1n=20Ram=C3=ADrez?= Date: Sat, 26 Jul 2025 23:27:35 +0200 Subject: [PATCH 17/60] =?UTF-8?q?=E2=9A=92=EF=B8=8F=20Update=20translate?= =?UTF-8?q?=20script,=20show=20and=20update=20outdated=20translations=20(#?= =?UTF-8?q?13933)?= 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> --- requirements-translations.txt | 1 + scripts/translate.py | 35 +++++++++++++++++++++++++++++++++++ 2 files changed, 36 insertions(+) diff --git a/requirements-translations.txt b/requirements-translations.txt index 7a2a8004e..90f718032 100644 --- a/requirements-translations.txt +++ b/requirements-translations.txt @@ -1 +1,2 @@ pydantic-ai==0.0.30 +GitPython==3.1.45 diff --git a/scripts/translate.py b/scripts/translate.py index 6af12dc98..b78d7211b 100644 --- a/scripts/translate.py +++ b/scripts/translate.py @@ -2,6 +2,7 @@ from functools import lru_cache from pathlib import Path from typing import Iterable +import git import typer import yaml from pydantic_ai import Agent @@ -243,5 +244,39 @@ def remove_all_removable() -> None: print("Done removing all removable paths") +@app.command() +def list_outdated(lang: str) -> list[Path]: + dir_path = Path(__file__).absolute().parent.parent + repo = git.Repo(dir_path) + + outdated_paths: list[Path] = [] + en_lang_paths = list(iter_en_paths_to_translate()) + for path in en_lang_paths: + lang_path = generate_lang_path(lang=lang, path=path) + if not lang_path.exists(): + outdated_paths.append(path) + continue + en_commit_datetime = list(repo.iter_commits(paths=path, max_count=1))[ + 0 + ].committed_datetime + lang_commit_datetime = list(repo.iter_commits(paths=lang_path, max_count=1))[ + 0 + ].committed_datetime + if lang_commit_datetime < en_commit_datetime: + outdated_paths.append(path) + print(outdated_paths) + return outdated_paths + + +@app.command() +def update_outdated(lang: str) -> None: + outdated_paths = list_outdated(lang) + for path in outdated_paths: + print(f"Updating lang: {lang} path: {path}") + translate_page(lang=lang, path=path) + print(f"Done updating: {path}") + print("Done updating all outdated paths") + + if __name__ == "__main__": app() From d5d302c3da11262f4e320a9af5dbb9d13386e1b5 Mon Sep 17 00:00:00 2001 From: github-actions Date: Sat, 26 Jul 2025 21:27:58 +0000 Subject: [PATCH 18/60] =?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 56c325977..f3984fa9e 100644 --- a/docs/en/docs/release-notes.md +++ b/docs/en/docs/release-notes.md @@ -23,6 +23,7 @@ hide: ### Internal +* ⚒️ Update translate script, show and update outdated translations. PR [#13933](https://github.com/fastapi/fastapi/pull/13933) by [@tiangolo](https://github.com/tiangolo). * 🔨 Refactor translate script with extra feedback (prints). PR [#13932](https://github.com/fastapi/fastapi/pull/13932) by [@tiangolo](https://github.com/tiangolo). * 🔨 Update translations script to remove old (removed) files. PR [#13928](https://github.com/fastapi/fastapi/pull/13928) by [@tiangolo](https://github.com/tiangolo). * ⬆ [pre-commit.ci] pre-commit autoupdate. PR [#13894](https://github.com/fastapi/fastapi/pull/13894) by [@pre-commit-ci[bot]](https://github.com/apps/pre-commit-ci). From 6516a6c4a60c91de881cc73c40a3c609001dd29c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebasti=C3=A1n=20Ram=C3=ADrez?= Date: Sun, 27 Jul 2025 21:12:19 +0200 Subject: [PATCH 19/60] =?UTF-8?q?=F0=9F=91=B7=20Add=20CI=20to=20translate?= =?UTF-8?q?=20with=20LLMs=20(#13937)?= 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> --- .github/workflows/translate.yml | 77 ++++++++++++++++++++++++++ scripts/translate.py | 96 +++++++++++++++++++++++++++++---- 2 files changed, 162 insertions(+), 11 deletions(-) create mode 100644 .github/workflows/translate.yml diff --git a/.github/workflows/translate.yml b/.github/workflows/translate.yml new file mode 100644 index 000000000..edbff6fe5 --- /dev/null +++ b/.github/workflows/translate.yml @@ -0,0 +1,77 @@ +name: Translate + +on: + workflow_dispatch: + inputs: + debug_enabled: + description: Run with tmate debugging enabled (https://github.com/marketplace/actions/debugging-with-tmate) + required: false + default: "false" + command: + description: Command to run + type: choice + options: + - translate-page + - translate-lang + - update-outdated + - add-missing + - update-and-add + - remove-all-removable + lang: + description: Language to translate to as a letter code (e.g. "es" for Spanish) + type: string + required: false + default: "" + en_path: + description: File path in English to translate (e.g. docs/en/docs/index.md) + type: string + required: false + default: "" + +env: + UV_SYSTEM_PYTHON: 1 + +jobs: + job: + if: github.repository_owner == 'fastapi' + runs-on: ubuntu-latest + permissions: + contents: write + steps: + - name: Dump GitHub context + env: + GITHUB_CONTEXT: ${{ toJson(github) }} + run: echo "$GITHUB_CONTEXT" + - uses: actions/checkout@v4 + - name: Set up Python + uses: actions/setup-python@v5 + with: + python-version: "3.11" + - name: Setup uv + uses: astral-sh/setup-uv@v6 + with: + version: "0.4.15" + enable-cache: true + cache-dependency-glob: | + requirements**.txt + pyproject.toml + - name: Install Dependencies + run: uv pip install -r requirements-github-actions.txt -r requirements-translations.txt + # Allow debugging with tmate + - name: Setup tmate session + uses: mxschmitt/action-tmate@v3 + if: ${{ github.event_name == 'workflow_dispatch' && github.event.inputs.debug_enabled == 'true' }} + with: + limit-access-to-actor: true + env: + GITHUB_TOKEN: ${{ secrets.FASTAPI_TRANSLATIONS }} + OPENAI_API_KEY: ${{ secrets.OPENAI_API_KEY }} + - name: FastAPI Translate + run: | + python ./scripts/translate.py ${{ github.event.inputs.command }} + python ./scripts/translate.py make-pr + env: + GITHUB_TOKEN: ${{ secrets.FASTAPI_TRANSLATIONS }} + OPENAI_API_KEY: ${{ secrets.OPENAI_API_KEY }} + LANG: ${{ github.event.inputs.lang }} + EN_PATH: ${{ github.event.inputs.en_path }} diff --git a/scripts/translate.py b/scripts/translate.py index b78d7211b..5fdbe7220 100644 --- a/scripts/translate.py +++ b/scripts/translate.py @@ -1,10 +1,13 @@ +import secrets +import subprocess from functools import lru_cache from pathlib import Path -from typing import Iterable +from typing import Annotated, Iterable import git import typer import yaml +from github import Github from pydantic_ai import Agent from rich import print @@ -89,7 +92,11 @@ def generate_en_path(*, lang: str, path: Path) -> Path: @app.command() -def translate_page(*, lang: str, path: Path) -> None: +def translate_page( + *, + lang: Annotated[str, typer.Option(envvar="LANG")], + en_path: Annotated[Path, typer.Option(envvar="EN_PATH")], +) -> None: langs = get_langs() language = langs[lang] lang_path = Path(f"docs/{lang}") @@ -99,17 +106,17 @@ def translate_page(*, lang: str, path: Path) -> None: lang_prompt_content = lang_prompt_path.read_text() en_docs_path = Path("docs/en/docs") - assert str(path).startswith(str(en_docs_path)), ( + assert str(en_path).startswith(str(en_docs_path)), ( f"Path must be inside {en_docs_path}" ) - out_path = generate_lang_path(lang=lang, path=path) + out_path = generate_lang_path(lang=lang, path=en_path) out_path.parent.mkdir(parents=True, exist_ok=True) - original_content = path.read_text() + original_content = en_path.read_text() old_translation: str | None = None if out_path.exists(): print(f"Found existing translation: {out_path}") old_translation = out_path.read_text() - print(f"Translating {path} to {lang} ({language})") + print(f"Translating {en_path} to {lang} ({language})") agent = Agent("openai:gpt-4o") prompt_segments = [ @@ -173,7 +180,7 @@ def iter_en_paths_to_translate() -> Iterable[Path]: @app.command() -def translate_all(lang: str) -> None: +def translate_lang(lang: Annotated[str, typer.Option(envvar="LANG")]) -> None: paths_to_process = list(iter_en_paths_to_translate()) print("Original paths:") for p in paths_to_process: @@ -197,7 +204,7 @@ def translate_all(lang: str) -> None: print(f"Total paths to process: {len(missing_paths)}") for p in missing_paths: print(f"Translating: {p}") - translate_page(lang="es", path=p) + translate_page(lang="es", en_path=p) print(f"Done translating: {p}") @@ -244,6 +251,18 @@ def remove_all_removable() -> None: print("Done removing all removable paths") +@app.command() +def list_missing(lang: str) -> list[Path]: + missing_paths: list[Path] = [] + en_lang_paths = list(iter_en_paths_to_translate()) + for path in en_lang_paths: + lang_path = generate_lang_path(lang=lang, path=path) + if not lang_path.exists(): + missing_paths.append(path) + print(missing_paths) + return missing_paths + + @app.command() def list_outdated(lang: str) -> list[Path]: dir_path = Path(__file__).absolute().parent.parent @@ -254,7 +273,6 @@ def list_outdated(lang: str) -> list[Path]: for path in en_lang_paths: lang_path = generate_lang_path(lang=lang, path=path) if not lang_path.exists(): - outdated_paths.append(path) continue en_commit_datetime = list(repo.iter_commits(paths=path, max_count=1))[ 0 @@ -269,14 +287,70 @@ def list_outdated(lang: str) -> list[Path]: @app.command() -def update_outdated(lang: str) -> None: +def update_outdated(lang: Annotated[str, typer.Option(envvar="LANG")]) -> None: outdated_paths = list_outdated(lang) for path in outdated_paths: print(f"Updating lang: {lang} path: {path}") - translate_page(lang=lang, path=path) + translate_page(lang=lang, en_path=path) print(f"Done updating: {path}") print("Done updating all outdated paths") +@app.command() +def add_missing(lang: Annotated[str, typer.Option(envvar="LANG")]) -> None: + missing_paths = list_missing(lang) + for path in missing_paths: + print(f"Adding lang: {lang} path: {path}") + translate_page(lang=lang, en_path=path) + print(f"Done adding: {path}") + print("Done adding all missing paths") + + +@app.command() +def update_and_add(lang: Annotated[str, typer.Option(envvar="LANG")]) -> None: + print(f"Updating outdated translations for {lang}") + update_outdated(lang=lang) + print(f"Adding missing translations for {lang}") + add_missing(lang=lang) + print(f"Done updating and adding for {lang}") + + +@app.command() +def make_pr( + *, + lang: Annotated[str, typer.Option(envvar="LANG")], + github_token: Annotated[str, typer.Option(envvar="GITHUB_TOKEN")], + github_repository: Annotated[str, typer.Option(envvar="GITHUB_REPOSITORY")], +) -> None: + print("Setting up GitHub Actions git user") + repo = git.Repo(Path(__file__).absolute().parent.parent) + if not repo.is_dirty(untracked_files=True): + print("Repository is clean, no changes to commit") + return + subprocess.run(["git", "config", "user.name", "github-actions"], check=True) + subprocess.run( + ["git", "config", "user.email", "github-actions@github.com"], check=True + ) + branch_name = f"translate-{lang}-{secrets.token_hex(4)}" + print(f"Creating a new branch {branch_name}") + subprocess.run(["git", "checkout", "-b", branch_name], check=True) + print("Adding updated files") + lang_path = Path(f"docs/{lang}") + subprocess.run(["git", "add", str(lang_path)], check=True) + print("Committing updated file") + message = f"🌐 Update translations - {lang}" + subprocess.run(["git", "commit", "-m", message], check=True) + print("Pushing branch") + subprocess.run(["git", "push", "origin", branch_name], check=True) + print("Creating PR") + g = Github(github_token) + gh_repo = g.get_repo(github_repository) + pr = gh_repo.create_pull( + title=message, body=message, base="master", head=branch_name + ) + print(f"Created PR: {pr.number}") + print("Finished") + + if __name__ == "__main__": app() From c74e7d1ce45ddd39e5bf364aa20662855626de14 Mon Sep 17 00:00:00 2001 From: github-actions Date: Sun, 27 Jul 2025 19:12:39 +0000 Subject: [PATCH 20/60] =?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 f3984fa9e..f7fec547a 100644 --- a/docs/en/docs/release-notes.md +++ b/docs/en/docs/release-notes.md @@ -23,6 +23,7 @@ hide: ### Internal +* 👷 Add CI to translate with LLMs. PR [#13937](https://github.com/fastapi/fastapi/pull/13937) by [@tiangolo](https://github.com/tiangolo). * ⚒️ Update translate script, show and update outdated translations. PR [#13933](https://github.com/fastapi/fastapi/pull/13933) by [@tiangolo](https://github.com/tiangolo). * 🔨 Refactor translate script with extra feedback (prints). PR [#13932](https://github.com/fastapi/fastapi/pull/13932) by [@tiangolo](https://github.com/tiangolo). * 🔨 Update translations script to remove old (removed) files. PR [#13928](https://github.com/fastapi/fastapi/pull/13928) by [@tiangolo](https://github.com/tiangolo). From 9aab3d9e2239c51628f580eff442b630bd165d31 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebasti=C3=A1n=20Ram=C3=ADrez?= Date: Mon, 28 Jul 2025 01:51:53 +0200 Subject: [PATCH 21/60] =?UTF-8?q?=E2=9A=92=EF=B8=8F=20Tweak=20translate=20?= =?UTF-8?q?script=20and=20CI=20(#13939)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .github/workflows/translate.yml | 4 +- scripts/translate.py | 79 ++++++++++++++++++--------------- 2 files changed, 44 insertions(+), 39 deletions(-) diff --git a/.github/workflows/translate.yml b/.github/workflows/translate.yml index edbff6fe5..fc6b4d730 100644 --- a/.github/workflows/translate.yml +++ b/.github/workflows/translate.yml @@ -17,7 +17,7 @@ on: - add-missing - update-and-add - remove-all-removable - lang: + language: description: Language to translate to as a letter code (e.g. "es" for Spanish) type: string required: false @@ -73,5 +73,5 @@ jobs: env: GITHUB_TOKEN: ${{ secrets.FASTAPI_TRANSLATIONS }} OPENAI_API_KEY: ${{ secrets.OPENAI_API_KEY }} - LANG: ${{ github.event.inputs.lang }} + LANGUAGE: ${{ github.event.inputs.language }} EN_PATH: ${{ github.event.inputs.en_path }} diff --git a/scripts/translate.py b/scripts/translate.py index 5fdbe7220..e18449685 100644 --- a/scripts/translate.py +++ b/scripts/translate.py @@ -94,12 +94,12 @@ def generate_en_path(*, lang: str, path: Path) -> Path: @app.command() def translate_page( *, - lang: Annotated[str, typer.Option(envvar="LANG")], + language: Annotated[str, typer.Option(envvar="LANGUAGE")], en_path: Annotated[Path, typer.Option(envvar="EN_PATH")], ) -> None: langs = get_langs() - language = langs[lang] - lang_path = Path(f"docs/{lang}") + language_name = langs[language] + lang_path = Path(f"docs/{language}") lang_path.mkdir(exist_ok=True) lang_prompt_path = lang_path / "llm-prompt.md" assert lang_prompt_path.exists(), f"Prompt file not found: {lang_prompt_path}" @@ -109,14 +109,14 @@ def translate_page( assert str(en_path).startswith(str(en_docs_path)), ( f"Path must be inside {en_docs_path}" ) - out_path = generate_lang_path(lang=lang, path=en_path) + out_path = generate_lang_path(lang=language, path=en_path) out_path.parent.mkdir(parents=True, exist_ok=True) original_content = en_path.read_text() old_translation: str | None = None if out_path.exists(): print(f"Found existing translation: {out_path}") old_translation = out_path.read_text() - print(f"Translating {en_path} to {lang} ({language})") + print(f"Translating {en_path} to {language} ({language_name})") agent = Agent("openai:gpt-4o") prompt_segments = [ @@ -135,7 +135,7 @@ def translate_page( ) prompt_segments.extend( [ - f"Translate to {language} ({lang}).", + f"Translate to {language} ({language_name}).", "Original content:", f"%%%\n{original_content}%%%", ] @@ -180,7 +180,7 @@ def iter_en_paths_to_translate() -> Iterable[Path]: @app.command() -def translate_lang(lang: Annotated[str, typer.Option(envvar="LANG")]) -> None: +def translate_lang(language: Annotated[str, typer.Option(envvar="LANGUAGE")]) -> None: paths_to_process = list(iter_en_paths_to_translate()) print("Original paths:") for p in paths_to_process: @@ -189,7 +189,7 @@ def translate_lang(lang: Annotated[str, typer.Option(envvar="LANG")]) -> None: missing_paths: list[Path] = [] skipped_paths: list[Path] = [] for p in paths_to_process: - lang_path = generate_lang_path(lang=lang, path=p) + lang_path = generate_lang_path(lang=language, path=p) if lang_path.exists(): skipped_paths.append(p) continue @@ -204,16 +204,16 @@ def translate_lang(lang: Annotated[str, typer.Option(envvar="LANG")]) -> None: print(f"Total paths to process: {len(missing_paths)}") for p in missing_paths: print(f"Translating: {p}") - translate_page(lang="es", en_path=p) + translate_page(language="es", en_path=p) print(f"Done translating: {p}") @app.command() -def list_removable(lang: str) -> list[Path]: +def list_removable(language: str) -> list[Path]: removable_paths: list[Path] = [] - lang_paths = Path(f"docs/{lang}").rglob("*.md") + lang_paths = Path(f"docs/{language}").rglob("*.md") for path in lang_paths: - en_path = generate_en_path(lang=lang, path=path) + en_path = generate_en_path(lang=language, path=path) if not en_path.exists(): removable_paths.append(path) print(removable_paths) @@ -234,8 +234,8 @@ def list_all_removable() -> list[Path]: @app.command() -def remove_removable(lang: str) -> None: - removable_paths = list_removable(lang) +def remove_removable(language: str) -> None: + removable_paths = list_removable(language) for path in removable_paths: path.unlink() print(f"Removed: {path}") @@ -252,11 +252,11 @@ def remove_all_removable() -> None: @app.command() -def list_missing(lang: str) -> list[Path]: +def list_missing(language: str) -> list[Path]: missing_paths: list[Path] = [] en_lang_paths = list(iter_en_paths_to_translate()) for path in en_lang_paths: - lang_path = generate_lang_path(lang=lang, path=path) + lang_path = generate_lang_path(lang=language, path=path) if not lang_path.exists(): missing_paths.append(path) print(missing_paths) @@ -264,14 +264,14 @@ def list_missing(lang: str) -> list[Path]: @app.command() -def list_outdated(lang: str) -> list[Path]: +def list_outdated(language: str) -> list[Path]: dir_path = Path(__file__).absolute().parent.parent repo = git.Repo(dir_path) outdated_paths: list[Path] = [] en_lang_paths = list(iter_en_paths_to_translate()) for path in en_lang_paths: - lang_path = generate_lang_path(lang=lang, path=path) + lang_path = generate_lang_path(lang=language, path=path) if not lang_path.exists(): continue en_commit_datetime = list(repo.iter_commits(paths=path, max_count=1))[ @@ -287,38 +287,38 @@ def list_outdated(lang: str) -> list[Path]: @app.command() -def update_outdated(lang: Annotated[str, typer.Option(envvar="LANG")]) -> None: - outdated_paths = list_outdated(lang) +def update_outdated(language: Annotated[str, typer.Option(envvar="LANGUAGE")]) -> None: + outdated_paths = list_outdated(language) for path in outdated_paths: - print(f"Updating lang: {lang} path: {path}") - translate_page(lang=lang, en_path=path) + print(f"Updating lang: {language} path: {path}") + translate_page(language=language, en_path=path) print(f"Done updating: {path}") print("Done updating all outdated paths") @app.command() -def add_missing(lang: Annotated[str, typer.Option(envvar="LANG")]) -> None: - missing_paths = list_missing(lang) +def add_missing(language: Annotated[str, typer.Option(envvar="LANGUAGE")]) -> None: + missing_paths = list_missing(language) for path in missing_paths: - print(f"Adding lang: {lang} path: {path}") - translate_page(lang=lang, en_path=path) + print(f"Adding lang: {language} path: {path}") + translate_page(language=language, en_path=path) print(f"Done adding: {path}") print("Done adding all missing paths") @app.command() -def update_and_add(lang: Annotated[str, typer.Option(envvar="LANG")]) -> None: - print(f"Updating outdated translations for {lang}") - update_outdated(lang=lang) - print(f"Adding missing translations for {lang}") - add_missing(lang=lang) - print(f"Done updating and adding for {lang}") +def update_and_add(language: Annotated[str, typer.Option(envvar="LANGUAGE")]) -> None: + print(f"Updating outdated translations for {language}") + update_outdated(language=language) + print(f"Adding missing translations for {language}") + add_missing(language=language) + print(f"Done updating and adding for {language}") @app.command() def make_pr( *, - lang: Annotated[str, typer.Option(envvar="LANG")], + language: Annotated[str | None, typer.Option(envvar="LANGUAGE")] = None, github_token: Annotated[str, typer.Option(envvar="GITHUB_TOKEN")], github_repository: Annotated[str, typer.Option(envvar="GITHUB_REPOSITORY")], ) -> None: @@ -331,14 +331,19 @@ def make_pr( subprocess.run( ["git", "config", "user.email", "github-actions@github.com"], check=True ) - branch_name = f"translate-{lang}-{secrets.token_hex(4)}" + branch_name = "translate" + if language: + branch_name += f"-{language}" + branch_name += f"-{secrets.token_hex(4)}" print(f"Creating a new branch {branch_name}") subprocess.run(["git", "checkout", "-b", branch_name], check=True) print("Adding updated files") - lang_path = Path(f"docs/{lang}") - subprocess.run(["git", "add", str(lang_path)], check=True) + git_path = Path("docs") + subprocess.run(["git", "add", str(git_path)], check=True) print("Committing updated file") - message = f"🌐 Update translations - {lang}" + message = "🌐 Update translations" + if language: + message += f" for {language}" subprocess.run(["git", "commit", "-m", message], check=True) print("Pushing branch") subprocess.run(["git", "push", "origin", branch_name], check=True) From c6566716092b1d98eb5cb1b6827b98b3d378ed8a Mon Sep 17 00:00:00 2001 From: github-actions Date: Sun, 27 Jul 2025 23:52:18 +0000 Subject: [PATCH 22/60] =?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 f7fec547a..c7af5d6fa 100644 --- a/docs/en/docs/release-notes.md +++ b/docs/en/docs/release-notes.md @@ -23,6 +23,7 @@ hide: ### Internal +* ⚒️ Tweak translate script and CI. PR [#13939](https://github.com/fastapi/fastapi/pull/13939) by [@tiangolo](https://github.com/tiangolo). * 👷 Add CI to translate with LLMs. PR [#13937](https://github.com/fastapi/fastapi/pull/13937) by [@tiangolo](https://github.com/tiangolo). * ⚒️ Update translate script, show and update outdated translations. PR [#13933](https://github.com/fastapi/fastapi/pull/13933) by [@tiangolo](https://github.com/tiangolo). * 🔨 Refactor translate script with extra feedback (prints). PR [#13932](https://github.com/fastapi/fastapi/pull/13932) by [@tiangolo](https://github.com/tiangolo). From 616106ca7686821860c5f4d947cf2a9896bc1225 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Mon, 28 Jul 2025 22:17:52 +0200 Subject: [PATCH 23/60] =?UTF-8?q?=E2=AC=86=20[pre-commit.ci]=20pre-commit?= =?UTF-8?q?=20autoupdate=20(#13943)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit updates: - [github.com/astral-sh/ruff-pre-commit: v0.12.4 → v0.12.5](https://github.com/astral-sh/ruff-pre-commit/compare/v0.12.4...v0.12.5) 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 e461b0133..0f882b221 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.12.4 + rev: v0.12.5 hooks: - id: ruff args: From 7b2631a88d69ca651d0cf270cde542ec880ae107 Mon Sep 17 00:00:00 2001 From: github-actions Date: Mon, 28 Jul 2025 20:18:19 +0000 Subject: [PATCH 24/60] =?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 c7af5d6fa..bd8ebf16c 100644 --- a/docs/en/docs/release-notes.md +++ b/docs/en/docs/release-notes.md @@ -23,6 +23,7 @@ hide: ### Internal +* ⬆ [pre-commit.ci] pre-commit autoupdate. PR [#13943](https://github.com/fastapi/fastapi/pull/13943) by [@pre-commit-ci[bot]](https://github.com/apps/pre-commit-ci). * ⚒️ Tweak translate script and CI. PR [#13939](https://github.com/fastapi/fastapi/pull/13939) by [@tiangolo](https://github.com/tiangolo). * 👷 Add CI to translate with LLMs. PR [#13937](https://github.com/fastapi/fastapi/pull/13937) by [@tiangolo](https://github.com/tiangolo). * ⚒️ Update translate script, show and update outdated translations. PR [#13933](https://github.com/fastapi/fastapi/pull/13933) by [@tiangolo](https://github.com/tiangolo). From b40acb83c9023af2e52e9b31e63b54db3793447d Mon Sep 17 00:00:00 2001 From: Motov Yurii <109919500+YuriiMotov@users.noreply.github.com> Date: Wed, 30 Jul 2025 18:37:49 +0200 Subject: [PATCH 25/60] =?UTF-8?q?=E2=9A=92=EF=B8=8F=20Update=20translate?= =?UTF-8?q?=20script,=20update=20prompt=20to=20minimize=20generated=20diff?= =?UTF-8?q?=20(#13947)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- scripts/translate.py | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/scripts/translate.py b/scripts/translate.py index e18449685..2fdc18ca0 100644 --- a/scripts/translate.py +++ b/scripts/translate.py @@ -26,6 +26,8 @@ non_translated_sections = ( general_prompt = """ For technical terms in English that don't have a common translation term use the original term in English. +If you have instructions to translate specific terms or phrases in a specific way, please follow those instructions instead of keeping the old and outdated content. + For code snippets or fragments, surrounded by backticks (`), don't translate the content, keep the original in English. For example, `list`, `dict`, keep them as is. The content is written in markdown, write the translation in markdown as well. Don't add triple backticks (`) around the generated translation content. @@ -127,8 +129,15 @@ def translate_page( prompt_segments.extend( [ "There's an existing previous translation for this content that is probably outdated with old content or old instructions.", - "Update the translation given your current instructions and the original content.", - "If you have instructions to translate specific terms or phrases in a specific way, please follow those instructions instead of keeping the old and outdated content.", + "Update the translation only where necessary:", + "- If the original English content has changed, reflect that in the translation.", + "- If the previous translation violates current instructions, update it.", + "- Otherwise, preserve the original translation **line-by-line** as-is.", + "Do not:", + "- Rephrase or rewrite correct lines just to improve the style.", + "- Add or remove line breaks unless the English source changed.", + "- Change formatting or whitespace unless absolutely required.", + "Only change what must be changed. The goal is to minimize diffs for easier review.", "Previous translation:", f"%%%\n{old_translation}%%%", ] From 8af92a61399e8d1ac6cfccd600201aca248ea724 Mon Sep 17 00:00:00 2001 From: github-actions Date: Wed, 30 Jul 2025 16:38:11 +0000 Subject: [PATCH 26/60] =?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 bd8ebf16c..43219f175 100644 --- a/docs/en/docs/release-notes.md +++ b/docs/en/docs/release-notes.md @@ -23,6 +23,7 @@ hide: ### Internal +* ⚒️ Update translate script, update prompt to minimize generated diff. PR [#13947](https://github.com/fastapi/fastapi/pull/13947) by [@YuriiMotov](https://github.com/YuriiMotov). * ⬆ [pre-commit.ci] pre-commit autoupdate. PR [#13943](https://github.com/fastapi/fastapi/pull/13943) by [@pre-commit-ci[bot]](https://github.com/apps/pre-commit-ci). * ⚒️ Tweak translate script and CI. PR [#13939](https://github.com/fastapi/fastapi/pull/13939) by [@tiangolo](https://github.com/tiangolo). * 👷 Add CI to translate with LLMs. PR [#13937](https://github.com/fastapi/fastapi/pull/13937) by [@tiangolo](https://github.com/tiangolo). From e326cec10ebab167d8ae77cf211b29bfa19e7195 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebasti=C3=A1n=20Ram=C3=ADrez?= Date: Thu, 31 Jul 2025 19:47:31 +0200 Subject: [PATCH 27/60] =?UTF-8?q?=F0=9F=94=A7=20Update=20sponsors:=20Add?= =?UTF-8?q?=20Railway=20(#13953)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 1 + docs/en/data/sponsors.yml | 3 +++ docs/en/data/sponsors_badge.yml | 1 + docs/en/docs/deployment/cloud.md | 1 + docs/en/docs/img/sponsors/railway-banner.png | Bin 0 -> 11596 bytes docs/en/docs/img/sponsors/railway.png | Bin 0 -> 26226 bytes docs/en/overrides/main.html | 6 ++++++ 7 files changed, 12 insertions(+) create mode 100644 docs/en/docs/img/sponsors/railway-banner.png create mode 100644 docs/en/docs/img/sponsors/railway.png diff --git a/README.md b/README.md index b3eaa6b35..a0752ed10 100644 --- a/README.md +++ b/README.md @@ -56,6 +56,7 @@ The key features are: + diff --git a/docs/en/data/sponsors.yml b/docs/en/data/sponsors.yml index 784fd6692..19e8a8e3c 100644 --- a/docs/en/data/sponsors.yml +++ b/docs/en/data/sponsors.yml @@ -29,6 +29,9 @@ gold: - url: https://vibe.mobb.ai/?utm_source=Fast+APi&utm_medium=Image&utm_campaign=MVS title: Secure Your AI-Generated Code to Unlock Dev Productivity img: https://fastapi.tiangolo.com/img/sponsors/mobbai.png + - url: https://docs.railway.com/guides/fastapi?utm_medium=integration&utm_source=docs&utm_campaign=fastapi + title: Deploy enterprise applications at startup speed + img: https://fastapi.tiangolo.com/img/sponsors/railway.png silver: - url: https://databento.com/ title: Pay as you go for market data diff --git a/docs/en/data/sponsors_badge.yml b/docs/en/data/sponsors_badge.yml index a8895c8ed..0090e6865 100644 --- a/docs/en/data/sponsors_badge.yml +++ b/docs/en/data/sponsors_badge.yml @@ -44,3 +44,4 @@ logins: - LambdaTest-Inc - dribia - madisonredtfeldt + - railwayapp diff --git a/docs/en/docs/deployment/cloud.md b/docs/en/docs/deployment/cloud.md index d713379c3..c6d408f8c 100644 --- a/docs/en/docs/deployment/cloud.md +++ b/docs/en/docs/deployment/cloud.md @@ -15,3 +15,4 @@ You might want to try their services and follow their guides: * Platform.sh * Porter * Render +* Railway diff --git a/docs/en/docs/img/sponsors/railway-banner.png b/docs/en/docs/img/sponsors/railway-banner.png new file mode 100644 index 0000000000000000000000000000000000000000..f6146a7c1fc50352357367a6de6964fa473acff7 GIT binary patch literal 11596 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

v|w1?s_p#Ev#~&IU|!f!yE=Jl)n% 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 F{{Rhzf!Y87 literal 0 HcmV?d00001 diff --git a/docs/en/overrides/main.html b/docs/en/overrides/main.html index 22630e188..12585507d 100644 --- a/docs/en/overrides/main.html +++ b/docs/en/overrides/main.html @@ -86,6 +86,12 @@ +

{% endblock %} From cf726c93d910513da09c5b7dca93dd0cc40e4333 Mon Sep 17 00:00:00 2001 From: github-actions Date: Thu, 31 Jul 2025 17:47:55 +0000 Subject: [PATCH 28/60] =?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 43219f175..a488ebcdd 100644 --- a/docs/en/docs/release-notes.md +++ b/docs/en/docs/release-notes.md @@ -23,6 +23,7 @@ hide: ### Internal +* 🔧 Update sponsors: Add Railway. PR [#13953](https://github.com/fastapi/fastapi/pull/13953) by [@tiangolo](https://github.com/tiangolo). * ⚒️ Update translate script, update prompt to minimize generated diff. PR [#13947](https://github.com/fastapi/fastapi/pull/13947) by [@YuriiMotov](https://github.com/YuriiMotov). * ⬆ [pre-commit.ci] pre-commit autoupdate. PR [#13943](https://github.com/fastapi/fastapi/pull/13943) by [@pre-commit-ci[bot]](https://github.com/apps/pre-commit-ci). * ⚒️ Tweak translate script and CI. PR [#13939](https://github.com/fastapi/fastapi/pull/13939) by [@tiangolo](https://github.com/tiangolo). From 8abfa0f106b1f3c40ed858c64cd8035c0b4ac4eb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebasti=C3=A1n=20Ram=C3=ADrez?= Date: Thu, 31 Jul 2025 20:20:49 +0200 Subject: [PATCH 29/60] =?UTF-8?q?=F0=9F=94=A7=20Update=20sponsors:=20Datab?= =?UTF-8?q?ento=20link=20and=20sponsors=5Fbadge=20data=20(#13954)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 2 +- docs/en/data/sponsors.yml | 2 +- docs/en/data/sponsors_badge.yml | 1 + 3 files changed, 3 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index a0752ed10..0e421c347 100644 --- a/README.md +++ b/README.md @@ -57,7 +57,7 @@ The key features are: - + diff --git a/docs/en/data/sponsors.yml b/docs/en/data/sponsors.yml index 19e8a8e3c..2b3cd282d 100644 --- a/docs/en/data/sponsors.yml +++ b/docs/en/data/sponsors.yml @@ -33,7 +33,7 @@ gold: title: Deploy enterprise applications at startup speed img: https://fastapi.tiangolo.com/img/sponsors/railway.png silver: - - url: https://databento.com/ + - url: https://databento.com/?utm_source=fastapi&utm_medium=sponsor&utm_content=display title: Pay as you go for market data img: https://fastapi.tiangolo.com/img/sponsors/databento.svg - url: https://speakeasy.com/editor?utm_source=fastapi+repo&utm_medium=github+sponsorship diff --git a/docs/en/data/sponsors_badge.yml b/docs/en/data/sponsors_badge.yml index 0090e6865..62ba6a84c 100644 --- a/docs/en/data/sponsors_badge.yml +++ b/docs/en/data/sponsors_badge.yml @@ -45,3 +45,4 @@ logins: - dribia - madisonredtfeldt - railwayapp + - subtotal From 1e4f123eb042cc910b9726ac73ff83e8d012ccbe Mon Sep 17 00:00:00 2001 From: github-actions Date: Thu, 31 Jul 2025 18:21:09 +0000 Subject: [PATCH 30/60] =?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 a488ebcdd..72ca423d6 100644 --- a/docs/en/docs/release-notes.md +++ b/docs/en/docs/release-notes.md @@ -23,6 +23,7 @@ hide: ### Internal +* 🔧 Update sponsors: Databento link and sponsors_badge data. PR [#13954](https://github.com/fastapi/fastapi/pull/13954) by [@tiangolo](https://github.com/tiangolo). * 🔧 Update sponsors: Add Railway. PR [#13953](https://github.com/fastapi/fastapi/pull/13953) by [@tiangolo](https://github.com/tiangolo). * ⚒️ Update translate script, update prompt to minimize generated diff. PR [#13947](https://github.com/fastapi/fastapi/pull/13947) by [@YuriiMotov](https://github.com/YuriiMotov). * ⬆ [pre-commit.ci] pre-commit autoupdate. PR [#13943](https://github.com/fastapi/fastapi/pull/13943) by [@pre-commit-ci[bot]](https://github.com/apps/pre-commit-ci). From a9fbc4b8f508d938bbfe280ee4df6f028194b6f8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebasti=C3=A1n=20Ram=C3=ADrez?= Date: Fri, 1 Aug 2025 08:16:58 +0200 Subject: [PATCH 31/60] =?UTF-8?q?=F0=9F=91=A5=20Update=20FastAPI=20People?= =?UTF-8?q?=20-=20Contributors=20and=20Translators=20(#13955)?= 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 | 20 ++--- docs/en/data/translation_reviewers.yml | 103 +++++++++++++++++-------- docs/en/data/translators.yml | 20 +++-- 3 files changed, 94 insertions(+), 49 deletions(-) diff --git a/docs/en/data/contributors.yml b/docs/en/data/contributors.yml index e06510ac4..05ff0c7d4 100644 --- a/docs/en/data/contributors.yml +++ b/docs/en/data/contributors.yml @@ -1,21 +1,21 @@ tiangolo: login: tiangolo - count: 753 + count: 768 avatarUrl: https://avatars.githubusercontent.com/u/1326112?u=cb5d06e73a9e1998141b1641aa88e443c6717651&v=4 url: https://github.com/tiangolo dependabot: login: dependabot - count: 104 + count: 106 avatarUrl: https://avatars.githubusercontent.com/in/29110?v=4 url: https://github.com/apps/dependabot alejsdev: login: alejsdev - count: 47 + count: 48 avatarUrl: https://avatars.githubusercontent.com/u/90076947?u=638c65283ac9e9e2c3a0f9d1e3370db4b8a2c58d&v=4 url: https://github.com/alejsdev pre-commit-ci: login: pre-commit-ci - count: 33 + count: 37 avatarUrl: https://avatars.githubusercontent.com/in/68672?v=4 url: https://github.com/apps/pre-commit-ci github-actions: @@ -138,6 +138,11 @@ AlexWendland: count: 4 avatarUrl: https://avatars.githubusercontent.com/u/3949212?u=c4c0c615e0ea33d00bfe16b779cf6ebc0f58071c&v=4 url: https://github.com/AlexWendland +YuriiMotov: + login: YuriiMotov + count: 4 + avatarUrl: https://avatars.githubusercontent.com/u/109919500?u=b9b13d598dddfab529a52d264df80a900bfe7060&v=4 + url: https://github.com/YuriiMotov divums: login: divums count: 3 @@ -421,7 +426,7 @@ davidefiocco: adriencaccia: login: adriencaccia count: 2 - avatarUrl: https://avatars.githubusercontent.com/u/19605940?u=980b0b366a02791a5600b2e9f9ac2037679acaa8&v=4 + avatarUrl: https://avatars.githubusercontent.com/u/19605940?u=9a59081f46bfc9d839886a49d5092cf572879049&v=4 url: https://github.com/adriencaccia jamescurtin: login: jamescurtin @@ -553,8 +558,3 @@ blueswen: count: 2 avatarUrl: https://avatars.githubusercontent.com/u/1564148?u=6d6b8cc8f2b5cef715e68d6175154a8a94d518ee&v=4 url: https://github.com/blueswen -YuriiMotov: - login: YuriiMotov - count: 2 - avatarUrl: https://avatars.githubusercontent.com/u/109919500?u=e83a39697a2d33ab2ec9bfbced794ee48bc29cec&v=4 - url: https://github.com/YuriiMotov diff --git a/docs/en/data/translation_reviewers.yml b/docs/en/data/translation_reviewers.yml index 4f3c95b27..8eaf93d9c 100644 --- a/docs/en/data/translation_reviewers.yml +++ b/docs/en/data/translation_reviewers.yml @@ -10,12 +10,12 @@ Xewus: url: https://github.com/Xewus sodaMelon: login: sodaMelon - count: 126 + count: 127 avatarUrl: https://avatars.githubusercontent.com/u/66295123?u=be939db90f1119efee9e6110cc05066ff1f40f00&v=4 url: https://github.com/sodaMelon ceb10n: login: ceb10n - count: 112 + count: 116 avatarUrl: https://avatars.githubusercontent.com/u/235213?u=edcce471814a1eba9f0cdaa4cd0de18921a940a6&v=4 url: https://github.com/ceb10n tokusumi: @@ -40,8 +40,8 @@ alv2017: url: https://github.com/alv2017 nazarepiedady: login: nazarepiedady - count: 83 - avatarUrl: https://avatars.githubusercontent.com/u/31008635?u=8dc25777dc9cb51fb0dbba2f137988953d330b78&v=4 + count: 86 + avatarUrl: https://avatars.githubusercontent.com/u/31008635?u=f69ddc4ea8bda3bdfac7aa0e2ea38de282e6ee2d&v=4 url: https://github.com/nazarepiedady AlertRED: login: AlertRED @@ -123,6 +123,11 @@ JavierSanchezCastro: count: 38 avatarUrl: https://avatars.githubusercontent.com/u/72013291?u=ae5679e6bd971d9d98cd5e76e8683f83642ba950&v=4 url: https://github.com/JavierSanchezCastro +alejsdev: + login: alejsdev + count: 37 + avatarUrl: https://avatars.githubusercontent.com/u/90076947?u=638c65283ac9e9e2c3a0f9d1e3370db4b8a2c58d&v=4 + url: https://github.com/alejsdev stlucasgarcia: login: stlucasgarcia count: 36 @@ -133,11 +138,6 @@ SwftAlpc: count: 36 avatarUrl: https://avatars.githubusercontent.com/u/52768429?u=6a3aa15277406520ad37f6236e89466ed44bc5b8&v=4 url: https://github.com/SwftAlpc -alejsdev: - login: alejsdev - count: 36 - avatarUrl: https://avatars.githubusercontent.com/u/90076947?u=638c65283ac9e9e2c3a0f9d1e3370db4b8a2c58d&v=4 - url: https://github.com/alejsdev timothy-jeong: login: timothy-jeong count: 36 @@ -178,6 +178,11 @@ LorhanSohaky: count: 30 avatarUrl: https://avatars.githubusercontent.com/u/16273730?u=095b66f243a2cd6a0aadba9a095009f8aaf18393&v=4 url: https://github.com/LorhanSohaky +YuriiMotov: + login: YuriiMotov + count: 30 + avatarUrl: https://avatars.githubusercontent.com/u/109919500?u=b9b13d598dddfab529a52d264df80a900bfe7060&v=4 + url: https://github.com/YuriiMotov Vincy1230: login: Vincy1230 count: 30 @@ -243,11 +248,6 @@ mycaule: count: 25 avatarUrl: https://avatars.githubusercontent.com/u/6161385?u=e3cec75bd6d938a0d73fae0dc5534d1ab2ed1b0e&v=4 url: https://github.com/mycaule -YuriiMotov: - login: YuriiMotov - count: 24 - avatarUrl: https://avatars.githubusercontent.com/u/109919500?u=e83a39697a2d33ab2ec9bfbced794ee48bc29cec&v=4 - url: https://github.com/YuriiMotov Aruelius: login: Aruelius count: 24 @@ -548,6 +548,11 @@ KNChiu: count: 11 avatarUrl: https://avatars.githubusercontent.com/u/36751646?v=4 url: https://github.com/KNChiu +maru0123-2004: + login: maru0123-2004 + count: 11 + avatarUrl: https://avatars.githubusercontent.com/u/43961566?u=16ed8603a4d6a4665cb6c53a7aece6f31379b769&v=4 + url: https://github.com/maru0123-2004 mariacamilagl: login: mariacamilagl count: 10 @@ -606,13 +611,8 @@ nick-cjyx9: lucasbalieiro: login: lucasbalieiro count: 10 - avatarUrl: https://avatars.githubusercontent.com/u/37416577?u=eabaf4aebbaa88a94a4886273edba689012cee70&v=4 + avatarUrl: https://avatars.githubusercontent.com/u/37416577?u=dad91601ee4f40458d691774ec439aff308344d7&v=4 url: https://github.com/lucasbalieiro -maru0123-2004: - login: maru0123-2004 - count: 10 - avatarUrl: https://avatars.githubusercontent.com/u/43961566?u=16ed8603a4d6a4665cb6c53a7aece6f31379b769&v=4 - url: https://github.com/maru0123-2004 Zhongheng-Cheng: login: Zhongheng-Cheng count: 10 @@ -753,11 +753,6 @@ anthonycepeda: count: 7 avatarUrl: https://avatars.githubusercontent.com/u/72019805?u=60bdf46240cff8fca482ff0fc07d963fd5e1a27c&v=4 url: https://github.com/anthonycepeda -Muaytie666: - login: Muaytie666 - count: 7 - avatarUrl: https://avatars.githubusercontent.com/u/198508825?v=4 - url: https://github.com/Muaytie666 fabioueno: login: fabioueno count: 7 @@ -1028,6 +1023,11 @@ devluisrodrigues: count: 5 avatarUrl: https://avatars.githubusercontent.com/u/21125286?v=4 url: https://github.com/11kkw +soroushgh1: + login: soroushgh1 + count: 5 + avatarUrl: https://avatars.githubusercontent.com/u/178516095?u=5e26f6a5f66cdb32d7b56e6ab362bf18ba7858b9&v=4 + url: https://github.com/soroushgh1 lpdswing: login: lpdswing count: 4 @@ -1163,6 +1163,11 @@ cookie-byte217: count: 4 avatarUrl: https://avatars.githubusercontent.com/u/57880178?v=4 url: https://github.com/cookie-byte217 +AbolfazlKameli: + login: AbolfazlKameli + count: 4 + avatarUrl: https://avatars.githubusercontent.com/u/120686133?u=05d405115fc834d46260ec24ec7b28e23a13477e&v=4 + url: https://github.com/AbolfazlKameli tyronedamasceno: login: tyronedamasceno count: 3 @@ -1251,7 +1256,7 @@ rafsaf: frnsimoes: login: frnsimoes count: 3 - avatarUrl: https://avatars.githubusercontent.com/u/66239468?u=a405e8f10654251e239a4a1d9dd5bda59216727d&v=4 + avatarUrl: https://avatars.githubusercontent.com/u/66239468?u=fd8d408946633acc4bea057c207e6c0833871527&v=4 url: https://github.com/frnsimoes lieryan: login: lieryan @@ -1403,16 +1408,21 @@ tienduong-21: count: 3 avatarUrl: https://avatars.githubusercontent.com/u/80129618?v=4 url: https://github.com/tienduong-21 -soroushgh1: - login: soroushgh1 - count: 3 - avatarUrl: https://avatars.githubusercontent.com/u/178516095?u=5e26f6a5f66cdb32d7b56e6ab362bf18ba7858b9&v=4 - url: https://github.com/soroushgh1 zbellos: login: zbellos count: 3 avatarUrl: https://avatars.githubusercontent.com/u/204500646?v=4 url: https://github.com/zbellos +Mohammad222PR: + login: Mohammad222PR + count: 3 + avatarUrl: https://avatars.githubusercontent.com/u/116789737?u=25810a5fe049d2f1618e2e7417cea011cc353ce4&v=4 + url: https://github.com/Mohammad222PR +EdmilsonRodrigues: + login: EdmilsonRodrigues + count: 3 + avatarUrl: https://avatars.githubusercontent.com/u/62777025?u=217d6f3cd6cc750bb8818a3af7726c8d74eb7c2d&v=4 + url: https://github.com/EdmilsonRodrigues blaisep: login: blaisep count: 2 @@ -1508,11 +1518,11 @@ its0x08: count: 2 avatarUrl: https://avatars.githubusercontent.com/u/15280042?u=d7c2058f29d4e8fbdae09b194e04c5e410350211&v=4 url: https://github.com/its0x08 -lindsayzhou: - login: lindsayzhou +linsein: + login: linsein count: 2 avatarUrl: https://avatars.githubusercontent.com/u/23748021?u=4db169ce262b69aa7292f82b785436544f69fb88&v=4 - url: https://github.com/lindsayzhou + url: https://github.com/linsein 0xflotus: login: 0xflotus count: 2 @@ -1668,6 +1678,11 @@ siavashyj: count: 2 avatarUrl: https://avatars.githubusercontent.com/u/43583410?u=562005ddc7901cd27a1219a118a2363817b14977&v=4 url: https://github.com/siavashyj +Ramin-RX7: + login: Ramin-RX7 + count: 2 + avatarUrl: https://avatars.githubusercontent.com/u/52785580?u=b3678f779ad0ee9cd9dca9e50ccb804b5eb990a5&v=4 + url: https://github.com/Ramin-RX7 DevSpace88: login: DevSpace88 count: 2 @@ -1763,6 +1778,11 @@ logan2d5: count: 2 avatarUrl: https://avatars.githubusercontent.com/u/146642263?u=dbd6621f8b0330d6919f6a7131277b92e26fbe87&v=4 url: https://github.com/logan2d5 +guspan-tanadi: + login: guspan-tanadi + count: 2 + avatarUrl: https://avatars.githubusercontent.com/u/36249910?v=4 + url: https://github.com/guspan-tanadi tiaggo16: login: tiaggo16 count: 2 @@ -1793,6 +1813,11 @@ ivintoiu: count: 2 avatarUrl: https://avatars.githubusercontent.com/u/1853336?u=5e3d0977f44661fb9712fa297cc8f7608ea6ce48&v=4 url: https://github.com/ivintoiu +TechnoService2: + login: TechnoService2 + count: 2 + avatarUrl: https://avatars.githubusercontent.com/u/142113388?v=4 + url: https://github.com/TechnoService2 EgorOnishchuk: login: EgorOnishchuk count: 2 @@ -1818,3 +1843,13 @@ NavesSapnis: count: 2 avatarUrl: https://avatars.githubusercontent.com/u/79222417?u=b5b10291b8e9130ca84fd20f0a641e04ed94b6b1&v=4 url: https://github.com/NavesSapnis +eqsdxr: + login: eqsdxr + count: 2 + avatarUrl: https://avatars.githubusercontent.com/u/157279130?u=58fddf77ed76966eaa8c73eea9bea4bb0c53b673&v=4 + url: https://github.com/eqsdxr +syedasamina56: + login: syedasamina56 + count: 2 + avatarUrl: https://avatars.githubusercontent.com/u/183273097?v=4 + url: https://github.com/syedasamina56 diff --git a/docs/en/data/translators.yml b/docs/en/data/translators.yml index 3cd6120d0..410c9c826 100644 --- a/docs/en/data/translators.yml +++ b/docs/en/data/translators.yml @@ -121,7 +121,7 @@ batlopes: lucasbalieiro: login: lucasbalieiro count: 6 - avatarUrl: https://avatars.githubusercontent.com/u/37416577?u=eabaf4aebbaa88a94a4886273edba689012cee70&v=4 + avatarUrl: https://avatars.githubusercontent.com/u/37416577?u=dad91601ee4f40458d691774ec439aff308344d7&v=4 url: https://github.com/lucasbalieiro Alexandrhub: login: Alexandrhub @@ -208,6 +208,16 @@ k94-ishi: count: 4 avatarUrl: https://avatars.githubusercontent.com/u/32672580?u=bc7c5c07af0656be9fe4f1784a444af8d81ded89&v=4 url: https://github.com/k94-ishi +Mohammad222PR: + login: Mohammad222PR + count: 4 + avatarUrl: https://avatars.githubusercontent.com/u/116789737?u=25810a5fe049d2f1618e2e7417cea011cc353ce4&v=4 + url: https://github.com/Mohammad222PR +NavesSapnis: + login: NavesSapnis + count: 4 + avatarUrl: https://avatars.githubusercontent.com/u/79222417?u=b5b10291b8e9130ca84fd20f0a641e04ed94b6b1&v=4 + url: https://github.com/NavesSapnis jfunez: login: jfunez count: 3 @@ -528,8 +538,8 @@ EgorOnishchuk: count: 2 avatarUrl: https://avatars.githubusercontent.com/u/120256301?v=4 url: https://github.com/EgorOnishchuk -NavesSapnis: - login: NavesSapnis +EdmilsonRodrigues: + login: EdmilsonRodrigues count: 2 - avatarUrl: https://avatars.githubusercontent.com/u/79222417?u=b5b10291b8e9130ca84fd20f0a641e04ed94b6b1&v=4 - url: https://github.com/NavesSapnis + avatarUrl: https://avatars.githubusercontent.com/u/62777025?u=217d6f3cd6cc750bb8818a3af7726c8d74eb7c2d&v=4 + url: https://github.com/EdmilsonRodrigues From a0ede1839abe958544b4b5e9afb1dc6c5608c421 Mon Sep 17 00:00:00 2001 From: github-actions Date: Fri, 1 Aug 2025 06:17:21 +0000 Subject: [PATCH 32/60] =?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 72ca423d6..3aae933c1 100644 --- a/docs/en/docs/release-notes.md +++ b/docs/en/docs/release-notes.md @@ -23,6 +23,7 @@ hide: ### Internal +* 👥 Update FastAPI People - Contributors and Translators. PR [#13955](https://github.com/fastapi/fastapi/pull/13955) by [@tiangolo](https://github.com/tiangolo). * 🔧 Update sponsors: Databento link and sponsors_badge data. PR [#13954](https://github.com/fastapi/fastapi/pull/13954) by [@tiangolo](https://github.com/tiangolo). * 🔧 Update sponsors: Add Railway. PR [#13953](https://github.com/fastapi/fastapi/pull/13953) by [@tiangolo](https://github.com/tiangolo). * ⚒️ Update translate script, update prompt to minimize generated diff. PR [#13947](https://github.com/fastapi/fastapi/pull/13947) by [@YuriiMotov](https://github.com/YuriiMotov). From 3ad01a124707f05f743a85dfd6544dea79188b0e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebasti=C3=A1n=20Ram=C3=ADrez?= Date: Fri, 1 Aug 2025 08:19:53 +0200 Subject: [PATCH 33/60] =?UTF-8?q?=F0=9F=91=A5=20Update=20FastAPI=20People?= =?UTF-8?q?=20-=20Sponsors=20(#13956)?= 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 | 136 ++++++++++++++----------------- 1 file changed, 59 insertions(+), 77 deletions(-) diff --git a/docs/en/data/github_sponsors.yml b/docs/en/data/github_sponsors.yml index 0cb200185..778ec6a95 100644 --- a/docs/en/data/github_sponsors.yml +++ b/docs/en/data/github_sponsors.yml @@ -1,7 +1,4 @@ sponsors: -- - login: classmethod - avatarUrl: https://avatars.githubusercontent.com/u/1532151?v=4 - url: https://github.com/classmethod - - login: renderinc avatarUrl: https://avatars.githubusercontent.com/u/36424661?v=4 url: https://github.com/renderinc @@ -23,15 +20,15 @@ sponsors: - login: subtotal avatarUrl: https://avatars.githubusercontent.com/u/176449348?v=4 url: https://github.com/subtotal + - login: railwayapp + avatarUrl: https://avatars.githubusercontent.com/u/66716858?v=4 + url: https://github.com/railwayapp - login: Nixtla avatarUrl: https://avatars.githubusercontent.com/u/79945230?v=4 url: https://github.com/Nixtla - login: scalar avatarUrl: https://avatars.githubusercontent.com/u/301879?v=4 url: https://github.com/scalar -- - login: ObliviousAI - avatarUrl: https://avatars.githubusercontent.com/u/65656077?v=4 - url: https://github.com/ObliviousAI - - login: dribia avatarUrl: https://avatars.githubusercontent.com/u/41189616?v=4 url: https://github.com/dribia @@ -50,10 +47,7 @@ sponsors: - login: permitio avatarUrl: https://avatars.githubusercontent.com/u/71775833?v=4 url: https://github.com/permitio -- - login: xoflare - avatarUrl: https://avatars.githubusercontent.com/u/74335107?v=4 - url: https://github.com/xoflare - - login: marvin-robot +- - login: marvin-robot avatarUrl: https://avatars.githubusercontent.com/u/41086007?u=b9fcab402d0cd0aec738b6574fe60855cb0cd36d&v=4 url: https://github.com/marvin-robot - login: mercedes-benz @@ -62,9 +56,6 @@ sponsors: - login: Ponte-Energy-Partners avatarUrl: https://avatars.githubusercontent.com/u/114745848?v=4 url: https://github.com/Ponte-Energy-Partners - - login: snapit-cypher - avatarUrl: https://avatars.githubusercontent.com/u/115662654?v=4 - url: https://github.com/snapit-cypher - login: LambdaTest-Inc avatarUrl: https://avatars.githubusercontent.com/u/171592363?u=96606606a45fa170427206199014f2a5a2a4920b&v=4 url: https://github.com/LambdaTest-Inc @@ -101,24 +92,18 @@ sponsors: - - login: samuelcolvin avatarUrl: https://avatars.githubusercontent.com/u/4039449?u=42eb3b833047c8c4b4f647a031eaef148c16d93f&v=4 url: https://github.com/samuelcolvin - - login: CoodingPenguin - avatarUrl: https://avatars.githubusercontent.com/u/37505775?u=6a9e1f6647fbf95f99afeee82a3682e15fc6e959&v=4 - url: https://github.com/CoodingPenguin - - login: deight93 - avatarUrl: https://avatars.githubusercontent.com/u/37678115?u=a608798b5bd0034183a9c430ebb42fb266db86ce&v=4 - url: https://github.com/deight93 - login: otosky avatarUrl: https://avatars.githubusercontent.com/u/42260747?u=69d089387c743d89427aa4ad8740cfb34045a9e0&v=4 url: https://github.com/otosky - login: ramonalmeidam avatarUrl: https://avatars.githubusercontent.com/u/45269580?u=3358750b3a5854d7c3ed77aaca7dd20a0f529d32&v=4 url: https://github.com/ramonalmeidam - - login: kaoru0310 - avatarUrl: https://avatars.githubusercontent.com/u/80977929?u=1b61d10142b490e56af932ddf08a390fae8ee94f&v=4 - url: https://github.com/kaoru0310 - - login: RaamEEIL - avatarUrl: https://avatars.githubusercontent.com/u/20320552?v=4 - url: https://github.com/RaamEEIL + - 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 @@ -134,27 +119,21 @@ sponsors: - login: ProteinQure avatarUrl: https://avatars.githubusercontent.com/u/33707203?v=4 url: https://github.com/ProteinQure + - 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: eruditis - avatarUrl: https://avatars.githubusercontent.com/u/95244703?v=4 - url: https://github.com/eruditis - login: jugeeem avatarUrl: https://avatars.githubusercontent.com/u/116043716?u=ae590d79c38ac79c91b9c5caa6887d061e865a3d&v=4 url: https://github.com/jugeeem - login: logic-automation avatarUrl: https://avatars.githubusercontent.com/u/144732884?v=4 url: https://github.com/logic-automation - - 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: patsatsia avatarUrl: https://avatars.githubusercontent.com/u/61111267?u=3271b85f7a37b479c8d0ae0a235182e83c166edf&v=4 url: https://github.com/patsatsia @@ -197,6 +176,12 @@ sponsors: - login: gorhack avatarUrl: https://avatars.githubusercontent.com/u/4141690?u=ec119ebc4bdf00a7bc84657a71aa17834f4f27f3&v=4 url: https://github.com/gorhack + - login: Ryandaydev + avatarUrl: https://avatars.githubusercontent.com/u/4292423?u=679ff84cb7b988c5795a5fa583857f574a055763&v=4 + url: https://github.com/Ryandaydev + - login: jaredtrog + avatarUrl: https://avatars.githubusercontent.com/u/4381365?v=4 + url: https://github.com/jaredtrog - login: vincentkoc avatarUrl: https://avatars.githubusercontent.com/u/25068?u=fbd5b2d51142daa4bdbc21e21953a3b8b8188a4a&v=4 url: https://github.com/vincentkoc @@ -215,9 +200,6 @@ sponsors: - login: pamelafox avatarUrl: https://avatars.githubusercontent.com/u/297042?v=4 url: https://github.com/pamelafox - - login: ericof - avatarUrl: https://avatars.githubusercontent.com/u/306014?u=cf7c8733620397e6584a451505581c01c5d842d7&v=4 - url: https://github.com/ericof - login: wshayes avatarUrl: https://avatars.githubusercontent.com/u/365303?u=07ca03c5ee811eb0920e633cc3c3db73dbec1aa5&v=4 url: https://github.com/wshayes @@ -251,12 +233,9 @@ sponsors: - login: ashi-agrawal avatarUrl: https://avatars.githubusercontent.com/u/17105294?u=99c7a854035e5398d8e7b674f2d42baae6c957f8&v=4 url: https://github.com/ashi-agrawal - - login: Ryandaydev - avatarUrl: https://avatars.githubusercontent.com/u/4292423?u=679ff84cb7b988c5795a5fa583857f574a055763&v=4 - url: https://github.com/Ryandaydev - - login: jaredtrog - avatarUrl: https://avatars.githubusercontent.com/u/4381365?v=4 - url: https://github.com/jaredtrog + - login: RaamEEIL + avatarUrl: https://avatars.githubusercontent.com/u/20320552?v=4 + url: https://github.com/RaamEEIL - login: oliverxchen avatarUrl: https://avatars.githubusercontent.com/u/4471774?u=534191f25e32eeaadda22dfab4b0a428733d5489&v=4 url: https://github.com/oliverxchen @@ -275,9 +254,9 @@ sponsors: - login: hiancdtrsnm avatarUrl: https://avatars.githubusercontent.com/u/7343177?v=4 url: https://github.com/hiancdtrsnm -- - login: jpizquierdo - avatarUrl: https://avatars.githubusercontent.com/u/6716239?v=4 - url: https://github.com/jpizquierdo +- - login: manoelpqueiroz + avatarUrl: https://avatars.githubusercontent.com/u/23669137?u=b12e84b28a84369ab5b30bd5a79e5788df5a0756&v=4 + url: https://github.com/manoelpqueiroz - - login: pawamoy avatarUrl: https://avatars.githubusercontent.com/u/3999221?u=b030e4c89df2f3a36bc4710b925bdeb6745c9856&v=4 url: https://github.com/pawamoy @@ -296,9 +275,9 @@ sponsors: - login: caviri avatarUrl: https://avatars.githubusercontent.com/u/45425937?u=4e14bd64282bad8f385eafbdb004b5a279366d6e&v=4 url: https://github.com/caviri - - login: joshuatz - avatarUrl: https://avatars.githubusercontent.com/u/17817563?u=f1bf05b690d1fc164218f0b420cdd3acb7913e21&v=4 - url: https://github.com/joshuatz + - login: hgalytoby + avatarUrl: https://avatars.githubusercontent.com/u/50397689?u=62c7ff3519858423579676cd0efbd7e3f1ffe63a&v=4 + url: https://github.com/hgalytoby - login: SebTota avatarUrl: https://avatars.githubusercontent.com/u/25122511?v=4 url: https://github.com/SebTota @@ -320,21 +299,15 @@ sponsors: - login: bnkc avatarUrl: https://avatars.githubusercontent.com/u/34930566?u=db5e6f4f87836cad26c2aa90ce390ce49041c5a9&v=4 url: https://github.com/bnkc - - login: lukzmu - avatarUrl: https://avatars.githubusercontent.com/u/175964415?u=75348f25bb99a5f92ddb40c0b9b1ff7acb39c150&v=4 - url: https://github.com/lukzmu - - login: hgalytoby - avatarUrl: https://avatars.githubusercontent.com/u/50397689?u=62c7ff3519858423579676cd0efbd7e3f1ffe63a&v=4 - url: https://github.com/hgalytoby + - 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: browniebroke - avatarUrl: https://avatars.githubusercontent.com/u/861044?u=5abfca5588f3e906b31583d7ee62f6de4b68aa24&v=4 - url: https://github.com/browniebroke - login: miguelgr avatarUrl: https://avatars.githubusercontent.com/u/1484589?u=54556072b8136efa12ae3b6902032ea2a39ace4b&v=4 url: https://github.com/miguelgr @@ -362,12 +335,6 @@ sponsors: - login: tochikuji avatarUrl: https://avatars.githubusercontent.com/u/851759?v=4 url: https://github.com/tochikuji - - login: moonape1226 - avatarUrl: https://avatars.githubusercontent.com/u/8532038?u=d9f8b855a429fff9397c3833c2ff83849ebf989d&v=4 - url: https://github.com/moonape1226 - - login: msehnout - avatarUrl: https://avatars.githubusercontent.com/u/9369632?u=8c988f1b008a3f601385a3616f9327820f66e3a5&v=4 - url: https://github.com/msehnout - login: xncbf avatarUrl: https://avatars.githubusercontent.com/u/9462045?u=a80a7bb349555b277645632ed66639ff43400614&v=4 url: https://github.com/xncbf @@ -389,12 +356,12 @@ sponsors: - login: Zuzah avatarUrl: https://avatars.githubusercontent.com/u/10934846?u=1ef43e075ddc87bd1178372bf4d95ee6175cae27&v=4 url: https://github.com/Zuzah - - login: artempronevskiy - avatarUrl: https://avatars.githubusercontent.com/u/12235104?u=03df6e1e55c9c6fe5d230adabb8dd7d43d8bbe8f&v=4 - url: https://github.com/artempronevskiy - login: TheR1D avatarUrl: https://avatars.githubusercontent.com/u/16740832?u=b0dfdbdb27b79729430c71c6128962f77b7b53f7&v=4 url: https://github.com/TheR1D + - 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 @@ -419,39 +386,54 @@ sponsors: - login: harsh183 avatarUrl: https://avatars.githubusercontent.com/u/7780198?v=4 url: https://github.com/harsh183 + - login: moonape1226 + avatarUrl: https://avatars.githubusercontent.com/u/8532038?u=d9f8b855a429fff9397c3833c2ff83849ebf989d&v=4 + url: https://github.com/moonape1226 - - login: andrecorumba avatarUrl: https://avatars.githubusercontent.com/u/37807517?u=9b9be3b41da9bda60957da9ef37b50dbf65baa61&v=4 url: https://github.com/andrecorumba + - 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 avatarUrl: https://avatars.githubusercontent.com/u/47593005?u=c30ab7230f82a12a9b938dcb54f84a996931409a&v=4 url: https://github.com/morzan1001 - - login: sadikkuzu - avatarUrl: https://avatars.githubusercontent.com/u/23168063?u=d179c06bb9f65c4167fcab118526819f8e0dac17&v=4 - url: https://github.com/sadikkuzu - 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: v4lerdon + avatarUrl: https://avatars.githubusercontent.com/u/98405746?u=10969728d51e8f08e203f5d65fda948c21545c73&v=4 + url: https://github.com/v4lerdon + - login: hauanitech + avatarUrl: https://avatars.githubusercontent.com/u/211940501?u=48f70c3ef9b89c598d2dde528cda2d4f6468a135&v=4 + url: https://github.com/hauanitech + - login: igor-kan + avatarUrl: https://avatars.githubusercontent.com/u/61065863?u=3bade33799d183510fd381e2e4f5e1b61af8631a&v=4 + url: https://github.com/igor-kan - login: 0ne-stone avatarUrl: https://avatars.githubusercontent.com/u/62360849?u=746dd21c34e7e06eefb11b03e8bb01aaae3c2a4f&v=4 url: https://github.com/0ne-stone - - login: darixsamani - avatarUrl: https://avatars.githubusercontent.com/u/67915678?u=cfa82128692eeeec4bf0e7a0faaa9a614695c0f9&v=4 - url: https://github.com/darixsamani + - login: t3llscode + avatarUrl: https://avatars.githubusercontent.com/u/65864434?u=35df974cec16993343bf6494d60a14e71f66c5af&v=4 + url: https://github.com/t3llscode - login: nayasinghania - avatarUrl: https://avatars.githubusercontent.com/u/74111380?u=af853245a21fe052b6a27e41a8de8cf4cdf76e85&v=4 + avatarUrl: https://avatars.githubusercontent.com/u/74111380?u=752e99a5e139389fdc0a0677122adc08438eb076&v=4 url: https://github.com/nayasinghania - login: Toothwitch avatarUrl: https://avatars.githubusercontent.com/u/1710406?u=5eebb23b46cd26e48643b9e5179536cad491c17a&v=4 url: https://github.com/Toothwitch - - login: roboman-tech - avatarUrl: https://avatars.githubusercontent.com/u/8183070?u=fdeaa2ed29f598eb7901693884c0ad32b16982e3&v=4 - url: https://github.com/roboman-tech - login: andreagrandi avatarUrl: https://avatars.githubusercontent.com/u/636391?u=13d90cb8ec313593a5b71fbd4e33b78d6da736f5&v=4 url: https://github.com/andreagrandi + - login: sadikkuzu + avatarUrl: https://avatars.githubusercontent.com/u/23168063?u=d179c06bb9f65c4167fcab118526819f8e0dac17&v=4 + url: https://github.com/sadikkuzu + - login: roboman-tech + avatarUrl: https://avatars.githubusercontent.com/u/8183070?u=fdeaa2ed29f598eb7901693884c0ad32b16982e3&v=4 + url: https://github.com/roboman-tech From 1c1c2e8ab971a2d650032260d4d39a124e28aa17 Mon Sep 17 00:00:00 2001 From: github-actions Date: Fri, 1 Aug 2025 06:20:13 +0000 Subject: [PATCH 34/60] =?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 3aae933c1..a81b54a65 100644 --- a/docs/en/docs/release-notes.md +++ b/docs/en/docs/release-notes.md @@ -23,6 +23,7 @@ hide: ### Internal +* 👥 Update FastAPI People - Sponsors. PR [#13956](https://github.com/fastapi/fastapi/pull/13956) by [@tiangolo](https://github.com/tiangolo). * 👥 Update FastAPI People - Contributors and Translators. PR [#13955](https://github.com/fastapi/fastapi/pull/13955) by [@tiangolo](https://github.com/tiangolo). * 🔧 Update sponsors: Databento link and sponsors_badge data. PR [#13954](https://github.com/fastapi/fastapi/pull/13954) by [@tiangolo](https://github.com/tiangolo). * 🔧 Update sponsors: Add Railway. PR [#13953](https://github.com/fastapi/fastapi/pull/13953) by [@tiangolo](https://github.com/tiangolo). From 79d2576508b62ff8918db358756694d73e55b9af Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 1 Aug 2025 08:22:27 +0200 Subject: [PATCH 35/60] =?UTF-8?q?=E2=AC=86=20Bump=20tiangolo/latest-change?= =?UTF-8?q?s=20from=200.3.2=20to=200.4.0=20(#13952)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Bumps [tiangolo/latest-changes](https://github.com/tiangolo/latest-changes) from 0.3.2 to 0.4.0. - [Release notes](https://github.com/tiangolo/latest-changes/releases) - [Commits](https://github.com/tiangolo/latest-changes/compare/0.3.2...0.4.0) --- updated-dependencies: - dependency-name: tiangolo/latest-changes dependency-version: 0.4.0 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> --- .github/workflows/latest-changes.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/latest-changes.yml b/.github/workflows/latest-changes.yml index b8b5c42ee..208ab0c65 100644 --- a/.github/workflows/latest-changes.yml +++ b/.github/workflows/latest-changes.yml @@ -34,7 +34,7 @@ jobs: if: ${{ github.event_name == 'workflow_dispatch' && github.event.inputs.debug_enabled == 'true' }} with: limit-access-to-actor: true - - uses: tiangolo/latest-changes@0.3.2 + - uses: tiangolo/latest-changes@0.4.0 with: token: ${{ secrets.GITHUB_TOKEN }} latest_changes_file: docs/en/docs/release-notes.md From 6e69d62bfeb538cb82e9c69f53e939a25268cf79 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Fri, 1 Aug 2025 06:22:46 +0000 Subject: [PATCH 36/60] =?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 a81b54a65..8bc413f26 100644 --- a/docs/en/docs/release-notes.md +++ b/docs/en/docs/release-notes.md @@ -23,6 +23,7 @@ hide: ### Internal +* ⬆ Bump tiangolo/latest-changes from 0.3.2 to 0.4.0. PR [#13952](https://github.com/fastapi/fastapi/pull/13952) by [@dependabot[bot]](https://github.com/apps/dependabot). * 👥 Update FastAPI People - Sponsors. PR [#13956](https://github.com/fastapi/fastapi/pull/13956) by [@tiangolo](https://github.com/tiangolo). * 👥 Update FastAPI People - Contributors and Translators. PR [#13955](https://github.com/fastapi/fastapi/pull/13955) by [@tiangolo](https://github.com/tiangolo). * 🔧 Update sponsors: Databento link and sponsors_badge data. PR [#13954](https://github.com/fastapi/fastapi/pull/13954) by [@tiangolo](https://github.com/tiangolo). From e7401d2e4283211c3d53faa6915415327b0957c0 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 1 Aug 2025 15:09:18 +0200 Subject: [PATCH 37/60] =?UTF-8?q?=E2=AC=86=20Bump=20mkdocs-material=20from?= =?UTF-8?q?=209.6.15=20to=209.6.16=20(#13961)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Bumps [mkdocs-material](https://github.com/squidfunk/mkdocs-material) from 9.6.15 to 9.6.16. - [Release notes](https://github.com/squidfunk/mkdocs-material/releases) - [Changelog](https://github.com/squidfunk/mkdocs-material/blob/master/CHANGELOG) - [Commits](https://github.com/squidfunk/mkdocs-material/compare/9.6.15...9.6.16) --- updated-dependencies: - dependency-name: mkdocs-material dependency-version: 9.6.16 dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- requirements-docs.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/requirements-docs.txt b/requirements-docs.txt index 5c5701f73..4713d187e 100644 --- a/requirements-docs.txt +++ b/requirements-docs.txt @@ -1,6 +1,6 @@ -e . -r requirements-docs-tests.txt -mkdocs-material==9.6.15 +mkdocs-material==9.6.16 mdx-include >=1.4.1,<2.0.0 mkdocs-redirects>=1.2.1,<1.3.0 typer == 0.16.0 From d07159797b4eef6a38ec09b351c3cc1c7669bad3 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Fri, 1 Aug 2025 13:09:46 +0000 Subject: [PATCH 38/60] =?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 8bc413f26..170e579b5 100644 --- a/docs/en/docs/release-notes.md +++ b/docs/en/docs/release-notes.md @@ -23,6 +23,7 @@ hide: ### Internal +* ⬆ Bump mkdocs-material from 9.6.15 to 9.6.16. PR [#13961](https://github.com/fastapi/fastapi/pull/13961) by [@dependabot[bot]](https://github.com/apps/dependabot). * ⬆ Bump tiangolo/latest-changes from 0.3.2 to 0.4.0. PR [#13952](https://github.com/fastapi/fastapi/pull/13952) by [@dependabot[bot]](https://github.com/apps/dependabot). * 👥 Update FastAPI People - Sponsors. PR [#13956](https://github.com/fastapi/fastapi/pull/13956) by [@tiangolo](https://github.com/tiangolo). * 👥 Update FastAPI People - Contributors and Translators. PR [#13955](https://github.com/fastapi/fastapi/pull/13955) by [@tiangolo](https://github.com/tiangolo). From 2e16e105c9a0085d4deb952e39a78d919a29c3a2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebasti=C3=A1n=20Ram=C3=ADrez?= Date: Fri, 1 Aug 2025 15:19:22 +0200 Subject: [PATCH 39/60] =?UTF-8?q?=F0=9F=91=A5=20Update=20FastAPI=20GitHub?= =?UTF-8?q?=20topic=20repositories=20(#13962)?= 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 | 384 +++++++++++++++++------------------ 1 file changed, 192 insertions(+), 192 deletions(-) diff --git a/docs/en/data/topic_repos.yml b/docs/en/data/topic_repos.yml index ab9f21995..631edbb77 100644 --- a/docs/en/data/topic_repos.yml +++ b/docs/en/data/topic_repos.yml @@ -1,91 +1,96 @@ - name: full-stack-fastapi-template html_url: https://github.com/fastapi/full-stack-fastapi-template - stars: 34156 + stars: 35002 owner_login: fastapi owner_html_url: https://github.com/fastapi - name: Hello-Python html_url: https://github.com/mouredev/Hello-Python - stars: 30835 + stars: 31317 owner_login: mouredev owner_html_url: https://github.com/mouredev - name: serve html_url: https://github.com/jina-ai/serve - stars: 21631 + stars: 21680 owner_login: jina-ai owner_html_url: https://github.com/jina-ai - name: HivisionIDPhotos html_url: https://github.com/Zeyi-Lin/HivisionIDPhotos - stars: 18125 + stars: 18700 owner_login: Zeyi-Lin owner_html_url: https://github.com/Zeyi-Lin - name: sqlmodel html_url: https://github.com/fastapi/sqlmodel - stars: 16249 + stars: 16469 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: 13279 + stars: 13663 owner_login: Evil0ctal owner_html_url: https://github.com/Evil0ctal - name: fastapi-best-practices html_url: https://github.com/zhanymkanov/fastapi-best-practices - stars: 12334 + stars: 12716 owner_login: zhanymkanov owner_html_url: https://github.com/zhanymkanov - name: awesome-fastapi html_url: https://github.com/mjhea0/awesome-fastapi - stars: 9934 + stars: 10099 owner_login: mjhea0 owner_html_url: https://github.com/mjhea0 - name: FastUI html_url: https://github.com/pydantic/FastUI - stars: 8838 + stars: 8850 owner_login: pydantic owner_html_url: https://github.com/pydantic - name: XHS-Downloader html_url: https://github.com/JoeanAmier/XHS-Downloader - stars: 7962 + stars: 8305 owner_login: JoeanAmier owner_html_url: https://github.com/JoeanAmier -- name: nonebot2 - html_url: https://github.com/nonebot/nonebot2 - stars: 6834 - owner_login: nonebot - owner_html_url: https://github.com/nonebot - name: FileCodeBox html_url: https://github.com/vastsa/FileCodeBox - stars: 6783 + stars: 6936 owner_login: vastsa owner_html_url: https://github.com/vastsa +- name: nonebot2 + html_url: https://github.com/nonebot/nonebot2 + stars: 6911 + owner_login: nonebot + owner_html_url: https://github.com/nonebot - name: fastapi_mcp html_url: https://github.com/tadata-org/fastapi_mcp - stars: 5846 + stars: 6767 owner_login: tadata-org owner_html_url: https://github.com/tadata-org +- name: SurfSense + html_url: https://github.com/MODSetter/SurfSense + stars: 6202 + owner_login: MODSetter + owner_html_url: https://github.com/MODSetter - name: hatchet html_url: https://github.com/hatchet-dev/hatchet - stars: 5773 + stars: 5878 owner_login: hatchet-dev owner_html_url: https://github.com/hatchet-dev -- name: serge - html_url: https://github.com/serge-chat/serge - stars: 5728 - owner_login: serge-chat - owner_html_url: https://github.com/serge-chat - name: polar html_url: https://github.com/polarsource/polar - stars: 5709 + stars: 5872 owner_login: polarsource owner_html_url: https://github.com/polarsource +- name: serge + html_url: https://github.com/serge-chat/serge + stars: 5740 + owner_login: serge-chat + owner_html_url: https://github.com/serge-chat - name: fastapi-users html_url: https://github.com/fastapi-users/fastapi-users - stars: 5336 + stars: 5429 owner_login: fastapi-users owner_html_url: https://github.com/fastapi-users - name: strawberry html_url: https://github.com/strawberry-graphql/strawberry - stars: 4317 + stars: 4345 owner_login: strawberry-graphql owner_html_url: https://github.com/strawberry-graphql - name: chatgpt-web-share @@ -93,184 +98,184 @@ stars: 4301 owner_login: chatpire owner_html_url: https://github.com/chatpire +- name: poem + html_url: https://github.com/poem-web/poem + stars: 4107 + owner_login: poem-web + owner_html_url: https://github.com/poem-web - name: atrilabs-engine html_url: https://github.com/Atri-Labs/atrilabs-engine - stars: 4106 + stars: 4103 owner_login: Atri-Labs owner_html_url: https://github.com/Atri-Labs - name: dynaconf html_url: https://github.com/dynaconf/dynaconf - stars: 4045 + stars: 4079 owner_login: dynaconf owner_html_url: https://github.com/dynaconf -- name: poem - html_url: https://github.com/poem-web/poem - stars: 4037 - owner_login: poem-web - owner_html_url: https://github.com/poem-web -- name: farfalle - html_url: https://github.com/rashadphz/farfalle - stars: 3348 - owner_login: rashadphz - owner_html_url: https://github.com/rashadphz - name: LitServe html_url: https://github.com/Lightning-AI/LitServe - stars: 3347 + stars: 3430 owner_login: Lightning-AI owner_html_url: https://github.com/Lightning-AI -- name: fastapi-admin - html_url: https://github.com/fastapi-admin/fastapi-admin - stars: 3309 - owner_login: fastapi-admin - owner_html_url: https://github.com/fastapi-admin -- name: datamodel-code-generator - html_url: https://github.com/koxudaxi/datamodel-code-generator - stars: 3291 - owner_login: koxudaxi - owner_html_url: https://github.com/koxudaxi - name: logfire html_url: https://github.com/pydantic/logfire - stars: 3288 + stars: 3420 owner_login: pydantic owner_html_url: https://github.com/pydantic +- name: farfalle + html_url: https://github.com/rashadphz/farfalle + stars: 3391 + owner_login: rashadphz + owner_html_url: https://github.com/rashadphz +- name: Kokoro-FastAPI + html_url: https://github.com/remsky/Kokoro-FastAPI + stars: 3375 + owner_login: remsky + owner_html_url: https://github.com/remsky +- name: datamodel-code-generator + html_url: https://github.com/koxudaxi/datamodel-code-generator + stars: 3354 + owner_login: koxudaxi + owner_html_url: https://github.com/koxudaxi +- name: fastapi-admin + html_url: https://github.com/fastapi-admin/fastapi-admin + stars: 3353 + owner_login: fastapi-admin + owner_html_url: https://github.com/fastapi-admin - name: huma html_url: https://github.com/danielgtaylor/huma - stars: 3201 + stars: 3277 owner_login: danielgtaylor owner_html_url: https://github.com/danielgtaylor - name: opyrator html_url: https://github.com/ml-tooling/opyrator - stars: 3132 + stars: 3131 owner_login: ml-tooling owner_html_url: https://github.com/ml-tooling -- name: Kokoro-FastAPI - html_url: https://github.com/remsky/Kokoro-FastAPI - stars: 3099 - owner_login: remsky - owner_html_url: https://github.com/remsky - name: docarray html_url: https://github.com/docarray/docarray - stars: 3075 + stars: 3085 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: 2902 - owner_login: nsidnev - owner_html_url: https://github.com/nsidnev - name: tracecat html_url: https://github.com/TracecatHQ/tracecat - stars: 2888 + stars: 2921 owner_login: TracecatHQ owner_html_url: https://github.com/TracecatHQ +- name: fastapi-realworld-example-app + html_url: https://github.com/nsidnev/fastapi-realworld-example-app + stars: 2919 + 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: 2775 + stars: 2789 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: 2537 + stars: 2560 owner_login: ml-tooling owner_html_url: https://github.com/ml-tooling - name: RasaGPT html_url: https://github.com/paulpierre/RasaGPT - stars: 2427 + stars: 2434 owner_login: paulpierre owner_html_url: https://github.com/paulpierre - name: fastapi-react html_url: https://github.com/Buuntu/fastapi-react - stars: 2397 + stars: 2419 owner_login: Buuntu owner_html_url: https://github.com/Buuntu - name: FastAPI-template html_url: https://github.com/s3rius/FastAPI-template - stars: 2334 + stars: 2369 owner_login: s3rius owner_html_url: https://github.com/s3rius - name: nextpy html_url: https://github.com/dot-agent/nextpy - stars: 2295 + stars: 2304 owner_login: dot-agent owner_html_url: https://github.com/dot-agent - name: sqladmin html_url: https://github.com/aminalaee/sqladmin - stars: 2235 + stars: 2272 owner_login: aminalaee owner_html_url: https://github.com/aminalaee - name: 30-Days-of-Python html_url: https://github.com/codingforentrepreneurs/30-Days-of-Python - stars: 2181 + stars: 2192 owner_login: codingforentrepreneurs owner_html_url: https://github.com/codingforentrepreneurs +- name: supabase-py + html_url: https://github.com/supabase/supabase-py + stars: 2141 + owner_login: supabase + owner_html_url: https://github.com/supabase - name: langserve html_url: https://github.com/langchain-ai/langserve - stars: 2119 + stars: 2140 owner_login: langchain-ai owner_html_url: https://github.com/langchain-ai - name: fastapi-utils html_url: https://github.com/fastapiutils/fastapi-utils - stars: 2100 + stars: 2107 owner_login: fastapiutils owner_html_url: https://github.com/fastapiutils -- name: supabase-py - html_url: https://github.com/supabase/supabase-py - stars: 2084 - owner_login: supabase - owner_html_url: https://github.com/supabase - name: solara html_url: https://github.com/widgetti/solara - stars: 2056 + stars: 2063 owner_login: widgetti owner_html_url: https://github.com/widgetti - name: mangum html_url: https://github.com/Kludex/mangum - stars: 1923 + stars: 1943 owner_login: Kludex owner_html_url: https://github.com/Kludex - name: python-week-2022 html_url: https://github.com/rochacbruno/python-week-2022 - stars: 1821 + stars: 1819 owner_login: rochacbruno owner_html_url: https://github.com/rochacbruno - name: agentkit html_url: https://github.com/BCG-X-Official/agentkit - stars: 1765 + stars: 1774 owner_login: BCG-X-Official owner_html_url: https://github.com/BCG-X-Official - name: manage-fastapi html_url: https://github.com/ycd/manage-fastapi - stars: 1756 + stars: 1769 owner_login: ycd owner_html_url: https://github.com/ycd - name: ormar html_url: https://github.com/collerek/ormar - stars: 1755 + stars: 1761 owner_login: collerek owner_html_url: https://github.com/collerek -- name: langchain-serve - html_url: https://github.com/jina-ai/langchain-serve - stars: 1631 - owner_login: jina-ai - owner_html_url: https://github.com/jina-ai - name: piccolo html_url: https://github.com/piccolo-orm/piccolo - stars: 1629 + stars: 1658 owner_login: piccolo-orm owner_html_url: https://github.com/piccolo-orm -- name: termpair - html_url: https://github.com/cs01/termpair - stars: 1616 - owner_login: cs01 - owner_html_url: https://github.com/cs01 +- name: langchain-serve + html_url: https://github.com/jina-ai/langchain-serve + stars: 1632 + owner_login: jina-ai + owner_html_url: https://github.com/jina-ai - name: openapi-python-client html_url: https://github.com/openapi-generators/openapi-python-client - stars: 1603 + stars: 1628 owner_login: openapi-generators owner_html_url: https://github.com/openapi-generators +- name: termpair + html_url: https://github.com/cs01/termpair + stars: 1617 + owner_login: cs01 + owner_html_url: https://github.com/cs01 - name: fastapi-cache html_url: https://github.com/long2ice/fastapi-cache - stars: 1589 + stars: 1607 owner_login: long2ice owner_html_url: https://github.com/long2ice - name: coronavirus-tracker-api @@ -280,137 +285,152 @@ owner_html_url: https://github.com/ExpDev07 - name: slowapi html_url: https://github.com/laurentS/slowapi - stars: 1533 + stars: 1551 owner_login: laurentS owner_html_url: https://github.com/laurentS - name: fastapi-crudrouter html_url: https://github.com/awtkns/fastapi-crudrouter - stars: 1518 + stars: 1522 owner_login: awtkns owner_html_url: https://github.com/awtkns -- name: awesome-fastapi-projects - html_url: https://github.com/Kludex/awesome-fastapi-projects - stars: 1461 - owner_login: Kludex - owner_html_url: https://github.com/Kludex - name: vue-fastapi-admin html_url: https://github.com/mizhexiaoxiao/vue-fastapi-admin - stars: 1409 + stars: 1505 owner_login: mizhexiaoxiao owner_html_url: https://github.com/mizhexiaoxiao +- name: awesome-fastapi-projects + html_url: https://github.com/Kludex/awesome-fastapi-projects + stars: 1468 + owner_login: Kludex + owner_html_url: https://github.com/Kludex - name: awesome-python-resources html_url: https://github.com/DjangoEx/awesome-python-resources - stars: 1393 + stars: 1403 owner_login: DjangoEx owner_html_url: https://github.com/DjangoEx - name: fastapi-pagination html_url: https://github.com/uriyyo/fastapi-pagination - stars: 1378 + stars: 1396 owner_login: uriyyo owner_html_url: https://github.com/uriyyo +- name: FastAPI-boilerplate + html_url: https://github.com/benavlabs/FastAPI-boilerplate + stars: 1378 + owner_login: benavlabs + owner_html_url: https://github.com/benavlabs - name: fastapi-boilerplate html_url: https://github.com/teamhide/fastapi-boilerplate - stars: 1348 + stars: 1373 owner_login: teamhide owner_html_url: https://github.com/teamhide +- name: bracket + html_url: https://github.com/evroon/bracket + stars: 1367 + owner_login: evroon + owner_html_url: https://github.com/evroon - name: budgetml html_url: https://github.com/ebhy/budgetml - stars: 1344 + stars: 1345 owner_login: ebhy owner_html_url: https://github.com/ebhy - name: fastapi-amis-admin html_url: https://github.com/amisadmin/fastapi-amis-admin - stars: 1284 + stars: 1300 owner_login: amisadmin owner_html_url: https://github.com/amisadmin -- name: bracket - html_url: https://github.com/evroon/bracket - stars: 1274 - owner_login: evroon - owner_html_url: https://github.com/evroon - name: fastapi-tutorial html_url: https://github.com/liaogx/fastapi-tutorial - stars: 1265 + stars: 1284 owner_login: liaogx owner_html_url: https://github.com/liaogx - name: fastapi-code-generator html_url: https://github.com/koxudaxi/fastapi-code-generator - stars: 1216 + stars: 1232 owner_login: koxudaxi owner_html_url: https://github.com/koxudaxi -- name: bolt-python - html_url: https://github.com/slackapi/bolt-python - stars: 1190 - owner_login: slackapi - owner_html_url: https://github.com/slackapi - name: fastcrud html_url: https://github.com/benavlabs/fastcrud - stars: 1169 + stars: 1208 owner_login: benavlabs owner_html_url: https://github.com/benavlabs - name: prometheus-fastapi-instrumentator html_url: https://github.com/trallnag/prometheus-fastapi-instrumentator - stars: 1167 + stars: 1200 owner_login: trallnag owner_html_url: https://github.com/trallnag -- name: fastapi_production_template - html_url: https://github.com/zhanymkanov/fastapi_production_template - stars: 1165 - owner_login: zhanymkanov - owner_html_url: https://github.com/zhanymkanov +- name: bolt-python + html_url: https://github.com/slackapi/bolt-python + stars: 1197 + owner_login: slackapi + owner_html_url: https://github.com/slackapi - name: bedrock-chat html_url: https://github.com/aws-samples/bedrock-chat - stars: 1163 + stars: 1188 owner_login: aws-samples owner_html_url: https://github.com/aws-samples -- name: langchain-extract - html_url: https://github.com/langchain-ai/langchain-extract - stars: 1142 - owner_login: langchain-ai - owner_html_url: https://github.com/langchain-ai -- name: odmantic - html_url: https://github.com/art049/odmantic - stars: 1121 - owner_login: art049 - owner_html_url: https://github.com/art049 - name: fastapi_best_architecture html_url: https://github.com/fastapi-practices/fastapi_best_architecture - stars: 1118 + stars: 1178 owner_login: fastapi-practices owner_html_url: https://github.com/fastapi-practices +- name: fastapi_production_template + html_url: https://github.com/zhanymkanov/fastapi_production_template + stars: 1173 + owner_login: zhanymkanov + owner_html_url: https://github.com/zhanymkanov +- name: langchain-extract + html_url: https://github.com/langchain-ai/langchain-extract + stars: 1148 + 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: 1116 + stars: 1134 owner_login: jonra1993 owner_html_url: https://github.com/jonra1993 -- name: FastAPI-boilerplate - html_url: https://github.com/benavlabs/FastAPI-boilerplate - stars: 1070 - owner_login: benavlabs - owner_html_url: https://github.com/benavlabs +- name: odmantic + html_url: https://github.com/art049/odmantic + stars: 1122 + owner_login: art049 + owner_html_url: https://github.com/art049 - name: restish html_url: https://github.com/rest-sh/restish - stars: 1069 + stars: 1088 owner_login: rest-sh owner_html_url: https://github.com/rest-sh +- name: fastapi-scaf + html_url: https://github.com/atpuxiner/fastapi-scaf + stars: 1061 + owner_login: atpuxiner + owner_html_url: https://github.com/atpuxiner - name: runhouse html_url: https://github.com/run-house/runhouse - stars: 1037 + stars: 1041 owner_login: run-house owner_html_url: https://github.com/run-house +- name: fastapi-langgraph-agent-production-ready-template + html_url: https://github.com/wassim249/fastapi-langgraph-agent-production-ready-template + stars: 1037 + owner_login: wassim249 + owner_html_url: https://github.com/wassim249 - name: autollm html_url: https://github.com/viddexa/autollm - stars: 994 + stars: 997 owner_login: viddexa owner_html_url: https://github.com/viddexa - name: lanarky html_url: https://github.com/ajndkr/lanarky - stars: 992 + stars: 994 owner_login: ajndkr owner_html_url: https://github.com/ajndkr +- name: mcp-context-forge + html_url: https://github.com/IBM/mcp-context-forge + stars: 981 + owner_login: IBM + owner_html_url: https://github.com/IBM - name: authx html_url: https://github.com/yezz123/authx - stars: 953 + stars: 967 owner_login: yezz123 owner_html_url: https://github.com/yezz123 - name: secure @@ -418,78 +438,58 @@ stars: 941 owner_login: TypeError owner_html_url: https://github.com/TypeError +- name: flock + html_url: https://github.com/Onelevenvy/flock + stars: 937 + owner_login: Onelevenvy + owner_html_url: https://github.com/Onelevenvy - name: energy-forecasting html_url: https://github.com/iusztinpaul/energy-forecasting - stars: 928 + stars: 934 owner_login: iusztinpaul owner_html_url: https://github.com/iusztinpaul - name: langcorn html_url: https://github.com/msoedov/langcorn - stars: 927 + stars: 932 owner_login: msoedov owner_html_url: https://github.com/msoedov - name: titiler html_url: https://github.com/developmentseed/titiler - stars: 901 + stars: 917 owner_login: developmentseed owner_html_url: https://github.com/developmentseed -- name: flock - html_url: https://github.com/Onelevenvy/flock - stars: 896 - owner_login: Onelevenvy - owner_html_url: https://github.com/Onelevenvy -- name: fastapi-langgraph-agent-production-ready-template - html_url: https://github.com/wassim249/fastapi-langgraph-agent-production-ready-template - stars: 896 - owner_login: wassim249 - owner_html_url: https://github.com/wassim249 - name: marker-api html_url: https://github.com/adithya-s-k/marker-api - stars: 875 + stars: 880 owner_login: adithya-s-k owner_html_url: https://github.com/adithya-s-k - name: httpdbg html_url: https://github.com/cle-b/httpdbg - stars: 870 + stars: 875 owner_login: cle-b owner_html_url: https://github.com/cle-b - name: fastapi-do-zero html_url: https://github.com/dunossauro/fastapi-do-zero - stars: 855 + stars: 873 owner_login: dunossauro owner_html_url: https://github.com/dunossauro -- name: ludic - html_url: https://github.com/getludic/ludic - stars: 849 - owner_login: getludic - owner_html_url: https://github.com/getludic - name: fastapi-observability html_url: https://github.com/blueswen/fastapi-observability - stars: 837 + stars: 861 owner_login: blueswen owner_html_url: https://github.com/blueswen -- name: fastapi-scaf - html_url: https://github.com/atpuxiner/fastapi-scaf - stars: 821 - owner_login: atpuxiner - owner_html_url: https://github.com/atpuxiner -- name: starlette-admin - html_url: https://github.com/jowilf/starlette-admin - stars: 808 - owner_login: jowilf - owner_html_url: https://github.com/jowilf -- name: fastapi-mail - html_url: https://github.com/sabuhish/fastapi-mail - stars: 807 - owner_login: sabuhish - owner_html_url: https://github.com/sabuhish +- name: ludic + html_url: https://github.com/getludic/ludic + stars: 854 + owner_login: getludic + owner_html_url: https://github.com/getludic - name: aktools html_url: https://github.com/akfamily/aktools - stars: 796 + stars: 839 owner_login: akfamily owner_html_url: https://github.com/akfamily - name: RuoYi-Vue3-FastAPI html_url: https://github.com/insistence/RuoYi-Vue3-FastAPI - stars: 782 + stars: 836 owner_login: insistence owner_html_url: https://github.com/insistence From 92ea53baca590b7a9a61c4b7f0530a1dc7a68e02 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Fri, 1 Aug 2025 13:19:48 +0000 Subject: [PATCH 40/60] =?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 170e579b5..9b64aeb32 100644 --- a/docs/en/docs/release-notes.md +++ b/docs/en/docs/release-notes.md @@ -23,6 +23,7 @@ hide: ### Internal +* 👥 Update FastAPI GitHub topic repositories. PR [#13962](https://github.com/fastapi/fastapi/pull/13962) by [@tiangolo](https://github.com/tiangolo). * ⬆ Bump mkdocs-material from 9.6.15 to 9.6.16. PR [#13961](https://github.com/fastapi/fastapi/pull/13961) by [@dependabot[bot]](https://github.com/apps/dependabot). * ⬆ Bump tiangolo/latest-changes from 0.3.2 to 0.4.0. PR [#13952](https://github.com/fastapi/fastapi/pull/13952) by [@dependabot[bot]](https://github.com/apps/dependabot). * 👥 Update FastAPI People - Sponsors. PR [#13956](https://github.com/fastapi/fastapi/pull/13956) by [@tiangolo](https://github.com/tiangolo). From b42e28753e4f6b810e9f8a876e02ff6fc1ec434a Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 1 Aug 2025 15:50:16 +0200 Subject: [PATCH 41/60] =?UTF-8?q?=E2=AC=86=20Bump=20pydantic-ai=20from=200?= =?UTF-8?q?.0.30=20to=200.4.10=20(#13958)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Bumps [pydantic-ai](https://github.com/pydantic/pydantic-ai) from 0.0.30 to 0.4.10. - [Release notes](https://github.com/pydantic/pydantic-ai/releases) - [Changelog](https://github.com/pydantic/pydantic-ai/blob/main/docs/changelog.md) - [Commits](https://github.com/pydantic/pydantic-ai/compare/v0.0.30...v0.4.10) --- updated-dependencies: - dependency-name: pydantic-ai dependency-version: 0.4.10 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-translations.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/requirements-translations.txt b/requirements-translations.txt index 90f718032..a62ba3ac1 100644 --- a/requirements-translations.txt +++ b/requirements-translations.txt @@ -1,2 +1,2 @@ -pydantic-ai==0.0.30 +pydantic-ai==0.4.10 GitPython==3.1.45 From 391887db91d9873db6a927b8d905b6d25e7ac882 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Fri, 1 Aug 2025 13:50:42 +0000 Subject: [PATCH 42/60] =?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 9b64aeb32..d4e17f549 100644 --- a/docs/en/docs/release-notes.md +++ b/docs/en/docs/release-notes.md @@ -23,6 +23,7 @@ hide: ### Internal +* ⬆ Bump pydantic-ai from 0.0.30 to 0.4.10. PR [#13958](https://github.com/fastapi/fastapi/pull/13958) by [@dependabot[bot]](https://github.com/apps/dependabot). * 👥 Update FastAPI GitHub topic repositories. PR [#13962](https://github.com/fastapi/fastapi/pull/13962) by [@tiangolo](https://github.com/tiangolo). * ⬆ Bump mkdocs-material from 9.6.15 to 9.6.16. PR [#13961](https://github.com/fastapi/fastapi/pull/13961) by [@dependabot[bot]](https://github.com/apps/dependabot). * ⬆ Bump tiangolo/latest-changes from 0.3.2 to 0.4.0. PR [#13952](https://github.com/fastapi/fastapi/pull/13952) by [@dependabot[bot]](https://github.com/apps/dependabot). From f8013621ccfff954fba1061c13dde96105ec221c Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 1 Aug 2025 16:06:33 +0200 Subject: [PATCH 43/60] =?UTF-8?q?=E2=AC=86=20Bump=20cairosvg=20from=202.7.?= =?UTF-8?q?1=20to=202.8.2=20(#13959)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Bumps [cairosvg](https://github.com/Kozea/CairoSVG) from 2.7.1 to 2.8.2. - [Release notes](https://github.com/Kozea/CairoSVG/releases) - [Changelog](https://github.com/Kozea/CairoSVG/blob/main/NEWS.rst) - [Commits](https://github.com/Kozea/CairoSVG/compare/2.7.1...2.8.2) --- updated-dependencies: - dependency-name: cairosvg dependency-version: 2.8.2 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.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/requirements-docs.txt b/requirements-docs.txt index 4713d187e..eeb41b5ce 100644 --- a/requirements-docs.txt +++ b/requirements-docs.txt @@ -10,7 +10,7 @@ jieba==0.42.1 # For image processing by Material for MkDocs pillow==11.3.0 # For image processing by Material for MkDocs -cairosvg==2.7.1 +cairosvg==2.8.2 mkdocstrings[python]==0.26.1 griffe-typingdoc==0.2.8 # For griffe, it formats with black From 37dd99ffe39356e2263bc8f0ab006560184db740 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Fri, 1 Aug 2025 14:06:58 +0000 Subject: [PATCH 44/60] =?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 d4e17f549..c76b31323 100644 --- a/docs/en/docs/release-notes.md +++ b/docs/en/docs/release-notes.md @@ -23,6 +23,7 @@ hide: ### Internal +* ⬆ Bump cairosvg from 2.7.1 to 2.8.2. PR [#13959](https://github.com/fastapi/fastapi/pull/13959) by [@dependabot[bot]](https://github.com/apps/dependabot). * ⬆ Bump pydantic-ai from 0.0.30 to 0.4.10. PR [#13958](https://github.com/fastapi/fastapi/pull/13958) by [@dependabot[bot]](https://github.com/apps/dependabot). * 👥 Update FastAPI GitHub topic repositories. PR [#13962](https://github.com/fastapi/fastapi/pull/13962) by [@tiangolo](https://github.com/tiangolo). * ⬆ Bump mkdocs-material from 9.6.15 to 9.6.16. PR [#13961](https://github.com/fastapi/fastapi/pull/13961) by [@dependabot[bot]](https://github.com/apps/dependabot). From 11893d9cea2d8dabcc5dc9071624f64c0a11a5e8 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 1 Aug 2025 16:09:11 +0200 Subject: [PATCH 45/60] =?UTF-8?q?=E2=AC=86=20Bump=20ruff=20from=200.11.2?= =?UTF-8?q?=20to=200.12.7=20(#13957)?= 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.11.2 to 0.12.7. - [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.11.2...0.12.7) --- updated-dependencies: - dependency-name: ruff dependency-version: 0.12.7 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 e7684a2e3..f9a490975 100644 --- a/requirements-docs-tests.txt +++ b/requirements-docs-tests.txt @@ -1,4 +1,4 @@ # For mkdocstrings and tests httpx >=0.23.0,<0.29.0 # For linting and generating docs versions -ruff ==0.11.2 +ruff ==0.12.7 From c40bd0e426ee803ef56be9848276e86ab3d603dc Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Fri, 1 Aug 2025 14:09:56 +0000 Subject: [PATCH 46/60] =?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 c76b31323..bb228270c 100644 --- a/docs/en/docs/release-notes.md +++ b/docs/en/docs/release-notes.md @@ -23,6 +23,7 @@ hide: ### Internal +* ⬆ Bump ruff from 0.11.2 to 0.12.7. PR [#13957](https://github.com/fastapi/fastapi/pull/13957) by [@dependabot[bot]](https://github.com/apps/dependabot). * ⬆ Bump cairosvg from 2.7.1 to 2.8.2. PR [#13959](https://github.com/fastapi/fastapi/pull/13959) by [@dependabot[bot]](https://github.com/apps/dependabot). * ⬆ Bump pydantic-ai from 0.0.30 to 0.4.10. PR [#13958](https://github.com/fastapi/fastapi/pull/13958) by [@dependabot[bot]](https://github.com/apps/dependabot). * 👥 Update FastAPI GitHub topic repositories. PR [#13962](https://github.com/fastapi/fastapi/pull/13962) by [@tiangolo](https://github.com/tiangolo). From f736e48ab3e46684bf379407e27a1bd7f300a865 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebasti=C3=A1n=20Ram=C3=ADrez?= Date: Fri, 1 Aug 2025 16:32:33 +0200 Subject: [PATCH 47/60] =?UTF-8?q?=F0=9F=91=A5=20Update=20FastAPI=20People?= =?UTF-8?q?=20-=20Experts=20(#13963)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: github-actions --- docs/en/data/people.yml | 294 +++++++++++++++++++--------------------- 1 file changed, 143 insertions(+), 151 deletions(-) diff --git a/docs/en/data/people.yml b/docs/en/data/people.yml index e3eab5d01..714d2eac7 100644 --- a/docs/en/data/people.yml +++ b/docs/en/data/people.yml @@ -9,8 +9,8 @@ experts: avatarUrl: https://avatars.githubusercontent.com/u/1326112?u=cb5d06e73a9e1998141b1641aa88e443c6717651&v=4 url: https://github.com/tiangolo - login: YuriiMotov - count: 941 - avatarUrl: https://avatars.githubusercontent.com/u/109919500?u=e83a39697a2d33ab2ec9bfbced794ee48bc29cec&v=4 + count: 952 + avatarUrl: https://avatars.githubusercontent.com/u/109919500?u=b9b13d598dddfab529a52d264df80a900bfe7060&v=4 url: https://github.com/YuriiMotov - login: github-actions count: 769 @@ -53,11 +53,11 @@ experts: avatarUrl: https://avatars.githubusercontent.com/u/331403?v=4 url: https://github.com/phy25 - login: JavierSanchezCastro - count: 93 + count: 94 avatarUrl: https://avatars.githubusercontent.com/u/72013291?u=ae5679e6bd971d9d98cd5e76e8683f83642ba950&v=4 url: https://github.com/JavierSanchezCastro - login: luzzodev - count: 84 + count: 87 avatarUrl: https://avatars.githubusercontent.com/u/27291415?u=5607ae1ce75c5f54f09500ca854227f7bfd2033b&v=4 url: https://github.com/luzzodev - login: raphaelauv @@ -192,6 +192,14 @@ experts: count: 19 avatarUrl: https://avatars.githubusercontent.com/u/10840422?u=45f015f95e1c0f06df602be4ab688d4b854cc8a8&v=4 url: https://github.com/estebanx64 +- login: valentinDruzhinin + count: 19 + avatarUrl: https://avatars.githubusercontent.com/u/12831905?u=aae1ebc675c91e8fa582df4fcc4fc4128106344d&v=4 + url: https://github.com/valentinDruzhinin +- login: sehraramiz + count: 18 + avatarUrl: https://avatars.githubusercontent.com/u/14166324?u=8fac65e84dfff24245d304a5b5b09f7b5bd69dc9&v=4 + url: https://github.com/sehraramiz - login: retnikt count: 18 avatarUrl: https://avatars.githubusercontent.com/u/24581770?v=4 @@ -200,10 +208,6 @@ experts: count: 18 avatarUrl: https://avatars.githubusercontent.com/u/22326718?u=31ba446ac290e23e56eea8e4f0c558aaf0b40779&v=4 url: https://github.com/zoliknemet -- login: sehraramiz - count: 18 - avatarUrl: https://avatars.githubusercontent.com/u/14166324?u=8fac65e84dfff24245d304a5b5b09f7b5bd69dc9&v=4 - url: https://github.com/sehraramiz - login: Hultner count: 17 avatarUrl: https://avatars.githubusercontent.com/u/2669034?u=115e53df959309898ad8dc9443fbb35fee71df07&v=4 @@ -228,6 +232,10 @@ experts: count: 16 avatarUrl: https://avatars.githubusercontent.com/u/26334101?u=f601c3f111f2148bd9244c2cb3ebbd57b592e674&v=4 url: https://github.com/jonatasoli +- login: abhint + count: 15 + avatarUrl: https://avatars.githubusercontent.com/u/25699289?u=b5d219277b4d001ac26fb8be357fddd88c29d51b&v=4 + url: https://github.com/abhint - login: ghost count: 15 avatarUrl: https://avatars.githubusercontent.com/u/10137?u=b1951d34a583cf12ec0d3b0781ba19be97726318&v=4 @@ -236,76 +244,52 @@ experts: count: 15 avatarUrl: https://avatars.githubusercontent.com/u/12537771?u=7444d20019198e34911082780cc7ad73f2b97cb3&v=4 url: https://github.com/jorgerpo -- login: pythonweb2 - count: 15 - avatarUrl: https://avatars.githubusercontent.com/u/32141163?v=4 - url: https://github.com/pythonweb2 -- login: abhint - count: 15 - avatarUrl: https://avatars.githubusercontent.com/u/25699289?u=b5d219277b4d001ac26fb8be357fddd88c29d51b&v=4 - url: https://github.com/abhint last_month_experts: - login: YuriiMotov - count: 289 - avatarUrl: https://avatars.githubusercontent.com/u/109919500?u=e83a39697a2d33ab2ec9bfbced794ee48bc29cec&v=4 + count: 69 + avatarUrl: https://avatars.githubusercontent.com/u/109919500?u=b9b13d598dddfab529a52d264df80a900bfe7060&v=4 url: https://github.com/YuriiMotov - login: luzzodev - count: 12 + count: 8 avatarUrl: https://avatars.githubusercontent.com/u/27291415?u=5607ae1ce75c5f54f09500ca854227f7bfd2033b&v=4 url: https://github.com/luzzodev -- login: raceychan - count: 6 - avatarUrl: https://avatars.githubusercontent.com/u/75417963?u=060c62870ec5a791765e63ac20d8885d11143786&v=4 - url: https://github.com/raceychan - login: valentinDruzhinin - count: 5 + count: 7 avatarUrl: https://avatars.githubusercontent.com/u/12831905?u=aae1ebc675c91e8fa582df4fcc4fc4128106344d&v=4 url: https://github.com/valentinDruzhinin -- login: DoctorJohn - count: 5 - avatarUrl: https://avatars.githubusercontent.com/u/14076775?u=2913e70a6142772847e91e2aaa5b9152391715e9&v=4 - url: https://github.com/DoctorJohn - login: eqsdxr count: 4 avatarUrl: https://avatars.githubusercontent.com/u/157279130?u=58fddf77ed76966eaa8c73eea9bea4bb0c53b673&v=4 url: https://github.com/eqsdxr -- login: sachinh35 - count: 4 - avatarUrl: https://avatars.githubusercontent.com/u/21972708?u=8560b97b8b41e175f476270b56de8a493b84f302&v=4 - url: https://github.com/sachinh35 -- login: tiangolo - count: 2 - avatarUrl: https://avatars.githubusercontent.com/u/1326112?u=cb5d06e73a9e1998141b1641aa88e443c6717651&v=4 - url: https://github.com/tiangolo -- login: Brikas - count: 2 - avatarUrl: https://avatars.githubusercontent.com/u/80290187?v=4 - url: https://github.com/Brikas -- login: TaigoFr +- login: Jelle-tenB + count: 3 + avatarUrl: https://avatars.githubusercontent.com/u/210023470?u=c25d66addf36a747bd9fab773c4a6e7b238f45d4&v=4 + url: https://github.com/Jelle-tenB +- login: Garrett-R count: 2 - avatarUrl: https://avatars.githubusercontent.com/u/17792131?u=372b27056ec82f1ae03d8b3f37ef55b04a7cfdd1&v=4 - url: https://github.com/TaigoFr + avatarUrl: https://avatars.githubusercontent.com/u/6614695?u=c128fd775002882f6e391bda5a89d1bdc5bdf45f&v=4 + url: https://github.com/Garrett-R three_months_experts: - login: YuriiMotov - count: 732 - avatarUrl: https://avatars.githubusercontent.com/u/109919500?u=e83a39697a2d33ab2ec9bfbced794ee48bc29cec&v=4 + count: 736 + avatarUrl: https://avatars.githubusercontent.com/u/109919500?u=b9b13d598dddfab529a52d264df80a900bfe7060&v=4 url: https://github.com/YuriiMotov - login: luzzodev - count: 26 + count: 27 avatarUrl: https://avatars.githubusercontent.com/u/27291415?u=5607ae1ce75c5f54f09500ca854227f7bfd2033b&v=4 url: https://github.com/luzzodev - login: valentinDruzhinin - count: 14 + count: 19 avatarUrl: https://avatars.githubusercontent.com/u/12831905?u=aae1ebc675c91e8fa582df4fcc4fc4128106344d&v=4 url: https://github.com/valentinDruzhinin -- login: sachinh35 - count: 8 - avatarUrl: https://avatars.githubusercontent.com/u/21972708?u=8560b97b8b41e175f476270b56de8a493b84f302&v=4 - url: https://github.com/sachinh35 - login: raceychan count: 6 avatarUrl: https://avatars.githubusercontent.com/u/75417963?u=060c62870ec5a791765e63ac20d8885d11143786&v=4 url: https://github.com/raceychan +- login: sachinh35 + count: 6 + avatarUrl: https://avatars.githubusercontent.com/u/21972708?u=8560b97b8b41e175f476270b56de8a493b84f302&v=4 + url: https://github.com/sachinh35 - login: DoctorJohn count: 5 avatarUrl: https://avatars.githubusercontent.com/u/14076775?u=2913e70a6142772847e91e2aaa5b9152391715e9&v=4 @@ -314,14 +298,30 @@ three_months_experts: count: 4 avatarUrl: https://avatars.githubusercontent.com/u/157279130?u=58fddf77ed76966eaa8c73eea9bea4bb0c53b673&v=4 url: https://github.com/eqsdxr +- login: Jelle-tenB + count: 3 + avatarUrl: https://avatars.githubusercontent.com/u/210023470?u=c25d66addf36a747bd9fab773c4a6e7b238f45d4&v=4 + url: https://github.com/Jelle-tenB +- login: JavierSanchezCastro + count: 3 + avatarUrl: https://avatars.githubusercontent.com/u/72013291?u=ae5679e6bd971d9d98cd5e76e8683f83642ba950&v=4 + url: https://github.com/JavierSanchezCastro +- login: purepani + count: 2 + avatarUrl: https://avatars.githubusercontent.com/u/7587353?v=4 + url: https://github.com/purepani - login: tiangolo count: 2 avatarUrl: https://avatars.githubusercontent.com/u/1326112?u=cb5d06e73a9e1998141b1641aa88e443c6717651&v=4 url: https://github.com/tiangolo -- login: JavierSanchezCastro +- login: TaigoFr count: 2 - avatarUrl: https://avatars.githubusercontent.com/u/72013291?u=ae5679e6bd971d9d98cd5e76e8683f83642ba950&v=4 - url: https://github.com/JavierSanchezCastro + avatarUrl: https://avatars.githubusercontent.com/u/17792131?u=372b27056ec82f1ae03d8b3f37ef55b04a7cfdd1&v=4 + url: https://github.com/TaigoFr +- login: Garrett-R + count: 2 + avatarUrl: https://avatars.githubusercontent.com/u/6614695?u=c128fd775002882f6e391bda5a89d1bdc5bdf45f&v=4 + url: https://github.com/Garrett-R - login: henrymcl count: 2 avatarUrl: https://avatars.githubusercontent.com/u/26480299?v=4 @@ -334,47 +334,39 @@ three_months_experts: count: 2 avatarUrl: https://avatars.githubusercontent.com/u/80290187?v=4 url: https://github.com/Brikas -- login: TaigoFr - count: 2 - avatarUrl: https://avatars.githubusercontent.com/u/17792131?u=372b27056ec82f1ae03d8b3f37ef55b04a7cfdd1&v=4 - url: https://github.com/TaigoFr - login: davidhuser count: 2 avatarUrl: https://avatars.githubusercontent.com/u/4357648?u=6ed702f8f6d49a8b2a0ed33cbd8ab59c2d7db7f7&v=4 url: https://github.com/davidhuser -- login: KianAnbarestani - count: 2 - avatarUrl: https://avatars.githubusercontent.com/u/145364424?u=dcc3d8fb4ca07d36fb52a17f38b6650565de40be&v=4 - url: https://github.com/KianAnbarestani - login: Kludex count: 2 avatarUrl: https://avatars.githubusercontent.com/u/7353520?u=df8a3f06ba8f55ae1967a3e2d5ed882903a4e330&v=4 url: https://github.com/Kludex six_months_experts: - login: YuriiMotov - count: 749 - avatarUrl: https://avatars.githubusercontent.com/u/109919500?u=e83a39697a2d33ab2ec9bfbced794ee48bc29cec&v=4 + count: 754 + avatarUrl: https://avatars.githubusercontent.com/u/109919500?u=b9b13d598dddfab529a52d264df80a900bfe7060&v=4 url: https://github.com/YuriiMotov - login: luzzodev count: 51 avatarUrl: https://avatars.githubusercontent.com/u/27291415?u=5607ae1ce75c5f54f09500ca854227f7bfd2033b&v=4 url: https://github.com/luzzodev - login: alv2017 - count: 26 + count: 23 avatarUrl: https://avatars.githubusercontent.com/u/31544722?v=4 url: https://github.com/alv2017 -- login: Kludex - count: 20 - avatarUrl: https://avatars.githubusercontent.com/u/7353520?u=df8a3f06ba8f55ae1967a3e2d5ed882903a4e330&v=4 - url: https://github.com/Kludex - login: valentinDruzhinin - count: 14 + count: 19 avatarUrl: https://avatars.githubusercontent.com/u/12831905?u=aae1ebc675c91e8fa582df4fcc4fc4128106344d&v=4 url: https://github.com/valentinDruzhinin - login: jgould22 count: 13 avatarUrl: https://avatars.githubusercontent.com/u/4335847?u=ed77f67e0bb069084639b24d812dbb2a2b1dc554&v=4 url: https://github.com/jgould22 +- login: Kludex + count: 11 + avatarUrl: https://avatars.githubusercontent.com/u/7353520?u=df8a3f06ba8f55ae1967a3e2d5ed882903a4e330&v=4 + url: https://github.com/Kludex - login: JavierSanchezCastro count: 10 avatarUrl: https://avatars.githubusercontent.com/u/72013291?u=ae5679e6bd971d9d98cd5e76e8683f83642ba950&v=4 @@ -399,18 +391,34 @@ six_months_experts: count: 5 avatarUrl: https://avatars.githubusercontent.com/u/14076775?u=2913e70a6142772847e91e2aaa5b9152391715e9&v=4 url: https://github.com/DoctorJohn -- login: sehraramiz - count: 5 - avatarUrl: https://avatars.githubusercontent.com/u/14166324?u=8fac65e84dfff24245d304a5b5b09f7b5bd69dc9&v=4 - url: https://github.com/sehraramiz - login: eqsdxr count: 4 avatarUrl: https://avatars.githubusercontent.com/u/157279130?u=58fddf77ed76966eaa8c73eea9bea4bb0c53b673&v=4 url: https://github.com/eqsdxr +- login: Jelle-tenB + count: 3 + avatarUrl: https://avatars.githubusercontent.com/u/210023470?u=c25d66addf36a747bd9fab773c4a6e7b238f45d4&v=4 + url: https://github.com/Jelle-tenB - login: SobikXexe count: 3 avatarUrl: https://avatars.githubusercontent.com/u/87701130?v=4 url: https://github.com/SobikXexe +- login: purepani + count: 2 + avatarUrl: https://avatars.githubusercontent.com/u/7587353?v=4 + url: https://github.com/purepani +- login: WilliamDEdwards + count: 2 + avatarUrl: https://avatars.githubusercontent.com/u/12184311?u=9b29d5d1d71f5f1a7ef9e439963ad3529e3b33a4&v=4 + url: https://github.com/WilliamDEdwards +- login: TaigoFr + count: 2 + avatarUrl: https://avatars.githubusercontent.com/u/17792131?u=372b27056ec82f1ae03d8b3f37ef55b04a7cfdd1&v=4 + url: https://github.com/TaigoFr +- login: Garrett-R + count: 2 + avatarUrl: https://avatars.githubusercontent.com/u/6614695?u=c128fd775002882f6e391bda5a89d1bdc5bdf45f&v=4 + url: https://github.com/Garrett-R - login: EverStarck count: 2 avatarUrl: https://avatars.githubusercontent.com/u/51029456?u=343409b7cb6b3ea6a59359f4e8370d9c3f140ecd&v=4 @@ -435,10 +443,6 @@ six_months_experts: count: 2 avatarUrl: https://avatars.githubusercontent.com/u/2555532?u=354a525847a276bbb4426b0c95791a8ba5970f9b&v=4 url: https://github.com/JacobHayes -- login: TaigoFr - count: 2 - avatarUrl: https://avatars.githubusercontent.com/u/17792131?u=372b27056ec82f1ae03d8b3f37ef55b04a7cfdd1&v=4 - url: https://github.com/TaigoFr - login: davidhuser count: 2 avatarUrl: https://avatars.githubusercontent.com/u/4357648?u=6ed702f8f6d49a8b2a0ed33cbd8ab59c2d7db7f7&v=4 @@ -451,10 +455,6 @@ six_months_experts: count: 2 avatarUrl: https://avatars.githubusercontent.com/u/145364424?u=dcc3d8fb4ca07d36fb52a17f38b6650565de40be&v=4 url: https://github.com/KianAnbarestani -- login: Ykaiqx - count: 2 - avatarUrl: https://avatars.githubusercontent.com/u/56395004?u=1eebf5ce25a8067f7bfa6251a24f667be492d9d6&v=4 - url: https://github.com/Ykaiqx - login: sinisaos count: 2 avatarUrl: https://avatars.githubusercontent.com/u/30960668?v=4 @@ -463,71 +463,63 @@ six_months_experts: count: 2 avatarUrl: https://avatars.githubusercontent.com/u/64859146?u=d52a6ecf8d83d2927e2ae270bdfcc83495dba8c9&v=4 url: https://github.com/Ale-Cas -- login: nbx3 - count: 2 - avatarUrl: https://avatars.githubusercontent.com/u/34649527?u=943812f69e0d40adbd3fa1c9b8ef50dd971a2a45&v=4 - url: https://github.com/nbx3 - login: marsboy02 count: 2 - avatarUrl: https://avatars.githubusercontent.com/u/86903678?u=efe3aa9e4b22689df7633a96328fb35bf4a23905&v=4 + avatarUrl: https://avatars.githubusercontent.com/u/86903678?u=04cc319d6605f8d1ba3a0bed9f4f55a582719ae6&v=4 url: https://github.com/marsboy02 - login: vtgn count: 2 avatarUrl: https://avatars.githubusercontent.com/u/112889052?v=4 url: https://github.com/vtgn -- login: Trinkes - count: 2 - avatarUrl: https://avatars.githubusercontent.com/u/9466879?v=4 - url: https://github.com/Trinkes one_year_experts: - login: YuriiMotov - count: 831 - avatarUrl: https://avatars.githubusercontent.com/u/109919500?u=e83a39697a2d33ab2ec9bfbced794ee48bc29cec&v=4 + count: 820 + avatarUrl: https://avatars.githubusercontent.com/u/109919500?u=b9b13d598dddfab529a52d264df80a900bfe7060&v=4 url: https://github.com/YuriiMotov - login: luzzodev - count: 84 + count: 87 avatarUrl: https://avatars.githubusercontent.com/u/27291415?u=5607ae1ce75c5f54f09500ca854227f7bfd2033b&v=4 url: https://github.com/luzzodev - login: Kludex - count: 55 + count: 51 avatarUrl: https://avatars.githubusercontent.com/u/7353520?u=df8a3f06ba8f55ae1967a3e2d5ed882903a4e330&v=4 url: https://github.com/Kludex - login: sinisaos - count: 41 + count: 39 avatarUrl: https://avatars.githubusercontent.com/u/30960668?v=4 url: https://github.com/sinisaos +- login: JavierSanchezCastro + count: 26 + avatarUrl: https://avatars.githubusercontent.com/u/72013291?u=ae5679e6bd971d9d98cd5e76e8683f83642ba950&v=4 + url: https://github.com/JavierSanchezCastro - login: alv2017 count: 26 avatarUrl: https://avatars.githubusercontent.com/u/31544722?v=4 url: https://github.com/alv2017 -- login: JavierSanchezCastro - count: 25 - avatarUrl: https://avatars.githubusercontent.com/u/72013291?u=ae5679e6bd971d9d98cd5e76e8683f83642ba950&v=4 - url: https://github.com/JavierSanchezCastro - login: tiangolo - count: 22 + count: 21 avatarUrl: https://avatars.githubusercontent.com/u/1326112?u=cb5d06e73a9e1998141b1641aa88e443c6717651&v=4 url: https://github.com/tiangolo +- login: valentinDruzhinin + count: 19 + avatarUrl: https://avatars.githubusercontent.com/u/12831905?u=aae1ebc675c91e8fa582df4fcc4fc4128106344d&v=4 + url: https://github.com/valentinDruzhinin - login: jgould22 count: 17 avatarUrl: https://avatars.githubusercontent.com/u/4335847?u=ed77f67e0bb069084639b24d812dbb2a2b1dc554&v=4 url: https://github.com/jgould22 -- login: valentinDruzhinin - count: 14 - avatarUrl: https://avatars.githubusercontent.com/u/12831905?u=aae1ebc675c91e8fa582df4fcc4fc4128106344d&v=4 - url: https://github.com/valentinDruzhinin - login: Kfir-G count: 13 avatarUrl: https://avatars.githubusercontent.com/u/57500876?u=0cd29db046a17f12f382d398141319fca7ff230a&v=4 url: https://github.com/Kfir-G -- login: estebanx64 - count: 11 - avatarUrl: https://avatars.githubusercontent.com/u/10840422?u=45f015f95e1c0f06df602be4ab688d4b854cc8a8&v=4 - url: https://github.com/estebanx64 - login: sehraramiz count: 11 avatarUrl: https://avatars.githubusercontent.com/u/14166324?u=8fac65e84dfff24245d304a5b5b09f7b5bd69dc9&v=4 url: https://github.com/sehraramiz +- login: estebanx64 + count: 10 + avatarUrl: https://avatars.githubusercontent.com/u/10840422?u=45f015f95e1c0f06df602be4ab688d4b854cc8a8&v=4 + url: https://github.com/estebanx64 - login: ceb10n count: 10 avatarUrl: https://avatars.githubusercontent.com/u/235213?u=edcce471814a1eba9f0cdaa4cd0de18921a940a6&v=4 @@ -541,7 +533,7 @@ one_year_experts: avatarUrl: https://avatars.githubusercontent.com/u/51629535?u=fc1817060daf2df438bfca86c44f33da5cd667db&v=4 url: https://github.com/yauhen-sobaleu - login: n8sty - count: 8 + count: 7 avatarUrl: https://avatars.githubusercontent.com/u/2964996?v=4 url: https://github.com/n8sty - login: yvallois @@ -556,10 +548,6 @@ one_year_experts: count: 5 avatarUrl: https://avatars.githubusercontent.com/u/14076775?u=2913e70a6142772847e91e2aaa5b9152391715e9&v=4 url: https://github.com/DoctorJohn -- login: AIdjis - count: 5 - avatarUrl: https://avatars.githubusercontent.com/u/88404339?u=2a80d80b054e9228391e32fb9bb39571509dab6a&v=4 - url: https://github.com/AIdjis - login: eqsdxr count: 4 avatarUrl: https://avatars.githubusercontent.com/u/157279130?u=58fddf77ed76966eaa8c73eea9bea4bb0c53b673&v=4 @@ -572,10 +560,6 @@ one_year_experts: count: 4 avatarUrl: https://avatars.githubusercontent.com/u/71908316?u=4ba43bd63c169b5c015137d8916752a44001445a&v=4 url: https://github.com/yokwejuste -- login: PhysicallyActive - count: 4 - avatarUrl: https://avatars.githubusercontent.com/u/160476156?u=7a8e44f4a43d3bba636f795bb7d9476c9233b4d8&v=4 - url: https://github.com/PhysicallyActive - login: svlandeg count: 4 avatarUrl: https://avatars.githubusercontent.com/u/8796347?u=556c97650c27021911b0b9447ec55e75987b0e8a&v=4 @@ -584,13 +568,17 @@ one_year_experts: count: 3 avatarUrl: https://avatars.githubusercontent.com/u/3409962?u=d22ea18aa8ea688af25a45df306134d593621a44&v=4 url: https://github.com/mattmess1221 +- login: Jelle-tenB + count: 3 + avatarUrl: https://avatars.githubusercontent.com/u/210023470?u=c25d66addf36a747bd9fab773c4a6e7b238f45d4&v=4 + url: https://github.com/Jelle-tenB - login: pythonweb2 count: 3 avatarUrl: https://avatars.githubusercontent.com/u/32141163?v=4 url: https://github.com/pythonweb2 - login: viniciusCalcantara count: 3 - avatarUrl: https://avatars.githubusercontent.com/u/108818737?u=3d7ffe5808843ee4372f9cc5a559ff1674cf1792&v=4 + avatarUrl: https://avatars.githubusercontent.com/u/108818737?u=80f3ec7427fa6a41d5896984d0c526432f2299fa&v=4 url: https://github.com/viniciusCalcantara - login: davidhuser count: 3 @@ -604,14 +592,14 @@ one_year_experts: count: 3 avatarUrl: https://avatars.githubusercontent.com/u/9778569?u=f2f1e9135b5e4f1b0c6821a548b17f97572720fc&v=4 url: https://github.com/dbfreem +- login: PhysicallyActive + count: 3 + avatarUrl: https://avatars.githubusercontent.com/u/160476156?u=7a8e44f4a43d3bba636f795bb7d9476c9233b4d8&v=4 + url: https://github.com/PhysicallyActive - login: SobikXexe count: 3 avatarUrl: https://avatars.githubusercontent.com/u/87701130?v=4 url: https://github.com/SobikXexe -- login: DeoLeung - count: 3 - avatarUrl: https://avatars.githubusercontent.com/u/3764720?u=4c222ef513814de4c7fb3736d0a7adf11d953d43&v=4 - url: https://github.com/DeoLeung - login: pawelad count: 3 avatarUrl: https://avatars.githubusercontent.com/u/7062874?u=d27dc220545a8401ad21840590a97d474d7101e6&v=4 @@ -624,10 +612,42 @@ one_year_experts: count: 3 avatarUrl: https://avatars.githubusercontent.com/u/8108085?u=b028dbc308fa8485e0e2e9402b3d03d8deb22bf9&v=4 url: https://github.com/Minibrams +- login: AIdjis + count: 3 + avatarUrl: https://avatars.githubusercontent.com/u/88404339?u=2a80d80b054e9228391e32fb9bb39571509dab6a&v=4 + url: https://github.com/AIdjis +- login: dolfinus + count: 2 + avatarUrl: https://avatars.githubusercontent.com/u/4661021?u=ed5ddadcf36d9b943ebe61febe0b96ee34e5425d&v=4 + url: https://github.com/dolfinus +- login: slafs + count: 2 + avatarUrl: https://avatars.githubusercontent.com/u/210173?v=4 + url: https://github.com/slafs +- login: purepani + count: 2 + avatarUrl: https://avatars.githubusercontent.com/u/7587353?v=4 + url: https://github.com/purepani +- login: ddahan + count: 2 + avatarUrl: https://avatars.githubusercontent.com/u/1933516?u=1d200a620e8d6841df017e9f2bb7efb58b580f40&v=4 + url: https://github.com/ddahan - login: yanggeorge count: 2 avatarUrl: https://avatars.githubusercontent.com/u/2434407?v=4 url: https://github.com/yanggeorge +- login: WilliamDEdwards + count: 2 + avatarUrl: https://avatars.githubusercontent.com/u/12184311?u=9b29d5d1d71f5f1a7ef9e439963ad3529e3b33a4&v=4 + url: https://github.com/WilliamDEdwards +- login: TaigoFr + count: 2 + avatarUrl: https://avatars.githubusercontent.com/u/17792131?u=372b27056ec82f1ae03d8b3f37ef55b04a7cfdd1&v=4 + url: https://github.com/TaigoFr +- login: Garrett-R + count: 2 + avatarUrl: https://avatars.githubusercontent.com/u/6614695?u=c128fd775002882f6e391bda5a89d1bdc5bdf45f&v=4 + url: https://github.com/Garrett-R - login: mmzeynalli count: 2 avatarUrl: https://avatars.githubusercontent.com/u/33568903?u=19efd0c0722730b83a70b7c86c36e5b7d83e07d2&v=4 @@ -640,10 +660,6 @@ one_year_experts: count: 2 avatarUrl: https://avatars.githubusercontent.com/u/51029456?u=343409b7cb6b3ea6a59359f4e8370d9c3f140ecd&v=4 url: https://github.com/EverStarck -- login: slafs - count: 2 - avatarUrl: https://avatars.githubusercontent.com/u/210173?v=4 - url: https://github.com/slafs - login: henrymcl count: 2 avatarUrl: https://avatars.githubusercontent.com/u/26480299?v=4 @@ -676,10 +692,6 @@ one_year_experts: count: 2 avatarUrl: https://avatars.githubusercontent.com/u/2555532?u=354a525847a276bbb4426b0c95791a8ba5970f9b&v=4 url: https://github.com/JacobHayes -- login: TaigoFr - count: 2 - avatarUrl: https://avatars.githubusercontent.com/u/17792131?u=372b27056ec82f1ae03d8b3f37ef55b04a7cfdd1&v=4 - url: https://github.com/TaigoFr - login: rlimberger count: 2 avatarUrl: https://avatars.githubusercontent.com/u/4841242?u=6a13252caf3cedceb07b6e2775b6592445d13b70&v=4 @@ -700,23 +712,3 @@ one_year_experts: count: 2 avatarUrl: https://avatars.githubusercontent.com/u/19860056?u=47b584eb1c1ab45e31c1b474109a962d7e82be49&v=4 url: https://github.com/PidgeyBE -- login: KianAnbarestani - count: 2 - avatarUrl: https://avatars.githubusercontent.com/u/145364424?u=dcc3d8fb4ca07d36fb52a17f38b6650565de40be&v=4 - url: https://github.com/KianAnbarestani -- login: Ykaiqx - count: 2 - avatarUrl: https://avatars.githubusercontent.com/u/56395004?u=1eebf5ce25a8067f7bfa6251a24f667be492d9d6&v=4 - url: https://github.com/Ykaiqx -- login: AliYmn - count: 2 - avatarUrl: https://avatars.githubusercontent.com/u/18416653?u=a77e2605e3ce6aaf6fef8ad4a7b0d32954fba47a&v=4 - url: https://github.com/AliYmn -- login: dolfinus - count: 2 - avatarUrl: https://avatars.githubusercontent.com/u/4661021?u=ed5ddadcf36d9b943ebe61febe0b96ee34e5425d&v=4 - url: https://github.com/dolfinus -- login: gelezo43 - count: 2 - avatarUrl: https://avatars.githubusercontent.com/u/40732698?u=611f39d3c1d2f4207a590937a78c1f10eed6232c&v=4 - url: https://github.com/gelezo43 From 6df50d40fe195adc026af169d6ebf298a1c183a5 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Fri, 1 Aug 2025 14:32:59 +0000 Subject: [PATCH 48/60] =?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 bb228270c..b57ff80f0 100644 --- a/docs/en/docs/release-notes.md +++ b/docs/en/docs/release-notes.md @@ -23,6 +23,7 @@ hide: ### Internal +* 👥 Update FastAPI People - Experts. PR [#13963](https://github.com/fastapi/fastapi/pull/13963) by [@tiangolo](https://github.com/tiangolo). * ⬆ Bump ruff from 0.11.2 to 0.12.7. PR [#13957](https://github.com/fastapi/fastapi/pull/13957) by [@dependabot[bot]](https://github.com/apps/dependabot). * ⬆ Bump cairosvg from 2.7.1 to 2.8.2. PR [#13959](https://github.com/fastapi/fastapi/pull/13959) by [@dependabot[bot]](https://github.com/apps/dependabot). * ⬆ Bump pydantic-ai from 0.0.30 to 0.4.10. PR [#13958](https://github.com/fastapi/fastapi/pull/13958) by [@dependabot[bot]](https://github.com/apps/dependabot). From 5c8d5214ff6a45e269c482b1940a46a931fda995 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 8 Aug 2025 07:43:20 +0200 Subject: [PATCH 49/60] =?UTF-8?q?=E2=AC=86=20Bump=20actions/download-artif?= =?UTF-8?q?act=20from=204=20to=205=20(#13975)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Bumps [actions/download-artifact](https://github.com/actions/download-artifact) from 4 to 5. - [Release notes](https://github.com/actions/download-artifact/releases) - [Commits](https://github.com/actions/download-artifact/compare/v4...v5) --- updated-dependencies: - dependency-name: actions/download-artifact dependency-version: '5' dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/deploy-docs.yml | 2 +- .github/workflows/smokeshow.yml | 2 +- .github/workflows/test.yml | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/deploy-docs.yml b/.github/workflows/deploy-docs.yml index 9ca69b208..c088d4ad1 100644 --- a/.github/workflows/deploy-docs.yml +++ b/.github/workflows/deploy-docs.yml @@ -48,7 +48,7 @@ jobs: run: | rm -rf ./site mkdir ./site - - uses: actions/download-artifact@v4 + - uses: actions/download-artifact@v5 with: path: ./site/ pattern: docs-site-* diff --git a/.github/workflows/smokeshow.yml b/.github/workflows/smokeshow.yml index d8a5dfb30..4788b4f1b 100644 --- a/.github/workflows/smokeshow.yml +++ b/.github/workflows/smokeshow.yml @@ -34,7 +34,7 @@ jobs: requirements**.txt pyproject.toml - run: uv pip install -r requirements-github-actions.txt - - uses: actions/download-artifact@v4 + - uses: actions/download-artifact@v5 with: name: coverage-html path: htmlcov diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index c3940be01..1f9df620c 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -122,7 +122,7 @@ jobs: - name: Install Dependencies run: uv pip install -r requirements-tests.txt - name: Get coverage files - uses: actions/download-artifact@v4 + uses: actions/download-artifact@v5 with: pattern: coverage-* path: coverage From 6cee687a7903aad5678a7beeb76929c2af417b22 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Fri, 8 Aug 2025 05:43:40 +0000 Subject: [PATCH 50/60] =?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 b57ff80f0..1a116c720 100644 --- a/docs/en/docs/release-notes.md +++ b/docs/en/docs/release-notes.md @@ -23,6 +23,7 @@ hide: ### Internal +* ⬆ Bump actions/download-artifact from 4 to 5. PR [#13975](https://github.com/fastapi/fastapi/pull/13975) by [@dependabot[bot]](https://github.com/apps/dependabot). * 👥 Update FastAPI People - Experts. PR [#13963](https://github.com/fastapi/fastapi/pull/13963) by [@tiangolo](https://github.com/tiangolo). * ⬆ Bump ruff from 0.11.2 to 0.12.7. PR [#13957](https://github.com/fastapi/fastapi/pull/13957) by [@dependabot[bot]](https://github.com/apps/dependabot). * ⬆ Bump cairosvg from 2.7.1 to 2.8.2. PR [#13959](https://github.com/fastapi/fastapi/pull/13959) by [@dependabot[bot]](https://github.com/apps/dependabot). From 6ccad060814a7a9c5170f1f37e38eb42b93f76f0 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Fri, 8 Aug 2025 07:44:02 +0200 Subject: [PATCH 51/60] =?UTF-8?q?=E2=AC=86=20[pre-commit.ci]=20pre-commit?= =?UTF-8?q?=20autoupdate=20(#13969)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit updates: - [github.com/astral-sh/ruff-pre-commit: v0.12.5 → v0.12.7](https://github.com/astral-sh/ruff-pre-commit/compare/v0.12.5...v0.12.7) 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 0f882b221..c2e628466 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.12.5 + rev: v0.12.7 hooks: - id: ruff args: From 12b36a048c5433d7555294a67ed8bc159ceb1383 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Fri, 8 Aug 2025 05:44:22 +0000 Subject: [PATCH 52/60] =?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 1a116c720..8458d3547 100644 --- a/docs/en/docs/release-notes.md +++ b/docs/en/docs/release-notes.md @@ -23,6 +23,7 @@ hide: ### Internal +* ⬆ [pre-commit.ci] pre-commit autoupdate. PR [#13969](https://github.com/fastapi/fastapi/pull/13969) by [@pre-commit-ci[bot]](https://github.com/apps/pre-commit-ci). * ⬆ Bump actions/download-artifact from 4 to 5. PR [#13975](https://github.com/fastapi/fastapi/pull/13975) by [@dependabot[bot]](https://github.com/apps/dependabot). * 👥 Update FastAPI People - Experts. PR [#13963](https://github.com/fastapi/fastapi/pull/13963) by [@tiangolo](https://github.com/tiangolo). * ⬆ Bump ruff from 0.11.2 to 0.12.7. PR [#13957](https://github.com/fastapi/fastapi/pull/13957) by [@dependabot[bot]](https://github.com/apps/dependabot). From ba0f6121b97876ecda096afdfca94628223d9c23 Mon Sep 17 00:00:00 2001 From: Chai Landau <112015853+chailandau@users.noreply.github.com> Date: Fri, 8 Aug 2025 01:48:21 -0400 Subject: [PATCH 53/60] =?UTF-8?q?=F0=9F=94=A7=20Update=20Speakeasy=20spons?= =?UTF-8?q?or=20graphic=20(#13971)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docs/en/docs/img/sponsors/speakeasy.png | Bin 11887 -> 18817 bytes 1 file changed, 0 insertions(+), 0 deletions(-) diff --git a/docs/en/docs/img/sponsors/speakeasy.png b/docs/en/docs/img/sponsors/speakeasy.png index 5ddc25487b6b52ea5da49effe465605de207ee3d..7bb9c3a18e1efa4f7d65c3c2ba8a817a3a4f71dc 100644 GIT binary patch literal 18817 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
lE-+3E5_5E z@({rTx?dreyh)b#*3Qm!jTw_?e3X&*I9-6rm@QsAcHAv3FZ&lR*2ouMTw3x+rr_m^ zrShe5KD7{TGtvj-HbY4lmlnx&?)!VV({Q5^`V_}RFDw+h`1z9!y$jvGBf;?BVKxgU zdnM)>y0YQ8^Eg^OKN4pN(P8=U?5hk%J%U;HP~zfe9nbi@;pjY)7717LJyc)KFMcP0(R*0@d1+S249f>o=x2|!Vi^)94r{+~moXDP zpfT}~mXTm1hB(ANFI?#rlEF<{^1;p=_?Q9Z@oNP-Us=}%>jdf1Qm5nJz`_#J8Vx;R z(YqACK=I8|-=?$CPW4S8t0R%8S_jQw|HV-GW)#2b2xVh;TH}a$1eO3z@5?EFUJowP z3%5EJ@;u!Ymgym0RON|T@>I)M#eWMYhg6)FJ8RV^MqjF>4bha!H(gf3oCmKC_>Px9 zNWi#uk7O1TPq2*q@Dw>8W9&`R!o%vdmy+H_xKkt_;FDxqVVUc^i-V7qE zoJZi#3U2!{NN<#Dw!ViXF8iQWQ$2TQta^ z6)x66#w>&GoON7GDPxvY#>Mh$!w~CmLv^(1mjQBvRg6L=vgybDkj6S65a5bK0=%M9 zT&t8-%t*KVd(t&p`f0iq|7KS0hzwhN)uAQM65}N$gl4^N@c0>Y>X7c^Yj6m?Y zz>-;3;L70VU5z~V3XB&yB#saqtMOzx+gcYJ*A>rfiM0!zAFlCA{iq23c5rUJ_?g?@@tH7b27#10d zw?i{x77;OGs+2GmbZ;MGy2ZSr<0!U3DSFppypomLoI97?I3e0%9gam?NMKTg!?J#{ z2Dj)5;j!Sy;La0bf?bt2M!%Iegh%uJ(39~o0&dZfXqueaFj4jrLInUuZ zI99Jvryr|t6<-R9MFPgU!{Ly|tX=O0<52F6^>ug8efPN+o`2pS-i`N~CzG*Tzr9W_ zNP{M!ihY6PVc&3{VWF`jMjKm=5EdNj4fsF~I4yq&_{8n)?7i$Bn!o*pON1~wm`vRs zD6n^{^TP(oBY0AUUYBJ)#*`$KC$*!R2WJXTs}x$|3DIHUN~PycI{H*=Y~j&$Y51WR z$;)Ws*L4BmfF`2aSneb#*(W(_H;d)YJzDzYvGCpjW}A!QCia3J8b_y8@tveiN(X^L5fP)KQDhLhTf zSVEd7cu6t*GQ_+rE00WzDXPUot22w$!%~Wvf>gC>Rh$(c>Rcq=s`8c`g*te;9=gyW z!Yv?G6`7}^smw`@x9F6vk_Bg8Aqe%dRl*f2Th#$rN}%(^LX56?uk+%y>KvI`D-6zZ(2^ojHTf3FqHbEwz2RsaA107*qo IM6N<$f{ZBLzW@LL literal 11887 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 From 753bb9fb9ffc01865abff74f43e367cb8f70e723 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Fri, 8 Aug 2025 05:48:47 +0000 Subject: [PATCH 54/60] =?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 8458d3547..414e54965 100644 --- a/docs/en/docs/release-notes.md +++ b/docs/en/docs/release-notes.md @@ -23,6 +23,7 @@ hide: ### Internal +* 🔧 Update Speakeasy sponsor graphic. PR [#13971](https://github.com/fastapi/fastapi/pull/13971) by [@chailandau](https://github.com/chailandau). * ⬆ [pre-commit.ci] pre-commit autoupdate. PR [#13969](https://github.com/fastapi/fastapi/pull/13969) by [@pre-commit-ci[bot]](https://github.com/apps/pre-commit-ci). * ⬆ Bump actions/download-artifact from 4 to 5. PR [#13975](https://github.com/fastapi/fastapi/pull/13975) by [@dependabot[bot]](https://github.com/apps/dependabot). * 👥 Update FastAPI People - Experts. PR [#13963](https://github.com/fastapi/fastapi/pull/13963) by [@tiangolo](https://github.com/tiangolo). From 7df361eb41e74c764d6001674e23027fda02b7cf Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 15 Aug 2025 23:44:06 +0200 Subject: [PATCH 55/60] =?UTF-8?q?=E2=AC=86=20Bump=20actions/checkout=20fro?= =?UTF-8?q?m=204=20to=205=20(#13986)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Bumps [actions/checkout](https://github.com/actions/checkout) from 4 to 5. - [Release notes](https://github.com/actions/checkout/releases) - [Changelog](https://github.com/actions/checkout/blob/main/CHANGELOG.md) - [Commits](https://github.com/actions/checkout/compare/v4...v5) --- updated-dependencies: - dependency-name: actions/checkout dependency-version: '5' dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/build-docs.yml | 6 +++--- .github/workflows/contributors.yml | 2 +- .github/workflows/deploy-docs.yml | 2 +- .github/workflows/label-approved.yml | 2 +- .github/workflows/latest-changes.yml | 2 +- .github/workflows/notify-translations.yml | 2 +- .github/workflows/people.yml | 2 +- .github/workflows/publish.yml | 2 +- .github/workflows/smokeshow.yml | 2 +- .github/workflows/sponsors.yml | 2 +- .github/workflows/test-redistribute.yml | 2 +- .github/workflows/test.yml | 6 +++--- .github/workflows/topic-repos.yml | 2 +- .github/workflows/translate.yml | 2 +- 14 files changed, 18 insertions(+), 18 deletions(-) diff --git a/.github/workflows/build-docs.yml b/.github/workflows/build-docs.yml index e84e4e4ab..4b01354ed 100644 --- a/.github/workflows/build-docs.yml +++ b/.github/workflows/build-docs.yml @@ -21,7 +21,7 @@ jobs: outputs: docs: ${{ steps.filter.outputs.docs }} steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@v5 # For pull requests it's not necessary to checkout the code but for the main branch it is - uses: dorny/paths-filter@v3 id: filter @@ -47,7 +47,7 @@ jobs: outputs: langs: ${{ steps.show-langs.outputs.langs }} steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@v5 - name: Set up Python uses: actions/setup-python@v5 with: @@ -89,7 +89,7 @@ jobs: env: GITHUB_CONTEXT: ${{ toJson(github) }} run: echo "$GITHUB_CONTEXT" - - uses: actions/checkout@v4 + - uses: actions/checkout@v5 - name: Set up Python uses: actions/setup-python@v5 with: diff --git a/.github/workflows/contributors.yml b/.github/workflows/contributors.yml index 34b54b452..d957aa46e 100644 --- a/.github/workflows/contributors.yml +++ b/.github/workflows/contributors.yml @@ -24,7 +24,7 @@ jobs: env: GITHUB_CONTEXT: ${{ toJson(github) }} run: echo "$GITHUB_CONTEXT" - - uses: actions/checkout@v4 + - uses: actions/checkout@v5 - name: Set up Python uses: actions/setup-python@v5 with: diff --git a/.github/workflows/deploy-docs.yml b/.github/workflows/deploy-docs.yml index c088d4ad1..40590793e 100644 --- a/.github/workflows/deploy-docs.yml +++ b/.github/workflows/deploy-docs.yml @@ -23,7 +23,7 @@ jobs: env: GITHUB_CONTEXT: ${{ toJson(github) }} run: echo "$GITHUB_CONTEXT" - - uses: actions/checkout@v4 + - uses: actions/checkout@v5 - name: Set up Python uses: actions/setup-python@v5 with: diff --git a/.github/workflows/label-approved.yml b/.github/workflows/label-approved.yml index 908a9453d..5cd12e5d8 100644 --- a/.github/workflows/label-approved.yml +++ b/.github/workflows/label-approved.yml @@ -20,7 +20,7 @@ jobs: env: GITHUB_CONTEXT: ${{ toJson(github) }} run: echo "$GITHUB_CONTEXT" - - uses: actions/checkout@v4 + - uses: actions/checkout@v5 - name: Set up Python uses: actions/setup-python@v5 with: diff --git a/.github/workflows/latest-changes.yml b/.github/workflows/latest-changes.yml index 208ab0c65..2fa832fab 100644 --- a/.github/workflows/latest-changes.yml +++ b/.github/workflows/latest-changes.yml @@ -24,7 +24,7 @@ jobs: env: GITHUB_CONTEXT: ${{ toJson(github) }} run: echo "$GITHUB_CONTEXT" - - uses: actions/checkout@v4 + - uses: actions/checkout@v5 with: # To allow latest-changes to commit to the main branch token: ${{ secrets.FASTAPI_LATEST_CHANGES }} diff --git a/.github/workflows/notify-translations.yml b/.github/workflows/notify-translations.yml index 621d1253a..e5f0c3ebb 100644 --- a/.github/workflows/notify-translations.yml +++ b/.github/workflows/notify-translations.yml @@ -28,7 +28,7 @@ jobs: env: GITHUB_CONTEXT: ${{ toJson(github) }} run: echo "$GITHUB_CONTEXT" - - uses: actions/checkout@v4 + - uses: actions/checkout@v5 - name: Set up Python uses: actions/setup-python@v5 with: diff --git a/.github/workflows/people.yml b/.github/workflows/people.yml index c1df3455e..2e4ec1326 100644 --- a/.github/workflows/people.yml +++ b/.github/workflows/people.yml @@ -24,7 +24,7 @@ jobs: env: GITHUB_CONTEXT: ${{ toJson(github) }} run: echo "$GITHUB_CONTEXT" - - uses: actions/checkout@v4 + - uses: actions/checkout@v5 - name: Set up Python uses: actions/setup-python@v5 with: diff --git a/.github/workflows/publish.yml b/.github/workflows/publish.yml index bf88d59b1..5a83cf7d8 100644 --- a/.github/workflows/publish.yml +++ b/.github/workflows/publish.yml @@ -20,7 +20,7 @@ jobs: env: GITHUB_CONTEXT: ${{ toJson(github) }} run: echo "$GITHUB_CONTEXT" - - uses: actions/checkout@v4 + - uses: actions/checkout@v5 - name: Set up Python uses: actions/setup-python@v5 with: diff --git a/.github/workflows/smokeshow.yml b/.github/workflows/smokeshow.yml index 4788b4f1b..27f078838 100644 --- a/.github/workflows/smokeshow.yml +++ b/.github/workflows/smokeshow.yml @@ -21,7 +21,7 @@ jobs: env: GITHUB_CONTEXT: ${{ toJson(github) }} run: echo "$GITHUB_CONTEXT" - - uses: actions/checkout@v4 + - uses: actions/checkout@v5 - uses: actions/setup-python@v5 with: python-version: '3.9' diff --git a/.github/workflows/sponsors.yml b/.github/workflows/sponsors.yml index 6da4d90e1..07153b6a9 100644 --- a/.github/workflows/sponsors.yml +++ b/.github/workflows/sponsors.yml @@ -24,7 +24,7 @@ jobs: env: GITHUB_CONTEXT: ${{ toJson(github) }} run: echo "$GITHUB_CONTEXT" - - uses: actions/checkout@v4 + - uses: actions/checkout@v5 - name: Set up Python uses: actions/setup-python@v5 with: diff --git a/.github/workflows/test-redistribute.yml b/.github/workflows/test-redistribute.yml index 693f0c603..71d21ae52 100644 --- a/.github/workflows/test-redistribute.yml +++ b/.github/workflows/test-redistribute.yml @@ -22,7 +22,7 @@ jobs: env: GITHUB_CONTEXT: ${{ toJson(github) }} run: echo "$GITHUB_CONTEXT" - - uses: actions/checkout@v4 + - uses: actions/checkout@v5 - name: Set up Python uses: actions/setup-python@v5 with: diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 1f9df620c..620e55df3 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -23,7 +23,7 @@ jobs: env: GITHUB_CONTEXT: ${{ toJson(github) }} run: echo "$GITHUB_CONTEXT" - - uses: actions/checkout@v4 + - uses: actions/checkout@v5 - name: Set up Python uses: actions/setup-python@v5 with: @@ -61,7 +61,7 @@ jobs: env: GITHUB_CONTEXT: ${{ toJson(github) }} run: echo "$GITHUB_CONTEXT" - - uses: actions/checkout@v4 + - uses: actions/checkout@v5 - name: Set up Python uses: actions/setup-python@v5 with: @@ -107,7 +107,7 @@ jobs: env: GITHUB_CONTEXT: ${{ toJson(github) }} run: echo "$GITHUB_CONTEXT" - - uses: actions/checkout@v4 + - uses: actions/checkout@v5 - uses: actions/setup-python@v5 with: python-version: '3.8' diff --git a/.github/workflows/topic-repos.yml b/.github/workflows/topic-repos.yml index 433aeb00b..9e953010d 100644 --- a/.github/workflows/topic-repos.yml +++ b/.github/workflows/topic-repos.yml @@ -19,7 +19,7 @@ jobs: env: GITHUB_CONTEXT: ${{ toJson(github) }} run: echo "$GITHUB_CONTEXT" - - uses: actions/checkout@v4 + - uses: actions/checkout@v5 - name: Set up Python uses: actions/setup-python@v5 with: diff --git a/.github/workflows/translate.yml b/.github/workflows/translate.yml index fc6b4d730..b7c3efe13 100644 --- a/.github/workflows/translate.yml +++ b/.github/workflows/translate.yml @@ -42,7 +42,7 @@ jobs: env: GITHUB_CONTEXT: ${{ toJson(github) }} run: echo "$GITHUB_CONTEXT" - - uses: actions/checkout@v4 + - uses: actions/checkout@v5 - name: Set up Python uses: actions/setup-python@v5 with: From 078324583c1bbc2ac87e628c692a5a83435f97ba Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Fri, 15 Aug 2025 21:44:33 +0000 Subject: [PATCH 56/60] =?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 414e54965..8bd9d8bbb 100644 --- a/docs/en/docs/release-notes.md +++ b/docs/en/docs/release-notes.md @@ -23,6 +23,7 @@ hide: ### Internal +* ⬆ Bump actions/checkout from 4 to 5. PR [#13986](https://github.com/fastapi/fastapi/pull/13986) by [@dependabot[bot]](https://github.com/apps/dependabot). * 🔧 Update Speakeasy sponsor graphic. PR [#13971](https://github.com/fastapi/fastapi/pull/13971) by [@chailandau](https://github.com/chailandau). * ⬆ [pre-commit.ci] pre-commit autoupdate. PR [#13969](https://github.com/fastapi/fastapi/pull/13969) by [@pre-commit-ci[bot]](https://github.com/apps/pre-commit-ci). * ⬆ Bump actions/download-artifact from 4 to 5. PR [#13975](https://github.com/fastapi/fastapi/pull/13975) by [@dependabot[bot]](https://github.com/apps/dependabot). From f1b144995898dc6bdf3ebca8d9e145ddf60cdc52 Mon Sep 17 00:00:00 2001 From: Lubos Date: Sat, 16 Aug 2025 05:59:47 +0800 Subject: [PATCH 57/60] =?UTF-8?q?=F0=9F=93=9D=20Update=20`docs/en/docs/adv?= =?UTF-8?q?anced/generate-clients.md`=20(#13793)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docs/en/docs/advanced/generate-clients.md | 147 +++++++--------------- 1 file changed, 47 insertions(+), 100 deletions(-) diff --git a/docs/en/docs/advanced/generate-clients.md b/docs/en/docs/advanced/generate-clients.md index 55e6a08b1..e8b2fefbd 100644 --- a/docs/en/docs/advanced/generate-clients.md +++ b/docs/en/docs/advanced/generate-clients.md @@ -1,34 +1,42 @@ -# Generate Clients +# Generating SDKs -As **FastAPI** is based on the OpenAPI specification, you get automatic compatibility with many tools, including the automatic API docs (provided by Swagger UI). +Because **FastAPI** is based on the **OpenAPI** specification, its APIs can be described in a standard format that many tools understand. -One particular advantage that is not necessarily obvious is that you can **generate clients** (sometimes called **SDKs** ) for your API, for many different **programming languages**. +This makes it easy to generate up-to-date **documentation**, client libraries (**SDKs**) in multiple languages, and **testing** or **automation workflows** that stay in sync with your code. -## OpenAPI Client Generators +In this guide, you'll learn how to generate a **TypeScript SDK** for your FastAPI backend. -There are many tools to generate clients from **OpenAPI**. +## Open Source SDK Generators -A common tool is OpenAPI Generator. +A versatile option is the OpenAPI Generator, which supports **many programming languages** and can generate SDKs from your OpenAPI specification. -If you are building a **frontend**, a very interesting alternative is openapi-ts. +For **TypeScript clients**, Hey API is a purpose-built solution, providing an optimized experience for the TypeScript ecosystem. -## Client and SDK Generators - Sponsor +You can discover more SDK generators on OpenAPI.Tools. -There are also some **company-backed** Client and SDK generators based on OpenAPI (FastAPI), in some cases they can offer you **additional features** on top of high-quality generated SDKs/clients. +/// tip + +FastAPI automatically generates **OpenAPI 3.1** specifications, so any tool you use must support this version. + +/// + +## SDK Generators from FastAPI Sponsors + +This section highlights **venture-backed** and **company-supported** solutions from companies that sponsor FastAPI. These products provide **additional features** and **integrations** on top of high-quality generated SDKs. -Some of them also ✨ [**sponsor FastAPI**](../help-fastapi.md#sponsor-the-author){.internal-link target=_blank} ✨, this ensures the continued and healthy **development** of FastAPI and its **ecosystem**. +By ✨ [**sponsoring FastAPI**](../help-fastapi.md#sponsor-the-author){.internal-link target=_blank} ✨, these companies help ensure the framework and its **ecosystem** remain healthy and **sustainable**. -And it shows their true commitment to FastAPI and its **community** (you), as they not only want to provide you a **good service** but also want to make sure you have a **good and healthy framework**, FastAPI. 🙇 +Their sponsorship also demonstrates a strong commitment to the FastAPI **community** (you), showing that they care not only about offering a **great service** but also about supporting a **robust and thriving framework**, FastAPI. 🙇 For example, you might want to try: * Speakeasy -* Stainless +* Stainless * liblab -There are also several other companies offering similar services that you can search and find online. 🤓 +Some of these solutions may also be open source or offer free tiers, so you can try them without a financial commitment. Other commercial SDK generators are available and can be found online. 🤓 -## Generate a TypeScript Frontend Client +## Create a TypeScript SDK Let's start with a simple FastAPI application: @@ -38,78 +46,31 @@ Notice that the *path operations* define the models they use for request payload ### API Docs -If you go to the API docs, you will see that it has the **schemas** for the data to be sent in requests and received in responses: +If you go to `/docs`, you will see that it has the **schemas** for the data to be sent in requests and received in responses: You can see those schemas because they were declared with the models in the app. -That information is available in the app's **OpenAPI schema**, and then shown in the API docs (by Swagger UI). +That information is available in the app's **OpenAPI schema**, and then shown in the API docs. -And that same information from the models that is included in OpenAPI is what can be used to **generate the client code**. +That same information from the models that is included in OpenAPI is what can be used to **generate the client code**. -### Generate a TypeScript Client +### Hey API -Now that we have the app with the models, we can generate the client code for the frontend. +Once we have a FastAPI app with the models, we can use Hey API to generate a TypeScript client. The fastest way to do that is via npx. -#### Install `openapi-ts` - -You can install `openapi-ts` in your frontend code with: - -
- -```console -$ npm install @hey-api/openapi-ts --save-dev - ----> 100% +```sh +npx @hey-api/openapi-ts -i http://localhost:8000/openapi.json -o src/client ``` -
- -#### Generate Client Code +This will generate a TypeScript SDK in `./src/client`. -To generate the client code you can use the command line application `openapi-ts` that would now be installed. +You can learn how to install `@hey-api/openapi-ts` and read about the generated output on their website. -Because it is installed in the local project, you probably wouldn't be able to call that command directly, but you would put it on your `package.json` file. +### Using the SDK -It could look like this: - -```JSON hl_lines="7" -{ - "name": "frontend-app", - "version": "1.0.0", - "description": "", - "main": "index.js", - "scripts": { - "generate-client": "openapi-ts --input http://localhost:8000/openapi.json --output ./src/client --client axios" - }, - "author": "", - "license": "", - "devDependencies": { - "@hey-api/openapi-ts": "^0.27.38", - "typescript": "^4.6.2" - } -} -``` - -After having that NPM `generate-client` script there, you can run it with: - -
- -```console -$ npm run generate-client - -frontend-app@1.0.0 generate-client /home/user/code/frontend-app -> openapi-ts --input http://localhost:8000/openapi.json --output ./src/client --client axios -``` - -
- -That command will generate code in `./src/client` and will use `axios` (the frontend HTTP library) internally. - -### Try Out the Client Code - -Now you can import and use the client code, it could look like this, notice that you get autocompletion for the methods: +Now you can import and use the client code. It could look like this, notice that you get autocompletion for the methods: @@ -133,7 +94,7 @@ The response object will also have autocompletion: ## FastAPI App with Tags -In many cases your FastAPI app will be bigger, and you will probably use tags to separate different groups of *path operations*. +In many cases, your FastAPI app will be bigger, and you will probably use tags to separate different groups of *path operations*. For example, you could have a section for **items** and another section for **users**, and they could be separated by tags: @@ -143,18 +104,18 @@ For example, you could have a section for **items** and another section for **us If you generate a client for a FastAPI app using tags, it will normally also separate the client code based on the tags. -This way you will be able to have things ordered and grouped correctly for the client code: +This way, you will be able to have things ordered and grouped correctly for the client code: -In this case you have: +In this case, you have: * `ItemsService` * `UsersService` ### Client Method Names -Right now the generated method names like `createItemItemsPost` don't look very clean: +Right now, the generated method names like `createItemItemsPost` don't look very clean: ```TypeScript ItemsService.createItemItemsPost({name: "Plumbus", price: 5}) @@ -170,13 +131,13 @@ But I'll show you how to improve that next. 🤓 You can **modify** the way these operation IDs are **generated** to make them simpler and have **simpler method names** in the clients. -In this case you will have to ensure that each operation ID is **unique** in some other way. +In this case, you will have to ensure that each operation ID is **unique** in some other way. For example, you could make sure that each *path operation* has a tag, and then generate the operation ID based on the **tag** and the *path operation* **name** (the function name). ### Custom Generate Unique ID Function -FastAPI uses a **unique ID** for each *path operation*, it is used for the **operation ID** and also for the names of any needed custom models, for requests or responses. +FastAPI uses a **unique ID** for each *path operation*, which is used for the **operation ID** and also for the names of any needed custom models, for requests or responses. You can customize that function. It takes an `APIRoute` and outputs a string. @@ -188,7 +149,7 @@ You can then pass that custom function to **FastAPI** as the `generate_unique_id ### Generate a TypeScript Client with Custom Operation IDs -Now if you generate the client again, you will see that it has the improved method names: +Now, if you generate the client again, you will see that it has the improved method names: @@ -202,7 +163,7 @@ We already know that this method is related to the **items** because that word i We will probably still want to keep it for OpenAPI in general, as that will ensure that the operation IDs are **unique**. -But for the generated client we could **modify** the OpenAPI operation IDs right before generating the clients, just to make those method names nicer and **cleaner**. +But for the generated client, we could **modify** the OpenAPI operation IDs right before generating the clients, just to make those method names nicer and **cleaner**. We could download the OpenAPI JSON to a file `openapi.json` and then we could **remove that prefixed tag** with a script like this: @@ -220,24 +181,10 @@ With that, the operation IDs would be renamed from things like `items-get_items` ### Generate a TypeScript Client with the Preprocessed OpenAPI -Now as the end result is in a file `openapi.json`, you would modify the `package.json` to use that local file, for example: - -```JSON hl_lines="7" -{ - "name": "frontend-app", - "version": "1.0.0", - "description": "", - "main": "index.js", - "scripts": { - "generate-client": "openapi-ts --input ./openapi.json --output ./src/client --client axios" - }, - "author": "", - "license": "", - "devDependencies": { - "@hey-api/openapi-ts": "^0.27.38", - "typescript": "^4.6.2" - } -} +Since the end result is now in an `openapi.json` file, you need to update your input location: + +```sh +npx @hey-api/openapi-ts -i ./openapi.json -o src/client ``` After generating the new client, you would now have **clean method names**, with all the **autocompletion**, **inline errors**, etc: @@ -246,7 +193,7 @@ After generating the new client, you would now have **clean method names**, with ## Benefits -When using the automatically generated clients you would get **autocompletion** for: +When using the automatically generated clients, you would get **autocompletion** for: * Methods. * Request payloads in the body, query parameters, etc. @@ -256,6 +203,6 @@ You would also have **inline errors** for everything. And whenever you update the backend code, and **regenerate** the frontend, it would have any new *path operations* available as methods, the old ones removed, and any other change would be reflected on the generated code. 🤓 -This also means that if something changed it will be **reflected** on the client code automatically. And if you **build** the client it will error out if you have any **mismatch** in the data used. +This also means that if something changed, it will be **reflected** on the client code automatically. And if you **build** the client, it will error out if you have any **mismatch** in the data used. So, you would **detect many errors** very early in the development cycle instead of having to wait for the errors to show up to your final users in production and then trying to debug where the problem is. ✨ From dbc9d3a0cee5dc855451353e185890bc78a6666e Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Fri, 15 Aug 2025 22:00:13 +0000 Subject: [PATCH 58/60] =?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 8bd9d8bbb..badd0ed25 100644 --- a/docs/en/docs/release-notes.md +++ b/docs/en/docs/release-notes.md @@ -9,6 +9,7 @@ hide: ### Docs +* 📝 Update `docs/en/docs/advanced/generate-clients.md`. PR [#13793](https://github.com/fastapi/fastapi/pull/13793) by [@mrlubos](https://github.com/mrlubos). * 📝 Add discussion template for new language translation requests. PR [#13535](https://github.com/fastapi/fastapi/pull/13535) by [@alejsdev](https://github.com/alejsdev). ### Translations From d12c1ac82c1bf571bab078e0d047d868727a26de Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Sat, 16 Aug 2025 00:00:47 +0200 Subject: [PATCH 59/60] =?UTF-8?q?=E2=AC=86=20[pre-commit.ci]=20pre-commit?= =?UTF-8?q?=20autoupdate=20(#13983)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit updates: - [github.com/pre-commit/pre-commit-hooks: v5.0.0 → v6.0.0](https://github.com/pre-commit/pre-commit-hooks/compare/v5.0.0...v6.0.0) - [github.com/astral-sh/ruff-pre-commit: v0.12.7 → v0.12.8](https://github.com/astral-sh/ruff-pre-commit/compare/v0.12.7...v0.12.8) Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> --- .pre-commit-config.yaml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index c2e628466..7175d21eb 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -4,7 +4,7 @@ default_language_version: python: python3.10 repos: - repo: https://github.com/pre-commit/pre-commit-hooks - rev: v5.0.0 + rev: v6.0.0 hooks: - id: check-added-large-files - id: check-toml @@ -14,7 +14,7 @@ repos: - id: end-of-file-fixer - id: trailing-whitespace - repo: https://github.com/astral-sh/ruff-pre-commit - rev: v0.12.7 + rev: v0.12.8 hooks: - id: ruff args: From 9c7abbff43121bca35bec3156a428105e98c0324 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Fri, 15 Aug 2025 22:01:21 +0000 Subject: [PATCH 60/60] =?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 badd0ed25..bfa253408 100644 --- a/docs/en/docs/release-notes.md +++ b/docs/en/docs/release-notes.md @@ -24,6 +24,7 @@ hide: ### Internal +* ⬆ [pre-commit.ci] pre-commit autoupdate. PR [#13983](https://github.com/fastapi/fastapi/pull/13983) by [@pre-commit-ci[bot]](https://github.com/apps/pre-commit-ci). * ⬆ Bump actions/checkout from 4 to 5. PR [#13986](https://github.com/fastapi/fastapi/pull/13986) by [@dependabot[bot]](https://github.com/apps/dependabot). * 🔧 Update Speakeasy sponsor graphic. PR [#13971](https://github.com/fastapi/fastapi/pull/13971) by [@chailandau](https://github.com/chailandau). * ⬆ [pre-commit.ci] pre-commit autoupdate. PR [#13969](https://github.com/fastapi/fastapi/pull/13969) by [@pre-commit-ci[bot]](https://github.com/apps/pre-commit-ci).