From 7c6b79eb3bee614dc2f0eedba513a1866d9979b4 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 22 Apr 2026 14:41:23 +0200 Subject: [PATCH 001/462] =?UTF-8?q?=E2=AC=86=20Bump=20mypy=20from=201.19.1?= =?UTF-8?q?=20to=201.20.1=20(#15410)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- uv.lock | 230 +++++++++++++++++++++++++++++++------------------------- 1 file changed, 127 insertions(+), 103 deletions(-) diff --git a/uv.lock b/uv.lock index e3436aa89..0b0bc9199 100644 --- a/uv.lock +++ b/uv.lock @@ -2488,75 +2488,87 @@ wheels = [ [[package]] name = "librt" -version = "0.7.8" -source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/e7/24/5f3646ff414285e0f7708fa4e946b9bf538345a41d1c375c439467721a5e/librt-0.7.8.tar.gz", hash = "sha256:1a4ede613941d9c3470b0368be851df6bb78ab218635512d0370b27a277a0862", size = 148323, upload-time = "2026-01-14T12:56:16.876Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/44/13/57b06758a13550c5f09563893b004f98e9537ee6ec67b7df85c3571c8832/librt-0.7.8-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:b45306a1fc5f53c9330fbee134d8b3227fe5da2ab09813b892790400aa49352d", size = 56521, upload-time = "2026-01-14T12:54:40.066Z" }, - { url = "https://files.pythonhosted.org/packages/c2/24/bbea34d1452a10612fb45ac8356f95351ba40c2517e429602160a49d1fd0/librt-0.7.8-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:864c4b7083eeee250ed55135d2127b260d7eb4b5e953a9e5df09c852e327961b", size = 58456, upload-time = "2026-01-14T12:54:41.471Z" }, - { url = "https://files.pythonhosted.org/packages/04/72/a168808f92253ec3a810beb1eceebc465701197dbc7e865a1c9ceb3c22c7/librt-0.7.8-cp310-cp310-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:6938cc2de153bc927ed8d71c7d2f2ae01b4e96359126c602721340eb7ce1a92d", size = 164392, upload-time = "2026-01-14T12:54:42.843Z" }, - { url = "https://files.pythonhosted.org/packages/14/5c/4c0d406f1b02735c2e7af8ff1ff03a6577b1369b91aa934a9fa2cc42c7ce/librt-0.7.8-cp310-cp310-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:66daa6ac5de4288a5bbfbe55b4caa7bf0cd26b3269c7a476ffe8ce45f837f87d", size = 172959, upload-time = "2026-01-14T12:54:44.602Z" }, - { url = "https://files.pythonhosted.org/packages/82/5f/3e85351c523f73ad8d938989e9a58c7f59fb9c17f761b9981b43f0025ce7/librt-0.7.8-cp310-cp310-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:4864045f49dc9c974dadb942ac56a74cd0479a2aafa51ce272c490a82322ea3c", size = 186717, upload-time = "2026-01-14T12:54:45.986Z" }, - { url = "https://files.pythonhosted.org/packages/08/f8/18bfe092e402d00fe00d33aa1e01dda1bd583ca100b393b4373847eade6d/librt-0.7.8-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:a36515b1328dc5b3ffce79fe204985ca8572525452eacabee2166f44bb387b2c", size = 184585, upload-time = "2026-01-14T12:54:47.139Z" }, - { url = "https://files.pythonhosted.org/packages/4e/fc/f43972ff56fd790a9fa55028a52ccea1875100edbb856b705bd393b601e3/librt-0.7.8-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:b7e7f140c5169798f90b80d6e607ed2ba5059784968a004107c88ad61fb3641d", size = 180497, upload-time = "2026-01-14T12:54:48.946Z" }, - { url = "https://files.pythonhosted.org/packages/e1/3a/25e36030315a410d3ad0b7d0f19f5f188e88d1613d7d3fd8150523ea1093/librt-0.7.8-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:ff71447cb778a4f772ddc4ce360e6ba9c95527ed84a52096bd1bbf9fee2ec7c0", size = 200052, upload-time = "2026-01-14T12:54:50.382Z" }, - { url = "https://files.pythonhosted.org/packages/fc/b8/f3a5a1931ae2a6ad92bf6893b9ef44325b88641d58723529e2c2935e8abe/librt-0.7.8-cp310-cp310-win32.whl", hash = "sha256:047164e5f68b7a8ebdf9fae91a3c2161d3192418aadd61ddd3a86a56cbe3dc85", size = 43477, upload-time = "2026-01-14T12:54:51.815Z" }, - { url = "https://files.pythonhosted.org/packages/fe/91/c4202779366bc19f871b4ad25db10fcfa1e313c7893feb942f32668e8597/librt-0.7.8-cp310-cp310-win_amd64.whl", hash = "sha256:d6f254d096d84156a46a84861183c183d30734e52383602443292644d895047c", size = 49806, upload-time = "2026-01-14T12:54:53.149Z" }, - { url = "https://files.pythonhosted.org/packages/1b/a3/87ea9c1049f2c781177496ebee29430e4631f439b8553a4969c88747d5d8/librt-0.7.8-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:ff3e9c11aa260c31493d4b3197d1e28dd07768594a4f92bec4506849d736248f", size = 56507, upload-time = "2026-01-14T12:54:54.156Z" }, - { url = "https://files.pythonhosted.org/packages/5e/4a/23bcef149f37f771ad30203d561fcfd45b02bc54947b91f7a9ac34815747/librt-0.7.8-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:ddb52499d0b3ed4aa88746aaf6f36a08314677d5c346234c3987ddc506404eac", size = 58455, upload-time = "2026-01-14T12:54:55.978Z" }, - { url = "https://files.pythonhosted.org/packages/22/6e/46eb9b85c1b9761e0f42b6e6311e1cc544843ac897457062b9d5d0b21df4/librt-0.7.8-cp311-cp311-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:e9c0afebbe6ce177ae8edba0c7c4d626f2a0fc12c33bb993d163817c41a7a05c", size = 164956, upload-time = "2026-01-14T12:54:57.311Z" }, - { url = "https://files.pythonhosted.org/packages/7a/3f/aa7c7f6829fb83989feb7ba9aa11c662b34b4bd4bd5b262f2876ba3db58d/librt-0.7.8-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:631599598e2c76ded400c0a8722dec09217c89ff64dc54b060f598ed68e7d2a8", size = 174364, upload-time = "2026-01-14T12:54:59.089Z" }, - { url = "https://files.pythonhosted.org/packages/3f/2d/d57d154b40b11f2cb851c4df0d4c4456bacd9b1ccc4ecb593ddec56c1a8b/librt-0.7.8-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:9c1ba843ae20db09b9d5c80475376168feb2640ce91cd9906414f23cc267a1ff", size = 188034, upload-time = "2026-01-14T12:55:00.141Z" }, - { url = "https://files.pythonhosted.org/packages/59/f9/36c4dad00925c16cd69d744b87f7001792691857d3b79187e7a673e812fb/librt-0.7.8-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:b5b007bb22ea4b255d3ee39dfd06d12534de2fcc3438567d9f48cdaf67ae1ae3", size = 186295, upload-time = "2026-01-14T12:55:01.303Z" }, - { url = "https://files.pythonhosted.org/packages/23/9b/8a9889d3df5efb67695a67785028ccd58e661c3018237b73ad081691d0cb/librt-0.7.8-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:dbd79caaf77a3f590cbe32dc2447f718772d6eea59656a7dcb9311161b10fa75", size = 181470, upload-time = "2026-01-14T12:55:02.492Z" }, - { url = "https://files.pythonhosted.org/packages/43/64/54d6ef11afca01fef8af78c230726a9394759f2addfbf7afc5e3cc032a45/librt-0.7.8-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:87808a8d1e0bd62a01cafc41f0fd6818b5a5d0ca0d8a55326a81643cdda8f873", size = 201713, upload-time = "2026-01-14T12:55:03.919Z" }, - { url = "https://files.pythonhosted.org/packages/2d/29/73e7ed2991330b28919387656f54109139b49e19cd72902f466bd44415fd/librt-0.7.8-cp311-cp311-win32.whl", hash = "sha256:31724b93baa91512bd0a376e7cf0b59d8b631ee17923b1218a65456fa9bda2e7", size = 43803, upload-time = "2026-01-14T12:55:04.996Z" }, - { url = "https://files.pythonhosted.org/packages/3f/de/66766ff48ed02b4d78deea30392ae200bcbd99ae61ba2418b49fd50a4831/librt-0.7.8-cp311-cp311-win_amd64.whl", hash = "sha256:978e8b5f13e52cf23a9e80f3286d7546baa70bc4ef35b51d97a709d0b28e537c", size = 50080, upload-time = "2026-01-14T12:55:06.489Z" }, - { url = "https://files.pythonhosted.org/packages/6f/e3/33450438ff3a8c581d4ed7f798a70b07c3206d298cf0b87d3806e72e3ed8/librt-0.7.8-cp311-cp311-win_arm64.whl", hash = "sha256:20e3946863d872f7cabf7f77c6c9d370b8b3d74333d3a32471c50d3a86c0a232", size = 43383, upload-time = "2026-01-14T12:55:07.49Z" }, - { url = "https://files.pythonhosted.org/packages/56/04/79d8fcb43cae376c7adbab7b2b9f65e48432c9eced62ac96703bcc16e09b/librt-0.7.8-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:9b6943885b2d49c48d0cff23b16be830ba46b0152d98f62de49e735c6e655a63", size = 57472, upload-time = "2026-01-14T12:55:08.528Z" }, - { url = "https://files.pythonhosted.org/packages/b4/ba/60b96e93043d3d659da91752689023a73981336446ae82078cddf706249e/librt-0.7.8-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:46ef1f4b9b6cc364b11eea0ecc0897314447a66029ee1e55859acb3dd8757c93", size = 58986, upload-time = "2026-01-14T12:55:09.466Z" }, - { url = "https://files.pythonhosted.org/packages/7c/26/5215e4cdcc26e7be7eee21955a7e13cbf1f6d7d7311461a6014544596fac/librt-0.7.8-cp312-cp312-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:907ad09cfab21e3c86e8f1f87858f7049d1097f77196959c033612f532b4e592", size = 168422, upload-time = "2026-01-14T12:55:10.499Z" }, - { url = "https://files.pythonhosted.org/packages/0f/84/e8d1bc86fa0159bfc24f3d798d92cafd3897e84c7fea7fe61b3220915d76/librt-0.7.8-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:2991b6c3775383752b3ca0204842743256f3ad3deeb1d0adc227d56b78a9a850", size = 177478, upload-time = "2026-01-14T12:55:11.577Z" }, - { url = "https://files.pythonhosted.org/packages/57/11/d0268c4b94717a18aa91df1100e767b010f87b7ae444dafaa5a2d80f33a6/librt-0.7.8-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:03679b9856932b8c8f674e87aa3c55ea11c9274301f76ae8dc4d281bda55cf62", size = 192439, upload-time = "2026-01-14T12:55:12.7Z" }, - { url = "https://files.pythonhosted.org/packages/8d/56/1e8e833b95fe684f80f8894ae4d8b7d36acc9203e60478fcae599120a975/librt-0.7.8-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:3968762fec1b2ad34ce57458b6de25dbb4142713e9ca6279a0d352fa4e9f452b", size = 191483, upload-time = "2026-01-14T12:55:13.838Z" }, - { url = "https://files.pythonhosted.org/packages/17/48/f11cf28a2cb6c31f282009e2208312aa84a5ee2732859f7856ee306176d5/librt-0.7.8-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:bb7a7807523a31f03061288cc4ffc065d684c39db7644c676b47d89553c0d714", size = 185376, upload-time = "2026-01-14T12:55:15.017Z" }, - { url = "https://files.pythonhosted.org/packages/b8/6a/d7c116c6da561b9155b184354a60a3d5cdbf08fc7f3678d09c95679d13d9/librt-0.7.8-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:ad64a14b1e56e702e19b24aae108f18ad1bf7777f3af5fcd39f87d0c5a814449", size = 206234, upload-time = "2026-01-14T12:55:16.571Z" }, - { url = "https://files.pythonhosted.org/packages/61/de/1975200bb0285fc921c5981d9978ce6ce11ae6d797df815add94a5a848a3/librt-0.7.8-cp312-cp312-win32.whl", hash = "sha256:0241a6ed65e6666236ea78203a73d800dbed896cf12ae25d026d75dc1fcd1dac", size = 44057, upload-time = "2026-01-14T12:55:18.077Z" }, - { url = "https://files.pythonhosted.org/packages/8e/cd/724f2d0b3461426730d4877754b65d39f06a41ac9d0a92d5c6840f72b9ae/librt-0.7.8-cp312-cp312-win_amd64.whl", hash = "sha256:6db5faf064b5bab9675c32a873436b31e01d66ca6984c6f7f92621656033a708", size = 50293, upload-time = "2026-01-14T12:55:19.179Z" }, - { url = "https://files.pythonhosted.org/packages/bd/cf/7e899acd9ee5727ad8160fdcc9994954e79fab371c66535c60e13b968ffc/librt-0.7.8-cp312-cp312-win_arm64.whl", hash = "sha256:57175aa93f804d2c08d2edb7213e09276bd49097611aefc37e3fa38d1fb99ad0", size = 43574, upload-time = "2026-01-14T12:55:20.185Z" }, - { url = "https://files.pythonhosted.org/packages/a1/fe/b1f9de2829cf7fc7649c1dcd202cfd873837c5cc2fc9e526b0e7f716c3d2/librt-0.7.8-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:4c3995abbbb60b3c129490fa985dfe6cac11d88fc3c36eeb4fb1449efbbb04fc", size = 57500, upload-time = "2026-01-14T12:55:21.219Z" }, - { url = "https://files.pythonhosted.org/packages/eb/d4/4a60fbe2e53b825f5d9a77325071d61cd8af8506255067bf0c8527530745/librt-0.7.8-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:44e0c2cbc9bebd074cf2cdbe472ca185e824be4e74b1c63a8e934cea674bebf2", size = 59019, upload-time = "2026-01-14T12:55:22.256Z" }, - { url = "https://files.pythonhosted.org/packages/6a/37/61ff80341ba5159afa524445f2d984c30e2821f31f7c73cf166dcafa5564/librt-0.7.8-cp313-cp313-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:4d2f1e492cae964b3463a03dc77a7fe8742f7855d7258c7643f0ee32b6651dd3", size = 169015, upload-time = "2026-01-14T12:55:23.24Z" }, - { url = "https://files.pythonhosted.org/packages/1c/86/13d4f2d6a93f181ebf2fc953868826653ede494559da8268023fe567fca3/librt-0.7.8-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:451e7ffcef8f785831fdb791bd69211f47e95dc4c6ddff68e589058806f044c6", size = 178161, upload-time = "2026-01-14T12:55:24.826Z" }, - { url = "https://files.pythonhosted.org/packages/88/26/e24ef01305954fc4d771f1f09f3dd682f9eb610e1bec188ffb719374d26e/librt-0.7.8-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:3469e1af9f1380e093ae06bedcbdd11e407ac0b303a56bbe9afb1d6824d4982d", size = 193015, upload-time = "2026-01-14T12:55:26.04Z" }, - { url = "https://files.pythonhosted.org/packages/88/a0/92b6bd060e720d7a31ed474d046a69bd55334ec05e9c446d228c4b806ae3/librt-0.7.8-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:f11b300027ce19a34f6d24ebb0a25fd0e24a9d53353225a5c1e6cadbf2916b2e", size = 192038, upload-time = "2026-01-14T12:55:27.208Z" }, - { url = "https://files.pythonhosted.org/packages/06/bb/6f4c650253704279c3a214dad188101d1b5ea23be0606628bc6739456624/librt-0.7.8-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:4adc73614f0d3c97874f02f2c7fd2a27854e7e24ad532ea6b965459c5b757eca", size = 186006, upload-time = "2026-01-14T12:55:28.594Z" }, - { url = "https://files.pythonhosted.org/packages/dc/00/1c409618248d43240cadf45f3efb866837fa77e9a12a71481912135eb481/librt-0.7.8-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:60c299e555f87e4c01b2eca085dfccda1dde87f5a604bb45c2906b8305819a93", size = 206888, upload-time = "2026-01-14T12:55:30.214Z" }, - { url = "https://files.pythonhosted.org/packages/d9/83/b2cfe8e76ff5c1c77f8a53da3d5de62d04b5ebf7cf913e37f8bca43b5d07/librt-0.7.8-cp313-cp313-win32.whl", hash = "sha256:b09c52ed43a461994716082ee7d87618096851319bf695d57ec123f2ab708951", size = 44126, upload-time = "2026-01-14T12:55:31.44Z" }, - { url = "https://files.pythonhosted.org/packages/a9/0b/c59d45de56a51bd2d3a401fc63449c0ac163e4ef7f523ea8b0c0dee86ec5/librt-0.7.8-cp313-cp313-win_amd64.whl", hash = "sha256:f8f4a901a3fa28969d6e4519deceab56c55a09d691ea7b12ca830e2fa3461e34", size = 50262, upload-time = "2026-01-14T12:55:33.01Z" }, - { url = "https://files.pythonhosted.org/packages/fc/b9/973455cec0a1ec592395250c474164c4a58ebf3e0651ee920fef1a2623f1/librt-0.7.8-cp313-cp313-win_arm64.whl", hash = "sha256:43d4e71b50763fcdcf64725ac680d8cfa1706c928b844794a7aa0fa9ac8e5f09", size = 43600, upload-time = "2026-01-14T12:55:34.054Z" }, - { url = "https://files.pythonhosted.org/packages/1a/73/fa8814c6ce2d49c3827829cadaa1589b0bf4391660bd4510899393a23ebc/librt-0.7.8-cp314-cp314-macosx_10_13_x86_64.whl", hash = "sha256:be927c3c94c74b05128089a955fba86501c3b544d1d300282cc1b4bd370cb418", size = 57049, upload-time = "2026-01-14T12:55:35.056Z" }, - { url = "https://files.pythonhosted.org/packages/53/fe/f6c70956da23ea235fd2e3cc16f4f0b4ebdfd72252b02d1164dd58b4e6c3/librt-0.7.8-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:7b0803e9008c62a7ef79058233db7ff6f37a9933b8f2573c05b07ddafa226611", size = 58689, upload-time = "2026-01-14T12:55:36.078Z" }, - { url = "https://files.pythonhosted.org/packages/1f/4d/7a2481444ac5fba63050d9abe823e6bc16896f575bfc9c1e5068d516cdce/librt-0.7.8-cp314-cp314-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:79feb4d00b2a4e0e05c9c56df707934f41fcb5fe53fd9efb7549068d0495b758", size = 166808, upload-time = "2026-01-14T12:55:37.595Z" }, - { url = "https://files.pythonhosted.org/packages/ac/3c/10901d9e18639f8953f57c8986796cfbf4c1c514844a41c9197cf87cb707/librt-0.7.8-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:b9122094e3f24aa759c38f46bd8863433820654927370250f460ae75488b66ea", size = 175614, upload-time = "2026-01-14T12:55:38.756Z" }, - { url = "https://files.pythonhosted.org/packages/db/01/5cbdde0951a5090a80e5ba44e6357d375048123c572a23eecfb9326993a7/librt-0.7.8-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:7e03bea66af33c95ce3addf87a9bf1fcad8d33e757bc479957ddbc0e4f7207ac", size = 189955, upload-time = "2026-01-14T12:55:39.939Z" }, - { url = "https://files.pythonhosted.org/packages/6a/b4/e80528d2f4b7eaf1d437fcbd6fc6ba4cbeb3e2a0cb9ed5a79f47c7318706/librt-0.7.8-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:f1ade7f31675db00b514b98f9ab9a7698c7282dad4be7492589109471852d398", size = 189370, upload-time = "2026-01-14T12:55:41.057Z" }, - { url = "https://files.pythonhosted.org/packages/c1/ab/938368f8ce31a9787ecd4becb1e795954782e4312095daf8fd22420227c8/librt-0.7.8-cp314-cp314-musllinux_1_2_i686.whl", hash = "sha256:a14229ac62adcf1b90a15992f1ab9c69ae8b99ffb23cb64a90878a6e8a2f5b81", size = 183224, upload-time = "2026-01-14T12:55:42.328Z" }, - { url = "https://files.pythonhosted.org/packages/3c/10/559c310e7a6e4014ac44867d359ef8238465fb499e7eb31b6bfe3e3f86f5/librt-0.7.8-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:5bcaaf624fd24e6a0cb14beac37677f90793a96864c67c064a91458611446e83", size = 203541, upload-time = "2026-01-14T12:55:43.501Z" }, - { url = "https://files.pythonhosted.org/packages/f8/db/a0db7acdb6290c215f343835c6efda5b491bb05c3ddc675af558f50fdba3/librt-0.7.8-cp314-cp314-win32.whl", hash = "sha256:7aa7d5457b6c542ecaed79cec4ad98534373c9757383973e638ccced0f11f46d", size = 40657, upload-time = "2026-01-14T12:55:44.668Z" }, - { url = "https://files.pythonhosted.org/packages/72/e0/4f9bdc2a98a798511e81edcd6b54fe82767a715e05d1921115ac70717f6f/librt-0.7.8-cp314-cp314-win_amd64.whl", hash = "sha256:3d1322800771bee4a91f3b4bd4e49abc7d35e65166821086e5afd1e6c0d9be44", size = 46835, upload-time = "2026-01-14T12:55:45.655Z" }, - { url = "https://files.pythonhosted.org/packages/f9/3d/59c6402e3dec2719655a41ad027a7371f8e2334aa794ed11533ad5f34969/librt-0.7.8-cp314-cp314-win_arm64.whl", hash = "sha256:5363427bc6a8c3b1719f8f3845ea53553d301382928a86e8fab7984426949bce", size = 39885, upload-time = "2026-01-14T12:55:47.138Z" }, - { url = "https://files.pythonhosted.org/packages/4e/9c/2481d80950b83085fb14ba3c595db56330d21bbc7d88a19f20165f3538db/librt-0.7.8-cp314-cp314t-macosx_10_13_x86_64.whl", hash = "sha256:ca916919793a77e4a98d4a1701e345d337ce53be4a16620f063191f7322ac80f", size = 59161, upload-time = "2026-01-14T12:55:48.45Z" }, - { url = "https://files.pythonhosted.org/packages/96/79/108df2cfc4e672336765d54e3ff887294c1cc36ea4335c73588875775527/librt-0.7.8-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:54feb7b4f2f6706bb82325e836a01be805770443e2400f706e824e91f6441dde", size = 61008, upload-time = "2026-01-14T12:55:49.527Z" }, - { url = "https://files.pythonhosted.org/packages/46/f2/30179898f9994a5637459d6e169b6abdc982012c0a4b2d4c26f50c06f911/librt-0.7.8-cp314-cp314t-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:39a4c76fee41007070f872b648cc2f711f9abf9a13d0c7162478043377b52c8e", size = 187199, upload-time = "2026-01-14T12:55:50.587Z" }, - { url = "https://files.pythonhosted.org/packages/b4/da/f7563db55cebdc884f518ba3791ad033becc25ff68eb70902b1747dc0d70/librt-0.7.8-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:ac9c8a458245c7de80bc1b9765b177055efff5803f08e548dd4bb9ab9a8d789b", size = 198317, upload-time = "2026-01-14T12:55:51.991Z" }, - { url = "https://files.pythonhosted.org/packages/b3/6c/4289acf076ad371471fa86718c30ae353e690d3de6167f7db36f429272f1/librt-0.7.8-cp314-cp314t-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:95b67aa7eff150f075fda09d11f6bfb26edffd300f6ab1666759547581e8f666", size = 210334, upload-time = "2026-01-14T12:55:53.682Z" }, - { url = "https://files.pythonhosted.org/packages/4a/7f/377521ac25b78ac0a5ff44127a0360ee6d5ddd3ce7327949876a30533daa/librt-0.7.8-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:535929b6eff670c593c34ff435d5440c3096f20fa72d63444608a5aef64dd581", size = 211031, upload-time = "2026-01-14T12:55:54.827Z" }, - { url = "https://files.pythonhosted.org/packages/c5/b1/e1e96c3e20b23d00cf90f4aad48f0deb4cdfec2f0ed8380d0d85acf98bbf/librt-0.7.8-cp314-cp314t-musllinux_1_2_i686.whl", hash = "sha256:63937bd0f4d1cb56653dc7ae900d6c52c41f0015e25aaf9902481ee79943b33a", size = 204581, upload-time = "2026-01-14T12:55:56.811Z" }, - { url = "https://files.pythonhosted.org/packages/43/71/0f5d010e92ed9747e14bef35e91b6580533510f1e36a8a09eb79ee70b2f0/librt-0.7.8-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:cf243da9e42d914036fd362ac3fa77d80a41cadcd11ad789b1b5eec4daaf67ca", size = 224731, upload-time = "2026-01-14T12:55:58.175Z" }, - { url = "https://files.pythonhosted.org/packages/22/f0/07fb6ab5c39a4ca9af3e37554f9d42f25c464829254d72e4ebbd81da351c/librt-0.7.8-cp314-cp314t-win32.whl", hash = "sha256:171ca3a0a06c643bd0a2f62a8944e1902c94aa8e5da4db1ea9a8daf872685365", size = 41173, upload-time = "2026-01-14T12:55:59.315Z" }, - { url = "https://files.pythonhosted.org/packages/24/d4/7e4be20993dc6a782639625bd2f97f3c66125c7aa80c82426956811cfccf/librt-0.7.8-cp314-cp314t-win_amd64.whl", hash = "sha256:445b7304145e24c60288a2f172b5ce2ca35c0f81605f5299f3fa567e189d2e32", size = 47668, upload-time = "2026-01-14T12:56:00.261Z" }, - { url = "https://files.pythonhosted.org/packages/fc/85/69f92b2a7b3c0f88ffe107c86b952b397004b5b8ea5a81da3d9c04c04422/librt-0.7.8-cp314-cp314t-win_arm64.whl", hash = "sha256:8766ece9de08527deabcd7cb1b4f1a967a385d26e33e536d6d8913db6ef74f06", size = 40550, upload-time = "2026-01-14T12:56:01.542Z" }, +version = "0.9.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/eb/6b/3d5c13fb3e3c4f43206c8f9dfed13778c2ed4f000bacaa0b7ce3c402a265/librt-0.9.0.tar.gz", hash = "sha256:a0951822531e7aee6e0dfb556b30d5ee36bbe234faf60c20a16c01be3530869d", size = 184368, upload-time = "2026-04-09T16:06:26.173Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/f3/4a/c64265d71b84030174ff3ac2cd16d8b664072afab8c41fccd8e2ee5a6f8d/librt-0.9.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:2f8e12706dcb8ff6b3ed57514a19e45c49ad00bcd423e87b2b2e4b5f64578443", size = 67529, upload-time = "2026-04-09T16:04:27.373Z" }, + { url = "https://files.pythonhosted.org/packages/23/b1/30ca0b3a8bdac209a00145c66cf42e5e7da2cc056ffc6ebc5c7b430ddd34/librt-0.9.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:4e3dda8345307fd7306db0ed0cb109a63a2c85ba780eb9dc2d09b2049a931f9c", size = 70248, upload-time = "2026-04-09T16:04:28.758Z" }, + { url = "https://files.pythonhosted.org/packages/fa/fc/c6018dc181478d6ac5aa24a5846b8185101eb90894346db239eb3ea53209/librt-0.9.0-cp310-cp310-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:de7dac64e3eb832ffc7b840eb8f52f76420cde1b845be51b2a0f6b870890645e", size = 202184, upload-time = "2026-04-09T16:04:29.893Z" }, + { url = "https://files.pythonhosted.org/packages/bf/58/d69629f002203370ef41ea69ff71c49a2c618aec39b226ff49986ecd8623/librt-0.9.0-cp310-cp310-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:22a904cbdb678f7cb348c90d543d3c52f581663d687992fee47fd566dcbf5285", size = 212926, upload-time = "2026-04-09T16:04:31.126Z" }, + { url = "https://files.pythonhosted.org/packages/cc/55/01d859f57824e42bd02465c77bec31fa5ef9d8c2bcee702ccf8ef1b9f508/librt-0.9.0-cp310-cp310-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:224b9727eb8bc188bc3bcf29d969dba0cd61b01d9bac80c41575520cc4baabb2", size = 225664, upload-time = "2026-04-09T16:04:32.352Z" }, + { url = "https://files.pythonhosted.org/packages/9b/02/32f63ad0ef085a94a70315291efe1151a48b9947af12261882f8445b2a30/librt-0.9.0-cp310-cp310-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:e94cbc6ad9a6aeea46d775cbb11f361022f778a9cc8cc90af653d3a594b057ce", size = 219534, upload-time = "2026-04-09T16:04:33.667Z" }, + { url = "https://files.pythonhosted.org/packages/6a/5a/9d77111a183c885acf3b3b6e4c00f5b5b07b5817028226499a55f1fedc59/librt-0.9.0-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:7bc30ad339f4e1a01d4917d645e522a0bc0030644d8973f6346397c93ba1503f", size = 227322, upload-time = "2026-04-09T16:04:34.945Z" }, + { url = "https://files.pythonhosted.org/packages/d5/e7/05d700c93063753e12ab230b972002a3f8f3b9c95d8a980c2f646c8b6963/librt-0.9.0-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:56d65b583cf43b8cf4c8fbe1e1da20fa3076cc32a1149a141507af1062718236", size = 223407, upload-time = "2026-04-09T16:04:36.22Z" }, + { url = "https://files.pythonhosted.org/packages/c0/26/26c3124823c67c987456977c683da9a27cc874befc194ddcead5f9988425/librt-0.9.0-cp310-cp310-musllinux_1_2_riscv64.whl", hash = "sha256:0a1be03168b2691ba61927e299b352a6315189199ca18a57b733f86cb3cc8d38", size = 221302, upload-time = "2026-04-09T16:04:37.62Z" }, + { url = "https://files.pythonhosted.org/packages/50/2b/c7cc2be5cf4ff7b017d948a789256288cb33a517687ff1995e72a7eea79f/librt-0.9.0-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:63c12efcd160e1d14da11af0c46c0217473e1e0d2ae1acbccc83f561ea4c2a7b", size = 243893, upload-time = "2026-04-09T16:04:38.909Z" }, + { url = "https://files.pythonhosted.org/packages/62/d3/da553d37417a337d12660450535d5fd51373caffbedf6962173c87867246/librt-0.9.0-cp310-cp310-win32.whl", hash = "sha256:e9002e98dcb1c0a66723592520decd86238ddcef168b37ff6cfb559200b4b774", size = 55375, upload-time = "2026-04-09T16:04:40.148Z" }, + { url = "https://files.pythonhosted.org/packages/9b/5a/46fa357bab8311b6442a83471591f2f9e5b15ecc1d2121a43725e0c529b8/librt-0.9.0-cp310-cp310-win_amd64.whl", hash = "sha256:9fcb461fbf70654a52a7cc670e606f04449e2374c199b1825f754e16dacfedd8", size = 62581, upload-time = "2026-04-09T16:04:41.452Z" }, + { url = "https://files.pythonhosted.org/packages/e2/1e/2ec7afcebcf3efea593d13aee18bbcfdd3a243043d848ebf385055e9f636/librt-0.9.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:90904fac73c478f4b83f4ed96c99c8208b75e6f9a8a1910548f69a00f1eaa671", size = 67155, upload-time = "2026-04-09T16:04:42.933Z" }, + { url = "https://files.pythonhosted.org/packages/18/77/72b85afd4435268338ad4ec6231b3da8c77363f212a0227c1ff3b45e4d35/librt-0.9.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:789fff71757facc0738e8d89e3b84e4f0251c1c975e85e81b152cdaca927cc2d", size = 69916, upload-time = "2026-04-09T16:04:44.042Z" }, + { url = "https://files.pythonhosted.org/packages/27/fb/948ea0204fbe2e78add6d46b48330e58d39897e425560674aee302dca81c/librt-0.9.0-cp311-cp311-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:1bf465d1e5b0a27713862441f6467b5ab76385f4ecf8f1f3a44f8aa3c695b4b6", size = 199635, upload-time = "2026-04-09T16:04:45.5Z" }, + { url = "https://files.pythonhosted.org/packages/ac/cd/894a29e251b296a27957856804cfd21e93c194aa131de8bb8032021be07e/librt-0.9.0-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:f819e0c6413e259a17a7c0d49f97f405abadd3c2a316a3b46c6440b7dbbedbb1", size = 211051, upload-time = "2026-04-09T16:04:47.016Z" }, + { url = "https://files.pythonhosted.org/packages/18/8f/dcaed0bc084a35f3721ff2d081158db569d2c57ea07d35623ddaca5cfc8e/librt-0.9.0-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:e0785c2fb4a81e1aece366aa3e2e039f4a4d7d21aaaded5227d7f3c703427882", size = 224031, upload-time = "2026-04-09T16:04:48.207Z" }, + { url = "https://files.pythonhosted.org/packages/03/44/88f6c1ed1132cd418601cc041fbd92fed28b3a09f39de81978e0822d13ff/librt-0.9.0-cp311-cp311-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:80b25c7b570a86c03b5da69e665809deb39265476e8e21d96a9328f9762f9990", size = 218069, upload-time = "2026-04-09T16:04:50.025Z" }, + { url = "https://files.pythonhosted.org/packages/a3/90/7d02e981c2db12188d82b4410ff3e35bfdb844b26aecd02233626f46af2b/librt-0.9.0-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:d4d16b608a1c43d7e33142099a75cd93af482dadce0bf82421e91cad077157f4", size = 224857, upload-time = "2026-04-09T16:04:51.684Z" }, + { url = "https://files.pythonhosted.org/packages/ef/c3/c77e706b7215ca32e928d47535cf13dbc3d25f096f84ddf8fbc06693e229/librt-0.9.0-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:194fc1a32e1e21fe809d38b5faea66cc65eaa00217c8901fbdb99866938adbdb", size = 219865, upload-time = "2026-04-09T16:04:52.949Z" }, + { url = "https://files.pythonhosted.org/packages/52/d1/32b0c1a0eb8461c70c11656c46a29f760b7c7edf3c36d6f102470c17170f/librt-0.9.0-cp311-cp311-musllinux_1_2_riscv64.whl", hash = "sha256:8c6bc1384d9738781cfd41d09ad7f6e8af13cfea2c75ece6bd6d2566cdea2076", size = 218451, upload-time = "2026-04-09T16:04:54.174Z" }, + { url = "https://files.pythonhosted.org/packages/74/d1/adfd0f9c44761b1d49b1bec66173389834c33ee2bd3c7fd2e2367f1942d4/librt-0.9.0-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:15cb151e52a044f06e54ac7f7b47adbfc89b5c8e2b63e1175a9d587c43e8942a", size = 241300, upload-time = "2026-04-09T16:04:55.452Z" }, + { url = "https://files.pythonhosted.org/packages/09/b0/9074b64407712f0003c27f5b1d7655d1438979155f049720e8a1abd9b1a1/librt-0.9.0-cp311-cp311-win32.whl", hash = "sha256:f100bfe2acf8a3689af9d0cc660d89f17286c9c795f9f18f7b62dd1a6b247ae6", size = 55668, upload-time = "2026-04-09T16:04:56.689Z" }, + { url = "https://files.pythonhosted.org/packages/24/19/40b77b77ce80b9389fb03971431b09b6b913911c38d412059e0b3e2a9ef2/librt-0.9.0-cp311-cp311-win_amd64.whl", hash = "sha256:0b73e4266307e51c95e09c0750b7ec383c561d2e97d58e473f6f6a209952fbb8", size = 62976, upload-time = "2026-04-09T16:04:57.733Z" }, + { url = "https://files.pythonhosted.org/packages/70/9d/9fa7a64041e29035cb8c575af5f0e3840be1b97b4c4d9061e0713f171849/librt-0.9.0-cp311-cp311-win_arm64.whl", hash = "sha256:bc5518873822d2faa8ebdd2c1a4d7c8ef47b01a058495ab7924cb65bdbf5fc9a", size = 53502, upload-time = "2026-04-09T16:04:58.806Z" }, + { url = "https://files.pythonhosted.org/packages/bf/90/89ddba8e1c20b0922783cd93ed8e64f34dc05ab59c38a9c7e313632e20ff/librt-0.9.0-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:9b3e3bc363f71bda1639a4ee593cb78f7fbfeacc73411ec0d4c92f00730010a4", size = 68332, upload-time = "2026-04-09T16:05:00.09Z" }, + { url = "https://files.pythonhosted.org/packages/a8/40/7aa4da1fb08bdeeb540cb07bfc8207cb32c5c41642f2594dbd0098a0662d/librt-0.9.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:0a09c2f5869649101738653a9b7ab70cf045a1105ac66cbb8f4055e61df78f2d", size = 70581, upload-time = "2026-04-09T16:05:01.213Z" }, + { url = "https://files.pythonhosted.org/packages/48/ac/73a2187e1031041e93b7e3a25aae37aa6f13b838c550f7e0f06f66766212/librt-0.9.0-cp312-cp312-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:5ca8e133d799c948db2ab1afc081c333a825b5540475164726dcbf73537e5c2f", size = 203984, upload-time = "2026-04-09T16:05:02.542Z" }, + { url = "https://files.pythonhosted.org/packages/5e/3d/23460d571e9cbddb405b017681df04c142fb1b04cbfce77c54b08e28b108/librt-0.9.0-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:603138ee838ee1583f1b960b62d5d0007845c5c423feb68e44648b1359014e27", size = 215762, upload-time = "2026-04-09T16:05:04.127Z" }, + { url = "https://files.pythonhosted.org/packages/de/1e/42dc7f8ab63e65b20640d058e63e97fd3e482c1edbda3570d813b4d0b927/librt-0.9.0-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:f4003f70c56a5addd6aa0897f200dd59afd3bf7bcd5b3cce46dd21f925743bc2", size = 230288, upload-time = "2026-04-09T16:05:05.883Z" }, + { url = "https://files.pythonhosted.org/packages/dc/08/ca812b6d8259ad9ece703397f8ad5c03af5b5fedfce64279693d3ce4087c/librt-0.9.0-cp312-cp312-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:78042f6facfd98ecb25e9829c7e37cce23363d9d7c83bc5f72702c5059eb082b", size = 224103, upload-time = "2026-04-09T16:05:07.148Z" }, + { url = "https://files.pythonhosted.org/packages/b6/3f/620490fb2fa66ffd44e7f900254bc110ebec8dac6c1b7514d64662570e6f/librt-0.9.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:a361c9434a64d70a7dbb771d1de302c0cc9f13c0bffe1cf7e642152814b35265", size = 232122, upload-time = "2026-04-09T16:05:08.386Z" }, + { url = "https://files.pythonhosted.org/packages/e9/83/12864700a1b6a8be458cf5d05db209b0d8e94ae281e7ec261dbe616597b4/librt-0.9.0-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:dd2c7e082b0b92e1baa4da28163a808672485617bc855cc22a2fd06978fa9084", size = 225045, upload-time = "2026-04-09T16:05:09.707Z" }, + { url = "https://files.pythonhosted.org/packages/fd/1b/845d339c29dc7dbc87a2e992a1ba8d28d25d0e0372f9a0a2ecebde298186/librt-0.9.0-cp312-cp312-musllinux_1_2_riscv64.whl", hash = "sha256:7e6274fd33fc5b2a14d41c9119629d3ff395849d8bcbc80cf637d9e8d2034da8", size = 227372, upload-time = "2026-04-09T16:05:10.942Z" }, + { url = "https://files.pythonhosted.org/packages/8d/fe/277985610269d926a64c606f761d58d3db67b956dbbf40024921e95e7fcb/librt-0.9.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:5093043afb226ecfa1400120d1ebd4442b4f99977783e4f4f7248879009b227f", size = 248224, upload-time = "2026-04-09T16:05:12.254Z" }, + { url = "https://files.pythonhosted.org/packages/92/1b/ee486d244b8de6b8b5dbaefabe6bfdd4a72e08f6353edf7d16d27114da8d/librt-0.9.0-cp312-cp312-win32.whl", hash = "sha256:9edcc35d1cae9fd5320171b1a838c7da8a5c968af31e82ecc3dff30b4be0957f", size = 55986, upload-time = "2026-04-09T16:05:13.529Z" }, + { url = "https://files.pythonhosted.org/packages/89/7a/ba1737012308c17dc6d5516143b5dce9a2c7ba3474afd54e11f44a4d1ef3/librt-0.9.0-cp312-cp312-win_amd64.whl", hash = "sha256:3cc2917258e131ae5f958a4d872e07555b51cb7466a43433218061c74ef33745", size = 63260, upload-time = "2026-04-09T16:05:14.68Z" }, + { url = "https://files.pythonhosted.org/packages/36/e4/01752c113da15127f18f7bf11142f5640038f062407a611c059d0036c6aa/librt-0.9.0-cp312-cp312-win_arm64.whl", hash = "sha256:90e6d5420fc8a300518d4d2288154ff45005e920425c22cbbfe8330f3f754bd9", size = 53694, upload-time = "2026-04-09T16:05:16.095Z" }, + { url = "https://files.pythonhosted.org/packages/5f/d7/1b3e26fffde1452d82f5666164858a81c26ebe808e7ae8c9c88628981540/librt-0.9.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:f29b68cd9714531672db62cc54f6e8ff981900f824d13fa0e00749189e13778e", size = 68367, upload-time = "2026-04-09T16:05:17.243Z" }, + { url = "https://files.pythonhosted.org/packages/a5/5b/c61b043ad2e091fbe1f2d35d14795e545d0b56b03edaa390fa1dcee3d160/librt-0.9.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:7d5c8a5929ac325729f6119802070b561f4db793dffc45e9ac750992a4ed4d22", size = 70595, upload-time = "2026-04-09T16:05:18.471Z" }, + { url = "https://files.pythonhosted.org/packages/a3/22/2448471196d8a73370aa2f23445455dc42712c21404081fcd7a03b9e0749/librt-0.9.0-cp313-cp313-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:756775d25ec8345b837ab52effee3ad2f3b2dfd6bbee3e3f029c517bd5d8f05a", size = 204354, upload-time = "2026-04-09T16:05:19.593Z" }, + { url = "https://files.pythonhosted.org/packages/ac/5e/39fc4b153c78cfd2c8a2dcb32700f2d41d2312aa1050513183be4540930d/librt-0.9.0-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:2b8f5d00b49818f4e2b1667db994488b045835e0ac16fe2f924f3871bd2b8ac5", size = 216238, upload-time = "2026-04-09T16:05:20.868Z" }, + { url = "https://files.pythonhosted.org/packages/d7/42/bc2d02d0fa7badfa63aa8d6dcd8793a9f7ef5a94396801684a51ed8d8287/librt-0.9.0-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:c81aef782380f0f13ead670aae01825eb653b44b046aa0e5ebbb79f76ed4aa11", size = 230589, upload-time = "2026-04-09T16:05:22.305Z" }, + { url = "https://files.pythonhosted.org/packages/c8/7b/e2d95cc513866373692aa5edf98080d5602dd07cabfb9e5d2f70df2f25f7/librt-0.9.0-cp313-cp313-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:66b58fed90a545328e80d575467244de3741e088c1af928f0b489ebec3ef3858", size = 224610, upload-time = "2026-04-09T16:05:23.647Z" }, + { url = "https://files.pythonhosted.org/packages/31/d5/6cec4607e998eaba57564d06a1295c21b0a0c8de76e4e74d699e627bd98c/librt-0.9.0-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:e78fb7419e07d98c2af4b8567b72b3eaf8cb05caad642e9963465569c8b2d87e", size = 232558, upload-time = "2026-04-09T16:05:25.025Z" }, + { url = "https://files.pythonhosted.org/packages/95/8c/27f1d8d3aaf079d3eb26439bf0b32f1482340c3552e324f7db9dca858671/librt-0.9.0-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:2c3786f0f4490a5cd87f1ed6cefae833ad6b1060d52044ce0434a2e85893afd0", size = 225521, upload-time = "2026-04-09T16:05:26.311Z" }, + { url = "https://files.pythonhosted.org/packages/6b/d8/1e0d43b1c329b416017619469b3c3801a25a6a4ef4a1c68332aeaa6f72ca/librt-0.9.0-cp313-cp313-musllinux_1_2_riscv64.whl", hash = "sha256:8494cfc61e03542f2d381e71804990b3931175a29b9278fdb4a5459948778dc2", size = 227789, upload-time = "2026-04-09T16:05:27.624Z" }, + { url = "https://files.pythonhosted.org/packages/2c/b4/d3d842e88610fcd4c8eec7067b0c23ef2d7d3bff31496eded6a83b0f99be/librt-0.9.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:07cf11f769831186eeac424376e6189f20ace4f7263e2134bdb9757340d84d4d", size = 248616, upload-time = "2026-04-09T16:05:29.181Z" }, + { url = "https://files.pythonhosted.org/packages/ec/28/527df8ad0d1eb6c8bdfa82fc190f1f7c4cca5a1b6d7b36aeabf95b52d74d/librt-0.9.0-cp313-cp313-win32.whl", hash = "sha256:850d6d03177e52700af605fd60db7f37dcb89782049a149674d1a9649c2138fd", size = 56039, upload-time = "2026-04-09T16:05:30.709Z" }, + { url = "https://files.pythonhosted.org/packages/f3/a7/413652ad0d92273ee5e30c000fc494b361171177c83e57c060ecd3c21538/librt-0.9.0-cp313-cp313-win_amd64.whl", hash = "sha256:a5af136bfba820d592f86c67affcef9b3ff4d4360ac3255e341e964489b48519", size = 63264, upload-time = "2026-04-09T16:05:31.881Z" }, + { url = "https://files.pythonhosted.org/packages/a4/0a/92c244309b774e290ddb15e93363846ae7aa753d9586b8aad511c5e6145b/librt-0.9.0-cp313-cp313-win_arm64.whl", hash = "sha256:4c4d0440a3a8e31d962340c3e1cc3fc9ee7febd34c8d8f770d06adb947779ea5", size = 53728, upload-time = "2026-04-09T16:05:33.31Z" }, + { url = "https://files.pythonhosted.org/packages/cd/c1/184e539543f06ea2912f4b92a5ffaede4f9b392689e3f00acbf8134bee92/librt-0.9.0-cp314-cp314-macosx_10_13_x86_64.whl", hash = "sha256:3f05d145df35dca5056a8bc3838e940efebd893a54b3e19b2dda39ceaa299bcb", size = 67830, upload-time = "2026-04-09T16:05:34.517Z" }, + { url = "https://files.pythonhosted.org/packages/f3/ad/23399bdcb7afca819acacdef31b37ee59de261bd66b503a7995c03c4b0dc/librt-0.9.0-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:1c587494461ebd42229d0f1739f3aa34237dd9980623ecf1be8d3bcba79f4499", size = 70280, upload-time = "2026-04-09T16:05:35.649Z" }, + { url = "https://files.pythonhosted.org/packages/9f/0b/4542dc5a2b8772dbf92cafb9194701230157e73c14b017b6961a23598b03/librt-0.9.0-cp314-cp314-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:b0a2040f801406b93657a70b72fa12311063a319fee72ce98e1524da7200171f", size = 201925, upload-time = "2026-04-09T16:05:36.739Z" }, + { url = "https://files.pythonhosted.org/packages/31/d4/8ee7358b08fd0cfce051ef96695380f09b3c2c11b77c9bfbc367c921cce5/librt-0.9.0-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:f38bc489037eca88d6ebefc9c4d41a4e07c8e8b4de5188a9e6d290273ad7ebb1", size = 212381, upload-time = "2026-04-09T16:05:38.043Z" }, + { url = "https://files.pythonhosted.org/packages/f2/94/a2025fe442abedf8b038038dab3dba942009ad42b38ea064a1a9e6094241/librt-0.9.0-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:f3fd278f5e6bf7c75ccd6d12344eb686cc020712683363b66f46ac79d37c799f", size = 227065, upload-time = "2026-04-09T16:05:39.394Z" }, + { url = "https://files.pythonhosted.org/packages/7c/e9/b9fcf6afa909f957cfbbf918802f9dada1bd5d3c1da43d722fd6a310dc3f/librt-0.9.0-cp314-cp314-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:fcbdf2a9ca24e87bbebb47f1fe34e531ef06f104f98c9ccfc953a3f3344c567a", size = 221333, upload-time = "2026-04-09T16:05:40.999Z" }, + { url = "https://files.pythonhosted.org/packages/ac/7c/ba54cd6aa6a3c8cd12757a6870e0c79a64b1e6327f5248dcff98423f4d43/librt-0.9.0-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:e306d956cfa027fe041585f02a1602c32bfa6bb8ebea4899d373383295a6c62f", size = 229051, upload-time = "2026-04-09T16:05:42.605Z" }, + { url = "https://files.pythonhosted.org/packages/4b/4b/8cfdbad314c8677a0148bf0b70591d6d18587f9884d930276098a235461b/librt-0.9.0-cp314-cp314-musllinux_1_2_i686.whl", hash = "sha256:465814ab157986acb9dfa5ccd7df944be5eefc0d08d31ec6e8d88bc71251d845", size = 222492, upload-time = "2026-04-09T16:05:43.842Z" }, + { url = "https://files.pythonhosted.org/packages/1f/d1/2eda69563a1a88706808decdce035e4b32755dbfbb0d05e1a65db9547ed1/librt-0.9.0-cp314-cp314-musllinux_1_2_riscv64.whl", hash = "sha256:703f4ae36d6240bfe24f542bac784c7e4194ec49c3ba5a994d02891649e2d85b", size = 223849, upload-time = "2026-04-09T16:05:45.054Z" }, + { url = "https://files.pythonhosted.org/packages/04/44/b2ed37df6be5b3d42cfe36318e0598e80843d5c6308dd63d0bf4e0ce5028/librt-0.9.0-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:3be322a15ee5e70b93b7a59cfd074614f22cc8c9ff18bd27f474e79137ea8d3b", size = 245001, upload-time = "2026-04-09T16:05:46.34Z" }, + { url = "https://files.pythonhosted.org/packages/47/e7/617e412426df89169dd2a9ed0cc8752d5763336252c65dbf945199915119/librt-0.9.0-cp314-cp314-win32.whl", hash = "sha256:b8da9f8035bb417770b1e1610526d87ad4fc58a2804dc4d79c53f6d2cf5a6eb9", size = 51799, upload-time = "2026-04-09T16:05:47.738Z" }, + { url = "https://files.pythonhosted.org/packages/24/ed/c22ca4db0ca3cbc285e4d9206108746beda561a9792289c3c31281d7e9df/librt-0.9.0-cp314-cp314-win_amd64.whl", hash = "sha256:b8bd70d5d816566a580d193326912f4a76ec2d28a97dc4cd4cc831c0af8e330e", size = 59165, upload-time = "2026-04-09T16:05:49.198Z" }, + { url = "https://files.pythonhosted.org/packages/24/56/875398fafa4cbc8f15b89366fc3287304ddd3314d861f182a4b87595ace0/librt-0.9.0-cp314-cp314-win_arm64.whl", hash = "sha256:fc5758e2b7a56532dc33e3c544d78cbaa9ecf0a0f2a2da2df882c1d6b99a317f", size = 49292, upload-time = "2026-04-09T16:05:50.362Z" }, + { url = "https://files.pythonhosted.org/packages/4c/61/bc448ecbf9b2d69c5cff88fe41496b19ab2a1cbda0065e47d4d0d51c0867/librt-0.9.0-cp314-cp314t-macosx_10_13_x86_64.whl", hash = "sha256:f24b90b0e0c8cc9491fb1693ae91fe17cb7963153a1946395acdbdd5818429a4", size = 70175, upload-time = "2026-04-09T16:05:51.564Z" }, + { url = "https://files.pythonhosted.org/packages/60/f2/c47bb71069a73e2f04e70acbd196c1e5cc411578ac99039a224b98920fd4/librt-0.9.0-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:3fe56e80badb66fdcde06bef81bbaa5bfcf6fbd7aefb86222d9e369c38c6b228", size = 72951, upload-time = "2026-04-09T16:05:52.699Z" }, + { url = "https://files.pythonhosted.org/packages/29/19/0549df59060631732df758e8886d92088da5fdbedb35b80e4643664e8412/librt-0.9.0-cp314-cp314t-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:527b5b820b47a09e09829051452bb0d1dd2122261254e2a6f674d12f1d793d54", size = 225864, upload-time = "2026-04-09T16:05:53.895Z" }, + { url = "https://files.pythonhosted.org/packages/9d/f8/3b144396d302ac08e50f89e64452c38db84bc7b23f6c60479c5d3abd303c/librt-0.9.0-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:7d429bdd4ac0ab17c8e4a8af0ed2a7440b16eba474909ab357131018fe8c7e71", size = 241155, upload-time = "2026-04-09T16:05:55.191Z" }, + { url = "https://files.pythonhosted.org/packages/7a/ce/ee67ec14581de4043e61d05786d2aed6c9b5338816b7859bcf07455c6a9f/librt-0.9.0-cp314-cp314t-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:7202bdcac47d3a708271c4304a474a8605a4a9a4a709e954bf2d3241140aa938", size = 252235, upload-time = "2026-04-09T16:05:56.549Z" }, + { url = "https://files.pythonhosted.org/packages/8a/fa/0ead15daa2b293a54101550b08d4bafe387b7d4a9fc6d2b985602bae69b6/librt-0.9.0-cp314-cp314t-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:c0d620e74897f8c2613b3c4e2e9c1e422eb46d2ddd07df540784d44117836af3", size = 244963, upload-time = "2026-04-09T16:05:57.858Z" }, + { url = "https://files.pythonhosted.org/packages/29/68/9fbf9a9aa704ba87689e40017e720aced8d9a4d2b46b82451d8142f91ec9/librt-0.9.0-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:d69fc39e627908f4c03297d5a88d9284b73f4d90b424461e32e8c2485e21c283", size = 257364, upload-time = "2026-04-09T16:05:59.686Z" }, + { url = "https://files.pythonhosted.org/packages/1a/8d/9d60869f1b6716c762e45f66ed945b1e5dd649f7377684c3b176ae424648/librt-0.9.0-cp314-cp314t-musllinux_1_2_i686.whl", hash = "sha256:c2640e23d2b7c98796f123ffd95cf2022c7777aa8a4a3b98b36c570d37e85eee", size = 247661, upload-time = "2026-04-09T16:06:00.938Z" }, + { url = "https://files.pythonhosted.org/packages/70/ff/a5c365093962310bfdb4f6af256f191085078ffb529b3f0cbebb5b33ebe2/librt-0.9.0-cp314-cp314t-musllinux_1_2_riscv64.whl", hash = "sha256:451daa98463b7695b0a30aa56bf637831ea559e7b8101ac2ef6382e8eb15e29c", size = 248238, upload-time = "2026-04-09T16:06:02.537Z" }, + { url = "https://files.pythonhosted.org/packages/a0/3c/2d34365177f412c9e19c0a29f969d70f5343f27634b76b765a54d8b27705/librt-0.9.0-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:928bd06eca2c2bbf4349e5b817f837509b0604342e65a502de1d50a7570afd15", size = 269457, upload-time = "2026-04-09T16:06:03.833Z" }, + { url = "https://files.pythonhosted.org/packages/bc/cd/de45b239ea3bdf626f982a00c14bfcf2e12d261c510ba7db62c5969a27cd/librt-0.9.0-cp314-cp314t-win32.whl", hash = "sha256:a9c63e04d003bc0fb6a03b348018b9a3002f98268200e22cc80f146beac5dc40", size = 52453, upload-time = "2026-04-09T16:06:05.229Z" }, + { url = "https://files.pythonhosted.org/packages/7f/f9/bfb32ae428aa75c0c533915622176f0a17d6da7b72b5a3c6363685914f70/librt-0.9.0-cp314-cp314t-win_amd64.whl", hash = "sha256:f162af66a2ed3f7d1d161a82ca584efd15acd9c1cff190a373458c32f7d42118", size = 60044, upload-time = "2026-04-09T16:06:06.398Z" }, + { url = "https://files.pythonhosted.org/packages/aa/47/7d70414bcdbb3bc1f458a8d10558f00bbfdb24e5a11740fc8197e12c3255/librt-0.9.0-cp314-cp314t-win_arm64.whl", hash = "sha256:a4b25c6c25cac5d0d9d6d6da855195b254e0021e513e0249f0e3b444dc6e0e61", size = 50009, upload-time = "2026-04-09T16:06:07.995Z" }, ] [[package]] @@ -3087,7 +3099,7 @@ wheels = [ [[package]] name = "mypy" -version = "1.19.1" +version = "1.20.1" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "librt", marker = "platform_python_implementation != 'PyPy'" }, @@ -3096,39 +3108,51 @@ dependencies = [ { name = "tomli", marker = "python_full_version < '3.11'" }, { name = "typing-extensions" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/f5/db/4efed9504bc01309ab9c2da7e352cc223569f05478012b5d9ece38fd44d2/mypy-1.19.1.tar.gz", hash = "sha256:19d88bb05303fe63f71dd2c6270daca27cb9401c4ca8255fe50d1d920e0eb9ba", size = 3582404, upload-time = "2025-12-15T05:03:48.42Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/2f/63/e499890d8e39b1ff2df4c0c6ce5d371b6844ee22b8250687a99fd2f657a8/mypy-1.19.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:5f05aa3d375b385734388e844bc01733bd33c644ab48e9684faa54e5389775ec", size = 13101333, upload-time = "2025-12-15T05:03:03.28Z" }, - { url = "https://files.pythonhosted.org/packages/72/4b/095626fc136fba96effc4fd4a82b41d688ab92124f8c4f7564bffe5cf1b0/mypy-1.19.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:022ea7279374af1a5d78dfcab853fe6a536eebfda4b59deab53cd21f6cd9f00b", size = 12164102, upload-time = "2025-12-15T05:02:33.611Z" }, - { url = "https://files.pythonhosted.org/packages/0c/5b/952928dd081bf88a83a5ccd49aaecfcd18fd0d2710c7ff07b8fb6f7032b9/mypy-1.19.1-cp310-cp310-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:ee4c11e460685c3e0c64a4c5de82ae143622410950d6be863303a1c4ba0e36d6", size = 12765799, upload-time = "2025-12-15T05:03:28.44Z" }, - { url = "https://files.pythonhosted.org/packages/2a/0d/93c2e4a287f74ef11a66fb6d49c7a9f05e47b0a4399040e6719b57f500d2/mypy-1.19.1-cp310-cp310-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:de759aafbae8763283b2ee5869c7255391fbc4de3ff171f8f030b5ec48381b74", size = 13522149, upload-time = "2025-12-15T05:02:36.011Z" }, - { url = "https://files.pythonhosted.org/packages/7b/0e/33a294b56aaad2b338d203e3a1d8b453637ac36cb278b45005e0901cf148/mypy-1.19.1-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:ab43590f9cd5108f41aacf9fca31841142c786827a74ab7cc8a2eacb634e09a1", size = 13810105, upload-time = "2025-12-15T05:02:40.327Z" }, - { url = "https://files.pythonhosted.org/packages/0e/fd/3e82603a0cb66b67c5e7abababce6bf1a929ddf67bf445e652684af5c5a0/mypy-1.19.1-cp310-cp310-win_amd64.whl", hash = "sha256:2899753e2f61e571b3971747e302d5f420c3fd09650e1951e99f823bc3089dac", size = 10057200, upload-time = "2025-12-15T05:02:51.012Z" }, - { url = "https://files.pythonhosted.org/packages/ef/47/6b3ebabd5474d9cdc170d1342fbf9dddc1b0ec13ec90bf9004ee6f391c31/mypy-1.19.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:d8dfc6ab58ca7dda47d9237349157500468e404b17213d44fc1cb77bce532288", size = 13028539, upload-time = "2025-12-15T05:03:44.129Z" }, - { url = "https://files.pythonhosted.org/packages/5c/a6/ac7c7a88a3c9c54334f53a941b765e6ec6c4ebd65d3fe8cdcfbe0d0fd7db/mypy-1.19.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:e3f276d8493c3c97930e354b2595a44a21348b320d859fb4a2b9f66da9ed27ab", size = 12083163, upload-time = "2025-12-15T05:03:37.679Z" }, - { url = "https://files.pythonhosted.org/packages/67/af/3afa9cf880aa4a2c803798ac24f1d11ef72a0c8079689fac5cfd815e2830/mypy-1.19.1-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:2abb24cf3f17864770d18d673c85235ba52456b36a06b6afc1e07c1fdcd3d0e6", size = 12687629, upload-time = "2025-12-15T05:02:31.526Z" }, - { url = "https://files.pythonhosted.org/packages/2d/46/20f8a7114a56484ab268b0ab372461cb3a8f7deed31ea96b83a4e4cfcfca/mypy-1.19.1-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:a009ffa5a621762d0c926a078c2d639104becab69e79538a494bcccb62cc0331", size = 13436933, upload-time = "2025-12-15T05:03:15.606Z" }, - { url = "https://files.pythonhosted.org/packages/5b/f8/33b291ea85050a21f15da910002460f1f445f8007adb29230f0adea279cb/mypy-1.19.1-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:f7cee03c9a2e2ee26ec07479f38ea9c884e301d42c6d43a19d20fb014e3ba925", size = 13661754, upload-time = "2025-12-15T05:02:26.731Z" }, - { url = "https://files.pythonhosted.org/packages/fd/a3/47cbd4e85bec4335a9cd80cf67dbc02be21b5d4c9c23ad6b95d6c5196bac/mypy-1.19.1-cp311-cp311-win_amd64.whl", hash = "sha256:4b84a7a18f41e167f7995200a1d07a4a6810e89d29859df936f1c3923d263042", size = 10055772, upload-time = "2025-12-15T05:03:26.179Z" }, - { url = "https://files.pythonhosted.org/packages/06/8a/19bfae96f6615aa8a0604915512e0289b1fad33d5909bf7244f02935d33a/mypy-1.19.1-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:a8174a03289288c1f6c46d55cef02379b478bfbc8e358e02047487cad44c6ca1", size = 13206053, upload-time = "2025-12-15T05:03:46.622Z" }, - { url = "https://files.pythonhosted.org/packages/a5/34/3e63879ab041602154ba2a9f99817bb0c85c4df19a23a1443c8986e4d565/mypy-1.19.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:ffcebe56eb09ff0c0885e750036a095e23793ba6c2e894e7e63f6d89ad51f22e", size = 12219134, upload-time = "2025-12-15T05:03:24.367Z" }, - { url = "https://files.pythonhosted.org/packages/89/cc/2db6f0e95366b630364e09845672dbee0cbf0bbe753a204b29a944967cd9/mypy-1.19.1-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:b64d987153888790bcdb03a6473d321820597ab8dd9243b27a92153c4fa50fd2", size = 12731616, upload-time = "2025-12-15T05:02:44.725Z" }, - { url = "https://files.pythonhosted.org/packages/00/be/dd56c1fd4807bc1eba1cf18b2a850d0de7bacb55e158755eb79f77c41f8e/mypy-1.19.1-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:c35d298c2c4bba75feb2195655dfea8124d855dfd7343bf8b8c055421eaf0cf8", size = 13620847, upload-time = "2025-12-15T05:03:39.633Z" }, - { url = "https://files.pythonhosted.org/packages/6d/42/332951aae42b79329f743bf1da088cd75d8d4d9acc18fbcbd84f26c1af4e/mypy-1.19.1-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:34c81968774648ab5ac09c29a375fdede03ba253f8f8287847bd480782f73a6a", size = 13834976, upload-time = "2025-12-15T05:03:08.786Z" }, - { url = "https://files.pythonhosted.org/packages/6f/63/e7493e5f90e1e085c562bb06e2eb32cae27c5057b9653348d38b47daaecc/mypy-1.19.1-cp312-cp312-win_amd64.whl", hash = "sha256:b10e7c2cd7870ba4ad9b2d8a6102eb5ffc1f16ca35e3de6bfa390c1113029d13", size = 10118104, upload-time = "2025-12-15T05:03:10.834Z" }, - { url = "https://files.pythonhosted.org/packages/de/9f/a6abae693f7a0c697dbb435aac52e958dc8da44e92e08ba88d2e42326176/mypy-1.19.1-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:e3157c7594ff2ef1634ee058aafc56a82db665c9438fd41b390f3bde1ab12250", size = 13201927, upload-time = "2025-12-15T05:02:29.138Z" }, - { url = "https://files.pythonhosted.org/packages/9a/a4/45c35ccf6e1c65afc23a069f50e2c66f46bd3798cbe0d680c12d12935caa/mypy-1.19.1-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:bdb12f69bcc02700c2b47e070238f42cb87f18c0bc1fc4cdb4fb2bc5fd7a3b8b", size = 12206730, upload-time = "2025-12-15T05:03:01.325Z" }, - { url = "https://files.pythonhosted.org/packages/05/bb/cdcf89678e26b187650512620eec8368fded4cfd99cfcb431e4cdfd19dec/mypy-1.19.1-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:f859fb09d9583a985be9a493d5cfc5515b56b08f7447759a0c5deaf68d80506e", size = 12724581, upload-time = "2025-12-15T05:03:20.087Z" }, - { url = "https://files.pythonhosted.org/packages/d1/32/dd260d52babf67bad8e6770f8e1102021877ce0edea106e72df5626bb0ec/mypy-1.19.1-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:c9a6538e0415310aad77cb94004ca6482330fece18036b5f360b62c45814c4ef", size = 13616252, upload-time = "2025-12-15T05:02:49.036Z" }, - { url = "https://files.pythonhosted.org/packages/71/d0/5e60a9d2e3bd48432ae2b454b7ef2b62a960ab51292b1eda2a95edd78198/mypy-1.19.1-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:da4869fc5e7f62a88f3fe0b5c919d1d9f7ea3cef92d3689de2823fd27e40aa75", size = 13840848, upload-time = "2025-12-15T05:02:55.95Z" }, - { url = "https://files.pythonhosted.org/packages/98/76/d32051fa65ecf6cc8c6610956473abdc9b4c43301107476ac03559507843/mypy-1.19.1-cp313-cp313-win_amd64.whl", hash = "sha256:016f2246209095e8eda7538944daa1d60e1e8134d98983b9fc1e92c1fc0cb8dd", size = 10135510, upload-time = "2025-12-15T05:02:58.438Z" }, - { url = "https://files.pythonhosted.org/packages/de/eb/b83e75f4c820c4247a58580ef86fcd35165028f191e7e1ba57128c52782d/mypy-1.19.1-cp314-cp314-macosx_10_15_x86_64.whl", hash = "sha256:06e6170bd5836770e8104c8fdd58e5e725cfeb309f0a6c681a811f557e97eac1", size = 13199744, upload-time = "2025-12-15T05:03:30.823Z" }, - { url = "https://files.pythonhosted.org/packages/94/28/52785ab7bfa165f87fcbb61547a93f98bb20e7f82f90f165a1f69bce7b3d/mypy-1.19.1-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:804bd67b8054a85447c8954215a906d6eff9cabeabe493fb6334b24f4bfff718", size = 12215815, upload-time = "2025-12-15T05:02:42.323Z" }, - { url = "https://files.pythonhosted.org/packages/0a/c6/bdd60774a0dbfb05122e3e925f2e9e846c009e479dcec4821dad881f5b52/mypy-1.19.1-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:21761006a7f497cb0d4de3d8ef4ca70532256688b0523eee02baf9eec895e27b", size = 12740047, upload-time = "2025-12-15T05:03:33.168Z" }, - { url = "https://files.pythonhosted.org/packages/32/2a/66ba933fe6c76bd40d1fe916a83f04fed253152f451a877520b3c4a5e41e/mypy-1.19.1-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:28902ee51f12e0f19e1e16fbe2f8f06b6637f482c459dd393efddd0ec7f82045", size = 13601998, upload-time = "2025-12-15T05:03:13.056Z" }, - { url = "https://files.pythonhosted.org/packages/e3/da/5055c63e377c5c2418760411fd6a63ee2b96cf95397259038756c042574f/mypy-1.19.1-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:481daf36a4c443332e2ae9c137dfee878fcea781a2e3f895d54bd3002a900957", size = 13807476, upload-time = "2025-12-15T05:03:17.977Z" }, - { url = "https://files.pythonhosted.org/packages/cd/09/4ebd873390a063176f06b0dbf1f7783dd87bd120eae7727fa4ae4179b685/mypy-1.19.1-cp314-cp314-win_amd64.whl", hash = "sha256:8bb5c6f6d043655e055be9b542aa5f3bdd30e4f3589163e85f93f3640060509f", size = 10281872, upload-time = "2025-12-15T05:03:05.549Z" }, - { url = "https://files.pythonhosted.org/packages/8d/f4/4ce9a05ce5ded1de3ec1c1d96cf9f9504a04e54ce0ed55cfa38619a32b8d/mypy-1.19.1-py3-none-any.whl", hash = "sha256:f1235f5ea01b7db5468d53ece6aaddf1ad0b88d9e7462b86ef96fe04995d7247", size = 2471239, upload-time = "2025-12-15T05:03:07.248Z" }, +sdist = { url = "https://files.pythonhosted.org/packages/0b/3d/5b373635b3146264eb7a68d09e5ca11c305bbb058dfffbb47c47daf4f632/mypy-1.20.1.tar.gz", hash = "sha256:6fc3f4ecd52de81648fed1945498bf42fa2993ddfad67c9056df36ae5757f804", size = 3815892, upload-time = "2026-04-13T02:46:51.474Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/21/4b/b1fa23297c8a5c403aabaac0649549efc5a0af7095f3dd33e7482863f973/mypy-1.20.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:3ba5d1e712ada9c3b6223dcbc5a31dac334ed62991e5caa17bcf5a4ddc349af0", size = 14426426, upload-time = "2026-04-13T02:46:37.828Z" }, + { url = "https://files.pythonhosted.org/packages/22/53/82923480aee5507a46df22428316e28b2b710d08506a128b2acef81ab18e/mypy-1.20.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:2e731284c117b0987fb1e6c5013a56f33e7faa1fce594066ab83876183ce1c66", size = 13307651, upload-time = "2026-04-13T02:46:22.676Z" }, + { url = "https://files.pythonhosted.org/packages/4e/0c/91905b393c790440fa273f0903ee2b07cce95bb6deccac87e6eb343d077a/mypy-1.20.1-cp310-cp310-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:f8e945b872a05f4fbefabe2249c0b07b6b194e5e11a86ebee9edf855de09806c", size = 13746066, upload-time = "2026-04-13T02:45:15.345Z" }, + { url = "https://files.pythonhosted.org/packages/88/b9/8a7017270438e34544e19dd6284cad54fd65dde3c35418a2ce07a1897804/mypy-1.20.1-cp310-cp310-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:2fc88acef0dc9b15246502b418980478c1bfc9702057a0e1e7598d01a7af8937", size = 14617944, upload-time = "2026-04-13T02:45:44.954Z" }, + { url = "https://files.pythonhosted.org/packages/0c/cf/5a61ceec3fc133e0f559d1e1f9adf4150abdbc2ad8eb831ec26fc8459196/mypy-1.20.1-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:14911a115c73608f155f648b978c5055d16ff974e6b1b5512d7fedf4fa8b15c6", size = 14918205, upload-time = "2026-04-13T02:45:42.653Z" }, + { url = "https://files.pythonhosted.org/packages/6f/80/afb1c665e9c426c78e4711cce04e446b645867bfb97936158886103c1648/mypy-1.20.1-cp310-cp310-win_amd64.whl", hash = "sha256:76d9b4c992cca3331d9793ef197ae360ea44953cf35beb2526e95b9e074f2866", size = 10823344, upload-time = "2026-04-13T02:46:07.607Z" }, + { url = "https://files.pythonhosted.org/packages/11/68/7ad64b49b7663c88fef76a2ac689ea73e17804832ac4cb5416bcff17775b/mypy-1.20.1-cp310-cp310-win_arm64.whl", hash = "sha256:b408722f80be44845da555671a5ef3a0c63f51ca5752b0c20e992dc9c0fbd3cd", size = 9760694, upload-time = "2026-04-13T02:46:49.369Z" }, + { url = "https://files.pythonhosted.org/packages/82/0d/555ab7453cc4a4a8643b7f21c842b1a84c36b15392061ae7b052ee119320/mypy-1.20.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:c01eb9bac2c6a962d00f9d23421cd2913840e65bba365167d057bd0b4171a92e", size = 14336012, upload-time = "2026-04-13T02:45:39.935Z" }, + { url = "https://files.pythonhosted.org/packages/57/26/85a28893f7db8a16ebb41d1e9dfcb4475844d06a88480b6639e32a74d6ef/mypy-1.20.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:55d12ddbd8a9cac5b276878bd534fa39fff5bf543dc6ae18f25d30c8d7d27fca", size = 13224636, upload-time = "2026-04-13T02:45:49.659Z" }, + { url = "https://files.pythonhosted.org/packages/93/41/bd4cd3c2caeb6c448b669222b8cfcbdee4a03b89431527b56fca9e56b6f3/mypy-1.20.1-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:c0aa322c1468b6cdfc927a44ce130f79bb44bcd34eb4a009eb9f96571fd80955", size = 13663471, upload-time = "2026-04-13T02:46:20.276Z" }, + { url = "https://files.pythonhosted.org/packages/3e/56/7ee8c471e10402d64b6517ae10434541baca053cffd81090e4097d5609d4/mypy-1.20.1-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:3f8bc95899cf676b6e2285779a08a998cc3a7b26f1026752df9d2741df3c79e8", size = 14532344, upload-time = "2026-04-13T02:46:44.205Z" }, + { url = "https://files.pythonhosted.org/packages/b5/95/b37d1fa859a433f6156742e12f62b0bb75af658544fb6dada9363918743a/mypy-1.20.1-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:47c2b90191a870a04041e910277494b0d92f0711be9e524d45c074fe60c00b65", size = 14776670, upload-time = "2026-04-13T02:45:52.481Z" }, + { url = "https://files.pythonhosted.org/packages/03/77/b302e4cb0b80d2bdf6bf4fce5864bb4cbfa461f7099cea544eaf2457df78/mypy-1.20.1-cp311-cp311-win_amd64.whl", hash = "sha256:9857dc8d2ec1a392ffbda518075beb00ac58859979c79f9e6bdcb7277082c2f2", size = 10816524, upload-time = "2026-04-13T02:45:37.711Z" }, + { url = "https://files.pythonhosted.org/packages/7f/21/d969d7a68eb964993ebcc6170d5ecaf0cf65830c58ac3344562e16dc42a9/mypy-1.20.1-cp311-cp311-win_arm64.whl", hash = "sha256:09d8df92bb25b6065ab91b178da843dda67b33eb819321679a6e98a907ce0e10", size = 9750419, upload-time = "2026-04-13T02:45:08.542Z" }, + { url = "https://files.pythonhosted.org/packages/69/1b/75a7c825a02781ca10bc2f2f12fba2af5202f6d6005aad8d2d1f264d8d78/mypy-1.20.1-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:36ee2b9c6599c230fea89bbd79f401f9f9f8e9fcf0c777827789b19b7da90f51", size = 14494077, upload-time = "2026-04-13T02:45:55.085Z" }, + { url = "https://files.pythonhosted.org/packages/b0/54/5e5a569ea5c2b4d48b729fb32aa936eeb4246e4fc3e6f5b3d36a2dfbefb9/mypy-1.20.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:fba3fb0968a7b48806b0c90f38d39296f10766885a94c83bd21399de1e14eb28", size = 13319495, upload-time = "2026-04-13T02:45:29.674Z" }, + { url = "https://files.pythonhosted.org/packages/6f/a4/a1945b19f33e91721b59deee3abb484f2fa5922adc33bb166daf5325d76d/mypy-1.20.1-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:ef1415a637cd3627d6304dfbeddbadd21079dafc2a8a753c477ce4fc0c2af54f", size = 13696948, upload-time = "2026-04-13T02:46:15.006Z" }, + { url = "https://files.pythonhosted.org/packages/b2/c6/75e969781c2359b2f9c15b061f28ec6d67c8b61865ceda176e85c8e7f2de/mypy-1.20.1-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:ef3461b1ad5cd446e540016e90b5984657edda39f982f4cc45ca317b628f5a37", size = 14706744, upload-time = "2026-04-13T02:46:00.482Z" }, + { url = "https://files.pythonhosted.org/packages/a8/6e/b221b1de981fc4262fe3e0bf9ec272d292dfe42394a689c2d49765c144c4/mypy-1.20.1-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:542dd63c9e1339b6092eb25bd515f3a32a1453aee8c9521d2ddb17dacd840237", size = 14949035, upload-time = "2026-04-13T02:45:06.021Z" }, + { url = "https://files.pythonhosted.org/packages/ca/4b/298ba2de0aafc0da3ff2288da06884aae7ba6489bc247c933f87847c41b3/mypy-1.20.1-cp312-cp312-win_amd64.whl", hash = "sha256:1d55c7cd8ca22e31f93af2a01160a9e95465b5878de23dba7e48116052f20a8d", size = 10883216, upload-time = "2026-04-13T02:45:47.232Z" }, + { url = "https://files.pythonhosted.org/packages/c7/f9/5e25b8f0b8cb92f080bfed9c21d3279b2a0b6a601cdca369a039ba84789d/mypy-1.20.1-cp312-cp312-win_arm64.whl", hash = "sha256:f5b84a79070586e0d353ee07b719d9d0a4aa7c8ee90c0ea97747e98cbe193019", size = 9814299, upload-time = "2026-04-13T02:45:21.934Z" }, + { url = "https://files.pythonhosted.org/packages/21/e8/ef0991aa24c8f225df10b034f3c2681213cb54cf247623c6dec9a5744e70/mypy-1.20.1-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:8f3886c03e40afefd327bd70b3f634b39ea82e87f314edaa4d0cce4b927ddcc1", size = 14500739, upload-time = "2026-04-13T02:46:05.442Z" }, + { url = "https://files.pythonhosted.org/packages/23/73/416ebec3047636ed89fa871dc8c54bf05e9e20aa9499da59790d7adb312d/mypy-1.20.1-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:e860eb3904f9764e83bafd70c8250bdffdc7dde6b82f486e8156348bf7ceb184", size = 13314735, upload-time = "2026-04-13T02:46:47.154Z" }, + { url = "https://files.pythonhosted.org/packages/10/1e/1505022d9c9ac2e014a384eb17638fb37bf8e9d0a833ea60605b66f8f7ba/mypy-1.20.1-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:a4b5aac6e785719da51a84f5d09e9e843d473170a9045b1ea7ea1af86225df4b", size = 13704356, upload-time = "2026-04-13T02:45:19.773Z" }, + { url = "https://files.pythonhosted.org/packages/98/91/275b01f5eba5c467a3318ec214dd865abb66e9c811231c8587287b92876a/mypy-1.20.1-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:f37b6cd0fe2ad3a20f05ace48ca3523fc52ff86940e34937b439613b6854472e", size = 14696420, upload-time = "2026-04-13T02:45:24.205Z" }, + { url = "https://files.pythonhosted.org/packages/a1/57/b3779e134e1b7250d05f874252780d0a88c068bc054bcff99ca20a3a2986/mypy-1.20.1-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:e4bbb0f6b54ce7cc350ef4a770650d15fa70edd99ad5267e227133eda9c94218", size = 14936093, upload-time = "2026-04-13T02:45:32.087Z" }, + { url = "https://files.pythonhosted.org/packages/be/33/81b64991b0f3f278c3b55c335888794af190b2d59031a5ad1401bcb69f1e/mypy-1.20.1-cp313-cp313-win_amd64.whl", hash = "sha256:c3dc20f8ec76eecd77148cdd2f1542ed496e51e185713bf488a414f862deb8f2", size = 10889659, upload-time = "2026-04-13T02:46:02.926Z" }, + { url = "https://files.pythonhosted.org/packages/1b/fd/7adcb8053572edf5ef8f3db59599dfeeee3be9cc4c8c97e2d28f66f42ac5/mypy-1.20.1-cp313-cp313-win_arm64.whl", hash = "sha256:a9d62bbac5d6d46718e2b0330b25e6264463ed832722b8f7d4440ff1be3ca895", size = 9815515, upload-time = "2026-04-13T02:46:32.103Z" }, + { url = "https://files.pythonhosted.org/packages/40/cd/db831e84c81d57d4886d99feee14e372f64bbec6a9cb1a88a19e243f2ef5/mypy-1.20.1-cp314-cp314-macosx_10_15_x86_64.whl", hash = "sha256:12927b9c0ed794daedcf1dab055b6c613d9d5659ac511e8d936d96f19c087d12", size = 14483064, upload-time = "2026-04-13T02:45:26.901Z" }, + { url = "https://files.pythonhosted.org/packages/d5/82/74e62e7097fa67da328ac8ece8de09133448c04d20ddeaeba251a3000f01/mypy-1.20.1-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:752507dd481e958b2c08fc966d3806c962af5a9433b5bf8f3bdd7175c20e34fe", size = 13335694, upload-time = "2026-04-13T02:46:12.514Z" }, + { url = "https://files.pythonhosted.org/packages/74/c4/97e9a0abe4f3cdbbf4d079cb87a03b786efeccf5bf2b89fe4f96939ab2e6/mypy-1.20.1-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:c614655b5a065e56274c6cbbe405f7cf7e96c0654db7ba39bc680238837f7b08", size = 13726365, upload-time = "2026-04-13T02:45:17.422Z" }, + { url = "https://files.pythonhosted.org/packages/d7/aa/a19d884a8d28fcd3c065776323029f204dbc774e70ec9c85eba228b680de/mypy-1.20.1-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:2c3f6221a76f34d5100c6d35b3ef6b947054123c3f8d6938a4ba00b1308aa572", size = 14693472, upload-time = "2026-04-13T02:46:41.253Z" }, + { url = "https://files.pythonhosted.org/packages/84/44/cc9324bd21cf786592b44bf3b5d224b3923c1230ec9898d508d00241d465/mypy-1.20.1-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:4bdfc06303ac06500af71ea0cdbe995c502b3c9ba32f3f8313523c137a25d1b6", size = 14919266, upload-time = "2026-04-13T02:46:28.37Z" }, + { url = "https://files.pythonhosted.org/packages/6e/dc/779abb25a8c63e8f44bf5a336217fa92790fa17e0c40e0c725d10cb01bbd/mypy-1.20.1-cp314-cp314-win_amd64.whl", hash = "sha256:0131edd7eba289973d1ba1003d1a37c426b85cdef76650cd02da6420898a5eb3", size = 11049713, upload-time = "2026-04-13T02:45:57.673Z" }, + { url = "https://files.pythonhosted.org/packages/28/08/4172be2ad7de9119b5a92ca36abbf641afdc5cb1ef4ae0c3a8182f29674f/mypy-1.20.1-cp314-cp314-win_arm64.whl", hash = "sha256:33f02904feb2c07e1fdf7909026206396c9deeb9e6f34d466b4cfedb0aadbbe4", size = 9999819, upload-time = "2026-04-13T02:46:35.039Z" }, + { url = "https://files.pythonhosted.org/packages/2d/af/af9e46b0c8eabbce9fc04a477564170f47a1c22b308822282a59b7ff315f/mypy-1.20.1-cp314-cp314t-macosx_10_15_x86_64.whl", hash = "sha256:168472149dd8cc505c98cefd21ad77e4257ed6022cd5ed2fe2999bed56977a5a", size = 15547508, upload-time = "2026-04-13T02:46:25.588Z" }, + { url = "https://files.pythonhosted.org/packages/a7/cd/39c9e4ad6ba33e069e5837d772a9e6c304b4a5452a14a975d52b36444650/mypy-1.20.1-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:eb674600309a8f22790cca883a97c90299f948183ebb210fbef6bcee07cb1986", size = 14399557, upload-time = "2026-04-13T02:46:10.021Z" }, + { url = "https://files.pythonhosted.org/packages/83/c1/3fd71bdc118ffc502bf57559c909927bb7e011f327f7bb8e0488e98a5870/mypy-1.20.1-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:ef2b2e4cc464ba9795459f2586923abd58a0055487cbe558cb538ea6e6bc142a", size = 15045789, upload-time = "2026-04-13T02:45:10.81Z" }, + { url = "https://files.pythonhosted.org/packages/8e/73/6f07ff8b57a7d7b3e6e5bf34685d17632382395c8bb53364ec331661f83e/mypy-1.20.1-cp314-cp314t-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:dee461d396dd46b3f0ed5a098dbc9b8860c81c46ad44fa071afcfbc149f167c9", size = 15850795, upload-time = "2026-04-13T02:45:03.349Z" }, + { url = "https://files.pythonhosted.org/packages/ec/e2/f7dffec1c7767078f9e9adf0c786d1fe0ff30964a77eb213c09b8b58cb76/mypy-1.20.1-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:e364926308b3e66f1361f81a566fc1b2f8cd47fc8525e8136d4058a65a4b4f02", size = 16088539, upload-time = "2026-04-13T02:46:17.841Z" }, + { url = "https://files.pythonhosted.org/packages/1a/76/e0dee71035316e75a69d73aec2f03c39c21c967b97e277fd0ef8fd6aec66/mypy-1.20.1-cp314-cp314t-win_amd64.whl", hash = "sha256:a0c17fbd746d38c70cbc42647cfd884f845a9708a4b160a8b4f7e70d41f4d7fa", size = 12575567, upload-time = "2026-04-13T02:45:34.795Z" }, + { url = "https://files.pythonhosted.org/packages/22/a8/7ed43c9d9c3d1468f86605e323a5d97e411a448790a00f07e779f3211a46/mypy-1.20.1-cp314-cp314t-win_arm64.whl", hash = "sha256:db2cb89654626a912efda69c0d5c1d22d948265e2069010d3dde3abf751c7d08", size = 10378823, upload-time = "2026-04-13T02:45:13.35Z" }, + { url = "https://files.pythonhosted.org/packages/d8/28/926bd972388e65a39ee98e188ccf67e81beb3aacfd5d6b310051772d974b/mypy-1.20.1-py3-none-any.whl", hash = "sha256:1aae28507f253fe82d883790d1c0a0d35798a810117c88184097fe8881052f06", size = 2636553, upload-time = "2026-04-13T02:46:30.45Z" }, ] [[package]] From 750ef483f28b68dc5764d3cb59941e5640a3d746 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Wed, 22 Apr 2026 12:41:48 +0000 Subject: [PATCH 002/462] =?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 e9b1b9c5d..0bcdb9932 100644 --- a/docs/en/docs/release-notes.md +++ b/docs/en/docs/release-notes.md @@ -9,6 +9,7 @@ hide: ### Internal +* ⬆ Bump mypy from 1.19.1 to 1.20.1. PR [#15410](https://github.com/fastapi/fastapi/pull/15410) by [@dependabot[bot]](https://github.com/apps/dependabot). * ⬆ Bump python-dotenv from 1.2.1 to 1.2.2. PR [#15400](https://github.com/fastapi/fastapi/pull/15400) by [@dependabot[bot]](https://github.com/apps/dependabot). * ⬆ Bump starlette from 0.52.1 to 1.0.0. PR [#15397](https://github.com/fastapi/fastapi/pull/15397) by [@dependabot[bot]](https://github.com/apps/dependabot). * ⬆ Bump pygithub from 2.8.1 to 2.9.1. PR [#15396](https://github.com/fastapi/fastapi/pull/15396) by [@dependabot[bot]](https://github.com/apps/dependabot). From 7402e33375f9ea85bbceadd52c6a667891d5375f Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 22 Apr 2026 14:44:48 +0200 Subject: [PATCH 003/462] =?UTF-8?q?=E2=AC=86=20Bump=20cloudflare/wrangler-?= =?UTF-8?q?action=20from=203.14.1=20to=203.15.0=20(#15405)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/deploy-docs.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/deploy-docs.yml b/.github/workflows/deploy-docs.yml index ead5ed4bc..3c65db23a 100644 --- a/.github/workflows/deploy-docs.yml +++ b/.github/workflows/deploy-docs.yml @@ -60,7 +60,7 @@ jobs: env: PROJECT_NAME: fastapitiangolo BRANCH: ${{ ( github.event.workflow_run.head_repository.full_name == github.repository && github.event.workflow_run.head_branch == 'master' && 'main' ) || ( github.event.workflow_run.head_sha ) }} - uses: cloudflare/wrangler-action@da0e0dfe58b7a431659754fdf3f186c529afbe65 # v3.14.1 + uses: cloudflare/wrangler-action@9acf94ace14e7dc412b076f2c5c20b8ce93c79cd # v3.15.0 with: apiToken: ${{ secrets.CLOUDFLARE_API_TOKEN }} # zizmor: ignore[secrets-outside-env] accountId: ${{ secrets.CLOUDFLARE_ACCOUNT_ID }} # zizmor: ignore[secrets-outside-env] From 5f68b19002050e227666b560b30c8f983bbeb58b Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Wed, 22 Apr 2026 12:45:14 +0000 Subject: [PATCH 004/462] =?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 0bcdb9932..a85ab7e15 100644 --- a/docs/en/docs/release-notes.md +++ b/docs/en/docs/release-notes.md @@ -9,6 +9,7 @@ hide: ### Internal +* ⬆ Bump cloudflare/wrangler-action from 3.14.1 to 3.15.0. PR [#15405](https://github.com/fastapi/fastapi/pull/15405) by [@dependabot[bot]](https://github.com/apps/dependabot). * ⬆ Bump mypy from 1.19.1 to 1.20.1. PR [#15410](https://github.com/fastapi/fastapi/pull/15410) by [@dependabot[bot]](https://github.com/apps/dependabot). * ⬆ Bump python-dotenv from 1.2.1 to 1.2.2. PR [#15400](https://github.com/fastapi/fastapi/pull/15400) by [@dependabot[bot]](https://github.com/apps/dependabot). * ⬆ Bump starlette from 0.52.1 to 1.0.0. PR [#15397](https://github.com/fastapi/fastapi/pull/15397) by [@dependabot[bot]](https://github.com/apps/dependabot). From ea230dc80b2ce061f82aceb59755553934a1e181 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 22 Apr 2026 14:49:01 +0200 Subject: [PATCH 005/462] =?UTF-8?q?=E2=AC=86=20Bump=20pytest-cov=20from=20?= =?UTF-8?q?7.0.0=20to=207.1.0=20(#15406)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- uv.lock | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/uv.lock b/uv.lock index 0b0bc9199..67e9e3314 100644 --- a/uv.lock +++ b/uv.lock @@ -4224,16 +4224,16 @@ wheels = [ [[package]] name = "pytest-cov" -version = "7.0.0" +version = "7.1.0" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "coverage", extra = ["toml"] }, { name = "pluggy" }, { name = "pytest" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/5e/f7/c933acc76f5208b3b00089573cf6a2bc26dc80a8aece8f52bb7d6b1855ca/pytest_cov-7.0.0.tar.gz", hash = "sha256:33c97eda2e049a0c5298e91f519302a1334c26ac65c1a483d6206fd458361af1", size = 54328, upload-time = "2025-09-09T10:57:02.113Z" } +sdist = { url = "https://files.pythonhosted.org/packages/b1/51/a849f96e117386044471c8ec2bd6cfebacda285da9525c9106aeb28da671/pytest_cov-7.1.0.tar.gz", hash = "sha256:30674f2b5f6351aa09702a9c8c364f6a01c27aae0c1366ae8016160d1efc56b2", size = 55592, upload-time = "2026-03-21T20:11:16.284Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/ee/49/1377b49de7d0c1ce41292161ea0f721913fa8722c19fb9c1e3aa0367eecb/pytest_cov-7.0.0-py3-none-any.whl", hash = "sha256:3b8e9558b16cc1479da72058bdecf8073661c7f57f7d3c5f22a1c23507f2d861", size = 22424, upload-time = "2025-09-09T10:57:00.695Z" }, + { url = "https://files.pythonhosted.org/packages/9d/7a/d968e294073affff457b041c2be9868a40c1c71f4a35fcc1e45e5493067b/pytest_cov-7.1.0-py3-none-any.whl", hash = "sha256:a0461110b7865f9a271aa1b51e516c9a95de9d696734a2f71e3e78f46e1d4678", size = 22876, upload-time = "2026-03-21T20:11:14.438Z" }, ] [[package]] From 71f3c3010831e121da36d890ce1f0d162a6fe5eb Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Wed, 22 Apr 2026 12:49:37 +0000 Subject: [PATCH 006/462] =?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 a85ab7e15..0e995e6e0 100644 --- a/docs/en/docs/release-notes.md +++ b/docs/en/docs/release-notes.md @@ -9,6 +9,7 @@ hide: ### Internal +* ⬆ Bump pytest-cov from 7.0.0 to 7.1.0. PR [#15406](https://github.com/fastapi/fastapi/pull/15406) by [@dependabot[bot]](https://github.com/apps/dependabot). * ⬆ Bump cloudflare/wrangler-action from 3.14.1 to 3.15.0. PR [#15405](https://github.com/fastapi/fastapi/pull/15405) by [@dependabot[bot]](https://github.com/apps/dependabot). * ⬆ Bump mypy from 1.19.1 to 1.20.1. PR [#15410](https://github.com/fastapi/fastapi/pull/15410) by [@dependabot[bot]](https://github.com/apps/dependabot). * ⬆ Bump python-dotenv from 1.2.1 to 1.2.2. PR [#15400](https://github.com/fastapi/fastapi/pull/15400) by [@dependabot[bot]](https://github.com/apps/dependabot). From 04958499e0a3c11881233f5e2fe0416b86f90db6 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 22 Apr 2026 14:53:36 +0200 Subject: [PATCH 007/462] =?UTF-8?q?=E2=AC=86=20Bump=20pytest-codspeed=20fr?= =?UTF-8?q?om=204.3.0=20to=204.4.0=20(#15407)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- uv.lock | 32 ++++++++++++++++---------------- 1 file changed, 16 insertions(+), 16 deletions(-) diff --git a/uv.lock b/uv.lock index 67e9e3314..91ec94346 100644 --- a/uv.lock +++ b/uv.lock @@ -4198,28 +4198,28 @@ wheels = [ [[package]] name = "pytest-codspeed" -version = "4.3.0" +version = "4.4.0" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "cffi" }, { name = "pytest" }, { name = "rich" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/98/ab/eca41967d11c95392829a8b4bfa9220a51cffc4a33ec4653358000356918/pytest_codspeed-4.3.0.tar.gz", hash = "sha256:5230d9d65f39063a313ed1820df775166227ec5c20a1122968f85653d5efee48", size = 124745, upload-time = "2026-02-09T15:23:34.745Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/7b/64/800bdaeabd3eb126aff7e3e22dc45b2826305f61cbfd093284caf8d9ca01/pytest_codspeed-4.3.0-cp310-cp310-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:b2acecc4126658abebc683b38121adec405a46e18a619d49d6154c6e60c5deb2", size = 347077, upload-time = "2026-02-09T15:23:17.2Z" }, - { url = "https://files.pythonhosted.org/packages/f3/f1/d69707440829adab86d078d5f1c8c070df116b1624f8eae4ff36933ba612/pytest_codspeed-4.3.0-cp310-cp310-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:619120775e92a3f43fb4ff4c256a251b1554c904d95e2154a382484283f0388a", size = 342234, upload-time = "2026-02-09T15:23:18.407Z" }, - { url = "https://files.pythonhosted.org/packages/d9/15/ec0ac1f022173b3134c9638f2a35f21fbb3142c75da066d9e49e5a8bb4bd/pytest_codspeed-4.3.0-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:dbeff1eb2f2e36df088658b556fa993e6937bf64ffb07406de4db16fd2b26874", size = 347076, upload-time = "2026-02-09T15:23:19.989Z" }, - { url = "https://files.pythonhosted.org/packages/a5/e8/1fe375794ad02b7835f378a7bcfa8fbac9acadefe600a782a7c4a7064db7/pytest_codspeed-4.3.0-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:878aad5e4bb7b401ad8d82f3af5186030cd2bd0d0446782e10dabb9db8827466", size = 342215, upload-time = "2026-02-09T15:23:20.954Z" }, - { url = "https://files.pythonhosted.org/packages/09/58/50df94e9a78e1c77818a492c90557eeb1309af025120c9a21e6375950c52/pytest_codspeed-4.3.0-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:527a3a02eaa3e4d4583adc4ba2327eef79628f3e1c682a4b959439551a72588e", size = 347395, upload-time = "2026-02-09T15:23:21.986Z" }, - { url = "https://files.pythonhosted.org/packages/e4/56/7dfbd3eefd112a14e6fb65f9ff31dacf2e9c381cb94b27332b81d2b13f8d/pytest_codspeed-4.3.0-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:9858c2a6e1f391d5696757e7b6e9484749a7376c46f8b4dd9aebf093479a9667", size = 342625, upload-time = "2026-02-09T15:23:23.035Z" }, - { url = "https://files.pythonhosted.org/packages/7f/53/7255f6a25bc56ff1745b254b21545dfe0be2268f5b91ce78f7e8a908f0ad/pytest_codspeed-4.3.0-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:34f2fd8497456eefbd325673f677ea80d93bb1bc08a578c1fa43a09cec3d1879", size = 347325, upload-time = "2026-02-09T15:23:23.998Z" }, - { url = "https://files.pythonhosted.org/packages/2e/f8/82ae570d8b9ad30f33c9d4002a7a1b2740de0e090540c69a28e4f711ebe2/pytest_codspeed-4.3.0-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:df6a36a2a9da1406bc50428437f657f0bd8c842ae54bee5fb3ad30e01d50c0f5", size = 342558, upload-time = "2026-02-09T15:23:25.656Z" }, - { url = "https://files.pythonhosted.org/packages/b3/e1/55cfe9474f91d174c7a4b04d257b5fc6d4d06f3d3680f2da672ee59ccc10/pytest_codspeed-4.3.0-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:bec30f4fc9c4973143cd80f0d33fa780e9fa3e01e4dbe8cedf229e72f1212c62", size = 347383, upload-time = "2026-02-09T15:23:26.68Z" }, - { url = "https://files.pythonhosted.org/packages/7f/3b/8fd781d959bbe789b3de8ce4c50d5706a684a0df377147dfb27b200c20c1/pytest_codspeed-4.3.0-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:e6584e641cadf27d894ae90b87c50377232a97cbfd76ee0c7ecd0c056fa3f7f4", size = 342481, upload-time = "2026-02-09T15:23:27.686Z" }, - { url = "https://files.pythonhosted.org/packages/bb/0c/368045133c6effa2c665b1634b7b8a9c88b307f877fa31f1f8df47885b51/pytest_codspeed-4.3.0-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:df0d1f6ea594f29b745c634d66d5f5f1caa1c3abd2af82fea49d656038e8fc77", size = 353680, upload-time = "2026-02-09T15:23:28.726Z" }, - { url = "https://files.pythonhosted.org/packages/59/21/e543abcd72244294e25ae88ec3a9311ade24d6913f8c8f42569d671700bc/pytest_codspeed-4.3.0-cp314-cp314t-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:a2f5bb6d8898bea7db45e3c8b916ee48e36905b929477bb511b79c5a3ccacda4", size = 347888, upload-time = "2026-02-09T15:23:30.443Z" }, - { url = "https://files.pythonhosted.org/packages/55/d9/b8a53c20cf5b41042c205bb9d36d37da00418d30fd1a94bf9eb147820720/pytest_codspeed-4.3.0-py3-none-any.whl", hash = "sha256:05baff2a61dc9f3e92b92b9c2ab5fb45d9b802438f5373073f5766a91319ed7a", size = 125224, upload-time = "2026-02-09T15:23:33.774Z" }, +sdist = { url = "https://files.pythonhosted.org/packages/52/bc/9070fdbfb479a0e92a12652a68875de157dc9be7dc4865a06a519e3a1877/pytest_codspeed-4.4.0.tar.gz", hash = "sha256:edb7c101d9c50439a42cf02cfa9c0ac92da618841636bbebf87c3fa54669442a", size = 201093, upload-time = "2026-04-14T15:13:20.014Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/b5/8d/773162f910630c87ba5ea992ff1f267099ee55b3872f65bcbab5da9bc239/pytest_codspeed-4.4.0-cp310-cp310-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:f3ae6f4053042c3a9ae3b05416fb42253c5e514e89391eb25e9c9e3ac8de8677", size = 820073, upload-time = "2026-04-14T15:12:57.575Z" }, + { url = "https://files.pythonhosted.org/packages/1c/90/9f0cc2fc3245a3d3ee349fd521d6737ac26f79dfb94ed826086bb6ddd321/pytest_codspeed-4.4.0-cp310-cp310-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:83479a6719598d2910969a60cc410c7283c262c876422a9157dca2f2ab42fa1d", size = 828915, upload-time = "2026-04-14T15:12:59.346Z" }, + { url = "https://files.pythonhosted.org/packages/97/26/b9a6620f52642ae6b7ba3f8c2dd3d85c636869a600553deabea98a7ae00e/pytest_codspeed-4.4.0-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:29b1bf8a36e18d11641a5e610e23a94036b04185e3099978d81a873a5bd3635c", size = 820072, upload-time = "2026-04-14T15:13:00.636Z" }, + { url = "https://files.pythonhosted.org/packages/de/4a/08a974ec4467258aa8e00d7ef3993c454ca265d6fe09bd6335135d818cb3/pytest_codspeed-4.4.0-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:06943110e7a8a4b54f4b13aaa3ff8db39caa02b2f61705916887649e36b9713a", size = 828928, upload-time = "2026-04-14T15:13:02.084Z" }, + { url = "https://files.pythonhosted.org/packages/3e/70/4a401b37f80aaebbcbfb2803b0fab75331af554cd75755bc2059f7809bb4/pytest_codspeed-4.4.0-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:6a5c1d51e7ca72ffe247c99b9a97a54191185e8f7a27528e2200d7416da2a68b", size = 820334, upload-time = "2026-04-14T15:13:03.605Z" }, + { url = "https://files.pythonhosted.org/packages/16/52/beb46293d414d65163f8f3218aaa2f05e53bdc5cf64f24cc3843c31d3ca4/pytest_codspeed-4.4.0-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:215170441e57bfcbefd179dfd86ccd54ed0ee235e0602a068ce4448b35f13cb2", size = 829269, upload-time = "2026-04-14T15:13:05.197Z" }, + { url = "https://files.pythonhosted.org/packages/78/53/031793dab3a0edbbcbbd8755648ace0853f4cfb92a0e09e620f301f9ef5d/pytest_codspeed-4.4.0-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:ee3e1964446011ca192eebf0350227df231a5b88af57e518f2a4328fc8ca5131", size = 820300, upload-time = "2026-04-14T15:13:06.791Z" }, + { url = "https://files.pythonhosted.org/packages/e7/66/0c3530c0dd9959b7f0930551b3de296db391040e5e8ad3e0cab917736980/pytest_codspeed-4.4.0-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:340dbb1cc5a21434e0e29bd68ab03c7dc7ad9bfde09d1980b7161352c4c2f048", size = 829201, upload-time = "2026-04-14T15:13:08Z" }, + { url = "https://files.pythonhosted.org/packages/f2/8a/24c7997d95f8bda081b8d4346750a5db0d9d8405183ee5cb9062f7381476/pytest_codspeed-4.4.0-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:413666266762f9cef1321ba971a9e127b97a1f1dad40ddfd2184c2bc5ac157f9", size = 820242, upload-time = "2026-04-14T15:13:09.191Z" }, + { url = "https://files.pythonhosted.org/packages/8b/7f/3912bf6c2bcddb69189d23213f28e5bc058fd4c78fca15dd0010938154b0/pytest_codspeed-4.4.0-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:e258e6c3d5a8a02ae02a64831be3acd44c19210ffbf13321bdbb8c111c5c6fe4", size = 829190, upload-time = "2026-04-14T15:13:10.762Z" }, + { url = "https://files.pythonhosted.org/packages/d8/f4/2cc5e10847aee4233690aa511df6b6f1c2c09f9d8ae506628a138f4ba201/pytest_codspeed-4.4.0-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:56d5dd94dcb69460f916acb9c69865d0171b98acec3ce256645d0c0275b553d7", size = 827557, upload-time = "2026-04-14T15:13:12.553Z" }, + { url = "https://files.pythonhosted.org/packages/7f/57/982ce8aa81089b285730dca8404c76af648af41e46d95012be54452913e6/pytest_codspeed-4.4.0-cp314-cp314t-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:33c38e0e797c74506004f231fc53eab0e412987de281755f714018334381aa3a", size = 835388, upload-time = "2026-04-14T15:13:14.232Z" }, + { url = "https://files.pythonhosted.org/packages/99/36/9e84323c6be426728e897133f8e9f3e65a90c26c137e190ca9b27bf304c3/pytest_codspeed-4.4.0-py3-none-any.whl", hash = "sha256:a6aab2fa73523f538e7729c20ccf4a1e8e921324c9877a816b05334135950fd9", size = 203809, upload-time = "2026-04-14T15:13:18.72Z" }, ] [[package]] From 4f8b5d14d324ae8e15cfae8d85adb4186d4c2175 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Wed, 22 Apr 2026 12:53:59 +0000 Subject: [PATCH 008/462] =?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 0e995e6e0..a99ab83e3 100644 --- a/docs/en/docs/release-notes.md +++ b/docs/en/docs/release-notes.md @@ -9,6 +9,7 @@ hide: ### Internal +* ⬆ Bump pytest-codspeed from 4.3.0 to 4.4.0. PR [#15407](https://github.com/fastapi/fastapi/pull/15407) by [@dependabot[bot]](https://github.com/apps/dependabot). * ⬆ Bump pytest-cov from 7.0.0 to 7.1.0. PR [#15406](https://github.com/fastapi/fastapi/pull/15406) by [@dependabot[bot]](https://github.com/apps/dependabot). * ⬆ Bump cloudflare/wrangler-action from 3.14.1 to 3.15.0. PR [#15405](https://github.com/fastapi/fastapi/pull/15405) by [@dependabot[bot]](https://github.com/apps/dependabot). * ⬆ Bump mypy from 1.19.1 to 1.20.1. PR [#15410](https://github.com/fastapi/fastapi/pull/15410) by [@dependabot[bot]](https://github.com/apps/dependabot). From d9eb39d1a1bf2f6e6e5d3a55088f61c712cb864e Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 22 Apr 2026 15:04:27 +0200 Subject: [PATCH 009/462] =?UTF-8?q?=E2=AC=86=20Bump=20inline-snapshot=20fr?= =?UTF-8?q?om=200.31.1=20to=200.32.6=20(#15409)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: Motov Yurii <109919500+YuriiMotov@users.noreply.github.com> --- uv.lock | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/uv.lock b/uv.lock index 91ec94346..df69a4bd4 100644 --- a/uv.lock +++ b/uv.lock @@ -2216,7 +2216,7 @@ wheels = [ [[package]] name = "inline-snapshot" -version = "0.31.1" +version = "0.32.6" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "asttokens" }, @@ -2224,10 +2224,11 @@ dependencies = [ { name = "pytest" }, { name = "rich" }, { name = "tomli", marker = "python_full_version < '3.11'" }, + { name = "typing-extensions" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/1c/b1/52b5ee59f73ed31d5fe21b10881bf2d121d07d54b23c0b6b74186792e620/inline_snapshot-0.31.1.tar.gz", hash = "sha256:4ea5ed70aa1d652713bbfd750606b94bd8a42483f7d3680433b3e92994495f64", size = 2606338, upload-time = "2025-11-07T07:36:18.932Z" } +sdist = { url = "https://files.pythonhosted.org/packages/ee/df/d831f0312478b4feb7c3195291071dd13f130176fcdcae2d6d2a2d5fda1d/inline_snapshot-0.32.6.tar.gz", hash = "sha256:224a96eeb86c4b2831d274239d3468dc0b7819264f608f595b2f9d01f79a6e38", size = 2627401, upload-time = "2026-04-10T05:46:22.922Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/ba/52/945db420380efbda8c69a7a4a16c53df9d7ac50d8217286b9d41e5d825ff/inline_snapshot-0.31.1-py3-none-any.whl", hash = "sha256:7875a73c986a03388c7e758fb5cb8a43d2c3a20328aa1d851bfb4ed536c4496f", size = 71965, upload-time = "2025-11-07T07:36:16.836Z" }, + { url = "https://files.pythonhosted.org/packages/f8/c7/8b54418a67ef2b10771a82d03e2b6b69016e5bfb0527fd491884a890e1d6/inline_snapshot-0.32.6-py3-none-any.whl", hash = "sha256:1f8fb6353dff0aa824e00eecf17d53d7d08d36f2167752756ec8ea73f39d7e15", size = 85157, upload-time = "2026-04-10T05:46:21.402Z" }, ] [[package]] From ae230ad2f9d90a4e3f6222ff1a5d6e8da41ec0ad Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Wed, 22 Apr 2026 13:04:53 +0000 Subject: [PATCH 010/462] =?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 a99ab83e3..e625cb840 100644 --- a/docs/en/docs/release-notes.md +++ b/docs/en/docs/release-notes.md @@ -9,6 +9,7 @@ hide: ### Internal +* ⬆ Bump inline-snapshot from 0.31.1 to 0.32.6. PR [#15409](https://github.com/fastapi/fastapi/pull/15409) by [@dependabot[bot]](https://github.com/apps/dependabot). * ⬆ Bump pytest-codspeed from 4.3.0 to 4.4.0. PR [#15407](https://github.com/fastapi/fastapi/pull/15407) by [@dependabot[bot]](https://github.com/apps/dependabot). * ⬆ Bump pytest-cov from 7.0.0 to 7.1.0. PR [#15406](https://github.com/fastapi/fastapi/pull/15406) by [@dependabot[bot]](https://github.com/apps/dependabot). * ⬆ Bump cloudflare/wrangler-action from 3.14.1 to 3.15.0. PR [#15405](https://github.com/fastapi/fastapi/pull/15405) by [@dependabot[bot]](https://github.com/apps/dependabot). From c39415673e621665fdb7bbdde69beba7eb1dfd12 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 22 Apr 2026 15:10:45 +0200 Subject: [PATCH 011/462] =?UTF-8?q?=E2=AC=86=20Bump=20mkdocs-material=20fr?= =?UTF-8?q?om=209.7.1=20to=209.7.6=20(#15408)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- uv.lock | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/uv.lock b/uv.lock index df69a4bd4..e1cf6abe1 100644 --- a/uv.lock +++ b/uv.lock @@ -2873,7 +2873,7 @@ wheels = [ [[package]] name = "mkdocs-material" -version = "9.7.1" +version = "9.7.6" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "babel" }, @@ -2888,9 +2888,9 @@ dependencies = [ { name = "pymdown-extensions" }, { name = "requests" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/27/e2/2ffc356cd72f1473d07c7719d82a8f2cbd261666828614ecb95b12169f41/mkdocs_material-9.7.1.tar.gz", hash = "sha256:89601b8f2c3e6c6ee0a918cc3566cb201d40bf37c3cd3c2067e26fadb8cce2b8", size = 4094392, upload-time = "2025-12-18T09:49:00.308Z" } +sdist = { url = "https://files.pythonhosted.org/packages/45/29/6d2bcf41ae40802c4beda2432396fff97b8456fb496371d1bc7aad6512ec/mkdocs_material-9.7.6.tar.gz", hash = "sha256:00bdde50574f776d328b1862fe65daeaf581ec309bd150f7bff345a098c64a69", size = 4097959, upload-time = "2026-03-19T15:41:58.161Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/3e/32/ed071cb721aca8c227718cffcf7bd539620e9799bbf2619e90c757bfd030/mkdocs_material-9.7.1-py3-none-any.whl", hash = "sha256:3f6100937d7d731f87f1e3e3b021c97f7239666b9ba1151ab476cabb96c60d5c", size = 9297166, upload-time = "2025-12-18T09:48:56.664Z" }, + { url = "https://files.pythonhosted.org/packages/2c/01/bc663630c510822c95c47a66af9fa7a443c295b47d5f041e5e6ae62ef659/mkdocs_material-9.7.6-py3-none-any.whl", hash = "sha256:71b84353921b8ea1ba84fe11c50912cc512da8fe0881038fcc9a0761c0e635ba", size = 9305470, upload-time = "2026-03-19T15:41:55.217Z" }, ] [[package]] From 4fa826ce0a3b16884a04f51e5aac95d01790b599 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Wed, 22 Apr 2026 13:11:11 +0000 Subject: [PATCH 012/462] =?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 e625cb840..0aa5add05 100644 --- a/docs/en/docs/release-notes.md +++ b/docs/en/docs/release-notes.md @@ -9,6 +9,7 @@ hide: ### Internal +* ⬆ Bump mkdocs-material from 9.7.1 to 9.7.6. PR [#15408](https://github.com/fastapi/fastapi/pull/15408) by [@dependabot[bot]](https://github.com/apps/dependabot). * ⬆ Bump inline-snapshot from 0.31.1 to 0.32.6. PR [#15409](https://github.com/fastapi/fastapi/pull/15409) by [@dependabot[bot]](https://github.com/apps/dependabot). * ⬆ Bump pytest-codspeed from 4.3.0 to 4.4.0. PR [#15407](https://github.com/fastapi/fastapi/pull/15407) by [@dependabot[bot]](https://github.com/apps/dependabot). * ⬆ Bump pytest-cov from 7.0.0 to 7.1.0. PR [#15406](https://github.com/fastapi/fastapi/pull/15406) by [@dependabot[bot]](https://github.com/apps/dependabot). From 38039e12a86e67f2001b9b7d96c219691d6cb4af Mon Sep 17 00:00:00 2001 From: Motov Yurii <109919500+YuriiMotov@users.noreply.github.com> Date: Thu, 23 Apr 2026 18:35:43 +0200 Subject: [PATCH 013/462] =?UTF-8?q?=F0=9F=94=A8=20Tweak=20translation=20sc?= =?UTF-8?q?ript=20(#15174)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- scripts/general-llm-prompt.md | 4 ++ scripts/translate.py | 96 +++++++++++++++++++++++------------ 2 files changed, 67 insertions(+), 33 deletions(-) diff --git a/scripts/general-llm-prompt.md b/scripts/general-llm-prompt.md index cfad6ff43..06c26d7af 100644 --- a/scripts/general-llm-prompt.md +++ b/scripts/general-llm-prompt.md @@ -6,6 +6,8 @@ The original content is written in Markdown, write the translation in Markdown a The original content will be surrounded by triple percentage signs (%%%). Do not include the triple percentage signs in the translation. +[placeholder_for_additional_instructions] + ### Technical terms in English For technical terms in English that don't have a common translation term, use the original term in English. @@ -223,6 +225,8 @@ Result (German): Use the following rules for links (apply both to Markdown-style links ([text](url)) and to HTML-style text tags): +- The order of links should match the order of links in the English source. Do not change the order of links. Rephrase the sentence if necessary. + - For relative URLs, only translate the link text. Do not translate the URL or its parts. Example: diff --git a/scripts/translate.py b/scripts/translate.py index 1bfa92f88..e2ce52fd5 100644 --- a/scripts/translate.py +++ b/scripts/translate.py @@ -57,39 +57,19 @@ def generate_en_path(*, lang: str, path: Path) -> Path: return out_path -@app.command() -def translate_page( - *, - language: Annotated[str, typer.Option(envvar="LANGUAGE")], - en_path: Annotated[Path, typer.Option(envvar="EN_PATH")], -) -> None: - assert language != "en", ( - "`en` is the source language, choose another language as translation target" +def get_prompt( + lang_prompt_content: str, + old_translation: str | None, + language: str, + language_name: str, + original_content: str, + additional_instructions: str, +) -> str: + general_prompt_with_additional_instructions = general_prompt.replace( + "[placeholder_for_additional_instructions]", additional_instructions ) - langs = get_langs() - 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}" - lang_prompt_content = lang_prompt_path.read_text(encoding="utf-8") - - en_docs_path = Path("docs/en/docs") - assert str(en_path).startswith(str(en_docs_path)), ( - f"Path must be inside {en_docs_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(encoding="utf-8") - old_translation: str | None = None - if out_path.exists(): - print(f"Found existing translation: {out_path}") - old_translation = out_path.read_text(encoding="utf-8") - print(f"Translating {en_path} to {language} ({language_name})") - agent = Agent("openai:gpt-5") - prompt_segments = [ - general_prompt, + general_prompt_with_additional_instructions, lang_prompt_content, ] if old_translation: @@ -119,12 +99,57 @@ def translate_page( f"%%%\n{original_content}%%%", ] ) - prompt = "\n\n".join(prompt_segments) + return "\n\n".join(prompt_segments) + + +@app.command() +def translate_page( + *, + language: Annotated[str, typer.Option(envvar="LANGUAGE")], + en_path: Annotated[Path, typer.Option(envvar="EN_PATH")], +) -> None: + assert language != "en", ( + "`en` is the source language, choose another language as translation target" + ) + langs = get_langs() + 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}" + lang_prompt_content = lang_prompt_path.read_text(encoding="utf-8") + + en_docs_path = Path("docs/en/docs") + assert str(en_path).startswith(str(en_docs_path)), ( + f"Path must be inside {en_docs_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(encoding="utf-8") + old_translation: str | None = None + if out_path.exists(): + print(f"Found existing translation: {out_path}") + old_translation = out_path.read_text(encoding="utf-8") + print(f"Translating {en_path} to {language} ({language_name})") + agent = Agent("openai:gpt-5") MAX_ATTEMPTS = 3 + additional_instructions = "" for attempt_no in range(1, MAX_ATTEMPTS + 1): print(f"Running agent for {out_path} (attempt {attempt_no}/{MAX_ATTEMPTS})") - result = agent.run_sync(prompt) + prompt = get_prompt( + lang_prompt_content=lang_prompt_content, + old_translation=old_translation, + language=language, + language_name=language_name, + original_content=original_content, + additional_instructions=additional_instructions, + ) + result = agent.run_sync( + prompt.replace( + "[placeholder_for_additional_instructions]", additional_instructions + ) + ) out_content = f"{result.output.strip()}\n" try: check_translation( @@ -139,6 +164,11 @@ def translate_page( print( f"Translation check failed on attempt {attempt_no}/{MAX_ATTEMPTS}: {e}" ) + additional_instructions = ( + f"Current translation fails validation checks ({str(e)}). " + "Please, pay special attention to it." + ) + old_translation = out_content continue # Retry if not reached max attempts else: # Max retry attempts reached print(f"Translation failed for {out_path} after {MAX_ATTEMPTS} attempts") From ef1c927b0558d414e199a666833942a6fabb3a51 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Thu, 23 Apr 2026 16:36:15 +0000 Subject: [PATCH 014/462] =?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 0aa5add05..f4f77d8ec 100644 --- a/docs/en/docs/release-notes.md +++ b/docs/en/docs/release-notes.md @@ -9,6 +9,7 @@ hide: ### Internal +* 🔨 Tweak translation script. PR [#15174](https://github.com/fastapi/fastapi/pull/15174) by [@YuriiMotov](https://github.com/YuriiMotov). * ⬆ Bump mkdocs-material from 9.7.1 to 9.7.6. PR [#15408](https://github.com/fastapi/fastapi/pull/15408) by [@dependabot[bot]](https://github.com/apps/dependabot). * ⬆ Bump inline-snapshot from 0.31.1 to 0.32.6. PR [#15409](https://github.com/fastapi/fastapi/pull/15409) by [@dependabot[bot]](https://github.com/apps/dependabot). * ⬆ Bump pytest-codspeed from 4.3.0 to 4.4.0. PR [#15407](https://github.com/fastapi/fastapi/pull/15407) by [@dependabot[bot]](https://github.com/apps/dependabot). From 7815a32f2ed177b8b786a48b3e0712c05b5c644f Mon Sep 17 00:00:00 2001 From: Sofie Van Landeghem Date: Thu, 23 Apr 2026 18:40:29 +0200 Subject: [PATCH 015/462] =?UTF-8?q?=E2=AC=86=EF=B8=8F=20Update=20Pydantic?= =?UTF-8?q?=20v2=20code=20to=20address=20deprecations=20(#15101)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: pre-commit-ci-lite[bot] <117423508+pre-commit-ci-lite[bot]@users.noreply.github.com> --- fastapi/_compat/__init__.py | 2 +- fastapi/_compat/v2.py | 17 +++++++++++++++-- fastapi/dependencies/utils.py | 4 ++-- fastapi/encoders.py | 21 +++++++++++++++++++-- tests/test_jsonable_encoder.py | 18 ++++++++++++++++++ 5 files changed, 55 insertions(+), 7 deletions(-) diff --git a/fastapi/_compat/__init__.py b/fastapi/_compat/__init__.py index 40810eab7..4581c38c8 100644 --- a/fastapi/_compat/__init__.py +++ b/fastapi/_compat/__init__.py @@ -26,7 +26,7 @@ from .v2 import Undefined as Undefined from .v2 import Url as Url from .v2 import copy_field_info as copy_field_info from .v2 import create_body_model as create_body_model -from .v2 import evaluate_forwardref as evaluate_forwardref # ty: ignore[deprecated] +from .v2 import evaluate_forwardref as evaluate_forwardref from .v2 import get_cached_model_fields as get_cached_model_fields from .v2 import get_definitions as get_definitions from .v2 import get_flat_models_from_fields as get_flat_models_from_fields diff --git a/fastapi/_compat/v2.py b/fastapi/_compat/v2.py index 535af0784..3b64fba76 100644 --- a/fastapi/_compat/v2.py +++ b/fastapi/_compat/v2.py @@ -22,10 +22,10 @@ from pydantic import BaseModel, ConfigDict, Field, TypeAdapter, create_model from pydantic import PydanticSchemaGenerationError as PydanticSchemaGenerationError from pydantic import PydanticUndefinedAnnotation as PydanticUndefinedAnnotation from pydantic import ValidationError as ValidationError +from pydantic._internal import _typing_extra as _pydantic_typing_extra from pydantic._internal._schema_generation_shared import ( # type: ignore[attr-defined] # ty: ignore[unused-ignore-comment] GetJsonSchemaHandler as GetJsonSchemaHandler, ) -from pydantic._internal._typing_extra import eval_type_lenient # ty: ignore[deprecated] from pydantic.fields import FieldInfo as FieldInfo from pydantic.json_schema import GenerateJsonSchema as _GenerateJsonSchema from pydantic.json_schema import JsonSchemaValue as JsonSchemaValue @@ -38,7 +38,20 @@ from pydantic_core.core_schema import ( RequiredParam = PydanticUndefined Undefined = PydanticUndefined -evaluate_forwardref = eval_type_lenient # ty: ignore[deprecated] + + +def evaluate_forwardref( + value: Any, + globalns: dict[str, Any] | None = None, + localns: dict[str, Any] | None = None, +) -> Any: + # eval_type_lenient has been deprecated since Pydantic v2.10.0b1 (PR #10530) + try_eval_type = getattr(_pydantic_typing_extra, "try_eval_type", None) + if try_eval_type is not None: + return try_eval_type(value, globalns, localns)[0] + return _pydantic_typing_extra.eval_type_lenient( # ty: ignore[deprecated] + value, globalns, localns + ) class GenerateJsonSchema(_GenerateJsonSchema): diff --git a/fastapi/dependencies/utils.py b/fastapi/dependencies/utils.py index 6b14dac8d..aceca6a1d 100644 --- a/fastapi/dependencies/utils.py +++ b/fastapi/dependencies/utils.py @@ -33,7 +33,7 @@ from fastapi._compat import ( Undefined, copy_field_info, create_body_model, - evaluate_forwardref, # ty: ignore[deprecated] + evaluate_forwardref, field_annotation_is_scalar, field_annotation_is_scalar_sequence, field_annotation_is_sequence, @@ -245,7 +245,7 @@ def get_typed_signature(call: Callable[..., Any]) -> inspect.Signature: def get_typed_annotation(annotation: Any, globalns: dict[str, Any]) -> Any: if isinstance(annotation, str): annotation = ForwardRef(annotation) - annotation = evaluate_forwardref(annotation, globalns, globalns) # ty: ignore[deprecated] + annotation = evaluate_forwardref(annotation, globalns, globalns) if annotation is type(None): return None return annotation diff --git a/fastapi/encoders.py b/fastapi/encoders.py index 84893dc80..43f24101b 100644 --- a/fastapi/encoders.py +++ b/fastapi/encoders.py @@ -22,7 +22,6 @@ from annotated_doc import Doc from fastapi.exceptions import PydanticV1NotSupportedError from fastapi.types import IncEx from pydantic import BaseModel -from pydantic.color import Color # ty: ignore[deprecated] from pydantic.networks import AnyUrl, NameEmail from pydantic.types import SecretBytes, SecretStr from pydantic_core import PydanticUndefinedType @@ -32,6 +31,23 @@ from ._compat import ( is_pydantic_v1_model_instance, ) +try: + # pydantic.color.Color is deprecated since v2.0b3, but supporting for bwd-compat + from pydantic.color import Color # ty: ignore[deprecated] +except ImportError: # pragma: no cover + + class Color: # type: ignore[no-redef] # ty: ignore[unused-ignore-comment] + pass + + +try: + # Supporting the new Color format for newer versions of Pydantic + from pydantic_extra_types.color import Color as PyExtraColor +except ImportError: # pragma: no cover + + class PyExtraColor: # type: ignore[no-redef] # ty: ignore[unused-ignore-comment] + pass + # Taken from Pydantic v1 as is def isoformat(o: datetime.date | datetime.time) -> str: @@ -67,7 +83,8 @@ def decimal_encoder(dec_value: Decimal) -> int | float: ENCODERS_BY_TYPE: dict[type[Any], Callable[[Any], Any]] = { bytes: lambda o: o.decode(), - Color: str, # ty: ignore[deprecated] + Color: str, + PyExtraColor: str, datetime.date: isoformat, datetime.datetime: isoformat, datetime.time: isoformat, diff --git a/tests/test_jsonable_encoder.py b/tests/test_jsonable_encoder.py index 595202bea..c23a9e5d7 100644 --- a/tests/test_jsonable_encoder.py +++ b/tests/test_jsonable_encoder.py @@ -311,3 +311,21 @@ def test_encode_deque_encodes_child_models(): def test_encode_pydantic_undefined(): data = {"value": Undefined} assert jsonable_encoder(data) == {"value": None} + + +@pytest.mark.filterwarnings("ignore::DeprecationWarning") +@pytest.mark.parametrize( + "module_path", + [ + pytest.param("pydantic.color"), + pytest.param("pydantic_extra_types.color"), + ], +) +def test_encode_color(module_path): + try: + Color = __import__(module_path, fromlist=["Color"]).Color + except ImportError: # pragma: no cover + pytest.skip(f"{module_path} not available") + + data = {"color": Color("blue")} + assert jsonable_encoder(data) == {"color": "blue"} From 9a8a5fd99902c3b80d4cc94b85e120e2b808825f Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Thu, 23 Apr 2026 16:40:58 +0000 Subject: [PATCH 016/462] =?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 f4f77d8ec..841f201c5 100644 --- a/docs/en/docs/release-notes.md +++ b/docs/en/docs/release-notes.md @@ -7,6 +7,10 @@ hide: ## Latest Changes +### Upgrades + +* ⬆️ Update Pydantic v2 code to address deprecations. PR [#15101](https://github.com/fastapi/fastapi/pull/15101) by [@svlandeg](https://github.com/svlandeg). + ### Internal * 🔨 Tweak translation script. PR [#15174](https://github.com/fastapi/fastapi/pull/15174) by [@YuriiMotov](https://github.com/YuriiMotov). From e54e5a8980ffa6d7ff68ee7b25a1c46036375521 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebasti=C3=A1n=20Ram=C3=ADrez?= Date: Thu, 23 Apr 2026 18:45:55 +0200 Subject: [PATCH 017/462] =?UTF-8?q?=F0=9F=94=96=20Release=20version=200.13?= =?UTF-8?q?6.1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docs/en/docs/release-notes.md | 2 ++ fastapi/__init__.py | 2 +- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/docs/en/docs/release-notes.md b/docs/en/docs/release-notes.md index 841f201c5..3fc0fda0c 100644 --- a/docs/en/docs/release-notes.md +++ b/docs/en/docs/release-notes.md @@ -7,6 +7,8 @@ hide: ## Latest Changes +## 0.136.1 (2026-04-23) + ### Upgrades * ⬆️ Update Pydantic v2 code to address deprecations. PR [#15101](https://github.com/fastapi/fastapi/pull/15101) by [@svlandeg](https://github.com/svlandeg). diff --git a/fastapi/__init__.py b/fastapi/__init__.py index 73a1c20e9..f07511a25 100644 --- a/fastapi/__init__.py +++ b/fastapi/__init__.py @@ -1,6 +1,6 @@ """FastAPI framework, high performance, easy to learn, fast to code, ready for production""" -__version__ = "0.136.0" +__version__ = "0.136.1" from starlette import status as status From 37472046770ac0de07a23d9744327c1c59cb040d Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 24 Apr 2026 11:34:24 +0200 Subject: [PATCH 018/462] =?UTF-8?q?=E2=AC=86=20Bump=20astral-sh/setup-uv?= =?UTF-8?q?=20from=207.6.0=20to=208.1.0=20(#15415)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/build-docs.yml | 4 ++-- .github/workflows/contributors.yml | 2 +- .github/workflows/deploy-docs.yml | 2 +- .github/workflows/label-approved.yml | 2 +- .github/workflows/notify-translations.yml | 2 +- .github/workflows/people.yml | 2 +- .github/workflows/pre-commit.yml | 2 +- .github/workflows/publish.yml | 2 +- .github/workflows/smokeshow.yml | 2 +- .github/workflows/sponsors.yml | 2 +- .github/workflows/test.yml | 6 +++--- .github/workflows/topic-repos.yml | 2 +- .github/workflows/translate.yml | 4 ++-- 13 files changed, 17 insertions(+), 17 deletions(-) diff --git a/.github/workflows/build-docs.yml b/.github/workflows/build-docs.yml index 288a6237a..d8e5d9e94 100644 --- a/.github/workflows/build-docs.yml +++ b/.github/workflows/build-docs.yml @@ -54,7 +54,7 @@ jobs: with: python-version-file: ".python-version" - name: Setup uv - uses: astral-sh/setup-uv@37802adc94f370d6bfd71619e3f0bf239e1f3b78 # v7.6.0 + uses: astral-sh/setup-uv@08807647e7069bb48b6ef5acd8ec9567f424441b # v8.1.0 with: version: "0.11.4" enable-cache: true @@ -90,7 +90,7 @@ jobs: with: python-version-file: ".python-version" - name: Setup uv - uses: astral-sh/setup-uv@37802adc94f370d6bfd71619e3f0bf239e1f3b78 # v7.6.0 + uses: astral-sh/setup-uv@08807647e7069bb48b6ef5acd8ec9567f424441b # v8.1.0 with: version: "0.11.4" enable-cache: true diff --git a/.github/workflows/contributors.yml b/.github/workflows/contributors.yml index 785ecea93..17649a653 100644 --- a/.github/workflows/contributors.yml +++ b/.github/workflows/contributors.yml @@ -31,7 +31,7 @@ jobs: with: python-version-file: ".python-version" - name: Setup uv - uses: astral-sh/setup-uv@37802adc94f370d6bfd71619e3f0bf239e1f3b78 # v7.6.0 + uses: astral-sh/setup-uv@08807647e7069bb48b6ef5acd8ec9567f424441b # v8.1.0 with: version: "0.11.4" enable-cache: true diff --git a/.github/workflows/deploy-docs.yml b/.github/workflows/deploy-docs.yml index 3c65db23a..503aec2a8 100644 --- a/.github/workflows/deploy-docs.yml +++ b/.github/workflows/deploy-docs.yml @@ -29,7 +29,7 @@ jobs: with: python-version-file: ".python-version" - name: Setup uv - uses: astral-sh/setup-uv@37802adc94f370d6bfd71619e3f0bf239e1f3b78 # v7.6.0 + uses: astral-sh/setup-uv@08807647e7069bb48b6ef5acd8ec9567f424441b # v8.1.0 with: version: "0.11.4" enable-cache: false diff --git a/.github/workflows/label-approved.yml b/.github/workflows/label-approved.yml index 1f2780936..e8ad87439 100644 --- a/.github/workflows/label-approved.yml +++ b/.github/workflows/label-approved.yml @@ -26,7 +26,7 @@ jobs: with: python-version-file: ".python-version" - name: Setup uv - uses: astral-sh/setup-uv@37802adc94f370d6bfd71619e3f0bf239e1f3b78 # v7.6.0 + uses: astral-sh/setup-uv@08807647e7069bb48b6ef5acd8ec9567f424441b # v8.1.0 with: version: "0.11.4" enable-cache: true diff --git a/.github/workflows/notify-translations.yml b/.github/workflows/notify-translations.yml index 07d4e0bdf..9b8c6d7f1 100644 --- a/.github/workflows/notify-translations.yml +++ b/.github/workflows/notify-translations.yml @@ -37,7 +37,7 @@ jobs: with: python-version-file: ".python-version" - name: Setup uv - uses: astral-sh/setup-uv@37802adc94f370d6bfd71619e3f0bf239e1f3b78 # v7.6.0 + uses: astral-sh/setup-uv@08807647e7069bb48b6ef5acd8ec9567f424441b # v8.1.0 with: version: "0.11.4" enable-cache: true diff --git a/.github/workflows/people.yml b/.github/workflows/people.yml index 51e2188cc..d3baec1d0 100644 --- a/.github/workflows/people.yml +++ b/.github/workflows/people.yml @@ -31,7 +31,7 @@ jobs: with: python-version-file: ".python-version" - name: Setup uv - uses: astral-sh/setup-uv@37802adc94f370d6bfd71619e3f0bf239e1f3b78 # v7.6.0 + uses: astral-sh/setup-uv@08807647e7069bb48b6ef5acd8ec9567f424441b # v8.1.0 with: version: "0.11.4" enable-cache: true diff --git a/.github/workflows/pre-commit.yml b/.github/workflows/pre-commit.yml index 5b0be3801..5e358e8f2 100644 --- a/.github/workflows/pre-commit.yml +++ b/.github/workflows/pre-commit.yml @@ -46,7 +46,7 @@ jobs: with: python-version-file: ".python-version" - name: Setup uv - uses: astral-sh/setup-uv@37802adc94f370d6bfd71619e3f0bf239e1f3b78 # v7.6.0 + uses: astral-sh/setup-uv@08807647e7069bb48b6ef5acd8ec9567f424441b # v8.1.0 with: version: "0.11.4" cache-dependency-glob: | diff --git a/.github/workflows/publish.yml b/.github/workflows/publish.yml index 2695854dc..32d6ea4f9 100644 --- a/.github/workflows/publish.yml +++ b/.github/workflows/publish.yml @@ -26,7 +26,7 @@ jobs: with: python-version-file: ".python-version" - name: Install uv - uses: astral-sh/setup-uv@37802adc94f370d6bfd71619e3f0bf239e1f3b78 # v7.6.0 + uses: astral-sh/setup-uv@08807647e7069bb48b6ef5acd8ec9567f424441b # v8.1.0 with: version: "0.11.4" - name: Build distribution diff --git a/.github/workflows/smokeshow.yml b/.github/workflows/smokeshow.yml index 46f261018..c177b7390 100644 --- a/.github/workflows/smokeshow.yml +++ b/.github/workflows/smokeshow.yml @@ -25,7 +25,7 @@ jobs: with: python-version-file: ".python-version" - name: Setup uv - uses: astral-sh/setup-uv@37802adc94f370d6bfd71619e3f0bf239e1f3b78 # v7.6.0 + uses: astral-sh/setup-uv@08807647e7069bb48b6ef5acd8ec9567f424441b # v8.1.0 with: version: "0.11.4" cache-dependency-glob: | diff --git a/.github/workflows/sponsors.yml b/.github/workflows/sponsors.yml index ef72a6824..b1ab7f11d 100644 --- a/.github/workflows/sponsors.yml +++ b/.github/workflows/sponsors.yml @@ -31,7 +31,7 @@ jobs: with: python-version-file: ".python-version" - name: Setup uv - uses: astral-sh/setup-uv@37802adc94f370d6bfd71619e3f0bf239e1f3b78 # v7.6.0 + uses: astral-sh/setup-uv@08807647e7069bb48b6ef5acd8ec9567f424441b # v8.1.0 with: version: "0.11.4" enable-cache: true diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 36cf5a287..1b1daf36b 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -111,7 +111,7 @@ jobs: with: python-version: ${{ matrix.python-version }} - name: Setup uv - uses: astral-sh/setup-uv@37802adc94f370d6bfd71619e3f0bf239e1f3b78 # v7.6.0 + uses: astral-sh/setup-uv@08807647e7069bb48b6ef5acd8ec9567f424441b # v8.1.0 with: version: "0.11.4" enable-cache: true @@ -168,7 +168,7 @@ jobs: with: python-version: "3.13" - name: Setup uv - uses: astral-sh/setup-uv@37802adc94f370d6bfd71619e3f0bf239e1f3b78 # v7.6.0 + uses: astral-sh/setup-uv@08807647e7069bb48b6ef5acd8ec9567f424441b # v8.1.0 with: version: "0.11.4" enable-cache: true @@ -199,7 +199,7 @@ jobs: with: python-version-file: ".python-version" - name: Setup uv - uses: astral-sh/setup-uv@37802adc94f370d6bfd71619e3f0bf239e1f3b78 # v7.6.0 + uses: astral-sh/setup-uv@08807647e7069bb48b6ef5acd8ec9567f424441b # v8.1.0 with: version: "0.11.4" enable-cache: true diff --git a/.github/workflows/topic-repos.yml b/.github/workflows/topic-repos.yml index 0f40b7b3d..69bfdaff9 100644 --- a/.github/workflows/topic-repos.yml +++ b/.github/workflows/topic-repos.yml @@ -26,7 +26,7 @@ jobs: with: python-version-file: ".python-version" - name: Setup uv - uses: astral-sh/setup-uv@37802adc94f370d6bfd71619e3f0bf239e1f3b78 # v7.6.0 + uses: astral-sh/setup-uv@08807647e7069bb48b6ef5acd8ec9567f424441b # v8.1.0 with: version: "0.11.4" enable-cache: true diff --git a/.github/workflows/translate.yml b/.github/workflows/translate.yml index ed21881cd..22fd7e4f1 100644 --- a/.github/workflows/translate.yml +++ b/.github/workflows/translate.yml @@ -58,7 +58,7 @@ jobs: with: python-version-file: ".python-version" - name: Setup uv - uses: astral-sh/setup-uv@37802adc94f370d6bfd71619e3f0bf239e1f3b78 # v7.6.0 + uses: astral-sh/setup-uv@08807647e7069bb48b6ef5acd8ec9567f424441b # v8.1.0 with: version: "0.11.4" cache-dependency-glob: | @@ -97,7 +97,7 @@ jobs: with: python-version-file: ".python-version" - name: Setup uv - uses: astral-sh/setup-uv@37802adc94f370d6bfd71619e3f0bf239e1f3b78 # v7.6.0 + uses: astral-sh/setup-uv@08807647e7069bb48b6ef5acd8ec9567f424441b # v8.1.0 with: version: "0.11.4" cache-dependency-glob: | From 91dd310da90586e9077521b7c78b16b066d61a48 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Fri, 24 Apr 2026 09:34:53 +0000 Subject: [PATCH 019/462] =?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 3fc0fda0c..ecac88133 100644 --- a/docs/en/docs/release-notes.md +++ b/docs/en/docs/release-notes.md @@ -7,6 +7,10 @@ hide: ## Latest Changes +### Internal + +* ⬆ Bump astral-sh/setup-uv from 7.6.0 to 8.1.0. PR [#15415](https://github.com/fastapi/fastapi/pull/15415) by [@dependabot[bot]](https://github.com/apps/dependabot). + ## 0.136.1 (2026-04-23) ### Upgrades From 086048e395490d78a6416cff9c4fdb364792170f Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 24 Apr 2026 14:25:04 +0200 Subject: [PATCH 020/462] =?UTF-8?q?=E2=AC=86=20Bump=20fastar=20from=200.9.?= =?UTF-8?q?0=20to=200.11.0=20(#15419)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- uv.lock | 222 ++++++++++++++++++++++++++++---------------------------- 1 file changed, 111 insertions(+), 111 deletions(-) diff --git a/uv.lock b/uv.lock index e1cf6abe1..b5a3a086a 100644 --- a/uv.lock +++ b/uv.lock @@ -1405,118 +1405,118 @@ wheels = [ [[package]] name = "fastar" -version = "0.9.0" +version = "0.11.0" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/dd/00/dab9ca274cf1fde19223fea7104631bea254751026e75bf99f2b6d0d1568/fastar-0.9.0.tar.gz", hash = "sha256:d49114d5f0b76c5cc242875d90fa4706de45e0456ddedf416608ecd0787fb410", size = 70124, upload-time = "2026-03-20T14:26:34.503Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/24/48/3d8e24c9ae7796e59231f50133640463c6a20b00ce684b308dc6de0e28fe/fastar-0.9.0-cp310-cp310-macosx_10_12_x86_64.whl", hash = "sha256:19a384395f26daa3ecb6c24054f3a50ce919e250e06b82614a252a0fadcbca17", size = 709092, upload-time = "2026-03-20T14:25:30.007Z" }, - { url = "https://files.pythonhosted.org/packages/d9/e5/4d7dc06f3ad5457b9a1510a75e3f9ec431ad020688fcf954012a2bcae6e8/fastar-0.9.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:b9c82b1fef26d8fd4abad1152f4c74eeb86bc9d46c814757b695847a751b9b0b", size = 630252, upload-time = "2026-03-20T14:25:17.673Z" }, - { url = "https://files.pythonhosted.org/packages/79/d4/ebb285a263cc2070d04d39917288b5d1c7f49e1c47ed5544e86283e091c6/fastar-0.9.0-cp310-cp310-manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:e5c91cb4527a6e634e7477a01aa52ccfbb978df1d9803172685c1e0802a2c18c", size = 869584, upload-time = "2026-03-20T14:24:52.067Z" }, - { url = "https://files.pythonhosted.org/packages/23/19/a293b6f75ea1b9e14d384859253ee65f966a73be306cea39552a557c9e34/fastar-0.9.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c6bc32f40a3e8ab12b8ebce48c4808d2bcf89bd3dac3023980b8a9b4aaf719f2", size = 762379, upload-time = "2026-03-20T14:23:47.429Z" }, - { url = "https://files.pythonhosted.org/packages/95/2f/a31f00c31f16a3bffd6f6ab3414964100fb35a79983f21283fc8b81d3cec/fastar-0.9.0-cp310-cp310-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:ee4a1d85a58cd955a5409b221450762b851879ce6e080d6d717265fb9a4e939d", size = 759567, upload-time = "2026-03-20T14:24:00.677Z" }, - { url = "https://files.pythonhosted.org/packages/b0/46/5a4b1fb1e5c8b6cd1eb464e658ed75d667f1f53834f353e6323ca71bd113/fastar-0.9.0-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:b72e25ec1cbad0fc2a5f93a147978cc41e054ce5789807ebd3bcece5f276c0c2", size = 925850, upload-time = "2026-03-20T14:24:13.669Z" }, - { url = "https://files.pythonhosted.org/packages/f6/ec/a5543fb1b059a82ce4c6fc571fe429390294e8150c09bb537d228471eac6/fastar-0.9.0-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:9862ddfaf73c7388d708bcbeb75e2e336605465b88d952407621c847bab5d3cb", size = 818858, upload-time = "2026-03-20T14:24:39.431Z" }, - { url = "https://files.pythonhosted.org/packages/53/9a/af5ae6d24e1170702d096225989b4ee3470b22bbecb5c09c899e816aefd7/fastar-0.9.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3471fa2627b9703830d13c8b0a6ba19eeff4e2e0ff924631065ecceca56abb2b", size = 821941, upload-time = "2026-03-20T14:25:05.534Z" }, - { url = "https://files.pythonhosted.org/packages/54/3f/399d8b080f7c5fe1fa88dadaa7a30bd0bb885ad490d3c2ef2c667877c5c4/fastar-0.9.0-cp310-cp310-manylinux_2_31_riscv64.whl", hash = "sha256:e3d2e68e0239ab24b65b0674f2b74ac71d8fb5ea221a3e0d0ab966292bd83e12", size = 886548, upload-time = "2026-03-20T14:24:26.209Z" }, - { url = "https://files.pythonhosted.org/packages/63/cd/034b5f61e99df67e092e1d3d538150a5f562d00c0259e6402cbcb62e15a9/fastar-0.9.0-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:dcabfe31c48ff6a994c3dc4ddc27287b15d78a09c737beef8a6b1f210b720a6a", size = 970244, upload-time = "2026-03-20T14:25:42.928Z" }, - { url = "https://files.pythonhosted.org/packages/3e/8f/3a8b0d711050b300a3448c9d145c6d234958e148e456ab4a15daca6e4b05/fastar-0.9.0-cp310-cp310-musllinux_1_2_armv7l.whl", hash = "sha256:f1723bb9cc3dcd087b5dd066a0369f27529a925d467ccc896d1f6cd0212417bf", size = 1036944, upload-time = "2026-03-20T14:25:55.867Z" }, - { url = "https://files.pythonhosted.org/packages/34/11/cd5ebd16529c5fbff2431b494bd6f3f8ecafeca8f874449bf65ccf58c77b/fastar-0.9.0-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:3ec2e699af02ba78f359b1cf1f4b3da22f41dec3a327f1cda6a1d31a43365a71", size = 1078612, upload-time = "2026-03-20T14:26:09.042Z" }, - { url = "https://files.pythonhosted.org/packages/85/c7/752c184e3c5e8de592e5d7ce3d081bf665ae5dbbe4a3df816daf38043143/fastar-0.9.0-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:761708eb2f6e402d4cda04ac81d0c2406b1c10375601e238083d2e885ec52a42", size = 1029368, upload-time = "2026-03-20T14:26:21.79Z" }, - { url = "https://files.pythonhosted.org/packages/68/b3/2a5551942adaecb9874ebc0d0922f3ab9dd058298b7a36a7900da93a3e68/fastar-0.9.0-cp310-cp310-win32.whl", hash = "sha256:a5ea0969c94845faed7bf681850df704da9617ad7231850dbc7ca4017080133a", size = 454507, upload-time = "2026-03-20T14:26:54.124Z" }, - { url = "https://files.pythonhosted.org/packages/23/30/7a2f25837ee7353ff5eaa815d9a6321f8704fcc39a94570a1b2d958639c0/fastar-0.9.0-cp310-cp310-win_amd64.whl", hash = "sha256:e5646f10a747282904f2def929612ed19cace4bd702029c3d7c78205ef604abd", size = 486500, upload-time = "2026-03-20T14:26:42.142Z" }, - { url = "https://files.pythonhosted.org/packages/6f/01/4ecbe0b4938608f9c6c5c4d4f6b872975fe30152bfaa8e44fe0e3b6cbcc4/fastar-0.9.0-cp311-cp311-macosx_10_12_x86_64.whl", hash = "sha256:facc7522bd1c1e7569bedb602932fc7292408a320f415d72180634d58f661bf0", size = 708809, upload-time = "2026-03-20T14:25:31.299Z" }, - { url = "https://files.pythonhosted.org/packages/11/6a/085b3cae0e04da4d42306dc07e2cc4f95d9c8f27df4dfd1a25d0f80516cb/fastar-0.9.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:c8ac3e8aaee57dfc822b04f570f0a963c2381a9dc8990fe0c6e965efd23fd451", size = 629764, upload-time = "2026-03-20T14:25:19.017Z" }, - { url = "https://files.pythonhosted.org/packages/3c/c2/cdd996a37837e6cc5edc4d09775d2a2bc63e9e931129db69947cf4c77148/fastar-0.9.0-cp311-cp311-manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:d90493b4bb56db728b38eb18a551df386113d72ad4e7f1a97572f3662a9b8a85", size = 869631, upload-time = "2026-03-20T14:24:53.779Z" }, - { url = "https://files.pythonhosted.org/packages/30/d4/4a5a3c341d26197ea3ae6bed79fc9bb4ead8ddc74a93bdb74e4ee0bac18e/fastar-0.9.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:17e2c3b46408193ea13c1e1177275ca7951e88bd3dce16baccb8de4f5e0dc2e8", size = 762096, upload-time = "2026-03-20T14:23:49.175Z" }, - { url = "https://files.pythonhosted.org/packages/bc/dd/1d346cdfcd3064f6c435eff90a8d7cf0021487e3681453bdd681b9488d81/fastar-0.9.0-cp311-cp311-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:52f96a3d4cfbe4f06b376706fa0562f3a1d2329bc37168119af0e47e1ac21cab", size = 759627, upload-time = "2026-03-20T14:24:01.984Z" }, - { url = "https://files.pythonhosted.org/packages/02/a1/e91eb7ae1e41c0d3ead86dc199beb13a0b80101e2948d66adeb578b09e60/fastar-0.9.0-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:57e9b94e485713c79bb259f7ecff1213527d05e9aa43a157c3fbc88812cf163e", size = 926211, upload-time = "2026-03-20T14:24:15.218Z" }, - { url = "https://files.pythonhosted.org/packages/9b/63/9fea9604e7aecc2f062f0df5729f74712d81615a1b18fa6a1a13106184fa/fastar-0.9.0-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:fb06d0a0cc3cf52a9c07559bb16ab99eb75afe0b3d5ce68f5c299569460851ac", size = 818748, upload-time = "2026-03-20T14:24:40.765Z" }, - { url = "https://files.pythonhosted.org/packages/b0/f8/521438041d69873bb68b144b09080ae4f1621cebb8238b1e54821057206b/fastar-0.9.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c75e779f72d845037d4bf6692d01ac66f014eaef965c9231d41d5cc1276b89fc", size = 822380, upload-time = "2026-03-20T14:25:06.825Z" }, - { url = "https://files.pythonhosted.org/packages/92/05/f33cc3f5f96ffb7d81a7f06c9239d4eea584527292a030a73d3218148f41/fastar-0.9.0-cp311-cp311-manylinux_2_31_riscv64.whl", hash = "sha256:24b13fc4ef3f1e3c9cc2dcf07ad9445900db9d3ce09b73021547a55994d0407f", size = 886569, upload-time = "2026-03-20T14:24:27.567Z" }, - { url = "https://files.pythonhosted.org/packages/60/32/6e7cb45dce544f97b0199325084a0a5a895cb903e0539690619e78d8d7cf/fastar-0.9.0-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:ec7852de506d022ad36ad56f4aefb10c259dd59e485bf87af827954d404ba9d5", size = 969993, upload-time = "2026-03-20T14:25:44.222Z" }, - { url = "https://files.pythonhosted.org/packages/6a/ee/04cf9374e5e6a82ddc87073d684c1fa7a9ca368bf85c2786535b1bfc38a9/fastar-0.9.0-cp311-cp311-musllinux_1_2_armv7l.whl", hash = "sha256:a79c53c3003958dca88a7ec3dd805bf9c2fb2a659110039f44571d57e329e3d4", size = 1036738, upload-time = "2026-03-20T14:25:57.551Z" }, - { url = "https://files.pythonhosted.org/packages/b6/94/e6f6ad29c25c5f531a406e3a35ef5c034ea177748f9fb621073519adb3d5/fastar-0.9.0-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:00328ce7ae76be7f9e2faa6a221a0b41212e4115c27e2ac5e585bcf226bfc2eb", size = 1078557, upload-time = "2026-03-20T14:26:10.358Z" }, - { url = "https://files.pythonhosted.org/packages/1f/44/a1c9f6afe93d1cc1abb68a7cda2bada509d756d24e22d5d949ca86b4f45e/fastar-0.9.0-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:5c03fad1ad9ac57cf03a4db9e18c7109c37416ff4eb9ebfca98fcd2b233a26c4", size = 1029251, upload-time = "2026-03-20T14:26:23.215Z" }, - { url = "https://files.pythonhosted.org/packages/75/31/9e77bc2af3c8b8a433b7175d14b9c75d0ab901542c7452fdf942ece5a155/fastar-0.9.0-cp311-cp311-win32.whl", hash = "sha256:163ba4c543d2112c8186be2f134d11456b593071ba9ea3faba4f155bde7c5dac", size = 454633, upload-time = "2026-03-20T14:26:55.344Z" }, - { url = "https://files.pythonhosted.org/packages/0c/d4/a78d51d1290cdce2d6d3162a18d12c736b71d3feef5a446b3fe021443eb3/fastar-0.9.0-cp311-cp311-win_amd64.whl", hash = "sha256:2137d5d26044b44bb19197a8fc959256c772615ee959cddd0f74320b548fc966", size = 486772, upload-time = "2026-03-20T14:26:43.569Z" }, - { url = "https://files.pythonhosted.org/packages/fa/39/471aefca4c8180689cc0dc6f2f23bc283a3ca07114f713307fb947d320af/fastar-0.9.0-cp311-cp311-win_arm64.whl", hash = "sha256:ecb94de3bc96d9fae95641a7907385541517a4c17416153d3b952d37dce0a2a3", size = 463586, upload-time = "2026-03-20T14:26:35.483Z" }, - { url = "https://files.pythonhosted.org/packages/4d/9b/300bc0dafa8495718976076db216f42d57b251a582589566a63b4ed2cb82/fastar-0.9.0-cp312-cp312-macosx_10_12_x86_64.whl", hash = "sha256:7a8b5daa50d9b4c07367dffc40880467170bf1c31ca63a2286506edbe6d3d65b", size = 706914, upload-time = "2026-03-20T14:25:32.501Z" }, - { url = "https://files.pythonhosted.org/packages/95/97/f1e34c8224dc373c6fab5b33e33be0d184751fdc27013af3278b1e4e6e6c/fastar-0.9.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:9ec841a69fea73361c6df6d9183915c09e9ce3bd96493763fa46019e79918400", size = 627422, upload-time = "2026-03-20T14:25:20.318Z" }, - { url = "https://files.pythonhosted.org/packages/a9/ad/e2499d136e24c2d896f2ec58183c91c6f8185d758177537724ed2f3e1b54/fastar-0.9.0-cp312-cp312-manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:ad46bc23040142e9be4b4005ea366834dbf0f1b6a90b8ecdc3ec96c42dec4adf", size = 865265, upload-time = "2026-03-20T14:24:55.418Z" }, - { url = "https://files.pythonhosted.org/packages/fe/cf/b6ad68b2ab1d7b74b0d38725d817418016bdd64880b36108be80d2460b4d/fastar-0.9.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:de264da9e8ef6407aa0b23c7c47ed4e34fde867e7c1f6e3cb98945a93e5f89f2", size = 760583, upload-time = "2026-03-20T14:23:50.447Z" }, - { url = "https://files.pythonhosted.org/packages/b8/96/086116ad46e3b98f6c217919d680e619f2857ffa6b5cc0d7e46e4f214b83/fastar-0.9.0-cp312-cp312-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:75c70be3a7da3ff9342f64c15ec3749c13ef56bc28e69075d82d03768532a8d0", size = 758000, upload-time = "2026-03-20T14:24:03.471Z" }, - { url = "https://files.pythonhosted.org/packages/9b/e6/ea642ea61eea98d609343080399a296a9ff132bd0492a6638d6e0d9e41a7/fastar-0.9.0-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:4a734506b071d2a8844771fe735fbd6d67dd0eec80eef5f189bbe763ebe7a0b8", size = 923647, upload-time = "2026-03-20T14:24:16.875Z" }, - { url = "https://files.pythonhosted.org/packages/c6/3e/53874aad61e4a664af555a2aa7a52fe46cfadd423db0e592fa0cfe0fa668/fastar-0.9.0-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:8eac084ab215aaf65fa406c9b9da1ac4e697c3d3a1a183e09c488e555802f62d", size = 816528, upload-time = "2026-03-20T14:24:42.048Z" }, - { url = "https://files.pythonhosted.org/packages/41/df/d663214d35380b07a24a796c48d7d7d4dc3a28ec0756edbcb7e2a81dc572/fastar-0.9.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:acb62e2369834fb23d26327157f0a2dbec40b230c709fa85b1ce96cf010e6fbf", size = 819050, upload-time = "2026-03-20T14:25:08.352Z" }, - { url = "https://files.pythonhosted.org/packages/7c/5a/455b53f11527568100ba6d5847635430645bad62d676f0bae4173fc85c90/fastar-0.9.0-cp312-cp312-manylinux_2_31_riscv64.whl", hash = "sha256:f2f399fffb74bcd9e9d4507e253ace2430b5ccf61000596bda41e90414bcf4f2", size = 885257, upload-time = "2026-03-20T14:24:28.86Z" }, - { url = "https://files.pythonhosted.org/packages/4f/dd/0a8ea7b910293b07f8c82ef4e6451262ccf2a6f2020e880f184dc4abd6c2/fastar-0.9.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:87006c8770dfc558aefe927590bbcdaf9648ca4472a9ee6d10dfb7c0bda4ce5b", size = 968135, upload-time = "2026-03-20T14:25:45.614Z" }, - { url = "https://files.pythonhosted.org/packages/6b/cb/5c7e9231d6ba00e225623947068db09ddd4e401800b0afaf39eece14bfee/fastar-0.9.0-cp312-cp312-musllinux_1_2_armv7l.whl", hash = "sha256:4d012644421d669d9746157193f4eafd371e8ae56ff7aef97612a4922418664c", size = 1034940, upload-time = "2026-03-20T14:25:58.893Z" }, - { url = "https://files.pythonhosted.org/packages/b5/b4/eccfcf7fe9d2a0cea6d71630acc48a762404058c9b3ae1323f74abcda005/fastar-0.9.0-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:094fd03b2e41b20a2602d340e2b52ad10051d82caa1263411cf247c1b1bc139f", size = 1073807, upload-time = "2026-03-20T14:26:11.694Z" }, - { url = "https://files.pythonhosted.org/packages/8b/53/6ddda28545b428d54c42f341d797046467c689616a36eae9a43ba56f2545/fastar-0.9.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:59bc500d7b6bdaf2ffb2b632bc6b0f97ddfb3bb7d31b54d61ceb00b5698d6484", size = 1025314, upload-time = "2026-03-20T14:26:24.624Z" }, - { url = "https://files.pythonhosted.org/packages/03/cf/71e2a67b0a69971044ad57fe7d196287ac32ab710bfc47f34745bb4a7834/fastar-0.9.0-cp312-cp312-win32.whl", hash = "sha256:25a1fd512ce23eb5aaab514742e7c6120244c211c349b86af068c3ae35792ec3", size = 452740, upload-time = "2026-03-20T14:26:56.604Z" }, - { url = "https://files.pythonhosted.org/packages/c0/c5/0ffa2fffac0d80d2283db577ff23f8d91886010ea858c657f8278c2a222c/fastar-0.9.0-cp312-cp312-win_amd64.whl", hash = "sha256:b10a409797d01ee4062547e95e4a89f6bb52677b144076fd5a1f9d28d463ab10", size = 485282, upload-time = "2026-03-20T14:26:44.926Z" }, - { url = "https://files.pythonhosted.org/packages/14/20/999d72dc12e793a6c7889176fc42ad917d568d802c91b4126629e9be45a9/fastar-0.9.0-cp312-cp312-win_arm64.whl", hash = "sha256:ea4d98fc62990986ce00d2021f08ff2aa6eae71636415c5a5f65f3a6a657dc5e", size = 461795, upload-time = "2026-03-20T14:26:36.728Z" }, - { url = "https://files.pythonhosted.org/packages/9a/26/ea9339facfe4ee224be673c6888dbf077f28b0f81185f80353966c9f4925/fastar-0.9.0-cp313-cp313-macosx_10_12_x86_64.whl", hash = "sha256:7b55ae4a3a481fd90a63ac558a7e8aab652ac1dfd15d8657266e71bf65346408", size = 706740, upload-time = "2026-03-20T14:25:33.741Z" }, - { url = "https://files.pythonhosted.org/packages/77/52/f3b06867e5ca8d5b2c1c15a1563415e0037b5831f2058ee72b03960296d9/fastar-0.9.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:f07c6bdeedfeb30ef459f21fa9ab06e2b6727f7e7653176d3abb7a85f447c400", size = 627615, upload-time = "2026-03-20T14:25:21.608Z" }, - { url = "https://files.pythonhosted.org/packages/52/32/021b0a633bca18bca4f831392c2938c15c4605de2d9895b783ad6d64679c/fastar-0.9.0-cp313-cp313-manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:90f46492e05141089766699e95c79d470e8013192fbbb16ef16b576281f3b8ee", size = 864584, upload-time = "2026-03-20T14:24:56.941Z" }, - { url = "https://files.pythonhosted.org/packages/3f/54/e2e1b4c8512d670373047e5e585b1d1ff9ffd722b0a17647d22c9c9bd248/fastar-0.9.0-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:108bb46c080ca152bb331f1e0576177d36e9badba51b1d5724d2823542e0dd1f", size = 760246, upload-time = "2026-03-20T14:23:51.964Z" }, - { url = "https://files.pythonhosted.org/packages/fa/7d/1e283dd8dbb3647049594bb477bdc053045c6fff2d3f06386d2dcacce7aa/fastar-0.9.0-cp313-cp313-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:d17d311cfbb559154ba940972b6d07a3a7ac221a2a01208f119ad03495f01d32", size = 757024, upload-time = "2026-03-20T14:24:04.69Z" }, - { url = "https://files.pythonhosted.org/packages/87/ac/82d3cb64d318ce16c5d1a26a40b8aa570fcc9b23684221aece838c4cbada/fastar-0.9.0-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:d2ef34e7088f308e73460e1b8d9b0479a743f679816782a80db6ae87ee68714a", size = 921630, upload-time = "2026-03-20T14:24:18.155Z" }, - { url = "https://files.pythonhosted.org/packages/f7/b8/3e7892f1a25a1a2054a20de6c846c0794b8fa361e5b9d3d00915b41e97bd/fastar-0.9.0-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:c93bf4732d0dd6adae4a8b3bbebe19af76ee1072b7688bf39c5a1d120425a772", size = 815791, upload-time = "2026-03-20T14:24:43.28Z" }, - { url = "https://files.pythonhosted.org/packages/db/5e/8fcc662db1fd0985f4f8a54e79276416565a0d1fcb8da66665b2061ead30/fastar-0.9.0-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:5a67b061b1099cf3b8b6234dd3605fa16f5078ab6b51c8d77ad7a5d11c3cf834", size = 818980, upload-time = "2026-03-20T14:25:09.545Z" }, - { url = "https://files.pythonhosted.org/packages/68/ed/37291fbd6c9b5b0905712da6191bdfc25a7dc236efbf130e3a1a7d1b9440/fastar-0.9.0-cp313-cp313-manylinux_2_31_riscv64.whl", hash = "sha256:912efe3121dc1f3c05940cfa1c6b09b8868d702d24566506aa1d0d96e429923a", size = 884578, upload-time = "2026-03-20T14:24:30.584Z" }, - { url = "https://files.pythonhosted.org/packages/94/19/7b3b7af978ae4f012664781554716d67549ab19ddbcb6e6d1adc04d7a5e7/fastar-0.9.0-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:2394980cc126a3263e115600bc4ff9e7320cddde83c99fc334ab530be5b7166e", size = 967790, upload-time = "2026-03-20T14:25:46.975Z" }, - { url = "https://files.pythonhosted.org/packages/e6/38/4cce2a8e529a7d3e99e427c9bbcccd7013ff6b3ba295613e6f1c573c9e6c/fastar-0.9.0-cp313-cp313-musllinux_1_2_armv7l.whl", hash = "sha256:d0aff74ea98642784c941d3cd8c35943258d4b9626157858901c5b181683339b", size = 1033892, upload-time = "2026-03-20T14:26:00.22Z" }, - { url = "https://files.pythonhosted.org/packages/1a/3f/86f25d79b1b369c2756ee338b76d1696a9cac3a737e819459b0ad7822ede/fastar-0.9.0-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:3e8a1deaf490f4ec15eca7e66127ff89cdefd20217f358739d4b7b1cb322f663", size = 1072969, upload-time = "2026-03-20T14:26:13.089Z" }, - { url = "https://files.pythonhosted.org/packages/10/4f/6ec0c123c15bbcb9a9b82e979dc81273789ebbfbb4a2b41a1a6941577c94/fastar-0.9.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:c9bd8879ebf05aa247e60e454bb7568cbdd44f016b8c58e31e5398039403e61d", size = 1025768, upload-time = "2026-03-20T14:26:25.957Z" }, - { url = "https://files.pythonhosted.org/packages/5a/d1/cbdcdb78ca034ed51a9f53c2650885873d8b06727452c1cc33f56ad0c66a/fastar-0.9.0-cp313-cp313-win32.whl", hash = "sha256:11b35e6453a2da8715dd8415b3999ea57805125493e44ce41a32404bf9a510a7", size = 452742, upload-time = "2026-03-20T14:26:58.014Z" }, - { url = "https://files.pythonhosted.org/packages/74/ee/138d2f8e3504232a279afa224d3e5922c15dc7126613e6c135cfc8e10ec9/fastar-0.9.0-cp313-cp313-win_amd64.whl", hash = "sha256:10a1e7f7bfa1c6f03e4c657fdc0a32ebe42d8e48f681403dc0c67258e1cb5bef", size = 484917, upload-time = "2026-03-20T14:26:46.135Z" }, - { url = "https://files.pythonhosted.org/packages/db/ca/f518ee9dccc45097560a2cff245590c65b7b348171c8d2f2e487cf92a69f/fastar-0.9.0-cp313-cp313-win_arm64.whl", hash = "sha256:e5484ac1415e0ca8bc7b69231e3e3afb52887fed10b839ca676767635a13f06f", size = 461202, upload-time = "2026-03-20T14:26:37.937Z" }, - { url = "https://files.pythonhosted.org/packages/cf/00/99700dd33273c118d7d9ab7ad5db6650b430448d4cfae62aec6ef6ca4cb7/fastar-0.9.0-cp314-cp314-macosx_10_12_x86_64.whl", hash = "sha256:ccb2289f24ee6555330eb77149486d3a2ec8926450a96157dd20c636a0eec085", size = 707059, upload-time = "2026-03-20T14:25:35.086Z" }, - { url = "https://files.pythonhosted.org/packages/e9/a4/4808dcfa8dddb9d7f50d830a39a9084d9d148ed06fcac8b040620848bc24/fastar-0.9.0-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:2bfee749a46666785151b33980aef8f916e6e0341c3d241bde4d3de6be23f00c", size = 627135, upload-time = "2026-03-20T14:25:23.134Z" }, - { url = "https://files.pythonhosted.org/packages/da/cb/9c92e97d760d769846cae6ce53332a5f2a9246eb07b369ac2a4ebf10480c/fastar-0.9.0-cp314-cp314-manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:f6096ec3f216a21fa9ac430ce509447f56c5bd979170c4c0c3b4f3cb2051c1a8", size = 864974, upload-time = "2026-03-20T14:24:58.624Z" }, - { url = "https://files.pythonhosted.org/packages/84/38/9dadebd0b7408b4f415827db35169bbd0741e726e38e3afd3e491b589c61/fastar-0.9.0-cp314-cp314-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f7a806e54d429f7f57e35dc709e801da8c0ba9095deb7331d6574c05ae4537ea", size = 760262, upload-time = "2026-03-20T14:23:53.275Z" }, - { url = "https://files.pythonhosted.org/packages/d6/7d/7afc5721429515aa0873b268513f656f905d27ff1ca54d875af6be9e9bc6/fastar-0.9.0-cp314-cp314-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:f9a06abf8c7f74643a75003334683eb6e94fabef05f60449b7841eeb093a47b0", size = 757575, upload-time = "2026-03-20T14:24:06.143Z" }, - { url = "https://files.pythonhosted.org/packages/fc/5d/7498842c62bd6057553aa598cd175a0db41fdfeda7bdfde48dab63ffb285/fastar-0.9.0-cp314-cp314-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:1e9b5c155946f20ce3f999fb1362ed102876156ad6539e1b73a921f14efb758c", size = 924827, upload-time = "2026-03-20T14:24:19.364Z" }, - { url = "https://files.pythonhosted.org/packages/69/ab/13322e98fe1a00ed6efbfa5bf06fcfff8a6979804ef7fcef884b5e0c6f85/fastar-0.9.0-cp314-cp314-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:fbdedac6a84ef9ebc1cee6d777599ad51c9e98ceb8ebb386159483dcd60d0e16", size = 816536, upload-time = "2026-03-20T14:24:44.844Z" }, - { url = "https://files.pythonhosted.org/packages/fe/fd/0aa5b9994c8dba75b73a9527be4178423cb926db9f7eca562559e27ccdfd/fastar-0.9.0-cp314-cp314-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:51df60a2f7af09f75b2a4438b25cb903d8774e24c492acf2bca8b0863026f34c", size = 818686, upload-time = "2026-03-20T14:25:10.799Z" }, - { url = "https://files.pythonhosted.org/packages/46/d6/e000cd49ef85c11a8350e461e6c48a4345ace94fb52242ac8c1d5dad1dfc/fastar-0.9.0-cp314-cp314-manylinux_2_31_riscv64.whl", hash = "sha256:15016d0da7dbc664f09145fc7db549ba8fe32628c6e44e20926655b82de10658", size = 885043, upload-time = "2026-03-20T14:24:32.231Z" }, - { url = "https://files.pythonhosted.org/packages/68/28/ee734fe273475b9b25554370d92a21fc809376cf79aa072de29d23c17518/fastar-0.9.0-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:c66a8e1f7dae6357be8c1f83ce6330febbc08e49fc40a5a2e91061e7867bbcbf", size = 967965, upload-time = "2026-03-20T14:25:48.397Z" }, - { url = "https://files.pythonhosted.org/packages/c1/35/165b3a75f1ee8045af9478c8aae5b5e20913cca2d4a5adb1be445e8d015a/fastar-0.9.0-cp314-cp314-musllinux_1_2_armv7l.whl", hash = "sha256:1c6829be3f55d2978cb62921ef4d7c3dd58fe68ee994f81d49bd0a3c5240c977", size = 1034507, upload-time = "2026-03-20T14:26:01.518Z" }, - { url = "https://files.pythonhosted.org/packages/ba/4e/4097b5015da02484468c16543db2f8dec2fe827d321a798acbd9068e0f13/fastar-0.9.0-cp314-cp314-musllinux_1_2_i686.whl", hash = "sha256:68db849e01d49543f31d56ef2fe15527afe2b9e0fb21794edc4d772553d83407", size = 1073388, upload-time = "2026-03-20T14:26:14.448Z" }, - { url = "https://files.pythonhosted.org/packages/07/d7/3b86af4e63a551398763a1bbbbac91e1c0754ece7ac7157218b33a065f4c/fastar-0.9.0-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:5569510407c0ded580cfeec99e46ebe85ce27e199e020c5c1ea6f570e302c946", size = 1025190, upload-time = "2026-03-20T14:26:27.316Z" }, - { url = "https://files.pythonhosted.org/packages/39/07/8c50a60f03e095053306fcf57d9d99343bce0e99d5b758bf96de31aec849/fastar-0.9.0-cp314-cp314-win32.whl", hash = "sha256:3f7be0a34ffbead52ab5f4a1e445e488bf39736acb006298d3b3c5b4f2c5915e", size = 452301, upload-time = "2026-03-20T14:26:59.234Z" }, - { url = "https://files.pythonhosted.org/packages/ee/69/aa6d67b09485ba031408296d6ff844c7d83cdcb9f8fcc240422c6f83be87/fastar-0.9.0-cp314-cp314-win_amd64.whl", hash = "sha256:cf7f68b98ed34ce628994c9bbd4f56cf6b4b175b3f7b8cbe35c884c8efec0a5b", size = 484948, upload-time = "2026-03-20T14:26:48.45Z" }, - { url = "https://files.pythonhosted.org/packages/20/6d/dba29d87ca929f95a5a7025c7d30720ad8478beed29fff482f29e1e8b045/fastar-0.9.0-cp314-cp314-win_arm64.whl", hash = "sha256:155dae97aca4b245eabb25e23fd16bfd42a0447f9db7f7789ab1299b02d94487", size = 461170, upload-time = "2026-03-20T14:26:39.191Z" }, - { url = "https://files.pythonhosted.org/packages/96/8f/c3ea0adac50a8037987ee7f15ff94767ebb604faf6008cbd2b8efa46c372/fastar-0.9.0-cp314-cp314t-macosx_10_12_x86_64.whl", hash = "sha256:a63df018232623e136178953031057c7ac0dbf0acc6f0e8c1dc7dbc19e64c22f", size = 705857, upload-time = "2026-03-20T14:25:36.842Z" }, - { url = "https://files.pythonhosted.org/packages/ae/b3/e0e1aad1778065559680a73cdf982ed07b04300c2e5bf778dec8668eda6f/fastar-0.9.0-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:6fb44f8675ef87087cb08f9bf4dfa15e818571a5f567ff692f3ea007cff867b5", size = 626210, upload-time = "2026-03-20T14:25:24.361Z" }, - { url = "https://files.pythonhosted.org/packages/94/f3/3c117335cbea26b3bc05382c27e6028278ed048d610b8de427c68f2fec84/fastar-0.9.0-cp314-cp314t-manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:81092daa991d0f095424e0e28ed589e03c81a21eeddc9b981184ddda5869bf9d", size = 864879, upload-time = "2026-03-20T14:25:00.131Z" }, - { url = "https://files.pythonhosted.org/packages/26/5d/e8d00ec3b2692d14ea111ddae25bf10e0cb60d5d79915c3d8ea393a87d5c/fastar-0.9.0-cp314-cp314t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:9e8793e2618d0d6d5a7762d6007371f57f02544364864e40e6b9d304b0f151b2", size = 759117, upload-time = "2026-03-20T14:23:54.826Z" }, - { url = "https://files.pythonhosted.org/packages/1a/61/6e080fdbc28c72dded8b6ff396035d6dc292f9b1c67b8797ac2372ca5733/fastar-0.9.0-cp314-cp314t-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:83f7ef7056791fc95b6afa987238368c9a73ad0edcedc6bc80076f9fbd3a2a78", size = 756527, upload-time = "2026-03-20T14:24:07.494Z" }, - { url = "https://files.pythonhosted.org/packages/e8/97/2cf1a07884d171c028bd4ae5ecf7ded6f31581f79ab26711dcdad0a3d5ab/fastar-0.9.0-cp314-cp314t-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:b3a456230fcc0e560823f5d04ae8e4c867300d8ee710b14ddcdd1b316ac3dd8d", size = 921763, upload-time = "2026-03-20T14:24:20.787Z" }, - { url = "https://files.pythonhosted.org/packages/f6/e3/c1d698a45f9f5dc892ed7d64badc9c38f1e5c1667048191969c438d2b428/fastar-0.9.0-cp314-cp314t-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:a60b117ebadc46c10c87852d2158a4d6489adbfbbec37be036b4cfbeca07b449", size = 815493, upload-time = "2026-03-20T14:24:46.482Z" }, - { url = "https://files.pythonhosted.org/packages/25/38/e124a404043fba75a8cb2f755ca49e4f01e18400bb6607a5f76526e07164/fastar-0.9.0-cp314-cp314t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7a6199b4ca0c092a7ae47f5f387492d46a0a2d82cb3b7aa0bf50d7f7d5d8d57f", size = 819166, upload-time = "2026-03-20T14:25:12.027Z" }, - { url = "https://files.pythonhosted.org/packages/85/4a/5b1ea5c8d0dbdfcec2fd1e6a243d6bb5a1c7cd55e132cc532eb8b1cbd6d9/fastar-0.9.0-cp314-cp314t-manylinux_2_31_riscv64.whl", hash = "sha256:34efe114caf10b4d5ea404069ff1f6cc0e55a708c7091059b0fc087f65c0a331", size = 883618, upload-time = "2026-03-20T14:24:33.552Z" }, - { url = "https://files.pythonhosted.org/packages/d3/0b/ae46e5722a67a3c2e0ff83d539b0907d6e5092f6395840c0eb6ede81c5d6/fastar-0.9.0-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:4d44c1f8d9c5a3e4e58e6ffb77f4ca023ba9d9ddd88e7c613b3419a8feaa3db7", size = 966294, upload-time = "2026-03-20T14:25:50.024Z" }, - { url = "https://files.pythonhosted.org/packages/98/58/b161cf8711f4a50a3e57b6f89bc703c1aed282cad50434b3bc8524738b20/fastar-0.9.0-cp314-cp314t-musllinux_1_2_armv7l.whl", hash = "sha256:d2af970a1f773965b05f1765017a417380ad080ea49590516eb25b23c039158a", size = 1033177, upload-time = "2026-03-20T14:26:02.868Z" }, - { url = "https://files.pythonhosted.org/packages/e2/76/faac7292bce9b30106a6b6a9f5ddb658fdb03abe2644688b82023c8f76b9/fastar-0.9.0-cp314-cp314t-musllinux_1_2_i686.whl", hash = "sha256:1675346d7cbdde0d21869c3b597be19b5e31a36442bdf3a48d83a49765b269dc", size = 1073620, upload-time = "2026-03-20T14:26:16.121Z" }, - { url = "https://files.pythonhosted.org/packages/b8/be/dd55ffcc302d6f0ff4aba1616a0da3edc8fcefb757869cad81de74604a35/fastar-0.9.0-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:dc440daa28591aeb4d387c171e824f179ad2ab256ce7a315472395b8d5f80392", size = 1025147, upload-time = "2026-03-20T14:26:28.767Z" }, - { url = "https://files.pythonhosted.org/packages/4b/c7/080bbb2b3c4e739fe6486fd765a09905f6c16c1068b2fcf2bb51a5e83937/fastar-0.9.0-cp314-cp314t-win32.whl", hash = "sha256:32787880600a988d11547628034993ef948499ae4514a30509817242c4eb98b1", size = 452317, upload-time = "2026-03-20T14:27:03.243Z" }, - { url = "https://files.pythonhosted.org/packages/42/39/00553739a7e9e35f78a0c5911d181acf6b6e132337adc9bbc3575f5f6f04/fastar-0.9.0-cp314-cp314t-win_amd64.whl", hash = "sha256:92fa18ec4958f33473259980685d29248ac44c96eed34026ad7550f93dd9ee23", size = 483994, upload-time = "2026-03-20T14:26:52.76Z" }, - { url = "https://files.pythonhosted.org/packages/4f/36/a7af08d233624515d9a0f5d41b7a01a51fd825b8c795e41800215a3200e7/fastar-0.9.0-cp314-cp314t-win_arm64.whl", hash = "sha256:34f646ac4f5bed3661a106ca56c1744e7146a02aacf517d47b24fd3f25dc1ff6", size = 460604, upload-time = "2026-03-20T14:26:40.771Z" }, - { url = "https://files.pythonhosted.org/packages/69/9f/4aeaa0a1ac2aca142a276ea136e651e94ba1341bd840ba455ed250d1970b/fastar-0.9.0-pp311-pypy311_pp73-macosx_10_12_x86_64.whl", hash = "sha256:b74ce299066288f3b90221dca8507f59c7d9e8df91387948006b9a0fea4f9bdc", size = 710738, upload-time = "2026-03-20T14:25:41.17Z" }, - { url = "https://files.pythonhosted.org/packages/d0/19/9f8fb5c0e803254c5d535c362102dd604d9bdb206d5a36150f4637cadf09/fastar-0.9.0-pp311-pypy311_pp73-macosx_11_0_arm64.whl", hash = "sha256:76be31936cabce31cbb6381128f851cf0a6da2d5c25357615cd1504b26dc31cf", size = 633000, upload-time = "2026-03-20T14:25:28.496Z" }, - { url = "https://files.pythonhosted.org/packages/ef/8d/0d1d9a87a78f1e686bb6c7c69688a4c9ad1efb65e49cc66310b97fdf900b/fastar-0.9.0-pp311-pypy311_pp73-manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:c4c9ea0e0d69445b0ca3b0bd80bd8237fec8a914275b0472ecca2b555c12f3a3", size = 871226, upload-time = "2026-03-20T14:25:04.351Z" }, - { url = "https://files.pythonhosted.org/packages/ef/04/366937320b1cca522570c527a45b1254bd68d057e68956baefc49eacae27/fastar-0.9.0-pp311-pypy311_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b665c33afcd1d581b82235b690d999c5446ccc2c4d80c4a95f30df3b43d22494", size = 763872, upload-time = "2026-03-20T14:23:59.122Z" }, - { url = "https://files.pythonhosted.org/packages/c8/f2/121c5432bb152da68fc466a0d0206d66383a40a2f9beff5583d9277aceee/fastar-0.9.0-pp311-pypy311_pp73-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:d2a9a49f9217f4f60f9ba23fdd1f7f3f04fed97391145eb9460ec83ca0b4bd33", size = 762897, upload-time = "2026-03-20T14:24:11.932Z" }, - { url = "https://files.pythonhosted.org/packages/80/9e/88d3a603b997063e032f94cc0fff74031d76903f38cc30416a400395df03/fastar-0.9.0-pp311-pypy311_pp73-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:59d860e82a531e9cc67e7f500a299bffbe6e93d80bbf48401fd8f452a0c58f28", size = 927024, upload-time = "2026-03-20T14:24:24.689Z" }, - { url = "https://files.pythonhosted.org/packages/a6/17/d6dc778c45b0c7d9a279706d7a5d62122dab0a7a0cb39aac6f5ef42f13f6/fastar-0.9.0-pp311-pypy311_pp73-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:3feede2d72ec0782b5ccc18568f36cbe33816be396551aa47b3e1b73c322cdd2", size = 821265, upload-time = "2026-03-20T14:24:50.407Z" }, - { url = "https://files.pythonhosted.org/packages/e0/e0/cec25d43df7ea4b4e3e875352c6d51c848c855792ba276c546732a7170af/fastar-0.9.0-pp311-pypy311_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d9ac410d32cbb514e966c45f0fedd0f9447b0dea9e734af714648da503603df6", size = 824024, upload-time = "2026-03-20T14:25:16.142Z" }, - { url = "https://files.pythonhosted.org/packages/52/90/c354969770d21d1b07c9281b5e23052392c288d22984a1917d30940e86cb/fastar-0.9.0-pp311-pypy311_pp73-manylinux_2_31_riscv64.whl", hash = "sha256:40b8c08df809e5e58d1839ccb37bafe4485deb6ee56bb7c5f0cbb72d701eb965", size = 888886, upload-time = "2026-03-20T14:24:38.229Z" }, - { url = "https://files.pythonhosted.org/packages/8c/ac/eb2a01ed94e79b72003840448d2b69644a54a47f615c7d693432a1337caa/fastar-0.9.0-pp311-pypy311_pp73-musllinux_1_2_aarch64.whl", hash = "sha256:d62a4fd86eda3bea7cc32efd64d43b6d0fcdbbec009558b750fc362f20142789", size = 972503, upload-time = "2026-03-20T14:25:54.207Z" }, - { url = "https://files.pythonhosted.org/packages/8d/88/f7e28100fa7ff4a26a3493ad7a5d45d70f6de858c05f5c34aca3570c5839/fastar-0.9.0-pp311-pypy311_pp73-musllinux_1_2_armv7l.whl", hash = "sha256:7bf6958bb6f94e5ec522e4a255b8e940d3561ad973f0be5dde6115b5a0854af5", size = 1039106, upload-time = "2026-03-20T14:26:07.686Z" }, - { url = "https://files.pythonhosted.org/packages/c0/de/52c578180fdaaf0f3289de8a878f1ac070f7e3e18a0689d3fd44dd7dae2c/fastar-0.9.0-pp311-pypy311_pp73-musllinux_1_2_i686.whl", hash = "sha256:c210b839c0a33cf8d08270963ad237bcb63029dddf6d6025333f7e5ca63930bd", size = 1080754, upload-time = "2026-03-20T14:26:20.299Z" }, - { url = "https://files.pythonhosted.org/packages/a4/45/1ea024be428ad9d89e9f738c9379507e97df9f9ed97e50e4a1d10ff90fef/fastar-0.9.0-pp311-pypy311_pp73-musllinux_1_2_x86_64.whl", hash = "sha256:fad70e257daefb42bab68dcd68beaf2e2a99da056d65f2c9f988449a4e869306", size = 1031304, upload-time = "2026-03-20T14:26:33.294Z" }, +sdist = { url = "https://files.pythonhosted.org/packages/03/0f/0aeb3fc50046617702acc0078b277b58367fd62eb727b9ec733ae0e8bbcc/fastar-0.11.0.tar.gz", hash = "sha256:aa7f100f7313c03fdb20f1385927ba95671071ba308ad0c1763fef295e1895ce", size = 70238, upload-time = "2026-04-13T17:11:17.143Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/9b/4a/0d79fe52243a4130aa41d0a3a9eea22e00427db761e1a6782ee817c50222/fastar-0.11.0-cp310-cp310-macosx_10_12_x86_64.whl", hash = "sha256:e7c906ad371ca365591ebcb7630009923f3eceb20956814494d15591a78e9e46", size = 709786, upload-time = "2026-04-13T17:09:53.974Z" }, + { url = "https://files.pythonhosted.org/packages/9f/e4/77c94eaafc035e39f5ce5176e32743da4e3fe890f28790e708e53d8f75cd/fastar-0.11.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:6919497b35fa5bd978d2c26ee117cf1771b90ee5073f7518e44b9bc364b57715", size = 632127, upload-time = "2026-04-13T17:09:39.023Z" }, + { url = "https://files.pythonhosted.org/packages/3c/f6/97658dd992f4e45747d35adb24c0b100f6b6d451490685ae3fe8a3a2ee1b/fastar-0.11.0-cp310-cp310-manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:56b50206aeedd99e22b83289e6fb3ff8f7d7da4407d2419902e4716b4f90585a", size = 869608, upload-time = "2026-04-13T17:09:08.268Z" }, + { url = "https://files.pythonhosted.org/packages/e9/fc/81c1ec4d8146a437399e7b95631b51be312f323a9ce64569f932db6c3914/fastar-0.11.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:7a1811a69ae81d469720df0c8af3f84f834a93b5e4f8be0e0e8bde6a52fa11f2", size = 762925, upload-time = "2026-04-13T17:07:52.788Z" }, + { url = "https://files.pythonhosted.org/packages/b9/35/49baf480ecb197aea7ce2515c503a2f25061958dd3b4c98e98a3a11cdcc7/fastar-0.11.0-cp310-cp310-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:10486238c55589a3947c38f9cfb88a67d8a608eb8dddc722038237d0278a41d7", size = 759913, upload-time = "2026-04-13T17:08:07.324Z" }, + { url = "https://files.pythonhosted.org/packages/94/eb/946f1980267f2824efb7d7c518d47a49b89c0e9cd7c449301f5a7531558a/fastar-0.11.0-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:1555ef9992d368a6ec39092276990cef8d329c39a1d86ebd847eaa3b10efd472", size = 926054, upload-time = "2026-04-13T17:08:22.196Z" }, + { url = "https://files.pythonhosted.org/packages/0c/19/d5eb611085ce054382570d8d4e24a5e2ff23cd6d2404528a6643841d6059/fastar-0.11.0-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:b1f4aca0a9620b76988bbf6225cdea6678a392902444ca18bb8a51495b165a89", size = 818594, upload-time = "2026-04-13T17:08:52.366Z" }, + { url = "https://files.pythonhosted.org/packages/4a/52/18e8d55c0d3d917713f381cb2d0cb793da00c209c802e011d8dc72018cd5/fastar-0.11.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:75beeecac7d11a666a6c4a0b7f7e80842ae5cf523f2f890b99c78fc82b403545", size = 823005, upload-time = "2026-04-13T17:09:23.051Z" }, + { url = "https://files.pythonhosted.org/packages/2c/b4/0fecdcf33e5aaffe777b96a1c10a3204fe0b05bf18e971033a0bfedafc1c/fastar-0.11.0-cp310-cp310-manylinux_2_31_riscv64.whl", hash = "sha256:a08cdf5d16daa401c65c9c7493a18db7dc515c52155a17071ec7098bb07da9d3", size = 887115, upload-time = "2026-04-13T17:08:37.385Z" }, + { url = "https://files.pythonhosted.org/packages/08/f8/2a6ad1c2523eb72a4595a9331162fc67ce0f0aee3348728598026c516986/fastar-0.11.0-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:6e210375e5a7ba53586cbd6017aa417d2d2ceacbe8671682470281bd0a15e8ef", size = 973595, upload-time = "2026-04-13T17:10:09.258Z" }, + { url = "https://files.pythonhosted.org/packages/5c/a6/2aa48843228673feacc2b80876b8924e63ea9c5f5f607bd7a72416b86bae/fastar-0.11.0-cp310-cp310-musllinux_1_2_armv7l.whl", hash = "sha256:a2988eb2604b8e15670f355425e8c800e4dcd4edfbcbfe194397f8f17b7eb19e", size = 1036988, upload-time = "2026-04-13T17:10:26.133Z" }, + { url = "https://files.pythonhosted.org/packages/92/ac/3dd14b21c323e8484f47c910110d1d93139ba44621ac2c4c597dbe9fcdb7/fastar-0.11.0-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:34abc857b46068fdf91d157bd0203bfd6791dc7a432d1ed180f5af6c2f5bcce9", size = 1078267, upload-time = "2026-04-13T17:10:43.645Z" }, + { url = "https://files.pythonhosted.org/packages/de/a1/3f89e58d6fa99160c9e7e17220c8ab5040b5cc017c4fac2356c6ed18453d/fastar-0.11.0-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:0d884be84e37a01053776395441fc960031974e0265801ce574efc3d05e0cdaf", size = 1032551, upload-time = "2026-04-13T17:11:00.667Z" }, + { url = "https://files.pythonhosted.org/packages/f6/ea/24dd3cfc2096933d7d2a80c926e79602cff1fa481124ed2165b60c1dd9ef/fastar-0.11.0-cp310-cp310-win32.whl", hash = "sha256:c721c1ad758e3e4c2c1fd9e96911a0fa58c0a6be5668f1bcfd0b741e72c7cb63", size = 456022, upload-time = "2026-04-13T17:11:41.859Z" }, + { url = "https://files.pythonhosted.org/packages/82/ef/6eb39ee9cdd59822d1c7337c4d28fdc948885bdf455af9e70efa9879e06f/fastar-0.11.0-cp310-cp310-win_amd64.whl", hash = "sha256:ba4180b7c3080f55f9035fdd7d8c39fe0e1485087a68ff615bb4784a10b8106b", size = 488392, upload-time = "2026-04-13T17:11:27.486Z" }, + { url = "https://files.pythonhosted.org/packages/11/7a/fb367bdaf4efa2c7952a45aeab2e87a564293ecffe150af673ec8edfda46/fastar-0.11.0-cp311-cp311-macosx_10_12_x86_64.whl", hash = "sha256:b82fd6f996e65a86f67a6bd64dd22ef3e8ae2dcaed0ae3b550e71f7e1bbb1df5", size = 709869, upload-time = "2026-04-13T17:09:55.62Z" }, + { url = "https://files.pythonhosted.org/packages/80/ff/b87efb0dcfd081c62c7c7601d7681dabe63103cd51fc16f8d57a1ab45961/fastar-0.11.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:27eed386fd0558e6daa29211111bbd7b740f7c7e881197f8a00ac7c0f3cdb1d7", size = 631668, upload-time = "2026-04-13T17:09:40.537Z" }, + { url = "https://files.pythonhosted.org/packages/24/7c/0ed6dd38b9adc04b3a8ec3b7045908e7c2170ba0ff6e6d2c51bc9fc770f3/fastar-0.11.0-cp311-cp311-manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:a6931bebc1d8e95ddeef55732c195449e6b44ef33aa31b325505097ed3b4d6aa", size = 869663, upload-time = "2026-04-13T17:09:09.78Z" }, + { url = "https://files.pythonhosted.org/packages/58/ce/8b7fb3f23855accebaaf2d2637eac7f261a7a5d936f861a172079f1ef511/fastar-0.11.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:891f72ce42a5e28a74fbd4d5fbf1a3ac1a1163d13cbc200cbd005fb0fabc54bd", size = 762938, upload-time = "2026-04-13T17:07:54.51Z" }, + { url = "https://files.pythonhosted.org/packages/07/cc/5491e2b677bb841f768e3aba052d0344338a5c78aa5d4c18b443831a8e8d/fastar-0.11.0-cp311-cp311-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:5b83c1f61f7017d6e1498568038f8745440cfc16ca2f697ec81bac83050108f6", size = 759232, upload-time = "2026-04-13T17:08:08.864Z" }, + { url = "https://files.pythonhosted.org/packages/4e/b7/643630bdbd179e41e9fae31c03b4cf6061dbf4d6fbbae8425d16eb12545d/fastar-0.11.0-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:db73a9b765a516e73983b25341e7b5e0189733878279e278b2295131b0e3a21e", size = 926271, upload-time = "2026-04-13T17:08:23.68Z" }, + { url = "https://files.pythonhosted.org/packages/09/5d/37ade50003b4540e0a53ef100f6692d7ab2ac1122d5acf39920cc09a3e8b/fastar-0.11.0-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:625827d52eb4e8fec942e0233f125ff8010fcf6a67c0a974a8e5f4666b771e3c", size = 818634, upload-time = "2026-04-13T17:08:54.268Z" }, + { url = "https://files.pythonhosted.org/packages/c3/ff/135d177de32cc1e837c99019e4643e6e79352bde49544d4ece5b5eebf56b/fastar-0.11.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d7f5fd8fa21ec0a88296a38dc5d7fc35efd3b26d46a17b8b7c73c5563925ca15", size = 822755, upload-time = "2026-04-13T17:09:25.01Z" }, + { url = "https://files.pythonhosted.org/packages/27/cb/b835dbe76ceac7fa6105851468c259ffd06830eb9c029402e499d0ec153b/fastar-0.11.0-cp311-cp311-manylinux_2_31_riscv64.whl", hash = "sha256:8c15af91b8cd87ddf23ea55355ae513c1de3ab67178f26dad017c9e9c0af6096", size = 887101, upload-time = "2026-04-13T17:08:39.248Z" }, + { url = "https://files.pythonhosted.org/packages/9e/54/aa8289eb57fc550535470397cb051f5a58a7c89ca4de31d5502b916dd894/fastar-0.11.0-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:03a112395a8b0bff251423bd1564c012f0cc058ad8b6bd8fba96f3d7fc117e44", size = 973606, upload-time = "2026-04-13T17:10:10.98Z" }, + { url = "https://files.pythonhosted.org/packages/1f/fd/776d50a0897c01dc6bfd0926772ee913436fdae91b9affaf0a0cbd09f0a1/fastar-0.11.0-cp311-cp311-musllinux_1_2_armv7l.whl", hash = "sha256:f2994bb8f5f8c11eb12beae1e6e77a907173c9819236b8a4c8f0573652ceccce", size = 1036696, upload-time = "2026-04-13T17:10:28.502Z" }, + { url = "https://files.pythonhosted.org/packages/c8/f1/cf0f9b499fb37ac065c8a01ec642f96a3c5eb849c38ae983b59f3b3245e0/fastar-0.11.0-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:dcf99e4b5973d842c7f19c776c3a83cdc0977d505edce6206438505c0456b517", size = 1078182, upload-time = "2026-04-13T17:10:45.318Z" }, + { url = "https://files.pythonhosted.org/packages/f8/9e/21e4701aec4a1123d4dc4d31578dc18875582b5710e4725f7ceb752a248b/fastar-0.11.0-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:29c9c386dc0d5dda78845a8e6b1480d26ab861c1e0b68f42ae5735cb70ca07f1", size = 1032336, upload-time = "2026-04-13T17:11:02.364Z" }, + { url = "https://files.pythonhosted.org/packages/ce/e2/5872b28c72c27ec1a00760eace6ff35f714f41ebbd5208cf016b12e29250/fastar-0.11.0-cp311-cp311-win32.whl", hash = "sha256:030b2580fc394f2c9b7890b6735810404e9b9ed5e0344db150b945965b5482b7", size = 457368, upload-time = "2026-04-13T17:11:43.528Z" }, + { url = "https://files.pythonhosted.org/packages/fd/6e/ce6832a16193eb4466f4108be8809c249b51cb1f89dd7894545700d079d5/fastar-0.11.0-cp311-cp311-win_amd64.whl", hash = "sha256:83ab57ae067969cd0b483ac3b6dccc4b595fc77f5c820760998648d4c42822b5", size = 488605, upload-time = "2026-04-13T17:11:29.161Z" }, + { url = "https://files.pythonhosted.org/packages/15/5a/9cfb80661cf38fd7b0889224beb7d2746784d4ade2a931ed9775a18d8602/fastar-0.11.0-cp311-cp311-win_arm64.whl", hash = "sha256:27b1a4cee2298b704de8151d310462ee7335ed036011ca9aa6e784b30b6c73a9", size = 464580, upload-time = "2026-04-13T17:11:18.583Z" }, + { url = "https://files.pythonhosted.org/packages/0f/06/a5773706afc8bd496769786590bbc56d2d0ee419a299cc12ea3f5717fcf3/fastar-0.11.0-cp312-cp312-macosx_10_12_x86_64.whl", hash = "sha256:3c51f1c2cdddbd1420d2897ace7738e36c65e17f6ae84e0bfe763f8d1068bb97", size = 708394, upload-time = "2026-04-13T17:09:57.269Z" }, + { url = "https://files.pythonhosted.org/packages/cc/a6/d5e2a4e48495616440a21eed07558219ca90243ad00b0502586f95bd4833/fastar-0.11.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:0d9d6b052baf5380baea866675dab6ccd04ec2460d12b1c46f10ce3f4ee6a820", size = 628417, upload-time = "2026-04-13T17:09:42.145Z" }, + { url = "https://files.pythonhosted.org/packages/ab/69/9816d69ac8265c9e50456637a487ccfb7a9c566efd9dbcd673df9c2558c2/fastar-0.11.0-cp312-cp312-manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:bd2f05666d4df7e14885b5c38fefd92a785917387513d33d837ff42ec143a22f", size = 863950, upload-time = "2026-04-13T17:09:11.506Z" }, + { url = "https://files.pythonhosted.org/packages/5b/0d/f88daad53aff2e754b6b5ff2a7113f72447a34f6ef17cc23ca99988117b7/fastar-0.11.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c1e6e74aba1ae77ca4aedcaf1697cd413319f4c88a5ccbe5b42c709517c5097e", size = 760737, upload-time = "2026-04-13T17:07:55.958Z" }, + { url = "https://files.pythonhosted.org/packages/2f/a6/82ef4ecd969d50d92ed3ed9dbd8fe77faa24be5e5736f716edc9f4ce8d62/fastar-0.11.0-cp312-cp312-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:38ef77fe940bbc9b37a98bd838727f844b11731cd39358a2640ff864fb385086", size = 757603, upload-time = "2026-04-13T17:08:10.623Z" }, + { url = "https://files.pythonhosted.org/packages/03/35/50249f0d827251f8ac511495e2eacccebda80a00a0ad73e9615b8113b84f/fastar-0.11.0-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:8955e61b32d6aff82c983217abf80933fd823b0e727586fc72f08043d996fd59", size = 923952, upload-time = "2026-04-13T17:08:25.526Z" }, + { url = "https://files.pythonhosted.org/packages/7b/d8/faee41659e9c379d906d24eaee6d6833ac8cfef0a5df480e5c2a8d3efb33/fastar-0.11.0-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:483532442cdb08fbff0169510224eae0836f2f672cea6aacb52847d90fefdc46", size = 816574, upload-time = "2026-04-13T17:08:56.076Z" }, + { url = "https://files.pythonhosted.org/packages/22/47/0448ea7992b997dad2bf004bfd98eca74b5858630eae080b50c7b17d9ddc/fastar-0.11.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ef5a6071121e05d8287fc75bccb054bcbac8bb0501200a0c0a8feeace5303ea4", size = 819382, upload-time = "2026-04-13T17:09:26.66Z" }, + { url = "https://files.pythonhosted.org/packages/33/ef/0d63eb43586831b7a6f8b22c4d77125a7c594423af1f4f090fa9541b9b40/fastar-0.11.0-cp312-cp312-manylinux_2_31_riscv64.whl", hash = "sha256:e45e598af5afe8412197d4786efd6cf29be02e7d3d4f6a3461149eae5d7e94f1", size = 885254, upload-time = "2026-04-13T17:08:40.9Z" }, + { url = "https://files.pythonhosted.org/packages/01/25/edd584675d69e49a165052c3ee886df1c5d574f3e7d813c990306387c623/fastar-0.11.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:2e160919b1c47ddb8538e7e8eb4cd527281b40f0bf75110a75993838ef61f286", size = 971239, upload-time = "2026-04-13T17:10:12.997Z" }, + { url = "https://files.pythonhosted.org/packages/a5/37/e8bb24f506ba2b08fbaf36c5800e843bd4d542954e9331f00418e2d23349/fastar-0.11.0-cp312-cp312-musllinux_1_2_armv7l.whl", hash = "sha256:4bb4dc0fc8f7a6807febcebce8a2f3626ba4955a9263d81ecc630aad83be84c0", size = 1035185, upload-time = "2026-04-13T17:10:30.207Z" }, + { url = "https://files.pythonhosted.org/packages/9a/bf/be753736296338149ee4cb3e92e2b5423d6ba17c7b951d15218fd7e99bbf/fastar-0.11.0-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:4ec95af56aa173f6e320e1183001bf108ba59beaf13edd1fc8200648db203588", size = 1072191, upload-time = "2026-04-13T17:10:47.072Z" }, + { url = "https://files.pythonhosted.org/packages/d2/cd/a81c1aaafb5a22ce57c98ae22f39c89413ed53e4ee6e1b1444b0bd666a6c/fastar-0.11.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:136cf342735464091c39dc3708168f9fdeb9ebea40b1ead937c61afaf46143d9", size = 1028054, upload-time = "2026-04-13T17:11:04.293Z" }, + { url = "https://files.pythonhosted.org/packages/ec/88/1ce4eed3d70627c95f49ca017f6bbbf2ddcc4b0c601d293259de7689bc20/fastar-0.11.0-cp312-cp312-win32.whl", hash = "sha256:35f23c11b556cc4d3704587faacbc0037f7bdf6c4525cd1d09c70bda4b1c6809", size = 454198, upload-time = "2026-04-13T17:11:45.168Z" }, + { url = "https://files.pythonhosted.org/packages/8f/1d/26ce92f4331cd61a69840db9ca6115829805eec24f285481a854f578e917/fastar-0.11.0-cp312-cp312-win_amd64.whl", hash = "sha256:920bc56c3c0b8a8ca492904941d1883c1c947c858cd93343356c29122a38f44c", size = 486697, upload-time = "2026-04-13T17:11:31.084Z" }, + { url = "https://files.pythonhosted.org/packages/ed/96/e6eda4480559c69b05d466e7b5ea9170e81fef3795a73e059959a3258319/fastar-0.11.0-cp312-cp312-win_arm64.whl", hash = "sha256:395248faf89e8a6bd5dc1fd544c8465113b627cb6d7c8b296796b60ebea33593", size = 462591, upload-time = "2026-04-13T17:11:20.577Z" }, + { url = "https://files.pythonhosted.org/packages/c9/d6/3be260037e86fb694e88d47f583bac3a0188c99cee1a6b257ac26cb6b53c/fastar-0.11.0-cp313-cp313-macosx_10_12_x86_64.whl", hash = "sha256:33f544b08b4541b678e53749b4552a44720d96761fb79c172b005b1089c443ed", size = 707975, upload-time = "2026-04-13T17:09:58.866Z" }, + { url = "https://files.pythonhosted.org/packages/e1/cd/7867aefb1784662554a335f2952c75a50f0c70585ed0d2210d6cc15e5627/fastar-0.11.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:91c1c792447e4a642745f347ff9847c52af39633071c57ee67ed53c157fc3506", size = 628460, upload-time = "2026-04-13T17:09:43.776Z" }, + { url = "https://files.pythonhosted.org/packages/e5/2b/d11d84bdd5e0e377771b955755771e3460b290da5809cb78c1b735ee2228/fastar-0.11.0-cp313-cp313-manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:881247e6b6eaea59fc6569f9b61447aa6b9fc2ee864e048b4643d69c52745805", size = 863054, upload-time = "2026-04-13T17:09:13.048Z" }, + { url = "https://files.pythonhosted.org/packages/25/39/d3f428b318fa940b1b6e785b8d54fc895dfb5d5b945ef8d5442ffa904fb2/fastar-0.11.0-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:863b7929845c9fec92ef6c8d59579cf46af5136655e5342f8df5cebe46cab06c", size = 760247, upload-time = "2026-04-13T17:07:57.396Z" }, + { url = "https://files.pythonhosted.org/packages/9e/04/03949aee82aabb8ede06ac5a4a5579ffaf98a8fe59ce958494508ff15513/fastar-0.11.0-cp313-cp313-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:96b4a57df12bf3211662627a3ea29d62ecb314a2434a0d0843f9fc23e47536e5", size = 756512, upload-time = "2026-04-13T17:08:12.415Z" }, + { url = "https://files.pythonhosted.org/packages/3f/0c/2ca1ae0a3828ca51047962d932b80daca2522db73e8cb9d040cb6ebe28d5/fastar-0.11.0-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:ceef1c2c4df7b7b8ebd3f5d718bbf457b9bbdf25ce0bd07870211ec4fbd9aff4", size = 922183, upload-time = "2026-04-13T17:08:27.187Z" }, + { url = "https://files.pythonhosted.org/packages/65/68/7fe808b1f73a68e686f25434f538c6dc10ef4dfb3db0ace22cd861744bf8/fastar-0.11.0-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:b8e545918441910a779659d4759ad0eef349e935fbdb4668a666d3681567eb05", size = 816394, upload-time = "2026-04-13T17:08:57.657Z" }, + { url = "https://files.pythonhosted.org/packages/1f/17/07d086080f8a83b8d7966955e29bcdbd6a060f5bd949dc9d5abd3658cead/fastar-0.11.0-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:28095bb8f821e85fc2764e1a55f03e5e2876dee2abe7cd0ee9420d929905d643", size = 818983, upload-time = "2026-04-13T17:09:28.46Z" }, + { url = "https://files.pythonhosted.org/packages/fb/e2/2c4edf0910af2e814ff6d65b77a91196d472ca8a9fb2033bd983f6856caa/fastar-0.11.0-cp313-cp313-manylinux_2_31_riscv64.whl", hash = "sha256:0fafb95ecbe70f666a5e9b35dd63974ccdc9bb3d99ccdbd4014a823ec3e659b5", size = 884689, upload-time = "2026-04-13T17:08:42.763Z" }, + { url = "https://files.pythonhosted.org/packages/fa/ba/04fdcbd6558e60de4ced3b55230fac47675d181252582b2fcec3c74608e5/fastar-0.11.0-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:af48fed039b94016629dcdad1c95c90c486326dd068de2b0a4df419ee09b6821", size = 970677, upload-time = "2026-04-13T17:10:15.124Z" }, + { url = "https://files.pythonhosted.org/packages/df/b3/2b860a9658550167dbd5824c85e88d0b4b912bf493e42a6322544d6e483d/fastar-0.11.0-cp313-cp313-musllinux_1_2_armv7l.whl", hash = "sha256:74cd96163f39b8638ab4e8d49708ca887959672a22871d8170d01f067319533b", size = 1034026, upload-time = "2026-04-13T17:10:32.318Z" }, + { url = "https://files.pythonhosted.org/packages/b7/9b/fa42ea1188b144bac4b1b60753dfd449974a4d5eda132029ee7711569f94/fastar-0.11.0-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:4e8b993cb5613bab495ed482810bedc0986633fcb9a3b55c37ec88e0d6714f6a", size = 1071147, upload-time = "2026-04-13T17:10:48.833Z" }, + { url = "https://files.pythonhosted.org/packages/95/c8/d2e501556dca9f1fbc9246111a31792fb49ad908fa4927f34938a97a3604/fastar-0.11.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:dfe39d91fc28e37e06162d94afe01050220edb7df554acb5b702b5503e564816", size = 1028377, upload-time = "2026-04-13T17:11:06.374Z" }, + { url = "https://files.pythonhosted.org/packages/db/33/5f11f23eca0a569cd052507bc45dda2e5468697f8665728d25be44120f7d/fastar-0.11.0-cp313-cp313-win32.whl", hash = "sha256:c5f63d4d99ff4bfb37c659982ec413358bdee747005348756cc50a04d412d989", size = 454089, upload-time = "2026-04-13T17:11:46.821Z" }, + { url = "https://files.pythonhosted.org/packages/da/2f/35ff03c939cba7a255a9132367873fec6c355fd06a7f84fedcbaf4c8129f/fastar-0.11.0-cp313-cp313-win_amd64.whl", hash = "sha256:8690ed1928d31ded3ada308e1086525fb3871f5fa81e1b69601a3f7774004583", size = 486312, upload-time = "2026-04-13T17:11:32.86Z" }, + { url = "https://files.pythonhosted.org/packages/ef/71/ee9246cbfcbfd4144558f35e7e9a306ffe0a7564730a5188c45f21d2dab8/fastar-0.11.0-cp313-cp313-win_arm64.whl", hash = "sha256:d977ded9d98a0719a305e0a4d5ee811f1d3e856d853a50acb8ae833c3cd6d5d2", size = 461975, upload-time = "2026-04-13T17:11:22.589Z" }, + { url = "https://files.pythonhosted.org/packages/7a/cd/3644c48ecac456f928c12d47ec3bed36c36555b17c3859856f1ff860265d/fastar-0.11.0-cp314-cp314-macosx_10_12_x86_64.whl", hash = "sha256:71375bd6f03c2a43eb47bd949ea38ff45434917f9cdac79675c5b9f60de4fa73", size = 707860, upload-time = "2026-04-13T17:10:00.371Z" }, + { url = "https://files.pythonhosted.org/packages/69/ca/dee04476ae3626b2b040a60ad84628f77e1ffd8444232f2426b0ca1e0d7e/fastar-0.11.0-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:eddfd9cab16e19ae247fe44bf992cb403ccfe27d3931d6de29a4695d95ad386c", size = 628216, upload-time = "2026-04-13T17:09:45.355Z" }, + { url = "https://files.pythonhosted.org/packages/dc/5e/9395c7353d079cb4f5be0f7982ce0dc9f2e7dec5fd175eef466729d6023a/fastar-0.11.0-cp314-cp314-manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:7c371f1d4386c699018bb64eb2fa785feacf32785559049d2bb72fe4af023f53", size = 864378, upload-time = "2026-04-13T17:09:14.611Z" }, + { url = "https://files.pythonhosted.org/packages/fa/ba/1e4f67148223ff219612b6281a6000357abbcc2417964fa5c83f11d68fce/fastar-0.11.0-cp314-cp314-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:cad7fa41e3e66554387481c1a09365e4638becd322904932674159d5f4046728", size = 760921, upload-time = "2026-04-13T17:07:59.138Z" }, + { url = "https://files.pythonhosted.org/packages/0f/82/09d11fb6d12f17993ffaf32ffd30c3c121a11e2966e84f19fb6f66430118/fastar-0.11.0-cp314-cp314-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:cf36652fa71b83761717c9899b98732498f8a2cb6327ff16bbf07f6be85c3437", size = 757012, upload-time = "2026-04-13T17:08:14.186Z" }, + { url = "https://files.pythonhosted.org/packages/52/1f/5aeeacc4cb65615e2c9292cd9c5b0cd6fb6d2e6ee472ca6adc6c1b1b22ef/fastar-0.11.0-cp314-cp314-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:f68ff8c17833053da4841720e95edde80ce45bb994b6b7d51418dddaac70ee47", size = 924510, upload-time = "2026-04-13T17:08:28.741Z" }, + { url = "https://files.pythonhosted.org/packages/bb/1a/1e5bdabbeaf2e856928956292609f2ff6a650f94480fb8afaca30229e483/fastar-0.11.0-cp314-cp314-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:4563ed37a12ea1cdc398af8571258d24b988bf342b7b3bf5451bd5891243280c", size = 816602, upload-time = "2026-04-13T17:08:59.461Z" }, + { url = "https://files.pythonhosted.org/packages/87/24/f960147910da3bed41a3adfcb026e17d5f50f4cf467a3324237a7088f61a/fastar-0.11.0-cp314-cp314-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:cee63c9875cba3b70dc44338c560facc5d6e763047dcc4a30501f9a68cf5f890", size = 819452, upload-time = "2026-04-13T17:09:29.926Z" }, + { url = "https://files.pythonhosted.org/packages/cc/f4/3e77d7901d5707fd7f8a352e153c8ae09ea974e6fabad0b7c4eb9944b8d4/fastar-0.11.0-cp314-cp314-manylinux_2_31_riscv64.whl", hash = "sha256:bd76bfffae6d0a91f4ac4a612f721e7aec108db97dccdd120ae063cd66959f27", size = 885254, upload-time = "2026-04-13T17:08:44.285Z" }, + { url = "https://files.pythonhosted.org/packages/47/01/1585edd5ec47782ae93cd94edf05828e0ab02ef00aec00aea4194a600464/fastar-0.11.0-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:8f5b707501ec01c1bc0518f741f01d322e50c9adc19a451aa24f67a2316e9397", size = 971496, upload-time = "2026-04-13T17:10:17.024Z" }, + { url = "https://files.pythonhosted.org/packages/f1/e9/6874c9d1236ded565a0bed54b320ac9f165f287b1d89490fb70f9f323c81/fastar-0.11.0-cp314-cp314-musllinux_1_2_armv7l.whl", hash = "sha256:37c0b5a88a657839aad98b0a6c9e4ac4c2c15d6b49c44ee3935c6b08e9d3e479", size = 1034685, upload-time = "2026-04-13T17:10:34.063Z" }, + { url = "https://files.pythonhosted.org/packages/14/d8/4ab20613ce2983427aee958e39be878dba874aa227c530a845e32429c4f6/fastar-0.11.0-cp314-cp314-musllinux_1_2_i686.whl", hash = "sha256:6c55f536c62a6efb180c1af0d5182948bff576bbfe6276e8e1359c9c7d2215d8", size = 1072675, upload-time = "2026-04-13T17:10:50.53Z" }, + { url = "https://files.pythonhosted.org/packages/1f/ae/5ac3b7c20ce4b08f011dd2b979f96caabe64f9b10b157f211ea91bdfadca/fastar-0.11.0-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:3082eeca59e189b9039335862f4c2780c0c8871d656bfdf559db4414a105b251", size = 1029330, upload-time = "2026-04-13T17:11:08.138Z" }, + { url = "https://files.pythonhosted.org/packages/8a/e7/37cd6a1d4e288292170b64e19d79ecce2a7de8bb76790323399a2abc4619/fastar-0.11.0-cp314-cp314-win32.whl", hash = "sha256:b201a0a4e29f9fec2a177e13154b8725ec65ab9f83bd6415483efaa2aa18344b", size = 453940, upload-time = "2026-04-13T17:11:48.713Z" }, + { url = "https://files.pythonhosted.org/packages/ff/1c/795c878b1ee29d79021cf8ed81f18f2b25ccde58453b0d34b9bdc7e025ea/fastar-0.11.0-cp314-cp314-win_amd64.whl", hash = "sha256:868fddb26072a43e870a8819134b9f80ee602931be5a76e6fb873e04da343637", size = 486334, upload-time = "2026-04-13T17:11:34.882Z" }, + { url = "https://files.pythonhosted.org/packages/ff/a4/113f104301df8bddcc0b3775b611a30cb7610baa3add933c7ccac9386467/fastar-0.11.0-cp314-cp314-win_arm64.whl", hash = "sha256:3db39c9cc42abb0c780a26b299f24dfbc8be455985e969e15336d70d7b2f833b", size = 461534, upload-time = "2026-04-13T17:11:24.329Z" }, + { url = "https://files.pythonhosted.org/packages/5a/a6/5c5f2c2c8e0c63e56a5636ebc7721589c889e94c0092cec7eb28ae7207e6/fastar-0.11.0-cp314-cp314t-macosx_10_12_x86_64.whl", hash = "sha256:49c3299dec5e125e7ebaa27545714da9c7391777366015427e0ae62d548b442b", size = 707156, upload-time = "2026-04-13T17:10:02.176Z" }, + { url = "https://files.pythonhosted.org/packages/df/f7/982c01b61f0fc135ad2b16d01e6d0ee53cf8791e68827f5f7c5a65b2e5b1/fastar-0.11.0-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:3328ed1ed56d31f5198350b17dd60449b8d6b9d47abb4688bab6aef4450a165b", size = 627032, upload-time = "2026-04-13T17:09:46.978Z" }, + { url = "https://files.pythonhosted.org/packages/2b/c3/38f1dac77ae0c71c37b176277c96d830796b8ce2fe69705f917829b53829/fastar-0.11.0-cp314-cp314t-manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:bd3eca3bbfec84a614bcb4143b4ad4f784d0895babc26cfc88436af88ca23c7a", size = 864403, upload-time = "2026-04-13T17:09:16.58Z" }, + { url = "https://files.pythonhosted.org/packages/6e/f0/e69c363bdb3e5a5848e937b662b5469581ee6682c51bc1c0556494773929/fastar-0.11.0-cp314-cp314t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ff86a967acb0d621dd24063dda090daa67bf4993b9570e97fe156de88a9006ca", size = 759480, upload-time = "2026-04-13T17:08:00.599Z" }, + { url = "https://files.pythonhosted.org/packages/3b/29/4d8737590c2a6357d614d7cc7288e8f68e7e449680b8922997cc4349e65e/fastar-0.11.0-cp314-cp314t-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:86eaf7c0e985d93a7734168be2fb232b2a8cca53e41431c2782d7c12b12c03b1", size = 756219, upload-time = "2026-04-13T17:08:15.699Z" }, + { url = "https://files.pythonhosted.org/packages/bb/ec/400de7b3b7d48801908f19cf5462177104395799472671b3e8152b2b04ca/fastar-0.11.0-cp314-cp314t-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:91f07b0b8eb67e2f177733a1f884edad7dfb9f8977ffef15927b20cb9604027d", size = 923669, upload-time = "2026-04-13T17:08:30.574Z" }, + { url = "https://files.pythonhosted.org/packages/5d/01/8926c53da923fed7ab4b96e7fbf7f73b663beb4f02095b654d6fab46f9ad/fastar-0.11.0-cp314-cp314t-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:f85c896885eb4abf1a635d54dea22cac6ae48d04fc2ea26ae652fcf1febe1220", size = 815729, upload-time = "2026-04-13T17:09:01.204Z" }, + { url = "https://files.pythonhosted.org/packages/89/f0/5fef4c7946e352651b504b1a4235dac3505e7cfd24020788ab50552e84bf/fastar-0.11.0-cp314-cp314t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:075c07095c8de4b774ba8f28b9c0a02b1a2cd254da50cbe464dd3bb2432e9158", size = 819812, upload-time = "2026-04-13T17:09:31.907Z" }, + { url = "https://files.pythonhosted.org/packages/b3/c8/0ebc3298b4a45e7bddc50b169ae6a6f5b80c939394d4befe6e60de535ee7/fastar-0.11.0-cp314-cp314t-manylinux_2_31_riscv64.whl", hash = "sha256:07f028933820c65750baf3383b807ecce1cd9385cf00ce192b79d263ad6b856c", size = 884074, upload-time = "2026-04-13T17:08:45.802Z" }, + { url = "https://files.pythonhosted.org/packages/ae/9f/7baa4cdff8d6fbca41fa5c764b48a941fed8a9ec6c4cc92de65895a28299/fastar-0.11.0-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:039f875efa0f01fa43c20bf4e2fc7305489c61d0ac76eda991acfba7820a0e63", size = 969450, upload-time = "2026-04-13T17:10:18.667Z" }, + { url = "https://files.pythonhosted.org/packages/d4/dc/1ebbfb58a47056ba866494f19efbcdd2ba2897096b94f36e796594b4d05b/fastar-0.11.0-cp314-cp314t-musllinux_1_2_armv7l.whl", hash = "sha256:fff12452a9a5c6814a012445f26365541cc3d99dcca61f09762e6a389f7a32ea", size = 1033775, upload-time = "2026-04-13T17:10:36.165Z" }, + { url = "https://files.pythonhosted.org/packages/c2/5f/ce4e3914066f08c99eb8c32952cc07c1a013e81b1db1b0f598130bf6b974/fastar-0.11.0-cp314-cp314t-musllinux_1_2_i686.whl", hash = "sha256:2bf733e09f942b6fa876efe30a90508d1f4caef5630c00fb2a84fba355873712", size = 1072158, upload-time = "2026-04-13T17:10:52.497Z" }, + { url = "https://files.pythonhosted.org/packages/03/2a/6bca72992c84151c387cc6558f3867f5ebe5fb3684ee6fa9b76280ba4b8e/fastar-0.11.0-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:d1531fa848fdd3677d2dce0a4b436ea64d9ae38fb8babe2ddbc180dd153cb7a3", size = 1028577, upload-time = "2026-04-13T17:11:09.934Z" }, + { url = "https://files.pythonhosted.org/packages/83/18/7a7c15657a3da5569b26fc51cde6a80f8d84cb54b3b1aea6d74a103db4ad/fastar-0.11.0-cp314-cp314t-win32.whl", hash = "sha256:5744551bc67c6fc6581cbd0e34a0fd6e2cd0bd30b43e94b1c3119cf35064b162", size = 453601, upload-time = "2026-04-13T17:11:53.726Z" }, + { url = "https://files.pythonhosted.org/packages/6d/d8/331b59a6de279f3ad75c10c02c40a12f21d64a437d9c3d6f1af2dcbd7a76/fastar-0.11.0-cp314-cp314t-win_amd64.whl", hash = "sha256:f4ce44e3b56c47cf38244b98d29f269b259740a580c47a2552efa5b96a5458fb", size = 486436, upload-time = "2026-04-13T17:11:40.089Z" }, + { url = "https://files.pythonhosted.org/packages/6b/fd/5390ec4f49100f3ecb9968a392f9e6d039f1e3fe0ecd28443716ff01e589/fastar-0.11.0-cp314-cp314t-win_arm64.whl", hash = "sha256:76c1359314355eafbc6989f20fb1ad565a3d10200117923b9da765a17e2f6f11", size = 461049, upload-time = "2026-04-13T17:11:25.918Z" }, + { url = "https://files.pythonhosted.org/packages/cc/5c/9bbeffbf1905391446dd98aa520422ce7affde5c9a7c22d757cc5d7c1397/fastar-0.11.0-pp311-pypy311_pp73-macosx_10_12_x86_64.whl", hash = "sha256:1266d6a004f427b0d61bd6c7b544d84cc964691b2232c2f4d635a1b75f2f6d5e", size = 711644, upload-time = "2026-04-13T17:10:07.663Z" }, + { url = "https://files.pythonhosted.org/packages/7e/af/ae5cf39d4fb82d0c592705f5ec6db1b065be5265c151b108f86126ee8773/fastar-0.11.0-pp311-pypy311_pp73-macosx_11_0_arm64.whl", hash = "sha256:298a827ec04ade43733f6ca960d0faec38706aa1494175869ea7ea17f5bad5d3", size = 634371, upload-time = "2026-04-13T17:09:52.083Z" }, + { url = "https://files.pythonhosted.org/packages/7e/36/8d4569e26473c72ccb02d1c5df3ed710073f1c06eca09c26d52ea79fd815/fastar-0.11.0-pp311-pypy311_pp73-manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:8800e2387e463a0e5799416a1cbe72dd0fde7270a20e4bde684145e7878f6516", size = 870850, upload-time = "2026-04-13T17:09:21.439Z" }, + { url = "https://files.pythonhosted.org/packages/bf/46/724dc796e1756d3977970f820d30d59bb8cab8e3671b285f1d82ab513aec/fastar-0.11.0-pp311-pypy311_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:7496def0a2befd82d429cb004ef7ca831585cc887947bd6b9abb68a5ef852b0b", size = 764469, upload-time = "2026-04-13T17:08:05.638Z" }, + { url = "https://files.pythonhosted.org/packages/99/e3/74d6859e632e8fb9339a14f652fb9f800c2bd6aa53071e311c0be3fbab8b/fastar-0.11.0-pp311-pypy311_pp73-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:878eaf15463eb572e3538af7ca3a8534e5e279cf8196db902d24e5725c4af86e", size = 761375, upload-time = "2026-04-13T17:08:20.669Z" }, + { url = "https://files.pythonhosted.org/packages/a3/e7/cc70e2be5ef8731a7525552b1c35c1448cf9eae6a62cb3a56f12c1bf27ea/fastar-0.11.0-pp311-pypy311_pp73-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:0324ed1d1ef0186e1bbd843b17807d6d837d0906899d4c99378b02c5d86bdd9c", size = 928189, upload-time = "2026-04-13T17:08:35.663Z" }, + { url = "https://files.pythonhosted.org/packages/3c/33/c9a969e78dca323547276a6fee5f4f9588f7cd5ab45acec3778c67399589/fastar-0.11.0-pp311-pypy311_pp73-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:bdf9bd863205590beaf8ef6e66f315310196632180dceaf674985d01a876cac3", size = 820864, upload-time = "2026-04-13T17:09:06.366Z" }, + { url = "https://files.pythonhosted.org/packages/84/bd/6b9434b541fe55c125b5f2e017a565596a2d215aa09207e4555e4585064f/fastar-0.11.0-pp311-pypy311_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:59af8dbb683b24b90fb5b506de080faeab0a17a908e6c2a5d93a97260ed75d7b", size = 824060, upload-time = "2026-04-13T17:09:37.377Z" }, + { url = "https://files.pythonhosted.org/packages/24/8d/871d5f8cf4c6f13987119fb0a9ae8be131e34f2756c2524e9974adf33824/fastar-0.11.0-pp311-pypy311_pp73-manylinux_2_31_riscv64.whl", hash = "sha256:9f3df73a3c4292cfe15696cdf59cdb6c309ab59d30b34c733be13c6e32d9a264", size = 889217, upload-time = "2026-04-13T17:08:50.884Z" }, + { url = "https://files.pythonhosted.org/packages/d0/26/cca0fd2704f3ed20165e5613ed911549aef3aaf3b0b5b02fee0e8e23e6cc/fastar-0.11.0-pp311-pypy311_pp73-musllinux_1_2_aarch64.whl", hash = "sha256:aa3762cbb16e41a76b61f4a6914937a71aab3a7b6c2d82ca233bc686ebaf756b", size = 975418, upload-time = "2026-04-13T17:10:24.307Z" }, + { url = "https://files.pythonhosted.org/packages/99/94/8bbb0b13f5b6cbe2492f0b7cbba5103e6163976a3331466d010e781fa189/fastar-0.11.0-pp311-pypy311_pp73-musllinux_1_2_armv7l.whl", hash = "sha256:a8c7bc8ac74cb359bb546b199288c83236372d094b402e557c197e85527495cd", size = 1038492, upload-time = "2026-04-13T17:10:41.939Z" }, + { url = "https://files.pythonhosted.org/packages/ed/d3/5b7df222a30eac2822ffd00f82fd4c2ce84fba4b369d1e1a03732fd177fc/fastar-0.11.0-pp311-pypy311_pp73-musllinux_1_2_i686.whl", hash = "sha256:587cbd060a2699c5f66281081395bb4657b2b1e0eef5c206b1aabf740019d670", size = 1080210, upload-time = "2026-04-13T17:10:58.462Z" }, + { url = "https://files.pythonhosted.org/packages/ec/6d/56ef943ea524784598c035ccbd42e564e937da0438ae3f55f0e76cb95571/fastar-0.11.0-pp311-pypy311_pp73-musllinux_1_2_x86_64.whl", hash = "sha256:6a1c56957ac82408be37a3f63594bc83e0919e8760492a4475e542f9f1828778", size = 1034886, upload-time = "2026-04-13T17:11:15.617Z" }, ] [[package]] From 33aa27c7b79ceb3479706fb9736ebce79fff404a Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Fri, 24 Apr 2026 12:25:32 +0000 Subject: [PATCH 021/462] =?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 ecac88133..cee54caba 100644 --- a/docs/en/docs/release-notes.md +++ b/docs/en/docs/release-notes.md @@ -9,6 +9,7 @@ hide: ### Internal +* ⬆ Bump fastar from 0.9.0 to 0.11.0. PR [#15419](https://github.com/fastapi/fastapi/pull/15419) by [@dependabot[bot]](https://github.com/apps/dependabot). * ⬆ Bump astral-sh/setup-uv from 7.6.0 to 8.1.0. PR [#15415](https://github.com/fastapi/fastapi/pull/15415) by [@dependabot[bot]](https://github.com/apps/dependabot). ## 0.136.1 (2026-04-23) From 4216f9951558a825d33891029a02df06fcc7d53c Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 24 Apr 2026 14:37:27 +0200 Subject: [PATCH 022/462] =?UTF-8?q?=E2=AC=86=20Bump=20prek=20from=200.3.2?= =?UTF-8?q?=20to=200.3.9=20(#15418)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- uv.lock | 40 ++++++++++++++++++++-------------------- 1 file changed, 20 insertions(+), 20 deletions(-) diff --git a/uv.lock b/uv.lock index b5a3a086a..86c0b882f 100644 --- a/uv.lock +++ b/uv.lock @@ -3515,26 +3515,26 @@ wheels = [ [[package]] name = "prek" -version = "0.3.2" -source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/d3/f5/ee52def928dd1355c20bcfcf765e1e61434635c33f3075e848e7b83a157b/prek-0.3.2.tar.gz", hash = "sha256:dce0074ff1a21290748ca567b4bda7553ee305a8c7b14d737e6c58364a499364", size = 334229, upload-time = "2026-02-06T13:49:47.539Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/76/69/70a5fc881290a63910494df2677c0fb241d27cfaa435bbcd0de5cd2e2443/prek-0.3.2-py3-none-linux_armv6l.whl", hash = "sha256:4f352f9c3fc98aeed4c8b2ec4dbf16fc386e45eea163c44d67e5571489bd8e6f", size = 4614960, upload-time = "2026-02-06T13:50:05.818Z" }, - { url = "https://files.pythonhosted.org/packages/c0/15/a82d5d32a2207ccae5d86ea9e44f2b93531ed000faf83a253e8d1108e026/prek-0.3.2-py3-none-macosx_10_12_x86_64.whl", hash = "sha256:4a000cfbc3a6ec7d424f8be3c3e69ccd595448197f92daac8652382d0acc2593", size = 4622889, upload-time = "2026-02-06T13:49:53.662Z" }, - { url = "https://files.pythonhosted.org/packages/89/75/ea833b58a12741397017baef9b66a6e443bfa8286ecbd645d14111446280/prek-0.3.2-py3-none-macosx_11_0_arm64.whl", hash = "sha256:5436bdc2702cbd7bcf9e355564ae66f8131211e65fefae54665a94a07c3d450a", size = 4239653, upload-time = "2026-02-06T13:50:02.88Z" }, - { url = "https://files.pythonhosted.org/packages/10/b4/d9c3885987afac6e20df4cb7db14e3b0d5a08a77ae4916488254ebac4d0b/prek-0.3.2-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.musllinux_1_1_aarch64.whl", hash = "sha256:0161b5f584f9e7f416d6cf40a17b98f17953050ff8d8350ec60f20fe966b86b6", size = 4595101, upload-time = "2026-02-06T13:49:49.813Z" }, - { url = "https://files.pythonhosted.org/packages/21/a6/1a06473ed83dbc898de22838abdb13954e2583ce229f857f61828384634c/prek-0.3.2-py3-none-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:4e641e8533bca38797eebb49aa89ed0e8db0e61225943b27008c257e3af4d631", size = 4521978, upload-time = "2026-02-06T13:49:41.266Z" }, - { url = "https://files.pythonhosted.org/packages/0c/5e/c38390d5612e6d86b32151c1d2fdab74a57913473193591f0eb00c894c21/prek-0.3.2-py3-none-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:cfca1810d49d3f9ef37599c958c4e716bc19a1d78a7e88cbdcb332e0b008994f", size = 4829108, upload-time = "2026-02-06T13:49:44.598Z" }, - { url = "https://files.pythonhosted.org/packages/80/a6/cecce2ab623747ff65ed990bb0d95fa38449ee19b348234862acf9392fff/prek-0.3.2-py3-none-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:e5d69d754299a95a85dc20196f633232f306bee7e7c8cba61791f49ce70404ec", size = 5357520, upload-time = "2026-02-06T13:49:48.512Z" }, - { url = "https://files.pythonhosted.org/packages/a5/18/d6bcb29501514023c76d55d5cd03bdbc037737c8de8b6bc41cdebfb1682c/prek-0.3.2-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:539dcb90ad9b20837968539855df6a29493b328a1ae87641560768eed4f313b0", size = 4852635, upload-time = "2026-02-06T13:49:58.347Z" }, - { url = "https://files.pythonhosted.org/packages/1b/0a/ae46f34ba27ba87aea5c9ad4ac9cd3e07e014fd5079ae079c84198f62118/prek-0.3.2-py3-none-manylinux_2_28_aarch64.whl", hash = "sha256:1998db3d0cbe243984736c82232be51318f9192e2433919a6b1c5790f600b5fd", size = 4599484, upload-time = "2026-02-06T13:49:43.296Z" }, - { url = "https://files.pythonhosted.org/packages/1a/a9/73bfb5b3f7c3583f9b0d431924873928705cdef6abb3d0461c37254a681b/prek-0.3.2-py3-none-manylinux_2_31_riscv64.whl", hash = "sha256:07ab237a5415a3e8c0db54de9d63899bcd947624bdd8820d26f12e65f8d19eb7", size = 4657694, upload-time = "2026-02-06T13:50:01.074Z" }, - { url = "https://files.pythonhosted.org/packages/a7/bc/0994bc176e1a80110fad3babce2c98b0ac4007630774c9e18fc200a34781/prek-0.3.2-py3-none-musllinux_1_1_armv7l.whl", hash = "sha256:0ced19701d69c14a08125f14a5dd03945982edf59e793c73a95caf4697a7ac30", size = 4509337, upload-time = "2026-02-06T13:49:54.891Z" }, - { url = "https://files.pythonhosted.org/packages/f9/13/e73f85f65ba8f626468e5d1694ab3763111513da08e0074517f40238c061/prek-0.3.2-py3-none-musllinux_1_1_i686.whl", hash = "sha256:ffb28189f976fa111e770ee94e4f298add307714568fb7d610c8a7095cb1ce59", size = 4697350, upload-time = "2026-02-06T13:50:04.526Z" }, - { url = "https://files.pythonhosted.org/packages/14/47/98c46dcd580305b9960252a4eb966f1a7b1035c55c363f378d85662ba400/prek-0.3.2-py3-none-musllinux_1_1_x86_64.whl", hash = "sha256:f63134b3eea14421789a7335d86f99aee277cb520427196f2923b9260c60e5c5", size = 4955860, upload-time = "2026-02-06T13:49:56.581Z" }, - { url = "https://files.pythonhosted.org/packages/73/42/1bb4bba3ff47897df11e9dfd774027cdfa135482c961a54e079af0faf45a/prek-0.3.2-py3-none-win32.whl", hash = "sha256:58c806bd1344becd480ef5a5ba348846cc000af0e1fbe854fef91181a2e06461", size = 4267619, upload-time = "2026-02-06T13:49:39.503Z" }, - { url = "https://files.pythonhosted.org/packages/97/11/6665f47a7c350d83de17403c90bbf7a762ef50876ece456a86f64f46fbfb/prek-0.3.2-py3-none-win_amd64.whl", hash = "sha256:70114b48e9eb8048b2c11b4c7715ce618529c6af71acc84dd8877871a2ef71a6", size = 4624324, upload-time = "2026-02-06T13:49:45.922Z" }, - { url = "https://files.pythonhosted.org/packages/22/e7/740997ca82574d03426f897fd88afe3fc8a7306b8c7ea342a8bc1c538488/prek-0.3.2-py3-none-win_arm64.whl", hash = "sha256:9144d176d0daa2469a25c303ef6f6fa95a8df015eb275232f5cb53551ecefef0", size = 4336008, upload-time = "2026-02-06T13:49:52.27Z" }, +version = "0.3.9" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/15/ff/5b7a2a9c4fa3dd2ffc8b13a9ec22aa550deda5b39ab273f8e02863b12642/prek-0.3.9.tar.gz", hash = "sha256:f82b92d81f42f1f90a47f5fbbf492373e25ef1f790080215b2722dd6da66510e", size = 423801, upload-time = "2026-04-13T12:30:38.191Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/3c/08/c11a6b7834b461223763b6b1552f32c9199393685d52d555de621e900ee7/prek-0.3.9-py3-none-linux_armv6l.whl", hash = "sha256:3ed793d51bfaa27bddb64d525d7acb77a7c8644f549412d82252e3eb0b88aad8", size = 5337784, upload-time = "2026-04-13T12:30:46.044Z" }, + { url = "https://files.pythonhosted.org/packages/15/d9/974b02832a645c6411069c713e3191ce807f9962006da108e4727efd2fa1/prek-0.3.9-py3-none-macosx_10_12_x86_64.whl", hash = "sha256:399c58400c0bd0b82a93a3c09dc1bfd88d8d0cfb242d414d2ed247187b06ead1", size = 5713864, upload-time = "2026-04-13T12:30:27.007Z" }, + { url = "https://files.pythonhosted.org/packages/40/e1/4ed14bef15eb30039a75177b0807ac007095a5a110284706ccf900a8d512/prek-0.3.9-py3-none-macosx_11_0_arm64.whl", hash = "sha256:e2ea1ffb124e92f081b8e2ca5b5a623a733efb3be0c5b1f4b7ffe2ee17d1f20c", size = 5290437, upload-time = "2026-04-13T12:30:30.658Z" }, + { url = "https://files.pythonhosted.org/packages/67/80/d5c3015e9da161dede566bfeef41f098f92470613157daa4f7377ab08d58/prek-0.3.9-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.musllinux_1_1_aarch64.whl", hash = "sha256:aaf639f95b7301639298311d8d44aad0d0b4864e9736083ad3c71ce9765d37ab", size = 5536208, upload-time = "2026-04-13T12:30:47.964Z" }, + { url = "https://files.pythonhosted.org/packages/c8/54/8cdc5eb1018437d7828740defd322e7a96459c02fc8961160c4120325313/prek-0.3.9-py3-none-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:ff104863b187fa443ea8451ca55d51e2c6e94f99f00d88784b5c3c4c623f1ebe", size = 5251785, upload-time = "2026-04-13T12:30:39.78Z" }, + { url = "https://files.pythonhosted.org/packages/bd/e2/a5fc35a0fd3167224a000ca1b6235ecbdea0ac77e24af5979a75b0e6b5a4/prek-0.3.9-py3-none-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:039ecaf87c63a3e67cca645ebd5bc5eb6aafa6c9d929e9a27b2921e7849d7ef9", size = 5668548, upload-time = "2026-04-13T12:30:24.914Z" }, + { url = "https://files.pythonhosted.org/packages/09/e8/a189ee79f401c259f66f8af587f899d4d5bfb04e0ca371bfd01e49871007/prek-0.3.9-py3-none-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:3bde2a3d045705095983c7f78ba04f72a7565fe1c2b4e85f5628502a254754ff", size = 6660927, upload-time = "2026-04-13T12:30:44.495Z" }, + { url = "https://files.pythonhosted.org/packages/a4/5a/54117316e98ff62a14911ad1488a3a0945530242a2ce3e92f7a40b6ccc02/prek-0.3.9-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:28a0960a21543563e2c8e19aaad176cc8423a87aac3c914d0f313030d7a9244a", size = 5932244, upload-time = "2026-04-13T12:30:49.532Z" }, + { url = "https://files.pythonhosted.org/packages/a7/f9/e88d4361f59be7adeeb3a8a3819d69d286d86fe6f7606840af6734362675/prek-0.3.9-py3-none-manylinux_2_28_aarch64.whl", hash = "sha256:0dfb5d5171d7523271909246ee306b4dc3d5b63752e7dd7c7e8a8908fc9490d1", size = 5542139, upload-time = "2026-04-13T12:30:41.266Z" }, + { url = "https://files.pythonhosted.org/packages/11/1f/204837115087bb8d063bda754a7fe975428c5d5b6548c30dd749f8ab85d4/prek-0.3.9-py3-none-manylinux_2_31_riscv64.whl", hash = "sha256:82b791bd36c1430c84d3ae7220a85152babc7eaf00f70adcb961bd594e756ba3", size = 5392519, upload-time = "2026-04-13T12:30:32.603Z" }, + { url = "https://files.pythonhosted.org/packages/bd/00/de57b5795e670b6d38e7eda6d9ac6fd6d757ca22f725e5054b042104cd53/prek-0.3.9-py3-none-musllinux_1_1_armv7l.whl", hash = "sha256:6eac6d2f736b041118f053a1487abed468a70dd85a8688eaf87bb42d3dcecf20", size = 5222780, upload-time = "2026-04-13T12:30:36.576Z" }, + { url = "https://files.pythonhosted.org/packages/f5/14/0bc055c305d92980b151f2ec00c14d28fe94c6d51180ca07fded28771cbf/prek-0.3.9-py3-none-musllinux_1_1_i686.whl", hash = "sha256:5517e46e761367a3759b3168eabc120840ffbca9dfbc53187167298a98f87dc4", size = 5524310, upload-time = "2026-04-13T12:30:34.469Z" }, + { url = "https://files.pythonhosted.org/packages/b9/d1/eebc2b69be0de36cd84adbe0a0710f4deb468a90e30525be027d6db02d54/prek-0.3.9-py3-none-musllinux_1_1_x86_64.whl", hash = "sha256:92024778cf78683ca32687bb249ab6a7d5c33887b5ee1d1a9f6d0c14228f4cf3", size = 6043751, upload-time = "2026-04-13T12:30:29.101Z" }, + { url = "https://files.pythonhosted.org/packages/46/cb/be98c04e702cbc0b0328cd745ff4634ace69ad5a84461bde36f88a7be873/prek-0.3.9-py3-none-win32.whl", hash = "sha256:7f89c55e5f480f5d073769e319924ad69d4bf9f98c5cb46a83082e26e634c958", size = 5045940, upload-time = "2026-04-13T12:30:42.882Z" }, + { url = "https://files.pythonhosted.org/packages/a6/b6/b51771d69f6282e34edeb73f23d956da34f2cabbb5ba16ba175cc0a056f9/prek-0.3.9-py3-none-win_amd64.whl", hash = "sha256:7722f3372eaa83b147e70a43cb7b9fe2128c13d0c78d8a1cdbf2a8ec2ee071eb", size = 5435204, upload-time = "2026-04-13T12:30:51.482Z" }, + { url = "https://files.pythonhosted.org/packages/30/8a/f8a87c15b095460eccd67c8d89a086b7a37aac8d363f89544b8ce6ec653d/prek-0.3.9-py3-none-win_arm64.whl", hash = "sha256:0bced6278d6cc8a4b46048979e36bc9da034611dc8facd77ab123177b833a929", size = 5279552, upload-time = "2026-04-13T12:30:53.011Z" }, ] [[package]] From 5c89b88c9f535a4a27663b706a6cf0fd3fc3db15 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Fri, 24 Apr 2026 12:37:51 +0000 Subject: [PATCH 023/462] =?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 cee54caba..6af178db3 100644 --- a/docs/en/docs/release-notes.md +++ b/docs/en/docs/release-notes.md @@ -9,6 +9,7 @@ hide: ### Internal +* ⬆ Bump prek from 0.3.2 to 0.3.9. PR [#15418](https://github.com/fastapi/fastapi/pull/15418) by [@dependabot[bot]](https://github.com/apps/dependabot). * ⬆ Bump fastar from 0.9.0 to 0.11.0. PR [#15419](https://github.com/fastapi/fastapi/pull/15419) by [@dependabot[bot]](https://github.com/apps/dependabot). * ⬆ Bump astral-sh/setup-uv from 7.6.0 to 8.1.0. PR [#15415](https://github.com/fastapi/fastapi/pull/15415) by [@dependabot[bot]](https://github.com/apps/dependabot). From f43cc1c0efae89d2c44579847c478d8b6ba11c41 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 24 Apr 2026 15:06:10 +0200 Subject: [PATCH 024/462] =?UTF-8?q?=E2=AC=86=20Bump=20pydantic-ai=20from?= =?UTF-8?q?=201.63.0=20to=201.83.0=20(#15417)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- uv.lock | 142 +++++++++++++++++++++++++++++--------------------------- 1 file changed, 74 insertions(+), 68 deletions(-) diff --git a/uv.lock b/uv.lock index 86c0b882f..98e8ae153 100644 --- a/uv.lock +++ b/uv.lock @@ -432,30 +432,30 @@ wheels = [ [[package]] name = "boto3" -version = "1.42.43" +version = "1.42.94" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "botocore" }, { name = "jmespath" }, { name = "s3transfer" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/c2/47/29afb754de7df0a0ebceaa9d83e209136ef7b62744259a6c09862fef4765/boto3-1.42.43.tar.gz", hash = "sha256:01fc5501209b23849fb30b01c6c086583ac91c40842a76083662fbfb84a82491", size = 112844, upload-time = "2026-02-05T20:31:44.974Z" } +sdist = { url = "https://files.pythonhosted.org/packages/6a/6a/95302333208830de932ad1d0b69599ee13e936349a44981fb72632507861/boto3-1.42.94.tar.gz", hash = "sha256:5b6056a661c19e974aaea3cb97690ddbe30d10c31e4f887df3bff06574f34510", size = 113211, upload-time = "2026-04-22T20:36:19.167Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/80/92/584447b14ae70f57f133a4bc64393902a72a3087486a7c09ce1bab25263c/boto3-1.42.43-py3-none-any.whl", hash = "sha256:44ddcaa37c350333c5a4799f533e786a595a97f1ee2fd7fc3e394cdebeb15e44", size = 140603, upload-time = "2026-02-05T20:31:43.698Z" }, + { url = "https://files.pythonhosted.org/packages/c4/6f/4e175604f3168befcb413c95bf45eada67d12042f92f76a9305d6a817ea9/boto3-1.42.94-py3-none-any.whl", hash = "sha256:56d53bce75629cc7c78a32da8b62de74cee3e2a3d54a2b60ba1a65f9f1b129da", size = 140555, upload-time = "2026-04-22T20:36:16.182Z" }, ] [[package]] name = "botocore" -version = "1.42.43" +version = "1.42.94" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "jmespath" }, { name = "python-dateutil" }, { name = "urllib3" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/af/d6/def916ad1d13de5d511074afcde538a958e2e8a7c7020fb698d1f392f63b/botocore-1.42.43.tar.gz", hash = "sha256:41d04ead0b0862eec21f841811fb5764fe370a2df9b319e0d5297325c50fba1b", size = 14934077, upload-time = "2026-02-05T20:31:35.15Z" } +sdist = { url = "https://files.pythonhosted.org/packages/b7/90/1a4d0e81b325d38e37f81d907ceacac3b8f509ad38b495bb95086ecb609d/botocore-1.42.94.tar.gz", hash = "sha256:41c6b3b11b073221a41f52b222ba387be34459fb77cdc506e8b74cdaf24bdcce", size = 15260901, upload-time = "2026-04-22T20:36:00.853Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/4c/a8/95656f91b795eb47b73a00d36c51c7a5729eafa632c7348caa068ff63e50/botocore-1.42.43-py3-none-any.whl", hash = "sha256:1c0e30f62e274978ac3bcab253e3a859febea634b72b5e343589db7d17f83cd6", size = 14610179, upload-time = "2026-02-05T20:31:32.727Z" }, + { url = "https://files.pythonhosted.org/packages/61/73/313af9ee02ac0155247bcf3f04fcf54fcae2e33250bb437528c18aeefd81/botocore-1.42.94-py3-none-any.whl", hash = "sha256:a2143742132ed0f6cdb90204d667b89d0301068b1045e8bc099efa267bf1b348", size = 14942938, upload-time = "2026-04-22T20:35:55.663Z" }, ] [[package]] @@ -1568,12 +1568,13 @@ wheels = [ [[package]] name = "fastmcp" -version = "3.2.0" +version = "3.2.4" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "authlib" }, { name = "cyclopts" }, { name = "exceptiongroup" }, + { name = "griffelib" }, { name = "httpx" }, { name = "jsonref" }, { name = "jsonschema-path" }, @@ -1593,9 +1594,9 @@ dependencies = [ { name = "watchfiles" }, { name = "websockets" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/d0/32/4f1b2cfd7b50db89114949f90158b1dcc2c92a1917b9f57c0ff24e47a2f4/fastmcp-3.2.0.tar.gz", hash = "sha256:d4830b8ffc3592d3d9c76dc0f398904cf41f04910e41a0de38cc1004e0903bef", size = 26318581, upload-time = "2026-03-30T20:25:37.692Z" } +sdist = { url = "https://files.pythonhosted.org/packages/9c/13/29544fbc6dfe45ea38046af0067311e0bad7acc7d1f2ad38bb08f2409fe2/fastmcp-3.2.4.tar.gz", hash = "sha256:083ecb75b44a4169e7fc0f632f94b781bdb0ff877c6b35b9877cbb566fd4d4d1", size = 28746127, upload-time = "2026-04-14T01:42:24.174Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/4f/67/684fa2d2de1e7504549d4ca457b4f854ccec3cd3be03bd86b33b599fbf58/fastmcp-3.2.0-py3-none-any.whl", hash = "sha256:e71aba3df16f86f546a4a9e513261d3233bcc92bef0dfa647bac3fa33623f681", size = 705550, upload-time = "2026-03-30T20:25:35.499Z" }, + { url = "https://files.pythonhosted.org/packages/cf/76/b310d52fa0e30d39bd937eb58ec2c1f1ea1b5f519f0575e9dd9612f01deb/fastmcp-3.2.4-py3-none-any.whl", hash = "sha256:e6c9c429171041455e47ab94bb3f83c4657622a0ec28922f6940053959bd58a9", size = 728599, upload-time = "2026-04-14T01:42:26.85Z" }, ] [[package]] @@ -1805,16 +1806,15 @@ wheels = [ [[package]] name = "google-auth" -version = "2.48.0" +version = "2.49.2" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "cryptography" }, { name = "pyasn1-modules" }, - { name = "rsa" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/0c/41/242044323fbd746615884b1c16639749e73665b718209946ebad7ba8a813/google_auth-2.48.0.tar.gz", hash = "sha256:4f7e706b0cd3208a3d940a19a822c37a476ddba5450156c3e6624a71f7c841ce", size = 326522, upload-time = "2026-01-26T19:22:47.157Z" } +sdist = { url = "https://files.pythonhosted.org/packages/c6/fc/e925290a1ad95c975c459e2df070fac2b90954e13a0370ac505dff78cb99/google_auth-2.49.2.tar.gz", hash = "sha256:c1ae38500e73065dcae57355adb6278cf8b5c8e391994ae9cbadbcb9631ab409", size = 333958, upload-time = "2026-04-10T00:41:21.888Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/83/1d/d6466de3a5249d35e832a52834115ca9d1d0de6abc22065f049707516d47/google_auth-2.48.0-py3-none-any.whl", hash = "sha256:2e2a537873d449434252a9632c28bfc268b0adb1e53f9fb62afc5333a975903f", size = 236499, upload-time = "2026-01-26T19:22:45.099Z" }, + { url = "https://files.pythonhosted.org/packages/73/76/d241a5c927433420507215df6cac1b1fa4ac0ba7a794df42a84326c68da8/google_auth-2.49.2-py3-none-any.whl", hash = "sha256:c2720924dfc82dedb962c9f52cabb2ab16714fd0a6a707e40561d217574ed6d5", size = 240638, upload-time = "2026-04-10T00:41:14.501Z" }, ] [package.optional-dependencies] @@ -1824,7 +1824,7 @@ requests = [ [[package]] name = "google-genai" -version = "1.62.0" +version = "1.73.1" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "anyio" }, @@ -1838,9 +1838,9 @@ dependencies = [ { name = "typing-extensions" }, { name = "websockets" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/94/4c/71b32b5c8db420cf2fd0d5ef8a672adbde97d85e5d44a0b4fca712264ef1/google_genai-1.62.0.tar.gz", hash = "sha256:709468a14c739a080bc240a4f3191df597bf64485b1ca3728e0fb67517774c18", size = 490888, upload-time = "2026-02-04T22:48:41.989Z" } +sdist = { url = "https://files.pythonhosted.org/packages/3d/d8/40f5f107e5a2976bbac52d421f04d14fc221b55a8f05e66be44b2f739fe6/google_genai-1.73.1.tar.gz", hash = "sha256:b637e3a3b9e2eccc46f27136d470165803de84eca52abfed2e7352081a4d5a15", size = 530998, upload-time = "2026-04-14T21:06:19.153Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/09/5f/4645d8a28c6e431d0dd6011003a852563f3da7037d36af53154925b099fd/google_genai-1.62.0-py3-none-any.whl", hash = "sha256:4c3daeff3d05fafee4b9a1a31f9c07f01bc22051081aa58b4d61f58d16d1bcc0", size = 724166, upload-time = "2026-02-04T22:48:39.956Z" }, + { url = "https://files.pythonhosted.org/packages/65/af/508e0528015240d710c6763f7c89ff44fab9a94a80b4377e265d692cbfd6/google_genai-1.73.1-py3-none-any.whl", hash = "sha256:af2d2287d25e42a187de19811ef33beb2e347c7e2bdb4dc8c467d78254e43a2c", size = 783595, upload-time = "2026-04-14T21:06:17.464Z" }, ] [[package]] @@ -2231,15 +2231,6 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/f8/c7/8b54418a67ef2b10771a82d03e2b6b69016e5bfb0527fd491884a890e1d6/inline_snapshot-0.32.6-py3-none-any.whl", hash = "sha256:1f8fb6353dff0aa824e00eecf17d53d7d08d36f2167752756ec8ea73f39d7e15", size = 85157, upload-time = "2026-04-10T05:46:21.402Z" }, ] -[[package]] -name = "invoke" -version = "2.2.1" -source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/de/bd/b461d3424a24c80490313fd77feeb666ca4f6a28c7e72713e3d9095719b4/invoke-2.2.1.tar.gz", hash = "sha256:515bf49b4a48932b79b024590348da22f39c4942dff991ad1fb8b8baea1be707", size = 304762, upload-time = "2025-10-11T00:36:35.172Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/32/4b/b99e37f88336009971405cbb7630610322ed6fbfa31e1d7ab3fbf3049a2d/invoke-2.2.1-py3-none-any.whl", hash = "sha256:2413bc441b376e5cd3f55bb5d364f973ad8bdd7bf87e53c79de3c11bf3feecc8", size = 160287, upload-time = "2025-10-11T00:36:33.703Z" }, -] - [[package]] name = "itsdangerous" version = "2.2.0" @@ -2418,6 +2409,15 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/14/2f/967ba146e6d58cf6a652da73885f52fc68001525b4197effc174321d70b4/jmespath-1.1.0-py3-none-any.whl", hash = "sha256:a5663118de4908c91729bea0acadca56526eb2698e83de10cd116ae0f4e97c64", size = 20419, upload-time = "2026-01-22T16:35:24.919Z" }, ] +[[package]] +name = "jsonpath-python" +version = "1.1.5" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/2d/db/2f4ecc24da35c6142b39c353d5b7c16eef955cc94b35a48d3fa47996d7c3/jsonpath_python-1.1.5.tar.gz", hash = "sha256:ceea2efd9e56add09330a2c9631ea3d55297b9619348c1055e5bfb9cb0b8c538", size = 87352, upload-time = "2026-03-17T06:16:40.597Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/28/50/1a313fb700526b134c71eb8a225d8b83be0385dbb0204337b4379c698cef/jsonpath_python-1.1.5-py3-none-any.whl", hash = "sha256:a60315404d70a65e76c9a782c84e50600480221d94a58af47b7b4d437351cb4b", size = 14090, upload-time = "2026-03-17T06:16:39.152Z" }, +] + [[package]] name = "jsonref" version = "1.1.0" @@ -2782,20 +2782,21 @@ wheels = [ [[package]] name = "mistralai" -version = "1.9.11" +version = "2.4.1" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "eval-type-backport" }, { name = "httpx" }, - { name = "invoke" }, + { name = "jsonpath-python" }, + { name = "opentelemetry-api" }, + { name = "opentelemetry-semantic-conventions" }, { name = "pydantic" }, { name = "python-dateutil" }, - { name = "pyyaml" }, { name = "typing-inspection" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/5a/8d/d8b7af67a966b6f227024e1cb7287fc19901a434f87a5a391dcfe635d338/mistralai-1.9.11.tar.gz", hash = "sha256:3df9e403c31a756ec79e78df25ee73cea3eb15f86693773e16b16adaf59c9b8a", size = 208051, upload-time = "2025-10-02T15:53:40.473Z" } +sdist = { url = "https://files.pythonhosted.org/packages/88/e2/fb226b81fdfba702a59ad50635fd9e72d6321cb92b2b4e76adfef7fe1903/mistralai-2.4.1.tar.gz", hash = "sha256:9aad8270b3085e84a1a88b07a7824aa6b97ee8470baee1a57f23a3f2b17b286c", size = 413448, upload-time = "2026-04-21T13:44:59.563Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/fe/76/4ce12563aea5a76016f8643eff30ab731e6656c845e9e4d090ef10c7b925/mistralai-1.9.11-py3-none-any.whl", hash = "sha256:7a3dc2b8ef3fceaa3582220234261b5c4e3e03a972563b07afa150e44a25a6d3", size = 442796, upload-time = "2025-10-02T15:53:39.134Z" }, + { url = "https://files.pythonhosted.org/packages/0c/03/1ab3de0cb123c0b5e4df612bacce65a5ad4c4f322dcdf95db2786092ea6d/mistralai-2.4.1-py3-none-any.whl", hash = "sha256:a535ac7fafec368ce66e7ecd22380489ce04d8b1466a35a20905c45e020f660e", size = 975691, upload-time = "2026-04-21T13:44:57.586Z" }, ] [[package]] @@ -3167,19 +3168,19 @@ wheels = [ [[package]] name = "nexus-rpc" -version = "1.2.0" +version = "1.4.0" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "typing-extensions" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/06/50/95d7bc91f900da5e22662c82d9bf0f72a4b01f2a552708bf2f43807707a1/nexus_rpc-1.2.0.tar.gz", hash = "sha256:b4ddaffa4d3996aaeadf49b80dfcdfbca48fe4cb616defaf3b3c5c2c8fc61890", size = 74142, upload-time = "2025-11-17T19:17:06.798Z" } +sdist = { url = "https://files.pythonhosted.org/packages/35/d5/cd1ffb202b76ebc1b33c1332a3416e55a39929006982adc2b1eb069aaa9b/nexus_rpc-1.4.0.tar.gz", hash = "sha256:3b8b373d4865671789cc43623e3dc0bcbf192562e40e13727e17f1c149050fba", size = 82367, upload-time = "2026-02-25T22:01:34.053Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/13/04/eaac430d0e6bf21265ae989427d37e94be5e41dc216879f1fbb6c5339942/nexus_rpc-1.2.0-py3-none-any.whl", hash = "sha256:977876f3af811ad1a09b2961d3d1ac9233bda43ff0febbb0c9906483b9d9f8a3", size = 28166, upload-time = "2025-11-17T19:17:05.64Z" }, + { url = "https://files.pythonhosted.org/packages/11/52/6327a5f4fda01207205038a106a99848a41c83e933cd23ea2cab3d2ebc6c/nexus_rpc-1.4.0-py3-none-any.whl", hash = "sha256:14c953d3519113f8ccec533a9efdb6b10c28afef75d11cdd6d422640c40b3a49", size = 29645, upload-time = "2026-02-25T22:01:33.122Z" }, ] [[package]] name = "openai" -version = "2.17.0" +version = "2.32.0" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "anyio" }, @@ -3191,9 +3192,9 @@ dependencies = [ { name = "tqdm" }, { name = "typing-extensions" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/9c/a2/677f22c4b487effb8a09439fb6134034b5f0a39ca27df8b95fac23a93720/openai-2.17.0.tar.gz", hash = "sha256:47224b74bd20f30c6b0a6a329505243cb2f26d5cf84d9f8d0825ff8b35e9c999", size = 631445, upload-time = "2026-02-05T16:27:40.953Z" } +sdist = { url = "https://files.pythonhosted.org/packages/ed/59/bdcc6b759b8c42dd73afaf5bf8f902c04b37987a5514dbc1c64dba390fef/openai-2.32.0.tar.gz", hash = "sha256:c54b27a9e4cb8d51f0dd94972ffd1a04437efeb259a9e60d8922b8bd26fe55e0", size = 693286, upload-time = "2026-04-15T22:28:19.434Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/44/97/284535aa75e6e84ab388248b5a323fc296b1f70530130dee37f7f4fbe856/openai-2.17.0-py3-none-any.whl", hash = "sha256:4f393fd886ca35e113aac7ff239bcd578b81d8f104f5aedc7d3693eb2af1d338", size = 1069524, upload-time = "2026-02-05T16:27:38.941Z" }, + { url = "https://files.pythonhosted.org/packages/1e/c1/d6e64ccd0536bf616556f0cad2b6d94a8125f508d25cfd814b1d2db4e2f1/openai-2.32.0-py3-none-any.whl", hash = "sha256:4dcc9badeb4bf54ad0d187453742f290226d30150890b7890711bda4f32f192f", size = 1162570, upload-time = "2026-04-15T22:28:17.714Z" }, ] [[package]] @@ -3797,19 +3798,19 @@ email = [ [[package]] name = "pydantic-ai" -version = "1.63.0" +version = "1.83.0" source = { registry = "https://pypi.org/simple" } dependencies = [ - { name = "pydantic-ai-slim", extra = ["ag-ui", "anthropic", "bedrock", "cli", "cohere", "evals", "fastmcp", "google", "groq", "huggingface", "logfire", "mcp", "mistral", "openai", "retries", "temporal", "ui", "vertexai", "xai"] }, + { name = "pydantic-ai-slim", extra = ["ag-ui", "anthropic", "bedrock", "cli", "cohere", "evals", "fastmcp", "google", "groq", "huggingface", "logfire", "mcp", "mistral", "openai", "retries", "spec", "temporal", "ui", "vertexai", "xai"] }, ] -sdist = { url = "https://files.pythonhosted.org/packages/15/13/f0a11d43e3e5b2705dd7ee687d4b0fa9b02a7cd23ea4170b92c0a79eb1d3/pydantic_ai-1.63.0.tar.gz", hash = "sha256:269665fbc947d1d4238296a697c12a60d8b1b2c82536f2af4be801f73e165a92", size = 12130, upload-time = "2026-02-23T17:56:34.489Z" } +sdist = { url = "https://files.pythonhosted.org/packages/c8/45/410dd1061e1dc0fed3f50d64defc942aa5426bc82cbb7d074057d20bd2f6/pydantic_ai-1.83.0.tar.gz", hash = "sha256:76a5f30e42734630577edc2b531fe3760bbaf3957c82cbde59a02d531fdd5a0d", size = 13026, upload-time = "2026-04-16T01:34:03.084Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/a6/4b/7cf9f5b2f8971a176be6ef218ffe6a30a5461bc2bfe914356881808ce159/pydantic_ai-1.63.0-py3-none-any.whl", hash = "sha256:586f63f391aa24e8b06bd0aeafbb1058de1d4f3bfe34c5f13d4f29a2d870afa5", size = 7229, upload-time = "2026-02-23T17:56:26.921Z" }, + { url = "https://files.pythonhosted.org/packages/0e/43/9a1cfe16afc92243c5cbd3b62149da2fd65d556bd7aaafbd4a6f57497cf4/pydantic_ai-1.83.0-py3-none-any.whl", hash = "sha256:2517569f392656efd30fca92a629657700df63e8678401849561a4aba68795a0", size = 7577, upload-time = "2026-04-16T01:33:54.217Z" }, ] [[package]] name = "pydantic-ai-slim" -version = "1.63.0" +version = "1.83.0" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "exceptiongroup", marker = "python_full_version < '3.11'" }, @@ -3821,9 +3822,9 @@ dependencies = [ { name = "pydantic-graph" }, { name = "typing-inspection" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/da/6d/2b5c0c60b42e6af49830f6a09b5d38fecdb1f20d9659152691eba95613b4/pydantic_ai_slim-1.63.0.tar.gz", hash = "sha256:9377afecdfe4bc17f5c9ed72c758e460703ac5876931aa2f18ace8ac0e69312a", size = 426862, upload-time = "2026-02-23T17:56:36.215Z" } +sdist = { url = "https://files.pythonhosted.org/packages/77/9e/82d16cbf428d41d22b396ab8102b9be946a6d8eb569dfbcefdfcfec36dec/pydantic_ai_slim-1.83.0.tar.gz", hash = "sha256:1293548de338c3d86e0dd64158292630adc7151ebfd3b8734df72dd188df0d14", size = 556556, upload-time = "2026-04-16T01:34:04.946Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/f2/ca/c4e39eec1cff5a294b64313a8a959b38d326819e0f0a41f48e61ce019a22/pydantic_ai_slim-1.63.0-py3-none-any.whl", hash = "sha256:ed393b0f871b748171f65bec5191c3025b5abb8a4fc616afee17eb9dc2dfa15d", size = 554190, upload-time = "2026-02-23T17:56:29.533Z" }, + { url = "https://files.pythonhosted.org/packages/51/87/037508c091cbea3f69d2834a37a5a8361c9c20ff702707ddbb3fc73f82c6/pydantic_ai_slim-1.83.0-py3-none-any.whl", hash = "sha256:a9283d4cdf3ce2d2f8eddb23b71cfbb2e3a40cfe71ca73ed13a1956cbabbd4ce", size = 711822, upload-time = "2026-04-16T01:33:56.985Z" }, ] [package.optional-dependencies] @@ -3841,6 +3842,7 @@ cli = [ { name = "argcomplete" }, { name = "prompt-toolkit" }, { name = "pyperclip" }, + { name = "pyyaml" }, { name = "rich" }, ] cohere = [ @@ -3877,6 +3879,10 @@ openai = [ retries = [ { name = "tenacity" }, ] +spec = [ + { name = "pydantic-handlebars" }, + { name = "pyyaml" }, +] temporal = [ { name = "temporalio" }, ] @@ -4011,7 +4017,7 @@ wheels = [ [[package]] name = "pydantic-evals" -version = "1.63.0" +version = "1.83.0" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "anyio" }, @@ -4021,9 +4027,9 @@ dependencies = [ { name = "pyyaml" }, { name = "rich" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/99/43/21b6ddf65b56f7401c344f98e4e6258a02d2868c8a52a8b79c0e0e701029/pydantic_evals-1.63.0.tar.gz", hash = "sha256:eed56a7192e07c8be8cf16e53bb2ef652b4f7f7b8527650ac45fde865a4ecf9d", size = 56365, upload-time = "2026-02-23T17:56:37.71Z" } +sdist = { url = "https://files.pythonhosted.org/packages/55/e1/abea282c390e72a718b8e232d1ff12963f83643234f89ff4b4ada057f5d0/pydantic_evals-1.83.0.tar.gz", hash = "sha256:cb58e1213d2470750517149ad7d21c7c96b88cb8a94159e8a1de3904586b25c9", size = 65793, upload-time = "2026-04-16T01:34:06.372Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/9b/f2/7174ad6abca2457e35a1b902ca4fa78aa8ee72e4ec2e9cd5dc8904014ec9/pydantic_evals-1.63.0-py3-none-any.whl", hash = "sha256:2e92a3af579a5670b2babf2044081d0ef99ab5a9ef141972616d71fd7e5bfd0e", size = 67279, upload-time = "2026-02-23T17:56:31.008Z" }, + { url = "https://files.pythonhosted.org/packages/3d/0d/6108ef3516de28cf20628511b7e7dfc0471e395eb30eb18ab8a2b15ab184/pydantic_evals-1.83.0-py3-none-any.whl", hash = "sha256:b748d0ab6c5355211c482488b07b5a71bab6ea7951235c59a5a7bebd22f37bdb", size = 77711, upload-time = "2026-04-16T01:33:58.939Z" }, ] [[package]] @@ -4041,7 +4047,7 @@ wheels = [ [[package]] name = "pydantic-graph" -version = "1.63.0" +version = "1.83.0" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "httpx" }, @@ -4049,9 +4055,21 @@ dependencies = [ { name = "pydantic" }, { name = "typing-inspection" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/7a/c8/aa3cb56552562b799f31e9de291c8bd88306308cfc9647d220dfff2bea18/pydantic_graph-1.63.0.tar.gz", hash = "sha256:5fd98bb22fa6181f0357a6ffad38a3214af12868bd46492d6456c5db434466b4", size = 58528, upload-time = "2026-02-23T17:56:39.118Z" } +sdist = { url = "https://files.pythonhosted.org/packages/29/9a/3f4afe8466d5950347e79d73242b70009efcfd8879e4b512fd1ee2fffbfa/pydantic_graph-1.83.0.tar.gz", hash = "sha256:f0e5f26247b0ac7d2424e9a25dbd8b0016542d21f13e2730cd4d97eb088cf728", size = 59241, upload-time = "2026-04-16T01:34:07.337Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/e4/2f/45f63c878c14742e3f7ee881d7f79ead7e57ce24518ce02e6cf0528bf51d/pydantic_graph-1.83.0-py3-none-any.whl", hash = "sha256:554534ab9ec88a4f239af303e27eaf72949f9e99c3b71a8050dec70f8838d692", size = 73064, upload-time = "2026-04-16T01:34:00.487Z" }, +] + +[[package]] +name = "pydantic-handlebars" +version = "0.1.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "pydantic" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/90/16/d41768bd3fd77e6250c20be11a3e68fee5fff07c3356455e6708f6a60f2a/pydantic_handlebars-0.1.0.tar.gz", hash = "sha256:1931c54946add1b5e3796c9bf6a005ed7662cef0109bb05c352f0b3d031a1260", size = 159826, upload-time = "2026-03-01T20:00:17.497Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/a4/1c/8dcae24c824dd2690fbe7375083b369b10ed1ad773e2b9d1122bb6c0fcdc/pydantic_graph-1.63.0-py3-none-any.whl", hash = "sha256:d9b7a387116f358d470c042b07aa08125cadfcfa8c08ef01769746a489aef0d5", size = 72353, upload-time = "2026-02-23T17:56:32.304Z" }, + { url = "https://files.pythonhosted.org/packages/99/5f/86b1630be61bdebf253c2f953a6c3f073ec21bb0725565ea3896802e1ca3/pydantic_handlebars-0.1.0-py3-none-any.whl", hash = "sha256:8a436fe8bc607295eb04bec58bd6e2c9498c9e069c557ff0b505e3d568c783bc", size = 40890, upload-time = "2026-03-01T20:00:16.106Z" }, ] [[package]] @@ -4910,18 +4928,6 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/d1/b7/b95708304cd49b7b6f82fdd039f1748b66ec2b21d6a45180910802f1abf1/rpds_py-0.30.0-pp311-pypy311_pp73-musllinux_1_2_x86_64.whl", hash = "sha256:ac37f9f516c51e5753f27dfdef11a88330f04de2d564be3991384b2f3535d02e", size = 562191, upload-time = "2025-11-30T20:24:36.853Z" }, ] -[[package]] -name = "rsa" -version = "4.9.1" -source = { registry = "https://pypi.org/simple" } -dependencies = [ - { name = "pyasn1" }, -] -sdist = { url = "https://files.pythonhosted.org/packages/da/8a/22b7beea3ee0d44b1916c0c1cb0ee3af23b700b6da9f04991899d0c555d4/rsa-4.9.1.tar.gz", hash = "sha256:e7bdbfdb5497da4c07dfd35530e1a902659db6ff241e39d9953cad06ebd0ae75", size = 29034, upload-time = "2025-04-16T09:51:18.218Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/64/8d/0133e4eb4beed9e425d9a98ed6e081a55d195481b7632472be1af08d2f6b/rsa-4.9.1-py3-none-any.whl", hash = "sha256:68635866661c6836b8d39430f97a996acbd61bfa49406748ea243539fe239762", size = 34696, upload-time = "2025-04-16T09:51:17.142Z" }, -] - [[package]] name = "ruff" version = "0.15.8" @@ -5168,7 +5174,7 @@ wheels = [ [[package]] name = "temporalio" -version = "1.20.0" +version = "1.26.0" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "nexus-rpc" }, @@ -5177,13 +5183,13 @@ dependencies = [ { name = "types-protobuf" }, { name = "typing-extensions" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/21/db/7d5118d28b0918888e1ec98f56f659fdb006351e06d95f30f4274962a76f/temporalio-1.20.0.tar.gz", hash = "sha256:5a6a85b7d298b7359bffa30025f7deac83c74ac095a4c6952fbf06c249a2a67c", size = 1850498, upload-time = "2025-11-25T21:25:20.225Z" } +sdist = { url = "https://files.pythonhosted.org/packages/ae/d4/fa21150a225393f87732ed6fef3cc9735d9e751edc6be415fe6e375105c6/temporalio-1.26.0.tar.gz", hash = "sha256:f4bfb35125e6f5e8c7f7ed1277c7354d812c6fac7ed5f8dbd50536cf289aaaa7", size = 2388994, upload-time = "2026-04-15T23:43:00.911Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/f4/1b/e69052aa6003eafe595529485d9c62d1382dd5e671108f1bddf544fb6032/temporalio-1.20.0-cp310-abi3-macosx_10_12_x86_64.whl", hash = "sha256:fba70314b4068f8b1994bddfa0e2ad742483f0ae714d2ef52e63013ccfd7042e", size = 12061638, upload-time = "2025-11-25T21:24:57.918Z" }, - { url = "https://files.pythonhosted.org/packages/ae/3b/3e8c67ed7f23bedfa231c6ac29a7a9c12b89881da7694732270f3ecd6b0c/temporalio-1.20.0-cp310-abi3-macosx_11_0_arm64.whl", hash = "sha256:ffc5bb6cabc6ae67f0bfba44de6a9c121603134ae18784a2ff3a7f230ad99080", size = 11562603, upload-time = "2025-11-25T21:25:01.721Z" }, - { url = "https://files.pythonhosted.org/packages/6d/be/ed0cc11702210522a79e09703267ebeca06eb45832b873a58de3ca76b9d0/temporalio-1.20.0-cp310-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a1e80c1e4cdf88fa8277177f563edc91466fe4dc13c0322f26e55c76b6a219e6", size = 11824016, upload-time = "2025-11-25T21:25:06.771Z" }, - { url = "https://files.pythonhosted.org/packages/9d/97/09c5cafabc80139d97338a2bdd8ec22e08817dfd2949ab3e5b73565006eb/temporalio-1.20.0-cp310-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ba92d909188930860c9d89ca6d7a753bc5a67e4e9eac6cea351477c967355eed", size = 12189521, upload-time = "2025-11-25T21:25:12.091Z" }, - { url = "https://files.pythonhosted.org/packages/11/23/5689c014a76aff3b744b3ee0d80815f63b1362637814f5fbb105244df09b/temporalio-1.20.0-cp310-abi3-win_amd64.whl", hash = "sha256:eacfd571b653e0a0f4aa6593f4d06fc628797898f0900d400e833a1f40cad03a", size = 12745027, upload-time = "2025-11-25T21:25:16.827Z" }, + { url = "https://files.pythonhosted.org/packages/1e/27/8c421c622d18cc8e034247d5d72b89e6456937344b5bec1de40abef3c085/temporalio-1.26.0-cp310-abi3-macosx_10_12_x86_64.whl", hash = "sha256:5489040c0cf621edeb36984199dd9e4fbd2b3a07d61a4f2a8da1f2cb9820ef26", size = 14221070, upload-time = "2026-04-15T23:42:26.21Z" }, + { url = "https://files.pythonhosted.org/packages/49/7c/d2b691d16ec5db87198c2e08dbfba58e286c096faee15753613a581abdce/temporalio-1.26.0-cp310-abi3-macosx_11_0_arm64.whl", hash = "sha256:b18dd85771509c19ef059a31908bcd4e6130d1f67037c4db519702f3f2ad6d4a", size = 13583991, upload-time = "2026-04-15T23:42:34.357Z" }, + { url = "https://files.pythonhosted.org/packages/05/ca/b8728451320ca9d8bb6e1680b9bd23767118f86d5b8644edf2304d533f1b/temporalio-1.26.0-cp310-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:46187d5f82ca2ae81f35ea5916a76db0e2f067210dc6b1852c3749475721946e", size = 13808036, upload-time = "2026-04-15T23:42:42.757Z" }, + { url = "https://files.pythonhosted.org/packages/cb/54/3113f5e0ac58655790abac64656373e06191b351d74bfb94692e81bd6784/temporalio-1.26.0-cp310-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:03300c3e5237443367ac61bb20bd726c656b3daa50310bdd436599d5bdc7cf97", size = 14336604, upload-time = "2026-04-15T23:42:49.851Z" }, + { url = "https://files.pythonhosted.org/packages/fd/9b/c50840a26af3587c0c8d9af04d9976743e22496996dc1a377efc75dcd316/temporalio-1.26.0-cp310-abi3-win_amd64.whl", hash = "sha256:1c4a0d82f0a3796cbf78864c799f8dca0b94cdaec68e7b8b224c859005686ec4", size = 14525849, upload-time = "2026-04-15T23:42:57.589Z" }, ] [[package]] From b44585589a04a095abf4bf0f1b4526b35ddaeca8 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Fri, 24 Apr 2026 13:06:36 +0000 Subject: [PATCH 025/462] =?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 6af178db3..ffff30400 100644 --- a/docs/en/docs/release-notes.md +++ b/docs/en/docs/release-notes.md @@ -9,6 +9,7 @@ hide: ### Internal +* ⬆ Bump pydantic-ai from 1.63.0 to 1.83.0. PR [#15417](https://github.com/fastapi/fastapi/pull/15417) by [@dependabot[bot]](https://github.com/apps/dependabot). * ⬆ Bump prek from 0.3.2 to 0.3.9. PR [#15418](https://github.com/fastapi/fastapi/pull/15418) by [@dependabot[bot]](https://github.com/apps/dependabot). * ⬆ Bump fastar from 0.9.0 to 0.11.0. PR [#15419](https://github.com/fastapi/fastapi/pull/15419) by [@dependabot[bot]](https://github.com/apps/dependabot). * ⬆ Bump astral-sh/setup-uv from 7.6.0 to 8.1.0. PR [#15415](https://github.com/fastapi/fastapi/pull/15415) by [@dependabot[bot]](https://github.com/apps/dependabot). From edc4c8ba33f1851d0ac589f34e8d7dcdc5b9b856 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 27 Apr 2026 22:11:27 +0200 Subject: [PATCH 026/462] =?UTF-8?q?=E2=AC=86=20Bump=20pydantic=20from=202.?= =?UTF-8?q?12.5=20to=202.13.2=20(#15439)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- uv.lock | 224 ++++++++++++++++++++++++++++---------------------------- 1 file changed, 111 insertions(+), 113 deletions(-) diff --git a/uv.lock b/uv.lock index 98e8ae153..2723f635d 100644 --- a/uv.lock +++ b/uv.lock @@ -3778,7 +3778,7 @@ wheels = [ [[package]] name = "pydantic" -version = "2.12.5" +version = "2.13.2" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "annotated-types" }, @@ -3786,9 +3786,9 @@ dependencies = [ { name = "typing-extensions" }, { name = "typing-inspection" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/69/44/36f1a6e523abc58ae5f928898e4aca2e0ea509b5aa6f6f392a5d882be928/pydantic-2.12.5.tar.gz", hash = "sha256:4d351024c75c0f085a9febbb665ce8c0c6ec5d30e903bdb6394b7ede26aebb49", size = 821591, upload-time = "2025-11-26T15:11:46.471Z" } +sdist = { url = "https://files.pythonhosted.org/packages/09/e5/06d23afac9973109d1e3c8ad38e1547a12e860610e327c05ee686827dc37/pydantic-2.13.2.tar.gz", hash = "sha256:b418196607e61081c3226dcd4f0672f2a194828abb9109e9cfb84026564df2d1", size = 843836, upload-time = "2026-04-17T09:31:59.636Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/5a/87/b70ad306ebb6f9b585f114d0ac2137d792b48be34d732d60e597c2f8465a/pydantic-2.12.5-py3-none-any.whl", hash = "sha256:e561593fccf61e8a20fc46dfc2dfe075b8be7d0188df33f221ad1f0139180f9d", size = 463580, upload-time = "2025-11-26T15:11:44.605Z" }, + { url = "https://files.pythonhosted.org/packages/77/ca/b45c378e6e8d0b90577288b533e04e95b7afd61bb1d51b6c263176435489/pydantic-2.13.2-py3-none-any.whl", hash = "sha256:a525087f4c03d7e7456a3de89b64cd693d2229933bb1068b9af6befd5563694e", size = 471947, upload-time = "2026-04-17T09:31:57.541Z" }, ] [package.optional-dependencies] @@ -3899,120 +3899,118 @@ xai = [ [[package]] name = "pydantic-core" -version = "2.41.5" +version = "2.46.2" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "typing-extensions" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/71/70/23b021c950c2addd24ec408e9ab05d59b035b39d97cdc1130e1bce647bb6/pydantic_core-2.41.5.tar.gz", hash = "sha256:08daa51ea16ad373ffd5e7606252cc32f07bc72b28284b6bc9c6df804816476e", size = 460952, upload-time = "2025-11-04T13:43:49.098Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/c6/90/32c9941e728d564b411d574d8ee0cf09b12ec978cb22b294995bae5549a5/pydantic_core-2.41.5-cp310-cp310-macosx_10_12_x86_64.whl", hash = "sha256:77b63866ca88d804225eaa4af3e664c5faf3568cea95360d21f4725ab6e07146", size = 2107298, upload-time = "2025-11-04T13:39:04.116Z" }, - { url = "https://files.pythonhosted.org/packages/fb/a8/61c96a77fe28993d9a6fb0f4127e05430a267b235a124545d79fea46dd65/pydantic_core-2.41.5-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:dfa8a0c812ac681395907e71e1274819dec685fec28273a28905df579ef137e2", size = 1901475, upload-time = "2025-11-04T13:39:06.055Z" }, - { url = "https://files.pythonhosted.org/packages/5d/b6/338abf60225acc18cdc08b4faef592d0310923d19a87fba1faf05af5346e/pydantic_core-2.41.5-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5921a4d3ca3aee735d9fd163808f5e8dd6c6972101e4adbda9a4667908849b97", size = 1918815, upload-time = "2025-11-04T13:39:10.41Z" }, - { url = "https://files.pythonhosted.org/packages/d1/1c/2ed0433e682983d8e8cba9c8d8ef274d4791ec6a6f24c58935b90e780e0a/pydantic_core-2.41.5-cp310-cp310-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:e25c479382d26a2a41b7ebea1043564a937db462816ea07afa8a44c0866d52f9", size = 2065567, upload-time = "2025-11-04T13:39:12.244Z" }, - { url = "https://files.pythonhosted.org/packages/b3/24/cf84974ee7d6eae06b9e63289b7b8f6549d416b5c199ca2d7ce13bbcf619/pydantic_core-2.41.5-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:f547144f2966e1e16ae626d8ce72b4cfa0caedc7fa28052001c94fb2fcaa1c52", size = 2230442, upload-time = "2025-11-04T13:39:13.962Z" }, - { url = "https://files.pythonhosted.org/packages/fd/21/4e287865504b3edc0136c89c9c09431be326168b1eb7841911cbc877a995/pydantic_core-2.41.5-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:6f52298fbd394f9ed112d56f3d11aabd0d5bd27beb3084cc3d8ad069483b8941", size = 2350956, upload-time = "2025-11-04T13:39:15.889Z" }, - { url = "https://files.pythonhosted.org/packages/a8/76/7727ef2ffa4b62fcab916686a68a0426b9b790139720e1934e8ba797e238/pydantic_core-2.41.5-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:100baa204bb412b74fe285fb0f3a385256dad1d1879f0a5cb1499ed2e83d132a", size = 2068253, upload-time = "2025-11-04T13:39:17.403Z" }, - { url = "https://files.pythonhosted.org/packages/d5/8c/a4abfc79604bcb4c748e18975c44f94f756f08fb04218d5cb87eb0d3a63e/pydantic_core-2.41.5-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:05a2c8852530ad2812cb7914dc61a1125dc4e06252ee98e5638a12da6cc6fb6c", size = 2177050, upload-time = "2025-11-04T13:39:19.351Z" }, - { url = "https://files.pythonhosted.org/packages/67/b1/de2e9a9a79b480f9cb0b6e8b6ba4c50b18d4e89852426364c66aa82bb7b3/pydantic_core-2.41.5-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:29452c56df2ed968d18d7e21f4ab0ac55e71dc59524872f6fc57dcf4a3249ed2", size = 2147178, upload-time = "2025-11-04T13:39:21Z" }, - { url = "https://files.pythonhosted.org/packages/16/c1/dfb33f837a47b20417500efaa0378adc6635b3c79e8369ff7a03c494b4ac/pydantic_core-2.41.5-cp310-cp310-musllinux_1_1_armv7l.whl", hash = "sha256:d5160812ea7a8a2ffbe233d8da666880cad0cbaf5d4de74ae15c313213d62556", size = 2341833, upload-time = "2025-11-04T13:39:22.606Z" }, - { url = "https://files.pythonhosted.org/packages/47/36/00f398642a0f4b815a9a558c4f1dca1b4020a7d49562807d7bc9ff279a6c/pydantic_core-2.41.5-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:df3959765b553b9440adfd3c795617c352154e497a4eaf3752555cfb5da8fc49", size = 2321156, upload-time = "2025-11-04T13:39:25.843Z" }, - { url = "https://files.pythonhosted.org/packages/7e/70/cad3acd89fde2010807354d978725ae111ddf6d0ea46d1ea1775b5c1bd0c/pydantic_core-2.41.5-cp310-cp310-win32.whl", hash = "sha256:1f8d33a7f4d5a7889e60dc39856d76d09333d8a6ed0f5f1190635cbec70ec4ba", size = 1989378, upload-time = "2025-11-04T13:39:27.92Z" }, - { url = "https://files.pythonhosted.org/packages/76/92/d338652464c6c367e5608e4488201702cd1cbb0f33f7b6a85a60fe5f3720/pydantic_core-2.41.5-cp310-cp310-win_amd64.whl", hash = "sha256:62de39db01b8d593e45871af2af9e497295db8d73b085f6bfd0b18c83c70a8f9", size = 2013622, upload-time = "2025-11-04T13:39:29.848Z" }, - { url = "https://files.pythonhosted.org/packages/e8/72/74a989dd9f2084b3d9530b0915fdda64ac48831c30dbf7c72a41a5232db8/pydantic_core-2.41.5-cp311-cp311-macosx_10_12_x86_64.whl", hash = "sha256:a3a52f6156e73e7ccb0f8cced536adccb7042be67cb45f9562e12b319c119da6", size = 2105873, upload-time = "2025-11-04T13:39:31.373Z" }, - { url = "https://files.pythonhosted.org/packages/12/44/37e403fd9455708b3b942949e1d7febc02167662bf1a7da5b78ee1ea2842/pydantic_core-2.41.5-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:7f3bf998340c6d4b0c9a2f02d6a400e51f123b59565d74dc60d252ce888c260b", size = 1899826, upload-time = "2025-11-04T13:39:32.897Z" }, - { url = "https://files.pythonhosted.org/packages/33/7f/1d5cab3ccf44c1935a359d51a8a2a9e1a654b744b5e7f80d41b88d501eec/pydantic_core-2.41.5-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:378bec5c66998815d224c9ca994f1e14c0c21cb95d2f52b6021cc0b2a58f2a5a", size = 1917869, upload-time = "2025-11-04T13:39:34.469Z" }, - { url = "https://files.pythonhosted.org/packages/6e/6a/30d94a9674a7fe4f4744052ed6c5e083424510be1e93da5bc47569d11810/pydantic_core-2.41.5-cp311-cp311-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:e7b576130c69225432866fe2f4a469a85a54ade141d96fd396dffcf607b558f8", size = 2063890, upload-time = "2025-11-04T13:39:36.053Z" }, - { url = "https://files.pythonhosted.org/packages/50/be/76e5d46203fcb2750e542f32e6c371ffa9b8ad17364cf94bb0818dbfb50c/pydantic_core-2.41.5-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:6cb58b9c66f7e4179a2d5e0f849c48eff5c1fca560994d6eb6543abf955a149e", size = 2229740, upload-time = "2025-11-04T13:39:37.753Z" }, - { url = "https://files.pythonhosted.org/packages/d3/ee/fed784df0144793489f87db310a6bbf8118d7b630ed07aa180d6067e653a/pydantic_core-2.41.5-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:88942d3a3dff3afc8288c21e565e476fc278902ae4d6d134f1eeda118cc830b1", size = 2350021, upload-time = "2025-11-04T13:39:40.94Z" }, - { url = "https://files.pythonhosted.org/packages/c8/be/8fed28dd0a180dca19e72c233cbf58efa36df055e5b9d90d64fd1740b828/pydantic_core-2.41.5-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f31d95a179f8d64d90f6831d71fa93290893a33148d890ba15de25642c5d075b", size = 2066378, upload-time = "2025-11-04T13:39:42.523Z" }, - { url = "https://files.pythonhosted.org/packages/b0/3b/698cf8ae1d536a010e05121b4958b1257f0b5522085e335360e53a6b1c8b/pydantic_core-2.41.5-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:c1df3d34aced70add6f867a8cf413e299177e0c22660cc767218373d0779487b", size = 2175761, upload-time = "2025-11-04T13:39:44.553Z" }, - { url = "https://files.pythonhosted.org/packages/b8/ba/15d537423939553116dea94ce02f9c31be0fa9d0b806d427e0308ec17145/pydantic_core-2.41.5-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:4009935984bd36bd2c774e13f9a09563ce8de4abaa7226f5108262fa3e637284", size = 2146303, upload-time = "2025-11-04T13:39:46.238Z" }, - { url = "https://files.pythonhosted.org/packages/58/7f/0de669bf37d206723795f9c90c82966726a2ab06c336deba4735b55af431/pydantic_core-2.41.5-cp311-cp311-musllinux_1_1_armv7l.whl", hash = "sha256:34a64bc3441dc1213096a20fe27e8e128bd3ff89921706e83c0b1ac971276594", size = 2340355, upload-time = "2025-11-04T13:39:48.002Z" }, - { url = "https://files.pythonhosted.org/packages/e5/de/e7482c435b83d7e3c3ee5ee4451f6e8973cff0eb6007d2872ce6383f6398/pydantic_core-2.41.5-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:c9e19dd6e28fdcaa5a1de679aec4141f691023916427ef9bae8584f9c2fb3b0e", size = 2319875, upload-time = "2025-11-04T13:39:49.705Z" }, - { url = "https://files.pythonhosted.org/packages/fe/e6/8c9e81bb6dd7560e33b9053351c29f30c8194b72f2d6932888581f503482/pydantic_core-2.41.5-cp311-cp311-win32.whl", hash = "sha256:2c010c6ded393148374c0f6f0bf89d206bf3217f201faa0635dcd56bd1520f6b", size = 1987549, upload-time = "2025-11-04T13:39:51.842Z" }, - { url = "https://files.pythonhosted.org/packages/11/66/f14d1d978ea94d1bc21fc98fcf570f9542fe55bfcc40269d4e1a21c19bf7/pydantic_core-2.41.5-cp311-cp311-win_amd64.whl", hash = "sha256:76ee27c6e9c7f16f47db7a94157112a2f3a00e958bc626e2f4ee8bec5c328fbe", size = 2011305, upload-time = "2025-11-04T13:39:53.485Z" }, - { url = "https://files.pythonhosted.org/packages/56/d8/0e271434e8efd03186c5386671328154ee349ff0354d83c74f5caaf096ed/pydantic_core-2.41.5-cp311-cp311-win_arm64.whl", hash = "sha256:4bc36bbc0b7584de96561184ad7f012478987882ebf9f9c389b23f432ea3d90f", size = 1972902, upload-time = "2025-11-04T13:39:56.488Z" }, - { url = "https://files.pythonhosted.org/packages/5f/5d/5f6c63eebb5afee93bcaae4ce9a898f3373ca23df3ccaef086d0233a35a7/pydantic_core-2.41.5-cp312-cp312-macosx_10_12_x86_64.whl", hash = "sha256:f41a7489d32336dbf2199c8c0a215390a751c5b014c2c1c5366e817202e9cdf7", size = 2110990, upload-time = "2025-11-04T13:39:58.079Z" }, - { url = "https://files.pythonhosted.org/packages/aa/32/9c2e8ccb57c01111e0fd091f236c7b371c1bccea0fa85247ac55b1e2b6b6/pydantic_core-2.41.5-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:070259a8818988b9a84a449a2a7337c7f430a22acc0859c6b110aa7212a6d9c0", size = 1896003, upload-time = "2025-11-04T13:39:59.956Z" }, - { url = "https://files.pythonhosted.org/packages/68/b8/a01b53cb0e59139fbc9e4fda3e9724ede8de279097179be4ff31f1abb65a/pydantic_core-2.41.5-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e96cea19e34778f8d59fe40775a7a574d95816eb150850a85a7a4c8f4b94ac69", size = 1919200, upload-time = "2025-11-04T13:40:02.241Z" }, - { url = "https://files.pythonhosted.org/packages/38/de/8c36b5198a29bdaade07b5985e80a233a5ac27137846f3bc2d3b40a47360/pydantic_core-2.41.5-cp312-cp312-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:ed2e99c456e3fadd05c991f8f437ef902e00eedf34320ba2b0842bd1c3ca3a75", size = 2052578, upload-time = "2025-11-04T13:40:04.401Z" }, - { url = "https://files.pythonhosted.org/packages/00/b5/0e8e4b5b081eac6cb3dbb7e60a65907549a1ce035a724368c330112adfdd/pydantic_core-2.41.5-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:65840751b72fbfd82c3c640cff9284545342a4f1eb1586ad0636955b261b0b05", size = 2208504, upload-time = "2025-11-04T13:40:06.072Z" }, - { url = "https://files.pythonhosted.org/packages/77/56/87a61aad59c7c5b9dc8caad5a41a5545cba3810c3e828708b3d7404f6cef/pydantic_core-2.41.5-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:e536c98a7626a98feb2d3eaf75944ef6f3dbee447e1f841eae16f2f0a72d8ddc", size = 2335816, upload-time = "2025-11-04T13:40:07.835Z" }, - { url = "https://files.pythonhosted.org/packages/0d/76/941cc9f73529988688a665a5c0ecff1112b3d95ab48f81db5f7606f522d3/pydantic_core-2.41.5-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:eceb81a8d74f9267ef4081e246ffd6d129da5d87e37a77c9bde550cb04870c1c", size = 2075366, upload-time = "2025-11-04T13:40:09.804Z" }, - { url = "https://files.pythonhosted.org/packages/d3/43/ebef01f69baa07a482844faaa0a591bad1ef129253ffd0cdaa9d8a7f72d3/pydantic_core-2.41.5-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:d38548150c39b74aeeb0ce8ee1d8e82696f4a4e16ddc6de7b1d8823f7de4b9b5", size = 2171698, upload-time = "2025-11-04T13:40:12.004Z" }, - { url = "https://files.pythonhosted.org/packages/b1/87/41f3202e4193e3bacfc2c065fab7706ebe81af46a83d3e27605029c1f5a6/pydantic_core-2.41.5-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:c23e27686783f60290e36827f9c626e63154b82b116d7fe9adba1fda36da706c", size = 2132603, upload-time = "2025-11-04T13:40:13.868Z" }, - { url = "https://files.pythonhosted.org/packages/49/7d/4c00df99cb12070b6bccdef4a195255e6020a550d572768d92cc54dba91a/pydantic_core-2.41.5-cp312-cp312-musllinux_1_1_armv7l.whl", hash = "sha256:482c982f814460eabe1d3bb0adfdc583387bd4691ef00b90575ca0d2b6fe2294", size = 2329591, upload-time = "2025-11-04T13:40:15.672Z" }, - { url = "https://files.pythonhosted.org/packages/cc/6a/ebf4b1d65d458f3cda6a7335d141305dfa19bdc61140a884d165a8a1bbc7/pydantic_core-2.41.5-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:bfea2a5f0b4d8d43adf9d7b8bf019fb46fdd10a2e5cde477fbcb9d1fa08c68e1", size = 2319068, upload-time = "2025-11-04T13:40:17.532Z" }, - { url = "https://files.pythonhosted.org/packages/49/3b/774f2b5cd4192d5ab75870ce4381fd89cf218af999515baf07e7206753f0/pydantic_core-2.41.5-cp312-cp312-win32.whl", hash = "sha256:b74557b16e390ec12dca509bce9264c3bbd128f8a2c376eaa68003d7f327276d", size = 1985908, upload-time = "2025-11-04T13:40:19.309Z" }, - { url = "https://files.pythonhosted.org/packages/86/45/00173a033c801cacf67c190fef088789394feaf88a98a7035b0e40d53dc9/pydantic_core-2.41.5-cp312-cp312-win_amd64.whl", hash = "sha256:1962293292865bca8e54702b08a4f26da73adc83dd1fcf26fbc875b35d81c815", size = 2020145, upload-time = "2025-11-04T13:40:21.548Z" }, - { url = "https://files.pythonhosted.org/packages/f9/22/91fbc821fa6d261b376a3f73809f907cec5ca6025642c463d3488aad22fb/pydantic_core-2.41.5-cp312-cp312-win_arm64.whl", hash = "sha256:1746d4a3d9a794cacae06a5eaaccb4b8643a131d45fbc9af23e353dc0a5ba5c3", size = 1976179, upload-time = "2025-11-04T13:40:23.393Z" }, - { url = "https://files.pythonhosted.org/packages/87/06/8806241ff1f70d9939f9af039c6c35f2360cf16e93c2ca76f184e76b1564/pydantic_core-2.41.5-cp313-cp313-macosx_10_12_x86_64.whl", hash = "sha256:941103c9be18ac8daf7b7adca8228f8ed6bb7a1849020f643b3a14d15b1924d9", size = 2120403, upload-time = "2025-11-04T13:40:25.248Z" }, - { url = "https://files.pythonhosted.org/packages/94/02/abfa0e0bda67faa65fef1c84971c7e45928e108fe24333c81f3bfe35d5f5/pydantic_core-2.41.5-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:112e305c3314f40c93998e567879e887a3160bb8689ef3d2c04b6cc62c33ac34", size = 1896206, upload-time = "2025-11-04T13:40:27.099Z" }, - { url = "https://files.pythonhosted.org/packages/15/df/a4c740c0943e93e6500f9eb23f4ca7ec9bf71b19e608ae5b579678c8d02f/pydantic_core-2.41.5-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0cbaad15cb0c90aa221d43c00e77bb33c93e8d36e0bf74760cd00e732d10a6a0", size = 1919307, upload-time = "2025-11-04T13:40:29.806Z" }, - { url = "https://files.pythonhosted.org/packages/9a/e3/6324802931ae1d123528988e0e86587c2072ac2e5394b4bc2bc34b61ff6e/pydantic_core-2.41.5-cp313-cp313-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:03ca43e12fab6023fc79d28ca6b39b05f794ad08ec2feccc59a339b02f2b3d33", size = 2063258, upload-time = "2025-11-04T13:40:33.544Z" }, - { url = "https://files.pythonhosted.org/packages/c9/d4/2230d7151d4957dd79c3044ea26346c148c98fbf0ee6ebd41056f2d62ab5/pydantic_core-2.41.5-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:dc799088c08fa04e43144b164feb0c13f9a0bc40503f8df3e9fde58a3c0c101e", size = 2214917, upload-time = "2025-11-04T13:40:35.479Z" }, - { url = "https://files.pythonhosted.org/packages/e6/9f/eaac5df17a3672fef0081b6c1bb0b82b33ee89aa5cec0d7b05f52fd4a1fa/pydantic_core-2.41.5-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:97aeba56665b4c3235a0e52b2c2f5ae9cd071b8a8310ad27bddb3f7fb30e9aa2", size = 2332186, upload-time = "2025-11-04T13:40:37.436Z" }, - { url = "https://files.pythonhosted.org/packages/cf/4e/35a80cae583a37cf15604b44240e45c05e04e86f9cfd766623149297e971/pydantic_core-2.41.5-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:406bf18d345822d6c21366031003612b9c77b3e29ffdb0f612367352aab7d586", size = 2073164, upload-time = "2025-11-04T13:40:40.289Z" }, - { url = "https://files.pythonhosted.org/packages/bf/e3/f6e262673c6140dd3305d144d032f7bd5f7497d3871c1428521f19f9efa2/pydantic_core-2.41.5-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:b93590ae81f7010dbe380cdeab6f515902ebcbefe0b9327cc4804d74e93ae69d", size = 2179146, upload-time = "2025-11-04T13:40:42.809Z" }, - { url = "https://files.pythonhosted.org/packages/75/c7/20bd7fc05f0c6ea2056a4565c6f36f8968c0924f19b7d97bbfea55780e73/pydantic_core-2.41.5-cp313-cp313-musllinux_1_1_aarch64.whl", hash = "sha256:01a3d0ab748ee531f4ea6c3e48ad9dac84ddba4b0d82291f87248f2f9de8d740", size = 2137788, upload-time = "2025-11-04T13:40:44.752Z" }, - { url = "https://files.pythonhosted.org/packages/3a/8d/34318ef985c45196e004bc46c6eab2eda437e744c124ef0dbe1ff2c9d06b/pydantic_core-2.41.5-cp313-cp313-musllinux_1_1_armv7l.whl", hash = "sha256:6561e94ba9dacc9c61bce40e2d6bdc3bfaa0259d3ff36ace3b1e6901936d2e3e", size = 2340133, upload-time = "2025-11-04T13:40:46.66Z" }, - { url = "https://files.pythonhosted.org/packages/9c/59/013626bf8c78a5a5d9350d12e7697d3d4de951a75565496abd40ccd46bee/pydantic_core-2.41.5-cp313-cp313-musllinux_1_1_x86_64.whl", hash = "sha256:915c3d10f81bec3a74fbd4faebe8391013ba61e5a1a8d48c4455b923bdda7858", size = 2324852, upload-time = "2025-11-04T13:40:48.575Z" }, - { url = "https://files.pythonhosted.org/packages/1a/d9/c248c103856f807ef70c18a4f986693a46a8ffe1602e5d361485da502d20/pydantic_core-2.41.5-cp313-cp313-win32.whl", hash = "sha256:650ae77860b45cfa6e2cdafc42618ceafab3a2d9a3811fcfbd3bbf8ac3c40d36", size = 1994679, upload-time = "2025-11-04T13:40:50.619Z" }, - { url = "https://files.pythonhosted.org/packages/9e/8b/341991b158ddab181cff136acd2552c9f35bd30380422a639c0671e99a91/pydantic_core-2.41.5-cp313-cp313-win_amd64.whl", hash = "sha256:79ec52ec461e99e13791ec6508c722742ad745571f234ea6255bed38c6480f11", size = 2019766, upload-time = "2025-11-04T13:40:52.631Z" }, - { url = "https://files.pythonhosted.org/packages/73/7d/f2f9db34af103bea3e09735bb40b021788a5e834c81eedb541991badf8f5/pydantic_core-2.41.5-cp313-cp313-win_arm64.whl", hash = "sha256:3f84d5c1b4ab906093bdc1ff10484838aca54ef08de4afa9de0f5f14d69639cd", size = 1981005, upload-time = "2025-11-04T13:40:54.734Z" }, - { url = "https://files.pythonhosted.org/packages/ea/28/46b7c5c9635ae96ea0fbb779e271a38129df2550f763937659ee6c5dbc65/pydantic_core-2.41.5-cp314-cp314-macosx_10_12_x86_64.whl", hash = "sha256:3f37a19d7ebcdd20b96485056ba9e8b304e27d9904d233d7b1015db320e51f0a", size = 2119622, upload-time = "2025-11-04T13:40:56.68Z" }, - { url = "https://files.pythonhosted.org/packages/74/1a/145646e5687e8d9a1e8d09acb278c8535ebe9e972e1f162ed338a622f193/pydantic_core-2.41.5-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:1d1d9764366c73f996edd17abb6d9d7649a7eb690006ab6adbda117717099b14", size = 1891725, upload-time = "2025-11-04T13:40:58.807Z" }, - { url = "https://files.pythonhosted.org/packages/23/04/e89c29e267b8060b40dca97bfc64a19b2a3cf99018167ea1677d96368273/pydantic_core-2.41.5-cp314-cp314-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:25e1c2af0fce638d5f1988b686f3b3ea8cd7de5f244ca147c777769e798a9cd1", size = 1915040, upload-time = "2025-11-04T13:41:00.853Z" }, - { url = "https://files.pythonhosted.org/packages/84/a3/15a82ac7bd97992a82257f777b3583d3e84bdb06ba6858f745daa2ec8a85/pydantic_core-2.41.5-cp314-cp314-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:506d766a8727beef16b7adaeb8ee6217c64fc813646b424d0804d67c16eddb66", size = 2063691, upload-time = "2025-11-04T13:41:03.504Z" }, - { url = "https://files.pythonhosted.org/packages/74/9b/0046701313c6ef08c0c1cf0e028c67c770a4e1275ca73131563c5f2a310a/pydantic_core-2.41.5-cp314-cp314-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:4819fa52133c9aa3c387b3328f25c1facc356491e6135b459f1de698ff64d869", size = 2213897, upload-time = "2025-11-04T13:41:05.804Z" }, - { url = "https://files.pythonhosted.org/packages/8a/cd/6bac76ecd1b27e75a95ca3a9a559c643b3afcd2dd62086d4b7a32a18b169/pydantic_core-2.41.5-cp314-cp314-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:2b761d210c9ea91feda40d25b4efe82a1707da2ef62901466a42492c028553a2", size = 2333302, upload-time = "2025-11-04T13:41:07.809Z" }, - { url = "https://files.pythonhosted.org/packages/4c/d2/ef2074dc020dd6e109611a8be4449b98cd25e1b9b8a303c2f0fca2f2bcf7/pydantic_core-2.41.5-cp314-cp314-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:22f0fb8c1c583a3b6f24df2470833b40207e907b90c928cc8d3594b76f874375", size = 2064877, upload-time = "2025-11-04T13:41:09.827Z" }, - { url = "https://files.pythonhosted.org/packages/18/66/e9db17a9a763d72f03de903883c057b2592c09509ccfe468187f2a2eef29/pydantic_core-2.41.5-cp314-cp314-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:2782c870e99878c634505236d81e5443092fba820f0373997ff75f90f68cd553", size = 2180680, upload-time = "2025-11-04T13:41:12.379Z" }, - { url = "https://files.pythonhosted.org/packages/d3/9e/3ce66cebb929f3ced22be85d4c2399b8e85b622db77dad36b73c5387f8f8/pydantic_core-2.41.5-cp314-cp314-musllinux_1_1_aarch64.whl", hash = "sha256:0177272f88ab8312479336e1d777f6b124537d47f2123f89cb37e0accea97f90", size = 2138960, upload-time = "2025-11-04T13:41:14.627Z" }, - { url = "https://files.pythonhosted.org/packages/a6/62/205a998f4327d2079326b01abee48e502ea739d174f0a89295c481a2272e/pydantic_core-2.41.5-cp314-cp314-musllinux_1_1_armv7l.whl", hash = "sha256:63510af5e38f8955b8ee5687740d6ebf7c2a0886d15a6d65c32814613681bc07", size = 2339102, upload-time = "2025-11-04T13:41:16.868Z" }, - { url = "https://files.pythonhosted.org/packages/3c/0d/f05e79471e889d74d3d88f5bd20d0ed189ad94c2423d81ff8d0000aab4ff/pydantic_core-2.41.5-cp314-cp314-musllinux_1_1_x86_64.whl", hash = "sha256:e56ba91f47764cc14f1daacd723e3e82d1a89d783f0f5afe9c364b8bb491ccdb", size = 2326039, upload-time = "2025-11-04T13:41:18.934Z" }, - { url = "https://files.pythonhosted.org/packages/ec/e1/e08a6208bb100da7e0c4b288eed624a703f4d129bde2da475721a80cab32/pydantic_core-2.41.5-cp314-cp314-win32.whl", hash = "sha256:aec5cf2fd867b4ff45b9959f8b20ea3993fc93e63c7363fe6851424c8a7e7c23", size = 1995126, upload-time = "2025-11-04T13:41:21.418Z" }, - { url = "https://files.pythonhosted.org/packages/48/5d/56ba7b24e9557f99c9237e29f5c09913c81eeb2f3217e40e922353668092/pydantic_core-2.41.5-cp314-cp314-win_amd64.whl", hash = "sha256:8e7c86f27c585ef37c35e56a96363ab8de4e549a95512445b85c96d3e2f7c1bf", size = 2015489, upload-time = "2025-11-04T13:41:24.076Z" }, - { url = "https://files.pythonhosted.org/packages/4e/bb/f7a190991ec9e3e0ba22e4993d8755bbc4a32925c0b5b42775c03e8148f9/pydantic_core-2.41.5-cp314-cp314-win_arm64.whl", hash = "sha256:e672ba74fbc2dc8eea59fb6d4aed6845e6905fc2a8afe93175d94a83ba2a01a0", size = 1977288, upload-time = "2025-11-04T13:41:26.33Z" }, - { url = "https://files.pythonhosted.org/packages/92/ed/77542d0c51538e32e15afe7899d79efce4b81eee631d99850edc2f5e9349/pydantic_core-2.41.5-cp314-cp314t-macosx_10_12_x86_64.whl", hash = "sha256:8566def80554c3faa0e65ac30ab0932b9e3a5cd7f8323764303d468e5c37595a", size = 2120255, upload-time = "2025-11-04T13:41:28.569Z" }, - { url = "https://files.pythonhosted.org/packages/bb/3d/6913dde84d5be21e284439676168b28d8bbba5600d838b9dca99de0fad71/pydantic_core-2.41.5-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:b80aa5095cd3109962a298ce14110ae16b8c1aece8b72f9dafe81cf597ad80b3", size = 1863760, upload-time = "2025-11-04T13:41:31.055Z" }, - { url = "https://files.pythonhosted.org/packages/5a/f0/e5e6b99d4191da102f2b0eb9687aaa7f5bea5d9964071a84effc3e40f997/pydantic_core-2.41.5-cp314-cp314t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3006c3dd9ba34b0c094c544c6006cc79e87d8612999f1a5d43b769b89181f23c", size = 1878092, upload-time = "2025-11-04T13:41:33.21Z" }, - { url = "https://files.pythonhosted.org/packages/71/48/36fb760642d568925953bcc8116455513d6e34c4beaa37544118c36aba6d/pydantic_core-2.41.5-cp314-cp314t-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:72f6c8b11857a856bcfa48c86f5368439f74453563f951e473514579d44aa612", size = 2053385, upload-time = "2025-11-04T13:41:35.508Z" }, - { url = "https://files.pythonhosted.org/packages/20/25/92dc684dd8eb75a234bc1c764b4210cf2646479d54b47bf46061657292a8/pydantic_core-2.41.5-cp314-cp314t-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:5cb1b2f9742240e4bb26b652a5aeb840aa4b417c7748b6f8387927bc6e45e40d", size = 2218832, upload-time = "2025-11-04T13:41:37.732Z" }, - { url = "https://files.pythonhosted.org/packages/e2/09/f53e0b05023d3e30357d82eb35835d0f6340ca344720a4599cd663dca599/pydantic_core-2.41.5-cp314-cp314t-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:bd3d54f38609ff308209bd43acea66061494157703364ae40c951f83ba99a1a9", size = 2327585, upload-time = "2025-11-04T13:41:40Z" }, - { url = "https://files.pythonhosted.org/packages/aa/4e/2ae1aa85d6af35a39b236b1b1641de73f5a6ac4d5a7509f77b814885760c/pydantic_core-2.41.5-cp314-cp314t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:2ff4321e56e879ee8d2a879501c8e469414d948f4aba74a2d4593184eb326660", size = 2041078, upload-time = "2025-11-04T13:41:42.323Z" }, - { url = "https://files.pythonhosted.org/packages/cd/13/2e215f17f0ef326fc72afe94776edb77525142c693767fc347ed6288728d/pydantic_core-2.41.5-cp314-cp314t-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:d0d2568a8c11bf8225044aa94409e21da0cb09dcdafe9ecd10250b2baad531a9", size = 2173914, upload-time = "2025-11-04T13:41:45.221Z" }, - { url = "https://files.pythonhosted.org/packages/02/7a/f999a6dcbcd0e5660bc348a3991c8915ce6599f4f2c6ac22f01d7a10816c/pydantic_core-2.41.5-cp314-cp314t-musllinux_1_1_aarch64.whl", hash = "sha256:a39455728aabd58ceabb03c90e12f71fd30fa69615760a075b9fec596456ccc3", size = 2129560, upload-time = "2025-11-04T13:41:47.474Z" }, - { url = "https://files.pythonhosted.org/packages/3a/b1/6c990ac65e3b4c079a4fb9f5b05f5b013afa0f4ed6780a3dd236d2cbdc64/pydantic_core-2.41.5-cp314-cp314t-musllinux_1_1_armv7l.whl", hash = "sha256:239edca560d05757817c13dc17c50766136d21f7cd0fac50295499ae24f90fdf", size = 2329244, upload-time = "2025-11-04T13:41:49.992Z" }, - { url = "https://files.pythonhosted.org/packages/d9/02/3c562f3a51afd4d88fff8dffb1771b30cfdfd79befd9883ee094f5b6c0d8/pydantic_core-2.41.5-cp314-cp314t-musllinux_1_1_x86_64.whl", hash = "sha256:2a5e06546e19f24c6a96a129142a75cee553cc018ffee48a460059b1185f4470", size = 2331955, upload-time = "2025-11-04T13:41:54.079Z" }, - { url = "https://files.pythonhosted.org/packages/5c/96/5fb7d8c3c17bc8c62fdb031c47d77a1af698f1d7a406b0f79aaa1338f9ad/pydantic_core-2.41.5-cp314-cp314t-win32.whl", hash = "sha256:b4ececa40ac28afa90871c2cc2b9ffd2ff0bf749380fbdf57d165fd23da353aa", size = 1988906, upload-time = "2025-11-04T13:41:56.606Z" }, - { url = "https://files.pythonhosted.org/packages/22/ed/182129d83032702912c2e2d8bbe33c036f342cc735737064668585dac28f/pydantic_core-2.41.5-cp314-cp314t-win_amd64.whl", hash = "sha256:80aa89cad80b32a912a65332f64a4450ed00966111b6615ca6816153d3585a8c", size = 1981607, upload-time = "2025-11-04T13:41:58.889Z" }, - { url = "https://files.pythonhosted.org/packages/9f/ed/068e41660b832bb0b1aa5b58011dea2a3fe0ba7861ff38c4d4904c1c1a99/pydantic_core-2.41.5-cp314-cp314t-win_arm64.whl", hash = "sha256:35b44f37a3199f771c3eaa53051bc8a70cd7b54f333531c59e29fd4db5d15008", size = 1974769, upload-time = "2025-11-04T13:42:01.186Z" }, - { url = "https://files.pythonhosted.org/packages/11/72/90fda5ee3b97e51c494938a4a44c3a35a9c96c19bba12372fb9c634d6f57/pydantic_core-2.41.5-graalpy311-graalpy242_311_native-macosx_10_12_x86_64.whl", hash = "sha256:b96d5f26b05d03cc60f11a7761a5ded1741da411e7fe0909e27a5e6a0cb7b034", size = 2115441, upload-time = "2025-11-04T13:42:39.557Z" }, - { url = "https://files.pythonhosted.org/packages/1f/53/8942f884fa33f50794f119012dc6a1a02ac43a56407adaac20463df8e98f/pydantic_core-2.41.5-graalpy311-graalpy242_311_native-macosx_11_0_arm64.whl", hash = "sha256:634e8609e89ceecea15e2d61bc9ac3718caaaa71963717bf3c8f38bfde64242c", size = 1930291, upload-time = "2025-11-04T13:42:42.169Z" }, - { url = "https://files.pythonhosted.org/packages/79/c8/ecb9ed9cd942bce09fc888ee960b52654fbdbede4ba6c2d6e0d3b1d8b49c/pydantic_core-2.41.5-graalpy311-graalpy242_311_native-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:93e8740d7503eb008aa2df04d3b9735f845d43ae845e6dcd2be0b55a2da43cd2", size = 1948632, upload-time = "2025-11-04T13:42:44.564Z" }, - { url = "https://files.pythonhosted.org/packages/2e/1b/687711069de7efa6af934e74f601e2a4307365e8fdc404703afc453eab26/pydantic_core-2.41.5-graalpy311-graalpy242_311_native-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f15489ba13d61f670dcc96772e733aad1a6f9c429cc27574c6cdaed82d0146ad", size = 2138905, upload-time = "2025-11-04T13:42:47.156Z" }, - { url = "https://files.pythonhosted.org/packages/09/32/59b0c7e63e277fa7911c2fc70ccfb45ce4b98991e7ef37110663437005af/pydantic_core-2.41.5-graalpy312-graalpy250_312_native-macosx_10_12_x86_64.whl", hash = "sha256:7da7087d756b19037bc2c06edc6c170eeef3c3bafcb8f532ff17d64dc427adfd", size = 2110495, upload-time = "2025-11-04T13:42:49.689Z" }, - { url = "https://files.pythonhosted.org/packages/aa/81/05e400037eaf55ad400bcd318c05bb345b57e708887f07ddb2d20e3f0e98/pydantic_core-2.41.5-graalpy312-graalpy250_312_native-macosx_11_0_arm64.whl", hash = "sha256:aabf5777b5c8ca26f7824cb4a120a740c9588ed58df9b2d196ce92fba42ff8dc", size = 1915388, upload-time = "2025-11-04T13:42:52.215Z" }, - { url = "https://files.pythonhosted.org/packages/6e/0d/e3549b2399f71d56476b77dbf3cf8937cec5cd70536bdc0e374a421d0599/pydantic_core-2.41.5-graalpy312-graalpy250_312_native-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c007fe8a43d43b3969e8469004e9845944f1a80e6acd47c150856bb87f230c56", size = 1942879, upload-time = "2025-11-04T13:42:56.483Z" }, - { url = "https://files.pythonhosted.org/packages/f7/07/34573da085946b6a313d7c42f82f16e8920bfd730665de2d11c0c37a74b5/pydantic_core-2.41.5-graalpy312-graalpy250_312_native-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:76d0819de158cd855d1cbb8fcafdf6f5cf1eb8e470abe056d5d161106e38062b", size = 2139017, upload-time = "2025-11-04T13:42:59.471Z" }, - { url = "https://files.pythonhosted.org/packages/e6/b0/1a2aa41e3b5a4ba11420aba2d091b2d17959c8d1519ece3627c371951e73/pydantic_core-2.41.5-pp310-pypy310_pp73-macosx_10_12_x86_64.whl", hash = "sha256:b5819cd790dbf0c5eb9f82c73c16b39a65dd6dd4d1439dcdea7816ec9adddab8", size = 2103351, upload-time = "2025-11-04T13:43:02.058Z" }, - { url = "https://files.pythonhosted.org/packages/a4/ee/31b1f0020baaf6d091c87900ae05c6aeae101fa4e188e1613c80e4f1ea31/pydantic_core-2.41.5-pp310-pypy310_pp73-macosx_11_0_arm64.whl", hash = "sha256:5a4e67afbc95fa5c34cf27d9089bca7fcab4e51e57278d710320a70b956d1b9a", size = 1925363, upload-time = "2025-11-04T13:43:05.159Z" }, - { url = "https://files.pythonhosted.org/packages/e1/89/ab8e86208467e467a80deaca4e434adac37b10a9d134cd2f99b28a01e483/pydantic_core-2.41.5-pp310-pypy310_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ece5c59f0ce7d001e017643d8d24da587ea1f74f6993467d85ae8a5ef9d4f42b", size = 2135615, upload-time = "2025-11-04T13:43:08.116Z" }, - { url = "https://files.pythonhosted.org/packages/99/0a/99a53d06dd0348b2008f2f30884b34719c323f16c3be4e6cc1203b74a91d/pydantic_core-2.41.5-pp310-pypy310_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:16f80f7abe3351f8ea6858914ddc8c77e02578544a0ebc15b4c2e1a0e813b0b2", size = 2175369, upload-time = "2025-11-04T13:43:12.49Z" }, - { url = "https://files.pythonhosted.org/packages/6d/94/30ca3b73c6d485b9bb0bc66e611cff4a7138ff9736b7e66bcf0852151636/pydantic_core-2.41.5-pp310-pypy310_pp73-musllinux_1_1_aarch64.whl", hash = "sha256:33cb885e759a705b426baada1fe68cbb0a2e68e34c5d0d0289a364cf01709093", size = 2144218, upload-time = "2025-11-04T13:43:15.431Z" }, - { url = "https://files.pythonhosted.org/packages/87/57/31b4f8e12680b739a91f472b5671294236b82586889ef764b5fbc6669238/pydantic_core-2.41.5-pp310-pypy310_pp73-musllinux_1_1_armv7l.whl", hash = "sha256:c8d8b4eb992936023be7dee581270af5c6e0697a8559895f527f5b7105ecd36a", size = 2329951, upload-time = "2025-11-04T13:43:18.062Z" }, - { url = "https://files.pythonhosted.org/packages/7d/73/3c2c8edef77b8f7310e6fb012dbc4b8551386ed575b9eb6fb2506e28a7eb/pydantic_core-2.41.5-pp310-pypy310_pp73-musllinux_1_1_x86_64.whl", hash = "sha256:242a206cd0318f95cd21bdacff3fcc3aab23e79bba5cac3db5a841c9ef9c6963", size = 2318428, upload-time = "2025-11-04T13:43:20.679Z" }, - { url = "https://files.pythonhosted.org/packages/2f/02/8559b1f26ee0d502c74f9cca5c0d2fd97e967e083e006bbbb4e97f3a043a/pydantic_core-2.41.5-pp310-pypy310_pp73-win_amd64.whl", hash = "sha256:d3a978c4f57a597908b7e697229d996d77a6d3c94901e9edee593adada95ce1a", size = 2147009, upload-time = "2025-11-04T13:43:23.286Z" }, - { url = "https://files.pythonhosted.org/packages/5f/9b/1b3f0e9f9305839d7e84912f9e8bfbd191ed1b1ef48083609f0dabde978c/pydantic_core-2.41.5-pp311-pypy311_pp73-macosx_10_12_x86_64.whl", hash = "sha256:b2379fa7ed44ddecb5bfe4e48577d752db9fc10be00a6b7446e9663ba143de26", size = 2101980, upload-time = "2025-11-04T13:43:25.97Z" }, - { url = "https://files.pythonhosted.org/packages/a4/ed/d71fefcb4263df0da6a85b5d8a7508360f2f2e9b3bf5814be9c8bccdccc1/pydantic_core-2.41.5-pp311-pypy311_pp73-macosx_11_0_arm64.whl", hash = "sha256:266fb4cbf5e3cbd0b53669a6d1b039c45e3ce651fd5442eff4d07c2cc8d66808", size = 1923865, upload-time = "2025-11-04T13:43:28.763Z" }, - { url = "https://files.pythonhosted.org/packages/ce/3a/626b38db460d675f873e4444b4bb030453bbe7b4ba55df821d026a0493c4/pydantic_core-2.41.5-pp311-pypy311_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:58133647260ea01e4d0500089a8c4f07bd7aa6ce109682b1426394988d8aaacc", size = 2134256, upload-time = "2025-11-04T13:43:31.71Z" }, - { url = "https://files.pythonhosted.org/packages/83/d9/8412d7f06f616bbc053d30cb4e5f76786af3221462ad5eee1f202021eb4e/pydantic_core-2.41.5-pp311-pypy311_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:287dad91cfb551c363dc62899a80e9e14da1f0e2b6ebde82c806612ca2a13ef1", size = 2174762, upload-time = "2025-11-04T13:43:34.744Z" }, - { url = "https://files.pythonhosted.org/packages/55/4c/162d906b8e3ba3a99354e20faa1b49a85206c47de97a639510a0e673f5da/pydantic_core-2.41.5-pp311-pypy311_pp73-musllinux_1_1_aarch64.whl", hash = "sha256:03b77d184b9eb40240ae9fd676ca364ce1085f203e1b1256f8ab9984dca80a84", size = 2143141, upload-time = "2025-11-04T13:43:37.701Z" }, - { url = "https://files.pythonhosted.org/packages/1f/f2/f11dd73284122713f5f89fc940f370d035fa8e1e078d446b3313955157fe/pydantic_core-2.41.5-pp311-pypy311_pp73-musllinux_1_1_armv7l.whl", hash = "sha256:a668ce24de96165bb239160b3d854943128f4334822900534f2fe947930e5770", size = 2330317, upload-time = "2025-11-04T13:43:40.406Z" }, - { url = "https://files.pythonhosted.org/packages/88/9d/b06ca6acfe4abb296110fb1273a4d848a0bfb2ff65f3ee92127b3244e16b/pydantic_core-2.41.5-pp311-pypy311_pp73-musllinux_1_1_x86_64.whl", hash = "sha256:f14f8f046c14563f8eb3f45f499cc658ab8d10072961e07225e507adb700e93f", size = 2316992, upload-time = "2025-11-04T13:43:43.602Z" }, - { url = "https://files.pythonhosted.org/packages/36/c7/cfc8e811f061c841d7990b0201912c3556bfeb99cdcb7ed24adc8d6f8704/pydantic_core-2.41.5-pp311-pypy311_pp73-win_amd64.whl", hash = "sha256:56121965f7a4dc965bff783d70b907ddf3d57f6eba29b6d2e5dabfaf07799c51", size = 2145302, upload-time = "2025-11-04T13:43:46.64Z" }, +sdist = { url = "https://files.pythonhosted.org/packages/43/bb/4742f05b739b2478459bb16fa8470549518c802e06ddcf3f106c5081315e/pydantic_core-2.46.2.tar.gz", hash = "sha256:37bb079f9ee3f1a519392b73fda2a96379b31f2013c6b467fe693e7f2987f596", size = 471269, upload-time = "2026-04-17T09:10:07.017Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/a4/f2/98f37e836c5ba0335432768e0d8645e6f50a3c838b48a74d9256256784fc/pydantic_core-2.46.2-cp310-cp310-macosx_10_12_x86_64.whl", hash = "sha256:160ef93541f4f84e3e5068e6c1f64d8fd6f57586e5853d609b467d3333f8146a", size = 2108178, upload-time = "2026-04-17T09:10:24.689Z" }, + { url = "https://files.pythonhosted.org/packages/55/69/975458de8e5453322cfc57d6c7029c3e66d9e7a4389c53ddd5ad02d5e5da/pydantic_core-2.46.2-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:1a9124b63f4f40a12a0666df57450b4c24b98407ff74349221b869ec085a5d8e", size = 1949232, upload-time = "2026-04-17T09:11:39.536Z" }, + { url = "https://files.pythonhosted.org/packages/94/8d/938175e6e82d051ac4644765680db06571d7e106a42f760da09bd90f6525/pydantic_core-2.46.2-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:de12004a7da7f1eb67ece37439a5a23a915636085dd042176fda362e006e6940", size = 1974741, upload-time = "2026-04-17T09:13:01.922Z" }, + { url = "https://files.pythonhosted.org/packages/f2/38/7329f8ac5c732bddf15f939c2add40b95170e0ecca5ef124c12def3f78ba/pydantic_core-2.46.2-cp310-cp310-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:a070c7769fec277409ad0b3d55b2f0a3703a6f00cf5031fe93090f155bf56382", size = 2041905, upload-time = "2026-04-17T09:11:11.94Z" }, + { url = "https://files.pythonhosted.org/packages/99/2c/47cfd069937ee5cbc0d9e18fa9795c8f80c49a6b4fc777d4cd870f2ade7b/pydantic_core-2.46.2-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:41d701bb34f81f0b11c724cc544b9a10b26a28f4d0d1197f2037c91225708706", size = 2222703, upload-time = "2026-04-17T09:10:31.196Z" }, + { url = "https://files.pythonhosted.org/packages/83/b0/7ed83ca8cd92c99bcab90cf42ed953723fbc19d8a20c8c12bb68c51febc1/pydantic_core-2.46.2-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:19631e7350b7a574fb6b6db222f4b17e8bd31803074b3307d07df62379d2b2e4", size = 2276317, upload-time = "2026-04-17T09:09:53.263Z" }, + { url = "https://files.pythonhosted.org/packages/85/70/50b1b62990996e7916aae2852b29cbf3ecc3fdae78209eb284cd61e2c918/pydantic_core-2.46.2-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:48b1059e4f2a6ec3e41983148eb1eec5ef9fa3a80bbc4ac0893ac76b115fe039", size = 2092152, upload-time = "2026-04-17T09:10:44.683Z" }, + { url = "https://files.pythonhosted.org/packages/c1/51/a062864e6b34ada7e343ad9ed29368e495620a8ef1c009b47a68b46e1634/pydantic_core-2.46.2-cp310-cp310-manylinux_2_31_riscv64.whl", hash = "sha256:df73724fce8ad53c670358c905b37930bd7b9d92e57db640a65c53b2706eee00", size = 2118091, upload-time = "2026-04-17T09:10:05.083Z" }, + { url = "https://files.pythonhosted.org/packages/07/e0/fcc97c4d0319615dc0b5b132b420904639652f8514e9c76482acb70ea1d4/pydantic_core-2.46.2-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:a0891a9be0def16fb320af21a198ece052eed72bf44d73d8ff43f702bd26fd6b", size = 2174304, upload-time = "2026-04-17T09:11:00.54Z" }, + { url = "https://files.pythonhosted.org/packages/00/52/28f53796ca74b7e3dd45938f300517f04970e985ad600d0d0f36a11378bd/pydantic_core-2.46.2-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:2ca790779aa1cba1329b8dc42ccebada441d9ac1d932de980183d544682c646d", size = 2181444, upload-time = "2026-04-17T09:11:45.442Z" }, + { url = "https://files.pythonhosted.org/packages/22/49/164d5d3a7356d2607a72e77264a3b252a7c7d9362a81fc9df47bef7ae3aa/pydantic_core-2.46.2-cp310-cp310-musllinux_1_1_armv7l.whl", hash = "sha256:6b865eb702c3af71cf7331919a787563ce2413f7a54ef49ec6709a01b4f22ce6", size = 2328611, upload-time = "2026-04-17T09:10:08.574Z" }, + { url = "https://files.pythonhosted.org/packages/6b/77/6266bb3b79c27b533e5ee02c1e3da5848872112178880cc5006a84e857ac/pydantic_core-2.46.2-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:631bec5f951a30a4b332b4a57d0cdd5a2c8187eb71301f966425f2e54a697855", size = 2351070, upload-time = "2026-04-17T09:13:34.92Z" }, + { url = "https://files.pythonhosted.org/packages/10/7f/d4233852d16d8e85b034a524d8017e051a0aa4acd04c64c3a69a1a2a0ba6/pydantic_core-2.46.2-cp310-cp310-win32.whl", hash = "sha256:8cbd9d67357f3a925f2af1d44db3e8ef1ce1a293ea0add98081b072d4a12e3b4", size = 1976750, upload-time = "2026-04-17T09:13:15.537Z" }, + { url = "https://files.pythonhosted.org/packages/70/31/d65117cf5f89d81705da5b1dcdad8efa0a0b65dbbc7f13cafbabb7d01615/pydantic_core-2.46.2-cp310-cp310-win_amd64.whl", hash = "sha256:dd51dd16182b4bfdcefd27b39b856aa4a57b77f15b231a2d10c45391b0a02028", size = 2073989, upload-time = "2026-04-17T09:12:17.315Z" }, + { url = "https://files.pythonhosted.org/packages/89/91/089f517a725f29084364169437833ab0ae4da4d7a6ed9d4474db7f1412e6/pydantic_core-2.46.2-cp311-cp311-macosx_10_12_x86_64.whl", hash = "sha256:d8060f42db3cd204871db0afd51fef54a13fa544c4dd48cdcae2e174ef40c8ba", size = 2106218, upload-time = "2026-04-17T09:10:48.023Z" }, + { url = "https://files.pythonhosted.org/packages/a0/92/23858ed1b58f2a134e50c2fdd0e34ea72721ccb257e1e9346514e1ccb5b9/pydantic_core-2.46.2-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:73a9d2809bd8d4a7cda4d336dc996a565eb4feaaa39932f9d85a65fa18382f28", size = 1948087, upload-time = "2026-04-17T09:11:58.639Z" }, + { url = "https://files.pythonhosted.org/packages/5d/ac/e2240fccb4794e965817593d5a46cf5ea22f2001b73fe360b7578925b7d8/pydantic_core-2.46.2-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3b0a2dee92dfaabcfb93629188c3e9cf74fdfc0f22e7c369cb444a98814a1e50", size = 1972931, upload-time = "2026-04-17T09:13:13.304Z" }, + { url = "https://files.pythonhosted.org/packages/1a/da/3b11dab2aa15c5c8ed20a01eb7aa432a78b8e3a4713659f7e58490a020a5/pydantic_core-2.46.2-cp311-cp311-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:3098446ba8cf774f61cb8d4008c1dba14a30426a15169cd95ac3392a461193b1", size = 2040454, upload-time = "2026-04-17T09:13:47.895Z" }, + { url = "https://files.pythonhosted.org/packages/d7/39/c4cf5e1f1c6c34c53c0902039c95d81dc15cdd1f03634bd1a93f33e70a72/pydantic_core-2.46.2-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:57c584af6c375ea3f826d8131a94cb212b3d9926eaff67117e3711bbff3a83a5", size = 2221320, upload-time = "2026-04-17T09:13:08.568Z" }, + { url = "https://files.pythonhosted.org/packages/c7/46/891035bc9e93538e754c3188424d24b5a69ec3ae5210fa01d483e99b3302/pydantic_core-2.46.2-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:547381cca999be88b4715a0ed7afa11f07fc7e53cb1883687b190d25a92c56cf", size = 2274559, upload-time = "2026-04-17T09:11:10.257Z" }, + { url = "https://files.pythonhosted.org/packages/ab/d0/7af0b905b3148152c159c9caf203e7ecd9b90b76389f0862e6ab0cf1b2a3/pydantic_core-2.46.2-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:caeed15dcb1233a5a94bc6ff37ef5393cf5b33a45e4bdfb2d6042f3d24e1cb27", size = 2089239, upload-time = "2026-04-17T09:13:06.326Z" }, + { url = "https://files.pythonhosted.org/packages/c5/bc/566afe02ba2de37712eece74ac7bfba322abd7916410bf90504f1b17ddad/pydantic_core-2.46.2-cp311-cp311-manylinux_2_31_riscv64.whl", hash = "sha256:c05f53362568c75476b5c96659377a5dfd982cfbe5a5c07de5106d08a04efc4f", size = 2116182, upload-time = "2026-04-17T09:11:33.738Z" }, + { url = "https://files.pythonhosted.org/packages/4e/5b/3fcb3a229bbfa23b0e3c65014057af0f9d51ec7a2d9f7adb282f41ff5ac8/pydantic_core-2.46.2-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:2643ac7eae296200dbd48762a1c852cf2cad5f5e3eba34e652053cebf03becf8", size = 2172346, upload-time = "2026-04-17T09:10:46.472Z" }, + { url = "https://files.pythonhosted.org/packages/43/9a/baa9e3aa70ea7bbcb9db0f87162a371649ac80c03e43eb54af193390cf17/pydantic_core-2.46.2-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:dc4620a47c6fe6a39f89392c00833a82fc050ce90169798f78a25a8d4df03b6e", size = 2179540, upload-time = "2026-04-17T09:11:21.881Z" }, + { url = "https://files.pythonhosted.org/packages/bd/46/912047a5427f949c909495704b3c8b9ead9d1c66f87e96606011beab1fcb/pydantic_core-2.46.2-cp311-cp311-musllinux_1_1_armv7l.whl", hash = "sha256:78cb0d2453b50bf2035f85fd0d9cfabdb98c47f9c53ddb7c23873cd83da9560b", size = 2327423, upload-time = "2026-04-17T09:13:40.291Z" }, + { url = "https://files.pythonhosted.org/packages/e9/bf/c5e661451dc9411c2ab88a244c1ba57644950c971486040dc200f77b69f4/pydantic_core-2.46.2-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:f0c1cbb7d6112932cc188c6be007a5e2867005a069e47f42fe67bf5f122b0908", size = 2348652, upload-time = "2026-04-17T09:10:37.76Z" }, + { url = "https://files.pythonhosted.org/packages/77/b3/3219e7c522af54b010cf7422dcb11cc6616a4414d1ccd628b0d3f61c6af6/pydantic_core-2.46.2-cp311-cp311-win32.whl", hash = "sha256:c1ce5b2366f85cfdbf7f0907755043707f86d09a5b1b1acebbb7bf1600d75c64", size = 1974410, upload-time = "2026-04-17T09:13:27.392Z" }, + { url = "https://files.pythonhosted.org/packages/e5/29/e5cfac8a74c59873dfd47d3a1477c39ad9247639a7120d3e251a9ff12417/pydantic_core-2.46.2-cp311-cp311-win_amd64.whl", hash = "sha256:f1a6197eadff5bd0bb932f12bb038d403cb75db5b0b391e70e816a647745ddaf", size = 2071158, upload-time = "2026-04-17T09:09:57.69Z" }, + { url = "https://files.pythonhosted.org/packages/6f/8b/b7b19b717cdb3675cb109de143f62d4dc62f5d4a0b9879b6f1ace62c6654/pydantic_core-2.46.2-cp311-cp311-win_arm64.whl", hash = "sha256:15e42885b283f87846ee79e161002c5c496ef747a73f6e47054f45a13d9035bc", size = 2043507, upload-time = "2026-04-17T09:09:51.828Z" }, + { url = "https://files.pythonhosted.org/packages/97/ec/2fafa4c86f5d2a69372c7cddef30925fd0e370b1efaf556609c1a0196d8a/pydantic_core-2.46.2-cp312-cp312-macosx_10_12_x86_64.whl", hash = "sha256:ea1ad8c89da31512fe2d249cf0638fb666925bda341901541bc5f3311c6fcc9e", size = 2101729, upload-time = "2026-04-17T09:12:30.042Z" }, + { url = "https://files.pythonhosted.org/packages/cf/55/be5386c2c4b49af346e8a26b748194ff25757bbb6cf544130854e997af7a/pydantic_core-2.46.2-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:b308da17b92481e0587244631c5529e5d91d04cb2b08194825627b1eca28e21e", size = 1951546, upload-time = "2026-04-17T09:10:10.585Z" }, + { url = "https://files.pythonhosted.org/packages/29/92/89e273a055ce440e6636c756379af35ad86da9d336a560049c3ba5e41c80/pydantic_core-2.46.2-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d333a50bdd814a917d8d6a7ee35ba2395d53ddaa882613bc24e54a9d8b129095", size = 1976178, upload-time = "2026-04-17T09:11:49.619Z" }, + { url = "https://files.pythonhosted.org/packages/91/b3/e4664469cf70c0cb0f7b2f5719d64e5968bb6f38217042c2afa3d3c4ba17/pydantic_core-2.46.2-cp312-cp312-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:1d00b99590c5bd1fabbc5d28b170923e32c1b1071b1f1de1851a4d14d89eb192", size = 2051697, upload-time = "2026-04-17T09:12:04.917Z" }, + { url = "https://files.pythonhosted.org/packages/98/58/dbf68213ee06ce51cdd6d8c95f97980e646858c45bd96bd2dfb40433be73/pydantic_core-2.46.2-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:9f0e686960ffe9e65066395af856ac2d52c159043144433602c50c221d81c1ba", size = 2233160, upload-time = "2026-04-17T09:12:00.956Z" }, + { url = "https://files.pythonhosted.org/packages/f5/d3/68092aa0ee6c60ff4de4740eb82db3d4ce338ec89b3cecb978c532472f12/pydantic_core-2.46.2-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:2d1128da41c9cb474e0a4701f9c363ec645c9d1a02229904c76bf4e0a194fde2", size = 2298398, upload-time = "2026-04-17T09:10:29.694Z" }, + { url = "https://files.pythonhosted.org/packages/e4/51/5d6155eb737db55b0ad354ca5f333ef009f75feb67df2d79a84bace45af6/pydantic_core-2.46.2-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:48649cf2d8c358d79586e9fb2f8235902fcaa2d969ec1c5301f2d1873b2f8321", size = 2094058, upload-time = "2026-04-17T09:12:10.995Z" }, + { url = "https://files.pythonhosted.org/packages/6b/f3/eb4a986197d71319430464ff181226c95adc8f06d932189b158bae5a82f5/pydantic_core-2.46.2-cp312-cp312-manylinux_2_31_riscv64.whl", hash = "sha256:b902f0fc7c2cf503865a05718b68147c6cd5d0a3867af38c527be574a9fa6e9d", size = 2130388, upload-time = "2026-04-17T09:12:41.159Z" }, + { url = "https://files.pythonhosted.org/packages/56/00/44a9c4fe6d0f64b5786d6a8c649d6f0e34ba6c89b3663add1066e54451a2/pydantic_core-2.46.2-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:e80011f808b03d1d87a8f1e76ae3da19a18eb706c823e17981dcf1fae43744fc", size = 2184245, upload-time = "2026-04-17T09:12:36.532Z" }, + { url = "https://files.pythonhosted.org/packages/78/6b/685b98a834d5e3d1c34a1bde1627525559dd223b75075bc7490cdb24eb33/pydantic_core-2.46.2-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:b839d5c802e31348b949b6473f8190cddbf7d47475856d8ac995a373ee16ec59", size = 2186842, upload-time = "2026-04-17T09:13:04.054Z" }, + { url = "https://files.pythonhosted.org/packages/22/64/caa2f5a2ac8b6113adaa410ccdf31ba7f54897a6e54cd0d726fc7e780c88/pydantic_core-2.46.2-cp312-cp312-musllinux_1_1_armv7l.whl", hash = "sha256:c6b1064f3f9cf9072e1d59dd2936f9f3b668bec1c37039708c9222db703c0d5b", size = 2336066, upload-time = "2026-04-17T09:12:13.006Z" }, + { url = "https://files.pythonhosted.org/packages/ee/f9/7d2701bf82945b5b9e7df8347be97ef6a36da2846bfe5b4afec299ffe27b/pydantic_core-2.46.2-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:37a68e6f2ac95578ce3c0564802404b27b24988649616e556c07e77111ed3f1d", size = 2363691, upload-time = "2026-04-17T09:13:42.972Z" }, + { url = "https://files.pythonhosted.org/packages/3b/65/0dab11574101522941055109419db3cc09db871643dc3fc74e2413215e5b/pydantic_core-2.46.2-cp312-cp312-win32.whl", hash = "sha256:d9ffa75a7ef4b97d6e5e205fabd4304ef01fec09e6f1bdde04b9ad1b07d20289", size = 1958801, upload-time = "2026-04-17T09:11:31.981Z" }, + { url = "https://files.pythonhosted.org/packages/13/2b/df84baa609c676f6450b8ecad44ea59146c805e3371b7b52443c0899f989/pydantic_core-2.46.2-cp312-cp312-win_amd64.whl", hash = "sha256:0551f2d2ddb68af5a00e26497f8025c538f73ef3cb698f8e5a487042cd2792a8", size = 2072634, upload-time = "2026-04-17T09:11:02.407Z" }, + { url = "https://files.pythonhosted.org/packages/d1/4e/e1ce8029fc438086a946739bf9d596f70ff470aad4a8345555920618cabe/pydantic_core-2.46.2-cp312-cp312-win_arm64.whl", hash = "sha256:83aef30f106edcc21a6a4cc44b82d3169a1dbe255508db788e778f3c804d3583", size = 2026188, upload-time = "2026-04-17T09:13:11.083Z" }, + { url = "https://files.pythonhosted.org/packages/07/2b/662e48254479a2d3450ba24b1e25061108b64339794232f503990c519144/pydantic_core-2.46.2-cp313-cp313-macosx_10_12_x86_64.whl", hash = "sha256:d26e9eea3715008a09a74585fe9becd0c67fbb145dc4df9756d597d7230a652c", size = 2101762, upload-time = "2026-04-17T09:10:13.87Z" }, + { url = "https://files.pythonhosted.org/packages/73/ab/bafd7c7503757ccc8ec4d1911e106fe474c629443648c51a88f08b0fe91a/pydantic_core-2.46.2-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:48b36e3235140510dc7861f0cd58b714b1cdd3d48f75e10ce52e69866b746f10", size = 1951814, upload-time = "2026-04-17T09:12:25.934Z" }, + { url = "https://files.pythonhosted.org/packages/92/cc/7549c2d57ba2e9a42caa5861a2d398dbe31c02c6aca783253ace59ce84f8/pydantic_core-2.46.2-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:36b1f99dc451f1a3981f236151465bcf995bbe712d0727c9f7b236fe228a8133", size = 1977329, upload-time = "2026-04-17T09:13:37.605Z" }, + { url = "https://files.pythonhosted.org/packages/18/50/7ed4a8a0d478a4dca8f0134a5efa7193f03cc8520dd4c9509339fb2e5002/pydantic_core-2.46.2-cp313-cp313-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:8641c8d535c2d95b45c2e19b646ecd23ebba35d461e0ae48a3498277006250ab", size = 2051832, upload-time = "2026-04-17T09:12:49.771Z" }, + { url = "https://files.pythonhosted.org/packages/dc/16/bb35b193741c0298ddc5f5e4234269efdc0c65e2bcd198aa0de9b68845e4/pydantic_core-2.46.2-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:20fb194788a0a50993e87013e693494ba183a2af5b44e99cf060bbae10912b11", size = 2233127, upload-time = "2026-04-17T09:11:04.449Z" }, + { url = "https://files.pythonhosted.org/packages/91/a5/98f4b637149185addea19e1785ea20c373cca31b202f589111d8209d9873/pydantic_core-2.46.2-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:9262d11d0cd11ee3303a95156939402bed6cedfe5ed0e331b95a283a4da6eb8b", size = 2297418, upload-time = "2026-04-17T09:11:25.929Z" }, + { url = "https://files.pythonhosted.org/packages/36/90/93a5d21990b152da7b7507b7fddb0b935f6a0984d57ac3ec45a6e17777a2/pydantic_core-2.46.2-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ac204542736aa295fa25f713b7fad6fc50b46ab7764d16087575c85f085174f3", size = 2093735, upload-time = "2026-04-17T09:12:06.908Z" }, + { url = "https://files.pythonhosted.org/packages/14/22/b8b1ffdddf08b4e84380bcb67f41dbbf4c171377c1d36fc6290794bb2094/pydantic_core-2.46.2-cp313-cp313-manylinux_2_31_riscv64.whl", hash = "sha256:9a7c43a0584742dface3ca0daf6f719d46c1ac2f87cf080050f9ae052c75e1b2", size = 2127570, upload-time = "2026-04-17T09:11:53.906Z" }, + { url = "https://files.pythonhosted.org/packages/c6/26/e60d72b4e2d0ce1fa811044a974412ac1c567fe067d97b3e6b290530786e/pydantic_core-2.46.2-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:fd05e1edb6a90ad446fa268ab09e59202766b837597b714b2492db11ee87fab9", size = 2183524, upload-time = "2026-04-17T09:11:30.092Z" }, + { url = "https://files.pythonhosted.org/packages/35/32/36bec7584a1eefb17dec4dfa1c946d3fe4440f466c5705b8adfda69c9a9f/pydantic_core-2.46.2-cp313-cp313-musllinux_1_1_aarch64.whl", hash = "sha256:91155b110788b5501abc7ea954f1d08606219e4e28e3c73a94124307c06efb80", size = 2185408, upload-time = "2026-04-17T09:10:57.228Z" }, + { url = "https://files.pythonhosted.org/packages/fc/d6/1a5689d873620efd67d6b163db0c444c056adb0849b5bc33e2b9f09665a6/pydantic_core-2.46.2-cp313-cp313-musllinux_1_1_armv7l.whl", hash = "sha256:e4e2c72a529fa03ff228be1d2b76944013f428220b764e03cc50ada67e17a42c", size = 2335171, upload-time = "2026-04-17T09:11:43.369Z" }, + { url = "https://files.pythonhosted.org/packages/3e/8e/675104802abe8ef502b072050ee5f2e915251aa1a3af87e1015ce31ec42d/pydantic_core-2.46.2-cp313-cp313-musllinux_1_1_x86_64.whl", hash = "sha256:56291ec1a11c3499890c99a8fd9053b47e60fe837a77ec72c0671b1b8b3dce24", size = 2362743, upload-time = "2026-04-17T09:10:18.333Z" }, + { url = "https://files.pythonhosted.org/packages/8d/bc/86c5dde4fa6e24467680eef5047da3c1a19be0a527d0d8e14aa76b39307c/pydantic_core-2.46.2-cp313-cp313-win32.whl", hash = "sha256:b50f9c5f826ddca1246f055148df939f5f3f2d0d96db73de28e2233f22210d4c", size = 1958074, upload-time = "2026-04-17T09:12:38.622Z" }, + { url = "https://files.pythonhosted.org/packages/2a/97/2537e8c1282b2c4eb062580c0d7a4339e10b072b803d1ee0b7f1f0a5c22c/pydantic_core-2.46.2-cp313-cp313-win_amd64.whl", hash = "sha256:251a57788823230ca8cbc99e6245d1a2ed6e180ec4864f251c94182c580c7f2e", size = 2071741, upload-time = "2026-04-17T09:13:32.405Z" }, + { url = "https://files.pythonhosted.org/packages/da/aa/2ee75798706f9dbc4e76dbe59e41a396c5c311e3d6223b9cf6a5fa7780be/pydantic_core-2.46.2-cp313-cp313-win_arm64.whl", hash = "sha256:315d32d1a71494d6b4e1e14a9fa7a4329597b4c4340088ad7e1a9dafbeed92a9", size = 2025955, upload-time = "2026-04-17T09:10:15.567Z" }, + { url = "https://files.pythonhosted.org/packages/d0/96/a50ccb6b539ae780f73cea74905468777680e30c6c3bdf714b9d4c116ea0/pydantic_core-2.46.2-cp314-cp314-macosx_10_12_x86_64.whl", hash = "sha256:4f59b45f3ef8650c0c736a57f59031d47ed9df4c0a64e83796849d7d14863a2d", size = 2097111, upload-time = "2026-04-17T09:10:49.617Z" }, + { url = "https://files.pythonhosted.org/packages/34/5f/fdead7b3afa822ab6e5a18ee0ecffd54937de1877c01ed13a342e0fb3f07/pydantic_core-2.46.2-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:3a075a29ebef752784a91532a1a85be6b234ccffec0a9d7978a92696387c3da6", size = 1951904, upload-time = "2026-04-17T09:12:32.062Z" }, + { url = "https://files.pythonhosted.org/packages/95/e0/1c5d547e550cdab1bec737492aa08865337af6fe7fc9b96f7f45f17d9519/pydantic_core-2.46.2-cp314-cp314-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0d12d786e30c04a9d307c5d7080bf720d9bac7f1668191d8e37633a9562749e2", size = 1978667, upload-time = "2026-04-17T09:11:35.589Z" }, + { url = "https://files.pythonhosted.org/packages/0e/cb/665ce629e218c8228302cb94beff4f6531082a2c87d3ecc3d5e63a26f392/pydantic_core-2.46.2-cp314-cp314-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:0d5e6d6343b0b5dcacb3503b5de90022968da8ed0ab9ab39d3eda71c20cbf84e", size = 2046721, upload-time = "2026-04-17T09:11:47.725Z" }, + { url = "https://files.pythonhosted.org/packages/77/e9/6cb2cf60f54c1472bbdfce19d957553b43dbba79d1d7b2930a195c594785/pydantic_core-2.46.2-cp314-cp314-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:233eebac0999b6b9ba76eb56f3ec8fce13164aa16b6d2225a36a79e0f95b5973", size = 2228483, upload-time = "2026-04-17T09:12:08.837Z" }, + { url = "https://files.pythonhosted.org/packages/0d/2a/93e018dd5571f781ebaeda8c0cf65398489d5bee9b1f484df0b6149b43b9/pydantic_core-2.46.2-cp314-cp314-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:9cc0eee720dd2f14f3b7c349469402b99ad81a174ab49d3533974529e9d93992", size = 2294663, upload-time = "2026-04-17T09:12:52.053Z" }, + { url = "https://files.pythonhosted.org/packages/5e/4f/49e57ca55c770c93d9bb046666a54949b42e3c9099a0c5fe94557873fe30/pydantic_core-2.46.2-cp314-cp314-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:83ee76bf2c9910513dbc19e7d82367131fa7508dedd6186a462393071cc11059", size = 2098742, upload-time = "2026-04-17T09:13:45.472Z" }, + { url = "https://files.pythonhosted.org/packages/c6/b0/6e46b5cd3332af665f794b8cdeea206618a8630bd9e7bcc36864518fce81/pydantic_core-2.46.2-cp314-cp314-manylinux_2_31_riscv64.whl", hash = "sha256:d61db38eb4ee5192f0c261b7f2d38e420b554df8912245e3546aee5c45e2fd78", size = 2125922, upload-time = "2026-04-17T09:12:54.304Z" }, + { url = "https://files.pythonhosted.org/packages/06/d1/40850c81585be443a2abfdf7f795f8fae831baf8e2f9b2133c8246ac671c/pydantic_core-2.46.2-cp314-cp314-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:8f09a713d17bcd55da8ab02ebd9110c5246a49c44182af213b5212800af8bc83", size = 2183000, upload-time = "2026-04-17T09:10:59.027Z" }, + { url = "https://files.pythonhosted.org/packages/04/af/8493d7dfa03ebb7866909e577c6aa65ea0de7377b86023cc51d0c8e11db3/pydantic_core-2.46.2-cp314-cp314-musllinux_1_1_aarch64.whl", hash = "sha256:30cacc5fb696e64b8ef6fd31d9549d394dd7d52760db072eecb98e37e3af1677", size = 2180335, upload-time = "2026-04-17T09:12:57.01Z" }, + { url = "https://files.pythonhosted.org/packages/72/5b/1f6a344c4ffdf284da41c6067b82d5ebcbd11ce1b515ae4b662d4adb6f61/pydantic_core-2.46.2-cp314-cp314-musllinux_1_1_armv7l.whl", hash = "sha256:7ccfb105fcfe91a22bbb5563ad3dc124bc1aa75bfd2e53a780ab05f78cdf6108", size = 2330002, upload-time = "2026-04-17T09:12:02.958Z" }, + { url = "https://files.pythonhosted.org/packages/25/ff/9a694126c12d6d2f48a0cafa6f8eef88ef0d8825600e18d03ff2e896c3b2/pydantic_core-2.46.2-cp314-cp314-musllinux_1_1_x86_64.whl", hash = "sha256:13ffef637dc8370c249e5b26bd18e9a80a4fca3d809618c44e18ec834a7ca7a8", size = 2359920, upload-time = "2026-04-17T09:10:27.764Z" }, + { url = "https://files.pythonhosted.org/packages/51/c8/3a35c763d68a9cb2675eb10ef242cf66c5d4701b28ae12e688d67d2c180e/pydantic_core-2.46.2-cp314-cp314-win32.whl", hash = "sha256:1b0ab6d756ca2704a938e6c31b53f290c2f9c10d3914235410302a149de1a83e", size = 1953701, upload-time = "2026-04-17T09:13:30.021Z" }, + { url = "https://files.pythonhosted.org/packages/1a/6a/f2726a780365f7dfd89d62036f984f7acb99978c60c5e1fa7c0cb898ed11/pydantic_core-2.46.2-cp314-cp314-win_amd64.whl", hash = "sha256:99ebade8c9ada4df975372d8dd25883daa0e379a05f1cd0c99aa0c04368d01a6", size = 2071867, upload-time = "2026-04-17T09:10:39.205Z" }, + { url = "https://files.pythonhosted.org/packages/e1/79/76baacb9feba3d7c399b245ca1a29c74ea0db04ea693811374827eec2290/pydantic_core-2.46.2-cp314-cp314-win_arm64.whl", hash = "sha256:de87422197cf7f83db91d89c86a21660d749b3cd76cd8a45d115b8e675670f02", size = 2017252, upload-time = "2026-04-17T09:10:26.175Z" }, + { url = "https://files.pythonhosted.org/packages/f1/3b/77c26938f817668d9ad9bab1a905cb23f11d9a3d4bf724d429b3e55a8eaf/pydantic_core-2.46.2-cp314-cp314t-macosx_10_12_x86_64.whl", hash = "sha256:236f22b4a206b5b61db955396b7cf9e2e1ff77f372efe9570128ccfcd6a525eb", size = 2094545, upload-time = "2026-04-17T09:12:19.339Z" }, + { url = "https://files.pythonhosted.org/packages/fe/de/42c13f590e3c260966aa49bcdb1674774f975467c49abd51191e502bea28/pydantic_core-2.46.2-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:c2012f64d2cd7cca50f49f22445aa5a88691ac2b4498ee0a9a977f8ca4f7289f", size = 1933953, upload-time = "2026-04-17T09:09:55.889Z" }, + { url = "https://files.pythonhosted.org/packages/4e/84/ebe3ebb3e2d8db656937cfa6f97f544cb7132f2307a4a7dfdcd0ea102a12/pydantic_core-2.46.2-cp314-cp314t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d07d6c63106d3a9c9a333e2636f9c82c703b1a9e3b079299e58747964e4fdb72", size = 1974435, upload-time = "2026-04-17T09:10:12.371Z" }, + { url = "https://files.pythonhosted.org/packages/b9/15/0bf51ca6709477cd4ef86148b6d7844f3308f029eac361dd0383f1e17b1a/pydantic_core-2.46.2-cp314-cp314t-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:c326a2b4b85e959d9a1fc3a11f32f84611b6ec07c053e1828a860edf8d068208", size = 2031113, upload-time = "2026-04-17T09:10:00.752Z" }, + { url = "https://files.pythonhosted.org/packages/02/ae/b7b5af9b79db036d9e61a44c481c17a213dc8fc4b8b71fe6875a72fc778b/pydantic_core-2.46.2-cp314-cp314t-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:ac8a65e798f2462552c00d2e013d532c94d646729dda98458beaf51f9ec7b120", size = 2236325, upload-time = "2026-04-17T09:10:33.227Z" }, + { url = "https://files.pythonhosted.org/packages/a6/ae/ecef7477b5a03d4a499708f7e75d2836452ebb70b776c2d64612b334f57a/pydantic_core-2.46.2-cp314-cp314t-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:5a3c2bc1cc8164bedbc160b7bb1e8cc1e8b9c27f69ae4f9ae2b976cdae02b2dd", size = 2278135, upload-time = "2026-04-17T09:10:23.287Z" }, + { url = "https://files.pythonhosted.org/packages/db/e4/2f9d82faa47af6c39fc3f120145fd915971e1e0cb6b55b494fad9fdf8275/pydantic_core-2.46.2-cp314-cp314t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e69aa5e10b7e8b1bb4a6888650fd12fcbf11d396ca11d4a44de1450875702830", size = 2109071, upload-time = "2026-04-17T09:11:06.149Z" }, + { url = "https://files.pythonhosted.org/packages/f1/9c/677cf10873fbd0b116575ab7b97c90482b21564f8a8040beb18edef7a577/pydantic_core-2.46.2-cp314-cp314t-manylinux_2_31_riscv64.whl", hash = "sha256:4e6df5c3301e65fb42bc5338bf9a1027a02b0a31dc7f54c33775229af474daf0", size = 2106028, upload-time = "2026-04-17T09:10:51.525Z" }, + { url = "https://files.pythonhosted.org/packages/d6/53/6a06183544daba51c059123a2064a99039df25f115a06bdb26f2ea177038/pydantic_core-2.46.2-cp314-cp314t-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:2c2f6e32548ac8d559b47944effcf8ae4d81c161f6b6c885edc53bc08b8f192d", size = 2164816, upload-time = "2026-04-17T09:11:56.187Z" }, + { url = "https://files.pythonhosted.org/packages/57/6f/10fcdd9e3eca66fc828eef0f6f5850f2dd3bca2c59e6e041fb8bc3da39be/pydantic_core-2.46.2-cp314-cp314t-musllinux_1_1_aarch64.whl", hash = "sha256:b089a81c58e6ea0485562bbbbbca4f65c0549521606d5ef27fba217aac9b665a", size = 2166130, upload-time = "2026-04-17T09:10:03.804Z" }, + { url = "https://files.pythonhosted.org/packages/29/83/92d3fd0e0156cad2e3cb5c26de73794af78ac9fa0c22ab666e566dd67061/pydantic_core-2.46.2-cp314-cp314t-musllinux_1_1_armv7l.whl", hash = "sha256:7f700a6d6f64112ae9193709b84303bbab84424ad4b47d0253301aabce9dfc70", size = 2316605, upload-time = "2026-04-17T09:12:45.249Z" }, + { url = "https://files.pythonhosted.org/packages/97/f1/facffdb970981068219582e499b8d0871ed163ffcc6b347de5c412669e4c/pydantic_core-2.46.2-cp314-cp314t-musllinux_1_1_x86_64.whl", hash = "sha256:67db6814beaa5fefe91101ec7eb9efda613795767be96f7cf58b1ca8c9ca9972", size = 2358385, upload-time = "2026-04-17T09:09:54.657Z" }, + { url = "https://files.pythonhosted.org/packages/8b/a1/b8160b2f22b2199467bc68581a4ed380643c16b348a27d6165c6c242d694/pydantic_core-2.46.2-cp314-cp314t-win32.whl", hash = "sha256:32fbc7447be8e3be99bf7869f7066308f16be55b61f9882c2cefc7931f5c7664", size = 1942373, upload-time = "2026-04-17T09:12:59.594Z" }, + { url = "https://files.pythonhosted.org/packages/0d/90/db89acabe5b150e11d1b59fe3d947dda2ef6abbfef5c82f056ff63802f5d/pydantic_core-2.46.2-cp314-cp314t-win_amd64.whl", hash = "sha256:b317a2b97019c0b95ce99f4f901ae383f40132da6706cdf1731066a73394c25c", size = 2052078, upload-time = "2026-04-17T09:10:19.96Z" }, + { url = "https://files.pythonhosted.org/packages/97/32/e19b83ceb07a3f1bb21798407790bbc9a31740158fd132b94139cb84e16c/pydantic_core-2.46.2-cp314-cp314t-win_arm64.whl", hash = "sha256:7dcb9d40930dfad7ab6b20bcc6ca9d2b030b0f347a0cd9909b54bd53ead521b1", size = 2016941, upload-time = "2026-04-17T09:12:34.447Z" }, + { url = "https://files.pythonhosted.org/packages/25/ec/e91aa08df1c33d5e3c2b60c07a1eca9f21809728a824c7b467bb3bda68b5/pydantic_core-2.46.2-graalpy311-graalpy242_311_native-macosx_10_12_x86_64.whl", hash = "sha256:7c5a5b3dbb9e8918e223be6580da5ffcf861c0505bbc196ebed7176ce05b7b4e", size = 2105046, upload-time = "2026-04-17T09:10:55.614Z" }, + { url = "https://files.pythonhosted.org/packages/f0/73/27112400a0452e375290e7c40aef5cc9844ac0920fb1029238cfc68121fa/pydantic_core-2.46.2-graalpy311-graalpy242_311_native-macosx_11_0_arm64.whl", hash = "sha256:bc1e8ce33d5a337f2ba862e0719b8201cd54aaed967406c748e009191d47efdd", size = 1940029, upload-time = "2026-04-17T09:12:21.5Z" }, + { url = "https://files.pythonhosted.org/packages/b1/44/3d39f782bc82ddd0b2d82bde83b408aa40a332cdf6f3018acb34e3d4dcfc/pydantic_core-2.46.2-graalpy311-graalpy242_311_native-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b737c0b280f41143266445de2689c0e49c79307e51c44ce3a77fef2bedad4994", size = 1987772, upload-time = "2026-04-17T09:10:02.357Z" }, + { url = "https://files.pythonhosted.org/packages/c4/1a/0242e5b7b6cf51dbccc065029f0420107b6bf7e191fcb918f5cb71218acf/pydantic_core-2.46.2-graalpy311-graalpy242_311_native-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:1b877d597afb82b4898e35354bba55de6f7f048421ae0edadbb9886ec137b532", size = 2138468, upload-time = "2026-04-17T09:11:51.546Z" }, + { url = "https://files.pythonhosted.org/packages/f3/d2/66c146f421178641bda880b0267c0d57dd84f5fec9ecc8e46be17b480742/pydantic_core-2.46.2-graalpy312-graalpy250_312_native-macosx_10_12_x86_64.whl", hash = "sha256:e9fcabd1857492b5bf16f90258babde50f618f55d046b1309972da2396321ff9", size = 2091621, upload-time = "2026-04-17T09:12:47.501Z" }, + { url = "https://files.pythonhosted.org/packages/ee/b2/c28419aa9fc8055f4ac8e801d1d11c6357351bfa4321ed9bafab3eb98087/pydantic_core-2.46.2-graalpy312-graalpy250_312_native-macosx_11_0_arm64.whl", hash = "sha256:fb3ec2c7f54c07b30d89983ce78dc32c37dd06a972448b8716d609493802d628", size = 1937059, upload-time = "2026-04-17T09:10:53.554Z" }, + { url = "https://files.pythonhosted.org/packages/30/ce/cd0824a2db213dc17113291b7a09b9b0ccd9fbf97daa4b81548703341baf/pydantic_core-2.46.2-graalpy312-graalpy250_312_native-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:130a6c837d819ef33e8c2bf702ed2c3429237ea69807f1140943d6f4bdaf52fa", size = 1997278, upload-time = "2026-04-17T09:12:23.784Z" }, + { url = "https://files.pythonhosted.org/packages/c9/69/47283fe3c0c967d3e9e9cd6c42b70907610c8a6f8d6e8381f1bb55f8006c/pydantic_core-2.46.2-graalpy312-graalpy250_312_native-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c2e25417cec5cd9bddb151e33cb08c50160f317479ecc02b22a95ec18f8fe004", size = 2147096, upload-time = "2026-04-17T09:12:43.124Z" }, + { url = "https://files.pythonhosted.org/packages/16/d5/dec7c127fa722ff56e1ccf1e960ae1318a9f66742135e97bf9771447216f/pydantic_core-2.46.2-pp311-pypy311_pp73-macosx_10_12_x86_64.whl", hash = "sha256:c3ad79ed32004d9de91cacd4b5faaff44d56051392fe1d5526feda596f01af25", size = 2107613, upload-time = "2026-04-17T09:10:36.269Z" }, + { url = "https://files.pythonhosted.org/packages/bc/35/975c109b337260a71c93198baf663982b6b39fe3e584e279548a0969e5d4/pydantic_core-2.46.2-pp311-pypy311_pp73-macosx_11_0_arm64.whl", hash = "sha256:d157c48d28eebe5d46906de06a6a2f2c9e00b67d3e42de1f1b9c2d42b810f77c", size = 1947099, upload-time = "2026-04-17T09:12:15.304Z" }, + { url = "https://files.pythonhosted.org/packages/4e/11/52a971a0f9218631690274be533f05e5ddde5547f0823bb3e9dfd1be49f6/pydantic_core-2.46.2-pp311-pypy311_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7b42c6471288dedc979ac8400d9c9770f03967dd187db1f8d3405d4d182cc714", size = 2133866, upload-time = "2026-04-17T09:12:27.994Z" }, + { url = "https://files.pythonhosted.org/packages/fe/7a/33d94d0698602b2d1712e78c703a33952eb2ca69e02e8e4b208e7f6602b5/pydantic_core-2.46.2-pp311-pypy311_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:4f27bc4801358dc070d6697b41237fce9923d8e69a1ce1e95606ac36c1552dc1", size = 2161721, upload-time = "2026-04-17T09:11:16.111Z" }, + { url = "https://files.pythonhosted.org/packages/b0/cb/0df7ee0a148e9ce0968a80787967ddca9f6b3f8a49152a881b88da262701/pydantic_core-2.46.2-pp311-pypy311_pp73-musllinux_1_1_aarch64.whl", hash = "sha256:e094a8f85db41aa7f6a45c5dac2950afc9862e66832934231962252b5d284eed", size = 2180175, upload-time = "2026-04-17T09:11:41.577Z" }, + { url = "https://files.pythonhosted.org/packages/8e/a8/258a32878140347532be4e44c6f3b1ace3b52b9c9ca7548a65ce18adf4b4/pydantic_core-2.46.2-pp311-pypy311_pp73-musllinux_1_1_armv7l.whl", hash = "sha256:807eeda5551f6884d3b4421578be37be50ddb7a58832348e99617a6714a73748", size = 2319882, upload-time = "2026-04-17T09:10:21.872Z" }, + { url = "https://files.pythonhosted.org/packages/13/b9/5071c298a0f91314a5402b8c56e0efbcebe77085327d0b4df7dc9cb0b674/pydantic_core-2.46.2-pp311-pypy311_pp73-musllinux_1_1_x86_64.whl", hash = "sha256:fcaa1c3c846a7f6686b38fe493d1b2e8007380e293bfef6a9354563c026cbf36", size = 2348065, upload-time = "2026-04-17T09:11:08.263Z" }, + { url = "https://files.pythonhosted.org/packages/75/f3/0a7087e5f861d66ca64ce927230b397cc264c87b712156e6a93b26a459c8/pydantic_core-2.46.2-pp311-pypy311_pp73-win_amd64.whl", hash = "sha256:154dbfdfb11b8cbd8ff4d00d0b81e3d19f4cb4bedd5aa9f091060ba071474c6a", size = 2192159, upload-time = "2026-04-17T09:11:20.123Z" }, ] [[package]] From 44ddc3e7c8bd8546ee59a08e00cb0fa1961f0b71 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Mon, 27 Apr 2026 20:11:55 +0000 Subject: [PATCH 027/462] =?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 ffff30400..52eef29c1 100644 --- a/docs/en/docs/release-notes.md +++ b/docs/en/docs/release-notes.md @@ -9,6 +9,7 @@ hide: ### Internal +* ⬆ Bump pydantic from 2.12.5 to 2.13.2. PR [#15439](https://github.com/fastapi/fastapi/pull/15439) by [@dependabot[bot]](https://github.com/apps/dependabot). * ⬆ Bump pydantic-ai from 1.63.0 to 1.83.0. PR [#15417](https://github.com/fastapi/fastapi/pull/15417) by [@dependabot[bot]](https://github.com/apps/dependabot). * ⬆ Bump prek from 0.3.2 to 0.3.9. PR [#15418](https://github.com/fastapi/fastapi/pull/15418) by [@dependabot[bot]](https://github.com/apps/dependabot). * ⬆ Bump fastar from 0.9.0 to 0.11.0. PR [#15419](https://github.com/fastapi/fastapi/pull/15419) by [@dependabot[bot]](https://github.com/apps/dependabot). From 4bad6d2597f8df0251aa39cf388e3567bfd6290e Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 27 Apr 2026 22:22:06 +0200 Subject: [PATCH 028/462] =?UTF-8?q?=E2=AC=86=20Bump=20CodSpeedHQ/action=20?= =?UTF-8?q?from=204.12.1=20to=204.14.0=20(#15436)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/test.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 1b1daf36b..7380cb75e 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -178,7 +178,7 @@ jobs: - name: Install Dependencies run: uv sync --no-dev --group tests --extra all - name: CodSpeed benchmarks - uses: CodSpeedHQ/action@1c8ae4843586d3ba879736b7f6b7b0c990757fab # v4.12.1 + uses: CodSpeedHQ/action@658a901452bb54c799643e060733b7afe9121b8d # v4.14.0 with: mode: simulation run: uv run --no-sync pytest tests/benchmarks --codspeed From 0e788246341a1fa50fb54fc4914d1b223208faa0 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Mon, 27 Apr 2026 20:22:35 +0000 Subject: [PATCH 029/462] =?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 52eef29c1..a5e36e6cb 100644 --- a/docs/en/docs/release-notes.md +++ b/docs/en/docs/release-notes.md @@ -9,6 +9,7 @@ hide: ### Internal +* ⬆ Bump CodSpeedHQ/action from 4.12.1 to 4.14.0. PR [#15436](https://github.com/fastapi/fastapi/pull/15436) by [@dependabot[bot]](https://github.com/apps/dependabot). * ⬆ Bump pydantic from 2.12.5 to 2.13.2. PR [#15439](https://github.com/fastapi/fastapi/pull/15439) by [@dependabot[bot]](https://github.com/apps/dependabot). * ⬆ Bump pydantic-ai from 1.63.0 to 1.83.0. PR [#15417](https://github.com/fastapi/fastapi/pull/15417) by [@dependabot[bot]](https://github.com/apps/dependabot). * ⬆ Bump prek from 0.3.2 to 0.3.9. PR [#15418](https://github.com/fastapi/fastapi/pull/15418) by [@dependabot[bot]](https://github.com/apps/dependabot). From 1f7c8c1ad328857d158e922da46a573b8b08e38a Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 27 Apr 2026 22:25:27 +0200 Subject: [PATCH 030/462] =?UTF-8?q?=E2=AC=86=20Bump=20sqlmodel=20from=200.?= =?UTF-8?q?0.32=20to=200.0.38=20(#15437)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: Motov Yurii <109919500+YuriiMotov@users.noreply.github.com> --- uv.lock | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/uv.lock b/uv.lock index 2723f635d..b198d9761 100644 --- a/uv.lock +++ b/uv.lock @@ -5105,15 +5105,16 @@ wheels = [ [[package]] name = "sqlmodel" -version = "0.0.32" +version = "0.0.38" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "pydantic" }, { name = "sqlalchemy" }, + { name = "typing-extensions" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/d1/89/67f8964f3b2ed073fa4e95201e708291935d00e3600f36f09c1be3e279fe/sqlmodel-0.0.32.tar.gz", hash = "sha256:48e8fe4c8c3d7d8bf8468db17fa92ca680421e86cfec8b352217ef40736767be", size = 94140, upload-time = "2026-02-01T18:19:14.752Z" } +sdist = { url = "https://files.pythonhosted.org/packages/64/0d/26ec1329960ea9430131fe63f63a95ea4cb8971d49c891ff7e1f3255421c/sqlmodel-0.0.38.tar.gz", hash = "sha256:d583ec237b14103809f74e8630032bc40ab68cd6b754a610f0813c56911a547b", size = 86710, upload-time = "2026-04-02T21:03:55.571Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/ed/de/d9b40ed2c570fd612c2abd57e4d9084a9d8eb1797447e2ce897b77b1c4b2/sqlmodel-0.0.32-py3-none-any.whl", hash = "sha256:d62f0702599592046c1a136d3512feab3d5a80e2988642ef0ed2c89b9b8b297b", size = 27416, upload-time = "2026-02-01T18:19:15.992Z" }, + { url = "https://files.pythonhosted.org/packages/72/c7/10c60af0607ab6fa136264f7f39d205932218516226d38585324ffda705d/sqlmodel-0.0.38-py3-none-any.whl", hash = "sha256:84e3fa990a77395461ded72a6c73173438ce8449d5c1c4d97fbff1b1df692649", size = 27294, upload-time = "2026-04-02T21:03:56.406Z" }, ] [[package]] From 4f64b8f65191b497255004e896a2bbfd7cfd1886 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Mon, 27 Apr 2026 20:25:54 +0000 Subject: [PATCH 031/462] =?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 a5e36e6cb..f849feeb0 100644 --- a/docs/en/docs/release-notes.md +++ b/docs/en/docs/release-notes.md @@ -9,6 +9,7 @@ hide: ### Internal +* ⬆ Bump sqlmodel from 0.0.32 to 0.0.38. PR [#15437](https://github.com/fastapi/fastapi/pull/15437) by [@dependabot[bot]](https://github.com/apps/dependabot). * ⬆ Bump CodSpeedHQ/action from 4.12.1 to 4.14.0. PR [#15436](https://github.com/fastapi/fastapi/pull/15436) by [@dependabot[bot]](https://github.com/apps/dependabot). * ⬆ Bump pydantic from 2.12.5 to 2.13.2. PR [#15439](https://github.com/fastapi/fastapi/pull/15439) by [@dependabot[bot]](https://github.com/apps/dependabot). * ⬆ Bump pydantic-ai from 1.63.0 to 1.83.0. PR [#15417](https://github.com/fastapi/fastapi/pull/15417) by [@dependabot[bot]](https://github.com/apps/dependabot). From a217d2ff2a46475d6d33fcb8245d132f057d1cce Mon Sep 17 00:00:00 2001 From: Alejandra <90076947+alejsdev@users.noreply.github.com> Date: Thu, 30 Apr 2026 12:15:20 +0200 Subject: [PATCH 032/462] =?UTF-8?q?=F0=9F=93=9D=20Add=20FastAPI=20Conf=20'?= =?UTF-8?q?26=20announcement=20to=20docs=20(#15457)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: github-actions[bot] --- README.md | 6 ++++++ docs/en/docs/img/fastapi-conf.jpeg | Bin 0 -> 19284 bytes docs/en/docs/index.md | 6 ++++++ docs/en/overrides/main.html | 7 +++++++ 4 files changed, 19 insertions(+) create mode 100644 docs/en/docs/img/fastapi-conf.jpeg diff --git a/README.md b/README.md index 9ed338a1b..03bcce385 100644 --- a/README.md +++ b/README.md @@ -118,6 +118,12 @@ The key features are: --- +## FastAPI Conf + +[**FastAPI Conf '26**](https://fastapiconf.com) is happening on **October 28, 2026** in **Amsterdam, NL**. All about FastAPI, right from the source. 🎤 + +FastAPI Conf '26 - October 28, 2026 - Amsterdam, NL + ## FastAPI mini documentary There's a [FastAPI mini documentary](https://www.youtube.com/watch?v=mpR8ngthqiE) released at the end of 2025, you can watch it online: diff --git a/docs/en/docs/img/fastapi-conf.jpeg b/docs/en/docs/img/fastapi-conf.jpeg new file mode 100644 index 0000000000000000000000000000000000000000..14e77b997ffa76726974f13b0042c248fa4b1570 GIT binary patch literal 19284 zcmd421$Z32vM4xXd(6ztiJ6(1nVFf{F*7r>9Wyht9a9`LbIdVA%!wghC;$1+J?GxL z-@f<0x4Tc>(^FlNN>$ZTSE*WhU3uLGAWMr&i35N@008)Q0AAMtA^;FL1Ox;)=1JPHyjDhd(`3K}Lp78*J(1_}x`2{tYP0TB@q8Wt%zDIqyNArawk zBEYw*P>@iF(9np4=qTuf|I_Jp0DuAwGy^LK2a*E7P=Melz}F!F{u`5EVBl|@{xg9? zfFQx3pnvD$0RKw=%zKjx91H~Ux(0xMs{@7%j{JtXQ2dwt-=GA3V!(ewY5u2s2&XUD z{|N>9&vpL)CS%-SKKp=%l5OKIyEUob(Oy(}@Gv3Hw6u7m+H1jo+=h@@A#c0o)>W$e zmn0~k$qfO(>%tu|?VV3lq&nLzOFvT6Los&5Je2g&HU0x2)PO>CqYD5U{wEFmML>L! zOHRhLnaa7f zhP&sNWo)z#H-{d=4;K#8gh6cjC8I|2PZMqob_6gIy0==3zF!tmu%{lc(<{gSFaf=n z#0UVCqz;>j5P+r`Kbsut!0Cl9%`CB#r-puWnP9x0YP9DRhN7H_lUH(NFbG%kVcnAilFW0D#`uUR^Ol?Rvpg%StJK{R&`I(>v3+D^E5x zyl&&^Zt23}EyG>tSZ80HdVoL+c&le(r`8Mr1puK^d~JZ7ymuzOCxo_Vza|bmqj|O# z5mQ%rR6WC~wwefBR=Yh3Xc(NFcoPP^V*!8ee_w#HE$TA> zOaNHwG;40~Kx$K?v%b;o@m*!VJwsMOE2Czz%UmlGKTh7`3F1EKB71Gg{N(wIL|TK# z#Cg_ImCO0LLR{5U$JZ{^p^Yw1v$HqK{~};qLBeO8EG_5>2u~0AcN-!5$orfacD}8~ zrlV?ijC=$DUILWgLz**xneyURSdNymc3&?!99H7Qz~*eZ$-JETHs*kvRgm z;@-rx4Z&4Wf+ay>86KAFNte=%@_IV3nkQbfWNq!oi`~t|hq{j%>-U6tSr3kbTW|7# zaqh0AAd zYhQLuV3;m(P7P&X_4S+RPK!!Au=Y;DbJzYjD^^=%X$ws{4t>lX3Ah8)||`OGBHx4M5z0q>4y97es{ z3fn3~TT(JeVLIs3Gsc+HWePfIftJJ{UTg4R!uB|%7hx&`&7h!BlePX58HPxBo$yYl`wAe?mpboV(nc?4RlrK*LPBC zS|gYD<$WK1d^^LEkxSbkB(P>Y3{_qxhn2;or2*q2%a7J1U&|z*Qx;TUSR*_1$L|U5 z=nybhSDnyMlbw-K3G%DR{A8RLo@}h>HJl_98+($O z6~>^4ql}%VSM*qF9z1;5+P;U)E8M`^31j@A!ZW_YaM|PjiKri=#<{y2_IjIIUR1Im zZzSp>T>oZI4DyqP?ziDr1j4_yjO8g z->;o2Pw4ALpW-tx?`xB%o#r{-q@nEMGq^0QZOh_Yua z{>fUI-D!s(O=Bnh~c8#A4PqMe!S#cMt;#+^L~)NQjV5tRYyhsqw_>(byc^u zP0oc4c}RvAzG`y3j2X&7w51;xk6)Kz{5Dir-5~a7e%5@C`g>5eP^&)zTIT3 zVP_Cr@J@u!nJ?kfQFInJQ?~(`N$d|FdR;dk5wwK(@G$>IgYYZ~pYXs}z&~`b%x2Ui;EQMWyzxb>6#q@nn;W&Nt{D?&(sm z(MlxjljdYdxsT=IBB5hhLqnuRBASiys=a&1#r)W~CD%Bz+@+0X#m>5lN7#l4UC??F z1(ccHE}j!|skDugH|Phd30cR%o-^->w(a%p?4&G{zWdzF^Ibw|@uqT;Ng4^Wz}^9+ zU39vcvO;eODp~Dma-&3dQhVp!8sdRj#TW7G2q(G5NQ|11V$_z6vbn9}yLGIWDpYBD zd0{k|)tzsS!Rp4aLZe@33}WMkP=q<@-$nSk_tcpH&l%VLJc z_Q+YIJ_85e;pmdrjH&Pbd1ei?lcO;){xYP|t5PMqN6mEv)F+w!KD{DQ9-exOPWO6ku>!bG9Ari{O-C}%@ zGn%z;1R(9F_ix>Q%JInlEHI?>(aH?+w4@b@ED&LohincIN~iGHMFN@2<-IWJf>36sbD{ zt$Ya8XPh|#7KE#1vNvcX$jn2$LajAkQkk8 zEO<=OYBx+VzW%Qo9It?3bZM=H&Tu#KZ{{72K}k&Y$&B97=7Qfk^GsP60we4!P)ip) zaYArqL`h{sbtmpY8+Yrd49A0psk%yp8foQ+IpPf$?lQ`GriBEwi!>9u+~=st`q~jx z=WxUCPA~>oCOu`5ob~JurQhEd%qQW{E(5+bl6Mt^Eo4i@UJLQsiKohZ))N0y zsJUni_Gmha#5Zf*7iP5SQbJPozxAx()W)GUYhAUu8vn1J&Ob0${%^h%B?v!D z2mS470l~ll5GZI&il`(YWFe&hQbs{Tqdy)LI1nfR{DG`+bLGqu#~{Uh$Fvp2T+Ufy zI7l|FE#Rf0&WX>$39+wgi*4#zFNQM=7jj=>U;Qi4(}`Spq~cWLgELGs$!6NcE{y00 z!j=!7#OcB)cd8#W7{^eZ`jF^4r9WlQ6(^GFx0a{Yl`a{D;weYs-VNXrdAVnesg1jV z4;ifK>PoF!OFj!ZGBatYE91E3^BvnBW+^^EIkf948oC#d=EkEMi)=)lM%XE3+=Tv^ zeiM=8O~khZ{HKHfAQ%9JL=hP^0GybV(eRIKV83O%BE8bCyjNNvbfNi9nIDWHrj?5x ztyxYzL0znUJct6IKz;_vx@I_)OQ<1#l&6U*;t8Pg8{2K+U_n^&v3P4r0{KmwVBiqo z@KBI%&gq*JmD zNq*rK2D#`z+*L>cuvb7m?DBW-Q~&R9xgb5pi^0}yjU)~xn=g17E&H((+SlR-be?1` znB9pT(fX1b!*%5L#>@YE3oOG9zSw9OfD@`}3Ae1Vvm=xU6OetR^|YN5S6P=pX_Cjr zI_-gJl}1J)VlQ6b5tU4z5}di%s(YvrqyOT}usk{U3RslOM5)cR`xxQSy?_Y|ySe)a zCU<#Kh|!o=WDU9krZ-twYa&-x*k`iAXQrB>*ly{6y$d}m^HzkR^IeQ_i(@pCA$g{z zTr?5Rtn+sFqOoi!TWCr@rfZ8IX<+Okvm1VRvG24hzAQ#ujO?9Lv2hGzgkT-L#9pXSZ|X)Cm(GmVJDX+ zTieP~()+xRY^naK3ZK6{>l4{FkFIBE&KvtB%pIwLYK-KS1q&7M6b7X=UG_)q%Y3nK z4ryJON|1bcDA%;;H90ii3{lwWE5JXNZu5|nLcVsIEq%3YxG#D*0c>5ZWzsSKfGG9< zq>EgODioTFq*pAs%_z*|K4Z?(l_#i; z{TVMN8_nvjVaPLcUTo4`e&gZW`17`RlAmtd^rvuQ@(Nyw!T`AnJMRvP|Dg7j) zX{|Q%{fvdW(|JG7rJtJM=5|tU4Go^-?`go}#;fC25h`O!1~ z32H&t{;L=m%5eoL<3q;o)P!B#U3t0@@s#AUkfWWo)ZrldgnU&05%-CC93%)deBQ-` z^($pqY_d)HK%7HxxfX4!&OKNm*Fu(uFahk0ZE3+=?D(r#jqkxCzOwkl8QWOv($Lyg zsL_z7O{8Ynadb`j846D8L_Ublt>yDTX`B*nC8!?n?t9}C>yNg;nzJNYNxvugS837kH>t3V_CUP) zaVN_Nn9rLGdd$8A*i2pKSUtAaF=;JTl#zg2STz*7bobOI$_{TjEiEB})MgJ8i?7a9 zib8~HT;UQ!*q0w}Gs%cVmSNlZJyl~&y_e7G8p>t$(dvZG zUY^c<)#?oE0wYD~uYiPBHw3%%=NVhkYh$`QyAt)8aHLm=S^3C$m>HqQ|XLR=pK=I>Sb<%)=dIx8MLD@Z9Ht9I~` zRX7LVYJki8EQ2uc5$@xAcW=fMjsg-9`0*tPv0meBq$KF3m}(7QvDhs3IOsT|3>~JE z7Lk}xxQIXv@N)P0&!LIT4IS`pO9illv`!2LS_=#9O}!TNcSvUs#3Qj&>~^PkRVaaU zeZ3T?kLoN2S08t6kj~O~z7E;^BJ=sjfbR8WXi|vwpvU#@Sx0fw+8Y#(T|)-fd#7@W zVFvK3qN%JuBW-$*3F0ec`a0$KJ?(syCM@q<6AtlE68yBPl9Io2r|jEP4(o%@E|Kj& zh>`KXSHeYXQXe$j6uQrCoI%^xld$GHwF^z*zPpb%2-GYRq9+;d=LtAxdj%W{j3=dA z+1?-PwC0}s6yD(rh|}b({X98zGYiFakl)d}ffxLxUj4o0Nka1iJyLeaZF8XOZLB@l z=tvqcp5A&^^RId*7N@^WfzuS(?&`@!oF8}uO&&56{Z z*>u69q6{`Ex-_e8N0_f8Ca+Bg7CS~J5y!R-?Cw1&Bpr$xoRfWJ7`&*p6U6N$!d;(( z)934~!N*sCv}V%F_fz{Z_iV;k?l%2ASx(9$hCW|0yE**QGzfO9504eOE7dZq%d#uF zPhxnHz1G5xH_+>aFGOr_BiK=jR4-ibZA8b)J0ok}#>>dqTvx|MjjxDd6F^Qxn|+mu zNaGo8U1mD@ss&-Uch1nv(N~)!8UUr@=In<|=+ebds{719 z5@7>$-;8DO^y_Gw3Ir_G2fSgtA|5wwkXjA+|MVNg_b5HPh62=syLhh7kgPazpB4!B z=w+oES_TmOYiKkB40Q~y3hbWLdrVyHSC`P<-pt^decb|UG@!FkLtlqSb&gAhQ_Xl~ z|JHhcmpg&3#;8fISHMU#CYQr}!c5e=#;CqEA!UWTakD#Ek9}N}pQ`X(H}QX-It?ep z#Y=x17Eh>wHDEIBuzFU*u|x3vuPn>OPC@V=M1TClZnWJUVaG~2uA$G0`yqr^c&|wU^Y)NRBOG%6jQa zfxJZi7;agpcwx=q{rIY8rK3aftF#!!A(P1h^0^5Kub9o3vPq-+@eK$(DsTfe?W^p~ zSHO7bW14(`N!Dgw+KsG+;Fy*!})w_ANS@)loU&D?rL>N=}DegILEA6Yn_DFi?J(a?+RA?$^079Ix;XB~~R1j+H!?w=OuSvkN@G#deQ?odYhz!e2XL^G{?6_uxgqTCRjX1zM5ADx>Ps( z2w4r}&wAvF+HoaLZ4w8br7Hs!?9UQT|xotK(V&g;gS zbgMLhyDM_s+ZW9zUM`(`t)X7_e#+W5@I`iMA5Va^S@j0tPttr9{+jm)?lmP-K{}aQ zlcDZ2_x|jY{-=uAl>?52pYe0T=_{RGz(>nO-XKI$}R znDt-{MZQ(~uK=Pw&=htBpX5I5_Lm8^PstfJ!4!g@HvCJI9y@v%q|FyrU$tH z+p-t$5q+I;H4DW=^}yolo&dk&d^E^!-#>q^y!q!^9UuyTgh@z=(a7o3cjUmt0>cKu zSz^VVtG_>%3Xr@4)QYb3h@y_3H6(UB1u$lR)W#3H`qBIo`FOv`R!m`4(XBWscVaE$ za;M3lEUQW&vv?G8S5VJyjfN^G!mM3-rL6c0K#~Av2S|6S6ez%*R4*res3X7Bm)h)3 z?(wAXx|YA&&prLZ^S_ABSZPb{k)dLWkgy1fH{3yG`C=YQD=vfso(AV&J&`n6Ievwe z?}ug;oz2d@)RUJtAieVWTu28tqVztl&fmII;48#|9Sa5(3+rb?GGiemZc=G$vbAW; zQPhX5Ol)#PI+Gk9we5SG6p6J%Ze7A{pp=L791;SpT%a4$-Zc9hj`bpLlCLr-VZNM6p;i(l~(|@9Yc>U{tZ(H z7gs8Ez)#3v~bhedCY-)| zB*i^V+=J#@jVy9Fk_?@iwot2{L!SXhJyz8j`dJ_ zVz0nMokMyx+ed?o7+v!RH9DrV3i~R3NA4U|Giznc-I%%vCit5IdT0Y)C~Ek7K!D=&Z1g!VtV=a z5no7Lcn3K~s!g+i)M3JaGfk0Kir4aAgLxg*5c`;!og7yLnuX)#9KJL^QO$D}PmCfhG6wt$#E zIVPq@x z^W*J@#Zat9K+)kYb}*!i%x63-VRTNDnFWBb>H@^Yp$43FM9^{R#eI+)kw)q zGvb9|5)+-BK)xCKh>SQ1DgB_CP|;1F>QmXIosy4Hd(`#REyn=nAfgpAkusJ0H!*|Z zc6|9%iWNTRP6Em(Fm}G;36RE(-?(QI$lxT+mye}_1EEE}`Cu<4OVSlh7)oK5>Y>vJFOsR$qsa@n+0 z0-eEe&BaQusfALMngK*$)Do14s>VwayUFH3W_og*;gBEMS~wL?u9c2X!i`MF)(Rop zh-oFwiqmv{%0XDgsFEjUwi9J#Q3)HK`bq~#iI}n*>nNhIj0zMwutL^rDetovGR0bo zyrTh?H?q`wtCCFl_N^ZQ>suc9qpyS^gV0a3Ljz71cip{MW9a+%JoMThIdME$hT?bd zag{CM(Ve|2m`$Z{Uja)xLn_V}+Y6dq&=n${DQYXS0|Iq=qM`>sqY_hlQiz2D$Yxfs zjMyfjAWAUACYu2P0e4Di5APt5|5EGE&#*bA0!k}ii^)4-y!Bgvq!O#JED^W#gA&2S zNva;vYD@3!7#>(>f!Kz^ca=pr6X*o$$e$NU1R<(Q-UV6t5u8kRy?a?KI*_4YnH^ss zJ3Cc~J4-*VsSd1M;?igCK51U!X@9-)<*=;&&>8b} z#e+h#iZ0&Hb7dJES_Bjs$|!D2RBdd>CYqDX+;=NA?rtTShhS@2uK?>!s~$ZvJ6LGw ziGVlP@x2@Ld$9oGA$zsN8P;Njvtf&Ez{hV`}>_tc(%Ln&PeyLGdk#pZK_n?+mMwFcU7g zs=W(BtSI!=JaDwQ5D?I#@dy1~SOGZrir;K$F5Z=UtidQuQ6?ZKvX!Cc3(|3M&#qfl zl4qMKvmn#;eD|KwRMa~vn z6$2twAS|OC4P+W|=H!9ZbEhk_TcP2An2hIQn(+=u0*5vACJakd&!B#Km$Jt=6 zU?D-%?08z#qO)HWN*T@`@#Be8YS(NnYL3B#f##yKWpMpqJ;_#n74(hRw1}x*K?%^W zfOrx5U8)`3@FW)gwo+;~=N8vs_ec5Lhb5*1>jHz#^hY`t9@MPejA1PtLM|%Q@PAv_{SQ^ycWQpik{oJ+sY~@ zd_De*f#a};bT&3N)+EwWnGyzSga8)2C*|yBK&OD5)Tb{noMVA3swzl6SzL-MWaVzIx3byt5m)w}T? za_{pi3bGd^QZCB?T0f-LLSk|U*F0^aVNTU9MiMmElI1ia?8p3LNOB_V!W~9V@Wi8( zWUBFX^pIYdU$m^Q{Q=NmshKd+L5#c=c2Yy17K^}@L$o3X#}Xc6N=KMyuD4-kgp5iz zIK{v$7=BQ*YJTw6hQ6vXqg41&1_yzpcoBPMaiXH8ugei0?0bO8a z;Fp4#3q^H4vTur9!TR>?7`n4^wk#0CK}@BPOM=C8&oZdFWVw;XlB!j%5C`y}Jh1s)o=RI_6xT zD9BC#li?4=nQN6%q~T*>m?Ld77&c_msTZ^Zm}2wN?ihSo!HLyYCvgyWKt)qE*Zr^_ zm-A`lN%C$PXLe4I@rqx?FUnx0E&+s<68KjoXDCca&lvr16j)pAnzpZGftJ}M_i7XG^^_ZoSyhQs zsxZ%tjZmAGzm1x&Oj2X04)f;psR~XRRzR%HqzpJfHm!j;f0oqa77M>SJC`Cx|9}8# zG?#{m&y+Tn{1!aa!(@Tfju-%$60e|GEyW@J_87m9ry3&rCmYc#8@&lFyVyKgE%Uq} zjGGNMV}L-Osh4wCs^!R&^|jP8Co}SEA*7c!Rcbj5X2FuR)%#x>=tUiD{+Jd#Li)F} z0VQN8;VtqJdfup|Fk32&o(00Q$o&bc3ss$2c$&YW#`4Tu!~CQVGX>j~Qr8zB2ShS} z)DgwcAhO$NF$~&MzkOvW;(!h4V58Uhq@9}{0`i^+FO>p|ZhL)9S>|0d{DoV_WQz3erxImMW z$FixWZ_^26+)VTSmlMCq3Z?*JrXK0;@xPgJ{>MDjzv^wK`ezdf;P*lcApW0xV$aL|1HPX8C-Pr_N#tMv;~@N>^G%hX@Kt0PjS$Ge{-$sx$G+#w z^6_6!z6;`0Z%Qzmlf2gaxkeA?ok=}v zr4gZXW|t+Od1ZHge08f^67sh6QdnTlucHfar}(b+Ps*-X`K>u~u>8Kdci~&)Hrn={ zCS>^yK5GFeD8{Tm@|jrhUjfcarLn*}!@UDg==+jlWkJ|^yAL9CgCZF=HF;?M*3I>| zm!URZY_)EL?(9z0OYAJ$J1xuOLgmlAZ%QFUdD~3}_~(XzH?;r(D9CRCE+a-orSHUo z0ki*H=7s!>um?M63+)TL)v_Mk0z*&Ax}zzXwQaEqHr|d>hH{;LgIWb!`y6r3>ww-$ z#_p>I#k7Y2)7R_&5#eCwk(i`gI1%H{IH0574n5b`Z_06rjQ7GLj!ztoeY20 zi~SXqdke}j1|}j48h$5MENGbhm#7@_TU74aALFM$)bqz-KZV^siYtTUA9Y`zHTHke z{7c5&5you9yTv8AA2|Nlal+$_)MVHb0k9e|;0pNPLZt?Meiev9r4F@XYJCV%BF#R8 z5|SXM3WgO6!Sk_zDlpp^0s+5t8|sCo=}JZ6cHafmOMCsA-hYH8mlniRI|Zx+al0Nv zEf6VeV$y0h7!ODP=Ra*o_kupdby(&obZ}&Mve6fecp7U^NIsajX9gPh^BD`cvtXny zS_CxiV{|Kfbw>U$dr}xBJf4j%c0ULiy&~)kPWkMVOhFv*E*411^KR+$SY-|(=?NAC z1u!%QidrrUkRUaV@d*@t)8JdHSgFgp6z4F{V7pX=O5D1UJRZXr2r8z5{8<)Y7*6%G zSxPd15Ec^8BnZ3_QI5f9kBS(>FNEB*lVFFna6SoerXy6DHB!;G$5~T^E27IN1BQhm z#EQ466d1_{77$L83kmjZhX>ul?c$FTwnaFVE%uEewm~vQi-U;JLLyiI`BpsMeWjo_ zPQlQ-Qy&L3hE((%u!3HY9jKhdcj;|v~cBSz9G zHGim(c~S*{ey;QUAZnY-M8ZMBfe#ZIQCKqN{g;E8P{8Wi7wOn*dsRFbLz>U3f2047 zw80Hn?mP{ejkZro0g-^g__9dCdMt?{7w>zIykD>(RtkVz^c*l}TM4iu!ZE2LkUf8B z8i$wuO3AkARjzL+`lU?;tX7cqq(!0CZhiWRAm!$XA^C_H*Nvb%2)Bom+0-7~5iei^ za+?F#j?n-AbOY)YI_!`xXj6K4q$Q>+iAa70Fy+JuINZ*}dVFk1bgu>VBeM4$c;}1f z^H#_{*sELj%R^_y~*D?CIK&AXBorbk9=SW zXAdImBx_owjN{iv5dvKbg)5n(mg{-<8SFojOY8R;8Ov1j8goyiwFwM z&$1%Whrh^}esTax^`yu6E?yRqqB+Ux$-bmc0iJSY_%l3yUg0)R;193Z8Q_lM<(OS< zrq`#)MDLb*=EA#T%Be?@w^{c;L_kSnwqSco>3qUUswZO7?19XP-~rtFG!o$k1$my8 zSYyx??2Rf@CXZ0O4+(|BSUx1!r`*#q_TO}7$>pm_6VH;n*<&|A&&1`BU#xoQL{cK3C$BgGDtjUMDM!+%teK#F?X-+-!_p9usBmybzE-xVbcdb=eJGHfG>bnPo(Cq8w)d%`6nfM8C_lfb9BLSM z{K#`1$=r4kS<~!W>%8+s2ars{7{D9$u!%2O4#r((V*Y8UiH&$v+iNH{MAAf1x^9bT z1@q+e2fPmOfE#!YwGKH-xu4|~7?8Ec>!PvhsBNgsB{|^|fT}1iVJ@weD49^tXv8-O1T0OeB+6_~t zG>{NIgrH|<07eXDH^cN7iTxZ_X)}Ep_JC^(;*umnu>>GM9aB6i5Y=7#B2U44xyR(=f-3;#EP7w@#2sc~5mPvWf1VsdKaAByFc+aa>4n zg*?Zi^d)q;YWrNp2gxBzvOkmeh%~#6aVK5uaApdTlyrc2=-Fk4iRBMN_1c9jv@8r|X(M{Jv>j;x^77dRQ3nIq}p#x8KO_Vy3oeTk5E zarg|TfKvc29G`+g<{`phzOg4RmbM@Pt#qVb_(YFAqQ5(#fYhT1N%DIUlD%6IN}HIE z#mq!)R^-OKkxnF1&{_TmxB`Nq^@bi2@>oFo=X-S+YT^W5)yXtG=-v_H-2{$RG^A{2 zf`e4YC9Za!`mH=!RnhCdXRbjVY{E~ESbUbq{2ziOA<+Fq&^f8~G|mGipn-rF9n#9m zy61iXV1~fgKlv!k(Z9^9V38p?fISz`esT@u6GDH8FXf;PHoR$n{?>4WiO}X3Jgxdj zCnjU_384iU#iY^H*%%+Bhjni9Q9M=@vvD;JcDbQ`d@%!VADc~w%PB5b^3CoaefH-J z?HTPoW-2jS#r6jK<@B{3My59Y*=rcAgU(u!g1G7)Z5fP`hYZQEFNauqMyk%xzija* ze}n}jk^MS^lKqUOPyOb5G`m?>J{@0F-8EEDy0{%v44Nm1r0{w(eV+Q*YemgV35rNm zvxw4~GiOF08UtJRIA!TLXDv0}v#N)Y3{0qIw@dhJEdV(MJ7yjm0I&d75_>?eaIjHO|qmluzQZl&uw9m97FWe4L!-pZov1CvPfuy z2=FIlW<>*r5h*~(Vlb?FhQLhr?WROl2v2lzl~Yz{LF(GzDe$0+1>TnLYTIEs>Q+|hd88D!NYG`1}W?@NMLyg@hifZ^npkv?Ic1vb=C2mhH0qi zh(q2?PL893fduf%T#AaKJ@1xkzjJx$(RaOkN+XGqGm;hSPS>S}#t*~bqF}zEgKP*H zjG4juwacRE180h_Hmj4%t=>bAtY)J`;t5dqWaLd18dl6GD85A7z&efUEv9${c(nfj zghEA$tnCI!&g;+4Kxi!R#loQd*td?Z*lb`#fH#0U;3cVxFJ zqAgH?MJgUV*WYw=ED%6Ikr@}M+8g+mvkJ4Lh|+b?k&A>CXv7t9^Yy{4Z@Qa{H|Q*#KlCi461*@a%DJs=5J1A7+=v;pW=ZydxgEI@|~kf9)U`atozpUXCA@ zWj(>q%vuJ}o4_|}9`h4t5)|ZEZW_KyxJqEe%BSi7j-Kze*`SICQ(<%8vPbW1GcXoE(ZGz(HGP=&_Gt7JmB`AUg{VrPo4~8M#gF2KNeJ z3*tXoeDiKlhDZU<9c#D{k*c#<4~!qXoM0mlYNm4MA9r^iqy%1au=r;Dg$-u&p_4!S zIw)dga0z}M1WGn>=`$5)UH|Z%>bODXuHEsJM+E=G7%Pom)qL*U9tqXQ{PAbF$tUyv z@TmDSkD-QPe6a8Vp7x(m)6}9*QNG_FKmO+Gvx9hUDdFPM(~`gU;4K7DmQgy~Na0Jw z(y};XGmM*Mp`Njvk)mQ-R3q0Cr27(3H<47EGVT@NGoxFa8bbPctm;!Qa(>xilyL6? zOSuiIqGENVBULHZ!f4*n=oUyg7RcrNEQZP&_H~SaqMFPE5r+CWA9@_}^uwN+f=PaZ zohoOxO4qfUPbK(T8BvkKxvyWiXumQ{+B$JDK`-|uSHXwQMfLNWkcOScpBh>B-FxUq zN;7rSC^`A6j-Ha>8<*f;#0L;ySUDX8OrS#cPUmpZ7q5N}2>;sNR5kvQ*QfE@?Zk#? zw-oF2aMh8=*H7?dltma4QJ|T!S<1V{_e2Kv_pa2`(o%z6>Y;GqyI3tKk6IZ+AQTU? zQVB*uGzxKaVrNi=^b;D*^8c{Al~T-4NI>ZBT)tdmk3bZ>Ci{{)oGRHfo(y+|d1w`V z!3AeK9ftr_5b>UP1_5u)^Kn9w5+t-gZG`srg#!tg4=!{ZvLh}D8DZ&Y*v|~%L0R{8 z;G2lC1nkNoeDh1Byz1Olxb;$hGhoIoX0b+8H`KkmZ+pfIIgwCo`DC_4DFHi(>6+Qb zv;Cs>k^yuQ2c2T|F!b(eUtaRlcPOI2q!r;FuoBX*3=>%q1Zoo28;w(NrgtG1!f&JG zm?ek@5SjHz*()U-A}diALvc2mM}Vb3tbVfaUc$pS$0#61mbP(_ZJeCQL@C7MR|)4{ zwhUHu6}@ni6>+)p!cg5fL3=Jm_OayDGAYK%?l?g@6L)0w8_V0b0 z1HE}Io9%&wngo;eG0i0)*m55OuC@>Rw!++Y{)f0Dwpc<)?whSU#gt|kcHW53JNFr| z?$HjF->lX$l%%UtYUMuRM6bst1j6XFD|`FEKtdDNd^Ovt+Lh6cj0Ygtkc)E7j^u-T zZI2?bZVym9_(ohqE4%p}q#XmG6}#4R%$W21z2@@#2R?TFwrx;H&6sd85$_-#5GX_p zKH%7#e{NxC9p~y16nHP}?q6>1@*~4Bl)4OaJ(wfLSd{V$Qz&Kmhk+L~7__z^xQmGH zn4gidlg=aG*^5-qnTmRpPiI`1SZgdr85ciqIdGOL@0y1bLxy09H;7kauE0}+IRSeT zIPAY3x(Hg;m)v+^2M|zF`VKrS+2EqIYi_gpexdYREbe$$todO^_z@8vYbaEx%!&uU z4h3-r#0sFDG4*JEpN4EpN$S*Nm|Dsnp$dT4Cg8y86+t`=1$W~7JiLqrai4_F#mO{7 zEgV5eD2QacAS?y}uqm9mS)nm&)31<<&46g#VQa|XF$B#d2gev040x3bO6?l;;BYo? z=hWbzbr5s^?DtnuHbB5VYRJ+&z$av$t9Fd z``2-Y^MIi9+Mj3Jqzw5^6pQ^%JmFm?Cj5%~xrEf(tVLNWiZ-2d)-t^~#g(*+_pqDL zgYAcw)btj(9$~Ck5ifb~-CTS$(68J3NV-JL#Od|lr!_tj?g`|Yy5@ep&E{j4A=;V| zl>wEvyE!VPo9H zvd8iJyN65nJP1`kk>Sy#r#mn3kzn)%5m$!HuCz6?1>#xTv%Y_+^Iy>P+r+OuqkkK4 zMWgFW!MG0lJr57J^T}8gpi>R@yDa!?c-Q%I1b<#rD-YZqqJAMIK}l8crD1#4kv)gb nC-UEuDLjsWZXdpLe?e0=KgZFT7vx|6!#(r`9~1kx{{Kw?heSE^ literal 0 HcmV?d00001 diff --git a/docs/en/docs/index.md b/docs/en/docs/index.md index 88fcc4545..d5f7c39de 100644 --- a/docs/en/docs/index.md +++ b/docs/en/docs/index.md @@ -117,6 +117,12 @@ The key features are: --- +## FastAPI Conf { #fastapi-conf } + +[**FastAPI Conf '26**](https://fastapiconf.com) is happening on **October 28, 2026** in **Amsterdam, NL**. All about FastAPI, right from the source. 🎤 + +FastAPI Conf '26 - October 28, 2026 - Amsterdam, NL + ## FastAPI mini documentary { #fastapi-mini-documentary } There's a [FastAPI mini documentary](https://www.youtube.com/watch?v=mpR8ngthqiE) released at the end of 2025, you can watch it online: diff --git a/docs/en/overrides/main.html b/docs/en/overrides/main.html index 54c36fbc7..7559de529 100644 --- a/docs/en/overrides/main.html +++ b/docs/en/overrides/main.html @@ -10,6 +10,13 @@ Join the FastAPI Cloud waiting list 🚀 +
From 6b20159c596709731fa764a4c3b0edc55d353f35 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Thu, 30 Apr 2026 10:15:55 +0000 Subject: [PATCH 033/462] =?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 f849feeb0..6e631eb30 100644 --- a/docs/en/docs/release-notes.md +++ b/docs/en/docs/release-notes.md @@ -7,6 +7,10 @@ hide: ## Latest Changes +### Docs + +* 📝 Add FastAPI Conf '26 announcement to docs. PR [#15457](https://github.com/fastapi/fastapi/pull/15457) by [@alejsdev](https://github.com/alejsdev). + ### Internal * ⬆ Bump sqlmodel from 0.0.32 to 0.0.38. PR [#15437](https://github.com/fastapi/fastapi/pull/15437) by [@dependabot[bot]](https://github.com/apps/dependabot). From aff0b7cd43ddce84b2f80780e199e208ef85e6fa Mon Sep 17 00:00:00 2001 From: Alejandra <90076947+alejsdev@users.noreply.github.com> Date: Thu, 30 Apr 2026 15:39:30 +0200 Subject: [PATCH 034/462] =?UTF-8?q?=F0=9F=92=84=20Refactor=20opinions=20se?= =?UTF-8?q?ction=20with=20interactive=20tabs=20and=20new=20logos=20(#15458?= =?UTF-8?q?)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: github-actions[bot] --- README.md | 29 +++---- docs/en/docs/css/custom.css | 110 +++++++++++++++++++++++++++ docs/en/docs/img/logos/cisco.svg | 35 +++++++++ docs/en/docs/img/logos/microsoft.svg | 8 ++ docs/en/docs/img/logos/netflix.svg | 1 + docs/en/docs/img/logos/uber.svg | 39 ++++++++++ docs/en/docs/index.md | 63 ++++++++++----- docs/en/docs/js/custom.js | 38 +++++++++ 8 files changed, 283 insertions(+), 40 deletions(-) create mode 100644 docs/en/docs/img/logos/cisco.svg create mode 100644 docs/en/docs/img/logos/microsoft.svg create mode 100644 docs/en/docs/img/logos/netflix.svg create mode 100644 docs/en/docs/img/logos/uber.svg diff --git a/README.md b/README.md index 03bcce385..b064f31f0 100644 --- a/README.md +++ b/README.md @@ -74,6 +74,13 @@ The key features are: ## Opinions + + +
+ +| [Microsoft](https://github.com/fastapi/fastapi/pull/26 "Microsoft") | [Uber](https://eng.uber.com/ludwig-v0-2/ "Uber") | [Netflix](https://netflixtechblog.com/introducing-dispatch-da4b8a2a8072 "Netflix") | [Cisco](https://www.linkedin.com/posts/deonpillsbury_cisco-cx-python-activity-6963242628536487936-trAp/ "Cisco") | +| :---: | :---: | :---: | :---: | + "_[...] I'm using **FastAPI** a ton these days. [...] I'm actually planning to use it for all of my team's **ML services at Microsoft**. Some of them are getting integrated into the core **Windows** product and some **Office** products._" @@ -92,32 +99,14 @@ The key features are: --- -"_I’m over the moon excited about **FastAPI**. It’s so fun!_" - -
Brian Okken - [Python Bytes](https://pythonbytes.fm/episodes/show/123/time-to-right-the-py-wrongs?time_in_sec=855) podcast host (ref)
- ---- - -"_Honestly, what you've built looks super solid and polished. In many ways, it's what I wanted **Hug** to be - it's really inspiring to see someone build that._" - -
Timothy Crosley - [Hug](https://github.com/hugapi/hug) creator (ref)
- ---- - -"_If you're looking to learn one **modern framework** for building REST APIs, check out **FastAPI** [...] It's fast, easy to use and easy to learn [...]_" - -"_We've switched over to **FastAPI** for our **APIs** [...] I think you'll like it [...]_" - -
Ines Montani - Matthew Honnibal - [Explosion AI](https://explosion.ai) founders - [spaCy](https://spacy.io) creators (ref) - (ref)
- ---- - "_If anyone is looking to build a production Python API, I would highly recommend **FastAPI**. It is **beautifully designed**, **simple to use** and **highly scalable**, it has become a **key component** in our API first development strategy and is driving many automations and services such as our Virtual TAC Engineer._"
Deon Pillsbury - Cisco (ref)
--- +
+ ## FastAPI Conf [**FastAPI Conf '26**](https://fastapiconf.com) is happening on **October 28, 2026** in **Amsterdam, NL**. All about FastAPI, right from the source. 🎤 diff --git a/docs/en/docs/css/custom.css b/docs/en/docs/css/custom.css index bbfd49b55..eb9fcf94d 100644 --- a/docs/en/docs/css/custom.css +++ b/docs/en/docs/css/custom.css @@ -264,3 +264,113 @@ Inspired by Termynal's CSS tricks with modifications border-bottom: .05rem dotted var(--md-default-fg-color--light); cursor: help; } + +/* Opinions: interactive logo tabs */ +.fastapi-opinions { + margin: 1.5rem 0 2rem; +} +.fastapi-opinions__tabs { + display: grid; + grid-template-columns: repeat(4, 1fr); + gap: 0.25rem; + margin-bottom: 1rem; +} +.fastapi-opinions__tab { + appearance: none; + background: none; + border: 0; + padding: 0.5rem; + margin: 0; + cursor: pointer; + display: flex; + align-items: center; + justify-content: center; + border-radius: 6px; + transition: background-color 0.15s; + color: inherit; + font: inherit; + min-height: 40px; + min-width: 0; +} +.fastapi-opinions__tab:hover { + background-color: var(--md-default-fg-color--lightest); +} +.fastapi-opinions__tab:focus-visible { + outline: 2px solid var(--md-primary-fg-color); + outline-offset: 2px; +} +.fastapi-opinions__mark { + display: flex; + align-items: center; + justify-content: center; + height: 20px; + max-width: 100%; + filter: grayscale(1); + opacity: 0.5; + transition: filter 0.2s, opacity 0.2s; +} +.fastapi-opinions__mark img { + height: 100%; + width: auto; + max-width: 100%; + object-fit: contain; + display: block; +} +.fastapi-opinions__tab:hover .fastapi-opinions__mark { + filter: grayscale(0.3); + opacity: 0.85; +} +.fastapi-opinions__tab[aria-selected="true"] { + background-color: var(--md-default-fg-color--lightest); +} +.fastapi-opinions__tab[aria-selected="true"] .fastapi-opinions__mark { + filter: grayscale(0); + opacity: 1; +} + +/* Dark mode: brighten dark wordmarks so they read on slate */ +[data-md-color-scheme="slate"] .fastapi-opinions__mark { + filter: grayscale(1) invert(0.85); +} +[data-md-color-scheme="slate"] .fastapi-opinions__tab:hover .fastapi-opinions__mark { + filter: grayscale(0.3) invert(0.4); +} +[data-md-color-scheme="slate"] .fastapi-opinions__tab[aria-selected="true"] .fastapi-opinions__mark { + filter: none; +} + +.fastapi-opinions__panel { + background-color: rgba(0, 148, 133, 0.06); + border-left: 2px solid var(--md-primary-fg-color); + padding: 1rem 1.25rem; + border-radius: 0 4px 4px 0; +} +.fastapi-opinions__quote { + margin: 0; + font-size: 0.9rem; + font-style: italic; + line-height: 1.6; + color: var(--md-default-fg-color); +} +.fastapi-opinions__quote strong { font-style: normal; } +.fastapi-opinions__attr { + margin-top: 0.625rem; + font-size: 0.75rem; + color: var(--md-default-fg-color--light); +} +.fastapi-opinions__attr strong { color: var(--md-default-fg-color); } +.fastapi-opinions__attr a { + color: var(--md-primary-fg-color); + text-decoration: none; + font-size: 0.7rem; + margin-left: 0.25rem; +} +.fastapi-opinions__attr a:hover { text-decoration: underline; } + +@media (max-width: 600px) { + .fastapi-opinions__tabs { gap: 0.125rem; } + .fastapi-opinions__mark { height: 18px; } +} + +/* Hidden in MkDocs; rendered on GitHub (which doesn't load this stylesheet) */ +.only-github { display: none; } diff --git a/docs/en/docs/img/logos/cisco.svg b/docs/en/docs/img/logos/cisco.svg new file mode 100644 index 000000000..b1f6ae27b --- /dev/null +++ b/docs/en/docs/img/logos/cisco.svg @@ -0,0 +1,35 @@ + + + + + + + + + + + diff --git a/docs/en/docs/img/logos/microsoft.svg b/docs/en/docs/img/logos/microsoft.svg new file mode 100644 index 000000000..e77821b28 --- /dev/null +++ b/docs/en/docs/img/logos/microsoft.svg @@ -0,0 +1,8 @@ + + + + + + + + diff --git a/docs/en/docs/img/logos/netflix.svg b/docs/en/docs/img/logos/netflix.svg new file mode 100644 index 000000000..3c015f960 --- /dev/null +++ b/docs/en/docs/img/logos/netflix.svg @@ -0,0 +1 @@ + diff --git a/docs/en/docs/img/logos/uber.svg b/docs/en/docs/img/logos/uber.svg new file mode 100644 index 000000000..bc0bd54d8 --- /dev/null +++ b/docs/en/docs/img/logos/uber.svg @@ -0,0 +1,39 @@ + + + + + + + + + + + diff --git a/docs/en/docs/index.md b/docs/en/docs/index.md index d5f7c39de..44bc22d82 100644 --- a/docs/en/docs/index.md +++ b/docs/en/docs/index.md @@ -73,6 +73,47 @@ The key features are: ## Opinions { #opinions } + +
+
+ + + + +
+ +
+
"I'm using FastAPI a ton these days. I'm actually planning to use it for all of my team's ML services at Microsoft. Some of them are getting integrated into the core Windows product and some Office products."
+
— Kabir Khan, Microsoft (ref)
+
+ + + +
+ + +
+ +| [Microsoft](https://github.com/fastapi/fastapi/pull/26 "Microsoft") | [Uber](https://eng.uber.com/ludwig-v0-2/ "Uber") | [Netflix](https://netflixtechblog.com/introducing-dispatch-da4b8a2a8072 "Netflix") | [Cisco](https://www.linkedin.com/posts/deonpillsbury_cisco-cx-python-activity-6963242628536487936-trAp/ "Cisco") | +| :---: | :---: | :---: | :---: | + "_[...] I'm using **FastAPI** a ton these days. [...] I'm actually planning to use it for all of my team's **ML services at Microsoft**. Some of them are getting integrated into the core **Windows** product and some **Office** products._"
Kabir Khan - Microsoft (ref)
@@ -91,32 +132,14 @@ The key features are: --- -"_I’m over the moon excited about **FastAPI**. It’s so fun!_" - -
Brian Okken - [Python Bytes](https://pythonbytes.fm/episodes/show/123/time-to-right-the-py-wrongs?time_in_sec=855) podcast host (ref)
- ---- - -"_Honestly, what you've built looks super solid and polished. In many ways, it's what I wanted **Hug** to be - it's really inspiring to see someone build that._" - -
Timothy Crosley - [Hug](https://github.com/hugapi/hug) creator (ref)
- ---- - -"_If you're looking to learn one **modern framework** for building REST APIs, check out **FastAPI** [...] It's fast, easy to use and easy to learn [...]_" - -"_We've switched over to **FastAPI** for our **APIs** [...] I think you'll like it [...]_" - -
Ines Montani - Matthew Honnibal - [Explosion AI](https://explosion.ai) founders - [spaCy](https://spacy.io) creators (ref) - (ref)
- ---- - "_If anyone is looking to build a production Python API, I would highly recommend **FastAPI**. It is **beautifully designed**, **simple to use** and **highly scalable**, it has become a **key component** in our API first development strategy and is driving many automations and services such as our Virtual TAC Engineer._"
Deon Pillsbury - Cisco (ref)
--- +
+ ## FastAPI Conf { #fastapi-conf } [**FastAPI Conf '26**](https://fastapiconf.com) is happening on **October 28, 2026** in **Amsterdam, NL**. All about FastAPI, right from the source. 🎤 diff --git a/docs/en/docs/js/custom.js b/docs/en/docs/js/custom.js index 311995d7c..a4db853f5 100644 --- a/docs/en/docs/js/custom.js +++ b/docs/en/docs/js/custom.js @@ -201,11 +201,49 @@ function openLinksInNewTab() { }); } +function setupOpinionsTabs() { + const root = document.querySelector('.fastapi-opinions'); + if (!root) return; + const tabs = Array.from(root.querySelectorAll('[role="tab"]')); + const panels = Array.from(root.querySelectorAll('[role="tabpanel"]')); + if (!tabs.length) return; + + function activate(tab, focus) { + tabs.forEach(t => { + const selected = t === tab; + t.setAttribute('aria-selected', selected ? 'true' : 'false'); + t.setAttribute('tabindex', selected ? '0' : '-1'); + }); + const targetId = tab.getAttribute('aria-controls'); + panels.forEach(p => { + if (p.id === targetId) p.removeAttribute('hidden'); + else p.setAttribute('hidden', ''); + }); + if (focus) tab.focus(); + } + + tabs.forEach((tab, i) => { + tab.addEventListener('click', () => activate(tab, false)); + tab.addEventListener('keydown', (e) => { + let next = null; + if (e.key === 'ArrowRight') next = tabs[(i + 1) % tabs.length]; + else if (e.key === 'ArrowLeft') next = tabs[(i - 1 + tabs.length) % tabs.length]; + else if (e.key === 'Home') next = tabs[0]; + else if (e.key === 'End') next = tabs[tabs.length - 1]; + if (next) { + e.preventDefault(); + activate(next, true); + } + }); + }); +} + async function main() { setupTermynal(); showRandomAnnouncement('announce-left', 5000) handleSponsorImages(); openLinksInNewTab(); + setupOpinionsTabs(); } document$.subscribe(() => { main() From a3ceb9ca7415d8874233edac857e85e47d2a6680 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Thu, 30 Apr 2026 13:40:02 +0000 Subject: [PATCH 035/462] =?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 6e631eb30..b4db8913c 100644 --- a/docs/en/docs/release-notes.md +++ b/docs/en/docs/release-notes.md @@ -9,6 +9,7 @@ hide: ### Docs +* 💄 Refactor opinions section with interactive tabs and new logos. PR [#15458](https://github.com/fastapi/fastapi/pull/15458) by [@alejsdev](https://github.com/alejsdev). * 📝 Add FastAPI Conf '26 announcement to docs. PR [#15457](https://github.com/fastapi/fastapi/pull/15457) by [@alejsdev](https://github.com/alejsdev). ### Internal From b363a1d0023b25fba9231c17ae371c9d44c65c68 Mon Sep 17 00:00:00 2001 From: Alejandra <90076947+alejsdev@users.noreply.github.com> Date: Thu, 30 Apr 2026 18:03:33 +0200 Subject: [PATCH 036/462] =?UTF-8?q?=F0=9F=92=84=20Improve=20layout=20and?= =?UTF-8?q?=20styling=20(#15462)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: github-actions[bot] --- README.md | 12 ++-- docs/en/docs/css/custom.css | 116 +++++++++++++++++++++++++++++------- docs/en/docs/index.md | 26 ++++---- scripts/docs.py | 8 ++- 4 files changed, 123 insertions(+), 39 deletions(-) diff --git a/README.md b/README.md index b064f31f0..97f794475 100644 --- a/README.md +++ b/README.md @@ -49,7 +49,7 @@ The key features are: -### Gold and Silver Sponsors +### Gold Sponsors @@ -61,6 +61,9 @@ The key features are: + +### Silver Sponsors + @@ -78,9 +81,6 @@ The key features are:
-| [Microsoft](https://github.com/fastapi/fastapi/pull/26 "Microsoft") | [Uber](https://eng.uber.com/ludwig-v0-2/ "Uber") | [Netflix](https://netflixtechblog.com/introducing-dispatch-da4b8a2a8072 "Netflix") | [Cisco](https://www.linkedin.com/posts/deonpillsbury_cisco-cx-python-activity-6963242628536487936-trAp/ "Cisco") | -| :---: | :---: | :---: | :---: | - "_[...] I'm using **FastAPI** a ton these days. [...] I'm actually planning to use it for all of my team's **ML services at Microsoft**. Some of them are getting integrated into the core **Windows** product and some **Office** products._"
Kabir Khan - Microsoft (ref)
@@ -111,13 +111,13 @@ The key features are: [**FastAPI Conf '26**](https://fastapiconf.com) is happening on **October 28, 2026** in **Amsterdam, NL**. All about FastAPI, right from the source. 🎤 -FastAPI Conf '26 - October 28, 2026 - Amsterdam, NL +FastAPI Conf '26 - October 28, 2026 - Amsterdam, NL ## FastAPI mini documentary There's a [FastAPI mini documentary](https://www.youtube.com/watch?v=mpR8ngthqiE) released at the end of 2025, you can watch it online: -FastAPI Mini Documentary +FastAPI Mini Documentary ## **Typer**, the FastAPI of CLIs diff --git a/docs/en/docs/css/custom.css b/docs/en/docs/css/custom.css index eb9fcf94d..147181c48 100644 --- a/docs/en/docs/css/custom.css +++ b/docs/en/docs/css/custom.css @@ -273,37 +273,51 @@ Inspired by Termynal's CSS tricks with modifications display: grid; grid-template-columns: repeat(4, 1fr); gap: 0.25rem; - margin-bottom: 1rem; + margin-bottom: 1.5rem; + border-bottom: 1px solid var(--md-default-fg-color--lightest); } .fastapi-opinions__tab { + position: relative; appearance: none; background: none; border: 0; - padding: 0.5rem; + padding: 0.625rem 0.5rem; margin: 0; cursor: pointer; display: flex; align-items: center; justify-content: center; - border-radius: 6px; - transition: background-color 0.15s; color: inherit; font: inherit; min-height: 40px; min-width: 0; } -.fastapi-opinions__tab:hover { - background-color: var(--md-default-fg-color--lightest); +.fastapi-opinions__tab::after { + content: ""; + position: absolute; + left: 50%; + right: 50%; + bottom: -1px; + height: 2px; + background-color: var(--md-primary-fg-color); + opacity: 0; + transition: left 0.2s ease, right 0.2s ease, opacity 0.2s ease; +} +.fastapi-opinions__tab[aria-selected="true"]::after { + left: 12%; + right: 12%; + opacity: 1; } .fastapi-opinions__tab:focus-visible { outline: 2px solid var(--md-primary-fg-color); outline-offset: 2px; + border-radius: 4px; } .fastapi-opinions__mark { display: flex; align-items: center; justify-content: center; - height: 20px; + height: 22px; max-width: 100%; filter: grayscale(1); opacity: 0.5; @@ -320,9 +334,6 @@ Inspired by Termynal's CSS tricks with modifications filter: grayscale(0.3); opacity: 0.85; } -.fastapi-opinions__tab[aria-selected="true"] { - background-color: var(--md-default-fg-color--lightest); -} .fastapi-opinions__tab[aria-selected="true"] .fastapi-opinions__mark { filter: grayscale(0); opacity: 1; @@ -340,36 +351,101 @@ Inspired by Termynal's CSS tricks with modifications } .fastapi-opinions__panel { - background-color: rgba(0, 148, 133, 0.06); - border-left: 2px solid var(--md-primary-fg-color); - padding: 1rem 1.25rem; - border-radius: 0 4px 4px 0; + position: relative; + padding: 0.5rem 1rem 0.5rem 3rem; +} +.fastapi-opinions__panel::before { + content: "\201C"; + position: absolute; + top: -0.75rem; + left: 0.25rem; + font-family: Georgia, "Times New Roman", serif; + font-size: 4rem; + line-height: 1; + color: var(--md-primary-fg-color); + opacity: 0.18; + pointer-events: none; } -.fastapi-opinions__quote { +.md-typeset blockquote.fastapi-opinions__quote { margin: 0; - font-size: 0.9rem; + font-size: 1rem; font-style: italic; - line-height: 1.6; + line-height: 1.65; color: var(--md-default-fg-color); + border-left: 0; + padding-left: 0; } .fastapi-opinions__quote strong { font-style: normal; } .fastapi-opinions__attr { - margin-top: 0.625rem; - font-size: 0.75rem; + margin-top: 0.875rem; + font-size: 0.8rem; color: var(--md-default-fg-color--light); } .fastapi-opinions__attr strong { color: var(--md-default-fg-color); } .fastapi-opinions__attr a { color: var(--md-primary-fg-color); text-decoration: none; - font-size: 0.7rem; + font-size: 0.75rem; margin-left: 0.25rem; } .fastapi-opinions__attr a:hover { text-decoration: underline; } +@media (prefers-reduced-motion: reduce) { + .fastapi-opinions__tab::after { transition: none; } +} + @media (max-width: 600px) { .fastapi-opinions__tabs { gap: 0.125rem; } .fastapi-opinions__mark { height: 18px; } + .fastapi-opinions__panel { padding-left: 2.25rem; } + .fastapi-opinions__panel::before { font-size: 3rem; } +} + +.fastapi-sponsors { + display: flex; + flex-wrap: wrap; + justify-content: center; + align-items: center; + gap: 1rem 1.25rem; + margin: 1rem 0 2rem; +} + +.fastapi-sponsors__card { + transition: transform 0.15s ease; +} + +.fastapi-sponsors__card:hover { + transform: translateY(-1px); +} + +.fastapi-sponsors__card--keystone { + width: 100%; + max-width: 560px; +} + +.fastapi-sponsors__banner { + display: block; + border-radius: 12px; +} + +.fastapi-sponsors__card--keystone .fastapi-sponsors__banner { width: 100%; } +.fastapi-sponsors__card--gold .fastapi-sponsors__banner { height: 80px; } +.fastapi-sponsors__card--silver .fastapi-sponsors__banner { height: 60px; } + +@media (max-width: 600px) { + .fastapi-sponsors__card--gold .fastapi-sponsors__banner { height: 64px; } + .fastapi-sponsors__card--silver .fastapi-sponsors__banner { height: 50px; } +} + +.fastapi-feature-banner { + display: block; + max-width: 680px; + margin: 1rem auto 1.5rem; +} +.fastapi-feature-banner img { + display: block; + width: 100%; + border-radius: 12px; } /* Hidden in MkDocs; rendered on GitHub (which doesn't load this stylesheet) */ diff --git a/docs/en/docs/index.md b/docs/en/docs/index.md index 44bc22d82..026961e25 100644 --- a/docs/en/docs/index.md +++ b/docs/en/docs/index.md @@ -54,18 +54,27 @@ The key features are: ### Keystone Sponsor { #keystone-sponsor } +
{% for sponsor in sponsors.keystone -%} - +{{ sponsor.title }} {% endfor -%} +
-### Gold and Silver Sponsors { #gold-and-silver-sponsors } +### Gold Sponsors { #gold-sponsors } +
{% for sponsor in sponsors.gold -%} - +{{ sponsor.title }} {% endfor -%} -{%- for sponsor in sponsors.silver -%} - +
+ +### Silver Sponsors { #silver-sponsors } + +
+{% for sponsor in sponsors.silver -%} +{{ sponsor.title }} {% endfor %} +
@@ -111,9 +120,6 @@ The key features are:
-| [Microsoft](https://github.com/fastapi/fastapi/pull/26 "Microsoft") | [Uber](https://eng.uber.com/ludwig-v0-2/ "Uber") | [Netflix](https://netflixtechblog.com/introducing-dispatch-da4b8a2a8072 "Netflix") | [Cisco](https://www.linkedin.com/posts/deonpillsbury_cisco-cx-python-activity-6963242628536487936-trAp/ "Cisco") | -| :---: | :---: | :---: | :---: | - "_[...] I'm using **FastAPI** a ton these days. [...] I'm actually planning to use it for all of my team's **ML services at Microsoft**. Some of them are getting integrated into the core **Windows** product and some **Office** products._"
Kabir Khan - Microsoft (ref)
@@ -144,13 +150,13 @@ The key features are: [**FastAPI Conf '26**](https://fastapiconf.com) is happening on **October 28, 2026** in **Amsterdam, NL**. All about FastAPI, right from the source. 🎤 -FastAPI Conf '26 - October 28, 2026 - Amsterdam, NL +FastAPI Conf '26 - October 28, 2026 - Amsterdam, NL ## FastAPI mini documentary { #fastapi-mini-documentary } There's a [FastAPI mini documentary](https://www.youtube.com/watch?v=mpR8ngthqiE) released at the end of 2025, you can watch it online: -FastAPI Mini Documentary +FastAPI Mini Documentary ## **Typer**, the FastAPI of CLIs { #typer-the-fastapi-of-clis } diff --git a/scripts/docs.py b/scripts/docs.py index 39845144b..c36f976d5 100644 --- a/scripts/docs.py +++ b/scripts/docs.py @@ -190,12 +190,14 @@ index_sponsors_template = """ {% for sponsor in sponsors.keystone -%} {% endfor %} -### Gold and Silver Sponsors +### Gold Sponsors {% for sponsor in sponsors.gold -%} -{% endfor -%} -{%- for sponsor in sponsors.silver -%} +{% endfor %} +### Silver Sponsors + +{% for sponsor in sponsors.silver -%} {% endfor %} From d8a2c1edaa793ae926e0ac76b242a1c6631eefd1 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Thu, 30 Apr 2026 16:04:10 +0000 Subject: [PATCH 037/462] =?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 b4db8913c..b5a5e5fcb 100644 --- a/docs/en/docs/release-notes.md +++ b/docs/en/docs/release-notes.md @@ -9,6 +9,7 @@ hide: ### Docs +* 💄 Improve layout and styling. PR [#15462](https://github.com/fastapi/fastapi/pull/15462) by [@alejsdev](https://github.com/alejsdev). * 💄 Refactor opinions section with interactive tabs and new logos. PR [#15458](https://github.com/fastapi/fastapi/pull/15458) by [@alejsdev](https://github.com/alejsdev). * 📝 Add FastAPI Conf '26 announcement to docs. PR [#15457](https://github.com/fastapi/fastapi/pull/15457) by [@alejsdev](https://github.com/alejsdev). From 33ed5aecdf978bc2802bde4505d368f96f3c279f Mon Sep 17 00:00:00 2001 From: Motov Yurii <109919500+YuriiMotov@users.noreply.github.com> Date: Fri, 1 May 2026 16:29:41 +0200 Subject: [PATCH 038/462] =?UTF-8?q?=F0=9F=91=B7=20Fix=20missing=20credenti?= =?UTF-8?q?als=20issue=20in=20`translate`=20workflow=20(#15468)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .github/workflows/translate.yml | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/.github/workflows/translate.yml b/.github/workflows/translate.yml index 22fd7e4f1..87023623e 100644 --- a/.github/workflows/translate.yml +++ b/.github/workflows/translate.yml @@ -79,6 +79,8 @@ jobs: if: github.repository_owner == 'fastapi' needs: langs runs-on: ubuntu-latest + permissions: + contents: write strategy: matrix: lang: ${{ fromJson(needs.langs.outputs.langs) }} @@ -91,7 +93,7 @@ jobs: - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 with: fetch-depth: 0 - persist-credentials: false + persist-credentials: true # Required for `git push` in `translate.py` - name: Set up Python uses: actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405 # v6.2.0 with: From e0a2c75b1a980c52c336cfefd12f2277238c4e8f Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Fri, 1 May 2026 14:30:09 +0000 Subject: [PATCH 039/462] =?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 b5a5e5fcb..644918e9c 100644 --- a/docs/en/docs/release-notes.md +++ b/docs/en/docs/release-notes.md @@ -15,6 +15,7 @@ hide: ### Internal +* 👷 Fix missing credentials issue in `translate` workflow. PR [#15468](https://github.com/fastapi/fastapi/pull/15468) by [@YuriiMotov](https://github.com/YuriiMotov). * ⬆ Bump sqlmodel from 0.0.32 to 0.0.38. PR [#15437](https://github.com/fastapi/fastapi/pull/15437) by [@dependabot[bot]](https://github.com/apps/dependabot). * ⬆ Bump CodSpeedHQ/action from 4.12.1 to 4.14.0. PR [#15436](https://github.com/fastapi/fastapi/pull/15436) by [@dependabot[bot]](https://github.com/apps/dependabot). * ⬆ Bump pydantic from 2.12.5 to 2.13.2. PR [#15439](https://github.com/fastapi/fastapi/pull/15439) by [@dependabot[bot]](https://github.com/apps/dependabot). From bc8b1d101caf6316b2a4e8214ff384c7ee5487a0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebasti=C3=A1n=20Ram=C3=ADrez?= Date: Sun, 3 May 2026 15:26:47 +0200 Subject: [PATCH 040/462] =?UTF-8?q?=F0=9F=91=A5=20Update=20FastAPI=20Peopl?= =?UTF-8?q?e=20-=20Contributors=20and=20Translators=20(#15467)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: github-actions[bot] --- docs/en/data/contributors.yml | 12 ++++++------ docs/en/data/translation_reviewers.yml | 12 ++++++------ docs/en/data/translators.yml | 4 ++-- 3 files changed, 14 insertions(+), 14 deletions(-) diff --git a/docs/en/data/contributors.yml b/docs/en/data/contributors.yml index e003b3a42..10bb2be96 100644 --- a/docs/en/data/contributors.yml +++ b/docs/en/data/contributors.yml @@ -1,21 +1,21 @@ tiangolo: login: tiangolo - count: 935 + count: 942 avatarUrl: https://avatars.githubusercontent.com/u/1326112?u=cb5d06e73a9e1998141b1641aa88e443c6717651&v=4 url: https://github.com/tiangolo dependabot: login: dependabot - count: 157 + count: 189 avatarUrl: https://avatars.githubusercontent.com/in/29110?v=4 url: https://github.com/apps/dependabot YuriiMotov: login: YuriiMotov - count: 66 + count: 70 avatarUrl: https://avatars.githubusercontent.com/u/109919500?u=bc48be95c429989224786106b027f3c5e40cc354&v=4 url: https://github.com/YuriiMotov alejsdev: login: alejsdev - count: 53 + count: 56 avatarUrl: https://avatars.githubusercontent.com/u/90076947?u=0facffe3abf87f57a1f05fa773d1119cc5c2f6a5&v=4 url: https://github.com/alejsdev pre-commit-ci: @@ -35,7 +35,7 @@ Kludex: url: https://github.com/Kludex svlandeg: login: svlandeg - count: 21 + count: 23 avatarUrl: https://avatars.githubusercontent.com/u/8796347?u=556c97650c27021911b0b9447ec55e75987b0e8a&v=4 url: https://github.com/svlandeg dmontagu: @@ -556,7 +556,7 @@ chailandau: DanielKusyDev: login: DanielKusyDev count: 2 - avatarUrl: https://avatars.githubusercontent.com/u/36250676?u=2ea6114ff751fc48b55f231987a0e2582c6b1bd2&v=4 + avatarUrl: https://avatars.githubusercontent.com/u/36250676?u=411f1f5923596480b896d160e23c908318f39003&v=4 url: https://github.com/DanielKusyDev Viicos: login: Viicos diff --git a/docs/en/data/translation_reviewers.yml b/docs/en/data/translation_reviewers.yml index 480bf72f3..4216d0d07 100644 --- a/docs/en/data/translation_reviewers.yml +++ b/docs/en/data/translation_reviewers.yml @@ -65,7 +65,7 @@ nilslindemann: url: https://github.com/nilslindemann YuriiMotov: login: YuriiMotov - count: 66 + count: 67 avatarUrl: https://avatars.githubusercontent.com/u/109919500?u=bc48be95c429989224786106b027f3c5e40cc354&v=4 url: https://github.com/YuriiMotov cassiobotaro: @@ -301,7 +301,7 @@ delhi09: rogerbrinkmann: login: rogerbrinkmann count: 20 - avatarUrl: https://avatars.githubusercontent.com/u/5690226?v=4 + avatarUrl: https://avatars.githubusercontent.com/u/5690226?u=a1fe0aee927d33ce9db8c455eabc40c1cdf2bb65&v=4 url: https://github.com/rogerbrinkmann DevDae: login: DevDae @@ -471,7 +471,7 @@ NastasiaSaby: oandersonmagalhaes: login: oandersonmagalhaes count: 12 - avatarUrl: https://avatars.githubusercontent.com/u/83456692?v=4 + avatarUrl: https://avatars.githubusercontent.com/u/83456692?u=daf5f302a59b950efc6d21129314af207e35441f&v=4 url: https://github.com/oandersonmagalhaes mkdir700: login: mkdir700 @@ -906,7 +906,7 @@ bankofsardine: Rekl0w: login: Rekl0w count: 6 - avatarUrl: https://avatars.githubusercontent.com/u/91488737?u=3b62b04a3e6699eab9b1eea4e88c09a39b753a17&v=4 + avatarUrl: https://avatars.githubusercontent.com/u/91488737?u=7d2b7791665e04a12695150776a1d516a6ea7d21&v=4 url: https://github.com/Rekl0w rsip22: login: rsip22 @@ -1276,7 +1276,7 @@ rafsaf: frnsimoes: login: frnsimoes count: 3 - avatarUrl: https://avatars.githubusercontent.com/u/66239468?u=98fb2a38bcac765ea9651af8a0ab8f37df86570d&v=4 + avatarUrl: https://avatars.githubusercontent.com/u/66239468?u=bd788dabd4d9321455db8b8751c1a2676783f50f&v=4 url: https://github.com/frnsimoes lieryan: login: lieryan @@ -1606,7 +1606,7 @@ ayr-ton: Kadermiyanyedi: login: Kadermiyanyedi count: 2 - avatarUrl: https://avatars.githubusercontent.com/u/48386782?u=e34f31bf50a8ed8d37fbfa4f301b0c190b1b4b86&v=4 + avatarUrl: https://avatars.githubusercontent.com/u/48386782?u=08c0f1594c5baf28b6fab7520a848cb9c3806c8e&v=4 url: https://github.com/Kadermiyanyedi raphaelauv: login: raphaelauv diff --git a/docs/en/data/translators.yml b/docs/en/data/translators.yml index 395025f44..5f4208fe2 100644 --- a/docs/en/data/translators.yml +++ b/docs/en/data/translators.yml @@ -386,7 +386,7 @@ dukkee: oandersonmagalhaes: login: oandersonmagalhaes count: 2 - avatarUrl: https://avatars.githubusercontent.com/u/83456692?v=4 + avatarUrl: https://avatars.githubusercontent.com/u/83456692?u=daf5f302a59b950efc6d21129314af207e35441f&v=4 url: https://github.com/oandersonmagalhaes leandrodesouzadev: login: leandrodesouzadev @@ -416,7 +416,7 @@ ayr-ton: Kadermiyanyedi: login: Kadermiyanyedi count: 2 - avatarUrl: https://avatars.githubusercontent.com/u/48386782?u=e34f31bf50a8ed8d37fbfa4f301b0c190b1b4b86&v=4 + avatarUrl: https://avatars.githubusercontent.com/u/48386782?u=08c0f1594c5baf28b6fab7520a848cb9c3806c8e&v=4 url: https://github.com/Kadermiyanyedi KdHyeon0661: login: KdHyeon0661 From 205bd85a4605bbf9746167b41c57559e160e93ab Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Sun, 3 May 2026 13:27:17 +0000 Subject: [PATCH 041/462] =?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 644918e9c..ca0adcfee 100644 --- a/docs/en/docs/release-notes.md +++ b/docs/en/docs/release-notes.md @@ -15,6 +15,7 @@ hide: ### Internal +* 👥 Update FastAPI People - Contributors and Translators. PR [#15467](https://github.com/fastapi/fastapi/pull/15467) by [@tiangolo](https://github.com/tiangolo). * 👷 Fix missing credentials issue in `translate` workflow. PR [#15468](https://github.com/fastapi/fastapi/pull/15468) by [@YuriiMotov](https://github.com/YuriiMotov). * ⬆ Bump sqlmodel from 0.0.32 to 0.0.38. PR [#15437](https://github.com/fastapi/fastapi/pull/15437) by [@dependabot[bot]](https://github.com/apps/dependabot). * ⬆ Bump CodSpeedHQ/action from 4.12.1 to 4.14.0. PR [#15436](https://github.com/fastapi/fastapi/pull/15436) by [@dependabot[bot]](https://github.com/apps/dependabot). From 8da79ec2fe9f80c66e957745fb04a19a452aaa05 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebasti=C3=A1n=20Ram=C3=ADrez?= Date: Sun, 3 May 2026 15:37:17 +0200 Subject: [PATCH 042/462] =?UTF-8?q?=F0=9F=91=A5=20Update=20FastAPI=20Peopl?= =?UTF-8?q?e=20-=20Experts=20(#15471)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: github-actions[bot] --- docs/en/data/people.yml | 320 ++++++++++++++++++++++------------------ 1 file changed, 176 insertions(+), 144 deletions(-) diff --git a/docs/en/data/people.yml b/docs/en/data/people.yml index 01c01d06b..cde0c9633 100644 --- a/docs/en/data/people.yml +++ b/docs/en/data/people.yml @@ -1,19 +1,19 @@ maintainers: - login: tiangolo - answers: 1922 + answers: 1927 avatarUrl: https://avatars.githubusercontent.com/u/1326112?u=cb5d06e73a9e1998141b1641aa88e443c6717651&v=4 url: https://github.com/tiangolo experts: - login: tiangolo - count: 1922 + count: 1927 avatarUrl: https://avatars.githubusercontent.com/u/1326112?u=cb5d06e73a9e1998141b1641aa88e443c6717651&v=4 url: https://github.com/tiangolo - login: YuriiMotov - count: 1156 + count: 1164 avatarUrl: https://avatars.githubusercontent.com/u/109919500?u=bc48be95c429989224786106b027f3c5e40cc354&v=4 url: https://github.com/YuriiMotov - login: github-actions - count: 769 + count: 770 avatarUrl: https://avatars.githubusercontent.com/in/15368?v=4 url: https://github.com/apps/github-actions - login: Kludex @@ -25,7 +25,7 @@ experts: avatarUrl: https://avatars.githubusercontent.com/u/4335847?u=ed77f67e0bb069084639b24d812dbb2a2b1dc554&v=4 url: https://github.com/jgould22 - login: dmontagu - count: 239 + count: 240 avatarUrl: https://avatars.githubusercontent.com/u/35119617?u=540f30c937a6450812628b9592a1dfe91bbe148e&v=4 url: https://github.com/dmontagu - login: Mause @@ -41,7 +41,7 @@ experts: avatarUrl: https://avatars.githubusercontent.com/u/13659033?u=e8bea32d07a5ef72f7dde3b2079ceb714923ca05&v=4 url: https://github.com/JarroVGIT - login: euri10 - count: 152 + count: 153 avatarUrl: https://avatars.githubusercontent.com/u/1104190?u=321a2e953e6645a7d09b732786c7a8061e0f8a8b&v=4 url: https://github.com/euri10 - login: iudeen @@ -57,7 +57,7 @@ experts: avatarUrl: https://avatars.githubusercontent.com/u/72013291?u=ae5679e6bd971d9d98cd5e76e8683f83642ba950&v=4 url: https://github.com/JavierSanchezCastro - login: luzzodev - count: 105 + count: 107 avatarUrl: https://avatars.githubusercontent.com/u/27291415?u=5607ae1ce75c5f54f09500ca854227f7bfd2033b&v=4 url: https://github.com/luzzodev - login: raphaelauv @@ -89,7 +89,7 @@ experts: avatarUrl: https://avatars.githubusercontent.com/u/685002?u=b5094ab4527fc84b006c0ac9ff54367bdebb2267&v=4 url: https://github.com/acidjunk - login: sm-Fifteen - count: 48 + count: 49 avatarUrl: https://avatars.githubusercontent.com/u/516999?u=437c0c5038558c67e887ccd863c1ba0f846c03da&v=4 url: https://github.com/sm-Fifteen - login: adriangb @@ -246,99 +246,123 @@ experts: url: https://github.com/mattmess1221 last_month_experts: - login: YuriiMotov - count: 37 + count: 12 avatarUrl: https://avatars.githubusercontent.com/u/109919500?u=bc48be95c429989224786106b027f3c5e40cc354&v=4 url: https://github.com/YuriiMotov -- login: christiansousadev +- login: Firatasi + count: 7 + avatarUrl: https://avatars.githubusercontent.com/u/112112161?u=3219914a49a4a604b3626007823db7de049b6d66&v=4 + url: https://github.com/Firatasi +- login: ericgitangu count: 3 - avatarUrl: https://avatars.githubusercontent.com/u/103544118?u=690f3f76d1dc4d0929de5020679d5604f860acbc&v=4 - url: https://github.com/christiansousadev -- login: saitarrun + avatarUrl: https://avatars.githubusercontent.com/u/11472845?u=9d916cf0f5c80e63cb1d753b8b50dcb8ced3b883&v=4 + url: https://github.com/ericgitangu +- login: cookesan count: 2 - avatarUrl: https://avatars.githubusercontent.com/u/116748905?u=3433afbaf06676a482ebf4ba33b08ddb3fc5c5bf&v=4 - url: https://github.com/saitarrun -- login: Vision-Executive + avatarUrl: https://avatars.githubusercontent.com/u/6601329?u=7bfc9b017198a9fa50929ae8ae0a787632424ffd&v=4 + url: https://github.com/cookesan +- login: coleifer count: 2 - avatarUrl: https://avatars.githubusercontent.com/u/259394686?u=dd28bbc246e4e2cd2adb1d497e7b7585b5d24585&v=4 - url: https://github.com/Vision-Executive -- login: JavierSanchezCastro + avatarUrl: https://avatars.githubusercontent.com/u/119974?u=b3a546c94ee1105e792e0acad2c4743d800e7975&v=4 + url: https://github.com/coleifer +- login: Bahtya count: 2 - avatarUrl: https://avatars.githubusercontent.com/u/72013291?u=ae5679e6bd971d9d98cd5e76e8683f83642ba950&v=4 - url: https://github.com/JavierSanchezCastro + avatarUrl: https://avatars.githubusercontent.com/u/34988899?u=b8e3c0cf26f4bd1faea265d2f5f66f564af63463&v=4 + url: https://github.com/Bahtya +- login: luzzodev + count: 2 + avatarUrl: https://avatars.githubusercontent.com/u/27291415?u=5607ae1ce75c5f54f09500ca854227f7bfd2033b&v=4 + url: https://github.com/luzzodev +- login: DoctorJohn + count: 2 + avatarUrl: https://avatars.githubusercontent.com/u/14076775?u=ec43fe79a98dbc864b428afc7220753e25ca3af2&v=4 + url: https://github.com/DoctorJohn three_months_experts: - login: YuriiMotov - count: 85 + count: 74 avatarUrl: https://avatars.githubusercontent.com/u/109919500?u=bc48be95c429989224786106b027f3c5e40cc354&v=4 url: https://github.com/YuriiMotov +- login: Firatasi + count: 7 + avatarUrl: https://avatars.githubusercontent.com/u/112112161?u=3219914a49a4a604b3626007823db7de049b6d66&v=4 + url: https://github.com/Firatasi - login: JavierSanchezCastro - count: 9 + count: 7 avatarUrl: https://avatars.githubusercontent.com/u/72013291?u=ae5679e6bd971d9d98cd5e76e8683f83642ba950&v=4 url: https://github.com/JavierSanchezCastro - login: Toygarmetu count: 5 avatarUrl: https://avatars.githubusercontent.com/u/92878791?u=538530cb6d5554e71f9c28709d794db9a74d23d9&v=4 url: https://github.com/Toygarmetu -- login: ceb10n - count: 5 - avatarUrl: https://avatars.githubusercontent.com/u/235213?u=edcce471814a1eba9f0cdaa4cd0de18921a940a6&v=4 - url: https://github.com/ceb10n - login: tiangolo - count: 4 + count: 5 avatarUrl: https://avatars.githubusercontent.com/u/1326112?u=cb5d06e73a9e1998141b1641aa88e443c6717651&v=4 url: https://github.com/tiangolo - login: luzzodev - count: 3 + count: 4 avatarUrl: https://avatars.githubusercontent.com/u/27291415?u=5607ae1ce75c5f54f09500ca854227f7bfd2033b&v=4 url: https://github.com/luzzodev -- login: christiansousadev +- login: ericgitangu count: 3 - avatarUrl: https://avatars.githubusercontent.com/u/103544118?u=690f3f76d1dc4d0929de5020679d5604f860acbc&v=4 - url: https://github.com/christiansousadev -- login: Kludex + avatarUrl: https://avatars.githubusercontent.com/u/11472845?u=9d916cf0f5c80e63cb1d753b8b50dcb8ced3b883&v=4 + url: https://github.com/ericgitangu +- login: cookesan count: 2 - avatarUrl: https://avatars.githubusercontent.com/u/7353520?u=df8a3f06ba8f55ae1967a3e2d5ed882903a4e330&v=4 - url: https://github.com/Kludex + avatarUrl: https://avatars.githubusercontent.com/u/6601329?u=7bfc9b017198a9fa50929ae8ae0a787632424ffd&v=4 + url: https://github.com/cookesan +- login: coleifer + count: 2 + avatarUrl: https://avatars.githubusercontent.com/u/119974?u=b3a546c94ee1105e792e0acad2c4743d800e7975&v=4 + url: https://github.com/coleifer +- login: Bahtya + count: 2 + avatarUrl: https://avatars.githubusercontent.com/u/34988899?u=b8e3c0cf26f4bd1faea265d2f5f66f564af63463&v=4 + url: https://github.com/Bahtya - login: saitarrun count: 2 avatarUrl: https://avatars.githubusercontent.com/u/116748905?u=3433afbaf06676a482ebf4ba33b08ddb3fc5c5bf&v=4 url: https://github.com/saitarrun -- login: Vision-Executive - count: 2 - avatarUrl: https://avatars.githubusercontent.com/u/259394686?u=dd28bbc246e4e2cd2adb1d497e7b7585b5d24585&v=4 - url: https://github.com/Vision-Executive - login: EmmanuelNiyonshuti count: 2 avatarUrl: https://avatars.githubusercontent.com/u/142030687?u=ab131d5ad4670280a978f489babe71c9bf9c1097&v=4 url: https://github.com/EmmanuelNiyonshuti +- login: christiansousadev + count: 2 + avatarUrl: https://avatars.githubusercontent.com/u/103544118?u=690f3f76d1dc4d0929de5020679d5604f860acbc&v=4 + url: https://github.com/christiansousadev +- login: DoctorJohn + count: 2 + avatarUrl: https://avatars.githubusercontent.com/u/14076775?u=ec43fe79a98dbc864b428afc7220753e25ca3af2&v=4 + url: https://github.com/DoctorJohn +- login: gaardhus + count: 2 + avatarUrl: https://avatars.githubusercontent.com/u/46934916?u=18d7aacc6ce59f054749209645d11cfe77b52f90&v=4 + url: https://github.com/gaardhus - login: valentinDruzhinin count: 2 avatarUrl: https://avatars.githubusercontent.com/u/12831905?u=aae1ebc675c91e8fa582df4fcc4fc4128106344d&v=4 url: https://github.com/valentinDruzhinin -- login: RichieB2B - count: 2 - avatarUrl: https://avatars.githubusercontent.com/u/1461970?u=edaa57d1077705244ea5c9244f4783d94ff11f12&v=4 - url: https://github.com/RichieB2B -- login: dotmitsu - count: 2 - avatarUrl: https://avatars.githubusercontent.com/u/42657211?u=3bccc9a2f386a3f24230ec393080f8904fe2a5b2&v=4 - url: https://github.com/dotmitsu six_months_experts: - login: YuriiMotov - count: 182 + count: 166 avatarUrl: https://avatars.githubusercontent.com/u/109919500?u=bc48be95c429989224786106b027f3c5e40cc354&v=4 url: https://github.com/YuriiMotov - login: tiangolo - count: 24 + count: 23 avatarUrl: https://avatars.githubusercontent.com/u/1326112?u=cb5d06e73a9e1998141b1641aa88e443c6717651&v=4 url: https://github.com/tiangolo - login: JavierSanchezCastro - count: 15 + count: 12 avatarUrl: https://avatars.githubusercontent.com/u/72013291?u=ae5679e6bd971d9d98cd5e76e8683f83642ba950&v=4 url: https://github.com/JavierSanchezCastro - login: luzzodev - count: 10 + count: 9 avatarUrl: https://avatars.githubusercontent.com/u/27291415?u=5607ae1ce75c5f54f09500ca854227f7bfd2033b&v=4 url: https://github.com/luzzodev +- login: Firatasi + count: 7 + avatarUrl: https://avatars.githubusercontent.com/u/112112161?u=3219914a49a4a604b3626007823db7de049b6d66&v=4 + url: https://github.com/Firatasi - login: Toygarmetu count: 5 avatarUrl: https://avatars.githubusercontent.com/u/92878791?u=538530cb6d5554e71f9c28709d794db9a74d23d9&v=4 @@ -347,10 +371,6 @@ six_months_experts: count: 5 avatarUrl: https://avatars.githubusercontent.com/u/235213?u=edcce471814a1eba9f0cdaa4cd0de18921a940a6&v=4 url: https://github.com/ceb10n -- login: RichieB2B - count: 5 - avatarUrl: https://avatars.githubusercontent.com/u/1461970?u=edaa57d1077705244ea5c9244f4783d94ff11f12&v=4 - url: https://github.com/RichieB2B - login: JunjieAraoXiong count: 5 avatarUrl: https://avatars.githubusercontent.com/u/167785867?u=b69afe090c8bf5fd73f2d23fc3a887b28f68f192&v=4 @@ -359,50 +379,66 @@ six_months_experts: count: 4 avatarUrl: https://avatars.githubusercontent.com/u/12831905?u=aae1ebc675c91e8fa582df4fcc4fc4128106344d&v=4 url: https://github.com/valentinDruzhinin -- login: ArmanShirzad - count: 4 - avatarUrl: https://avatars.githubusercontent.com/u/68951175?u=1f1efae2fa5d0d17c38a1a8413bedca5e538cedb&v=4 - url: https://github.com/ArmanShirzad -- login: CodeKraken-cmd - count: 4 - avatarUrl: https://avatars.githubusercontent.com/u/48470371?u=e7c0e7ec8e35ca5fb3ae40a586ed5e788fd0fe6d&v=4 - url: https://github.com/CodeKraken-cmd -- login: svlandeg - count: 4 - avatarUrl: https://avatars.githubusercontent.com/u/8796347?u=556c97650c27021911b0b9447ec55e75987b0e8a&v=4 - url: https://github.com/svlandeg - login: krylosov-aa count: 4 avatarUrl: https://avatars.githubusercontent.com/u/242901957?u=4c9c7b468203b09bca64936fb464620e32cdd252&v=4 url: https://github.com/krylosov-aa -- login: Kludex +- login: ericgitangu count: 3 - avatarUrl: https://avatars.githubusercontent.com/u/7353520?u=df8a3f06ba8f55ae1967a3e2d5ed882903a4e330&v=4 - url: https://github.com/Kludex -- login: christiansousadev + avatarUrl: https://avatars.githubusercontent.com/u/11472845?u=9d916cf0f5c80e63cb1d753b8b50dcb8ced3b883&v=4 + url: https://github.com/ericgitangu +- login: EmmanuelNiyonshuti count: 3 - avatarUrl: https://avatars.githubusercontent.com/u/103544118?u=690f3f76d1dc4d0929de5020679d5604f860acbc&v=4 - url: https://github.com/christiansousadev + avatarUrl: https://avatars.githubusercontent.com/u/142030687?u=ab131d5ad4670280a978f489babe71c9bf9c1097&v=4 + url: https://github.com/EmmanuelNiyonshuti - login: sachinh35 count: 3 avatarUrl: https://avatars.githubusercontent.com/u/21972708?u=8560b97b8b41e175f476270b56de8a493b84f302&v=4 url: https://github.com/sachinh35 +- login: RichieB2B + count: 3 + avatarUrl: https://avatars.githubusercontent.com/u/1461970?u=edaa57d1077705244ea5c9244f4783d94ff11f12&v=4 + url: https://github.com/RichieB2B +- login: cookesan + count: 2 + avatarUrl: https://avatars.githubusercontent.com/u/6601329?u=7bfc9b017198a9fa50929ae8ae0a787632424ffd&v=4 + url: https://github.com/cookesan +- login: coleifer + count: 2 + avatarUrl: https://avatars.githubusercontent.com/u/119974?u=b3a546c94ee1105e792e0acad2c4743d800e7975&v=4 + url: https://github.com/coleifer +- login: Bahtya + count: 2 + avatarUrl: https://avatars.githubusercontent.com/u/34988899?u=b8e3c0cf26f4bd1faea265d2f5f66f564af63463&v=4 + url: https://github.com/Bahtya - login: saitarrun count: 2 avatarUrl: https://avatars.githubusercontent.com/u/116748905?u=3433afbaf06676a482ebf4ba33b08ddb3fc5c5bf&v=4 url: https://github.com/saitarrun +- login: cepedus + count: 2 + avatarUrl: https://avatars.githubusercontent.com/u/26345924?u=38495abbdbb8695dd76478cae5963bf994c498bc&v=4 + url: https://github.com/cepedus +- login: christiansousadev + count: 2 + avatarUrl: https://avatars.githubusercontent.com/u/103544118?u=690f3f76d1dc4d0929de5020679d5604f860acbc&v=4 + url: https://github.com/christiansousadev +- login: DoctorJohn + count: 2 + avatarUrl: https://avatars.githubusercontent.com/u/14076775?u=ec43fe79a98dbc864b428afc7220753e25ca3af2&v=4 + url: https://github.com/DoctorJohn +- login: gaardhus + count: 2 + avatarUrl: https://avatars.githubusercontent.com/u/46934916?u=18d7aacc6ce59f054749209645d11cfe77b52f90&v=4 + url: https://github.com/gaardhus +- login: Kludex + count: 2 + avatarUrl: https://avatars.githubusercontent.com/u/7353520?u=df8a3f06ba8f55ae1967a3e2d5ed882903a4e330&v=4 + url: https://github.com/Kludex - login: y2kbugger count: 2 avatarUrl: https://avatars.githubusercontent.com/u/6101677?u=1d50077e29582dc01fcbdff846f04fe7ec73fe2e&v=4 url: https://github.com/y2kbugger -- login: Vision-Executive - count: 2 - avatarUrl: https://avatars.githubusercontent.com/u/259394686?u=dd28bbc246e4e2cd2adb1d497e7b7585b5d24585&v=4 - url: https://github.com/Vision-Executive -- login: EmmanuelNiyonshuti - count: 2 - avatarUrl: https://avatars.githubusercontent.com/u/142030687?u=ab131d5ad4670280a978f489babe71c9bf9c1097&v=4 - url: https://github.com/EmmanuelNiyonshuti - login: davidbrochart count: 2 avatarUrl: https://avatars.githubusercontent.com/u/4711805?u=d39696d995a9e02ec3613ffb2f62b20b14f92f26&v=4 @@ -419,10 +455,6 @@ six_months_experts: count: 2 avatarUrl: https://avatars.githubusercontent.com/u/4661021?u=ed5ddadcf36d9b943ebe61febe0b96ee34e5425d&v=4 url: https://github.com/dolfinus -- login: skion - count: 2 - avatarUrl: https://avatars.githubusercontent.com/u/532192?v=4 - url: https://github.com/skion - login: florentx count: 2 avatarUrl: https://avatars.githubusercontent.com/u/142113?u=bf10f10080026346b092633c380977b61cee0d9c&v=4 @@ -431,37 +463,33 @@ six_months_experts: count: 2 avatarUrl: https://avatars.githubusercontent.com/u/51329768?v=4 url: https://github.com/jc-louis -- login: WilliamDEdwards - count: 2 - avatarUrl: https://avatars.githubusercontent.com/u/12184311?u=9b29d5d1d71f5f1a7ef9e439963ad3529e3b33a4&v=4 - url: https://github.com/WilliamDEdwards - login: bughuntr7 count: 2 avatarUrl: https://avatars.githubusercontent.com/u/236391583?u=7f51ff690e3a5711f845a115903c39e21c8af938&v=4 url: https://github.com/bughuntr7 +- login: CodeKraken-cmd + count: 2 + avatarUrl: https://avatars.githubusercontent.com/u/48470371?u=e7c0e7ec8e35ca5fb3ae40a586ed5e788fd0fe6d&v=4 + url: https://github.com/CodeKraken-cmd +- login: svlandeg + count: 2 + avatarUrl: https://avatars.githubusercontent.com/u/8796347?u=556c97650c27021911b0b9447ec55e75987b0e8a&v=4 + url: https://github.com/svlandeg - login: jymchng count: 2 avatarUrl: https://avatars.githubusercontent.com/u/27895426?u=fb88c47775147d62a395fdb895d1af4148c7b566&v=4 url: https://github.com/jymchng -- login: XieJiSS - count: 2 - avatarUrl: https://avatars.githubusercontent.com/u/24671280?u=7ea0d9bfe46cf762594d62fd2f3c6d3813c3584c&v=4 - url: https://github.com/XieJiSS -- login: profatsky - count: 2 - avatarUrl: https://avatars.githubusercontent.com/u/92920843?u=81e54bb0b613c171f7cd0ab3cbb58873782c9c9c&v=4 - url: https://github.com/profatsky one_year_experts: - login: YuriiMotov count: 951 avatarUrl: https://avatars.githubusercontent.com/u/109919500?u=bc48be95c429989224786106b027f3c5e40cc354&v=4 url: https://github.com/YuriiMotov - login: luzzodev - count: 53 + count: 48 avatarUrl: https://avatars.githubusercontent.com/u/27291415?u=5607ae1ce75c5f54f09500ca854227f7bfd2033b&v=4 url: https://github.com/luzzodev - login: tiangolo - count: 31 + count: 30 avatarUrl: https://avatars.githubusercontent.com/u/1326112?u=cb5d06e73a9e1998141b1641aa88e443c6717651&v=4 url: https://github.com/tiangolo - login: valentinDruzhinin @@ -473,9 +501,17 @@ one_year_experts: avatarUrl: https://avatars.githubusercontent.com/u/72013291?u=ae5679e6bd971d9d98cd5e76e8683f83642ba950&v=4 url: https://github.com/JavierSanchezCastro - login: sachinh35 - count: 11 + count: 9 avatarUrl: https://avatars.githubusercontent.com/u/21972708?u=8560b97b8b41e175f476270b56de8a493b84f302&v=4 url: https://github.com/sachinh35 +- login: Firatasi + count: 7 + avatarUrl: https://avatars.githubusercontent.com/u/112112161?u=3219914a49a4a604b3626007823db7de049b6d66&v=4 + url: https://github.com/Firatasi +- login: DoctorJohn + count: 7 + avatarUrl: https://avatars.githubusercontent.com/u/14076775?u=ec43fe79a98dbc864b428afc7220753e25ca3af2&v=4 + url: https://github.com/DoctorJohn - login: raceychan count: 6 avatarUrl: https://avatars.githubusercontent.com/u/75417963?u=060c62870ec5a791765e63ac20d8885d11143786&v=4 @@ -484,14 +520,14 @@ one_year_experts: count: 6 avatarUrl: https://avatars.githubusercontent.com/u/37829370?u=da44ca53aefd5c23f346fab8e9fd2e108294c179&v=4 url: https://github.com/yinziyan1206 -- login: Kludex - count: 5 - avatarUrl: https://avatars.githubusercontent.com/u/7353520?u=df8a3f06ba8f55ae1967a3e2d5ed882903a4e330&v=4 - url: https://github.com/Kludex - login: Toygarmetu count: 5 avatarUrl: https://avatars.githubusercontent.com/u/92878791?u=538530cb6d5554e71f9c28709d794db9a74d23d9&v=4 url: https://github.com/Toygarmetu +- login: Kludex + count: 5 + avatarUrl: https://avatars.githubusercontent.com/u/7353520?u=df8a3f06ba8f55ae1967a3e2d5ed882903a4e330&v=4 + url: https://github.com/Kludex - login: ceb10n count: 5 avatarUrl: https://avatars.githubusercontent.com/u/235213?u=edcce471814a1eba9f0cdaa4cd0de18921a940a6&v=4 @@ -508,14 +544,6 @@ one_year_experts: count: 5 avatarUrl: https://avatars.githubusercontent.com/u/8796347?u=556c97650c27021911b0b9447ec55e75987b0e8a&v=4 url: https://github.com/svlandeg -- login: DoctorJohn - count: 5 - avatarUrl: https://avatars.githubusercontent.com/u/14076775?u=ec43fe79a98dbc864b428afc7220753e25ca3af2&v=4 - url: https://github.com/DoctorJohn -- login: alv2017 - count: 4 - avatarUrl: https://avatars.githubusercontent.com/u/31544722?v=4 - url: https://github.com/alv2017 - login: WilliamDEdwards count: 4 avatarUrl: https://avatars.githubusercontent.com/u/12184311?u=9b29d5d1d71f5f1a7ef9e439963ad3529e3b33a4&v=4 @@ -536,10 +564,18 @@ one_year_experts: count: 4 avatarUrl: https://avatars.githubusercontent.com/u/157279130?u=16d6466476cf7dbc55a4cd575b6ea920ebdd81e1&v=4 url: https://github.com/isgin01 -- login: christiansousadev +- login: ericgitangu count: 3 - avatarUrl: https://avatars.githubusercontent.com/u/103544118?u=690f3f76d1dc4d0929de5020679d5604f860acbc&v=4 - url: https://github.com/christiansousadev + avatarUrl: https://avatars.githubusercontent.com/u/11472845?u=9d916cf0f5c80e63cb1d753b8b50dcb8ced3b883&v=4 + url: https://github.com/ericgitangu +- login: henrymcl + count: 3 + avatarUrl: https://avatars.githubusercontent.com/u/26480299?v=4 + url: https://github.com/henrymcl +- login: EmmanuelNiyonshuti + count: 3 + avatarUrl: https://avatars.githubusercontent.com/u/142030687?u=ab131d5ad4670280a978f489babe71c9bf9c1097&v=4 + url: https://github.com/EmmanuelNiyonshuti - login: dolfinus count: 3 avatarUrl: https://avatars.githubusercontent.com/u/4661021?u=ed5ddadcf36d9b943ebe61febe0b96ee34e5425d&v=4 @@ -564,18 +600,38 @@ one_year_experts: count: 3 avatarUrl: https://avatars.githubusercontent.com/u/210023470?u=c25d66addf36a747bd9fab773c4a6e7b238f45d4&v=4 url: https://github.com/Jelle-tenB +- login: cookesan + count: 2 + avatarUrl: https://avatars.githubusercontent.com/u/6601329?u=7bfc9b017198a9fa50929ae8ae0a787632424ffd&v=4 + url: https://github.com/cookesan +- login: coleifer + count: 2 + avatarUrl: https://avatars.githubusercontent.com/u/119974?u=b3a546c94ee1105e792e0acad2c4743d800e7975&v=4 + url: https://github.com/coleifer +- login: Bahtya + count: 2 + avatarUrl: https://avatars.githubusercontent.com/u/34988899?u=b8e3c0cf26f4bd1faea265d2f5f66f564af63463&v=4 + url: https://github.com/Bahtya - login: saitarrun count: 2 avatarUrl: https://avatars.githubusercontent.com/u/116748905?u=3433afbaf06676a482ebf4ba33b08ddb3fc5c5bf&v=4 url: https://github.com/saitarrun +- login: cepedus + count: 2 + avatarUrl: https://avatars.githubusercontent.com/u/26345924?u=38495abbdbb8695dd76478cae5963bf994c498bc&v=4 + url: https://github.com/cepedus +- login: christiansousadev + count: 2 + avatarUrl: https://avatars.githubusercontent.com/u/103544118?u=690f3f76d1dc4d0929de5020679d5604f860acbc&v=4 + url: https://github.com/christiansousadev +- login: gaardhus + count: 2 + avatarUrl: https://avatars.githubusercontent.com/u/46934916?u=18d7aacc6ce59f054749209645d11cfe77b52f90&v=4 + url: https://github.com/gaardhus - login: y2kbugger count: 2 avatarUrl: https://avatars.githubusercontent.com/u/6101677?u=1d50077e29582dc01fcbdff846f04fe7ec73fe2e&v=4 url: https://github.com/y2kbugger -- login: Vision-Executive - count: 2 - avatarUrl: https://avatars.githubusercontent.com/u/259394686?u=dd28bbc246e4e2cd2adb1d497e7b7585b5d24585&v=4 - url: https://github.com/Vision-Executive - login: Garrett-R count: 2 avatarUrl: https://avatars.githubusercontent.com/u/6614695?u=c128fd775002882f6e391bda5a89d1bdc5bdf45f&v=4 @@ -584,10 +640,6 @@ one_year_experts: count: 2 avatarUrl: https://avatars.githubusercontent.com/u/17792131?u=372b27056ec82f1ae03d8b3f37ef55b04a7cfdd1&v=4 url: https://github.com/TaigoFr -- login: EmmanuelNiyonshuti - count: 2 - avatarUrl: https://avatars.githubusercontent.com/u/142030687?u=ab131d5ad4670280a978f489babe71c9bf9c1097&v=4 - url: https://github.com/EmmanuelNiyonshuti - login: stan-dot count: 2 avatarUrl: https://avatars.githubusercontent.com/u/56644812?u=a7dd773084f1c17c5f05019cc25a984e24873691&v=4 @@ -612,10 +664,6 @@ one_year_experts: count: 2 avatarUrl: https://avatars.githubusercontent.com/u/1070878?u=68f78a891c9751dd87571ac712a6309090c4bc01&v=4 url: https://github.com/kiranzo -- login: sinisaos - count: 2 - avatarUrl: https://avatars.githubusercontent.com/u/30960668?v=4 - url: https://github.com/sinisaos - login: dotmitsu count: 2 avatarUrl: https://avatars.githubusercontent.com/u/42657211?u=3bccc9a2f386a3f24230ec393080f8904fe2a5b2&v=4 @@ -636,10 +684,6 @@ one_year_experts: count: 2 avatarUrl: https://avatars.githubusercontent.com/u/532192?v=4 url: https://github.com/skion -- login: Danstiv - count: 2 - avatarUrl: https://avatars.githubusercontent.com/u/50794055?v=4 - url: https://github.com/Danstiv - login: florentx count: 2 avatarUrl: https://avatars.githubusercontent.com/u/142113?u=bf10f10080026346b092633c380977b61cee0d9c&v=4 @@ -658,12 +702,8 @@ one_year_experts: url: https://github.com/purepani - login: asmaier count: 2 - avatarUrl: https://avatars.githubusercontent.com/u/3169297?v=4 + avatarUrl: https://avatars.githubusercontent.com/u/3169297?u=84c83cbdb64104331febe16ae232ecf30952d01d&v=4 url: https://github.com/asmaier -- login: henrymcl - count: 2 - avatarUrl: https://avatars.githubusercontent.com/u/26480299?v=4 - url: https://github.com/henrymcl - login: davidhuser count: 2 avatarUrl: https://avatars.githubusercontent.com/u/4357648?u=6ed702f8f6d49a8b2a0ed33cbd8ab59c2d7db7f7&v=4 @@ -680,11 +720,3 @@ one_year_experts: count: 2 avatarUrl: https://avatars.githubusercontent.com/u/32141163?v=4 url: https://github.com/pythonweb2 -- login: PidgeyBE - 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 From f72afb6f6e2393fcc211e0300805e14b9e65ac1b Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Sun, 3 May 2026 13:37:48 +0000 Subject: [PATCH 043/462] =?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 ca0adcfee..55acf4ac7 100644 --- a/docs/en/docs/release-notes.md +++ b/docs/en/docs/release-notes.md @@ -15,6 +15,7 @@ hide: ### Internal +* 👥 Update FastAPI People - Experts. PR [#15471](https://github.com/fastapi/fastapi/pull/15471) by [@tiangolo](https://github.com/tiangolo). * 👥 Update FastAPI People - Contributors and Translators. PR [#15467](https://github.com/fastapi/fastapi/pull/15467) by [@tiangolo](https://github.com/tiangolo). * 👷 Fix missing credentials issue in `translate` workflow. PR [#15468](https://github.com/fastapi/fastapi/pull/15468) by [@YuriiMotov](https://github.com/YuriiMotov). * ⬆ Bump sqlmodel from 0.0.32 to 0.0.38. PR [#15437](https://github.com/fastapi/fastapi/pull/15437) by [@dependabot[bot]](https://github.com/apps/dependabot). From 9ccaab154add00216c58e45917f40669fae74a2d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebasti=C3=A1n=20Ram=C3=ADrez?= Date: Sun, 3 May 2026 15:44:38 +0200 Subject: [PATCH 044/462] =?UTF-8?q?=F0=9F=91=A5=20Update=20FastAPI=20GitHu?= =?UTF-8?q?b=20topic=20repositories=20(#15470)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: github-actions[bot] --- docs/en/data/topic_repos.yml | 404 +++++++++++++++++------------------ 1 file changed, 202 insertions(+), 202 deletions(-) diff --git a/docs/en/data/topic_repos.yml b/docs/en/data/topic_repos.yml index 9703c7a6b..b2921b2f3 100644 --- a/docs/en/data/topic_repos.yml +++ b/docs/en/data/topic_repos.yml @@ -1,495 +1,495 @@ - name: full-stack-fastapi-template html_url: https://github.com/fastapi/full-stack-fastapi-template - stars: 42397 + stars: 42944 owner_login: fastapi owner_html_url: https://github.com/fastapi - name: Hello-Python html_url: https://github.com/mouredev/Hello-Python - stars: 34997 + stars: 35430 owner_login: mouredev owner_html_url: https://github.com/mouredev - name: serve html_url: https://github.com/jina-ai/serve - stars: 21857 + stars: 21876 owner_login: jina-ai owner_html_url: https://github.com/jina-ai - name: HivisionIDPhotos html_url: https://github.com/Zeyi-Lin/HivisionIDPhotos - stars: 20868 + stars: 21054 owner_login: Zeyi-Lin owner_html_url: https://github.com/Zeyi-Lin - name: sqlmodel html_url: https://github.com/fastapi/sqlmodel - stars: 17770 + stars: 17886 owner_login: fastapi owner_html_url: https://github.com/fastapi -- name: fastapi-best-practices - html_url: https://github.com/zhanymkanov/fastapi-best-practices - stars: 16897 - owner_login: zhanymkanov - owner_html_url: https://github.com/zhanymkanov - name: Douyin_TikTok_Download_API html_url: https://github.com/Evil0ctal/Douyin_TikTok_Download_API - stars: 16878 + stars: 17546 owner_login: Evil0ctal owner_html_url: https://github.com/Evil0ctal +- name: fastapi-best-practices + html_url: https://github.com/zhanymkanov/fastapi-best-practices + stars: 17138 + owner_login: zhanymkanov + owner_html_url: https://github.com/zhanymkanov - name: SurfSense html_url: https://github.com/MODSetter/SurfSense - stars: 13614 + stars: 14045 owner_login: MODSetter owner_html_url: https://github.com/MODSetter - name: machine-learning-zoomcamp html_url: https://github.com/DataTalksClub/machine-learning-zoomcamp - stars: 12780 + stars: 13015 owner_login: DataTalksClub owner_html_url: https://github.com/DataTalksClub - name: fastapi_mcp html_url: https://github.com/tadata-org/fastapi_mcp - stars: 11752 + stars: 11837 owner_login: tadata-org owner_html_url: https://github.com/tadata-org - name: awesome-fastapi html_url: https://github.com/mjhea0/awesome-fastapi - stars: 11203 + stars: 11315 owner_login: mjhea0 owner_html_url: https://github.com/mjhea0 - name: XHS-Downloader html_url: https://github.com/JoeanAmier/XHS-Downloader - stars: 10612 + stars: 11013 owner_login: JoeanAmier owner_html_url: https://github.com/JoeanAmier - name: polar html_url: https://github.com/polarsource/polar - stars: 9626 + stars: 9775 owner_login: polarsource owner_html_url: https://github.com/polarsource +- name: pycaret + html_url: https://github.com/pycaret/pycaret + stars: 9753 + owner_login: pycaret + owner_html_url: https://github.com/pycaret - name: FastUI html_url: https://github.com/pydantic/FastUI - stars: 8958 + stars: 8961 owner_login: pydantic owner_html_url: https://github.com/pydantic - name: FileCodeBox html_url: https://github.com/vastsa/FileCodeBox - stars: 8191 + stars: 8241 owner_login: vastsa owner_html_url: https://github.com/vastsa - name: nonebot2 html_url: https://github.com/nonebot/nonebot2 - stars: 7456 + stars: 7488 owner_login: nonebot owner_html_url: https://github.com/nonebot - name: hatchet html_url: https://github.com/hatchet-dev/hatchet - stars: 6784 + stars: 7044 owner_login: hatchet-dev owner_html_url: https://github.com/hatchet-dev - name: fastapi-users html_url: https://github.com/fastapi-users/fastapi-users - stars: 6064 + stars: 6107 owner_login: fastapi-users owner_html_url: https://github.com/fastapi-users - name: serge html_url: https://github.com/serge-chat/serge - stars: 5738 + stars: 5731 owner_login: serge-chat owner_html_url: https://github.com/serge-chat - name: Yuxi html_url: https://github.com/xerrors/Yuxi - stars: 4761 + stars: 5063 owner_login: xerrors owner_html_url: https://github.com/xerrors - name: Kokoro-FastAPI html_url: https://github.com/remsky/Kokoro-FastAPI - stars: 4649 + stars: 4785 owner_login: remsky owner_html_url: https://github.com/remsky - name: strawberry html_url: https://github.com/strawberry-graphql/strawberry - stars: 4636 + stars: 4649 owner_login: strawberry-graphql owner_html_url: https://github.com/strawberry-graphql - name: devpush html_url: https://github.com/hunvreus/devpush - stars: 4589 + stars: 4641 owner_login: hunvreus owner_html_url: https://github.com/hunvreus - name: poem html_url: https://github.com/poem-web/poem - stars: 4375 + stars: 4387 owner_login: poem-web owner_html_url: https://github.com/poem-web - name: dynaconf html_url: https://github.com/dynaconf/dynaconf - stars: 4276 + stars: 4291 owner_login: dynaconf owner_html_url: https://github.com/dynaconf - name: chatgpt-web-share html_url: https://github.com/chatpire/chatgpt-web-share - stars: 4272 + stars: 4269 owner_login: chatpire owner_html_url: https://github.com/chatpire - name: logfire html_url: https://github.com/pydantic/logfire - stars: 4145 + stars: 4206 owner_login: pydantic owner_html_url: https://github.com/pydantic - name: atrilabs-engine html_url: https://github.com/Atri-Labs/atrilabs-engine - stars: 4086 + stars: 4080 owner_login: Atri-Labs owner_html_url: https://github.com/Atri-Labs - name: huma html_url: https://github.com/danielgtaylor/huma - stars: 3933 + stars: 4043 owner_login: danielgtaylor owner_html_url: https://github.com/danielgtaylor -- name: LitServe - html_url: https://github.com/Lightning-AI/LitServe - stars: 3851 - owner_login: Lightning-AI - owner_html_url: https://github.com/Lightning-AI - name: datamodel-code-generator html_url: https://github.com/koxudaxi/datamodel-code-generator - stars: 3839 + stars: 3882 owner_login: koxudaxi owner_html_url: https://github.com/koxudaxi +- name: LitServe + html_url: https://github.com/Lightning-AI/LitServe + stars: 3879 + 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: 3745 + stars: 3759 owner_login: fastapi-admin owner_html_url: https://github.com/fastapi-admin +- name: mcp-context-forge + html_url: https://github.com/IBM/mcp-context-forge + stars: 3644 + owner_login: IBM + owner_html_url: https://github.com/IBM - name: tracecat html_url: https://github.com/TracecatHQ/tracecat - stars: 3542 + stars: 3564 owner_login: TracecatHQ owner_html_url: https://github.com/TracecatHQ - name: farfalle html_url: https://github.com/rashadphz/farfalle - stars: 3521 + stars: 3530 owner_login: rashadphz owner_html_url: https://github.com/rashadphz -- name: mcp-context-forge - html_url: https://github.com/IBM/mcp-context-forge - stars: 3501 - owner_login: IBM - owner_html_url: https://github.com/IBM - name: opyrator html_url: https://github.com/ml-tooling/opyrator stars: 3137 owner_login: ml-tooling owner_html_url: https://github.com/ml-tooling +- name: honcho + html_url: https://github.com/plastic-labs/honcho + stars: 3135 + owner_login: plastic-labs + owner_html_url: https://github.com/plastic-labs - name: docarray html_url: https://github.com/docarray/docarray - stars: 3120 + stars: 3118 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: 3092 + stars: 3111 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: 2913 + stars: 2912 owner_login: tiangolo owner_html_url: https://github.com/tiangolo - name: FastAPI-template html_url: https://github.com/s3rius/FastAPI-template - stars: 2768 + stars: 2780 owner_login: s3rius owner_html_url: https://github.com/s3rius -- name: best-of-web-python - html_url: https://github.com/ml-tooling/best-of-web-python - stars: 2703 - owner_login: ml-tooling - owner_html_url: https://github.com/ml-tooling - name: sqladmin html_url: https://github.com/smithyhq/sqladmin - stars: 2696 + stars: 2716 owner_login: smithyhq owner_html_url: https://github.com/smithyhq +- name: best-of-web-python + html_url: https://github.com/ml-tooling/best-of-web-python + stars: 2711 + owner_login: ml-tooling + owner_html_url: https://github.com/ml-tooling - name: YC-Killer html_url: https://github.com/sahibzada-allahyar/YC-Killer - stars: 2675 + stars: 2626 owner_login: sahibzada-allahyar owner_html_url: https://github.com/sahibzada-allahyar - name: fastapi-react html_url: https://github.com/Buuntu/fastapi-react - stars: 2579 + stars: 2581 owner_login: Buuntu owner_html_url: https://github.com/Buuntu - name: supabase-py html_url: https://github.com/supabase/supabase-py - stars: 2486 + stars: 2499 owner_login: supabase owner_html_url: https://github.com/supabase - name: RasaGPT html_url: https://github.com/paulpierre/RasaGPT - stars: 2462 + stars: 2466 owner_login: paulpierre owner_html_url: https://github.com/paulpierre -- name: 30-Days-of-Python - html_url: https://github.com/codingforentrepreneurs/30-Days-of-Python - stars: 2450 - owner_login: codingforentrepreneurs - owner_html_url: https://github.com/codingforentrepreneurs - name: NoteDiscovery html_url: https://github.com/gamosoft/NoteDiscovery - stars: 2400 + stars: 2465 owner_login: gamosoft owner_html_url: https://github.com/gamosoft +- name: 30-Days-of-Python + html_url: https://github.com/codingforentrepreneurs/30-Days-of-Python + stars: 2459 + owner_login: codingforentrepreneurs + owner_html_url: https://github.com/codingforentrepreneurs +- name: AIstudioProxyAPI + html_url: https://github.com/CJackHwang/AIstudioProxyAPI + stars: 2346 + owner_login: CJackHwang + owner_html_url: https://github.com/CJackHwang - name: nextpy html_url: https://github.com/dot-agent/nextpy - stars: 2339 + stars: 2336 owner_login: dot-agent owner_html_url: https://github.com/dot-agent -- name: fastapi-utils - html_url: https://github.com/fastapiutils/fastapi-utils - stars: 2308 - owner_login: fastapiutils - owner_html_url: https://github.com/fastapiutils - name: langserve html_url: https://github.com/langchain-ai/langserve - stars: 2300 + stars: 2319 owner_login: langchain-ai owner_html_url: https://github.com/langchain-ai -- name: solara - html_url: https://github.com/widgetti/solara - stars: 2156 - owner_login: widgetti - owner_html_url: https://github.com/widgetti -- name: fastapi-best-architecture - html_url: https://github.com/fastapi-practices/fastapi-best-architecture - stars: 2148 - owner_login: fastapi-practices - owner_html_url: https://github.com/fastapi-practices +- name: fastapi-utils + html_url: https://github.com/fastapiutils/fastapi-utils + stars: 2306 + owner_login: fastapiutils + owner_html_url: https://github.com/fastapiutils - name: fastapi-langgraph-agent-production-ready-template html_url: https://github.com/wassim249/fastapi-langgraph-agent-production-ready-template - stars: 2103 + stars: 2218 owner_login: wassim249 owner_html_url: https://github.com/wassim249 -- name: mangum - html_url: https://github.com/Kludex/mangum - stars: 2100 - owner_login: Kludex - owner_html_url: https://github.com/Kludex +- name: fastapi-best-architecture + html_url: https://github.com/fastapi-practices/fastapi-best-architecture + stars: 2206 + owner_login: fastapi-practices + owner_html_url: https://github.com/fastapi-practices +- name: solara + html_url: https://github.com/widgetti/solara + stars: 2160 + owner_login: widgetti + owner_html_url: https://github.com/widgetti - name: vue-fastapi-admin html_url: https://github.com/mizhexiaoxiao/vue-fastapi-admin - stars: 2059 + stars: 2108 owner_login: mizhexiaoxiao owner_html_url: https://github.com/mizhexiaoxiao -- name: agentkit - html_url: https://github.com/BCG-X-Official/agentkit - stars: 1947 - owner_login: BCG-X-Official - owner_html_url: https://github.com/BCG-X-Official +- name: mangum + html_url: https://github.com/Kludex/mangum + stars: 2106 + owner_login: Kludex + owner_html_url: https://github.com/Kludex - name: slowapi html_url: https://github.com/laurentS/slowapi - stars: 1946 + stars: 1960 owner_login: laurentS owner_html_url: https://github.com/laurentS -- name: openapi-python-client - html_url: https://github.com/openapi-generators/openapi-python-client - stars: 1930 - owner_login: openapi-generators - owner_html_url: https://github.com/openapi-generators - name: xhs_ai_publisher html_url: https://github.com/BetaStreetOmnis/xhs_ai_publisher - stars: 1904 + stars: 1948 owner_login: BetaStreetOmnis owner_html_url: https://github.com/BetaStreetOmnis +- name: agentkit + html_url: https://github.com/BCG-X-Official/agentkit + stars: 1944 + owner_login: BCG-X-Official + owner_html_url: https://github.com/BCG-X-Official +- name: openapi-python-client + html_url: https://github.com/openapi-generators/openapi-python-client + stars: 1941 + owner_login: openapi-generators + owner_html_url: https://github.com/openapi-generators - name: manage-fastapi html_url: https://github.com/ycd/manage-fastapi - stars: 1898 + stars: 1901 owner_login: ycd owner_html_url: https://github.com/ycd - name: piccolo html_url: https://github.com/piccolo-orm/piccolo - stars: 1876 + stars: 1896 owner_login: piccolo-orm owner_html_url: https://github.com/piccolo-orm - name: FastAPI-boilerplate html_url: https://github.com/benavlabs/FastAPI-boilerplate - stars: 1859 + stars: 1892 owner_login: benavlabs owner_html_url: https://github.com/benavlabs - name: fastapi-cache html_url: https://github.com/long2ice/fastapi-cache - stars: 1853 + stars: 1859 owner_login: long2ice owner_html_url: https://github.com/long2ice +- name: any-auto-register + html_url: https://github.com/lxf746/any-auto-register + stars: 1857 + owner_login: lxf746 + owner_html_url: https://github.com/lxf746 - name: python-week-2022 html_url: https://github.com/rochacbruno/python-week-2022 - stars: 1809 + stars: 1810 owner_login: rochacbruno owner_html_url: https://github.com/rochacbruno - name: ormar html_url: https://github.com/ormar-orm/ormar - stars: 1808 + stars: 1806 owner_login: ormar-orm owner_html_url: https://github.com/ormar-orm - name: termpair html_url: https://github.com/cs01/termpair - stars: 1730 + stars: 1731 owner_login: cs01 owner_html_url: https://github.com/cs01 - name: fastapi-crudrouter html_url: https://github.com/awtkns/fastapi-crudrouter - stars: 1683 + stars: 1687 owner_login: awtkns owner_html_url: https://github.com/awtkns -- name: fastapi-pagination - html_url: https://github.com/uriyyo/fastapi-pagination - stars: 1638 - owner_login: uriyyo - owner_html_url: https://github.com/uriyyo - name: bracket html_url: https://github.com/evroon/bracket - stars: 1638 + stars: 1653 owner_login: evroon owner_html_url: https://github.com/evroon +- name: WebRPA + html_url: https://github.com/pmh1314520/WebRPA + stars: 1653 + owner_login: pmh1314520 + owner_html_url: https://github.com/pmh1314520 +- name: fastapi-pagination + html_url: https://github.com/uriyyo/fastapi-pagination + stars: 1646 + owner_login: uriyyo + owner_html_url: https://github.com/uriyyo - name: langchain-serve html_url: https://github.com/jina-ai/langchain-serve - stars: 1634 + stars: 1640 owner_login: jina-ai owner_html_url: https://github.com/jina-ai +- name: headroom + html_url: https://github.com/chopratejas/headroom + stars: 1624 + owner_login: chopratejas + owner_html_url: https://github.com/chopratejas - name: awesome-fastapi-projects html_url: https://github.com/Kludex/awesome-fastapi-projects - stars: 1597 + stars: 1599 owner_login: Kludex owner_html_url: https://github.com/Kludex - name: coronavirus-tracker-api html_url: https://github.com/ExpDev07/coronavirus-tracker-api - stars: 1568 + stars: 1567 owner_login: ExpDev07 owner_html_url: https://github.com/ExpDev07 -- name: WebRPA - html_url: https://github.com/pmh1314520/WebRPA - stars: 1532 - owner_login: pmh1314520 - owner_html_url: https://github.com/pmh1314520 - name: fastapi-amis-admin html_url: https://github.com/amisadmin/fastapi-amis-admin - stars: 1527 + stars: 1541 owner_login: amisadmin owner_html_url: https://github.com/amisadmin - name: fastcrud html_url: https://github.com/benavlabs/fastcrud - stars: 1506 + stars: 1512 owner_login: benavlabs owner_html_url: https://github.com/benavlabs +- name: open-wearables + html_url: https://github.com/the-momentum/open-wearables + stars: 1496 + owner_login: the-momentum + owner_html_url: https://github.com/the-momentum - name: fastapi-boilerplate html_url: https://github.com/teamhide/fastapi-boilerplate - stars: 1482 + stars: 1486 owner_login: teamhide owner_html_url: https://github.com/teamhide -- name: awesome-python-resources - html_url: https://github.com/DjangoEx/awesome-python-resources - stars: 1444 - owner_login: DjangoEx - owner_html_url: https://github.com/DjangoEx -- name: prometheus-fastapi-instrumentator - html_url: https://github.com/trallnag/prometheus-fastapi-instrumentator - stars: 1438 - owner_login: trallnag - owner_html_url: https://github.com/trallnag -- name: honcho - html_url: https://github.com/plastic-labs/honcho - stars: 1419 - owner_login: plastic-labs - owner_html_url: https://github.com/plastic-labs - name: tavily-key-generator html_url: https://github.com/skernelx/tavily-key-generator - stars: 1416 + stars: 1478 owner_login: skernelx owner_html_url: https://github.com/skernelx +- name: prometheus-fastapi-instrumentator + html_url: https://github.com/trallnag/prometheus-fastapi-instrumentator + stars: 1451 + owner_login: trallnag + owner_html_url: https://github.com/trallnag +- name: awesome-python-resources + html_url: https://github.com/DjangoEx/awesome-python-resources + stars: 1449 + owner_login: DjangoEx + owner_html_url: https://github.com/DjangoEx - name: fastapi-tutorial html_url: https://github.com/liaogx/fastapi-tutorial - stars: 1384 + stars: 1399 owner_login: liaogx owner_html_url: https://github.com/liaogx - name: fastapi-code-generator html_url: https://github.com/koxudaxi/fastapi-code-generator - stars: 1384 + stars: 1383 owner_login: koxudaxi owner_html_url: https://github.com/koxudaxi - name: budgetml html_url: https://github.com/ebhy/budgetml - stars: 1346 + stars: 1345 owner_login: ebhy owner_html_url: https://github.com/ebhy -- name: bolt-python - html_url: https://github.com/slackapi/bolt-python - stars: 1286 - owner_login: slackapi - owner_html_url: https://github.com/slackapi - name: aktools html_url: https://github.com/akfamily/aktools - stars: 1283 + stars: 1334 owner_login: akfamily owner_html_url: https://github.com/akfamily +- name: RuoYi-Vue3-FastAPI + html_url: https://github.com/insistence/RuoYi-Vue3-FastAPI + stars: 1302 + owner_login: insistence + owner_html_url: https://github.com/insistence +- name: bolt-python + html_url: https://github.com/slackapi/bolt-python + stars: 1296 + owner_login: slackapi + owner_html_url: https://github.com/slackapi - name: bedrock-chat html_url: https://github.com/aws-samples/bedrock-chat - stars: 1282 + stars: 1288 owner_login: aws-samples owner_html_url: https://github.com/aws-samples -- name: fastapi-scaff - html_url: https://github.com/atpuxiner/fastapi-scaff - stars: 1275 - owner_login: atpuxiner - owner_html_url: https://github.com/atpuxiner -- name: fastapi-alembic-sqlmodel-async - html_url: https://github.com/vargasjona/fastapi-alembic-sqlmodel-async - stars: 1267 - owner_login: vargasjona - owner_html_url: https://github.com/vargasjona - name: restish html_url: https://github.com/rest-sh/restish - stars: 1258 + stars: 1279 owner_login: rest-sh owner_html_url: https://github.com/rest-sh -- name: RuoYi-Vue3-FastAPI - html_url: https://github.com/insistence/RuoYi-Vue3-FastAPI - stars: 1248 - owner_login: insistence - owner_html_url: https://github.com/insistence +- name: fastapi-alembic-sqlmodel-async + html_url: https://github.com/vargasjona/fastapi-alembic-sqlmodel-async + stars: 1270 + owner_login: vargasjona + owner_html_url: https://github.com/vargasjona - name: fastapi_production_template html_url: https://github.com/zhanymkanov/fastapi_production_template - stars: 1240 + stars: 1243 owner_login: zhanymkanov owner_html_url: https://github.com/zhanymkanov -- name: langchain-extract - html_url: https://github.com/langchain-ai/langchain-extract - stars: 1193 - owner_login: langchain-ai - owner_html_url: https://github.com/langchain-ai -- name: open-wearables - html_url: https://github.com/the-momentum/open-wearables - stars: 1170 - owner_login: the-momentum - owner_html_url: https://github.com/the-momentum -- name: odmantic - html_url: https://github.com/art049/odmantic - stars: 1168 - owner_login: art049 - owner_html_url: https://github.com/art049 -- name: authx - html_url: https://github.com/yezz123/authx - stars: 1160 - owner_login: yezz123 - owner_html_url: https://github.com/yezz123 -- name: FileSync - html_url: https://github.com/polius/FileSync - stars: 1153 - owner_login: polius - owner_html_url: https://github.com/polius -- name: enterprise-deep-research - html_url: https://github.com/SalesforceAIResearch/enterprise-deep-research - stars: 1150 - owner_login: SalesforceAIResearch - owner_html_url: https://github.com/SalesforceAIResearch - name: yubal html_url: https://github.com/guillevc/yubal - stars: 1135 + stars: 1203 owner_login: guillevc owner_html_url: https://github.com/guillevc +- name: langchain-extract + html_url: https://github.com/langchain-ai/langchain-extract + stars: 1196 + owner_login: langchain-ai + owner_html_url: https://github.com/langchain-ai +- name: Chatterbox-TTS-Server + html_url: https://github.com/devnen/Chatterbox-TTS-Server + stars: 1194 + owner_login: devnen + owner_html_url: https://github.com/devnen From ecf73d61c3bb0284f214cc26b480323b7120ff53 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Sun, 3 May 2026 13:45:03 +0000 Subject: [PATCH 045/462] =?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 55acf4ac7..1ae37559a 100644 --- a/docs/en/docs/release-notes.md +++ b/docs/en/docs/release-notes.md @@ -15,6 +15,7 @@ hide: ### Internal +* 👥 Update FastAPI GitHub topic repositories. PR [#15470](https://github.com/fastapi/fastapi/pull/15470) by [@tiangolo](https://github.com/tiangolo). * 👥 Update FastAPI People - Experts. PR [#15471](https://github.com/fastapi/fastapi/pull/15471) by [@tiangolo](https://github.com/tiangolo). * 👥 Update FastAPI People - Contributors and Translators. PR [#15467](https://github.com/fastapi/fastapi/pull/15467) by [@tiangolo](https://github.com/tiangolo). * 👷 Fix missing credentials issue in `translate` workflow. PR [#15468](https://github.com/fastapi/fastapi/pull/15468) by [@YuriiMotov](https://github.com/YuriiMotov). From 810fd2a888b03cfde5670118608c35684a870dc7 Mon Sep 17 00:00:00 2001 From: Isaac <2509809+isaacbernat@users.noreply.github.com> Date: Mon, 4 May 2026 16:53:29 +0200 Subject: [PATCH 046/462] =?UTF-8?q?=E2=9C=8F=EF=B8=8F=20Fix=20Azkaban=20sp?= =?UTF-8?q?elling=20typo=20in=20`virtual-environments.md=E2=80=8E`=20(#154?= =?UTF-8?q?63)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docs/en/docs/virtual-environments.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/en/docs/virtual-environments.md b/docs/en/docs/virtual-environments.md index bd46eb820..1035013a0 100644 --- a/docs/en/docs/virtual-environments.md +++ b/docs/en/docs/virtual-environments.md @@ -819,7 +819,7 @@ Traceback (most recent call last):
-But if you deactivate the virtual environment and activate the new one for `prisoner-of-askaban` then when you run `python` it will use the Python from the virtual environment in `prisoner-of-azkaban`. +But if you deactivate the virtual environment and activate the new one for `prisoner-of-azkaban` then when you run `python` it will use the Python from the virtual environment in `prisoner-of-azkaban`.
From 8c660a6819698d88623eab8826408671706e3627 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Mon, 4 May 2026 14:54:02 +0000 Subject: [PATCH 047/462] =?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 1ae37559a..1836fbed6 100644 --- a/docs/en/docs/release-notes.md +++ b/docs/en/docs/release-notes.md @@ -9,6 +9,7 @@ hide: ### Docs +* ✏️ Fix Azkaban spelling typo in `virtual-environments.md‎`. PR [#15463](https://github.com/fastapi/fastapi/pull/15463) by [@isaacbernat](https://github.com/isaacbernat). * 💄 Improve layout and styling. PR [#15462](https://github.com/fastapi/fastapi/pull/15462) by [@alejsdev](https://github.com/alejsdev). * 💄 Refactor opinions section with interactive tabs and new logos. PR [#15458](https://github.com/fastapi/fastapi/pull/15458) by [@alejsdev](https://github.com/alejsdev). * 📝 Add FastAPI Conf '26 announcement to docs. PR [#15457](https://github.com/fastapi/fastapi/pull/15457) by [@alejsdev](https://github.com/alejsdev). From f8cbeabf81afba89f24bed790f73432b67941450 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Carlos=20Rodr=C3=ADguez=20Romo?= <110995013+crr004@users.noreply.github.com> Date: Tue, 5 May 2026 10:04:50 +0200 Subject: [PATCH 048/462] =?UTF-8?q?=F0=9F=8C=90=20Fix=20typos=20in=20Spani?= =?UTF-8?q?sh=20LLM-prompt=20(#15472)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Motov Yurii <109919500+YuriiMotov@users.noreply.github.com> --- docs/es/llm-prompt.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/docs/es/llm-prompt.md b/docs/es/llm-prompt.md index fcf4ad2b1..720de02b7 100644 --- a/docs/es/llm-prompt.md +++ b/docs/es/llm-prompt.md @@ -49,7 +49,7 @@ For the next terms, use the following translations: * Deep Learning: Deep Learning (do not translate to "Aprendizaje Profundo") * callback hell: callback hell (do not translate to "infierno de callbacks") * tip: Consejo (do not translate to "tip") -* check: Revisa (do not translate to "chequea" or "comprobación) +* check: Revisa (do not translate to "chequea" or "comprobación") * Cross-Origin Resource Sharing: Cross-Origin Resource Sharing (do not translate to "Compartición de Recursos de Origen Cruzado") * Release Notes: Release Notes (do not translate to "Notas de la Versión") * Semantic Versioning: Semantic Versioning (do not translate to "Versionado Semántico") @@ -83,8 +83,8 @@ For the next terms, use the following translations: * instantiate: crear un instance (do not translate to "instanciar") * OAuth2 Scopes: Scopes de OAuth2 (do not translate to "Alcances de OAuth2") * on the fly: sobre la marcha (do not translate to "al vuelo") -* terminal: terminal (femenine, as in "la terminal") -* terminals: terminales (plural femenine, as in "las terminales") +* terminal: terminal (feminine, as in "la terminal") +* terminals: terminales (plural feminine, as in "las terminales") * lifespan: lifespan (do not translate to "vida útil" or "tiempo de vida") * unload: quitar de memoria (do not translate to "descargar") * mount (noun): mount (do not translate to "montura") From 3efd86c1fde830c79b1233b4ecbb46b3dde81066 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Tue, 5 May 2026 08:05:22 +0000 Subject: [PATCH 049/462] =?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 1836fbed6..8b46fec31 100644 --- a/docs/en/docs/release-notes.md +++ b/docs/en/docs/release-notes.md @@ -14,6 +14,10 @@ hide: * 💄 Refactor opinions section with interactive tabs and new logos. PR [#15458](https://github.com/fastapi/fastapi/pull/15458) by [@alejsdev](https://github.com/alejsdev). * 📝 Add FastAPI Conf '26 announcement to docs. PR [#15457](https://github.com/fastapi/fastapi/pull/15457) by [@alejsdev](https://github.com/alejsdev). +### Translations + +* 🌐 Fix typos in Spanish LLM-prompt. PR [#15472](https://github.com/fastapi/fastapi/pull/15472) by [@crr004](https://github.com/crr004). + ### Internal * 👥 Update FastAPI GitHub topic repositories. PR [#15470](https://github.com/fastapi/fastapi/pull/15470) by [@tiangolo](https://github.com/tiangolo). From fb7429378d14bd2d868abf145e1f18724b15e25d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebasti=C3=A1n=20Ram=C3=ADrez?= Date: Tue, 5 May 2026 11:44:36 +0200 Subject: [PATCH 050/462] =?UTF-8?q?=F0=9F=91=B7=20Add=20pre-commit=20to=20?= =?UTF-8?q?check=20typos=20(#15482)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .pre-commit-config.yaml | 6 +++ pyproject.toml | 37 +++++++++++++++++++ ... test_response_set_response_code_empty.py} | 0 .../test_tutorial002.py | 7 +++- .../test_tutorial005.py | 2 +- tests/test_ws_router.py | 2 +- 6 files changed, 50 insertions(+), 4 deletions(-) rename tests/{test_reponse_set_reponse_code_empty.py => test_response_set_response_code_empty.py} (100%) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 7913c813a..d304b78e8 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -14,6 +14,12 @@ repos: - id: end-of-file-fixer - id: trailing-whitespace + - repo: https://github.com/crate-ci/typos + rev: bbaefadf97b0ec5fdc942684b647f1a6ab250274 # v1.46.0 + hooks: + - id: typos + args: [--force-exclude] + - repo: local hooks: - id: local-ruff-check diff --git a/pyproject.toml b/pyproject.toml index 8d8c4978d..7abb9a33c 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -335,3 +335,40 @@ keep-runtime-typing = true [tool.inline-snapshot] # default-flags=["fix"] # default-flags=["create"] + +[tool.typos.files] +extend-exclude = [ + "coverage/", + "dist/", + "docs/de/", + "docs/en/data/", + "docs/en/docs/img/", + "docs/en/docs/release-notes.md", + "docs/es/", + "docs/fr/", + "docs/ja/", + "docs/ko/", + "docs/language_names.yml", + "docs/pt/", + "docs/ru/", + "docs/tr/", + "docs/uk/", + "docs/zh/", + "docs/zh-hant/", + "htmlcov/", + "scripts/general-llm-prompt.md", + "scripts/tests/test_translation_fixer/test_complex_doc/", + "site/", + "site_build/", + "uv.lock", +] + +[tool.typos.default.extend-identifiers] +alls = "alls" + +[tool.typos.default.extend-words] +ba = "ba" +fo = "fo" +havin = "havin" +Ines = "Ines" +ser = "ser" diff --git a/tests/test_reponse_set_reponse_code_empty.py b/tests/test_response_set_response_code_empty.py similarity index 100% rename from tests/test_reponse_set_reponse_code_empty.py rename to tests/test_response_set_response_code_empty.py diff --git a/tests/test_tutorial/test_body_multiple_params/test_tutorial002.py b/tests/test_tutorial/test_body_multiple_params/test_tutorial002.py index b23402c3c..b9b9928ba 100644 --- a/tests/test_tutorial/test_body_multiple_params/test_tutorial002.py +++ b/tests/test_tutorial/test_body_multiple_params/test_tutorial002.py @@ -154,13 +154,16 @@ def test_post_missing_required_field_in_item(client: TestClient): def test_post_missing_required_field_in_user(client: TestClient): response = client.put( "/items/5", - json={"item": {"name": "Foo", "price": 50.5}, "user": {"ful_name": "John Doe"}}, + json={ + "item": {"name": "Foo", "price": 50.5}, + "user": {"full_name": "John Doe"}, + }, ) assert response.status_code == 422 assert response.json() == { "detail": [ { - "input": {"ful_name": "John Doe"}, + "input": {"full_name": "John Doe"}, "loc": [ "body", "user", diff --git a/tests/test_tutorial/test_body_multiple_params/test_tutorial005.py b/tests/test_tutorial/test_body_multiple_params/test_tutorial005.py index b8fc98cd7..6186380c9 100644 --- a/tests/test_tutorial/test_body_multiple_params/test_tutorial005.py +++ b/tests/test_tutorial/test_body_multiple_params/test_tutorial005.py @@ -82,7 +82,7 @@ def test_post_no_body(client: TestClient): } -def test_post_like_not_embeded(client: TestClient): +def test_post_like_not_embedded(client: TestClient): response = client.put( "/items/5", json={ diff --git a/tests/test_ws_router.py b/tests/test_ws_router.py index 240a42bb0..d8bcf1758 100644 --- a/tests/test_ws_router.py +++ b/tests/test_ws_router.py @@ -176,7 +176,7 @@ def test_router_with_params(): def test_wrong_uri(): """ - Verify that a websocket connection to a non-existent endpoing returns in a shutdown + Verify that a websocket connection to a non-existent endpoint returns in a shutdown """ client = TestClient(app) with pytest.raises(WebSocketDisconnect) as e: From 622b6356b5102113d0074083ac23c82367f4284b Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Tue, 5 May 2026 09:45:26 +0000 Subject: [PATCH 051/462] =?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 8b46fec31..a85f51e23 100644 --- a/docs/en/docs/release-notes.md +++ b/docs/en/docs/release-notes.md @@ -20,6 +20,7 @@ hide: ### Internal +* 👷 Add pre-commit to check typos. PR [#15482](https://github.com/fastapi/fastapi/pull/15482) by [@tiangolo](https://github.com/tiangolo). * 👥 Update FastAPI GitHub topic repositories. PR [#15470](https://github.com/fastapi/fastapi/pull/15470) by [@tiangolo](https://github.com/tiangolo). * 👥 Update FastAPI People - Experts. PR [#15471](https://github.com/fastapi/fastapi/pull/15471) by [@tiangolo](https://github.com/tiangolo). * 👥 Update FastAPI People - Contributors and Translators. PR [#15467](https://github.com/fastapi/fastapi/pull/15467) by [@tiangolo](https://github.com/tiangolo). From 3ec959abc7e93f90034ce63f0987f787a881463a Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 11 May 2026 13:58:35 +0200 Subject: [PATCH 052/462] =?UTF-8?q?=E2=AC=86=20Bump=20pydantic=20from=202.?= =?UTF-8?q?13.2=20to=202.13.3=20(#15444)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- uv.lock | 222 ++++++++++++++++++++++++++++---------------------------- 1 file changed, 111 insertions(+), 111 deletions(-) diff --git a/uv.lock b/uv.lock index b198d9761..5143597f5 100644 --- a/uv.lock +++ b/uv.lock @@ -3778,7 +3778,7 @@ wheels = [ [[package]] name = "pydantic" -version = "2.13.2" +version = "2.13.3" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "annotated-types" }, @@ -3786,9 +3786,9 @@ dependencies = [ { name = "typing-extensions" }, { name = "typing-inspection" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/09/e5/06d23afac9973109d1e3c8ad38e1547a12e860610e327c05ee686827dc37/pydantic-2.13.2.tar.gz", hash = "sha256:b418196607e61081c3226dcd4f0672f2a194828abb9109e9cfb84026564df2d1", size = 843836, upload-time = "2026-04-17T09:31:59.636Z" } +sdist = { url = "https://files.pythonhosted.org/packages/d9/e4/40d09941a2cebcb20609b86a559817d5b9291c49dd6f8c87e5feffbe703a/pydantic-2.13.3.tar.gz", hash = "sha256:af09e9d1d09f4e7fe37145c1f577e1d61ceb9a41924bf0094a36506285d0a84d", size = 844068, upload-time = "2026-04-20T14:46:43.632Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/77/ca/b45c378e6e8d0b90577288b533e04e95b7afd61bb1d51b6c263176435489/pydantic-2.13.2-py3-none-any.whl", hash = "sha256:a525087f4c03d7e7456a3de89b64cd693d2229933bb1068b9af6befd5563694e", size = 471947, upload-time = "2026-04-17T09:31:57.541Z" }, + { url = "https://files.pythonhosted.org/packages/f3/0a/fd7d723f8f8153418fb40cf9c940e82004fce7e987026b08a68a36dd3fe7/pydantic-2.13.3-py3-none-any.whl", hash = "sha256:6db14ac8dfc9a1e57f87ea2c0de670c251240f43cb0c30a5130e9720dc612927", size = 471981, upload-time = "2026-04-20T14:46:41.402Z" }, ] [package.optional-dependencies] @@ -3899,118 +3899,118 @@ xai = [ [[package]] name = "pydantic-core" -version = "2.46.2" +version = "2.46.3" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "typing-extensions" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/43/bb/4742f05b739b2478459bb16fa8470549518c802e06ddcf3f106c5081315e/pydantic_core-2.46.2.tar.gz", hash = "sha256:37bb079f9ee3f1a519392b73fda2a96379b31f2013c6b467fe693e7f2987f596", size = 471269, upload-time = "2026-04-17T09:10:07.017Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/a4/f2/98f37e836c5ba0335432768e0d8645e6f50a3c838b48a74d9256256784fc/pydantic_core-2.46.2-cp310-cp310-macosx_10_12_x86_64.whl", hash = "sha256:160ef93541f4f84e3e5068e6c1f64d8fd6f57586e5853d609b467d3333f8146a", size = 2108178, upload-time = "2026-04-17T09:10:24.689Z" }, - { url = "https://files.pythonhosted.org/packages/55/69/975458de8e5453322cfc57d6c7029c3e66d9e7a4389c53ddd5ad02d5e5da/pydantic_core-2.46.2-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:1a9124b63f4f40a12a0666df57450b4c24b98407ff74349221b869ec085a5d8e", size = 1949232, upload-time = "2026-04-17T09:11:39.536Z" }, - { url = "https://files.pythonhosted.org/packages/94/8d/938175e6e82d051ac4644765680db06571d7e106a42f760da09bd90f6525/pydantic_core-2.46.2-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:de12004a7da7f1eb67ece37439a5a23a915636085dd042176fda362e006e6940", size = 1974741, upload-time = "2026-04-17T09:13:01.922Z" }, - { url = "https://files.pythonhosted.org/packages/f2/38/7329f8ac5c732bddf15f939c2add40b95170e0ecca5ef124c12def3f78ba/pydantic_core-2.46.2-cp310-cp310-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:a070c7769fec277409ad0b3d55b2f0a3703a6f00cf5031fe93090f155bf56382", size = 2041905, upload-time = "2026-04-17T09:11:11.94Z" }, - { url = "https://files.pythonhosted.org/packages/99/2c/47cfd069937ee5cbc0d9e18fa9795c8f80c49a6b4fc777d4cd870f2ade7b/pydantic_core-2.46.2-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:41d701bb34f81f0b11c724cc544b9a10b26a28f4d0d1197f2037c91225708706", size = 2222703, upload-time = "2026-04-17T09:10:31.196Z" }, - { url = "https://files.pythonhosted.org/packages/83/b0/7ed83ca8cd92c99bcab90cf42ed953723fbc19d8a20c8c12bb68c51febc1/pydantic_core-2.46.2-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:19631e7350b7a574fb6b6db222f4b17e8bd31803074b3307d07df62379d2b2e4", size = 2276317, upload-time = "2026-04-17T09:09:53.263Z" }, - { url = "https://files.pythonhosted.org/packages/85/70/50b1b62990996e7916aae2852b29cbf3ecc3fdae78209eb284cd61e2c918/pydantic_core-2.46.2-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:48b1059e4f2a6ec3e41983148eb1eec5ef9fa3a80bbc4ac0893ac76b115fe039", size = 2092152, upload-time = "2026-04-17T09:10:44.683Z" }, - { url = "https://files.pythonhosted.org/packages/c1/51/a062864e6b34ada7e343ad9ed29368e495620a8ef1c009b47a68b46e1634/pydantic_core-2.46.2-cp310-cp310-manylinux_2_31_riscv64.whl", hash = "sha256:df73724fce8ad53c670358c905b37930bd7b9d92e57db640a65c53b2706eee00", size = 2118091, upload-time = "2026-04-17T09:10:05.083Z" }, - { url = "https://files.pythonhosted.org/packages/07/e0/fcc97c4d0319615dc0b5b132b420904639652f8514e9c76482acb70ea1d4/pydantic_core-2.46.2-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:a0891a9be0def16fb320af21a198ece052eed72bf44d73d8ff43f702bd26fd6b", size = 2174304, upload-time = "2026-04-17T09:11:00.54Z" }, - { url = "https://files.pythonhosted.org/packages/00/52/28f53796ca74b7e3dd45938f300517f04970e985ad600d0d0f36a11378bd/pydantic_core-2.46.2-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:2ca790779aa1cba1329b8dc42ccebada441d9ac1d932de980183d544682c646d", size = 2181444, upload-time = "2026-04-17T09:11:45.442Z" }, - { url = "https://files.pythonhosted.org/packages/22/49/164d5d3a7356d2607a72e77264a3b252a7c7d9362a81fc9df47bef7ae3aa/pydantic_core-2.46.2-cp310-cp310-musllinux_1_1_armv7l.whl", hash = "sha256:6b865eb702c3af71cf7331919a787563ce2413f7a54ef49ec6709a01b4f22ce6", size = 2328611, upload-time = "2026-04-17T09:10:08.574Z" }, - { url = "https://files.pythonhosted.org/packages/6b/77/6266bb3b79c27b533e5ee02c1e3da5848872112178880cc5006a84e857ac/pydantic_core-2.46.2-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:631bec5f951a30a4b332b4a57d0cdd5a2c8187eb71301f966425f2e54a697855", size = 2351070, upload-time = "2026-04-17T09:13:34.92Z" }, - { url = "https://files.pythonhosted.org/packages/10/7f/d4233852d16d8e85b034a524d8017e051a0aa4acd04c64c3a69a1a2a0ba6/pydantic_core-2.46.2-cp310-cp310-win32.whl", hash = "sha256:8cbd9d67357f3a925f2af1d44db3e8ef1ce1a293ea0add98081b072d4a12e3b4", size = 1976750, upload-time = "2026-04-17T09:13:15.537Z" }, - { url = "https://files.pythonhosted.org/packages/70/31/d65117cf5f89d81705da5b1dcdad8efa0a0b65dbbc7f13cafbabb7d01615/pydantic_core-2.46.2-cp310-cp310-win_amd64.whl", hash = "sha256:dd51dd16182b4bfdcefd27b39b856aa4a57b77f15b231a2d10c45391b0a02028", size = 2073989, upload-time = "2026-04-17T09:12:17.315Z" }, - { url = "https://files.pythonhosted.org/packages/89/91/089f517a725f29084364169437833ab0ae4da4d7a6ed9d4474db7f1412e6/pydantic_core-2.46.2-cp311-cp311-macosx_10_12_x86_64.whl", hash = "sha256:d8060f42db3cd204871db0afd51fef54a13fa544c4dd48cdcae2e174ef40c8ba", size = 2106218, upload-time = "2026-04-17T09:10:48.023Z" }, - { url = "https://files.pythonhosted.org/packages/a0/92/23858ed1b58f2a134e50c2fdd0e34ea72721ccb257e1e9346514e1ccb5b9/pydantic_core-2.46.2-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:73a9d2809bd8d4a7cda4d336dc996a565eb4feaaa39932f9d85a65fa18382f28", size = 1948087, upload-time = "2026-04-17T09:11:58.639Z" }, - { url = "https://files.pythonhosted.org/packages/5d/ac/e2240fccb4794e965817593d5a46cf5ea22f2001b73fe360b7578925b7d8/pydantic_core-2.46.2-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3b0a2dee92dfaabcfb93629188c3e9cf74fdfc0f22e7c369cb444a98814a1e50", size = 1972931, upload-time = "2026-04-17T09:13:13.304Z" }, - { url = "https://files.pythonhosted.org/packages/1a/da/3b11dab2aa15c5c8ed20a01eb7aa432a78b8e3a4713659f7e58490a020a5/pydantic_core-2.46.2-cp311-cp311-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:3098446ba8cf774f61cb8d4008c1dba14a30426a15169cd95ac3392a461193b1", size = 2040454, upload-time = "2026-04-17T09:13:47.895Z" }, - { url = "https://files.pythonhosted.org/packages/d7/39/c4cf5e1f1c6c34c53c0902039c95d81dc15cdd1f03634bd1a93f33e70a72/pydantic_core-2.46.2-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:57c584af6c375ea3f826d8131a94cb212b3d9926eaff67117e3711bbff3a83a5", size = 2221320, upload-time = "2026-04-17T09:13:08.568Z" }, - { url = "https://files.pythonhosted.org/packages/c7/46/891035bc9e93538e754c3188424d24b5a69ec3ae5210fa01d483e99b3302/pydantic_core-2.46.2-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:547381cca999be88b4715a0ed7afa11f07fc7e53cb1883687b190d25a92c56cf", size = 2274559, upload-time = "2026-04-17T09:11:10.257Z" }, - { url = "https://files.pythonhosted.org/packages/ab/d0/7af0b905b3148152c159c9caf203e7ecd9b90b76389f0862e6ab0cf1b2a3/pydantic_core-2.46.2-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:caeed15dcb1233a5a94bc6ff37ef5393cf5b33a45e4bdfb2d6042f3d24e1cb27", size = 2089239, upload-time = "2026-04-17T09:13:06.326Z" }, - { url = "https://files.pythonhosted.org/packages/c5/bc/566afe02ba2de37712eece74ac7bfba322abd7916410bf90504f1b17ddad/pydantic_core-2.46.2-cp311-cp311-manylinux_2_31_riscv64.whl", hash = "sha256:c05f53362568c75476b5c96659377a5dfd982cfbe5a5c07de5106d08a04efc4f", size = 2116182, upload-time = "2026-04-17T09:11:33.738Z" }, - { url = "https://files.pythonhosted.org/packages/4e/5b/3fcb3a229bbfa23b0e3c65014057af0f9d51ec7a2d9f7adb282f41ff5ac8/pydantic_core-2.46.2-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:2643ac7eae296200dbd48762a1c852cf2cad5f5e3eba34e652053cebf03becf8", size = 2172346, upload-time = "2026-04-17T09:10:46.472Z" }, - { url = "https://files.pythonhosted.org/packages/43/9a/baa9e3aa70ea7bbcb9db0f87162a371649ac80c03e43eb54af193390cf17/pydantic_core-2.46.2-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:dc4620a47c6fe6a39f89392c00833a82fc050ce90169798f78a25a8d4df03b6e", size = 2179540, upload-time = "2026-04-17T09:11:21.881Z" }, - { url = "https://files.pythonhosted.org/packages/bd/46/912047a5427f949c909495704b3c8b9ead9d1c66f87e96606011beab1fcb/pydantic_core-2.46.2-cp311-cp311-musllinux_1_1_armv7l.whl", hash = "sha256:78cb0d2453b50bf2035f85fd0d9cfabdb98c47f9c53ddb7c23873cd83da9560b", size = 2327423, upload-time = "2026-04-17T09:13:40.291Z" }, - { url = "https://files.pythonhosted.org/packages/e9/bf/c5e661451dc9411c2ab88a244c1ba57644950c971486040dc200f77b69f4/pydantic_core-2.46.2-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:f0c1cbb7d6112932cc188c6be007a5e2867005a069e47f42fe67bf5f122b0908", size = 2348652, upload-time = "2026-04-17T09:10:37.76Z" }, - { url = "https://files.pythonhosted.org/packages/77/b3/3219e7c522af54b010cf7422dcb11cc6616a4414d1ccd628b0d3f61c6af6/pydantic_core-2.46.2-cp311-cp311-win32.whl", hash = "sha256:c1ce5b2366f85cfdbf7f0907755043707f86d09a5b1b1acebbb7bf1600d75c64", size = 1974410, upload-time = "2026-04-17T09:13:27.392Z" }, - { url = "https://files.pythonhosted.org/packages/e5/29/e5cfac8a74c59873dfd47d3a1477c39ad9247639a7120d3e251a9ff12417/pydantic_core-2.46.2-cp311-cp311-win_amd64.whl", hash = "sha256:f1a6197eadff5bd0bb932f12bb038d403cb75db5b0b391e70e816a647745ddaf", size = 2071158, upload-time = "2026-04-17T09:09:57.69Z" }, - { url = "https://files.pythonhosted.org/packages/6f/8b/b7b19b717cdb3675cb109de143f62d4dc62f5d4a0b9879b6f1ace62c6654/pydantic_core-2.46.2-cp311-cp311-win_arm64.whl", hash = "sha256:15e42885b283f87846ee79e161002c5c496ef747a73f6e47054f45a13d9035bc", size = 2043507, upload-time = "2026-04-17T09:09:51.828Z" }, - { url = "https://files.pythonhosted.org/packages/97/ec/2fafa4c86f5d2a69372c7cddef30925fd0e370b1efaf556609c1a0196d8a/pydantic_core-2.46.2-cp312-cp312-macosx_10_12_x86_64.whl", hash = "sha256:ea1ad8c89da31512fe2d249cf0638fb666925bda341901541bc5f3311c6fcc9e", size = 2101729, upload-time = "2026-04-17T09:12:30.042Z" }, - { url = "https://files.pythonhosted.org/packages/cf/55/be5386c2c4b49af346e8a26b748194ff25757bbb6cf544130854e997af7a/pydantic_core-2.46.2-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:b308da17b92481e0587244631c5529e5d91d04cb2b08194825627b1eca28e21e", size = 1951546, upload-time = "2026-04-17T09:10:10.585Z" }, - { url = "https://files.pythonhosted.org/packages/29/92/89e273a055ce440e6636c756379af35ad86da9d336a560049c3ba5e41c80/pydantic_core-2.46.2-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d333a50bdd814a917d8d6a7ee35ba2395d53ddaa882613bc24e54a9d8b129095", size = 1976178, upload-time = "2026-04-17T09:11:49.619Z" }, - { url = "https://files.pythonhosted.org/packages/91/b3/e4664469cf70c0cb0f7b2f5719d64e5968bb6f38217042c2afa3d3c4ba17/pydantic_core-2.46.2-cp312-cp312-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:1d00b99590c5bd1fabbc5d28b170923e32c1b1071b1f1de1851a4d14d89eb192", size = 2051697, upload-time = "2026-04-17T09:12:04.917Z" }, - { url = "https://files.pythonhosted.org/packages/98/58/dbf68213ee06ce51cdd6d8c95f97980e646858c45bd96bd2dfb40433be73/pydantic_core-2.46.2-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:9f0e686960ffe9e65066395af856ac2d52c159043144433602c50c221d81c1ba", size = 2233160, upload-time = "2026-04-17T09:12:00.956Z" }, - { url = "https://files.pythonhosted.org/packages/f5/d3/68092aa0ee6c60ff4de4740eb82db3d4ce338ec89b3cecb978c532472f12/pydantic_core-2.46.2-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:2d1128da41c9cb474e0a4701f9c363ec645c9d1a02229904c76bf4e0a194fde2", size = 2298398, upload-time = "2026-04-17T09:10:29.694Z" }, - { url = "https://files.pythonhosted.org/packages/e4/51/5d6155eb737db55b0ad354ca5f333ef009f75feb67df2d79a84bace45af6/pydantic_core-2.46.2-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:48649cf2d8c358d79586e9fb2f8235902fcaa2d969ec1c5301f2d1873b2f8321", size = 2094058, upload-time = "2026-04-17T09:12:10.995Z" }, - { url = "https://files.pythonhosted.org/packages/6b/f3/eb4a986197d71319430464ff181226c95adc8f06d932189b158bae5a82f5/pydantic_core-2.46.2-cp312-cp312-manylinux_2_31_riscv64.whl", hash = "sha256:b902f0fc7c2cf503865a05718b68147c6cd5d0a3867af38c527be574a9fa6e9d", size = 2130388, upload-time = "2026-04-17T09:12:41.159Z" }, - { url = "https://files.pythonhosted.org/packages/56/00/44a9c4fe6d0f64b5786d6a8c649d6f0e34ba6c89b3663add1066e54451a2/pydantic_core-2.46.2-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:e80011f808b03d1d87a8f1e76ae3da19a18eb706c823e17981dcf1fae43744fc", size = 2184245, upload-time = "2026-04-17T09:12:36.532Z" }, - { url = "https://files.pythonhosted.org/packages/78/6b/685b98a834d5e3d1c34a1bde1627525559dd223b75075bc7490cdb24eb33/pydantic_core-2.46.2-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:b839d5c802e31348b949b6473f8190cddbf7d47475856d8ac995a373ee16ec59", size = 2186842, upload-time = "2026-04-17T09:13:04.054Z" }, - { url = "https://files.pythonhosted.org/packages/22/64/caa2f5a2ac8b6113adaa410ccdf31ba7f54897a6e54cd0d726fc7e780c88/pydantic_core-2.46.2-cp312-cp312-musllinux_1_1_armv7l.whl", hash = "sha256:c6b1064f3f9cf9072e1d59dd2936f9f3b668bec1c37039708c9222db703c0d5b", size = 2336066, upload-time = "2026-04-17T09:12:13.006Z" }, - { url = "https://files.pythonhosted.org/packages/ee/f9/7d2701bf82945b5b9e7df8347be97ef6a36da2846bfe5b4afec299ffe27b/pydantic_core-2.46.2-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:37a68e6f2ac95578ce3c0564802404b27b24988649616e556c07e77111ed3f1d", size = 2363691, upload-time = "2026-04-17T09:13:42.972Z" }, - { url = "https://files.pythonhosted.org/packages/3b/65/0dab11574101522941055109419db3cc09db871643dc3fc74e2413215e5b/pydantic_core-2.46.2-cp312-cp312-win32.whl", hash = "sha256:d9ffa75a7ef4b97d6e5e205fabd4304ef01fec09e6f1bdde04b9ad1b07d20289", size = 1958801, upload-time = "2026-04-17T09:11:31.981Z" }, - { url = "https://files.pythonhosted.org/packages/13/2b/df84baa609c676f6450b8ecad44ea59146c805e3371b7b52443c0899f989/pydantic_core-2.46.2-cp312-cp312-win_amd64.whl", hash = "sha256:0551f2d2ddb68af5a00e26497f8025c538f73ef3cb698f8e5a487042cd2792a8", size = 2072634, upload-time = "2026-04-17T09:11:02.407Z" }, - { url = "https://files.pythonhosted.org/packages/d1/4e/e1ce8029fc438086a946739bf9d596f70ff470aad4a8345555920618cabe/pydantic_core-2.46.2-cp312-cp312-win_arm64.whl", hash = "sha256:83aef30f106edcc21a6a4cc44b82d3169a1dbe255508db788e778f3c804d3583", size = 2026188, upload-time = "2026-04-17T09:13:11.083Z" }, - { url = "https://files.pythonhosted.org/packages/07/2b/662e48254479a2d3450ba24b1e25061108b64339794232f503990c519144/pydantic_core-2.46.2-cp313-cp313-macosx_10_12_x86_64.whl", hash = "sha256:d26e9eea3715008a09a74585fe9becd0c67fbb145dc4df9756d597d7230a652c", size = 2101762, upload-time = "2026-04-17T09:10:13.87Z" }, - { url = "https://files.pythonhosted.org/packages/73/ab/bafd7c7503757ccc8ec4d1911e106fe474c629443648c51a88f08b0fe91a/pydantic_core-2.46.2-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:48b36e3235140510dc7861f0cd58b714b1cdd3d48f75e10ce52e69866b746f10", size = 1951814, upload-time = "2026-04-17T09:12:25.934Z" }, - { url = "https://files.pythonhosted.org/packages/92/cc/7549c2d57ba2e9a42caa5861a2d398dbe31c02c6aca783253ace59ce84f8/pydantic_core-2.46.2-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:36b1f99dc451f1a3981f236151465bcf995bbe712d0727c9f7b236fe228a8133", size = 1977329, upload-time = "2026-04-17T09:13:37.605Z" }, - { url = "https://files.pythonhosted.org/packages/18/50/7ed4a8a0d478a4dca8f0134a5efa7193f03cc8520dd4c9509339fb2e5002/pydantic_core-2.46.2-cp313-cp313-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:8641c8d535c2d95b45c2e19b646ecd23ebba35d461e0ae48a3498277006250ab", size = 2051832, upload-time = "2026-04-17T09:12:49.771Z" }, - { url = "https://files.pythonhosted.org/packages/dc/16/bb35b193741c0298ddc5f5e4234269efdc0c65e2bcd198aa0de9b68845e4/pydantic_core-2.46.2-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:20fb194788a0a50993e87013e693494ba183a2af5b44e99cf060bbae10912b11", size = 2233127, upload-time = "2026-04-17T09:11:04.449Z" }, - { url = "https://files.pythonhosted.org/packages/91/a5/98f4b637149185addea19e1785ea20c373cca31b202f589111d8209d9873/pydantic_core-2.46.2-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:9262d11d0cd11ee3303a95156939402bed6cedfe5ed0e331b95a283a4da6eb8b", size = 2297418, upload-time = "2026-04-17T09:11:25.929Z" }, - { url = "https://files.pythonhosted.org/packages/36/90/93a5d21990b152da7b7507b7fddb0b935f6a0984d57ac3ec45a6e17777a2/pydantic_core-2.46.2-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ac204542736aa295fa25f713b7fad6fc50b46ab7764d16087575c85f085174f3", size = 2093735, upload-time = "2026-04-17T09:12:06.908Z" }, - { url = "https://files.pythonhosted.org/packages/14/22/b8b1ffdddf08b4e84380bcb67f41dbbf4c171377c1d36fc6290794bb2094/pydantic_core-2.46.2-cp313-cp313-manylinux_2_31_riscv64.whl", hash = "sha256:9a7c43a0584742dface3ca0daf6f719d46c1ac2f87cf080050f9ae052c75e1b2", size = 2127570, upload-time = "2026-04-17T09:11:53.906Z" }, - { url = "https://files.pythonhosted.org/packages/c6/26/e60d72b4e2d0ce1fa811044a974412ac1c567fe067d97b3e6b290530786e/pydantic_core-2.46.2-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:fd05e1edb6a90ad446fa268ab09e59202766b837597b714b2492db11ee87fab9", size = 2183524, upload-time = "2026-04-17T09:11:30.092Z" }, - { url = "https://files.pythonhosted.org/packages/35/32/36bec7584a1eefb17dec4dfa1c946d3fe4440f466c5705b8adfda69c9a9f/pydantic_core-2.46.2-cp313-cp313-musllinux_1_1_aarch64.whl", hash = "sha256:91155b110788b5501abc7ea954f1d08606219e4e28e3c73a94124307c06efb80", size = 2185408, upload-time = "2026-04-17T09:10:57.228Z" }, - { url = "https://files.pythonhosted.org/packages/fc/d6/1a5689d873620efd67d6b163db0c444c056adb0849b5bc33e2b9f09665a6/pydantic_core-2.46.2-cp313-cp313-musllinux_1_1_armv7l.whl", hash = "sha256:e4e2c72a529fa03ff228be1d2b76944013f428220b764e03cc50ada67e17a42c", size = 2335171, upload-time = "2026-04-17T09:11:43.369Z" }, - { url = "https://files.pythonhosted.org/packages/3e/8e/675104802abe8ef502b072050ee5f2e915251aa1a3af87e1015ce31ec42d/pydantic_core-2.46.2-cp313-cp313-musllinux_1_1_x86_64.whl", hash = "sha256:56291ec1a11c3499890c99a8fd9053b47e60fe837a77ec72c0671b1b8b3dce24", size = 2362743, upload-time = "2026-04-17T09:10:18.333Z" }, - { url = "https://files.pythonhosted.org/packages/8d/bc/86c5dde4fa6e24467680eef5047da3c1a19be0a527d0d8e14aa76b39307c/pydantic_core-2.46.2-cp313-cp313-win32.whl", hash = "sha256:b50f9c5f826ddca1246f055148df939f5f3f2d0d96db73de28e2233f22210d4c", size = 1958074, upload-time = "2026-04-17T09:12:38.622Z" }, - { url = "https://files.pythonhosted.org/packages/2a/97/2537e8c1282b2c4eb062580c0d7a4339e10b072b803d1ee0b7f1f0a5c22c/pydantic_core-2.46.2-cp313-cp313-win_amd64.whl", hash = "sha256:251a57788823230ca8cbc99e6245d1a2ed6e180ec4864f251c94182c580c7f2e", size = 2071741, upload-time = "2026-04-17T09:13:32.405Z" }, - { url = "https://files.pythonhosted.org/packages/da/aa/2ee75798706f9dbc4e76dbe59e41a396c5c311e3d6223b9cf6a5fa7780be/pydantic_core-2.46.2-cp313-cp313-win_arm64.whl", hash = "sha256:315d32d1a71494d6b4e1e14a9fa7a4329597b4c4340088ad7e1a9dafbeed92a9", size = 2025955, upload-time = "2026-04-17T09:10:15.567Z" }, - { url = "https://files.pythonhosted.org/packages/d0/96/a50ccb6b539ae780f73cea74905468777680e30c6c3bdf714b9d4c116ea0/pydantic_core-2.46.2-cp314-cp314-macosx_10_12_x86_64.whl", hash = "sha256:4f59b45f3ef8650c0c736a57f59031d47ed9df4c0a64e83796849d7d14863a2d", size = 2097111, upload-time = "2026-04-17T09:10:49.617Z" }, - { url = "https://files.pythonhosted.org/packages/34/5f/fdead7b3afa822ab6e5a18ee0ecffd54937de1877c01ed13a342e0fb3f07/pydantic_core-2.46.2-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:3a075a29ebef752784a91532a1a85be6b234ccffec0a9d7978a92696387c3da6", size = 1951904, upload-time = "2026-04-17T09:12:32.062Z" }, - { url = "https://files.pythonhosted.org/packages/95/e0/1c5d547e550cdab1bec737492aa08865337af6fe7fc9b96f7f45f17d9519/pydantic_core-2.46.2-cp314-cp314-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0d12d786e30c04a9d307c5d7080bf720d9bac7f1668191d8e37633a9562749e2", size = 1978667, upload-time = "2026-04-17T09:11:35.589Z" }, - { url = "https://files.pythonhosted.org/packages/0e/cb/665ce629e218c8228302cb94beff4f6531082a2c87d3ecc3d5e63a26f392/pydantic_core-2.46.2-cp314-cp314-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:0d5e6d6343b0b5dcacb3503b5de90022968da8ed0ab9ab39d3eda71c20cbf84e", size = 2046721, upload-time = "2026-04-17T09:11:47.725Z" }, - { url = "https://files.pythonhosted.org/packages/77/e9/6cb2cf60f54c1472bbdfce19d957553b43dbba79d1d7b2930a195c594785/pydantic_core-2.46.2-cp314-cp314-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:233eebac0999b6b9ba76eb56f3ec8fce13164aa16b6d2225a36a79e0f95b5973", size = 2228483, upload-time = "2026-04-17T09:12:08.837Z" }, - { url = "https://files.pythonhosted.org/packages/0d/2a/93e018dd5571f781ebaeda8c0cf65398489d5bee9b1f484df0b6149b43b9/pydantic_core-2.46.2-cp314-cp314-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:9cc0eee720dd2f14f3b7c349469402b99ad81a174ab49d3533974529e9d93992", size = 2294663, upload-time = "2026-04-17T09:12:52.053Z" }, - { url = "https://files.pythonhosted.org/packages/5e/4f/49e57ca55c770c93d9bb046666a54949b42e3c9099a0c5fe94557873fe30/pydantic_core-2.46.2-cp314-cp314-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:83ee76bf2c9910513dbc19e7d82367131fa7508dedd6186a462393071cc11059", size = 2098742, upload-time = "2026-04-17T09:13:45.472Z" }, - { url = "https://files.pythonhosted.org/packages/c6/b0/6e46b5cd3332af665f794b8cdeea206618a8630bd9e7bcc36864518fce81/pydantic_core-2.46.2-cp314-cp314-manylinux_2_31_riscv64.whl", hash = "sha256:d61db38eb4ee5192f0c261b7f2d38e420b554df8912245e3546aee5c45e2fd78", size = 2125922, upload-time = "2026-04-17T09:12:54.304Z" }, - { url = "https://files.pythonhosted.org/packages/06/d1/40850c81585be443a2abfdf7f795f8fae831baf8e2f9b2133c8246ac671c/pydantic_core-2.46.2-cp314-cp314-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:8f09a713d17bcd55da8ab02ebd9110c5246a49c44182af213b5212800af8bc83", size = 2183000, upload-time = "2026-04-17T09:10:59.027Z" }, - { url = "https://files.pythonhosted.org/packages/04/af/8493d7dfa03ebb7866909e577c6aa65ea0de7377b86023cc51d0c8e11db3/pydantic_core-2.46.2-cp314-cp314-musllinux_1_1_aarch64.whl", hash = "sha256:30cacc5fb696e64b8ef6fd31d9549d394dd7d52760db072eecb98e37e3af1677", size = 2180335, upload-time = "2026-04-17T09:12:57.01Z" }, - { url = "https://files.pythonhosted.org/packages/72/5b/1f6a344c4ffdf284da41c6067b82d5ebcbd11ce1b515ae4b662d4adb6f61/pydantic_core-2.46.2-cp314-cp314-musllinux_1_1_armv7l.whl", hash = "sha256:7ccfb105fcfe91a22bbb5563ad3dc124bc1aa75bfd2e53a780ab05f78cdf6108", size = 2330002, upload-time = "2026-04-17T09:12:02.958Z" }, - { url = "https://files.pythonhosted.org/packages/25/ff/9a694126c12d6d2f48a0cafa6f8eef88ef0d8825600e18d03ff2e896c3b2/pydantic_core-2.46.2-cp314-cp314-musllinux_1_1_x86_64.whl", hash = "sha256:13ffef637dc8370c249e5b26bd18e9a80a4fca3d809618c44e18ec834a7ca7a8", size = 2359920, upload-time = "2026-04-17T09:10:27.764Z" }, - { url = "https://files.pythonhosted.org/packages/51/c8/3a35c763d68a9cb2675eb10ef242cf66c5d4701b28ae12e688d67d2c180e/pydantic_core-2.46.2-cp314-cp314-win32.whl", hash = "sha256:1b0ab6d756ca2704a938e6c31b53f290c2f9c10d3914235410302a149de1a83e", size = 1953701, upload-time = "2026-04-17T09:13:30.021Z" }, - { url = "https://files.pythonhosted.org/packages/1a/6a/f2726a780365f7dfd89d62036f984f7acb99978c60c5e1fa7c0cb898ed11/pydantic_core-2.46.2-cp314-cp314-win_amd64.whl", hash = "sha256:99ebade8c9ada4df975372d8dd25883daa0e379a05f1cd0c99aa0c04368d01a6", size = 2071867, upload-time = "2026-04-17T09:10:39.205Z" }, - { url = "https://files.pythonhosted.org/packages/e1/79/76baacb9feba3d7c399b245ca1a29c74ea0db04ea693811374827eec2290/pydantic_core-2.46.2-cp314-cp314-win_arm64.whl", hash = "sha256:de87422197cf7f83db91d89c86a21660d749b3cd76cd8a45d115b8e675670f02", size = 2017252, upload-time = "2026-04-17T09:10:26.175Z" }, - { url = "https://files.pythonhosted.org/packages/f1/3b/77c26938f817668d9ad9bab1a905cb23f11d9a3d4bf724d429b3e55a8eaf/pydantic_core-2.46.2-cp314-cp314t-macosx_10_12_x86_64.whl", hash = "sha256:236f22b4a206b5b61db955396b7cf9e2e1ff77f372efe9570128ccfcd6a525eb", size = 2094545, upload-time = "2026-04-17T09:12:19.339Z" }, - { url = "https://files.pythonhosted.org/packages/fe/de/42c13f590e3c260966aa49bcdb1674774f975467c49abd51191e502bea28/pydantic_core-2.46.2-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:c2012f64d2cd7cca50f49f22445aa5a88691ac2b4498ee0a9a977f8ca4f7289f", size = 1933953, upload-time = "2026-04-17T09:09:55.889Z" }, - { url = "https://files.pythonhosted.org/packages/4e/84/ebe3ebb3e2d8db656937cfa6f97f544cb7132f2307a4a7dfdcd0ea102a12/pydantic_core-2.46.2-cp314-cp314t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d07d6c63106d3a9c9a333e2636f9c82c703b1a9e3b079299e58747964e4fdb72", size = 1974435, upload-time = "2026-04-17T09:10:12.371Z" }, - { url = "https://files.pythonhosted.org/packages/b9/15/0bf51ca6709477cd4ef86148b6d7844f3308f029eac361dd0383f1e17b1a/pydantic_core-2.46.2-cp314-cp314t-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:c326a2b4b85e959d9a1fc3a11f32f84611b6ec07c053e1828a860edf8d068208", size = 2031113, upload-time = "2026-04-17T09:10:00.752Z" }, - { url = "https://files.pythonhosted.org/packages/02/ae/b7b5af9b79db036d9e61a44c481c17a213dc8fc4b8b71fe6875a72fc778b/pydantic_core-2.46.2-cp314-cp314t-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:ac8a65e798f2462552c00d2e013d532c94d646729dda98458beaf51f9ec7b120", size = 2236325, upload-time = "2026-04-17T09:10:33.227Z" }, - { url = "https://files.pythonhosted.org/packages/a6/ae/ecef7477b5a03d4a499708f7e75d2836452ebb70b776c2d64612b334f57a/pydantic_core-2.46.2-cp314-cp314t-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:5a3c2bc1cc8164bedbc160b7bb1e8cc1e8b9c27f69ae4f9ae2b976cdae02b2dd", size = 2278135, upload-time = "2026-04-17T09:10:23.287Z" }, - { url = "https://files.pythonhosted.org/packages/db/e4/2f9d82faa47af6c39fc3f120145fd915971e1e0cb6b55b494fad9fdf8275/pydantic_core-2.46.2-cp314-cp314t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e69aa5e10b7e8b1bb4a6888650fd12fcbf11d396ca11d4a44de1450875702830", size = 2109071, upload-time = "2026-04-17T09:11:06.149Z" }, - { url = "https://files.pythonhosted.org/packages/f1/9c/677cf10873fbd0b116575ab7b97c90482b21564f8a8040beb18edef7a577/pydantic_core-2.46.2-cp314-cp314t-manylinux_2_31_riscv64.whl", hash = "sha256:4e6df5c3301e65fb42bc5338bf9a1027a02b0a31dc7f54c33775229af474daf0", size = 2106028, upload-time = "2026-04-17T09:10:51.525Z" }, - { url = "https://files.pythonhosted.org/packages/d6/53/6a06183544daba51c059123a2064a99039df25f115a06bdb26f2ea177038/pydantic_core-2.46.2-cp314-cp314t-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:2c2f6e32548ac8d559b47944effcf8ae4d81c161f6b6c885edc53bc08b8f192d", size = 2164816, upload-time = "2026-04-17T09:11:56.187Z" }, - { url = "https://files.pythonhosted.org/packages/57/6f/10fcdd9e3eca66fc828eef0f6f5850f2dd3bca2c59e6e041fb8bc3da39be/pydantic_core-2.46.2-cp314-cp314t-musllinux_1_1_aarch64.whl", hash = "sha256:b089a81c58e6ea0485562bbbbbca4f65c0549521606d5ef27fba217aac9b665a", size = 2166130, upload-time = "2026-04-17T09:10:03.804Z" }, - { url = "https://files.pythonhosted.org/packages/29/83/92d3fd0e0156cad2e3cb5c26de73794af78ac9fa0c22ab666e566dd67061/pydantic_core-2.46.2-cp314-cp314t-musllinux_1_1_armv7l.whl", hash = "sha256:7f700a6d6f64112ae9193709b84303bbab84424ad4b47d0253301aabce9dfc70", size = 2316605, upload-time = "2026-04-17T09:12:45.249Z" }, - { url = "https://files.pythonhosted.org/packages/97/f1/facffdb970981068219582e499b8d0871ed163ffcc6b347de5c412669e4c/pydantic_core-2.46.2-cp314-cp314t-musllinux_1_1_x86_64.whl", hash = "sha256:67db6814beaa5fefe91101ec7eb9efda613795767be96f7cf58b1ca8c9ca9972", size = 2358385, upload-time = "2026-04-17T09:09:54.657Z" }, - { url = "https://files.pythonhosted.org/packages/8b/a1/b8160b2f22b2199467bc68581a4ed380643c16b348a27d6165c6c242d694/pydantic_core-2.46.2-cp314-cp314t-win32.whl", hash = "sha256:32fbc7447be8e3be99bf7869f7066308f16be55b61f9882c2cefc7931f5c7664", size = 1942373, upload-time = "2026-04-17T09:12:59.594Z" }, - { url = "https://files.pythonhosted.org/packages/0d/90/db89acabe5b150e11d1b59fe3d947dda2ef6abbfef5c82f056ff63802f5d/pydantic_core-2.46.2-cp314-cp314t-win_amd64.whl", hash = "sha256:b317a2b97019c0b95ce99f4f901ae383f40132da6706cdf1731066a73394c25c", size = 2052078, upload-time = "2026-04-17T09:10:19.96Z" }, - { url = "https://files.pythonhosted.org/packages/97/32/e19b83ceb07a3f1bb21798407790bbc9a31740158fd132b94139cb84e16c/pydantic_core-2.46.2-cp314-cp314t-win_arm64.whl", hash = "sha256:7dcb9d40930dfad7ab6b20bcc6ca9d2b030b0f347a0cd9909b54bd53ead521b1", size = 2016941, upload-time = "2026-04-17T09:12:34.447Z" }, - { url = "https://files.pythonhosted.org/packages/25/ec/e91aa08df1c33d5e3c2b60c07a1eca9f21809728a824c7b467bb3bda68b5/pydantic_core-2.46.2-graalpy311-graalpy242_311_native-macosx_10_12_x86_64.whl", hash = "sha256:7c5a5b3dbb9e8918e223be6580da5ffcf861c0505bbc196ebed7176ce05b7b4e", size = 2105046, upload-time = "2026-04-17T09:10:55.614Z" }, - { url = "https://files.pythonhosted.org/packages/f0/73/27112400a0452e375290e7c40aef5cc9844ac0920fb1029238cfc68121fa/pydantic_core-2.46.2-graalpy311-graalpy242_311_native-macosx_11_0_arm64.whl", hash = "sha256:bc1e8ce33d5a337f2ba862e0719b8201cd54aaed967406c748e009191d47efdd", size = 1940029, upload-time = "2026-04-17T09:12:21.5Z" }, - { url = "https://files.pythonhosted.org/packages/b1/44/3d39f782bc82ddd0b2d82bde83b408aa40a332cdf6f3018acb34e3d4dcfc/pydantic_core-2.46.2-graalpy311-graalpy242_311_native-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b737c0b280f41143266445de2689c0e49c79307e51c44ce3a77fef2bedad4994", size = 1987772, upload-time = "2026-04-17T09:10:02.357Z" }, - { url = "https://files.pythonhosted.org/packages/c4/1a/0242e5b7b6cf51dbccc065029f0420107b6bf7e191fcb918f5cb71218acf/pydantic_core-2.46.2-graalpy311-graalpy242_311_native-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:1b877d597afb82b4898e35354bba55de6f7f048421ae0edadbb9886ec137b532", size = 2138468, upload-time = "2026-04-17T09:11:51.546Z" }, - { url = "https://files.pythonhosted.org/packages/f3/d2/66c146f421178641bda880b0267c0d57dd84f5fec9ecc8e46be17b480742/pydantic_core-2.46.2-graalpy312-graalpy250_312_native-macosx_10_12_x86_64.whl", hash = "sha256:e9fcabd1857492b5bf16f90258babde50f618f55d046b1309972da2396321ff9", size = 2091621, upload-time = "2026-04-17T09:12:47.501Z" }, - { url = "https://files.pythonhosted.org/packages/ee/b2/c28419aa9fc8055f4ac8e801d1d11c6357351bfa4321ed9bafab3eb98087/pydantic_core-2.46.2-graalpy312-graalpy250_312_native-macosx_11_0_arm64.whl", hash = "sha256:fb3ec2c7f54c07b30d89983ce78dc32c37dd06a972448b8716d609493802d628", size = 1937059, upload-time = "2026-04-17T09:10:53.554Z" }, - { url = "https://files.pythonhosted.org/packages/30/ce/cd0824a2db213dc17113291b7a09b9b0ccd9fbf97daa4b81548703341baf/pydantic_core-2.46.2-graalpy312-graalpy250_312_native-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:130a6c837d819ef33e8c2bf702ed2c3429237ea69807f1140943d6f4bdaf52fa", size = 1997278, upload-time = "2026-04-17T09:12:23.784Z" }, - { url = "https://files.pythonhosted.org/packages/c9/69/47283fe3c0c967d3e9e9cd6c42b70907610c8a6f8d6e8381f1bb55f8006c/pydantic_core-2.46.2-graalpy312-graalpy250_312_native-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c2e25417cec5cd9bddb151e33cb08c50160f317479ecc02b22a95ec18f8fe004", size = 2147096, upload-time = "2026-04-17T09:12:43.124Z" }, - { url = "https://files.pythonhosted.org/packages/16/d5/dec7c127fa722ff56e1ccf1e960ae1318a9f66742135e97bf9771447216f/pydantic_core-2.46.2-pp311-pypy311_pp73-macosx_10_12_x86_64.whl", hash = "sha256:c3ad79ed32004d9de91cacd4b5faaff44d56051392fe1d5526feda596f01af25", size = 2107613, upload-time = "2026-04-17T09:10:36.269Z" }, - { url = "https://files.pythonhosted.org/packages/bc/35/975c109b337260a71c93198baf663982b6b39fe3e584e279548a0969e5d4/pydantic_core-2.46.2-pp311-pypy311_pp73-macosx_11_0_arm64.whl", hash = "sha256:d157c48d28eebe5d46906de06a6a2f2c9e00b67d3e42de1f1b9c2d42b810f77c", size = 1947099, upload-time = "2026-04-17T09:12:15.304Z" }, - { url = "https://files.pythonhosted.org/packages/4e/11/52a971a0f9218631690274be533f05e5ddde5547f0823bb3e9dfd1be49f6/pydantic_core-2.46.2-pp311-pypy311_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7b42c6471288dedc979ac8400d9c9770f03967dd187db1f8d3405d4d182cc714", size = 2133866, upload-time = "2026-04-17T09:12:27.994Z" }, - { url = "https://files.pythonhosted.org/packages/fe/7a/33d94d0698602b2d1712e78c703a33952eb2ca69e02e8e4b208e7f6602b5/pydantic_core-2.46.2-pp311-pypy311_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:4f27bc4801358dc070d6697b41237fce9923d8e69a1ce1e95606ac36c1552dc1", size = 2161721, upload-time = "2026-04-17T09:11:16.111Z" }, - { url = "https://files.pythonhosted.org/packages/b0/cb/0df7ee0a148e9ce0968a80787967ddca9f6b3f8a49152a881b88da262701/pydantic_core-2.46.2-pp311-pypy311_pp73-musllinux_1_1_aarch64.whl", hash = "sha256:e094a8f85db41aa7f6a45c5dac2950afc9862e66832934231962252b5d284eed", size = 2180175, upload-time = "2026-04-17T09:11:41.577Z" }, - { url = "https://files.pythonhosted.org/packages/8e/a8/258a32878140347532be4e44c6f3b1ace3b52b9c9ca7548a65ce18adf4b4/pydantic_core-2.46.2-pp311-pypy311_pp73-musllinux_1_1_armv7l.whl", hash = "sha256:807eeda5551f6884d3b4421578be37be50ddb7a58832348e99617a6714a73748", size = 2319882, upload-time = "2026-04-17T09:10:21.872Z" }, - { url = "https://files.pythonhosted.org/packages/13/b9/5071c298a0f91314a5402b8c56e0efbcebe77085327d0b4df7dc9cb0b674/pydantic_core-2.46.2-pp311-pypy311_pp73-musllinux_1_1_x86_64.whl", hash = "sha256:fcaa1c3c846a7f6686b38fe493d1b2e8007380e293bfef6a9354563c026cbf36", size = 2348065, upload-time = "2026-04-17T09:11:08.263Z" }, - { url = "https://files.pythonhosted.org/packages/75/f3/0a7087e5f861d66ca64ce927230b397cc264c87b712156e6a93b26a459c8/pydantic_core-2.46.2-pp311-pypy311_pp73-win_amd64.whl", hash = "sha256:154dbfdfb11b8cbd8ff4d00d0b81e3d19f4cb4bedd5aa9f091060ba071474c6a", size = 2192159, upload-time = "2026-04-17T09:11:20.123Z" }, +sdist = { url = "https://files.pythonhosted.org/packages/2a/ef/f7abb56c49382a246fd2ce9c799691e3c3e7175ec74b14d99e798bcddb1a/pydantic_core-2.46.3.tar.gz", hash = "sha256:41c178f65b8c29807239d47e6050262eb6bf84eb695e41101e62e38df4a5bc2c", size = 471412, upload-time = "2026-04-20T14:40:56.672Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/22/98/b50eb9a411e87483b5c65dba4fa430a06bac4234d3403a40e5a9905ebcd0/pydantic_core-2.46.3-cp310-cp310-macosx_10_12_x86_64.whl", hash = "sha256:1da3786b8018e60349680720158cc19161cc3b4bdd815beb0a321cd5ce1ad5b1", size = 2108971, upload-time = "2026-04-20T14:43:51.945Z" }, + { url = "https://files.pythonhosted.org/packages/08/4b/f364b9d161718ff2217160a4b5d41ce38de60aed91c3689ebffa1c939d23/pydantic_core-2.46.3-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:cc0988cb29d21bf4a9d5cf2ef970b5c0e38d8d8e107a493278c05dc6c1dda69f", size = 1949588, upload-time = "2026-04-20T14:44:10.386Z" }, + { url = "https://files.pythonhosted.org/packages/8f/8b/30bd03ee83b2f5e29f5ba8e647ab3c456bf56f2ec72fdbcc0215484a0854/pydantic_core-2.46.3-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:27f9067c3bfadd04c55484b89c0d267981b2f3512850f6f66e1e74204a4e4ce3", size = 1975986, upload-time = "2026-04-20T14:43:57.106Z" }, + { url = "https://files.pythonhosted.org/packages/3c/54/13ccf954d84ec275d5d023d5786e4aa48840bc9f161f2838dc98e1153518/pydantic_core-2.46.3-cp310-cp310-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:a642ac886ecf6402d9882d10c405dcf4b902abeb2972cd5fb4a48c83cd59279a", size = 2055830, upload-time = "2026-04-20T14:44:15.499Z" }, + { url = "https://files.pythonhosted.org/packages/be/0e/65f38125e660fdbd72aa858e7dfae893645cfa0e7b13d333e174a367cd23/pydantic_core-2.46.3-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:79f561438481f28681584b89e2effb22855e2179880314bcddbf5968e935e807", size = 2222340, upload-time = "2026-04-20T14:41:51.353Z" }, + { url = "https://files.pythonhosted.org/packages/d1/88/f3ab7739efe0e7e80777dbb84c59eb98518e3f57ea433206194c2e425272/pydantic_core-2.46.3-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:57a973eae4665352a47cf1a99b4ee864620f2fe663a217d7a8da68a1f3a5bfda", size = 2280727, upload-time = "2026-04-20T14:41:30.461Z" }, + { url = "https://files.pythonhosted.org/packages/2a/6d/c228219080817bec4982f9531cadb18da6aaa770fdeb114f49c237ac2c9f/pydantic_core-2.46.3-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:83d002b97072a53ea150d63e0a3adfae5670cef5aa8a6e490240e482d3b22e57", size = 2092158, upload-time = "2026-04-20T14:44:07.305Z" }, + { url = "https://files.pythonhosted.org/packages/0f/b1/525a16711e7c6d61635fac3b0bd54600b5c5d9f60c6fc5aaab26b64a2297/pydantic_core-2.46.3-cp310-cp310-manylinux_2_31_riscv64.whl", hash = "sha256:b40ddd51e7c44b28cfaef746c9d3c506d658885e0a46f9eeef2ee815cbf8e045", size = 2116626, upload-time = "2026-04-20T14:42:34.118Z" }, + { url = "https://files.pythonhosted.org/packages/ef/7c/17d30673351439a6951bf54f564cf2443ab00ae264ec9df00e2efd710eb5/pydantic_core-2.46.3-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:ac5ec7fb9b87f04ee839af2d53bcadea57ded7d229719f56c0ed895bff987943", size = 2160691, upload-time = "2026-04-20T14:41:14.023Z" }, + { url = "https://files.pythonhosted.org/packages/86/66/af8adbcbc0886ead7f1a116606a534d75a307e71e6e08226000d51b880d2/pydantic_core-2.46.3-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:a3b11c812f61b3129c4905781a2601dfdfdea5fe1e6c1cfb696b55d14e9c054f", size = 2182543, upload-time = "2026-04-20T14:40:48.886Z" }, + { url = "https://files.pythonhosted.org/packages/b0/37/6de71e0f54c54a4190010f57deb749e1ddf75c568ada3b1320b70067f121/pydantic_core-2.46.3-cp310-cp310-musllinux_1_1_armv7l.whl", hash = "sha256:1108da631e602e5b3c38d6d04fe5bb3bfa54349e6918e3ca6cf570b2e2b2f9d4", size = 2324513, upload-time = "2026-04-20T14:42:36.121Z" }, + { url = "https://files.pythonhosted.org/packages/51/b1/9fc74ce94f603d5ef59ff258ca9c2c8fb902fb548d340a96f77f4d1c3b7f/pydantic_core-2.46.3-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:de885175515bcfa98ae618c1df7a072f13d179f81376c8007112af20567fd08a", size = 2361853, upload-time = "2026-04-20T14:43:24.886Z" }, + { url = "https://files.pythonhosted.org/packages/40/d0/4c652fc592db35f100279ee751d5a145aca1b9a7984b9684ba7c1b5b0535/pydantic_core-2.46.3-cp310-cp310-win32.whl", hash = "sha256:d11058e3201527d41bc6b545c79187c9e4bf85e15a236a6007f0e991518882b7", size = 1980465, upload-time = "2026-04-20T14:44:46.239Z" }, + { url = "https://files.pythonhosted.org/packages/27/b8/a920453c38afbe1f355e1ea0b0d94a0a3e0b0879d32d793108755fa171d5/pydantic_core-2.46.3-cp310-cp310-win_amd64.whl", hash = "sha256:3612edf65c8ea67ac13616c4d23af12faef1ae435a8a93e5934c2a0cbbdd1fd6", size = 2073884, upload-time = "2026-04-20T14:43:01.201Z" }, + { url = "https://files.pythonhosted.org/packages/22/a2/1ba90a83e85a3f94c796b184f3efde9c72f2830dcda493eea8d59ba78e6d/pydantic_core-2.46.3-cp311-cp311-macosx_10_12_x86_64.whl", hash = "sha256:ab124d49d0459b2373ecf54118a45c28a1e6d4192a533fbc915e70f556feb8e5", size = 2106740, upload-time = "2026-04-20T14:41:20.932Z" }, + { url = "https://files.pythonhosted.org/packages/b6/f6/99ae893c89a0b9d3daec9f95487aa676709aa83f67643b3f0abaf4ab628a/pydantic_core-2.46.3-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:cca67d52a5c7a16aed2b3999e719c4bcf644074eac304a5d3d62dd70ae7d4b2c", size = 1948293, upload-time = "2026-04-20T14:43:42.115Z" }, + { url = "https://files.pythonhosted.org/packages/3e/b8/2e8e636dc9e3f16c2e16bf0849e24be82c5ee82c603c65fc0326666328fc/pydantic_core-2.46.3-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5c024e08c0ba23e6fd68c771a521e9d6a792f2ebb0fa734296b36394dc30390e", size = 1973222, upload-time = "2026-04-20T14:41:57.841Z" }, + { url = "https://files.pythonhosted.org/packages/34/36/0e730beec4d83c5306f417afbd82ff237d9a21e83c5edf675f31ed84c1fe/pydantic_core-2.46.3-cp311-cp311-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:6645ce7eec4928e29a1e3b3d5c946621d105d3e79f0c9cddf07c2a9770949287", size = 2053852, upload-time = "2026-04-20T14:40:43.077Z" }, + { url = "https://files.pythonhosted.org/packages/4b/f0/3071131f47e39136a17814576e0fada9168569f7f8c0e6ac4d1ede6a4958/pydantic_core-2.46.3-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:a712c7118e6c5ea96562f7b488435172abb94a3c53c22c9efc1412264a45cbbe", size = 2221134, upload-time = "2026-04-20T14:43:03.349Z" }, + { url = "https://files.pythonhosted.org/packages/2f/a9/a2dc023eec5aa4b02a467874bad32e2446957d2adcab14e107eab502e978/pydantic_core-2.46.3-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:69a868ef3ff206343579021c40faf3b1edc64b1cc508ff243a28b0a514ccb050", size = 2279785, upload-time = "2026-04-20T14:41:19.285Z" }, + { url = "https://files.pythonhosted.org/packages/0a/44/93f489d16fb63fbd41c670441536541f6e8cfa1e5a69f40bc9c5d30d8c90/pydantic_core-2.46.3-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:cc7e8c32db809aa0f6ea1d6869ebc8518a65d5150fdfad8bcae6a49ae32a22e2", size = 2089404, upload-time = "2026-04-20T14:43:10.108Z" }, + { url = "https://files.pythonhosted.org/packages/2a/78/8692e3aa72b2d004f7a5d937f1dfdc8552ba26caf0bec75f342c40f00dec/pydantic_core-2.46.3-cp311-cp311-manylinux_2_31_riscv64.whl", hash = "sha256:3481bd1341dc85779ee506bc8e1196a277ace359d89d28588a9468c3ecbe63fa", size = 2114898, upload-time = "2026-04-20T14:44:51.475Z" }, + { url = "https://files.pythonhosted.org/packages/6a/62/e83133f2e7832532060175cebf1f13748f4c7e7e7165cdd1f611f174494b/pydantic_core-2.46.3-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:8690eba565c6d68ffd3a8655525cbdd5246510b44a637ee2c6c03a7ebfe64d3c", size = 2157856, upload-time = "2026-04-20T14:43:46.64Z" }, + { url = "https://files.pythonhosted.org/packages/6d/ec/6a500e3ad7718ee50583fae79c8651f5d37e3abce1fa9ae177ae65842c53/pydantic_core-2.46.3-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:4de88889d7e88d50d40ee5b39d5dac0bcaef9ba91f7e536ac064e6b2834ecccf", size = 2180168, upload-time = "2026-04-20T14:42:00.302Z" }, + { url = "https://files.pythonhosted.org/packages/d8/53/8267811054b1aa7fc1dc7ded93812372ef79a839f5e23558136a6afbfde1/pydantic_core-2.46.3-cp311-cp311-musllinux_1_1_armv7l.whl", hash = "sha256:e480080975c1ef7f780b8f99ed72337e7cc5efea2e518a20a692e8e7b278eb8b", size = 2322885, upload-time = "2026-04-20T14:41:05.253Z" }, + { url = "https://files.pythonhosted.org/packages/c8/c1/1c0acdb3aa0856ddc4ecc55214578f896f2de16f400cf51627eb3c26c1c4/pydantic_core-2.46.3-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:de3a5c376f8cd94da9a1b8fd3dd1c16c7a7b216ed31dc8ce9fd7a22bf13b836e", size = 2360328, upload-time = "2026-04-20T14:41:43.991Z" }, + { url = "https://files.pythonhosted.org/packages/f0/d0/ef39cd0f4a926814f360e71c1adeab48ad214d9727e4deb48eedfb5bce1a/pydantic_core-2.46.3-cp311-cp311-win32.whl", hash = "sha256:fc331a5314ffddd5385b9ee9d0d2fee0b13c27e0e02dad71b1ae5d6561f51eeb", size = 1979464, upload-time = "2026-04-20T14:43:12.215Z" }, + { url = "https://files.pythonhosted.org/packages/18/9c/f41951b0d858e343f1cf09398b2a7b3014013799744f2c4a8ad6a3eec4f2/pydantic_core-2.46.3-cp311-cp311-win_amd64.whl", hash = "sha256:b5b9c6cf08a8a5e502698f5e153056d12c34b8fb30317e0c5fd06f45162a6346", size = 2070837, upload-time = "2026-04-20T14:41:47.707Z" }, + { url = "https://files.pythonhosted.org/packages/9f/1e/264a17cd582f6ed50950d4d03dd5fefd84e570e238afe1cb3e25cf238769/pydantic_core-2.46.3-cp311-cp311-win_arm64.whl", hash = "sha256:5dfd51cf457482f04ec49491811a2b8fd5b843b64b11eecd2d7a1ee596ea78a6", size = 2053647, upload-time = "2026-04-20T14:42:27.535Z" }, + { url = "https://files.pythonhosted.org/packages/4b/cb/5b47425556ecc1f3fe18ed2a0083188aa46e1dd812b06e406475b3a5d536/pydantic_core-2.46.3-cp312-cp312-macosx_10_12_x86_64.whl", hash = "sha256:b11b59b3eee90a80a36701ddb4576d9ae31f93f05cb9e277ceaa09e6bf074a67", size = 2101946, upload-time = "2026-04-20T14:40:52.581Z" }, + { url = "https://files.pythonhosted.org/packages/a1/4f/2fb62c2267cae99b815bbf4a7b9283812c88ca3153ef29f7707200f1d4e5/pydantic_core-2.46.3-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:af8653713055ea18a3abc1537fe2ebc42f5b0bbb768d1eb79fd74eb47c0ac089", size = 1951612, upload-time = "2026-04-20T14:42:42.996Z" }, + { url = "https://files.pythonhosted.org/packages/50/6e/b7348fd30d6556d132cddd5bd79f37f96f2601fe0608afac4f5fb01ec0b3/pydantic_core-2.46.3-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:75a519dab6d63c514f3a81053e5266c549679e4aa88f6ec57f2b7b854aceb1b0", size = 1977027, upload-time = "2026-04-20T14:42:02.001Z" }, + { url = "https://files.pythonhosted.org/packages/82/11/31d60ee2b45540d3fb0b29302a393dbc01cd771c473f5b5147bcd353e593/pydantic_core-2.46.3-cp312-cp312-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:a6cd87cb1575b1ad05ba98894c5b5c96411ef678fa2f6ed2576607095b8d9789", size = 2063008, upload-time = "2026-04-20T14:44:17.952Z" }, + { url = "https://files.pythonhosted.org/packages/8a/db/3a9d1957181b59258f44a2300ab0f0be9d1e12d662a4f57bb31250455c52/pydantic_core-2.46.3-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:f80a55484b8d843c8ada81ebf70a682f3f00a3d40e378c06cf17ecb44d280d7d", size = 2233082, upload-time = "2026-04-20T14:40:57.934Z" }, + { url = "https://files.pythonhosted.org/packages/9c/e1/3277c38792aeb5cfb18c2f0c5785a221d9ff4e149abbe1184d53d5f72273/pydantic_core-2.46.3-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:3861f1731b90c50a3266316b9044f5c9b405eecb8e299b0a7120596334e4fe9c", size = 2304615, upload-time = "2026-04-20T14:42:12.584Z" }, + { url = "https://files.pythonhosted.org/packages/5e/d5/e3d9717c9eba10855325650afd2a9cba8e607321697f18953af9d562da2f/pydantic_core-2.46.3-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:fb528e295ed31570ac3dcc9bfdd6e0150bc11ce6168ac87a8082055cf1a67395", size = 2094380, upload-time = "2026-04-20T14:43:05.522Z" }, + { url = "https://files.pythonhosted.org/packages/a1/20/abac35dedcbfd66c6f0b03e4e3564511771d6c9b7ede10a362d03e110d9b/pydantic_core-2.46.3-cp312-cp312-manylinux_2_31_riscv64.whl", hash = "sha256:367508faa4973b992b271ba1494acaab36eb7e8739d1e47be5035fb1ea225396", size = 2135429, upload-time = "2026-04-20T14:41:55.549Z" }, + { url = "https://files.pythonhosted.org/packages/6c/a5/41bfd1df69afad71b5cf0535055bccc73022715ad362edbc124bc1e021d7/pydantic_core-2.46.3-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:5ad3c826fe523e4becf4fe39baa44286cff85ef137c729a2c5e269afbfd0905d", size = 2174582, upload-time = "2026-04-20T14:41:45.96Z" }, + { url = "https://files.pythonhosted.org/packages/79/65/38d86ea056b29b2b10734eb23329b7a7672ca604df4f2b6e9c02d4ee22fe/pydantic_core-2.46.3-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:ec638c5d194ef8af27db69f16c954a09797c0dc25015ad6123eb2c73a4d271ca", size = 2187533, upload-time = "2026-04-20T14:40:55.367Z" }, + { url = "https://files.pythonhosted.org/packages/b6/55/a1129141678a2026badc539ad1dee0a71d06f54c2f06a4bd68c030ac781b/pydantic_core-2.46.3-cp312-cp312-musllinux_1_1_armv7l.whl", hash = "sha256:28ed528c45446062ee66edb1d33df5d88828ae167de76e773a3c7f64bd14e976", size = 2332985, upload-time = "2026-04-20T14:44:13.05Z" }, + { url = "https://files.pythonhosted.org/packages/d7/60/cb26f4077719f709e54819f4e8e1d43f4091f94e285eb6bd21e1190a7b7c/pydantic_core-2.46.3-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:aed19d0c783886d5bd86d80ae5030006b45e28464218747dcf83dabfdd092c7b", size = 2373670, upload-time = "2026-04-20T14:41:53.421Z" }, + { url = "https://files.pythonhosted.org/packages/6b/7e/c3f21882bdf1d8d086876f81b5e296206c69c6082551d776895de7801fa0/pydantic_core-2.46.3-cp312-cp312-win32.whl", hash = "sha256:06d5d8820cbbdb4147578c1fe7ffcd5b83f34508cb9f9ab76e807be7db6ff0a4", size = 1966722, upload-time = "2026-04-20T14:44:30.588Z" }, + { url = "https://files.pythonhosted.org/packages/57/be/6b5e757b859013ebfbd7adba02f23b428f37c86dcbf78b5bb0b4ffd36e99/pydantic_core-2.46.3-cp312-cp312-win_amd64.whl", hash = "sha256:c3212fda0ee959c1dd04c60b601ec31097aaa893573a3a1abd0a47bcac2968c1", size = 2072970, upload-time = "2026-04-20T14:42:54.248Z" }, + { url = "https://files.pythonhosted.org/packages/bf/f8/a989b21cc75e9a32d24192ef700eea606521221a89faa40c919ce884f2b1/pydantic_core-2.46.3-cp312-cp312-win_arm64.whl", hash = "sha256:f1f8338dd7a7f31761f1f1a3c47503a9a3b34eea3c8b01fa6ee96408affb5e72", size = 2035963, upload-time = "2026-04-20T14:44:20.4Z" }, + { url = "https://files.pythonhosted.org/packages/9b/3c/9b5e8eb9821936d065439c3b0fb1490ffa64163bfe7e1595985a47896073/pydantic_core-2.46.3-cp313-cp313-macosx_10_12_x86_64.whl", hash = "sha256:12bc98de041458b80c86c56b24df1d23832f3e166cbaff011f25d187f5c62c37", size = 2102109, upload-time = "2026-04-20T14:41:24.219Z" }, + { url = "https://files.pythonhosted.org/packages/91/97/1c41d1f5a19f241d8069f1e249853bcce378cdb76eec8ab636d7bc426280/pydantic_core-2.46.3-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:85348b8f89d2c3508b65b16c3c33a4da22b8215138d8b996912bb1532868885f", size = 1951820, upload-time = "2026-04-20T14:42:14.236Z" }, + { url = "https://files.pythonhosted.org/packages/30/b4/d03a7ae14571bc2b6b3c7b122441154720619afe9a336fa3a95434df5e2f/pydantic_core-2.46.3-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1105677a6df914b1fb71a81b96c8cce7726857e1717d86001f29be06a25ee6f8", size = 1977785, upload-time = "2026-04-20T14:42:31.648Z" }, + { url = "https://files.pythonhosted.org/packages/ae/0c/4086f808834b59e3c8f1aa26df8f4b6d998cdcf354a143d18ef41529d1fe/pydantic_core-2.46.3-cp313-cp313-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:87082cd65669a33adeba5470769e9704c7cf026cc30afb9cc77fd865578ebaad", size = 2062761, upload-time = "2026-04-20T14:40:37.093Z" }, + { url = "https://files.pythonhosted.org/packages/fa/71/a649be5a5064c2df0db06e0a512c2281134ed2fcc981f52a657936a7527c/pydantic_core-2.46.3-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:60e5f66e12c4f5212d08522963380eaaeac5ebd795826cfd19b2dfb0c7a52b9c", size = 2232989, upload-time = "2026-04-20T14:42:59.254Z" }, + { url = "https://files.pythonhosted.org/packages/a2/84/7756e75763e810b3a710f4724441d1ecc5883b94aacb07ca71c5fb5cfb69/pydantic_core-2.46.3-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:b6cdf19bf84128d5e7c37e8a73a0c5c10d51103a650ac585d42dd6ae233f2b7f", size = 2303975, upload-time = "2026-04-20T14:41:32.287Z" }, + { url = "https://files.pythonhosted.org/packages/6c/35/68a762e0c1e31f35fa0dac733cbd9f5b118042853698de9509c8e5bf128b/pydantic_core-2.46.3-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:031bb17f4885a43773c8c763089499f242aee2ea85cf17154168775dccdecf35", size = 2095325, upload-time = "2026-04-20T14:42:47.685Z" }, + { url = "https://files.pythonhosted.org/packages/77/bf/1bf8c9a8e91836c926eae5e3e51dce009bf495a60ca56060689d3df3f340/pydantic_core-2.46.3-cp313-cp313-manylinux_2_31_riscv64.whl", hash = "sha256:bcf2a8b2982a6673693eae7348ef3d8cf3979c1d63b54fca7c397a635cc68687", size = 2133368, upload-time = "2026-04-20T14:41:22.766Z" }, + { url = "https://files.pythonhosted.org/packages/e5/50/87d818d6bab915984995157ceb2380f5aac4e563dddbed6b56f0ed057aba/pydantic_core-2.46.3-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:28e8cf2f52d72ced402a137145923a762cbb5081e48b34312f7a0c8f55928ec3", size = 2173908, upload-time = "2026-04-20T14:42:52.044Z" }, + { url = "https://files.pythonhosted.org/packages/91/88/a311fb306d0bd6185db41fa14ae888fb81d0baf648a761ae760d30819d33/pydantic_core-2.46.3-cp313-cp313-musllinux_1_1_aarch64.whl", hash = "sha256:17eaface65d9fc5abb940003020309c1bf7a211f5f608d7870297c367e6f9022", size = 2186422, upload-time = "2026-04-20T14:43:29.55Z" }, + { url = "https://files.pythonhosted.org/packages/8f/79/28fd0d81508525ab2054fef7c77a638c8b5b0afcbbaeee493cf7c3fef7e1/pydantic_core-2.46.3-cp313-cp313-musllinux_1_1_armv7l.whl", hash = "sha256:93fd339f23408a07e98950a89644f92c54d8729719a40b30c0a30bb9ebc55d23", size = 2332709, upload-time = "2026-04-20T14:42:16.134Z" }, + { url = "https://files.pythonhosted.org/packages/b3/21/795bf5fe5c0f379308b8ef19c50dedab2e7711dbc8d0c2acf08f1c7daa05/pydantic_core-2.46.3-cp313-cp313-musllinux_1_1_x86_64.whl", hash = "sha256:23cbdb3aaa74dfe0837975dbf69b469753bbde8eacace524519ffdb6b6e89eb7", size = 2372428, upload-time = "2026-04-20T14:41:10.974Z" }, + { url = "https://files.pythonhosted.org/packages/45/b3/ed14c659cbe7605e3ef063077680a64680aec81eb1a04763a05190d49b7f/pydantic_core-2.46.3-cp313-cp313-win32.whl", hash = "sha256:610eda2e3838f401105e6326ca304f5da1e15393ae25dacae5c5c63f2c275b13", size = 1965601, upload-time = "2026-04-20T14:41:42.128Z" }, + { url = "https://files.pythonhosted.org/packages/ef/bb/adb70d9a762ddd002d723fbf1bd492244d37da41e3af7b74ad212609027e/pydantic_core-2.46.3-cp313-cp313-win_amd64.whl", hash = "sha256:68cc7866ed863db34351294187f9b729964c371ba33e31c26f478471c52e1ed0", size = 2071517, upload-time = "2026-04-20T14:43:36.096Z" }, + { url = "https://files.pythonhosted.org/packages/52/eb/66faefabebfe68bd7788339c9c9127231e680b11906368c67ce112fdb47f/pydantic_core-2.46.3-cp313-cp313-win_arm64.whl", hash = "sha256:f64b5537ac62b231572879cd08ec05600308636a5d63bcbdb15063a466977bec", size = 2035802, upload-time = "2026-04-20T14:43:38.507Z" }, + { url = "https://files.pythonhosted.org/packages/7f/db/a7bcb4940183fda36022cd18ba8dd12f2dff40740ec7b58ce7457befa416/pydantic_core-2.46.3-cp314-cp314-macosx_10_12_x86_64.whl", hash = "sha256:afa3aa644f74e290cdede48a7b0bee37d1c35e71b05105f6b340d484af536d9b", size = 2097614, upload-time = "2026-04-20T14:44:38.374Z" }, + { url = "https://files.pythonhosted.org/packages/24/35/e4066358a22e3e99519db370494c7528f5a2aa1367370e80e27e20283543/pydantic_core-2.46.3-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:ced3310e51aa425f7f77da8bbbb5212616655bedbe82c70944320bc1dbe5e018", size = 1951896, upload-time = "2026-04-20T14:40:53.996Z" }, + { url = "https://files.pythonhosted.org/packages/87/92/37cf4049d1636996e4b888c05a501f40a43ff218983a551d57f9d5e14f0d/pydantic_core-2.46.3-cp314-cp314-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e29908922ce9da1a30b4da490bd1d3d82c01dcfdf864d2a74aacee674d0bfa34", size = 1979314, upload-time = "2026-04-20T14:41:49.446Z" }, + { url = "https://files.pythonhosted.org/packages/d8/36/9ff4d676dfbdfb2d591cf43f3d90ded01e15b1404fd101180ed2d62a2fd3/pydantic_core-2.46.3-cp314-cp314-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:0c9ff69140423eea8ed2d5477df3ba037f671f5e897d206d921bc9fdc39613e7", size = 2056133, upload-time = "2026-04-20T14:42:23.574Z" }, + { url = "https://files.pythonhosted.org/packages/bc/f0/405b442a4d7ba855b06eec8b2bf9c617d43b8432d099dfdc7bf999293495/pydantic_core-2.46.3-cp314-cp314-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:b675ab0a0d5b1c8fdb81195dc5bcefea3f3c240871cdd7ff9a2de8aa50772eb2", size = 2228726, upload-time = "2026-04-20T14:44:22.816Z" }, + { url = "https://files.pythonhosted.org/packages/e7/f8/65cd92dd5a0bd89ba277a98ecbfaf6fc36bbd3300973c7a4b826d6ab1391/pydantic_core-2.46.3-cp314-cp314-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:0087084960f209a9a4af50ecd1fb063d9ad3658c07bb81a7a53f452dacbfb2ba", size = 2301214, upload-time = "2026-04-20T14:44:48.792Z" }, + { url = "https://files.pythonhosted.org/packages/fd/86/ef96a4c6e79e7a2d0410826a68fbc0eccc0fd44aa733be199d5fcac3bb87/pydantic_core-2.46.3-cp314-cp314-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ed42e6cc8e1b0e2b9b96e2276bad70ae625d10d6d524aed0c93de974ae029f9f", size = 2099927, upload-time = "2026-04-20T14:41:40.196Z" }, + { url = "https://files.pythonhosted.org/packages/6d/53/269caf30e0096e0a8a8f929d1982a27b3879872cca2d917d17c2f9fdf4fe/pydantic_core-2.46.3-cp314-cp314-manylinux_2_31_riscv64.whl", hash = "sha256:f1771ce258afb3e4201e67d154edbbae712a76a6081079fe247c2f53c6322c22", size = 2128789, upload-time = "2026-04-20T14:41:15.868Z" }, + { url = "https://files.pythonhosted.org/packages/00/b0/1a6d9b6a587e118482910c244a1c5acf4d192604174132efd12bf0ac486f/pydantic_core-2.46.3-cp314-cp314-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:a7610b6a5242a6c736d8ad47fd5fff87fcfe8f833b281b1c409c3d6835d9227f", size = 2173815, upload-time = "2026-04-20T14:44:25.152Z" }, + { url = "https://files.pythonhosted.org/packages/87/56/e7e00d4041a7e62b5a40815590114db3b535bf3ca0bf4dca9f16cef25246/pydantic_core-2.46.3-cp314-cp314-musllinux_1_1_aarch64.whl", hash = "sha256:ff5e7783bcc5476e1db448bf268f11cb257b1c276d3e89f00b5727be86dd0127", size = 2181608, upload-time = "2026-04-20T14:41:28.933Z" }, + { url = "https://files.pythonhosted.org/packages/e8/22/4bd23c3d41f7c185d60808a1de83c76cf5aeabf792f6c636a55c3b1ec7f9/pydantic_core-2.46.3-cp314-cp314-musllinux_1_1_armv7l.whl", hash = "sha256:9d2e32edcc143bc01e95300671915d9ca052d4f745aa0a49c48d4803f8a85f2c", size = 2326968, upload-time = "2026-04-20T14:42:03.962Z" }, + { url = "https://files.pythonhosted.org/packages/24/ac/66cd45129e3915e5ade3b292cb3bc7fd537f58f8f8dbdaba6170f7cabb74/pydantic_core-2.46.3-cp314-cp314-musllinux_1_1_x86_64.whl", hash = "sha256:6e42d83d1c6b87fa56b521479cff237e626a292f3b31b6345c15a99121b454c1", size = 2369842, upload-time = "2026-04-20T14:41:35.52Z" }, + { url = "https://files.pythonhosted.org/packages/a2/51/dd4248abb84113615473aa20d5545b7c4cd73c8644003b5259686f93996c/pydantic_core-2.46.3-cp314-cp314-win32.whl", hash = "sha256:07bc6d2a28c3adb4f7c6ae46aa4f2d2929af127f587ed44057af50bf1ce0f505", size = 1959661, upload-time = "2026-04-20T14:41:00.042Z" }, + { url = "https://files.pythonhosted.org/packages/20/eb/59980e5f1ae54a3b86372bd9f0fa373ea2d402e8cdcd3459334430f91e91/pydantic_core-2.46.3-cp314-cp314-win_amd64.whl", hash = "sha256:8940562319bc621da30714617e6a7eaa6b98c84e8c685bcdc02d7ed5e7c7c44e", size = 2071686, upload-time = "2026-04-20T14:43:16.471Z" }, + { url = "https://files.pythonhosted.org/packages/8c/db/1cf77e5247047dfee34bc01fa9bca134854f528c8eb053e144298893d370/pydantic_core-2.46.3-cp314-cp314-win_arm64.whl", hash = "sha256:5dcbbcf4d22210ced8f837c96db941bdb078f419543472aca5d9a0bb7cddc7df", size = 2026907, upload-time = "2026-04-20T14:43:31.732Z" }, + { url = "https://files.pythonhosted.org/packages/57/c0/b3df9f6a543276eadba0a48487b082ca1f201745329d97dbfa287034a230/pydantic_core-2.46.3-cp314-cp314t-macosx_10_12_x86_64.whl", hash = "sha256:d0fe3dce1e836e418f912c1ad91c73357d03e556a4d286f441bf34fed2dbeecf", size = 2095047, upload-time = "2026-04-20T14:42:37.982Z" }, + { url = "https://files.pythonhosted.org/packages/66/57/886a938073b97556c168fd99e1a7305bb363cd30a6d2c76086bf0587b32a/pydantic_core-2.46.3-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:9ce92e58abc722dac1bf835a6798a60b294e48eb0e625ec9fd994b932ac5feee", size = 1934329, upload-time = "2026-04-20T14:43:49.655Z" }, + { url = "https://files.pythonhosted.org/packages/0b/7c/b42eaa5c34b13b07ecb51da21761297a9b8eb43044c864a035999998f328/pydantic_core-2.46.3-cp314-cp314t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a03e6467f0f5ab796a486146d1b887b2dc5e5f9b3288898c1b1c3ad974e53e4a", size = 1974847, upload-time = "2026-04-20T14:42:10.737Z" }, + { url = "https://files.pythonhosted.org/packages/e6/9b/92b42db6543e7de4f99ae977101a2967b63122d4b6cf7773812da2d7d5b5/pydantic_core-2.46.3-cp314-cp314t-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:2798b6ba041b9d70acfb9071a2ea13c8456dd1e6a5555798e41ba7b0790e329c", size = 2041742, upload-time = "2026-04-20T14:40:44.262Z" }, + { url = "https://files.pythonhosted.org/packages/0f/19/46fbe1efabb5aa2834b43b9454e70f9a83ad9c338c1291e48bdc4fecf167/pydantic_core-2.46.3-cp314-cp314t-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:9be3e221bdc6d69abf294dcf7aff6af19c31a5cdcc8f0aa3b14be29df4bd03b1", size = 2236235, upload-time = "2026-04-20T14:41:27.307Z" }, + { url = "https://files.pythonhosted.org/packages/77/da/b3f95bc009ad60ec53120f5d16c6faa8cabdbe8a20d83849a1f2b8728148/pydantic_core-2.46.3-cp314-cp314t-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:f13936129ce841f2a5ddf6f126fea3c43cd128807b5a59588c37cf10178c2e64", size = 2282633, upload-time = "2026-04-20T14:44:33.271Z" }, + { url = "https://files.pythonhosted.org/packages/cc/6e/401336117722e28f32fb8220df676769d28ebdf08f2f4469646d404c43a3/pydantic_core-2.46.3-cp314-cp314t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:28b5f2ef03416facccb1c6ef744c69793175fd27e44ef15669201601cf423acb", size = 2109679, upload-time = "2026-04-20T14:44:41.065Z" }, + { url = "https://files.pythonhosted.org/packages/fc/53/b289f9bc8756a32fe718c46f55afaeaf8d489ee18d1a1e7be1db73f42cc4/pydantic_core-2.46.3-cp314-cp314t-manylinux_2_31_riscv64.whl", hash = "sha256:830d1247d77ad23852314f069e9d7ddafeec5f684baf9d7e7065ed46a049c4e6", size = 2108342, upload-time = "2026-04-20T14:42:50.144Z" }, + { url = "https://files.pythonhosted.org/packages/10/5b/8292fc7c1f9111f1b2b7c1b0dcf1179edcd014fc3ea4517499f50b829d71/pydantic_core-2.46.3-cp314-cp314t-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:d0793c90c1a3c74966e7975eaef3ed30ebdff3260a0f815a62a22adc17e4c01c", size = 2157208, upload-time = "2026-04-20T14:42:08.133Z" }, + { url = "https://files.pythonhosted.org/packages/2b/9e/f80044e9ec07580f057a89fc131f78dda7a58751ddf52bbe05eaf31db50f/pydantic_core-2.46.3-cp314-cp314t-musllinux_1_1_aarch64.whl", hash = "sha256:d2d0aead851b66f5245ec0c4fb2612ef457f8bbafefdf65a2bf9d6bac6140f47", size = 2167237, upload-time = "2026-04-20T14:42:25.412Z" }, + { url = "https://files.pythonhosted.org/packages/f8/84/6781a1b037f3b96be9227edbd1101f6d3946746056231bf4ac48cdff1a8d/pydantic_core-2.46.3-cp314-cp314t-musllinux_1_1_armv7l.whl", hash = "sha256:2f40e4246676beb31c5ce77c38a55ca4e465c6b38d11ea1bd935420568e0b1ab", size = 2312540, upload-time = "2026-04-20T14:40:40.313Z" }, + { url = "https://files.pythonhosted.org/packages/3e/db/19c0839feeb728e7df03255581f198dfdf1c2aeb1e174a8420b63c5252e5/pydantic_core-2.46.3-cp314-cp314t-musllinux_1_1_x86_64.whl", hash = "sha256:cf489cf8986c543939aeee17a09c04d6ffb43bfef8ca16fcbcc5cfdcbed24dba", size = 2369556, upload-time = "2026-04-20T14:41:09.427Z" }, + { url = "https://files.pythonhosted.org/packages/e0/15/3228774cb7cd45f5f721ddf1b2242747f4eb834d0c491f0c02d606f09fed/pydantic_core-2.46.3-cp314-cp314t-win32.whl", hash = "sha256:ffe0883b56cfc05798bf994164d2b2ff03efe2d22022a2bb080f3b626176dd56", size = 1949756, upload-time = "2026-04-20T14:41:25.717Z" }, + { url = "https://files.pythonhosted.org/packages/b8/2a/c79cf53fd91e5a87e30d481809f52f9a60dd221e39de66455cf04deaad37/pydantic_core-2.46.3-cp314-cp314t-win_amd64.whl", hash = "sha256:706d9d0ce9cf4593d07270d8e9f53b161f90c57d315aeec4fb4fd7a8b10240d8", size = 2051305, upload-time = "2026-04-20T14:43:18.627Z" }, + { url = "https://files.pythonhosted.org/packages/0b/db/d8182a7f1d9343a032265aae186eb063fe26ca4c40f256b21e8da4498e89/pydantic_core-2.46.3-cp314-cp314t-win_arm64.whl", hash = "sha256:77706aeb41df6a76568434701e0917da10692da28cb69d5fb6919ce5fdb07374", size = 2026310, upload-time = "2026-04-20T14:41:01.778Z" }, + { url = "https://files.pythonhosted.org/packages/66/7f/03dbad45cd3aa9083fbc93c210ae8b005af67e4136a14186950a747c6874/pydantic_core-2.46.3-graalpy311-graalpy242_311_native-macosx_10_12_x86_64.whl", hash = "sha256:9715525891ed524a0a1eb6d053c74d4d4ad5017677fb00af0b7c2644a31bae46", size = 2105683, upload-time = "2026-04-20T14:42:19.779Z" }, + { url = "https://files.pythonhosted.org/packages/26/22/4dc186ac8ea6b257e9855031f51b62a9637beac4d68ac06bee02f046f836/pydantic_core-2.46.3-graalpy311-graalpy242_311_native-macosx_11_0_arm64.whl", hash = "sha256:9d2f400712a99a013aff420ef1eb9be077f8189a36c1e3ef87660b4e1088a874", size = 1940052, upload-time = "2026-04-20T14:43:59.274Z" }, + { url = "https://files.pythonhosted.org/packages/0d/ca/d376391a5aff1f2e8188960d7873543608130a870961c2b6b5236627c116/pydantic_core-2.46.3-graalpy311-graalpy242_311_native-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:bd2aab0e2e9dc2daf36bd2686c982535d5e7b1d930a1344a7bb6e82baab42a76", size = 1988172, upload-time = "2026-04-20T14:41:17.469Z" }, + { url = "https://files.pythonhosted.org/packages/0e/6b/523b9f85c23788755d6ab949329de692a2e3a584bc6beb67fef5e035aa9d/pydantic_core-2.46.3-graalpy311-graalpy242_311_native-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4e9d76736da5f362fabfeea6a69b13b7f2be405c6d6966f06b2f6bfff7e64531", size = 2128596, upload-time = "2026-04-20T14:40:41.707Z" }, + { url = "https://files.pythonhosted.org/packages/34/42/f426db557e8ab2791bc7562052299944a118655496fbff99914e564c0a94/pydantic_core-2.46.3-graalpy312-graalpy250_312_native-macosx_10_12_x86_64.whl", hash = "sha256:b12dd51f1187c2eb489af8e20f880362db98e954b54ab792fa5d92e8bcc6b803", size = 2091877, upload-time = "2026-04-20T14:43:27.091Z" }, + { url = "https://files.pythonhosted.org/packages/5c/4f/86a832a9d14df58e663bfdf4627dc00d3317c2bd583c4fb23390b0f04b8e/pydantic_core-2.46.3-graalpy312-graalpy250_312_native-macosx_11_0_arm64.whl", hash = "sha256:f00a0961b125f1a47af7bcc17f00782e12f4cd056f83416006b30111d941dfa3", size = 1932428, upload-time = "2026-04-20T14:40:45.781Z" }, + { url = "https://files.pythonhosted.org/packages/11/1a/fe857968954d93fb78e0d4b6df5c988c74c4aaa67181c60be7cfe327c0ca/pydantic_core-2.46.3-graalpy312-graalpy250_312_native-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:57697d7c056aca4bbb680200f96563e841a6386ac1129370a0102592f4dddff5", size = 1997550, upload-time = "2026-04-20T14:44:02.425Z" }, + { url = "https://files.pythonhosted.org/packages/17/eb/9d89ad2d9b0ba8cd65393d434471621b98912abb10fbe1df08e480ba57b5/pydantic_core-2.46.3-graalpy312-graalpy250_312_native-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:fd35aa21299def8db7ef4fe5c4ff862941a9a158ca7b63d61e66fe67d30416b4", size = 2137657, upload-time = "2026-04-20T14:42:45.149Z" }, + { url = "https://files.pythonhosted.org/packages/1f/da/99d40830684f81dec901cac521b5b91c095394cc1084b9433393cde1c2df/pydantic_core-2.46.3-pp311-pypy311_pp73-macosx_10_12_x86_64.whl", hash = "sha256:13afdd885f3d71280cf286b13b310ee0f7ccfefd1dbbb661514a474b726e2f25", size = 2107973, upload-time = "2026-04-20T14:42:06.175Z" }, + { url = "https://files.pythonhosted.org/packages/99/a5/87024121818d75bbb2a98ddbaf638e40e7a18b5e0f5492c9ca4b1b316107/pydantic_core-2.46.3-pp311-pypy311_pp73-macosx_11_0_arm64.whl", hash = "sha256:f91c0aff3e3ee0928edd1232c57f643a7a003e6edf1860bc3afcdc749cb513f3", size = 1947191, upload-time = "2026-04-20T14:43:14.319Z" }, + { url = "https://files.pythonhosted.org/packages/60/62/0c1acfe10945b83a6a59d19fbaa92f48825381509e5701b855c08f13db76/pydantic_core-2.46.3-pp311-pypy311_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6529d1d128321a58d30afcc97b49e98836542f68dd41b33c2e972bb9e5290536", size = 2123791, upload-time = "2026-04-20T14:43:22.766Z" }, + { url = "https://files.pythonhosted.org/packages/75/3e/3b2393b4c8f44285561dc30b00cf307a56a2eff7c483a824db3b8221ca51/pydantic_core-2.46.3-pp311-pypy311_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:975c267cff4f7e7272eacbe50f6cc03ca9a3da4c4fbd66fffd89c94c1e311aa1", size = 2153197, upload-time = "2026-04-20T14:44:27.932Z" }, + { url = "https://files.pythonhosted.org/packages/ba/75/5af02fb35505051eee727c061f2881c555ab4f8ddb2d42da715a42c9731b/pydantic_core-2.46.3-pp311-pypy311_pp73-musllinux_1_1_aarch64.whl", hash = "sha256:2b8e4f2bbdf71415c544b4b1138b8060db7b6611bc927e8064c769f64bed651c", size = 2181073, upload-time = "2026-04-20T14:43:20.729Z" }, + { url = "https://files.pythonhosted.org/packages/10/92/7e0e1bd9ca3c68305db037560ca2876f89b2647deb2f8b6319005de37505/pydantic_core-2.46.3-pp311-pypy311_pp73-musllinux_1_1_armv7l.whl", hash = "sha256:e61ea8e9fff9606d09178f577ff8ccdd7206ff73d6552bcec18e1033c4254b85", size = 2315886, upload-time = "2026-04-20T14:44:04.826Z" }, + { url = "https://files.pythonhosted.org/packages/b8/d8/101655f27eaf3e44558ead736b2795d12500598beed4683f279396fa186e/pydantic_core-2.46.3-pp311-pypy311_pp73-musllinux_1_1_x86_64.whl", hash = "sha256:b504bda01bafc69b6d3c7a0c7f039dcf60f47fab70e06fe23f57b5c75bdc82b8", size = 2360528, upload-time = "2026-04-20T14:40:47.431Z" }, + { url = "https://files.pythonhosted.org/packages/07/0f/1c34a74c8d07136f0d729ffe5e1fdab04fbdaa7684f61a92f92511a84a15/pydantic_core-2.46.3-pp311-pypy311_pp73-win_amd64.whl", hash = "sha256:b00b76f7142fc60c762ce579bd29c8fa44aaa56592dd3c54fab3928d0d4ca6ff", size = 2184144, upload-time = "2026-04-20T14:42:57Z" }, ] [[package]] From 7cb195394c5ac560b5c8acf6884537c8f721ea65 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Mon, 11 May 2026 11:58:59 +0000 Subject: [PATCH 053/462] =?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 a85f51e23..70f7d9799 100644 --- a/docs/en/docs/release-notes.md +++ b/docs/en/docs/release-notes.md @@ -20,6 +20,7 @@ hide: ### Internal +* ⬆ Bump pydantic from 2.13.2 to 2.13.3. PR [#15444](https://github.com/fastapi/fastapi/pull/15444) by [@dependabot[bot]](https://github.com/apps/dependabot). * 👷 Add pre-commit to check typos. PR [#15482](https://github.com/fastapi/fastapi/pull/15482) by [@tiangolo](https://github.com/tiangolo). * 👥 Update FastAPI GitHub topic repositories. PR [#15470](https://github.com/fastapi/fastapi/pull/15470) by [@tiangolo](https://github.com/tiangolo). * 👥 Update FastAPI People - Experts. PR [#15471](https://github.com/fastapi/fastapi/pull/15471) by [@tiangolo](https://github.com/tiangolo). From 5d5666bec590c2d9740362ab65506aae0d128bd0 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 11 May 2026 16:59:50 +0200 Subject: [PATCH 054/462] =?UTF-8?q?=E2=AC=86=20Bump=20ty=20from=200.0.21?= =?UTF-8?q?=20to=200.0.34=20(#15443)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: svlandeg Co-authored-by: github-actions[bot] --- fastapi/_compat/shared.py | 4 ++-- fastapi/_compat/v2.py | 12 +++++----- fastapi/applications.py | 10 ++++---- fastapi/cli.py | 2 +- fastapi/dependencies/utils.py | 6 ++--- fastapi/encoders.py | 8 +++---- fastapi/openapi/models.py | 4 ++-- fastapi/openapi/utils.py | 2 +- fastapi/params.py | 20 ++++++++-------- fastapi/responses.py | 4 ++-- fastapi/routing.py | 8 +++---- pyproject.toml | 5 +++- uv.lock | 44 +++++++++++++++++------------------ 13 files changed, 66 insertions(+), 63 deletions(-) diff --git a/fastapi/_compat/shared.py b/fastapi/_compat/shared.py index 9d76dabe6..bd38c5534 100644 --- a/fastapi/_compat/shared.py +++ b/fastapi/_compat/shared.py @@ -23,7 +23,7 @@ _T = TypeVar("_T") # Copy from Pydantic: pydantic/_internal/_typing_extra.py WithArgsTypes: tuple[Any, ...] = ( - typing._GenericAlias, # type: ignore[attr-defined] + typing._GenericAlias, # type: ignore[attr-defined] # ty: ignore[unresolved-attribute] types.GenericAlias, types.UnionType, ) # pyright: ignore[reportAttributeAccessIssue] @@ -48,7 +48,7 @@ def lenient_issubclass( cls: Any, class_or_tuple: type[_T] | tuple[type[_T], ...] | None ) -> TypeGuard[type[_T]]: try: - return isinstance(cls, type) and issubclass(cls, class_or_tuple) # type: ignore[arg-type] + return isinstance(cls, type) and issubclass(cls, class_or_tuple) # type: ignore[arg-type] # ty: ignore[invalid-argument-type] except TypeError: # pragma: no cover if isinstance(cls, WithArgsTypes): return False diff --git a/fastapi/_compat/v2.py b/fastapi/_compat/v2.py index 3b64fba76..7be686d86 100644 --- a/fastapi/_compat/v2.py +++ b/fastapi/_compat/v2.py @@ -23,7 +23,7 @@ from pydantic import PydanticSchemaGenerationError as PydanticSchemaGenerationEr from pydantic import PydanticUndefinedAnnotation as PydanticUndefinedAnnotation from pydantic import ValidationError as ValidationError from pydantic._internal import _typing_extra as _pydantic_typing_extra -from pydantic._internal._schema_generation_shared import ( # type: ignore[attr-defined] # ty: ignore[unused-ignore-comment] +from pydantic._internal._schema_generation_shared import ( # type: ignore[attr-defined] GetJsonSchemaHandler as GetJsonSchemaHandler, ) from pydantic.fields import FieldInfo as FieldInfo @@ -372,8 +372,8 @@ def serialize_sequence_value(*, field: ModelField, value: Any) -> Sequence[Any]: continue origin_type = get_origin(union_arg) or union_arg break - assert issubclass(origin_type, shared.sequence_types) # type: ignore[arg-type] - return shared.sequence_annotation_to_type[origin_type](value) # type: ignore[no-any-return,index] + assert issubclass(origin_type, shared.sequence_types) # type: ignore[arg-type] # ty: ignore[invalid-argument-type] + return shared.sequence_annotation_to_type[origin_type](value) # type: ignore[no-any-return,index] # ty: ignore[invalid-return-type] def get_missing_field_error(loc: tuple[int | str, ...]) -> dict[str, Any]: @@ -381,14 +381,14 @@ def get_missing_field_error(loc: tuple[int | str, ...]) -> dict[str, Any]: "Field required", [{"type": "missing", "loc": loc, "input": {}}] ).errors(include_url=False)[0] error["input"] = None - return error # type: ignore[return-value] + return error # type: ignore[return-value] # ty: ignore[invalid-return-type] def create_body_model( *, fields: Sequence[ModelField], model_name: str ) -> type[BaseModel]: field_params = {f.name: (f.field_info.annotation, f.field_info) for f in fields} - BodyModel: type[BaseModel] = create_model(model_name, **field_params) # type: ignore[call-overload] + BodyModel: type[BaseModel] = create_model(model_name, **field_params) # type: ignore[call-overload] # ty: ignore[no-matching-overload] return BodyModel @@ -451,7 +451,7 @@ def get_flat_models_from_annotation( for arg in get_args(annotation): if lenient_issubclass(arg, (BaseModel, Enum)): if arg not in known_models: - known_models.add(arg) # type: ignore[arg-type] # ty: ignore[unused-ignore-comment] + known_models.add(arg) # type: ignore[arg-type] if lenient_issubclass(arg, BaseModel): get_flat_models_from_model(arg, known_models=known_models) else: diff --git a/fastapi/applications.py b/fastapi/applications.py index 4af1146b0..faac6853f 100644 --- a/fastapi/applications.py +++ b/fastapi/applications.py @@ -1006,7 +1006,7 @@ class FastAPI(Starlette): # Starlette still has incorrect type specification for the handlers self.exception_handlers.setdefault( WebSocketRequestValidationError, - websocket_request_validation_exception_handler, # type: ignore[arg-type] # ty: ignore[unused-ignore-comment] + websocket_request_validation_exception_handler, # type: ignore[arg-type] ) # ty: ignore[no-matching-overload] self.user_middleware: list[Middleware] = ( @@ -1029,11 +1029,11 @@ class FastAPI(Starlette): exception_handlers[key] = value middleware = ( - [Middleware(ServerErrorMiddleware, handler=error_handler, debug=debug)] # ty: ignore[invalid-argument-type] + [Middleware(ServerErrorMiddleware, handler=error_handler, debug=debug)] + self.user_middleware + [ Middleware( - ExceptionMiddleware, # ty: ignore[invalid-argument-type] + ExceptionMiddleware, handlers=exception_handlers, debug=debug, ), @@ -1056,7 +1056,7 @@ class FastAPI(Starlette): # user middlewares, the same context is used. # This is currently not needed, only for closing files, but used to be # important when dependencies with yield were closed here. - Middleware(AsyncExitStackMiddleware), # ty: ignore[invalid-argument-type] + Middleware(AsyncExitStackMiddleware), ] ) @@ -4638,7 +4638,7 @@ class FastAPI(Starlette): """ def decorator(func: DecoratedCallable) -> DecoratedCallable: - self.add_middleware(BaseHTTPMiddleware, dispatch=func) # ty: ignore[invalid-argument-type] + self.add_middleware(BaseHTTPMiddleware, dispatch=func) return func return decorator diff --git a/fastapi/cli.py b/fastapi/cli.py index fda271a53..8d3301e9d 100644 --- a/fastapi/cli.py +++ b/fastapi/cli.py @@ -6,7 +6,7 @@ except ImportError: # pragma: no cover def main() -> None: - if not cli_main: # type: ignore[truthy-function] # ty: ignore[unused-ignore-comment] + if not cli_main: # type: ignore[truthy-function] message = 'To use the fastapi command, please install "fastapi[standard]":\n\n\tpip install "fastapi[standard]"\n' print(message) raise RuntimeError(message) # noqa: B904 diff --git a/fastapi/dependencies/utils.py b/fastapi/dependencies/utils.py index aceca6a1d..7c6558c69 100644 --- a/fastapi/dependencies/utils.py +++ b/fastapi/dependencies/utils.py @@ -100,14 +100,14 @@ def ensure_multipart_is_installed() -> None: except (ImportError, AssertionError): try: # __version__ is available in both multiparts, and can be mocked - from multipart import ( # type: ignore[no-redef,import-untyped] # ty: ignore[unused-ignore-comment] + from multipart import ( # type: ignore[no-redef,import-untyped] __version__, ) assert __version__ try: # parse_options_header is only available in the right multipart - from multipart.multipart import ( # type: ignore[import-untyped] # ty: ignore[unused-ignore-comment] + from multipart.multipart import ( # type: ignore[import-untyped] parse_options_header, ) @@ -622,7 +622,7 @@ async def solve_dependencies( if response is None: response = Response() del response.headers["content-length"] - response.status_code = None # type: ignore # ty: ignore[unused-ignore-comment] + response.status_code = None # type: ignore if dependency_cache is None: dependency_cache = {} for sub_dependant in dependant.dependencies: diff --git a/fastapi/encoders.py b/fastapi/encoders.py index 43f24101b..c9f882d2b 100644 --- a/fastapi/encoders.py +++ b/fastapi/encoders.py @@ -36,7 +36,7 @@ try: from pydantic.color import Color # ty: ignore[deprecated] except ImportError: # pragma: no cover - class Color: # type: ignore[no-redef] # ty: ignore[unused-ignore-comment] + class Color: # type: ignore[no-redef] pass @@ -45,7 +45,7 @@ try: from pydantic_extra_types.color import Color as PyExtraColor except ImportError: # pragma: no cover - class PyExtraColor: # type: ignore[no-redef] # ty: ignore[unused-ignore-comment] + class PyExtraColor: # type: ignore[no-redef] pass @@ -237,9 +237,9 @@ def jsonable_encoder( if isinstance(obj, encoder_type): return encoder_instance(obj) if include is not None and not isinstance(include, (set, dict)): - include = set(include) # type: ignore[assignment] # ty: ignore[unused-ignore-comment] + include = set(include) # type: ignore[assignment] # ty: ignore[invalid-assignment] if exclude is not None and not isinstance(exclude, (set, dict)): - exclude = set(exclude) # type: ignore[assignment] # ty: ignore[unused-ignore-comment] + exclude = set(exclude) # type: ignore[assignment] # ty: ignore[invalid-assignment] if isinstance(obj, BaseModel): obj_dict = obj.model_dump( mode="json", diff --git a/fastapi/openapi/models.py b/fastapi/openapi/models.py index b9fad31a7..ca26bf931 100644 --- a/fastapi/openapi/models.py +++ b/fastapi/openapi/models.py @@ -20,7 +20,7 @@ try: from pydantic import EmailStr except ImportError: # pragma: no cover - class EmailStr(str): # type: ignore # ty: ignore[unused-ignore-comment] + class EmailStr(str): # type: ignore[no-redef] @classmethod def __get_validators__(cls) -> Iterable[Callable[..., Any]]: yield cls.validate @@ -215,7 +215,7 @@ class Example(TypedDict, total=False): value: Any | None externalValue: AnyUrl | None - __pydantic_config__ = {"extra": "allow"} # type: ignore[misc] + __pydantic_config__ = {"extra": "allow"} # type: ignore[misc] # ty: ignore[invalid-typed-dict-statement] class ParameterInType(Enum): diff --git a/fastapi/openapi/utils.py b/fastapi/openapi/utils.py index 8f1852b0c..1c7a17c4c 100644 --- a/fastapi/openapi/utils.py +++ b/fastapi/openapi/utils.py @@ -603,4 +603,4 @@ def get_openapi( output["tags"] = tags if external_docs: output["externalDocs"] = external_docs - return jsonable_encoder(OpenAPI(**output), by_alias=True, exclude_none=True) # type: ignore # ty: ignore[unused-ignore-comment] + return jsonable_encoder(OpenAPI(**output), by_alias=True, exclude_none=True) # type: ignore[no-any-return] diff --git a/fastapi/params.py b/fastapi/params.py index e8f2eb290..d3f2ae175 100644 --- a/fastapi/params.py +++ b/fastapi/params.py @@ -23,7 +23,7 @@ class ParamTypes(Enum): cookie = "cookie" -class Param(FieldInfo): # type: ignore[misc] +class Param(FieldInfo): # type: ignore[misc] # ty: ignore[subclass-of-final-class] in_: ParamTypes def __init__( @@ -128,13 +128,13 @@ class Param(FieldInfo): # type: ignore[misc] use_kwargs = {k: v for k, v in kwargs.items() if v is not _Unset} - super().__init__(**use_kwargs) + super().__init__(**use_kwargs) # ty: ignore[invalid-argument-type] def __repr__(self) -> str: return f"{self.__class__.__name__}({self.default})" -class Path(Param): # type: ignore[misc] # ty: ignore[unused-ignore-comment] +class Path(Param): # type: ignore[misc] in_ = ParamTypes.path def __init__( @@ -218,7 +218,7 @@ class Path(Param): # type: ignore[misc] # ty: ignore[unused-ignore-comment] ) -class Query(Param): # type: ignore[misc] # ty: ignore[unused-ignore-comment] +class Query(Param): # type: ignore[misc] in_ = ParamTypes.query def __init__( @@ -300,7 +300,7 @@ class Query(Param): # type: ignore[misc] # ty: ignore[unused-ignore-comment] ) -class Header(Param): # type: ignore[misc] # ty: ignore[unused-ignore-comment] +class Header(Param): # type: ignore[misc] in_ = ParamTypes.header def __init__( @@ -384,7 +384,7 @@ class Header(Param): # type: ignore[misc] # ty: ignore[unused-ignore-comment] ) -class Cookie(Param): # type: ignore[misc] # ty: ignore[unused-ignore-comment] +class Cookie(Param): # type: ignore[misc] in_ = ParamTypes.cookie def __init__( @@ -466,7 +466,7 @@ class Cookie(Param): # type: ignore[misc] # ty: ignore[unused-ignore-comment] ) -class Body(FieldInfo): # type: ignore[misc] +class Body(FieldInfo): # type: ignore[misc] # ty: ignore[subclass-of-final-class] def __init__( self, default: Any = Undefined, @@ -572,13 +572,13 @@ class Body(FieldInfo): # type: ignore[misc] use_kwargs = {k: v for k, v in kwargs.items() if v is not _Unset} - super().__init__(**use_kwargs) + super().__init__(**use_kwargs) # ty: ignore[invalid-argument-type] def __repr__(self) -> str: return f"{self.__class__.__name__}({self.default})" -class Form(Body): # type: ignore[misc] # ty: ignore[unused-ignore-comment] +class Form(Body): # type: ignore[misc] def __init__( self, default: Any = Undefined, @@ -660,7 +660,7 @@ class Form(Body): # type: ignore[misc] # ty: ignore[unused-ignore-comment] ) -class File(Form): # type: ignore[misc] # ty: ignore[unused-ignore-comment] +class File(Form): # type: ignore[misc] def __init__( self, default: Any = Undefined, diff --git a/fastapi/responses.py b/fastapi/responses.py index 970f36551..29df4b7a6 100644 --- a/fastapi/responses.py +++ b/fastapi/responses.py @@ -27,13 +27,13 @@ class _OrjsonModule(Protocol): try: ujson = cast(_UjsonModule, importlib.import_module("ujson")) except ModuleNotFoundError: # pragma: nocover - ujson = None # type: ignore # ty: ignore[unused-ignore-comment] + ujson = None # type: ignore[assignment] try: orjson = cast(_OrjsonModule, importlib.import_module("orjson")) except ModuleNotFoundError: # pragma: nocover - orjson = None # type: ignore # ty: ignore[unused-ignore-comment] + orjson = None # type: ignore[assignment] @deprecated( diff --git a/fastapi/routing.py b/fastapi/routing.py index 36acb6b89..21a1385a2 100644 --- a/fastapi/routing.py +++ b/fastapi/routing.py @@ -102,9 +102,9 @@ def request_response( and returns an ASGI application. """ f: Callable[[Request], Awaitable[Response]] = ( - func # type: ignore[assignment] # ty: ignore[unused-ignore-comment] + func # type: ignore[assignment] if is_async_callable(func) - else functools.partial(run_in_threadpool, func) # type: ignore[call-arg] # ty: ignore[unused-ignore-comment] + else functools.partial(run_in_threadpool, func) # type: ignore[call-arg] ) # ty: ignore[invalid-assignment] async def app(scope: Scope, receive: Receive, send: Send) -> None: @@ -220,7 +220,7 @@ def _merge_lifespan_context( else: yield {**(maybe_nested_state or {}), **(maybe_original_state or {})} - return merged_lifespan # type: ignore[return-value] + return merged_lifespan # type: ignore[return-value] # ty: ignore[invalid-return-type] class _DefaultLifespan: @@ -912,7 +912,7 @@ class APIRoute(routing.Route): mode="serialization", ) else: - self.response_field = None # type: ignore # ty: ignore[unused-ignore-comment] + self.response_field = None # type: ignore[assignment] if self.stream_item_type: stream_item_name = "StreamItem_" + self.unique_id self.stream_item_field: ModelField | None = create_model_field( diff --git a/pyproject.toml b/pyproject.toml index 7abb9a33c..2d0e4cc8b 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -175,7 +175,7 @@ tests = [ "pyyaml >=5.3.1,<7.0.0", "sqlmodel >=0.0.31", "strawberry-graphql >=0.200.0,<1.0.0", - "ty>=0.0.9", + "ty>=0.0.25", "a2wsgi >=1.9.0,<=2.0.0", "pytest-xdist[psutil]>=2.5.0", "pytest-cov>=4.0.0", @@ -372,3 +372,6 @@ fo = "fo" havin = "havin" Ines = "Ines" ser = "ser" + +[tool.ty.terminal] +error-on-warning = true diff --git a/uv.lock b/uv.lock index 5143597f5..72407ae03 100644 --- a/uv.lock +++ b/uv.lock @@ -1295,7 +1295,7 @@ dev = [ { name = "ruff", specifier = ">=0.14.14" }, { name = "sqlmodel", specifier = ">=0.0.31" }, { name = "strawberry-graphql", specifier = ">=0.200.0,<1.0.0" }, - { name = "ty", specifier = ">=0.0.9" }, + { name = "ty", specifier = ">=0.0.25" }, { name = "typer", specifier = ">=0.21.1" }, { name = "zizmor", specifier = ">=1.23.1" }, ] @@ -1352,7 +1352,7 @@ tests = [ { name = "ruff", specifier = ">=0.14.14" }, { name = "sqlmodel", specifier = ">=0.0.31" }, { name = "strawberry-graphql", specifier = ">=0.200.0,<1.0.0" }, - { name = "ty", specifier = ">=0.0.9" }, + { name = "ty", specifier = ">=0.0.25" }, ] translations = [ { name = "gitpython", specifier = ">=3.1.46" }, @@ -5407,26 +5407,26 @@ wheels = [ [[package]] name = "ty" -version = "0.0.21" -source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/ee/20/2ba8fd9493c89c41dfe9dbb73bc70a28b28028463bc0d2897ba8be36230a/ty-0.0.21.tar.gz", hash = "sha256:a4c2ba5d67d64df8fcdefd8b280ac1149d24a73dbda82fa953a0dff9d21400ed", size = 5297967, upload-time = "2026-03-06T01:57:13.809Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/36/70/edf38bb37517531681d1c37f5df64744e5ad02673c02eb48447eae4bea08/ty-0.0.21-py3-none-linux_armv6l.whl", hash = "sha256:7bdf2f572378de78e1f388d24691c89db51b7caf07cf90f2bfcc1d6b18b70a76", size = 10299222, upload-time = "2026-03-06T01:57:16.64Z" }, - { url = "https://files.pythonhosted.org/packages/72/62/0047b0bd19afeefbc7286f20a5f78a2aa39f92b4d89853f0d7185ab89edc/ty-0.0.21-py3-none-macosx_10_12_x86_64.whl", hash = "sha256:7e9613994610431ab8625025bd2880dbcb77c5c9fabdd21134cda12d840a529d", size = 10130513, upload-time = "2026-03-06T01:57:29.93Z" }, - { url = "https://files.pythonhosted.org/packages/a2/20/0b93a9e91aaed23155780258cdfdb4726ef68b6985378ac069bc427291a0/ty-0.0.21-py3-none-macosx_11_0_arm64.whl", hash = "sha256:56d3b198b64dd0a19b2b66e257deaed2ecea568e722ae5352f3c6fb62027f89d", size = 9605425, upload-time = "2026-03-06T01:57:27.115Z" }, - { url = "https://files.pythonhosted.org/packages/ea/fd/9945e2fa2996a1287b1e1d7ce050e97e1f420233b271e770934bfa0880a0/ty-0.0.21-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d23d2c34f7a77d974bb08f0860ef700addc8a683d81a0319f71c08f87506cfd0", size = 10108298, upload-time = "2026-03-06T01:57:35.429Z" }, - { url = "https://files.pythonhosted.org/packages/52/e7/4ec52fcb15f3200826c9f048472c062549a05b0d1ef0b51f32d527b513c4/ty-0.0.21-py3-none-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:56b01fd2519637a4ca88344f61c96225f540c98ff18bca321d4eaa7bb0f7aa2f", size = 10121556, upload-time = "2026-03-06T01:57:03.242Z" }, - { url = "https://files.pythonhosted.org/packages/ee/c0/ad457be2a8abea0f25549598bd098554540ced66229488daa0d558dad3c8/ty-0.0.21-py3-none-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:e9de7e11c63c6afc40f3e9ba716374add171aee7fabc70b5146a510705c6d41b", size = 10603264, upload-time = "2026-03-06T01:56:52.134Z" }, - { url = "https://files.pythonhosted.org/packages/f8/5b/2ecc7a2175243a4bcb72f5298ae41feabbb93b764bb0dc45722f3752c2c2/ty-0.0.21-py3-none-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:62f7f5b235c4f7876db305c36997aea07b7af29b1a068f373d0e2547e25f32ff", size = 11196428, upload-time = "2026-03-06T01:57:32.94Z" }, - { url = "https://files.pythonhosted.org/packages/37/f5/aff507d6a901f328ef96a298032b0c11aaaf950a146ed7dd3b5bf2cd3acf/ty-0.0.21-py3-none-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:ee8399f7c453a425291e6688efe430cfae7ab0ac4ffd50eba9f872bf878b54f6", size = 10866355, upload-time = "2026-03-06T01:56:57.831Z" }, - { url = "https://files.pythonhosted.org/packages/be/30/822bbcb92d55b65989aa7ed06d9585f28ade9c9447369194ed4b0fb3b5b9/ty-0.0.21-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:210e7568c9f886c4d01308d751949ee714ad7ad9d7d928d2ba90d329dd880367", size = 10738177, upload-time = "2026-03-06T01:57:11.256Z" }, - { url = "https://files.pythonhosted.org/packages/57/cc/46e7991b6469e93ac2c7e533a028983e402485580150ac864c56352a3a82/ty-0.0.21-py3-none-musllinux_1_2_aarch64.whl", hash = "sha256:53508e345b11569f78b21ba8e2b4e61df38a9754947fb3cd9f2ef574367338fb", size = 10079158, upload-time = "2026-03-06T01:57:00.516Z" }, - { url = "https://files.pythonhosted.org/packages/15/c2/0bbdadfbd008240f8f1a87dc877433cb3884436097926107ccf06e618199/ty-0.0.21-py3-none-musllinux_1_2_armv7l.whl", hash = "sha256:553e43571f4a35604c36cfd07d8b61a5eb7a714e3c67f8c4ff2cf674fefbaef9", size = 10150535, upload-time = "2026-03-06T01:57:08.815Z" }, - { url = "https://files.pythonhosted.org/packages/c5/b5/2dbdb7b57b5362200ef0a39738ebd31331726328336def0143ac097ee59d/ty-0.0.21-py3-none-musllinux_1_2_i686.whl", hash = "sha256:666f6822e3b9200abfa7e95eb0ddd576460adb8d66b550c0ad2c70abc84a2048", size = 10319803, upload-time = "2026-03-06T01:57:19.106Z" }, - { url = "https://files.pythonhosted.org/packages/72/84/70e52c0b7abc7c2086f9876ef454a73b161d3125315536d8d7e911c94ca4/ty-0.0.21-py3-none-musllinux_1_2_x86_64.whl", hash = "sha256:a0854d008347ce4a5fb351af132f660a390ab2a1163444d075251d43e6f74b9b", size = 10826239, upload-time = "2026-03-06T01:57:21.727Z" }, - { url = "https://files.pythonhosted.org/packages/a1/8a/1f72480fd013bbc6cd1929002abbbcde9a0b08ead6a15154de9d7f7fa37e/ty-0.0.21-py3-none-win32.whl", hash = "sha256:bef3ab4c7b966bcc276a8ac6c11b63ba222d21355b48d471ea782c4104eee4e0", size = 9693196, upload-time = "2026-03-06T01:57:24.126Z" }, - { url = "https://files.pythonhosted.org/packages/8d/f8/1104808b875c26c640e536945753a78562d606bef4e241d9dbf3d92477f6/ty-0.0.21-py3-none-win_amd64.whl", hash = "sha256:a709d576e5bea84b745d43058d8b9cd4f27f74a0b24acb4b0cbb7d3d41e0d050", size = 10668660, upload-time = "2026-03-06T01:56:55.06Z" }, - { url = "https://files.pythonhosted.org/packages/1b/b8/25e0adc404bbf986977657b25318991f93097b49f8aea640d93c0b0db68e/ty-0.0.21-py3-none-win_arm64.whl", hash = "sha256:f72047996598ac20553fb7e21ba5741e3c82dee4e9eadf10d954551a5fe09391", size = 10104161, upload-time = "2026-03-06T01:57:06.072Z" }, +version = "0.0.34" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/c4/69/e24eefe2c35c0fdbdec9b60e162727af669bb76d64d993d982eb67b24c38/ty-0.0.34.tar.gz", hash = "sha256:a6efe66b0f13c03a65e6c72ec9abfe2792e2fd063c74fa67e2c4930e29d661be", size = 5585933, upload-time = "2026-05-01T23:06:46.388Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/83/7b/8b85003d6639ef17a97dcbb31f4511cfe78f1c81a964470db100c8c883e7/ty-0.0.34-py3-none-linux_armv6l.whl", hash = "sha256:9ecc3d14f07a95a6ceb88e07f8e62358dbd37325d3d5bd56da7217ff1fef7fb8", size = 11067094, upload-time = "2026-05-01T23:06:21.133Z" }, + { url = "https://files.pythonhosted.org/packages/d7/25/b0098f65b020b015c40567c763fc66fffbec88b2ba6f584bca1e92f05ebb/ty-0.0.34-py3-none-macosx_10_12_x86_64.whl", hash = "sha256:0dccffd8a9d02321cd2dee3249df205e26d62694e741f4eeca36b157fd8b419f", size = 10840909, upload-time = "2026-05-01T23:06:18.409Z" }, + { url = "https://files.pythonhosted.org/packages/e4/55/5e4adcf7d2a1006b844903b27cb81244a9b748d850433a46a6c21776c401/ty-0.0.34-py3-none-macosx_11_0_arm64.whl", hash = "sha256:b0ea47a2998e167ab3b21d2f4b5309a9cf33c297809f6d7e3e753252223174d0", size = 10279378, upload-time = "2026-05-01T23:06:37.962Z" }, + { url = "https://files.pythonhosted.org/packages/4d/91/f537dca0db8fe2558e8ab04d8941d687b384fcc1df5eb9023b2db75ac26c/ty-0.0.34-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8b37da00b41a118a459ae56d8947e70651073fb33ebfbceb820e4a10b22d5023", size = 10817423, upload-time = "2026-05-01T23:06:26.247Z" }, + { url = "https://files.pythonhosted.org/packages/2c/c4/55a3ad1da2815af1009bdc1b8c90dc11a364cd314e4b48c5128ba9d38859/ty-0.0.34-py3-none-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:81cbbb93c2342fe3de43e625d3a9eb149633e9f485e816ebf6395d08685355d8", size = 10851826, upload-time = "2026-05-01T23:06:24.198Z" }, + { url = "https://files.pythonhosted.org/packages/ce/8c/9c7606af22d73fb43ea4369472d9c66ece11231be73b0efe8e3c61655559/ty-0.0.34-py3-none-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:4c5b4dea1594a021289e172582df9cde7089dce14b276fc650e7b212b1772e12", size = 11356318, upload-time = "2026-05-01T23:06:51.139Z" }, + { url = "https://files.pythonhosted.org/packages/20/54/bb423f663721ab4138b216425c6b55eaefd3a068243b24d6d8fe988f4e13/ty-0.0.34-py3-none-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:030fb00aa2d2a5b5ae9d9183d574e0c82dae80566700a7490c43669d8ece40cd", size = 11902968, upload-time = "2026-05-01T23:06:35.82Z" }, + { url = "https://files.pythonhosted.org/packages/b6/22/01122b21ab6b534a2f618c6bbe5f1f7f49fd56f4b2ec8887cd6d40d08fb3/ty-0.0.34-py3-none-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:5ae9555e24e36c63a8218e037a5a63f15579eb6aa94f41017e57cd41d335cfb5", size = 11548860, upload-time = "2026-05-01T23:06:42.155Z" }, + { url = "https://files.pythonhosted.org/packages/d1/50/86008b1392ec64bed1957bbcc7aaa43b466b50dfc91bb131841c21d7c5c3/ty-0.0.34-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:99eb23df9ed129fc26d1ab00d6f0b8dfe5253b09c2ac6abdb11523fa70d67f10", size = 11457097, upload-time = "2026-05-01T23:06:53.477Z" }, + { url = "https://files.pythonhosted.org/packages/92/3e/4558b2296963ba99c58d8409c57d7db4f3061b656c3613cb21c02c1ef4c2/ty-0.0.34-py3-none-musllinux_1_2_aarch64.whl", hash = "sha256:85de45382016eceae69e104815eb2cfa200787df104002e262a86cbd43ed2c02", size = 10798192, upload-time = "2026-05-01T23:06:40.004Z" }, + { url = "https://files.pythonhosted.org/packages/76/bf/650d24402be2ef678528d60caac1d9477a40fc37e3792ecef07834fd7a4a/ty-0.0.34-py3-none-musllinux_1_2_armv7l.whl", hash = "sha256:14cb575fb8fa5131f5129d100cfe23c1575d23faf5dfc5158432749a3e38c9b5", size = 10890390, upload-time = "2026-05-01T23:06:33.076Z" }, + { url = "https://files.pythonhosted.org/packages/5c/ef/ccd2ca13906079f7935fd7e067661b24233017f57d987d51d6a121d85bb5/ty-0.0.34-py3-none-musllinux_1_2_i686.whl", hash = "sha256:c6fc0b69d8450e6910ba9db34572b959b81329a97ae273c391f70e9fb6c1aade", size = 11031564, upload-time = "2026-05-01T23:06:55.812Z" }, + { url = "https://files.pythonhosted.org/packages/ba/2d/d27b72005b6f43599e3bcabab0d7135ac0c230b7a307bb99f9eea02c1cda/ty-0.0.34-py3-none-musllinux_1_2_x86_64.whl", hash = "sha256:30dfcec2f0fde3993f4f912ed0e057dcbebc8615299f610a4c2ddb7b5a3e1e06", size = 11553430, upload-time = "2026-05-01T23:06:31.096Z" }, + { url = "https://files.pythonhosted.org/packages/a7/12/20812e1ad930b8d4af70eebf19ad23cff6e31efcfa613ef884531fcdbaa1/ty-0.0.34-py3-none-win32.whl", hash = "sha256:97b77ddf007271b812a313a8f0a14929bc5590958433e1fb83ef585676f53342", size = 10436048, upload-time = "2026-05-01T23:06:49.108Z" }, + { url = "https://files.pythonhosted.org/packages/b0/6a/afa095c5987868fbda27c0f731146ac8e3d07b357adfa83daccaee5b1a16/ty-0.0.34-py3-none-win_amd64.whl", hash = "sha256:1f543968accb952705134028d1fda8656882787dbbc667ad4d6c3ba23791d604", size = 11462526, upload-time = "2026-05-01T23:06:28.514Z" }, + { url = "https://files.pythonhosted.org/packages/63/8f/bf041a06260d77662c0605e56dacfe90b786bf824cbe1aed238d15fe5e84/ty-0.0.34-py3-none-win_arm64.whl", hash = "sha256:ea09108cbcb16b6b06d7596312b433bf49681e78d30e4dc7fb3c1b248a95e09a", size = 10846945, upload-time = "2026-05-01T23:06:44.428Z" }, ] [[package]] From e89a37e50d27f124b77e947b7965b6df75052a35 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Mon, 11 May 2026 15:00:29 +0000 Subject: [PATCH 055/462] =?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 70f7d9799..27719ef2e 100644 --- a/docs/en/docs/release-notes.md +++ b/docs/en/docs/release-notes.md @@ -20,6 +20,7 @@ hide: ### Internal +* ⬆ Bump ty from 0.0.21 to 0.0.34. PR [#15443](https://github.com/fastapi/fastapi/pull/15443) by [@dependabot[bot]](https://github.com/apps/dependabot). * ⬆ Bump pydantic from 2.13.2 to 2.13.3. PR [#15444](https://github.com/fastapi/fastapi/pull/15444) by [@dependabot[bot]](https://github.com/apps/dependabot). * 👷 Add pre-commit to check typos. PR [#15482](https://github.com/fastapi/fastapi/pull/15482) by [@tiangolo](https://github.com/tiangolo). * 👥 Update FastAPI GitHub topic repositories. PR [#15470](https://github.com/fastapi/fastapi/pull/15470) by [@tiangolo](https://github.com/tiangolo). From 2c26191e305da47362510506d6e5f7b6cef3085f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebasti=C3=A1n=20Ram=C3=ADrez?= Date: Fri, 15 May 2026 09:09:35 +0200 Subject: [PATCH 056/462] =?UTF-8?q?=F0=9F=94=A7=20Add=20sponsor:=20TalorDa?= =?UTF-8?q?ta=20(#15531)?= 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/docs/img/sponsors/talordata.png | Bin 0 -> 1755 bytes 3 files changed, 4 insertions(+) create mode 100644 docs/en/docs/img/sponsors/talordata.png diff --git a/README.md b/README.md index 97f794475..eb0368762 100644 --- a/README.md +++ b/README.md @@ -70,6 +70,7 @@ The key features are: + diff --git a/docs/en/data/sponsors.yml b/docs/en/data/sponsors.yml index ea9eec0de..e1c9ab34b 100644 --- a/docs/en/data/sponsors.yml +++ b/docs/en/data/sponsors.yml @@ -52,6 +52,9 @@ silver: - url: https://dribia.com/en/ title: Dribia - Data Science within your reach img: https://fastapi.tiangolo.com/img/sponsors/dribia.png + - url: https://talordata.com/?campaignid=oh5dVZ3Zc3YGiAI2&utm_source=fastapi&utm_term=fastapi + title: TalorData SERP API - Multi-Engine Search Results Data + img: https://fastapi.tiangolo.com/img/sponsors/talordata.png bronze: - url: https://www.exoflare.com/open-source/?utm_source=FastAPI&utm_campaign=open_source title: Biosecurity risk assessments made easy. diff --git a/docs/en/docs/img/sponsors/talordata.png b/docs/en/docs/img/sponsors/talordata.png new file mode 100644 index 0000000000000000000000000000000000000000..541bfcab840c103b405548c09c0ba71b51e22047 GIT binary patch literal 1755 zcmX|CcT`h(7XG~?gqnbZg(?neSfq%cR1pVZ0SOTU8+wQiMVe$}1e7GanLz`t41$zU zMg~|>iX`-)z&vL`iU=bm1{NfA!J$P7v(yQDcK45a@44kWx18^so8nG#!YODd003|< z&JJX$U6D$V99F9N#Vs8GV2fQGzVeJ8SsbhWdw}D9WMbQ(a=)fQ`-#-6p;vgd&O8qj zZ{NzWLqw#TL={`g}ewtFs<&!wXHK`nsz6jLBR7Xe?eBLl)+%+^lV&~OxI80Tg` zwmr3e0uF4x$-HqaeRB#$D^^5exNq)cDDc1C!^vpnHKn#}RB@-pY0Mjh)Qga$BuT5y zFNfPabC~gAVmHe@i5mLs{=xc@iZ=UgVP9Fb^D!BEPf5w>ZAc9P#u!VztAZ%B8WIk% zAI(=S?Gjo)pIT!v@buoHIF}ZnM9YFB{F$z(>}1Z`TY#m1gY1OYQA??b3~{pFteL%6 zm~uq~sx^r*Y~@Z3VSSUM#*B&)T#;YPPuRIaK&AEYnJTSJ+^`GERG4(bKNKJCZZ zY+sVmK!Kl*wxXrvJ#&Ec^l{pAX|px>IQItm^=S*JD&QnQdmD+$T(p36yo*rZalRt% zyPVnI6t+`cRW-$5gH7v7_9bECKd41nKJ0ZC#spq8n*Mo3OS%`<1csDod%*qwR|Tn_ zRZ|S!i#a*qA#Jr62ZYZu|0|R-Nr{HqW7vOlSSi8w{NP_t+A$})p6qyx*M=6xy--~6 zuduB|ojcn+Ln>sMm;Wd$TbL{JVYBCUpf4GmRXrTiyUzb+>L_q}Rgz|FT=Sk;Z%tM- zZ?uE>@>}8Anf?Quax2Xx|z}xN5u;vVE2HRd5|tdS4WNp zg_PZz(bnLdX%;{cQ3C-J=LC~BO0xWR?sO;Y)RitM-}xuhkaxdNSEP8z7@z)u7d*yB zMOx*ToWiE%=Y zh70i`JQNW>8wv5+9`rZ*yxwgb=W42UbaXhL-}vQYXJ=99mp=?Y+iw>YBt*$KdNy@)8&O5iiGPYX630GeY!pTcK-Vvub_ z1vo6}%J){l0$cDy@ca#PLbaH3{#1$#O|Qw=BG%Rr{>k|sHPwy-X02A-;RN3l84(`1 z>fCQ9ch6529*qcF=A>=|3f@~>ex&-@gEvag7a-}C(=Z~QX4z7;E=7`v7Iv~|i5ZXX z-ak?jG~MZ=W0=mij#W2;Qy&k8F;Q*T^lxVO65s9Eq4{6X<_Gm+R<9Q&%~HVJ^(jBG zGuMIQ43sk{f;hvpp}1lVr{o6|iWl`7@WL1}|90eL-N)I{U=U-9hHb7zyAG4sn4XD{ zHJjY5hJf3;Xjl_!IGfoZ$M;;C7I+1Mm~$qw49!=HqPy@j-3A5km;^uD)vx1`gZuoj zzwdw47y0kb!$8v^Qkz#QX<*GBgmJn{5YK?uRwo&D1r#j*<`WGZy+VgHU#SBq7=G*% z>xV0r6&A?3tzI1iDWf%kzlQi1Wg?pH)7j4+fP^Zvu+E}hjL5XnRKKDejOx>JIGJOY vvU|p2AYpKHf8zYHwCrz}Or<~Jve6F4yr+LnTdpQw`m}(HBgvu4p7#BpZ6z#n literal 0 HcmV?d00001 From b70238d9e30eed1ebd8d6901fb96576acb2f0802 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Fri, 15 May 2026 07:10:03 +0000 Subject: [PATCH 057/462] =?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 27719ef2e..421b4cc7a 100644 --- a/docs/en/docs/release-notes.md +++ b/docs/en/docs/release-notes.md @@ -20,6 +20,7 @@ hide: ### Internal +* 🔧 Add sponsor: TalorData. PR [#15531](https://github.com/fastapi/fastapi/pull/15531) by [@tiangolo](https://github.com/tiangolo). * ⬆ Bump ty from 0.0.21 to 0.0.34. PR [#15443](https://github.com/fastapi/fastapi/pull/15443) by [@dependabot[bot]](https://github.com/apps/dependabot). * ⬆ Bump pydantic from 2.13.2 to 2.13.3. PR [#15444](https://github.com/fastapi/fastapi/pull/15444) by [@dependabot[bot]](https://github.com/apps/dependabot). * 👷 Add pre-commit to check typos. PR [#15482](https://github.com/fastapi/fastapi/pull/15482) by [@tiangolo](https://github.com/tiangolo). From b71da659cf19e4d8f0af8cc7cfc633c79288c3e3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebasti=C3=A1n=20Ram=C3=ADrez?= Date: Fri, 15 May 2026 09:42:33 +0200 Subject: [PATCH 058/462] =?UTF-8?q?=F0=9F=94=A7=20Update=20sponsors=20badg?= =?UTF-8?q?e=20(#15532)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docs/en/data/sponsors_badge.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/en/data/sponsors_badge.yml b/docs/en/data/sponsors_badge.yml index d648be5fc..d35a4b19f 100644 --- a/docs/en/data/sponsors_badge.yml +++ b/docs/en/data/sponsors_badge.yml @@ -48,3 +48,4 @@ logins: - subtotal - requestly - greptileai + - talorelowen From b31ffc1efdc9b90462bd44aacc097b330bf0f947 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Fri, 15 May 2026 07:43:05 +0000 Subject: [PATCH 059/462] =?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 421b4cc7a..183d37d89 100644 --- a/docs/en/docs/release-notes.md +++ b/docs/en/docs/release-notes.md @@ -20,6 +20,7 @@ hide: ### Internal +* 🔧 Update sponsors badge. PR [#15532](https://github.com/fastapi/fastapi/pull/15532) by [@tiangolo](https://github.com/tiangolo). * 🔧 Add sponsor: TalorData. PR [#15531](https://github.com/fastapi/fastapi/pull/15531) by [@tiangolo](https://github.com/tiangolo). * ⬆ Bump ty from 0.0.21 to 0.0.34. PR [#15443](https://github.com/fastapi/fastapi/pull/15443) by [@dependabot[bot]](https://github.com/apps/dependabot). * ⬆ Bump pydantic from 2.13.2 to 2.13.3. PR [#15444](https://github.com/fastapi/fastapi/pull/15444) by [@dependabot[bot]](https://github.com/apps/dependabot). From b6abc93bffd0ed5d14fa245d8110bb587d026741 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebasti=C3=A1n=20Ram=C3=ADrez?= Date: Fri, 15 May 2026 12:15:37 +0200 Subject: [PATCH 060/462] =?UTF-8?q?=F0=9F=94=A7=20Remove=20Ruff=20ignored?= =?UTF-8?q?=20rule=20for=20tabs=20(#15533)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- pyproject.toml | 1 - 1 file changed, 1 deletion(-) diff --git a/pyproject.toml b/pyproject.toml index 2d0e4cc8b..8b066c125 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -278,7 +278,6 @@ ignore = [ "E501", # line too long, handled by black "B008", # do not perform function calls in argument defaults "C901", # too complex - "W191", # indentation contains tabs ] [tool.ruff.lint.per-file-ignores] From 6f2dbb96ac03ca17e1c81fee5cdbcd7114260641 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Fri, 15 May 2026 10:16:08 +0000 Subject: [PATCH 061/462] =?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 183d37d89..d851aaa89 100644 --- a/docs/en/docs/release-notes.md +++ b/docs/en/docs/release-notes.md @@ -20,6 +20,7 @@ hide: ### Internal +* 🔧 Remove Ruff ignored rule for tabs. PR [#15533](https://github.com/fastapi/fastapi/pull/15533) by [@tiangolo](https://github.com/tiangolo). * 🔧 Update sponsors badge. PR [#15532](https://github.com/fastapi/fastapi/pull/15532) by [@tiangolo](https://github.com/tiangolo). * 🔧 Add sponsor: TalorData. PR [#15531](https://github.com/fastapi/fastapi/pull/15531) by [@tiangolo](https://github.com/tiangolo). * ⬆ Bump ty from 0.0.21 to 0.0.34. PR [#15443](https://github.com/fastapi/fastapi/pull/15443) by [@dependabot[bot]](https://github.com/apps/dependabot). From a0f42dd7d533f4fb0cdd7074efa87e1cf4f9baad Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 15 May 2026 15:02:56 +0200 Subject: [PATCH 062/462] =?UTF-8?q?=E2=AC=86=20Bump=20actions/labeler=20fr?= =?UTF-8?q?om=206.0.1=20to=206.1.0=20(#15507)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/labeler.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/labeler.yml b/.github/workflows/labeler.yml index 58c689237..2072a3f0b 100644 --- a/.github/workflows/labeler.yml +++ b/.github/workflows/labeler.yml @@ -18,7 +18,7 @@ jobs: pull-requests: write runs-on: ubuntu-latest steps: - - uses: actions/labeler@634933edcd8ababfe52f92936142cc22ac488b1b # v6.0.1 + - uses: actions/labeler@f27b608878404679385c85cfa523b85ccb86e213 # v6.1.0 if: ${{ github.event.action != 'labeled' && github.event.action != 'unlabeled' }} - run: echo "Done adding labels" # Run this after labeler applied labels From 40e383e0b2bb0a97f3aeaaedbef6000676208952 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Fri, 15 May 2026 13:03:21 +0000 Subject: [PATCH 063/462] =?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 d851aaa89..364090a2c 100644 --- a/docs/en/docs/release-notes.md +++ b/docs/en/docs/release-notes.md @@ -20,6 +20,7 @@ hide: ### Internal +* ⬆ Bump actions/labeler from 6.0.1 to 6.1.0. PR [#15507](https://github.com/fastapi/fastapi/pull/15507) by [@dependabot[bot]](https://github.com/apps/dependabot). * 🔧 Remove Ruff ignored rule for tabs. PR [#15533](https://github.com/fastapi/fastapi/pull/15533) by [@tiangolo](https://github.com/tiangolo). * 🔧 Update sponsors badge. PR [#15532](https://github.com/fastapi/fastapi/pull/15532) by [@tiangolo](https://github.com/tiangolo). * 🔧 Add sponsor: TalorData. PR [#15531](https://github.com/fastapi/fastapi/pull/15531) by [@tiangolo](https://github.com/tiangolo). From 6939bf8bb75f200567285d3a2f321c1a72a8c8b4 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 15 May 2026 17:17:52 +0200 Subject: [PATCH 064/462] =?UTF-8?q?=E2=AC=86=20Bump=20actions/add-to-proje?= =?UTF-8?q?ct=20from=201.0.2=20to=202.0.0=20(#15490)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/add-to-project.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/add-to-project.yml b/.github/workflows/add-to-project.yml index 01a082444..318c3c2fb 100644 --- a/.github/workflows/add-to-project.yml +++ b/.github/workflows/add-to-project.yml @@ -14,7 +14,7 @@ jobs: name: Add to project runs-on: ubuntu-latest steps: - - uses: actions/add-to-project@244f685bbc3b7adfa8466e08b698b5577571133e # v1.0.2 + - uses: actions/add-to-project@5afcf98fcd03f1c2f92c3c83f58ae24323cc57fd # v2.0.0 with: project-url: https://github.com/orgs/fastapi/projects/2 github-token: ${{ secrets.PROJECTS_TOKEN }} # zizmor: ignore[secrets-outside-env] From ecace740f3eaccb1aba152cf1de79477095c56f4 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Fri, 15 May 2026 15:18:26 +0000 Subject: [PATCH 065/462] =?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 364090a2c..f4966b7ad 100644 --- a/docs/en/docs/release-notes.md +++ b/docs/en/docs/release-notes.md @@ -20,6 +20,7 @@ hide: ### Internal +* ⬆ Bump actions/add-to-project from 1.0.2 to 2.0.0. PR [#15490](https://github.com/fastapi/fastapi/pull/15490) by [@dependabot[bot]](https://github.com/apps/dependabot). * ⬆ Bump actions/labeler from 6.0.1 to 6.1.0. PR [#15507](https://github.com/fastapi/fastapi/pull/15507) by [@dependabot[bot]](https://github.com/apps/dependabot). * 🔧 Remove Ruff ignored rule for tabs. PR [#15533](https://github.com/fastapi/fastapi/pull/15533) by [@tiangolo](https://github.com/tiangolo). * 🔧 Update sponsors badge. PR [#15532](https://github.com/fastapi/fastapi/pull/15532) by [@tiangolo](https://github.com/tiangolo). From 3e2ef69479875b056b63d88f01603ea51ad125a9 Mon Sep 17 00:00:00 2001 From: Yurii Motov <109919500+YuriiMotov@users.noreply.github.com> Date: Mon, 18 May 2026 09:03:01 +0200 Subject: [PATCH 066/462] =?UTF-8?q?=F0=9F=93=9D=20Fix=20image=20URLs=20in?= =?UTF-8?q?=20`index.md`=20(#15534)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docs/en/docs/index.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/docs/en/docs/index.md b/docs/en/docs/index.md index 026961e25..149e44a04 100644 --- a/docs/en/docs/index.md +++ b/docs/en/docs/index.md @@ -86,16 +86,16 @@ The key features are:
From a35a0b8b624982d46e7fb9a1d380abd10b8c6615 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Mon, 18 May 2026 07:03:26 +0000 Subject: [PATCH 067/462] =?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 f4966b7ad..54b7ab7c7 100644 --- a/docs/en/docs/release-notes.md +++ b/docs/en/docs/release-notes.md @@ -9,6 +9,7 @@ hide: ### Docs +* 📝 Fix image URLs in `index.md`. PR [#15534](https://github.com/fastapi/fastapi/pull/15534) by [@YuriiMotov](https://github.com/YuriiMotov). * ✏️ Fix Azkaban spelling typo in `virtual-environments.md‎`. PR [#15463](https://github.com/fastapi/fastapi/pull/15463) by [@isaacbernat](https://github.com/isaacbernat). * 💄 Improve layout and styling. PR [#15462](https://github.com/fastapi/fastapi/pull/15462) by [@alejsdev](https://github.com/alejsdev). * 💄 Refactor opinions section with interactive tabs and new logos. PR [#15458](https://github.com/fastapi/fastapi/pull/15458) by [@alejsdev](https://github.com/alejsdev). From 72f127ddadd4f1789efb2d418d1b188869f5b89c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebasti=C3=A1n=20Ram=C3=ADrez?= Date: Mon, 18 May 2026 10:26:15 +0200 Subject: [PATCH 068/462] =?UTF-8?q?=F0=9F=8C=90=20Update=20translations=20?= =?UTF-8?q?for=20ru=20(update-outdated)=20(#15521)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: github-actions[bot] Co-authored-by: Yurii Motov <109919500+YuriiMotov@users.noreply.github.com> Co-authored-by: Yurii Motov --- docs/ru/docs/advanced/generate-clients.md | 1 - docs/ru/docs/index.md | 85 ++++++++++++++++------- docs/ru/docs/virtual-environments.md | 2 +- 3 files changed, 61 insertions(+), 27 deletions(-) diff --git a/docs/ru/docs/advanced/generate-clients.md b/docs/ru/docs/advanced/generate-clients.md index 75bd7c47c..dfedc5dc0 100644 --- a/docs/ru/docs/advanced/generate-clients.md +++ b/docs/ru/docs/advanced/generate-clients.md @@ -30,7 +30,6 @@ FastAPI автоматически генерирует спецификации Например, вы можете попробовать: -* [Speakeasy](https://speakeasy.com/editor?utm_source=fastapi+repo&utm_medium=github+sponsorship) * [Stainless](https://www.stainless.com/?utm_source=fastapi&utm_medium=referral) * [liblab](https://developers.liblab.com/tutorials/sdk-for-fastapi?utm_source=fastapi) diff --git a/docs/ru/docs/index.md b/docs/ru/docs/index.md index 5694b9f29..10184990b 100644 --- a/docs/ru/docs/index.md +++ b/docs/ru/docs/index.md @@ -40,7 +40,7 @@ FastAPI — это современный, быстрый (высокопрои * **Скорость**: Очень высокая производительность, на уровне **NodeJS** и **Go** (благодаря Starlette и Pydantic). [Один из самых быстрых доступных фреймворков Python](#performance). * **Быстрота разработки**: Увеличьте скорость разработки фич примерно на 200–300%. * * **Меньше ошибок**: Сократите примерно на 40% количество ошибок, вызванных человеком (разработчиком). * -* **Интуитивность**: Отличная поддержка редактора кода. Автозавершение везде. Меньше времени на отладку. +* **Интуитивность**: Отличная поддержка редактора кода. Автозавершение везде. Меньше времени на отладку. * **Простота**: Разработан так, чтобы его было легко использовать и осваивать. Меньше времени на чтение документации. * **Краткость**: Минимизируйте дублирование кода. Несколько возможностей из каждого объявления параметров. Меньше ошибок. * **Надежность**: Получите код, готовый к продакшн. С автоматической интерактивной документацией. @@ -54,18 +54,27 @@ FastAPI — это современный, быстрый (высокопрои ### Ключевой-спонсор { #keystone-sponsor } +
{% for sponsor in sponsors.keystone -%} - +{{ sponsor.title }} {% endfor -%} +
-### Золотые и серебряные спонсоры { #gold-and-silver-sponsors } +### Золотые спонсоры { #gold-sponsors } +
{% for sponsor in sponsors.gold -%} - +{{ sponsor.title }} {% endfor -%} -{%- for sponsor in sponsors.silver -%} - +
+ +### Серебряные спонсоры { #silver-sponsors } + +
+{% for sponsor in sponsors.silver -%} +{{ sponsor.title }} {% endfor %} +
@@ -73,6 +82,44 @@ FastAPI — это современный, быстрый (высокопрои ## Мнения { #opinions } + +
+
+ + + + +
+ +
+
«В последнее время я много где использую FastAPI. На самом деле я планирую использовать его для всех ML-сервисов моей команды в Microsoft. Некоторые из них интегрируются в основной продукт Windows, а некоторые — в продукты Office».
+
— Kabir Khan, Microsoft (ref)
+
+ + + +
+ + +
+ "_[...] В последнее время я много где использую **FastAPI**. [...] На самом деле я планирую использовать его для всех **ML-сервисов моей команды в Microsoft**. Некоторые из них интегрируются в основной продукт **Windows**, а некоторые — в продукты **Office**._"
Kabir Khan - Microsoft (ref)
@@ -91,37 +138,25 @@ FastAPI — это современный, быстрый (высокопрои --- -"_Я в полном восторге от **FastAPI**. Это так весело!_" - -
Brian Okken - Ведущий подкаста [Python Bytes](https://pythonbytes.fm/episodes/show/123/time-to-right-the-py-wrongs?time_in_sec=855) (ref)
- ---- - -"_Честно говоря, то, что вы создали, выглядит очень солидно и отполировано. Во многих смыслах это то, чем я хотел видеть **Hug** — очень вдохновляет видеть, как кто-то это создал._" +"_Если кто-то собирается делать продакшн-API на Python, я настоятельно рекомендую **FastAPI**. Он **прекрасно спроектирован**, **прост в использовании** и **отлично масштабируется**, стал **ключевым компонентом** нашей стратегии API-first и приводит в действие множество автоматизаций и сервисов, таких как наш Virtual TAC Engineer._" -
Timothy Crosley - Создатель [Hug](https://github.com/hugapi/hug) (ref)
+
Deon Pillsbury - Cisco (ref)
--- -"_Если вы хотите изучить один **современный фреймворк** для создания REST API, посмотрите **FastAPI** [...] Он быстрый, простой в использовании и лёгкий в изучении [...]_" - -"_Мы переключились на **FastAPI** для наших **API** [...] Думаю, вам тоже понравится [...]_" - -
Ines Montani - Matthew Honnibal - Основатели [Explosion AI](https://explosion.ai) — создатели [spaCy](https://spacy.io) (ref) - (ref)
- ---- +
-"_Если кто-то собирается делать продакшн-API на Python, я настоятельно рекомендую **FastAPI**. Он **прекрасно спроектирован**, **прост в использовании** и **отлично масштабируется**, стал **ключевым компонентом** нашей стратегии API-first и приводит в действие множество автоматизаций и сервисов, таких как наш Virtual TAC Engineer._" +## FastAPI Conf { #fastapi-conf } -
Deon Pillsbury - Cisco (ref)
+[**FastAPI Conf '26**](https://fastapiconf.com) пройдёт **28 октября 2026** в **Амстердаме, Нидерланды**. Всё о FastAPI — из первых рук. 🎤 ---- +FastAPI Conf '26 — 28 октября 2026 — Амстердам, Нидерланды ## Мини-документальный фильм о FastAPI { #fastapi-mini-documentary } В конце 2025 года вышел [мини-документальный фильм о FastAPI](https://www.youtube.com/watch?v=mpR8ngthqiE), вы можете посмотреть его онлайн: -FastAPI Mini Documentary +FastAPI Mini Documentary ## **Typer**, FastAPI для CLI { #typer-the-fastapi-of-clis } diff --git a/docs/ru/docs/virtual-environments.md b/docs/ru/docs/virtual-environments.md index 633137d09..2addc869d 100644 --- a/docs/ru/docs/virtual-environments.md +++ b/docs/ru/docs/virtual-environments.md @@ -819,7 +819,7 @@ Traceback (most recent call last):
-Но если вы деактивируете виртуальное окружение и активируете новое для `prisoner-of-askaban`, тогда при запуске `python` он будет использовать Python из виртуального окружения `prisoner-of-azkaban`. +Но если вы деактивируете виртуальное окружение и активируете новое для `prisoner-of-azkaban`, тогда при запуске `python` он будет использовать Python из виртуального окружения `prisoner-of-azkaban`.
From 9364f552e6dd907a5c50a26a9a4b003e4e43f390 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Mon, 18 May 2026 08:26:50 +0000 Subject: [PATCH 069/462] =?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 54b7ab7c7..0e621ba57 100644 --- a/docs/en/docs/release-notes.md +++ b/docs/en/docs/release-notes.md @@ -17,6 +17,7 @@ hide: ### Translations +* 🌐 Update translations for ru (update-outdated). PR [#15521](https://github.com/fastapi/fastapi/pull/15521) by [@tiangolo](https://github.com/tiangolo). * 🌐 Fix typos in Spanish LLM-prompt. PR [#15472](https://github.com/fastapi/fastapi/pull/15472) by [@crr004](https://github.com/crr004). ### Internal From eff8bc4e66dd8651059134a1d6404fce766f1aff Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebasti=C3=A1n=20Ram=C3=ADrez?= Date: Mon, 18 May 2026 10:37:41 +0200 Subject: [PATCH 070/462] =?UTF-8?q?=F0=9F=8C=90=20Update=20translations=20?= =?UTF-8?q?for=20zh=20(update-outdated)=20(#15520)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: github-actions[bot] Co-authored-by: Yurii Motov <109919500+YuriiMotov@users.noreply.github.com> --- docs/zh/docs/advanced/generate-clients.md | 1 - docs/zh/docs/index.md | 89 ++++++++++++++++------- docs/zh/docs/virtual-environments.md | 4 +- 3 files changed, 64 insertions(+), 30 deletions(-) diff --git a/docs/zh/docs/advanced/generate-clients.md b/docs/zh/docs/advanced/generate-clients.md index 5f53aa434..049241bc9 100644 --- a/docs/zh/docs/advanced/generate-clients.md +++ b/docs/zh/docs/advanced/generate-clients.md @@ -30,7 +30,6 @@ FastAPI 会自动生成 **OpenAPI 3.1** 规范,因此你使用的任何工具 例如,你可以尝试: -* [Speakeasy](https://speakeasy.com/editor?utm_source=fastapi+repo&utm_medium=github+sponsorship) * [Stainless](https://www.stainless.com/?utm_source=fastapi&utm_medium=referral) * [liblab](https://developers.liblab.com/tutorials/sdk-for-fastapi?utm_source=fastapi) diff --git a/docs/zh/docs/index.md b/docs/zh/docs/index.md index a88c25efb..c1d1c1f9b 100644 --- a/docs/zh/docs/index.md +++ b/docs/zh/docs/index.md @@ -54,18 +54,27 @@ FastAPI 是一个用于构建 API 的现代、快速(高性能)的 Web 框 ### Keystone 赞助商 { #keystone-sponsor } +
{% for sponsor in sponsors.keystone -%} - +{{ sponsor.title }} {% endfor -%} +
-### 金牌和银牌赞助商 { #gold-and-silver-sponsors } +### 金牌赞助商 { #gold-sponsors } +
{% for sponsor in sponsors.gold -%} - +{{ sponsor.title }} {% endfor -%} -{%- for sponsor in sponsors.silver -%} - +
+ +### 银牌赞助商 { #silver-sponsors } + +
+{% for sponsor in sponsors.silver -%} +{{ sponsor.title }} {% endfor %} +
@@ -73,13 +82,51 @@ FastAPI 是一个用于构建 API 的现代、快速(高性能)的 Web 框 ## 评价 { #opinions } -「_[...] 最近我大量使用 **FastAPI**。[...] 我实际上计划把它用于我团队在 **微软** 的所有 **机器学习服务**。其中一些正在集成进核心 **Windows** 产品以及一些 **Office** 产品。_」 + +
+
+ + + + +
+ +
+
“我最近大量使用 FastAPI。我实际上计划把它用于我团队在 微软的机器学习(ML)服务。其中一些正在集成进核心 Windows 产品以及一些 Office 产品。”
+
— Kabir Khan,Microsoft (ref)
+
+ + + +
+ + +
+ +「_[...] 我最近大量使用 **FastAPI**。[...] 我实际上计划把它用于我团队在 **微软的机器学习(ML)服务**。其中一些正在集成进核心 **Windows** 产品以及一些 **Office** 产品。_」
Kabir Khan - Microsoft (ref)
--- -「_我们采用 **FastAPI** 来构建可查询以获取**预测结果**的 **REST** 服务器。[用于 Ludwig]_」 +「_我们采用 **FastAPI** 库来启动一个可查询以获取**预测结果**的 **REST** 服务器。[用于 Ludwig]_」
Piero Molino,Yaroslav Dudin,Sai Sumanth Miryala - Uber (ref)
@@ -91,43 +138,31 @@ FastAPI 是一个用于构建 API 的现代、快速(高性能)的 Web 框 --- -「_我对 **FastAPI** 兴奋到飞起。它太有趣了!_」 - -
Brian Okken - [Python Bytes](https://pythonbytes.fm/episodes/show/123/time-to-right-the-py-wrongs?time_in_sec=855) 播客主持人 (ref)
- ---- - -「_老实说,你构建的东西非常稳健而且打磨得很好。从很多方面看,这就是我想让 **Hug** 成为的样子 —— 看到有人把它做出来真的很鼓舞人心。_」 +「_如果有人正在构建生产级的 Python API,我强烈推荐 **FastAPI**。它**设计优雅**、**使用简单**且**高度可扩展**,它已经成为我们 API 优先开发战略中的**关键组件**,并驱动了许多自动化和服务,比如我们的 Virtual TAC Engineer。_」 -
Timothy Crosley - [Hug](https://github.com/hugapi/hug) 作者 (ref)
+
Deon Pillsbury - Cisco (ref)
--- -「_如果你想学一个用于构建 REST API 的**现代框架**,看看 **FastAPI** [...] 它快速、易用且易学 [...]_」 - -「_我们已经把我们的 **API** 切换到 **FastAPI** [...] 我想你会喜欢它 [...]_」 - -
Ines Montani - Matthew Honnibal - [Explosion AI](https://explosion.ai) 创始人 - [spaCy](https://spacy.io) 作者 (ref) - (ref)
+
---- +## FastAPI 大会 { #fastapi-conf } -「_如果有人正在构建生产级的 Python API,我强烈推荐 **FastAPI**。它**设计优雅**、**使用简单**且**高度可扩展**,已经成为我们 API 优先开发战略中的**关键组件**,并驱动了许多自动化和服务,比如我们的 Virtual TAC Engineer。_」 +[**FastAPI Conf '26**](https://fastapiconf.com) 将于 **2026 年 10 月 28 日** 在 **荷兰阿姆斯特丹** 举行。来自源头的 FastAPI 干货。🎤 -
Deon Pillsbury - Cisco (ref)
- ---- +FastAPI Conf '26 - 2026 年 10 月 28 日 - 荷兰阿姆斯特丹 ## FastAPI 迷你纪录片 { #fastapi-mini-documentary } 在 2025 年末发布了一部 [FastAPI 迷你纪录片](https://www.youtube.com/watch?v=mpR8ngthqiE),你可以在线观看: -FastAPI Mini Documentary +FastAPI 迷你纪录片 ## **Typer**,命令行中的 FastAPI { #typer-the-fastapi-of-clis } -如果你要开发一个用于终端的 命令行应用而不是 Web API,看看 [**Typer**](https://typer.tiangolo.com/)。 +如果你要开发一个用于终端而不是 Web API 的 CLI 应用,看看 [**Typer**](https://typer.tiangolo.com/)。 **Typer** 是 FastAPI 的小同胞。它的目标是成为**命令行中的 FastAPI**。⌨️ 🚀 diff --git a/docs/zh/docs/virtual-environments.md b/docs/zh/docs/virtual-environments.md index 14ee53863..7a96170d3 100644 --- a/docs/zh/docs/virtual-environments.md +++ b/docs/zh/docs/virtual-environments.md @@ -819,7 +819,7 @@ Traceback (most recent call last):
-但是如果你停用虚拟环境并激活 `prisoner-of-askaban` 的新虚拟环境,那么当你运行 `python` 时,它会使用 `prisoner-of-askaban` 中的虚拟环境中的 Python。 +但是如果你停用虚拟环境并激活 `prisoner-of-azkaban` 的新虚拟环境,那么当你运行 `python` 时,它会使用 `prisoner-of-azkaban` 中的虚拟环境中的 Python。
@@ -861,4 +861,4 @@ I solemnly swear 🐺 如果你读过并理解了所有这些,现在**你对虚拟环境的了解比很多开发者都要多**。🤓 -在未来当你调试看起来复杂的东西时,了解这些细节很可能会有用,你会知道**它是如何在底层工作的**。😎 +在未来当你调看看起来复杂的东西时,了解这些细节很可能会有用,你会知道**它是如何在底层工作的**。😎 From c7171f86b2189bc4394118a5b4b0e88bc5990535 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Mon, 18 May 2026 08:38:07 +0000 Subject: [PATCH 071/462] =?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 0e621ba57..e2c7e5287 100644 --- a/docs/en/docs/release-notes.md +++ b/docs/en/docs/release-notes.md @@ -17,6 +17,7 @@ hide: ### Translations +* 🌐 Update translations for zh (update-outdated). PR [#15520](https://github.com/fastapi/fastapi/pull/15520) by [@tiangolo](https://github.com/tiangolo). * 🌐 Update translations for ru (update-outdated). PR [#15521](https://github.com/fastapi/fastapi/pull/15521) by [@tiangolo](https://github.com/tiangolo). * 🌐 Fix typos in Spanish LLM-prompt. PR [#15472](https://github.com/fastapi/fastapi/pull/15472) by [@crr004](https://github.com/crr004). From 6163cc79967796fb103e152ea68fe251e665a2a4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebasti=C3=A1n=20Ram=C3=ADrez?= Date: Mon, 18 May 2026 10:55:28 +0200 Subject: [PATCH 072/462] =?UTF-8?q?=F0=9F=8C=90=20Update=20translations=20?= =?UTF-8?q?for=20es=20(update-outdated)=20(#15523)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: github-actions[bot] Co-authored-by: Yurii Motov <109919500+YuriiMotov@users.noreply.github.com> --- docs/es/docs/advanced/generate-clients.md | 1 - docs/es/docs/index.md | 93 ++++++++++++++++------- docs/es/docs/virtual-environments.md | 4 +- 3 files changed, 66 insertions(+), 32 deletions(-) diff --git a/docs/es/docs/advanced/generate-clients.md b/docs/es/docs/advanced/generate-clients.md index e43cb7f05..534c5e98a 100644 --- a/docs/es/docs/advanced/generate-clients.md +++ b/docs/es/docs/advanced/generate-clients.md @@ -30,7 +30,6 @@ Su sponsorship también demuestra un fuerte compromiso con la **comunidad** de F Por ejemplo, podrías querer probar: -* [Speakeasy](https://speakeasy.com/editor?utm_source=fastapi+repo&utm_medium=github+sponsorship) * [Stainless](https://www.stainless.com/?utm_source=fastapi&utm_medium=referral) * [liblab](https://developers.liblab.com/tutorials/sdk-for-fastapi?utm_source=fastapi) diff --git a/docs/es/docs/index.md b/docs/es/docs/index.md index 6aea22142..bcae23914 100644 --- a/docs/es/docs/index.md +++ b/docs/es/docs/index.md @@ -54,18 +54,27 @@ Las funcionalidades clave son: ### Sponsor Keystone { #keystone-sponsor } +
{% for sponsor in sponsors.keystone -%} - +{{ sponsor.title }} {% endfor -%} +
-### Sponsors Oro y Plata { #gold-and-silver-sponsors } +### Sponsors Oro { #gold-sponsors } +
{% for sponsor in sponsors.gold -%} - +{{ sponsor.title }} {% endfor -%} -{%- for sponsor in sponsors.silver -%} - +
+ +### Sponsors Plata { #silver-sponsors } + +
+{% for sponsor in sponsors.silver -%} +{{ sponsor.title }} {% endfor %} +
@@ -73,7 +82,45 @@ Las funcionalidades clave son: ## Opiniones { #opinions } -"_[...] Estoy usando **FastAPI** un montón estos días. [...] De hecho, estoy planeando usarlo para todos los servicios de **ML de mi equipo en Microsoft**. Algunos de ellos se están integrando en el núcleo del producto **Windows** y algunos productos de **Office**._" + +
+
+ + + + +
+ +
+
"Estoy usando FastAPI un montón estos días. De hecho, estoy planeando usarlo para todos los servicios de ML de mi equipo en Microsoft. Algunos de ellos se están integrando en el producto principal de Windows y algunos productos de Office."
+
— Kabir Khan, Microsoft (ref)
+
+ + + +
+ + +
+ +"_[...] Estoy usando **FastAPI** un montón estos días. [...] De hecho, estoy planeando usarlo para todos los **servicios de ML de mi equipo en Microsoft**. Algunos de ellos se están integrando en el núcleo del producto **Windows** y algunos productos de **Office**._"
Kabir Khan - Microsoft (ref)
@@ -81,47 +128,35 @@ Las funcionalidades clave son: "_Adoptamos el paquete **FastAPI** para crear un servidor **REST** que pueda ser consultado para obtener **predicciones**. [para Ludwig]_" -
Piero Molino, Yaroslav Dudin, y Sai Sumanth Miryala - Uber (ref)
+
Piero Molino, Yaroslav Dudin, and Sai Sumanth Miryala - Uber (ref)
--- -"_**Netflix** se complace en anunciar el lanzamiento de código abierto de nuestro framework de orquestación de **gestión de crisis**: **Dispatch**! [construido con **FastAPI**]_" +"_**Netflix** se complace en anunciar el lanzamiento open source de nuestro framework de orquestación de **gestión de crisis**: **Dispatch**! [construido con **FastAPI**]_"
Kevin Glisson, Marc Vilanova, Forest Monsen - Netflix (ref)
--- -"_Estoy súper emocionado con **FastAPI**. ¡Es tan divertido!_" - -
Brian Okken - [Python Bytes](https://pythonbytes.fm/episodes/show/123/time-to-right-the-py-wrongs?time_in_sec=855) host del podcast (ref)
- ---- - -"_Honestamente, lo que has construido parece súper sólido y pulido. En muchos aspectos, es lo que quería que **Hug** fuera; es realmente inspirador ver a alguien construir eso._" +"_Si alguien está buscando construir una API de Python para producción, recomendaría altamente **FastAPI**. Está **hermosamente diseñado**, es **simple de usar** y **altamente escalable**, se ha convertido en un **componente clave** en nuestra estrategia de desarrollo API primero y está impulsando muchas automatizaciones y servicios como nuestro Ingeniero Virtual TAC._" -
Timothy Crosley - [Hug](https://github.com/hugapi/hug) creador (ref)
+
Deon Pillsbury - Cisco (ref)
--- -"_Si estás buscando aprender un **framework moderno** para construir APIs REST, échale un vistazo a **FastAPI** [...] Es rápido, fácil de usar y fácil de aprender [...]_" - -"_Nos hemos cambiado a **FastAPI** para nuestras **APIs** [...] Creo que te gustará [...]_" - -
Ines Montani - Matthew Honnibal - [fundadores de Explosion AI](https://explosion.ai) - [creadores de spaCy](https://spacy.io) (ref) - (ref)
+
---- +## FastAPI Conf { #fastapi-conf } -"_Si alguien está buscando construir una API de Python para producción, altamente recomendaría **FastAPI**. Está **hermosamente diseñado**, es **simple de usar** y **altamente escalable**, se ha convertido en un **componente clave** en nuestra estrategia de desarrollo API primero y está impulsando muchas automatizaciones y servicios como nuestro Ingeniero Virtual TAC._" +[**FastAPI Conf '26**](https://fastapiconf.com) se llevará a cabo el **28 de octubre de 2026** en **Ámsterdam, NL**. Todo sobre FastAPI, directo de la fuente. 🎤 -
Deon Pillsbury - Cisco (ref)
- ---- +FastAPI Conf '26 - October 28, 2026 - Amsterdam, NL ## Mini documental de FastAPI { #fastapi-mini-documentary } Hay un [mini documental de FastAPI](https://www.youtube.com/watch?v=mpR8ngthqiE) lanzado a finales de 2025, puedes verlo online: -FastAPI Mini Documentary +FastAPI Mini Documentary ## **Typer**, el FastAPI de las CLIs { #typer-the-fastapi-of-clis } @@ -245,7 +280,7 @@ Puedes leer más sobre esto en la [documentación del CLI de FastAPI](https://fa -### Revísalo { #check-it } +### Revisa { #check-it } Abre tu navegador en [http://127.0.0.1:8000/items/5?q=somequery](http://127.0.0.1:8000/items/5?q=somequery). @@ -258,7 +293,7 @@ Verás el response JSON como: Ya creaste una API que: * Recibe requests HTTP en los _paths_ `/` y `/items/{item_id}`. -* Ambos _paths_ toman _operaciones_ `GET` (también conocidas como métodos HTTP). +* Ambos _paths_ toman `GET` operaciones (también conocidas como _métodos_ HTTP). * El _path_ `/items/{item_id}` tiene un _parámetro de path_ `item_id` que debe ser un `int`. * El _path_ `/items/{item_id}` tiene un _parámetro de query_ `q` opcional que es un `str`. diff --git a/docs/es/docs/virtual-environments.md b/docs/es/docs/virtual-environments.md index 682f9e947..0d8a7fcbd 100644 --- a/docs/es/docs/virtual-environments.md +++ b/docs/es/docs/virtual-environments.md @@ -166,7 +166,7 @@ $ source .venv/Scripts/activate Cada vez que instales un **nuevo paquete** en ese entorno, **activa** el entorno de nuevo. -Esto asegura que si usas un programa de **terminal (CLI)** instalado por ese paquete, uses el de tu entorno virtual y no cualquier otro que podría estar instalado globalmente, probablemente con una versión diferente a la que necesitas. +Esto asegura que si usas un **programa de terminal (CLI)** instalado por ese paquete, uses el de tu entorno virtual y no cualquier otro que podría estar instalado globalmente, probablemente con una versión diferente a la que necesitas. /// @@ -817,7 +817,7 @@ Traceback (most recent call last):
-Pero si desactivas el entorno virtual y activas el nuevo para `prisoner-of-askaban` entonces cuando ejecutes `python` utilizará el Python del entorno virtual en `prisoner-of-azkaban`. +Pero si desactivas el entorno virtual y activas el nuevo para `prisoner-of-azkaban` entonces cuando ejecutes `python` utilizará el Python del entorno virtual en `prisoner-of-azkaban`.
From 8106d6391debfadf4a60c994fc8a1172e56c8eb3 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Mon, 18 May 2026 08:55:57 +0000 Subject: [PATCH 073/462] =?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 e2c7e5287..9869d0bbe 100644 --- a/docs/en/docs/release-notes.md +++ b/docs/en/docs/release-notes.md @@ -17,6 +17,7 @@ hide: ### Translations +* 🌐 Update translations for es (update-outdated). PR [#15523](https://github.com/fastapi/fastapi/pull/15523) by [@tiangolo](https://github.com/tiangolo). * 🌐 Update translations for zh (update-outdated). PR [#15520](https://github.com/fastapi/fastapi/pull/15520) by [@tiangolo](https://github.com/tiangolo). * 🌐 Update translations for ru (update-outdated). PR [#15521](https://github.com/fastapi/fastapi/pull/15521) by [@tiangolo](https://github.com/tiangolo). * 🌐 Fix typos in Spanish LLM-prompt. PR [#15472](https://github.com/fastapi/fastapi/pull/15472) by [@crr004](https://github.com/crr004). From 622dcdc99c9561bacce7f292bc0b38f49ec8fd57 Mon Sep 17 00:00:00 2001 From: Sofie Van Landeghem Date: Mon, 18 May 2026 11:06:23 +0200 Subject: [PATCH 074/462] =?UTF-8?q?=F0=9F=94=92=EF=B8=8F=20Only=20allow=20?= =?UTF-8?q?team=20members=20to=20modify=20dependencies=20(#15548)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .github/workflows/guard-dependencies.yml | 52 ++++++++++++++++++++++++ docs/en/docs/help-fastapi.md | 3 ++ 2 files changed, 55 insertions(+) create mode 100644 .github/workflows/guard-dependencies.yml diff --git a/.github/workflows/guard-dependencies.yml b/.github/workflows/guard-dependencies.yml new file mode 100644 index 000000000..c3f97c375 --- /dev/null +++ b/.github/workflows/guard-dependencies.yml @@ -0,0 +1,52 @@ +name: Guard Dependencies + +on: + pull_request_target: # zizmor: ignore[dangerous-triggers] -- This workflow only reads context.payload metadata, never checks out PR code + branches: [master] + paths: + - pyproject.toml + - uv.lock + +permissions: + contents: read + issues: write + pull-requests: write + +jobs: + check-author: + runs-on: ubuntu-latest + steps: + - name: Check if author is org member or allowed bot + uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0 + with: + script: | + const pr = context.payload.pull_request; + const author = pr.user.login; + const assoc = pr.author_association; + + const botAllowlist = new Set(['dependabot[bot]']); + const orgAuthorAssociations = new Set(['MEMBER', 'OWNER']); + + const allowed = + botAllowlist.has(author) || + (assoc != null && orgAuthorAssociations.has(assoc)); + + if (!allowed) { + await github.rest.issues.createComment({ + owner: context.repo.owner, + repo: context.repo.repo, + issue_number: context.payload.pull_request.number, + body: `This PR modifies dependency files (\`pyproject.toml\` or \`uv.lock\`), which is restricted to members of the **${context.repo.owner}** organization on GitHub.\n\nIf you need a dependency change, please [open a discussion](https://github.com/${context.repo.owner}/${context.repo.repo}/discussions/new) describing what you need and why.\n\nClosing this PR automatically.` + }); + + await github.rest.pulls.update({ + owner: context.repo.owner, + repo: context.repo.repo, + pull_number: context.payload.pull_request.number, + state: 'closed' + }); + + core.setFailed('Dependency changes are restricted to organization members.'); + } else { + console.log(`Author ${author} (author_association=${assoc}) is allowed to make dependency changes.`); + } diff --git a/docs/en/docs/help-fastapi.md b/docs/en/docs/help-fastapi.md index ab2ded721..ab68961ca 100644 --- a/docs/en/docs/help-fastapi.md +++ b/docs/en/docs/help-fastapi.md @@ -210,6 +210,9 @@ You can [contribute](contributing.md) to the source code with Pull Requests, for * Make sure to add tests. * Make sure to add documentation if it's relevant. +Note that PRs from non-team members are not allowed to modify `pyproject.toml` or `uv.lock`, to prevent supply chain risk. +If you would like to add a new dependency, create a new [Discussion](https://github.com/fastapi/fastapi/discussions/categories/questions) to explain why. + ## Help Maintain FastAPI { #help-maintain-fastapi } Help me maintain **FastAPI**! 🤓 From 34a82b1b874f216db5b8bacb1f5c7191055e1fa2 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Mon, 18 May 2026 09:06:54 +0000 Subject: [PATCH 075/462] =?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 9869d0bbe..6944518c3 100644 --- a/docs/en/docs/release-notes.md +++ b/docs/en/docs/release-notes.md @@ -24,6 +24,7 @@ hide: ### Internal +* 🔒️ Only allow team members to modify dependencies. PR [#15548](https://github.com/fastapi/fastapi/pull/15548) by [@svlandeg](https://github.com/svlandeg). * ⬆ Bump actions/add-to-project from 1.0.2 to 2.0.0. PR [#15490](https://github.com/fastapi/fastapi/pull/15490) by [@dependabot[bot]](https://github.com/apps/dependabot). * ⬆ Bump actions/labeler from 6.0.1 to 6.1.0. PR [#15507](https://github.com/fastapi/fastapi/pull/15507) by [@dependabot[bot]](https://github.com/apps/dependabot). * 🔧 Remove Ruff ignored rule for tabs. PR [#15533](https://github.com/fastapi/fastapi/pull/15533) by [@tiangolo](https://github.com/tiangolo). From e6edf14a27cf59590ec57ee1dd53f7cb689b79bb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebasti=C3=A1n=20Ram=C3=ADrez?= Date: Mon, 18 May 2026 11:52:29 +0200 Subject: [PATCH 076/462] =?UTF-8?q?=F0=9F=8C=90=20Update=20translations=20?= =?UTF-8?q?for=20fr=20(update-outdated)=20(#15522)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: github-actions[bot] Co-authored-by: Yurii Motov <109919500+YuriiMotov@users.noreply.github.com> --- docs/fr/docs/advanced/generate-clients.md | 1 - docs/fr/docs/index.md | 89 ++++++++++++++++------- docs/fr/docs/virtual-environments.md | 2 +- 3 files changed, 63 insertions(+), 29 deletions(-) diff --git a/docs/fr/docs/advanced/generate-clients.md b/docs/fr/docs/advanced/generate-clients.md index 58bd48181..69402aefe 100644 --- a/docs/fr/docs/advanced/generate-clients.md +++ b/docs/fr/docs/advanced/generate-clients.md @@ -30,7 +30,6 @@ Leur sponsoring démontre également un fort engagement envers la **communauté* Par exemple, vous pourriez essayer : -* [Speakeasy](https://speakeasy.com/editor?utm_source=fastapi+repo&utm_medium=github+sponsorship) * [Stainless](https://www.stainless.com/?utm_source=fastapi&utm_medium=referral) * [liblab](https://developers.liblab.com/tutorials/sdk-for-fastapi?utm_source=fastapi) diff --git a/docs/fr/docs/index.md b/docs/fr/docs/index.md index 3b297ffd3..a351071f0 100644 --- a/docs/fr/docs/index.md +++ b/docs/fr/docs/index.md @@ -54,18 +54,27 @@ Les principales fonctionnalités sont : ### Sponsor clé de voûte { #keystone-sponsor } +
{% for sponsor in sponsors.keystone -%} - +{{ sponsor.title }} {% endfor -%} +
-### Sponsors Or et Argent { #gold-and-silver-sponsors } +### Sponsors Or { #gold-sponsors } +
{% for sponsor in sponsors.gold -%} - +{{ sponsor.title }} {% endfor -%} -{%- for sponsor in sponsors.silver -%} - +
+ +### Sponsors Argent { #silver-sponsors } + +
+{% for sponsor in sponsors.silver -%} +{{ sponsor.title }} {% endfor %} +
@@ -73,55 +82,81 @@ Les principales fonctionnalités sont : ## Opinions { #opinions } -« _[...] J'utilise beaucoup **FastAPI** ces derniers temps. [...] Je prévois de l'utiliser dans mon équipe pour tous les **services de ML chez Microsoft**. Certains d'entre eux sont intégrés au cœur de **Windows** et à certains produits **Office**._ » + +
+
+ + + + +
+ +
+
« J'utilise énormément FastAPI ces derniers temps. Je prévois de l'utiliser pour tous les services de ML chez Microsoft de mon équipe. Certains d'entre eux sont intégrés au cœur de Windows et à certains produits Office. »
+
— Kabir Khan, Microsoft (ref)
+
+ + + +
+ + +
+ +« _[...] J'utilise **FastAPI** énormément ces derniers temps. [...] Je prévois de l'utiliser pour tous les **services de ML chez Microsoft** de mon équipe. Certains d'entre eux sont intégrés au cœur de **Windows** et à certains produits **Office**._ »
Kabir Khan - Microsoft (ref)
--- -« _Nous avons adopté la bibliothèque **FastAPI** pour créer un serveur **REST** qui peut être interrogé pour obtenir des **prédictions**. [pour Ludwig]_ » +« _Nous avons adopté la bibliothèque **FastAPI** pour lancer un serveur **REST** qui peut être interrogé pour obtenir des **prédictions**. [pour Ludwig]_ »
Piero Molino, Yaroslav Dudin, et Sai Sumanth Miryala - Uber (ref)
--- -« _**Netflix** est heureux d'annoncer la publication en open source de notre framework d'orchestration de **gestion de crise** : **Dispatch** ! [construit avec **FastAPI**]_ » +« _**Netflix** est heureux d’annoncer la publication en open source de notre framework d’orchestration de **gestion de crise** : **Dispatch** ! [construit avec **FastAPI**]_ »
Kevin Glisson, Marc Vilanova, Forest Monsen - Netflix (ref)
--- -« _Je suis plus qu'enthousiaste à propos de **FastAPI**. C'est tellement fun !_ » - -
Brian Okken - Animateur du podcast [Python Bytes](https://pythonbytes.fm/episodes/show/123/time-to-right-the-py-wrongs?time_in_sec=855) (ref)
- ---- - -« _Honnêtement, ce que vous avez construit a l'air super solide et soigné. À bien des égards, c'est ce que je voulais que **Hug** soit — c'est vraiment inspirant de voir quelqu'un construire ça._ » +« _Si quelqu’un cherche à construire une API Python de production, je recommande vivement **FastAPI**. Il est **magnifiquement conçu**, **simple à utiliser** et **hautement scalable** — il est devenu un **composant clé** de notre stratégie de développement API-first._ » -
Timothy Crosley - Créateur de [Hug](https://github.com/hugapi/hug) (ref)
+
Deon Pillsbury - Cisco (ref)
--- -« _Si vous cherchez à apprendre un **framework moderne** pour créer des APIs REST, regardez **FastAPI** [...] C'est rapide, facile à utiliser et facile à apprendre [...]_ » - -« _Nous sommes passés à **FastAPI** pour nos **APIs** [...] Je pense que vous l'aimerez [...]_ » - -
Ines Montani - Matthew Honnibal - Fondateurs de [Explosion AI](https://explosion.ai) - Créateurs de [spaCy](https://spacy.io) (ref) - (ref)
+
---- +## FastAPI Conf { #fastapi-conf } -« _Si quelqu'un cherche à construire une API Python de production, je recommande vivement **FastAPI**. Il est **magnifiquement conçu**, **simple à utiliser** et **hautement scalable**. Il est devenu un **composant clé** de notre stratégie de développement API-first et alimente de nombreuses automatisations et services tels que notre ingénieur TAC virtuel._ » +[**FastAPI Conf '26**](https://fastapiconf.com) aura lieu le **28 octobre 2026** à **Amsterdam, NL**. Tout sur FastAPI, à la source. 🎤 -
Deon Pillsbury - Cisco (ref)
- ---- +FastAPI Conf '26 - 28 octobre 2026 - Amsterdam, NL ## Mini documentaire FastAPI { #fastapi-mini-documentary } Un [mini documentaire FastAPI](https://www.youtube.com/watch?v=mpR8ngthqiE) est sorti fin 2025, vous pouvez le regarder en ligne : -FastAPI Mini Documentary +FastAPI Mini Documentary ## **Typer**, le FastAPI des CLIs { #typer-the-fastapi-of-clis } diff --git a/docs/fr/docs/virtual-environments.md b/docs/fr/docs/virtual-environments.md index 4793e5dac..94bc65072 100644 --- a/docs/fr/docs/virtual-environments.md +++ b/docs/fr/docs/virtual-environments.md @@ -819,7 +819,7 @@ Traceback (most recent call last):
-Mais si vous désactivez l’environnement virtuel et activez le nouveau pour `prisoner-of-askaban`, alors lorsque vous exécuterez `python`, il utilisera le Python de l’environnement virtuel de `prisoner-of-azkaban`. +Mais si vous désactivez l’environnement virtuel et activez le nouveau pour `prisoner-of-azkaban`, alors lorsque vous exécuterez `python`, il utilisera le Python de l’environnement virtuel de `prisoner-of-azkaban`.
From 4047993ba8d0d1ade4b76e8dbbcd150570f69a3d Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Mon, 18 May 2026 09:52:55 +0000 Subject: [PATCH 077/462] =?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 6944518c3..fb15bab81 100644 --- a/docs/en/docs/release-notes.md +++ b/docs/en/docs/release-notes.md @@ -17,6 +17,7 @@ hide: ### Translations +* 🌐 Update translations for fr (update-outdated). PR [#15522](https://github.com/fastapi/fastapi/pull/15522) by [@tiangolo](https://github.com/tiangolo). * 🌐 Update translations for es (update-outdated). PR [#15523](https://github.com/fastapi/fastapi/pull/15523) by [@tiangolo](https://github.com/tiangolo). * 🌐 Update translations for zh (update-outdated). PR [#15520](https://github.com/fastapi/fastapi/pull/15520) by [@tiangolo](https://github.com/tiangolo). * 🌐 Update translations for ru (update-outdated). PR [#15521](https://github.com/fastapi/fastapi/pull/15521) by [@tiangolo](https://github.com/tiangolo). From f0c3d87da2902e18097244004bc3e6fd7fd0e7be Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebasti=C3=A1n=20Ram=C3=ADrez?= Date: Mon, 18 May 2026 11:53:58 +0200 Subject: [PATCH 078/462] =?UTF-8?q?=F0=9F=8C=90=20Update=20translations=20?= =?UTF-8?q?for=20zh-hant=20(update-outdated)=20(#15524)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: github-actions[bot] Co-authored-by: Yurii Motov <109919500+YuriiMotov@users.noreply.github.com> Co-authored-by: Yurii Motov --- .../zh-hant/docs/advanced/generate-clients.md | 1 - docs/zh-hant/docs/index.md | 83 +++++++++++++------ docs/zh-hant/docs/virtual-environments.md | 2 +- 3 files changed, 60 insertions(+), 26 deletions(-) diff --git a/docs/zh-hant/docs/advanced/generate-clients.md b/docs/zh-hant/docs/advanced/generate-clients.md index c069a8034..c1aa88ef7 100644 --- a/docs/zh-hant/docs/advanced/generate-clients.md +++ b/docs/zh-hant/docs/advanced/generate-clients.md @@ -30,7 +30,6 @@ FastAPI 會自動產生 **OpenAPI 3.1** 規格,因此你使用的任何工具 例如,你可以嘗試: -* [Speakeasy](https://speakeasy.com/editor?utm_source=fastapi+repo&utm_medium=github+sponsorship) * [Stainless](https://www.stainless.com/?utm_source=fastapi&utm_medium=referral) * [liblab](https://developers.liblab.com/tutorials/sdk-for-fastapi?utm_source=fastapi) diff --git a/docs/zh-hant/docs/index.md b/docs/zh-hant/docs/index.md index d57791bf8..60122a74e 100644 --- a/docs/zh-hant/docs/index.md +++ b/docs/zh-hant/docs/index.md @@ -54,18 +54,27 @@ FastAPI 是一個現代、快速(高效能)的 Web 框架,用於以 Python ### 基石贊助商 { #keystone-sponsor } +
{% for sponsor in sponsors.keystone -%} - +{{ sponsor.title }} {% endfor -%} +
-### 金級與銀級贊助商 { #gold-and-silver-sponsors } +### 金級贊助商 { #gold-sponsors } +
{% for sponsor in sponsors.gold -%} - +{{ sponsor.title }} {% endfor -%} -{%- for sponsor in sponsors.silver -%} - +
+ +### 銀級贊助商 { #silver-sponsors } + +
+{% for sponsor in sponsors.silver -%} +{{ sponsor.title }} {% endfor %} +
@@ -73,6 +82,44 @@ FastAPI 是一個現代、快速(高效能)的 Web 框架,用於以 Python ## 評價 { #opinions } + +
+
+ + + + +
+ +
+
「近期大量使用 FastAPI。我實際上打算把它用在我在 微軟 團隊的所有 機器學習服務 上。其中一些正整合進核心的 Windows 與部分 Office 產品。」
+
— Kabir Khan,Microsoft (ref)
+
+ + + +
+ + +
+ "_[...] 近期大量使用 **FastAPI**。[...] 我實際上打算在我在**微軟**團隊的所有**機器學習**服務上使用它。其中一些正在整合到核心的 **Windows** 產品,以及一些 **Office** 產品。_"
Kabir Khan - Microsoft (ref)
@@ -91,37 +138,25 @@ FastAPI 是一個現代、快速(高效能)的 Web 框架,用於以 Python --- -"_我對 **FastAPI** 興奮得不得了。超好玩!_" - -
Brian Okken - [Python Bytes](https://pythonbytes.fm/episodes/show/123/time-to-right-the-py-wrongs?time_in_sec=855) podcast 主持人 (ref)
- ---- - -"_老實說,你們做的看起來非常穩健又精緻。很多方面都正是我希望 **Hug** 成為的樣子——看到有人把它建出來真的很鼓舞人心。_" +"_如果有人想要打造一個可用於生產環境的 Python API,我強力推薦 **FastAPI**。它**設計優雅**、**簡單易用**且**高度可擴展**,已經成為我們 API first 開發策略中的**關鍵元件**,推動了許多自動化與服務,例如我們的 Virtual TAC Engineer._" -
Timothy Crosley - [Hug](https://github.com/hugapi/hug) 創作者 (ref)
+
Deon Pillsbury - Cisco (ref)
--- -"_如果你想學一個用於構建 REST API 的**現代框架**,看看 **FastAPI** [...] 它很快、易用、也容易學習 [...]_" - -"_我們的 **API** 已經改用 **FastAPI** [...] 我想你會喜歡它 [...]_" - -
Ines Montani - Matthew Honnibal - [Explosion AI](https://explosion.ai) 創辦人 - [spaCy](https://spacy.io) 創作者 (ref) - (ref)
+
---- +## FastAPI 大會 { #fastapi-conf } -"_如果有人想要打造一個可用於生產環境的 Python API,我強力推薦 **FastAPI**。它**設計優雅**、**簡單易用**且**高度可擴展**,已經成為我們 API first 開發策略中的**關鍵元件**,推動了許多自動化與服務,例如我們的 Virtual TAC Engineer。_" +[**FastAPI Conf '26**](https://fastapiconf.com) 將於 **2026 年 10 月 28 日** 在 **荷蘭阿姆斯特丹** 舉行。全部關於 FastAPI,來自第一手來源。🎤 -
Deon Pillsbury - Cisco (ref)
- ---- +FastAPI Conf '26 - October 28, 2026 - Amsterdam, NL ## FastAPI 迷你紀錄片 { #fastapi-mini-documentary } 在 2025 年底發布了一支 [FastAPI 迷你紀錄片](https://www.youtube.com/watch?v=mpR8ngthqiE),你可以在線上觀看: -FastAPI Mini Documentary +FastAPI Mini Documentary ## **Typer**,命令列的 FastAPI { #typer-the-fastapi-of-clis } diff --git a/docs/zh-hant/docs/virtual-environments.md b/docs/zh-hant/docs/virtual-environments.md index 908303dcf..c0ac22474 100644 --- a/docs/zh-hant/docs/virtual-environments.md +++ b/docs/zh-hant/docs/virtual-environments.md @@ -294,7 +294,7 @@ $ echo "*" > .venv/.gitignore 而 `*` 對於 Git 來說意味著「所有內容」。所以,它會忽略 `.venv` 目錄中的所有內容。 -該指令會建立一個名為 .gitignore 的檔案,內容如下: +該指令會建立一個名為 `.gitignore` 的檔案,內容如下: ```gitignore * From 480fdba26a557f4a6de1bc0f207a30c098fb9627 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Mon, 18 May 2026 09:54:43 +0000 Subject: [PATCH 079/462] =?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 fb15bab81..a52aede85 100644 --- a/docs/en/docs/release-notes.md +++ b/docs/en/docs/release-notes.md @@ -17,6 +17,7 @@ hide: ### Translations +* 🌐 Update translations for zh-hant (update-outdated). PR [#15524](https://github.com/fastapi/fastapi/pull/15524) by [@tiangolo](https://github.com/tiangolo). * 🌐 Update translations for fr (update-outdated). PR [#15522](https://github.com/fastapi/fastapi/pull/15522) by [@tiangolo](https://github.com/tiangolo). * 🌐 Update translations for es (update-outdated). PR [#15523](https://github.com/fastapi/fastapi/pull/15523) by [@tiangolo](https://github.com/tiangolo). * 🌐 Update translations for zh (update-outdated). PR [#15520](https://github.com/fastapi/fastapi/pull/15520) by [@tiangolo](https://github.com/tiangolo). From 99812444ab99526d3c961837b138dfdc7bda23f5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebasti=C3=A1n=20Ram=C3=ADrez?= Date: Mon, 18 May 2026 13:55:19 +0200 Subject: [PATCH 080/462] =?UTF-8?q?=F0=9F=93=9D=20Update=20docs,=20simplif?= =?UTF-8?q?y=20usage=20of=20admonitions,=20only=20default=20ones=20(#15553?= =?UTF-8?q?)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docs/en/docs/_llm-test.md | 8 ---- docs/en/docs/advanced/additional-responses.md | 4 +- .../en/docs/advanced/advanced-dependencies.md | 2 +- docs/en/docs/advanced/custom-response.md | 4 +- docs/en/docs/advanced/dataclasses.md | 2 +- docs/en/docs/advanced/events.md | 4 +- docs/en/docs/advanced/openapi-webhooks.md | 4 +- docs/en/docs/advanced/response-directly.md | 2 +- .../docs/advanced/security/oauth2-scopes.md | 4 +- docs/en/docs/advanced/stream-data.md | 4 +- docs/en/docs/advanced/strict-content-type.md | 2 +- docs/en/docs/advanced/websockets.md | 2 +- docs/en/docs/advanced/wsgi.md | 2 +- docs/en/docs/alternatives.md | 44 +++++++++---------- docs/en/docs/async.md | 4 +- docs/en/docs/deployment/docker.md | 4 +- docs/en/docs/deployment/server-workers.md | 2 +- docs/en/docs/external-links.md | 2 +- docs/en/docs/features.md | 2 +- docs/en/docs/help-fastapi.md | 2 +- docs/en/docs/how-to/extending-openapi.md | 2 +- .../docs/how-to/separate-openapi-schemas.md | 2 +- docs/en/docs/python-types.md | 6 +-- docs/en/docs/tutorial/bigger-applications.md | 12 ++--- docs/en/docs/tutorial/body-multiple-params.md | 2 +- docs/en/docs/tutorial/body-nested-models.md | 4 +- docs/en/docs/tutorial/body.md | 2 +- docs/en/docs/tutorial/cookie-param-models.md | 2 +- docs/en/docs/tutorial/cookie-params.md | 4 +- docs/en/docs/tutorial/debugging.md | 2 +- ...pendencies-in-path-operation-decorators.md | 2 +- .../dependencies/dependencies-with-yield.md | 2 +- docs/en/docs/tutorial/dependencies/index.md | 4 +- .../tutorial/dependencies/sub-dependencies.md | 2 +- docs/en/docs/tutorial/first-steps.md | 4 +- docs/en/docs/tutorial/header-params.md | 2 +- docs/en/docs/tutorial/metadata.md | 2 +- .../tutorial/path-operation-configuration.md | 4 +- .../path-params-numeric-validations.md | 4 +- docs/en/docs/tutorial/path-params.md | 8 ++-- .../tutorial/query-params-str-validations.md | 4 +- docs/en/docs/tutorial/query-params.md | 2 +- docs/en/docs/tutorial/request-files.md | 4 +- docs/en/docs/tutorial/request-form-models.md | 2 +- .../docs/tutorial/request-forms-and-files.md | 2 +- docs/en/docs/tutorial/request-forms.md | 4 +- docs/en/docs/tutorial/response-model.md | 4 +- docs/en/docs/tutorial/response-status-code.md | 2 +- docs/en/docs/tutorial/schema-extra-example.md | 6 +-- docs/en/docs/tutorial/security/first-steps.md | 10 ++--- .../tutorial/security/get-current-user.md | 2 +- docs/en/docs/tutorial/security/oauth2-jwt.md | 4 +- .../docs/tutorial/security/simple-oauth2.md | 8 ++-- docs/en/docs/tutorial/server-sent-events.md | 2 +- docs/en/docs/tutorial/stream-json-lines.md | 4 +- docs/en/docs/tutorial/testing.md | 4 +- docs/en/docs/virtual-environments.md | 4 +- docs/en/mkdocs.yml | 4 ++ 58 files changed, 122 insertions(+), 126 deletions(-) diff --git a/docs/en/docs/_llm-test.md b/docs/en/docs/_llm-test.md index cc9cb48fb..2b548064d 100644 --- a/docs/en/docs/_llm-test.md +++ b/docs/en/docs/_llm-test.md @@ -124,10 +124,6 @@ See section `### Content of code blocks` in the general prompt in `scripts/trans //// tab | Test -/// info -Some text -/// - /// note Some text /// @@ -136,10 +132,6 @@ Some text Some text /// -/// check -Some text -/// - /// tip Some text /// diff --git a/docs/en/docs/advanced/additional-responses.md b/docs/en/docs/advanced/additional-responses.md index 577c06daa..494143b07 100644 --- a/docs/en/docs/advanced/additional-responses.md +++ b/docs/en/docs/advanced/additional-responses.md @@ -34,7 +34,7 @@ Keep in mind that you have to return the `JSONResponse` directly. /// -/// info +/// note The `model` key is not part of OpenAPI. @@ -183,7 +183,7 @@ Notice that you have to return the image using a `FileResponse` directly. /// -/// info +/// note Unless you specify a different media type explicitly in your `responses` parameter, FastAPI will assume the response has the same media type as the main response class (default `application/json`). diff --git a/docs/en/docs/advanced/advanced-dependencies.md b/docs/en/docs/advanced/advanced-dependencies.md index 6c940f5a9..59ab62bf0 100644 --- a/docs/en/docs/advanced/advanced-dependencies.md +++ b/docs/en/docs/advanced/advanced-dependencies.md @@ -98,7 +98,7 @@ For example, if you had a database session in a dependency with `yield`, the `St This behavior was reverted in 0.118.0, to make the exit code after `yield` be executed after the response is sent. -/// info +/// note As you will see below, this is very similar to the behavior before version 0.106.0, but with several improvements and bug fixes for corner cases. diff --git a/docs/en/docs/advanced/custom-response.md b/docs/en/docs/advanced/custom-response.md index 0dcb57517..016868fe7 100644 --- a/docs/en/docs/advanced/custom-response.md +++ b/docs/en/docs/advanced/custom-response.md @@ -41,7 +41,7 @@ To return a response with HTML directly from **FastAPI**, use `HTMLResponse`. {* ../../docs_src/custom_response/tutorial002_py310.py hl[2,7] *} -/// info +/// note The parameter `response_class` will also be used to define the "media type" of the response. @@ -65,7 +65,7 @@ A `Response` returned directly by your *path operation function* won't be docume /// -/// info +/// note Of course, the actual `Content-Type` header, status code, etc, will come from the `Response` object you returned. diff --git a/docs/en/docs/advanced/dataclasses.md b/docs/en/docs/advanced/dataclasses.md index 52fe4ae7c..292dc3fba 100644 --- a/docs/en/docs/advanced/dataclasses.md +++ b/docs/en/docs/advanced/dataclasses.md @@ -18,7 +18,7 @@ And of course, it supports the same: This works the same way as with Pydantic models. And it is actually achieved in the same way underneath, using Pydantic. -/// info +/// note Keep in mind that dataclasses can't do everything Pydantic models can do. diff --git a/docs/en/docs/advanced/events.md b/docs/en/docs/advanced/events.md index 820f06d55..3e65854e7 100644 --- a/docs/en/docs/advanced/events.md +++ b/docs/en/docs/advanced/events.md @@ -120,7 +120,7 @@ To add a function that should be run when the application is shutting down, decl Here, the `shutdown` event handler function will write a text line `"Application shutdown"` to a file `log.txt`. -/// info +/// note In the `open()` function, the `mode="a"` means "append", so, the line will be added after whatever is on that file, without overwriting the previous contents. @@ -152,7 +152,7 @@ Just a technical detail for the curious nerds. 🤓 Underneath, in the ASGI technical specification, this is part of the [Lifespan Protocol](https://asgi.readthedocs.io/en/latest/specs/lifespan.html), and it defines events called `startup` and `shutdown`. -/// info +/// note You can read more about the Starlette `lifespan` handlers in [Starlette's Lifespan' docs](https://www.starlette.dev/lifespan/). diff --git a/docs/en/docs/advanced/openapi-webhooks.md b/docs/en/docs/advanced/openapi-webhooks.md index 3da42819a..abcbe8ce2 100644 --- a/docs/en/docs/advanced/openapi-webhooks.md +++ b/docs/en/docs/advanced/openapi-webhooks.md @@ -22,7 +22,7 @@ With **FastAPI**, using OpenAPI, you can define the names of these webhooks, the This can make it a lot easier for your users to **implement their APIs** to receive your **webhook** requests, they might even be able to autogenerate some of their own API code. -/// info +/// note Webhooks are available in OpenAPI 3.1.0 and above, supported by FastAPI `0.99.0` and above. @@ -36,7 +36,7 @@ When you create a **FastAPI** application, there is a `webhooks` attribute that The webhooks that you define will end up in the **OpenAPI** schema and the automatic **docs UI**. -/// info +/// note The `app.webhooks` object is actually just an `APIRouter`, the same type you would use when structuring your app with multiple files. diff --git a/docs/en/docs/advanced/response-directly.md b/docs/en/docs/advanced/response-directly.md index c9d18649f..9dd50a62d 100644 --- a/docs/en/docs/advanced/response-directly.md +++ b/docs/en/docs/advanced/response-directly.md @@ -18,7 +18,7 @@ You will normally have much better performance using a [Response Model](../tutor You can return a `Response` or any sub-class of it. -/// info +/// note `JSONResponse` itself is a sub-class of `Response`. diff --git a/docs/en/docs/advanced/security/oauth2-scopes.md b/docs/en/docs/advanced/security/oauth2-scopes.md index 459646bbd..92b604757 100644 --- a/docs/en/docs/advanced/security/oauth2-scopes.md +++ b/docs/en/docs/advanced/security/oauth2-scopes.md @@ -46,7 +46,7 @@ They are normally used to declare specific security permissions, for example: * `instagram_basic` is used by Facebook / Instagram. * `https://www.googleapis.com/auth/drive` is used by Google. -/// info +/// note In OAuth2 a "scope" is just a string that declares a specific permission required. @@ -126,7 +126,7 @@ We are doing it here to demonstrate how **FastAPI** handles scopes declared at d {* ../../docs_src/security/tutorial005_an_py310.py hl[5,141,172] *} -/// info | Technical Details +/// note | Technical Details `Security` is actually a subclass of `Depends`, and it has just one extra parameter that we'll see later. diff --git a/docs/en/docs/advanced/stream-data.md b/docs/en/docs/advanced/stream-data.md index 4af12fa31..3e7c89a93 100644 --- a/docs/en/docs/advanced/stream-data.md +++ b/docs/en/docs/advanced/stream-data.md @@ -4,7 +4,7 @@ If you want to stream data that can be structured as JSON, you should [Stream JS But if you want to **stream pure binary data** or strings, here's how you can do it. -/// info +/// note Added in FastAPI 0.134.0. @@ -90,7 +90,7 @@ For example, they don't have an `await file.read()`, or `async for chunk in file And in many cases, reading them would be a blocking operation (that could block the event loop), because they are read from disk or from the network. -/// info +/// note The example above is actually an exception, because the `io.BytesIO` object is already in memory, so reading it won't block anything. diff --git a/docs/en/docs/advanced/strict-content-type.md b/docs/en/docs/advanced/strict-content-type.md index 54c099410..a0d9a1423 100644 --- a/docs/en/docs/advanced/strict-content-type.md +++ b/docs/en/docs/advanced/strict-content-type.md @@ -81,7 +81,7 @@ If you need to support clients that don't send a `Content-Type` header, you can With this setting, requests without a `Content-Type` header will have their body parsed as JSON, which is the same behavior as older versions of FastAPI. -/// info +/// note This behavior and configuration was added in FastAPI 0.132.0. diff --git a/docs/en/docs/advanced/websockets.md b/docs/en/docs/advanced/websockets.md index 50c5e89a4..6f4603e6a 100644 --- a/docs/en/docs/advanced/websockets.md +++ b/docs/en/docs/advanced/websockets.md @@ -111,7 +111,7 @@ They work the same way as for other FastAPI endpoints/*path operations*: {* ../../docs_src/websockets_/tutorial002_an_py310.py hl[68:69,82] *} -/// info +/// note As this is a WebSocket it doesn't really make sense to raise an `HTTPException`, instead we raise a `WebSocketException`. diff --git a/docs/en/docs/advanced/wsgi.md b/docs/en/docs/advanced/wsgi.md index 44807b723..39a492eb6 100644 --- a/docs/en/docs/advanced/wsgi.md +++ b/docs/en/docs/advanced/wsgi.md @@ -6,7 +6,7 @@ For that, you can use the `WSGIMiddleware` and use it to wrap your WSGI applicat ## Using `WSGIMiddleware` { #using-wsgimiddleware } -/// info +/// note This requires installing `a2wsgi` for example with `pip install a2wsgi`. diff --git a/docs/en/docs/alternatives.md b/docs/en/docs/alternatives.md index bfaa7aa13..0e7dc8571 100644 --- a/docs/en/docs/alternatives.md +++ b/docs/en/docs/alternatives.md @@ -36,7 +36,7 @@ Django REST Framework was created by Tom Christie. The same creator of Starlette /// -/// check | Inspired **FastAPI** to +/// tip | Inspired **FastAPI** to Have an automatic API documentation web user interface. @@ -56,7 +56,7 @@ This decoupling of parts, and being a "microframework" that could be extended to Given the simplicity of Flask, it seemed like a good match for building APIs. The next thing to find was a "Django REST Framework" for Flask. -/// check | Inspired **FastAPI** to +/// tip | Inspired **FastAPI** to Be a micro-framework. Making it easy to mix and match the tools and parts needed. @@ -98,7 +98,7 @@ def read_url(): See the similarities in `requests.get(...)` and `@app.get(...)`. -/// check | Inspired **FastAPI** to +/// tip | Inspired **FastAPI** to * Have a simple and intuitive API. * Use HTTP method names (operations) directly, in a straightforward and intuitive way. @@ -118,7 +118,7 @@ At some point, Swagger was given to the Linux Foundation, to be renamed OpenAPI. That's why when talking about version 2.0 it's common to say "Swagger", and for version 3+ "OpenAPI". -/// check | Inspired **FastAPI** to +/// tip | Inspired **FastAPI** to Adopt and use an open standard for API specifications, instead of a custom schema. @@ -147,7 +147,7 @@ These features are what Marshmallow was built to provide. It is a great library, But it was created before there existed Python type hints. So, to define every schema you need to use specific utils and classes provided by Marshmallow. -/// check | Inspired **FastAPI** to +/// tip | Inspired **FastAPI** to Use code to define "schemas" that provide data types and validation, automatically. @@ -163,13 +163,13 @@ It uses Marshmallow underneath to do the data validation. And it was created by It's a great tool and I have used it a lot too, before having **FastAPI**. -/// info +/// note Webargs was created by the same Marshmallow developers. /// -/// check | Inspired **FastAPI** to +/// tip | Inspired **FastAPI** to Have automatic validation of incoming request data. @@ -193,13 +193,13 @@ But then, we have again the problem of having a micro-syntax, inside of a Python The editor can't help much with that. And if we modify parameters or Marshmallow schemas and forget to also modify that YAML docstring, the generated schema would be obsolete. -/// info +/// note APISpec was created by the same Marshmallow developers. /// -/// check | Inspired **FastAPI** to +/// tip | Inspired **FastAPI** to Support the open standard for APIs, OpenAPI. @@ -225,13 +225,13 @@ Using it led to the creation of several Flask full-stack generators. These are t And these same full-stack generators were the base of the [**FastAPI** Project Generators](project-generation.md). -/// info +/// note Flask-apispec was created by the same Marshmallow developers. /// -/// check | Inspired **FastAPI** to +/// tip | Inspired **FastAPI** to Generate the OpenAPI schema automatically, from the same code that defines serialization and validation. @@ -251,7 +251,7 @@ But as TypeScript data is not preserved after compilation to JavaScript, it cann It can't handle nested models very well. So, if the JSON body in the request is a JSON object that has inner fields that in turn are nested JSON objects, it cannot be properly documented and validated. -/// check | Inspired **FastAPI** to +/// tip | Inspired **FastAPI** to Use Python types to have great editor support. @@ -271,7 +271,7 @@ It clearly inspired Uvicorn and Starlette, that are currently faster than Sanic /// -/// check | Inspired **FastAPI** to +/// tip | Inspired **FastAPI** to Find a way to have a crazy performance. @@ -287,7 +287,7 @@ It is designed to have functions that receive two parameters, one "request" and So, data validation, serialization, and documentation, have to be done in code, not automatically. Or they have to be implemented as a framework on top of Falcon, like Hug. This same distinction happens in other frameworks that are inspired by Falcon's design, of having one request object and one response object as parameters. -/// check | Inspired **FastAPI** to +/// tip | Inspired **FastAPI** to Find ways to get great performance. @@ -313,7 +313,7 @@ The dependency injection system requires pre-registration of the dependencies an Routes are declared in a single place, using functions declared in other places (instead of using decorators that can be placed right on top of the function that handles the endpoint). This is closer to how Django does it than to how Flask (and Starlette) does it. It separates in the code things that are relatively tightly coupled. -/// check | Inspired **FastAPI** to +/// tip | Inspired **FastAPI** to Define extra validations for data types using the "default" value of model attributes. This improves editor support, and it was not available in Pydantic before. @@ -335,13 +335,13 @@ It has an interesting, uncommon feature: using the same framework, it's possible As it is based on the previous standard for synchronous Python web frameworks (WSGI), it can't handle Websockets and other things, although it still has high performance too. -/// info +/// note Hug was created by Timothy Crosley, the same creator of [`isort`](https://github.com/timothycrosley/isort), a great tool to automatically sort imports in Python files. /// -/// check | Ideas inspiring **FastAPI** +/// tip | Ideas inspiring **FastAPI** Hug inspired parts of APIStar, and was one of the tools I found most promising, alongside APIStar. @@ -375,7 +375,7 @@ It was no longer an API web framework, as the creator needed to focus on Starlet Now APIStar is a set of tools to validate OpenAPI specifications, not a web framework. -/// info +/// note APIStar was created by Tom Christie. The same guy that created: @@ -385,7 +385,7 @@ APIStar was created by Tom Christie. The same guy that created: /// -/// check | Inspired **FastAPI** to +/// tip | Inspired **FastAPI** to Exist. @@ -409,7 +409,7 @@ That makes it extremely intuitive. It is comparable to Marshmallow. Although it's faster than Marshmallow in benchmarks. And as it is based on the same Python type hints, the editor support is great. -/// check | **FastAPI** uses it to +/// tip | **FastAPI** uses it to Handle all the data validation, data serialization and automatic model documentation (based on JSON Schema). @@ -452,7 +452,7 @@ Nevertheless, it is already being used as a "standard" by several tools. This gr /// -/// check | **FastAPI** uses it to +/// tip | **FastAPI** uses it to Handle all the core web parts. Adding features on top. @@ -470,7 +470,7 @@ It is not a web framework, but a server. For example, it doesn't provide tools f It is the recommended server for Starlette and **FastAPI**. -/// check | **FastAPI** recommends it as +/// tip | **FastAPI** recommends it as The main web server to run **FastAPI** applications. diff --git a/docs/en/docs/async.md b/docs/en/docs/async.md index 8d445ace1..1ad996034 100644 --- a/docs/en/docs/async.md +++ b/docs/en/docs/async.md @@ -139,7 +139,7 @@ You and your crush eat the burgers and have a nice time. ✨ -/// info +/// note Beautiful illustrations by [Ketrina Thompson](https://www.instagram.com/ketrinadrawsalot). 🎨 @@ -205,7 +205,7 @@ You just eat them, and you are done. ⏹ There was not much talk or flirting as most of the time was spent waiting 🕙 in front of the counter. 😞 -/// info +/// note Beautiful illustrations by [Ketrina Thompson](https://www.instagram.com/ketrinadrawsalot). 🎨 diff --git a/docs/en/docs/deployment/docker.md b/docs/en/docs/deployment/docker.md index ce7d0f1c7..b021ef1b6 100644 --- a/docs/en/docs/deployment/docker.md +++ b/docs/en/docs/deployment/docker.md @@ -132,7 +132,7 @@ Successfully installed fastapi pydantic
-/// info +/// note There are other formats and tools to define and install package dependencies. @@ -556,7 +556,7 @@ If you are using containers (e.g. Docker, Kubernetes), then there are two main a If you have **multiple containers**, probably each one running a **single process** (for example, in a **Kubernetes** cluster), then you would probably want to have a **separate container** doing the work of the **previous steps** in a single container, running a single process, **before** running the replicated worker containers. -/// info +/// note If you are using Kubernetes, this would probably be an [Init Container](https://kubernetes.io/docs/concepts/workloads/pods/init-containers/). diff --git a/docs/en/docs/deployment/server-workers.md b/docs/en/docs/deployment/server-workers.md index 4f292224c..fb0741acb 100644 --- a/docs/en/docs/deployment/server-workers.md +++ b/docs/en/docs/deployment/server-workers.md @@ -17,7 +17,7 @@ As you saw in the previous chapter about [Deployment Concepts](concepts.md), the Here I'll show you how to use **Uvicorn** with **worker processes** using the `fastapi` command or the `uvicorn` command directly. -/// info +/// note If you are using containers, for example with Docker or Kubernetes, I'll tell you more about that in the next chapter: [FastAPI in Containers - Docker](docker.md). diff --git a/docs/en/docs/external-links.md b/docs/en/docs/external-links.md index 80485fd30..e92c881f4 100644 --- a/docs/en/docs/external-links.md +++ b/docs/en/docs/external-links.md @@ -6,7 +6,7 @@ There are many posts, articles, tools, and projects, related to **FastAPI**. You could easily use a search engine or video platform to find many resources related to FastAPI. -/// info +/// note Before, this page used to list links to external articles. diff --git a/docs/en/docs/features.md b/docs/en/docs/features.md index eee11cd1e..a1a271d28 100644 --- a/docs/en/docs/features.md +++ b/docs/en/docs/features.md @@ -63,7 +63,7 @@ second_user_data = { my_second_user: User = User(**second_user_data) ``` -/// info +/// note `**second_user_data` means: diff --git a/docs/en/docs/help-fastapi.md b/docs/en/docs/help-fastapi.md index ab68961ca..92ff0f2e0 100644 --- a/docs/en/docs/help-fastapi.md +++ b/docs/en/docs/help-fastapi.md @@ -170,7 +170,7 @@ And if there's any other style or consistency need, I'll ask directly for that, * Then **comment** saying that you did that, that's how I will know you really checked it. -/// info +/// note Unfortunately, I can't simply trust PRs that just have several approvals. diff --git a/docs/en/docs/how-to/extending-openapi.md b/docs/en/docs/how-to/extending-openapi.md index c110a444f..65f584438 100644 --- a/docs/en/docs/how-to/extending-openapi.md +++ b/docs/en/docs/how-to/extending-openapi.md @@ -27,7 +27,7 @@ And that function `get_openapi()` receives as parameters: * `description`: The description of your API, this can include markdown and will be shown in the docs. * `routes`: A list of routes, these are each of the registered *path operations*. They are taken from `app.routes`. -/// info +/// note The parameter `summary` is available in OpenAPI 3.1.0 and above, supported by FastAPI 0.99.0 and above. diff --git a/docs/en/docs/how-to/separate-openapi-schemas.md b/docs/en/docs/how-to/separate-openapi-schemas.md index d790c600b..4eb684dc9 100644 --- a/docs/en/docs/how-to/separate-openapi-schemas.md +++ b/docs/en/docs/how-to/separate-openapi-schemas.md @@ -85,7 +85,7 @@ Probably the main use case for this is if you already have some autogenerated cl In that case, you can disable this feature in **FastAPI**, with the parameter `separate_input_output_schemas=False`. -/// info +/// note Support for `separate_input_output_schemas` was added in FastAPI `0.102.0`. 🤓 diff --git a/docs/en/docs/python-types.md b/docs/en/docs/python-types.md index 0cddcd390..976129117 100644 --- a/docs/en/docs/python-types.md +++ b/docs/en/docs/python-types.md @@ -172,7 +172,7 @@ As the list is a type that contains some internal types, you put them in square {* ../../docs_src/python_types/tutorial006_py310.py hl[1] *} -/// info +/// note Those internal types in the square brackets are called "type parameters". @@ -283,7 +283,7 @@ An example from the official Pydantic docs: {* ../../docs_src/python_types/tutorial011_py310.py *} -/// info +/// note To learn more about [Pydantic, check its docs](https://docs.pydantic.dev/). @@ -341,7 +341,7 @@ This might all sound abstract. Don't worry. You'll see all this in action in the The important thing is that by using standard Python types, in a single place (instead of adding more classes, decorators, etc), **FastAPI** will do a lot of the work for you. -/// info +/// note If you already went through all the tutorial and came back to see more about types, a good resource is [the "cheat sheet" from `mypy`](https://mypy.readthedocs.io/en/latest/cheat_sheet_py3.html). diff --git a/docs/en/docs/tutorial/bigger-applications.md b/docs/en/docs/tutorial/bigger-applications.md index 675ec1b43..8950d59b4 100644 --- a/docs/en/docs/tutorial/bigger-applications.md +++ b/docs/en/docs/tutorial/bigger-applications.md @@ -4,7 +4,7 @@ If you are building an application or a web API, it's rarely the case that you c **FastAPI** provides a convenience tool to structure your application while keeping all the flexibility. -/// info +/// note If you come from Flask, this would be the equivalent of Flask's Blueprints. @@ -194,7 +194,7 @@ Having `dependencies` in the `APIRouter` can be used, for example, to require au /// -/// check +/// tip The `prefix`, `tags`, `responses`, and `dependencies` parameters are (as in many other cases) just a feature from **FastAPI** to help you avoid code duplication. @@ -339,7 +339,7 @@ We could also import them like: from app.routers import items, users ``` -/// info +/// note The first version is a "relative import": @@ -382,7 +382,7 @@ Now, let's include the `router`s from the submodules `users` and `items`: {* ../../docs_src/bigger_applications/app_an_py310/main.py hl[10:11] title["app/main.py"] *} -/// info +/// note `users.router` contains the `APIRouter` inside of the file `app/routers/users.py`. @@ -402,7 +402,7 @@ So, behind the scenes, it will actually work as if everything was the same singl /// -/// check +/// tip You don't have to worry about performance when including routers. @@ -451,7 +451,7 @@ Here we do it... just to show that we can 🤷: and it will work correctly, together with all the other *path operations* added with `app.include_router()`. -/// info | Very Technical Details +/// note | Very Technical Details **Note**: this is a very technical detail that you probably can **just skip**. diff --git a/docs/en/docs/tutorial/body-multiple-params.md b/docs/en/docs/tutorial/body-multiple-params.md index d904fb839..cdef50ec3 100644 --- a/docs/en/docs/tutorial/body-multiple-params.md +++ b/docs/en/docs/tutorial/body-multiple-params.md @@ -111,7 +111,7 @@ For example: {* ../../docs_src/body_multiple_params/tutorial004_an_py310.py hl[28] *} -/// info +/// note `Body` also has all the same extra validation and metadata parameters as `Query`, `Path` and others you will see later. diff --git a/docs/en/docs/tutorial/body-nested-models.md b/docs/en/docs/tutorial/body-nested-models.md index 17c560f40..5479ab2a4 100644 --- a/docs/en/docs/tutorial/body-nested-models.md +++ b/docs/en/docs/tutorial/body-nested-models.md @@ -136,7 +136,7 @@ This will expect (convert, validate, document, etc.) a JSON body like: } ``` -/// info +/// note Notice how the `images` key now has a list of image objects. @@ -148,7 +148,7 @@ You can define arbitrarily deeply nested models: {* ../../docs_src/body_nested_models/tutorial007_py310.py hl[7,12,18,21,25] *} -/// info +/// note Notice how `Offer` has a list of `Item`s, which in turn have an optional list of `Image`s diff --git a/docs/en/docs/tutorial/body.md b/docs/en/docs/tutorial/body.md index ca72548a4..dda9798d8 100644 --- a/docs/en/docs/tutorial/body.md +++ b/docs/en/docs/tutorial/body.md @@ -8,7 +8,7 @@ Your API almost always has to send a **response** body. But clients don't necess To declare a **request** body, you use [Pydantic](https://docs.pydantic.dev/) models with all their power and benefits. -/// info +/// note To send data, you should use one of: `POST` (the more common), `PUT`, `DELETE` or `PATCH`. diff --git a/docs/en/docs/tutorial/cookie-param-models.md b/docs/en/docs/tutorial/cookie-param-models.md index 609838f76..27fb1164a 100644 --- a/docs/en/docs/tutorial/cookie-param-models.md +++ b/docs/en/docs/tutorial/cookie-param-models.md @@ -32,7 +32,7 @@ You can see the defined cookies in the docs UI at `/docs`:
-/// info +/// note Have in mind that, as **browsers handle cookies** in special ways and behind the scenes, they **don't** easily allow **JavaScript** to touch them. diff --git a/docs/en/docs/tutorial/cookie-params.md b/docs/en/docs/tutorial/cookie-params.md index f44fd41bd..b57cea8a7 100644 --- a/docs/en/docs/tutorial/cookie-params.md +++ b/docs/en/docs/tutorial/cookie-params.md @@ -24,13 +24,13 @@ But remember that when you import `Query`, `Path`, `Cookie` and others from `fas /// -/// info +/// note To declare cookies, you need to use `Cookie`, because otherwise the parameters would be interpreted as query parameters. /// -/// info +/// note Have in mind that, as **browsers handle cookies** in special ways and behind the scenes, they **don't** easily allow **JavaScript** to touch them. diff --git a/docs/en/docs/tutorial/debugging.md b/docs/en/docs/tutorial/debugging.md index d157cb7bf..8db47b934 100644 --- a/docs/en/docs/tutorial/debugging.md +++ b/docs/en/docs/tutorial/debugging.md @@ -72,7 +72,7 @@ So, the line: will not be executed. -/// info +/// note For more information, check [the official Python docs](https://docs.python.org/3/library/__main__.html). diff --git a/docs/en/docs/tutorial/dependencies/dependencies-in-path-operation-decorators.md b/docs/en/docs/tutorial/dependencies/dependencies-in-path-operation-decorators.md index e663c4082..82d4526b1 100644 --- a/docs/en/docs/tutorial/dependencies/dependencies-in-path-operation-decorators.md +++ b/docs/en/docs/tutorial/dependencies/dependencies-in-path-operation-decorators.md @@ -28,7 +28,7 @@ It might also help avoid confusion for new developers that see an unused paramet /// -/// info +/// note In this example we use invented custom headers `X-Key` and `X-Token`. diff --git a/docs/en/docs/tutorial/dependencies/dependencies-with-yield.md b/docs/en/docs/tutorial/dependencies/dependencies-with-yield.md index 7b80a74e4..658dee7c2 100644 --- a/docs/en/docs/tutorial/dependencies/dependencies-with-yield.md +++ b/docs/en/docs/tutorial/dependencies/dependencies-with-yield.md @@ -170,7 +170,7 @@ participant tasks as Background tasks end ``` -/// info +/// note Only **one response** will be sent to the client. It might be one of the error responses or it will be the response from the *path operation*. diff --git a/docs/en/docs/tutorial/dependencies/index.md b/docs/en/docs/tutorial/dependencies/index.md index 396c23acb..0bf651adb 100644 --- a/docs/en/docs/tutorial/dependencies/index.md +++ b/docs/en/docs/tutorial/dependencies/index.md @@ -51,7 +51,7 @@ In this case, this dependency expects: And then it just returns a `dict` containing those values. -/// info +/// note FastAPI added support for `Annotated` (and started recommending it) in version 0.95.0. @@ -106,7 +106,7 @@ common_parameters --> read_users This way you write shared code once and **FastAPI** takes care of calling it for your *path operations*. -/// check +/// tip Notice that you don't have to create a special class and pass it somewhere to **FastAPI** to "register" it or anything similar. diff --git a/docs/en/docs/tutorial/dependencies/sub-dependencies.md b/docs/en/docs/tutorial/dependencies/sub-dependencies.md index 99588dd3c..34b0248e9 100644 --- a/docs/en/docs/tutorial/dependencies/sub-dependencies.md +++ b/docs/en/docs/tutorial/dependencies/sub-dependencies.md @@ -35,7 +35,7 @@ Then we can use the dependency with: {* ../../docs_src/dependencies/tutorial005_an_py310.py hl[23] *} -/// info +/// note Notice that we are only declaring one dependency in the *path operation function*, the `query_or_cookie_extractor`. diff --git a/docs/en/docs/tutorial/first-steps.md b/docs/en/docs/tutorial/first-steps.md index 335507990..96aaa7463 100644 --- a/docs/en/docs/tutorial/first-steps.md +++ b/docs/en/docs/tutorial/first-steps.md @@ -270,7 +270,7 @@ https://example.com/items/foo /items/foo ``` -/// info +/// note A "path" is also commonly called an "endpoint" or a "route". @@ -322,7 +322,7 @@ The `@app.get("/")` tells **FastAPI** that the function right below is in charge * the path `/` * using a get operation -/// info | `@decorator` Info +/// note | `@decorator` Info That `@something` syntax in Python is called a "decorator". diff --git a/docs/en/docs/tutorial/header-params.md b/docs/en/docs/tutorial/header-params.md index 3765956a0..9f72545d3 100644 --- a/docs/en/docs/tutorial/header-params.md +++ b/docs/en/docs/tutorial/header-params.md @@ -24,7 +24,7 @@ But remember that when you import `Query`, `Path`, `Header`, and others from `fa /// -/// info +/// note To declare headers, you need to use `Header`, because otherwise the parameters would be interpreted as query parameters. diff --git a/docs/en/docs/tutorial/metadata.md b/docs/en/docs/tutorial/metadata.md index 2abf0a342..9cab5ca71 100644 --- a/docs/en/docs/tutorial/metadata.md +++ b/docs/en/docs/tutorial/metadata.md @@ -74,7 +74,7 @@ Use the `tags` parameter with your *path operations* (and `APIRouter`s) to assig {* ../../docs_src/metadata/tutorial004_py310.py hl[21,26] *} -/// info +/// note Read more about tags in [Path Operation Configuration](path-operation-configuration.md#tags). diff --git a/docs/en/docs/tutorial/path-operation-configuration.md b/docs/en/docs/tutorial/path-operation-configuration.md index e350f7683..8dfc6e2ff 100644 --- a/docs/en/docs/tutorial/path-operation-configuration.md +++ b/docs/en/docs/tutorial/path-operation-configuration.md @@ -72,13 +72,13 @@ You can specify the response description with the parameter `response_descriptio {* ../../docs_src/path_operation_configuration/tutorial005_py310.py hl[18] *} -/// info +/// note Notice that `response_description` refers specifically to the response, the `description` refers to the *path operation* in general. /// -/// check +/// tip OpenAPI specifies that each *path operation* requires a response description. diff --git a/docs/en/docs/tutorial/path-params-numeric-validations.md b/docs/en/docs/tutorial/path-params-numeric-validations.md index 2ba40e92f..8039b8048 100644 --- a/docs/en/docs/tutorial/path-params-numeric-validations.md +++ b/docs/en/docs/tutorial/path-params-numeric-validations.md @@ -8,7 +8,7 @@ First, import `Path` from `fastapi`, and import `Annotated`: {* ../../docs_src/path_params_numeric_validations/tutorial001_an_py310.py hl[1,3] *} -/// info +/// note FastAPI added support for `Annotated` (and started recommending it) in version 0.95.0. @@ -131,7 +131,7 @@ And you can also declare numeric validations: * `lt`: `l`ess `t`han * `le`: `l`ess than or `e`qual -/// info +/// note `Query`, `Path`, and other classes you will see later are subclasses of a common `Param` class. diff --git a/docs/en/docs/tutorial/path-params.md b/docs/en/docs/tutorial/path-params.md index 6614dfdcb..c8fe68f5e 100644 --- a/docs/en/docs/tutorial/path-params.md +++ b/docs/en/docs/tutorial/path-params.md @@ -20,7 +20,7 @@ You can declare the type of a path parameter in the function, using standard Pyt In this case, `item_id` is declared to be an `int`. -/// check +/// tip This will give you editor support inside of your function, with error checks, completion, etc. @@ -34,7 +34,7 @@ If you run this example and open your browser at [http://127.0.0.1:8000/items/3] {"item_id":3} ``` -/// check +/// tip Notice that the value your function received (and returned) is `3`, as a Python `int`, not a string `"3"`. @@ -66,7 +66,7 @@ because the path parameter `item_id` had a value of `"foo"`, which is not an `in The same error would appear if you provided a `float` instead of an `int`, as in: [http://127.0.0.1:8000/items/4.2](http://127.0.0.1:8000/items/4.2) -/// check +/// tip So, with the same Python type declaration, **FastAPI** gives you data validation. @@ -82,7 +82,7 @@ And when you open your browser at [http://127.0.0.1:8000/docs](http://127.0.0.1: -/// check +/// tip Again, just with that same Python type declaration, **FastAPI** gives you automatic, interactive documentation (integrating Swagger UI). diff --git a/docs/en/docs/tutorial/query-params-str-validations.md b/docs/en/docs/tutorial/query-params-str-validations.md index 4765b36cb..0714d8beb 100644 --- a/docs/en/docs/tutorial/query-params-str-validations.md +++ b/docs/en/docs/tutorial/query-params-str-validations.md @@ -29,7 +29,7 @@ To achieve that, first import: {* ../../docs_src/query_params_str_validations/tutorial002_an_py310.py hl[1,3] *} -/// info +/// note FastAPI added support for `Annotated` (and started recommending it) in version 0.95.0. @@ -382,7 +382,7 @@ For example, this custom validator checks that the item ID starts with `isbn-` f {* ../../docs_src/query_params_str_validations/tutorial015_an_py310.py hl[5,16:19,24] *} -/// info +/// note This is available with Pydantic version 2 or above. 😎 diff --git a/docs/en/docs/tutorial/query-params.md b/docs/en/docs/tutorial/query-params.md index efe2c6d7a..563d39f7d 100644 --- a/docs/en/docs/tutorial/query-params.md +++ b/docs/en/docs/tutorial/query-params.md @@ -65,7 +65,7 @@ The same way, you can declare optional query parameters, by setting their defaul In this case, the function parameter `q` will be optional, and will be `None` by default. -/// check +/// tip Also notice that **FastAPI** is smart enough to notice that the path parameter `item_id` is a path parameter and `q` is not, so, it's a query parameter. diff --git a/docs/en/docs/tutorial/request-files.md b/docs/en/docs/tutorial/request-files.md index ae3d6a119..fe4290449 100644 --- a/docs/en/docs/tutorial/request-files.md +++ b/docs/en/docs/tutorial/request-files.md @@ -2,7 +2,7 @@ You can define files to be uploaded by the client using `File`. -/// info +/// note To receive uploaded files, first install [`python-multipart`](https://github.com/Kludex/python-multipart). @@ -28,7 +28,7 @@ Create file parameters the same way you would for `Body` or `Form`: {* ../../docs_src/request_files/tutorial001_an_py310.py hl[9] *} -/// info +/// note `File` is a class that inherits directly from `Form`. diff --git a/docs/en/docs/tutorial/request-form-models.md b/docs/en/docs/tutorial/request-form-models.md index 2e0f46329..71766bd4e 100644 --- a/docs/en/docs/tutorial/request-form-models.md +++ b/docs/en/docs/tutorial/request-form-models.md @@ -2,7 +2,7 @@ You can use **Pydantic models** to declare **form fields** in FastAPI. -/// info +/// note To use forms, first install [`python-multipart`](https://github.com/Kludex/python-multipart). diff --git a/docs/en/docs/tutorial/request-forms-and-files.md b/docs/en/docs/tutorial/request-forms-and-files.md index 144300412..f6a839491 100644 --- a/docs/en/docs/tutorial/request-forms-and-files.md +++ b/docs/en/docs/tutorial/request-forms-and-files.md @@ -2,7 +2,7 @@ You can define files and form fields at the same time using `File` and `Form`. -/// info +/// note To receive uploaded files and/or form data, first install [`python-multipart`](https://github.com/Kludex/python-multipart). diff --git a/docs/en/docs/tutorial/request-forms.md b/docs/en/docs/tutorial/request-forms.md index 8c4b32d85..64e90a244 100644 --- a/docs/en/docs/tutorial/request-forms.md +++ b/docs/en/docs/tutorial/request-forms.md @@ -2,7 +2,7 @@ When you need to receive form fields instead of JSON, you can use `Form`. -/// info +/// note To use forms, first install [`python-multipart`](https://github.com/Kludex/python-multipart). @@ -32,7 +32,7 @@ The spec requires the fields to be exactly name With `Form` you can declare the same configurations as with `Body` (and `Query`, `Path`, `Cookie`), including validation, examples, an alias (e.g. `user-name` instead of `username`), etc. -/// info +/// note `Form` is a class that inherits directly from `Body`. diff --git a/docs/en/docs/tutorial/response-model.md b/docs/en/docs/tutorial/response-model.md index d628167dd..ae93eece6 100644 --- a/docs/en/docs/tutorial/response-model.md +++ b/docs/en/docs/tutorial/response-model.md @@ -72,7 +72,7 @@ Here we are declaring a `UserIn` model, it will contain a plaintext password: {* ../../docs_src/response_model/tutorial002_py310.py hl[7,9] *} -/// info +/// note To use `EmailStr`, first install [`email-validator`](https://github.com/JoshData/python-email-validator). @@ -251,7 +251,7 @@ So, if you send a request to that *path operation* for the item with ID `foo`, t } ``` -/// info +/// note You can also use: diff --git a/docs/en/docs/tutorial/response-status-code.md b/docs/en/docs/tutorial/response-status-code.md index dcadaa36d..a5f82ffb6 100644 --- a/docs/en/docs/tutorial/response-status-code.md +++ b/docs/en/docs/tutorial/response-status-code.md @@ -18,7 +18,7 @@ Notice that `status_code` is a parameter of the "decorator" method (`get`, `post The `status_code` parameter receives a number with the HTTP status code. -/// info +/// note `status_code` can alternatively also receive an `IntEnum`, such as Python's [`http.HTTPStatus`](https://docs.python.org/3/library/http.html#http.HTTPStatus). diff --git a/docs/en/docs/tutorial/schema-extra-example.md b/docs/en/docs/tutorial/schema-extra-example.md index 2b5fe11c0..67c7ac37c 100644 --- a/docs/en/docs/tutorial/schema-extra-example.md +++ b/docs/en/docs/tutorial/schema-extra-example.md @@ -24,7 +24,7 @@ For example you could use it to add metadata for a frontend user interface, etc. /// -/// info +/// note OpenAPI 3.1.0 (used since FastAPI 0.99.0) added support for `examples`, which is part of the **JSON Schema** standard. @@ -155,7 +155,7 @@ OpenAPI also added `example` and `examples` fields to other parts of the specifi * `File()` * `Form()` -/// info +/// note This old OpenAPI-specific `examples` parameter is now `openapi_examples` since FastAPI `0.103.0`. @@ -171,7 +171,7 @@ And now this new `examples` field takes precedence over the old single (and cust This new `examples` field in JSON Schema is **just a `list`** of examples, not a dict with extra metadata as in the other places in OpenAPI (described above). -/// info +/// note Even after OpenAPI 3.1.0 was released with this new simpler integration with JSON Schema, for a while, Swagger UI, the tool that provides the automatic docs, didn't support OpenAPI 3.1.0 (it does since version 5.0.0 🎉). diff --git a/docs/en/docs/tutorial/security/first-steps.md b/docs/en/docs/tutorial/security/first-steps.md index cf19f7dbd..095b8b901 100644 --- a/docs/en/docs/tutorial/security/first-steps.md +++ b/docs/en/docs/tutorial/security/first-steps.md @@ -24,7 +24,7 @@ Copy the example in a file `main.py`: ## Run it { #run-it } -/// info +/// note The [`python-multipart`](https://github.com/Kludex/python-multipart) package is automatically installed with **FastAPI** when you run the `pip install "fastapi[standard]"` command. @@ -60,7 +60,7 @@ You will see something like this: -/// check | Authorize button! +/// tip | Authorize button! You already have a shiny new "Authorize" button. @@ -118,7 +118,7 @@ So, let's review it from that simplified point of view: In this example we are going to use **OAuth2**, with the **Password** flow, using a **Bearer** token. We do that using the `OAuth2PasswordBearer` class. -/// info +/// note A "bearer" token is not the only option. @@ -148,7 +148,7 @@ This parameter doesn't create that endpoint / *path operation*, but declares tha We will soon also create the actual path operation. -/// info +/// note If you are a very strict "Pythonista" you might dislike the style of the parameter name `tokenUrl` instead of `token_url`. @@ -176,7 +176,7 @@ This dependency will provide a `str` that is assigned to the parameter `token` o **FastAPI** will know that it can use this dependency to define a "security scheme" in the OpenAPI schema (and the automatic API docs). -/// info | Technical Details +/// note | Technical Details **FastAPI** will know that it can use the class `OAuth2PasswordBearer` (declared in a dependency) to define the security scheme in OpenAPI because it inherits from `fastapi.security.oauth2.OAuth2`, which in turn inherits from `fastapi.security.base.SecurityBase`. diff --git a/docs/en/docs/tutorial/security/get-current-user.md b/docs/en/docs/tutorial/security/get-current-user.md index 2eb80341f..f8a5fdf82 100644 --- a/docs/en/docs/tutorial/security/get-current-user.md +++ b/docs/en/docs/tutorial/security/get-current-user.md @@ -52,7 +52,7 @@ Here **FastAPI** won't get confused because you are using `Depends`. /// -/// check +/// tip The way this dependency system is designed allows us to have different dependencies (different "dependables") that all return a `User` model. diff --git a/docs/en/docs/tutorial/security/oauth2-jwt.md b/docs/en/docs/tutorial/security/oauth2-jwt.md index fabdd06a6..983da9a85 100644 --- a/docs/en/docs/tutorial/security/oauth2-jwt.md +++ b/docs/en/docs/tutorial/security/oauth2-jwt.md @@ -42,7 +42,7 @@ $ pip install pyjwt
-/// info +/// note If you are planning to use digital signature algorithms like RSA or ECDSA, you should install the cryptography library dependency `pyjwt[crypto]`. @@ -213,7 +213,7 @@ Using the credentials: Username: `johndoe` Password: `secret` -/// check +/// tip Notice that nowhere in the code is the plaintext password "`secret`", we only have the hashed version. diff --git a/docs/en/docs/tutorial/security/simple-oauth2.md b/docs/en/docs/tutorial/security/simple-oauth2.md index a98112d76..afe3ba128 100644 --- a/docs/en/docs/tutorial/security/simple-oauth2.md +++ b/docs/en/docs/tutorial/security/simple-oauth2.md @@ -32,7 +32,7 @@ They are normally used to declare specific security permissions, for example: * `instagram_basic` is used by Facebook / Instagram. * `https://www.googleapis.com/auth/drive` is used by Google. -/// info +/// note In OAuth2 a "scope" is just a string that declares a specific permission required. @@ -72,7 +72,7 @@ If you need to enforce it, use `OAuth2PasswordRequestFormStrict` instead of `OAu * An optional `client_id` (we don't need it for our example). * An optional `client_secret` (we don't need it for our example). -/// info +/// note The `OAuth2PasswordRequestForm` is not a special class for **FastAPI** as is `OAuth2PasswordBearer`. @@ -144,7 +144,7 @@ UserInDB( ) ``` -/// info +/// note For a more complete explanation of `**user_dict` check back in [the documentation for **Extra Models**](../extra-models.md#about-user-in-dict). @@ -196,7 +196,7 @@ So, in our endpoint, we will only get a user if the user exists, was correctly a {* ../../docs_src/security/tutorial003_an_py310.py hl[58:66,69:74,94] *} -/// info +/// note The additional header `WWW-Authenticate` with value `Bearer` we are returning here is also part of the spec. diff --git a/docs/en/docs/tutorial/server-sent-events.md b/docs/en/docs/tutorial/server-sent-events.md index d264f8536..bbac05bd6 100644 --- a/docs/en/docs/tutorial/server-sent-events.md +++ b/docs/en/docs/tutorial/server-sent-events.md @@ -4,7 +4,7 @@ You can stream data to the client using **Server-Sent Events** (SSE). This is similar to [Stream JSON Lines](stream-json-lines.md), but uses the `text/event-stream` format, which is supported natively by browsers with the [`EventSource` API](https://developer.mozilla.org/en-US/docs/Web/API/EventSource). -/// info +/// note Added in FastAPI 0.135.0. diff --git a/docs/en/docs/tutorial/stream-json-lines.md b/docs/en/docs/tutorial/stream-json-lines.md index 300663636..ea1b781a7 100644 --- a/docs/en/docs/tutorial/stream-json-lines.md +++ b/docs/en/docs/tutorial/stream-json-lines.md @@ -2,7 +2,7 @@ You could have a sequence of data that you would like to send in a "**stream**", you could do it with **JSON Lines**. -/// info +/// note Added in FastAPI 0.134.0. @@ -48,7 +48,7 @@ A response would have a content type of `application/jsonl` (instead of `applica It's very similar to a JSON array (equivalent of a Python list), but instead of being wrapped in `[]` and having `,` between the items, it has **one JSON object per line**, they are separated by a new line character. -/// info +/// note The important point is that your app will be able to produce each line in turn, while the client consumes the previous lines. diff --git a/docs/en/docs/tutorial/testing.md b/docs/en/docs/tutorial/testing.md index 5b8fbba07..72f849f4b 100644 --- a/docs/en/docs/tutorial/testing.md +++ b/docs/en/docs/tutorial/testing.md @@ -8,7 +8,7 @@ With it, you can use [pytest](https://docs.pytest.org/) directly with **FastAPI* ## Using `TestClient` { #using-testclient } -/// info +/// note To use `TestClient`, first install [`httpx`](https://www.python-httpx.org). @@ -144,7 +144,7 @@ E.g.: For more information about how to pass data to the backend (using `httpx` or the `TestClient`) check the [HTTPX documentation](https://www.python-httpx.org). -/// info +/// note Note that the `TestClient` receives data that can be converted to JSON, not Pydantic models. diff --git a/docs/en/docs/virtual-environments.md b/docs/en/docs/virtual-environments.md index 1035013a0..119a6926a 100644 --- a/docs/en/docs/virtual-environments.md +++ b/docs/en/docs/virtual-environments.md @@ -2,7 +2,7 @@ When you work in Python projects you probably should use a **virtual environment** (or a similar mechanism) to isolate the packages you install for each project. -/// info +/// note If you already know about virtual environments, how to create them and use them, you might want to skip this section. 🤓 @@ -18,7 +18,7 @@ A **virtual environment** is a directory with some files in it. /// -/// info +/// note This page will teach you how to use **virtual environments** and how they work. diff --git a/docs/en/mkdocs.yml b/docs/en/mkdocs.yml index 461419498..bb67bca91 100644 --- a/docs/en/mkdocs.yml +++ b/docs/en/mkdocs.yml @@ -290,7 +290,10 @@ markdown_extensions: format: !!python/name:pymdownx.superfences.fence_code_format '' pymdownx.tilde: null pymdownx.blocks.admonition: + # TODO: remove types section (with custom types) once translations are migrated to + # not use custom types too types: + # Default types - note - attention - caution @@ -299,6 +302,7 @@ markdown_extensions: - tip - hint - warning + # Custom types - info - check pymdownx.blocks.details: null From e3844f1972e35c73545a9df0a3d3ced316367363 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Mon, 18 May 2026 11:55:46 +0000 Subject: [PATCH 081/462] =?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 a52aede85..470015347 100644 --- a/docs/en/docs/release-notes.md +++ b/docs/en/docs/release-notes.md @@ -9,6 +9,7 @@ hide: ### Docs +* 📝 Update docs, simplify usage of admonitions, only default ones. PR [#15553](https://github.com/fastapi/fastapi/pull/15553) by [@tiangolo](https://github.com/tiangolo). * 📝 Fix image URLs in `index.md`. PR [#15534](https://github.com/fastapi/fastapi/pull/15534) by [@YuriiMotov](https://github.com/YuriiMotov). * ✏️ Fix Azkaban spelling typo in `virtual-environments.md‎`. PR [#15463](https://github.com/fastapi/fastapi/pull/15463) by [@isaacbernat](https://github.com/isaacbernat). * 💄 Improve layout and styling. PR [#15462](https://github.com/fastapi/fastapi/pull/15462) by [@alejsdev](https://github.com/alejsdev). From 5cfd983e1ddf5662eee01bcfedcbb9170d24f238 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebasti=C3=A1n=20Ram=C3=ADrez?= Date: Mon, 18 May 2026 17:00:20 +0200 Subject: [PATCH 082/462] =?UTF-8?q?=F0=9F=8C=90=20Update=20translations=20?= =?UTF-8?q?for=20ko=20(update-outdated)=20(#15525)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: github-actions[bot] Co-authored-by: Yurii Motov <109919500+YuriiMotov@users.noreply.github.com> --- docs/ko/docs/advanced/generate-clients.md | 1 - docs/ko/docs/index.md | 91 ++++++++++++++++------- docs/ko/docs/virtual-environments.md | 42 +++++------ 3 files changed, 84 insertions(+), 50 deletions(-) diff --git a/docs/ko/docs/advanced/generate-clients.md b/docs/ko/docs/advanced/generate-clients.md index bf29e52e9..1c2e32377 100644 --- a/docs/ko/docs/advanced/generate-clients.md +++ b/docs/ko/docs/advanced/generate-clients.md @@ -30,7 +30,6 @@ FastAPI는 **OpenAPI 3.1** 사양을 자동으로 생성하므로, 사용하는 예를 들어 다음을 사용해 볼 수 있습니다: -* [Speakeasy](https://speakeasy.com/editor?utm_source=fastapi+repo&utm_medium=github+sponsorship) * [Stainless](https://www.stainless.com/?utm_source=fastapi&utm_medium=referral) * [liblab](https://developers.liblab.com/tutorials/sdk-for-fastapi?utm_source=fastapi) diff --git a/docs/ko/docs/index.md b/docs/ko/docs/index.md index 91d27fcee..719fae821 100644 --- a/docs/ko/docs/index.md +++ b/docs/ko/docs/index.md @@ -54,18 +54,27 @@ FastAPI는 현대적이고, 빠르며(고성능), 파이썬 표준 타입 힌트 ### 키스톤 스폰서 { #keystone-sponsor } +
{% for sponsor in sponsors.keystone -%} - +{{ sponsor.title }} {% endfor -%} +
-### 골드 및 실버 스폰서 { #gold-and-silver-sponsors } +### 골드 스폰서 { #gold-sponsors } +
{% for sponsor in sponsors.gold -%} - +{{ sponsor.title }} {% endfor -%} -{%- for sponsor in sponsors.silver -%} - +
+ +### 실버 스폰서 { #silver-sponsors } + +
+{% for sponsor in sponsors.silver -%} +{{ sponsor.title }} {% endfor %} +
@@ -73,55 +82,81 @@ FastAPI는 현대적이고, 빠르며(고성능), 파이썬 표준 타입 힌트 ## 의견들 { #opinions } -"_[...] 저는 요즘 **FastAPI**를 많이 사용하고 있습니다. [...] 사실 우리 팀의 **마이크로소프트 ML 서비스** 전부를 바꿀 계획입니다. 그중 일부는 핵심 **Windows**와 몇몇의 **Office** 제품들이 통합되고 있습니다._" + +
+
+ + + + +
+ +
+
"저는 요즘 FastAPI를 많이 사용하고 있습니다. 우리 팀의 모든 마이크로소프트 ML 서비스에 사용할 계획입니다. 그중 일부는 핵심 Windows 제품과 일부 Office 제품에 통합되고 있습니다."
+
— Kabir Khan, Microsoft (ref)
+
+ + + +
+ -
Kabir Khan - 마이크로소프트 (ref)
+
---- - -"_**FastAPI** 라이브러리를 채택하여 **예측**을 얻기 위해 쿼리를 실행 할 수 있는 **REST** 서버를 생성했습니다. [Ludwig을 위해]_" +"_[...] 저는 요즘 **FastAPI**를 많이 사용하고 있습니다. [...] 사실 우리 팀의 **마이크로소프트 ML 서비스** 전부를 바꿀 계획입니다. 그중 일부는 핵심 **Windows**와 몇몇의 **Office** 제품들이 통합되고 있습니다._" -
Piero Molino, Yaroslav Dudin 그리고 Sai Sumanth Miryala - 우버 (ref)
+
Kabir Khan - Microsoft (ref)
--- -"_**Netflix**는 우리의 오픈 소스 배포판인 **위기 관리** 오케스트레이션 프레임워크를 발표할 수 있어 기쁩니다: 바로 **Dispatch**입니다! [**FastAPI**로 빌드]_" +"_**FastAPI** 라이브러리를 채택하여 **예측**을 얻기 위해 쿼리를 실행할 수 있는 **REST** 서버를 생성했습니다. [Ludwig을 위해]_" -
Kevin Glisson, Marc Vilanova, Forest Monsen - 넷플릭스 (ref)
+
Piero Molino, Yaroslav Dudin, and Sai Sumanth Miryala - Uber (ref)
--- -"_**FastAPI**가 너무 좋아서 구름 위를 걷는듯 합니다. 정말 즐겁습니다!_" +"_**Netflix**는 우리의 오픈 소스 배포판인 **위기 관리** 오케스트레이션 프레임워크를 발표할 수 있어 기쁩니다: 바로 **Dispatch**입니다! [**FastAPI**로 빌드]_" -
Brian Okken - [Python Bytes](https://pythonbytes.fm/episodes/show/123/time-to-right-the-py-wrongs?time_in_sec=855) podcast host (ref)
+
Kevin Glisson, Marc Vilanova, Forest Monsen - Netflix (ref)
--- -"_솔직히, 당신이 만든 것은 매우 견고하고 세련되어 보입니다. 여러 면에서 **Hug**가 이렇게 되었으면 합니다 - 그걸 만든 누군가를 보는 것은 많은 영감을 줍니다._" +"_프로덕션 Python API를 만들고자 한다면, 저는 **FastAPI**를 강력히 추천합니다. **아름답게 설계**되었고, **사용이 간단**하며, **확장성이 매우 뛰어나** 우리의 API 우선 개발 전략에서 **핵심 구성 요소**가 되었습니다._" -
Timothy Crosley - [Hug](https://github.com/hugapi/hug) 제작자 (ref)
+
Deon Pillsbury - Cisco (ref)
--- -"_REST API를 만들기 위해 **현대적인 프레임워크**를 찾고 있다면 **FastAPI**를 확인해 보십시오. [...] 빠르고, 쓰기 쉽고, 배우기도 쉽습니다 [...]_" - -"_우리 **API**를 **FastAPI**로 바꿨습니다 [...] 아마 여러분도 좋아하실 것입니다 [...]_" - -
Ines Montani - Matthew Honnibal - [Explosion AI](https://explosion.ai) 설립자 - [spaCy](https://spacy.io) 제작자 (ref) - (ref)
+
---- +## FastAPI Conf { #fastapi-conf } -"_프로덕션 Python API를 만들고자 한다면, 저는 **FastAPI**를 강력히 추천합니다. **아름답게 설계**되었고, **사용이 간단**하며, **확장성이 매우 뛰어나**고, 우리의 API 우선 개발 전략에서 **핵심 구성 요소**가 되었으며 Virtual TAC Engineer 같은 많은 자동화와 서비스를 이끌고 있습니다._" +[**FastAPI Conf '26**](https://fastapiconf.com)은 **2026년 10월 28일**, **네덜란드 암스테르담**에서 열립니다. FastAPI에 관한 모든 것, 바로 출처에서. 🎤 -
Deon Pillsbury - Cisco (ref)
- ---- +FastAPI Conf '26 - October 28, 2026 - Amsterdam, NL ## FastAPI 미니 다큐멘터리 { #fastapi-mini-documentary } 2025년 말에 공개된 [FastAPI 미니 다큐멘터리](https://www.youtube.com/watch?v=mpR8ngthqiE)가 있습니다. 온라인에서 시청할 수 있습니다: -FastAPI Mini Documentary +FastAPI Mini Documentary ## **Typer**, CLI를 위한 FastAPI { #typer-the-fastapi-of-clis } diff --git a/docs/ko/docs/virtual-environments.md b/docs/ko/docs/virtual-environments.md index 7c2a59f81..d75ee8017 100644 --- a/docs/ko/docs/virtual-environments.md +++ b/docs/ko/docs/virtual-environments.md @@ -2,13 +2,13 @@ Python 프로젝트를 작업할 때는 **가상 환경**(또는 이와 유사한 메커니즘)을 사용해 각 프로젝트마다 설치하는 패키지를 분리하는 것이 좋습니다. -/// info +/// note | 참고 이미 가상 환경에 대해 알고 있고, 어떻게 생성하고 사용하는지도 알고 있다면, 이 섹션은 건너뛰어도 괜찮습니다. 🤓 /// -/// tip +/// tip | 팁 **가상 환경**은 **환경 변수**와 다릅니다. @@ -18,7 +18,7 @@ Python 프로젝트를 작업할 때는 **가상 환경**(또는 이와 유사 /// -/// info +/// note | 참고 이 페이지에서는 **가상 환경**을 사용하는 방법과 작동 방식을 알려드립니다. @@ -55,7 +55,7 @@ $ cd awesome-project Python 프로젝트를 **처음 시작할 때**, 가상 환경을 **프로젝트 내부**에 생성하세요. -/// tip +/// tip | 팁 이 작업은 **프로젝트당 한 번만** 하면 되며, 작업할 때마다 할 필요는 없습니다. @@ -96,7 +96,7 @@ $ uv venv
-/// tip +/// tip | 팁 기본적으로 `uv`는 `.venv`라는 디렉터리에 가상 환경을 생성합니다. @@ -118,7 +118,7 @@ $ uv venv 이후 실행하는 Python 명령어와 설치하는 패키지가 새 가상 환경을 사용하도록, 새 가상 환경을 활성화하세요. -/// tip +/// tip | 팁 프로젝트 작업을 위해 **새 터미널 세션**을 시작할 때마다 **매번** 이 작업을 하세요. @@ -162,7 +162,7 @@ $ source .venv/Scripts/activate //// -/// tip +/// tip | 팁 해당 환경에 **새 패키지**를 설치할 때마다, 환경을 다시 **활성화**하세요. @@ -174,7 +174,7 @@ $ source .venv/Scripts/activate 가상 환경이 활성화되어 있는지(이전 명령어가 작동했는지) 확인합니다. -/// tip +/// tip | 팁 이 단계는 **선택 사항**이지만, 모든 것이 예상대로 작동하고 있는지, 그리고 의도한 가상 환경을 사용하고 있는지 **확인**하는 좋은 방법입니다. @@ -214,7 +214,7 @@ C:\Users\user\code\awesome-project\.venv\Scripts\python ## `pip` 업그레이드 { #upgrade-pip } -/// tip +/// tip | 팁 [`uv`](https://github.com/astral-sh/uv)를 사용한다면, `pip` 대신 `uv`로 설치하게 되므로 `pip`을 업그레이드할 필요가 없습니다. 😎 @@ -224,7 +224,7 @@ C:\Users\user\code\awesome-project\.venv\Scripts\python 패키지 설치 중 발생하는 다양한 특이한 오류는 먼저 `pip`를 업그레이드하는 것만으로 해결되는 경우가 많습니다. -/// tip +/// tip | 팁 보통 이 작업은 가상 환경을 만든 직후 **한 번만** 하면 됩니다. @@ -242,7 +242,7 @@ $ python -m pip install --upgrade pip -/// tip +/// tip | 팁 때로는 pip를 업그레이드하려고 할 때 **`No module named pip`** 오류가 발생할 수 있습니다. @@ -266,13 +266,13 @@ $ python -m ensurepip --upgrade **Git**을 사용하고 있다면(사용하는 것이 좋습니다), `.venv`의 모든 내용을 Git에서 제외하도록 `.gitignore` 파일을 추가하세요. -/// tip +/// tip | 팁 [`uv`](https://github.com/astral-sh/uv)로 가상 환경을 만들었다면, 이미 자동으로 처리되어 있으므로 이 단계는 건너뛰어도 됩니다. 😎 /// -/// tip +/// tip | 팁 가상 환경을 만든 직후 **한 번만** 하면 됩니다. @@ -306,7 +306,7 @@ $ echo "*" > .venv/.gitignore 환경을 활성화한 뒤, 그 안에 패키지를 설치할 수 있습니다. -/// tip +/// tip | 팁 프로젝트에 필요한 패키지를 설치하거나 업그레이드할 때는 **한 번**만 하면 됩니다. @@ -318,7 +318,7 @@ $ echo "*" > .venv/.gitignore 급하게 작업 중이고 프로젝트의 패키지 요구사항을 선언하는 파일을 사용하고 싶지 않다면, 패키지를 직접 설치할 수 있습니다. -/// tip +/// tip | 팁 프로그램에 필요한 패키지와 버전을 파일(예: `requirements.txt` 또는 `pyproject.toml`)에 적어두는 것은 (매우) 좋은 생각입니다. @@ -419,7 +419,7 @@ Hello World * [VS Code](https://code.visualstudio.com/docs/python/environments#_select-and-activate-an-environment) * [PyCharm](https://www.jetbrains.com/help/pycharm/creating-virtual-environment.html) -/// tip +/// tip | 팁 보통 이 설정은 가상 환경을 만들 때 **한 번만** 하면 됩니다. @@ -445,7 +445,7 @@ $ deactivate -/// tip +/// tip | 팁 위의 내용이 무엇인지 더 이해하고 싶으신가요? @@ -536,7 +536,7 @@ flowchart LR end ``` -/// tip +/// tip | 팁 Python 패키지에서는 **새 버전**에서 **호환성을 깨뜨리는 변경(breaking changes)**을 **피하려고** 최선을 다하는 것이 매우 일반적이지만, 안전을 위해 더 최신 버전은 의도적으로 설치하고, 테스트를 실행해 모든 것이 올바르게 작동하는지 확인할 수 있을 때 설치하는 것이 좋습니다. @@ -643,7 +643,7 @@ $ source .venv/Scripts/activate 그 변수 중 하나가 `PATH` 변수입니다. -/// tip +/// tip | 팁 `PATH` 환경 변수에 대해 더 알아보려면 [환경 변수](environment-variables.md#path-environment-variable) 섹션을 참고하세요. @@ -776,7 +776,7 @@ Linux와 macOS에서는 `which`, Windows PowerShell에서는 `Get-Command`를 따라서 올바른 가상 환경에 있는지 확인할 수 있습니다. -/// tip +/// tip | 팁 가상 환경을 하나 활성화해서 Python을 사용한 다음, **다른 프로젝트로 이동**하기 쉽습니다. @@ -819,7 +819,7 @@ Traceback (most recent call last): -하지만 가상 환경을 비활성화하고 `prisoner-of-askaban`에 대한 새 가상 환경을 활성화하면, `python`을 실행할 때 `prisoner-of-azkaban`의 가상 환경에 있는 Python을 사용하게 됩니다. +하지만 가상 환경을 비활성화하고 `prisoner-of-azkaban`에 대한 새 가상 환경을 활성화하면, `python`을 실행할 때 `prisoner-of-azkaban`의 가상 환경에 있는 Python을 사용하게 됩니다.
From 1f48fb42fcd91d93cef8196d9fa343e80b516d04 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Mon, 18 May 2026 15:00:52 +0000 Subject: [PATCH 083/462] =?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 470015347..77a1e5cf3 100644 --- a/docs/en/docs/release-notes.md +++ b/docs/en/docs/release-notes.md @@ -18,6 +18,7 @@ hide: ### Translations +* 🌐 Update translations for ko (update-outdated). PR [#15525](https://github.com/fastapi/fastapi/pull/15525) by [@tiangolo](https://github.com/tiangolo). * 🌐 Update translations for zh-hant (update-outdated). PR [#15524](https://github.com/fastapi/fastapi/pull/15524) by [@tiangolo](https://github.com/tiangolo). * 🌐 Update translations for fr (update-outdated). PR [#15522](https://github.com/fastapi/fastapi/pull/15522) by [@tiangolo](https://github.com/tiangolo). * 🌐 Update translations for es (update-outdated). PR [#15523](https://github.com/fastapi/fastapi/pull/15523) by [@tiangolo](https://github.com/tiangolo). From f3963927ec830dfc1081a1bf27f5955ebefbc60c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebasti=C3=A1n=20Ram=C3=ADrez?= Date: Mon, 18 May 2026 17:06:50 +0200 Subject: [PATCH 084/462] =?UTF-8?q?=F0=9F=8C=90=20Update=20translations=20?= =?UTF-8?q?for=20tr=20(update-outdated)=20(#15526)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: github-actions[bot] Co-authored-by: Yurii Motov <109919500+YuriiMotov@users.noreply.github.com> Co-authored-by: Yurii Motov --- docs/tr/docs/advanced/generate-clients.md | 1 - docs/tr/docs/index.md | 85 ++++++++++++++++------- docs/tr/docs/virtual-environments.md | 26 +++---- 3 files changed, 73 insertions(+), 39 deletions(-) diff --git a/docs/tr/docs/advanced/generate-clients.md b/docs/tr/docs/advanced/generate-clients.md index 94d007404..80b5f6bbb 100644 --- a/docs/tr/docs/advanced/generate-clients.md +++ b/docs/tr/docs/advanced/generate-clients.md @@ -30,7 +30,6 @@ Sponsor olmaları aynı zamanda FastAPI **topluluğuna** (size) güçlü bir ba Örneğin şunları deneyebilirsiniz: -* [Speakeasy](https://speakeasy.com/editor?utm_source=fastapi+repo&utm_medium=github+sponsorship) * [Stainless](https://www.stainless.com/?utm_source=fastapi&utm_medium=referral) * [liblab](https://developers.liblab.com/tutorials/sdk-for-fastapi?utm_source=fastapi) diff --git a/docs/tr/docs/index.md b/docs/tr/docs/index.md index d2b24002f..4ad59fa0a 100644 --- a/docs/tr/docs/index.md +++ b/docs/tr/docs/index.md @@ -54,18 +54,27 @@ Temel özellikleri şunlardır: ### Keystone Sponsor { #keystone-sponsor } +
{% for sponsor in sponsors.keystone -%} - +{{ sponsor.title }} {% endfor -%} +
-### Gold and Silver Sponsors { #gold-and-silver-sponsors } +### Gold Sponsorlar { #gold-sponsors } +
{% for sponsor in sponsors.gold -%} - +{{ sponsor.title }} {% endfor -%} -{%- for sponsor in sponsors.silver -%} - +
+ +### Silver Sponsorlar { #silver-sponsors } + +
+{% for sponsor in sponsors.silver -%} +{{ sponsor.title }} {% endfor %} +
@@ -73,13 +82,51 @@ Temel özellikleri şunlardır: ## Görüşler { #opinions } + +
+
+ + + + +
+ +
+
"Bugünlerde FastAPI'ı çok fazla kullanıyorum. Aslında ekibimin tamamındaki Microsoft'taki ML servisleri için kullanmayı planlıyorum. Bunların bazıları çekirdek Windows ürününe ve bazıları da Office ürünlerine entegre ediliyor."
+
— Kabir Khan, Microsoft (ref)
+
+ + + +
+ + +
+ "_[...] Bugünlerde **FastAPI**'ı çok fazla kullanıyorum. [...] Aslında bunu ekibimin **Microsoft'taki ML servislerinin** tamamında kullanmayı planlıyorum. Bunlardan bazıları ana **Windows** ürününe ve bazı **Office** ürünlerine entegre ediliyor._"
Kabir Khan - Microsoft (ref)
--- -"_**predictions** almak için sorgulanabilecek bir **REST** server oluşturmak amacıyla **FastAPI** kütüphanesini benimsedik. [Ludwig için]_" +"_**FastAPI** kütüphanesini, **predictions** almak için sorgulanabilecek bir **REST** server oluşturmak amacıyla benimsedik. [Ludwig için]_"
Piero Molino, Yaroslav Dudin, and Sai Sumanth Miryala - Uber (ref)
@@ -91,37 +138,25 @@ Temel özellikleri şunlardır: --- -"_**FastAPI** için ayın üzerindeymişcesine heyecanlıyım. Çok eğlenceli!_" - -
Brian Okken - [Python Bytes](https://pythonbytes.fm/episodes/show/123/time-to-right-the-py-wrongs?time_in_sec=855) podcast host (ref)
- ---- - -"_Dürüst olmak gerekirse, inşa ettiğiniz şey gerçekten sağlam ve profesyonel görünüyor. Birçok açıdan, **Hug**'ın olmasını istediğim şey tam da bu - böyle bir şeyi inşa eden birini görmek gerçekten ilham verici._" +"_Production'da Python API geliştirmek isteyen herkese **FastAPI**'ı şiddetle tavsiye ederim. **Harika tasarlanmış**, **kullanımı kolay** ve **yüksek ölçeklenebilir**; API-first geliştirme stratejimizin **kilit bir bileşeni** haline geldi ve Virtual TAC Engineer gibi birçok otomasyon ve servise güç veriyor._" -
Timothy Crosley - [Hug](https://github.com/hugapi/hug) yaratıcısı (ref)
+
Deon Pillsbury - Cisco (ref)
--- -"_REST API'lar geliştirmek için **modern bir framework** öğrenmek istiyorsanız, **FastAPI**'a bir göz atın [...] Hızlı, kullanımı ve öğrenmesi kolay [...]_" - -"_**API**'larımız için **FastAPI**'a geçtik [...] Bence hoşunuza gidecek [...]_" - -
Ines Montani - Matthew Honnibal - [Explosion AI](https://explosion.ai) kurucuları - [spaCy](https://spacy.io) yaratıcıları (ref) - (ref)
- ---- +
-"_Production'da Python API geliştirmek isteyen herkese **FastAPI**'ı şiddetle tavsiye ederim. **Harika tasarlanmış**, **kullanımı kolay** ve **yüksek ölçeklenebilir**; API-first geliştirme stratejimizin **kilit bir bileşeni** haline geldi ve Virtual TAC Engineer gibi birçok otomasyon ve servise güç veriyor._" +## FastAPI Conf { #fastapi-conf } -
Deon Pillsbury - Cisco (ref)
+[**FastAPI Conf '26**](https://fastapiconf.com) **28 Ekim 2026**'da **Amsterdam, NL**'de gerçekleşiyor. Kaynağından, bütünüyle FastAPI. 🎤 ---- +FastAPI Conf '26 - 28 Ekim 2026 - Amsterdam, NL ## FastAPI mini belgeseli { #fastapi-mini-documentary } 2025'in sonunda yayınlanan bir [FastAPI mini belgeseli](https://www.youtube.com/watch?v=mpR8ngthqiE) var, online olarak izleyebilirsiniz: -FastAPI Mini Documentary +FastAPI Mini Documentary ## CLI'ların FastAPI'ı: **Typer** { #typer-the-fastapi-of-clis } diff --git a/docs/tr/docs/virtual-environments.md b/docs/tr/docs/virtual-environments.md index 6df0c9843..4db3b132f 100644 --- a/docs/tr/docs/virtual-environments.md +++ b/docs/tr/docs/virtual-environments.md @@ -2,7 +2,7 @@ Python projeleriyle çalışırken, her proje için kurduğunuz package'leri birbirinden izole etmek adına büyük ihtimalle bir **virtual environment** (veya benzer bir mekanizma) kullanmalısınız. -/// info | Bilgi +/// note | Not Virtual environment'leri, nasıl oluşturulduklarını ve nasıl kullanıldıklarını zaten biliyorsanız bu bölümü atlamak isteyebilirsiniz. 🤓 @@ -18,7 +18,7 @@ Virtual environment'leri, nasıl oluşturulduklarını ve nasıl kullanıldıkla /// -/// info | Bilgi +/// note | Not Bu sayfada **virtual environment**'leri nasıl kullanacağınızı ve nasıl çalıştıklarını öğreneceksiniz. @@ -37,15 +37,15 @@ Sonra bunun içinde her proje için ayrı bir klasör oluştururum.
```console -// Go to the home directory +// Gelelim home dizinine $ cd -// Create a directory for all your code projects +// Tüm kod projeleriniz için bir klasör oluşturun $ mkdir code -// Enter into that code directory +// Bu code klasörüne girin $ cd code -// Create a directory for this project +// Bu proje için bir klasör oluşturun $ mkdir awesome-project -// Enter into that project directory +// Proje klasörüne girin $ cd awesome-project ``` @@ -555,7 +555,7 @@ Bu klasörlerin bir kısmı, kurduğunuz tüm package'leri barındırmaktan soru
```console -// Don't run this now, it's just an example 🤓 +// Bunu şimdi çalıştırmayın, bu sadece bir örnek 🤓 $ pip install "fastapi[standard]" ---> 100% ``` @@ -809,7 +809,7 @@ $ cd ~/code/prisoner-of-azkaban $ python main.py -// Error importing sirius, it's not installed 😱 +// sirius import edilirken hata, kurulu değil 😱 Traceback (most recent call last): File "main.py", line 1, in import sirius @@ -817,20 +817,20 @@ Traceback (most recent call last):
-Ama virtual environment'i deactivate edip `prisoner-of-askaban` için yeni olanı aktive ederseniz, `python` çalıştırdığınızda `prisoner-of-azkaban` içindeki virtual environment'dan gelen Python kullanılır. +Ama virtual environment'i deactivate edip `prisoner-of-azkaban` için yeni olanı aktive ederseniz, `python` çalıştırdığınızda `prisoner-of-azkaban` içindeki virtual environment'dan gelen Python kullanılır.
```console $ cd ~/code/prisoner-of-azkaban -// You don't need to be in the old directory to deactivate, you can do it wherever you are, even after going to the other project 😎 +// Deactivate etmek için eski klasörde olmanız gerekmez; nerede olursanız olun, hatta diğer projeye geçtikten sonra bile yapabilirsiniz 😎 $ deactivate -// Activate the virtual environment in prisoner-of-azkaban/.venv 🚀 +// prisoner-of-azkaban/.venv içindeki virtual environment'i aktive edin 🚀 $ source .venv/bin/activate -// Now when you run python, it will find the package sirius installed in this virtual environment ✨ +// Artık python çalıştırdığınızda, bu virtual environment'e kurulu olan sirius package'ini bulacak ✨ $ python main.py I solemnly swear 🐺 From 3ab6f1b31df08d9a7af29ff979f7c3775e5a6c40 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Mon, 18 May 2026 15:07:31 +0000 Subject: [PATCH 085/462] =?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 77a1e5cf3..88e4dcf09 100644 --- a/docs/en/docs/release-notes.md +++ b/docs/en/docs/release-notes.md @@ -18,6 +18,7 @@ hide: ### Translations +* 🌐 Update translations for tr (update-outdated). PR [#15526](https://github.com/fastapi/fastapi/pull/15526) by [@tiangolo](https://github.com/tiangolo). * 🌐 Update translations for ko (update-outdated). PR [#15525](https://github.com/fastapi/fastapi/pull/15525) by [@tiangolo](https://github.com/tiangolo). * 🌐 Update translations for zh-hant (update-outdated). PR [#15524](https://github.com/fastapi/fastapi/pull/15524) by [@tiangolo](https://github.com/tiangolo). * 🌐 Update translations for fr (update-outdated). PR [#15522](https://github.com/fastapi/fastapi/pull/15522) by [@tiangolo](https://github.com/tiangolo). From f343905934d99411159780033bc83f028d20ae69 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebasti=C3=A1n=20Ram=C3=ADrez?= Date: Mon, 18 May 2026 17:13:52 +0200 Subject: [PATCH 086/462] =?UTF-8?q?=F0=9F=8C=90=20Update=20translations=20?= =?UTF-8?q?for=20de=20(update-outdated)=20(#15527)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: github-actions[bot] Co-authored-by: Yurii Motov <109919500+YuriiMotov@users.noreply.github.com> Co-authored-by: Yurii Motov --- docs/de/docs/advanced/generate-clients.md | 1 - docs/de/docs/index.md | 85 ++++++++++++++++------- docs/de/docs/virtual-environments.md | 6 +- 3 files changed, 63 insertions(+), 29 deletions(-) diff --git a/docs/de/docs/advanced/generate-clients.md b/docs/de/docs/advanced/generate-clients.md index 12ba4072c..4eab5bcb6 100644 --- a/docs/de/docs/advanced/generate-clients.md +++ b/docs/de/docs/advanced/generate-clients.md @@ -30,7 +30,6 @@ Ihr Sponsoring zeigt auch ein starkes Engagement für die FastAPI-**Community** Zum Beispiel könnten Sie ausprobieren: -* [Speakeasy](https://speakeasy.com/editor?utm_source=fastapi+repo&utm_medium=github+sponsorship) * [Stainless](https://www.stainless.com/?utm_source=fastapi&utm_medium=referral) * [liblab](https://developers.liblab.com/tutorials/sdk-for-fastapi?utm_source=fastapi) diff --git a/docs/de/docs/index.md b/docs/de/docs/index.md index d2c282959..c71391432 100644 --- a/docs/de/docs/index.md +++ b/docs/de/docs/index.md @@ -54,18 +54,27 @@ Seine Schlüssel-Merkmale sind: ### Keystone-Sponsor { #keystone-sponsor } +
{% for sponsor in sponsors.keystone -%} - +{{ sponsor.title }} {% endfor -%} +
-### Gold- und Silber-Sponsoren { #gold-and-silver-sponsors } +### Gold-Sponsoren { #gold-sponsors } +
{% for sponsor in sponsors.gold -%} - +{{ sponsor.title }} {% endfor -%} -{%- for sponsor in sponsors.silver -%} - +
+ +### Silber-Sponsoren { #silver-sponsors } + +
+{% for sponsor in sponsors.silver -%} +{{ sponsor.title }} {% endfor %} +
@@ -73,6 +82,44 @@ Seine Schlüssel-Merkmale sind: ## Meinungen { #opinions } + +
+
+ + + + +
+ +
+
„Ich verwende FastAPI heutzutage sehr oft. Ich plane tatsächlich, es für alle ML-Services meines Teams bei Microsoft zu verwenden. Einige davon werden in das Kernprodukt Windows und einige Office-Produkte integriert.“
+
— Kabir Khan, Microsoft (Ref.)
+
+ + + +
+ + +
+ „_[...] Ich verwende **FastAPI** heutzutage sehr oft. [...] Ich habe tatsächlich vor, es für alle **ML-Services meines Teams bei Microsoft** zu verwenden. Einige davon werden in das Kernprodukt **Windows** und einige **Office**-Produkte integriert._“
Kabir Khan – Microsoft (Ref.)
@@ -85,43 +132,31 @@ Seine Schlüssel-Merkmale sind: --- -„_**Netflix** freut sich, die Open-Source-Veröffentlichung unseres **Krisenmanagement**-Orchestrierung-Frameworks bekannt zu geben: **Dispatch**! [erstellt mit **FastAPI**]_“ +„_**Netflix** freut sich, die Open-Source-Veröffentlichung unseres **Krisenmanagement**-Orchestrierungsframeworks bekannt zu geben: **Dispatch**! [erstellt mit **FastAPI**]_“
Kevin Glisson, Marc Vilanova, Forest Monsen – Netflix (Ref.)
--- -„_Ich bin hellauf begeistert von **FastAPI**. Es macht so viel Spaß!_“ - -
Brian Okken – [Python Bytes](https://pythonbytes.fm/episodes/show/123/time-to-right-the-py-wrongs?time_in_sec=855) Podcast-Host (Ref.)
- ---- - -„_Ehrlich, was Du gebaut hast, sieht super solide und poliert aus. In vielerlei Hinsicht ist es so, wie ich **Hug** haben wollte – es ist wirklich inspirierend, jemanden so etwas bauen zu sehen._“ +„_Falls irgendjemand eine Produktions-Python-API erstellen möchte, kann ich **FastAPI** wärmstens empfehlen. Es ist **wunderschön konzipiert**, **einfach zu verwenden** und **hoch skalierbar**; es ist zu einer **Schlüsselkomponente** unserer API-First-Entwicklungsstrategie geworden und treibt viele Automatisierungen und Services an, wie etwa unseren Virtual TAC Engineer._“ -
Timothy Crosley – [Hug](https://github.com/hugapi/hug)-Autor (Ref.)
+
Deon Pillsbury – Cisco (Ref.)
--- -„_Wenn Sie ein **modernes Framework** zum Erstellen von REST-APIs erlernen möchten, schauen Sie sich **FastAPI** an. [...] Es ist schnell, einfach zu verwenden und leicht zu lernen [...]_“ - -„_Wir haben zu **FastAPI** für unsere **APIs** gewechselt [...] Ich denke, es wird Ihnen gefallen [...]_“ - -
Ines Montani – Matthew Honnibal – [Explosion AI](https://explosion.ai)-Gründer – [spaCy](https://spacy.io)-Autoren (Ref.)(Ref.)
- ---- +
-„_Falls irgendjemand eine Produktions-Python-API erstellen möchte, kann ich **FastAPI** wärmstens empfehlen. Es ist **wunderschön konzipiert**, **einfach zu verwenden** und **hoch skalierbar**; es ist zu einer **Schlüsselkomponente** unserer API-First-Entwicklungsstrategie geworden und treibt viele Automatisierungen und Services an, wie etwa unseren Virtual TAC Engineer._“ +## FastAPI Conf { #fastapi-conf } -
Deon Pillsbury – Cisco (Ref.)
+[**FastAPI Conf ’26**](https://fastapiconf.com) findet am **28. Oktober 2026** in **Amsterdam, NL** statt. Alles über FastAPI, direkt von der Quelle. 🎤 ---- +FastAPI Conf ’26 - 28. Oktober 2026 - Amsterdam, NL ## FastAPI Mini-Dokumentarfilm { #fastapi-mini-documentary } Es gibt einen [FastAPI-Mini-Dokumentarfilm](https://www.youtube.com/watch?v=mpR8ngthqiE), veröffentlicht Ende 2025, Sie können ihn online ansehen: -FastAPI Mini-Dokumentarfilm +FastAPI Mini-Dokumentarfilm ## **Typer**, das FastAPI der CLIs { #typer-the-fastapi-of-clis } diff --git a/docs/de/docs/virtual-environments.md b/docs/de/docs/virtual-environments.md index c008ec14c..81d13cc91 100644 --- a/docs/de/docs/virtual-environments.md +++ b/docs/de/docs/virtual-environments.md @@ -2,7 +2,7 @@ Wenn Sie an Python-Projekten arbeiten, sollten Sie wahrscheinlich eine **virtuelle Umgebung** (oder einen ähnlichen Mechanismus) verwenden, um die Packages, die Sie für jedes Projekt installieren, zu isolieren. -/// info | Info +/// note | Hinweis Wenn Sie bereits über virtuelle Umgebungen Bescheid wissen, wie man sie erstellt und verwendet, möchten Sie diesen Abschnitt vielleicht überspringen. 🤓 @@ -18,7 +18,7 @@ Eine **virtuelle Umgebung** ist ein Verzeichnis mit einigen Dateien darin. /// -/// info | Info +/// note | Hinweis Diese Seite wird Ihnen beibringen, wie Sie **virtuelle Umgebungen** verwenden und wie sie funktionieren. @@ -817,7 +817,7 @@ Traceback (most recent call last):
-Wenn Sie jedoch die virtuelle Umgebung deaktivieren und die neue für `prisoner-of-askaban` aktivieren, wird beim Ausführen von `python` das Python aus der virtuellen Umgebung in `prisoner-of-azkaban` verwendet. +Wenn Sie jedoch die virtuelle Umgebung deaktivieren und die neue für `prisoner-of-azkaban` aktivieren, wird beim Ausführen von `python` das Python aus der virtuellen Umgebung in `prisoner-of-azkaban` verwendet.
From bf3668de89f3d6f89de8de30d8de46b8a0523aec Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Mon, 18 May 2026 15:14:32 +0000 Subject: [PATCH 087/462] =?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 88e4dcf09..f51aa42fe 100644 --- a/docs/en/docs/release-notes.md +++ b/docs/en/docs/release-notes.md @@ -18,6 +18,7 @@ hide: ### Translations +* 🌐 Update translations for de (update-outdated). PR [#15527](https://github.com/fastapi/fastapi/pull/15527) by [@tiangolo](https://github.com/tiangolo). * 🌐 Update translations for tr (update-outdated). PR [#15526](https://github.com/fastapi/fastapi/pull/15526) by [@tiangolo](https://github.com/tiangolo). * 🌐 Update translations for ko (update-outdated). PR [#15525](https://github.com/fastapi/fastapi/pull/15525) by [@tiangolo](https://github.com/tiangolo). * 🌐 Update translations for zh-hant (update-outdated). PR [#15524](https://github.com/fastapi/fastapi/pull/15524) by [@tiangolo](https://github.com/tiangolo). From 628ff21528037c768e02f31a0a56669876489692 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebasti=C3=A1n=20Ram=C3=ADrez?= Date: Mon, 18 May 2026 17:15:46 +0200 Subject: [PATCH 088/462] =?UTF-8?q?=F0=9F=8C=90=20Update=20translations=20?= =?UTF-8?q?for=20pt=20(update-outdated)=20(#15528)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: github-actions[bot] Co-authored-by: Yurii Motov <109919500+YuriiMotov@users.noreply.github.com> Co-authored-by: Yurii Motov --- docs/pt/docs/advanced/generate-clients.md | 1 - docs/pt/docs/index.md | 85 ++++++++++++++++------- docs/pt/docs/virtual-environments.md | 6 +- 3 files changed, 63 insertions(+), 29 deletions(-) diff --git a/docs/pt/docs/advanced/generate-clients.md b/docs/pt/docs/advanced/generate-clients.md index 0d31a69af..23d512f76 100644 --- a/docs/pt/docs/advanced/generate-clients.md +++ b/docs/pt/docs/advanced/generate-clients.md @@ -30,7 +30,6 @@ O patrocínio também demonstra um forte compromisso com a **comunidade** FastAP Por exemplo, você pode querer experimentar: -* [Speakeasy](https://speakeasy.com/editor?utm_source=fastapi+repo&utm_medium=github+sponsorship) * [Stainless](https://www.stainless.com/?utm_source=fastapi&utm_medium=referral) * [liblab](https://developers.liblab.com/tutorials/sdk-for-fastapi?utm_source=fastapi) diff --git a/docs/pt/docs/index.md b/docs/pt/docs/index.md index 1679e34ba..a982657d8 100644 --- a/docs/pt/docs/index.md +++ b/docs/pt/docs/index.md @@ -54,18 +54,27 @@ Os recursos chave são: ### Patrocinador Keystone { #keystone-sponsor } +
{% for sponsor in sponsors.keystone -%} - +{{ sponsor.title }} {% endfor -%} +
-### Patrocinadores Ouro e Prata { #gold-and-silver-sponsors } +### Patrocinadores Ouro { #gold-sponsors } +
{% for sponsor in sponsors.gold -%} - +{{ sponsor.title }} {% endfor -%} -{%- for sponsor in sponsors.silver -%} - +
+ +### Patrocinadores Prata { #silver-sponsors } + +
+{% for sponsor in sponsors.silver -%} +{{ sponsor.title }} {% endfor %} +
@@ -73,6 +82,44 @@ Os recursos chave são: ## Opiniões { #opinions } + +
+
+ + + + +
+ +
+
"Estou usando o FastAPI muito esses dias. Estou na verdade planejando utilizá-lo em todos os meus times de serviços ML na Microsoft. Alguns deles estão sendo integrados no produto Windows principal e alguns produtos do Office."
+
— Kabir Khan, Microsoft (ref)
+
+ + + +
+ + +
+ "_[...] Estou usando **FastAPI** muito esses dias. [...] Estou na verdade planejando utilizar ele em todos os times de **serviços ML na Microsoft**. Alguns deles estão sendo integrados no _core_ do produto **Windows** e alguns produtos **Office**._"
Kabir Khan - Microsoft (ref)
@@ -81,7 +128,7 @@ Os recursos chave são: "_Nós adotamos a biblioteca **FastAPI** para iniciar um servidor **REST** que pode ser consultado para obter **previsões**. [para o Ludwig]_" -
Piero Molino, Yaroslav Dudin, e Sai Sumanth Miryala - Uber (ref)
+
Piero Molino, Yaroslav Dudin, and Sai Sumanth Miryala - Uber (ref)
--- @@ -91,37 +138,25 @@ Os recursos chave são: --- -"_Estou muito entusiasmado com o **FastAPI**. É tão divertido!_" - -
Brian Okken - [Python Bytes](https://pythonbytes.fm/episodes/show/123/time-to-right-the-py-wrongs?time_in_sec=855) apresentador do podcast (ref)
- ---- - -"_Honestamente, o que você construiu parece super sólido e refinado. De muitas formas, é o que eu queria que o **Hug** fosse - é realmente inspirador ver alguém construir isso._" +"_Se alguém estiver procurando construir uma API Python para produção, eu recomendaria fortemente o **FastAPI**. Ele é **lindamente projetado**, **simples de usar** e **altamente escalável**, e se tornou um **componente chave** para a nossa estratégia de desenvolvimento API first, impulsionando diversas automações e serviços, como o nosso Virtual TAC Engineer._" -
Timothy Crosley - criador do [Hug](https://github.com/hugapi/hug) (ref)
+
Deon Pillsbury - Cisco (ref)
--- -"_Se você está procurando aprender um **framework moderno** para construir APIs REST, dê uma olhada no **FastAPI** [...] É rápido, fácil de usar e fácil de aprender [...]_" - -"_Nós trocamos nossas **APIs** por **FastAPI** [...] Acredito que você gostará dele [...]_" - -
Ines Montani - Matthew Honnibal - fundadores da [Explosion AI](https://explosion.ai) - criadores da [spaCy](https://spacy.io) (ref) - (ref)
- ---- +
-"_Se alguém estiver procurando construir uma API Python para produção, eu recomendaria fortemente o **FastAPI**. Ele é **lindamente projetado**, **simples de usar** e **altamente escalável**, e se tornou um **componente chave** para a nossa estratégia de desenvolvimento API first, impulsionando diversas automações e serviços, como o nosso Virtual TAC Engineer._" +## FastAPI Conf { #fastapi-conf } -
Deon Pillsbury - Cisco (ref)
+[**FastAPI Conf '26**](https://fastapiconf.com) acontece em **28 de outubro de 2026** em **Amsterdã, NL**. Tudo sobre FastAPI, direto da fonte. 🎤 ---- +FastAPI Conf '26 - October 28, 2026 - Amsterdam, NL ## Mini documentário do FastAPI { #fastapi-mini-documentary } Há um [mini documentário do FastAPI](https://www.youtube.com/watch?v=mpR8ngthqiE) lançado no fim de 2025, você pode assisti-lo online: -FastAPI Mini Documentary +FastAPI Mini Documentary ## **Typer**, o FastAPI das interfaces de linhas de comando { #typer-the-fastapi-of-clis } diff --git a/docs/pt/docs/virtual-environments.md b/docs/pt/docs/virtual-environments.md index cfb86887f..245919608 100644 --- a/docs/pt/docs/virtual-environments.md +++ b/docs/pt/docs/virtual-environments.md @@ -2,7 +2,7 @@ Ao trabalhar em projetos Python, você provavelmente deveria usar um **ambiente virtual** (ou um mecanismo similar) para isolar os pacotes que você instala para cada projeto. -/// info | Informação +/// note | Nota Se você já sabe sobre ambientes virtuais, como criá-los e usá-los, talvez seja melhor pular esta seção. 🤓 @@ -18,7 +18,7 @@ Um **ambiente virtual** é um diretório com alguns arquivos. /// -/// info | Informação +/// note | Nota Esta página lhe ensinará como usar **ambientes virtuais** e como eles funcionam. @@ -819,7 +819,7 @@ Traceback (most recent call last):
-Mas se você desativar o ambiente virtual e ativar o novo para `prisoner-of-askaban`, quando você executar `python`, ele usará o Python do ambiente virtual em `prisoner-of-azkaban`. +Mas se você desativar o ambiente virtual e ativar o novo para `prisoner-of-azkaban`, quando você executar `python`, ele usará o Python do ambiente virtual em `prisoner-of-azkaban`.
From 21697d97945b5b865b4e5f52f63130ce8cd11fa9 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Mon, 18 May 2026 15:19:10 +0000 Subject: [PATCH 089/462] =?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 f51aa42fe..9ecdb7270 100644 --- a/docs/en/docs/release-notes.md +++ b/docs/en/docs/release-notes.md @@ -18,6 +18,7 @@ hide: ### Translations +* 🌐 Update translations for pt (update-outdated). PR [#15528](https://github.com/fastapi/fastapi/pull/15528) by [@tiangolo](https://github.com/tiangolo). * 🌐 Update translations for de (update-outdated). PR [#15527](https://github.com/fastapi/fastapi/pull/15527) by [@tiangolo](https://github.com/tiangolo). * 🌐 Update translations for tr (update-outdated). PR [#15526](https://github.com/fastapi/fastapi/pull/15526) by [@tiangolo](https://github.com/tiangolo). * 🌐 Update translations for ko (update-outdated). PR [#15525](https://github.com/fastapi/fastapi/pull/15525) by [@tiangolo](https://github.com/tiangolo). From 3780ba547260220753ac9156aec7977e23c02511 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebasti=C3=A1n=20Ram=C3=ADrez?= Date: Mon, 18 May 2026 17:21:59 +0200 Subject: [PATCH 090/462] =?UTF-8?q?=F0=9F=8C=90=20Update=20translations=20?= =?UTF-8?q?for=20uk=20(update-outdated)=20(#15529)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: github-actions[bot] Co-authored-by: Yurii Motov <109919500+YuriiMotov@users.noreply.github.com> Co-authored-by: Yurii Motov --- docs/uk/docs/advanced/generate-clients.md | 1 - docs/uk/docs/index.md | 95 ++++++++++++++++------- docs/uk/docs/virtual-environments.md | 6 +- 3 files changed, 68 insertions(+), 34 deletions(-) diff --git a/docs/uk/docs/advanced/generate-clients.md b/docs/uk/docs/advanced/generate-clients.md index 257089c41..d1b7e9c0c 100644 --- a/docs/uk/docs/advanced/generate-clients.md +++ b/docs/uk/docs/advanced/generate-clients.md @@ -30,7 +30,6 @@ FastAPI автоматично генерує специфікації **OpenAPI Наприклад, ви можете спробувати: -* [Speakeasy](https://speakeasy.com/editor?utm_source=fastapi+repo&utm_medium=github+sponsorship) * [Stainless](https://www.stainless.com/?utm_source=fastapi&utm_medium=referral) * [liblab](https://developers.liblab.com/tutorials/sdk-for-fastapi?utm_source=fastapi) diff --git a/docs/uk/docs/index.md b/docs/uk/docs/index.md index 06bf865d9..213cf8db4 100644 --- a/docs/uk/docs/index.md +++ b/docs/uk/docs/index.md @@ -8,7 +8,7 @@ FastAPI

- Фреймворк FastAPI - це висока продуктивність, легко вивчати, швидко писати код, готовий до продакшину + Фреймворк FastAPI - висока продуктивність, легко вивчати, швидко писати код, готовий до продакшну

@@ -43,7 +43,7 @@ FastAPI - це сучасний, швидкий (високопродуктив * **Інтуїтивний**: чудова підтримка редакторами коду. Автодоповнення всюди. Менше часу на налагодження. * **Простий**: спроєктований так, щоб бути простим у використанні та вивченні. Менше часу на читання документації. * **Короткий**: мінімізує дублювання коду. Кілька можливостей з кожного оголошення параметра. Менше помилок. -* **Надійний**: ви отримуєте код, готовий до продакшину. З автоматичною інтерактивною документацією. +* **Надійний**: ви отримуєте код, готовий до продакшну. З автоматичною інтерактивною документацією. * **Заснований на стандартах**: базується на (і повністю сумісний з) відкритими стандартами для API: [OpenAPI](https://github.com/OAI/OpenAPI-Specification) (раніше відомий як Swagger) та [JSON Schema](https://json-schema.org/). * оцінка на основі тестів, проведених внутрішньою командою розробників, що створює продакшн-застосунки. @@ -54,18 +54,27 @@ FastAPI - це сучасний, швидкий (високопродуктив ### Ключовий спонсор { #keystone-sponsor } +

-### Золоті та срібні спонсори { #gold-and-silver-sponsors } +### Золоті спонсори { #gold-sponsors } +
{% for sponsor in sponsors.gold -%} - +{{ sponsor.title }} {% endfor -%} -{%- for sponsor in sponsors.silver -%} - +
+ +### Срібні спонсори { #silver-sponsors } + +
+{% for sponsor in sponsors.silver -%} +{{ sponsor.title }} {% endfor %} +
@@ -73,6 +82,44 @@ FastAPI - це сучасний, швидкий (високопродуктив ## Враження { #opinions } + +
+
+ + + + +
+ +
+
«Я дуже часто використовую FastAPI останнім часом. Я насправді планую використовувати його для всіх ML-сервісів моєї команди в Microsoft. Деякі з них інтегруються до основного продукту Windows і деякі з продуктів Office».
+
— Kabir Khan, Microsoft (ref)
+
+ + + +
+ + +
+ "_[...] I'm using **FastAPI** a ton these days. [...] I'm actually planning to use it for all of my team's **ML services at Microsoft**. Some of them are getting integrated into the core **Windows** product and some **Office** products._"
Kabir Khan - Microsoft (ref)
@@ -91,37 +138,25 @@ FastAPI - це сучасний, швидкий (високопродуктив --- -"_I’m over the moon excited about **FastAPI**. It’s so fun!_" - -
Brian Okken - [Python Bytes](https://pythonbytes.fm/episodes/show/123/time-to-right-the-py-wrongs?time_in_sec=855) podcast host (ref)
- ---- - -"_Honestly, what you've built looks super solid and polished. In many ways, it's what I wanted **Hug** to be - it's really inspiring to see someone build that._" +"_If anyone is looking to build a production Python API, I would highly recommend **FastAPI**. It is **beautifully designed**, **simple to use** and **highly scalable**, it has become a **key component** in our API first development strategy and is driving many automations and services such as our Virtual TAC Engineer._" -
Timothy Crosley - [Hug](https://github.com/hugapi/hug) creator (ref)
+
Deon Pillsbury - Cisco (ref)
--- -"_If you're looking to learn one **modern framework** for building REST APIs, check out **FastAPI** [...] It's fast, easy to use and easy to learn [...]_" - -"_We've switched over to **FastAPI** for our **APIs** [...] I think you'll like it [...]_" - -
Ines Montani - Matthew Honnibal - [Explosion AI](https://explosion.ai) founders - [spaCy](https://spacy.io) creators (ref) - (ref)
- ---- +
-"_If anyone is looking to build a production Python API, I would highly recommend **FastAPI**. It is **beautifully designed**, **simple to use** and **highly scalable**, it has become a **key component** in our API first development strategy and is driving many automations and services such as our Virtual TAC Engineer._" +## Конференція FastAPI { #fastapi-conf } -
Deon Pillsbury - Cisco (ref)
+[**FastAPI Conf '26**](https://fastapiconf.com) відбудеться **28 жовтня 2026 року** в **Амстердамі, Нідерланди**. Усе про FastAPI з першоджерела. 🎤 ---- +FastAPI Conf '26 - October 28, 2026 - Amsterdam, NL ## Міні-документальний фільм про FastAPI { #fastapi-mini-documentary } Наприкінці 2025 року вийшов [міні-документальний фільм про FastAPI](https://www.youtube.com/watch?v=mpR8ngthqiE), ви можете переглянути його онлайн: -FastAPI Mini Documentary +FastAPI Mini Documentary ## **Typer**, FastAPI для CLI { #typer-the-fastapi-of-clis } @@ -280,7 +315,7 @@ INFO: Application startup complete. ## Приклад оновлення { #example-upgrade } -Тепер змініть файл `main.py`, щоб отримувати тіло `PUT`-запиту. +Тепер змініть файл `main.py`, щоб отримувати тіло з `PUT`-запиту. Оголосіть тіло, використовуючи стандартні типи Python, завдяки Pydantic. @@ -322,11 +357,11 @@ def update_item(item_id: int, item: Item): ![Swagger UI](https://fastapi.tiangolo.com/img/index/index-03-swagger-02.png) -* Натисніть кнопку "Try it out", вона дозволяє заповнити параметри та безпосередньо взаємодіяти з API: +* Натисніть кнопку «Try it out», вона дозволяє заповнити параметри та безпосередньо взаємодіяти з API: ![Swagger UI interaction](https://fastapi.tiangolo.com/img/index/index-04-swagger-03.png) -* Потім натисніть кнопку "Execute", інтерфейс користувача зв'яжеться з вашим API, надішле параметри, отримає результати та покаже їх на екрані: +* Потім натисніть кнопку «Execute», інтерфейс користувача зв'яжеться з вашим API, надішле параметри, отримає результати та покаже їх на екрані: ![Swagger UI interaction](https://fastapi.tiangolo.com/img/index/index-05-swagger-04.png) @@ -484,7 +519,7 @@ FastAPI Cloud - основний спонсор і джерело фінансу #### Розгортання в інших хмарних провайдерів { #deploy-to-other-cloud-providers } -FastAPI - open source проект і базується на стандартах. Ви можете розгортати застосунки FastAPI в будь-якому хмарному провайдері, який ви оберете. +FastAPI - open source проєкт і базується на стандартах. Ви можете розгортати застосунки FastAPI в будь-якому хмарному провайдері, який ви оберете. Дотримуйтеся інструкцій вашого хмарного провайдера, щоб розгорнути застосунки FastAPI у нього. 🤓 diff --git a/docs/uk/docs/virtual-environments.md b/docs/uk/docs/virtual-environments.md index d7735b234..26ad6b0cb 100644 --- a/docs/uk/docs/virtual-environments.md +++ b/docs/uk/docs/virtual-environments.md @@ -2,7 +2,7 @@ Коли ви працюєте над проєктами Python, вам, імовірно, слід використовувати віртуальне середовище (або схожий механізм), щоб ізолювати пакети, які ви встановлюєте для кожного проєкту. -/// info | Інформація +/// note | Примітка Якщо ви вже знаєте про віртуальні середовища, як їх створювати та використовувати, можете пропустити цей розділ. 🤓 @@ -18,7 +18,7 @@ /// -/// info | Інформація +/// note | Примітка На цій сторінці ви дізнаєтеся, як використовувати віртуальні середовища і як вони працюють. @@ -817,7 +817,7 @@ Traceback (most recent call last):
-Але якщо ви деактивуєте віртуальне середовище і активуєте нове для `prisoner-of-askaban`, тоді при запуску `python` він використовуватиме Python із віртуального середовища в `prisoner-of-azkaban`. +Але якщо ви деактивуєте віртуальне середовище і активуєте нове для `prisoner-of-azkaban`, тоді при запуску `python` він використовуватиме Python із віртуального середовища в `prisoner-of-azkaban`.
From 626ae1918c7a9cc28fdea5caaded6b218a1034eb Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Mon, 18 May 2026 15:22:32 +0000 Subject: [PATCH 091/462] =?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 9ecdb7270..2aedd35ae 100644 --- a/docs/en/docs/release-notes.md +++ b/docs/en/docs/release-notes.md @@ -18,6 +18,7 @@ hide: ### Translations +* 🌐 Update translations for uk (update-outdated). PR [#15529](https://github.com/fastapi/fastapi/pull/15529) by [@tiangolo](https://github.com/tiangolo). * 🌐 Update translations for pt (update-outdated). PR [#15528](https://github.com/fastapi/fastapi/pull/15528) by [@tiangolo](https://github.com/tiangolo). * 🌐 Update translations for de (update-outdated). PR [#15527](https://github.com/fastapi/fastapi/pull/15527) by [@tiangolo](https://github.com/tiangolo). * 🌐 Update translations for tr (update-outdated). PR [#15526](https://github.com/fastapi/fastapi/pull/15526) by [@tiangolo](https://github.com/tiangolo). From ff6a38a434f49fcea27daa8e32d46fabc29b2679 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebasti=C3=A1n=20Ram=C3=ADrez?= Date: Mon, 18 May 2026 17:39:27 +0200 Subject: [PATCH 092/462] =?UTF-8?q?=F0=9F=8C=90=20Update=20translations=20?= =?UTF-8?q?for=20ja=20(update-outdated)=20(#15530)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: github-actions[bot] Co-authored-by: Yurii Motov <109919500+YuriiMotov@users.noreply.github.com> Co-authored-by: Yurii Motov --- docs/ja/docs/advanced/generate-clients.md | 1 - docs/ja/docs/index.md | 83 ++++++++++++++++------- docs/ja/docs/virtual-environments.md | 17 ++--- 3 files changed, 68 insertions(+), 33 deletions(-) diff --git a/docs/ja/docs/advanced/generate-clients.md b/docs/ja/docs/advanced/generate-clients.md index b3472880e..eee8575f6 100644 --- a/docs/ja/docs/advanced/generate-clients.md +++ b/docs/ja/docs/advanced/generate-clients.md @@ -30,7 +30,6 @@ FastAPI は自動的に **OpenAPI 3.1** の仕様を生成します。したが 例えば、次のようなものがあります: -* [Speakeasy](https://speakeasy.com/editor?utm_source=fastapi+repo&utm_medium=github+sponsorship) * [Stainless](https://www.stainless.com/?utm_source=fastapi&utm_medium=referral) * [liblab](https://developers.liblab.com/tutorials/sdk-for-fastapi?utm_source=fastapi) diff --git a/docs/ja/docs/index.md b/docs/ja/docs/index.md index a8b974198..2068874eb 100644 --- a/docs/ja/docs/index.md +++ b/docs/ja/docs/index.md @@ -54,18 +54,27 @@ FastAPI は、Python の標準である型ヒントに基づいて Python で AP ### Keystone Sponsor { #keystone-sponsor } +
{% for sponsor in sponsors.keystone -%} - +{{ sponsor.title }} {% endfor -%} +
-### Gold and Silver Sponsors { #gold-and-silver-sponsors } +### Gold Sponsors { #gold-sponsors } +
{% for sponsor in sponsors.gold -%} - +{{ sponsor.title }} {% endfor -%} -{%- for sponsor in sponsors.silver -%} - +
+ +### Silver Sponsors { #silver-sponsors } + +
+{% for sponsor in sponsors.silver -%} +{{ sponsor.title }} {% endfor %} +
@@ -73,6 +82,44 @@ FastAPI は、Python の標準である型ヒントに基づいて Python で AP ## 評価 { #opinions } + +
+
+ + + + +
+ +
+
「最近は **FastAPI** をたくさん使っています。実際、私のチームの **Microsoft の ML サービス** 全てで使用する予定です。そのいくつかはコアな **Windows** 製品や **Office** 製品に統合されつつあります。」
+
— Kabir Khan, Microsoft (ref)
+
+ + + +
+ + +
+ "_[...] 最近 **FastAPI** を使っています。 [...] 実際に私のチームの全ての **Microsoft の機械学習サービス** で使用する予定です。 そのうちのいくつかのコアな **Windows** 製品と **Office** 製品に統合されつつあります。_"
Kabir Khan - Microsoft (ref)
@@ -91,37 +138,25 @@ FastAPI は、Python の標準である型ヒントに基づいて Python で AP --- -"_私は **FastAPI** にワクワクしています。 めちゃくちゃ楽しいです!_" - -
Brian Okken - [Python Bytes](https://pythonbytes.fm/episodes/show/123/time-to-right-the-py-wrongs?time_in_sec=855) podcast host (ref)
- ---- - -"_正直、あなたが作ったものは超堅実で洗練されているように見えます。いろんな意味で、それは私が **Hug** にそうなってほしかったものです。誰かがそれを作るのを見るのは本当に刺激的です。_" +"_本番運用の Python API を構築したい方には、**FastAPI** を強くおすすめします。**美しく設計**されており、**使いやすく**、**高いスケーラビリティ**があります。私たちの API ファースト開発戦略の **主要コンポーネント** となり、Virtual TAC Engineer などの多くの自動化やサービスを推進しています。_" -
Timothy Crosley - [Hug](https://github.com/hugapi/hug) creator (ref)
+
Deon Pillsbury - Cisco (ref)
--- -"_REST API を構築するための **モダンなフレームワーク** を学びたい方は、**FastAPI** [...] をチェックしてみてください。 [...] 高速で、使用・習得が簡単です [...]_" - -"_私たちの **API** は **FastAPI** に切り替えました [...] きっと気に入ると思います [...]_" - -
Ines Montani - Matthew Honnibal - [Explosion AI](https://explosion.ai) founders - [spaCy](https://spacy.io) creators (ref) - (ref)
- ---- +
-"_本番運用の Python API を構築したい方には、**FastAPI** を強くおすすめします。**美しく設計**されており、**使いやすく**、**高いスケーラビリティ**があります。私たちの API ファースト開発戦略の **主要コンポーネント** となり、Virtual TAC Engineer などの多くの自動化やサービスを推進しています。_" +## FastAPI Conf { #fastapi-conf } -
Deon Pillsbury - Cisco (ref)
+[**FastAPI Conf '26**](https://fastapiconf.com) は **2026 年 10 月 28 日** に **オランダ・アムステルダム** で開催されます。FastAPI のすべてを、ソースから直接。🎤 ---- +FastAPI Conf '26 - 2026年10月28日 - オランダ・アムステルダム ## FastAPI ミニドキュメンタリー { #fastapi-mini-documentary } 2025 年末に公開された [FastAPI ミニドキュメンタリー](https://www.youtube.com/watch?v=mpR8ngthqiE)があります。オンラインで視聴できます: -FastAPI Mini Documentary +FastAPI Mini Documentary ## **Typer**、CLI 版 FastAPI { #typer-the-fastapi-of-clis } diff --git a/docs/ja/docs/virtual-environments.md b/docs/ja/docs/virtual-environments.md index 21b7cd472..633825b64 100644 --- a/docs/ja/docs/virtual-environments.md +++ b/docs/ja/docs/virtual-environments.md @@ -2,7 +2,7 @@ Pythonプロジェクトの作業では、**仮想環境**(または類似の仕組み)を使用し、プロジェクトごとにインストールするパッケージを分離するべきでしょう。 -/// info | 情報 +/// note | 備考 もし、仮想環境の概要や作成方法、使用方法について既にご存知なら、このセクションをスキップした方がよいかもしれません。🤓 @@ -18,7 +18,8 @@ Pythonプロジェクトの作業では、**仮想環境**(または類似の /// -/// info | 情報 +/// note | 備考 + このページでは、**仮想環境**の使用方法と、そのはたらきについて説明します。 もし**すべてを管理するツール**(Pythonのインストールも含む)を導入する準備ができているなら、[uv](https://github.com/astral-sh/uv) をお試しください。 @@ -554,7 +555,7 @@ Pythonをインストールしたとき、ファイルを含んだいくつか
```console -// Don't run this now, it's just an example 🤓 +// 今は実行しないでください。これは単なる例です 🤓 $ pip install "fastapi[standard]" ---> 100% ``` @@ -800,7 +801,7 @@ $ cd ~/code/prisoner-of-azkaban $ python main.py -// Error importing sirius, it's not installed 😱 +// sirius のインポートエラー。インストールされていません 😱 Traceback (most recent call last): File "main.py", line 1, in import sirius @@ -808,20 +809,20 @@ Traceback (most recent call last):
-しかし、その仮想環境を無効化し、 `prisoner-of-askaban` のための新しい仮想環境を有効にすれば、 `python` を実行したときに `prisoner-of-azkaban` (アズカバンの囚人)の仮想環境の Python が使用されるようになります。 +しかし、その仮想環境を無効化し、 `prisoner-of-azkaban` のための新しい仮想環境を有効にすれば、 `python` を実行したときに `prisoner-of-azkaban` (アズカバンの囚人)の仮想環境の Python が使用されるようになります。
```console $ cd ~/code/prisoner-of-azkaban -// You don't need to be in the old directory to deactivate, you can do it wherever you are, even after going to the other project 😎 +// 無効化のために古いディレクトリにいる必要はありません。どこにいても、他のプロジェクトに移動した後でも実行できます 😎 $ deactivate -// Activate the virtual environment in prisoner-of-azkaban/.venv 🚀 +// prisoner-of-azkaban/.venv の仮想環境を有効化する 🚀 $ source .venv/bin/activate -// Now when you run python, it will find the package sirius installed in this virtual environment ✨ +// これで python を実行すると、この仮想環境にインストールされた sirius パッケージが見つかります ✨ $ python main.py I solemnly swear 🐺 From 53415286238a599c5266065477bb6b2ec7ff35ec Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Mon, 18 May 2026 15:40:01 +0000 Subject: [PATCH 093/462] =?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 2aedd35ae..45ca1240d 100644 --- a/docs/en/docs/release-notes.md +++ b/docs/en/docs/release-notes.md @@ -18,6 +18,7 @@ hide: ### Translations +* 🌐 Update translations for ja (update-outdated). PR [#15530](https://github.com/fastapi/fastapi/pull/15530) by [@tiangolo](https://github.com/tiangolo). * 🌐 Update translations for uk (update-outdated). PR [#15529](https://github.com/fastapi/fastapi/pull/15529) by [@tiangolo](https://github.com/tiangolo). * 🌐 Update translations for pt (update-outdated). PR [#15528](https://github.com/fastapi/fastapi/pull/15528) by [@tiangolo](https://github.com/tiangolo). * 🌐 Update translations for de (update-outdated). PR [#15527](https://github.com/fastapi/fastapi/pull/15527) by [@tiangolo](https://github.com/tiangolo). From 2b5cd26248cebb5dfbf58ea747671114e3e178be Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebasti=C3=A1n=20Ram=C3=ADrez?= Date: Tue, 19 May 2026 15:42:23 +0200 Subject: [PATCH 094/462] =?UTF-8?q?=F0=9F=8D=B1=20Update=20sponsors:=20Tal?= =?UTF-8?q?orData=20image=20(#15562)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docs/en/docs/img/sponsors/talordata.png | Bin 1755 -> 14921 bytes 1 file changed, 0 insertions(+), 0 deletions(-) diff --git a/docs/en/docs/img/sponsors/talordata.png b/docs/en/docs/img/sponsors/talordata.png index 541bfcab840c103b405548c09c0ba71b51e22047..53906ee6e8e84186b47ba52be817102a7bbdf392 100644 GIT binary patch literal 14921 zcmV-PI=01$P)UY(v>Y5;A012?Sp$@9p=Ri{RS0!5H7 ziLO=Dp;iNkRyxRSrm^H4_9)#P~$UF+oCqmxuhIAmXtvf1TF=xJ#-K@AE<(opcQm$(-zujimNhfQ&?Sqo$Qb}{J^fx z0AM@-ntIGDrE>m!=zUMGh`P}E^WhrpKrs(?45D^+^AS1}+}+NEG<@g^ng$zX?$gqy zN>v@u4Yw)p=qzg*4nR>Dz`(LDOz(=p237^$SziOY8fu|eX?ti}T$<2r1*O8EpYkSS zPaa5$580QcF(m09p5EHlKDPLwqqSZ?4HvQ(&4R~A#gjOQJyu#wl;MgwbN9iNm2|Qv zxA$#r<01Z))@a6ktY(T_eeeKuFRow?v>n-wRA5xzeT@g8PkAROX5KeK?5n^gLvdO9 zhv{F_7I?X^*h4S>+7vg1h`+#*wUy12Zb6BbtJR2Pv`Y0xzXvTkDjs_kV5*N#<|&Q26=weJ~S~E-B`O94kJ8q zk^BRbReKxjJe8MX!5_kA!)y+FK-3CaRC(oALKs4Yrriew7A)CBBFO#cssRaivn#L3 zi}^c9Xl0g&l%OwtGwKTzF6dU~ufWoRf`I%jV+g>8QI_0Lk|6=8i+##F!j{Gw*nM!n zdQV)StKL?>k120wMR{#xeL7VLq!~O)bj%u|gNmDnG!SYu)to9-KUsj%(O10>Rm0sr z`?C!!yu|Zi@o(s)ot|sejGLyM_V!8mL&v?O_U2O!iMzTY+l@WyWUsOgu&rSqG=zuZ za&fWaU=4I`UCuMkGLjJJj?lp!b)6oPyGqdwNDP5DrMSfBf!Xi`mWPrCgb-&{CcCjp z9u3uVq@@cMy6ze()xg6XC((~3Hqht?4o}#;5KB@(8WJ$Bg9Ls`idsQwackIASCud0 z3XI+tmyEi#ZtFx~7Xj0TeFf#ekhoIVCwXM$@pMQ^hL4RoJK=&ePCnoAInHN9P zZ{E8L=xzR$4%SbC)JYDp=`2XWEbBM(pYm>YdVLJ z++G$;dL3B*ZTd{Aw(powPclocC94t9oer(2_EGkEVi-!7F)zHGO?UZk^u9GL>)ej5 z_3DfSPNY88yfASr1l$J1)ea$W;x${S$*R!e36pxI3qV@#%{A{pDR+UaPOkZ2cCZ`m z=Ab91t>SOpx7u4qH3Jf7(sPh?h4$$(7SsEibzCLDrn(hS-E@#=r;GM8SBx7q%pF#$ z-AD#?Ad<78KG^KP&AXKSv&{wFm|Vk3w>E>QteIdLQySl4k74|tf!Tw!V9qboK7Vzb zvxTu{4|FNE%SdvlPty%a9(1ou#~6Y1P0^<~LS1cBT+CLDYM}^sd+6TRBx6EA4wTAB zA&cR5du?ka_NMw$0C1_JErg@_P(7XPVfbNj)kucGYaD1xpU!B+AbK5YBSm>N7e{7m zfBLcqj-5x4SX-uV$8YCF_p9a|sysGw*>ojfPPYwIvB&!_(~Z2(9)Vx|=jQwGF3{pNuXe8YFwZ#RYb zTb5n>9NZSI>9u`ca$~dw@lF5(hQ7sGMA$~@xI=fZW9t9;w zP-=Y_N3>Zk+)M_jv+Vz(R)L#^WH9ZJoIvuO3)^N4_D4>a*b_)D2qe3hEtJ(gu-BcRT+JIEo zAFysoQ8DwtMXd~GWL9Vh9cV?3IF$1Zqh!04?D=F`DosC7AFBR{vqk{oTkm&h6&KYH zrW586sHuvq(4cWBx7ABTsct|+D|MUls5EE@5?hN}Y3`|pQ&${!`$DFAHd7d8lqMfu z(DxRJomVDl+iy2RK?(+R2rbt%m5?Y6yvisFRDhLiAp@mt*5q9XNup*4Ieb(-v5gX4 zq8m_q3zfDAIsLd)Df>ki>FyP2ZAsJ2>^>0*=~D?swVg+_p2;N}A~wvNzbIZwLEa)Bb*~Tnj9%=~6o4@SXR|*h508l6s0@ z8VkxB*)ht|3su9n7j|%CsIJ}z3*K6sV!UYlzRAjD^$SRu*tlUc=TogKx3$TgNkNqy zwPxCN^J1#duc>?;CbXaqb_1{plwF8J2Mr&Ar)z~yj%>Kxpl)aM7tVCG0rZT&k04)r z?T_-;lO}&3I<#*Gx`BIP&MPp7eGo>E83E^?|7DUo1=#k5Idl2lyYIPGx)b+KT%CT} zSgst`-Eb9Lf8&*q1lM1Cvz3ST?c2k|$^QYSf46&OU4p6cL;g-2c_zPp?D1(ZYRvH# z4uX74mL$m(#BJRm$HB#Np^7LuSap}m_mk~9CAfj5Ce_g-?;lzWO}ZhLYuQvS4y)Dr zK(4+{Y5$&0eJ((}*+ou=YaN||Rcutsb8y8#wlmgR+IfUiQR^@5jeb0}1 z*#p1&E&Kci`u6P&vmT!gV$y}bkxqvW^qEgO%#wK5p-2%^^1)5tjGSqjReve%jk&F*vI;h(E-*$ zMIAdn;$b$ckMI~XFgQk6T=G4@F+_Ywd(wm{uwwa2ULV^{XE?AP-n;gOD;0x;1`6*l zn7=sB`}eduX!K3J*dn8W%8TWQj{>~EA%`b#Fh-ByzvsWTkkdFJ_d5*)c^+bp z5ccuJSj6XKrf7m^IT1BBXDlY&JOyUW{6oGi-ammEGf|K8T(vL%8?TYl3f3nq!+H0M zx$#0+!KM#L=TSCS7Bnw7?=oc^vCfOn&xPMTF^wy;;NB-1Q!`LOoQ3|U^8T$tnDHLK zf z1*fwygB)H|aO~BMJi^!v!;c&aOIE!BYqq=xm$I=yLw4(gDN5f(80{Jhea>w^^8KHn zz-K!Sf`99JWd8U5L-nw-c00VX`vcg~P-D~|(Y`O7-~AZa(^w0)t$P{7>AhcMI8I`? zD0q0=JMiAVP5k=gPD9|FF2mt{7RJxm@-`d_n~eJU1`cWt<(gM@VBP~mXH?)9o__@@ zD~G}Jb6)26#GvvSr~vp; z%BuDmcyF2XedbZoy9e+hQ!rFmR4Ak-JTtPDuFB|#BC0C3B}YWVJ|$Kmz8ALZ-fSY6%wBsjb4aQ;A^*uDf-F=aCYCD=_~3sT=#93M1S1gME$l@Y0_5VQt+mgD0OCHH5zXEFbdTkWZv|p-K$vp3Yanc ztFVi;xopLwa0r@U&4Jy#&N1!!z_ILu?b{W%fpJXX?^yQ=!HsVYTYls+gxmw80HG(C z$dXM6=X)fRs#$1C3!Y#0o#v5+?q_`g=8qXkwvd0L!l7rSmeE3MD;0#&M&7bIA0_CX z-4C0)e-l{p>j>s~1EL=^*cMUMQs+)A-+}l?0`$1^tJc8NJD0=FA3e`KX3y5`VN8cO zEFQ-~=T61tFmKOl*xgVI=XO5|I^~j1o9nA#VfA|WQ%w{q*EKc3!hP#`86GZ(@a1kt zK{502&+J?Qc;LbpyB!Hd0rjYSpNUA3s2)U^^u3c@4yl|C^Bx?PwdRy-k>c}Inv_N#~a^+qX)XYYl|f$c8#K^QsAw4=cp z#Xea6_{^u^Z7ER(PQ3QgB9pAG$v^$C4%LkZU_tddevQjI2zb=V`8__(kNv!7!#u9w zZCka0&v!c93upV{Qm(+L*gsuA7nZR0hnIDO-jQFUfI0D znan#1fyAYuK0S|OOG20A>$}W}Xot#DIdqJY`Ss;r#(y`PC->`lwDK9lcT4#@8dNAT zAHCA$DB(@E|ykzs-rkwYg=r>C8Y}$g9gE9g>%o2SuU#uyU>z;~U)}d4czgLeODmrZ0P@xb$Y1j?y?xt!GHd*J zd-#k>c+b5*VdHl@_bB)qcX8pC%V?RzZtO4r=GXYT=}e}$(NfZ4W!=|j4b;y>(R&5- z%@d*)W~Whkaj6UEtd}u9ajp6uEs(;GBGX8=ah_PbHk!V zi{RYz#*z0fykI;xAOe={-vVEFcd8W^{-N_nj=Ts?WJ-Ja%17bp9m`?*5f{QaEP18F z0p?N9T{;8asoubU_iWQ1{yg#~zRo;y(cN6JTd^?t$)hi2$*cZGd;D`6pLzR^{5<>U zw!Pr#W3I^G_ua)42h-UmMIvC8cTcJNzT;X{TU?{v%M_$<%AHp_eK*+myz79*1QTbN zffsN$Q)pB;RJ5h5-n6t0E%azl9OlLh$EtmYw#tsKG$3Q%RbRuVS`M=6oqy~Q`n>K( z!#8@4g1LJ>gy-1&w_EFWFuuoUU<3DLy9NfAbzxq2DEFRMt(pl9hazt~meoTK z{BK<<^9oD>W}S~}+Z&eEY=IxFekT7wzR_zGr;p26xTHiumR&q)L8c*x*}}KeSk(=x zD7d=t`Wlo_!%6Q0r*|2fDg}IVi3pj;@||E`tAeqgIqU8xVYy?C}T@VPqOxy)DjSGi44fsdyard*jjNtOKcSaS)ZhQWRF}* z2dAO&ZSzw;{KQfiV^9-VZZkls6h;Bp-EbwJPve|aY@b9pVf69*9@U;U335%fMYi!y zR$c__MvmBSru*|0f3L8fE%D%bEQc`K$g!$!Cp^0K9oSS~#ZUGuVq^7(oy*|2+tlph zW_BMvXP-75pKU8XWn%IkwC-pFyf_I8sSLdUgg zxZ*MQiw<0r^m5O2;D7A-@82HK{;rVZRn#uju5}Ltmftj<(6d!Y{PKUDQTE)vElda; zzoL?W#Ok9teo+ryR_up5`kp*#A{;nyfGr{Q@OgPgC_p3N5Yysrv*9zT`0p71}X46xc-g`Om9axsk`KM~l?f z*24eXb~}l!b?Xv1`|PvfZwUsn`R0>HT?(H>Xk8RNIyHe~12t2NwX4|j3GRPh&gOk$ zL;aa7>nfkTAs?#~VNogJIxems;(L!(wdla;T&mHT%+|E4s%tbnCVlgFaz-K4 zJh9!x`WsihX0gjwnpW)}3s6aLz4ns|2LQ9te*Q!j5`5u(?0J_Mdwx-2@n!zmk3Yy2 z8tct;9AOi^(>sE10HL;1Vp~*Re4P&yL#SA`BXRImKs*^l&iv~9qY=UlBo9b0S>RHT zu6Vdz(@y7MxQ->RuFcWGv%AE*x~>BS?CCg{kB+lQX+6J5mo6)|tEG+6f5P7)$N}G_ zmtMn_7vDO%o(VF3qw+=`c@;dygdg`u%TN2Kxx?w?wb#+w;ck_cL*cS3zQ*t2POF(S zpX3ULr*5DU%W(Y-S23mT$@r+@3Wtf~7yEU*q6bKK&hzR%xCR*KsS^sk}F zt5&UosrUacy!`SjOt`AFy8#RuH~_|t8w;0Rb}4-GTUYWqxC}4-@dX$rKhGrA$E&;z4UI5m z$`p8D+H_JuAji{3Yu3Q+Q|^EVANn=-(k;(d1KfMxeela){)%VgZP3)z1h2pT2E6&^ zTX5dF=fZ8b{WnYEwNAv3I44cM6@L5Mhrtg5DY>J22fb!|2VX$IcYpc(kPhwme|S_`Ped z=Pw=j0*0_H4O_Nsfm?t46L{vCXRTgQ2UO%)vuDGSrAuJO^l41!?XLvx+_ej?yY6~6 z6?hH&fwJ;y^rVXz3N&VXQ3>#!-ud$vkvIt zY4pfct|9-9TgkhyvUp|P^XikA6lY?&Y-sbq?%liLrvLapEMB}AK1qO4z`ghV44!`a z8OQ>wR=p2D_^%(refQl9ojY|h?xSaa=)s4$^7LICUe&Z2_vLpu$($`;zDmK5ihCCe;mxB~qwlw* zv#N2Pe!cY9B{+XGaUOgX=>15E2()T;`t|7j; zvgSft{Ie>kaOk;s5{oI_3v*uPo=#Wb(Yb@+%;l7r2Ye-O))Ub|?ZOk|I`bLC7R6f_ zZSgWadfvX|L3iRigxS)v5PI7Mpc;9ksh@9+5S`;ZEJr8WGU+4H<|3;8r*h7&4|;`i|T-#^KhZ(0(Nuf2Qe!`-`d=>k9e zuOBd>IsrPd&={2+!~gs5|0VqSz4wgzsH8Jz&4ycs56@?&>+0&@b>^L2fOY%y?E@V< zbQA}Cz~Di623KX1QwE0Rs8~O} zYbsku)-&9G(uB3%%^xAOmeAz+)PjKWd&6)?8<1WJ6KEXVDs%1 zXd5{`o^V-*?b~<23opJ%-WxM!4E*@kNpSe#@tIQn`t^h3jyn!cJ@pj$-uJF&ieC*a z1rI;+2w6U8@E~~L|9+|Pg=@~ZT@-m9JMMfw_toLW7yk%1Tz_5u)R8@V_Q0AoYrzJc zI(LQ%Kl&k@amMM;rcIl?;^TLmpHKJPrn7k|Caa$3N8xPBD+em~4L4rR*GnVFE(`e5 zK5pv3cWqIz%w0}y+;NZ^=CjWT7>?^pX80oh{I}v{oO&RAdbeZaOwS{@BA`NE!?lOq zIxWzT)NxIjfxqwS0$hhZ<|^}M2cYU^F~`=RLLo$1nmo{AFS0R#HOvBw@`ZP%(* zD;Rs;xzJLuWy@Alc~P-&1BnYpjT#Au4;f;VA8I@Vn>WX&5n{h>^ZvsR9|E8K?B^gW z*g`P*w@B>Rl{ZYl5a#Qv>#v1_i9`2IG!-h@la_9vU~|*cX$OvbSs>;hFv^Mdf$hWA zQeaEq3?4j$hm9^6G-wdC6x7tvbMhWNdL+K~SXNfX>rt?GZx#4J&z?P@Teq%|1$42? zqEK-#s86(l{1w$A1U1wQQc_oEk^#})XLbk*FKKAgX+VIinvnMIcDmzWwQiAlv!&J5 zgyLd)H476wN#NQMRVdhYPvNEj`wp=PFm$dvK=WT(S_(d38<#ZTFY30oVcr`HQ{c1f zEBcNxq)}n2y?VFhWi(b~*Pqo5l;1Y*o2LIR4-SgqjIJFga(sNjb~`MbtCsNqXI8nxX{`5gAYF7NAT)^`=opI>Iokgr1d}mx(AG}1LZD4kfMEh z&=tt;$&zD?EMc^`vS*yBsRUSSr=x45r>4@1=;o%C3sMh(KOAwyP|_=5GHmwj$N82- z3UJwGDqFH?DZr&6T*9K@7gO)&JI5%%IqkIRGuT|$Oy+g(-kpD18Uo9Ac6^i|3xR50 z+0ea^ditbGnPjyC7$Ku3{!8r zeG1+%lQ3QB!c_ zk(GQyO7nqRJj}F@+Z2bSGPttI%`w}ybK@Jniu!VYMPGd-*HurRLbz&DuVSY0zU~B^ zITppSu~BRr?BOy&ais*YIyRgr{FIu z{sJux7hZ4y%$V_@5z6CktEU(bxDE1z6Gp+n0R#93leuj92>GKj%Xq91X0Ow}Ug(C< zqeQ;vo{v#yPSINkY3z_vX($XapMhom8xp@wBa>Bjsh)<0j?fS%?wZHzhY7!m1F}LP zk03puKwosxMez9JPw=gXI-vJ`_Sxt7=i`P!g9gG^zWgP4^s$-7Jyg;)Yu50O51e+| zX>juAPKM@(_<4nn8sdJ^lhx19atV=s$5gp=Yr!!+{m-?;6p}VH{C?8>81fpTz%`CS3pHYIW#}$`3iT936t(q zK677vTdF5#oozTx3Ns#J#&_K&g04`<0CsGTmkamruY-#({ZClCZj*)E(D7R?2aPjR zd42LX<^(bzl4tJxaD*d-70W+_S+neCguB2MoKsLlKNz<)Zz;g-g5UYh)qJDGCkeWD z?*>z*+-BY6p9E->?!4m;IOdpR;I9edc`je^A)Ahz0OQA<%|8nlFJTHO4wYBuaADrB zQkdfUYu9e#N@)+SL%3z~&)GC1O8iw+l)=?k{yPllPmQT-zL}Kb3BAf(AS+|sUgjmx zK5`%rypN)vzRBO@`FH$FhGLbuzrH{I-ZkHaGM174@Bg{YntlFjz=#ne;NgdV3zuDX z1$_A7hu-b*g@@_WAAn<9M0x4e0-t$UG z)7`^IR5yfIQ_M2H^NAEjf(#& z!-=?FowpE%vwKMMIaU`9gZM1~Jsj36XFQy9_Q{-ob(S9FJt5XZUeC_eL#SnZy!z_G zJnoSrkAkxDGJX#gZyvjc-+1rjQ=&Jf)-hgp?AXJ{W+(f6{o=21YRKcdwVQd}BPs{y zX&^7JF+3|)tmgMdFdF6M_Vs^vW+Ak+0QXkPmRvfr(q!}DZ++{V@W{iz;pa}fHZ$Ow zYIn9)`_&6C_*g>kK?4WE(@#CgjSQZyVT%;7550T$h6~1zhdIwb+d|5VKzkedq(nQ^ z?yt+&-?n2HOq}#HCWu|w_#X{3XFt!C4*^5%U)=vNFRvVaI19gj#=W`BP3)6Y7%-p@ zv}H;%U_kG@;g~ghPDGz66kab{yo@Q#D0uGqc`#|x&-uOKl|$gcU;mydLPQ4@Z|ePz za3g@Y?znRr3&S^qzU+j`E7wDONC#o+)JM32qVd46|BgGR@%A_llaVg_aWXR)ix)42 z*|Q=ZQP~k6D(?})2XiX-PyHRoGvfFo84nxbf7x$t#VA$4>6<}l5qX)e%jQCm#7A{%>6-=S<`9AafT;|D60es>( zcRPRFS#Zk9k;l8~#>-*Koe%K)=y6AJPZD{n%6UWByq1NE(w{>{NkQe2Wv8<8aPD#O z9)1firNhO{tD&f#eb&ibdC+S@4&V0e=nt33lEQg{Xs(%G6S(_;Zklq z(BtY*A@L+a?3iw(#6oW>Nd9RkWbLO|cgZT^Y)N$rqdU8%*3`Xz+S3el>{L13imq+n zg{0Ps^Osq(3BF4(lz9xbQFL>F^IZ&OQIT(F9u^e==V)SXi^3^yWeS_ ziqaPAqX(VMLisDN`YNxpcFiWZ|NcjSo)`pt%tZU_&s@jqgD0+46cUWZ|E8Y@s{-g# z+dYpHzkNX-YX8)niFL{F``MIIcZ-cvgK`EfOA<)9zBzrqv8A(!)sJf z^qv^H3U7=_sLIMH`Guh(dT*P-1Phm99_kBvf00-8lE?#o7Bi(=m-Ci#O-w{#f(iS8 z(*ZO{NE<_D;a%|_8ia=)`aMsiVQ7tti*?bMt;o;sbpwyy_DD`wL?`Ig|MUBI=0j-T zr=UBzFrokY?_$$_h-CvIkmz#V?D0q;0;b)n$qo8*0)&vv9+YyWC`B`%XM1XG8ev+fUKY!ObidvBSpy~bw-U! z-CasV*(MVd*TMtK%3+@f=osSPwY3MJW`8Z`BLw?%LdC-Hm{LZ(S5DlE+muRlO-@Bg zRKHwVCi0b=Y)>_!zq5Y7I8vv=XeI*bEL+lI622V?iS~sZ$C6HoL+M`%eAO^}OEFgQ zFVWsL4yqs(5-kWU0R+U;aMO0x^yP_u0!gVjy?uJHKQmd9?X~4`clR|&Y;WEX?eww; zP=SlwL!TYuKreLE2*D-<{_{VzMtXB2hLGAiC)Z2HWGfF+v~F8(-_3{l48TE+{so%x zOQK0Bk?k4isZlqiN&ec^Q{0uW)mlYrr4S0Srm-bW&PGxY`@z5|N@goF;PA_U%ipmO z`6uvV(bf4)XF$}XooYO6qZwL%1r{ohqTH-S_bB#HVZLS>piGc^+|7Qg#xmW=+cE1k zLrC*v^=Xg|tJ+2{4{KFbcz ztnVj9%849>C@uwla{}3ZCl7k_fjM2E!{%h4?myf#ANI9Af7P%FaeAOVM+o#(#@{FT zP>dpG z>ZUJB0&v@T9a}nqHs^j}qIk%y&H1-q%b0rHR_~MSk?5R=j|WNu+P8{tUBuHFvNUxA z#aO7dY&+rt3m*4cz7Ob6l5SNL7!CZG$i@@^En+km{&P_~W_N8hEDXJsIw}?4g?PKr z@+&S+XGc-E##!f>JtRkmo}F9zmXkfWgzp7s}HR&x7qj8h~5e(ukst zSMcC^nLMuNZ)Ej$5!OJ8a;RrQjf0&RdQM5#rLI*Pfuo(C8xY@a*-4HmWD4|ML7|9F zS*Q>|^8DDQ3g$gMmX~K&vf#=O7Qm&J>AjHIn_WA1!lv~b`JV^{2vZ5<)-7AX#hU;; z2yY{!v60iM<+PBd*(PvciD386T{&I>w&S0GX=t?6i~;NKtEwhxsY(u`P%tO8iu-^{v|{Np zreFtQ!5eRKWx&rirWh!&$R!FsDh&cEBHqJof%y5$(&fBdt|OqKA^r;vs0iy;f5a)j z{l;7Q_mzcW$@sT3fyMGjF~eN@My01q-~BUFlsZ_MqrZo>ug$eVeE1Oxhu53eZ{U0* zRP%eaaFF$RU)4TNvzjY+VDOFC$af>F`{%b8^LqFZbfWQU;7W#yi!}D^+|BVKf2)?R z;B6Pbv4Ha^+F)J$H1M`td0p)Hc8;fxf8J+pQK_-rJ8vw=^<^K&Pd#@Z&;xeW-?<|m z(LN-~)6%z>>oKLhRjZqR^n+U}irYZ)T+41ZDAlI@rXG^S);~Sn2to_ZWE&W_e1GLC z_|&kW(7Ln~I&|m=ZA#m~pBBHv|9IM3Cb(F0{n~Y~zov!@Jt{mNGrNB6TCRkscwM@7 zVMbs%7tE?Xd!TdIu3ULune!s2g1=G7u?-$bfCm$F?a>`RT=_mP-@x!A9&C?gc>nzs ze}RsjJ3(1_Ij6bcwKo`^F8nusu>RWBYhlo*hQMA%^AKyZj45@;&YfZTdrLX5s0@e; z@gvXJH}u%3L>tzw=R7P~{4Q4z|DWhcW!i;kc7d;C(1>*N!Xm+7DLe6#M{m=-d&~f+>L^S!&7) zbuWtwyTF{8o7WN49cqB0#xQ#6Jeu#=!L>U`SIekW{f>W`!LEyTngo`guMUks1O>O2 zds=`st5-7*vV|+v;ln<~Puf6X?9sC)^y$}^E6pzU88~<#|7-Wcz*IA##y0p7P+U^X z6}P=~kUJ{g0M-`k$>D5oh8sWVjga0DMq6%&iiH9lo!u1C?9Y?~m9%%iKKvVb!}d64 z_~$|q2hzcE#EtC{gm*_=sGNv;Om?8$MgoYjf0<-3Q%CMZ4>$~%vIyqC;I+>Rpe1AaV?h>aKWw(Q*{ zT)EnDLk6&jg}8W){T_N$C9Ge)hT}%XT`>1`-nR1CPxEkj`MdA&dY!s<=3f52x8LRC zfqm%5c)<{P$CmAk)~9$|tL^6soJ=9=!=R`{xy#B zMqI)BHQU3%6^)n@1Ygh@dD0le1fjw+;>F{@r*Xt?uB6GzOCVqif#q}xevcinU7sCq(4SgkkSokU@6yIgd{B+s94d1 z73b!Rkiey_+@?GtIaFF+$~}*}7nEN}1~CHmzPm@UIfPjM6&upzXAx%Pz-21jqZp5e zT~29PQeRX_;?7Tcn^@$$c|TL&wflF49b1<}yW%zmF@M2M>#No9JFT~uF{OuC?9+H0 z8z$ZO_$rY}JD!Jy9_m<#0>$mk9{7((b16~UXF%6YZ@lDovEop!M2}a}8fqJDAo-y0 z=>6W`cn}UAWJ#=c#idZwct9c$lGiSl{D(en1E3F!t&Lw~;7$xsKq*lAC?qt*F~*ie zJF2Iyzh+g6z_To(VLpramv0YrFOwb8^||nfARya?IZi?g=6KX>BUFe{rKb_m9m+K9 zZ>)zdCFM}mp#&AUp1Wjq zCq&-~EVYw^Fp&JMdCrnK2Ld}Ah|4m)^H-en=BUT1V_ec_EUtl2(ESS z_+Py=4JR@^@$H9I)C{e-{Wt*4fZ6M**M)f+83K|QwI*dMZ1F=@KKyF=MyF{KuPVqg zV7mtHaJv+jLrKsodK;-*o3>EJ!sw>3kVoUgpb1Hek_G~=8mjFF3ol`UdK5NNCY>;a z5bHJ5j+E-TL*-kP#x+&pkpsH)Pe`X=>n~jvLLBI3rx}BgguvV7$nBEL(t+$)K>XXLqoRWu7|M!6 zV-GTlO{laD67ZRZMONbMU=Khc#hpT4H5HN8quI5)tSgP*$9P z#1I1Q$6OHmTOq#kJ^u_smZzom#y0j;p9AZiv~ojBZ)m9zTH6&$*L6DMqLXK@$5-CtD-sgW!XG0mNzst!A7RM zhn2Kty4lWb9fq{4-FdJE_B7P8u)3|G^$}`c2sI|-K`V3z7G<}RTg52@diRl@lMEq= zhjeq$>>ey?lO0_BiNV$*`?E?j2FXfHV^a-P_P-dSQVBhA>b28BIx`&8!{wsg2lhix zrnr>y@|rdUMyPLUgbj6j0N099i942*SxLH?3$#}5{i8__s1TKx4ToKc{V}HFf>w;A zfIms>)4za_O%w|;9u$4uaH>Wglyd4$db%pO$HE-Nkla_ z-oAOW^SwKF?#!7jM-YVB*rEvt0>H%J@xUiLlm-RB1b_id0Dl-v044xT0Wbkz022g& z0Zagx0${>0;7{*L~#@_U|qo+OO{a3Sgpt zz&YjzZZJ5~&O+wxM6fue{|ReCXl-l~9CUXRVADwc4x1LjBm!sj)~T1#rxx zquhD{7{CB71UM&R)@=hAz-j@9p6Rac|0cflG4+0Y4sg!ZcS*ef3}BUjYg~Ox0+xuF z_0a$ZaDQ>Y{%W*dre1%1@`xwqGeTEs4{NGCee-RRZH6g;=jxX7;{sp+7Y7{s`b}^* z?GLWCKx8T4n)L!OfSUkb5|;wId_s?o=9XGcEz_J^9~}!g_TGKdPN=1ix&RDd^?)U> za#G7QHvz6)F8~8rE#Rq18~_6tz)AtnCAbR>fq$3g&@EjPx00uCC0SsUO0~o**00S7n6aWJlz?_X#uH$^LyXOc1QveKL z00S7n04DSWfB_6(00S7n1b_hyU;@AdfB_6(00S7n00uAtU;@AdfMvojKYilKr~Xsl zvwvrwce@MfT&q2-0zN#v&VEV zXCZ^smB9kw+M}FO?Hv=Z6?n$&NPns0M6(~{UJWEi0V4pGidQK4$(GJ+}vDMVprT_mLmT-0r zcz174%{H?U0G~VeGJqR=?`{F-453QJGa0#{v;)?d<|e1T0o)jH&gO+uk$*EP0I*9+ zzz<-ffHiigoclxo1DGpt;|`Vcd{R5$oDBv}VS+gTHwK)8W$AJ@Cb9BXKrx90U?;gQ zH+DTNfSpK+UX4GP0OmRHP=I?{i3Q*e081Z?#Zt=Y;-4dHY44bg{Qy=DSn{eMv8|BJ z47%z8;0l0`1mLh6sqV2NR)6+?1K7xZV1JUHhKwMiWaP+MA1slFI(8W?fQ_ZpX?+63 zXeo7;&P><-KLfZDVCmE+bMbDWgyvQN=WgR$@<^{lR!9I3l2+DtERWT9q8dktkXBY# zUT6SU1T1}3ATPA*=GH%+mE82(p_10000 Date: Tue, 19 May 2026 13:42:52 +0000 Subject: [PATCH 095/462] =?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 45ca1240d..bd2ce703f 100644 --- a/docs/en/docs/release-notes.md +++ b/docs/en/docs/release-notes.md @@ -9,6 +9,7 @@ hide: ### Docs +* 🍱 Update sponsors: TalorData image. PR [#15562](https://github.com/fastapi/fastapi/pull/15562) by [@tiangolo](https://github.com/tiangolo). * 📝 Update docs, simplify usage of admonitions, only default ones. PR [#15553](https://github.com/fastapi/fastapi/pull/15553) by [@tiangolo](https://github.com/tiangolo). * 📝 Fix image URLs in `index.md`. PR [#15534](https://github.com/fastapi/fastapi/pull/15534) by [@YuriiMotov](https://github.com/YuriiMotov). * ✏️ Fix Azkaban spelling typo in `virtual-environments.md‎`. PR [#15463](https://github.com/fastapi/fastapi/pull/15463) by [@isaacbernat](https://github.com/isaacbernat). From 31ced9d49e253f1cdc78ab56a314ef1ad7d8d7ee Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebasti=C3=A1n=20Ram=C3=ADrez?= Date: Tue, 19 May 2026 19:40:41 +0200 Subject: [PATCH 096/462] =?UTF-8?q?=F0=9F=94=A7=20Migrate=20docs=20from=20?= =?UTF-8?q?MkDocs=20to=20Zensical=20(#15563)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .github/workflows/build-docs.yml | 20 +- .gitignore | 1 + docs/de/docs/index.md | 5 + docs/de/mkdocs.yml | 1 - docs/en/docs/contributing.md | 6 +- docs/en/docs/external-links.md | 5 + docs/en/docs/fastapi-people.md | 10 + docs/en/docs/index.md | 5 + docs/en/mkdocs.env.yml | 5 - docs/en/mkdocs.yml | 72 +++---- docs/en/overrides/partials/copyright.html | 4 +- docs/es/docs/index.md | 5 + docs/es/mkdocs.yml | 1 - docs/fr/docs/index.md | 5 + docs/fr/mkdocs.yml | 1 - docs/ja/docs/index.md | 5 + docs/ja/mkdocs.yml | 1 - docs/ko/docs/index.md | 5 + docs/ko/mkdocs.yml | 1 - docs/pt/docs/index.md | 5 + docs/pt/mkdocs.yml | 1 - docs/ru/docs/index.md | 5 + docs/ru/mkdocs.yml | 1 - docs/tr/docs/index.md | 5 + docs/tr/mkdocs.yml | 1 - docs/uk/docs/index.md | 5 + docs/uk/mkdocs.yml | 1 - docs/zh-hant/docs/index.md | 5 + docs/zh-hant/mkdocs.yml | 1 - docs/zh/docs/index.md | 5 + docs/zh/mkdocs.yml | 1 - pyproject.toml | 8 +- scripts/docs.py | 228 ++++++++++++++++------ scripts/mkdocs_hooks.py | 182 ----------------- uv.lock | 186 +++++------------- 35 files changed, 339 insertions(+), 459 deletions(-) delete mode 100644 docs/de/mkdocs.yml delete mode 100644 docs/en/mkdocs.env.yml delete mode 100644 docs/es/mkdocs.yml delete mode 100644 docs/fr/mkdocs.yml delete mode 100644 docs/ja/mkdocs.yml delete mode 100644 docs/ko/mkdocs.yml delete mode 100644 docs/pt/mkdocs.yml delete mode 100644 docs/ru/mkdocs.yml delete mode 100644 docs/tr/mkdocs.yml delete mode 100644 docs/uk/mkdocs.yml delete mode 100644 docs/zh-hant/mkdocs.yml delete mode 100644 docs/zh/mkdocs.yml delete mode 100644 scripts/mkdocs_hooks.py diff --git a/.github/workflows/build-docs.yml b/.github/workflows/build-docs.yml index d8e5d9e94..f30ea3bef 100644 --- a/.github/workflows/build-docs.yml +++ b/.github/workflows/build-docs.yml @@ -34,14 +34,13 @@ jobs: - docs_src/** - pyproject.toml - uv.lock - - mkdocs.yml - - mkdocs.env.yml - .github/workflows/build-docs.yml - .github/workflows/deploy-docs.yml - - scripts/mkdocs_hooks.py + - scripts/docs.py langs: needs: - changes + if: ${{ needs.changes.outputs.docs == 'true' }} runs-on: ubuntu-latest outputs: langs: ${{ steps.show-langs.outputs.langs }} @@ -103,21 +102,28 @@ jobs: run: uv run ./scripts/docs.py update-languages - uses: actions/cache@27d5ce7f107fe9357f9df03efb73ab90386fccae # v5.0.5 with: - key: mkdocs-cards-${{ matrix.lang }}-${{ github.ref }} - path: docs/${{ matrix.lang }}/.cache + key: zensical-${{ matrix.lang }}-${{ github.ref }} + path: site_zensical_src/${{ matrix.lang }}/.cache - name: Build Docs run: | # zizmor: ignore[template-injection] - comes from trusted source uv run ./scripts/docs.py build-lang ${{ matrix.lang }} - uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1 with: name: docs-site-${{ matrix.lang }} - path: ./site/** + # English owns root static assets. Translated pages reference /img, /css, + # and /js, so omit duplicated language-local copies from artifacts. + path: | + ./site/** + !./site/${{ matrix.lang }}/img/** + !./site/${{ matrix.lang }}/css/** + !./site/${{ matrix.lang }}/js/** include-hidden-files: true # https://github.com/marketplace/actions/alls-green#why docs-all-green: # This job does nothing and is only used for the branch protection if: always() needs: + - langs - build-docs runs-on: ubuntu-latest steps: @@ -125,4 +131,4 @@ jobs: uses: re-actors/alls-green@05ac9388f0aebcb5727afa17fcccfecd6f8ec5fe # v1.2.2 with: jobs: ${{ toJSON(needs) }} - allowed-skips: build-docs + allowed-skips: langs, build-docs diff --git a/.gitignore b/.gitignore index 243cdb93a..2c0d859ad 100644 --- a/.gitignore +++ b/.gitignore @@ -7,6 +7,7 @@ __pycache__ htmlcov dist site +site_zensical_src .coverage* coverage.xml .netlify diff --git a/docs/de/docs/index.md b/docs/de/docs/index.md index c71391432..d557554a1 100644 --- a/docs/de/docs/index.md +++ b/docs/de/docs/index.md @@ -1,3 +1,8 @@ +--- +include_yaml: + sponsors: data/sponsors.yml +--- + # FastAPI { #fastapi } + +

+ FastAPI +

+

+ FastAPI फ़्रेमवर्क, उच्च प्रदर्शन, सीखने में आसान, कोड लिखने में तेज़, प्रोडक्शन के लिए तैयार +

+

+ + टेस्ट + + + कवरेज + + + पैकेज संस्करण + + + समर्थित Python संस्करण + +

+ +--- + +**दस्तावेज़**: [https://fastapi.tiangolo.com](https://fastapi.tiangolo.com/hi) + +**स्रोत कोड**: [https://github.com/fastapi/fastapi](https://github.com/fastapi/fastapi) + +--- + +FastAPI एक आधुनिक, तेज़ (उच्च-प्रदर्शन) वेब फ़्रेमवर्क है जो मानक Python type hints के आधार पर Python से APIs बनाने के लिए है। + +मुख्य विशेषताएँ: + +* **तेज़**: बहुत उच्च प्रदर्शन, **NodeJS** और **Go** के समकक्ष (Starlette और Pydantic की बदौलत)। [उपलब्ध सबसे तेज़ Python फ़्रेमवर्क्स में से एक](#performance)। +* **कोड लिखने में तेज़**: फ़ीचर्स विकसित करने की गति लगभग 200% से 300% तक बढ़ाएँ। * +* **कम बग्स**: मानवीय (डेवलपर) त्रुटियों में लगभग 40% की कमी। * +* **सहज**: बेहतरीन एडिटर सपोर्ट। हर जगह ऑटो-कम्प्लीट। डिबगिंग में कम समय। +* **आसान**: इस्तेमाल और सीखने में आसान। दस्तावेज़ पढ़ने में कम समय। +* **संक्षिप्त**: कोड डुप्लीकेशन को न्यूनतम करें। प्रत्येक parameter declaration से कई फ़ीचर्स। कम बग्स। +* **मजबूत**: प्रोडक्शन-रेडी कोड प्राप्त करें। स्वतः इंटरैक्टिव दस्तावेज़ीकरण के साथ। +* **मानकों पर आधारित**: APIs के खुले मानकों पर आधारित (और पूर्णतः अनुकूल): [OpenAPI](https://github.com/OAI/OpenAPI-Specification) (जिसे पहले Swagger कहा जाता था) और [JSON Schema](https://json-schema.org/)। + +* आंतरिक डेवलपमेंट टीम द्वारा प्रोडक्शन ऐप्स बनाते समय किए गए परीक्षणों के आधार पर अनुमान। + +## प्रायोजक { #sponsors } + + + +### कीस्टोन प्रायोजक { #keystone-sponsor } + +
+{% for sponsor in sponsors.keystone -%} +{{ sponsor.title }} +{% endfor -%} +
+ +### गोल्ड प्रायोजक { #gold-sponsors } + +
+{% for sponsor in sponsors.gold -%} +{{ sponsor.title }} +{% endfor -%} +
+ +### सिल्वर प्रायोजक { #silver-sponsors } + +
+{% for sponsor in sponsors.silver -%} +{{ sponsor.title }} +{% endfor %} +
+ + + +[अन्य प्रायोजक](https://fastapi.tiangolo.com/hi/fastapi-people/#sponsors) + +## विचार { #opinions } + + +
+
+ + + + +
+ +
+
"मैं इन दिनों FastAPI का बहुत उपयोग कर रहा/रही हूँ। वास्तव में मैं अपनी टीम की Microsoft में ML सेवाओं के लिए इसे उपयोग करने की योजना बना रहा/रही हूँ। इनमें से कुछ को मुख्य Windows प्रोडक्ट और कुछ Office प्रोडक्ट्स में इंटीग्रेट किया जा रहा है।"
+
— कबीर खान, Microsoft (संदर्भ)
+
+ + + +
+ + +
+ +"_[...] मैं इन दिनों **FastAPI** का बहुत उपयोग कर रहा/रही हूँ। [...] वास्तव में मैं अपनी टीम की **Microsoft में ML सेवाओं** के लिए इसे उपयोग करने की योजना बना रहा/रही हूँ। इनमें से कुछ को मुख्य **Windows** प्रोडक्ट और कुछ **Office** प्रोडक्ट्स में इंटीग्रेट किया जा रहा है._" + +
कबीर खान - Microsoft (संदर्भ)
+ +--- + +"_हमने **FastAPI** लाइब्रेरी अपनाई ताकि एक **REST** सर्वर स्पॉन किया जा सके जिसे **अनुमानों** को प्राप्त करने के लिए क्वेरी किया जा सके। [Ludwig के लिए]_" + +
पिएरो मोलिनो, यारोस्लाव डुडिन, और साई सुमंत मिर्याला - Uber (संदर्भ)
+ +--- + +"_**Netflix** हमारे **संकट प्रबंधन** ऑर्केस्ट्रेशन फ़्रेमवर्क: **Dispatch** के ओपन-सोर्स रिलीज़ की घोषणा करते हुए प्रसन्न है! [**FastAPI** के साथ बनाया गया]_" + +
केविन ग्लिसन, मार्क विलानोवा, फॉरेस्ट मॉन्सेन - Netflix (संदर्भ)
+ +--- + +"_यदि कोई प्रोडक्शन Python API बनाना चाहता है, तो मैं **FastAPI** की अत्यधिक अनुशंसा करूंगा/करूंगी। यह **सुंदरता से डिज़ाइन** किया गया है, **उपयोग में सरल** है और **बेहद स्केलेबल** है, यह हमारी API-फ़र्स्ट डेवलपमेंट रणनीति का **मुख्य घटक** बन गया है और हमारे Virtual TAC Engineer जैसे कई ऑटोमेशन्स और सेवाओं को चला रहा है._" + +
डीयोन पिल्सबरी - Cisco (संदर्भ)
+ +--- + +
+ +## FastAPI कॉन्फ़ { #fastapi-conf } + +[**FastAPI Conf '26**](https://fastapiconf.com) **28 अक्टूबर, 2026** को **एम्स्टर्डम, नीदरलैंड्स** में हो रही है। सब कुछ FastAPI के बारे में, सीधे स्रोत से। 🎤 + +FastAPI Conf '26 - 28 अक्टूबर, 2026 - एम्स्टर्डम, NL + +## FastAPI मिनी डॉक्यूमेंट्री { #fastapi-mini-documentary } + +साल 2025 के अंत में एक [FastAPI मिनी डॉक्यूमेंट्री](https://www.youtube.com/watch?v=mpR8ngthqiE) रिलीज़ हुई, आप इसे ऑनलाइन देख सकते हैं: + +FastAPI मिनी डॉक्यूमेंट्री + +## **Typer**, CLIs का FastAPI { #typer-the-fastapi-of-clis } + + + +यदि आप वेब API के बजाय टर्मिनल में उपयोग होने वाला CLI ऐप बना रहे हैं, तो [**Typer**](https://typer.tiangolo.com/) देखें। + +**Typer**, FastAPI का छोटा भाई/बहन है। और इसका उद्देश्य **CLIs का FastAPI** होना है। ⌨️ 🚀 + +## आवश्यकताएँ { #requirements } + +FastAPI दिग्गजों के कंधों पर खड़ा है: + +* वेब हिस्सों के लिए [Starlette](https://www.starlette.dev/)। +* डेटा हिस्सों के लिए [Pydantic](https://docs.pydantic.dev/)। + +## स्थापना { #installation } + +एक [वर्चुअल एन्वायरनमेंट](https://fastapi.tiangolo.com/hi/virtual-environments/) बनाएँ और सक्रिय करें, और फिर FastAPI स्थापित करें: + +
+ +```console +$ pip install "fastapi[standard]" + +---> 100% +``` + +
+ +**नोट**: सुनिश्चित करें कि आप सभी टर्मिनलों में काम करने के लिए `"fastapi[standard]"` को उद्धरण-चिह्नों में रखें। + +## उदाहरण { #example } + +### इसे बनाएँ { #create-it } + +`main.py` फ़ाइल बनाएँ और इसमें लिखें: + +```Python +from fastapi import FastAPI + +app = FastAPI() + + +@app.get("/") +def read_root(): + return {"Hello": "World"} + + +@app.get("/items/{item_id}") +def read_item(item_id: int, q: str | None = None): + return {"item_id": item_id, "q": q} +``` + +
+या async def का उपयोग करें... + +यदि आपका कोड `async` / `await` का उपयोग करता है, तो `async def` का उपयोग करें: + +```Python hl_lines="7 12" +from fastapi import FastAPI + +app = FastAPI() + + +@app.get("/") +async def read_root(): + return {"Hello": "World"} + + +@app.get("/items/{item_id}") +async def read_item(item_id: int, q: str | None = None): + return {"item_id": item_id, "q": q} +``` + +**नोट**: + +यदि आप नहीं जानते, तो _"जल्दी में?"_ सेक्शन देखें: दस्तावेज़ में [`async` और `await`](https://fastapi.tiangolo.com/hi/async/#in-a-hurry) के बारे में। + +
+ +### इसे चलाएँ { #run-it } + +सर्वर को इस कमांड से चलाएँ: + +
+ +```console +$ fastapi dev + + ╭────────── FastAPI CLI - Development mode ───────────╮ + │ │ + │ Serving at: http://127.0.0.1:8000 │ + │ │ + │ API docs: http://127.0.0.1:8000/docs │ + │ │ + │ Running in development mode, for production use: │ + │ │ + │ fastapi run │ + │ │ + ╰─────────────────────────────────────────────────────╯ + +INFO: Will watch for changes in these directories: ['/home/user/code/awesomeapp'] +INFO: Uvicorn running on http://127.0.0.1:8000 (Press CTRL+C to quit) +INFO: Started reloader process [2248755] using WatchFiles +INFO: Started server process [2248757] +INFO: Waiting for application startup. +INFO: Application startup complete. +``` + +
+ +
+fastapi dev कमांड के बारे में... + +`fastapi dev` कमांड आपका `main.py` फ़ाइल स्वतः पढ़ता है, उसमें **FastAPI** ऐप का पता लगाता है, और [Uvicorn](https://www.uvicorn.dev) का उपयोग करके सर्वर शुरू करता है। + +डिफ़ॉल्ट रूप से, `fastapi dev` लोकल डेवलपमेंट के लिए auto-reload सक्षम करके शुरू होगा। + +आप इसके बारे में और पढ़ सकते हैं: [FastAPI CLI दस्तावेज़](https://fastapi.tiangolo.com/hi/fastapi-cli/) में। + +
+ +### इसे जाँचें { #check-it } + +अपने ब्राउज़र में [http://127.0.0.1:8000/items/5?q=somequery](http://127.0.0.1:8000/items/5?q=somequery) खोलें। + +आपको JSON प्रतिक्रिया इस प्रकार दिखेगी: + +```JSON +{"item_id": 5, "q": "somequery"} +``` + +आपने पहले ही एक API बना ली है जो: + +* _paths_ `/` और `/items/{item_id}` पर HTTP अनुरोध स्वीकार करती है। +* दोनों _paths_ `GET` operations लेती हैं (जिन्हें HTTP _methods_ भी कहा जाता है)। +* _path_ `/items/{item_id}` में एक _path parameter_ `item_id` है जो `int` होना चाहिए। +* _path_ `/items/{item_id}` में एक वैकल्पिक `str` _query parameter_ `q` है। + +### इंटरैक्टिव API दस्तावेज़ { #interactive-api-docs } + +अब [http://127.0.0.1:8000/docs](http://127.0.0.1:8000/docs) पर जाएँ। + +आपको स्वचालित इंटरैक्टिव API दस्तावेज़ीकरण दिखेगा (जो [Swagger UI](https://github.com/swagger-api/swagger-ui) द्वारा प्रदान किया जाता है): + +![Swagger UI](https://fastapi.tiangolo.com/img/index/index-01-swagger-ui-simple.png) + +### वैकल्पिक API दस्तावेज़ { #alternative-api-docs } + +और अब, [http://127.0.0.1:8000/redoc](http://127.0.0.1:8000/redoc) पर जाएँ। + +आपको वैकल्पिक स्वचालित दस्तावेज़ीकरण दिखेगा (जो [ReDoc](https://github.com/Rebilly/ReDoc) द्वारा प्रदान किया जाता है): + +![ReDoc](https://fastapi.tiangolo.com/img/index/index-02-redoc-simple.png) + +## उदाहरण उन्नयन { #example-upgrade } + +अब `PUT` अनुरोध से body प्राप्त करने के लिए `main.py` फ़ाइल संशोधित करें। + +Pydantic की बदौलत, body को मानक Python प्रकारों से घोषित करें। + +```Python hl_lines="2 7-10 23-25" +from fastapi import FastAPI +from pydantic import BaseModel + +app = FastAPI() + + +class Item(BaseModel): + name: str + price: float + is_offer: bool | None = None + + +@app.get("/") +def read_root(): + return {"Hello": "World"} + + +@app.get("/items/{item_id}") +def read_item(item_id: int, q: str | None = None): + return {"item_id": item_id, "q": q} + + +@app.put("/items/{item_id}") +def update_item(item_id: int, item: Item): + return {"item_name": item.name, "item_id": item_id} +``` + +`fastapi dev` सर्वर स्वतः रीलोड होना चाहिए। + +### इंटरैक्टिव API दस्तावेज़ उन्नयन { #interactive-api-docs-upgrade } + +अब [http://127.0.0.1:8000/docs](http://127.0.0.1:8000/docs) पर जाएँ। + +* इंटरैक्टिव API दस्तावेज़ स्वतः अपडेट हो जाएगा, नए body सहित: + +![Swagger UI](https://fastapi.tiangolo.com/img/index/index-03-swagger-02.png) + +* "Try it out" बटन पर क्लिक करें, यह आपको parameters भरने और सीधे API के साथ इंटरेक्ट करने की अनुमति देता है: + +![Swagger UI interaction](https://fastapi.tiangolo.com/img/index/index-04-swagger-03.png) + +* फिर "Execute" बटन पर क्लिक करें, यूज़र इंटरफ़ेस आपकी API से संवाद करेगा, parameters भेजेगा, परिणाम प्राप्त करेगा और उन्हें स्क्रीन पर दिखाएगा: + +![Swagger UI interaction](https://fastapi.tiangolo.com/img/index/index-05-swagger-04.png) + +### वैकल्पिक API दस्तावेज़ उन्नयन { #alternative-api-docs-upgrade } + +और अब, [http://127.0.0.1:8000/redoc](http://127.0.0.1:8000/redoc) पर जाएँ। + +* वैकल्पिक दस्तावेज़ भी नए query parameter और body को दर्शाएगा: + +![ReDoc](https://fastapi.tiangolo.com/img/index/index-06-redoc-02.png) + +### पुनरावलोकन { #recap } + +संक्षेप में, आप parameters, body, आदि के प्रकार फ़ंक्शन parameters के रूप में **एक बार** घोषित करते हैं। + +आप यह मानक आधुनिक Python प्रकारों से करते हैं। + +आपको किसी नई सिंटैक्स, किसी विशेष लाइब्रेरी के methods या classes, आदि सीखने की आवश्यकता नहीं है। + +बस मानक **Python**। + +उदाहरण के लिए, एक `int` के लिए: + +```Python +item_id: int +``` + +या एक अधिक जटिल `Item` मॉडल के लिए: + +```Python +item: Item +``` + +...और केवल उसी एक घोषणा के साथ आपको मिलता है: + +* एडिटर सपोर्ट, जिसमें शामिल है: + * कम्प्लीशन। + * प्रकार जाँच। +* डेटा का वैधीकरण: + * जब डेटा अमान्य हो तो स्वतः और स्पष्ट त्रुटियाँ। + * गहराई से nested JSON objects के लिए भी वैधीकरण। +* इनपुट डेटा का रूपांतरण: नेटवर्क से Python डेटा और प्रकारों में। इनमें से पढ़ना: + * JSON। + * Path parameters। + * Query parameters। + * Cookies। + * Headers। + * Forms। + * Files। +* आउटपुट डेटा का रूपांतरण: Python डेटा और प्रकारों से नेटवर्क डेटा (JSON के रूप में) में: + * Python प्रकारों का रूपांतरण (`str`, `int`, `float`, `bool`, `list`, आदि)। + * `datetime` ऑब्जेक्ट्स। + * `UUID` ऑब्जेक्ट्स। + * डेटाबेस मॉडल्स। + * ...और बहुत कुछ। +* स्वचालित इंटरैक्टिव API दस्तावेज़ीकरण, जिनमें 2 वैकल्पिक यूज़र इंटरफ़ेस शामिल हैं: + * Swagger UI। + * ReDoc। + +--- + +पिछले कोड उदाहरण पर लौटते हुए, **FastAPI** यह करेगा: + +* `GET` और `PUT` अनुरोधों के लिए path में `item_id` है, यह सत्यापित करेगा। +* `GET` और `PUT` अनुरोधों के लिए `item_id` का प्रकार `int` है, यह सत्यापित करेगा। + * यदि नहीं है, तो क्लाइंट को एक उपयोगी, स्पष्ट त्रुटि दिखाई देगी। +* `GET` अनुरोधों के लिए यह जाँच करेगा कि `q` नाम का एक वैकल्पिक query parameter है (जैसे `http://127.0.0.1:8000/items/foo?q=somequery`)। + * क्योंकि `q` parameter `= None` के साथ घोषित है, यह वैकल्पिक है। + * `None` के बिना यह आवश्यक होता (जैसे `PUT` के मामले में body आवश्यक है)। +* `/items/{item_id}` पर `PUT` अनुरोधों के लिए, body को JSON के रूप में पढ़ेगा: + * यह जाँचेगा कि एक आवश्यक attribute `name` है जो `str` होना चाहिए। + * यह जाँचेगा कि एक आवश्यक attribute `price` है जो `float` होना चाहिए। + * यह जाँचेगा कि एक वैकल्पिक attribute `is_offer` है, जो यदि मौजूद है तो `bool` होना चाहिए। + * यह सब गहराई से nested JSON objects के लिए भी काम करेगा। +* JSON से और JSON में स्वतः रूपांतरण। +* हर चीज़ को OpenAPI के साथ दस्तावेज़ित करेगा, जिसे निम्न द्वारा उपयोग किया जा सकता है: + * इंटरैक्टिव दस्तावेज़ीकरण प्रणालियाँ। + * कई भाषाओं के लिए स्वचालित क्लाइंट कोड जनरेशन प्रणालियाँ। +* सीधे 2 इंटरैक्टिव दस्तावेज़ीकरण वेब इंटरफेसेज़ प्रदान करेगा। + +--- + +हमने केवल सतह को छुआ है, लेकिन आपको पहले ही समझ आ गया होगा कि यह सब कैसे काम करता है। + +इस पंक्ति को बदलकर देखें: + +```Python + return {"item_name": item.name, "item_id": item_id} +``` + +...यहाँ से: + +```Python + ... "item_name": item.name ... +``` + +...यहाँ तक: + +```Python + ... "item_price": item.price ... +``` + +...और देखें कि आपका एडिटर attributes को कैसे auto-complete करेगा और उनके प्रकार जानेगा: + +![editor support](https://fastapi.tiangolo.com/img/vscode-completion.png) + +अधिक फ़ीचर्स सहित एक अधिक सम्पूर्ण उदाहरण के लिए, ट्यूटोरियल - यूज़र गाइड देखें। + +**स्पॉइलर अलर्ट**: ट्यूटोरियल - यूज़र गाइड में शामिल है: + +* विभिन्न स्थानों से **parameters** की घोषणा: **headers**, **cookies**, **form fields** और **files**। +* `maximum_length` या `regex` जैसी **validation constraints** कैसे सेट करें। +* एक बहुत शक्तिशाली और उपयोग में आसान **डिपेंडेंसी इंजेक्शन** सिस्टम। +* सुरक्षा और प्रमाणीकरण, जिसमें **OAuth2** के साथ **JWT tokens** और **HTTP Basic** auth का समर्थन शामिल है। +* **गहराई से nested JSON मॉडल्स** घोषित करने की अधिक उन्नत (पर समान रूप से आसान) तकनीकें (Pydantic की बदौलत)। +* [Strawberry](https://strawberry.rocks) और अन्य लाइब्रेरीज़ के साथ **GraphQL** एकीकरण। +* कई अतिरिक्त फ़ीचर्स (Starlette की बदौलत) जैसे: + * **WebSockets** + * HTTPX और `pytest` पर आधारित अत्यंत आसान टेस्ट्स + * **CORS** + * **Cookie Sessions** + * ...आदि। + +### अपनी ऐप परिनियोजित करें (वैकल्पिक) { #deploy-your-app-optional } + +आप वैकल्पिक रूप से अपनी FastAPI ऐप को [FastAPI Cloud](https://fastapicloud.com) पर एक ही कमांड से डिप्लॉय कर सकते हैं। 🚀 + +
+ +```console +$ fastapi deploy + +Deploying to FastAPI Cloud... + +✅ Deployment successful! + +🐔 Ready the chicken! Your app is ready at https://myapp.fastapicloud.dev +``` + +
+ +CLI आपकी FastAPI एप्लिकेशन को स्वतः पहचान लेगा और उसे क्लाउड पर डिप्लॉय करेगा। यदि आप logged in नहीं हैं, तो प्रमाणीकरण प्रक्रिया पूरी करने के लिए आपका ब्राउज़र खुलेगा। + +बस इतना ही! अब आप उस URL पर अपनी ऐप एक्सेस कर सकते हैं। ✨ + +#### FastAPI Cloud के बारे में { #about-fastapi-cloud } + +**[FastAPI Cloud](https://fastapicloud.com)** को **FastAPI** के ही लेखक और टीम ने बनाया है। + +यह न्यूनतम प्रयास में किसी API को **बनाने**, **डिप्लॉय** करने और **एक्सेस** करने की प्रक्रिया को सरल बनाता है। + +यह FastAPI के साथ ऐप्स बनाने के उसी **डेवलपर अनुभव** को उन्हें क्लाउड में **डिप्लॉय** करने तक लाता है। 🎉 + +FastAPI Cloud, *FastAPI and friends* ओपन सोर्स प्रोजेक्ट्स के लिए मुख्य प्रायोजक और फंडिंग प्रदाता है। ✨ + +#### अन्य क्लाउड प्रदाताओं पर डिप्लॉय करें { #deploy-to-other-cloud-providers } + +FastAPI ओपन सोर्स है और मानकों पर आधारित है। आप FastAPI ऐप्स को किसी भी क्लाउड प्रदाता पर डिप्लॉय कर सकते हैं। + +अपने क्लाउड प्रदाता के गाइड्स का पालन करें और उनके साथ FastAPI ऐप्स डिप्लॉय करें। 🤓 + +## प्रदर्शन { #performance } + +स्वतंत्र TechEmpower बेंचमार्क दिखाते हैं कि Uvicorn के तहत चलने वाले **FastAPI** एप्लीकेशन्स [उपलब्ध सबसे तेज़ Python फ़्रेमवर्क्स में से एक](https://www.techempower.com/benchmarks/#section=test&runid=7464e520-0dc2-473d-bd34-dbdfd7e85911&hw=ph&test=query&l=zijzen-7) हैं, केवल Starlette और Uvicorn (जो FastAPI द्वारा आंतरिक रूप से उपयोग किए जाते हैं) से नीचे। (*) + +इसके बारे में अधिक समझने के लिए, [बेंचमार्क्स](https://fastapi.tiangolo.com/hi/benchmarks/) सेक्शन देखें। + +## निर्भरताएँ { #dependencies } + +FastAPI, Pydantic और Starlette पर निर्भर करता है। + +### `standard` निर्भरताएँ { #standard-dependencies } + +जब आप `pip install "fastapi[standard]"` के साथ FastAPI स्थापित करते हैं, तो यह `standard` समूह की वैकल्पिक निर्भरताओं के साथ आता है: + +Pydantic द्वारा उपयोग किया गया: + +* [`email-validator`](https://github.com/JoshData/python-email-validator) - ईमेल वैधीकरण के लिए। + +Starlette द्वारा उपयोग किया गया: + +* [`httpx`](https://www.python-httpx.org) - यदि आप `TestClient` का उपयोग करना चाहते हैं तो आवश्यक। +* [`jinja2`](https://jinja.palletsprojects.com) - यदि आप डिफ़ॉल्ट टेम्पलेट कॉन्फ़िगरेशन का उपयोग करना चाहते हैं तो आवश्यक। +* [`python-multipart`](https://github.com/Kludex/python-multipart) - यदि आप फॉर्म "पार्सिंग" का समर्थन करना चाहते हैं, `request.form()` के साथ, तो आवश्यक। + +FastAPI द्वारा उपयोग किया गया: + +* [`uvicorn`](https://www.uvicorn.dev) - वह सर्वर जो आपकी एप्लिकेशन को लोड और सर्व करता है। इसमें `uvicorn[standard]` शामिल है, जिसमें उच्च-प्रदर्शन सर्विंग के लिए कुछ निर्भरताएँ (जैसे `uvloop`) शामिल हैं। +* `fastapi-cli[standard]` - `fastapi` कमांड प्रदान करने के लिए। + * इसमें `fastapi-cloud-cli` शामिल है, जो आपको अपनी FastAPI एप्लिकेशन को [FastAPI Cloud](https://fastapicloud.com) पर डिप्लॉय करने की अनुमति देता है। + +### `standard` निर्भरताओं के बिना { #without-standard-dependencies } + +यदि आप `standard` वैकल्पिक निर्भरताओं को शामिल नहीं करना चाहते, तो आप `pip install fastapi` के साथ स्थापित कर सकते हैं, `pip install "fastapi[standard]"` के बजाय। + +### `fastapi-cloud-cli` के बिना { #without-fastapi-cloud-cli } + +यदि आप standard निर्भरताओं के साथ लेकिन `fastapi-cloud-cli` के बिना FastAPI स्थापित करना चाहते हैं, तो `pip install "fastapi[standard-no-fastapi-cloud-cli]"` के साथ स्थापित कर सकते हैं। + +### अतिरिक्त वैकल्पिक निर्भरताएँ { #additional-optional-dependencies } + +कुछ अतिरिक्त निर्भरताएँ हैं जिन्हें आप स्थापित करना चाहेंगे। + +अतिरिक्त वैकल्पिक Pydantic निर्भरताएँ: + +* [`pydantic-settings`](https://docs.pydantic.dev/latest/usage/pydantic_settings/) - सेटिंग्स प्रबंधन के लिए। +* [`pydantic-extra-types`](https://docs.pydantic.dev/latest/usage/types/extra_types/extra_types/) - Pydantic के साथ उपयोग करने के लिए अतिरिक्त प्रकारों हेतु। + +अतिरिक्त वैकल्पिक FastAPI निर्भरताएँ: + +* [`orjson`](https://github.com/ijl/orjson) - यदि आप `ORJSONResponse` उपयोग करना चाहते हैं तो आवश्यक। +* [`ujson`](https://github.com/esnme/ultrajson) - यदि आप `UJSONResponse` उपयोग करना चाहते हैं तो आवश्यक। + +## लाइसेंस { #license } + +यह प्रोजेक्ट MIT लाइसेंस की शर्तों के अंतर्गत लाइसेंस प्राप्त है। diff --git a/docs/hi/docs/translation-banner.md b/docs/hi/docs/translation-banner.md new file mode 100644 index 000000000..af9fedda8 --- /dev/null +++ b/docs/hi/docs/translation-banner.md @@ -0,0 +1,11 @@ +/// details | 🌐 एआई और मनुष्यों द्वारा किया गया अनुवाद + +यह अनुवाद मनुष्यों के मार्गदर्शन में एआई द्वारा किया गया है। 🤝 + +इसमें मूल अर्थ को गलत समझने या अप्राकृतिक लगने आदि जैसी गलतियाँ हो सकती हैं। 🤖 + +आप [हमें एआई LLM को बेहतर मार्गदर्शन करने में मदद करके](https://fastapi.tiangolo.com/hi/contributing/#translations) इस अनुवाद को बेहतर बना सकते हैं। + +[अंग्रेज़ी संस्करण](ENGLISH_VERSION_URL) + +/// diff --git a/docs/hi/llm-prompt.md b/docs/hi/llm-prompt.md new file mode 100644 index 000000000..337ea3823 --- /dev/null +++ b/docs/hi/llm-prompt.md @@ -0,0 +1,5 @@ +### Target language + +Translate to Hindi (हिन्दी). + +Language code: hi. diff --git a/docs/hi/mkdocs.yml b/docs/hi/mkdocs.yml new file mode 100644 index 000000000..de18856f4 --- /dev/null +++ b/docs/hi/mkdocs.yml @@ -0,0 +1 @@ +INHERIT: ../en/mkdocs.yml diff --git a/pyproject.toml b/pyproject.toml index 8b633a928..1030815b1 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -331,6 +331,7 @@ extend-exclude = [ "docs/uk/", "docs/zh/", "docs/zh-hant/", + "docs/hi/", "htmlcov/", "scripts/general-llm-prompt.md", "scripts/tests/test_translation_fixer/test_complex_doc/", diff --git a/scripts/docs.py b/scripts/docs.py index 5b693ba0a..8e3d5e832 100644 --- a/scripts/docs.py +++ b/scripts/docs.py @@ -31,6 +31,7 @@ SUPPORTED_LANGS = { "uk", "zh", "zh-hant", + "hi", } From 2d0047087526d2af3eca4cee77d56539c52651d1 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Fri, 19 Jun 2026 20:16:30 +0000 Subject: [PATCH 288/462] =?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 0e1881ae3..7c54f461f 100644 --- a/docs/en/docs/release-notes.md +++ b/docs/en/docs/release-notes.md @@ -11,6 +11,10 @@ hide: * ✏️ Fix grammar, typos, and broken links in docs. PR [#15694](https://github.com/fastapi/fastapi/pull/15694) by [@YuriiMotov](https://github.com/YuriiMotov). +### Translations + +* 🌐 Enable Hindi docs translations. PR [#15554](https://github.com/fastapi/fastapi/pull/15554) by [@YuriiMotov](https://github.com/YuriiMotov). + ### Internal * 📝 Tweak wording about deploying to FastAPI Cloud. PR [#15793](https://github.com/fastapi/fastapi/pull/15793) by [@tiangolo](https://github.com/tiangolo). From 22f99d9ad33676a60496379c749d3669f10f5410 Mon Sep 17 00:00:00 2001 From: Yurii Motov <109919500+YuriiMotov@users.noreply.github.com> Date: Sat, 20 Jun 2026 00:28:24 +0200 Subject: [PATCH 289/462] =?UTF-8?q?=F0=9F=94=A7=20Enable=20checking=20`rel?= =?UTF-8?q?ease-notes.md`=20for=20typos=20(#15796)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- pyproject.toml | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/pyproject.toml b/pyproject.toml index 1030815b1..e33e46fd8 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -319,7 +319,6 @@ extend-exclude = [ "docs/de/", "docs/en/data/", "docs/en/docs/img/", - "docs/en/docs/release-notes.md", "docs/es/", "docs/fr/", "docs/ja/", @@ -340,6 +339,16 @@ extend-exclude = [ "uv.lock", ] +[tool.typos.default] +extend-ignore-re = [ + # GitHub usernames in @mentions + "@[a-zA-Z0-9](?:-?[a-zA-Z0-9])*", + # Quoted typo documented in a release note + "'wll' to 'will'", + # German article title in a release note + "FastAPI Modul.", +] + [tool.typos.default.extend-identifiers] alls = "alls" From f1d750fddad90e2faad6c3cc5c85c7687b787e89 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Fri, 19 Jun 2026 22:28:49 +0000 Subject: [PATCH 290/462] =?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 7c54f461f..ba7109455 100644 --- a/docs/en/docs/release-notes.md +++ b/docs/en/docs/release-notes.md @@ -17,6 +17,7 @@ hide: ### Internal +* 🔧 Enable checking `release-notes.md` for typos. PR [#15796](https://github.com/fastapi/fastapi/pull/15796) by [@YuriiMotov](https://github.com/YuriiMotov). * 📝 Tweak wording about deploying to FastAPI Cloud. PR [#15793](https://github.com/fastapi/fastapi/pull/15793) by [@tiangolo](https://github.com/tiangolo). * 🔨 Use `gpt-5.5` model in `translate.py`, specify `-chat` to avoid warnings. PR [#15792](https://github.com/fastapi/fastapi/pull/15792) by [@YuriiMotov](https://github.com/YuriiMotov). From 4d3dc78b262c609daf8a23baa00f31221b386d52 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebasti=C3=A1n=20Ram=C3=ADrez?= Date: Sat, 20 Jun 2026 02:20:49 +0200 Subject: [PATCH 291/462] =?UTF-8?q?=E2=9C=A8=20Add=20support=20for=20`app.?= =?UTF-8?q?frontend("/",=20directory=3D"dist")`=20and=20`router.frontend("?= =?UTF-8?q?/",=20directory=3D"dist")`=20(#15800)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docs/en/docs/reference/apirouter.md | 1 + docs/en/docs/reference/fastapi.md | 1 + docs/en/docs/tutorial/frontend.md | 131 ++++ docs/en/docs/tutorial/static-files.md | 8 + docs/en/mkdocs.yml | 1 + docs_src/frontend/__init__.py | 0 docs_src/frontend/tutorial001_py310.py | 5 + docs_src/frontend/tutorial002_py310.py | 5 + docs_src/frontend/tutorial003_py310.py | 5 + docs_src/frontend/tutorial004_py310.py | 7 + docs_src/frontend/tutorial005_py310.py | 5 + docs_src/frontend/tutorial006_py310.py | 5 + fastapi/applications.py | 76 ++- fastapi/routing.py | 546 +++++++++++++++- tests/test_frontend.py | 858 +++++++++++++++++++++++++ 15 files changed, 1649 insertions(+), 5 deletions(-) create mode 100644 docs/en/docs/tutorial/frontend.md create mode 100644 docs_src/frontend/__init__.py create mode 100644 docs_src/frontend/tutorial001_py310.py create mode 100644 docs_src/frontend/tutorial002_py310.py create mode 100644 docs_src/frontend/tutorial003_py310.py create mode 100644 docs_src/frontend/tutorial004_py310.py create mode 100644 docs_src/frontend/tutorial005_py310.py create mode 100644 docs_src/frontend/tutorial006_py310.py create mode 100644 tests/test_frontend.py diff --git a/docs/en/docs/reference/apirouter.md b/docs/en/docs/reference/apirouter.md index d77364e45..819366dfb 100644 --- a/docs/en/docs/reference/apirouter.md +++ b/docs/en/docs/reference/apirouter.md @@ -13,6 +13,7 @@ from fastapi import APIRouter members: - websocket - include_router + - frontend - get - put - post diff --git a/docs/en/docs/reference/fastapi.md b/docs/en/docs/reference/fastapi.md index d5367ff34..e8ec991e5 100644 --- a/docs/en/docs/reference/fastapi.md +++ b/docs/en/docs/reference/fastapi.md @@ -18,6 +18,7 @@ from fastapi import FastAPI - openapi - websocket - include_router + - frontend - get - put - post diff --git a/docs/en/docs/tutorial/frontend.md b/docs/en/docs/tutorial/frontend.md new file mode 100644 index 000000000..9f0bc0566 --- /dev/null +++ b/docs/en/docs/tutorial/frontend.md @@ -0,0 +1,131 @@ +# Frontend { #frontend } + +You can serve static frontend apps with `app.frontend()` (or `router.frontend()`). + +This is useful for frontend tools that generate static files, like React with Vite, TanStack Router, Astro, Vue, Svelte, Angular, Solid, and others. + +With these tools, you normally have a step that builds the frontend, with a command like: + +```bash +npm run build +``` + +That would generate a directory like `./dist/` with your frontend files. + +You can use `app.frontend()` to serve that directory following the conventions needed by these frontend frameworks. + +**FastAPI** checks *path operations* first. The frontend files are checked only if no normal route matched, so your API won't be affected. + +## Serve a Frontend { #serve-a-frontend } + +After building your frontend, for example with `npm run build`, put the generated files in a directory, for example, `dist`. + +Your project structure could look like this: + +```text +. +├── pyproject.toml +├── app +│ ├── __init__.py +│ └── main.py +└── dist + ├── index.html + └── assets + └── app.js +``` + +Then serve it with `app.frontend()`: + +{* ../../docs_src/frontend/tutorial001_py310.py hl[5] *} + +With this, a request for `/assets/app.js` can serve `dist/assets/app.js`. + +If you also have a **FastAPI** *path operation*, the *path operation* wins. + +## Client-Side Routing { #client-side-routing } + +Many frontend apps, including **single-page apps** (SPAs), use client-side routing. A path like `/dashboard/settings` might not be a real file but the framework would take care of handling it. + +So, if accessing that URL directly (instead of navigating through the app), the backend should serve the frontend app from `index.html`, so that the frontend framework can then handle the client-side routing. + +For that, use `fallback="index.html"`: + +{* ../../docs_src/frontend/tutorial002_py310.py hl[5] *} + +**FastAPI** uses this fallback only for requests that look like browser navigation. Missing files like JavaScript, CSS, and images still return `404`. + +/// tip + +By default, `fallback` has a value of `fallback="auto"`. In most cases you won't need to specify `fallback`. Read below for details. + +/// + +This is what you would want with many frontend apps that use client-side routing, for example, React with TanStack Router, Vue, Angular, SvelteKit, or Solid. + +## Custom 404 Page { #custom-404-page } + +You can also serve a static `404.html` page for missing frontend paths: + +{* ../../docs_src/frontend/tutorial003_py310.py hl[5] *} + +That response keeps a status code of `404`. + +In this case, **FastAPI** won't serve `index.html` for missing frontend paths. It will return the `404.html` file instead. + +/// tip + +By default, `fallback` has a value of `fallback="auto"`. With this, if a `404.html` file is found, it will be used as the fallback automatically. + +So, you can normally omit the `fallback` argument. + +/// + +This is useful with frontend tools that generate static HTML files for each page, like Astro. + +## Fallback Auto { #fallback-auto } + +By default, `app.frontend()` uses `fallback="auto"`. + +If there is a `404.html` file in the frontend directory, missing frontend paths serve that file with status code `404`. + +Otherwise, if there is an `index.html` file, missing browser navigation paths serve `index.html`, which is what many frontend apps with client-side routing expect. + +So, in most cases you can use `app.frontend("/", directory="dist")` without specifying the `fallback` argument. + +{* ../../docs_src/frontend/tutorial001_py310.py hl[5] *} + +## Disable Fallback { #disable-fallback } + +If you don't want to serve a fallback file for missing frontend paths, use `fallback=None`: + +{* ../../docs_src/frontend/tutorial005_py310.py hl[5] *} + +Then missing frontend paths return the normal `404`. + +## Check Directory { #check-directory } + +By default, `app.frontend()` checks that the directory exists when the app is created. + +This helps catch configuration errors early. For example, if the frontend build output directory is missing, **FastAPI** will raise an error on startup. + +If your frontend files are created later, for example by a separate build step after the app object is created, set `check_dir=False`: + +{* ../../docs_src/frontend/tutorial006_py310.py hl[5] *} + +With `check_dir=False`, **FastAPI** will not check the directory when the app is created. If the configured directory is still missing when a request is handled, **FastAPI** will raise an error then. + +## Use it with `APIRouter` { #use-it-with-apirouter } + +You can also add frontend files to an `APIRouter` and include it with a prefix: + +{* ../../docs_src/frontend/tutorial004_py310.py hl[6,7] *} + +In this example, frontend paths are served under `/app`. + +Any regular *path operations* in the app will still take precedence, including in other routers. + +## Static Build Output Only { #static-build-output-only } + +`app.frontend()` serves files already generated by your frontend build. + +It does not run server-side rendering. It is for frontend frameworks that generate static files, not for frameworks that need dynamic rendering on the server for each request. diff --git a/docs/en/docs/tutorial/static-files.md b/docs/en/docs/tutorial/static-files.md index 0b73a35c1..4b5057c08 100644 --- a/docs/en/docs/tutorial/static-files.md +++ b/docs/en/docs/tutorial/static-files.md @@ -2,6 +2,14 @@ You can serve static files automatically from a directory using `StaticFiles`. +/// tip + +If you need to host a frontend, use `app.frontend()` instead, read about it in [Frontend](frontend.md). + +`app.frontend()` uses `StaticFiles` underneath, with several additional advantages for frontends, like handling client-side routing. + +/// + ## Use `StaticFiles` { #use-staticfiles } * Import `StaticFiles`. diff --git a/docs/en/mkdocs.yml b/docs/en/mkdocs.yml index 2d50ce2a4..884307dcf 100644 --- a/docs/en/mkdocs.yml +++ b/docs/en/mkdocs.yml @@ -133,6 +133,7 @@ nav: - tutorial/server-sent-events.md - tutorial/background-tasks.md - tutorial/metadata.md + - tutorial/frontend.md - tutorial/static-files.md - tutorial/testing.md - tutorial/debugging.md diff --git a/docs_src/frontend/__init__.py b/docs_src/frontend/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/docs_src/frontend/tutorial001_py310.py b/docs_src/frontend/tutorial001_py310.py new file mode 100644 index 000000000..69e6f37f9 --- /dev/null +++ b/docs_src/frontend/tutorial001_py310.py @@ -0,0 +1,5 @@ +from fastapi import FastAPI + +app = FastAPI() + +app.frontend("/", directory="dist") diff --git a/docs_src/frontend/tutorial002_py310.py b/docs_src/frontend/tutorial002_py310.py new file mode 100644 index 000000000..bb5349cde --- /dev/null +++ b/docs_src/frontend/tutorial002_py310.py @@ -0,0 +1,5 @@ +from fastapi import FastAPI + +app = FastAPI() + +app.frontend("/", directory="dist", fallback="index.html") diff --git a/docs_src/frontend/tutorial003_py310.py b/docs_src/frontend/tutorial003_py310.py new file mode 100644 index 000000000..d0a526632 --- /dev/null +++ b/docs_src/frontend/tutorial003_py310.py @@ -0,0 +1,5 @@ +from fastapi import FastAPI + +app = FastAPI() + +app.frontend("/", directory="dist", fallback="404.html") diff --git a/docs_src/frontend/tutorial004_py310.py b/docs_src/frontend/tutorial004_py310.py new file mode 100644 index 000000000..647e92d10 --- /dev/null +++ b/docs_src/frontend/tutorial004_py310.py @@ -0,0 +1,7 @@ +from fastapi import APIRouter, FastAPI + +app = FastAPI() +router = APIRouter() + +router.frontend("/", directory="dist", fallback="index.html") +app.include_router(router, prefix="/app") diff --git a/docs_src/frontend/tutorial005_py310.py b/docs_src/frontend/tutorial005_py310.py new file mode 100644 index 000000000..a167824af --- /dev/null +++ b/docs_src/frontend/tutorial005_py310.py @@ -0,0 +1,5 @@ +from fastapi import FastAPI + +app = FastAPI() + +app.frontend("/", directory="dist", fallback=None) diff --git a/docs_src/frontend/tutorial006_py310.py b/docs_src/frontend/tutorial006_py310.py new file mode 100644 index 000000000..451d2416d --- /dev/null +++ b/docs_src/frontend/tutorial006_py310.py @@ -0,0 +1,5 @@ +from fastapi import FastAPI + +app = FastAPI() + +app.frontend("/", directory="dist", check_dir=False) diff --git a/fastapi/applications.py b/fastapi/applications.py index c7c551e4e..56e1a3e60 100644 --- a/fastapi/applications.py +++ b/fastapi/applications.py @@ -1,6 +1,7 @@ +import os from collections.abc import Awaitable, Callable, Coroutine, Sequence from enum import Enum -from typing import Annotated, Any, TypeVar +from typing import Annotated, Any, Literal, TypeVar from annotated_doc import Doc from fastapi import routing @@ -1218,6 +1219,79 @@ class FastAPI(Starlette): generate_unique_id_function=generate_unique_id_function, ) + def frontend( + self, + path: Annotated[ + str, + Doc( + """ + The URL path prefix where the frontend build should be served. + """ + ), + ], + *, + directory: Annotated[ + str | os.PathLike[str], + Doc( + """ + The directory containing the static frontend build output. + """ + ), + ], + fallback: Annotated[ + Literal["auto", "index.html", "404.html"] | None, + Doc( + """ + The fallback file behavior for missing frontend paths. + """ + ), + ] = "auto", + check_dir: Annotated[ + bool, + Doc( + """ + Check that the frontend directory exists when the app is created. + """ + ), + ] = True, + ) -> None: + """ + Serve a static frontend build as low-priority routes. + + Use this for frontend tools that build static files into a directory, + such as `dist`. **FastAPI** path operations are checked first, and + the frontend files are checked only if no normal route matched. + + A typical project could look like this: + + ```text + . + ├── pyproject.toml + ├── app + │ ├── __init__.py + │ └── main.py + └── dist + ├── index.html + └── assets + └── app.js + ``` + + Then in `app/main.py`: + + ```python + from fastapi import FastAPI + + app = FastAPI() + app.frontend("/", directory="dist") + ``` + """ + self.router.frontend( + path, + directory=directory, + fallback=fallback, + check_dir=check_dir, + ) + def api_route( self, path: str, diff --git a/fastapi/routing.py b/fastapi/routing.py index 4a55fda8a..bd6289b58 100644 --- a/fastapi/routing.py +++ b/fastapi/routing.py @@ -1,9 +1,12 @@ import contextlib import copy import email.message +import errno import functools import inspect import json +import os +import stat import types from collections.abc import ( AsyncIterator, @@ -28,6 +31,7 @@ from enum import Enum, IntEnum from typing import ( Annotated, Any, + Literal, Protocol, TypeVar, cast, @@ -80,22 +84,25 @@ from starlette import routing from starlette._exception_handler import wrap_app_handling_exceptions from starlette._utils import get_route_path, is_async_callable from starlette.concurrency import iterate_in_threadpool, run_in_threadpool -from starlette.datastructures import FormData, URLPath +from starlette.datastructures import URL, FormData, URLPath from starlette.exceptions import HTTPException from starlette.requests import Request from starlette.responses import ( JSONResponse, PlainTextResponse, + RedirectResponse, Response, StreamingResponse, ) from starlette.routing import ( BaseRoute, Match, + NoMatchFound, compile_path, get_name, ) from starlette.routing import Mount as Mount # noqa +from starlette.staticfiles import StaticFiles from starlette.types import AppType, ASGIApp, Lifespan, Receive, Scope, Send from starlette.websockets import WebSocket from typing_extensions import deprecated @@ -819,6 +826,7 @@ class APIWebSocketRoute(routing.WebSocketRoute): _FASTAPI_SCOPE_KEY = "fastapi" _FASTAPI_EFFECTIVE_ROUTE_CONTEXT_KEY = "effective_route_context" +_FASTAPI_FRONTEND_PATH_KEY = "frontend_path" _FASTAPI_INCLUDED_ROUTER_KEY = "included_router" _effective_route_context_var: ContextVar[Any | None] = ContextVar( "fastapi_effective_route_context", default=None @@ -826,12 +834,25 @@ _effective_route_context_var: ContextVar[Any | None] = ContextVar( _SCOPE_MISSING = object() +class _RouteWithPath(Protocol): + path: str + + def _get_fastapi_scope(scope: Scope) -> dict[str, Any]: fastapi_scope = scope.setdefault(_FASTAPI_SCOPE_KEY, {}) assert isinstance(fastapi_scope, dict) return fastapi_scope +def _update_scope(scope: Scope, child_scope: Scope) -> None: + fastapi_child_scope = child_scope.get(_FASTAPI_SCOPE_KEY) + for key, value in child_scope.items(): + if key != _FASTAPI_SCOPE_KEY: + scope[key] = value + if isinstance(fastapi_child_scope, dict): + _get_fastapi_scope(scope).update(fastapi_child_scope) + + def _get_scope_effective_route_context(scope: Scope) -> Any | None: return scope.get(_FASTAPI_SCOPE_KEY, {}).get(_FASTAPI_EFFECTIVE_ROUTE_CONTEXT_KEY) @@ -1305,9 +1326,7 @@ class _RouterIncludeContext: dependency_overrides_provider=self.dependency_overrides_provider, ) - def path_for( - self, route: APIRoute | routing.Route | routing.WebSocketRoute | routing.Mount - ) -> str: + def path_for(self, route: _RouteWithPath) -> str: return self.prefix + route.path @@ -1503,6 +1522,10 @@ class _IncludedRouter(BaseRoute): default_factory=list ) _effective_candidates_version: int | None = None + _effective_low_priority_routes: list["_EffectiveRouteContext"] = field( + default_factory=list + ) + _effective_low_priority_routes_version: int | None = None def effective_candidates(self) -> list["_EffectiveRouteContext | _IncludedRouter"]: routes_version = self.original_router._get_routes_version() @@ -1525,6 +1548,28 @@ class _IncludedRouter(BaseRoute): self._effective_candidates_version = routes_version return self._effective_candidates + def effective_low_priority_routes(self) -> list["_EffectiveRouteContext"]: + routes_version = self.original_router._get_routes_version() + if routes_version == self._effective_low_priority_routes_version: + return self._effective_low_priority_routes + self._effective_low_priority_routes = [] + for route in self.original_router._low_priority_routes: + route_context = self._build_effective_context(route) + if route_context is not None: + self._effective_low_priority_routes.append(route_context) + for route in self.original_router.routes: + if isinstance(route, _IncludedRouter): + child_context = self.include_context.combine(route.include_context) + child_branch = _IncludedRouter( + original_router=route.original_router, + include_context=child_context, + ) + self._effective_low_priority_routes.extend( + child_branch.effective_low_priority_routes() + ) + self._effective_low_priority_routes_version = routes_version + return self._effective_low_priority_routes + def _build_effective_context( self, route: BaseRoute ) -> _EffectiveRouteContext | None: @@ -1533,6 +1578,11 @@ class _IncludedRouter(BaseRoute): original_route=route, include_context=self.include_context, ) + if isinstance(route, _FrontendRouteGroup): + return _EffectiveRouteContext( + original_route=route, + starlette_route=route.with_prefix(self.include_context.prefix), + ) if isinstance(route, routing.Route): starlette_route: BaseRoute = routing.Route( self.include_context.path_for(route), @@ -1720,6 +1770,294 @@ def _iter_routes_with_context( yield route, None +def _normalize_frontend_path(path: str) -> str: + if not path: + raise AssertionError("A frontend path cannot be empty") + if not path.startswith("/"): + raise AssertionError("A frontend path must start with '/'") + if path != "/": + path = path.rstrip("/") + return path + + +def _join_frontend_paths(prefix: str, path: str) -> str: + if not prefix: + return path + if path == "/": + return prefix + return prefix + path + + +def _frontend_path_specificity(path: str) -> int: + if path == "/": + return 0 + return len(path) + + +def _get_resolved_absolute_path(path: str | os.PathLike[str]) -> str: + return os.path.realpath(os.fspath(path)) + + +class _FrontendStaticFiles(StaticFiles): + def __init__( + self, + *, + directory: str | os.PathLike[str], + fallback: Literal["auto", "index.html", "404.html"] | None, + check_dir: bool = True, + ) -> None: + self.fallback = fallback + if check_dir and not os.path.isdir(directory): + raise RuntimeError( + f"Frontend directory {directory!r} does not exist. " + f"Resolved absolute path: {_get_resolved_absolute_path(directory)!r}" + ) + super().__init__( + directory=directory, + html=True, + check_dir=check_dir, + follow_symlink=False, + ) + if check_dir and fallback in {"index.html", "404.html"}: + self._check_fallback_file(fallback) + + def _check_fallback_file(self, fallback: str) -> None: + _, stat_result = self.lookup_path(fallback) + if stat_result is None or not stat.S_ISREG(stat_result.st_mode): + raise RuntimeError( + f"Frontend fallback file '{fallback}' does not exist in " + f"directory '{self.directory}'. Resolved absolute directory: " + f"'{self._get_resolved_directory()}'" + ) + + def _get_resolved_directory(self) -> str: + assert self.directory is not None + return _get_resolved_absolute_path(self.directory) + + def get_path(self, scope: Scope) -> str: + path = _get_fastapi_scope(scope).get(_FASTAPI_FRONTEND_PATH_KEY, "") + assert isinstance(path, str) + return os.path.normpath(os.path.join(*path.split("/"))) + + async def get_response(self, path: str, scope: Scope) -> Response: + if scope["method"] not in ("GET", "HEAD"): + raise HTTPException(status_code=405) + + try: + full_path, stat_result = await run_in_threadpool(self.lookup_path, path) + except PermissionError: + raise HTTPException(status_code=401) from None + except OSError as exc: + if exc.errno == errno.ENAMETOOLONG: + raise HTTPException(status_code=404) from None + raise exc + except ValueError: + raise HTTPException(status_code=404) from None + + if stat_result and stat.S_ISREG(stat_result.st_mode): + return self.file_response(full_path, stat_result, scope) + + if stat_result and stat.S_ISDIR(stat_result.st_mode): + index_path = os.path.join(path, "index.html") + full_path, stat_result = await run_in_threadpool( + self.lookup_path, index_path + ) + if stat_result is not None and stat.S_ISREG(stat_result.st_mode): + if not scope["path"].endswith("/"): + url = URL(scope=scope) + url = url.replace(path=url.path + "/") + return RedirectResponse(url=url) + return self.file_response(full_path, stat_result, scope) + + if self.fallback == "404.html" or ( + self.fallback == "auto" and self._fallback_file_exists("404.html") + ): + return await self._fallback_response("404.html", scope, status_code=404) + + if ( + self.fallback == "index.html" + or (self.fallback == "auto" and self._fallback_file_exists("index.html")) + ) and _is_frontend_navigation_request(scope): + return await self._fallback_response("index.html", scope, status_code=200) + + raise HTTPException(status_code=404) + + def _fallback_file_exists(self, fallback: str) -> bool: + _, stat_result = self.lookup_path(fallback) + return stat_result is not None and stat.S_ISREG(stat_result.st_mode) + + async def _fallback_response( + self, fallback: str, scope: Scope, *, status_code: int + ) -> Response: + full_path, stat_result = await run_in_threadpool(self.lookup_path, fallback) + if stat_result is None or not stat.S_ISREG(stat_result.st_mode): + raise RuntimeError( + f"Frontend fallback file '{fallback}' does not exist in " + f"directory '{self.directory}'. Resolved absolute directory: " + f"'{self._get_resolved_directory()}'" + ) + return self.file_response( + full_path, stat_result, scope, status_code=status_code + ) + + +def _iter_accept_media_types(accept: str) -> Iterator[tuple[str, float]]: + for raw_value in accept.split(","): + message = email.message.Message() + message["content-type"] = raw_value.strip() + q = message.get_param("q") + quality = 1.0 + if isinstance(q, str): + try: + quality = float(q) + except ValueError: + pass + yield ( + f"{message.get_content_maintype()}/{message.get_content_subtype()}", + quality, + ) + + +def _is_frontend_navigation_request(scope: Scope) -> bool: + route_path = get_route_path(scope) + final_segment = route_path.rsplit("/", 1)[-1] + if os.path.splitext(final_segment)[1]: + return False + request = Request(scope) + wildcard_accepted = False + html_rejected = False + for media_type, quality in _iter_accept_media_types( + request.headers.get("accept", "") + ): + if media_type in {"text/html", "application/xhtml+xml"}: + if quality == 0: + html_rejected = True + else: + return True + elif media_type == "*/*" and quality != 0: + wildcard_accepted = True + return wildcard_accepted and not html_rejected + + +class _FrontendRoute(BaseRoute): + def __init__( + self, + path: str, + *, + directory: str | os.PathLike[str], + fallback: Literal["auto", "index.html", "404.html"] | None = "auto", + check_dir: bool = True, + ) -> None: + if fallback not in {"auto", "index.html", "404.html", None}: + raise AssertionError( + "fallback must be 'auto', 'index.html', '404.html', or None" + ) + self.path = _normalize_frontend_path(path) + self.methods = {"GET", "HEAD"} + self.app = _FrontendStaticFiles( + directory=directory, fallback=fallback, check_dir=check_dir + ) + + def with_path(self, path: str) -> "_FrontendRoute": + route = copy.copy(self) + route.path = _normalize_frontend_path(path) + return route + + def matches(self, scope: Scope) -> tuple[Match, Scope]: + if scope["type"] != "http": + return Match.NONE, {} + frontend_path = self._get_frontend_path(get_route_path(scope)) + if frontend_path is None: + return Match.NONE, {} + child_scope = {_FASTAPI_SCOPE_KEY: {_FASTAPI_FRONTEND_PATH_KEY: frontend_path}} + if scope["method"] not in self.methods: + return Match.PARTIAL, child_scope + return Match.FULL, child_scope + + def _get_frontend_path(self, route_path: str) -> str | None: + if self.path == "/": + return route_path.lstrip("/") + if route_path == self.path: + return "" + prefix = self.path + "/" + if route_path.startswith(prefix): + return route_path[len(prefix) :] + return None + + async def handle(self, scope: Scope, receive: Receive, send: Send) -> None: + await self.app(scope, receive, send) + + def url_path_for(self, name: str, /, **path_params: Any) -> URLPath: + raise NoMatchFound(name, path_params) + + +class _FrontendRouteGroup(BaseRoute): + def __init__(self) -> None: + self.routes: list[_FrontendRoute] = [] + + def add_frontend_route( + self, + path: str, + *, + directory: str | os.PathLike[str], + fallback: Literal["auto", "index.html", "404.html"] | None = "auto", + check_dir: bool = True, + ) -> None: + self.routes.append( + _FrontendRoute( + path, + directory=directory, + fallback=fallback, + check_dir=check_dir, + ) + ) + + def with_prefix(self, prefix: str) -> "_FrontendRouteGroup": + route_group = copy.copy(self) + route_group.routes = [ + route.with_path(_join_frontend_paths(prefix, route.path)) + for route in self.routes + ] + return route_group + + def matches(self, scope: Scope) -> tuple[Match, Scope]: + match, child_scope, _ = self._match(scope) + return match, child_scope + + def _match(self, scope: Scope) -> tuple[Match, Scope, _FrontendRoute | None]: + full: tuple[Scope, _FrontendRoute] | None = None + partial: tuple[Scope, _FrontendRoute] | None = None + for route in self.routes: + match, child_scope = route.matches(scope) + if match == Match.FULL: + if full is None or _frontend_path_specificity( + route.path + ) > _frontend_path_specificity(full[1].path): + full = (child_scope, route) + elif match == Match.PARTIAL: + if partial is None or _frontend_path_specificity( + route.path + ) > _frontend_path_specificity(partial[1].path): + partial = (child_scope, route) + if full is not None: + child_scope, route = full + return Match.FULL, child_scope, route + if partial is not None: + child_scope, route = partial + return Match.PARTIAL, child_scope, route + return Match.NONE, {}, None + + async def handle(self, scope: Scope, receive: Receive, send: Send) -> None: + match, child_scope, route = self._match(scope) + if match == Match.NONE or route is None: + raise HTTPException(status_code=404) + _update_scope(scope, child_scope) + await route.handle(scope, receive, send) + + def url_path_for(self, name: str, /, **path_params: Any) -> URLPath: + raise NoMatchFound(name, path_params) + + class APIRouter(routing.Router): """ `APIRouter` class, used to group *path operations*, for example to structure @@ -2032,6 +2370,8 @@ class APIRouter(routing.Router): self.generate_unique_id_function = generate_unique_id_function self.strict_content_type = strict_content_type self._routes_version = 0 + self._low_priority_routes: list[BaseRoute] = [] + self._frontend_routes: _FrontendRouteGroup | None = None def _mark_routes_changed(self) -> None: self._routes_version += 1 @@ -2093,6 +2433,150 @@ class APIRouter(routing.Router): super().add_websocket_route(path, endpoint, name=name) self._mark_routes_changed() + def frontend( + self, + path: Annotated[ + str, + Doc( + """ + The URL path prefix where the frontend build should be served. + """ + ), + ], + *, + directory: Annotated[ + str | os.PathLike[str], + Doc( + """ + The directory containing the static frontend build output. + """ + ), + ], + fallback: Annotated[ + Literal["auto", "index.html", "404.html"] | None, + Doc( + """ + The fallback file behavior for missing frontend paths. + """ + ), + ] = "auto", + check_dir: Annotated[ + bool, + Doc( + """ + Check that the frontend directory exists when the app is created. + """ + ), + ] = True, + ) -> None: + """ + Serve a static frontend build as low-priority routes. + + Use this for frontend tools that build static files into a directory, + such as `dist`. **FastAPI** path operations are checked first, and + the frontend files are checked only if no normal route matched. + + A typical project could look like this: + + ```text + . + ├── pyproject.toml + ├── app + │ ├── __init__.py + │ └── main.py + └── dist + ├── index.html + └── assets + └── app.js + ``` + + Then in `app/main.py`: + + ```python + from fastapi import APIRouter, FastAPI + + app = FastAPI() + router = APIRouter() + router.frontend("/", directory="dist") + app.include_router(router) + ``` + """ + normalized_path = _normalize_frontend_path(path) + if self._frontend_routes is None: + self._frontend_routes = _FrontendRouteGroup() + self._low_priority_routes.append(self._frontend_routes) + self._frontend_routes.add_frontend_route( + _join_frontend_paths(self.prefix, normalized_path), + directory=directory, + fallback=fallback, + check_dir=check_dir, + ) + self._mark_routes_changed() + + async def app(self, scope: Scope, receive: Receive, send: Send) -> None: + assert scope["type"] in ("http", "websocket", "lifespan") + + if "router" not in scope: + scope["router"] = self + + if scope["type"] == "lifespan": + await self.lifespan(scope, receive, send) + return + + partial: tuple[BaseRoute, Scope] | None = None + for route in self.routes: + match, child_scope = route.matches(scope) + if match == Match.FULL: + scope.update(child_scope) + await route.handle(scope, receive, send) + return + if match == Match.PARTIAL and partial is None: + partial = (route, child_scope) + + if partial is not None: + route, child_scope = partial + scope.update(child_scope) + await route.handle(scope, receive, send) + return + + route_path = get_route_path(scope) + if scope["type"] == "http" and self.redirect_slashes and route_path != "/": + redirect_scope = dict(scope) + if route_path.endswith("/"): + redirect_scope["path"] = redirect_scope["path"].rstrip("/") + else: + redirect_scope["path"] = redirect_scope["path"] + "/" + + for route in self.routes: + match, _ = route.matches(redirect_scope) + if match != Match.NONE: + redirect_url = URL(scope=redirect_scope) + response = RedirectResponse(url=str(redirect_url)) + await response(scope, receive, send) + return + + ( + low_priority_match, + low_priority_scope, + low_priority_route, + low_priority_context, + ) = self._match_low_priority(scope) + if low_priority_match != Match.NONE and low_priority_route is not None: + _update_scope(scope, low_priority_scope) + if low_priority_context is not None: + _get_fastapi_scope(scope)[_FASTAPI_EFFECTIVE_ROUTE_CONTEXT_KEY] = ( + low_priority_context + ) + original_route = low_priority_context.original_route + if isinstance(original_route, APIRoute): + scope["route"] = original_route + await original_route.handle(scope, receive, send) + return + await low_priority_route.handle(scope, receive, send) + return + + await self.default(scope, receive, send) + async def handle(self, scope: Scope, receive: Receive, send: Send) -> None: included_router = _get_scope_included_router(scope) if ( @@ -2113,6 +2597,60 @@ class APIRouter(routing.Router): return match, child_scope return Match.NONE, {} + def _iter_low_priority_routes( + self, + ) -> Iterator[BaseRoute | _EffectiveRouteContext]: + yield from self._low_priority_routes + for route in self.routes: + if isinstance(route, _IncludedRouter): + yield from route.effective_low_priority_routes() + + def _match_low_priority( + self, scope: Scope + ) -> tuple[Match, Scope, BaseRoute | None, _EffectiveRouteContext | None]: + full: tuple[Scope, BaseRoute, _EffectiveRouteContext | None] | None = None + partial: tuple[Scope, BaseRoute, _EffectiveRouteContext | None] | None = None + for candidate in self._iter_low_priority_routes(): + route: BaseRoute + if isinstance(candidate, _EffectiveRouteContext): + route_context: _EffectiveRouteContext | None = candidate + original_route = candidate.original_route + if isinstance(original_route, APIRoute): + fastapi_scope = _get_fastapi_scope(scope) + previous_context = fastapi_scope.get( + _FASTAPI_EFFECTIVE_ROUTE_CONTEXT_KEY, _SCOPE_MISSING + ) + fastapi_scope[_FASTAPI_EFFECTIVE_ROUTE_CONTEXT_KEY] = route_context + try: + match, child_scope = original_route.matches(scope) + finally: + _restore_fastapi_scope_key( + scope, + _FASTAPI_EFFECTIVE_ROUTE_CONTEXT_KEY, + previous_context, + ) + route = original_route + else: + match, child_scope = candidate.matches(scope) + route = candidate.starlette_route or original_route + else: + route_context = None + match, child_scope = candidate.matches(scope) + route = candidate + if match == Match.FULL: + if full is None: + full = (child_scope, route, route_context) + elif match == Match.PARTIAL: + if partial is None: + partial = (child_scope, route, route_context) + if full is not None: + child_scope, route, route_context = full + return Match.FULL, child_scope, route, route_context + if partial is not None: + child_scope, route, route_context = partial + return Match.PARTIAL, child_scope, route, route_context + return Match.NONE, {}, None, None + def route( self, path: str, diff --git a/tests/test_frontend.py b/tests/test_frontend.py new file mode 100644 index 000000000..12be8eaf2 --- /dev/null +++ b/tests/test_frontend.py @@ -0,0 +1,858 @@ +import errno +import os +import runpy +from pathlib import Path + +import anyio +import pytest +from fastapi import APIRouter, FastAPI, HTTPException, Request, WebSocket +from fastapi.testclient import TestClient +from starlette.exceptions import HTTPException as StarletteHTTPException +from starlette.responses import PlainTextResponse, Response +from starlette.routing import BaseRoute, Match, NoMatchFound, Route + + +def write_file(path: Path, content: str) -> None: + path.parent.mkdir(parents=True, exist_ok=True) + path.write_text(content) + + +def test_frontend_exact_prefix_path_serves_index(tmp_path: Path): + dist = tmp_path / "dist" + write_file(dist / "index.html", "app") + app = FastAPI() + app.frontend("/app", directory=dist) + + response = TestClient(app).get("/app") + + assert response.status_code == 200 + assert response.text == "app" + + +def test_apirouter_frontend_with_router_prefix_and_frontend_subpath(tmp_path: Path): + dist = tmp_path / "dist" + write_file(dist / "asset.txt", "asset") + router = APIRouter(prefix="/internal") + router.frontend("/ui", directory=dist) + app = FastAPI() + app.include_router(router, prefix="/prefix") + + response = TestClient(app).get("/prefix/internal/ui/asset.txt") + + assert response.status_code == 200 + assert response.text == "asset" + + +def test_frontend_fallback_rejects_invalid_fallback(tmp_path: Path): + dist = tmp_path / "dist" + dist.mkdir() + app = FastAPI() + + with pytest.raises(AssertionError, match="fallback"): + app.frontend("/", directory=dist, fallback="invalid") # type: ignore[arg-type] # ty: ignore[invalid-argument-type] + + +def test_index_fallback_ignores_invalid_q_value(tmp_path: Path): + dist = tmp_path / "dist" + write_file(dist / "index.html", "app shell") + app = FastAPI() + app.frontend("/", directory=dist, fallback="index.html") + + response = TestClient(app).get( + "/dashboard/settings", headers={"accept": "text/html; q=wat"} + ) + + assert response.status_code == 200 + assert response.text == "app shell" + + +def test_frontend_static_files_lookup_errors(monkeypatch, tmp_path: Path): + dist = tmp_path / "dist" + write_file(dist / "index.html", "app") + app = FastAPI() + app.frontend("/", directory=dist) + frontend_routes = app.router._frontend_routes + assert frontend_routes is not None + static_files = frontend_routes.routes[0].app + + def raise_permission_error(path: str): + raise PermissionError + + monkeypatch.setattr(static_files, "lookup_path", raise_permission_error) + response = TestClient(app).get("/asset.txt") + assert response.status_code == 401 + + def raise_value_error(path: str): + raise ValueError + + monkeypatch.setattr(static_files, "lookup_path", raise_value_error) + response = TestClient(app).get("/asset.txt") + assert response.status_code == 404 + + def raise_name_too_long(path: str): + raise OSError(errno.ENAMETOOLONG, "name too long") + + monkeypatch.setattr(static_files, "lookup_path", raise_name_too_long) + response = TestClient(app).get("/asset.txt") + assert response.status_code == 404 + + def raise_os_error(path: str): + raise OSError(5, "other") + + monkeypatch.setattr(static_files, "lookup_path", raise_os_error) + with pytest.raises(OSError): + TestClient(app).get("/asset.txt") + + +def test_frontend_route_group_helpers(tmp_path: Path): + dist = tmp_path / "dist" + write_file(dist / "index.html", "app") + app = FastAPI() + app.frontend("/", directory=dist) + route_group = app.router._frontend_routes + assert route_group is not None + + match, child_scope = route_group.matches({"type": "websocket", "path": "/"}) + assert match == Match.NONE + assert child_scope == {} + + with pytest.raises(StarletteHTTPException) as exc_info: + anyio.run( + route_group.with_prefix("/app").handle, + {"type": "http", "path": "/missing", "method": "GET"}, + None, + None, + ) + assert exc_info.value.status_code == 404 + + with pytest.raises(NoMatchFound): + route_group.url_path_for("frontend") + with pytest.raises(NoMatchFound): + route_group.routes[0].url_path_for("frontend") + + +def test_included_low_priority_routes_cache_is_reused(): + async def low_priority_endpoint(request: Request): + return PlainTextResponse("low") + + router = APIRouter() + router._low_priority_routes.append(Route("/low", low_priority_endpoint)) + router._mark_routes_changed() + app = FastAPI() + app.include_router(router, prefix="/prefix") + included_router = next( + route + for route in app.router.routes + if hasattr(route, "effective_low_priority_routes") + ) + + first = included_router.effective_low_priority_routes() # ty: ignore[call-non-callable] + second = included_router.effective_low_priority_routes() # ty: ignore[call-non-callable] + response = TestClient(app).get("/prefix/low") + + assert first is second + assert response.status_code == 200 + assert response.text == "low" + + +def test_low_priority_api_route_handles_with_context(): + app = FastAPI() + + async def endpoint(request: Request) -> Response: + return PlainTextResponse(request.scope["path_params"]["item_id"]) + + route = app.router.route_class("/low/{item_id}", endpoint=endpoint, methods=["GET"]) + app.router._low_priority_routes.append(route) + app.router._mark_routes_changed() + + response = TestClient(app).get("/low/abc") + + assert response.status_code == 200 + assert response.text == "abc" + + +def test_included_low_priority_api_route_handles_with_context(): + router = APIRouter() + + async def endpoint(request: Request) -> Response: + return PlainTextResponse(request.scope["path_params"]["item_id"]) + + route = router.route_class("/low/{item_id}", endpoint=endpoint, methods=["GET"]) + router._low_priority_routes.append(route) + router._mark_routes_changed() + app = FastAPI() + app.include_router(router, prefix="/prefix") + + response = TestClient(app).get("/prefix/low/abc") + + assert response.status_code == 200 + assert response.text == "abc" + + +def test_normal_route_partial_match_returns_before_frontend(tmp_path: Path): + class PartialRoute(BaseRoute): + def matches(self, scope): + return Match.PARTIAL, {} + + async def handle(self, scope, receive, send): + response = PlainTextResponse("partial", status_code=405) + await response(scope, receive, send) + + dist = tmp_path / "dist" + write_file(dist / "index.html", "frontend") + app = FastAPI() + app.router.routes.append(PartialRoute()) + app.frontend("/", directory=dist) + + response = TestClient(app).get("/anything") + + assert response.status_code == 405 + assert response.text == "partial" + + +def test_normal_route_partial_match_wins_before_frontend(tmp_path: Path): + dist = tmp_path / "dist" + write_file(dist / "api", "frontend") + app = FastAPI() + + @app.get("/api") + def read_api(): + return {"source": "api"} + + app.frontend("/", directory=dist) + + client = TestClient(app) + + response = client.get("/api") + assert response.status_code == 200 + assert response.json() == {"source": "api"} + + response = client.post("/api") + assert response.status_code == 405 + + +def test_basic_file_serving(tmp_path: Path): + dist = tmp_path / "dist" + write_file(dist / "assets" / "app.js", "console.log('ok')") + app = FastAPI() + app.frontend("/", directory=dist) + + response = TestClient(app).get("/assets/app.js") + + assert response.status_code == 200 + assert response.text == "console.log('ok')" + assert "etag" in response.headers + assert "last-modified" in response.headers + + +def test_existing_api_route_wins_over_frontend(tmp_path: Path): + dist = tmp_path / "dist" + write_file(dist / "api" / "users", "frontend") + app = FastAPI() + + @app.get("/api/users") + def read_users(): + return {"source": "api"} + + app.frontend("/", directory=dist) + + response = TestClient(app).get("/api/users") + + assert response.status_code == 200 + assert response.json() == {"source": "api"} + + +def test_api_route_404_is_not_replaced_by_frontend_fallback(tmp_path: Path): + dist = tmp_path / "dist" + write_file(dist / "index.html", "frontend") + app = FastAPI() + + @app.get("/api/users") + def read_users(): + raise HTTPException(status_code=404, detail="api missing") + + app.frontend("/", directory=dist, fallback="index.html") + + response = TestClient(app).get("/api/users", headers={"accept": "text/html"}) + + assert response.status_code == 404 + assert response.json() == {"detail": "api missing"} + + +def test_index_fallback_for_navigation_request(tmp_path: Path): + dist = tmp_path / "dist" + write_file(dist / "index.html", "app shell") + app = FastAPI() + app.frontend("/", directory=dist, fallback="index.html") + + response = TestClient(app).get( + "/dashboard/settings", headers={"accept": "text/html"} + ) + + assert response.status_code == 200 + assert response.text == "app shell" + + +def test_index_fallback_parses_accept_parameters(tmp_path: Path): + dist = tmp_path / "dist" + write_file(dist / "index.html", "app shell") + app = FastAPI() + app.frontend("/", directory=dist, fallback="index.html") + + response = TestClient(app).get( + "/dashboard/settings", headers={"accept": "text/html; q=0.8"} + ) + + assert response.status_code == 200 + assert response.text == "app shell" + + +def test_index_fallback_ignores_q_zero_accept(tmp_path: Path): + dist = tmp_path / "dist" + write_file(dist / "index.html", "app shell") + app = FastAPI() + app.frontend("/", directory=dist, fallback="index.html") + + response = TestClient(app).get( + "/dashboard/settings", headers={"accept": "text/html; q=0.0"} + ) + + assert response.status_code == 404 + + +def test_index_fallback_respects_explicit_html_rejection_with_wildcard( + tmp_path: Path, +): + dist = tmp_path / "dist" + write_file(dist / "index.html", "app shell") + app = FastAPI() + app.frontend("/", directory=dist, fallback="index.html") + + response = TestClient(app).get( + "/dashboard/settings", + headers={"accept": "text/html; q=0, */*; q=1"}, + ) + + assert response.status_code == 404 + + +def test_index_fallback_respects_explicit_xhtml_rejection_with_wildcard( + tmp_path: Path, +): + dist = tmp_path / "dist" + write_file(dist / "index.html", "app shell") + app = FastAPI() + app.frontend("/", directory=dist, fallback="index.html") + + response = TestClient(app).get( + "/dashboard/settings", + headers={"accept": "application/xhtml+xml; q=0, */*; q=1"}, + ) + + assert response.status_code == 404 + + +@pytest.mark.parametrize( + ("path", "accept"), + [ + ("/assets/missing.js", "*/*"), + ("/assets/missing.css", "text/css"), + ("/assets/missing.png", "image/png"), + ("/api/missing", "application/json"), + ("/users/jane.doe", "text/html"), + ], +) +def test_index_fallback_does_not_handle_asset_like_or_non_html_requests( + tmp_path: Path, path: str, accept: str +): + dist = tmp_path / "dist" + write_file(dist / "index.html", "app shell") + app = FastAPI() + app.frontend("/", directory=dist, fallback="index.html") + + response = TestClient(app).get(path, headers={"accept": accept}) + + assert response.status_code == 404 + assert response.text != "app shell" + + +def test_404_fallback_handles_missing_assets(tmp_path: Path): + dist = tmp_path / "dist" + write_file(dist / "404.html", "missing") + app = FastAPI() + app.frontend("/", directory=dist, fallback="404.html") + + response = TestClient(app).get("/assets/missing.js") + + assert response.status_code == 404 + assert response.text == "missing" + + +def test_auto_fallback_prefers_404_over_index(tmp_path: Path): + dist = tmp_path / "dist" + write_file(dist / "index.html", "app shell") + write_file(dist / "404.html", "missing") + app = FastAPI() + app.frontend("/", directory=dist) + + response = TestClient(app).get("/dashboard", headers={"accept": "text/html"}) + + assert response.status_code == 404 + assert response.text == "missing" + + +def test_auto_fallback_uses_index_when_404_is_missing(tmp_path: Path): + dist = tmp_path / "dist" + write_file(dist / "index.html", "app shell") + app = FastAPI() + app.frontend("/", directory=dist) + + response = TestClient(app).get("/dashboard", headers={"accept": "text/html"}) + + assert response.status_code == 200 + assert response.text == "app shell" + + +def test_auto_fallback_returns_normal_404_without_fallback_files(tmp_path: Path): + dist = tmp_path / "dist" + dist.mkdir() + app = FastAPI() + app.frontend("/", directory=dist) + + response = TestClient(app).get("/dashboard", headers={"accept": "text/html"}) + + assert response.status_code == 404 + assert response.json() == {"detail": "Not Found"} + + +def test_no_fallback_returns_normal_404(tmp_path: Path): + dist = tmp_path / "dist" + write_file(dist / "index.html", "app shell") + app = FastAPI() + app.frontend("/", directory=dist, fallback=None) + + response = TestClient(app).get("/dashboard", headers={"accept": "text/html"}) + + assert response.status_code == 404 + assert response.json() == {"detail": "Not Found"} + + +def test_directory_index_and_redirect(tmp_path: Path): + dist = tmp_path / "dist" + write_file(dist / "about" / "index.html", "about") + app = FastAPI() + app.frontend("/", directory=dist) + client = TestClient(app) + + redirect = client.get("/about", follow_redirects=False) + response = client.get("/about/") + + assert redirect.status_code == 307 + assert redirect.headers["location"] == "http://testserver/about/" + assert response.status_code == 200 + assert response.text == "about" + + +def test_path_validation_and_trailing_slash_normalization(tmp_path: Path): + dist = tmp_path / "dist" + write_file(dist / "asset.txt", "ok") + app = FastAPI() + + with pytest.raises(AssertionError): + app.frontend("", directory=dist) + with pytest.raises(AssertionError): + app.frontend("app", directory=dist) + + app.frontend("/app/", directory=dist) + response = TestClient(app).get("/app/asset.txt") + + assert response.status_code == 200 + assert response.text == "ok" + + +def test_frontend_path_matching_uses_segment_boundaries(tmp_path: Path): + dist = tmp_path / "dist" + write_file(dist / "index.html", "app") + app = FastAPI() + app.frontend("/app", directory=dist, fallback="index.html") + + response = TestClient(app).get("/application", headers={"accept": "text/html"}) + + assert response.status_code == 404 + + +def test_multiple_frontends_use_longest_matching_prefix(tmp_path: Path): + site = tmp_path / "site" + admin = tmp_path / "admin" + write_file(site / "index.html", "site") + write_file(admin / "index.html", "admin") + app = FastAPI() + app.frontend("/", directory=site, fallback="index.html") + app.frontend("/admin", directory=admin, fallback="index.html") + + response = TestClient(app).get("/admin/settings", headers={"accept": "text/html"}) + + assert response.status_code == 200 + assert response.text == "admin" + + +def test_apirouter_frontend_uses_include_prefix(tmp_path: Path): + dist = tmp_path / "admin" + write_file(dist / "index.html", "admin") + router = APIRouter() + router.frontend("/", directory=dist, fallback="index.html") + app = FastAPI() + app.include_router(router, prefix="/admin") + + response = TestClient(app).get("/admin/settings", headers={"accept": "text/html"}) + + assert response.status_code == 200 + assert response.text == "admin" + + +def test_global_priority_across_included_routers(tmp_path: Path): + dist = tmp_path / "site" + write_file(dist / "index.html", "site") + site_router = APIRouter() + site_router.frontend("/", directory=dist, fallback="index.html") + api_router = APIRouter() + + @api_router.get("/api/users") + def read_users(): + return {"source": "api"} + + app = FastAPI() + app.include_router(site_router) + app.include_router(api_router) + + response = TestClient(app).get("/api/users", headers={"accept": "text/html"}) + + assert response.status_code == 200 + assert response.json() == {"source": "api"} + + +def test_nested_apirouter_frontend_uses_all_include_prefixes(tmp_path: Path): + dist = tmp_path / "admin" + write_file(dist / "index.html", "admin") + child_router = APIRouter() + child_router.frontend("/", directory=dist, fallback="index.html") + parent_router = APIRouter() + parent_router.include_router(child_router, prefix="/child") + app = FastAPI() + app.include_router(parent_router, prefix="/parent") + + response = TestClient(app).get( + "/parent/child/settings", headers={"accept": "text/html"} + ) + + assert response.status_code == 200 + assert response.text == "admin" + + +def test_low_priority_cache_updates_after_route_added_to_included_router( + tmp_path: Path, +): + dist = tmp_path / "site" + write_file(dist / "index.html", "site") + router = APIRouter() + router.frontend("/", directory=dist, fallback="index.html") + app = FastAPI() + app.include_router(router, prefix="/app") + client = TestClient(app) + + frontend_response = client.get("/app/dashboard", headers={"accept": "text/html"}) + + @router.get("/dashboard") + def read_dashboard(): + return {"source": "api"} + + api_response = client.get("/app/dashboard", headers={"accept": "text/html"}) + + assert frontend_response.status_code == 200 + assert frontend_response.text == "site" + assert api_response.status_code == 200 + assert api_response.json() == {"source": "api"} + + +def test_normal_route_slash_redirect_wins_before_frontend_redirect(tmp_path: Path): + dist = tmp_path / "site" + write_file(dist / "api" / "index.html", "frontend") + app = FastAPI() + + @app.get("/api/") + def read_api(): + return {"source": "api"} + + app.frontend("/", directory=dist) + + response = TestClient(app).get("/api", follow_redirects=False) + + assert response.status_code == 307 + assert response.headers["location"] == "http://testserver/api/" + + followed = TestClient(app).get("/api/") + assert followed.status_code == 200 + assert followed.json() == {"source": "api"} + + +def test_frontend_respects_root_path(tmp_path: Path): + dist = tmp_path / "dist" + write_file(dist / "assets" / "app.js", "console.log('ok')") + app = FastAPI() + app.frontend("/app", directory=dist) + + response = TestClient(app, root_path="/proxy").get("/app/assets/app.js") + + assert response.status_code == 200 + assert response.text == "console.log('ok')" + + +def test_websocket_route_wins_over_frontend(tmp_path: Path): + dist = tmp_path / "dist" + write_file(dist / "ws", "frontend") + app = FastAPI() + + @app.websocket("/ws") + async def websocket_endpoint(websocket: WebSocket): + await websocket.accept() + await websocket.send_text("websocket") + await websocket.close() + + app.frontend("/", directory=dist) + + with TestClient(app).websocket_connect("/ws") as websocket: + data = websocket.receive_text() + + assert data == "websocket" + + +def test_head_requests_work(tmp_path: Path): + dist = tmp_path / "dist" + write_file(dist / "asset.txt", "ok") + app = FastAPI() + app.frontend("/", directory=dist) + + response = TestClient(app).head("/asset.txt") + + assert response.status_code == 200 + assert response.text == "" + assert response.headers["content-length"] == "2" + + +def test_unsupported_methods_return_405(tmp_path: Path): + dist = tmp_path / "dist" + write_file(dist / "asset.txt", "ok") + app = FastAPI() + app.frontend("/", directory=dist) + + response = TestClient(app).post("/asset.txt") + + assert response.status_code == 405 + + +@pytest.mark.parametrize( + "path", + [ + "/../secret.txt", + "/%2e%2e/secret.txt", + "/..%2fsecret.txt", + "/%5c..%5csecret.txt", + "/..%5csecret.txt", + ], +) +def test_path_traversal_cannot_escape_directory(tmp_path: Path, path: str): + dist = tmp_path / "dist" + write_file(dist / "index.html", "app") + write_file(tmp_path / "secret.txt", "secret") + app = FastAPI() + app.frontend("/", directory=dist) + + response = TestClient(app).get(path) + + assert response.status_code == 404 + assert response.text != "secret" + + +def test_symlink_outside_directory_is_not_served(tmp_path: Path): + dist = tmp_path / "dist" + dist.mkdir() + outside = tmp_path / "secret.txt" + outside.write_text("secret") + link = dist / "secret.txt" + try: + os.symlink(outside, link) + except (OSError, NotImplementedError): # pragma: no cover + pytest.skip("symlinks are not supported") + app = FastAPI() + app.frontend("/", directory=dist) + + response = TestClient(app).get("/secret.txt") + + assert response.status_code == 404 + assert response.text != "secret" + + +def test_check_dir_true_fails_early_for_missing_directory(monkeypatch, tmp_path: Path): + app = FastAPI() + monkeypatch.chdir(tmp_path) + + with pytest.raises(RuntimeError, match="does not exist") as exc_info: + app.frontend("/", directory="missing") + + message = str(exc_info.value) + assert "'missing'" in message + assert str(tmp_path / "missing") in message + + +def test_check_dir_false_allows_missing_directory_and_fails_on_request(tmp_path: Path): + app = FastAPI() + app.frontend("/", directory=tmp_path / "missing", check_dir=False) + + with pytest.raises(RuntimeError, match="does not exist"): + TestClient(app).get("/asset.txt") + + +def test_explicit_fallback_files_fail_clearly_when_missing(monkeypatch, tmp_path: Path): + dist = tmp_path / "dist" + dist.mkdir() + monkeypatch.chdir(tmp_path) + app = FastAPI() + + with pytest.raises(RuntimeError, match="index.html") as exc_info: + app.frontend("/", directory="dist", fallback="index.html") + + message = str(exc_info.value) + assert "directory 'dist'" in message + assert str(dist) in message + + app = FastAPI() + app.frontend("/", directory="dist", fallback="404.html", check_dir=False) + + with pytest.raises(RuntimeError, match="404.html") as exc_info: + TestClient(app).get("/missing.js") + + message = str(exc_info.value) + assert "directory 'dist'" in message + assert str(dist) in message + + +def test_frontend_routes_are_not_in_openapi(tmp_path: Path): + dist = tmp_path / "dist" + write_file(dist / "index.html", "app") + app = FastAPI() + + @app.get("/api") + def read_api(): + return {"ok": True} + + app.frontend("/", directory=dist, fallback="index.html") + + schema = TestClient(app).get("/openapi.json").json() + + assert set(schema["paths"]) == {"/api"} + + response = TestClient(app).get("/api") + assert response.status_code == 200 + assert response.json() == {"ok": True} + + +@pytest.mark.parametrize( + ("example", "files", "path", "status_code", "body"), + [ + ( + "tutorial001_py310.py", + {"asset.txt": "asset"}, + "/asset.txt", + 200, + "asset", + ), + ( + "tutorial002_py310.py", + {"index.html": "index"}, + "/dashboard", + 200, + "index", + ), + ( + "tutorial003_py310.py", + {"404.html": "missing"}, + "/missing", + 404, + "missing", + ), + ( + "tutorial004_py310.py", + {"index.html": "index"}, + "/app/dashboard", + 200, + "index", + ), + ( + "tutorial005_py310.py", + {"index.html": "index"}, + "/dashboard", + 404, + '{"detail":"Not Found"}', + ), + ( + "tutorial006_py310.py", + {"asset.txt": "asset"}, + "/asset.txt", + 200, + "asset", + ), + ], +) +def test_docs_frontend_examples( + tmp_path: Path, + monkeypatch, + example: str, + files: dict[str, str], + path: str, + status_code: int, + body: str, +): + dist = tmp_path / "dist" + for file, content in files.items(): + write_file(dist / file, content) + monkeypatch.chdir(tmp_path) + + namespace = runpy.run_path( + str(Path(__file__).parents[1] / "docs_src" / "frontend" / example) + ) + + app = namespace["app"] + assert isinstance(app, FastAPI) + response = TestClient(app).get(path, headers={"accept": "text/html"}) + assert response.status_code == status_code + assert response.text == body + + +def test_low_priority_routes_can_store_non_frontend_routes(): + async def low_priority_endpoint(request): + return PlainTextResponse("low") + + app = FastAPI() + app.router._low_priority_routes.append(Route("/low", low_priority_endpoint)) + app.router._mark_routes_changed() + + response = TestClient(app).get("/low") + + assert response.status_code == 200 + assert response.text == "low" + + +def test_included_low_priority_routes_can_store_non_frontend_routes(): + async def low_priority_endpoint(request): + return PlainTextResponse("low") + + router = APIRouter() + router._low_priority_routes.append(Route("/low", low_priority_endpoint)) + router._mark_routes_changed() + app = FastAPI() + app.include_router(router, prefix="/prefix") + + response = TestClient(app).get("/prefix/low") + + assert response.status_code == 200 + assert response.text == "low" From e12833aaa2338d5ff31a71afb6b2d396ae18145f Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Sat, 20 Jun 2026 00:21:10 +0000 Subject: [PATCH 292/462] =?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 ba7109455..a43af90c0 100644 --- a/docs/en/docs/release-notes.md +++ b/docs/en/docs/release-notes.md @@ -7,6 +7,10 @@ hide: ## Latest Changes +### Features + +* ✨ Add support for `app.frontend("/", directory="dist")` and `router.frontend("/", directory="dist")`. PR [#15800](https://github.com/fastapi/fastapi/pull/15800) by [@tiangolo](https://github.com/tiangolo). + ### Docs * ✏️ Fix grammar, typos, and broken links in docs. PR [#15694](https://github.com/fastapi/fastapi/pull/15694) by [@YuriiMotov](https://github.com/YuriiMotov). From 459a51097be8187115047149d77dab983a361fb3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebasti=C3=A1n=20Ram=C3=ADrez?= Date: Sat, 20 Jun 2026 02:26:04 +0200 Subject: [PATCH 293/462] =?UTF-8?q?=E2=9C=8F=EF=B8=8F=20Update=20white=20s?= =?UTF-8?q?pace=20characters=20in=20bigger=20apps=20(#15801)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docs/en/docs/tutorial/bigger-applications.md | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/docs/en/docs/tutorial/bigger-applications.md b/docs/en/docs/tutorial/bigger-applications.md index b0e1a9b73..07478b5cc 100644 --- a/docs/en/docs/tutorial/bigger-applications.md +++ b/docs/en/docs/tutorial/bigger-applications.md @@ -17,16 +17,16 @@ Let's say you have a file structure like this: ``` . ├── app -│   ├── __init__.py -│   ├── main.py -│   ├── dependencies.py -│   └── routers -│   │ ├── __init__.py -│   │ ├── items.py -│   │ └── users.py -│   └── internal -│   ├── __init__.py -│   └── admin.py +│ ├── __init__.py +│ ├── main.py +│ ├── dependencies.py +│ └── routers +│ │ ├── __init__.py +│ │ ├── items.py +│ │ └── users.py +│ └── internal +│ ├── __init__.py +│ └── admin.py ``` /// tip From 71e608e00e16c88c90bd5b6ffd04b5253a5b4133 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Sat, 20 Jun 2026 00:26:30 +0000 Subject: [PATCH 294/462] =?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 a43af90c0..2f27a381d 100644 --- a/docs/en/docs/release-notes.md +++ b/docs/en/docs/release-notes.md @@ -13,6 +13,7 @@ hide: ### Docs +* ✏️ Update white space characters in bigger apps. PR [#15801](https://github.com/fastapi/fastapi/pull/15801) by [@tiangolo](https://github.com/tiangolo). * ✏️ Fix grammar, typos, and broken links in docs. PR [#15694](https://github.com/fastapi/fastapi/pull/15694) by [@YuriiMotov](https://github.com/YuriiMotov). ### Translations From d176e00b9fb136ea8324c092c84528fdc3e16919 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebasti=C3=A1n=20Ram=C3=ADrez?= Date: Sat, 20 Jun 2026 02:29:58 +0200 Subject: [PATCH 295/462] =?UTF-8?q?=F0=9F=93=9D=20Udpate=20release=20notes?= =?UTF-8?q?=20link=20(#15802)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docs/en/docs/release-notes.md | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/en/docs/release-notes.md b/docs/en/docs/release-notes.md index 2f27a381d..537cb5fe9 100644 --- a/docs/en/docs/release-notes.md +++ b/docs/en/docs/release-notes.md @@ -10,6 +10,7 @@ hide: ### Features * ✨ Add support for `app.frontend("/", directory="dist")` and `router.frontend("/", directory="dist")`. PR [#15800](https://github.com/fastapi/fastapi/pull/15800) by [@tiangolo](https://github.com/tiangolo). + * Read the docs: [Frontend](https://fastapi.tiangolo.com/tutorial/frontend/). ### Docs From 9c7eceb00ff6e1d37980954418f7c9dab30a4cd5 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Sat, 20 Jun 2026 00:30:21 +0000 Subject: [PATCH 296/462] =?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 537cb5fe9..4946e1cfd 100644 --- a/docs/en/docs/release-notes.md +++ b/docs/en/docs/release-notes.md @@ -14,6 +14,7 @@ hide: ### Docs +* 📝 Udpate release notes link. PR [#15802](https://github.com/fastapi/fastapi/pull/15802) by [@tiangolo](https://github.com/tiangolo). * ✏️ Update white space characters in bigger apps. PR [#15801](https://github.com/fastapi/fastapi/pull/15801) by [@tiangolo](https://github.com/tiangolo). * ✏️ Fix grammar, typos, and broken links in docs. PR [#15694](https://github.com/fastapi/fastapi/pull/15694) by [@YuriiMotov](https://github.com/YuriiMotov). From 7cb1ab6264bc03319832f553730b511192a0c0d3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebasti=C3=A1n=20Ram=C3=ADrez?= Date: Sat, 20 Jun 2026 02:45:19 +0200 Subject: [PATCH 297/462] =?UTF-8?q?=F0=9F=91=B7=20Fix=20test-alls-green=20?= =?UTF-8?q?(#15803)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .github/workflows/test.yml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 4bfec7501..d9c23cca0 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -245,9 +245,10 @@ jobs: - run: uv run coverage report --fail-under=100 # https://github.com/marketplace/actions/alls-green#why - check: # This job does nothing and is only used for the branch protection + test-alls-green: # This job does nothing and is only used for the branch protection if: always() needs: + - test - coverage-combine - benchmark runs-on: ubuntu-latest From 0cd5001d0ef80a07e2d775c5c75522391a3e06d7 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Sat, 20 Jun 2026 00:45:46 +0000 Subject: [PATCH 298/462] =?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 4946e1cfd..88c42b24d 100644 --- a/docs/en/docs/release-notes.md +++ b/docs/en/docs/release-notes.md @@ -24,6 +24,7 @@ hide: ### Internal +* 👷 Fix test-alls-green. PR [#15803](https://github.com/fastapi/fastapi/pull/15803) by [@tiangolo](https://github.com/tiangolo). * 🔧 Enable checking `release-notes.md` for typos. PR [#15796](https://github.com/fastapi/fastapi/pull/15796) by [@YuriiMotov](https://github.com/YuriiMotov). * 📝 Tweak wording about deploying to FastAPI Cloud. PR [#15793](https://github.com/fastapi/fastapi/pull/15793) by [@tiangolo](https://github.com/tiangolo). * 🔨 Use `gpt-5.5` model in `translate.py`, specify `-chat` to avoid warnings. PR [#15792](https://github.com/fastapi/fastapi/pull/15792) by [@YuriiMotov](https://github.com/YuriiMotov). From 2260afaf433103c8104b34d256cf0b96b058823b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebasti=C3=A1n=20Ram=C3=ADrez?= Date: Sat, 20 Jun 2026 02:51:31 +0200 Subject: [PATCH 299/462] =?UTF-8?q?=F0=9F=90=9B=20Fix=20failing=20test,=20?= =?UTF-8?q?update=20format=20for=20raised=20errors=20(#15804)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- fastapi/routing.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/fastapi/routing.py b/fastapi/routing.py index bd6289b58..3a2d75422 100644 --- a/fastapi/routing.py +++ b/fastapi/routing.py @@ -1809,8 +1809,8 @@ class _FrontendStaticFiles(StaticFiles): self.fallback = fallback if check_dir and not os.path.isdir(directory): raise RuntimeError( - f"Frontend directory {directory!r} does not exist. " - f"Resolved absolute path: {_get_resolved_absolute_path(directory)!r}" + f"Frontend directory '{directory}' does not exist. " + f"Resolved absolute path: '{_get_resolved_absolute_path(directory)}'" ) super().__init__( directory=directory, From 17945e5ab7f25234340c152a40d232a98857e079 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Sat, 20 Jun 2026 00:51:57 +0000 Subject: [PATCH 300/462] =?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 88c42b24d..19cf3d668 100644 --- a/docs/en/docs/release-notes.md +++ b/docs/en/docs/release-notes.md @@ -24,6 +24,7 @@ hide: ### Internal +* 🐛 Fix failing test, update format for raised errors. PR [#15804](https://github.com/fastapi/fastapi/pull/15804) by [@tiangolo](https://github.com/tiangolo). * 👷 Fix test-alls-green. PR [#15803](https://github.com/fastapi/fastapi/pull/15803) by [@tiangolo](https://github.com/tiangolo). * 🔧 Enable checking `release-notes.md` for typos. PR [#15796](https://github.com/fastapi/fastapi/pull/15796) by [@YuriiMotov](https://github.com/YuriiMotov). * 📝 Tweak wording about deploying to FastAPI Cloud. PR [#15793](https://github.com/fastapi/fastapi/pull/15793) by [@tiangolo](https://github.com/tiangolo). From 190f6e2033c8b886b25027be284d8c8c1893f28c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebasti=C3=A1n=20Ram=C3=ADrez?= Date: Sat, 20 Jun 2026 02:59:14 +0200 Subject: [PATCH 301/462] =?UTF-8?q?=F0=9F=93=9D=20Add=20Frontend=20instruc?= =?UTF-8?q?tions=20to=20Agent=20Library=20Skill=20(#15805)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- fastapi/.agents/skills/fastapi/SKILL.md | 26 +++++++++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/fastapi/.agents/skills/fastapi/SKILL.md b/fastapi/.agents/skills/fastapi/SKILL.md index d5f32fa3c..f2ecd9eec 100644 --- a/fastapi/.agents/skills/fastapi/SKILL.md +++ b/fastapi/.agents/skills/fastapi/SKILL.md @@ -288,6 +288,32 @@ There could be exceptions, but try to follow this convention. Apply shared dependencies at the router level via `dependencies=[Depends(...)]`. +## Serve Frontend Apps + +Use `app.frontend()` to serve a built static frontend app, for example a directory generated by Vite, Astro, Angular, Svelte, Vue, or a similar tool. + +```python +from fastapi import FastAPI + +app = FastAPI() + +app.frontend("/", directory="dist") +``` + +Use `router.frontend()` when the frontend belongs to an `APIRouter`; normal router prefix behavior applies when the router is included. + +```python +from fastapi import APIRouter, FastAPI + +app = FastAPI() +router = APIRouter(prefix="/admin") + +router.frontend("/", directory="admin-dist") +app.include_router(router) +``` + +`app.frontend()` and `router.frontend()` are low-priority routes: regular API routes are matched first, then frontend files and client-side routing fallbacks. Use this for single-page apps and built frontend assets instead of mounting `StaticFiles` manually. + ## Dependency Injection See [the dependency injection reference](references/dependencies.md) for detailed patterns including `yield` with `scope`, and class dependencies. From 0303491b69ff84a4632c0314e6db4df74f2f93f9 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Sat, 20 Jun 2026 00:59:37 +0000 Subject: [PATCH 302/462] =?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 19cf3d668..c026ca26f 100644 --- a/docs/en/docs/release-notes.md +++ b/docs/en/docs/release-notes.md @@ -14,6 +14,7 @@ hide: ### Docs +* 📝 Add `app.frontend()` instructions to Agent Library Skill. PR [#15805](https://github.com/fastapi/fastapi/pull/15805) by [@tiangolo](https://github.com/tiangolo). * 📝 Udpate release notes link. PR [#15802](https://github.com/fastapi/fastapi/pull/15802) by [@tiangolo](https://github.com/tiangolo). * ✏️ Update white space characters in bigger apps. PR [#15801](https://github.com/fastapi/fastapi/pull/15801) by [@tiangolo](https://github.com/tiangolo). * ✏️ Fix grammar, typos, and broken links in docs. PR [#15694](https://github.com/fastapi/fastapi/pull/15694) by [@YuriiMotov](https://github.com/YuriiMotov). From 10393846ede7a2947cec594d15a43f813001cab4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebasti=C3=A1n=20Ram=C3=ADrez?= Date: Sat, 20 Jun 2026 03:06:46 +0200 Subject: [PATCH 303/462] =?UTF-8?q?=F0=9F=93=9D=20Fix=20typo=20in=20releas?= =?UTF-8?q?e=20notes=20(#15807)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docs/en/docs/release-notes.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/en/docs/release-notes.md b/docs/en/docs/release-notes.md index c026ca26f..cd69d6c49 100644 --- a/docs/en/docs/release-notes.md +++ b/docs/en/docs/release-notes.md @@ -15,7 +15,7 @@ hide: ### Docs * 📝 Add `app.frontend()` instructions to Agent Library Skill. PR [#15805](https://github.com/fastapi/fastapi/pull/15805) by [@tiangolo](https://github.com/tiangolo). -* 📝 Udpate release notes link. PR [#15802](https://github.com/fastapi/fastapi/pull/15802) by [@tiangolo](https://github.com/tiangolo). +* 📝 Update release notes link. PR [#15802](https://github.com/fastapi/fastapi/pull/15802) by [@tiangolo](https://github.com/tiangolo). * ✏️ Update white space characters in bigger apps. PR [#15801](https://github.com/fastapi/fastapi/pull/15801) by [@tiangolo](https://github.com/tiangolo). * ✏️ Fix grammar, typos, and broken links in docs. PR [#15694](https://github.com/fastapi/fastapi/pull/15694) by [@YuriiMotov](https://github.com/YuriiMotov). From 041cb0cdfa2d0f705d14ed07c2c2e0f92ef5f32c Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Sat, 20 Jun 2026 01:07:09 +0000 Subject: [PATCH 304/462] =?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 cd69d6c49..9470fee38 100644 --- a/docs/en/docs/release-notes.md +++ b/docs/en/docs/release-notes.md @@ -14,6 +14,7 @@ hide: ### Docs +* 📝 Fix typo in release notes. PR [#15807](https://github.com/fastapi/fastapi/pull/15807) by [@tiangolo](https://github.com/tiangolo). * 📝 Add `app.frontend()` instructions to Agent Library Skill. PR [#15805](https://github.com/fastapi/fastapi/pull/15805) by [@tiangolo](https://github.com/tiangolo). * 📝 Update release notes link. PR [#15802](https://github.com/fastapi/fastapi/pull/15802) by [@tiangolo](https://github.com/tiangolo). * ✏️ Update white space characters in bigger apps. PR [#15801](https://github.com/fastapi/fastapi/pull/15801) by [@tiangolo](https://github.com/tiangolo). From 4b83b0d409009c8de9df4070fe163838b1a700c7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebasti=C3=A1n=20Ram=C3=ADrez?= Date: Sat, 20 Jun 2026 03:14:30 +0200 Subject: [PATCH 305/462] =?UTF-8?q?=F0=9F=94=96=20Release=20version=200.13?= =?UTF-8?q?8.0=20(#15808)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: github-actions[bot] --- docs/en/docs/release-notes.md | 2 ++ fastapi/__init__.py | 2 +- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/docs/en/docs/release-notes.md b/docs/en/docs/release-notes.md index 9470fee38..2b57dfd9a 100644 --- a/docs/en/docs/release-notes.md +++ b/docs/en/docs/release-notes.md @@ -7,6 +7,8 @@ hide: ## Latest Changes +## 0.138.0 (2026-06-20) + ### Features * ✨ Add support for `app.frontend("/", directory="dist")` and `router.frontend("/", directory="dist")`. PR [#15800](https://github.com/fastapi/fastapi/pull/15800) by [@tiangolo](https://github.com/tiangolo). diff --git a/fastapi/__init__.py b/fastapi/__init__.py index 579fb169d..d7b99b5df 100644 --- a/fastapi/__init__.py +++ b/fastapi/__init__.py @@ -1,6 +1,6 @@ """FastAPI framework, high performance, easy to learn, fast to code, ready for production""" -__version__ = "0.137.2" +__version__ = "0.138.0" from starlette import status as status From d69774c23db11e12474d5237b832dc54fd12bffa Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Sat, 20 Jun 2026 18:31:07 +0200 Subject: [PATCH 306/462] =?UTF-8?q?=E2=AC=86=20Bump=20pydantic-settings=20?= =?UTF-8?q?from=202.14.1=20to=202.14.2=20(#15799)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: Yurii Motov <109919500+YuriiMotov@users.noreply.github.com> --- uv.lock | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/uv.lock b/uv.lock index 84a513873..7d5e106ca 100644 --- a/uv.lock +++ b/uv.lock @@ -4103,16 +4103,16 @@ wheels = [ [[package]] name = "pydantic-settings" -version = "2.14.1" +version = "2.14.2" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "pydantic" }, { name = "python-dotenv" }, { name = "typing-inspection" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/07/60/1d1e59c9c90d54591469ada7d268251f71c24bdb765f1a8a832cee8c6653/pydantic_settings-2.14.1.tar.gz", hash = "sha256:e874d3bec7e787b0c9958277956ed9b4dd5de6a80e162188fdaff7c5e26fd5fa", size = 235551, upload-time = "2026-05-08T13:40:06.542Z" } +sdist = { url = "https://files.pythonhosted.org/packages/5c/b5/8f48e906c3e0205276e8bd8cb7512217a87b2685304d64be27cad5b3019f/pydantic_settings-2.14.2.tar.gz", hash = "sha256:c19dd64b19097f1de80184f0cc7b0272a13ae6e170cbf240a3e27e381ed14a5f", size = 237700, upload-time = "2026-06-19T13:44:56.324Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/ae/8d/f1af3832f5e6eb13ba94ee809e72b8ecb5eef226d27ee0bef7d963d943c7/pydantic_settings-2.14.1-py3-none-any.whl", hash = "sha256:6e3c7edfd8277687cdc598f56e5cff0e9bfff0910a3749deaa8d4401c3a2b9de", size = 60964, upload-time = "2026-05-08T13:40:04.958Z" }, + { url = "https://files.pythonhosted.org/packages/77/c1/6e422f34e569cf8e18df68d1939c81c099d2b61e4f7d9621c8a77560799c/pydantic_settings-2.14.2-py3-none-any.whl", hash = "sha256:a20c97b37910b6550d5ea50fbcc2d4187defe58cd57070b73863d069419c9440", size = 61715, upload-time = "2026-06-19T13:44:55.02Z" }, ] [[package]] From 0cb4a8e284b450abbccb71c543ad7757de46c0b2 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Sat, 20 Jun 2026 16:31:34 +0000 Subject: [PATCH 307/462] =?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 2b57dfd9a..48b78e51d 100644 --- a/docs/en/docs/release-notes.md +++ b/docs/en/docs/release-notes.md @@ -7,6 +7,10 @@ hide: ## Latest Changes +### Internal + +* ⬆ Bump pydantic-settings from 2.14.1 to 2.14.2. PR [#15799](https://github.com/fastapi/fastapi/pull/15799) by [@dependabot[bot]](https://github.com/apps/dependabot). + ## 0.138.0 (2026-06-20) ### Features From 8f3db3d3e79465a97cbfd9ae47506aca67a58e0f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebasti=C3=A1n=20Ram=C3=ADrez?= Date: Sun, 21 Jun 2026 21:39:25 +0200 Subject: [PATCH 308/462] =?UTF-8?q?=F0=9F=94=92=EF=B8=8F=20Update=20zizmor?= =?UTF-8?q?=20workflow=20security=20checks=20(#15820)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .github/workflows/zizmor.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/zizmor.yml b/.github/workflows/zizmor.yml index f68ec5c4a..04c027a85 100644 --- a/.github/workflows/zizmor.yml +++ b/.github/workflows/zizmor.yml @@ -4,6 +4,7 @@ on: push: branches: - main + pull_request: workflow_dispatch: permissions: {} From a497a025e7114ca442478ed28da7e0a1cdc6177a Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Sun, 21 Jun 2026 19:39:49 +0000 Subject: [PATCH 309/462] =?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 48b78e51d..948f45af9 100644 --- a/docs/en/docs/release-notes.md +++ b/docs/en/docs/release-notes.md @@ -9,6 +9,7 @@ hide: ### Internal +* 🔒️ Update zizmor workflow security checks. PR [#15820](https://github.com/fastapi/fastapi/pull/15820) by [@tiangolo](https://github.com/tiangolo). * ⬆ Bump pydantic-settings from 2.14.1 to 2.14.2. PR [#15799](https://github.com/fastapi/fastapi/pull/15799) by [@dependabot[bot]](https://github.com/apps/dependabot). ## 0.138.0 (2026-06-20) From 29fc8f61660b52cb626190f865680364d0f32ff2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebasti=C3=A1n=20Ram=C3=ADrez?= Date: Tue, 23 Jun 2026 23:04:19 +0200 Subject: [PATCH 310/462] =?UTF-8?q?=F0=9F=94=A7=20Update=20sponsors:=20Add?= =?UTF-8?q?=20TestMu=20again=20(#15830)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docs/en/data/sponsors.yml | 3 +++ docs/en/docs/fastapi-people.md | 10 ++++++++++ 2 files changed, 13 insertions(+) diff --git a/docs/en/data/sponsors.yml b/docs/en/data/sponsors.yml index 66bc340a3..3d011ba12 100644 --- a/docs/en/data/sponsors.yml +++ b/docs/en/data/sponsors.yml @@ -53,3 +53,6 @@ bronze: # - url: https://testdriven.io/courses/tdd-fastapi/ # title: Learn to build high-quality web apps with best practices # img: /img/sponsors/testdriven.svg + - url: https://www.testmu.ai/?utm_source=fastapi&utm_medium=partner&utm_campaign=sponsor&utm_term=opensource&utm_content=webpage + title: TestMu AI. The Native AI-Agentic Cloud Platform to Supercharge Quality Engineering. + img: /img/sponsors/testmu.png diff --git a/docs/en/docs/fastapi-people.md b/docs/en/docs/fastapi-people.md index 4fc1b0b1d..e79928fb3 100644 --- a/docs/en/docs/fastapi-people.md +++ b/docs/en/docs/fastapi-people.md @@ -249,6 +249,16 @@ They are supporting my work with **FastAPI** (and others), mainly through [GitHu {% endfor %} {% endif %} + +{% if sponsors.bronze %} + +### Bronze Sponsors + +{% for sponsor in sponsors.bronze -%} + +{% endfor %} +{% endif %} + {% endif %} ### Individual Sponsors From 457f4c705c0287e49d7aa4ddec292db6185d16e3 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Tue, 23 Jun 2026 21:04:44 +0000 Subject: [PATCH 311/462] =?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 948f45af9..2eed5c085 100644 --- a/docs/en/docs/release-notes.md +++ b/docs/en/docs/release-notes.md @@ -9,6 +9,7 @@ hide: ### Internal +* 🔧 Update sponsors: Add TestMu again. PR [#15830](https://github.com/fastapi/fastapi/pull/15830) by [@tiangolo](https://github.com/tiangolo). * 🔒️ Update zizmor workflow security checks. PR [#15820](https://github.com/fastapi/fastapi/pull/15820) by [@tiangolo](https://github.com/tiangolo). * ⬆ Bump pydantic-settings from 2.14.1 to 2.14.2. PR [#15799](https://github.com/fastapi/fastapi/pull/15799) by [@dependabot[bot]](https://github.com/apps/dependabot). From fcc8e1f99431a0b381eaef03e07446e6975422b7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebasti=C3=A1n=20Ram=C3=ADrez?= Date: Wed, 24 Jun 2026 01:15:12 +0200 Subject: [PATCH 312/462] =?UTF-8?q?=E2=AC=86=EF=B8=8F=20Update=20issue-man?= =?UTF-8?q?ager=20to=200.7.0=20(#15831)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .github/workflows/issue-manager.yml | 25 +------------------------ 1 file changed, 1 insertion(+), 24 deletions(-) diff --git a/.github/workflows/issue-manager.yml b/.github/workflows/issue-manager.yml index fca3f1f2f..02bd18c33 100644 --- a/.github/workflows/issue-manager.yml +++ b/.github/workflows/issue-manager.yml @@ -29,29 +29,6 @@ jobs: env: GITHUB_CONTEXT: ${{ toJson(github) }} run: echo "$GITHUB_CONTEXT" - - uses: tiangolo/issue-manager@2fb3484ec9279485df8659e8ec73de262431737d # 0.6.0 + - uses: tiangolo/issue-manager@8505bda3fd28623a64d93935cbe13fa23f14fd8b # 0.7.0 with: token: ${{ secrets.GITHUB_TOKEN }} - config: > - { - "answered": { - "delay": 864000, - "message": "Assuming the original need was handled, this will be automatically closed now. But feel free to add more comments or create new issues or PRs." - }, - "waiting": { - "delay": 2628000, - "message": "As this PR has been waiting for the original user for a while but seems to be inactive, it's now going to be closed. But if there's anyone interested, feel free to create a new PR.", - "reminder": { - "before": "P3D", - "message": "Heads-up: this will be closed in 3 days unless there's new activity." - } - }, - "invalid": { - "delay": 0, - "message": "This was marked as invalid and will be closed now. If this is an error, please provide additional details." - }, - "maybe-ai": { - "delay": 0, - "message": "This was marked as potentially AI generated and will be closed now. If this is an error, please provide additional details, make sure to read the docs about contributing and AI." - } - } From 219ac634ab82b6321492ef97fb223b618ce13948 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Tue, 23 Jun 2026 23:16:31 +0000 Subject: [PATCH 313/462] =?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 2eed5c085..7e22ac560 100644 --- a/docs/en/docs/release-notes.md +++ b/docs/en/docs/release-notes.md @@ -9,6 +9,7 @@ hide: ### Internal +* ⬆️ Update issue-manager to 0.7.0. PR [#15831](https://github.com/fastapi/fastapi/pull/15831) by [@tiangolo](https://github.com/tiangolo). * 🔧 Update sponsors: Add TestMu again. PR [#15830](https://github.com/fastapi/fastapi/pull/15830) by [@tiangolo](https://github.com/tiangolo). * 🔒️ Update zizmor workflow security checks. PR [#15820](https://github.com/fastapi/fastapi/pull/15820) by [@tiangolo](https://github.com/tiangolo). * ⬆ Bump pydantic-settings from 2.14.1 to 2.14.2. PR [#15799](https://github.com/fastapi/fastapi/pull/15799) by [@dependabot[bot]](https://github.com/apps/dependabot). From f6ea6b1f12e6d1a45c630a8fdf5d4c7c0959dad9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebasti=C3=A1n=20Ram=C3=ADrez?= Date: Wed, 24 Jun 2026 14:23:58 +0200 Subject: [PATCH 314/462] =?UTF-8?q?=F0=9F=91=B7=20Update=20issue-manager?= =?UTF-8?q?=20to=200.7.1=20(#15833)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .github/workflows/issue-manager.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/issue-manager.yml b/.github/workflows/issue-manager.yml index 02bd18c33..bba089c6f 100644 --- a/.github/workflows/issue-manager.yml +++ b/.github/workflows/issue-manager.yml @@ -29,6 +29,6 @@ jobs: env: GITHUB_CONTEXT: ${{ toJson(github) }} run: echo "$GITHUB_CONTEXT" - - uses: tiangolo/issue-manager@8505bda3fd28623a64d93935cbe13fa23f14fd8b # 0.7.0 + - uses: tiangolo/issue-manager@75d60679db1ea348f6f6ea1d0e20de80a7c04645 # 0.7.1 with: token: ${{ secrets.GITHUB_TOKEN }} From 3f28dbe6d84cdac19bdb2b41e1664981e37359ab Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Wed, 24 Jun 2026 12:28:30 +0000 Subject: [PATCH 315/462] =?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 7e22ac560..8993cf723 100644 --- a/docs/en/docs/release-notes.md +++ b/docs/en/docs/release-notes.md @@ -9,6 +9,7 @@ hide: ### Internal +* 👷 Update issue-manager to 0.7.1. PR [#15833](https://github.com/fastapi/fastapi/pull/15833) by [@tiangolo](https://github.com/tiangolo). * ⬆️ Update issue-manager to 0.7.0. PR [#15831](https://github.com/fastapi/fastapi/pull/15831) by [@tiangolo](https://github.com/tiangolo). * 🔧 Update sponsors: Add TestMu again. PR [#15830](https://github.com/fastapi/fastapi/pull/15830) by [@tiangolo](https://github.com/tiangolo). * 🔒️ Update zizmor workflow security checks. PR [#15820](https://github.com/fastapi/fastapi/pull/15820) by [@tiangolo](https://github.com/tiangolo). From 82c527e714f16bf9e07202aff0fb91cada329844 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebasti=C3=A1n=20Ram=C3=ADrez?= Date: Thu, 25 Jun 2026 00:35:30 +0200 Subject: [PATCH 316/462] =?UTF-8?q?=F0=9F=91=B7=20Simplify=20pull=20reques?= =?UTF-8?q?t=20workflow=20triggers=20(#15836)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .github/workflows/build-docs.yml | 4 ---- .github/workflows/pre-commit.yml | 4 ---- .github/workflows/test-redistribute.yml | 4 ---- .github/workflows/test.yml | 3 --- 4 files changed, 15 deletions(-) diff --git a/.github/workflows/build-docs.yml b/.github/workflows/build-docs.yml index 20b054b80..0cf8d1262 100644 --- a/.github/workflows/build-docs.yml +++ b/.github/workflows/build-docs.yml @@ -4,10 +4,6 @@ on: branches: - master pull_request: - types: - - opened - - synchronize - permissions: {} jobs: diff --git a/.github/workflows/pre-commit.yml b/.github/workflows/pre-commit.yml index da966f523..915e3a883 100644 --- a/.github/workflows/pre-commit.yml +++ b/.github/workflows/pre-commit.yml @@ -2,10 +2,6 @@ name: pre-commit on: pull_request: - types: - - opened - - synchronize - permissions: {} env: diff --git a/.github/workflows/test-redistribute.yml b/.github/workflows/test-redistribute.yml index 1555a7643..47a2a8ae4 100644 --- a/.github/workflows/test-redistribute.yml +++ b/.github/workflows/test-redistribute.yml @@ -5,10 +5,6 @@ on: branches: - master pull_request: - types: - - opened - - synchronize - permissions: {} jobs: diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index d9c23cca0..18abb7482 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -5,9 +5,6 @@ on: branches: - master pull_request: - types: - - opened - - synchronize schedule: # cron every week on monday - cron: "0 0 * * 1" From d5494c1f01796350fa082cf8a82b124e95162e9d Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Wed, 24 Jun 2026 22:37:31 +0000 Subject: [PATCH 317/462] =?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 8993cf723..642d103a5 100644 --- a/docs/en/docs/release-notes.md +++ b/docs/en/docs/release-notes.md @@ -9,6 +9,7 @@ hide: ### Internal +* 👷 Simplify pull request workflow triggers. PR [#15836](https://github.com/fastapi/fastapi/pull/15836) by [@tiangolo](https://github.com/tiangolo). * 👷 Update issue-manager to 0.7.1. PR [#15833](https://github.com/fastapi/fastapi/pull/15833) by [@tiangolo](https://github.com/tiangolo). * ⬆️ Update issue-manager to 0.7.0. PR [#15831](https://github.com/fastapi/fastapi/pull/15831) by [@tiangolo](https://github.com/tiangolo). * 🔧 Update sponsors: Add TestMu again. PR [#15830](https://github.com/fastapi/fastapi/pull/15830) by [@tiangolo](https://github.com/tiangolo). From 0af003a85da454dcf6b6783e0ad3f0dd687e944f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebasti=C3=A1n=20Ram=C3=ADrez?= Date: Thu, 25 Jun 2026 17:30:51 +0200 Subject: [PATCH 318/462] =?UTF-8?q?=E2=99=BB=EF=B8=8F=20Refactor=20Library?= =?UTF-8?q?=20Skills,=20make=20info=20easier=20to=20find=20for=20agents=20?= =?UTF-8?q?(#15841)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- fastapi/.agents/skills/fastapi/SKILL.md | 267 +++++------------- .../fastapi/references/path-operations.md | 93 ++++++ .../skills/fastapi/references/pydantic.md | 93 ++++++ .../skills/fastapi/references/responses.md | 79 ++++++ 4 files changed, 328 insertions(+), 204 deletions(-) create mode 100644 fastapi/.agents/skills/fastapi/references/path-operations.md create mode 100644 fastapi/.agents/skills/fastapi/references/pydantic.md create mode 100644 fastapi/.agents/skills/fastapi/references/responses.md diff --git a/fastapi/.agents/skills/fastapi/SKILL.md b/fastapi/.agents/skills/fastapi/SKILL.md index f2ecd9eec..fc35b97ed 100644 --- a/fastapi/.agents/skills/fastapi/SKILL.md +++ b/fastapi/.agents/skills/fastapi/SKILL.md @@ -1,12 +1,23 @@ --- name: fastapi -description: FastAPI best practices and conventions. Use when working with FastAPI APIs and Pydantic models for them. Keeps FastAPI code clean and up to date with the latest features and patterns, updated with new versions. Write new code or refactor and update old code. +description: FastAPI best practices and conventions. Use when working with FastAPI APIs, Pydantic models, dependencies, streaming responses including Server-Sent Events (SSE), and serving frontend apps. Keeps FastAPI code clean and up to date with the latest features and patterns. --- # FastAPI Official FastAPI skill to write code with best practices, keeping up to date with new versions and features. +## Quick Reference + +* Serve frontend apps: use `app.frontend()` or `router.frontend()` for built frontend assets; see [Serve Frontend Apps](#serve-frontend-apps). +* Server-Sent Events (SSE): use `response_class=EventSourceResponse` and `yield`; see [Streaming](#streaming-json-lines-sse-bytes) and [the streaming reference](references/streaming.md). +* JSON Lines and byte streaming: see [the streaming reference](references/streaming.md). +* Dependencies: use `Annotated[..., Depends(...)]`; see [Dependency Injection](#dependency-injection) and [the dependency injection reference](references/dependencies.md) for `yield`, scopes, and class dependencies. +* Response models: prefer return types; use `response_model` when the public response schema differs from the internal return value; see [the response reference](references/responses.md). +* Pydantic models: do not use ellipsis or `RootModel`; see [the Pydantic reference](references/pydantic.md). +* Routing: declare router-level prefix, tags, and shared dependencies on the `APIRouter`; see [the path operation reference](references/path-operations.md). +* Tooling and related libraries: use uv, Ruff, ty, Asyncer, SQLModel, and HTTPX when applicable; see [the other tools reference](references/other-tools.md). + ## Use the `fastapi` CLI Run the development server on localhost with reload: @@ -15,39 +26,28 @@ Run the development server on localhost with reload: fastapi dev ``` - Run the production server: ```bash fastapi run ``` -### Add an entrypoint in `pyproject.toml` - -FastAPI CLI will read the entrypoint in `pyproject.toml` to know where the FastAPI app is declared. +Prefer declaring the entrypoint in `pyproject.toml`: ```toml [tool.fastapi] entrypoint = "my_app.main:app" ``` -### Use `fastapi` with a path - -When adding the entrypoint to `pyproject.toml` is not possible, or the user explicitly asks not to, or it's running an independent small app, you can pass the app file path to the `fastapi` command: +When adding the entrypoint is not possible, or the user explicitly asks not to, pass the app file path: ```bash fastapi dev my_app/main.py ``` -Prefer to set the entrypoint in `pyproject.toml` when possible. - ## Use `Annotated` -Always prefer the `Annotated` style for parameter and dependency declarations. - -It keeps the function signatures working in other contexts, respects the types, allows reusability. - -### In Parameter Declarations +Always prefer the `Annotated` style for parameter and dependency declarations. It keeps function signatures working in other contexts, respects the types, and allows reusability. Use `Annotated` for parameter declarations, including `Path`, `Query`, `Header`, etc.: @@ -67,23 +67,7 @@ async def read_item( return {"message": "Hello World"} ``` -instead of: - -```python -# DO NOT DO THIS -@app.get("/items/{item_id}") -async def read_item( - item_id: int = Path(ge=1, description="The item ID"), - q: str | None = Query(default=None, max_length=50), -): - return {"message": "Hello World"} -``` - -### For Dependencies - -Use `Annotated` for dependencies with `Depends()`. - -Unless asked not to, create a new type alias for the dependency to allow re-using it. +Use `Annotated` for dependencies with `Depends()`. Unless asked not to, create a new type alias for the dependency to allow reusing it: ```python from typing import Annotated @@ -105,20 +89,9 @@ async def read_item(current_user: CurrentUserDep): return {"message": "Hello World"} ``` -instead of: - -```python -# DO NOT DO THIS -@app.get("/items/") -async def read_item(current_user: dict = Depends(get_current_user)): - return {"message": "Hello World"} -``` - ## Do not use Ellipsis for *path operations* or Pydantic models -Do not use `...` as a default value for required parameters, it's not needed and not recommended. - -Do this, without Ellipsis (`...`): +Do not use `...` as a default value for required parameters or model fields. It's not needed and not recommended. ```python from typing import Annotated @@ -126,6 +99,8 @@ from typing import Annotated from fastapi import FastAPI, Query from pydantic import BaseModel, Field +app = FastAPI() + class Item(BaseModel): name: str @@ -133,29 +108,12 @@ class Item(BaseModel): price: float = Field(gt=0) -app = FastAPI() - - @app.post("/items/") -async def create_item(item: Item, project_id: Annotated[int, Query()]): ... +async def create_item(item: Item, project_id: Annotated[int, Query()]): + return item ``` -instead of this: - -```python -# DO NOT DO THIS -class Item(BaseModel): - name: str = ... - description: str | None = None - price: float = Field(..., gt=0) - - -app = FastAPI() - - -@app.post("/items/") -async def create_item(item: Item, project_id: Annotated[int, Query(...)]): ... -``` +See [the Pydantic reference](references/pydantic.md) for more details. ## Return Type or Response Model @@ -178,62 +136,9 @@ async def get_item() -> Item: return Item(name="Plumbus", description="All-purpose home device") ``` -**Important**: Return types or response models are what filter data ensuring no sensitive information is exposed. And they are used to serialize data with Pydantic (in Rust), this is the main idea that can increase response performance. - -The return type doesn't have to be a Pydantic model, it could be a different type, like a list of integers, or a dict, etc. - -### When to use `response_model` instead - -If the return type is not the same as the type that you want to use to validate, filter, or serialize, use the `response_model` parameter on the decorator instead. - -```python -from typing import Any - -from fastapi import FastAPI -from pydantic import BaseModel - -app = FastAPI() - - -class Item(BaseModel): - name: str - description: str | None = None - - -@app.get("/items/me", response_model=Item) -async def get_item() -> Any: - return {"name": "Foo", "description": "A very nice Item"} -``` - -This can be particularly useful when filtering data to expose only the public fields and avoid exposing sensitive information. - -```python -from typing import Any - -from fastapi import FastAPI -from pydantic import BaseModel - -app = FastAPI() - - -class InternalItem(BaseModel): - name: str - description: str | None = None - secret_key: str - +Return types or response models filter data to avoid exposing sensitive information, and they let Pydantic serialize the data on the Rust side for performance. -class Item(BaseModel): - name: str - description: str | None = None - - -@app.get("/items/me", response_model=Item) -async def get_item() -> Any: - item = InternalItem( - name="Foo", description="A very nice Item", secret_key="supersecret" - ) - return item -``` +Use `response_model` when the type you return is not the same as the public schema you want to validate, filter, document, and serialize. See [the response reference](references/responses.md). ## Performance @@ -243,36 +148,23 @@ Instead, declare a return type or response model. Pydantic will handle the data ## Including Routers -When declaring routers, prefer to add router level parameters like prefix, tags, etc. to the router itself, instead of in `include_router()`. - -Do this: +When declaring routers, prefer to add router-level parameters like prefix, tags, and shared dependencies to the router itself instead of in `include_router()`. ```python -from fastapi import APIRouter, FastAPI +from fastapi import APIRouter, Depends, FastAPI app = FastAPI() -router = APIRouter(prefix="/items", tags=["items"]) - - -@router.get("/") -async def list_items(): - return [] - - -# In main.py -app.include_router(router) -``` - -instead of this: -```python -# DO NOT DO THIS -from fastapi import APIRouter, FastAPI +def get_current_user(): + return {"username": "johndoe"} -app = FastAPI() -router = APIRouter() +router = APIRouter( + prefix="/items", + tags=["items"], + dependencies=[Depends(get_current_user)], +) @router.get("/") @@ -280,13 +172,10 @@ async def list_items(): return [] -# In main.py -app.include_router(router, prefix="/items", tags=["items"]) +app.include_router(router) ``` -There could be exceptions, but try to follow this convention. - -Apply shared dependencies at the router level via `dependencies=[Depends(...)]`. +See [the path operation reference](references/path-operations.md) for more routing patterns. ## Serve Frontend Apps @@ -316,15 +205,15 @@ app.include_router(router) ## Dependency Injection -See [the dependency injection reference](references/dependencies.md) for detailed patterns including `yield` with `scope`, and class dependencies. - -Use dependencies when the logic can't be declared in Pydantic validation, depends on external resources, needs cleanup (with `yield`), or is shared across endpoints. +Use dependencies when the logic can't be declared in Pydantic validation, depends on external resources, needs cleanup with `yield`, or is shared across endpoints. Apply shared dependencies at the router level via `dependencies=[Depends(...)]`. +See [the dependency injection reference](references/dependencies.md) for detailed patterns including `yield` with `scope`, and class dependencies. + ## Async vs Sync *path operations* -Use `async` *path operations* only when fully certain that the logic called inside is compatible with async and await (it's called with `await`) or that it doesn't block. +Use `async` *path operations* only when fully certain that the logic called inside is compatible with async and await, and that it doesn't block. ```python from fastapi import FastAPI @@ -332,30 +221,44 @@ from fastapi import FastAPI app = FastAPI() -# Use async def when calling async code @app.get("/async-items/") async def read_async_items(): data = await some_async_library.fetch_items() return data -# Use plain def when calling blocking/sync code or when in doubt @app.get("/items/") def read_items(): data = some_blocking_library.fetch_items() return data ``` -In case of doubt, or by default, use regular `def` functions, those will be run in a threadpool so they don't block the event loop. +In case of doubt, or by default, use regular `def` functions. They will be run in a threadpool so they don't block the event loop. The same rules apply to dependencies. -The same rules apply to dependencies. - -Make sure blocking code is not run inside of `async` functions. The logic will work, but will damage the performance heavily. +Make sure blocking code is not run inside of `async` functions. The logic will work, but will damage performance heavily. When needing to mix blocking and async code, see Asyncer in [the other tools reference](references/other-tools.md). ## Streaming (JSON Lines, SSE, bytes) +To stream Server-Sent Events, use `response_class=EventSourceResponse` and `yield` items from the endpoint. + +```python +from collections.abc import AsyncIterable + +from fastapi import FastAPI +from fastapi.sse import EventSourceResponse, ServerSentEvent + +app = FastAPI() + + +@app.get("/events", response_class=EventSourceResponse) +async def stream_events() -> AsyncIterable[ServerSentEvent]: + yield ServerSentEvent(data={"status": "started"}, event="status", id="1") +``` + +Plain objects are automatically JSON-serialized as `data:` fields. Use `ServerSentEvent` for full control over SSE fields (`event`, `id`, `retry`, `comment`) and `raw_data` for pre-formatted strings. + See [the streaming reference](references/streaming.md) for JSON Lines, Server-Sent Events (`EventSourceResponse`, `ServerSentEvent`), and byte streaming (`StreamingResponse`) patterns. ## Tooling @@ -372,9 +275,7 @@ See [the other tools reference](references/other-tools.md) for details on other ## Do not use Pydantic RootModels -Do not use Pydantic `RootModel`, instead use regular type annotations with `Annotated` and Pydantic validation utilities. - -For example, for a list with validations you could do: +Do not use Pydantic `RootModel`; instead use regular type annotations with `Annotated` and Pydantic validation utilities. ```python from typing import Annotated @@ -390,35 +291,11 @@ async def create_items(items: Annotated[list[int], Field(min_length=1), Body()]) return items ``` -instead of: - -```python -# DO NOT DO THIS -from typing import Annotated - -from fastapi import FastAPI -from pydantic import Field, RootModel - -app = FastAPI() - - -class ItemList(RootModel[Annotated[list[int], Field(min_length=1)]]): - pass - - -@app.post("/items/") -async def create_items(items: ItemList): - return items - -``` - -FastAPI supports these type annotations and will create a Pydantic `TypeAdapter` for them, so that types can work as normally and there's no need for the custom logic and types in RootModels. +FastAPI supports these type annotations and will create a Pydantic `TypeAdapter` for them, so types work normally without custom wrapper models. See [the Pydantic reference](references/pydantic.md). ## Use one HTTP operation per function -Don't mix HTTP operations in a single function, having one function per HTTP operation helps separate concerns and organize the code. - -Do this: +Don't mix HTTP operations in a single function. Having one function per HTTP operation helps separate concerns and organize the code. ```python from fastapi import FastAPI @@ -441,22 +318,4 @@ async def create_item(item: Item): return item ``` -instead of this: - -```python -# DO NOT DO THIS -from fastapi import FastAPI, Request -from pydantic import BaseModel - -app = FastAPI() - - -class Item(BaseModel): - name: str - - -@app.api_route("/items/", methods=["GET", "POST"]) -async def handle_items(request: Request): - if request.method == "GET": - return [] -``` +See [the path operation reference](references/path-operations.md) for more examples. diff --git a/fastapi/.agents/skills/fastapi/references/path-operations.md b/fastapi/.agents/skills/fastapi/references/path-operations.md new file mode 100644 index 000000000..1292c1774 --- /dev/null +++ b/fastapi/.agents/skills/fastapi/references/path-operations.md @@ -0,0 +1,93 @@ +# Path Operations and Routing + +## Including Routers + +When declaring routers, prefer to add router-level parameters like prefix, tags, and shared dependencies to the router itself instead of in `include_router()`. + +Do this: + +```python +from fastapi import APIRouter, FastAPI + +app = FastAPI() + +router = APIRouter(prefix="/items", tags=["items"]) + + +@router.get("/") +async def list_items(): + return [] + + +app.include_router(router) +``` + +Instead of: + +```python +# DO NOT DO THIS +from fastapi import APIRouter, FastAPI + +app = FastAPI() + +router = APIRouter() + + +@router.get("/") +async def list_items(): + return [] + + +app.include_router(router, prefix="/items", tags=["items"]) +``` + +There could be exceptions, but try to follow this convention. + +Apply shared dependencies at the router level via `dependencies=[Depends(...)]`. + +## Use one HTTP operation per function + +Don't mix HTTP operations in a single function. Having one function per HTTP operation helps separate concerns and organize the code. + +Do this: + +```python +from fastapi import FastAPI +from pydantic import BaseModel + +app = FastAPI() + + +class Item(BaseModel): + name: str + + +@app.get("/items/") +async def list_items(): + return [] + + +@app.post("/items/") +async def create_item(item: Item): + return item +``` + +Instead of: + +```python +# DO NOT DO THIS +from fastapi import FastAPI, Request +from pydantic import BaseModel + +app = FastAPI() + + +class Item(BaseModel): + name: str + + +@app.api_route("/items/", methods=["GET", "POST"]) +async def handle_items(request: Request): + if request.method == "GET": + return [] +``` diff --git a/fastapi/.agents/skills/fastapi/references/pydantic.md b/fastapi/.agents/skills/fastapi/references/pydantic.md new file mode 100644 index 000000000..fadf99c1a --- /dev/null +++ b/fastapi/.agents/skills/fastapi/references/pydantic.md @@ -0,0 +1,93 @@ +# Pydantic + +## Do not use Ellipsis + +Do not use `...` as a default value for required parameters or model fields. It's not needed and not recommended. + +Do this, without Ellipsis (`...`): + +```python +from typing import Annotated + +from fastapi import FastAPI, Query +from pydantic import BaseModel, Field + +app = FastAPI() + + +class Item(BaseModel): + name: str + description: str | None = None + price: float = Field(gt=0) + + +@app.post("/items/") +async def create_item(item: Item, project_id: Annotated[int, Query()]): + return item +``` + +Instead of: + +```python +# DO NOT DO THIS +from typing import Annotated + +from fastapi import FastAPI, Query +from pydantic import BaseModel, Field + +app = FastAPI() + + +class Item(BaseModel): + name: str = ... + description: str | None = None + price: float = Field(..., gt=0) + + +@app.post("/items/") +async def create_item(item: Item, project_id: Annotated[int, Query(...)]): + return item +``` + +## Do not use Pydantic RootModels + +Do not use Pydantic `RootModel`; instead use regular type annotations with `Annotated` and Pydantic validation utilities. + +For example, for a list with validations: + +```python +from typing import Annotated + +from fastapi import Body, FastAPI +from pydantic import Field + +app = FastAPI() + + +@app.post("/items/") +async def create_items(items: Annotated[list[int], Field(min_length=1), Body()]): + return items +``` + +Instead of: + +```python +# DO NOT DO THIS +from typing import Annotated + +from fastapi import FastAPI +from pydantic import Field, RootModel + +app = FastAPI() + + +class ItemList(RootModel[Annotated[list[int], Field(min_length=1)]]): + pass + + +@app.post("/items/") +async def create_items(items: ItemList): + return items +``` + +FastAPI supports these type annotations and will create a Pydantic `TypeAdapter` for them, so types work normally without custom wrapper models. diff --git a/fastapi/.agents/skills/fastapi/references/responses.md b/fastapi/.agents/skills/fastapi/references/responses.md new file mode 100644 index 000000000..09081236a --- /dev/null +++ b/fastapi/.agents/skills/fastapi/references/responses.md @@ -0,0 +1,79 @@ +# Responses + +## Return Type or Response Model + +When possible, include a return type. It will be used to validate, filter, document, and serialize the response. + +```python +from fastapi import FastAPI +from pydantic import BaseModel + +app = FastAPI() + + +class Item(BaseModel): + name: str + description: str | None = None + + +@app.get("/items/me") +async def get_item() -> Item: + return Item(name="Plumbus", description="All-purpose home device") +``` + +Return types or response models filter data to avoid exposing sensitive information. They also let Pydantic serialize data on the Rust side for performance. + +The return type doesn't have to be a Pydantic model. It can be a different type, like a list of integers, a dict, etc. + +## When to use `response_model` + +If the return type is not the same as the type that you want to use to validate, filter, or serialize, use the `response_model` parameter on the decorator. + +```python +from typing import Any + +from fastapi import FastAPI +from pydantic import BaseModel + +app = FastAPI() + + +class Item(BaseModel): + name: str + description: str | None = None + + +@app.get("/items/me", response_model=Item) +async def get_item() -> Any: + return {"name": "Foo", "description": "A very nice Item"} +``` + +This is particularly useful when filtering data to expose only the public fields and avoid exposing sensitive information. + +```python +from typing import Any + +from fastapi import FastAPI +from pydantic import BaseModel + +app = FastAPI() + + +class InternalItem(BaseModel): + name: str + description: str | None = None + secret_key: str + + +class Item(BaseModel): + name: str + description: str | None = None + + +@app.get("/items/me", response_model=Item) +async def get_item() -> Any: + item = InternalItem( + name="Foo", description="A very nice Item", secret_key="supersecret" + ) + return item +``` From 1f2f3df4852bf7cb29be1187806d95a0fdc7ea40 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Thu, 25 Jun 2026 15:31:17 +0000 Subject: [PATCH 319/462] =?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 642d103a5..125481de7 100644 --- a/docs/en/docs/release-notes.md +++ b/docs/en/docs/release-notes.md @@ -7,6 +7,10 @@ hide: ## Latest Changes +### Refactors + +* ♻️ Refactor Library Skills, make info easier to find for agents. PR [#15841](https://github.com/fastapi/fastapi/pull/15841) by [@tiangolo](https://github.com/tiangolo). + ### Internal * 👷 Simplify pull request workflow triggers. PR [#15836](https://github.com/fastapi/fastapi/pull/15836) by [@tiangolo](https://github.com/tiangolo). From b90c49aefad4958abdfbcacf9c2f816940a8f0e2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebasti=C3=A1n=20Ram=C3=ADrez?= Date: Thu, 25 Jun 2026 17:38:29 +0200 Subject: [PATCH 320/462] =?UTF-8?q?=F0=9F=94=96=20Release=20version=200.13?= =?UTF-8?q?8.1=20(#15842)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: github-actions[bot] --- docs/en/docs/release-notes.md | 2 ++ fastapi/__init__.py | 2 +- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/docs/en/docs/release-notes.md b/docs/en/docs/release-notes.md index 125481de7..87286fe51 100644 --- a/docs/en/docs/release-notes.md +++ b/docs/en/docs/release-notes.md @@ -7,6 +7,8 @@ hide: ## Latest Changes +## 0.138.1 (2026-06-25) + ### Refactors * ♻️ Refactor Library Skills, make info easier to find for agents. PR [#15841](https://github.com/fastapi/fastapi/pull/15841) by [@tiangolo](https://github.com/tiangolo). diff --git a/fastapi/__init__.py b/fastapi/__init__.py index d7b99b5df..a61ac1bd7 100644 --- a/fastapi/__init__.py +++ b/fastapi/__init__.py @@ -1,6 +1,6 @@ """FastAPI framework, high performance, easy to learn, fast to code, ready for production""" -__version__ = "0.138.0" +__version__ = "0.138.1" from starlette import status as status From cba41585675ecb0e119d3ca258821659f07ec3f7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebasti=C3=A1n=20Ram=C3=ADrez?= Date: Sat, 27 Jun 2026 14:47:35 +0200 Subject: [PATCH 321/462] =?UTF-8?q?=E2=99=BB=EF=B8=8F=20Refactor=20how=20s?= =?UTF-8?q?ponsors=20data=20is=20handled=20for=20banners=20(#15852)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .pre-commit-config.yaml | 7 +++ docs/en/data/sponsors.yml | 11 ++++ docs/en/overrides/main.html | 49 +---------------- .../overrides/partials/banner-sponsors.html | 48 +++++++++++++++++ scripts/docs.py | 52 +++++++++++++++++++ 5 files changed, 119 insertions(+), 48 deletions(-) create mode 100644 docs/en/overrides/partials/banner-sponsors.html diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 22f8971e6..eb0762df5 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -65,6 +65,13 @@ repos: files: ^docs/en/docs/index\.md|docs/en/data/sponsors\.yml|scripts/docs\.py$ pass_filenames: false + - id: render-banner-sponsors + language: unsupported + name: render sponsor banner partial + entry: uv run ./scripts/docs.py render-banner-sponsors + files: ^docs/en/data/sponsors\.yml|^docs/en/overrides/partials/banner-sponsors\.html|^scripts/docs\.py$ + pass_filenames: false + - id: update-languages language: unsupported name: update languages diff --git a/docs/en/data/sponsors.yml b/docs/en/data/sponsors.yml index 3d011ba12..f9d4505f1 100644 --- a/docs/en/data/sponsors.yml +++ b/docs/en/data/sponsors.yml @@ -6,27 +6,38 @@ gold: - url: https://blockbee.io?ref=fastapi title: BlockBee Cryptocurrency Payment Gateway img: /img/sponsors/blockbee.png + banner_img: /img/sponsors/blockbee-banner.png - url: https://www.propelauth.com/?utm_source=fastapi&utm_campaign=1223&utm_medium=mainbadge title: Auth, user management and more for your B2B product img: /img/sponsors/propelauth.png + banner_url: https://www.propelauth.com/?utm_source=fastapi&utm_campaign=1223&utm_medium=topbanner + banner_img: /img/sponsors/propelauth-banner.png - url: https://docs.render.com/deploy-fastapi?utm_source=deploydoc&utm_medium=referral&utm_campaign=fastapi title: Deploy & scale any full-stack web app on Render. Focus on building apps, not infra. img: /img/sponsors/render.svg + banner_img: /img/sponsors/render-banner.svg - url: https://www.coderabbit.ai/?utm_source=fastapi&utm_medium=badge&utm_campaign=fastapi title: Cut Code Review Time & Bugs in Half with CodeRabbit img: /img/sponsors/coderabbit.png + banner_url: https://www.coderabbit.ai/?utm_source=fastapi&utm_medium=banner&utm_campaign=fastapi + banner_img: /img/sponsors/coderabbit-banner.png - url: https://subtotal.com/?utm_source=fastapi&utm_medium=sponsorship&utm_campaign=open-source title: The Gold Standard in Retail Account Linking img: /img/sponsors/subtotal.svg + banner_title: Making Retail Purchases Actionable for Brands and Developers + banner_img: /img/sponsors/subtotal-banner.svg - url: https://docs.railway.com/guides/fastapi?utm_medium=integration&utm_source=docs&utm_campaign=fastapi title: Deploy enterprise applications at startup speed img: /img/sponsors/railway.png + banner_img: /img/sponsors/railway-banner.png - url: https://serpapi.com/?utm_source=fastapi_website title: "SerpApi: Web Search API" img: /img/sponsors/serpapi.png + banner_img: /img/sponsors/serpapi-banner.png - url: https://www.greptile.com/?utm_source=fastapi&utm_medium=sponsorship&utm_campaign=fastapi_sponsor_page title: "Greptile: The AI Code Reviewer" img: /img/sponsors/greptile.png + banner_img: /img/sponsors/greptile-banner.png silver: - url: https://databento.com/?utm_source=fastapi&utm_medium=sponsor&utm_content=display title: Pay as you go for market data diff --git a/docs/en/overrides/main.html b/docs/en/overrides/main.html index 4b0e81111..1905a6573 100644 --- a/docs/en/overrides/main.html +++ b/docs/en/overrides/main.html @@ -40,54 +40,7 @@
- - - - - - - - + {% include "partials/banner-sponsors.html" %}
{% endblock %} diff --git a/docs/en/overrides/partials/banner-sponsors.html b/docs/en/overrides/partials/banner-sponsors.html new file mode 100644 index 000000000..ae689ad89 --- /dev/null +++ b/docs/en/overrides/partials/banner-sponsors.html @@ -0,0 +1,48 @@ + + + + + + + + diff --git a/scripts/docs.py b/scripts/docs.py index 8e3d5e832..a108c8ddf 100644 --- a/scripts/docs.py +++ b/scripts/docs.py @@ -249,6 +249,7 @@ def stage_zensical_docs(lang: str) -> Path: encoding="utf-8", ) + render_banner_sponsors() shutil.copytree(en_docs_path / "data", lang_stage_path / "data") shutil.copytree(en_docs_path / "overrides", lang_stage_path / "overrides") @@ -461,6 +462,7 @@ def live() -> None: """ Serve the English docs with livereload from the source files. """ + render_banner_sponsors() subprocess.run( [ "zensical", @@ -508,6 +510,56 @@ def get_updated_config_content() -> dict[str, Any]: return config +banner_sponsors_template = """{% for sponsor in banner_sponsors -%} + +{% endfor %} +""" + + +def get_banner_sponsors(sponsors: dict[str, Any]) -> list[dict[str, str]]: + banner_sponsors: list[dict[str, str]] = [] + for sponsor in sponsors.get("gold", []): + banner_img = sponsor.get("banner_img") + if not banner_img: + continue + banner_sponsors.append( + { + "url": sponsor.get("banner_url", sponsor["url"]), + "title": sponsor.get("banner_title", sponsor["title"]), + "img": banner_img, + } + ) + return banner_sponsors + + +def render_banner_sponsors_partial() -> str: + sponsors_path = en_docs_path / "data" / "sponsors.yml" + sponsors = yaml.safe_load(sponsors_path.read_text(encoding="utf-8")) + template = Template(banner_sponsors_template) + return template.render(banner_sponsors=get_banner_sponsors(sponsors)) + + +@app.command() +def render_banner_sponsors() -> None: + """ + Render the sponsor banner partial from sponsors.yml. + """ + partial_path = en_docs_path / "overrides" / "partials" / "banner-sponsors.html" + old_content = partial_path.read_text("utf-8") if partial_path.is_file() else "" + new_content = render_banner_sponsors_partial() + if new_content != old_content: + print(f"{partial_path} outdated from the latest sponsors.yml") + print(f"Updating {partial_path}") + partial_path.write_text(new_content, encoding="utf-8") + raise typer.Exit(1) + print(f"{partial_path} is up to date ✅") + + @app.command() def ensure_non_translated() -> None: """ From 1929ac23195136e8616ed1b7c3fd84c65b26d234 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Sat, 27 Jun 2026 12:48:01 +0000 Subject: [PATCH 322/462] =?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 87286fe51..7232820f3 100644 --- a/docs/en/docs/release-notes.md +++ b/docs/en/docs/release-notes.md @@ -7,6 +7,10 @@ hide: ## Latest Changes +### Internal + +* ♻️ Refactor how sponsors data is handled for banners. PR [#15852](https://github.com/fastapi/fastapi/pull/15852) by [@tiangolo](https://github.com/tiangolo). + ## 0.138.1 (2026-06-25) ### Refactors From 403b1fa16f9519f4b5ab52413daae059479fae4a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebasti=C3=A1n=20Ram=C3=ADrez?= Date: Mon, 29 Jun 2026 13:20:57 +0200 Subject: [PATCH 323/462] =?UTF-8?q?=F0=9F=94=A7=20Update=20sponsors:=20rem?= =?UTF-8?q?ove=20Stainless=20(#15862)?= 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/docs/advanced/generate-clients.md | 14 -------------- 3 files changed, 18 deletions(-) diff --git a/README.md b/README.md index fbf66a48b..03cd90e77 100644 --- a/README.md +++ b/README.md @@ -64,7 +64,6 @@ The key features are: - diff --git a/docs/en/data/sponsors.yml b/docs/en/data/sponsors.yml index f9d4505f1..ae2c0f6e2 100644 --- a/docs/en/data/sponsors.yml +++ b/docs/en/data/sponsors.yml @@ -45,9 +45,6 @@ silver: - url: https://www.svix.com/ title: Svix - Webhooks as a service img: /img/sponsors/svix.svg - - url: https://www.stainlessapi.com/?utm_source=fastapi&utm_medium=referral - title: Stainless | Generate best-in-class SDKs - img: /img/sponsors/stainless.png - url: https://www.permit.io/blog/implement-authorization-in-fastapi?utm_source=github&utm_medium=referral&utm_campaign=fastapi title: Fine-Grained Authorization for FastAPI img: /img/sponsors/permit.png diff --git a/docs/en/docs/advanced/generate-clients.md b/docs/en/docs/advanced/generate-clients.md index 7db45cc8a..67dfe736f 100644 --- a/docs/en/docs/advanced/generate-clients.md +++ b/docs/en/docs/advanced/generate-clients.md @@ -20,20 +20,6 @@ FastAPI automatically generates **OpenAPI 3.1** specifications, so any tool you /// -## SDK Generators from FastAPI Sponsors { #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. - -By ✨ [**sponsoring FastAPI**](https://github.com/sponsors/tiangolo) ✨, these companies help ensure the framework and its **ecosystem** remain healthy and **sustainable**. - -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: - -* [Stainless](https://www.stainless.com/?utm_source=fastapi&utm_medium=referral) - -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. 🤓 - ## Create a TypeScript SDK { #create-a-typescript-sdk } Let's start with a simple FastAPI application: From c2708d981729c96437dcc1d7cfa40cd15128bc60 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Mon, 29 Jun 2026 11:21:22 +0000 Subject: [PATCH 324/462] =?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 7232820f3..73d86cfab 100644 --- a/docs/en/docs/release-notes.md +++ b/docs/en/docs/release-notes.md @@ -9,6 +9,7 @@ hide: ### Internal +* 🔧 Update sponsors: remove Stainless. PR [#15862](https://github.com/fastapi/fastapi/pull/15862) by [@tiangolo](https://github.com/tiangolo). * ♻️ Refactor how sponsors data is handled for banners. PR [#15852](https://github.com/fastapi/fastapi/pull/15852) by [@tiangolo](https://github.com/tiangolo). ## 0.138.1 (2026-06-25) From b790e14cb686506df663959ac4879053cfed38db Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebasti=C3=A1n=20Ram=C3=ADrez?= Date: Mon, 29 Jun 2026 13:57:59 +0200 Subject: [PATCH 325/462] =?UTF-8?q?=E2=99=BB=EF=B8=8F=20Make=20`app.fronte?= =?UTF-8?q?nd()`=20return=20404=20for=20methods=20other=20than=20`GET`=20o?= =?UTF-8?q?r=20`HEAD`=20with=20no=20static=20file=20matches=20(#15863)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docs/en/docs/tutorial/frontend.md | 4 +- fastapi/routing.py | 62 ++++++++------ tests/test_frontend.py | 135 ++++++++++++++++++++++++++++++ 3 files changed, 175 insertions(+), 26 deletions(-) diff --git a/docs/en/docs/tutorial/frontend.md b/docs/en/docs/tutorial/frontend.md index 9f0bc0566..4cbc21fa1 100644 --- a/docs/en/docs/tutorial/frontend.md +++ b/docs/en/docs/tutorial/frontend.md @@ -52,7 +52,9 @@ For that, use `fallback="index.html"`: {* ../../docs_src/frontend/tutorial002_py310.py hl[5] *} -**FastAPI** uses this fallback only for requests that look like browser navigation. Missing files like JavaScript, CSS, and images still return `404`. +**FastAPI** uses this fallback only for `GET` and `HEAD` requests that look like browser navigation. Missing files like JavaScript, CSS, and images still return `404`. + +Requests with other methods, like `POST` or `PUT`, to paths that only match the frontend fallback also return `404`. Regular **FastAPI** *path operations* still have higher priority than frontend routes. /// tip diff --git a/fastapi/routing.py b/fastapi/routing.py index 3a2d75422..e41ef6a59 100644 --- a/fastapi/routing.py +++ b/fastapi/routing.py @@ -1841,34 +1841,19 @@ class _FrontendStaticFiles(StaticFiles): async def get_response(self, path: str, scope: Scope) -> Response: if scope["method"] not in ("GET", "HEAD"): - raise HTTPException(status_code=405) - - try: - full_path, stat_result = await run_in_threadpool(self.lookup_path, path) - except PermissionError: - raise HTTPException(status_code=401) from None - except OSError as exc: - if exc.errno == errno.ENAMETOOLONG: - raise HTTPException(status_code=404) from None - raise exc - except ValueError: - raise HTTPException(status_code=404) from None + if await self._lookup_static_resource(path) is not None: + raise HTTPException(status_code=405) + raise HTTPException(status_code=404) - if stat_result and stat.S_ISREG(stat_result.st_mode): + static_resource = await self._lookup_static_resource(path) + if static_resource is not None: + full_path, stat_result, is_directory_index = static_resource + if is_directory_index and not scope["path"].endswith("/"): + url = URL(scope=scope) + url = url.replace(path=url.path + "/") + return RedirectResponse(url=url) return self.file_response(full_path, stat_result, scope) - if stat_result and stat.S_ISDIR(stat_result.st_mode): - index_path = os.path.join(path, "index.html") - full_path, stat_result = await run_in_threadpool( - self.lookup_path, index_path - ) - if stat_result is not None and stat.S_ISREG(stat_result.st_mode): - if not scope["path"].endswith("/"): - url = URL(scope=scope) - url = url.replace(path=url.path + "/") - return RedirectResponse(url=url) - return self.file_response(full_path, stat_result, scope) - if self.fallback == "404.html" or ( self.fallback == "auto" and self._fallback_file_exists("404.html") ): @@ -1882,6 +1867,33 @@ class _FrontendStaticFiles(StaticFiles): raise HTTPException(status_code=404) + async def _lookup_path(self, path: str) -> tuple[str, os.stat_result | None]: + try: + return await run_in_threadpool(self.lookup_path, path) + except PermissionError: + raise HTTPException(status_code=401) from None + except OSError as exc: + if exc.errno == errno.ENAMETOOLONG: + raise HTTPException(status_code=404) from None + raise exc + except ValueError: + raise HTTPException(status_code=404) from None + + async def _lookup_static_resource( + self, path: str + ) -> tuple[str, os.stat_result, bool] | None: + full_path, stat_result = await self._lookup_path(path) + if stat_result is None: + return None + if stat.S_ISREG(stat_result.st_mode): + return full_path, stat_result, False + if stat.S_ISDIR(stat_result.st_mode): + index_path = os.path.join(path, "index.html") + full_path, stat_result = await self._lookup_path(index_path) + if stat_result is not None and stat.S_ISREG(stat_result.st_mode): + return full_path, stat_result, True + return None + def _fallback_file_exists(self, fallback: str) -> bool: _, stat_result = self.lookup_path(fallback) return stat_result is not None and stat.S_ISREG(stat_result.st_mode) diff --git a/tests/test_frontend.py b/tests/test_frontend.py index 12be8eaf2..81cffc228 100644 --- a/tests/test_frontend.py +++ b/tests/test_frontend.py @@ -2,6 +2,7 @@ import errno import os import runpy from pathlib import Path +from typing import Literal import anyio import pytest @@ -639,6 +640,21 @@ def test_head_requests_work(tmp_path: Path): assert response.headers["content-length"] == "2" +def test_head_fallback_request_works(tmp_path: Path): + dist = tmp_path / "dist" + write_file(dist / "index.html", "app shell") + app = FastAPI() + app.frontend("/", directory=dist, fallback="index.html") + + response = TestClient(app).head( + "/dashboard/settings", headers={"accept": "text/html"} + ) + + assert response.status_code == 200 + assert response.text == "" + assert response.headers["content-length"] == "9" + + def test_unsupported_methods_return_405(tmp_path: Path): dist = tmp_path / "dist" write_file(dist / "asset.txt", "ok") @@ -650,6 +666,125 @@ def test_unsupported_methods_return_405(tmp_path: Path): assert response.status_code == 405 +@pytest.mark.parametrize("method", ["POST", "PUT", "PATCH", "DELETE", "OPTIONS"]) +def test_unsupported_methods_to_fallback_only_routes_return_404( + tmp_path: Path, method: str +): + dist = tmp_path / "dist" + write_file(dist / "index.html", "app shell") + app = FastAPI() + app.frontend("/", directory=dist, fallback="index.html") + + response = TestClient(app).request( + method, "/dashboard/settings", headers={"accept": "text/html"} + ) + + assert response.status_code == 404 + + +def test_unsupported_methods_to_frontend_root_and_directory_index_return_405( + tmp_path: Path, +): + dist = tmp_path / "dist" + write_file(dist / "index.html", "app") + write_file(dist / "about" / "index.html", "about") + app = FastAPI() + app.frontend("/", directory=dist) + client = TestClient(app) + + root_response = client.post("/") + directory_response = client.post("/about/") + + assert root_response.status_code == 405 + assert directory_response.status_code == 405 + + +def test_unsupported_method_to_directory_without_index_returns_404(tmp_path: Path): + dist = tmp_path / "dist" + (dist / "empty").mkdir(parents=True) + write_file(dist / "index.html", "app") + app = FastAPI() + app.frontend("/", directory=dist) + + response = TestClient(app).post("/empty/") + + assert response.status_code == 404 + + +def test_unsupported_methods_to_fallback_only_routes_ignore_accept( + tmp_path: Path, +): + dist = tmp_path / "dist" + write_file(dist / "index.html", "app shell") + app = FastAPI() + app.frontend("/", directory=dist, fallback="index.html") + + response = TestClient(app).post( + "/dashboard/settings", headers={"accept": "application/json"} + ) + + assert response.status_code == 404 + + +@pytest.mark.parametrize( + ("fallback", "files"), + [ + ("404.html", {"404.html": "missing"}), + ("auto", {"index.html": "app shell"}), + (None, {"index.html": "app shell"}), + ], +) +def test_unsupported_methods_to_fallback_only_routes_return_404_for_fallback_modes( + tmp_path: Path, + fallback: Literal["auto", "index.html", "404.html"] | None, + files: dict[str, str], +): + dist = tmp_path / "dist" + for file, content in files.items(): + write_file(dist / file, content) + app = FastAPI() + app.frontend("/", directory=dist, fallback=fallback) + + response = TestClient(app).post( + "/dashboard/settings", headers={"accept": "text/html"} + ) + + assert response.status_code == 404 + + +def test_apirouter_frontend_unsupported_method_to_fallback_only_route_returns_404( + tmp_path: Path, +): + dist = tmp_path / "dist" + write_file(dist / "index.html", "admin") + router = APIRouter() + router.frontend("/", directory=dist, fallback="index.html") + app = FastAPI() + app.include_router(router, prefix="/admin") + + response = TestClient(app).post( + "/admin/client-route", headers={"accept": "text/html"} + ) + + assert response.status_code == 404 + + +def test_unsupported_method_uses_longest_matching_frontend_prefix(tmp_path: Path): + site = tmp_path / "site" + admin = tmp_path / "admin" + write_file(site / "admin" / "client-route", "site asset") + write_file(admin / "index.html", "admin") + app = FastAPI() + app.frontend("/", directory=site) + app.frontend("/admin", directory=admin, fallback="index.html") + + response = TestClient(app).post( + "/admin/client-route", headers={"accept": "text/html"} + ) + + assert response.status_code == 404 + + @pytest.mark.parametrize( "path", [ From 6466865eec63cb545869d80e2ee6fbc54c4d364e Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Mon, 29 Jun 2026 11:58:23 +0000 Subject: [PATCH 326/462] =?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 73d86cfab..fb7f61bed 100644 --- a/docs/en/docs/release-notes.md +++ b/docs/en/docs/release-notes.md @@ -7,6 +7,10 @@ hide: ## Latest Changes +### Refactors + +* ♻️ Make `app.frontend()` return 404 for methods other than `GET` or `HEAD` with no static file matches. PR [#15863](https://github.com/fastapi/fastapi/pull/15863) by [@tiangolo](https://github.com/tiangolo). + ### Internal * 🔧 Update sponsors: remove Stainless. PR [#15862](https://github.com/fastapi/fastapi/pull/15862) by [@tiangolo](https://github.com/tiangolo). From 702fea83bb3ef0b558104835d7936af49650fb2d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebasti=C3=A1n=20Ram=C3=ADrez?= Date: Mon, 29 Jun 2026 14:06:51 +0200 Subject: [PATCH 327/462] =?UTF-8?q?=F0=9F=94=96=20Release=20version=200.13?= =?UTF-8?q?8.2=20(#15864)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: github-actions[bot] --- docs/en/docs/release-notes.md | 2 ++ fastapi/__init__.py | 2 +- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/docs/en/docs/release-notes.md b/docs/en/docs/release-notes.md index fb7f61bed..5e8528c9f 100644 --- a/docs/en/docs/release-notes.md +++ b/docs/en/docs/release-notes.md @@ -7,6 +7,8 @@ hide: ## Latest Changes +## 0.138.2 (2026-06-29) + ### Refactors * ♻️ Make `app.frontend()` return 404 for methods other than `GET` or `HEAD` with no static file matches. PR [#15863](https://github.com/fastapi/fastapi/pull/15863) by [@tiangolo](https://github.com/tiangolo). diff --git a/fastapi/__init__.py b/fastapi/__init__.py index a61ac1bd7..af5117aec 100644 --- a/fastapi/__init__.py +++ b/fastapi/__init__.py @@ -1,6 +1,6 @@ """FastAPI framework, high performance, easy to learn, fast to code, ready for production""" -__version__ = "0.138.1" +__version__ = "0.138.2" from starlette import status as status From 4a298abff1d8c85c9d50e8f3600bb76b427b7f5a Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 30 Jun 2026 10:52:46 +0200 Subject: [PATCH 328/462] =?UTF-8?q?=E2=AC=86=20Bump=20CodSpeedHQ/action=20?= =?UTF-8?q?from=204.17.0=20to=204.17.5=20in=20the=20github-actions=20group?= =?UTF-8?q?=20(#15826)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/test.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 18abb7482..6870160de 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -191,7 +191,7 @@ jobs: - name: Install Dependencies run: uv sync --no-dev --group tests --extra all - name: CodSpeed benchmarks - uses: CodSpeedHQ/action@9d332c4d90b43981c3e55ae8e38e68709996240f # v4.17.0 + uses: CodSpeedHQ/action@c145068895e045cc725ee76fcd2307624b65c3af # v4.17.5 with: mode: simulation run: uv run --no-sync pytest tests/benchmarks --codspeed From a5d220ddbf49789f1d76d12e33b34b909ed4b019 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Tue, 30 Jun 2026 08:53:18 +0000 Subject: [PATCH 329/462] =?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 5e8528c9f..63477962c 100644 --- a/docs/en/docs/release-notes.md +++ b/docs/en/docs/release-notes.md @@ -7,6 +7,10 @@ hide: ## Latest Changes +### Internal + +* ⬆ Bump CodSpeedHQ/action from 4.17.0 to 4.17.5 in the github-actions group. PR [#15826](https://github.com/fastapi/fastapi/pull/15826) by [@dependabot[bot]](https://github.com/apps/dependabot). + ## 0.138.2 (2026-06-29) ### Refactors From 66a2ad87c17bae25e9e9cab44e285ba84b72734c Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 30 Jun 2026 11:20:46 +0200 Subject: [PATCH 330/462] =?UTF-8?q?=E2=AC=86=20Bump=20the=20python-package?= =?UTF-8?q?s=20group=20across=201=20directory=20with=2010=20updates=20(#15?= =?UTF-8?q?870)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- uv.lock | 237 ++++++++++++++++++++++++++++---------------------------- 1 file changed, 119 insertions(+), 118 deletions(-) diff --git a/uv.lock b/uv.lock index 7d5e106ca..4fdc971ee 100644 --- a/uv.lock +++ b/uv.lock @@ -2160,15 +2160,15 @@ wheels = [ [[package]] name = "httpcore2" -version = "2.3.0" +version = "2.4.0" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "h11" }, { name = "truststore" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/e6/34/18f1c596e677962f040284246f393b10a1f8ce440b3a7e69c637d0f1c7ad/httpcore2-2.3.0.tar.gz", hash = "sha256:07327e251560960eea8e969d92d4c6a325feb13cca39e25340731336c3baf924", size = 64300, upload-time = "2026-06-01T13:15:02.998Z" } +sdist = { url = "https://files.pythonhosted.org/packages/7b/9b/2b1d1833a58236d1f6ee755e027a3917da0db59cc9708554cefc440ee8b6/httpcore2-2.4.0.tar.gz", hash = "sha256:3093a8ab8980d9f910b9cb4351df9186a0ad2350a6284a9107ac9a362a584422", size = 64618, upload-time = "2026-06-11T06:35:53.425Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/c2/dd/3357218c69360d1cecc196c230c9a1d5c9afd5dba362056e23e60a5e64e5/httpcore2-2.3.0-py3-none-any.whl", hash = "sha256:477e9e334f74e5240dcac002e890580f36a57d40ff0fb14cc9655731d23b8415", size = 80024, upload-time = "2026-06-01T13:15:00.001Z" }, + { url = "https://files.pythonhosted.org/packages/7c/72/4fdf2306143a92a471fad9f3655aa542d43aa9188a7c9534e82c9aecf837/httpcore2-2.4.0-py3-none-any.whl", hash = "sha256:5218779da5d6e3c2013ac706121abfb3815d450e0613495c0de50264dce58242", size = 80151, upload-time = "2026-06-11T06:35:50.89Z" }, ] [[package]] @@ -2240,17 +2240,18 @@ wheels = [ [[package]] name = "httpx2" -version = "2.3.0" +version = "2.4.0" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "anyio" }, { name = "httpcore2" }, { name = "idna" }, { name = "truststore" }, + { name = "typing-extensions", marker = "python_full_version < '3.13'" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/9f/9a/cca0b9145f13d8ae34b885ae28d403a1469a433abc78e0f94f4ce94e650b/httpx2-2.3.0.tar.gz", hash = "sha256:227e7c41d95a76d4077a52640564132777215fc3394e07b66a3116c33d668fa9", size = 81115, upload-time = "2026-06-01T13:15:04.324Z" } +sdist = { url = "https://files.pythonhosted.org/packages/fc/60/b43ced4ccf26e95b396dbf67051d3e5042b645917d4da0469dd82a3bdd4f/httpx2-2.4.0.tar.gz", hash = "sha256:32e0734b61eb0824b3f56a9e98d6d92d381a3ef12c0045aa917ee63df6c411ef", size = 81691, upload-time = "2026-06-11T06:35:54.538Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/87/ce/ae2911859847f9ba1d6b23027e53481cbeb50b93234f355a968d300ca2cb/httpx2-2.3.0-py3-none-any.whl", hash = "sha256:6f393663bdf6dbe7fe90118e3eb5b2bd024a675cae0390ac08cec9198812d8b7", size = 74538, upload-time = "2026-06-01T13:15:01.566Z" }, + { url = "https://files.pythonhosted.org/packages/29/45/82bc57c3d9c3314f663b67cc057f1c017a6450685dde513f4f8db5cf431f/httpx2-2.4.0-py3-none-any.whl", hash = "sha256:425acd99297829599decf6701386dd84db3542597d36d3e2e4def930ecd57fd9", size = 74941, upload-time = "2026-06-11T06:35:52.235Z" }, ] [[package]] @@ -2276,11 +2277,11 @@ wheels = [ [[package]] name = "idna" -version = "3.15" +version = "3.18" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/82/77/7b3966d0b9d1d31a36ddf1746926a11dface89a83409bf1483f0237aa758/idna-3.15.tar.gz", hash = "sha256:ca962446ea538f7092a95e057da437618e886f4d349216d2b1e294abfdb65fdc", size = 199245, upload-time = "2026-05-12T22:45:57.011Z" } +sdist = { url = "https://files.pythonhosted.org/packages/cd/63/9496c57188a2ee585e0f1db071d75089a11e98aa86eb99d9d7618fc1edce/idna-3.18.tar.gz", hash = "sha256:ffb385a7e039654cef1ab9ef32c6fafe283c0c0467bba1d9029738ce4a14a848", size = 196711, upload-time = "2026-06-02T14:34:07.794Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/d2/23/408243171aa9aaba178d3e2559159c24c1171a641aa83b67bdd3394ead8e/idna-3.15-py3-none-any.whl", hash = "sha256:048adeaf8c2d788c40fee287673ccaa74c24ffd8dcf09ffa555a2fbb59f10ac8", size = 72340, upload-time = "2026-05-12T22:45:55.733Z" }, + { url = "https://files.pythonhosted.org/packages/1e/5e/d4e9f1a599fb8e573b7b87160658329fbf28d19eac2718f51fc3def3aa5a/idna-3.18-py3-none-any.whl", hash = "sha256:7f952cbe720b688055e3f87de14f5c3e5fdaa8bc3928985c4077ca689de849a2", size = 65455, upload-time = "2026-06-02T14:34:06.319Z" }, ] [[package]] @@ -2306,7 +2307,7 @@ wheels = [ [[package]] name = "inline-snapshot" -version = "0.34.1" +version = "0.34.2" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "asttokens" }, @@ -2316,9 +2317,9 @@ dependencies = [ { name = "tomli", marker = "python_full_version < '3.11'" }, { name = "typing-extensions" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/b8/2e/00c99468c7788bdb4f7d861bcfbfb091a5fe1bc475f9dd031f667c422a73/inline_snapshot-0.34.1.tar.gz", hash = "sha256:f8af37876c42069b7c0ed73f64357ace482955c3225ebcd27f243197ecfbcb65", size = 2638769, upload-time = "2026-06-05T16:58:47.921Z" } +sdist = { url = "https://files.pythonhosted.org/packages/91/c3/b5c36ab59e355b8d7c59205b8903fa74458c6938c9691f7d7730404f94c9/inline_snapshot-0.34.2.tar.gz", hash = "sha256:d160cb6059e00916c2e846abc014ead6f01fb24479f13696fb8670d7a7937f67", size = 2641142, upload-time = "2026-06-19T21:17:27.338Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/ba/83/21747d0ee2276e973a2889e960f2ec904fbbe83fac6fecd8a57995bb81df/inline_snapshot-0.34.1-py3-none-any.whl", hash = "sha256:4c043215866dfdbe6a3ead92d9d0a9294720c7deebddc346dc781654cb19daa9", size = 90039, upload-time = "2026-06-05T16:58:46.038Z" }, + { url = "https://files.pythonhosted.org/packages/bb/2a/84fe7ef052ac666e95e7cabdf0905aa3f2c90b5a117419760b39b577602a/inline_snapshot-0.34.2-py3-none-any.whl", hash = "sha256:743a514a08ffd0d2d62878b0208d4def5041585affa7db6b89f0ca2e23552361", size = 90717, upload-time = "2026-06-19T21:17:25.629Z" }, ] [[package]] @@ -3546,26 +3547,26 @@ wheels = [ [[package]] name = "prek" -version = "0.4.4" +version = "0.4.5" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/f6/13/3d71b3adbf385f7dc7fb6e16d6e25421fd8398b45d8f8410a328bf22bd3f/prek-0.4.4.tar.gz", hash = "sha256:4ec5771153d158a0e4473933b7fd9b51e1b1f57f2df50aeb7560ea6812226dc5", size = 470641, upload-time = "2026-06-04T07:26:07.199Z" } +sdist = { url = "https://files.pythonhosted.org/packages/2f/65/23866f43521d31173879aa74bb3a2df50ab7f3f74cdb4eaa31b8f446c7ca/prek-0.4.5.tar.gz", hash = "sha256:2be7bcf839de19a0144ed5a5aadf73bc5899cf6823bb1c58cf1d45ae389c201a", size = 482566, upload-time = "2026-06-15T11:36:48.299Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/06/9f/68a577888edf7f2647a652b02899508ccd84e57ce1f79c51a44edfd308d7/prek-0.4.4-py3-none-linux_armv6l.whl", hash = "sha256:23cfd96a25de1c93e3c43c746643b80489e3b2fa49ca9c0ffd6022e51535c900", size = 5550271, upload-time = "2026-06-04T07:26:17.834Z" }, - { url = "https://files.pythonhosted.org/packages/35/b8/5427a0023116343a8d787b446536a7fddfa5db7eec7713dd05618da2bdfe/prek-0.4.4-py3-none-macosx_10_12_x86_64.whl", hash = "sha256:a427b792c4436f49732b1f6ebccf221fdcc6390c148474280da9c2c6eaabc9c4", size = 5910136, upload-time = "2026-06-04T07:26:20.616Z" }, - { url = "https://files.pythonhosted.org/packages/9d/4f/d751e90b7e768e472e054cd41cbe502589436ca9c1a13bfe4fa9513f9cde/prek-0.4.4-py3-none-macosx_11_0_arm64.whl", hash = "sha256:b998038fc92c990e03147eb5b95b0f2c394517f8857ab911aac8e092f1b9b3ab", size = 5470124, upload-time = "2026-06-04T07:26:29.23Z" }, - { url = "https://files.pythonhosted.org/packages/c6/fe/e73241c5777b6f9b6b95132febbd27f9be9e89912e9e93c0982680593af2/prek-0.4.4-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.musllinux_1_1_aarch64.whl", hash = "sha256:9cebca8c15da4f1d6e3a25e6ae0611425c8596e926222050f2588c390e42df8a", size = 5732725, upload-time = "2026-06-04T07:26:19.133Z" }, - { url = "https://files.pythonhosted.org/packages/ca/a3/329bd910e7e5d9d0eb5e571f3ba48023213744e78411afb81f5ef8356cab/prek-0.4.4-py3-none-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:c8742ac26363e74c855df6215a709d5db183204d00ac0f1a722b13aed4da3cd0", size = 5457953, upload-time = "2026-06-04T07:26:23.41Z" }, - { url = "https://files.pythonhosted.org/packages/3d/f8/d642990513d9707398506bad45d39173d84266231f7d919899f694aefe2c/prek-0.4.4-py3-none-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:a2b7c8710546a1e894afa7ab022030cd4e21f1ee7ffb301b4360773d22f1f00f", size = 5860556, upload-time = "2026-06-04T07:26:11.692Z" }, - { url = "https://files.pythonhosted.org/packages/8d/17/a2e29cb278503a8c18612d8a62a15020648dc768e2e94bc4b4d4c9411e07/prek-0.4.4-py3-none-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:e02bd4d5e05c500e4d9f70f024e30d13aa361dc490724b7f476d2e35542c239f", size = 6652492, upload-time = "2026-06-04T07:26:09.962Z" }, - { url = "https://files.pythonhosted.org/packages/ab/10/ad3270b18135ee5d1af6f6cf4b0c8601b1cc2cb38d16e835081da820833a/prek-0.4.4-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3f3a25041733de987a47e5a7bace47182a6f0e2ae5f960cb54c1d4630afd2591", size = 6113837, upload-time = "2026-06-04T07:26:24.873Z" }, - { url = "https://files.pythonhosted.org/packages/59/d9/e8c201b9b41c4561673cea01c630ab604df89d13e952f87dbcb807d32588/prek-0.4.4-py3-none-manylinux_2_28_aarch64.whl", hash = "sha256:0b04a0f36d07474f2a9fc5b1ba1197a1b326b2b211f39cd74cf0d4613545f7f4", size = 5729155, upload-time = "2026-06-04T07:26:26.194Z" }, - { url = "https://files.pythonhosted.org/packages/e8/cd/227b0494fcbc91e8fe15c2a4db9e6dfff95314ef38db3e40e6ea96db249d/prek-0.4.4-py3-none-manylinux_2_31_riscv64.whl", hash = "sha256:f032ccbe2d6edc345f81a6d772c18cc169d63c27b5a8292bfe416b352bdfee57", size = 5590775, upload-time = "2026-06-04T07:26:22.038Z" }, - { url = "https://files.pythonhosted.org/packages/cc/e0/9d750b9cf21ece884afdc15668d0f005a36588fe1b0bb5ff4a8112ab51cb/prek-0.4.4-py3-none-musllinux_1_1_armv7l.whl", hash = "sha256:bad3586fcea3e913f0edf2e8f132f97889e03976b7ee3d120fd294ad4e89a5eb", size = 5437864, upload-time = "2026-06-04T07:26:30.673Z" }, - { url = "https://files.pythonhosted.org/packages/3a/48/e2e5c0299590ad18a253c0ac09508b615baa1b382010c511186572f711d3/prek-0.4.4-py3-none-musllinux_1_1_i686.whl", hash = "sha256:4058638532c6dcbf0076d23b9264cbdd9f0f0e320762e237a6b9e4e4b854a766", size = 5718579, upload-time = "2026-06-04T07:26:27.786Z" }, - { url = "https://files.pythonhosted.org/packages/54/48/7fb3d4e7f664d1ce8ae35ec553872ffddf9fab4c5081735fdaae610b1e7c/prek-0.4.4-py3-none-musllinux_1_1_x86_64.whl", hash = "sha256:619bab14071670249777deea0cc0b29d904c4a514cf33b20e583900a544f0399", size = 6231622, upload-time = "2026-06-04T07:26:16.309Z" }, - { url = "https://files.pythonhosted.org/packages/46/c0/a4ddbf38034afe67cfa97c4bd81c86429ada098e7c323218d9f9fd061566/prek-0.4.4-py3-none-win32.whl", hash = "sha256:143154b329c05b2f9fa3230e604d02d9c4297dd43f96135a8ba166772e8ecd60", size = 5240317, upload-time = "2026-06-04T07:26:08.726Z" }, - { url = "https://files.pythonhosted.org/packages/bc/8c/fe97b5b095187bb2f93bbe406bccf108c879e5e4c83f165809b0d16ce0fb/prek-0.4.4-py3-none-win_amd64.whl", hash = "sha256:c38c5140ae2ea55ebb02e6ca590a416664ea1af287cdd21f54daeec53a81015a", size = 5626104, upload-time = "2026-06-04T07:26:14.81Z" }, - { url = "https://files.pythonhosted.org/packages/25/63/3586226d536796e65f8e725b531d6104e55caaa18659bdcb512661629586/prek-0.4.4-py3-none-win_arm64.whl", hash = "sha256:3efa28fb37b9ddbafb7759da8d497f0d36cf02a05816e15d6541f5669d5d2114", size = 5470399, upload-time = "2026-06-04T07:26:13.231Z" }, + { url = "https://files.pythonhosted.org/packages/f4/cb/a9eedf9a35ca6ec72f12af2b4392d7f757bb24863b7b7af4523f939cf3fa/prek-0.4.5-py3-none-linux_armv6l.whl", hash = "sha256:f7517774c72b001573520dc7111156779fd3e5b4452c11f09ff53c71a067e835", size = 5618105, upload-time = "2026-06-15T11:36:21.998Z" }, + { url = "https://files.pythonhosted.org/packages/30/a7/c96c06f17db7da0a57be2be4c229aa00b525bca8001c9c765663b339cbb7/prek-0.4.5-py3-none-macosx_10_12_x86_64.whl", hash = "sha256:aca9fa995536036a0171bcf7a4db96dc0a14f480054eda1d7d1c2e7739650993", size = 5972998, upload-time = "2026-06-15T11:36:41.12Z" }, + { url = "https://files.pythonhosted.org/packages/28/f1/721695355cdaa44be6f091e3a77fb9c72ed60289520f78b2f8c9a7197bdd/prek-0.4.5-py3-none-macosx_11_0_arm64.whl", hash = "sha256:66877ff21ae9d548f0f7e56fab8e65f1500a74a810e7749188c3f35a4a1b911b", size = 5525098, upload-time = "2026-06-15T11:36:30.127Z" }, + { url = "https://files.pythonhosted.org/packages/9b/1b/a334e1bb5361b49adf52b5ac7b6532018940f9f0f253437e8f43c3c1f7f3/prek-0.4.5-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.musllinux_1_1_aarch64.whl", hash = "sha256:50697089a86a78d16f087c1912a2f3bc2bea82319a220fac52cc8e3ec9fc0426", size = 5793732, upload-time = "2026-06-15T11:36:35.745Z" }, + { url = "https://files.pythonhosted.org/packages/28/8c/aff94d276e91207a87cedff7cfefdd4aca20444137cca77bf53fffebe77a/prek-0.4.5-py3-none-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:590427a42a3c1e5064487a0dc91167ae0c8a52168e77f574758ef9b138fcfd61", size = 5521719, upload-time = "2026-06-15T11:36:39.383Z" }, + { url = "https://files.pythonhosted.org/packages/4f/73/cfb0c5c909442050a8357e26233f7e511ba8e0d2f4b0bdc460065d62beb6/prek-0.4.5-py3-none-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:1fd98b986767dafdb6b4305b563ee5a3a8f13bd3c78b98d708626815ea9f147f", size = 5922623, upload-time = "2026-06-15T11:36:18.063Z" }, + { url = "https://files.pythonhosted.org/packages/0a/ad/ff9d26551ba80d190bd08c6341176a5d56d4e6de9c2ebf077793d4adbb78/prek-0.4.5-py3-none-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:fccd11613ae92619d1ecda0ab3359ceebeb38898909ec84a8d383733d12158cc", size = 6722071, upload-time = "2026-06-15T11:36:43.086Z" }, + { url = "https://files.pythonhosted.org/packages/d3/43/11d1dfd66c919953fe89ae2fdedd4f413ee923883043816d35982177bb75/prek-0.4.5-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:14109d37b33e5529db41a3539d4f8f72d295f6eeddede3964994d898b8cec05c", size = 6176454, upload-time = "2026-06-15T11:36:33.803Z" }, + { url = "https://files.pythonhosted.org/packages/d7/d4/9749f25c2e0ee5225f812457b888acef301e0ccce64bebcda2ac1d04abee/prek-0.4.5-py3-none-manylinux_2_28_aarch64.whl", hash = "sha256:40d262418105b2ede9836593a1927fc927cc8093c432e998640964102196996e", size = 5791133, upload-time = "2026-06-15T11:36:23.891Z" }, + { url = "https://files.pythonhosted.org/packages/c7/72/5e0344bab1eacf813a5b1b082cb4c6253930096166dad51c1cccee0a4f83/prek-0.4.5-py3-none-manylinux_2_31_riscv64.whl", hash = "sha256:a586d14c3b852fdee1c3dcd0b9cb0915db9f9d054334b854fd9470bf68edf129", size = 5658098, upload-time = "2026-06-15T11:36:44.862Z" }, + { url = "https://files.pythonhosted.org/packages/be/a5/1f406e0362dd0f18ba09a562d50d7c04a70ac05d350b1ab6fba36ca3e9f0/prek-0.4.5-py3-none-musllinux_1_1_armv7l.whl", hash = "sha256:a8ed0d28f3e7790e4402a9324c386509066df6e67cc587f7406f9a245b97b7e8", size = 5498634, upload-time = "2026-06-15T11:36:31.828Z" }, + { url = "https://files.pythonhosted.org/packages/c7/df/b0cbf0fa527330188390b7b6c8d279cd5e509923262d0a6c5cc44bbdf103/prek-0.4.5-py3-none-musllinux_1_1_i686.whl", hash = "sha256:86f76bd3d2ecf6fd9034d75c62ff4c786eb11d0dd0a1f79bbb4343b023e12769", size = 5784840, upload-time = "2026-06-15T11:36:37.481Z" }, + { url = "https://files.pythonhosted.org/packages/9d/d7/977ee3c622c906677dd94187a00392ce2dd76035486b3a3b1b5a5267dd34/prek-0.4.5-py3-none-musllinux_1_1_x86_64.whl", hash = "sha256:e491a1a4641d91d8b03dcce5588397e76d2a5b432c9b0a6c70475972b4512ab4", size = 6300384, upload-time = "2026-06-15T11:36:27.602Z" }, + { url = "https://files.pythonhosted.org/packages/79/fa/43b1d761381dc1c7eeb8f2235c66e902970d4b2bff2dec0f02836c085769/prek-0.4.5-py3-none-win32.whl", hash = "sha256:7546989b2403c96137bd79d19ebfe21facb87266cefe819db2458c3b9b23f350", size = 5287935, upload-time = "2026-06-15T11:36:20.293Z" }, + { url = "https://files.pythonhosted.org/packages/f5/fe/59b5eb3124f5a4cc255a93857b9ab42402635b273f157e91de23bfa40e8f/prek-0.4.5-py3-none-win_amd64.whl", hash = "sha256:8b2ac9227504371d97338215b344184cb0b31ca94113515a3a90c509c6c5a707", size = 5682560, upload-time = "2026-06-15T11:36:25.865Z" }, + { url = "https://files.pythonhosted.org/packages/97/0e/589ff0eab9034909b1ec8654ee03483797305fb743b3554ce6140d82da9d/prek-0.4.5-py3-none-win_arm64.whl", hash = "sha256:646a86a1a082dbd99fed96314b1064f5644bb34c1f4037a63547a18e2160fb86", size = 5509019, upload-time = "2026-06-15T11:36:46.595Z" }, ] [[package]] @@ -3828,19 +3829,19 @@ email = [ [[package]] name = "pydantic-ai" -version = "1.106.0" +version = "1.107.0" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "pydantic-ai-slim", extra = ["ag-ui", "anthropic", "bedrock", "cli", "cohere", "evals", "fastmcp", "google", "groq", "huggingface", "logfire", "mcp", "mistral", "openai", "retries", "spec", "temporal", "ui", "vertexai", "xai"] }, ] -sdist = { url = "https://files.pythonhosted.org/packages/45/f1/6a0db6d336af199b436caa48d01ff63eeb6dbab14d5c50035ab5393a42f2/pydantic_ai-1.106.0.tar.gz", hash = "sha256:fb2b4bba143f924f2272926428ed173e456b00e0e5b3b125d7fd757f11b21fee", size = 18368, upload-time = "2026-06-05T01:29:06.762Z" } +sdist = { url = "https://files.pythonhosted.org/packages/17/71/7132293bc7ce791d8f3ee7f56b696b216a104bb30a08113f7b3db30a0c9a/pydantic_ai-1.107.0.tar.gz", hash = "sha256:254496d18451b2750a4dddc2591c6c42f25dd223d02ca4252812ab06e75f1044", size = 18414, upload-time = "2026-06-10T14:53:08.678Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/36/ca/bc39ecda2f1aa6544ec8559cfc50405462b241428ad06f77f44c776cdd39/pydantic_ai-1.106.0-py3-none-any.whl", hash = "sha256:c8c93979acab85b087dc3499e40249d5de4333f2212eb792c52a6c05c2448d69", size = 7589, upload-time = "2026-06-05T01:28:56.426Z" }, + { url = "https://files.pythonhosted.org/packages/65/38/db37ab59fced191a75babbbbe99470e512c91fe730b27d113e3280fdbe44/pydantic_ai-1.107.0-py3-none-any.whl", hash = "sha256:e031880b44ad7ce3836b2f6aa8ce2a0bd733cdb0b89a34adba647e96ddcba788", size = 7588, upload-time = "2026-06-10T14:53:00.57Z" }, ] [[package]] name = "pydantic-ai-slim" -version = "1.106.0" +version = "1.107.0" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "exceptiongroup", marker = "python_full_version < '3.11'" }, @@ -3852,9 +3853,9 @@ dependencies = [ { name = "pydantic-graph" }, { name = "typing-inspection" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/2b/45/2afc9100a7c370d8ac37bdfccfb54f46fc99da3bdce63f07c32c37807ebc/pydantic_ai_slim-1.106.0.tar.gz", hash = "sha256:e265598c8ee0e903ebb02d0494bb232be4cc8aa463ba1a55aa743cf34135dacf", size = 773504, upload-time = "2026-06-05T01:29:09.129Z" } +sdist = { url = "https://files.pythonhosted.org/packages/4c/26/ced63dfaabbc77f3beb86d59689cdea748e7ccffb6b419dbaf4780f211e8/pydantic_ai_slim-1.107.0.tar.gz", hash = "sha256:4616f689a92fcfecfecf2a7af27aca22f139a873cf6d7a8929eaeee9c0eedbb4", size = 779902, upload-time = "2026-06-10T14:53:10.574Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/72/d9/a2785c576e3519a72a5bbc0e12027c542b265ef6eea1aa72b9c440ac2531/pydantic_ai_slim-1.106.0-py3-none-any.whl", hash = "sha256:0dd7a99ea3fa89b490098406c2240ba7d75c327eea094c3fd057dd7aa9f3d163", size = 957617, upload-time = "2026-06-05T01:28:59.979Z" }, + { url = "https://files.pythonhosted.org/packages/15/57/71044e17f931b08cc3930bc0fe5a1e1fd37fa474ae826be004729ef1cb4a/pydantic_ai_slim-1.107.0-py3-none-any.whl", hash = "sha256:1af49bbae06a6c598f72c54d4734ba377100cac493c9a05fa8e089bebeae0da6", size = 964046, upload-time = "2026-06-10T14:53:03.333Z" }, ] [package.optional-dependencies] @@ -4046,7 +4047,7 @@ wheels = [ [[package]] name = "pydantic-evals" -version = "1.106.0" +version = "1.107.0" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "anyio" }, @@ -4056,9 +4057,9 @@ dependencies = [ { name = "pyyaml" }, { name = "rich" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/a4/d0/103e11d2c652980817ddcd874953437cf68d269e6893c9c4faa0b14f3568/pydantic_evals-1.106.0.tar.gz", hash = "sha256:ec870c2e93e2a34aea83468a7d7c21cba3e9dacf62f145eef2229d9fd71b2cac", size = 78539, upload-time = "2026-06-05T01:29:10.538Z" } +sdist = { url = "https://files.pythonhosted.org/packages/26/ad/f33306cf668d33cabce8af5e82b58ae367cc8422a2078c2df13327c13532/pydantic_evals-1.107.0.tar.gz", hash = "sha256:153378eda4847d48ca5e6b995e6221e5f0e4f4641771a1eed244fa2065923b27", size = 78546, upload-time = "2026-06-10T14:53:12.01Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/33/42/1319fdda0a120de24a544c9a76c2172005a3b53ac8e986ce149507694421/pydantic_evals-1.106.0-py3-none-any.whl", hash = "sha256:7994f8bebfac5e482fe62e5a5434b2e5f94118ca8bd766628635b84835118a78", size = 93528, upload-time = "2026-06-05T01:29:02.407Z" }, + { url = "https://files.pythonhosted.org/packages/23/ea/ecdaab037479f3b26c0efd47598f7caaad506fc53837196c1cf7e4701263/pydantic_evals-1.107.0-py3-none-any.whl", hash = "sha256:2df2f6deb82226f0404137ebecf9389c2270e08e30c066e239ae9090173826ec", size = 93586, upload-time = "2026-06-10T14:53:05.362Z" }, ] [[package]] @@ -4076,7 +4077,7 @@ wheels = [ [[package]] name = "pydantic-graph" -version = "1.106.0" +version = "1.107.0" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "httpx" }, @@ -4084,9 +4085,9 @@ dependencies = [ { name = "pydantic" }, { name = "typing-inspection" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/42/9b/dd6826cf21eedd96a7482302be51ba6087095acbe828362135de2a505092/pydantic_graph-1.106.0.tar.gz", hash = "sha256:55afa33df4f699ed5c1185f81b6a06e2161958f1aa0c20742b2dae5745e84cce", size = 62567, upload-time = "2026-06-05T01:29:11.833Z" } +sdist = { url = "https://files.pythonhosted.org/packages/dd/c3/6e8c2d13b8701041f1b3eac5deb41f25d4dbfa479a190d5c6becc23f2a49/pydantic_graph-1.107.0.tar.gz", hash = "sha256:278dd89b3e33f3a2963ac949f27a53aef705c5d883a8ce5d06d23e6e3cfbd972", size = 62564, upload-time = "2026-06-10T14:53:13.366Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/9b/e9/0058f0b98f5992e715a0a50128f6c3cc7946cc242d471f6e850efdf03f0c/pydantic_graph-1.106.0-py3-none-any.whl", hash = "sha256:e6bb61aef0fdb49185a81142d311f94fc3315329345471d12cab85ab5845221f", size = 80099, upload-time = "2026-06-05T01:29:04.219Z" }, + { url = "https://files.pythonhosted.org/packages/fc/72/621556e3f5068400d43a0375d38e5963de30256eaa5a702aba12e82ed0ff/pydantic_graph-1.107.0-py3-none-any.whl", hash = "sha256:71add94fe7e14c703977a895117c475aae6c0b02a774a036c4d00d9a63c78b00", size = 80106, upload-time = "2026-06-10T14:53:06.543Z" }, ] [[package]] @@ -4228,7 +4229,7 @@ wheels = [ [[package]] name = "pytest" -version = "9.0.3" +version = "9.1.1" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "colorama", marker = "sys_platform == 'win32'" }, @@ -4239,9 +4240,9 @@ dependencies = [ { name = "pygments" }, { name = "tomli", marker = "python_full_version < '3.11'" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/7d/0d/549bd94f1a0a402dc8cf64563a117c0f3765662e2e668477624baeec44d5/pytest-9.0.3.tar.gz", hash = "sha256:b86ada508af81d19edeb213c681b1d48246c1a91d304c6c81a427674c17eb91c", size = 1572165, upload-time = "2026-04-07T17:16:18.027Z" } +sdist = { url = "https://files.pythonhosted.org/packages/e4/47/b9efed96c114afcfa3c9d3fe98a76a1d14c74a9e266d397cf6eb64be5e01/pytest-9.1.1.tar.gz", hash = "sha256:1088fbde8f2b49d95a549a195707afa7a76a3ce9bcadc26b6d71f0ffda5fe313", size = 1636369, upload-time = "2026-06-19T10:58:32.857Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/d4/24/a372aaf5c9b7208e7112038812994107bc65a84cd00e0354a88c2c77a617/pytest-9.0.3-py3-none-any.whl", hash = "sha256:2c5efc453d45394fdd706ade797c0a81091eccd1d6e4bccfcd476e2b8e0ab5d9", size = 375249, upload-time = "2026-04-07T17:16:16.13Z" }, + { url = "https://files.pythonhosted.org/packages/24/25/1de2678b631f5a49215c6c96fff41ba892b0a34df68d6d80292b1b48aa7f/pytest-9.1.1-py3-none-any.whl", hash = "sha256:37a86b45efb9a47a61a36449063e8e18d0cab3161329fc099eb21783169c4f0c", size = 386536, upload-time = "2026-06-19T10:58:31.347Z" }, ] [[package]] @@ -4970,27 +4971,27 @@ wheels = [ [[package]] name = "ruff" -version = "0.15.16" -source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/a6/bd/5f7ec371001337d8fa61701c186ff8b613ecac1651848c5950f4c4d5f2e9/ruff-0.15.16.tar.gz", hash = "sha256:d05e78d38c78caf020b03789e25106c93017db5a0cb6e2819885018c61343b78", size = 4714267, upload-time = "2026-06-04T16:33:09.974Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/0c/42/53ef1c3953f157956db9bf7861e3bc50b9b887ce93300aa48cdba8336fe6/ruff-0.15.16-py3-none-linux_armv6l.whl", hash = "sha256:6ac3c0b3969cc6cf6b158c4e2f8f682acb58e7d700d8a44b65ecdc72d66ab0b2", size = 10709025, upload-time = "2026-06-04T16:32:51.935Z" }, - { url = "https://files.pythonhosted.org/packages/93/9a/a79159346f19134a956607754e57d8d128f7a4c00f4ad2f7514d224c172c/ruff-0.15.16-py3-none-macosx_10_12_x86_64.whl", hash = "sha256:197c207ed75ffba54a0dec23db4aa939a27a3053073e085e0042433cbdc58e4a", size = 11063550, upload-time = "2026-06-04T16:32:42.24Z" }, - { url = "https://files.pythonhosted.org/packages/bc/72/3ce2ac000a5299ec238e01f51397b3b653c93b077d9b1bfe8715bb895f20/ruff-0.15.16-py3-none-macosx_11_0_arm64.whl", hash = "sha256:3a39fec45ab316cc23e7558f23fea4a70403ddb5648ea9a4a3854a16973d0071", size = 10421345, upload-time = "2026-06-04T16:32:37.251Z" }, - { url = "https://files.pythonhosted.org/packages/b0/c2/cc7fad3ec9169373f5b6a18f1917b91080feec40c3f9658334a1d28e2f03/ruff-0.15.16-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ba93191d79003116b95128c9d306e045200fdbd0bccb782b110f3cd1d4abc5cf", size = 10757217, upload-time = "2026-06-04T16:32:54.722Z" }, - { url = "https://files.pythonhosted.org/packages/69/d2/3474009eaa0a65b31fa7152a2fad5e2f050c640ceb1e6b02ee6922e94c82/ruff-0.15.16-py3-none-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:c6ee4b90520630120ef032aa5cc10db483852dff950e78b1d717e2993a61ac8d", size = 10507035, upload-time = "2026-06-04T16:33:05.343Z" }, - { url = "https://files.pythonhosted.org/packages/ca/81/b7ae6ccbd11f0c8dc3d5d67fc4be9b57ff57ca86ba56152021378e1277f2/ruff-0.15.16-py3-none-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:4e4215bc938bc3c8215c1472c1aa437e310fee20cd427335fec9d7e609563628", size = 11255291, upload-time = "2026-06-04T16:32:49.49Z" }, - { url = "https://files.pythonhosted.org/packages/d9/e1/46e526f1a7cc90857ce6ddf25fbb77eb6568651ac38d71b033af07076dd5/ruff-0.15.16-py3-none-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:7c8d26be963b090f10e29abc8b3e74a2a321f6fa34e02424e30b5af89350ecbb", size = 12124922, upload-time = "2026-06-04T16:33:07.821Z" }, - { url = "https://files.pythonhosted.org/packages/1a/da/5c791b088b596b24d0deb967fa28ae02ad751a140c0b9ea81c5ab915d6c0/ruff-0.15.16-py3-none-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:f198cf4123602a2280ed46c307bcbafe41758d6fee5b456b6b6058ca1514b3b4", size = 11332186, upload-time = "2026-06-04T16:33:02.971Z" }, - { url = "https://files.pythonhosted.org/packages/72/11/5da87abe20047c8962361473923ebb2f62b595250126aadfad8c20649c1e/ruff-0.15.16-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:bb27515fa6240fb586ae82b901a59e67d24acff86f2190b433dc542fe0435aeb", size = 11373541, upload-time = "2026-06-04T16:32:47.007Z" }, - { url = "https://files.pythonhosted.org/packages/fe/2a/8554754c23a854ae3fd6b507e36ad61ddb121e298c6d5d617dec94ed0f14/ruff-0.15.16-py3-none-manylinux_2_31_riscv64.whl", hash = "sha256:a267c46ba1593fc26b8eecbea050b39d40c0b6bb7781ee11c90a02cd10032951", size = 11353014, upload-time = "2026-06-04T16:32:34.795Z" }, - { url = "https://files.pythonhosted.org/packages/62/25/62ea41529ec89f742ea3fed9cb1059c72877ec7cf9b9e99ac9cf3294d1d9/ruff-0.15.16-py3-none-musllinux_1_2_aarch64.whl", hash = "sha256:528c68f39a91498a8d50e91ff5985df3d105782bab49cc378e73ac26bff083e8", size = 10737467, upload-time = "2026-06-04T16:32:26.348Z" }, - { url = "https://files.pythonhosted.org/packages/90/17/334d3ad9de4d40f9dd58fdd09e35ce64553bb501e2f19a839e2fb6be14fc/ruff-0.15.16-py3-none-musllinux_1_2_armv7l.whl", hash = "sha256:7ed55c58950df60589a9a7a5d2f8fa5f54ebd287163be805adfe6ee95a9de123", size = 10521910, upload-time = "2026-06-04T16:32:32.54Z" }, - { url = "https://files.pythonhosted.org/packages/4d/bd/3ac7c6ae77a885c1004b3dda2446ea401768d24f851c14b4ad4b24f6639c/ruff-0.15.16-py3-none-musllinux_1_2_i686.whl", hash = "sha256:d482feaf51512b50f9790ceb417a56a61dd1e9d9bf967662b9ed27c01b34f53a", size = 10979190, upload-time = "2026-06-04T16:32:57.492Z" }, - { url = "https://files.pythonhosted.org/packages/33/d7/609546e6a413c3f216fbf2a50c928f97c80939154f6a0503114094a86191/ruff-0.15.16-py3-none-musllinux_1_2_x86_64.whl", hash = "sha256:1e15bc8c94513dae2a40cc9ef07c94fdd4ecc9e29dabebeebe170f952322c9e3", size = 11477014, upload-time = "2026-06-04T16:32:44.687Z" }, - { url = "https://files.pythonhosted.org/packages/74/0d/f2cd247ad32633a5c36e97141a2c21b11c6279f7957bc2ff360b1e08fddd/ruff-0.15.16-py3-none-win32.whl", hash = "sha256:580378f7bd4aa25f72e74aa54948a9622f142b1e509521dd10902e886681cc1e", size = 10735541, upload-time = "2026-06-04T16:32:30.145Z" }, - { url = "https://files.pythonhosted.org/packages/8b/9e/02e845ef151b1dee585e55c4739f8e1734ae1d9f1221dff65761c162208b/ruff-0.15.16-py3-none-win_amd64.whl", hash = "sha256:408256017284eddf98fff77b29aa4fb30f586042d535b2d9befc6512f400aaec", size = 11843403, upload-time = "2026-06-04T16:32:39.76Z" }, - { url = "https://files.pythonhosted.org/packages/15/19/016553f86f207450aebebc2b2b5088d086b901cc8186c02ac4284db3bd88/ruff-0.15.16-py3-none-win_arm64.whl", hash = "sha256:8cd61783afb39638a7133ef0d2dfb1e91277593962f81b5a8423eb0b888a6121", size = 11134555, upload-time = "2026-06-04T16:33:00.136Z" }, +version = "0.15.18" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/74/98/1295ad5a5aa9bc85bdcdfa5d82fe7b49c61af5657df4f227637ff9de0da6/ruff-0.15.18.tar.gz", hash = "sha256:2698a964c70e8bf402dcb99c8810472d270d141e7aa8c4e13599fd52033a2f33", size = 4761437, upload-time = "2026-06-18T18:25:39.224Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/b9/d0/686e984941269621e2be72612d5c1e461f8f7b38415a2a7d7a81c8ae6715/ruff-0.15.18-py3-none-linux_armv6l.whl", hash = "sha256:8b6850172348c8381b8b3084c5915a4393c2373b9b54cd5b5e1ea15812bc10df", size = 10887308, upload-time = "2026-06-18T18:25:03.062Z" }, + { url = "https://files.pythonhosted.org/packages/ed/21/bc4123e3f5515ee99f8ce1eb93a14a0628fe4d1678663cd08f933ac16931/ruff-0.15.18-py3-none-macosx_10_12_x86_64.whl", hash = "sha256:3fccc153a85417dcd976883160cacce486997b0a0058dd18f54b8aaaac7d1ce2", size = 11281305, upload-time = "2026-06-18T18:25:30.026Z" }, + { url = "https://files.pythonhosted.org/packages/51/93/4769464c25cf7ab2acb3c7dda9cad3d867eb41c59565b3e2a9d17249c90c/ruff-0.15.18-py3-none-macosx_11_0_arm64.whl", hash = "sha256:08d4c86a68f2c3ec2c9d56380a71fb4a4f65373055cbb8caabd645e9102f38d4", size = 10641215, upload-time = "2026-06-18T18:25:15.802Z" }, + { url = "https://files.pythonhosted.org/packages/6c/42/56926d17120db2c208d76bf60a1a019644dd9e91dc27f0f95c9caddb1366/ruff-0.15.18-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:37e5108745c2c0705da916d7d4de533ddf547051ef45f62888c31bae73f66318", size = 10957224, upload-time = "2026-06-18T18:25:36.955Z" }, + { url = "https://files.pythonhosted.org/packages/22/4f/d43fab8d8189afde803103022d000a8ef9f230616d436d52a8b2b8d63b50/ruff-0.15.18-py3-none-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:56949a6ce8b3abde54c0bcb22cebfe57e8771cadc84b407ae8b8eaf67ebdcd43", size = 10699024, upload-time = "2026-06-18T18:25:05.707Z" }, + { url = "https://files.pythonhosted.org/packages/63/42/1e3e4c68bd408b9768cf3e439acbe2c78245225faef253f7028a0cdb63e0/ruff-0.15.18-py3-none-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:01a754cd6a1b630d3f97e33eb452cf7a98040482318e870f8bc52a5a30e62657", size = 11491458, upload-time = "2026-06-18T18:25:20.275Z" }, + { url = "https://files.pythonhosted.org/packages/20/77/47a3484bea8521e14a203d98c389c5c97846675e4f02734672da4a69b52a/ruff-0.15.18-py3-none-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:6ba7a07e03a44dbf10bb086ee06705b173625014ec99f73a7e6836a5e5590a0c", size = 12383752, upload-time = "2026-06-18T18:25:22.535Z" }, + { url = "https://files.pythonhosted.org/packages/0a/ca/054159590787023d83b658a1a1819c4c8910114e7015069340b71c0961cb/ruff-0.15.18-py3-none-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:5a2c40a41a4cadbcf5897b548ab29dfe248b20c540961c0247d98a3973c70403", size = 11577923, upload-time = "2026-06-18T18:25:10.702Z" }, + { url = "https://files.pythonhosted.org/packages/6d/ff/d353d6b7bbd73cc0ec37f4463d7540e45e894338abdd9964eee0de332708/ruff-0.15.18-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:5f0480ce690cbb6c4db6e5d08f19fce98e10ba131a8b60c1bcdac42771e3ae2d", size = 11583925, upload-time = "2026-06-18T18:25:32.391Z" }, + { url = "https://files.pythonhosted.org/packages/c1/4a/891f89b9c296ed3e5f3ece1a5629badc989d9a8fdaa30431aaf4774bc1c2/ruff-0.15.18-py3-none-manylinux_2_31_riscv64.whl", hash = "sha256:2330215f1f393fa8733f55edce04fcf94c36a2c460fcde31f78cc84e4951e9b1", size = 11582834, upload-time = "2026-06-18T18:25:27.309Z" }, + { url = "https://files.pythonhosted.org/packages/32/a3/ed9e370154bf85de360b93c03026157f02d4943b2d01ff4945f4429f8e8a/ruff-0.15.18-py3-none-musllinux_1_2_aarch64.whl", hash = "sha256:a6aa6a3d979e48ae617578183674bf264fbe7d0114a796a26bd678d67963c7ff", size = 10927328, upload-time = "2026-06-18T18:25:34.676Z" }, + { url = "https://files.pythonhosted.org/packages/f5/d1/5cf5909329fedb5d39d555ee818ba5cf4638e1a301b89785d34f2905bfcb/ruff-0.15.18-py3-none-musllinux_1_2_armv7l.whl", hash = "sha256:a81beadbbff2c9c245561ae3f77b16709d87f35eec650d0501679239d3449b22", size = 10693187, upload-time = "2026-06-18T18:25:08.245Z" }, + { url = "https://files.pythonhosted.org/packages/fd/44/ff6c635cf2c4f4e7b618b6640da057376baa36014695487d88aed4794268/ruff-0.15.18-py3-none-musllinux_1_2_i686.whl", hash = "sha256:2186d9e940ae332ab293623a75b5f4fe49565f449954d50a72a046683aa6b809", size = 11208721, upload-time = "2026-06-18T18:25:41.327Z" }, + { url = "https://files.pythonhosted.org/packages/88/d9/5baa2a30861adfb7022cf33c1e35b2fc18085b08c16f83eff4c7b99a5f48/ruff-0.15.18-py3-none-musllinux_1_2_x86_64.whl", hash = "sha256:5c2abf140438032bc77b2284a6c9944ecd8a19e5f1c7b52b1b8e4a0a80d19a7a", size = 11678599, upload-time = "2026-06-18T18:25:13.607Z" }, + { url = "https://files.pythonhosted.org/packages/c3/1a/0725a7cfdc32ff769efb96ee782bec882e16448c5d9e3be947ec4c04ce27/ruff-0.15.18-py3-none-win32.whl", hash = "sha256:02299e6e9fa5b297a3f6d5d10d7bcd655c925b028bb8b9d4588214549c6b9ec4", size = 10901903, upload-time = "2026-06-18T18:25:24.755Z" }, + { url = "https://files.pythonhosted.org/packages/f3/51/805d9f6fb7970505c3504794a5ec350f605361b807fef4dcf214ebd35e72/ruff-0.15.18-py3-none-win_amd64.whl", hash = "sha256:dac80dc8d26b2257dbefabed62f5d255c3937b4ccb122da1fc634794fa3578b3", size = 12041189, upload-time = "2026-06-18T18:25:17.915Z" }, + { url = "https://files.pythonhosted.org/packages/29/4c/67bb45e41609eb4726f1bfeb59e083cf91d14c696d4bd14c234a980be93d/ruff-0.15.18-py3-none-win_arm64.whl", hash = "sha256:b2c9257fcbd4a3e5b977a1904e6facca016bafe2edc17df24db67cfaee03b4e4", size = 11329958, upload-time = "2026-06-18T18:25:43.686Z" }, ] [[package]] @@ -5187,7 +5188,7 @@ wheels = [ [[package]] name = "strawberry-graphql" -version = "0.316.0" +version = "0.319.0" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "cross-web" }, @@ -5196,9 +5197,9 @@ dependencies = [ { name = "python-dateutil" }, { name = "typing-extensions" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/cf/09/f189fd3c70544322eeba0398ccaa980d17857894c0a66d447aa0b5704686/strawberry_graphql-0.316.0.tar.gz", hash = "sha256:bee5ce0e20d522325bd1ed2db186c812c03c2ea7db29f997b35e7d694649820c", size = 223985, upload-time = "2026-05-19T17:06:10.443Z" } +sdist = { url = "https://files.pythonhosted.org/packages/7f/c4/5d7cf2f2459d9a553993217212acc911bfc63f3957a45980230105e1c92e/strawberry_graphql-0.319.0.tar.gz", hash = "sha256:e9afdfe2ca745b5337d3c4909ffd612e405105af6ffc21b1766a2b9848fcfd4f", size = 227709, upload-time = "2026-06-21T14:57:38.324Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/0b/dd/b2cf54803cbd0d37e3ce73c7274bdb144ba83743bc83351b5790eb2a5fad/strawberry_graphql-0.316.0-py3-none-any.whl", hash = "sha256:222e16fbbf953f5a1fa75f62bf9a8e95f274180f928f70bec459b566053aa2cb", size = 326530, upload-time = "2026-05-19T17:06:07.844Z" }, + { url = "https://files.pythonhosted.org/packages/d3/b4/5005afc8369dbb3f5c03dd681ac8a13a5c0b9a8c6ae13f1c0643bb815cfa/strawberry_graphql-0.319.0-py3-none-any.whl", hash = "sha256:fcd5cbe43a5d7274d91bda2261f272f57c84d39532ff58b95fadd0749d225835", size = 330534, upload-time = "2026-06-21T14:57:36.36Z" }, ] [[package]] @@ -5446,27 +5447,27 @@ wheels = [ [[package]] name = "ty" -version = "0.0.46" -source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/5a/7d/d95b5a9dea83472006be3ce5e480028c44b34138d84d0172e910f287fb69/ty-0.0.46.tar.gz", hash = "sha256:c6c2d7105b5633b49950b4c3a90d1ed2613eb9d794ad582bbbf6c4ffcb93accf", size = 5832380, upload-time = "2026-06-09T03:28:05.056Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/0e/24/f9f7533c391610521f4164e6b8e37ef72d0c1ee8651bc0d9ce9e658b953b/ty-0.0.46-py3-none-linux_armv6l.whl", hash = "sha256:5e716337994699cbc1a1a7b7a3e6622306f2574c710330f9d9691c2c3d8391b0", size = 11756264, upload-time = "2026-06-09T03:28:20.112Z" }, - { url = "https://files.pythonhosted.org/packages/66/49/ff3d13655b9b5cc8176f4c3446bf7ec2df43c8ad9e5272d4adc5d952fa45/ty-0.0.46-py3-none-macosx_10_12_x86_64.whl", hash = "sha256:51d618dec5403635690d0e3e298cd0ad3d84ebc6a576652939ef30ce96fce4b2", size = 11492723, upload-time = "2026-06-09T03:28:13.23Z" }, - { url = "https://files.pythonhosted.org/packages/82/4a/e7e3209e353c5835c7756339bbcdfda10852407b80fbb9ed46c17241873a/ty-0.0.46-py3-none-macosx_11_0_arm64.whl", hash = "sha256:acbafd6a2351b07a6cf4c945b0b1d47f6d2826faac2526a351dfa74d3a3cc664", size = 10892822, upload-time = "2026-06-09T03:27:51.179Z" }, - { url = "https://files.pythonhosted.org/packages/6c/20/4390c90434a9ddefcecb65e8df00e4c2700e9739dc0baf58bed36d25f713/ty-0.0.46-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:de5df602ffd760612ae36602bbad69b0123ff6cffd92e62aa92b7709317d69e3", size = 11408745, upload-time = "2026-06-09T03:27:58.049Z" }, - { url = "https://files.pythonhosted.org/packages/75/0c/f13a1bf9c6798530c773667095a6cf8f73ec9721db359423e7249bff7fbc/ty-0.0.46-py3-none-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:7abf5a10b30d8641faad90f6a19989daec941bb90261159e05cfeb04d2012046", size = 11544432, upload-time = "2026-06-09T03:27:53.519Z" }, - { url = "https://files.pythonhosted.org/packages/56/69/eb3710c13dff846a0362df04fadd8a39b64ccc244c0d02ce5285ede8eae5/ty-0.0.46-py3-none-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:8770404139c6ccee2ce2fc226478cfa4100915133c876c257e52197b8b92051d", size = 12031228, upload-time = "2026-06-09T03:28:29.816Z" }, - { url = "https://files.pythonhosted.org/packages/e9/68/5f5db9c84c1d44acdc67281089b372d9d818ee68123a60c59c66187095e2/ty-0.0.46-py3-none-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:f960d5a6e4860076924d2b86891d9872c4a3daa4663fb416e640b22cf3dbf68e", size = 12596073, upload-time = "2026-06-09T03:28:25.204Z" }, - { url = "https://files.pythonhosted.org/packages/14/be/cfd0bb272e6a1491f6de30c60da1f39c2b3c3524ec64a5c92b71365c9185/ty-0.0.46-py3-none-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:1d9000a4a3ed08fc37e8a2ff0b801cde06e1c2af3bc053677744bb5a1b751030", size = 12284885, upload-time = "2026-06-09T03:28:10.58Z" }, - { url = "https://files.pythonhosted.org/packages/a8/3a/2cd541f6320f5d6f70a45725c4e1016efedd5545348bb23b47ffb3e4c724/ty-0.0.46-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d1160e6dc86536109ab755f7142f36f4dda5333c8330cf230d61819494d27125", size = 12079480, upload-time = "2026-06-09T03:27:55.847Z" }, - { url = "https://files.pythonhosted.org/packages/de/91/8e0075bc6568fb477e7ef4d805c67fa6902b692cb4419e0bf5ce3c04c5bc/ty-0.0.46-py3-none-manylinux_2_31_riscv64.whl", hash = "sha256:b619c0efe007731f8221fa787701bfa4402da7a83eb26c61ae25e77b6ace6384", size = 12316547, upload-time = "2026-06-09T03:28:08.28Z" }, - { url = "https://files.pythonhosted.org/packages/00/28/b96cbfeda019a4044c6a8cd06ff84d08b631d4ba7d9a1e6dc0311df3563a/ty-0.0.46-py3-none-musllinux_1_2_aarch64.whl", hash = "sha256:ad98fccb6a8a94c4121b993761a0deee602f5826c4162e0a91f4f8118ddadd42", size = 11392846, upload-time = "2026-06-09T03:28:00.418Z" }, - { url = "https://files.pythonhosted.org/packages/3b/d0/4d77f699a95ac7a13b94ca1a58682667cfe974f91557d9e2a9fc0b808a7f/ty-0.0.46-py3-none-musllinux_1_2_armv7l.whl", hash = "sha256:74536b13c3cc3f5944408669c202d4c57c3d19ff154732df8e6145718aef9191", size = 11559017, upload-time = "2026-06-09T03:28:17.619Z" }, - { url = "https://files.pythonhosted.org/packages/88/62/1d6f6b51c2b132da8011c6a41ead0c1fd2a0b17ea72304bcf6ce084d581a/ty-0.0.46-py3-none-musllinux_1_2_i686.whl", hash = "sha256:5e50b1e96ced41b609e24ed27d9e4f508584ed7f4d0bb717ca8c8d75d2fd1b7c", size = 11666509, upload-time = "2026-06-09T03:28:22.454Z" }, - { url = "https://files.pythonhosted.org/packages/fe/9a/6643894bc12cb30c281f4c8bf37f6d30c1fbd9484ef39a12b0ea6dae3c1c/ty-0.0.46-py3-none-musllinux_1_2_x86_64.whl", hash = "sha256:0a7d9f58d26d938e5d2f607481b7a412d8c00d675a1ec72004fa9d6b3b9def99", size = 12180448, upload-time = "2026-06-09T03:28:32.329Z" }, - { url = "https://files.pythonhosted.org/packages/86/68/0f3b7bb03a7da676ef51b1c0af0bde1e500d69d5f0c807ed63b6f30b66dd/ty-0.0.46-py3-none-win32.whl", hash = "sha256:26db0ce89c573e60132d14e9688c9329a1633b1a8c26fe457025c7c406f7d5e6", size = 10960002, upload-time = "2026-06-09T03:28:02.832Z" }, - { url = "https://files.pythonhosted.org/packages/b1/f4/91ff618b2dee39d0633d23e1adac0174aa1de80df17e270acac534034dbc/ty-0.0.46-py3-none-win_amd64.whl", hash = "sha256:90e8e6d446b9cb7cb4bede9fca7b3c99fd1e2355605ecf431c131a51db2a5e93", size = 12097413, upload-time = "2026-06-09T03:28:27.495Z" }, - { url = "https://files.pythonhosted.org/packages/e5/2e/300174fca375a27a7c28dd80e990d857d7b3e3b25980c65063f980aa2f17/ty-0.0.46-py3-none-win_arm64.whl", hash = "sha256:ebd320d82605079b901a095dc4711037a0c488b4ace79a602fef4df0d3f4cf74", size = 11439595, upload-time = "2026-06-09T03:28:15.355Z" }, +version = "0.0.52" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/5d/84/4417eb08328dcc547bf407d20af5e45ec8c64a85470f388fc2d590c9200a/ty-0.0.52.tar.gz", hash = "sha256:f1191175429fea917f96f79a57773eb6e57b861ee97e9ad2d77cc7538f0f284b", size = 5973710, upload-time = "2026-06-23T01:43:31.906Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/22/8f/ba97090625c824bdb2ddac4e22e9f3568c6e5e20e75923daa49ff5254648/ty-0.0.52-py3-none-linux_armv6l.whl", hash = "sha256:5e9403d3b5c5067cef06e29f33e842b095a71479314e38e4aa5e0afe7940e4eb", size = 11956857, upload-time = "2026-06-23T01:42:43.935Z" }, + { url = "https://files.pythonhosted.org/packages/6e/d2/d8ed189611c658e567a2d267f088d5b1128ae6c80e4f40b29552679fd9e1/ty-0.0.52-py3-none-macosx_10_12_x86_64.whl", hash = "sha256:397971af92f63fd1ab244ded9f07e6a13834cf2299a53db19f20ff3076ec5998", size = 11745925, upload-time = "2026-06-23T01:42:47.85Z" }, + { url = "https://files.pythonhosted.org/packages/19/19/db06dd15512bf8e589f2bd92ddfe77a656185801e800cd73f99f12d86305/ty-0.0.52-py3-none-macosx_11_0_arm64.whl", hash = "sha256:3857ba38d5caa55be5a028c1dfda00a50fe9688a776455983f7e6f75783675e0", size = 11090262, upload-time = "2026-06-23T01:42:50.351Z" }, + { url = "https://files.pythonhosted.org/packages/c2/9a/15d3b77ad5e03b802266920bd406a321ac86be88ddbf7db058003559ccad/ty-0.0.52-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:bdb6b21947ab96cacf15384f245609439d117abfd67479d9dd9e193fc3c88332", size = 11634345, upload-time = "2026-06-23T01:42:53.164Z" }, + { url = "https://files.pythonhosted.org/packages/75/4e/a32b72b11f02e6aeda01ffa8459a6dfa3582cb1555212dc38485c36b44b0/ty-0.0.52-py3-none-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:c3acdcb7be88e2248c9ac3210fd21a7bf708ccf65365712ff860d6d2a5794295", size = 11741270, upload-time = "2026-06-23T01:42:55.996Z" }, + { url = "https://files.pythonhosted.org/packages/c6/e0/c2f4de96c2cb25ee74fc41b6bfb80f64b6f90d4e77580454860ee81dde19/ty-0.0.52-py3-none-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:186302513a72816f5253e32768a2c2f416fbc250079e1404ab6d758b963c402b", size = 12249540, upload-time = "2026-06-23T01:42:58.697Z" }, + { url = "https://files.pythonhosted.org/packages/c8/01/77d45372342983c98c1f3b26b4a8ea7139cb10b26820f0f6b37a298c9fa1/ty-0.0.52-py3-none-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:02ee1083e9fd1a8c221eaa1e7018d4bac40e7b8a9f06db724757491b2948857a", size = 12822873, upload-time = "2026-06-23T01:43:01.57Z" }, + { url = "https://files.pythonhosted.org/packages/1c/09/9bdb394da75cefd41498c86a1f357b7f319368122ac8943d457f28f02609/ty-0.0.52-py3-none-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:83cadaa3efdb3860d24eb45ee3103da0c9a4f7be73c089984e9df095545b9da5", size = 12441154, upload-time = "2026-06-23T01:43:04.129Z" }, + { url = "https://files.pythonhosted.org/packages/ea/07/969dce9b75fdfad9cad3aeae484761e57882b92a6e3d0fe8951b9427846b/ty-0.0.52-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:680738fdfdce72df8be1a213df9ed87add63e1e7705a7927bd360150cd4d749e", size = 12301402, upload-time = "2026-06-23T01:43:06.978Z" }, + { url = "https://files.pythonhosted.org/packages/0b/66/a6fc838efc21c5303d83fd1ccf2b8f0e551b8b3426c54513ea1b1499b1b9/ty-0.0.52-py3-none-manylinux_2_31_riscv64.whl", hash = "sha256:30bbe8390a4e58003f181d52c2b3e50facf6b83491c8638f9136a5b8a5a7d931", size = 12507384, upload-time = "2026-06-23T01:43:09.693Z" }, + { url = "https://files.pythonhosted.org/packages/c5/38/eb2c8c17ae3a022e5e1ca187afa5cc03fe0cc40d6dfb5404e6941c98f7af/ty-0.0.52-py3-none-musllinux_1_2_aarch64.whl", hash = "sha256:77c8699e796d37534243ea8ac54ac7f64690bf787e2894cb3be18c16ff6fc53c", size = 11600728, upload-time = "2026-06-23T01:43:12.236Z" }, + { url = "https://files.pythonhosted.org/packages/ce/3a/9f25321f6a173021bc728d158cd9e30c5ee28b62f4a20421fca3ebf3f6a5/ty-0.0.52-py3-none-musllinux_1_2_armv7l.whl", hash = "sha256:ef5c3f6e2cf649773382b9843227b62d689a0179ec1d0366159c349990ceaeb9", size = 11765676, upload-time = "2026-06-23T01:43:14.922Z" }, + { url = "https://files.pythonhosted.org/packages/fc/96/2790300be5bca3bedaa7eb143c26d02b9188685bbf9b9a6bae79e4566085/ty-0.0.52-py3-none-musllinux_1_2_i686.whl", hash = "sha256:dba4c4ee5e1b33c5ad6c965042101d09804b352a3b1482f3ad7b32ad78c22dd4", size = 11886884, upload-time = "2026-06-23T01:43:17.608Z" }, + { url = "https://files.pythonhosted.org/packages/74/06/c098d9422d297cccd27f6a8f5cf5e7eff857b62a89b4549bad9dd0759365/ty-0.0.52-py3-none-musllinux_1_2_x86_64.whl", hash = "sha256:3e2b06401af954515403f0b2bbe382ca74f09bf2993e7b64fc3c1ad96fde7948", size = 12401990, upload-time = "2026-06-23T01:43:20.267Z" }, + { url = "https://files.pythonhosted.org/packages/5c/c9/34b771d0581fbfd0dde89f869af597b3907c7e5c59439005f59f6671c7d5/ty-0.0.52-py3-none-win32.whl", hash = "sha256:6347248c640f0d71ba9c4fe5de941ec7e3df167008bdda5c2cf795055045f266", size = 11247464, upload-time = "2026-06-23T01:43:23.36Z" }, + { url = "https://files.pythonhosted.org/packages/33/b1/0c381ac39d85a885d4e2841173e9a88bf190b4f7cf7d15afd4a1d7e8c715/ty-0.0.52-py3-none-win_amd64.whl", hash = "sha256:57150a68abfea2ec4727647b26f136850695972a650587f44a4b98fc9d4a1096", size = 12385753, upload-time = "2026-06-23T01:43:26.479Z" }, + { url = "https://files.pythonhosted.org/packages/fb/1f/2744053d80ca1b350817dbf41286bac9c95491cfa437c0cc923feaf3522b/ty-0.0.52-py3-none-win_arm64.whl", hash = "sha256:c669df56e41c99ea53405191da0fd65cbcb9bb7162c676ef6f45e480c6a7da6e", size = 11695815, upload-time = "2026-06-23T01:43:29.465Z" }, ] [[package]] @@ -6066,7 +6067,7 @@ wheels = [ [[package]] name = "zensical" -version = "0.0.45" +version = "0.0.46" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "click" }, @@ -6078,20 +6079,20 @@ dependencies = [ { name = "pyyaml" }, { name = "tomli" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/f3/d1/ecb1889fd2208b2d577e6ff952d9bee201302eec7966b5b61cc64adfd8f5/zensical-0.0.45.tar.gz", hash = "sha256:315bce4ab0470338dd3588add38fb325f840856c375722e6802bd58a06446266", size = 3935947, upload-time = "2026-06-09T11:23:32.349Z" } +sdist = { url = "https://files.pythonhosted.org/packages/aa/57/c7bbb71f943e1e0ba5ce460f4930ec836ead7286969e7fd742f7a6c049ab/zensical-0.0.46.tar.gz", hash = "sha256:3ec21f4fb1e78cd7c0d6b07ae336b04770e27ba020dabc457b2790e5d34f1978", size = 3973968, upload-time = "2026-06-21T18:52:40.368Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/ad/fd/6b84115e3bbe6b76ebb1265e8ff2161c0bc88dcd6499eaf29c61a66421e9/zensical-0.0.45-cp310-abi3-macosx_10_12_x86_64.whl", hash = "sha256:c4cb2e11132f02ae824e246e016e073458e12e9de1eaf86fd39f01890d41204c", size = 12698844, upload-time = "2026-06-09T11:22:56.537Z" }, - { url = "https://files.pythonhosted.org/packages/e2/dc/4ddf05d77c1455c32cb26da71f2a19d355927a45a3db5b26fb258a07ce8f/zensical-0.0.45-cp310-abi3-macosx_11_0_arm64.whl", hash = "sha256:799a01de2102b5f731744ad31bdbc464d0c07d484e67ba148f6923679afa6ce6", size = 12571590, upload-time = "2026-06-09T11:23:00.192Z" }, - { url = "https://files.pythonhosted.org/packages/4c/53/60c6cc7b2ce8b1a83eb87bff3f7289447995552fd9a30ca76ffba22ca9d5/zensical-0.0.45-cp310-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6201e79ea8a64bd3ced3f05ef4b1529da0e675d67b1395987c0ba942e4e10dc4", size = 12939590, upload-time = "2026-06-09T11:23:02.721Z" }, - { url = "https://files.pythonhosted.org/packages/9f/1e/e9217ed75dba323a6f9a4eee28eb40416eff99932cd0ee6c394bf07b9ead/zensical-0.0.45-cp310-abi3-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:854aaf500e4a3ce64adea1faa7a1820c7cf9a4f66be1043e4e9ba727fe9cf2b5", size = 12911669, upload-time = "2026-06-09T11:23:05.407Z" }, - { url = "https://files.pythonhosted.org/packages/71/3c/6fc9fe2334bb4460a8a8d732e23a30d2ddc2ecf63c2eb3487d9e7405e70d/zensical-0.0.45-cp310-abi3-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:a80c57fd50fc60415914388286ac10a7d8b6f70b8ca7235597d09fb12c3171b0", size = 13267643, upload-time = "2026-06-09T11:23:07.915Z" }, - { url = "https://files.pythonhosted.org/packages/be/f9/5696114af4ede5f1bd01e641a4ff24ee8ca49810bfaa28e5be12d930c0ef/zensical-0.0.45-cp310-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:58c3510f69e08b6ed8bb9596fc9393e4687f90394aa0ef2d6118b1375ad97be5", size = 12972147, upload-time = "2026-06-09T11:23:12.069Z" }, - { url = "https://files.pythonhosted.org/packages/a3/9e/5c6acde480c43f8c993b13260925df8db31d51ab8a9977618e9efdd98d45/zensical-0.0.45-cp310-abi3-musllinux_1_2_aarch64.whl", hash = "sha256:01c484bb2ee85e98e21e24b397ff52ffc31101f7485935eee5d3afa6cca6cc08", size = 13117360, upload-time = "2026-06-09T11:23:15.155Z" }, - { url = "https://files.pythonhosted.org/packages/3d/31/ea21f102049b35a8fe5218c5331857a15eeb60deb1bb21823a4c0701e274/zensical-0.0.45-cp310-abi3-musllinux_1_2_armv7l.whl", hash = "sha256:3654b708830303759e866a58a60c483cd2a1c56a44acdaae5bbb341a3f40ebce", size = 13185593, upload-time = "2026-06-09T11:23:18.166Z" }, - { url = "https://files.pythonhosted.org/packages/b4/97/6ded39fe27fa8a292d17d9af713b018e4919315233b60fa4b4b0aca737a6/zensical-0.0.45-cp310-abi3-musllinux_1_2_i686.whl", hash = "sha256:c4da1c37eca1474b487def0ef40d7ac2aff31a9d7a029cb7479ef7c354437361", size = 13326882, upload-time = "2026-06-09T11:23:21.027Z" }, - { url = "https://files.pythonhosted.org/packages/79/80/075975032a9e20f319c0134f8ca659d295ee4908f15ab212702a2728247f/zensical-0.0.45-cp310-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:f8a1966c186feebd3b795f9d420000bfd582e16eefdd9bc7a286d878faabae52", size = 13253961, upload-time = "2026-06-09T11:23:23.99Z" }, - { url = "https://files.pythonhosted.org/packages/3f/6a/0eab0eb311af6a07cde15ca58d5d720cbfa02cd509e4c7fb5fa20cda0b46/zensical-0.0.45-cp310-abi3-win32.whl", hash = "sha256:a1dd63a5efb8d0e5f2fadf862f02771a279dc5cbe9a982700194650065758f01", size = 12257083, upload-time = "2026-06-09T11:23:26.769Z" }, - { url = "https://files.pythonhosted.org/packages/1f/cd/b117e749c60b1d1e16b8450db1355f69f38376f783b8c6c8815202988933/zensical-0.0.45-cp310-abi3-win_amd64.whl", hash = "sha256:1f2c0e69839ce4274bde34d18139d3b0d96bbf02b245ada46243590c9eedebc1", size = 12498335, upload-time = "2026-06-09T11:23:29.702Z" }, + { url = "https://files.pythonhosted.org/packages/4c/bd/bbc499ee35ac9ec5459dbfec7bb7231556689e97eaa13a5eddbe1f0443b5/zensical-0.0.46-cp310-abi3-macosx_10_12_x86_64.whl", hash = "sha256:d91af81ab058c8693dfd75f2f77b4c73bcba4125681d1d276f38624291820bd2", size = 12796482, upload-time = "2026-06-21T18:52:07.369Z" }, + { url = "https://files.pythonhosted.org/packages/88/1b/7acc273184d59b8e894d15ebe3cf1c5e81b3a822fde1792ea3e33be37a2e/zensical-0.0.46-cp310-abi3-macosx_11_0_arm64.whl", hash = "sha256:d9221264a9a87409900a47e29985607b0c9245dacb89077e87c8e16e31edc167", size = 12660030, upload-time = "2026-06-21T18:52:10.186Z" }, + { url = "https://files.pythonhosted.org/packages/80/df/bd0a68de98a19fc6050c58be11f36d05ea72a213b6a7ff7395d33c793747/zensical-0.0.46-cp310-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ec43018d5343ca2e1d71aa352eeddd560fef504effd03025840a5a783abefa4f", size = 13057130, upload-time = "2026-06-21T18:52:12.911Z" }, + { url = "https://files.pythonhosted.org/packages/f4/db/e27635f5787a42245f900e658340698a6654e165d466f9a3b640efced2cd/zensical-0.0.46-cp310-abi3-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:26e98fb8ab7ab50cdd20a73e2c7d4d9aae0b46cf2d8691e6bb22f9c261b8a60a", size = 13022345, upload-time = "2026-06-21T18:52:15.84Z" }, + { url = "https://files.pythonhosted.org/packages/e7/9d/6ce2ba11c97154870b458a8dae4637ade93b7097912f0102f5ea7fe8cf5b/zensical-0.0.46-cp310-abi3-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:46fe578f26963f8ee89567983e62737b6fadc9197d4742e1020b522e092d7baa", size = 13377445, upload-time = "2026-06-21T18:52:18.538Z" }, + { url = "https://files.pythonhosted.org/packages/68/06/9930d43cd9d2f899b648d63491007c1b4f9716cf118b0c98e867b933069c/zensical-0.0.46-cp310-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:aef03fa186a5589148e10b62610500989c6b075a2c08e1554233adbf91b2a3dc", size = 13086749, upload-time = "2026-06-21T18:52:21.452Z" }, + { url = "https://files.pythonhosted.org/packages/c4/ed/2342cf860fbb02314938b0d1f1b02344935801b04d185ff3151ef1812898/zensical-0.0.46-cp310-abi3-musllinux_1_2_aarch64.whl", hash = "sha256:bc7446cdf97a8dea390f20ed2bd6b030cddc1bd36a8ce113ea3efef6fa61c573", size = 13231120, upload-time = "2026-06-21T18:52:24.171Z" }, + { url = "https://files.pythonhosted.org/packages/de/b0/d2ece02f63cd767fcf10fd7608dc8e0a995f87dc5261209b1dbc296fd57b/zensical-0.0.46-cp310-abi3-musllinux_1_2_armv7l.whl", hash = "sha256:bbee37801f1ed500f158dc0992c569282950f780ae353c37fe6969f99983d701", size = 13295035, upload-time = "2026-06-21T18:52:26.942Z" }, + { url = "https://files.pythonhosted.org/packages/4b/b2/cb0048a612e63e615399fc507472a557d1c5b7c2f74065c5bf11998fd597/zensical-0.0.46-cp310-abi3-musllinux_1_2_i686.whl", hash = "sha256:9487c147c9cceb50c04d0ad70b024821a6eab1629dafd70ab6d1e86ec841e623", size = 13437191, upload-time = "2026-06-21T18:52:29.69Z" }, + { url = "https://files.pythonhosted.org/packages/91/16/515f81db8055b109a510063be481e60a657c4fad1a883680b2ee4aa9a424/zensical-0.0.46-cp310-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:f42a4683c762f026878d19ede4bcf7bfbb84dbecb5ad923949abb77806ed88a5", size = 13369382, upload-time = "2026-06-21T18:52:32.521Z" }, + { url = "https://files.pythonhosted.org/packages/b9/5c/da54ee65b642eb7d88dd4a3db35845d0765915638e05d5d434a10b42f1c3/zensical-0.0.46-cp310-abi3-win32.whl", hash = "sha256:85f018f2a7ee76a83915c87ddb12b58cf343fd6154081d33ac95b6751b011dd7", size = 12354298, upload-time = "2026-06-21T18:52:34.976Z" }, + { url = "https://files.pythonhosted.org/packages/73/26/fc7ef081acbdada8436825221cb728ee84a81d4d78a7bb79aa58bd150d31/zensical-0.0.46-cp310-abi3-win_amd64.whl", hash = "sha256:1543a693a160de60e86ca589592401b584670e7e12c5ae30e3c2ba76786f7ec3", size = 12599687, upload-time = "2026-06-21T18:52:37.913Z" }, ] [[package]] @@ -6105,18 +6106,18 @@ wheels = [ [[package]] name = "zizmor" -version = "1.25.2" -source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/b3/41/8987d546e3101cc76748b2f1b0ccda58e244773ef5124d39e7e749e3d6e4/zizmor-1.25.2.tar.gz", hash = "sha256:f26ffeb16659c8922c7b08203ca5a4f8bf5e1a7e8d190734961c40877cf778ea", size = 517794, upload-time = "2026-05-16T06:28:43.816Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/dc/bd/84108a92ccbfda0d28efc11f382997c7a767b58863bf4a550634b8cf0211/zizmor-1.25.2-py3-none-macosx_10_12_x86_64.whl", hash = "sha256:17cc8cfd9d472e8b11945a869c198d25cfdf4a33f36fa7a1f9674099f5fb509d", size = 9115548, upload-time = "2026-05-16T06:28:33.591Z" }, - { url = "https://files.pythonhosted.org/packages/c2/c0/66453a2553a66286a96ca32d75e3e6bcc94ce7f907cd5f8c2c3fce55315e/zizmor-1.25.2-py3-none-macosx_11_0_arm64.whl", hash = "sha256:d3e301eb4465e2da77857cf01ab4ef0184cf3818e826800b270ab01ae7338977", size = 8665071, upload-time = "2026-05-16T06:28:30.861Z" }, - { url = "https://files.pythonhosted.org/packages/52/3e/d60939d1cc4907c0d021a7c46362aab5e8045550bb09157d56c070e43568/zizmor-1.25.2-py3-none-manylinux_2_24_aarch64.whl", hash = "sha256:cf64374149b567c9373228b76c8e77a389b4071899f84b82c36ee50fab894e79", size = 8842884, upload-time = "2026-05-16T06:28:26.041Z" }, - { url = "https://files.pythonhosted.org/packages/46/82/f3e8d9b6d941194f2558591b449c106d46a16ea566b95eccff3a83bf6acc/zizmor-1.25.2-py3-none-manylinux_2_28_armv7l.whl", hash = "sha256:0beba1601be08bd00c9277e6ed4b026e125b26b379d86d6d98eb708409b3050d", size = 8449741, upload-time = "2026-05-16T06:28:45.424Z" }, - { url = "https://files.pythonhosted.org/packages/4b/13/445bc98acc2c976d6b8f8ca59b9c09f055adb5ffb3445d99af8ff7efcb4f/zizmor-1.25.2-py3-none-manylinux_2_28_x86_64.whl", hash = "sha256:c4246f1344d8dbeffc044d7bb11b131773a7db7eb57d9073c45942dfd3543a1f", size = 9285184, upload-time = "2026-05-16T06:28:39.21Z" }, - { url = "https://files.pythonhosted.org/packages/cf/78/fc7717c706bde7531b2fde12003994fbc04c47ab4f91aa6ca9b3b24b30fd/zizmor-1.25.2-py3-none-musllinux_1_2_aarch64.whl", hash = "sha256:dbb1b5c85b8de8eaa0227c6620f06c8e4fbd0a4da2086e218bc225c0bef0923d", size = 8886579, upload-time = "2026-05-16T06:28:51.384Z" }, - { url = "https://files.pythonhosted.org/packages/ca/bc/a46f11377cdc145c625d62d88c30fead56f9d29bc31652069a1a0eaed6c2/zizmor-1.25.2-py3-none-musllinux_1_2_armv7l.whl", hash = "sha256:d670a1e2f00b3cd56febd145bc1a0b2c4caf1cbe5dad8128721843fa877e2d2e", size = 8413576, upload-time = "2026-05-16T06:28:36.376Z" }, - { url = "https://files.pythonhosted.org/packages/2b/3b/0fd93b77171c8f229e8e1304eecc9931bf3009f722c57967d545d9f151b6/zizmor-1.25.2-py3-none-musllinux_1_2_x86_64.whl", hash = "sha256:b75c84d7387389f95edadbe859fb2aaf0a360c5b080932cc53e92ae1db6f09ef", size = 9378162, upload-time = "2026-05-16T06:28:41.999Z" }, - { url = "https://files.pythonhosted.org/packages/b5/3f/dcb85fb9a0d87794847f9043f9db9bb4d274cf4b8077604bc13850c8fdb4/zizmor-1.25.2-py3-none-win32.whl", hash = "sha256:aa9f4c43b499c55339c3ef2e885133c5017cd9a18d76d9335541203cfa5ae1e7", size = 7548509, upload-time = "2026-05-16T06:28:28.828Z" }, - { url = "https://files.pythonhosted.org/packages/d2/81/1cb088098bd53f9b910098b0c19d06dc587acf328a170ef8afd1cd93b482/zizmor-1.25.2-py3-none-win_amd64.whl", hash = "sha256:af55bd9bd119ea8cbce2a7addc3922503019de32c1fe31106d70b3dc77d77908", size = 8609822, upload-time = "2026-05-16T06:28:48.078Z" }, +version = "1.26.1" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/e4/a0/a29b38e24981b4bb41db4f292b2c9fb9ddf8b05d6b724abddd7bd108b621/zizmor-1.26.1.tar.gz", hash = "sha256:0c2cc575007a4db99d89d5acc6120cfa7b61504bc2394c3b50af348c73f1916e", size = 535275, upload-time = "2026-06-21T02:47:21.265Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/40/a9/2f47f7db8db9491025e00a7f1a0f25d32b642c0285b2fe070ac63e679b47/zizmor-1.26.1-py3-none-macosx_10_12_x86_64.whl", hash = "sha256:7ea21ca959c8e888de238fee81d73a1fdf89a82067eac75b8f1acdbd23e2eeaf", size = 9086061, upload-time = "2026-06-21T02:46:57.492Z" }, + { url = "https://files.pythonhosted.org/packages/58/92/cf6801f01e1d65cbda89a2e2926ea42caf1daad9ffa3f1fc88e4c68f48a9/zizmor-1.26.1-py3-none-macosx_11_0_arm64.whl", hash = "sha256:78083b495593f8b0b9dec14036a0836a5afcddda8a40738336ff4e399476b741", size = 8626865, upload-time = "2026-06-21T02:47:00.323Z" }, + { url = "https://files.pythonhosted.org/packages/b4/b1/ff38fc2921f1fb13244bb3a3642c4b45ecf3946c279942aafcb5dbf55a57/zizmor-1.26.1-py3-none-manylinux_2_24_aarch64.whl", hash = "sha256:bb7ebbe565a3742eb49a590352127ad549bb122b9b4ff9424ebab7525fa3b6b6", size = 8843965, upload-time = "2026-06-21T02:47:03.318Z" }, + { url = "https://files.pythonhosted.org/packages/3d/06/c07fd0eeef0427d93e99d552d5386526fbcd0bf05fc95cd37bdc6229fccb/zizmor-1.26.1-py3-none-manylinux_2_28_armv7l.whl", hash = "sha256:d3049010b6bd6f849413b6d20c28e0c677b90e0a5b2bc73cbee7f7bd86dc5828", size = 8386985, upload-time = "2026-06-21T02:47:05.741Z" }, + { url = "https://files.pythonhosted.org/packages/a8/2b/61ab13d45d6ce57ef5a08bb3246981f62e30bb4938098b17bb7b88110b79/zizmor-1.26.1-py3-none-manylinux_2_28_x86_64.whl", hash = "sha256:6a958d8a0941d7e1d0de8436670b5cb7fc64c8028b4d16e3f519ccc77f953cef", size = 9257232, upload-time = "2026-06-21T02:47:07.941Z" }, + { url = "https://files.pythonhosted.org/packages/e3/ad/bd74a96cb02045414ec5b573cd97ff3b82a97fd0bd6658f93c36a011c439/zizmor-1.26.1-py3-none-musllinux_1_2_aarch64.whl", hash = "sha256:d2744cdf944436ca7a009ae8b626a017a40381ec990216abd6cf6b8beb23323a", size = 8873798, upload-time = "2026-06-21T02:47:10.472Z" }, + { url = "https://files.pythonhosted.org/packages/b8/7e/fb3d608ee11e2f619d43ad93bab46eb7b32769fa82b1d86fd23f27c2585b/zizmor-1.26.1-py3-none-musllinux_1_2_armv7l.whl", hash = "sha256:44099f426af9da750ff9f548a0084e11d7d83e0158fe1a2778672398d728efdd", size = 8350857, upload-time = "2026-06-21T02:47:12.748Z" }, + { url = "https://files.pythonhosted.org/packages/27/cc/82d7a838c2d490071555c364f90eb851044b3eeefc1d68612179a2cd1ae5/zizmor-1.26.1-py3-none-musllinux_1_2_x86_64.whl", hash = "sha256:8313cc264dec792f00a7328eb7c8e89e7d62d54f950fc897d1e6a5a6e5762203", size = 9351148, upload-time = "2026-06-21T02:47:14.777Z" }, + { url = "https://files.pythonhosted.org/packages/f9/ee/d2a2301f30b9e1bf0d721bfd31739acd71e048757f9ba79279583eb30ac0/zizmor-1.26.1-py3-none-win32.whl", hash = "sha256:c96d7787d69fb298eae939e00dfdf7f534d7dfbd9cc17ab442c0650a56851415", size = 7531021, upload-time = "2026-06-21T02:47:17.247Z" }, + { url = "https://files.pythonhosted.org/packages/91/58/ad561f3a5057d3c0f152002e180a3a5745e72ea9d69bf66450ef9f5d3fe5/zizmor-1.26.1-py3-none-win_amd64.whl", hash = "sha256:0a05acf6068609fb6df3b137276cf18a686226a1e0e207941cb34a85929f16cf", size = 8616584, upload-time = "2026-06-21T02:47:19.094Z" }, ] From 02f80bc4d026bbbcbfcd9a79d4c674086764d9e7 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Tue, 30 Jun 2026 09:21:16 +0000 Subject: [PATCH 331/462] =?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 63477962c..f6156d438 100644 --- a/docs/en/docs/release-notes.md +++ b/docs/en/docs/release-notes.md @@ -9,6 +9,7 @@ hide: ### Internal +* ⬆ Bump the python-packages group across 1 directory with 10 updates. PR [#15870](https://github.com/fastapi/fastapi/pull/15870) by [@dependabot[bot]](https://github.com/apps/dependabot). * ⬆ Bump CodSpeedHQ/action from 4.17.0 to 4.17.5 in the github-actions group. PR [#15826](https://github.com/fastapi/fastapi/pull/15826) by [@dependabot[bot]](https://github.com/apps/dependabot). ## 0.138.2 (2026-06-29) From f6f3d25d1088045199209a234b8d106ac2c43163 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 30 Jun 2026 12:33:41 +0000 Subject: [PATCH 332/462] =?UTF-8?q?=E2=AC=86=20Bump=20the=20github-actions?= =?UTF-8?q?=20group=20with=205=20updates=20(#15872)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: Yurii Motov --- .github/workflows/build-docs.yml | 12 ++++++------ .github/workflows/contributors.yml | 4 ++-- .github/workflows/create-draft-release.yml | 4 ++-- .github/workflows/deploy-docs.yml | 5 +++-- .github/workflows/label-approved.yml | 4 ++-- .github/workflows/latest-changes.yml | 3 ++- .github/workflows/notify-translations.yml | 5 +++-- .github/workflows/people.yml | 4 ++-- .github/workflows/pre-commit.yml | 6 +++--- .github/workflows/prepare-release.yml | 4 ++-- .github/workflows/publish.yml | 4 ++-- .github/workflows/smokeshow.yml | 5 +++-- .github/workflows/sponsors.yml | 4 ++-- .github/workflows/test-redistribute.yml | 4 ++-- .github/workflows/test.yml | 16 ++++++++-------- .github/workflows/topic-repos.yml | 4 ++-- .github/workflows/translate.yml | 8 ++++---- .github/workflows/zizmor.yml | 4 ++-- 18 files changed, 52 insertions(+), 48 deletions(-) diff --git a/.github/workflows/build-docs.yml b/.github/workflows/build-docs.yml index 0cf8d1262..fe2a39c45 100644 --- a/.github/workflows/build-docs.yml +++ b/.github/workflows/build-docs.yml @@ -17,7 +17,7 @@ jobs: outputs: docs: ${{ steps.filter.outputs.docs }} steps: - - uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3 + - uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0 with: persist-credentials: false # For pull requests it's not necessary to checkout the code but for the main branch it is @@ -43,11 +43,11 @@ jobs: outputs: langs: ${{ steps.show-langs.outputs.langs }} steps: - - uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3 + - uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0 with: persist-credentials: false - name: Set up Python - uses: actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405 # v6.2.0 + uses: actions/setup-python@ece7cb06caefa5fff74198d8649806c4678c61a1 # v6.3.0 with: python-version-file: ".python-version" - name: Setup uv @@ -82,11 +82,11 @@ jobs: env: GITHUB_CONTEXT: ${{ toJson(github) }} run: echo "$GITHUB_CONTEXT" - - uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3 + - uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0 with: persist-credentials: false - name: Set up Python - uses: actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405 # v6.2.0 + uses: actions/setup-python@ece7cb06caefa5fff74198d8649806c4678c61a1 # v6.3.0 with: python-version-file: ".python-version" - name: Setup uv @@ -103,7 +103,7 @@ jobs: run: uv sync --locked --no-dev --group docs - name: Update Languages run: uv run ./scripts/docs.py update-languages - - uses: actions/cache@27d5ce7f107fe9357f9df03efb73ab90386fccae # v5.0.5 + - uses: actions/cache@55cc8345863c7cc4c66a329aec7e433d2d1c52a9 # v6.1.0 with: key: zensical-${{ matrix.lang }}-${{ github.ref }} path: site_zensical_src/${{ matrix.lang }}/.cache diff --git a/.github/workflows/contributors.yml b/.github/workflows/contributors.yml index bc6059218..1d869e7b8 100644 --- a/.github/workflows/contributors.yml +++ b/.github/workflows/contributors.yml @@ -23,11 +23,11 @@ jobs: env: GITHUB_CONTEXT: ${{ toJson(github) }} run: echo "$GITHUB_CONTEXT" - - uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3 + - uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0 with: persist-credentials: true # Required for `git push` in `contributors.py` - name: Set up Python - uses: actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405 # v6.2.0 + uses: actions/setup-python@ece7cb06caefa5fff74198d8649806c4678c61a1 # v6.3.0 with: python-version-file: ".python-version" - name: Setup uv diff --git a/.github/workflows/create-draft-release.yml b/.github/workflows/create-draft-release.yml index 15df98ab4..e0af097e2 100644 --- a/.github/workflows/create-draft-release.yml +++ b/.github/workflows/create-draft-release.yml @@ -22,12 +22,12 @@ jobs: env: GITHUB_CONTEXT: ${{ toJson(github) }} run: echo "$GITHUB_CONTEXT" - - uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3 + - uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0 with: ref: ${{ github.event.repository.default_branch }} persist-credentials: true - name: Set up Python - uses: actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405 # v6.2.0 + uses: actions/setup-python@ece7cb06caefa5fff74198d8649806c4678c61a1 # v6.3.0 with: python-version-file: ".python-version" - name: Install uv diff --git a/.github/workflows/deploy-docs.yml b/.github/workflows/deploy-docs.yml index 04f02d3e7..be377df94 100644 --- a/.github/workflows/deploy-docs.yml +++ b/.github/workflows/deploy-docs.yml @@ -22,11 +22,12 @@ jobs: env: GITHUB_CONTEXT: ${{ toJson(github) }} run: echo "$GITHUB_CONTEXT" - - uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3 + - uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0 with: persist-credentials: false + allow-unsafe-pr-checkout: true - name: Set up Python - uses: actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405 # v6.2.0 + uses: actions/setup-python@ece7cb06caefa5fff74198d8649806c4678c61a1 # v6.3.0 with: python-version-file: ".python-version" - name: Setup uv diff --git a/.github/workflows/label-approved.yml b/.github/workflows/label-approved.yml index 041bac942..6d4f2ef52 100644 --- a/.github/workflows/label-approved.yml +++ b/.github/workflows/label-approved.yml @@ -19,11 +19,11 @@ jobs: env: GITHUB_CONTEXT: ${{ toJson(github) }} run: echo "$GITHUB_CONTEXT" - - uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3 + - uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0 with: persist-credentials: false - name: Set up Python - uses: actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405 # v6.2.0 + uses: actions/setup-python@ece7cb06caefa5fff74198d8649806c4678c61a1 # v6.3.0 with: python-version-file: ".python-version" - name: Setup uv diff --git a/.github/workflows/latest-changes.yml b/.github/workflows/latest-changes.yml index 9390bc538..f934823fe 100644 --- a/.github/workflows/latest-changes.yml +++ b/.github/workflows/latest-changes.yml @@ -28,11 +28,12 @@ jobs: env: GITHUB_CONTEXT: ${{ toJson(github) }} run: echo "$GITHUB_CONTEXT" - - uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3 + - uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0 with: # To allow latest-changes to commit to the main branch token: ${{ secrets.FASTAPI_LATEST_CHANGES }} # zizmor: ignore[secrets-outside-env] persist-credentials: true # required by tiangolo/latest-changes + allow-unsafe-pr-checkout: true # Allow debugging with tmate - name: Setup tmate session uses: mxschmitt/action-tmate@35b54afac29c97fb54faba5b513f8fbd1882f113 # v3.24 diff --git a/.github/workflows/notify-translations.yml b/.github/workflows/notify-translations.yml index 360a4df69..d2175f30d 100644 --- a/.github/workflows/notify-translations.yml +++ b/.github/workflows/notify-translations.yml @@ -30,11 +30,12 @@ jobs: env: GITHUB_CONTEXT: ${{ toJson(github) }} run: echo "$GITHUB_CONTEXT" - - uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3 + - uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0 with: persist-credentials: false + allow-unsafe-pr-checkout: true - name: Set up Python - uses: actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405 # v6.2.0 + uses: actions/setup-python@ece7cb06caefa5fff74198d8649806c4678c61a1 # v6.3.0 with: python-version-file: ".python-version" - name: Setup uv diff --git a/.github/workflows/people.yml b/.github/workflows/people.yml index bc4f19727..2e48c9d70 100644 --- a/.github/workflows/people.yml +++ b/.github/workflows/people.yml @@ -23,11 +23,11 @@ jobs: env: GITHUB_CONTEXT: ${{ toJson(github) }} run: echo "$GITHUB_CONTEXT" - - uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3 + - uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0 with: persist-credentials: true # Required for `git push` in `people.py` - name: Set up Python - uses: actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405 # v6.2.0 + uses: actions/setup-python@ece7cb06caefa5fff74198d8649806c4678c61a1 # v6.3.0 with: python-version-file: ".python-version" - name: Setup uv diff --git a/.github/workflows/pre-commit.yml b/.github/workflows/pre-commit.yml index 915e3a883..963fd68ab 100644 --- a/.github/workflows/pre-commit.yml +++ b/.github/workflows/pre-commit.yml @@ -17,7 +17,7 @@ jobs: env: GITHUB_CONTEXT: ${{ toJson(github) }} run: echo "$GITHUB_CONTEXT" - - uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3 + - uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0 name: Checkout PR for own repo if: env.HAS_SECRETS == 'true' with: @@ -30,7 +30,7 @@ jobs: token: ${{ secrets.PRE_COMMIT }} # zizmor: ignore[secrets-outside-env] persist-credentials: true # Required for `git push` command # pre-commit lite ci needs the default checkout configs to work - - uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3 + - uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0 name: Checkout PR for fork if: env.HAS_SECRETS == 'false' with: @@ -39,7 +39,7 @@ jobs: fetch-depth: 0 persist-credentials: false - name: Set up Python - uses: actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405 # v6.2.0 + uses: actions/setup-python@ece7cb06caefa5fff74198d8649806c4678c61a1 # v6.3.0 with: python-version-file: ".python-version" - name: Setup uv diff --git a/.github/workflows/prepare-release.yml b/.github/workflows/prepare-release.yml index 9561e9422..5b241aa4f 100644 --- a/.github/workflows/prepare-release.yml +++ b/.github/workflows/prepare-release.yml @@ -34,12 +34,12 @@ jobs: env: GITHUB_CONTEXT: ${{ toJson(github) }} run: echo "$GITHUB_CONTEXT" - - uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3 + - uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0 with: token: ${{ secrets.FASTAPI_LATEST_CHANGES }} # zizmor: ignore[secrets-outside-env] persist-credentials: true - name: Set up Python - uses: actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405 # v6.2.0 + uses: actions/setup-python@ece7cb06caefa5fff74198d8649806c4678c61a1 # v6.3.0 with: python-version-file: ".python-version" - name: Install uv diff --git a/.github/workflows/publish.yml b/.github/workflows/publish.yml index 270fab4d4..447ce8c33 100644 --- a/.github/workflows/publish.yml +++ b/.github/workflows/publish.yml @@ -19,11 +19,11 @@ jobs: env: GITHUB_CONTEXT: ${{ toJson(github) }} run: echo "$GITHUB_CONTEXT" - - uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3 + - uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0 with: persist-credentials: false - name: Set up Python - uses: actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405 # v6.2.0 + uses: actions/setup-python@ece7cb06caefa5fff74198d8649806c4678c61a1 # v6.3.0 with: python-version-file: ".python-version" - name: Install uv diff --git a/.github/workflows/smokeshow.yml b/.github/workflows/smokeshow.yml index a674f6261..5e2f2ea55 100644 --- a/.github/workflows/smokeshow.yml +++ b/.github/workflows/smokeshow.yml @@ -19,10 +19,11 @@ jobs: env: GITHUB_CONTEXT: ${{ toJson(github) }} run: echo "$GITHUB_CONTEXT" - - uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3 + - uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0 with: persist-credentials: false - - uses: actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405 # v6.2.0 + allow-unsafe-pr-checkout: true + - uses: actions/setup-python@ece7cb06caefa5fff74198d8649806c4678c61a1 # v6.3.0 with: python-version-file: ".python-version" - name: Setup uv diff --git a/.github/workflows/sponsors.yml b/.github/workflows/sponsors.yml index d3a78b5f8..a20dcaf05 100644 --- a/.github/workflows/sponsors.yml +++ b/.github/workflows/sponsors.yml @@ -24,11 +24,11 @@ jobs: env: GITHUB_CONTEXT: ${{ toJson(github) }} run: echo "$GITHUB_CONTEXT" - - uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3 + - uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0 with: persist-credentials: true # Required for `git push` in `sponsors.py` - name: Set up Python - uses: actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405 # v6.2.0 + uses: actions/setup-python@ece7cb06caefa5fff74198d8649806c4678c61a1 # v6.3.0 with: python-version-file: ".python-version" - name: Setup uv diff --git a/.github/workflows/test-redistribute.yml b/.github/workflows/test-redistribute.yml index 47a2a8ae4..cffb9d8c8 100644 --- a/.github/workflows/test-redistribute.yml +++ b/.github/workflows/test-redistribute.yml @@ -16,11 +16,11 @@ jobs: env: GITHUB_CONTEXT: ${{ toJson(github) }} run: echo "$GITHUB_CONTEXT" - - uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3 + - uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0 with: persist-credentials: false - name: Set up Python - uses: actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405 # v6.2.0 + uses: actions/setup-python@ece7cb06caefa5fff74198d8649806c4678c61a1 # v6.3.0 with: python-version-file: ".python-version" - name: Install build dependencies diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 6870160de..e28e90e3e 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -26,7 +26,7 @@ jobs: outputs: src: ${{ steps.filter.outputs.src }} steps: - - uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3 + - uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0 with: persist-credentials: false # For pull requests it's not necessary to checkout the code but for the main branch it is @@ -107,11 +107,11 @@ jobs: env: GITHUB_CONTEXT: ${{ toJson(github) }} run: echo "$GITHUB_CONTEXT" - - uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3 + - uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0 with: persist-credentials: false - name: Set up Python - uses: actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405 # v6.2.0 + uses: actions/setup-python@ece7cb06caefa5fff74198d8649806c4678c61a1 # v6.3.0 with: python-version: ${{ matrix.python-version }} - name: Setup uv @@ -171,11 +171,11 @@ jobs: env: GITHUB_CONTEXT: ${{ toJson(github) }} run: echo "$GITHUB_CONTEXT" - - uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3 + - uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0 with: persist-credentials: false - name: Set up Python - uses: actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405 # v6.2.0 + uses: actions/setup-python@ece7cb06caefa5fff74198d8649806c4678c61a1 # v6.3.0 with: python-version: "3.13" - name: Setup uv @@ -191,7 +191,7 @@ jobs: - name: Install Dependencies run: uv sync --no-dev --group tests --extra all - name: CodSpeed benchmarks - uses: CodSpeedHQ/action@c145068895e045cc725ee76fcd2307624b65c3af # v4.17.5 + uses: CodSpeedHQ/action@63f3e98b61959fe67f146a3ff022e4136fe9bb9c # v4.17.6 with: mode: simulation run: uv run --no-sync pytest tests/benchmarks --codspeed @@ -206,10 +206,10 @@ jobs: env: GITHUB_CONTEXT: ${{ toJson(github) }} run: echo "$GITHUB_CONTEXT" - - uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3 + - uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0 with: persist-credentials: false - - uses: actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405 # v6.2.0 + - uses: actions/setup-python@ece7cb06caefa5fff74198d8649806c4678c61a1 # v6.3.0 with: python-version-file: ".python-version" - name: Setup uv diff --git a/.github/workflows/topic-repos.yml b/.github/workflows/topic-repos.yml index abe8cf14b..b0fb40398 100644 --- a/.github/workflows/topic-repos.yml +++ b/.github/workflows/topic-repos.yml @@ -19,11 +19,11 @@ jobs: env: GITHUB_CONTEXT: ${{ toJson(github) }} run: echo "$GITHUB_CONTEXT" - - uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3 + - uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0 with: persist-credentials: true # Required for `git push` in `topic_repos.py` - name: Set up Python - uses: actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405 # v6.2.0 + uses: actions/setup-python@ece7cb06caefa5fff74198d8649806c4678c61a1 # v6.3.0 with: python-version-file: ".python-version" - name: Setup uv diff --git a/.github/workflows/translate.yml b/.github/workflows/translate.yml index 18df9c157..7f96798da 100644 --- a/.github/workflows/translate.yml +++ b/.github/workflows/translate.yml @@ -50,11 +50,11 @@ jobs: langs: ${{ steps.show-langs.outputs.langs }} commands: ${{ steps.show-langs.outputs.commands }} steps: - - uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3 + - uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0 with: persist-credentials: false - name: Set up Python - uses: actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405 # v6.2.0 + uses: actions/setup-python@ece7cb06caefa5fff74198d8649806c4678c61a1 # v6.3.0 with: python-version-file: ".python-version" - name: Setup uv @@ -92,12 +92,12 @@ jobs: env: GITHUB_CONTEXT: ${{ toJson(github) }} run: echo "$GITHUB_CONTEXT" - - uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3 + - uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0 with: fetch-depth: 0 persist-credentials: true # Required for `git push` in `translate.py` - name: Set up Python - uses: actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405 # v6.2.0 + uses: actions/setup-python@ece7cb06caefa5fff74198d8649806c4678c61a1 # v6.3.0 with: python-version-file: ".python-version" - name: Setup uv diff --git a/.github/workflows/zizmor.yml b/.github/workflows/zizmor.yml index 04c027a85..11ecb8272 100644 --- a/.github/workflows/zizmor.yml +++ b/.github/workflows/zizmor.yml @@ -18,8 +18,8 @@ jobs: security-events: write # Required for upload-sarif (used by zizmor-action) to upload SARIF files. steps: - name: Checkout repository - uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3 + uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0 with: persist-credentials: false - name: Run zizmor - uses: zizmorcore/zizmor-action@5f14fd08f7cf1cb1609c1e344975f152c7ee938d # v0.5.6 + uses: zizmorcore/zizmor-action@192e21d79ab29983730a13d1382995c2307fbcaa # v0.5.7 From fe450d9a414572cf9a7354cef77d99e8d16e7d73 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Tue, 30 Jun 2026 12:34:14 +0000 Subject: [PATCH 333/462] =?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 f6156d438..bbceb404d 100644 --- a/docs/en/docs/release-notes.md +++ b/docs/en/docs/release-notes.md @@ -9,6 +9,7 @@ hide: ### Internal +* ⬆ Bump the github-actions group with 5 updates. PR [#15872](https://github.com/fastapi/fastapi/pull/15872) by [@dependabot[bot]](https://github.com/apps/dependabot). * ⬆ Bump the python-packages group across 1 directory with 10 updates. PR [#15870](https://github.com/fastapi/fastapi/pull/15870) by [@dependabot[bot]](https://github.com/apps/dependabot). * ⬆ Bump CodSpeedHQ/action from 4.17.0 to 4.17.5 in the github-actions group. PR [#15826](https://github.com/fastapi/fastapi/pull/15826) by [@dependabot[bot]](https://github.com/apps/dependabot). From 8da95e1842e2eaa9c12e3ee5a7e3c5522376922e Mon Sep 17 00:00:00 2001 From: Yurii Motov <109919500+YuriiMotov@users.noreply.github.com> Date: Tue, 30 Jun 2026 20:57:35 +0200 Subject: [PATCH 334/462] =?UTF-8?q?=F0=9F=91=B7=20Remove=20not=20needed=20?= =?UTF-8?q?`allow-unsafe-pr-checkout:=20true`=20(#15876)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .github/workflows/deploy-docs.yml | 1 - .github/workflows/latest-changes.yml | 1 - .github/workflows/notify-translations.yml | 1 - .github/workflows/smokeshow.yml | 1 - 4 files changed, 4 deletions(-) diff --git a/.github/workflows/deploy-docs.yml b/.github/workflows/deploy-docs.yml index be377df94..d8353ad55 100644 --- a/.github/workflows/deploy-docs.yml +++ b/.github/workflows/deploy-docs.yml @@ -25,7 +25,6 @@ jobs: - uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0 with: persist-credentials: false - allow-unsafe-pr-checkout: true - name: Set up Python uses: actions/setup-python@ece7cb06caefa5fff74198d8649806c4678c61a1 # v6.3.0 with: diff --git a/.github/workflows/latest-changes.yml b/.github/workflows/latest-changes.yml index f934823fe..111b47424 100644 --- a/.github/workflows/latest-changes.yml +++ b/.github/workflows/latest-changes.yml @@ -33,7 +33,6 @@ jobs: # To allow latest-changes to commit to the main branch token: ${{ secrets.FASTAPI_LATEST_CHANGES }} # zizmor: ignore[secrets-outside-env] persist-credentials: true # required by tiangolo/latest-changes - allow-unsafe-pr-checkout: true # Allow debugging with tmate - name: Setup tmate session uses: mxschmitt/action-tmate@35b54afac29c97fb54faba5b513f8fbd1882f113 # v3.24 diff --git a/.github/workflows/notify-translations.yml b/.github/workflows/notify-translations.yml index d2175f30d..aa006978c 100644 --- a/.github/workflows/notify-translations.yml +++ b/.github/workflows/notify-translations.yml @@ -33,7 +33,6 @@ jobs: - uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0 with: persist-credentials: false - allow-unsafe-pr-checkout: true - name: Set up Python uses: actions/setup-python@ece7cb06caefa5fff74198d8649806c4678c61a1 # v6.3.0 with: diff --git a/.github/workflows/smokeshow.yml b/.github/workflows/smokeshow.yml index 5e2f2ea55..41804cee9 100644 --- a/.github/workflows/smokeshow.yml +++ b/.github/workflows/smokeshow.yml @@ -22,7 +22,6 @@ jobs: - uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0 with: persist-credentials: false - allow-unsafe-pr-checkout: true - uses: actions/setup-python@ece7cb06caefa5fff74198d8649806c4678c61a1 # v6.3.0 with: python-version-file: ".python-version" From bf8283b4444acfbe6bd6ac1de923760acf5e167a Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Tue, 30 Jun 2026 18:58:00 +0000 Subject: [PATCH 335/462] =?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 bbceb404d..f40434bb2 100644 --- a/docs/en/docs/release-notes.md +++ b/docs/en/docs/release-notes.md @@ -9,6 +9,7 @@ hide: ### Internal +* 👷 Remove not needed `allow-unsafe-pr-checkout: true`. PR [#15876](https://github.com/fastapi/fastapi/pull/15876) by [@YuriiMotov](https://github.com/YuriiMotov). * ⬆ Bump the github-actions group with 5 updates. PR [#15872](https://github.com/fastapi/fastapi/pull/15872) by [@dependabot[bot]](https://github.com/apps/dependabot). * ⬆ Bump the python-packages group across 1 directory with 10 updates. PR [#15870](https://github.com/fastapi/fastapi/pull/15870) by [@dependabot[bot]](https://github.com/apps/dependabot). * ⬆ Bump CodSpeedHQ/action from 4.17.0 to 4.17.5 in the github-actions group. PR [#15826](https://github.com/fastapi/fastapi/pull/15826) by [@dependabot[bot]](https://github.com/apps/dependabot). From 3ac41743924ca9e8fb4e391fe3c7b5bbccacafc6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebasti=C3=A1n=20Ram=C3=ADrez?= Date: Wed, 1 Jul 2026 12:20:39 +0200 Subject: [PATCH 336/462] =?UTF-8?q?=F0=9F=91=A5=20Update=20FastAPI=20Peopl?= =?UTF-8?q?e=20-=20Contributors=20and=20Translators=20(#15878)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: github-actions[bot] --- docs/en/data/contributors.yml | 8 +++--- docs/en/data/translation_reviewers.yml | 38 +++++++++++++------------- docs/en/data/translators.yml | 14 +++++----- 3 files changed, 30 insertions(+), 30 deletions(-) diff --git a/docs/en/data/contributors.yml b/docs/en/data/contributors.yml index 7e1572146..b22e0975b 100644 --- a/docs/en/data/contributors.yml +++ b/docs/en/data/contributors.yml @@ -1,21 +1,21 @@ tiangolo: login: tiangolo - count: 961 + count: 1005 avatarUrl: https://avatars.githubusercontent.com/u/1326112?u=cb5d06e73a9e1998141b1641aa88e443c6717651&v=4 url: https://github.com/tiangolo dependabot: login: dependabot - count: 201 + count: 221 avatarUrl: https://avatars.githubusercontent.com/in/29110?v=4 url: https://github.com/apps/dependabot YuriiMotov: login: YuriiMotov - count: 78 + count: 82 avatarUrl: https://avatars.githubusercontent.com/u/109919500?u=bc48be95c429989224786106b027f3c5e40cc354&v=4 url: https://github.com/YuriiMotov alejsdev: login: alejsdev - count: 56 + count: 57 avatarUrl: https://avatars.githubusercontent.com/u/90076947?u=0facffe3abf87f57a1f05fa773d1119cc5c2f6a5&v=4 url: https://github.com/alejsdev pre-commit-ci: diff --git a/docs/en/data/translation_reviewers.yml b/docs/en/data/translation_reviewers.yml index 3ed7d09d9..ccc4d604f 100644 --- a/docs/en/data/translation_reviewers.yml +++ b/docs/en/data/translation_reviewers.yml @@ -28,6 +28,11 @@ hard-coders: count: 102 avatarUrl: https://avatars.githubusercontent.com/u/9651103?u=78d12d1acdf853c817700145e73de7fd9e5d068b&v=4 url: https://github.com/hard-coders +YuriiMotov: + login: YuriiMotov + count: 95 + avatarUrl: https://avatars.githubusercontent.com/u/109919500?u=bc48be95c429989224786106b027f3c5e40cc354&v=4 + url: https://github.com/YuriiMotov hasansezertasan: login: hasansezertasan count: 95 @@ -38,11 +43,6 @@ alv2017: count: 88 avatarUrl: https://avatars.githubusercontent.com/u/31544722?v=4 url: https://github.com/alv2017 -YuriiMotov: - login: YuriiMotov - count: 87 - avatarUrl: https://avatars.githubusercontent.com/u/109919500?u=bc48be95c429989224786106b027f3c5e40cc354&v=4 - url: https://github.com/YuriiMotov nazarepiedady: login: nazarepiedady count: 87 @@ -383,6 +383,11 @@ mastizada: count: 16 avatarUrl: https://avatars.githubusercontent.com/u/1975818?u=0751a06d7271c8bf17cb73b1b845644ab4d2c6dc&v=4 url: https://github.com/mastizada +waketzheng: + login: waketzheng + count: 16 + avatarUrl: https://avatars.githubusercontent.com/u/35413830?u=df19e4fd5bb928e7d086e053ef26a46aad23bf84&v=4 + url: https://github.com/waketzheng Joao-Pedro-P-Holanda: login: Joao-Pedro-P-Holanda count: 16 @@ -448,11 +453,6 @@ impocode: count: 13 avatarUrl: https://avatars.githubusercontent.com/u/109408819?u=9cdfc5ccb31a2094c520f41b6087012fa9048982&v=4 url: https://github.com/impocode -waketzheng: - login: waketzheng - count: 13 - avatarUrl: https://avatars.githubusercontent.com/u/35413830?u=df19e4fd5bb928e7d086e053ef26a46aad23bf84&v=4 - url: https://github.com/waketzheng wesinalves: login: wesinalves count: 13 @@ -563,6 +563,11 @@ Pyth3rEx: count: 11 avatarUrl: https://avatars.githubusercontent.com/u/26427764?u=087724f74d813c95925d51e354554bd4b6d6bb60&v=4 url: https://github.com/Pyth3rEx +ABcDexter: + login: ABcDexter + count: 11 + avatarUrl: https://avatars.githubusercontent.com/u/7236257?u=baa7e62eb4d0014b5854bfd0d5c2b20bd9617e0d&v=4 + url: https://github.com/ABcDexter mariacamilagl: login: mariacamilagl count: 10 @@ -661,7 +666,7 @@ eVery1337: aykhans: login: aykhans count: 9 - avatarUrl: https://avatars.githubusercontent.com/u/88669260?u=798da457cc3276d3c6dd7fd628d0005ad8b298cc&v=4 + avatarUrl: https://avatars.githubusercontent.com/u/88669260?u=2760f6f6728ed11108b56265682bcf68d46067a5&v=4 url: https://github.com/aykhans riroan: login: riroan @@ -671,7 +676,7 @@ riroan: MinLee0210: login: MinLee0210 count: 9 - avatarUrl: https://avatars.githubusercontent.com/u/57653278?u=e7c4d8d7eeb7bceed1680ef0e5dafec0695f57e0&v=4 + avatarUrl: https://avatars.githubusercontent.com/u/57653278?u=9fef84dd2f7497e8b43db01ba517a5b2bd66ad88&v=4 url: https://github.com/MinLee0210 yodai-yodai: login: yodai-yodai @@ -693,11 +698,6 @@ Yarous: count: 9 avatarUrl: https://avatars.githubusercontent.com/u/61277193?u=5b462347458a373b2d599c6f416d2b75eddbffad&v=4 url: https://github.com/Yarous -ABcDexter: - login: ABcDexter - count: 9 - avatarUrl: https://avatars.githubusercontent.com/u/7236257?u=baa7e62eb4d0014b5854bfd0d5c2b20bd9617e0d&v=4 - url: https://github.com/ABcDexter dimaqq: login: dimaqq count: 8 @@ -756,7 +756,7 @@ EdmilsonRodrigues: roli2py: login: roli2py count: 8 - avatarUrl: https://avatars.githubusercontent.com/u/61126128?u=bcb7a286e435a6b9d6a84b07db1232580ee796d4&v=4 + avatarUrl: https://avatars.githubusercontent.com/u/61126128?u=d20921080d6b9499b39ef3431e850432fe68f903&v=4 url: https://github.com/roli2py Serrones: login: Serrones @@ -1281,7 +1281,7 @@ rafsaf: frnsimoes: login: frnsimoes count: 3 - avatarUrl: https://avatars.githubusercontent.com/u/66239468?u=be491199e4695bb0ac43d17d59cf7d41f9df629f&v=4 + avatarUrl: https://avatars.githubusercontent.com/u/66239468?u=c86ceed4afa180477e28b9ff0019ab894a1e1eb9&v=4 url: https://github.com/frnsimoes lieryan: login: lieryan diff --git a/docs/en/data/translators.yml b/docs/en/data/translators.yml index d0ca9a1d6..ccad6767f 100644 --- a/docs/en/data/translators.yml +++ b/docs/en/data/translators.yml @@ -5,7 +5,7 @@ nilslindemann: url: https://github.com/nilslindemann tiangolo: login: tiangolo - count: 78 + count: 100 avatarUrl: https://avatars.githubusercontent.com/u/1326112?u=cb5d06e73a9e1998141b1641aa88e443c6717651&v=4 url: https://github.com/tiangolo jaystone776: @@ -23,6 +23,11 @@ valentinDruzhinin: count: 29 avatarUrl: https://avatars.githubusercontent.com/u/12831905?u=aae1ebc675c91e8fa582df4fcc4fc4128106344d&v=4 url: https://github.com/valentinDruzhinin +YuriiMotov: + login: YuriiMotov + count: 24 + avatarUrl: https://avatars.githubusercontent.com/u/109919500?u=bc48be95c429989224786106b027f3c5e40cc354&v=4 + url: https://github.com/YuriiMotov tokusumi: login: tokusumi count: 23 @@ -33,11 +38,6 @@ SwftAlpc: count: 23 avatarUrl: https://avatars.githubusercontent.com/u/52768429?u=6a3aa15277406520ad37f6236e89466ed44bc5b8&v=4 url: https://github.com/SwftAlpc -YuriiMotov: - login: YuriiMotov - count: 23 - avatarUrl: https://avatars.githubusercontent.com/u/109919500?u=bc48be95c429989224786106b027f3c5e40cc354&v=4 - url: https://github.com/YuriiMotov hasansezertasan: login: hasansezertasan count: 22 @@ -466,7 +466,7 @@ ArtemKhymenko: hasnatsajid: login: hasnatsajid count: 2 - avatarUrl: https://avatars.githubusercontent.com/u/86589885?u=3712c0362d7a4000d76022339c545cf46aa5903f&v=4 + avatarUrl: https://avatars.githubusercontent.com/u/86589885?u=a1f0d462a558e4fc7271bfcdc7e5e7de92b9e10b&v=4 url: https://github.com/hasnatsajid alperiox: login: alperiox From 0df0261757e65fc8a8f22e2b8dff194ea349ddeb Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Wed, 1 Jul 2026 10:21:05 +0000 Subject: [PATCH 337/462] =?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 f40434bb2..ede72a33f 100644 --- a/docs/en/docs/release-notes.md +++ b/docs/en/docs/release-notes.md @@ -9,6 +9,7 @@ hide: ### Internal +* 👥 Update FastAPI People - Contributors and Translators. PR [#15878](https://github.com/fastapi/fastapi/pull/15878) by [@tiangolo](https://github.com/tiangolo). * 👷 Remove not needed `allow-unsafe-pr-checkout: true`. PR [#15876](https://github.com/fastapi/fastapi/pull/15876) by [@YuriiMotov](https://github.com/YuriiMotov). * ⬆ Bump the github-actions group with 5 updates. PR [#15872](https://github.com/fastapi/fastapi/pull/15872) by [@dependabot[bot]](https://github.com/apps/dependabot). * ⬆ Bump the python-packages group across 1 directory with 10 updates. PR [#15870](https://github.com/fastapi/fastapi/pull/15870) by [@dependabot[bot]](https://github.com/apps/dependabot). From f206f06f1a44e743720fdd5153a68af038098a5f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebasti=C3=A1n=20Ram=C3=ADrez?= Date: Wed, 1 Jul 2026 12:31:35 +0200 Subject: [PATCH 338/462] =?UTF-8?q?=F0=9F=8C=90=20Update=20translations=20?= =?UTF-8?q?for=20ru=20(add-missing)=20(#15879)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: github-actions[bot] Co-authored-by: Yurii Motov <109919500+YuriiMotov@users.noreply.github.com> --- docs/ru/docs/tutorial/frontend.md | 133 ++++++++++++++++++++++++++++++ 1 file changed, 133 insertions(+) create mode 100644 docs/ru/docs/tutorial/frontend.md diff --git a/docs/ru/docs/tutorial/frontend.md b/docs/ru/docs/tutorial/frontend.md new file mode 100644 index 000000000..3b3e43809 --- /dev/null +++ b/docs/ru/docs/tutorial/frontend.md @@ -0,0 +1,133 @@ +# Фронтенд { #frontend } + +Вы можете «отдавать» статические фронтенд-приложения с помощью `app.frontend()` (или `router.frontend()`). + +Это полезно для фронтенд-инструментов, которые генерируют статические файлы, таких как React с Vite, TanStack Router, Astro, Vue, Svelte, Angular, Solid и других. + +С такими инструментами обычно есть этап сборки фронтенда с помощью команды вроде: + +```bash +npm run build +``` + +Она сгенерирует директорию вроде `./dist/` с файлами вашего фронтенда. + +Вы можете использовать `app.frontend()`, чтобы «отдавать» эту директорию, следуя соглашениям, которые требуются этим фронтенд-фреймворкам. + +**FastAPI** сначала проверяет *операции пути*. Файлы фронтенда проверяются только если не совпал ни один обычный маршрут, поэтому ваш API не будет затронут. + +## Отдача фронтенда { #serve-a-frontend } + +После сборки фронтенда, например с помощью `npm run build`, поместите сгенерированные файлы в директорию, например `dist`. + +Структура вашего проекта может выглядеть так: + +```text +. +├── pyproject.toml +├── app +│ ├── __init__.py +│ └── main.py +└── dist + ├── index.html + └── assets + └── app.js +``` + +Затем «отдавайте» её с помощью `app.frontend()`: + +{* ../../docs_src/frontend/tutorial001_py310.py hl[5] *} + +При этом запрос к `/assets/app.js` может отдать `dist/assets/app.js`. + +Если у вас также есть *операция пути* **FastAPI**, приоритет будет у *операции пути*. + +## Маршрутизация на стороне клиента { #client-side-routing } + +Многие фронтенд-приложения, включая **single-page apps** (SPA), используют маршрутизацию на стороне клиента. Путь вроде `/dashboard/settings` может не быть реальным файлом, но фреймворк возьмёт на себя его обработку. + +Поэтому, если обратиться к этому URL напрямую (а не перейти к нему через приложение), backend должен отдать фронтенд-приложение из `index.html`, чтобы затем фронтенд-фреймворк мог обработать маршрутизацию на стороне клиента. + +Для этого используйте `fallback="index.html"`: + +{* ../../docs_src/frontend/tutorial002_py310.py hl[5] *} + +**FastAPI** использует этот fallback только для запросов `GET` и `HEAD`, которые похожи на навигацию в браузере. Отсутствующие файлы, такие как JavaScript, CSS и изображения, по-прежнему возвращают `404`. + +Запросы с другими методами, например `POST` или `PUT`, к путям, которые совпадают только с fallback фронтенда, также возвращают `404`. Обычные *операции пути* **FastAPI** по-прежнему имеют более высокий приоритет, чем маршруты фронтенда. + +/// tip | Совет + +По умолчанию `fallback` имеет значение `fallback="auto"`. В большинстве случаев вам не нужно будет указывать `fallback`. Подробности ниже. + +/// + +Именно такое поведение нужно для многих фронтенд-приложений, которые используют маршрутизацию на стороне клиента, например React с TanStack Router, Vue, Angular, SvelteKit или Solid. + +## Кастомная страница 404 { #custom-404-page } + +Вы также можете отдавать статическую страницу `404.html` для отсутствующих путей фронтенда: + +{* ../../docs_src/frontend/tutorial003_py310.py hl[5] *} + +Этот HTTP-ответ сохраняет статус-код `404`. + +В этом случае **FastAPI** не будет отдавать `index.html` для отсутствующих путей фронтенда. Вместо этого он вернёт файл `404.html`. + +/// tip | Совет + +По умолчанию `fallback` имеет значение `fallback="auto"`. При этом, если найден файл `404.html`, он будет автоматически использован как fallback. + +Поэтому обычно можно не указывать аргумент `fallback`. + +/// + +Это полезно с фронтенд-инструментами, которые генерируют статические HTML-файлы для каждой страницы, например Astro. + +## Автоматический fallback { #fallback-auto } + +По умолчанию `app.frontend()` использует `fallback="auto"`. + +Если в директории фронтенда есть файл `404.html`, отсутствующие пути фронтенда отдают этот файл со статус-кодом `404`. + +В противном случае, если есть файл `index.html`, отсутствующие пути навигации в браузере отдают `index.html`, что и ожидают многие фронтенд-приложения с маршрутизацией на стороне клиента. + +Поэтому в большинстве случаев можно использовать `app.frontend("/", directory="dist")` без указания аргумента `fallback`. + +{* ../../docs_src/frontend/tutorial001_py310.py hl[5] *} + +## Отключение fallback { #disable-fallback } + +Если вы не хотите отдавать fallback-файл для отсутствующих путей фронтенда, используйте `fallback=None`: + +{* ../../docs_src/frontend/tutorial005_py310.py hl[5] *} + +Тогда отсутствующие пути фронтенда будут возвращать обычный `404`. + +## Проверка директории { #check-directory } + +По умолчанию `app.frontend()` проверяет, что директория существует, при создании приложения. + +Это помогает рано обнаруживать ошибки конфигурации. Например, если отсутствует директория с результатом сборки фронтенда, **FastAPI** вызовет ошибку при запуске. + +Если ваши фронтенд-файлы создаются позже, например отдельным этапом сборки после создания объекта приложения, установите `check_dir=False`: + +{* ../../docs_src/frontend/tutorial006_py310.py hl[5] *} + +С `check_dir=False` **FastAPI** не будет проверять директорию при создании приложения. Если настроенная директория всё ещё отсутствует во время обработки HTTP-запроса, **FastAPI** вызовет ошибку тогда. + +## Использование с `APIRouter` { #use-it-with-apirouter } + +Вы также можете добавить фронтенд-файлы в `APIRouter` и включить его с префиксом: + +{* ../../docs_src/frontend/tutorial004_py310.py hl[6,7] *} + +В этом примере пути фронтенда отдаются под `/app`. + +Любые обычные *операции пути* в приложении всё равно будут иметь приоритет, включая операции в других роутерах. + +## Только статический результат сборки { #static-build-output-only } + +`app.frontend()` отдаёт файлы, уже сгенерированные сборкой вашего фронтенда. + +Он не запускает server-side rendering. Он предназначен для фронтенд-фреймворков, которые генерируют статические файлы, а не для фреймворков, которым требуется динамический рендеринг на сервере для каждого HTTP-запроса. From bf41b93fafb6540f254edba93a007e79d65c1947 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Wed, 1 Jul 2026 10:31:59 +0000 Subject: [PATCH 339/462] =?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 ede72a33f..ff1efc73a 100644 --- a/docs/en/docs/release-notes.md +++ b/docs/en/docs/release-notes.md @@ -7,6 +7,10 @@ hide: ## Latest Changes +### Translations + +* 🌐 Update translations for ru (add-missing). PR [#15879](https://github.com/fastapi/fastapi/pull/15879) by [@tiangolo](https://github.com/tiangolo). + ### Internal * 👥 Update FastAPI People - Contributors and Translators. PR [#15878](https://github.com/fastapi/fastapi/pull/15878) by [@tiangolo](https://github.com/tiangolo). From 065e7deee4b944684c12a8fa4a808760ff428759 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebasti=C3=A1n=20Ram=C3=ADrez?= Date: Wed, 1 Jul 2026 12:32:25 +0200 Subject: [PATCH 340/462] =?UTF-8?q?=F0=9F=8C=90=20Update=20translations=20?= =?UTF-8?q?for=20de=20(add-missing)=20(#15884)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: github-actions[bot] --- docs/de/docs/tutorial/frontend.md | 133 ++++++++++++++++++++++++++++++ 1 file changed, 133 insertions(+) create mode 100644 docs/de/docs/tutorial/frontend.md diff --git a/docs/de/docs/tutorial/frontend.md b/docs/de/docs/tutorial/frontend.md new file mode 100644 index 000000000..9cd4644d9 --- /dev/null +++ b/docs/de/docs/tutorial/frontend.md @@ -0,0 +1,133 @@ +# Frontend { #frontend } + +Sie können statische Frontend-Apps mit `app.frontend()` (oder `router.frontend()`) bereitstellen. + +Das ist nützlich für Frontend-Tools, die statische Dateien generieren, wie React mit Vite, TanStack Router, Astro, Vue, Svelte, Angular, Solid und andere. + +Mit diesen Tools haben Sie normalerweise einen Schritt, der das Frontend baut, mit einem Befehl wie: + +```bash +npm run build +``` + +Das würde ein Verzeichnis wie `./dist/` mit Ihren Frontend-Dateien generieren. + +Sie können `app.frontend()` verwenden, um dieses Verzeichnis gemäß den Konventionen bereitzustellen, die von diesen Frontend-Frameworks benötigt werden. + +**FastAPI** prüft zuerst *Pfadoperationen*. Die Frontend-Dateien werden nur geprüft, wenn keine normale Route gepasst hat, sodass Ihre API nicht beeinträchtigt wird. + +## Ein Frontend bereitstellen { #serve-a-frontend } + +Nachdem Sie Ihr Frontend gebaut haben, zum Beispiel mit `npm run build`, legen Sie die generierten Dateien in ein Verzeichnis, zum Beispiel `dist`. + +Ihre Projektstruktur könnte so aussehen: + +```text +. +├── pyproject.toml +├── app +│ ├── __init__.py +│ └── main.py +└── dist + ├── index.html + └── assets + └── app.js +``` + +Stellen Sie es dann mit `app.frontend()` bereit: + +{* ../../docs_src/frontend/tutorial001_py310.py hl[5] *} + +Damit kann ein Request für `/assets/app.js` `dist/assets/app.js` ausliefern. + +Wenn Sie außerdem eine **FastAPI**-*Pfadoperation* haben, gewinnt die *Pfadoperation*. + +## Clientseitiges Routing { #client-side-routing } + +Viele Frontend-Apps, einschließlich **Single-Page-Apps** (SPAs), verwenden clientseitiges Routing. Ein Pfad wie `/dashboard/settings` ist möglicherweise keine echte Datei, aber das Framework würde sich darum kümmern, ihn zu handhaben. + +Wenn also direkt auf diese URL zugegriffen wird (statt durch die App zu navigieren), sollte das Backend die Frontend-App von `index.html` bereitstellen, sodass das Frontend-Framework anschließend das clientseitige Routing handhaben kann. + +Verwenden Sie dafür `fallback="index.html"`: + +{* ../../docs_src/frontend/tutorial002_py310.py hl[5] *} + +**FastAPI** verwendet diesen Fallback nur für `GET`- und `HEAD`-Requests, die wie Browser-Navigation aussehen. Fehlende Dateien wie JavaScript, CSS und Bilder geben weiterhin `404` zurück. + +Requests mit anderen Methoden, wie `POST` oder `PUT`, an Pfade, die nur zum Frontend-Fallback passen, geben ebenfalls `404` zurück. Reguläre **FastAPI**-*Pfadoperationen* haben weiterhin eine höhere Priorität als Frontend-Routen. + +/// tip | Tipp + +Standardmäßig hat `fallback` einen Wert von `fallback="auto"`. In den meisten Fällen müssen Sie `fallback` nicht angeben. Lesen Sie weiter unten die Details. + +/// + +Das ist das, was Sie bei vielen Frontend-Apps möchten, die clientseitiges Routing verwenden, zum Beispiel React mit TanStack Router, Vue, Angular, SvelteKit oder Solid. + +## Benutzerdefinierte 404-Seite { #custom-404-page } + +Sie können auch eine statische `404.html`-Seite für fehlende Frontend-Pfade ausliefern: + +{* ../../docs_src/frontend/tutorial003_py310.py hl[5] *} + +Diese Response behält einen Statuscode von `404`. + +In diesem Fall liefert **FastAPI** für fehlende Frontend-Pfade nicht `index.html` aus. Stattdessen wird die Datei `404.html` zurückgegeben. + +/// tip | Tipp + +Standardmäßig hat `fallback` einen Wert von `fallback="auto"`. Damit wird, wenn eine `404.html`-Datei gefunden wird, diese automatisch als Fallback verwendet. + +Sie können das `fallback`-Argument also normalerweise weglassen. + +/// + +Das ist nützlich bei Frontend-Tools, die für jede Seite statische HTML-Dateien generieren, wie Astro. + +## Automatischer Fallback { #fallback-auto } + +Standardmäßig verwendet `app.frontend()` `fallback="auto"`. + +Wenn es im Frontend-Verzeichnis eine `404.html`-Datei gibt, liefern fehlende Frontend-Pfade diese Datei mit dem Statuscode `404` aus. + +Andernfalls, wenn es eine `index.html`-Datei gibt, liefern fehlende Browser-Navigationspfade `index.html` aus, was viele Frontend-Apps mit clientseitigem Routing erwarten. + +In den meisten Fällen können Sie also `app.frontend("/", directory="dist")` verwenden, ohne das `fallback`-Argument anzugeben. + +{* ../../docs_src/frontend/tutorial001_py310.py hl[5] *} + +## Fallback deaktivieren { #disable-fallback } + +Wenn Sie keine Fallback-Datei für fehlende Frontend-Pfade ausliefern möchten, verwenden Sie `fallback=None`: + +{* ../../docs_src/frontend/tutorial005_py310.py hl[5] *} + +Dann geben fehlende Frontend-Pfade das normale `404` zurück. + +## Verzeichnis prüfen { #check-directory } + +Standardmäßig prüft `app.frontend()`, dass das Verzeichnis existiert, wenn die App erstellt wird. + +Das hilft, Konfigurationsfehler früh zu erkennen. Wenn zum Beispiel das Output-Verzeichnis des Frontend-Builds fehlt, löst **FastAPI** beim Startup einen Fehler aus. + +Wenn Ihre Frontend-Dateien später erstellt werden, zum Beispiel durch einen separaten Build-Schritt, nachdem das App-Objekt erstellt wurde, setzen Sie `check_dir=False`: + +{* ../../docs_src/frontend/tutorial006_py310.py hl[5] *} + +Mit `check_dir=False` prüft **FastAPI** das Verzeichnis nicht, wenn die App erstellt wird. Wenn das konfigurierte Verzeichnis beim Verarbeiten eines Requests immer noch fehlt, löst **FastAPI** dann einen Fehler aus. + +## Mit `APIRouter` verwenden { #use-it-with-apirouter } + +Sie können Frontend-Dateien auch zu einem `APIRouter` hinzufügen und ihn mit einem Präfix einbinden: + +{* ../../docs_src/frontend/tutorial004_py310.py hl[6,7] *} + +In diesem Beispiel werden Frontend-Pfade unter `/app` bereitgestellt. + +Alle regulären *Pfadoperationen* in der App haben weiterhin Vorrang, auch in anderen Routern. + +## Nur statischer Build-Output { #static-build-output-only } + +`app.frontend()` liefert Dateien aus, die bereits von Ihrem Frontend-Build generiert wurden. + +Es führt kein serverseitiges Rendering aus. Es ist für Frontend-Frameworks gedacht, die statische Dateien generieren, nicht für Frameworks, die dynamisches Rendering auf dem Server für jeden Request benötigen. From a3aa0703a638886d2a72777a24804f57a54d94ac Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Wed, 1 Jul 2026 10:33:25 +0000 Subject: [PATCH 341/462] =?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 ff1efc73a..f7cb3bb5f 100644 --- a/docs/en/docs/release-notes.md +++ b/docs/en/docs/release-notes.md @@ -9,6 +9,7 @@ hide: ### Translations +* 🌐 Update translations for de (add-missing). PR [#15884](https://github.com/fastapi/fastapi/pull/15884) by [@tiangolo](https://github.com/tiangolo). * 🌐 Update translations for ru (add-missing). PR [#15879](https://github.com/fastapi/fastapi/pull/15879) by [@tiangolo](https://github.com/tiangolo). ### Internal From 241b9a70a89c390195ec1f0ba087d8418987692a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebasti=C3=A1n=20Ram=C3=ADrez?= Date: Wed, 1 Jul 2026 12:34:11 +0200 Subject: [PATCH 342/462] =?UTF-8?q?=F0=9F=8C=90=20Update=20translations=20?= =?UTF-8?q?for=20fr=20(add-missing)=20(#15881)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: github-actions[bot] --- docs/fr/docs/tutorial/frontend.md | 133 ++++++++++++++++++++++++++++++ 1 file changed, 133 insertions(+) create mode 100644 docs/fr/docs/tutorial/frontend.md diff --git a/docs/fr/docs/tutorial/frontend.md b/docs/fr/docs/tutorial/frontend.md new file mode 100644 index 000000000..6adb8a241 --- /dev/null +++ b/docs/fr/docs/tutorial/frontend.md @@ -0,0 +1,133 @@ +# Frontend { #frontend } + +Vous pouvez servir des applications frontend statiques avec `app.frontend()` (ou `router.frontend()`). + +C'est utile pour les outils frontend qui génèrent des fichiers statiques, comme React avec Vite, TanStack Router, Astro, Vue, Svelte, Angular, Solid, et d'autres. + +Avec ces outils, vous avez normalement une étape qui build le frontend, avec une commande comme : + +```bash +npm run build +``` + +Cela générerait un répertoire comme `./dist/` avec vos fichiers frontend. + +Vous pouvez utiliser `app.frontend()` pour servir ce répertoire en suivant les conventions nécessaires à ces frameworks frontend. + +**FastAPI** vérifie d'abord les *chemins d'accès*. Les fichiers frontend ne sont vérifiés que si aucune route normale ne correspond, donc votre API ne sera pas affectée. + +## Servir un frontend { #serve-a-frontend } + +Après avoir build votre frontend, par exemple avec `npm run build`, placez les fichiers générés dans un répertoire, par exemple `dist`. + +La structure de votre projet pourrait ressembler à ceci : + +```text +. +├── pyproject.toml +├── app +│ ├── __init__.py +│ └── main.py +└── dist + ├── index.html + └── assets + └── app.js +``` + +Servez-le ensuite avec `app.frontend()` : + +{* ../../docs_src/frontend/tutorial001_py310.py hl[5] *} + +Avec cela, une requête vers `/assets/app.js` peut servir `dist/assets/app.js`. + +Si vous avez également un *chemin d'accès* **FastAPI**, le *chemin d'accès* est prioritaire. + +## Routage côté client { #client-side-routing } + +De nombreuses applications frontend, y compris les **applications monopages** (SPAs), utilisent le routage côté client. Un chemin comme `/dashboard/settings` peut ne pas être un vrai fichier, mais le framework se chargerait de le gérer. + +Ainsi, si vous accédez directement à cette URL (au lieu de naviguer via l'application), le backend doit servir l'application frontend depuis `index.html`, afin que le framework frontend puisse ensuite gérer le routage côté client. + +Pour cela, utilisez `fallback="index.html"` : + +{* ../../docs_src/frontend/tutorial002_py310.py hl[5] *} + +**FastAPI** utilise ce fallback uniquement pour les requêtes `GET` et `HEAD` qui ressemblent à une navigation de navigateur. Les fichiers manquants comme JavaScript, CSS et les images renvoient toujours `404`. + +Les requêtes avec d'autres méthodes, comme `POST` ou `PUT`, vers des chemins qui ne correspondent qu'au fallback frontend renvoient également `404`. Les *chemins d'accès* **FastAPI** réguliers ont toujours une priorité plus élevée que les routes frontend. + +/// tip | Astuce + +Par défaut, `fallback` a une valeur de `fallback="auto"`. Dans la plupart des cas, vous n'avez pas besoin de spécifier `fallback`. Lisez ci-dessous pour plus de détails. + +/// + +C'est ce que vous souhaitez avec de nombreuses applications frontend qui utilisent le routage côté client, par exemple React avec TanStack Router, Vue, Angular, SvelteKit ou Solid. + +## Page 404 personnalisée { #custom-404-page } + +Vous pouvez également servir une page statique `404.html` pour les chemins frontend manquants : + +{* ../../docs_src/frontend/tutorial003_py310.py hl[5] *} + +Cette réponse conserve un code de statut `404`. + +Dans ce cas, **FastAPI** ne servira pas `index.html` pour les chemins frontend manquants. Il renverra le fichier `404.html` à la place. + +/// tip | Astuce + +Par défaut, `fallback` a une valeur de `fallback="auto"`. Avec cela, si un fichier `404.html` est trouvé, il sera utilisé automatiquement comme fallback. + +Vous pouvez donc normalement omettre l'argument `fallback`. + +/// + +C'est utile avec les outils frontend qui génèrent des fichiers HTML statiques pour chaque page, comme Astro. + +## Fallback automatique { #fallback-auto } + +Par défaut, `app.frontend()` utilise `fallback="auto"`. + +S'il y a un fichier `404.html` dans le répertoire frontend, les chemins frontend manquants servent ce fichier avec le code de statut `404`. + +Sinon, s'il y a un fichier `index.html`, les chemins de navigation de navigateur manquants servent `index.html`, ce qui est attendu par de nombreuses applications frontend avec routage côté client. + +Ainsi, dans la plupart des cas, vous pouvez utiliser `app.frontend("/", directory="dist")` sans spécifier l'argument `fallback`. + +{* ../../docs_src/frontend/tutorial001_py310.py hl[5] *} + +## Désactiver le fallback { #disable-fallback } + +Si vous ne souhaitez pas servir de fichier fallback pour les chemins frontend manquants, utilisez `fallback=None` : + +{* ../../docs_src/frontend/tutorial005_py310.py hl[5] *} + +Les chemins frontend manquants renvoient alors le `404` normal. + +## Vérifier le répertoire { #check-directory } + +Par défaut, `app.frontend()` vérifie que le répertoire existe lorsque l'application est créée. + +Cela permet de détecter tôt les erreurs de configuration. Par exemple, si le répertoire de sortie du build frontend est manquant, **FastAPI** lèvera une erreur au démarrage. + +Si vos fichiers frontend sont créés plus tard, par exemple par une étape de build séparée après la création de l'objet app, définissez `check_dir=False` : + +{* ../../docs_src/frontend/tutorial006_py310.py hl[5] *} + +Avec `check_dir=False`, **FastAPI** ne vérifiera pas le répertoire lorsque l'application est créée. Si le répertoire configuré est toujours manquant lorsqu'une requête est traitée, **FastAPI** lèvera alors une erreur. + +## L'utiliser avec `APIRouter` { #use-it-with-apirouter } + +Vous pouvez également ajouter des fichiers frontend à un `APIRouter` et l'inclure avec un préfixe : + +{* ../../docs_src/frontend/tutorial004_py310.py hl[6,7] *} + +Dans cet exemple, les chemins frontend sont servis sous `/app`. + +Tous les *chemins d'accès* réguliers dans l'application seront toujours prioritaires, y compris dans d'autres routers. + +## Sortie de build statique uniquement { #static-build-output-only } + +`app.frontend()` sert des fichiers déjà générés par votre build frontend. + +Il n'exécute pas de rendu côté serveur. Il est destiné aux frameworks frontend qui génèrent des fichiers statiques, pas aux frameworks qui nécessitent un rendu dynamique sur le serveur pour chaque requête. From c9f99ef24f75e573690d49df2fac8d1b83dcf627 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebasti=C3=A1n=20Ram=C3=ADrez?= Date: Wed, 1 Jul 2026 12:34:51 +0200 Subject: [PATCH 343/462] =?UTF-8?q?=F0=9F=8C=90=20Update=20translations=20?= =?UTF-8?q?for=20uk=20(add-missing)=20(#15886)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: github-actions[bot] --- docs/uk/docs/tutorial/frontend.md | 133 ++++++++++++++++++++++++++++++ 1 file changed, 133 insertions(+) create mode 100644 docs/uk/docs/tutorial/frontend.md diff --git a/docs/uk/docs/tutorial/frontend.md b/docs/uk/docs/tutorial/frontend.md new file mode 100644 index 000000000..c85e6693e --- /dev/null +++ b/docs/uk/docs/tutorial/frontend.md @@ -0,0 +1,133 @@ +# Фронтенд { #frontend } + +Ви можете обслуговувати статичні фронтенд-застосунки за допомогою `app.frontend()` (або `router.frontend()`). + +Це корисно для фронтенд-інструментів, які генерують статичні файли, як-от React з Vite, TanStack Router, Astro, Vue, Svelte, Angular, Solid та інші. + +З такими інструментами зазвичай є крок, який збирає фронтенд, командою на кшталт: + +```bash +npm run build +``` + +Це згенерує директорію на кшталт `./dist/` з вашими фронтенд-файлами. + +Ви можете використати `app.frontend()`, щоб обслуговувати цю директорію відповідно до конвенцій, потрібних цим фронтенд-фреймворкам. + +**FastAPI** спочатку перевіряє *операції шляху*. Фронтенд-файли перевіряються лише тоді, коли жоден звичайний маршрут не збігся, тому ваш API не буде зачеплено. + +## Обслуговування фронтенду { #serve-a-frontend } + +Після збірки вашого фронтенду, наприклад за допомогою `npm run build`, помістіть згенеровані файли в директорію, наприклад `dist`. + +Структура вашого проєкту може виглядати так: + +```text +. +├── pyproject.toml +├── app +│ ├── __init__.py +│ └── main.py +└── dist + ├── index.html + └── assets + └── app.js +``` + +Потім обслуговуйте її за допомогою `app.frontend()`: + +{* ../../docs_src/frontend/tutorial001_py310.py hl[5] *} + +З цим запит до `/assets/app.js` може обслуговувати `dist/assets/app.js`. + +Якщо у вас також є *операція шляху* **FastAPI**, *операція шляху* має пріоритет. + +## Маршрутизація на боці клієнта { #client-side-routing } + +Багато фронтенд-застосунків, включно з **односторінковими застосунками** (SPA), використовують маршрутизацію на боці клієнта. Шлях на кшталт `/dashboard/settings` може не бути реальним файлом, але фреймворк подбає про його обробку. + +Тому, якщо звертатися до цієї URL-адреси напряму (замість навігації через застосунок), бекенд має обслуговувати фронтенд-застосунок з `index.html`, щоб фронтенд-фреймворк потім міг обробити маршрутизацію на боці клієнта. + +Для цього використовуйте `fallback="index.html"`: + +{* ../../docs_src/frontend/tutorial002_py310.py hl[5] *} + +**FastAPI** використовує цей fallback лише для запитів `GET` і `HEAD`, які виглядають як навігація браузера. Відсутні файли, як-от JavaScript, CSS і зображення, все ще повертають `404`. + +Запити з іншими методами, як-от `POST` або `PUT`, до шляхів, що збігаються лише з frontend fallback, також повертають `404`. Звичайні *операції шляху* **FastAPI** все ще мають вищий пріоритет, ніж фронтенд-маршрути. + +/// tip | Порада + +За замовчуванням `fallback` має значення `fallback="auto"`. У більшості випадків вам не потрібно вказувати `fallback`. Деталі читайте нижче. + +/// + +Саме це потрібно для багатьох фронтенд-застосунків, які використовують маршрутизацію на боці клієнта, наприклад React з TanStack Router, Vue, Angular, SvelteKit або Solid. + +## Користувацька сторінка 404 { #custom-404-page } + +Ви також можете обслуговувати статичну сторінку `404.html` для відсутніх фронтенд-шляхів: + +{* ../../docs_src/frontend/tutorial003_py310.py hl[5] *} + +Ця відповідь зберігає код статусу `404`. + +У цьому випадку **FastAPI** не буде обслуговувати `index.html` для відсутніх фронтенд-шляхів. Натомість він поверне файл `404.html`. + +/// tip | Порада + +За замовчуванням `fallback` має значення `fallback="auto"`. З ним, якщо файл `404.html` знайдено, він буде використаний як fallback автоматично. + +Тому зазвичай ви можете не вказувати аргумент `fallback`. + +/// + +Це корисно з фронтенд-інструментами, які генерують статичні HTML-файли для кожної сторінки, як-от Astro. + +## Автоматичний fallback { #fallback-auto } + +За замовчуванням `app.frontend()` використовує `fallback="auto"`. + +Якщо в директорії фронтенду є файл `404.html`, відсутні фронтенд-шляхи обслуговують цей файл з кодом статусу `404`. + +Інакше, якщо є файл `index.html`, відсутні шляхи навігації браузера обслуговують `index.html`, що й очікують багато фронтенд-застосунків з маршрутизацією на боці клієнта. + +Отже, у більшості випадків ви можете використовувати `app.frontend("/", directory="dist")` без вказання аргументу `fallback`. + +{* ../../docs_src/frontend/tutorial001_py310.py hl[5] *} + +## Вимкнення fallback { #disable-fallback } + +Якщо ви не хочете обслуговувати fallback-файл для відсутніх фронтенд-шляхів, використовуйте `fallback=None`: + +{* ../../docs_src/frontend/tutorial005_py310.py hl[5] *} + +Тоді відсутні фронтенд-шляхи повертають звичайний `404`. + +## Перевірка директорії { #check-directory } + +За замовчуванням `app.frontend()` перевіряє, що директорія існує, коли застосунок створюється. + +Це допомагає виявити помилки конфігурації завчасно. Наприклад, якщо директорія вихідних файлів збірки фронтенду відсутня, **FastAPI** викличе помилку під час запуску. + +Якщо ваші фронтенд-файли створюються пізніше, наприклад окремим кроком збірки після створення об'єкта застосунку, встановіть `check_dir=False`: + +{* ../../docs_src/frontend/tutorial006_py310.py hl[5] *} + +З `check_dir=False` **FastAPI** не перевірятиме директорію під час створення застосунку. Якщо налаштована директорія все ще відсутня під час обробки запиту, **FastAPI** викличе помилку тоді. + +## Використання з `APIRouter` { #use-it-with-apirouter } + +Ви також можете додати фронтенд-файли до `APIRouter` і включити його з префіксом: + +{* ../../docs_src/frontend/tutorial004_py310.py hl[6,7] *} + +У цьому прикладі фронтенд-шляхи обслуговуються під `/app`. + +Будь-які звичайні *операції шляху* в застосунку все ще матимуть перевагу, включно з операціями в інших роутерах. + +## Лише статичний результат збірки { #static-build-output-only } + +`app.frontend()` обслуговує файли, вже згенеровані вашою фронтенд-збіркою. + +Він не виконує рендеринг на боці сервера. Він призначений для фронтенд-фреймворків, які генерують статичні файли, а не для фреймворків, що потребують динамічного рендерингу на сервері для кожного запиту. From f3e6899127daf4949b868bd4aa2b8d2515884b36 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Wed, 1 Jul 2026 10:35:54 +0000 Subject: [PATCH 344/462] =?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 f7cb3bb5f..29f94755d 100644 --- a/docs/en/docs/release-notes.md +++ b/docs/en/docs/release-notes.md @@ -9,6 +9,7 @@ hide: ### Translations +* 🌐 Update translations for fr (add-missing). PR [#15881](https://github.com/fastapi/fastapi/pull/15881) by [@tiangolo](https://github.com/tiangolo). * 🌐 Update translations for de (add-missing). PR [#15884](https://github.com/fastapi/fastapi/pull/15884) by [@tiangolo](https://github.com/tiangolo). * 🌐 Update translations for ru (add-missing). PR [#15879](https://github.com/fastapi/fastapi/pull/15879) by [@tiangolo](https://github.com/tiangolo). From 92cf50e546b2ff92c97a0c16cf48370d7b8f23ad Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Wed, 1 Jul 2026 10:36:23 +0000 Subject: [PATCH 345/462] =?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 29f94755d..ea3598e88 100644 --- a/docs/en/docs/release-notes.md +++ b/docs/en/docs/release-notes.md @@ -9,6 +9,7 @@ hide: ### Translations +* 🌐 Update translations for uk (add-missing). PR [#15886](https://github.com/fastapi/fastapi/pull/15886) by [@tiangolo](https://github.com/tiangolo). * 🌐 Update translations for fr (add-missing). PR [#15881](https://github.com/fastapi/fastapi/pull/15881) by [@tiangolo](https://github.com/tiangolo). * 🌐 Update translations for de (add-missing). PR [#15884](https://github.com/fastapi/fastapi/pull/15884) by [@tiangolo](https://github.com/tiangolo). * 🌐 Update translations for ru (add-missing). PR [#15879](https://github.com/fastapi/fastapi/pull/15879) by [@tiangolo](https://github.com/tiangolo). From 75737c19da4b6b4e1e823b7a18cbbbc5d023c3c3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebasti=C3=A1n=20Ram=C3=ADrez?= Date: Wed, 1 Jul 2026 12:37:00 +0200 Subject: [PATCH 346/462] =?UTF-8?q?=F0=9F=8C=90=20Update=20translations=20?= =?UTF-8?q?for=20tr=20(add-missing)=20(#15887)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: github-actions[bot] --- docs/tr/docs/tutorial/frontend.md | 133 ++++++++++++++++++++++++++++++ 1 file changed, 133 insertions(+) create mode 100644 docs/tr/docs/tutorial/frontend.md diff --git a/docs/tr/docs/tutorial/frontend.md b/docs/tr/docs/tutorial/frontend.md new file mode 100644 index 000000000..7918ca593 --- /dev/null +++ b/docs/tr/docs/tutorial/frontend.md @@ -0,0 +1,133 @@ +# Frontend { #frontend } + +Statik frontend uygulamalarını `app.frontend()` (veya `router.frontend()`) ile sunabilirsiniz. + +Bu, Vite ile React, TanStack Router, Astro, Vue, Svelte, Angular, Solid ve benzeri statik dosyalar üreten frontend araçları için kullanışlıdır. + +Bu araçlarda genellikle frontend'i build eden bir adım olur, örneğin şöyle bir komutla: + +```bash +npm run build +``` + +Bu komut, frontend dosyalarınızla birlikte `./dist/` gibi bir dizin oluşturur. + +Bu dizini, frontend framework'lerinin ihtiyaç duyduğu kurallara uygun şekilde sunmak için `app.frontend()` kullanabilirsiniz. + +**FastAPI** önce *path operation*'ları kontrol eder. Frontend dosyaları yalnızca hiçbir normal route eşleşmezse kontrol edilir, bu yüzden API'niz bundan etkilenmez. + +## Frontend Sunma { #serve-a-frontend } + +Frontend'inizi build ettikten sonra, örneğin `npm run build` ile, oluşturulan dosyaları bir dizine koyun; örneğin `dist`. + +Proje yapınız şöyle görünebilir: + +```text +. +├── pyproject.toml +├── app +│ ├── __init__.py +│ └── main.py +└── dist + ├── index.html + └── assets + └── app.js +``` + +Ardından bunu `app.frontend()` ile sunun: + +{* ../../docs_src/frontend/tutorial001_py310.py hl[5] *} + +Böylece `/assets/app.js` için gelen bir request, `dist/assets/app.js` dosyasını sunabilir. + +Aynı zamanda bir **FastAPI** *path operation*'ınız varsa, öncelik *path operation*'dadır. + +## Client-Side Routing { #client-side-routing } + +**Single-page app**'ler (SPA'ler) dahil birçok frontend uygulaması client-side routing kullanır. `/dashboard/settings` gibi bir path gerçek bir dosya olmayabilir; bunu frontend framework'ü ele alır. + +Bu yüzden, o URL'ye doğrudan erişildiğinde (uygulama içinde gezinmek yerine), backend frontend uygulamasını `index.html` üzerinden sunmalıdır. Böylece frontend framework'ü client-side routing'i işleyebilir. + +Bunun için `fallback="index.html"` kullanın: + +{* ../../docs_src/frontend/tutorial002_py310.py hl[5] *} + +**FastAPI** bu fallback'i yalnızca tarayıcı gezinmesi gibi görünen `GET` ve `HEAD` request'leri için kullanır. JavaScript, CSS ve görseller gibi eksik dosyalar yine `404` döndürür. + +`POST` veya `PUT` gibi diğer metotlarla, yalnızca frontend fallback'i ile eşleşen path'lere yapılan request'ler de `404` döndürür. Normal **FastAPI** *path operation*'ları frontend route'larından yine daha yüksek önceliğe sahiptir. + +/// tip | İpucu + +Varsayılan olarak `fallback`, `fallback="auto"` değerine sahiptir. Çoğu durumda `fallback` belirtmeniz gerekmez. Detaylar için aşağıyı okuyun. + +/// + +Client-side routing kullanan birçok frontend uygulamasında istediğiniz davranış budur; örneğin TanStack Router ile React, Vue, Angular, SvelteKit veya Solid. + +## Özel 404 Sayfası { #custom-404-page } + +Bulunamayan frontend path'leri için statik bir `404.html` sayfası da sunabilirsiniz: + +{* ../../docs_src/frontend/tutorial003_py310.py hl[5] *} + +Bu response, `404` status code'unu korur. + +Bu durumda **FastAPI**, bulunamayan frontend path'leri için `index.html` sunmaz. Bunun yerine `404.html` dosyasını döndürür. + +/// tip | İpucu + +Varsayılan olarak `fallback`, `fallback="auto"` değerine sahiptir. Bu durumda bir `404.html` dosyası bulunursa, otomatik olarak fallback olarak kullanılır. + +Bu yüzden normalde `fallback` argümanını atlayabilirsiniz. + +/// + +Bu, Astro gibi her sayfa için statik HTML dosyaları üreten frontend araçlarıyla kullanışlıdır. + +## Otomatik Fallback { #fallback-auto } + +Varsayılan olarak `app.frontend()`, `fallback="auto"` kullanır. + +Frontend dizininde bir `404.html` dosyası varsa, bulunamayan frontend path'leri bu dosyayı `404` status code'u ile sunar. + +Aksi halde bir `index.html` dosyası varsa, bulunamayan tarayıcı gezinme path'leri `index.html` sunar. Client-side routing kullanan birçok frontend uygulamasının beklediği davranış budur. + +Bu yüzden çoğu durumda `fallback` argümanını belirtmeden `app.frontend("/", directory="dist")` kullanabilirsiniz. + +{* ../../docs_src/frontend/tutorial001_py310.py hl[5] *} + +## Fallback'i Devre Dışı Bırakma { #disable-fallback } + +Bulunamayan frontend path'leri için fallback dosyası sunmak istemiyorsanız `fallback=None` kullanın: + +{* ../../docs_src/frontend/tutorial005_py310.py hl[5] *} + +Bundan sonra bulunamayan frontend path'leri normal `404` döndürür. + +## Dizini Kontrol Etme { #check-directory } + +Varsayılan olarak `app.frontend()`, uygulama oluşturulduğunda dizinin var olduğunu kontrol eder. + +Bu, yapılandırma hatalarını erken yakalamaya yardımcı olur. Örneğin frontend build çıktısı dizini yoksa, **FastAPI** başlangıçta hata verir. + +Frontend dosyalarınız daha sonra oluşturuluyorsa, örneğin app nesnesi oluşturulduktan sonra ayrı bir build adımıyla, `check_dir=False` ayarlayın: + +{* ../../docs_src/frontend/tutorial006_py310.py hl[5] *} + +`check_dir=False` ile **FastAPI**, app oluşturulduğunda dizini kontrol etmez. Yapılandırılan dizin bir request işlendiği sırada hâlâ yoksa, **FastAPI** o zaman hata verir. + +## `APIRouter` ile Kullanma { #use-it-with-apirouter } + +Frontend dosyalarını bir `APIRouter`'a da ekleyebilir ve bunu bir prefix ile dahil edebilirsiniz: + +{* ../../docs_src/frontend/tutorial004_py310.py hl[6,7] *} + +Bu örnekte frontend path'leri `/app` altında sunulur. + +Uygulamadaki herhangi bir normal *path operation*, diğer router'larda olanlar dahil, yine öncelikli olur. + +## Yalnızca Statik Build Çıktısı { #static-build-output-only } + +`app.frontend()`, frontend build'iniz tarafından önceden oluşturulmuş dosyaları sunar. + +Server-side rendering çalıştırmaz. Her request için server'da dinamik rendering gerektiren framework'ler için değil, statik dosyalar üreten frontend framework'leri içindir. From f382703ff71b1a45ecbfed754bc3eeb2e70b2902 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Wed, 1 Jul 2026 10:37:33 +0000 Subject: [PATCH 347/462] =?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 ea3598e88..7654aa902 100644 --- a/docs/en/docs/release-notes.md +++ b/docs/en/docs/release-notes.md @@ -9,6 +9,7 @@ hide: ### Translations +* 🌐 Update translations for tr (add-missing). PR [#15887](https://github.com/fastapi/fastapi/pull/15887) by [@tiangolo](https://github.com/tiangolo). * 🌐 Update translations for uk (add-missing). PR [#15886](https://github.com/fastapi/fastapi/pull/15886) by [@tiangolo](https://github.com/tiangolo). * 🌐 Update translations for fr (add-missing). PR [#15881](https://github.com/fastapi/fastapi/pull/15881) by [@tiangolo](https://github.com/tiangolo). * 🌐 Update translations for de (add-missing). PR [#15884](https://github.com/fastapi/fastapi/pull/15884) by [@tiangolo](https://github.com/tiangolo). From 2b0f1561936a31291757304e52cd3ece5c90afd4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebasti=C3=A1n=20Ram=C3=ADrez?= Date: Wed, 1 Jul 2026 12:40:30 +0200 Subject: [PATCH 348/462] =?UTF-8?q?=F0=9F=8C=90=20Update=20translations=20?= =?UTF-8?q?for=20zh=20(add-missing)=20(#15885)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: github-actions[bot] --- docs/zh/docs/tutorial/frontend.md | 133 ++++++++++++++++++++++++++++++ 1 file changed, 133 insertions(+) create mode 100644 docs/zh/docs/tutorial/frontend.md diff --git a/docs/zh/docs/tutorial/frontend.md b/docs/zh/docs/tutorial/frontend.md new file mode 100644 index 000000000..8b57bbe60 --- /dev/null +++ b/docs/zh/docs/tutorial/frontend.md @@ -0,0 +1,133 @@ +# 前端 { #frontend } + +你可以使用 `app.frontend()`(或 `router.frontend()`)来提供静态前端应用。 + +这对会生成静态文件的前端工具很有用,例如使用 Vite 的 React、TanStack Router、Astro、Vue、Svelte、Angular、Solid 等。 + +使用这些工具时,通常会有一个构建前端的步骤,命令类似: + +```bash +npm run build +``` + +它会生成一个类似 `./dist/` 的目录,里面包含你的前端文件。 + +你可以使用 `app.frontend()` 按照这些前端框架所需的约定来提供该目录。 + +**FastAPI** 会先检查*路径操作*。只有在没有普通路由匹配时,才会检查前端文件,因此你的 API 不会受到影响。 + +## 提供前端服务 { #serve-a-frontend } + +构建前端之后,例如使用 `npm run build`,将生成的文件放入一个目录,例如 `dist`。 + +你的项目结构可能如下所示: + +```text +. +├── pyproject.toml +├── app +│ ├── __init__.py +│ └── main.py +└── dist + ├── index.html + └── assets + └── app.js +``` + +然后使用 `app.frontend()` 提供服务: + +{* ../../docs_src/frontend/tutorial001_py310.py hl[5] *} + +这样,对 `/assets/app.js` 的请求可以提供 `dist/assets/app.js`。 + +如果你还有一个 **FastAPI** *路径操作*,则*路径操作*优先。 + +## 客户端路由 { #client-side-routing } + +许多前端应用,包括**单页应用**(SPA),都会使用客户端路由。像 `/dashboard/settings` 这样的路径可能并不是一个真实文件,而是由框架负责处理。 + +因此,如果直接访问该 URL(而不是通过应用内导航访问),后端应该从 `index.html` 提供前端应用,这样前端框架就可以处理客户端路由。 + +为此,使用 `fallback="index.html"`: + +{* ../../docs_src/frontend/tutorial002_py310.py hl[5] *} + +**FastAPI** 只会对看起来像浏览器导航的 `GET` 和 `HEAD` 请求使用此 fallback。缺失的 JavaScript、CSS 和图片等文件仍会返回 `404`。 + +对于其他方法的请求,例如 `POST` 或 `PUT`,如果路径只匹配前端 fallback,也会返回 `404`。常规 **FastAPI** *路径操作*仍然比前端路由具有更高优先级。 + +/// tip | 提示 + +默认情况下,`fallback` 的值为 `fallback="auto"`。在大多数情况下,你不需要指定 `fallback`。详情见下文。 + +/// + +这正是许多使用客户端路由的前端应用所需的行为,例如使用 TanStack Router 的 React、Vue、Angular、SvelteKit 或 Solid。 + +## 自定义 404 页面 { #custom-404-page } + +你也可以为缺失的前端路径提供一个静态 `404.html` 页面: + +{* ../../docs_src/frontend/tutorial003_py310.py hl[5] *} + +该响应会保持 `404` 状态码。 + +在这种情况下,**FastAPI** 不会为缺失的前端路径提供 `index.html`,而是返回 `404.html` 文件。 + +/// tip | 提示 + +默认情况下,`fallback` 的值为 `fallback="auto"`。这样,如果找到 `404.html` 文件,它会自动用作 fallback。 + +因此,通常你可以省略 `fallback` 参数。 + +/// + +这对会为每个页面生成静态 HTML 文件的前端工具很有用,例如 Astro。 + +## 自动 Fallback { #fallback-auto } + +默认情况下,`app.frontend()` 使用 `fallback="auto"`。 + +如果前端目录中存在 `404.html` 文件,缺失的前端路径会以状态码 `404` 提供该文件。 + +否则,如果存在 `index.html` 文件,缺失的浏览器导航路径会提供 `index.html`,这正是许多使用客户端路由的前端应用所期望的行为。 + +因此,在大多数情况下,你可以使用 `app.frontend("/", directory="dist")`,而无需指定 `fallback` 参数。 + +{* ../../docs_src/frontend/tutorial001_py310.py hl[5] *} + +## 禁用 Fallback { #disable-fallback } + +如果你不想为缺失的前端路径提供 fallback 文件,请使用 `fallback=None`: + +{* ../../docs_src/frontend/tutorial005_py310.py hl[5] *} + +这样,缺失的前端路径会返回普通的 `404`。 + +## 检查目录 { #check-directory } + +默认情况下,`app.frontend()` 会在应用创建时检查目录是否存在。 + +这有助于尽早发现配置错误。例如,如果前端构建输出目录缺失,**FastAPI** 会在启动时抛出错误。 + +如果你的前端文件会稍后创建,例如在应用对象创建之后由单独的构建步骤创建,请设置 `check_dir=False`: + +{* ../../docs_src/frontend/tutorial006_py310.py hl[5] *} + +使用 `check_dir=False` 时,**FastAPI** 不会在应用创建时检查目录。如果在处理请求时配置的目录仍然缺失,**FastAPI** 会在那时抛出错误。 + +## 与 `APIRouter` 一起使用 { #use-it-with-apirouter } + +你也可以将前端文件添加到一个 `APIRouter`,并使用前缀包含它: + +{* ../../docs_src/frontend/tutorial004_py310.py hl[6,7] *} + +在这个示例中,前端路径会在 `/app` 下提供服务。 + +应用中的任何常规*路径操作*仍会优先,包括其他 router 中的路径操作。 + +## 仅限静态构建输出 { #static-build-output-only } + +`app.frontend()` 提供的是你的前端构建已经生成的文件。 + +它不会运行服务端渲染。它适用于生成静态文件的前端框架,而不适用于需要在服务器上为每个请求进行动态渲染的框架。 From 0982d3c2ae1059adcf64a2ec51a41e96c891bbd7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebasti=C3=A1n=20Ram=C3=ADrez?= Date: Wed, 1 Jul 2026 12:41:19 +0200 Subject: [PATCH 349/462] =?UTF-8?q?=F0=9F=8C=90=20Update=20translations=20?= =?UTF-8?q?for=20ja=20(add-missing)=20(#15882)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: github-actions[bot] --- docs/ja/docs/tutorial/frontend.md | 133 ++++++++++++++++++++++++++++++ 1 file changed, 133 insertions(+) create mode 100644 docs/ja/docs/tutorial/frontend.md diff --git a/docs/ja/docs/tutorial/frontend.md b/docs/ja/docs/tutorial/frontend.md new file mode 100644 index 000000000..facbbc1d1 --- /dev/null +++ b/docs/ja/docs/tutorial/frontend.md @@ -0,0 +1,133 @@ +# フロントエンド { #frontend } + +`app.frontend()`(または `router.frontend()`)で静的なフロントエンドアプリを配信できます。 + +これは、Vite を使った React、TanStack Router、Astro、Vue、Svelte、Angular、Solid など、静的ファイルを生成するフロントエンドツールで役立ちます。 + +これらのツールでは、通常、次のようなコマンドでフロントエンドをビルドするステップがあります。 + +```bash +npm run build +``` + +これにより、フロントエンドファイルを含む `./dist/` のようなディレクトリが生成されます。 + +`app.frontend()` を使うと、これらのフロントエンドフレームワークが必要とする規約に従って、そのディレクトリを配信できます。 + +**FastAPI** は最初に *path operations* をチェックします。通常のルートに一致しなかった場合にのみフロントエンドファイルがチェックされるため、API には影響しません。 + +## フロントエンドの配信 { #serve-a-frontend } + +たとえば `npm run build` でフロントエンドをビルドした後、生成されたファイルを `dist` などのディレクトリに配置します。 + +プロジェクト構成は次のようになります。 + +```text +. +├── pyproject.toml +├── app +│ ├── __init__.py +│ └── main.py +└── dist + ├── index.html + └── assets + └── app.js +``` + +そして `app.frontend()` で配信します。 + +{* ../../docs_src/frontend/tutorial001_py310.py hl[5] *} + +これにより、`/assets/app.js` へのリクエストで `dist/assets/app.js` を配信できます。 + +**FastAPI** の *path operation* もある場合は、*path operation* が優先されます。 + +## クライアントサイドルーティング { #client-side-routing } + +**single-page apps**(SPA)を含む多くのフロントエンドアプリは、クライアントサイドルーティングを使います。`/dashboard/settings` のようなパスは実際のファイルではなく、フレームワークが処理するものかもしれません。 + +そのため、その URL に直接アクセスした場合(アプリ内で遷移するのではなく)、バックエンドは `index.html` からフロントエンドアプリを配信し、フロントエンドフレームワークがクライアントサイドルーティングを処理できるようにする必要があります。 + +そのためには、`fallback="index.html"` を使います。 + +{* ../../docs_src/frontend/tutorial002_py310.py hl[5] *} + +**FastAPI** は、このフォールバックをブラウザのナビゲーションに見える `GET` および `HEAD` リクエストにのみ使用します。JavaScript、CSS、画像などの存在しないファイルは引き続き `404` を返します。 + +`POST` や `PUT` など、他のメソッドのリクエストがフロントエンドのフォールバックにのみ一致するパスへ送られた場合も、`404` を返します。通常の **FastAPI** の *path operations* は、フロントエンドのルートよりも引き続き高い優先順位を持ちます。 + +/// tip | 豆知識 + +デフォルトでは、`fallback` の値は `fallback="auto"` です。ほとんどの場合、`fallback` を指定する必要はありません。詳細は以下を参照してください。 + +/// + +これは、TanStack Router を使った React、Vue、Angular、SvelteKit、Solid など、クライアントサイドルーティングを使う多くのフロントエンドアプリで望まれる動作です。 + +## カスタム 404 ページ { #custom-404-page } + +存在しないフロントエンドパスに対して、静的な `404.html` ページを配信することもできます。 + +{* ../../docs_src/frontend/tutorial003_py310.py hl[5] *} + +そのレスポンスはステータスコード `404` を保持します。 + +この場合、**FastAPI** は存在しないフロントエンドパスに対して `index.html` を配信しません。代わりに `404.html` ファイルを返します。 + +/// tip | 豆知識 + +デフォルトでは、`fallback` の値は `fallback="auto"` です。これにより、`404.html` ファイルが見つかった場合、自動的にフォールバックとして使われます。 + +そのため、通常は `fallback` 引数を省略できます。 + +/// + +これは、Astro のように各ページの静的 HTML ファイルを生成するフロントエンドツールで役立ちます。 + +## 自動フォールバック { #fallback-auto } + +デフォルトでは、`app.frontend()` は `fallback="auto"` を使います。 + +フロントエンドディレクトリに `404.html` ファイルがある場合、存在しないフロントエンドパスはそのファイルをステータスコード `404` で配信します。 + +そうでない場合、`index.html` ファイルがあれば、存在しないブラウザナビゲーションのパスは `index.html` を配信します。これは、クライアントサイドルーティングを使う多くのフロントエンドアプリが期待する動作です。 + +そのため、ほとんどの場合、`fallback` 引数を指定せずに `app.frontend("/", directory="dist")` を使用できます。 + +{* ../../docs_src/frontend/tutorial001_py310.py hl[5] *} + +## フォールバックの無効化 { #disable-fallback } + +存在しないフロントエンドパスに対してフォールバックファイルを配信したくない場合は、`fallback=None` を使います。 + +{* ../../docs_src/frontend/tutorial005_py310.py hl[5] *} + +すると、存在しないフロントエンドパスは通常の `404` を返します。 + +## ディレクトリのチェック { #check-directory } + +デフォルトでは、`app.frontend()` はアプリ作成時にディレクトリが存在することをチェックします。 + +これにより、設定エラーを早期に検出できます。たとえば、フロントエンドのビルド出力ディレクトリが存在しない場合、**FastAPI** は起動時にエラーを発生させます。 + +アプリオブジェクトの作成後に別のビルドステップなどでフロントエンドファイルが作成される場合は、`check_dir=False` を設定します。 + +{* ../../docs_src/frontend/tutorial006_py310.py hl[5] *} + +`check_dir=False` を指定すると、**FastAPI** はアプリ作成時にディレクトリをチェックしません。リクエストが処理される時点で設定されたディレクトリがまだ存在しない場合、**FastAPI** はその時点でエラーを発生させます。 + +## `APIRouter` での使用 { #use-it-with-apirouter } + +フロントエンドファイルを `APIRouter` に追加し、prefix 付きで include することもできます。 + +{* ../../docs_src/frontend/tutorial004_py310.py hl[6,7] *} + +この例では、フロントエンドのパスは `/app` 配下で配信されます。 + +他の router 内のものを含め、アプリ内の通常の *path operations* は引き続き優先されます。 + +## 静的ビルド出力のみ { #static-build-output-only } + +`app.frontend()` は、フロントエンドのビルドで既に生成されたファイルを配信します。 + +server-side rendering は実行しません。これは静的ファイルを生成するフロントエンドフレームワーク向けであり、各リクエストごとにサーバー上で動的レンダリングを必要とするフレームワーク向けではありません。 From 65fd47ffa0077da9760d4ee1d51eeceda4a6dc0f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebasti=C3=A1n=20Ram=C3=ADrez?= Date: Wed, 1 Jul 2026 12:42:52 +0200 Subject: [PATCH 350/462] =?UTF-8?q?=F0=9F=8C=90=20Update=20translations=20?= =?UTF-8?q?for=20pt=20(add-missing)=20(#15883)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: github-actions[bot] --- docs/pt/docs/tutorial/frontend.md | 133 ++++++++++++++++++++++++++++++ 1 file changed, 133 insertions(+) create mode 100644 docs/pt/docs/tutorial/frontend.md diff --git a/docs/pt/docs/tutorial/frontend.md b/docs/pt/docs/tutorial/frontend.md new file mode 100644 index 000000000..872c32e9e --- /dev/null +++ b/docs/pt/docs/tutorial/frontend.md @@ -0,0 +1,133 @@ +# Frontend { #frontend } + +Você pode servir aplicações frontend estáticas com `app.frontend()` ou `router.frontend()`. + +Isso é útil para ferramentas de frontend que geram arquivos estáticos, como React com Vite, TanStack Router, Astro, Vue, Svelte, Angular, Solid e outras. + +Com essas ferramentas, normalmente há uma etapa que faz o build do frontend, com um comando como: + +```bash +npm run build +``` + +Isso geraria um diretório como `./dist/` com seus arquivos de frontend. + +Você pode usar `app.frontend()` para servir esse diretório seguindo as convenções necessárias por esses frameworks de frontend. + +**FastAPI** verifica as *operações de rota* primeiro. Os arquivos de frontend são verificados somente se nenhuma rota normal corresponder, então sua API não será afetada. + +## Sirva um Frontend { #serve-a-frontend } + +Depois de fazer o build do seu frontend, por exemplo com `npm run build`, coloque os arquivos gerados em um diretório, por exemplo, `dist`. + +A estrutura do seu projeto poderia ser assim: + +```text +. +├── pyproject.toml +├── app +│ ├── __init__.py +│ └── main.py +└── dist + ├── index.html + └── assets + └── app.js +``` + +Então sirva-o com `app.frontend()`: + +{* ../../docs_src/frontend/tutorial001_py310.py hl[5] *} + +Com isso, um request para `/assets/app.js` pode servir `dist/assets/app.js`. + +Se você também tiver uma *operação de rota* do **FastAPI**, a *operação de rota* tem prioridade. + +## Roteamento no Lado do Cliente { #client-side-routing } + +Muitas aplicações frontend, incluindo **aplicações de página única** (SPAs), usam roteamento no lado do cliente. Um path como `/dashboard/settings` pode não ser um arquivo real, mas o framework cuidaria de lidar com ele. + +Então, ao acessar essa URL diretamente (em vez de navegar pela aplicação), o backend deveria servir a aplicação frontend a partir de `index.html`, para que o framework de frontend possa então lidar com o roteamento no lado do cliente. + +Para isso, use `fallback="index.html"`: + +{* ../../docs_src/frontend/tutorial002_py310.py hl[5] *} + +**FastAPI** usa esse fallback somente para requests `GET` e `HEAD` que parecem navegação do navegador. Arquivos ausentes como JavaScript, CSS e imagens ainda retornam `404`. + +Requests com outros métodos, como `POST` ou `PUT`, para paths que correspondem apenas ao fallback do frontend também retornam `404`. *Operações de rota* regulares do **FastAPI** ainda têm prioridade maior que rotas de frontend. + +/// tip | Dica + +Por padrão, `fallback` tem o valor `fallback="auto"`. Na maioria dos casos, você não precisará especificar `fallback`. Leia abaixo para detalhes. + +/// + +Isso é o que você desejaria com muitas aplicações frontend que usam roteamento no lado do cliente, por exemplo, React com TanStack Router, Vue, Angular, SvelteKit ou Solid. + +## Página 404 Personalizada { #custom-404-page } + +Você também pode servir uma página estática `404.html` para paths de frontend ausentes: + +{* ../../docs_src/frontend/tutorial003_py310.py hl[5] *} + +Essa response mantém um código de status `404`. + +Neste caso, **FastAPI** não servirá `index.html` para paths de frontend ausentes. Ele retornará o arquivo `404.html` em vez disso. + +/// tip | Dica + +Por padrão, `fallback` tem o valor `fallback="auto"`. Com isso, se um arquivo `404.html` for encontrado, ele será usado automaticamente como fallback. + +Então, normalmente você pode omitir o argumento `fallback`. + +/// + +Isso é útil com ferramentas de frontend que geram arquivos HTML estáticos para cada página, como Astro. + +## Fallback Automático { #fallback-auto } + +Por padrão, `app.frontend()` usa `fallback="auto"`. + +Se houver um arquivo `404.html` no diretório do frontend, paths de frontend ausentes servem esse arquivo com código de status `404`. + +Caso contrário, se houver um arquivo `index.html`, paths de navegação do navegador ausentes servem `index.html`, que é o que muitas aplicações frontend com roteamento no lado do cliente esperam. + +Então, na maioria dos casos, você pode usar `app.frontend("/", directory="dist")` sem especificar o argumento `fallback`. + +{* ../../docs_src/frontend/tutorial001_py310.py hl[5] *} + +## Desative o Fallback { #disable-fallback } + +Se você não quiser servir um arquivo de fallback para paths de frontend ausentes, use `fallback=None`: + +{* ../../docs_src/frontend/tutorial005_py310.py hl[5] *} + +Então paths de frontend ausentes retornam o `404` normal. + +## Verifique o Diretório { #check-directory } + +Por padrão, `app.frontend()` verifica se o diretório existe quando a aplicação é criada. + +Isso ajuda a identificar erros de configuração cedo. Por exemplo, se o diretório de saída do build do frontend estiver ausente, **FastAPI** gerará um erro na inicialização. + +Se seus arquivos de frontend forem criados depois, por exemplo por uma etapa de build separada após o objeto da aplicação ser criado, defina `check_dir=False`: + +{* ../../docs_src/frontend/tutorial006_py310.py hl[5] *} + +Com `check_dir=False`, **FastAPI** não verificará o diretório quando a aplicação for criada. Se o diretório configurado ainda estiver ausente quando um request for processado, **FastAPI** gerará um erro nesse momento. + +## Use com `APIRouter` { #use-it-with-apirouter } + +Você também pode adicionar arquivos de frontend a um `APIRouter` e incluí-lo com um prefixo: + +{* ../../docs_src/frontend/tutorial004_py310.py hl[6,7] *} + +Neste exemplo, os paths de frontend são servidos em `/app`. + +Quaisquer *operações de rota* regulares na aplicação ainda terão precedência, inclusive em outros routers. + +## Apenas Saída de Build Estático { #static-build-output-only } + +`app.frontend()` serve arquivos já gerados pelo build do seu frontend. + +Ele não executa renderização no lado do servidor. Ele é para frameworks de frontend que geram arquivos estáticos, não para frameworks que precisam de renderização dinâmica no servidor para cada request. From 7a79b7e9fb4afa0ee10ccf0bdc800f56adda8732 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Wed, 1 Jul 2026 10:43:20 +0000 Subject: [PATCH 351/462] =?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 7654aa902..a7ed8f122 100644 --- a/docs/en/docs/release-notes.md +++ b/docs/en/docs/release-notes.md @@ -9,6 +9,7 @@ hide: ### Translations +* 🌐 Update translations for ja (add-missing). PR [#15882](https://github.com/fastapi/fastapi/pull/15882) by [@tiangolo](https://github.com/tiangolo). * 🌐 Update translations for tr (add-missing). PR [#15887](https://github.com/fastapi/fastapi/pull/15887) by [@tiangolo](https://github.com/tiangolo). * 🌐 Update translations for uk (add-missing). PR [#15886](https://github.com/fastapi/fastapi/pull/15886) by [@tiangolo](https://github.com/tiangolo). * 🌐 Update translations for fr (add-missing). PR [#15881](https://github.com/fastapi/fastapi/pull/15881) by [@tiangolo](https://github.com/tiangolo). From eaace7a13e787e8fab3822165adbef36d21675dd Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Wed, 1 Jul 2026 10:43:23 +0000 Subject: [PATCH 352/462] =?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 a7ed8f122..e69546138 100644 --- a/docs/en/docs/release-notes.md +++ b/docs/en/docs/release-notes.md @@ -9,6 +9,7 @@ hide: ### Translations +* 🌐 Update translations for zh (add-missing). PR [#15885](https://github.com/fastapi/fastapi/pull/15885) by [@tiangolo](https://github.com/tiangolo). * 🌐 Update translations for ja (add-missing). PR [#15882](https://github.com/fastapi/fastapi/pull/15882) by [@tiangolo](https://github.com/tiangolo). * 🌐 Update translations for tr (add-missing). PR [#15887](https://github.com/fastapi/fastapi/pull/15887) by [@tiangolo](https://github.com/tiangolo). * 🌐 Update translations for uk (add-missing). PR [#15886](https://github.com/fastapi/fastapi/pull/15886) by [@tiangolo](https://github.com/tiangolo). From 78154e85a620556722d0b9318b61d7ba4a222c4d Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Wed, 1 Jul 2026 10:43:39 +0000 Subject: [PATCH 353/462] =?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 e69546138..ef2abfd68 100644 --- a/docs/en/docs/release-notes.md +++ b/docs/en/docs/release-notes.md @@ -9,6 +9,7 @@ hide: ### Translations +* 🌐 Update translations for pt (add-missing). PR [#15883](https://github.com/fastapi/fastapi/pull/15883) by [@tiangolo](https://github.com/tiangolo). * 🌐 Update translations for zh (add-missing). PR [#15885](https://github.com/fastapi/fastapi/pull/15885) by [@tiangolo](https://github.com/tiangolo). * 🌐 Update translations for ja (add-missing). PR [#15882](https://github.com/fastapi/fastapi/pull/15882) by [@tiangolo](https://github.com/tiangolo). * 🌐 Update translations for tr (add-missing). PR [#15887](https://github.com/fastapi/fastapi/pull/15887) by [@tiangolo](https://github.com/tiangolo). From 4011c1231827ae472ff35545b7fe1e32be4ba570 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebasti=C3=A1n=20Ram=C3=ADrez?= Date: Wed, 1 Jul 2026 12:43:53 +0200 Subject: [PATCH 354/462] =?UTF-8?q?=F0=9F=8C=90=20Update=20translations=20?= =?UTF-8?q?for=20zh-hant=20(add-missing)=20(#15889)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: github-actions[bot] --- docs/zh-hant/docs/tutorial/frontend.md | 133 +++++++++++++++++++++++++ 1 file changed, 133 insertions(+) create mode 100644 docs/zh-hant/docs/tutorial/frontend.md diff --git a/docs/zh-hant/docs/tutorial/frontend.md b/docs/zh-hant/docs/tutorial/frontend.md new file mode 100644 index 000000000..0c568b9f5 --- /dev/null +++ b/docs/zh-hant/docs/tutorial/frontend.md @@ -0,0 +1,133 @@ +# 前端 { #frontend } + +你可以使用 `app.frontend()`(或 `router.frontend()`)來提供靜態前端應用程式。 + +這對會產生靜態檔案的前端工具很有用,例如搭配 Vite 的 React、TanStack Router、Astro、Vue、Svelte、Angular、Solid 等。 + +使用這些工具時,你通常會有一個建置前端的步驟,使用像這樣的指令: + +```bash +npm run build +``` + +那會產生像 `./dist/` 這樣的目錄,裡面包含你的前端檔案。 + +你可以使用 `app.frontend()` 依照這些前端框架所需的慣例來提供該目錄。 + +**FastAPI** 會先檢查*路徑操作*。只有在沒有一般路由符合時,才會檢查前端檔案,因此你的 API 不會受到影響。 + +## 提供前端 { #serve-a-frontend } + +在建置前端之後,例如使用 `npm run build`,將產生的檔案放在某個目錄中,例如 `dist`。 + +你的專案結構可能如下: + +```text +. +├── pyproject.toml +├── app +│ ├── __init__.py +│ └── main.py +└── dist + ├── index.html + └── assets + └── app.js +``` + +然後使用 `app.frontend()` 來提供它: + +{* ../../docs_src/frontend/tutorial001_py310.py hl[5] *} + +如此一來,對 `/assets/app.js` 的請求就可以提供 `dist/assets/app.js`。 + +如果你也有 **FastAPI** *路徑操作*,則*路徑操作*會優先。 + +## 用戶端路由 { #client-side-routing } + +許多前端應用程式,包括 **single-page apps**(SPAs),都會使用用戶端路由。像 `/dashboard/settings` 這樣的路徑可能不是真實檔案,而是由框架負責處理。 + +因此,如果直接存取該 URL(而不是透過應用程式內導覽),後端應該從 `index.html` 提供前端應用程式,讓前端框架接著處理用戶端路由。 + +為此,請使用 `fallback="index.html"`: + +{* ../../docs_src/frontend/tutorial002_py310.py hl[5] *} + +**FastAPI** 只會對看起來像瀏覽器導覽的 `GET` 和 `HEAD` 請求使用這個 fallback。遺失的檔案,例如 JavaScript、CSS 和圖片,仍會回傳 `404`。 + +對於只符合前端 fallback 的路徑,使用其他方法的請求,例如 `POST` 或 `PUT`,也會回傳 `404`。一般的 **FastAPI** *路徑操作*仍然比前端路由有更高優先順序。 + +/// tip + +預設情況下,`fallback` 的值是 `fallback="auto"`。在大多數情況下,你不需要指定 `fallback`。請閱讀下方內容以了解詳細資訊。 + +/// + +這正是許多使用用戶端路由的前端應用程式所需要的行為,例如搭配 TanStack Router 的 React、Vue、Angular、SvelteKit 或 Solid。 + +## 自訂 404 頁面 { #custom-404-page } + +你也可以為遺失的前端路徑提供靜態 `404.html` 頁面: + +{* ../../docs_src/frontend/tutorial003_py310.py hl[5] *} + +該回應會保留 `404` 狀態碼。 + +在這種情況下,**FastAPI** 不會為遺失的前端路徑提供 `index.html`。它會改為回傳 `404.html` 檔案。 + +/// tip + +預設情況下,`fallback` 的值是 `fallback="auto"`。如此一來,如果找到 `404.html` 檔案,就會自動將其用作 fallback。 + +因此,你通常可以省略 `fallback` 引數。 + +/// + +這對會為每個頁面產生靜態 HTML 檔案的前端工具很有用,例如 Astro。 + +## 自動 Fallback { #fallback-auto } + +預設情況下,`app.frontend()` 會使用 `fallback="auto"`。 + +如果前端目錄中有 `404.html` 檔案,遺失的前端路徑會提供該檔案,並使用狀態碼 `404`。 + +否則,如果有 `index.html` 檔案,遺失的瀏覽器導覽路徑會提供 `index.html`,這正是許多使用用戶端路由的前端應用程式所預期的行為。 + +因此,在大多數情況下,你可以使用 `app.frontend("/", directory="dist")`,而不需要指定 `fallback` 引數。 + +{* ../../docs_src/frontend/tutorial001_py310.py hl[5] *} + +## 停用 Fallback { #disable-fallback } + +如果你不想為遺失的前端路徑提供 fallback 檔案,請使用 `fallback=None`: + +{* ../../docs_src/frontend/tutorial005_py310.py hl[5] *} + +接著,遺失的前端路徑會回傳一般的 `404`。 + +## 檢查目錄 { #check-directory } + +預設情況下,`app.frontend()` 會在建立應用程式時檢查目錄是否存在。 + +這有助於及早發現設定錯誤。例如,如果缺少前端建置輸出目錄,**FastAPI** 會在啟動時引發錯誤。 + +如果你的前端檔案稍後才會建立,例如在建立 app 物件之後由另一個建置步驟產生,請設定 `check_dir=False`: + +{* ../../docs_src/frontend/tutorial006_py310.py hl[5] *} + +使用 `check_dir=False` 時,**FastAPI** 不會在建立應用程式時檢查目錄。如果在處理請求時,設定的目錄仍然不存在,**FastAPI** 會在那時引發錯誤。 + +## 與 `APIRouter` 搭配使用 { #use-it-with-apirouter } + +你也可以將前端檔案加入 `APIRouter`,並使用前綴包含它: + +{* ../../docs_src/frontend/tutorial004_py310.py hl[6,7] *} + +在這個範例中,前端路徑會在 `/app` 底下提供。 + +應用程式中的任何一般*路徑操作*仍會優先,包括其他 router 中的路徑操作。 + +## 僅限靜態建置輸出 { #static-build-output-only } + +`app.frontend()` 會提供你的前端建置已經產生的檔案。 + +它不會執行 server-side rendering。它適用於會產生靜態檔案的前端框架,不適用於需要在伺服器上為每個請求進行動態 rendering 的框架。 From 2c4f3e3ece230410893471e66dac68b26b4c915a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebasti=C3=A1n=20Ram=C3=ADrez?= Date: Wed, 1 Jul 2026 12:44:10 +0200 Subject: [PATCH 355/462] =?UTF-8?q?=F0=9F=8C=90=20Update=20translations=20?= =?UTF-8?q?for=20ko=20(add-missing)=20(#15888)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: github-actions[bot] --- docs/ko/docs/tutorial/frontend.md | 133 ++++++++++++++++++++++++++++++ 1 file changed, 133 insertions(+) create mode 100644 docs/ko/docs/tutorial/frontend.md diff --git a/docs/ko/docs/tutorial/frontend.md b/docs/ko/docs/tutorial/frontend.md new file mode 100644 index 000000000..50149432c --- /dev/null +++ b/docs/ko/docs/tutorial/frontend.md @@ -0,0 +1,133 @@ +# 프론트엔드 { #frontend } + +`app.frontend()`(또는 `router.frontend()`)로 정적 프론트엔드 애플리케이션을 제공할 수 있습니다. + +이는 Vite를 사용하는 React, TanStack Router, Astro, Vue, Svelte, Angular, Solid 등과 같이 정적 파일을 생성하는 프론트엔드 도구에 유용합니다. + +이러한 도구에서는 보통 다음과 같은 명령어로 프론트엔드를 빌드하는 단계가 있습니다: + +```bash +npm run build +``` + +그러면 프론트엔드 파일이 들어 있는 `./dist/` 같은 디렉터리가 생성됩니다. + +`app.frontend()`를 사용하면 이러한 프론트엔드 프레임워크에 필요한 규칙에 따라 해당 디렉터리를 제공할 수 있습니다. + +**FastAPI**는 먼저 *경로 처리*를 확인합니다. 프론트엔드 파일은 일반 라우트와 매칭되지 않는 경우에만 확인되므로, API에는 영향을 주지 않습니다. + +## 프론트엔드 제공하기 { #serve-a-frontend } + +예를 들어 `npm run build`로 프론트엔드를 빌드한 후, 생성된 파일을 `dist` 같은 디렉터리에 넣습니다. + +프로젝트 구조는 다음과 같을 수 있습니다: + +```text +. +├── pyproject.toml +├── app +│ ├── __init__.py +│ └── main.py +└── dist + ├── index.html + └── assets + └── app.js +``` + +그런 다음 `app.frontend()`로 제공합니다: + +{* ../../docs_src/frontend/tutorial001_py310.py hl[5] *} + +이렇게 하면 `/assets/app.js`에 대한 요청이 `dist/assets/app.js`를 제공할 수 있습니다. + +**FastAPI** *경로 처리*도 있다면, *경로 처리*가 우선합니다. + +## 클라이언트 사이드 라우팅 { #client-side-routing } + +**single-page apps**(SPAs)를 포함한 많은 프론트엔드 애플리케이션은 클라이언트 사이드 라우팅을 사용합니다. `/dashboard/settings` 같은 경로는 실제 파일이 아닐 수 있지만, 프레임워크가 이를 처리합니다. + +따라서 해당 URL에 직접 접근하는 경우(애플리케이션 안에서 탐색하는 대신), 백엔드는 `index.html`에서 프론트엔드 애플리케이션을 제공해야 합니다. 그러면 프론트엔드 프레임워크가 클라이언트 사이드 라우팅을 처리할 수 있습니다. + +이를 위해 `fallback="index.html"`을 사용합니다: + +{* ../../docs_src/frontend/tutorial002_py310.py hl[5] *} + +**FastAPI**는 브라우저 탐색처럼 보이는 `GET` 및 `HEAD` 요청에만 이 fallback을 사용합니다. JavaScript, CSS, 이미지처럼 누락된 파일은 여전히 `404`를 반환합니다. + +`POST`나 `PUT` 같은 다른 메서드의 요청이 프론트엔드 fallback에만 매칭되는 경로로 들어와도 `404`를 반환합니다. 일반 **FastAPI** *경로 처리*는 여전히 프론트엔드 라우트보다 높은 우선순위를 가집니다. + +/// tip | 팁 + +기본적으로 `fallback`은 `fallback="auto"` 값을 가집니다. 대부분의 경우 `fallback`을 지정할 필요가 없습니다. 자세한 내용은 아래를 읽어보세요. + +/// + +이는 클라이언트 사이드 라우팅을 사용하는 많은 프론트엔드 애플리케이션에서 원하는 동작입니다. 예를 들어 TanStack Router를 사용하는 React, Vue, Angular, SvelteKit, Solid 등이 있습니다. + +## 사용자 정의 404 페이지 { #custom-404-page } + +누락된 프론트엔드 경로에 대해 정적 `404.html` 페이지를 제공할 수도 있습니다: + +{* ../../docs_src/frontend/tutorial003_py310.py hl[5] *} + +이 응답은 `404` 상태 코드를 유지합니다. + +이 경우 **FastAPI**는 누락된 프론트엔드 경로에 대해 `index.html`을 제공하지 않습니다. 대신 `404.html` 파일을 반환합니다. + +/// tip | 팁 + +기본적으로 `fallback`은 `fallback="auto"` 값을 가집니다. 이를 사용하면 `404.html` 파일이 발견될 경우 자동으로 fallback으로 사용됩니다. + +따라서 일반적으로 `fallback` 인자를 생략할 수 있습니다. + +/// + +이는 Astro처럼 각 페이지에 대한 정적 HTML 파일을 생성하는 프론트엔드 도구에 유용합니다. + +## Fallback 자동 설정 { #fallback-auto } + +기본적으로 `app.frontend()`는 `fallback="auto"`를 사용합니다. + +프론트엔드 디렉터리에 `404.html` 파일이 있으면, 누락된 프론트엔드 경로는 상태 코드 `404`와 함께 해당 파일을 제공합니다. + +그렇지 않고 `index.html` 파일이 있으면, 누락된 브라우저 탐색 경로는 `index.html`을 제공합니다. 이는 클라이언트 사이드 라우팅을 사용하는 많은 프론트엔드 애플리케이션이 기대하는 동작입니다. + +따라서 대부분의 경우 `fallback` 인자를 지정하지 않고 `app.frontend("/", directory="dist")`를 사용할 수 있습니다. + +{* ../../docs_src/frontend/tutorial001_py310.py hl[5] *} + +## Fallback 비활성화 { #disable-fallback } + +누락된 프론트엔드 경로에 대해 fallback 파일을 제공하고 싶지 않다면 `fallback=None`을 사용합니다: + +{* ../../docs_src/frontend/tutorial005_py310.py hl[5] *} + +그러면 누락된 프론트엔드 경로는 일반 `404`를 반환합니다. + +## 디렉터리 확인하기 { #check-directory } + +기본적으로 `app.frontend()`는 애플리케이션이 생성될 때 디렉터리가 존재하는지 확인합니다. + +이는 설정 오류를 일찍 발견하는 데 도움이 됩니다. 예를 들어 프론트엔드 빌드 출력 디렉터리가 없다면 **FastAPI**는 시작 시 오류를 발생시킵니다. + +프론트엔드 파일이 나중에 생성된다면, 예를 들어 애플리케이션 객체가 생성된 후 별도의 빌드 단계에서 생성된다면, `check_dir=False`를 설정합니다: + +{* ../../docs_src/frontend/tutorial006_py310.py hl[5] *} + +`check_dir=False`를 사용하면 **FastAPI**는 애플리케이션이 생성될 때 디렉터리를 확인하지 않습니다. 요청이 처리될 때 설정된 디렉터리가 여전히 없다면, 그때 **FastAPI**가 오류를 발생시킵니다. + +## `APIRouter`와 함께 사용하기 { #use-it-with-apirouter } + +프론트엔드 파일을 `APIRouter`에 추가하고 prefix와 함께 포함할 수도 있습니다: + +{* ../../docs_src/frontend/tutorial004_py310.py hl[6,7] *} + +이 예제에서는 프론트엔드 경로가 `/app` 아래에서 제공됩니다. + +다른 라우터에 있는 것을 포함하여, 애플리케이션의 모든 일반 *경로 처리*가 여전히 우선합니다. + +## 정적 빌드 출력만 사용하기 { #static-build-output-only } + +`app.frontend()`는 프론트엔드 빌드에서 이미 생성된 파일을 제공합니다. + +서버 사이드 렌더링은 실행하지 않습니다. 각 요청마다 서버에서 동적 렌더링이 필요한 프레임워크가 아니라, 정적 파일을 생성하는 프론트엔드 프레임워크를 위한 것입니다. From bfb663fa848e35d09b9d7bd21e3b346f442a7b80 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebasti=C3=A1n=20Ram=C3=ADrez?= Date: Wed, 1 Jul 2026 12:44:40 +0200 Subject: [PATCH 356/462] =?UTF-8?q?=F0=9F=8C=90=20Update=20translations=20?= =?UTF-8?q?for=20es=20(add-missing)=20(#15880)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: github-actions[bot] --- docs/es/docs/tutorial/frontend.md | 133 ++++++++++++++++++++++++++++++ 1 file changed, 133 insertions(+) create mode 100644 docs/es/docs/tutorial/frontend.md diff --git a/docs/es/docs/tutorial/frontend.md b/docs/es/docs/tutorial/frontend.md new file mode 100644 index 000000000..707772467 --- /dev/null +++ b/docs/es/docs/tutorial/frontend.md @@ -0,0 +1,133 @@ +# Frontend { #frontend } + +Puedes servir apps frontend estáticas con `app.frontend()` (o `router.frontend()`). + +Esto es útil para herramientas de frontend que generan archivos estáticos, como React con Vite, TanStack Router, Astro, Vue, Svelte, Angular, Solid y otras. + +Con estas herramientas, normalmente tienes un paso que construye el frontend, con un comando como: + +```bash +npm run build +``` + +Eso generaría un directorio como `./dist/` con tus archivos frontend. + +Puedes usar `app.frontend()` para servir ese directorio siguiendo las convenciones que necesitan estos frameworks frontend. + +**FastAPI** revisa primero las *path operations*. Los archivos frontend se revisan solo si ninguna ruta normal coincide, así que tu API no se verá afectada. + +## Sirve un Frontend { #serve-a-frontend } + +Después de construir tu frontend, por ejemplo con `npm run build`, pon los archivos generados en un directorio, por ejemplo, `dist`. + +La estructura de tu proyecto podría verse así: + +```text +. +├── pyproject.toml +├── app +│ ├── __init__.py +│ └── main.py +└── dist + ├── index.html + └── assets + └── app.js +``` + +Luego sírvelo con `app.frontend()`: + +{* ../../docs_src/frontend/tutorial001_py310.py hl[5] *} + +Con esto, un request a `/assets/app.js` puede servir `dist/assets/app.js`. + +Si también tienes una *path operation* de **FastAPI**, la *path operation* gana. + +## Routing del lado del cliente { #client-side-routing } + +Muchas apps frontend, incluidas las **single-page apps** (SPAs), usan routing del lado del cliente. Un path como `/dashboard/settings` podría no ser un archivo real, pero el framework se encargaría de manejarlo. + +Entonces, si se accede a esa URL directamente (en lugar de navegar por la app), el backend debería servir la app frontend desde `index.html`, para que el framework frontend pueda manejar el routing del lado del cliente. + +Para eso, usa `fallback="index.html"`: + +{* ../../docs_src/frontend/tutorial002_py310.py hl[5] *} + +**FastAPI** usa este fallback solo para requests `GET` y `HEAD` que parecen navegación del navegador. Los archivos faltantes como JavaScript, CSS e imágenes siguen devolviendo `404`. + +Los requests con otros métodos, como `POST` o `PUT`, a paths que solo coinciden con el fallback del frontend también devuelven `404`. Las *path operations* normales de **FastAPI** siguen teniendo mayor prioridad que las rutas frontend. + +/// tip | Consejo + +Por defecto, `fallback` tiene un valor de `fallback="auto"`. En la mayoría de los casos no necesitarás especificar `fallback`. Lee más abajo para los detalles. + +/// + +Esto es lo que querrías con muchas apps frontend que usan routing del lado del cliente, por ejemplo, React con TanStack Router, Vue, Angular, SvelteKit o Solid. + +## Página 404 personalizada { #custom-404-page } + +También puedes servir una página estática `404.html` para paths frontend faltantes: + +{* ../../docs_src/frontend/tutorial003_py310.py hl[5] *} + +Esa response mantiene un código de estado `404`. + +En este caso, **FastAPI** no servirá `index.html` para paths frontend faltantes. En su lugar, devolverá el archivo `404.html`. + +/// tip | Consejo + +Por defecto, `fallback` tiene un valor de `fallback="auto"`. Con esto, si se encuentra un archivo `404.html`, se usará automáticamente como fallback. + +Así que normalmente puedes omitir el argumento `fallback`. + +/// + +Esto es útil con herramientas de frontend que generan archivos HTML estáticos para cada página, como Astro. + +## Fallback automático { #fallback-auto } + +Por defecto, `app.frontend()` usa `fallback="auto"`. + +Si hay un archivo `404.html` en el directorio frontend, los paths frontend faltantes sirven ese archivo con código de estado `404`. + +De lo contrario, si hay un archivo `index.html`, los paths faltantes de navegación del navegador sirven `index.html`, que es lo que muchas apps frontend con routing del lado del cliente esperan. + +Así que, en la mayoría de los casos, puedes usar `app.frontend("/", directory="dist")` sin especificar el argumento `fallback`. + +{* ../../docs_src/frontend/tutorial001_py310.py hl[5] *} + +## Desactiva el fallback { #disable-fallback } + +Si no quieres servir un archivo fallback para paths frontend faltantes, usa `fallback=None`: + +{* ../../docs_src/frontend/tutorial005_py310.py hl[5] *} + +Entonces los paths frontend faltantes devuelven el `404` normal. + +## Revisa el directorio { #check-directory } + +Por defecto, `app.frontend()` revisa que el directorio exista cuando se crea la app. + +Esto ayuda a detectar errores de configuración temprano. Por ejemplo, si falta el directorio de salida del build del frontend, **FastAPI** lanzará un error al iniciar. + +Si tus archivos frontend se crean más tarde, por ejemplo mediante un paso de build separado después de crear el objeto app, configura `check_dir=False`: + +{* ../../docs_src/frontend/tutorial006_py310.py hl[5] *} + +Con `check_dir=False`, **FastAPI** no revisará el directorio cuando se cree la app. Si el directorio configurado todavía falta cuando se maneja un request, **FastAPI** lanzará un error en ese momento. + +## Úsalo con `APIRouter` { #use-it-with-apirouter } + +También puedes agregar archivos frontend a un `APIRouter` e incluirlo con un prefijo: + +{* ../../docs_src/frontend/tutorial004_py310.py hl[6,7] *} + +En este ejemplo, los paths frontend se sirven bajo `/app`. + +Cualquier *path operation* regular en la app seguirá teniendo prioridad, incluso en otros routers. + +## Solo salida estática del build { #static-build-output-only } + +`app.frontend()` sirve archivos ya generados por tu build del frontend. + +No ejecuta renderizado del lado del servidor. Es para frameworks frontend que generan archivos estáticos, no para frameworks que necesitan renderizado dinámico en el servidor para cada request. From bdc2dfc9aae56e7cf61fb14f9ca037a23c74255e Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Wed, 1 Jul 2026 10:46:08 +0000 Subject: [PATCH 357/462] =?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 ef2abfd68..52bd92c67 100644 --- a/docs/en/docs/release-notes.md +++ b/docs/en/docs/release-notes.md @@ -9,6 +9,7 @@ hide: ### Translations +* 🌐 Update translations for zh-hant (add-missing). PR [#15889](https://github.com/fastapi/fastapi/pull/15889) by [@tiangolo](https://github.com/tiangolo). * 🌐 Update translations for pt (add-missing). PR [#15883](https://github.com/fastapi/fastapi/pull/15883) by [@tiangolo](https://github.com/tiangolo). * 🌐 Update translations for zh (add-missing). PR [#15885](https://github.com/fastapi/fastapi/pull/15885) by [@tiangolo](https://github.com/tiangolo). * 🌐 Update translations for ja (add-missing). PR [#15882](https://github.com/fastapi/fastapi/pull/15882) by [@tiangolo](https://github.com/tiangolo). From 86dd7b8a23fdbcc4ceafaaa92000a1a5ce874b88 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Wed, 1 Jul 2026 10:46:58 +0000 Subject: [PATCH 358/462] =?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 52bd92c67..0767f9f9c 100644 --- a/docs/en/docs/release-notes.md +++ b/docs/en/docs/release-notes.md @@ -9,6 +9,7 @@ hide: ### Translations +* 🌐 Update translations for es (add-missing). PR [#15880](https://github.com/fastapi/fastapi/pull/15880) by [@tiangolo](https://github.com/tiangolo). * 🌐 Update translations for zh-hant (add-missing). PR [#15889](https://github.com/fastapi/fastapi/pull/15889) by [@tiangolo](https://github.com/tiangolo). * 🌐 Update translations for pt (add-missing). PR [#15883](https://github.com/fastapi/fastapi/pull/15883) by [@tiangolo](https://github.com/tiangolo). * 🌐 Update translations for zh (add-missing). PR [#15885](https://github.com/fastapi/fastapi/pull/15885) by [@tiangolo](https://github.com/tiangolo). From 473acc1adf0218a07510a157a6995b61f2591cb9 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Wed, 1 Jul 2026 10:47:05 +0000 Subject: [PATCH 359/462] =?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 0767f9f9c..edbcb6e10 100644 --- a/docs/en/docs/release-notes.md +++ b/docs/en/docs/release-notes.md @@ -9,6 +9,7 @@ hide: ### Translations +* 🌐 Update translations for ko (add-missing). PR [#15888](https://github.com/fastapi/fastapi/pull/15888) by [@tiangolo](https://github.com/tiangolo). * 🌐 Update translations for es (add-missing). PR [#15880](https://github.com/fastapi/fastapi/pull/15880) by [@tiangolo](https://github.com/tiangolo). * 🌐 Update translations for zh-hant (add-missing). PR [#15889](https://github.com/fastapi/fastapi/pull/15889) by [@tiangolo](https://github.com/tiangolo). * 🌐 Update translations for pt (add-missing). PR [#15883](https://github.com/fastapi/fastapi/pull/15883) by [@tiangolo](https://github.com/tiangolo). From c5ab51d50f576a9e53e0f887d4046033234787cd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebasti=C3=A1n=20Ram=C3=ADrez?= Date: Wed, 1 Jul 2026 14:51:57 +0200 Subject: [PATCH 360/462] =?UTF-8?q?=F0=9F=8C=90=20Update=20translations=20?= =?UTF-8?q?for=20ru=20(update-outdated)=20(#15894)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: github-actions[bot] Co-authored-by: Yurii Motov <109919500+YuriiMotov@users.noreply.github.com> Co-authored-by: Yurii Motov --- docs/ru/docs/_llm-test.md | 4 +- .../docs/advanced/additional-status-codes.md | 1 + .../ru/docs/advanced/advanced-dependencies.md | 4 +- docs/ru/docs/advanced/dataclasses.md | 6 +- docs/ru/docs/advanced/events.md | 54 +++++++-------- docs/ru/docs/advanced/generate-clients.md | 14 ---- docs/ru/docs/advanced/json-base64-bytes.md | 8 +-- docs/ru/docs/advanced/openapi-callbacks.md | 24 +++---- .../advanced/response-change-status-code.md | 4 +- docs/ru/docs/advanced/response-cookies.md | 1 + docs/ru/docs/advanced/response-headers.md | 12 ++-- .../docs/advanced/security/oauth2-scopes.md | 4 +- docs/ru/docs/advanced/settings.md | 8 +-- docs/ru/docs/advanced/stream-data.md | 4 +- docs/ru/docs/advanced/wsgi.md | 4 +- docs/ru/docs/alternatives.md | 4 +- docs/ru/docs/async.md | 10 +-- docs/ru/docs/deployment/cloud.md | 4 +- docs/ru/docs/deployment/concepts.md | 8 +-- docs/ru/docs/deployment/docker.md | 14 ++-- docs/ru/docs/deployment/https.md | 8 +-- docs/ru/docs/deployment/manually.md | 2 +- docs/ru/docs/editor-support.md | 2 +- docs/ru/docs/environment-variables.md | 16 ++--- docs/ru/docs/features.md | 22 +++--- docs/ru/docs/help-fastapi.md | 2 +- docs/ru/docs/how-to/configure-swagger-ui.md | 2 +- .../docs/how-to/custom-request-and-route.md | 12 ++-- docs/ru/docs/how-to/graphql.md | 1 + ...migrate-from-pydantic-v1-to-pydantic-v2.md | 18 +++++ .../docs/how-to/separate-openapi-schemas.md | 2 +- docs/ru/docs/index.md | 14 ++-- docs/ru/docs/project-generation.md | 4 +- docs/ru/docs/python-types.md | 30 ++++---- docs/ru/docs/tutorial/bigger-applications.md | 68 +++++++++---------- docs/ru/docs/tutorial/body-nested-models.md | 10 +-- docs/ru/docs/tutorial/body.md | 2 +- docs/ru/docs/tutorial/debugging.md | 8 +-- .../dependencies/dependencies-with-yield.md | 3 +- docs/ru/docs/tutorial/extra-data-types.md | 24 +++---- docs/ru/docs/tutorial/extra-models.md | 2 +- docs/ru/docs/tutorial/first-steps.md | 24 +++---- docs/ru/docs/tutorial/handling-errors.md | 60 ++++++++-------- docs/ru/docs/tutorial/index.md | 1 + docs/ru/docs/tutorial/metadata.md | 24 +++---- .../tutorial/path-operation-configuration.md | 14 ++-- .../tutorial/query-params-str-validations.md | 34 +++++----- docs/ru/docs/tutorial/query-params.md | 55 +++++++-------- docs/ru/docs/tutorial/request-files.md | 27 ++++---- docs/ru/docs/tutorial/request-forms.md | 1 + docs/ru/docs/tutorial/response-status-code.md | 24 +++---- docs/ru/docs/tutorial/schema-extra-example.md | 10 +-- docs/ru/docs/tutorial/security/first-steps.md | 4 +- .../tutorial/security/get-current-user.md | 4 +- docs/ru/docs/tutorial/security/oauth2-jwt.md | 24 +++---- .../docs/tutorial/security/simple-oauth2.md | 14 ++-- docs/ru/docs/tutorial/sql-databases.md | 6 +- docs/ru/docs/tutorial/static-files.md | 11 ++- docs/ru/docs/tutorial/testing.md | 12 ++-- docs/ru/docs/virtual-environments.md | 2 +- 60 files changed, 406 insertions(+), 389 deletions(-) diff --git a/docs/ru/docs/_llm-test.md b/docs/ru/docs/_llm-test.md index d33e803a0..1b2ee8f18 100644 --- a/docs/ru/docs/_llm-test.md +++ b/docs/ru/docs/_llm-test.md @@ -258,7 +258,7 @@ works(foo="bar") # Это работает 🎉 * `bar` как `str` * `baz` как `list` -* Учебник — Руководство пользователя +* Учебник - Руководство пользователя * Расширенное руководство пользователя * Документация по SQLModel * Документация API @@ -461,7 +461,7 @@ works(foo="bar") # Это работает 🎉 * библиотека * lifespan * блокировка -* middleware (Промежуточный слой) +* middleware (промежуточный слой) * мобильное приложение * модуль * монтирование diff --git a/docs/ru/docs/advanced/additional-status-codes.md b/docs/ru/docs/advanced/additional-status-codes.md index aec66a13f..a0d21e445 100644 --- a/docs/ru/docs/advanced/additional-status-codes.md +++ b/docs/ru/docs/advanced/additional-status-codes.md @@ -1,5 +1,6 @@ # Дополнительные статус-коды { #additional-status-codes } + По умолчанию **FastAPI** будет возвращать ответы, используя `JSONResponse`, помещая содержимое, которое вы возвращаете из вашей *операции пути*, внутрь этого `JSONResponse`. Он будет использовать статус-код по умолчанию или тот, который вы укажете в вашей *операции пути*. diff --git a/docs/ru/docs/advanced/advanced-dependencies.md b/docs/ru/docs/advanced/advanced-dependencies.md index fb6cb7ca8..0092313b2 100644 --- a/docs/ru/docs/advanced/advanced-dependencies.md +++ b/docs/ru/docs/advanced/advanced-dependencies.md @@ -36,7 +36,7 @@ {* ../../docs_src/dependencies/tutorial011_an_py310.py hl[18] *} -Так мы «параметризуем» нашу зависимость: теперь внутри неё хранится "bar" в атрибуте `checker.fixed_content`. +Так мы «параметризуем» нашу зависимость: теперь внутри неё хранится `"bar"` в атрибуте `checker.fixed_content`. ## Используем экземпляр как зависимость { #use-the-instance-as-a-dependency } @@ -48,7 +48,7 @@ checker(q="somequery") ``` -…и передаст возвращённое значение как значение зависимости в параметр `fixed_content_included` нашей *функции-обработчику пути*: +…и передаст возвращённое значение как значение зависимости в нашу *функцию-обработчик пути* в параметр `fixed_content_included`: {* ../../docs_src/dependencies/tutorial011_an_py310.py hl[22] *} diff --git a/docs/ru/docs/advanced/dataclasses.md b/docs/ru/docs/advanced/dataclasses.md index aa927cef1..5388e9832 100644 --- a/docs/ru/docs/advanced/dataclasses.md +++ b/docs/ru/docs/advanced/dataclasses.md @@ -12,9 +12,9 @@ FastAPI построен поверх **Pydantic**, и я показывал в И, конечно, поддерживаются те же возможности: -- валидация данных -- сериализация данных -- документирование данных и т.д. +* валидация данных +* сериализация данных +* документирование данных и т.д. Это работает так же, как с Pydantic-моделями. И на самом деле под капотом это достигается тем же образом, с использованием Pydantic. diff --git a/docs/ru/docs/advanced/events.md b/docs/ru/docs/advanced/events.md index 69ebe4ffc..00319575f 100644 --- a/docs/ru/docs/advanced/events.md +++ b/docs/ru/docs/advanced/events.md @@ -1,30 +1,30 @@ # События lifespan { #lifespan-events } -Вы можете определить логику (код), которую нужно выполнить перед тем, как приложение начнет запускаться. Это означает, что этот код будет выполнен один раз, перед тем как приложение начнет получать HTTP-запросы. +Вы можете определить логику (код), которую нужно выполнить перед тем, как приложение **запустится**. Это означает, что этот код будет выполнен **один раз**, **перед** тем как приложение **начнет получать HTTP-запросы**. -Аналогично, вы можете определить логику (код), которую нужно выполнить, когда приложение завершает работу. В этом случае код будет выполнен один раз, после обработки, возможно, многих запросов. +Аналогично, вы можете определить логику (код), которую нужно выполнить, когда приложение **завершает работу**. В этом случае код будет выполнен **один раз**, **после обработки**, возможно, **многих HTTP-запросов**. -Поскольку этот код выполняется до того, как приложение начинает принимать запросы, и сразу после того, как оно заканчивает их обрабатывать, он охватывает весь lifespan (жизненный цикл) приложения (слово «lifespan» станет важным через секунду 😉). +Поскольку этот код выполняется до того, как приложение **начинает** принимать HTTP-запросы, и сразу после того, как оно **заканчивает** их обрабатывать, он охватывает весь **lifespan** (жизненный цикл) приложения (слово «lifespan» станет важным через секунду 😉). -Это может быть очень полезно для настройки ресурсов, которые нужны для всего приложения, которые разделяются между запросами и/или которые нужно затем очистить. Например, пул подключений к базе данных или загрузка общей модели Машинного обучения. +Это может быть очень полезно для настройки **ресурсов**, которые нужны для всего приложения, которые **разделяются** между HTTP-запросами и/или которые нужно затем **очистить**. Например, пул подключений к базе данных или загрузка общей модели Машинного обучения. ## Вариант использования { #use-case } -Начнем с примера варианта использования, а затем посмотрим, как это решить. +Начнем с примера **варианта использования**, а затем посмотрим, как это решить. -Представим, что у вас есть несколько моделей Машинного обучения, которые вы хотите использовать для обработки запросов. 🤖 +Представим, что у вас есть несколько **моделей Машинного обучения**, которые вы хотите использовать для обработки HTTP-запросов. 🤖 -Эти же модели разделяются между запросами, то есть это не одна модель на запрос, не одна на пользователя и т.п. +Эти же модели разделяются между HTTP-запросами, то есть это не одна модель на HTTP-запрос, не одна на пользователя и т.п. -Представим, что загрузка модели может занимать довольно много времени, потому что ей нужно прочитать много данных с диска. Поэтому вы не хотите делать это для каждого запроса. +Представим, что загрузка модели может **занимать довольно много времени**, потому что ей нужно прочитать много **данных с диска**. Поэтому вы не хотите делать это для каждого HTTP-запроса. -Вы могли бы загрузить её на верхнем уровне модуля/файла, но это означало бы, что модель загружается даже если вы просто запускаете простой автоматический тест; тогда этот тест будет медленным, так как ему придется ждать загрузки модели перед запуском независимой части кода. +Вы могли бы загрузить её на верхнем уровне модуля/файла, но это означало бы, что модель будет **загружаться** даже если вы просто запускаете простой автоматический тест; тогда этот тест будет **медленным**, так как ему придется ждать загрузки модели перед запуском независимой части кода. -Именно это мы и решим: давайте загружать модель перед тем, как начнётся обработка запросов, но только непосредственно перед тем, как приложение начнет принимать запросы, а не во время загрузки кода. +Именно это мы и решим: давайте загружать модель перед тем, как начнётся обработка HTTP-запросов, но только непосредственно перед тем, как приложение начнет принимать HTTP-запросы, а не во время загрузки кода. ## Lifespan { #lifespan } -Вы можете определить логику для startup и shutdown, используя параметр `lifespan` приложения `FastAPI` и «менеджер контекста» (через секунду покажу что это). +Вы можете определить логику для *startup* и *shutdown*, используя параметр `lifespan` приложения `FastAPI` и «менеджер контекста» (через секунду покажу что это). Начнем с примера, а затем разберём его подробнее. @@ -32,13 +32,13 @@ {* ../../docs_src/events/tutorial003_py310.py hl[16,19] *} -Здесь мы симулируем дорогую операцию startup по загрузке модели, помещая (фиктивную) функцию модели в словарь с моделями Машинного обучения до `yield`. Этот код будет выполнен до того, как приложение начнет принимать запросы, во время startup. +Здесь мы симулируем дорогую операцию *startup* по загрузке модели, помещая (фиктивную) функцию модели в словарь с моделями Машинного обучения до `yield`. Этот код будет выполнен **до** того, как приложение **начнет принимать HTTP-запросы**, во время *startup*. -А затем сразу после `yield` мы выгружаем модель. Этот код будет выполнен после того, как приложение закончит обрабатывать запросы, непосредственно перед shutdown. Это может, например, освободить ресурсы, такие как память или GPU. +А затем сразу после `yield` мы выгружаем модель. Этот код будет выполнен **после** того, как приложение **закончит обрабатывать HTTP-запросы**, непосредственно перед *shutdown*. Это может, например, освободить ресурсы, такие как память или GPU. /// tip | Совет -`shutdown` произойдёт, когда вы останавливаете приложение. +`shutdown` произойдёт, когда вы **останавливаете** приложение. Возможно, вам нужно запустить новую версию, или вы просто устали от него. 🤷 @@ -50,26 +50,26 @@ {* ../../docs_src/events/tutorial003_py310.py hl[14:19] *} -Первая часть функции, до `yield`, будет выполнена до запуска приложения. +Первая часть функции, до `yield`, будет выполнена **до** запуска приложения. -А часть после `yield` будет выполнена после завершения работы приложения. +А часть после `yield` будет выполнена **после** завершения работы приложения. ### Асинхронный менеджер контекста { #async-context-manager } Если присмотреться, функция декорирована `@asynccontextmanager`. -Это превращает функцию в «асинхронный менеджер контекста». +Это превращает функцию в «**асинхронный менеджер контекста**». {* ../../docs_src/events/tutorial003_py310.py hl[1,13] *} -Менеджер контекста в Python — это то, что можно использовать в операторе `with`. Например, `open()` можно использовать как менеджер контекста: +**Менеджер контекста** в Python — это то, что можно использовать в операторе `with`. Например, `open()` можно использовать как менеджер контекста: ```Python with open("file.txt") as file: file.read() ``` -В последних версиях Python есть также асинхронный менеджер контекста. Его используют с `async with`: +В последних версиях Python есть также **асинхронный менеджер контекста**. Его используют с `async with`: ```Python async with lifespan(app): @@ -80,7 +80,7 @@ async with lifespan(app): В нашем примере выше мы не используем его напрямую, а передаём его в FastAPI, чтобы он использовал его сам. -Параметр `lifespan` приложения `FastAPI` принимает асинхронный менеджер контекста, поэтому мы можем передать ему наш новый асинхронный менеджер контекста `lifespan`. +Параметр `lifespan` приложения `FastAPI` принимает **асинхронный менеджер контекста**, поэтому мы можем передать ему наш новый асинхронный менеджер контекста `lifespan`. {* ../../docs_src/events/tutorial003_py310.py hl[22] *} @@ -88,13 +88,13 @@ async with lifespan(app): /// warning | Предупреждение -Рекомендуемый способ обрабатывать startup и shutdown — использовать параметр `lifespan` приложения `FastAPI`, как описано выше. Если вы укажете параметр `lifespan`, обработчики событий `startup` и `shutdown` больше вызываться не будут. Либо всё через `lifespan`, либо всё через события — не одновременно. +Рекомендуемый способ обрабатывать *startup* и *shutdown* — использовать параметр `lifespan` приложения `FastAPI`, как описано выше. Если вы укажете параметр `lifespan`, обработчики событий `startup` и `shutdown` больше вызываться не будут. Либо всё через `lifespan`, либо всё через события — не одновременно. Эту часть, скорее всего, можно пропустить. /// -Есть альтернативный способ определить логику, которую нужно выполнить во время startup и во время shutdown. +Есть альтернативный способ определить логику, которую нужно выполнить во время *startup* и во время *shutdown*. Вы можете определить обработчики событий (функции), которые нужно выполнить до старта приложения или при его завершении. @@ -110,7 +110,7 @@ async with lifespan(app): Вы можете добавить более одного обработчика события. -И ваше приложение не начнет принимать запросы, пока все обработчики события `startup` не завершатся. +И ваше приложение не начнет принимать HTTP-запросы, пока все обработчики события `startup` не завершатся. ### Событие `shutdown` { #shutdown-event } @@ -140,7 +140,7 @@ async with lifespan(app): ### `startup` и `shutdown` вместе { #startup-and-shutdown-together } -С высокой вероятностью логика для вашего startup и shutdown связана: вы можете хотеть что-то запустить, а затем завершить, получить ресурс, а затем освободить его и т.д. +С высокой вероятностью логика для вашего *startup* и *shutdown* связана: вы можете хотеть что-то запустить, а затем завершить, получить ресурс, а затем освободить его и т.д. Делать это в отдельных функциях, которые не разделяют общую логику или переменные, сложнее, так как придётся хранить значения в глобальных переменных или использовать похожие приёмы. @@ -148,9 +148,9 @@ async with lifespan(app): ## Технические детали { #technical-details } -Немного технических подробностей для любопытных умников. 🤓 +Просто техническая подробность для любопытных умников. 🤓 -Под капотом, в ASGI-технической спецификации, это часть [Протокола Lifespan](https://asgi.readthedocs.io/en/latest/specs/lifespan.html), и он определяет события `startup` и `shutdown`. +Под капотом, в технической спецификации ASGI, это часть [Протокола Lifespan](https://asgi.readthedocs.io/en/latest/specs/lifespan.html), и он определяет события `startup` и `shutdown`. /// note | Примечание @@ -162,4 +162,4 @@ async with lifespan(app): ## Подприложения { #sub-applications } -🚨 Имейте в виду, что эти события lifespan (startup и shutdown) будут выполнены только для основного приложения, а не для [Подприложения — Mounts](sub-applications.md). +🚨 Имейте в виду, что эти события lifespan (startup и shutdown) будут выполнены только для основного приложения, а не для [Подприложений - Mounts](sub-applications.md). diff --git a/docs/ru/docs/advanced/generate-clients.md b/docs/ru/docs/advanced/generate-clients.md index f05454d9c..04e8e88bc 100644 --- a/docs/ru/docs/advanced/generate-clients.md +++ b/docs/ru/docs/advanced/generate-clients.md @@ -20,20 +20,6 @@ FastAPI автоматически генерирует спецификации /// -## Генераторы SDK от спонсоров FastAPI { #sdk-generators-from-fastapi-sponsors } - -В этом разделе представлены решения с **венчурной поддержкой** и **поддержкой компаний** от компаний, которые спонсируют FastAPI. Эти продукты предоставляют **дополнительные возможности** и **интеграции** сверх высококачественно генерируемых SDK. - -Благодаря ✨ [**спонсорству FastAPI**](../help-fastapi.md#sponsor-the-author) ✨ эти компании помогают обеспечивать, чтобы фреймворк и его **экосистема** оставались здоровыми и **устойчивыми**. - -Их спонсорство также демонстрирует серьёзную приверженность **сообществу** FastAPI (вам), показывая, что им важно не только предоставлять **отличный сервис**, но и поддерживать **надёжный и процветающий фреймворк** FastAPI. 🙇 - -Например, вы можете попробовать: - -* [Stainless](https://www.stainless.com/?utm_source=fastapi&utm_medium=referral) - -Некоторые из этих решений также могут быть open source или иметь бесплатные тарифы, так что вы сможете попробовать их без финансовых затрат. Другие коммерческие генераторы SDK доступны и их можно найти онлайн. 🤓 - ## Создать TypeScript SDK { #create-a-typescript-sdk } Начнём с простого приложения FastAPI: diff --git a/docs/ru/docs/advanced/json-base64-bytes.md b/docs/ru/docs/advanced/json-base64-bytes.md index 390dd17fa..262766889 100644 --- a/docs/ru/docs/advanced/json-base64-bytes.md +++ b/docs/ru/docs/advanced/json-base64-bytes.md @@ -4,7 +4,7 @@ ## Base64 и файлы { #base64-vs-files } -Сначала рассмотрите возможность использовать [Файлы в запросе](../tutorial/request-files.md) для загрузки бинарных данных и [Пользовательский HTTP-ответ — FileResponse](./custom-response.md#fileresponse--fileresponse-) для отправки бинарных данных вместо кодирования их в JSON. +Сначала рассмотрите возможность использовать [Файлы в запросе](../tutorial/request-files.md) для загрузки бинарных данных и [Пользовательский HTTP-ответ — FileResponse](./custom-response.md#fileresponse) для отправки бинарных данных вместо кодирования их в JSON. JSON может содержать только строки в кодировке UTF-8, поэтому он не может содержать «сырые» байты. @@ -14,7 +14,7 @@ Base64 может кодировать бинарные данные в стро ## Pydantic `bytes` { #pydantic-bytes } -Вы можете объявить Pydantic-модель с полями `bytes`, а затем использовать `val_json_bytes` в конфиге модели, чтобы указать использовать base64 для валидации входящих JSON-данных; как часть этой валидации строка base64 будет декодирована в байты. +Вы можете объявить Pydantic-модель с полями `bytes`, а затем использовать `val_json_bytes` в конфиге модели, чтобы указать использовать base64 для *валидации* входящих JSON-данных; как часть этой валидации строка base64 будет декодирована в байты. {* ../../docs_src/json_base64_bytes/tutorial001_py310.py ln[1:9,29:35] hl[9] *} @@ -52,12 +52,12 @@ Base64 может кодировать бинарные данные в стро ## Pydantic `bytes` для выходных данных { #pydantic-bytes-for-output-data } -Вы также можете использовать поля `bytes` с `ser_json_bytes` в конфиге модели для выходных данных, и Pydantic будет сериализовать байты в base64 при формировании JSON-ответа. +Вы также можете использовать поля `bytes` с `ser_json_bytes` в конфиге модели для выходных данных, и Pydantic будет *сериализовать* байты в base64 при формировании JSON-ответа. {* ../../docs_src/json_base64_bytes/tutorial001_py310.py ln[1:2,12:16,29,38:41] hl[16] *} ## Pydantic `bytes` для входных и выходных данных { #pydantic-bytes-for-input-and-output-data } -И, конечно, вы можете использовать одну и ту же модель, настроенную на использование base64, чтобы обрабатывать и входящие данные (валидация) с `val_json_bytes`, и исходящие данные (сериализация) с `ser_json_bytes` при приеме и отправке JSON-данных. +И, конечно, вы можете использовать одну и ту же модель, настроенную на использование base64, чтобы обрабатывать и входящие данные (*валидировать*) с `val_json_bytes`, и исходящие данные (*сериализовать*) с `ser_json_bytes` при приеме и отправке JSON-данных. {* ../../docs_src/json_base64_bytes/tutorial001_py310.py ln[1:2,19:26,29,44:46] hl[23:26] *} diff --git a/docs/ru/docs/advanced/openapi-callbacks.md b/docs/ru/docs/advanced/openapi-callbacks.md index c9cb73d18..002b69c7c 100644 --- a/docs/ru/docs/advanced/openapi-callbacks.md +++ b/docs/ru/docs/advanced/openapi-callbacks.md @@ -1,10 +1,10 @@ # Обратные вызовы в OpenAPI { #openapi-callbacks } -Вы можете создать API с *операцией пути* (обработчиком пути), которая будет инициировать HTTP-запрос к *внешнему API*, созданному кем-то другим (скорее всего тем же разработчиком, который будет использовать ваш API). +Вы можете создать API с *операцией пути* (обработчиком пути), которая будет инициировать HTTP-запрос к *внешнему API*, созданному кем-то другим (скорее всего тем же разработчиком, который будет *использовать* ваш API). -Процесс, происходящий, когда ваше приложение API обращается к *внешнему API*, называется «callback» (обратный вызов). Программное обеспечение, написанное внешним разработчиком, отправляет HTTP-запрос вашему API, а затем ваш API выполняет обратный вызов, отправляя HTTP-запрос во *внешний API* (который, вероятно, тоже создал тот же разработчик). +Процесс, происходящий, когда ваше приложение API обращается к *внешнему API*, называется «callback» (обратный вызов). Потому что программное обеспечение, написанное внешним разработчиком, отправляет HTTP-запрос вашему API, а затем ваш API выполняет обратный вызов, отправляя HTTP-запрос во *внешний API* (который, вероятно, тоже создал тот же разработчик). -В этом случае вам может понадобиться задокументировать, как должно выглядеть это внешнее API: какую *операцию пути* оно должно иметь, какое тело запроса ожидать, какой ответ возвращать и т.д. +В этом случае вам может понадобиться задокументировать, как это внешнее API *должно* выглядеть: какую *операцию пути* оно должно иметь, какое тело запроса ожидать, какой HTTP-ответ возвращать и т.д. ## Приложение с обратными вызовами { #an-app-with-callbacks } @@ -82,7 +82,7 @@ httpx.post(callback_url, json={"description": "Invoice paid", "paid": True}) Когда вы пишете код для документирования обратного вызова, полезно представить, что вы — тот самый *внешний разработчик*. И что вы сейчас реализуете *внешний API*, а не *свой API*. -Временное принятие этой точки зрения (внешнего разработчика) поможет интуитивно понять, куда поместить параметры, какую Pydantic-модель использовать для тела запроса, для ответа и т.д. во *внешнем API*. +Временное принятие этой точки зрения (внешнего разработчика) поможет интуитивно понять, куда поместить параметры, какую Pydantic-модель использовать для тела запроса, для HTTP-ответа и т.д. во *внешнем API*. /// @@ -99,7 +99,7 @@ httpx.post(callback_url, json={"description": "Invoice paid", "paid": True}) Она должна выглядеть как обычная *операция пути* FastAPI: * Вероятно, в ней должно быть объявление тела запроса, например `body: InvoiceEvent`. -* А также может быть объявление модели ответа, например `response_model=InvoiceEventReceived`. +* А также может быть объявление HTTP-ответа, который она должна возвращать, например `response_model=InvoiceEventReceived`. {* ../../docs_src/openapi_callbacks/tutorial001_py310.py hl[14:16,19:20,26:30] *} @@ -124,7 +124,7 @@ httpx.post(callback_url, json={"description": "Invoice paid", "paid": True}) https://yourapi.com/invoices/?callback_url=https://www.external.org/events ``` -с телом JSON: +с телом запроса JSON: ```JSON { @@ -140,7 +140,7 @@ https://yourapi.com/invoices/?callback_url=https://www.external.org/events https://www.external.org/events/invoices/2expen51ve ``` -с телом JSON примерно такого вида: +с телом запроса JSON примерно такого вида: ```JSON { @@ -149,7 +149,7 @@ https://www.external.org/events/invoices/2expen51ve } ``` -и будет ожидать от *внешнего API* ответ с телом JSON вида: +и будет ожидать от *внешнего API* HTTP-ответ с JSON в теле ответа: ```JSON { @@ -163,17 +163,17 @@ https://www.external.org/events/invoices/2expen51ve /// -### Подключите маршрутизатор обратного вызова { #add-the-callback-router } +### Добавьте роутер обратного вызова { #add-the-callback-router } -К этому моменту у вас есть необходимые *операции пути* обратного вызова (те, которые *внешний разработчик* должен реализовать во *внешнем API*) в созданном выше маршрутизаторе обратных вызовов. +К этому моменту у вас есть необходимые *операции пути* обратного вызова (те, которые *внешний разработчик* должен реализовать во *внешнем API*) в созданном выше роутере обратных вызовов. -Теперь используйте параметр `callbacks` в *декораторе операции пути вашего API*, чтобы передать атрибут `.routes` из этого маршрутизатора обратных вызовов: +Теперь используйте параметр `callbacks` в *декораторе операции пути вашего API*, чтобы передать атрибут `.routes` из этого роутера обратных вызовов: {* ../../docs_src/openapi_callbacks/tutorial001_py310.py hl[33] *} /// tip | Совет -Обратите внимание, что вы передаёте не сам маршрутизатор (`invoices_callback_router`) в `callback=`, а его атрибут `.routes`, то есть `invoices_callback_router.routes`. FastAPI будет использовать эти маршруты для генерации документации OpenAPI для обратных вызовов. +Обратите внимание, что вы передаёте не сам роутер (`invoices_callback_router`) в `callbacks=`, а его атрибут `.routes`, то есть `invoices_callback_router.routes`. FastAPI будет использовать эти маршруты для генерации документации OpenAPI для обратных вызовов. /// diff --git a/docs/ru/docs/advanced/response-change-status-code.md b/docs/ru/docs/advanced/response-change-status-code.md index 3dd0c9446..a4ebd4fbc 100644 --- a/docs/ru/docs/advanced/response-change-status-code.md +++ b/docs/ru/docs/advanced/response-change-status-code.md @@ -1,6 +1,6 @@ # Response - Изменение статус-кода { #response-change-status-code } -Вы, вероятно, уже читали о том, что можно установить [статус-код ответа по умолчанию](../tutorial/response-status-code.md). +Вы, вероятно, уже читали о том, что можно установить [статус-код ответа](../tutorial/response-status-code.md) по умолчанию. Но в некоторых случаях нужно вернуть другой статус-код, отличный от значения по умолчанию. @@ -16,7 +16,7 @@ ## Использование параметра `Response` { #use-a-response-parameter } -Вы можете объявить параметр типа `Response` в вашей *функции обработки пути* (как и для cookies и HTTP-заголовков). +Вы можете объявить параметр типа `Response` в вашей *функции-обработчике пути* (как и для cookies и HTTP-заголовков). И затем вы можете установить `status_code` в этом *временном* объекте ответа. diff --git a/docs/ru/docs/advanced/response-cookies.md b/docs/ru/docs/advanced/response-cookies.md index 2adc1af85..3e16fe892 100644 --- a/docs/ru/docs/advanced/response-cookies.md +++ b/docs/ru/docs/advanced/response-cookies.md @@ -1,5 +1,6 @@ # Cookies в ответе { #response-cookies } + ## Использование параметра `Response` { #use-a-response-parameter } Вы можете объявить параметр типа `Response` в вашей функции-обработчике пути. diff --git a/docs/ru/docs/advanced/response-headers.md b/docs/ru/docs/advanced/response-headers.md index 806b89e1f..e0cfa66ed 100644 --- a/docs/ru/docs/advanced/response-headers.md +++ b/docs/ru/docs/advanced/response-headers.md @@ -2,7 +2,7 @@ ## Использовать параметр `Response` { #use-a-response-parameter } -Вы можете объявить параметр типа `Response` в вашей функции-обработчике пути (как можно сделать и для cookie). +Вы можете объявить параметр типа `Response` в вашей *функции-обработчике пути* (как можно сделать и для cookie). А затем вы можете устанавливать HTTP-заголовки в этом *временном* объекте ответа. @@ -14,13 +14,13 @@ **FastAPI** использует этот *временный* ответ, чтобы извлечь HTTP-заголовки (а также cookie и статус-код) и поместит их в финальный HTTP-ответ, который содержит возвращённое вами значение, отфильтрованное согласно `response_model`. -Вы также можете объявлять параметр `Response` в зависимостях и устанавливать в них заголовки (и cookie). +Вы также можете объявлять параметр `Response` в зависимостях и устанавливать в них HTTP-заголовки (и cookie). ## Вернуть `Response` напрямую { #return-a-response-directly } Вы также можете добавить HTTP-заголовки, когда возвращаете `Response` напрямую. -Создайте ответ, как описано в [Вернуть Response напрямую](response-directly.md), и передайте заголовки как дополнительный параметр: +Создайте ответ, как описано в [Вернуть Response напрямую](response-directly.md), и передайте HTTP-заголовки как дополнительный параметр: {* ../../docs_src/response_headers/tutorial001_py310.py hl[10:12] *} @@ -30,12 +30,12 @@ **FastAPI** предоставляет те же самые `starlette.responses` как `fastapi.responses` — для вашего удобства как разработчика. Но большинство доступных классов ответов поступают напрямую из Starlette. -И поскольку `Response` часто используется для установки заголовков и cookie, **FastAPI** также предоставляет его как `fastapi.Response`. +И поскольку `Response` часто используется для установки HTTP-заголовков и cookie, **FastAPI** также предоставляет его как `fastapi.Response`. /// ## Пользовательские HTTP-заголовки { #custom-headers } -Помните, что собственные проприетарные заголовки можно добавлять, [используя префикс `X-`](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers). +Помните, что собственные проприетарные HTTP-заголовки можно добавлять, [используя префикс `X-`](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers). -Но если у вас есть пользовательские заголовки, которые вы хотите показывать клиенту в браузере, вам нужно добавить их в настройки CORS (подробнее см. в [CORS (Cross-Origin Resource Sharing)](../tutorial/cors.md)), используя параметр `expose_headers`, описанный в [документации Starlette по CORS](https://www.starlette.dev/middleware/#corsmiddleware). +Но если у вас есть пользовательские HTTP-заголовки, которые вы хотите показывать клиенту в браузере, вам нужно добавить их в настройки CORS (подробнее см. в [CORS (Cross-Origin Resource Sharing)](../tutorial/cors.md)), используя параметр `expose_headers`, описанный в [документации Starlette по CORS](https://www.starlette.dev/middleware/#corsmiddleware). diff --git a/docs/ru/docs/advanced/security/oauth2-scopes.md b/docs/ru/docs/advanced/security/oauth2-scopes.md index a0b7a185c..7b1731c5d 100644 --- a/docs/ru/docs/advanced/security/oauth2-scopes.md +++ b/docs/ru/docs/advanced/security/oauth2-scopes.md @@ -76,7 +76,7 @@ OAuth2 со scopes — это механизм, который использу Так как теперь мы объявляем эти scopes, они появятся в документации API при входе/авторизации. -И вы сможете выбрать, какие scopes вы хотите выдать доступ: `me` и `items`. +И вы сможете выбрать, для каких scopes хотите предоставить доступ: `me` и `items`. Это тот же механизм, когда вы даёте разрешения при входе через Facebook, Google, GitHub и т.д.: @@ -100,7 +100,7 @@ OAuth2 со scopes — это механизм, который использу {* ../../docs_src/security/tutorial005_an_py310.py hl[157] *} -## Объявление scopes в *обработчиках путей* и зависимостях { #declare-scopes-in-path-operations-and-dependencies } +## Объявление scopes в *операциях пути* и зависимостях { #declare-scopes-in-path-operations-and-dependencies } Теперь объявим, что операция пути для `/users/me/items/` требует scope `items`. diff --git a/docs/ru/docs/advanced/settings.md b/docs/ru/docs/advanced/settings.md index 3ae063340..b85aa3959 100644 --- a/docs/ru/docs/advanced/settings.md +++ b/docs/ru/docs/advanced/settings.md @@ -205,7 +205,7 @@ APP_NAME="ChimichangApp" ### Создание `Settings` только один раз с помощью `lru_cache` { #creating-the-settings-only-once-with-lru-cache } -Чтение файла с диска обычно затратная (медленная) операция, поэтому, вероятно, вы захотите сделать это один раз и затем переиспользовать один и тот же объект настроек, а не читать файл при каждом запросе. +Чтение файла с диска обычно затратная (медленная) операция, поэтому, вероятно, вы захотите сделать это один раз и затем переиспользовать один и тот же объект настроек, а не читать файл при каждом HTTP-запросе. Но каждый раз, когда мы делаем: @@ -222,13 +222,13 @@ def get_settings(): return Settings() ``` -мы бы создавали этот объект для каждого запроса и читали файл `.env` на каждый запрос. ⚠️ +мы бы создавали этот объект для каждого HTTP-запроса и читали файл `.env` на каждый HTTP-запрос. ⚠️ Но так как мы используем декоратор `@lru_cache` сверху, объект `Settings` будет создан только один раз — при первом вызове. ✔️ {* ../../docs_src/settings/app03_an_py310/main.py hl[1,11] *} -Затем при любых последующих вызовах `get_settings()` в зависимостях для следующих запросов, вместо выполнения внутреннего кода `get_settings()` и создания нового объекта `Settings`, будет возвращаться тот же объект, что был возвращен при первом вызове, снова и снова. +Затем при любых последующих вызовах `get_settings()` в зависимостях для следующих HTTP-запросов, вместо выполнения внутреннего кода `get_settings()` и создания нового объекта `Settings`, будет возвращаться тот же объект, что был возвращен при первом вызове, снова и снова. #### Технические детали `lru_cache` { #lru-cache-technical-details } @@ -299,4 +299,4 @@ participant execute as Execute function * Используя зависимость, вы упрощаете тестирование. * Можно использовать файлы `.env`. -* `@lru_cache` позволяет не читать файл dotenv снова и снова для каждого запроса, при этом давая возможность переопределять его во время тестирования. +* `@lru_cache` позволяет не читать файл dotenv снова и снова для каждого HTTP-запроса, при этом давая возможность переопределять его во время тестирования. diff --git a/docs/ru/docs/advanced/stream-data.md b/docs/ru/docs/advanced/stream-data.md index 9ae6890a5..d6957a6cf 100644 --- a/docs/ru/docs/advanced/stream-data.md +++ b/docs/ru/docs/advanced/stream-data.md @@ -2,7 +2,7 @@ Если вам нужно передавать потоковые данные, которые можно представить как JSON, воспользуйтесь [стримингом JSON Lines](../tutorial/stream-json-lines.md). -Но если вы хотите передавать в потоке чистые бинарные данные или строки, ниже показано, как это сделать. +Но если вы хотите передавать в потоке **чистые бинарные данные** или строки, ниже показано, как это сделать. /// note | Примечание @@ -40,7 +40,7 @@ FastAPI будет передавать каждый чанк данных в `S {* ../../docs_src/stream_data/tutorial001_py310.py ln[32:35] hl[33] *} -Это также означает, что с `StreamingResponse` у вас есть и свобода, и ответственность — производить и кодировать байты данных ровно в том виде, в котором они должны быть отправлены, независимо от аннотаций типов. 🤓 +Это также означает, что с `StreamingResponse` у вас есть и **свобода**, и **ответственность** — производить и кодировать байты данных ровно в том виде, в котором они должны быть отправлены, независимо от аннотаций типов. 🤓 ### Потоковая передача байтов { #stream-bytes } diff --git a/docs/ru/docs/advanced/wsgi.md b/docs/ru/docs/advanced/wsgi.md index d62133c73..99ba50938 100644 --- a/docs/ru/docs/advanced/wsgi.md +++ b/docs/ru/docs/advanced/wsgi.md @@ -14,7 +14,7 @@ Нужно импортировать `WSGIMiddleware` из `a2wsgi`. -Затем оберните WSGI‑приложение (например, Flask) в middleware (Промежуточный слой). +Затем оберните WSGI‑приложение (например, Flask) в middleware (промежуточный слой). После этого смонтируйте его на путь. @@ -26,7 +26,7 @@ Вместо него рекомендуется использовать пакет `a2wsgi`. Использование остаётся таким же. -Просто убедитесь, что пакет `a2wsgi` установлен, и импортируйте `WSGIMiddleware` из `a2wsgi`. +Просто убедитесь, что пакет `a2wsgi` установлен, и правильно импортируйте `WSGIMiddleware` из `a2wsgi`. /// diff --git a/docs/ru/docs/alternatives.md b/docs/ru/docs/alternatives.md index 13f099da8..e1b8e277d 100644 --- a/docs/ru/docs/alternatives.md +++ b/docs/ru/docs/alternatives.md @@ -20,7 +20,7 @@ Он относительно тесно связан с реляционными базами данных (например, MySQL или PostgreSQL), поэтому использовать NoSQL-базу данных (например, Couchbase, MongoDB, Cassandra и т. п.) в качестве основного хранилища не очень просто. -Он был создан для генерации HTML на бэкенде, а не для создания API, используемых современным фронтендом (например, React, Vue.js и Angular) или другими системами (например, устройствами IoT), которые с ним общаются. +Он был создан для генерации HTML на бэкенде, а не для создания API, используемых современным фронтендом (например, React, Vue.js и Angular) или другими системами (например, устройствами IoT), которые с ним общаются. ### [Django REST Framework](https://www.django-rest-framework.org/) { #django-rest-framework } @@ -88,7 +88,7 @@ Requests имеет очень простой и понятный дизайн, response = requests.get("http://example.com/some/url") ``` -Соответствующая в FastAPI API-операция пути могла бы выглядеть так: +Соответствующая в FastAPI API-*операция пути* могла бы выглядеть так: ```Python hl_lines="1" @app.get("/some/url") diff --git a/docs/ru/docs/async.md b/docs/ru/docs/async.md index e2b98bd61..aba77a96b 100644 --- a/docs/ru/docs/async.md +++ b/docs/ru/docs/async.md @@ -12,7 +12,7 @@ results = await some_library() ``` -Тогда объявляйте *функции-обработчиков пути* с `async def`, например: +Тогда объявляйте *функции-обработчики пути* с `async def`, например: ```Python hl_lines="2" @app.get('/') @@ -29,7 +29,7 @@ async def read_results(): --- -Если вы используете стороннюю библиотеку, которая взаимодействует с чем-то (база данных, API, файловая система и т.д.) и не поддерживает использование `await` (сейчас это относится к большинству библиотек для БД), тогда объявляйте *функции-обработчиков пути* как обычно, просто с `def`, например: +Если вы используете стороннюю библиотеку, которая взаимодействует с чем-то (база данных, API, файловая система и т.д.) и не поддерживает использование `await` (сейчас это относится к большинству библиотек для БД), тогда объявляйте *функции-обработчики пути* как обычно, просто с `def`, например: ```Python hl_lines="2" @app.get('/') @@ -48,7 +48,7 @@ def results(): --- -**Примечание**: вы можете смешивать `def` и `async def` в *функциях-обработчиков пути* столько, сколько нужно, и объявлять каждую так, как лучше для вашего случая. FastAPI сделает с ними всё как надо. +**Примечание**: вы можете смешивать `def` и `async def` в *функциях-обработчиках пути* столько, сколько нужно, и объявлять каждую так, как лучше для вашего случая. FastAPI сделает с ними всё как надо. В любом из случаев выше FastAPI всё равно работает асинхронно и очень быстро. @@ -249,7 +249,7 @@ def results(): Именно такая асинхронность сделала NodeJS популярным (хотя NodeJS — не параллельный), и это сильная сторона Go как языка программирования. -Того же уровня производительности вы получаете с **FastAPI**. +Тот же уровень производительности вы получаете с **FastAPI**. А так как можно одновременно использовать параллелизм и асинхронность, вы получаете производительность выше, чем у большинства протестированных фреймворков на NodeJS и на уровне Go, который — компилируемый язык, ближе к C [(всё благодаря Starlette)](https://www.techempower.com/benchmarks/#section=data-r17&hw=ph&test=query&l=zijmkf-1). @@ -340,7 +340,7 @@ burgers = get_burgers(2) --- -Итак, если вы используете библиотеку, которую можно вызывать с `await`, вам нужно создать *функцию-обработчик пути*, которая её использует, с `async def`, например: +Итак, если вы используете библиотеку, которую можно вызывать с `await`, вам нужно создать *функции-обработчики пути*, которые её используют, с `async def`, например: ```Python hl_lines="2-3" @app.get('/burgers') diff --git a/docs/ru/docs/deployment/cloud.md b/docs/ru/docs/deployment/cloud.md index cbd517e36..eb1b49aa5 100644 --- a/docs/ru/docs/deployment/cloud.md +++ b/docs/ru/docs/deployment/cloud.md @@ -1,6 +1,6 @@ # Развертывание FastAPI у облачных провайдеров { #deploy-fastapi-on-cloud-providers } -Вы можете использовать практически любого облачного провайдера, чтобы развернуть свое приложение на FastAPI. +Вы можете использовать практически **любого облачного провайдера**, чтобы развернуть свое приложение на FastAPI. В большинстве случаев у основных облачных провайдеров есть руководства по развертыванию FastAPI на их платформе. @@ -16,7 +16,7 @@ FastAPI Cloud — основной спонсор и источник финан ## Облачные провайдеры — спонсоры { #cloud-providers-sponsors } -Некоторые другие облачные провайдеры ✨ [**спонсируют FastAPI**](../help-fastapi.md#sponsor-the-author) ✨ тоже. 🙇 +Некоторые другие облачные провайдеры ✨ [**спонсируют FastAPI**](https://github.com/sponsors/tiangolo) ✨ тоже. 🙇 Возможно, вы захотите попробовать их сервисы и воспользоваться их руководствами: diff --git a/docs/ru/docs/deployment/concepts.md b/docs/ru/docs/deployment/concepts.md index 900b842f9..23c62b8d3 100644 --- a/docs/ru/docs/deployment/concepts.md +++ b/docs/ru/docs/deployment/concepts.md @@ -243,7 +243,7 @@ Не беспокойтесь, если некоторые пункты про **контейнеры**, Docker или Kubernetes пока кажутся неочевидными. -Я расскажу больше про образы контейнеров, Docker, Kubernetes и т.п. в следующей главе: [FastAPI внутри контейнеров — Docker](docker.md). +Я расскажу больше про образы контейнеров, Docker, Kubernetes и т.п. в одной из будущих глав: [FastAPI внутри контейнеров — Docker](docker.md). /// @@ -281,7 +281,7 @@ /// tip | Совет -Я приведу более конкретные примеры с контейнерами в следующей главе: [FastAPI внутри контейнеров — Docker](docker.md). +Я приведу более конкретные примеры с контейнерами в одной из будущих глав: [FastAPI внутри контейнеров — Docker](docker.md). /// @@ -301,9 +301,9 @@ Также возможен **всплеск** использования вашего API: он мог «взорваться» по популярности, или какие‑то сервисы/боты начали его активно использовать. На такие случаи стоит иметь запас ресурсов. -Можно задать **целевое значение**, например **между 50% и 90%** использования ресурсов. Скорее всего, именно эти вещи вы будете измерять и на их основе настраивать развёртывание. +Можно задать **произвольное число** в качестве цели, например **между 50% и 90%** использования ресурсов. Скорее всего, именно эти вещи вы будете измерять и на их основе настраивать развёртывание. -Можно использовать простые инструменты вроде `htop`, чтобы смотреть загрузку CPU и RAM на сервере или по процессам. Или более сложные распределённые системы мониторинга. +Можно использовать простые инструменты вроде `htop`, чтобы смотреть загрузку CPU и RAM на сервере или по процессам. Или более сложные инструменты мониторинга, которые могут быть распределены по серверам и т.п. ## Резюме { #recap } diff --git a/docs/ru/docs/deployment/docker.md b/docs/ru/docs/deployment/docker.md index 50147750e..c3cf9a328 100644 --- a/docs/ru/docs/deployment/docker.md +++ b/docs/ru/docs/deployment/docker.md @@ -275,7 +275,7 @@ CMD fastapi run app/main.py --port 80 #### За прокси-сервером TSL-терминации { #behind-a-tls-termination-proxy } -Если вы запускаете контейнер за прокси-сервером TSL-терминации (балансировщиком нагрузки), таким как Nginx или Traefik, добавьте опцию `--proxy-headers`. Это сообщит Uvicorn (через FastAPI CLI), что приложение работает за HTTPS и можно доверять соответствующим заголовкам. +Если вы запускаете контейнер за прокси-сервером TSL-терминации (балансировщиком нагрузки), таким как Nginx или Traefik, добавьте опцию `--proxy-headers`. Это сообщит Uvicorn (через FastAPI CLI), что можно доверять заголовкам, отправленным этим прокси и сообщающим, что приложение работает за HTTPS, и т.д. ```Dockerfile CMD ["fastapi", "run", "app/main.py", "--proxy-headers", "--port", "80"] @@ -407,9 +407,9 @@ CMD ["fastapi", "run", "main.py", "--port", "80"] 1. Копируем файл `main.py` напрямую в `/code` (без директории `./app`). -2. Используем `fastapi run` для запуска приложения из одного файла `main.py`. +2. Используем `fastapi run`, чтобы «отдавать» приложение из одного файла `main.py`. -Когда вы передаёте файл в `fastapi run`, он автоматически определит, что это одиночный файл, а не часть пакета, и поймёт, как его импортировать и запустить ваше FastAPI-приложение. 😎 +Когда вы передаёте файл в `fastapi run`, он автоматически определит, что это одиночный файл, а не часть пакета, и поймёт, как импортировать и «отдавать» ваше FastAPI-приложение. 😎 ## Концепции развертывания { #deployment-concepts } @@ -525,7 +525,7 @@ CMD ["fastapi", "run", "app/main.py", "--port", "80", "--workers", "4"] Вы можете развёртывать на **одном сервере** (не кластере) с **Docker Compose**, и у вас не будет простого способа управлять репликацией контейнеров (в Docker Compose), сохраняя общую сеть и **балансировку нагрузки**. -Тогда вы можете захотеть **один контейнер** с **менеджером процессов**, который запускает **несколько воркеров** внутри. +Тогда вы можете захотеть **один контейнер** с **менеджером процессов**, который запускает **несколько воркер-процессов** внутри. --- @@ -566,7 +566,7 @@ CMD ["fastapi", "run", "app/main.py", "--port", "80", "--workers", "4"] ### Один контейнер { #single-container } -Если у вас простая схема с **одним контейнером**, который затем запускает несколько **воркеров** (или один процесс), можно выполнить подготовительные шаги в этом же контейнере непосредственно перед запуском процесса с приложением. +Если у вас простая схема с **одним контейнером**, который затем запускает несколько **воркер-процессов** (или один процесс), можно выполнить подготовительные шаги в этом же контейнере непосредственно перед запуском процесса с приложением. ### Базовый Docker-образ { #base-docker-image } @@ -580,7 +580,7 @@ CMD ["fastapi", "run", "app/main.py", "--port", "80", "--workers", "4"] /// note | Технические подробности -Этот Docker-образ был создан в то время, когда Uvicorn не умел управлять и перезапускать «упавших» воркеров, и приходилось использовать Gunicorn вместе с Uvicorn, что добавляло заметную сложность, лишь бы Gunicorn управлял и перезапускал воркеров Uvicorn. +Этот Docker-образ был создан в то время, когда Uvicorn не умел управлять и перезапускать «упавших» воркеров, и приходилось использовать Gunicorn вместе с Uvicorn, что добавляло заметную сложность, лишь бы Gunicorn управлял и перезапускал воркер-процессы Uvicorn. Но теперь, когда Uvicorn (и команда `fastapi`) поддерживают `--workers`, нет причин использовать базовый Docker-образ вместо сборки своего (кода получается примерно столько же 😅). @@ -615,4 +615,4 @@ CMD ["fastapi", "run", "app/main.py", "--port", "80", "--workers", "4"] В большинстве случаев вы, вероятно, не захотите использовать какой-либо базовый образ, а вместо этого **соберёте образ контейнера с нуля** на основе официального Docker-образа Python. -Заботясь о **порядке** инструкций в `Dockerfile` и используя **кэш Docker**, вы можете **минимизировать время сборки**, чтобы повысить продуктивность (и не скучать). 😎 +Заботясь о **порядке** инструкций в `Dockerfile` и используя **кэш Docker**, вы можете **минимизировать время сборки**, чтобы повысить продуктивность (и не скучать). 😎 diff --git a/docs/ru/docs/deployment/https.md b/docs/ru/docs/deployment/https.md index 181cac0d8..8c1b153f0 100644 --- a/docs/ru/docs/deployment/https.md +++ b/docs/ru/docs/deployment/https.md @@ -6,7 +6,7 @@ /// tip | Совет -Если вы торопитесь или вам это не важно, переходите к следующим разделам с пошаговыми инструкциями по настройке всего разными способами. +Если вы торопитесь или вам это не важно, продолжайте со следующих разделов с пошаговыми инструкциями по настройке всего разными способами. /// @@ -65,7 +65,7 @@ Чаще всего всё начинается с **приобретения** **имени домена**. Затем вы настраиваете его на DNS‑сервере (возможно, у того же облачного провайдера). -Скорее всего, вы получите облачный сервер (виртуальную машину) или что-то подобное, и у него будет постоянный **публичный IP-адрес**. +Скорее всего, вы получите облачный сервер (виртуальную машину) или что-то подобное, и у него будет постоянный **публичный IP-адрес**. На DNS‑сервере(ах) вы настроите запись («`A record`» - запись типа A), указывающую, что **ваш домен** должен указывать на публичный **IP‑адрес вашего сервера**. @@ -194,7 +194,7 @@ DNS‑серверы ответят браузеру, какой **конкре Когда вы используете прокси для обработки HTTPS, ваш **сервер приложения** (например, Uvicorn через FastAPI CLI) ничего не знает о процессе HTTPS, он общается обычным HTTP с **прокси‑сервером TLS-терминации**. -Обычно этот **прокси** на лету добавляет некоторые HTTP‑заголовки перед тем, как переслать запрос на **сервер приложения**, чтобы тот знал, что запрос был **проксирован**. +Обычно этот **прокси** на лету добавляет некоторые HTTP‑заголовки перед тем, как переслать запрос на **сервер приложения**, чтобы тот знал, что запрос был **переслан** прокси. /// note | Технические детали @@ -218,7 +218,7 @@ DNS‑серверы ответят браузеру, какой **конкре /// tip | Совет -Подробнее об этом вы можете узнать в документации: [За прокси — Включить пересылаемые заголовки прокси](../advanced/behind-a-proxy.md#enable-proxy-forwarded-headers) +Подробнее об этом вы можете узнать в документации: [За прокси — включить пересылаемые заголовки прокси](../advanced/behind-a-proxy.md#enable-proxy-forwarded-headers) /// diff --git a/docs/ru/docs/deployment/manually.md b/docs/ru/docs/deployment/manually.md index db5581ae5..e6408c944 100644 --- a/docs/ru/docs/deployment/manually.md +++ b/docs/ru/docs/deployment/manually.md @@ -2,7 +2,7 @@ ## Используйте команду `fastapi run` { #use-the-fastapi-run-command } -Коротко: используйте `fastapi run`, чтобы запустить ваше приложение FastAPI: +Коротко: используйте `fastapi run`, чтобы предоставлять доступ к вашему приложению FastAPI:
diff --git a/docs/ru/docs/editor-support.md b/docs/ru/docs/editor-support.md index 0543e7162..cd02c0f40 100644 --- a/docs/ru/docs/editor-support.md +++ b/docs/ru/docs/editor-support.md @@ -20,4 +20,4 @@ - **Развернуть в FastAPI Cloud** — развертывание вашего приложения в один клик в [FastAPI Cloud](https://fastapicloud.com/). - **Поток логов приложения** — потоковая передача логов в реальном времени из вашего приложения, развернутого в FastAPI Cloud, с фильтрацией по уровню и текстовым поиском. -Если вы хотите поверхностно ознакомиться с возможностями расширения, откройте палитру команд (Ctrl + Shift + P или на macOS: Cmd + Shift + P), выберите «Welcome: Open walkthrough...», а затем «Get started with FastAPI». +Если вы хотите ознакомиться с возможностями расширения, вы можете посмотреть walkthrough расширения, открыв палитру команд (Ctrl + Shift + P или на macOS: Cmd + Shift + P) и выбрав «Welcome: Open walkthrough...», а затем walkthrough «Get started with FastAPI». diff --git a/docs/ru/docs/environment-variables.md b/docs/ru/docs/environment-variables.md index 8db16d16c..3cd0bc78b 100644 --- a/docs/ru/docs/environment-variables.md +++ b/docs/ru/docs/environment-variables.md @@ -50,9 +50,9 @@ Hello Wade Wilson //// -## Чтение переменных окружения в python { #read-env-vars-in-python } +## Чтение переменных окружения в Python { #read-env-vars-in-python } -Так же существует возможность создания переменных окружения **вне** Python, в терминале (или любым другим способом), а затем **чтения их в Python**. +Также существует возможность создания переменных окружения **вне** Python, в терминале (или любым другим способом), а затем **чтения их в Python**. Например, у вас есть файл `main.py`: @@ -67,7 +67,7 @@ print(f"Hello {name} from Python") Второй аргумент [`os.getenv()`](https://docs.python.org/3.8/library/os.html#os.getenv) - это возвращаемое по умолчанию значение. -Если значение не указано, то по умолчанию оно равно `None`. В данном случае мы указываем `«World»` в качестве значения по умолчанию. +Если значение не указано, то по умолчанию оно равно `None`. В данном случае мы указываем `"World"` в качестве значения по умолчанию. /// @@ -157,13 +157,13 @@ Hello World from Python /// -## Типизация и Валидация { #types-and-validation } +## Типы и валидация { #types-and-validation } Эти переменные окружения могут работать только с **текстовыми строками**, поскольку они являются внешними по отношению к Python и должны быть совместимы с другими программами и остальной системой (и даже с различными операционными системами, такими как Linux, Windows, macOS). Это означает, что **любое значение**, считанное в Python из переменной окружения, **будет `str`**, и любое преобразование к другому типу или любая валидация должны быть выполнены в коде. -Подробнее об использовании переменных окружения для работы с **настройками приложения** вы узнаете в [Расширенное руководство пользователя - Настройки и переменные среды](./advanced/settings.md). +Подробнее об использовании переменных окружения для работы с **настройками приложения** вы узнаете в [Расширенном руководстве пользователя - Настройки и переменные окружения](./advanced/settings.md). ## Переменная окружения `PATH` { #path-environment-variable } @@ -285,14 +285,14 @@ $ C:\opt\custompython\bin\python //// -Эта информация будет полезна при изучении [Виртуальных окружений](virtual-environments.md). +Эта информация будет полезна при изучении [виртуальных окружений](virtual-environments.md). ## Вывод { #conclusion } Благодаря этому вы должны иметь базовое представление о том, что такое **переменные окружения** и как использовать их в Python. -Подробнее о них вы также можете прочитать в [статье о переменных окружения на википедии](https://en.wikipedia.org/wiki/Environment_variable). +Подробнее о них вы также можете прочитать в [статье о переменных окружения на Википедии](https://en.wikipedia.org/wiki/Environment_variable). Во многих случаях не всегда очевидно, как переменные окружения могут быть полезны и применимы. Но они постоянно появляются в различных сценариях разработки, поэтому знать о них полезно. -Например, эта информация понадобится вам в следующем разделе, посвященном [Виртуальным окружениям](virtual-environments.md). +Например, эта информация понадобится вам в следующем разделе, посвященном [виртуальным окружениям](virtual-environments.md). diff --git a/docs/ru/docs/features.md b/docs/ru/docs/features.md index 9755c3fe5..25bbe850c 100644 --- a/docs/ru/docs/features.md +++ b/docs/ru/docs/features.md @@ -17,7 +17,7 @@ * [**Swagger UI**](https://github.com/swagger-api/swagger-ui), с интерактивным исследованием, вызовом и тестированием вашего API прямо из браузера. -![Swagger UI interaction](https://fastapi.tiangolo.com/img/index/index-03-swagger-02.png) +![Взаимодействие со Swagger UI](https://fastapi.tiangolo.com/img/index/index-03-swagger-02.png) * Альтернативная документация API в [**ReDoc**](https://github.com/Rebilly/ReDoc). @@ -36,7 +36,7 @@ from datetime import date from pydantic import BaseModel -# Объявляем параметр как `str` +# Объявляем переменную как `str` # и получаем поддержку редактора кода внутри функции def main(user_id: str): return user_id @@ -71,9 +71,9 @@ my_second_user: User = User(**second_user_data) /// -### Поддержка редакторов { #editor-support } +### Поддержка редакторов кода { #editor-support } -Весь фреймворк был продуман так, чтобы быть простым и интуитивно понятным в использовании, все решения были проверены на множестве редакторов еще до начала разработки, чтобы обеспечить наилучшие условия при написании кода. +Весь фреймворк был продуман так, чтобы быть простым и интуитивно понятным в использовании, все решения были проверены на множестве редакторов кода еще до начала разработки, чтобы обеспечить наилучшие условия при написании кода. В опросах Python‑разработчиков видно, [что одной из самых часто используемых функций является «автозавершение»](https://www.jetbrains.com/research/python-developers-survey-2017/#tools-and-features). @@ -81,15 +81,15 @@ my_second_user: User = User(**second_user_data) Вам редко нужно будет возвращаться к документации. -Вот как ваш редактор может вам помочь: +Вот как ваш редактор кода может вам помочь: * в [Visual Studio Code](https://code.visualstudio.com/): -![editor support](https://fastapi.tiangolo.com/img/vscode-completion.png) +![поддержка редактора кода](https://fastapi.tiangolo.com/img/vscode-completion.png) * в [PyCharm](https://www.jetbrains.com/pycharm/): -![editor support](https://fastapi.tiangolo.com/img/pycharm-completion.png) +![поддержка редактора кода](https://fastapi.tiangolo.com/img/pycharm-completion.png) Вы будете получать автозавершение кода даже там, где вы считали это невозможным раньше. Как пример, ключ `price` внутри тела JSON (который может быть вложенным), приходящего в запросе. @@ -151,11 +151,11 @@ FastAPI включает в себя чрезвычайно простую в и Любая интеграция разработана настолько простой в использовании (с зависимостями), что вы можете создать «плагин» для своего приложения в пару строк кода, используя ту же структуру и синтаксис, что и для ваших *операций пути*. -### Проверен { #tested } +### Протестирован { #tested } -* 100% покрытие тестами. +* 100% покрытие тестами. * 100% аннотирование типов в кодовой базе. -* Используется в продакшн‑приложениях. +* Используется в приложениях в продакшн. ## Возможности Starlette { #starlette-features } @@ -190,7 +190,7 @@ FastAPI включает в себя чрезвычайно простую в и * **Никакой нервотрёпки**: * Не нужно изучать новые схемы в микроязыках. * Если вы знаете типы в Python, вы знаете, как использовать Pydantic. -* Прекрасно сочетается с вашим **IDE/линтер/мозгом**: +* Прекрасно сочетается с вашим **IDE/линтер/мозгом**: * Потому что структуры данных pydantic — это всего лишь экземпляры классов, определённых вами; автозавершение, проверка кода, mypy и ваша интуиция — всё будет работать с вашими валидированными данными. * Валидация **сложных структур**: * Использование иерархических моделей Pydantic; `List`, `Dict` и т.п. из модуля `typing`. diff --git a/docs/ru/docs/help-fastapi.md b/docs/ru/docs/help-fastapi.md index f9b9ebea3..ff47b93e8 100644 --- a/docs/ru/docs/help-fastapi.md +++ b/docs/ru/docs/help-fastapi.md @@ -38,7 +38,7 @@ ## Подписаться на автора { #follow-the-author } -Вы можете подписаться на [меня (Sebastián Ramírez / `tiangolo`)](https://tiangolo.com) в нескольких местах, чтобы узнавать новости о FastAPI и друзьях: +Вы можете подписаться на [меня (Sebastián Ramírez / `tiangolo`)](https://tiangolo.com), автора, в нескольких местах, чтобы узнавать новости о FastAPI и друзьях: * [@tiangolo в **GitHub**](https://github.com/tiangolo). * [@tiangolo в **X (Twitter)**](https://x.com/tiangolo) diff --git a/docs/ru/docs/how-to/configure-swagger-ui.md b/docs/ru/docs/how-to/configure-swagger-ui.md index b57a086b6..0dd60b423 100644 --- a/docs/ru/docs/how-to/configure-swagger-ui.md +++ b/docs/ru/docs/how-to/configure-swagger-ui.md @@ -26,7 +26,7 @@ FastAPI преобразует эти настройки в **JSON**, чтобы ## Изменить тему { #change-the-theme } -Аналогично вы можете задать тему подсветки синтаксиса с ключом "syntaxHighlight.theme" (обратите внимание, что посередине стоит точка): +Аналогично вы можете задать тему подсветки синтаксиса с ключом `"syntaxHighlight.theme"` (обратите внимание, что посередине стоит точка): {* ../../docs_src/configure_swagger_ui/tutorial002_py310.py hl[3] *} diff --git a/docs/ru/docs/how-to/custom-request-and-route.md b/docs/ru/docs/how-to/custom-request-and-route.md index 1e3a60856..6a7ecbca9 100644 --- a/docs/ru/docs/how-to/custom-request-and-route.md +++ b/docs/ru/docs/how-to/custom-request-and-route.md @@ -18,13 +18,13 @@ Некоторые сценарии: -* Преобразование тел запросов, не в формате JSON, в JSON (например, [`msgpack`](https://msgpack.org/index.html)). +* Преобразование тел запросов не в формате JSON в JSON (например, [`msgpack`](https://msgpack.org/index.html)). * Распаковка тел запросов, сжатых с помощью gzip. * Автоматическое логирование всех тел запросов. ## Обработка пользовательского кодирования тела запроса { #handling-custom-request-body-encodings } -Посмотрим как использовать пользовательский подкласс `Request` для распаковки gzip-запросов. +Посмотрим, как использовать пользовательский подкласс `Request` для распаковки gzip-запросов. И подкласс `APIRoute`, чтобы использовать этот пользовательский класс запроса. @@ -38,9 +38,9 @@ Сначала создадим класс `GzipRequest`, который переопределит метод `Request.body()` и распакует тело запроса при наличии соответствующего HTTP-заголовка. -Если в заголовке нет `gzip`, он не будет пытаться распаковывать тело. +Если в HTTP-заголовке нет `gzip`, он не будет пытаться распаковывать тело. -Таким образом, один и тот же класс маршрута сможет обрабатывать как gzip-сжатые, так и несжатые запросы. +Таким образом, один и тот же класс маршрута сможет обрабатывать как gzip-сжатые, так и несжатые HTTP-запросы. {* ../../docs_src/custom_request_and_route/tutorial001_an_py310.py hl[9:16] *} @@ -90,7 +90,7 @@ Тем же подходом можно воспользоваться, чтобы получить доступ к телу запроса в обработчике исключений. -Нужно лишь обработать запрос внутри блока `try`/`except`: +Нужно лишь обработать HTTP-запрос внутри блока `try`/`except`: {* ../../docs_src/custom_request_and_route/tutorial002_an_py310.py hl[14,16] *} @@ -104,6 +104,6 @@ {* ../../docs_src/custom_request_and_route/tutorial003_py310.py hl[26] *} -В этом примере *операции пути*, объявленные в `router`, будут использовать пользовательский класс `TimedRoute` и получат дополнительный HTTP-заголовок `X-Response-Time` в ответе с временем, затраченным на формирование ответа: +В этом примере *операции пути*, объявленные в `router`, будут использовать пользовательский класс `TimedRoute` и получат дополнительный HTTP-заголовок `X-Response-Time` в HTTP-ответе с временем, затраченным на формирование HTTP-ответа: {* ../../docs_src/custom_request_and_route/tutorial003_py310.py hl[13:20] *} diff --git a/docs/ru/docs/how-to/graphql.md b/docs/ru/docs/how-to/graphql.md index 1829a211c..880fca2a2 100644 --- a/docs/ru/docs/how-to/graphql.md +++ b/docs/ru/docs/how-to/graphql.md @@ -1,5 +1,6 @@ # GraphQL { #graphql } + Так как **FastAPI** основан на стандарте **ASGI**, очень легко интегрировать любую библиотеку **GraphQL**, также совместимую с ASGI. Вы можете комбинировать обычные *операции пути* FastAPI с GraphQL в одном приложении. diff --git a/docs/ru/docs/how-to/migrate-from-pydantic-v1-to-pydantic-v2.md b/docs/ru/docs/how-to/migrate-from-pydantic-v1-to-pydantic-v2.md index 46b4071da..e32192656 100644 --- a/docs/ru/docs/how-to/migrate-from-pydantic-v1-to-pydantic-v2.md +++ b/docs/ru/docs/how-to/migrate-from-pydantic-v1-to-pydantic-v2.md @@ -8,6 +8,8 @@ FastAPI версии 0.119.0 добавил частичную поддержк FastAPI 0.126.0 убрал поддержку Pydantic v1, при этом ещё некоторое время продолжал поддерживать `pydantic.v1`. +FastAPI 0.128.0 также убрал поддержку `pydantic.v1`, так что последние версии FastAPI требуют Pydantic v2. + /// warning | Предупреждение Команда Pydantic прекратила поддержку Pydantic v1 для последних версий Python, начиная с **Python 3.14**. @@ -54,6 +56,16 @@ Pydantic v2 включает всё из Pydantic v1 как подмодуль ` ### Поддержка FastAPI для Pydantic v1 внутри v2 { #fastapi-support-for-pydantic-v1-in-v2 } +/// warning | Предупреждение + +Эта поддержка FastAPI для моделей `pydantic.v1` была добавлена в **FastAPI 0.119.0** и удалена в **FastAPI 0.128.0**. Она задумывалась как временная помощь при миграции на Pydantic v2. + +В текущих версиях FastAPI использование модели `pydantic.v1` в вашем приложении вызовет ошибку. + +Остальная часть этого раздела описывает временную поддержку, доступную только в этих старых версиях. + +/// + Начиная с FastAPI 0.119.0, есть также частичная поддержка Pydantic v1 изнутри Pydantic v2, чтобы упростить миграцию на v2. Таким образом, вы можете обновить Pydantic до последней версии 2 и сменить импорты на подмодуль `pydantic.v1` — во многих случаях всё просто заработает. @@ -122,6 +134,12 @@ graph TB ### Мигрируйте по шагам { #migrate-in-steps } +/// warning | Предупреждение + +Постепенная миграция с использованием моделей Pydantic v1 и v2 в одном приложении, описанная ниже, работает только в **FastAPI 0.119.0 до 0.127.x**. Она была удалена в **FastAPI 0.128.0**, последние версии требуют модели **Pydantic v2**. + +/// + /// tip | Совет Сначала попробуйте `bump-pydantic`: если тесты проходят и всё работает, вы справились одной командой. ✨ diff --git a/docs/ru/docs/how-to/separate-openapi-schemas.md b/docs/ru/docs/how-to/separate-openapi-schemas.md index 3e0830891..32a056fd2 100644 --- a/docs/ru/docs/how-to/separate-openapi-schemas.md +++ b/docs/ru/docs/how-to/separate-openapi-schemas.md @@ -1,6 +1,6 @@ # Разделять схемы OpenAPI для входа и выхода или нет { #separate-openapi-schemas-for-input-and-output-or-not } -При использовании **Pydantic v2** сгенерированный OpenAPI становится чуть более точным и **корректным**, чем раньше. 😎 +С момента выхода **Pydantic v2** сгенерированный OpenAPI становится чуть более точным и **корректным**, чем раньше. 😎 На самом деле, в некоторых случаях в OpenAPI будет даже **две JSON-схемы** для одной и той же Pydantic‑модели: для входа и для выхода — в зависимости от наличия **значений по умолчанию**. diff --git a/docs/ru/docs/index.md b/docs/ru/docs/index.md index 1b6f3d40a..717d5d783 100644 --- a/docs/ru/docs/index.md +++ b/docs/ru/docs/index.md @@ -57,7 +57,7 @@ FastAPI — это современный, быстрый (высокопрои -### Ключевой-спонсор { #keystone-sponsor } +### Ключевой спонсор { #keystone-sponsor }
{% for sponsor in sponsors.keystone -%} @@ -161,7 +161,7 @@ FastAPI — это современный, быстрый (высокопрои В конце 2025 года вышел [мини-документальный фильм о FastAPI](https://www.youtube.com/watch?v=mpR8ngthqiE), вы можете посмотреть его онлайн: -FastAPI Mini Documentary +Мини-документальный фильм о FastAPI ## **Typer**, FastAPI для CLI { #typer-the-fastapi-of-clis } @@ -364,11 +364,11 @@ def update_item(item_id: int, item: Item): * Нажмите кнопку «Try it out», это позволит вам заполнить параметры и напрямую взаимодействовать с API: -![Swagger UI interaction](https://fastapi.tiangolo.com/img/index/index-04-swagger-03.png) +![Взаимодействие со Swagger UI](https://fastapi.tiangolo.com/img/index/index-04-swagger-03.png) * Затем нажмите кнопку «Execute», интерфейс свяжется с вашим API, отправит параметры, получит результаты и отобразит их на экране: -![Swagger UI interaction](https://fastapi.tiangolo.com/img/index/index-05-swagger-04.png) +![Взаимодействие со Swagger UI](https://fastapi.tiangolo.com/img/index/index-05-swagger-04.png) ### Обновление альтернативной документации API { #alternative-api-docs-upgrade } @@ -471,7 +471,7 @@ item: Item ...и посмотрите, как ваш редактор кода будет автоматически дополнять атрибуты и знать их типы: -![editor support](https://fastapi.tiangolo.com/img/vscode-completion.png) +![Поддержка редактора кода](https://fastapi.tiangolo.com/img/vscode-completion.png) Более полный пример с дополнительными возможностями см. в Учебник - Руководство пользователя. @@ -524,7 +524,7 @@ FastAPI Cloud — основной спонсор и источник финан #### Развертывание у других облачных провайдеров { #deploy-to-other-cloud-providers } -FastAPI — это open source и стандартизированный фреймворк. Вы можете развернуть приложения FastAPI у любого облачного провайдера на ваш выбор. +FastAPI — это проект с открытым исходным кодом, основанный на стандартах. Вы можете развернуть приложения FastAPI у любого облачного провайдера на ваш выбор. Следуйте руководствам вашего облачного провайдера по развертыванию приложений FastAPI. 🤓 @@ -544,7 +544,7 @@ FastAPI зависит от Pydantic и Starlette. Используется Pydantic: -* [`email-validator`](https://github.com/JoshData/python-email-validator) — для проверки адресов электронной почты. +* [`email-validator`](https://github.com/JoshData/python-email-validator) — для валидации адресов электронной почты. Используется Starlette: diff --git a/docs/ru/docs/project-generation.md b/docs/ru/docs/project-generation.md index 7a46b210d..abcc78edb 100644 --- a/docs/ru/docs/project-generation.md +++ b/docs/ru/docs/project-generation.md @@ -20,9 +20,9 @@ - 🦇 Поддержка тёмной темы. - 🐋 [Docker Compose](https://www.docker.com) для разработки и продакшн. - 🔒 Безопасное хэширование паролей по умолчанию. -- 🔑 Аутентификация по JWT‑токенам. +- 🔑 Аутентификация JWT (JSON Web Token). - 📫 Восстановление пароля по электронной почте. - ✅ Тесты с [Pytest](https://pytest.org). - 📞 [Traefik](https://traefik.io) в роли обратного прокси / балансировщика нагрузки. - 🚢 Инструкции по развёртыванию с использованием Docker Compose, включая настройку фронтенд‑прокси Traefik для автоматического получения сертификатов HTTPS. -- 🏭 CI (continuous integration) и CD (continuous deployment) на основе GitHub Actions. +- 🏭 CI (непрерывная интеграция) и CD (непрерывное развертывание) на основе GitHub Actions. diff --git a/docs/ru/docs/python-types.md b/docs/ru/docs/python-types.md index 4afdad935..4791899b1 100644 --- a/docs/ru/docs/python-types.md +++ b/docs/ru/docs/python-types.md @@ -1,20 +1,20 @@ # Введение в типы Python { #python-types-intro } -Python поддерживает необязательные «подсказки типов» (их также называют «аннотациями типов»). +Python поддерживает необязательные «аннотации типов» (также называемые «подсказками типов»). -Эти **«подсказки типов»** или аннотации — это специальный синтаксис, позволяющий объявлять тип переменной. +Эти **«аннотации типов»**, или просто аннотации, — это специальный синтаксис, позволяющий объявлять тип переменной. Объявляя типы для ваших переменных, редакторы кода и инструменты смогут лучше вас поддерживать. -Это всего лишь **краткое руководство / напоминание** о подсказках типов в Python. Оно охватывает только минимум, необходимый для их использования с **FastAPI**... что на самом деле очень мало. +Это всего лишь **краткое руководство / напоминание** об аннотациях типов в Python. Оно охватывает только минимум, необходимый для их использования с **FastAPI**... что на самом деле очень мало. -**FastAPI** целиком основан на этих подсказках типов — они дают ему множество преимуществ и выгод. +**FastAPI** целиком основан на этих аннотациях типов — они дают ему множество преимуществ и выгод. Но даже если вы никогда не используете **FastAPI**, вам будет полезно немного узнать о них. /// note | Примечание -Если вы являетесь экспертом в Python и уже знаете всё о подсказках типов, переходите к следующей главе. +Если вы являетесь экспертом в Python и уже знаете всё об аннотациях типов, переходите к следующей главе. /// @@ -76,7 +76,7 @@ John Doe Вот и всё. -Это и есть «подсказки типов»: +Это и есть «аннотации типов»: {* ../../docs_src/python_types/tutorial002_py310.py hl[1] *} @@ -90,9 +90,9 @@ John Doe Здесь мы используем двоеточия (`:`), а не знак равенства (`=`). -И добавление подсказок типов обычно не меняет поведение программы по сравнению с вариантом без них. +И добавление аннотаций типов обычно не меняет поведение программы по сравнению с вариантом без них. -Но теперь представьте, что вы снова посередине написания этой функции, только уже с подсказками типов. +Но теперь представьте, что вы снова посередине написания этой функции, только уже с аннотациями типов. В тот же момент вы пробуете вызвать автозавершение с помощью `Ctrl+Space` — и видите: @@ -104,7 +104,7 @@ John Doe ## Больше мотивации { #more-motivation } -Посмотрите на эту функцию — у неё уже есть подсказки типов: +Посмотрите на эту функцию — у неё уже есть аннотации типов: {* ../../docs_src/python_types/tutorial003_py310.py hl[1] *} @@ -118,7 +118,7 @@ John Doe ## Объявление типов { #declaring-types } -Вы только что увидели основное место, где объявляют подсказки типов — параметры функции. +Вы только что увидели основное место, где объявляют аннотации типов — параметры функции. Это также основное место, где вы будете использовать их с **FastAPI**. @@ -293,9 +293,9 @@ def some_function(data: Any): Вы увидите намного больше всего этого на практике в [Учебник - Руководство пользователя](tutorial/index.md). -## Подсказки типов с аннотациями метаданных { #type-hints-with-metadata-annotations } +## Аннотации типов с аннотациями метаданных { #type-hints-with-metadata-annotations } -В Python также есть возможность добавлять **дополнительные метаданные** к подсказкам типов с помощью `Annotated`. +В Python также есть возможность добавлять **дополнительные метаданные** к аннотациям типов с помощью `Annotated`. Вы можете импортировать `Annotated` из `typing`. @@ -321,16 +321,16 @@ def some_function(data: Any): ## Аннотации типов в **FastAPI** { #type-hints-in-fastapi } -**FastAPI** использует эти подсказки типов для выполнения нескольких задач. +**FastAPI** использует эти аннотации типов для выполнения нескольких задач. -С **FastAPI** вы объявляете параметры с подсказками типов и получаете: +С **FastAPI** вы объявляете параметры с аннотациями типов и получаете: * **Поддержку редактора кода**. * **Проверки типов**. ...и **FastAPI** использует эти же объявления для: -* **Определения требований**: из path-параметров пути запроса, query-параметров, HTTP-заголовков, тел запросов, зависимостей и т.д. +* **Определения требований**: из path-параметров HTTP-запроса, query-параметров, HTTP-заголовков, тел запросов, зависимостей и т.д. * **Преобразования данных**: из HTTP-запроса к требуемому типу. * **Валидации данных**: приходящих с каждого HTTP-запроса: * Генерации **автоматических ошибок**, возвращаемых клиенту, когда данные некорректны. diff --git a/docs/ru/docs/tutorial/bigger-applications.md b/docs/ru/docs/tutorial/bigger-applications.md index 2c7784f22..038777b0c 100644 --- a/docs/ru/docs/tutorial/bigger-applications.md +++ b/docs/ru/docs/tutorial/bigger-applications.md @@ -17,16 +17,16 @@ ``` . ├── app -│   ├── __init__.py -│   ├── main.py -│   ├── dependencies.py -│   └── routers -│   │ ├── __init__.py -│   │ ├── items.py -│   │ └── users.py -│   └── internal -│   ├── __init__.py -│   └── admin.py +│ ├── __init__.py +│ ├── main.py +│ ├── dependencies.py +│ └── routers +│ │ ├── __init__.py +│ │ ├── items.py +│ │ └── users.py +│ └── internal +│ ├── __init__.py +│ └── admin.py ``` /// tip | Подсказка @@ -58,16 +58,16 @@ from app.routers import items ```bash . -├── app # "app" пакет +├── app # "app" — Python-пакет │   ├── __init__.py # этот файл превращает "app" в "Python-пакет" │   ├── main.py # модуль "main", напр.: import app.main │   ├── dependencies.py # модуль "dependencies", напр.: import app.dependencies -│   └── routers # подпакет "routers" -│   │ ├── __init__.py # превращает "routers" в подпакет +│   └── routers # "routers" — "Python-подпакет" +│   │ ├── __init__.py # превращает "routers" в "Python-подпакет" │   │ ├── items.py # подмодуль "items", напр.: import app.routers.items │   │ └── users.py # подмодуль "users", напр.: import app.routers.users -│   └── internal # подпакет "internal" -│   ├── __init__.py # превращает "internal" в подпакет +│   └── internal # "internal" — "Python-подпакет" +│   ├── __init__.py # превращает "internal" в "Python-подпакет" │   └── admin.py # подмодуль "admin", напр.: import app.internal.admin ``` @@ -121,7 +121,7 @@ from app.routers import items /// tip | Подсказка -Для простоты мы воспользовались выдуманным заголовком. +Для простоты мы воспользовались выдуманным HTTP-заголовком. В реальных случаях для получения наилучших результатов используйте интегрированные [утилиты безопасности](security/index.md). @@ -163,9 +163,9 @@ async def read_item(item_id: str): В нашем случае префиксом является `/items`. -Мы также можем добавить список `tags` и дополнительные `responses`, которые будут применяться ко всем *операциям пути*, включённым в этот маршрутизатор. +Мы также можем добавить список `tags` и дополнительные `responses`, которые будут применяться ко всем *операциям пути*, включённым в этот роутер. -И ещё мы можем добавить список `dependencies`, которые будут добавлены ко всем *операциям пути* в маршрутизаторе и будут выполняться/разрешаться для каждого HTTP-запроса к ним. +И ещё мы можем добавить список `dependencies`, которые будут добавлены ко всем *операциям пути* в роутере и будут выполняться/разрешаться для каждого HTTP-запроса к ним. /// tip | Подсказка @@ -185,7 +185,7 @@ async def read_item(item_id: str): * Все они будут включать предопределённые `responses`. * Все эти *операции пути* будут иметь список `dependencies`, вычисляемых/выполняемых перед ними. * Если вы также объявите зависимости в конкретной *операции пути*, **они тоже будут выполнены**. - * Сначала выполняются зависимости маршрутизатора, затем [`dependencies` в декораторе](dependencies/dependencies-in-path-operation-decorators.md), и затем обычные параметрические зависимости. + * Сначала выполняются зависимости роутера, затем [`dependencies` в декораторе](dependencies/dependencies-in-path-operation-decorators.md), и затем обычные параметрические зависимости. * Вы также можете добавить [`Security`-зависимости с `scopes`](../advanced/security/oauth2-scopes.md). /// tip | Подсказка @@ -263,7 +263,7 @@ from ...dependencies import get_token_header то это бы означало: -* Начать в том же пакете, в котором находится этот модуль (файл `app/routers/items.py`) расположен в (каталоге `app/routers/`)... +* Начать в том же пакете, в котором находится этот модуль (файл `app/routers/items.py`) (каталог `app/routers/`)... * перейти в родительский пакет (каталог `app/`)... * затем перейти в родительский пакет этого пакета (родительского пакета нет, `app` — верхний уровень 😱)... * и там найти модуль `dependencies` (файл `app/dependencies.py`)... @@ -285,7 +285,7 @@ from ...dependencies import get_token_header Эта последняя операция пути будет иметь комбинацию тегов: `["items", "custom"]`. -И в документации у неё будут оба ответа: один для `404` и один для `403`. +И в документации у неё будут оба HTTP-ответа: один для `404` и один для `403`. /// @@ -325,7 +325,7 @@ from .routers import items, users означает: -* Начать в том же пакете, в котором находится этот модуль (файл `app/main.py`) расположен в (каталоге `app/`)... +* Начать в том же пакете, в котором находится этот модуль (файл `app/main.py`) (каталог `app/`)... * найти подпакет `routers` (каталог `app/routers/`)... * и импортировать из него подмодули `items` (файл `app/routers/items.py`) и `users` (файл `app/routers/users.py`)... @@ -392,19 +392,19 @@ from .routers.users import router С помощью `app.include_router()` мы можем добавить каждый `APIRouter` в основное приложение `FastAPI`. -Он включит все маршруты этого маршрутизатора как часть приложения. +Он включит все маршруты этого роутера как часть приложения. /// note | Технические детали -FastAPI сохраняет исходный `APIRouter` и его `APIRoute` активными, когда маршрутизатор включается в основное приложение. +FastAPI сохраняет исходный `APIRouter` и его `APIRoute` активными, когда роутер включается в основное приложение. -Это означает, что пользовательские подклассы `APIRouter` и `APIRoute` по-прежнему участвуют после подключения маршрутизатора. +Это означает, что пользовательские подклассы `APIRouter` и `APIRoute` по-прежнему участвуют после подключения роутера. /// /// tip | Подсказка -При подключении маршрутизаторов не нужно беспокоиться о производительности. +При подключении роутеров не нужно беспокоиться о производительности. Это сделано максимально лёгким и не добавляет накладных расходов на каждый запрос. @@ -435,7 +435,7 @@ FastAPI сохраняет исходный `APIRouter` и его `APIRoute` а * Префикс `/admin`. * Тег `admin`. * Зависимость `get_token_header`. -* Ответ `418`. 🍵 +* HTTP-ответ `418`. 🍵 Но это повлияет только на этот `APIRouter` в нашем приложении, а не на любой другой код, который его использует. @@ -461,7 +461,7 @@ FastAPI сохраняет исходный `APIRouter` и его `APIRoute` а Это потому, что мы хотим включить их *операции пути* в схему OpenAPI и пользовательские интерфейсы. -FastAPI сохраняет исходные маршрутизаторы и операции пути активными и комбинирует префиксы маршрутизаторов, зависимости, теги, ответы и другие метаданные при обработке запросов и генерации OpenAPI. +FastAPI сохраняет исходные роутеры и операции пути активными и комбинирует префиксы роутеров, зависимости, теги, HTTP-ответы и другие метаданные при обработке HTTP-запросов и генерации OpenAPI. /// @@ -516,9 +516,9 @@ $ fastapi dev -## Подключение одного и того же маршрутизатора несколько раз с разными `prefix` { #include-the-same-router-multiple-times-with-different-prefix } +## Подключение одного и того же роутера несколько раз с разными `prefix` { #include-the-same-router-multiple-times-with-different-prefix } -Вы можете использовать `.include_router()` несколько раз с *одним и тем же* маршрутизатором, используя разные префиксы. +Вы можете использовать `.include_router()` несколько раз с *одним и тем же* роутером, используя разные префиксы. Это может быть полезно, например, чтобы предоставить доступ к одному и тому же API с разными префиксами, например `/api/v1` и `/api/latest`. @@ -534,14 +534,14 @@ router.include_router(other_router) Вы можете сделать это до или после подключения `router` к приложению `FastAPI`. FastAPI всё равно включит *операции пути* из `other_router` в маршрутизацию и OpenAPI. -То же относится к *операциям пути*, добавленным позже в маршрутизаторы. Они также будут видны через более раннее включение. +То же относится к *операциям пути*, добавленным позже в роутеры. Они также будут видны через более раннее включение. /// warning | Технические детали -Избегайте прямой мутации `router.routes` после включения маршрутизатора. FastAPI рассматривает включение маршрутизатора как «живое», поэтому исходный маршрутизатор и его маршруты остаются частью маршрутизации и генерации OpenAPI. +Избегайте прямой мутации `router.routes` после включения роутера. FastAPI рассматривает включение роутера как «живое», поэтому исходный роутер и его маршруты остаются частью маршрутизации и генерации OpenAPI. -Используйте документированные API, такие как декораторы операций пути и `.include_router()`, чтобы добавлять маршруты и маршрутизаторы. +Используйте документированные API, такие как декораторы операций пути и `.include_router()`, чтобы добавлять маршруты и роутеры. -Считайте `router.routes` низкоуровневым деревом маршрутов, которое может содержать определения маршрутов и включённые маршрутизаторы, и избегайте воспринимать его как плоский список итоговых операций пути. +Считайте `router.routes` низкоуровневым деревом маршрутов, которое может содержать определения маршрутов и включённые роутеры, и избегайте воспринимать его как плоский список итоговых операций пути. /// diff --git a/docs/ru/docs/tutorial/body-nested-models.md b/docs/ru/docs/tutorial/body-nested-models.md index d4baf8230..5dc06d28a 100644 --- a/docs/ru/docs/tutorial/body-nested-models.md +++ b/docs/ru/docs/tutorial/body-nested-models.md @@ -12,7 +12,7 @@ ## Поля-списки с параметром типа { #list-fields-with-type-parameter } -В Python есть специальный способ объявлять списки с внутренними типами, или «параметрами типа»: +Но в Python есть специальный способ объявлять списки с внутренними типами, или «параметрами типа»: ### Объявите `list` с параметром типа { #declare-a-list-with-a-type-parameter } @@ -110,7 +110,7 @@ my_list: list[str] {* ../../docs_src/body_nested_models/tutorial006_py310.py hl[18] *} -Такая реализация будет ожидать (конвертировать, валидировать, документировать и т.д.) JSON-содержимое в следующем формате: +Такая реализация будет ожидать (конвертировать, валидировать, документировать и т.д.) JSON-тело запроса в следующем формате: ```JSON hl_lines="11" { @@ -154,9 +154,9 @@ my_list: list[str] /// -## Тела с чистыми списками элементов { #bodies-of-pure-lists } +## Тела запросов с чистыми списками элементов { #bodies-of-pure-lists } -Если верхний уровень значения тела JSON-объекта представляет собой JSON `array` (в Python — `list`), вы можете объявить тип в параметре функции, так же как в моделях Pydantic: +Если верхний уровень значения JSON-тела запроса представляет собой JSON `array` (в Python — `list`), вы можете объявить тип в параметре функции, так же как в моделях Pydantic: ```Python images: list[Image] @@ -212,7 +212,7 @@ images: list[Image] С помощью **FastAPI** вы получаете максимальную гибкость, предоставляемую моделями Pydantic, сохраняя при этом простоту, краткость и элегантность вашего кода. -И дополнительно вы получаете: +Но со всеми преимуществами: * Поддержку редактора кода (автозавершение доступно везде!) * Преобразование данных (также известно как парсинг / сериализация) diff --git a/docs/ru/docs/tutorial/body.md b/docs/ru/docs/tutorial/body.md index 7b3ab22d3..f1b76cba3 100644 --- a/docs/ru/docs/tutorial/body.md +++ b/docs/ru/docs/tutorial/body.md @@ -70,7 +70,7 @@ * Считает тело запроса как JSON. * Приведёт данные к соответствующим типам (если потребуется). * Проведёт валидацию данных. - * Если данные некорректны, вернёт понятную и наглядную ошибку, указывающую, где именно и что было некорректно. + * Если данные некорректны, вернёт понятную и наглядную ошибку, указывающую, где именно and что было некорректно. * Передаст полученные данные в параметр `item`. * Поскольку внутри функции вы объявили его с типом `Item`, у вас будет поддержка со стороны редактора кода (автозавершение и т.п.) для всех атрибутов и их типов. * Сгенерирует определения [JSON Schema](https://json-schema.org) для вашей модели; вы можете использовать их и в других местах, если это имеет смысл для вашего проекта. diff --git a/docs/ru/docs/tutorial/debugging.md b/docs/ru/docs/tutorial/debugging.md index deb92f1b9..5a5808579 100644 --- a/docs/ru/docs/tutorial/debugging.md +++ b/docs/ru/docs/tutorial/debugging.md @@ -1,10 +1,10 @@ # Отладка { #debugging } -Вы можете подключить отладчик в своем редакторе, например, в Visual Studio Code или PyCharm. +Вы можете подключить отладчик в своем редакторе кода, например, в Visual Studio Code или PyCharm. ## Вызов `uvicorn` { #call-uvicorn } -В вашем FastAPI приложении, импортируйте и вызовите `uvicorn` напрямую: +В вашем FastAPI приложении, импортируйте и запустите `uvicorn` напрямую: {* ../../docs_src/debugging/tutorial001_py310.py hl[1,15] *} @@ -62,7 +62,7 @@ from myapp import app # Еще немного кода ``` -то автоматическая создаваемая внутри файла `myapp.py` переменная `__name__` будет иметь значение отличающееся от `"__main__"`. +то автоматически создаваемая внутри файла `myapp.py` переменная `__name__` будет иметь значение, отличающееся от `"__main__"`. Следовательно, строка: @@ -80,7 +80,7 @@ from myapp import app ## Запуск вашего кода с помощью отладчика { #run-your-code-with-your-debugger } -Так как вы запускаете сервер Uvicorn непосредственно из вашего кода, вы можете вызвать Python программу (ваше FastAPI приложение) напрямую из отладчика. +Так как вы запускаете сервер Uvicorn непосредственно из вашего кода, вы можете запустить Python программу (ваше FastAPI приложение) напрямую из отладчика. --- diff --git a/docs/ru/docs/tutorial/dependencies/dependencies-with-yield.md b/docs/ru/docs/tutorial/dependencies/dependencies-with-yield.md index 61ab8f44d..71e782c0b 100644 --- a/docs/ru/docs/tutorial/dependencies/dependencies-with-yield.md +++ b/docs/ru/docs/tutorial/dependencies/dependencies-with-yield.md @@ -123,7 +123,7 @@ FastAPI поддерживает зависимости, которые выпо ### Всегда делайте `raise` в зависимостях с `yield` и `except` { #always-raise-in-dependencies-with-yield-and-except } -Если вы ловите исключение в зависимости с `yield`, то, если вы не вызываете другой `HTTPException` или что-то подобное, вам следует повторно вызвать исходное исключение. +Если вы ловите исключение в зависимости с `yield`, то, если вы не вызываете другой `HTTPException` или что-то подобное, **вам следует повторно вызвать исходное исключение**. Вы можете повторно вызвать то же самое исключение с помощью `raise`: @@ -234,6 +234,7 @@ participant operation as Функция-обработчик пути Зависимости с `yield` со временем эволюционировали, чтобы покрыть разные сценарии и исправить некоторые проблемы. Если вы хотите посмотреть, что менялось в разных версиях FastAPI, вы можете прочитать об этом подробнее в продвинутом руководстве: [Продвинутые зависимости — зависимости с `yield`, `HTTPException`, `except` и фоновыми задачами](../../advanced/advanced-dependencies.md#dependencies-with-yield-httpexception-except-and-background-tasks). + ## Контекстные менеджеры { #context-managers } ### Что такое «контекстные менеджеры» { #what-are-context-managers } diff --git a/docs/ru/docs/tutorial/extra-data-types.md b/docs/ru/docs/tutorial/extra-data-types.md index 062c19574..d05a00eca 100644 --- a/docs/ru/docs/tutorial/extra-data-types.md +++ b/docs/ru/docs/tutorial/extra-data-types.md @@ -12,7 +12,7 @@ При этом у вас останутся те же возможности, что и до сих пор: * Отличная поддержка редактора кода. -* Преобразование данных из входящих запросов. +* Преобразование данных из входящих HTTP-запросов. * Преобразование данных для ответа. * Валидация данных. * Автоматическая аннотация и документация. @@ -23,32 +23,32 @@ * `UUID`: * Стандартный "Универсальный уникальный идентификатор", используемый в качестве идентификатора во многих базах данных и системах. - * В запросах и ответах будет представлен как `str`. + * В HTTP-запросах и HTTP-ответах будет представлен как `str`. * `datetime.datetime`: * Встроенный в Python `datetime.datetime`. - * В запросах и ответах будет представлен как `str` в формате ISO 8601, например: `2008-09-15T15:53:00+05:00`. + * В HTTP-запросах и HTTP-ответах будет представлен как `str` в формате ISO 8601, например: `2008-09-15T15:53:00+05:00`. * `datetime.date`: * Встроенный в Python `datetime.date`. - * В запросах и ответах будет представлен как `str` в формате ISO 8601, например: `2008-09-15`. + * В HTTP-запросах и HTTP-ответах будет представлен как `str` в формате ISO 8601, например: `2008-09-15`. * `datetime.time`: * Встроенный в Python `datetime.time`. - * В запросах и ответах будет представлен как `str` в формате ISO 8601, например: `14:23:55.003`. + * В HTTP-запросах и HTTP-ответах будет представлен как `str` в формате ISO 8601, например: `14:23:55.003`. * `datetime.timedelta`: * Встроенный в Python `datetime.timedelta`. - * В запросах и ответах будет представлен в виде общего количества секунд типа `float`. + * В HTTP-запросах и HTTP-ответах будет представлен в виде общего количества секунд типа `float`. * Pydantic также позволяет представить его как "Кодировку разницы во времени ISO 8601", [см. документацию для получения дополнительной информации](https://docs.pydantic.dev/latest/concepts/serialization/#custom-serializers). * `frozenset`: - * В запросах и ответах обрабатывается так же, как и `set`: - * В запросах будет прочитан список, исключены дубликаты и преобразован в `set`. - * В ответах `set` будет преобразован в `list`. + * В HTTP-запросах и HTTP-ответах обрабатывается так же, как и `set`: + * В HTTP-запросах будет прочитан список, исключены дубликаты и преобразован в `set`. + * В HTTP-ответах `set` будет преобразован в `list`. * В сгенерированной схеме будет указано, что значения `set` уникальны (с помощью JSON-схемы `uniqueItems`). * `bytes`: * Встроенный в Python `bytes`. - * В запросах и ответах будет рассматриваться как `str`. - * В сгенерированной схеме будет указано, что это `str` в формате `binary`. + * В HTTP-запросах и HTTP-ответах будет рассматриваться как `str`. + * В сгенерированной схеме будет указано, что это `str` в "формате" `binary`. * `Decimal`: * Встроенный в Python `Decimal`. - * В запросах и ответах обрабатывается так же, как и `float`. + * В HTTP-запросах и HTTP-ответах обрабатывается так же, как и `float`. * Вы можете проверить все допустимые типы данных Pydantic здесь: [Типы данных Pydantic](https://docs.pydantic.dev/latest/usage/types/types/). ## Пример { #example } diff --git a/docs/ru/docs/tutorial/extra-models.md b/docs/ru/docs/tutorial/extra-models.md index becb76bc3..cec61ed5d 100644 --- a/docs/ru/docs/tutorial/extra-models.md +++ b/docs/ru/docs/tutorial/extra-models.md @@ -208,4 +208,4 @@ some_variable: PlaneItem | CarItem Используйте несколько Pydantic-моделей и свободно применяйте наследование для каждого случая. -Вам не обязательно иметь единственную модель данных для каждой сущности, если эта сущность должна иметь возможность быть в разных "состояниях". Как в случае с "сущностью" пользователя, у которого есть состояние, включающее `password`, `password_hash` и отсутствие пароля. +Вам не обязательно иметь единственную модель данных для каждой сущности, если эта сущность должна иметь возможность быть в разных "состояниях". **Пользователь** — пример такой "сущности", с состояниями, которые включают `password`, `password_hash` или отсутствие пароля. diff --git a/docs/ru/docs/tutorial/first-steps.md b/docs/ru/docs/tutorial/first-steps.md index ce743b369..8841a9004 100644 --- a/docs/ru/docs/tutorial/first-steps.md +++ b/docs/ru/docs/tutorial/first-steps.md @@ -244,9 +244,9 @@ CLI автоматически определит ваше приложение Это будет основная точка взаимодействия для создания всего вашего API. -### Шаг 3: создайте *операцию пути (path operation)* { #step-3-create-a-path-operation } +### Шаг 3: создайте *операцию пути* { #step-3-create-a-path-operation } -#### Путь (path) { #path } +#### Путь { #path } Здесь «путь» — это последняя часть URL, начиная с первого символа `/`. @@ -270,7 +270,7 @@ https://example.com/items/foo При создании API «путь» — это основной способ разделения «задач» и «ресурсов». -#### Операция (operation) { #operation } +#### Операция { #operation } «Операция» здесь — это один из HTTP-«методов». @@ -303,16 +303,16 @@ https://example.com/items/foo Таким образом, в OpenAPI каждый HTTP-метод называется «операцией». -Мы тоже будем называть их «операциями». +Мы тоже будем называть их «**операциями**». -#### Определите *декоратор операции пути (path operation decorator)* { #define-a-path-operation-decorator } +#### Определите *декоратор операции пути* { #define-a-path-operation-decorator } {* ../../docs_src/first_steps/tutorial001_py310.py hl[6] *} -`@app.get("/")` сообщает **FastAPI**, что функция прямо под ним отвечает за обработку запросов, поступающих: +`@app.get("/")` сообщает **FastAPI**, что функция прямо под ним отвечает за обработку HTTP-запросов, поступающих: * по пути `/` -* с использованием get операции +* с использованием операции get /// note | Информация о `@decorator` @@ -353,9 +353,9 @@ https://example.com/items/foo /// -### Шаг 4: определите **функцию операции пути** { #step-4-define-the-path-operation-function } +### Шаг 4: определите **функцию-обработчик пути** { #step-4-define-the-path-operation-function } -Вот наша «функция операции пути»: +Вот наша «**функция-обработчик пути**»: * **путь**: `/`. * **операция**: `get`. @@ -365,7 +365,7 @@ https://example.com/items/foo Это функция на Python. -**FastAPI** будет вызывать её каждый раз, когда получает запрос к URL «`/`» с операцией `GET`. +**FastAPI** будет вызывать её каждый раз, когда получает HTTP-запрос к URL «`/`» с операцией `GET`. В данном случае это асинхронная (`async`) функция. @@ -403,7 +403,7 @@ https://example.com/items/foo Он переносит тот же **опыт разработчика** при создании приложений с FastAPI на их **развертывание** в облаке. 🎉 -FastAPI Cloud — основной спонсор и источник финансирования для open-source проектов «FastAPI и друзья». ✨ +FastAPI Cloud — основной спонсор и источник финансирования для open-source проектов *FastAPI и друзья*. ✨ #### Развертывание у других облачных провайдеров { #deploy-to-other-cloud-providers } @@ -416,6 +416,6 @@ FastAPI — open-source и основан на стандартах. Вы мож * Импортируйте `FastAPI`. * Создайте экземпляр `app`. * Напишите **декоратор операции пути**, например `@app.get("/")`. -* Определите **функцию операции пути**; например, `def root(): ...`. +* Определите **функцию-обработчик пути**; например, `def root(): ...`. * Запустите сервер разработки командой `fastapi dev`. * При желании разверните приложение командой `fastapi deploy`. diff --git a/docs/ru/docs/tutorial/handling-errors.md b/docs/ru/docs/tutorial/handling-errors.md index fde188f09..9676ac78b 100644 --- a/docs/ru/docs/tutorial/handling-errors.md +++ b/docs/ru/docs/tutorial/handling-errors.md @@ -13,11 +13,11 @@ В таких случаях обычно возвращают **HTTP статус-код** в диапазоне **400** (от 400 до 499). -Они похожи на двухсотые HTTP статус-коды (от 200 до 299), которые означают, что запрос обработан успешно. +Они похожи на двухсотые HTTP статус-коды (от 200 до 299). Эти статус-коды "200" означают, что в HTTP-запросе в каком-то смысле был "успех". -Четырёхсотые статус-коды означают, что ошибка произошла по вине клиента. +HTTP статус-коды в диапазоне 400 означают, что произошла ошибка со стороны клиента. -Помните ли ошибки **"404 Not Found "** (и шутки) ? +Помните все эти ошибки **"404 Not Found"** (и шутки)? ## Использование `HTTPException` { #use-httpexception } @@ -31,19 +31,19 @@ `HTTPException` - это обычное исключение Python с дополнительными данными, актуальными для API. -Поскольку это исключение Python, то его не `возвращают`, а `вызывают`. +Поскольку это исключение Python, то его не `return`, а `raise`. -Это также означает, что если вы находитесь внутри функции, которая вызывается внутри вашей *функции операции пути*, и вы поднимаете `HTTPException` внутри этой функции, то она не будет выполнять остальной код в *функции операции пути*, а сразу завершит запрос и отправит HTTP-ошибку из `HTTPException` клиенту. +Это также означает, что если вы находитесь внутри вспомогательной функции, которая вызывается внутри вашей *функции-обработчика пути*, и вы вызываете `HTTPException` изнутри этой вспомогательной функции, то остальной код в *функции-обработчике пути* выполняться не будет, запрос сразу завершится, а HTTP-ошибка из `HTTPException` будет отправлена клиенту. -О том, насколько выгоднее `вызывать` исключение, чем `возвращать` значение, будет рассказано в разделе, посвященном зависимостям и безопасности. +Преимущество вызова исключения перед возвратом значения станет более очевидным в разделе о зависимостях и безопасности. -В данном примере, когда клиент запрашивает элемент по несуществующему ID, возникает исключение со статус-кодом `404`: +В данном примере, когда клиент запрашивает элемент по несуществующему ID, вызовите исключение со статус-кодом `404`: {* ../../docs_src/handling_errors/tutorial001_py310.py hl[11] *} ### Возвращаемый ответ { #the-resulting-response } -Если клиент запросит `http://example.com/items/foo` (`item_id` `"foo"`), то он получит статус-код 200 и ответ в формате JSON: +Если клиент запросит `http://example.com/items/foo` (`item_id` `"foo"`), то он получит HTTP статус-код 200 и ответ в формате JSON: ```JSON { @@ -51,7 +51,7 @@ } ``` -Но если клиент запросит `http://example.com/items/bar` (несуществующий `item_id` `"bar"`), то он получит статус-код 404 (ошибка "не найдено") и JSON-ответ в виде: +Но если клиент запросит `http://example.com/items/bar` (несуществующий `item_id` `"bar"`), то он получит HTTP статус-код 404 (ошибка "не найдено") и JSON-ответ в виде: ```JSON { @@ -69,13 +69,13 @@ /// -## Добавление пользовательских заголовков { #add-custom-headers } +## Добавление пользовательских HTTP-заголовков { #add-custom-headers } -В некоторых ситуациях полезно иметь возможность добавлять пользовательские HTTP-заголовки к ошибке HTTP. Например, для некоторых типов безопасности. +В некоторых ситуациях полезно иметь возможность добавлять пользовательские HTTP-заголовки к HTTP-ошибке. Например, для некоторых типов безопасности. -Скорее всего, вам не потребуется использовать его непосредственно в коде. +Скорее всего, вам не потребуется использовать это непосредственно в коде. -Но в случае, если это необходимо для продвинутого сценария, можно добавить пользовательские заголовки: +Но в случае, если это необходимо для продвинутого сценария, можно добавить пользовательские HTTP-заголовки: {* ../../docs_src/handling_errors/tutorial002_py310.py hl[14] *} @@ -83,7 +83,7 @@ Вы можете добавить пользовательские обработчики исключений с помощью [тех же утилит обработки исключений из Starlette](https://www.starlette.dev/exceptions/). -Допустим, у вас есть пользовательское исключение `UnicornException`, которое вы (или используемая вами библиотека) можете `вызвать`. +Допустим, у вас есть пользовательское исключение `UnicornException`, которое вы (или используемая вами библиотека) можете вызвать с помощью `raise`. И вы хотите обрабатывать это исключение глобально с помощью FastAPI. @@ -95,7 +95,7 @@ Но оно будет обработано `unicorn_exception_handler`. -Таким образом, вы получите чистую ошибку с кодом состояния HTTP `418` и содержимым JSON: +Таким образом, вы получите чистую ошибку с HTTP статус-кодом `418` и содержимым JSON: ```JSON {"message": "Oops! yolo did something. There goes a rainbow..."} @@ -113,17 +113,17 @@ **FastAPI** имеет некоторые обработчики исключений по умолчанию. -Эти обработчики отвечают за возврат стандартных JSON-ответов при `вызове` `HTTPException` и при наличии в запросе недопустимых данных. +Эти обработчики отвечают за возврат стандартных JSON-ответов при вызове `HTTPException` с помощью `raise` и при наличии в HTTP-запросе недопустимых данных. Вы можете переопределить эти обработчики исключений на свои собственные. -### Переопределение обработчика исключений проверки запроса { #override-request-validation-exceptions } +### Переопределение исключений валидации запроса { #override-request-validation-exceptions } -Когда запрос содержит недопустимые данные, **FastAPI** внутренне вызывает ошибку `RequestValidationError`. +Когда HTTP-запрос содержит недопустимые данные, **FastAPI** внутренне вызывает `RequestValidationError`. -А также включает в себя обработчик исключений по умолчанию. +А также включает в себя обработчик исключений по умолчанию для него. -Чтобы переопределить его, импортируйте `RequestValidationError` и используйте его с `@app.exception_handler(RequestValidationError)` для создания обработчика исключений. +Чтобы переопределить его, импортируйте `RequestValidationError` и используйте его с `@app.exception_handler(RequestValidationError)`, чтобы декорировать обработчик исключений. Обработчик исключения получит объект `Request` и исключение. @@ -146,7 +146,7 @@ } ``` -вы получите текстовую версию: +вы получите текстовую версию с: ``` Validation errors: @@ -171,7 +171,7 @@ Field: ('path', 'item_id'), Error: Input should be a valid integer, unable to pa /// warning | Внимание -Имейте в виду, что `RequestValidationError` содержит информацию об имени файла и строке, где произошла ошибка валидации, чтобы вы могли при желании отобразить её в логах с релевантными данными. +Имейте в виду, что `RequestValidationError` содержит информацию об имени файла и строке, где происходит ошибка валидации, чтобы вы могли при желании отобразить её в логах вместе с релевантной информацией. Но это означает, что если вы просто преобразуете её в строку и вернёте эту информацию напрямую, вы можете допустить небольшую утечку информации о своей системе, поэтому здесь код извлекает и показывает каждую ошибку отдельно. @@ -179,13 +179,13 @@ Field: ('path', 'item_id'), Error: Input should be a valid integer, unable to pa ### Используйте тело `RequestValidationError` { #use-the-requestvalidationerror-body } -Ошибка `RequestValidationError` содержит полученное `тело` с недопустимыми данными. +Ошибка `RequestValidationError` содержит `body` (тело запроса), которое она получила с недопустимыми данными. -Вы можете использовать его при разработке приложения для регистрации тела и его отладки, возврата пользователю и т.д. +Вы можете использовать его при разработке приложения для логирования тела запроса и его отладки, возврата пользователю и т.д. {* ../../docs_src/handling_errors/tutorial005_py310.py hl[14] *} -Теперь попробуйте отправить недействительный элемент, например: +Теперь попробуйте отправить недопустимый элемент, например: ```JSON { @@ -194,7 +194,7 @@ Field: ('path', 'item_id'), Error: Input should be a valid integer, unable to pa } ``` -Вы получите ответ о том, что данные недействительны, содержащий следующее тело: +Вы получите ответ о том, что данные недопустимы, содержащий полученное тело запроса: ```JSON hl_lines="12-15" { @@ -215,7 +215,7 @@ Field: ('path', 'item_id'), Error: Input should be a valid integer, unable to pa } ``` -#### `HTTPException` в FastAPI или в Starlette { #fastapis-httpexception-vs-starlettes-httpexception } +#### `HTTPException` в FastAPI и `HTTPException` в Starlette { #fastapis-httpexception-vs-starlettes-httpexception } **FastAPI** имеет собственный `HTTPException`. @@ -227,9 +227,9 @@ Field: ('path', 'item_id'), Error: Input should be a valid integer, unable to pa Но когда вы регистрируете обработчик исключений, вы должны зарегистрировать его для `HTTPException` от Starlette. -Таким образом, если какая-либо часть внутреннего кодa Starlette, расширение или плагин Starlette вызовет исключение Starlette `HTTPException`, ваш обработчик сможет перехватить и обработать его. +Таким образом, если какая-либо часть внутреннего кода Starlette, расширение или плагин Starlette вызовет исключение Starlette `HTTPException`, ваш обработчик сможет перехватить и обработать его. -В данном примере, чтобы иметь возможность использовать оба `HTTPException` в одном коде, исключения Starlette переименованы в `StarletteHTTPException`: +В данном примере, чтобы иметь возможность использовать оба `HTTPException` в одном коде, исключение Starlette переименовано в `StarletteHTTPException`: ```Python from starlette.exceptions import HTTPException as StarletteHTTPException @@ -241,4 +241,4 @@ from starlette.exceptions import HTTPException as StarletteHTTPException {* ../../docs_src/handling_errors/tutorial006_py310.py hl[2:5,15,21] *} -В этом примере вы просто `выводите в терминал` ошибку с очень выразительным сообщением, но идея вам понятна. Вы можете использовать исключение, а затем просто повторно использовать стандартные обработчики исключений. +В этом примере вы просто выводите ошибку с очень выразительным сообщением, но идея вам понятна. Вы можете использовать исключение, а затем просто повторно использовать стандартные обработчики исключений. diff --git a/docs/ru/docs/tutorial/index.md b/docs/ru/docs/tutorial/index.md index eec217b75..b843515f8 100644 --- a/docs/ru/docs/tutorial/index.md +++ b/docs/ru/docs/tutorial/index.md @@ -1,5 +1,6 @@ # Учебник - Руководство пользователя { #tutorial-user-guide } + В этом руководстве шаг за шагом показано, как использовать **FastAPI** с большинством его функций. Каждый раздел постепенно основывается на предыдущих, но структура разделяет темы, так что вы можете сразу перейти к нужной теме для решения ваших конкретных задач по API. diff --git a/docs/ru/docs/tutorial/metadata.md b/docs/ru/docs/tutorial/metadata.md index b1335f668..958c9cbbb 100644 --- a/docs/ru/docs/tutorial/metadata.md +++ b/docs/ru/docs/tutorial/metadata.md @@ -11,10 +11,10 @@ | `title` | `str` | Заголовок API. | | `summary` | `str` | Краткое резюме API. Доступно начиная с OpenAPI 3.1.0, FastAPI 0.99.0. | | `description` | `str` | Краткое описание API. Может быть использован Markdown. | -| `version` | `string` | Версия API. Версия вашего собственного приложения, а не OpenAPI. К примеру `2.5.0`. | -| `terms_of_service` | `str` | Ссылка к условиям пользования API. Если указано, то это должен быть URL-адрес. | -| `contact` | `dict` | Контактная информация для открытого API. Может содержать несколько полей.
поля contact
ПараметрТипОписание
namestrИдентификационное имя контактного лица/организации.
urlstrURL указывающий на контактную информацию. ДОЛЖЕН быть в формате URL.
emailstrEmail адрес контактного лица/организации. ДОЛЖЕН быть в формате email адреса.
| -| `license_info` | `dict` | Информация о лицензии открытого API. Может содержать несколько полей.
поля license_info
ПараметрТипОписание
namestrОБЯЗАТЕЛЬНО (если установлен параметр license_info). Название лицензии, используемой для API.
identifierstrВыражение лицензии [SPDX](https://spdx.org/licenses/) для API. Поле identifier взаимоисключающее с полем url. Доступно начиная с OpenAPI 3.1.0, FastAPI 0.99.0.
urlstrURL, указывающий на лицензию, используемую для API. ДОЛЖЕН быть в формате URL.
| +| `version` | `str` | Версия API. Версия вашего собственного приложения, а не OpenAPI. К примеру `2.5.0`. | +| `terms_of_service` | `str` | Ссылка на условия пользования API. Если указано, то это должен быть URL-адрес. | +| `contact` | `dict` | Контактная информация для открытого API. Может содержать несколько полей.
поля contact
ПараметрТипОписание
namestrИдентификационное имя контактного лица/организации.
urlstrURL, указывающий на контактную информацию. ДОЛЖЕН быть в формате URL.
emailstrEmail-адрес контактного лица/организации. ДОЛЖЕН быть в формате email-адреса.
| +| `license_info` | `dict` | Информация о лицензии открытого API. Может содержать несколько полей.
поля license_info
ПараметрТипОписание
namestrОБЯЗАТЕЛЬНО (если установлен параметр license_info). Название лицензии, используемой для API.
identifierstrВыражение лицензии [SPDX](https://spdx.org/licenses/) для API. Поле identifier является взаимоисключающим с полем url. Доступно начиная с OpenAPI 3.1.0, FastAPI 0.99.0.
urlstrURL, указывающий на лицензию, используемую для API. ДОЛЖЕН быть в формате URL.
| Вы можете задать их следующим образом: @@ -48,7 +48,7 @@ * `name` (**обязательно**): `str`-значение с тем же именем тега, которое вы используете в параметре `tags` в ваших *операциях пути* и `APIRouter`ах. * `description`: `str`-значение с кратким описанием для тега. Может содержать Markdown и будет отображаться в UI документации. -* `externalDocs`: `dict`-значение описывающее внешнюю документацию. Включает в себя: +* `externalDocs`: `dict`-значение, описывающее внешнюю документацию. Включает в себя: * `description`: `str`-значение с кратким описанием для внешней документации. * `url` (**обязательно**): `str`-значение с URL-адресом для внешней документации. @@ -64,7 +64,7 @@ /// tip | Подсказка -Вам необязательно добавлять метаданные для всех используемых тегов +Вам необязательно добавлять метаданные для всех используемых тегов. /// @@ -94,11 +94,11 @@ ## URL-адрес OpenAPI { #openapi-url } -По умолчанию схема OpenAPI отображена по адресу `/openapi.json`. +По умолчанию схема OpenAPI отдаётся по адресу `/openapi.json`. Но вы можете изменить это с помощью параметра `openapi_url`. -К примеру, чтобы задать её отображение по адресу `/api/v1/openapi.json`: +К примеру, чтобы задать её отдачу по адресу `/api/v1/openapi.json`: {* ../../docs_src/metadata/tutorial002_py310.py hl[3] *} @@ -106,15 +106,15 @@ ## URL-адреса документации { #docs-urls } -Вы можете изменить конфигурацию двух пользовательских интерфейсов документации, которые включены: +Вы можете изменить конфигурацию двух включённых пользовательских интерфейсов документации: -* **Swagger UI**: отображаемый по адресу `/docs`. +* **Swagger UI**: отдаётся по адресу `/docs`. * Вы можете задать его URL с помощью параметра `docs_url`. * Вы можете отключить это с помощью настройки `docs_url=None`. -* **ReDoc**: отображаемый по адресу `/redoc`. +* **ReDoc**: отдаётся по адресу `/redoc`. * Вы можете задать его URL с помощью параметра `redoc_url`. * Вы можете отключить это с помощью настройки `redoc_url=None`. -К примеру, чтобы задать отображение Swagger UI по адресу `/documentation` и отключить ReDoc: +К примеру, чтобы настроить отдачу Swagger UI по адресу `/documentation` и отключить ReDoc: {* ../../docs_src/metadata/tutorial003_py310.py hl[3] *} diff --git a/docs/ru/docs/tutorial/path-operation-configuration.md b/docs/ru/docs/tutorial/path-operation-configuration.md index c1264d9dd..c5099c3e0 100644 --- a/docs/ru/docs/tutorial/path-operation-configuration.md +++ b/docs/ru/docs/tutorial/path-operation-configuration.md @@ -1,10 +1,10 @@ -# Конфигурация операций пути { #path-operation-configuration } +# Конфигурация операции пути { #path-operation-configuration } -Существует несколько параметров, которые вы можете передать вашему *декоратору операций пути* для его настройки. +Существует несколько параметров, которые вы можете передать вашему *декоратору операции пути* для его настройки. /// warning | Внимание -Помните, что эти параметры передаются непосредственно *декоратору операций пути*, а не вашей *функции-обработчику пути*. +Помните, что эти параметры передаются непосредственно *декоратору операции пути*, а не вашей *функции-обработчику пути*. /// @@ -30,11 +30,11 @@ ## Теги { #tags } -Вы можете добавлять теги к вашим *операциям пути*, добавив параметр `tags` с `list` заполненным `str`-значениями (обычно в нём только одна строка): +Вы можете добавлять теги к вашей *операции пути*, передав параметр `tags` с `list` из `str` (обычно в нём только одна строка): {* ../../docs_src/path_operation_configuration/tutorial002_py310.py hl[15,20,25] *} -Они будут добавлены в схему OpenAPI и будут использованы в автоматической документации интерфейса: +Они будут добавлены в схему OpenAPI и будут использованы автоматическими интерфейсами документации: @@ -56,7 +56,7 @@ ## Описание из строк документации { #description-from-docstring } -Так как описания обычно длинные и содержат много строк, вы можете объявить описание *операции пути* в строке документации функции, и **FastAPI** прочитает её оттуда. +Так как описания обычно длинные и содержат много строк, вы можете объявить описание *операции пути* в строке документации функции, и **FastAPI** прочитает её оттуда. Вы можете использовать [Markdown](https://en.wikipedia.org/wiki/Markdown) в строке документации, и он будет интерпретирован и отображён корректно (с учетом отступа в строке документации). @@ -94,7 +94,7 @@ OpenAPI указывает, что каждой *операции пути* не {* ../../docs_src/path_operation_configuration/tutorial006_py310.py hl[16] *} -Он будет четко помечен как устаревший в интерактивной документации: +Она будет четко помечена как устаревшая в интерактивной документации: diff --git a/docs/ru/docs/tutorial/query-params-str-validations.md b/docs/ru/docs/tutorial/query-params-str-validations.md index 7af7ccfa0..5783b0cdf 100644 --- a/docs/ru/docs/tutorial/query-params-str-validations.md +++ b/docs/ru/docs/tutorial/query-params-str-validations.md @@ -80,8 +80,8 @@ q: Annotated[str | None] = None Теперь FastAPI будет: * **валидировать** данные, удостоверяясь, что максимальная длина — 50 символов; -* показывать **понятную ошибку** клиенту, если данные невалидны; -* **документировать** параметр в *операции пути* схемы OpenAPI (он будет показан в **UI автоматической документации**). +* отображать **понятную ошибку** клиенту, если данные невалидны; +* **документировать** параметр в *операции пути* схемы OpenAPI (он будет отображаться в **UI автоматической документации**). ## Альтернатива (устаревшее): `Query` как значение по умолчанию { #alternative-old-query-as-the-default-value } @@ -119,7 +119,7 @@ q: str | None = None q: str | None = Query(default=None, max_length=50) ``` -Это провалидирует данные, покажет понятную ошибку, если данные невалидны, и задокументирует параметр в *операции пути* схемы OpenAPI. +Это провалидирует данные, отобразит понятную ошибку, если данные невалидны, и задокументирует параметр в *операции пути* схемы OpenAPI. ### `Query` как значение по умолчанию или внутри `Annotated` { #query-as-the-default-value-or-in-annotated } @@ -141,7 +141,7 @@ q: Annotated[str, Query(default="rick")] = "morty" q: Annotated[str, Query()] = "rick" ``` -...или в старой кодовой базе вы увидите: +...или в старых кодовых базах вы увидите: ```Python q: str = Query(default="rick") @@ -153,19 +153,19 @@ q: str = Query(default="rick") **Значение по умолчанию** у **параметра функции** — это **настоящее значение по умолчанию**, что более интуитивно для Python. 😌 -Вы можете **вызвать** эту же функцию в **других местах** без FastAPI, и она будет **работать как ожидается**. Если есть **обязательный** параметр (без значения по умолчанию), ваш **редактор** сообщит об ошибке, **Python** тоже пожалуется, если вы запустите её без передачи обязательного параметра. +Вы можете **вызвать** эту же функцию в **других местах** без FastAPI, и она будет **работать как ожидается**. Если есть **обязательный** параметр (без значения по умолчанию), ваш **редактор кода** сообщит об ошибке, **Python** тоже пожалуется, если вы запустите её без передачи обязательного параметра. -Если вы не используете `Annotated`, а применяете **(устаревший) стиль со значением по умолчанию**, то при вызове этой функции без FastAPI в **других местах** вам нужно **помнить** о том, что надо передать аргументы, чтобы всё работало корректно, иначе значения будут не такими, как вы ожидаете (например, вместо `str` будет `QueryInfo` или что-то подобное). И ни редактор, ни Python не будут ругаться при самом вызове функции — ошибка проявится лишь при операциях внутри. +Если вы не используете `Annotated`, а применяете **(устаревший) стиль со значением по умолчанию**, то при вызове этой функции без FastAPI в **других местах** вам нужно **помнить** о том, что надо передать аргументы, чтобы всё работало корректно, иначе значения будут не такими, как вы ожидаете (например, вместо `str` будет `QueryInfo` или что-то подобное). И ни редактор кода, ни Python не будут ругаться при самом вызове функции — ошибка проявится лишь при операциях внутри. Так как `Annotated` может содержать больше одной аннотации метаданных, теперь вы можете использовать ту же функцию и с другими инструментами, например с [Typer](https://typer.tiangolo.com/). 🚀 -## Больше валидаций { #add-more-validations } +## Добавим больше валидаций { #add-more-validations } Можно также добавить параметр `min_length`: {* ../../docs_src/query_params_str_validations/tutorial003_an_py310.py hl[10] *} -## Регулярные выражения { #add-regular-expressions } +## Добавим регулярные выражения { #add-regular-expressions } Вы можете определить регулярное выражение `pattern`, которому должен соответствовать параметр: @@ -173,7 +173,7 @@ q: str = Query(default="rick") Данный шаблон регулярного выражения проверяет, что полученное значение параметра: -* `^`: начинается с следующих символов, до них нет символов. +* `^`: начинается со следующих символов, до них нет символов. * `fixedquery`: имеет точное значение `fixedquery`. * `$`: заканчивается здесь, после `fixedquery` нет никаких символов. @@ -191,7 +191,7 @@ q: str = Query(default="rick") /// note | Примечание -Наличие значения по умолчанию любого типа, включая `None`, делает параметр необязательным. +Наличие значения по умолчанию любого типа, включая `None`, делает параметр необязательным (не обязательным). /// @@ -243,7 +243,7 @@ http://localhost:8000/items/?q=foo&q=bar вы получите множественные значения *query-параметров* `q` (`foo` и `bar`) в виде Python-`list` внутри вашей *функции-обработчика пути*, в *параметре функции* `q`. -Таким образом, ответ на этот URL будет: +Таким образом, HTTP-ответом на этот URL будет: ```JSON { @@ -276,7 +276,7 @@ http://localhost:8000/items/?q=foo&q=bar http://localhost:8000/items/ ``` -значение по умолчанию для `q` будет: `["foo", "bar"]`, и ответом будет: +значение по умолчанию для `q` будет: `["foo", "bar"]`, и вашим HTTP-ответом будет: ```JSON { @@ -301,7 +301,7 @@ http://localhost:8000/items/ /// -## Больше метаданных { #declare-more-metadata } +## Объявление дополнительных метаданных { #declare-more-metadata } Можно добавить больше информации о параметре. @@ -369,7 +369,7 @@ http://127.0.0.1:8000/items/?item-query=foobaritems В таких случаях можно использовать **кастомную функцию-валидатор**, которая применяется после обычной валидации (например, после проверки, что значение — это `str`). -Этого можно добиться, используя [`AfterValidator` Pydantic](https://docs.pydantic.dev/latest/concepts/validators/#field-after-validator) внутри `Annotated`. +Этого можно добиться, используя [Pydantic `AfterValidator`](https://docs.pydantic.dev/latest/concepts/validators/#field-after-validator) внутри `Annotated`. /// tip | Совет @@ -377,7 +377,7 @@ http://127.0.0.1:8000/items/?item-query=foobaritems /// -Например, эта кастомная проверка убеждается, что ID элемента начинается с `isbn-` для номера книги ISBN или с `imdb-` для ID URL фильма на IMDB: +Например, эта кастомная проверка убеждается, что ID элемента начинается с `isbn-` для номера книги ISBN или с `imdb-` для ID URL фильма в IMDB: {* ../../docs_src/query_params_str_validations/tutorial015_an_py310.py hl[5,16:19,24] *} @@ -391,7 +391,7 @@ http://127.0.0.1:8000/items/?item-query=foobaritems Если вам нужна валидация, требующая общения с каким‑либо **внешним компонентом** — базой данных или другим API — вместо этого используйте **Зависимости FastAPI**, вы познакомитесь с ними позже. -Эти кастомные валидаторы предназначены для проверок, которые можно выполнить, имея **только** те же **данные**, что пришли в запросе. +Эти кастомные валидаторы предназначены для проверок, которые можно выполнить, имея **только** те же **данные**, что пришли в HTTP-запросе. /// @@ -429,7 +429,7 @@ http://127.0.0.1:8000/items/?item-query=foobaritems Вы можете объявлять дополнительные проверки и метаданные для параметров. -Общие метаданные и настройки: +Общие проверки и метаданные: * `alias` * `title` diff --git a/docs/ru/docs/tutorial/query-params.md b/docs/ru/docs/tutorial/query-params.md index 524b53945..65c0c2d9a 100644 --- a/docs/ru/docs/tutorial/query-params.md +++ b/docs/ru/docs/tutorial/query-params.md @@ -1,10 +1,10 @@ # Query-параметры { #query-parameters } -Когда вы объявляете параметры функции, которые не являются параметрами пути, они автоматически интерпретируются как "query"-параметры. +Когда вы объявляете параметры функции, которые не являются частью path-параметров, они автоматически интерпретируются как "query"-параметры. {* ../../docs_src/query_params/tutorial001_py310.py hl[9] *} -Query-параметры представляют из себя набор пар ключ-значение, которые идут после знака `?` в URL-адресе, разделенные символами `&`. +Query — это набор пар ключ-значение, которые идут после знака `?` в URL-адресе, разделенные символами `&`. Например, в этом URL-адресе: @@ -12,25 +12,25 @@ Query-параметры представляют из себя набор па http://127.0.0.1:8000/items/?skip=0&limit=10 ``` -...параметры запроса такие: +...query-параметры такие: * `skip`: со значением `0` * `limit`: со значением `10` -Будучи частью URL-адреса, они "по умолчанию" являются строками. +Будучи частью URL-адреса, они "естественным образом" являются строками. Но когда вы объявляете их с использованием типов Python (в примере выше, как `int`), они конвертируются в указанный тип данных и проходят проверку на соответствие ему. -Все те же правила, которые применяются к path-параметрам, также применяются и query-параметрам: +Все те же процессы, которые применяются к path-параметрам, также применяются и к query-параметрам: * Поддержка от редактора кода (очевидно) -* "Парсинг" данных -* Проверка на соответствие данных (Валидация) +* "Парсинг" данных +* Валидация данных * Автоматическая документация ## Значения по умолчанию { #defaults } -Поскольку query-параметры не являются фиксированной частью пути, они могут быть не обязательными и иметь значения по умолчанию. +Поскольку query-параметры не являются фиксированной частью пути, они могут быть необязательными и иметь значения по умолчанию. В примере выше значения по умолчанию равны `skip=0` и `limit=10`. @@ -40,13 +40,13 @@ http://127.0.0.1:8000/items/?skip=0&limit=10 http://127.0.0.1:8000/items/ ``` -будет таким же, как если перейти используя параметры по умолчанию: +будет таким же, как если перейти по: ``` http://127.0.0.1:8000/items/?skip=0&limit=10 ``` -Но если вы введёте, например: +Но если вы перейдёте, например, по: ``` http://127.0.0.1:8000/items/?skip=20 @@ -55,7 +55,7 @@ http://127.0.0.1:8000/items/?skip=20 Значения параметров в вашей функции будут: * `skip=20`: потому что вы установили это в URL-адресе -* `limit=10`: т.к это было значение по умолчанию +* `limit=10`: потому что это было значение по умолчанию ## Необязательные параметры { #optional-parameters } @@ -63,21 +63,21 @@ http://127.0.0.1:8000/items/?skip=20 {* ../../docs_src/query_params/tutorial002_py310.py hl[7] *} -В этом случае, параметр `q` будет не обязательным и будет иметь значение `None` по умолчанию. +В этом случае параметр функции `q` будет необязательным и будет иметь значение `None` по умолчанию. /// tip | Подсказка -Также обратите внимание, что **FastAPI** достаточно умён чтобы заметить, что параметр `item_id` является path-параметром, а `q` нет, поэтому, это параметр запроса. +Также обратите внимание, что **FastAPI** достаточно умён, чтобы заметить, что path-параметр `item_id` является path-параметром, а `q` — нет, поэтому это query-параметр. /// -## Преобразование типа параметра запроса { #query-parameter-type-conversion } +## Преобразование типа query-параметра { #query-parameter-type-conversion } -Вы также можете объявлять параметры с типом `bool`, которые будут преобразованы соответственно: +Вы также можете объявлять типы `bool`, и они будут преобразованы: {* ../../docs_src/query_params/tutorial003_py310.py hl[7] *} -В этом случае, если вы сделаете запрос: +В этом случае, если вы перейдёте по: ``` http://127.0.0.1:8000/items/foo?short=1 @@ -107,11 +107,12 @@ http://127.0.0.1:8000/items/foo?short=on http://127.0.0.1:8000/items/foo?short=yes ``` -или в любом другом варианте написания (в верхнем регистре, с заглавной буквой, и т.п), внутри вашей функции параметр `short` будет иметь значение `True` типа данных `bool` . В противном случае - `False`. +или в любом другом варианте написания (в верхнем регистре, с заглавной буквой и т.п.), внутри вашей функции параметр `short` будет иметь значение `True` типа данных `bool`. В противном случае — `False`. -## Смешивание query-параметров и path-параметров { #multiple-path-and-query-parameters } -Вы можете объявлять несколько query-параметров и path-параметров одновременно, **FastAPI** сам разберётся, что чем является. +## Несколько path-параметров и query-параметров { #multiple-path-and-query-parameters } + +Вы можете объявлять несколько path-параметров и query-параметров одновременно, **FastAPI** знает, что чем является. И вы не обязаны объявлять их в каком-либо определенном порядке. @@ -123,21 +124,21 @@ http://127.0.0.1:8000/items/foo?short=yes Когда вы объявляете значение по умолчанию для параметра, который не является path-параметром (в этом разделе мы пока что рассмотрели только query-параметры), то он не является обязательным. -Если вы не хотите задавать конкретное значение, но хотите сделать параметр необязательным, вы можете установить значение по умолчанию равным `None`. +Если вы не хотите задавать конкретное значение, но хотите просто сделать параметр необязательным, установите значение по умолчанию равным `None`. Но если вы хотите сделать query-параметр обязательным, вы можете просто не указывать значение по умолчанию: {* ../../docs_src/query_params/tutorial005_py310.py hl[6:7] *} -Здесь параметр запроса `needy` является обязательным параметром с типом данных `str`. +Здесь query-параметр `needy` является обязательным query-параметром с типом данных `str`. -Если вы откроете в браузере URL-адрес, например: +Если вы откроете в браузере URL-адрес вроде: ``` http://127.0.0.1:8000/items/foo-item ``` -...без добавления обязательного параметра `needy`, вы увидите подобного рода ошибку: +...без добавления обязательного параметра `needy`, вы увидите ошибку вроде: ```JSON { @@ -170,18 +171,18 @@ http://127.0.0.1:8000/items/foo-item?needy=sooooneedy } ``` -Конечно, вы можете определить некоторые параметры как обязательные, некоторые — со значением по умолчанию, а некоторые — полностью необязательные: +И, конечно, вы можете определить некоторые параметры как обязательные, некоторые — со значением по умолчанию, а некоторые — полностью необязательные: {* ../../docs_src/query_params/tutorial006_py310.py hl[8] *} -В этом примере, у нас есть 3 параметра запроса: +В этом случае есть 3 query-параметра: * `needy`, обязательный `str`. -* `skip`, типа `int` и со значением по умолчанию `0`. +* `skip`, `int` со значением по умолчанию `0`. * `limit`, необязательный `int`. /// tip | Подсказка -Вы можете использовать класс `Enum` также, как ранее применяли его с [Path-параметрами](path-params.md#predefined-values). +Вы можете использовать `Enum` так же, как ранее применяли его с [Path-параметрами](path-params.md#predefined-values). /// diff --git a/docs/ru/docs/tutorial/request-files.md b/docs/ru/docs/tutorial/request-files.md index 29a7f5ec1..6d40aaac6 100644 --- a/docs/ru/docs/tutorial/request-files.md +++ b/docs/ru/docs/tutorial/request-files.md @@ -38,13 +38,13 @@ $ pip install python-multipart /// tip | Подсказка -Для объявления тела файла необходимо использовать `File`, поскольку в противном случае параметры будут интерпретироваться как параметры запроса или параметры тела (JSON). +Чтобы объявить файлы в теле запроса, необходимо использовать `File`, поскольку иначе параметры будут интерпретироваться как параметры запроса или body-параметры (JSON). /// Файлы будут загружены как данные формы. -Если вы объявите тип параметра у *функции операции пути* как `bytes`, то **FastAPI** прочитает файл за вас, и вы получите его содержимое в виде `bytes`. +Если вы объявите тип параметра у *функции-обработчика пути* как `bytes`, то **FastAPI** прочитает файл за вас, и вы получите его содержимое в виде `bytes`. Следует иметь в виду, что все содержимое будет храниться в памяти. Это хорошо подходит для небольших файлов. @@ -64,15 +64,15 @@ $ pip install python-multipart * Это означает, что он будет хорошо работать с большими файлами, такими как изображения, видео, большие бинарные файлы и т.д., не потребляя при этом всю память. * Из загруженного файла можно получить метаданные. * Он реализует [file-like](https://docs.python.org/3/glossary.html#term-file-like-object) `async` интерфейс. -* Он предоставляет реальный объект Python [`SpooledTemporaryFile`](https://docs.python.org/3/library/tempfile.html#tempfile.SpooledTemporaryFile), который вы можете передать непосредственно другим библиотекам, которые ожидают файл в качестве объекта. +* Он предоставляет реальный объект Python [`SpooledTemporaryFile`](https://docs.python.org/3/library/tempfile.html#tempfile.SpooledTemporaryFile), который вы можете передать непосредственно другим библиотекам, которые ожидают file-like объект. ### `UploadFile` { #uploadfile } `UploadFile` имеет следующие атрибуты: * `filename`: Строка `str` с исходным именем файла, который был загружен (например, `myimage.jpg`). -* `content_type`: Строка `str` с типом содержимого (MIME type / media type) (например, `image/jpeg`). -* `file`: [`SpooledTemporaryFile`](https://docs.python.org/3/library/tempfile.html#tempfile.SpooledTemporaryFile) (a [file-like](https://docs.python.org/3/glossary.html#term-file-like-object) объект). Это фактический файл Python, который можно передавать непосредственно другим функциям или библиотекам, ожидающим файл в качестве объекта. +* `content_type`: Строка `str` с типом содержимого (MIME-тип / тип содержимого) (например, `image/jpeg`). +* `file`: [`SpooledTemporaryFile`](https://docs.python.org/3/library/tempfile.html#tempfile.SpooledTemporaryFile) ([file-like](https://docs.python.org/3/glossary.html#term-file-like-object) объект). Это фактический файл Python, который можно передавать непосредственно другим функциям или библиотекам, ожидающим file-like объект. `UploadFile` имеет следующие методы `async`. Все они вызывают соответствующие файловые методы (используя внутренний `SpooledTemporaryFile`). @@ -85,19 +85,18 @@ $ pip install python-multipart Поскольку все эти методы являются `async` методами, вам следует использовать "await" вместе с ними. -Например, внутри `async` *функции операции пути* можно получить содержимое с помощью: +Например, внутри `async` *функции-обработчика пути* можно получить содержимое с помощью: ```Python contents = await myfile.read() ``` -Если вы находитесь внутри обычной `def` *функции операции пути*, можно получить прямой доступ к файлу `UploadFile.file`, например: +Если вы находитесь внутри обычной `def` *функции-обработчика пути*, можно получить прямой доступ к файлу `UploadFile.file`, например: ```Python contents = myfile.file.read() ``` - /// note | Технические детали `async` При использовании методов `async` **FastAPI** запускает файловые методы в пуле потоков и ожидает их. @@ -106,7 +105,7 @@ contents = myfile.file.read() /// note | Технические детали Starlette -**FastAPI** наследует `UploadFile` непосредственно из **Starlette**, но добавляет некоторые детали для совместимости с **Pydantic** и другими частями FastAPI. +`UploadFile` из **FastAPI** наследуется непосредственно от `UploadFile` из **Starlette**, но добавляет некоторые необходимые части для совместимости с **Pydantic** и другими частями FastAPI. /// @@ -118,17 +117,17 @@ contents = myfile.file.read() /// note | Технические детали -Данные из форм обычно кодируются с использованием "media type" `application/x-www-form-urlencoded` когда он не включает файлы. +Данные из форм обычно кодируются с использованием типа содержимого `application/x-www-form-urlencoded`, когда они не включают файлы. -Но когда форма включает файлы, она кодируется как `multipart/form-data`. Если вы используете `File`, **FastAPI** будет знать, что ему нужно получить файлы из нужной части тела. +Но когда форма включает файлы, она кодируется как `multipart/form-data`. Если вы используете `File`, **FastAPI** будет знать, что ему нужно получить файлы из нужной части тела запроса. -Если вы хотите узнать больше об этих кодировках и полях форм, перейдите по ссылке [MDN web docs for `POST`](https://developer.mozilla.org/en-US/docs/Web/HTTP/Methods/POST). +Если вы хотите узнать больше об этих кодировках и полях форм, перейдите к [веб-документации MDN по `POST`](https://developer.mozilla.org/en-US/docs/Web/HTTP/Methods/POST). /// /// warning | Внимание -В операции *функции операции пути* можно объявить несколько параметров `File` и `Form`, но нельзя также объявлять поля `Body`, которые предполагается получить в виде JSON, поскольку тело запроса будет закодировано с помощью `multipart/form-data`, а не `application/json`. +В *операции пути* можно объявить несколько параметров `File` и `Form`, но нельзя также объявлять поля `Body`, которые предполагается получить в виде JSON, поскольку HTTP-запрос будет иметь тело, закодированное с помощью `multipart/form-data`, а не `application/json`. Это не является ограничением **FastAPI**, это часть протокола HTTP. @@ -174,4 +173,4 @@ contents = myfile.file.read() ## Резюме { #recap } -Используйте `File`, `bytes` и `UploadFile` для работы с файлами, которые будут загружаться и передаваться в виде данных формы. +Используйте `File`, `bytes` и `UploadFile`, чтобы объявлять файлы для загрузки в HTTP-запросе, передаваемые как данные формы. diff --git a/docs/ru/docs/tutorial/request-forms.md b/docs/ru/docs/tutorial/request-forms.md index 3108c933e..2067195dd 100644 --- a/docs/ru/docs/tutorial/request-forms.md +++ b/docs/ru/docs/tutorial/request-forms.md @@ -1,5 +1,6 @@ # Данные формы { #form-data } + Когда вам нужно получить поля формы вместо JSON, вы можете использовать `Form`. /// note | Примечание diff --git a/docs/ru/docs/tutorial/response-status-code.md b/docs/ru/docs/tutorial/response-status-code.md index ef190a341..16f83cd61 100644 --- a/docs/ru/docs/tutorial/response-status-code.md +++ b/docs/ru/docs/tutorial/response-status-code.md @@ -1,6 +1,6 @@ # Статус-код ответа { #response-status-code } -Подобно тому, как вы можете задать модель/схему ответа, вы можете объявить HTTP статус-код, используемый для ответа, с помощью параметра `status_code` в любой из *операций пути*: +Подобно тому, как вы можете задать модель ответа, вы можете объявить HTTP статус-код, используемый для ответа, с помощью параметра `status_code` в любой из *операций пути*: * `@app.get()` * `@app.post()` @@ -26,8 +26,8 @@ Это позволит: -* Возвращать указанный код статуса в ответе. -* Документировать его как код статуса ответа в OpenAPI схеме (а значит, и в пользовательских интерфейсах): +* Возвращать указанный статус-код в ответе. +* Документировать его как статус-код ответа в OpenAPI схеме (а значит, и в пользовательских интерфейсах): @@ -47,26 +47,26 @@ FastAPI знает об этом и создаст документацию Open /// -В протоколе HTTP числовой код состояния из 3 цифр отправляется как часть ответа. +В протоколе HTTP числовой статус-код из 3 цифр отправляется как часть ответа. -У кодов статуса есть названия, чтобы упростить их распознавание, но важны именно числовые значения. +У статус-кодов есть названия, чтобы упростить их распознавание, но важны именно числовые значения. Кратко: -* `100 - 199` – статус-коды информационного типа. Они редко используются разработчиками напрямую. Ответы с этими кодами не могут иметь тела. +* `100 - 199` – статус-коды информационного типа. Они редко используются разработчиками напрямую. Ответы с этими статус-кодами не могут иметь тела. * **`200 - 299`** – статус-коды, сообщающие об успешной обработке запроса. Они используются чаще всего. - * `200` – это код статуса ответа по умолчанию, который означает, что все прошло "OK". + * `200` – это статус-код по умолчанию, который означает, что все прошло "OK". * Другим примером может быть статус `201`, "Created". Он обычно используется после создания новой записи в базе данных. * Особый случай – `204`, "No Content". Этот статус ответа используется, когда нет содержимого для возврата клиенту, и поэтому ответ не должен иметь тела. -* **`300 - 399`** – статус-коды, сообщающие о перенаправлениях. Ответы с этими кодами статуса могут иметь или не иметь тело, за исключением ответов со статусом `304`, "Not Modified", у которых не должно быть тела. +* **`300 - 399`** – статус-коды, сообщающие о перенаправлениях. Ответы с этими статус-кодами могут иметь или не иметь тело, за исключением ответов со статусом `304`, "Not Modified", у которых не должно быть тела. * **`400 - 499`** – статус-коды, сообщающие о клиентской ошибке. Это ещё одна наиболее часто используемая категория. * Пример – код `404` для статуса "Not Found". * Для общих ошибок со стороны клиента можно просто использовать код `400`. -* `500 - 599` – статус-коды, сообщающие о серверной ошибке. Они почти никогда не используются разработчиками напрямую. Когда что-то идет не так в какой-то части кода вашего приложения или на сервере, он автоматически вернёт один из этих кодов статуса. +* `500 - 599` – статус-коды, сообщающие о серверной ошибке. Они почти никогда не используются разработчиками напрямую. Когда что-то идет не так в какой-то части кода вашего приложения или на сервере, он автоматически вернёт один из этих статус-кодов. /// tip | Подсказка -Чтобы узнать больше о HTTP кодах статуса и о том, для чего каждый из них предназначен, ознакомьтесь с [MDN документацией об HTTP статус-кодах](https://developer.mozilla.org/en-US/docs/Web/HTTP/Status). +Чтобы узнать больше о HTTP статус-кодах и о том, для чего каждый из них предназначен, ознакомьтесь с [MDN документацией об HTTP статус-кодах](https://developer.mozilla.org/en-US/docs/Web/HTTP/Status). /// @@ -76,7 +76,7 @@ FastAPI знает об этом и создаст документацию Open {* ../../docs_src/response_status_code/tutorial001_py310.py hl[6] *} -`201` – это код статуса "Создано". +`201` – это статус-код для "Created". Но вам не обязательно запоминать, что означает каждый из этих кодов. @@ -84,7 +84,7 @@ FastAPI знает об этом и создаст документацию Open {* ../../docs_src/response_status_code/tutorial002_py310.py hl[1,6] *} -Они содержат те же числовые значения, но позволяют использовать автозавершение редактора кода для выбора кода статуса: +Они существуют только для удобства, содержат те же числовые значения, но позволяют использовать автозавершение редактора кода для выбора статус-кода: diff --git a/docs/ru/docs/tutorial/schema-extra-example.md b/docs/ru/docs/tutorial/schema-extra-example.md index 435b34460..917e80838 100644 --- a/docs/ru/docs/tutorial/schema-extra-example.md +++ b/docs/ru/docs/tutorial/schema-extra-example.md @@ -1,4 +1,4 @@ -# Объявление примеров данных запроса { #declare-request-example-data } +# Объявление примеров данных HTTP-запроса { #declare-request-example-data } Вы можете объявлять примеры данных, которые ваше приложение может получать. @@ -12,7 +12,7 @@ Эта дополнительная информация будет добавлена как есть в выходную **JSON Schema** этой модели и будет использоваться в документации API. -Вы можете использовать атрибут `model_config`, который принимает `dict`, как описано в [Документация Pydantic: Конфигурация](https://docs.pydantic.dev/latest/api/config/). +Вы можете использовать атрибут `model_config`, который принимает `dict`, как описано в [документации Pydantic: Конфигурация](https://docs.pydantic.dev/latest/api/config/). Вы можете задать `"json_schema_extra"` с `dict`, содержащим любые дополнительные данные, которые вы хотите видеть в сгенерированной JSON Schema, включая `examples`. @@ -26,7 +26,7 @@ /// note | Примечание -OpenAPI 3.1.0 (используется начиная с FastAPI 0.99.0) добавил поддержку `examples`, который является частью стандарта **JSON Schema**. +OpenAPI 3.1.0 (используется начиная с FastAPI 0.99.0) добавил поддержку `examples`, которое является частью стандарта **JSON Schema**. До этого поддерживалось только ключевое слово `example` с одним примером. Оно всё ещё поддерживается в OpenAPI 3.1.0, но помечено как устаревшее и не является частью стандарта JSON Schema. Поэтому рекомендуется мигрировать `example` на `examples`. 🤓 @@ -80,13 +80,13 @@ OpenAPI 3.1.0 (используется начиная с FastAPI 0.99.0) доб Ещё до того как **JSON Schema** поддержала `examples`, в OpenAPI была поддержка другого поля, также называемого `examples`. -Эти **специфические для OpenAPI** `examples` находятся в другой секции спецификации OpenAPI. Они находятся в **подробностях для каждой операции пути (обработчика пути)**, а не внутри каждого объекта Schema. +Эти **специфические для OpenAPI** `examples` находятся в другой секции спецификации OpenAPI. Они находятся в **подробностях каждой *операции пути***, а не внутри каждой JSON Schema. И Swagger UI уже какое‑то время поддерживает именно это поле `examples`. Поэтому вы можете использовать его, чтобы **отобразить** разные **примеры в UI документации**. Структура этого специфичного для OpenAPI поля `examples` — это `dict` с **несколькими примерами** (вместо `list`), каждый с дополнительной информацией, которая также будет добавлена в **OpenAPI**. -Это не помещается внутрь каждого объекта Schema в OpenAPI, это находится снаружи, непосредственно на уровне самой *операции пути*. +Это не помещается внутрь каждой JSON Schema, содержащейся в OpenAPI, это находится снаружи, непосредственно на уровне самой *операции пути*. ### Использование параметра `openapi_examples` { #using-the-openapi-examples-parameter } diff --git a/docs/ru/docs/tutorial/security/first-steps.md b/docs/ru/docs/tutorial/security/first-steps.md index e702dfadb..35d63c843 100644 --- a/docs/ru/docs/tutorial/security/first-steps.md +++ b/docs/ru/docs/tutorial/security/first-steps.md @@ -186,9 +186,9 @@ oauth2_scheme(some, parameters) ## Что он делает { #what-it-does } -Он будет искать в запросе HTTP-заголовок `Authorization`, проверять, что его значение — это `Bearer ` плюс некоторый токен, и вернет токен как `str`. +Он будет искать в HTTP-запросе HTTP-заголовок `Authorization`, проверять, что его значение — это `Bearer ` плюс некоторый токен, и вернет токен как `str`. -Если заголовок `Authorization` отсутствует или его значение не содержит токен `Bearer `, он сразу ответит ошибкой со статус-кодом 401 (`UNAUTHORIZED`). +Если HTTP-заголовок `Authorization` отсутствует или его значение не содержит токен `Bearer `, он сразу ответит ошибкой со статус-кодом 401 (`UNAUTHORIZED`). Вам даже не нужно проверять наличие токена, чтобы вернуть ошибку. Вы можете быть уверены: если ваша функция была выполнена, в этом токене будет `str`. diff --git a/docs/ru/docs/tutorial/security/get-current-user.md b/docs/ru/docs/tutorial/security/get-current-user.md index 7bd48a9a0..8beebc51d 100644 --- a/docs/ru/docs/tutorial/security/get-current-user.md +++ b/docs/ru/docs/tutorial/security/get-current-user.md @@ -14,7 +14,7 @@ Точно так же, как мы используем Pydantic для объявления тел запросов, мы можем использовать его где угодно: -{* ../../docs_src/security/tutorial002_an_py310.py hl[5,12:6] *} +{* ../../docs_src/security/tutorial002_an_py310.py hl[5,12:16] *} ## Создать зависимость `get_current_user` { #create-a-get-current-user-dependency } @@ -54,7 +54,7 @@ /// tip | Подсказка -То, как устроена эта система зависимостей, позволяет иметь разные зависимости, которые возвращают модель `User`. +То, как устроена эта система зависимостей, позволяет иметь разные зависимости (разные "dependables"), которые все возвращают модель `User`. Мы не ограничены наличием только одной зависимости, которая может возвращать такой тип данных. diff --git a/docs/ru/docs/tutorial/security/oauth2-jwt.md b/docs/ru/docs/tutorial/security/oauth2-jwt.md index 0409cd0a9..63492e630 100644 --- a/docs/ru/docs/tutorial/security/oauth2-jwt.md +++ b/docs/ru/docs/tutorial/security/oauth2-jwt.md @@ -28,7 +28,7 @@ eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4 ## Установка `PyJWT` { #install-pyjwt } -Нам необходимо установить `pyjwt` для генерации и проверки JWT-токенов на языке Python. +Нам необходимо установить `PyJWT` для генерации и проверки JWT-токенов на языке Python. Убедитесь, что вы создали [виртуальное окружение](../../virtual-environments.md), активируйте его, а затем установите `pyjwt`: @@ -42,7 +42,7 @@ $ pip install pyjwt
-/// note | Дополнительная информация +/// note | Примечание Если вы планируете использовать алгоритмы цифровой подписи, такие как RSA или ECDSA, вам следует установить зависимость библиотеки криптографии `pyjwt[crypto]`. @@ -110,9 +110,9 @@ pwdlib также поддерживает алгоритм хешировани /// -Создайте служебную функцию для хэширования пароля, поступающего от пользователя. +Создайте вспомогательную функцию для хэширования пароля, поступающего от пользователя. -А затем создайте другую — для проверки соответствия полученного пароля и хранимого хэша. +А затем создайте другую вспомогательную функцию — для проверки соответствия полученного пароля и хранимого хэша. И еще одну — для аутентификации и возврата пользователя. @@ -120,15 +120,15 @@ pwdlib также поддерживает алгоритм хешировани Когда `authenticate_user` вызывается с именем пользователя, которого нет в базе данных, мы все равно запускаем `verify_password` с использованием фиктивного хэша. -Это гарантирует, что эндпоинт отвечает примерно за одно и то же время вне зависимости от того, существует имя пользователя или нет, предотвращая тайминговые атаки (атака по времени), с помощью которых можно было бы перечислять существующие имена пользователей. +Это гарантирует, что эндпоинт отвечает примерно за одно и то же время вне зависимости от того, существует имя пользователя или нет, предотвращая **тайминговые атаки** (атаки по времени), с помощью которых можно было бы перечислять существующие имена пользователей. -/// note | Технические детали +/// note | Примечание Если проверить новую (фальшивую) базу данных `fake_users_db`, то можно увидеть, как теперь выглядит хэшированный пароль: `"$argon2id$v=19$m=65536,t=3,p=4$wagCPXjifgvUFBzq4hqe3w$CYaIb8sB+wtD+Vu/P4uod1+Qof8h+1g7bbDlBID48Rc"`. /// -## Работа с JWT токенами { #handle-jwt-tokens } +## Работа с JWT-токенами { #handle-jwt-tokens } Импортируйте установленные модули. @@ -154,7 +154,7 @@ $ openssl rand -hex 32 Определите Pydantic-модель, которая будет использоваться для формирования ответа на запрос на получение токена. -Создайте служебную функцию для генерации нового токена доступа. +Создайте вспомогательную функцию для генерации нового токена доступа. {* ../../docs_src/security/tutorial004_an_py310.py hl[4,7,13:15,29:31,82:90] *} @@ -172,7 +172,7 @@ $ openssl rand -hex 32 Создайте `timedelta` со временем истечения срока действия токена. -Создайте реальный токен доступа JWT и верните его +Создайте реальный токен доступа JWT и верните его. {* ../../docs_src/security/tutorial004_an_py310.py hl[121:136] *} @@ -188,13 +188,13 @@ JWT может использоваться и для других целей, Затем вы могли бы добавить права доступа к этой сущности, например "управлять" (для автомобиля) или "редактировать" (для блога). -Затем вы могли бы передать этот JWT-токен пользователю (или боту), и они использовали бы его для выполнения определенных действий (управление автомобилем или редактирование запись в блоге), даже не имея учетной записи, просто используя JWT-токен, сгенерированный вашим API. +Затем вы могли бы передать этот JWT-токен пользователю (или боту), и они использовали бы его для выполнения определенных действий (управление автомобилем или редактирование записи в блоге), даже не имея учетной записи, просто используя JWT-токен, сгенерированный вашим API. Используя эти идеи, JWT можно применять для гораздо более сложных сценариев. В отдельных случаях несколько сущностей могут иметь один и тот же идентификатор, скажем, `foo` (пользователь `foo`, автомобиль `foo` и запись в блоге `foo`). -Поэтому, чтобы избежать коллизий идентификаторов, при создании JWT-токена для пользователя можно добавить префикс `username` к значению ключа `sub`. Таким образом, в данном примере значение `sub` было бы `username:johndoe`. +Поэтому, чтобы избежать коллизий идентификаторов, при создании JWT-токена для пользователя можно добавить префикс `username:` к значению ключа `sub`. Таким образом, в данном примере значение `sub` могло бы быть: `username:johndoe`. Важно помнить, что ключ `sub` должен иметь уникальный идентификатор для всего приложения и представлять собой строку. @@ -238,7 +238,7 @@ Password: `secret` -/// note | Техническая информация +/// note | Примечание Обратите внимание на HTTP-заголовок `Authorization`, значение которого начинается с `Bearer `. diff --git a/docs/ru/docs/tutorial/security/simple-oauth2.md b/docs/ru/docs/tutorial/security/simple-oauth2.md index 415ef017b..5ce89730c 100644 --- a/docs/ru/docs/tutorial/security/simple-oauth2.md +++ b/docs/ru/docs/tutorial/security/simple-oauth2.md @@ -14,7 +14,7 @@ OAuth2 определяет, что при использовании "password А ваши модели баз данных могут использовать любые другие имена. -Но для логин-операции пути нам нужно использовать именно эти имена, чтобы быть совместимыми со спецификацией (и иметь возможность, например, использовать встроенную систему документации API). +Но для *операции пути* входа в систему нам нужно использовать именно эти имена, чтобы быть совместимыми со спецификацией (и иметь возможность, например, использовать встроенную систему документации API). В спецификации также указано, что `username` и `password` должны передаваться в виде данных формы (так что никакого JSON здесь нет). @@ -88,7 +88,7 @@ OAuth2 определяет, что при использовании "password Теперь получим данные о пользователе из (ненастоящей) базы данных, используя `username` из поля формы. -Если такого пользователя нет, то мы возвращаем ошибку "Incorrect username or password" (неверное имя пользователя или пароль). +Если такого пользователя нет, то мы возвращаем ошибку "Incorrect username or password". Для ошибки используем исключение `HTTPException`: @@ -137,12 +137,12 @@ UserInDB( ``` /// note | Примечание -Более полное объяснение `**user_dict` можно найти в [документации к **Дополнительным моделям**](../extra-models.md#about-user-in-dict). +Более полное объяснение `**user_dict` можно найти в [документации к **Дополнительным моделям**](../extra-models.md#about-user-in-model-dump). /// ## Возврат токена { #return-the-token } -Ответ операции пути `/token` должен быть объектом JSON. +Ответ эндпоинта `token` должен быть объектом JSON. В нём должен быть `token_type`. В нашем случае, поскольку мы используем токены типа "Bearer", тип токена должен быть `bearer`. @@ -151,7 +151,7 @@ UserInDB( В этом простом примере мы намеренно поступим небезопасно и вернём тот же `username` в качестве токена. /// tip | Подсказка -В следующей главе вы увидите реальную защищённую реализацию с хешированием паролей и токенами JWT. +В следующей главе вы увидите реальную защищённую реализацию с хешированием паролей и токенами JWT. Но пока давайте сосредоточимся на необходимых нам деталях. /// @@ -266,8 +266,8 @@ UserInDB( Теперь у вас есть инструменты для реализации полноценной системы безопасности на основе `username` и `password` для вашего API. -Используя эти средства, можно сделать систему безопасности совместимой с любой базой данных и с любой пользовательской или моделью данных. +Используя эти средства, можно сделать систему безопасности совместимой с любой базой данных и с любой моделью пользователя или моделью данных. Единственная деталь, которой не хватает, — система пока ещё не "защищена" по-настоящему. -В следующей главе вы увидите, как использовать библиотеку безопасного хеширования паролей и токены JWT. +В следующей главе вы увидите, как использовать библиотеку безопасного хеширования паролей и токены JWT. diff --git a/docs/ru/docs/tutorial/sql-databases.md b/docs/ru/docs/tutorial/sql-databases.md index ae8637338..bf2e16fb9 100644 --- a/docs/ru/docs/tutorial/sql-databases.md +++ b/docs/ru/docs/tutorial/sql-databases.md @@ -1,6 +1,6 @@ # SQL (реляционные) базы данных { #sql-relational-databases } -**FastAPI** не требует использовать SQL (реляционную) базу данных. Но вы можете использовать любую базу данных, которую хотите. +**FastAPI** не требует использовать SQL (реляционную) базу данных. Но вы можете использовать **любую базу данных**, которую хотите. Здесь мы рассмотрим пример с использованием [SQLModel](https://sqlmodel.tiangolo.com/). @@ -8,7 +8,7 @@ /// tip | Подсказка -Вы можете использовать любую другую библиотеку для работы с SQL или NoSQL базами данных (иногда их называют "ORMs"), FastAPI ничего не навязывает. 😎 +Вы можете использовать любую другую библиотеку для работы с SQL или NoSQL базами данных (иногда их называют "ORMs"), FastAPI ничего не навязывает. 😎 /// @@ -119,7 +119,7 @@ $ pip install sqlmodel Так как каждая модель SQLModel также является моделью Pydantic, вы можете использовать её в тех же **аннотациях типов**, в которых используете модели Pydantic. -Например, если вы объявите параметр типа `Hero`, он будет прочитан из **JSON body (тела запроса)**. +Например, если вы объявите параметр типа `Hero`, он будет прочитан из **JSON-тела запроса**. Аналогично вы можете объявить её как **тип возвращаемого значения** функции, и тогда форма данных отобразится в автоматически сгенерированном UI документации API. diff --git a/docs/ru/docs/tutorial/static-files.md b/docs/ru/docs/tutorial/static-files.md index dfcc77b6f..84084ffac 100644 --- a/docs/ru/docs/tutorial/static-files.md +++ b/docs/ru/docs/tutorial/static-files.md @@ -2,6 +2,14 @@ Вы можете предоставлять статические файлы автоматически из директории, используя `StaticFiles`. +/// tip | Совет + +Если вам нужно разместить фронтенд, используйте вместо этого `app.frontend()`, подробнее читайте в разделе [Фронтенд](frontend.md). + +`app.frontend()` использует `StaticFiles` под капотом, с несколькими дополнительными преимуществами для фронтендов, такими как обработка маршрутизации на стороне клиента. + +/// + ## Использование `StaticFiles` { #use-staticfiles } * Импортируйте `StaticFiles`. @@ -21,8 +29,7 @@ "Монтирование" означает добавление полноценного "независимого" приложения на определённый путь, которое затем обрабатывает все подпути. -Это отличается от использования `APIRouter`, так как примонтированное приложение является полностью независимым. -OpenAPI и документация из вашего главного приложения не будут содержать ничего из примонтированного приложения, и т.д. +Это отличается от использования `APIRouter`, так как примонтированное приложение является полностью независимым. OpenAPI и документация из вашего главного приложения не будут содержать ничего из примонтированного приложения, и т.д. Вы можете прочитать больше об этом в [Расширенном руководстве пользователя](../advanced/index.md). diff --git a/docs/ru/docs/tutorial/testing.md b/docs/ru/docs/tutorial/testing.md index f7367bcba..d6038a3de 100644 --- a/docs/ru/docs/tutorial/testing.md +++ b/docs/ru/docs/tutorial/testing.md @@ -90,7 +90,7 @@ $ pip install httpx │   └── test_main.py ``` -Так как оба файла находятся в одной директории, для импорта объекта приложения из файла `main` в файл `test_main` Вы можете использовать относительный импорт: +Так как этот файл находится в том же пакете, для импорта объекта `app` из модуля `main` (`main.py`) Вы можете использовать относительный импорт: {* ../../docs_src/app_testing/app_a_py310/test_main.py hl[3] *} @@ -113,7 +113,7 @@ $ pip install httpx │   └── test_main.py ``` -Предположим, что в файле `main.py` с приложением **FastAPI** есть несколько **операций пути**. +Предположим, что теперь в файле `main.py` с приложением **FastAPI** есть несколько других **операций пути**. В нём описана операция `GET`, которая может вернуть ошибку. @@ -125,20 +125,20 @@ $ pip install httpx ### Расширенный файл тестов { #extended-testing-file } -Теперь обновим файл `test_main.py`, добавив в него тестов: +Теперь можно обновить файл `test_main.py`, добавив в него расширенные тесты: {* ../../docs_src/app_testing/app_b_an_py310/test_main.py *} -Если Вы не знаете, как передать информацию в запросе, можете воспользоваться поисковиком (погуглить) и задать вопрос: "Как передать информацию в запросе с помощью `httpx`", можно даже спросить: "Как передать информацию в запросе с помощью `requests`", поскольку дизайн HTTPX основан на дизайне Requests. +Если Вы не знаете, как передать информацию в запросе, можете воспользоваться поиском (Google) и задать вопрос: "Как передать информацию в запросе с помощью `httpx`", можно даже спросить: "Как передать информацию в запросе с помощью `requests`", поскольку дизайн HTTPX основан на дизайне Requests. Затем Вы просто применяете найденные ответы в тестах. Например: -* Передаёте *path*-параметры или *query*-параметры, вписав их непосредственно в строку URL. +* Чтобы передать *path*-параметр или *query*-параметр, добавьте его непосредственно в URL. * Передаёте JSON в теле запроса, передав Python-объект (например: `dict`) через именованный параметр `json`. -* Если же Вам необходимо отправить *форму с данными* вместо JSON, то используйте параметр `data` вместо `json`. +* Если же Вам необходимо отправить *данные формы* вместо JSON, то используйте параметр `data` вместо `json`. * Для передачи *HTTP-заголовков*, передайте объект `dict` через параметр `headers`. * Для передачи *cookies* также передайте `dict`, но через параметр `cookies`. diff --git a/docs/ru/docs/virtual-environments.md b/docs/ru/docs/virtual-environments.md index 119f3645e..b7c750842 100644 --- a/docs/ru/docs/virtual-environments.md +++ b/docs/ru/docs/virtual-environments.md @@ -811,7 +811,7 @@ $ cd ~/code/prisoner-of-azkaban $ python main.py -// Error importing sirius, it's not installed 😱 +// Ошибка при импорте sirius, он не установлен 😱 Traceback (most recent call last): File "main.py", line 1, in import sirius From 6c0df1738dc8893e6415ec7c58251898bd63a7a0 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Wed, 1 Jul 2026 12:52:28 +0000 Subject: [PATCH 361/462] =?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 edbcb6e10..9473c1b7e 100644 --- a/docs/en/docs/release-notes.md +++ b/docs/en/docs/release-notes.md @@ -9,6 +9,7 @@ hide: ### Translations +* 🌐 Update translations for ru (update-outdated). PR [#15894](https://github.com/fastapi/fastapi/pull/15894) by [@tiangolo](https://github.com/tiangolo). * 🌐 Update translations for ko (add-missing). PR [#15888](https://github.com/fastapi/fastapi/pull/15888) by [@tiangolo](https://github.com/tiangolo). * 🌐 Update translations for es (add-missing). PR [#15880](https://github.com/fastapi/fastapi/pull/15880) by [@tiangolo](https://github.com/tiangolo). * 🌐 Update translations for zh-hant (add-missing). PR [#15889](https://github.com/fastapi/fastapi/pull/15889) by [@tiangolo](https://github.com/tiangolo). From 3b7cb60067b982ac682a21485ee413fe89832d80 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebasti=C3=A1n=20Ram=C3=ADrez?= Date: Wed, 1 Jul 2026 15:16:28 +0200 Subject: [PATCH 362/462] =?UTF-8?q?=F0=9F=8C=90=20Update=20translations=20?= =?UTF-8?q?for=20ko=20(update-outdated)=20(#15890)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: github-actions[bot] Co-authored-by: Yurii Motov --- docs/ko/docs/_llm-test.md | 12 +-- .../docs/advanced/additional-status-codes.md | 2 +- .../ko/docs/advanced/advanced-dependencies.md | 2 +- docs/ko/docs/advanced/dataclasses.md | 2 +- docs/ko/docs/advanced/events.md | 14 +-- docs/ko/docs/advanced/generate-clients.md | 14 --- docs/ko/docs/advanced/json-base64-bytes.md | 2 +- docs/ko/docs/advanced/openapi-callbacks.md | 2 +- .../advanced/response-change-status-code.md | 1 + docs/ko/docs/advanced/response-cookies.md | 2 +- docs/ko/docs/advanced/response-headers.md | 1 + .../docs/advanced/security/oauth2-scopes.md | 4 +- docs/ko/docs/advanced/settings.md | 1 + docs/ko/docs/advanced/stream-data.md | 18 ++-- docs/ko/docs/advanced/wsgi.md | 2 +- docs/ko/docs/alternatives.md | 46 +++++----- docs/ko/docs/async.md | 1 + docs/ko/docs/deployment/cloud.md | 4 +- docs/ko/docs/deployment/concepts.md | 10 +-- docs/ko/docs/deployment/docker.md | 36 ++++---- docs/ko/docs/deployment/https.md | 2 +- docs/ko/docs/deployment/manually.md | 12 +-- docs/ko/docs/editor-support.md | 1 + docs/ko/docs/environment-variables.md | 1 + docs/ko/docs/features.md | 8 +- docs/ko/docs/help-fastapi.md | 1 + docs/ko/docs/how-to/configure-swagger-ui.md | 2 +- .../docs/how-to/custom-request-and-route.md | 1 + docs/ko/docs/how-to/graphql.md | 2 +- ...migrate-from-pydantic-v1-to-pydantic-v2.md | 18 ++++ .../docs/how-to/separate-openapi-schemas.md | 2 +- docs/ko/docs/index.md | 10 +-- docs/ko/docs/project-generation.md | 1 + docs/ko/docs/python-types.md | 4 +- docs/ko/docs/tutorial/bigger-applications.md | 90 +++++++++---------- docs/ko/docs/tutorial/body-nested-models.md | 2 +- docs/ko/docs/tutorial/body.md | 10 +-- docs/ko/docs/tutorial/debugging.md | 4 +- .../dependencies/dependencies-with-yield.md | 19 ++-- docs/ko/docs/tutorial/extra-data-types.md | 1 + docs/ko/docs/tutorial/extra-models.md | 8 +- docs/ko/docs/tutorial/first-steps.md | 29 +++--- docs/ko/docs/tutorial/handling-errors.md | 1 + docs/ko/docs/tutorial/index.md | 1 + docs/ko/docs/tutorial/metadata.md | 4 +- .../tutorial/path-operation-configuration.md | 1 + .../tutorial/query-params-str-validations.md | 4 +- docs/ko/docs/tutorial/query-params.md | 1 + docs/ko/docs/tutorial/request-files.md | 4 +- docs/ko/docs/tutorial/request-forms.md | 1 + docs/ko/docs/tutorial/response-status-code.md | 1 + docs/ko/docs/tutorial/schema-extra-example.md | 2 +- docs/ko/docs/tutorial/security/first-steps.md | 1 + .../tutorial/security/get-current-user.md | 2 +- docs/ko/docs/tutorial/security/oauth2-jwt.md | 1 + .../docs/tutorial/security/simple-oauth2.md | 6 +- docs/ko/docs/tutorial/sql-databases.md | 1 + docs/ko/docs/tutorial/static-files.md | 8 ++ docs/ko/docs/tutorial/testing.md | 8 +- docs/ko/docs/virtual-environments.md | 1 + 60 files changed, 243 insertions(+), 209 deletions(-) diff --git a/docs/ko/docs/_llm-test.md b/docs/ko/docs/_llm-test.md index ea22d6191..9e9d0ee73 100644 --- a/docs/ko/docs/_llm-test.md +++ b/docs/ko/docs/_llm-test.md @@ -7,11 +7,11 @@ 사용 방법은 다음과 같습니다: * 언어별 프롬프트 `docs/{language code}/llm-prompt.md`를 준비합니다. -* 이 문서를 원하는 대상 언어로 새로 번역합니다(예: `translate.py`의 `translate-page` 명령). 그러면 `docs/{language code}/docs/_llm-test.md` 아래에 번역이 생성됩니다. +* 이 문서를 원하는 대상 언어로 새로 번역합니다(예: `translate.py`의 `translate-page` 명령어). 그러면 `docs/{language code}/docs/_llm-test.md` 아래에 번역이 생성됩니다. * 번역에서 문제가 없는지 확인합니다. * 필요하다면 언어별 프롬프트, 일반 프롬프트, 또는 영어 문서를 개선합니다. * 그런 다음 번역에서 남아 있는 문제를 수동으로 수정해 좋은 번역이 되게 합니다. -* 좋은 번역을 둔 상태에서 다시 번역합니다. 이상적인 결과는 LLM이 더 이상 번역에 변경을 만들지 않는 것입니다. 이는 일반 프롬프트와 언어별 프롬프트가 가능한 한 최선이라는 뜻입니다(때때로 몇 가지 seemingly random 변경을 할 수 있는데, 그 이유는 [LLM은 결정론적 알고리즘이 아니기 때문](https://doublespeak.chat/#/handbook#deterministic-output)입니다). +* 좋은 번역을 둔 상태에서 다시 번역합니다. 이상적인 결과는 LLM이 더 이상 번역에 변경을 만들지 않는 것입니다. 이는 일반 프롬프트와 언어별 프롬프트가 가능한 한 최선이라는 뜻입니다(때때로 몇 가지 겉보기에 무작위인 변경을 할 수 있는데, 그 이유는 [LLM은 결정론적 알고리즘이 아니기 때문](https://doublespeak.chat/#/handbook#deterministic-output)입니다). 테스트: @@ -150,7 +150,7 @@ works(foo="bar") # 이건 동작합니다 🎉 탭과 `Info`/`Note`/`Warning`/등의 블록은 제목 번역을 수직 막대(`|`) 뒤에 추가해야 합니다. -`scripts/translate.py`의 일반 프롬프트에서 `### Special blocks`와 `### Tab blocks` 석션을 참고하세요. +`scripts/translate.py`의 일반 프롬프트에서 `### Special blocks`와 `### Tab blocks` 섹션을 참고하세요. //// @@ -240,7 +240,7 @@ works(foo="bar") # 이건 동작합니다 🎉 `scripts/translate.py`의 일반 프롬프트에서 `### Headings` 섹션을 참고하세요. -언어별 지침은 예를 들어 `docs/de/llm-prompt.md`의 `### Headings` 석션을 참고하세요. +언어별 지침은 예를 들어 `docs/de/llm-prompt.md`의 `### Headings` 섹션을 참고하세요. //// @@ -289,7 +289,7 @@ works(foo="bar") # 이건 동작합니다 🎉 * 애플리케이션을 서빙하다 * 페이지를 서빙하다 -* 앱 +* 애플리케이션 * 애플리케이션 * 요청 @@ -490,6 +490,6 @@ works(foo="bar") # 이건 동작합니다 🎉 이것은 문서에서 보이는 (대부분) 기술 용어의 불완전하고 비규범적인 목록입니다. 프롬프트 설계자가 어떤 용어에 대해 LLM에 추가적인 도움이 필요한지 파악하는 데 유용할 수 있습니다. 예를 들어, 좋은 번역을 계속 덜 좋은 번역으로 되돌릴 때, 또는 언어에서 용어의 활용/변화를 처리하는 데 문제가 있을 때 도움이 됩니다. -예를 들어 `docs/de/llm-prompt.md`의 `### List of English terms and their preferred German translations` 석션을 참고하세요. +예를 들어 `docs/de/llm-prompt.md`의 `### List of English terms and their preferred German translations` 섹션을 참고하세요. //// diff --git a/docs/ko/docs/advanced/additional-status-codes.md b/docs/ko/docs/advanced/additional-status-codes.md index 6251b68b2..4762c8eed 100644 --- a/docs/ko/docs/advanced/additional-status-codes.md +++ b/docs/ko/docs/advanced/additional-status-codes.md @@ -8,7 +8,7 @@ 기본 상태 코드와 별도로 추가 상태 코드를 반환하려면 `JSONResponse`와 같이 `Response`를 직접 반환하고 추가 상태 코드를 직접 설정할 수 있습니다. -예를 들어 항목을 업데이트할 수 있는 *경로 처리*가 있고 성공 시 200 “OK”의 HTTP 상태 코드를 반환한다고 가정해 보겠습니다. +예를 들어 항목을 업데이트할 수 있는 *경로 처리*가 있고 성공 시 200 "OK"의 HTTP 상태 코드를 반환한다고 가정해 보겠습니다. 하지만 새로운 항목을 허용하기를 원할 것입니다. 그리고 항목이 이전에 존재하지 않았다면 이를 생성하고 HTTP 상태 코드 201 "Created"를 반환합니다. diff --git a/docs/ko/docs/advanced/advanced-dependencies.md b/docs/ko/docs/advanced/advanced-dependencies.md index 3a35bbfc7..49b96bdad 100644 --- a/docs/ko/docs/advanced/advanced-dependencies.md +++ b/docs/ko/docs/advanced/advanced-dependencies.md @@ -79,7 +79,7 @@ checker(q="somequery") ### `yield`와 `scope`가 있는 의존성 { #dependencies-with-yield-and-scope } -0.121.0 버전에서 FastAPI는 `Depends(scope="function")` 지원을 추가했습니다. +0.121.0 버전에서 FastAPI는 `yield`가 있는 의존성을 위한 `Depends(scope="function")` 지원을 추가했습니다. `Depends(scope="function")`를 사용하면, `yield` 이후의 종료 코드는 *경로 처리 함수*가 끝난 직후(클라이언트에 응답이 반환되기 전)에 실행됩니다. diff --git a/docs/ko/docs/advanced/dataclasses.md b/docs/ko/docs/advanced/dataclasses.md index fb5d9fbd9..609cb6cd9 100644 --- a/docs/ko/docs/advanced/dataclasses.md +++ b/docs/ko/docs/advanced/dataclasses.md @@ -18,7 +18,7 @@ FastAPI는 **Pydantic** 위에 구축되어 있으며, 지금까지는 Pydantic 이는 Pydantic 모델을 사용할 때와 같은 방식으로 동작합니다. 그리고 실제로도 내부적으로는 Pydantic을 사용해 같은 방식으로 구현됩니다. -/// note +/// note | 참고 dataclasses는 Pydantic 모델이 할 수 있는 모든 것을 할 수는 없다는 점을 기억하세요. diff --git a/docs/ko/docs/advanced/events.md b/docs/ko/docs/advanced/events.md index 24ce55b4c..13db29ef2 100644 --- a/docs/ko/docs/advanced/events.md +++ b/docs/ko/docs/advanced/events.md @@ -6,15 +6,15 @@ 이 코드는 애플리케이션이 요청을 받기 **시작**하기 전에 실행되고, 요청 처리를 **끝낸 직후**에 실행되기 때문에 전체 애플리케이션의 **수명(lifespan)**을 다룹니다(잠시 후 "lifespan"이라는 단어가 중요해집니다 😉). -이는 전체 앱에서 사용해야 하는 **자원**을 설정하고, 요청 간에 **공유되는** 자원을 설정하고, 그리고/또는 이후에 **정리**하는 데 매우 유용할 수 있습니다. 예를 들어, 데이터베이스 연결 풀 또는 공유 머신러닝 모델을 로드하는 경우입니다. +이는 전체 애플리케이션에서 사용해야 하는 **자원**을 설정하고, 요청 간에 **공유되는** 자원을 설정하고, 그리고/또는 이후에 **정리**하는 데 매우 유용할 수 있습니다. 예를 들어, 데이터베이스 연결 풀 또는 공유 머신러닝 모델을 로드하는 경우입니다. ## 사용 사례 { #use-case } 먼저 **사용 사례** 예시로 시작한 다음, 이를 어떻게 해결할지 살펴보겠습니다. -요청을 처리하는 데 사용하고 싶은 **머신러닝 모델**이 있다고 상상해 봅시다. 🤖 +요청을 처리하는 데 사용하고 싶은 몇 가지 **머신러닝 모델**이 있다고 상상해 봅시다. 🤖 -동일한 모델이 요청 간에 공유되므로, 요청마다 모델이 하나씩 있거나 사용자마다 하나씩 있는 등의 방식이 아닙니다. +동일한 모델들이 요청 간에 공유되므로, 요청마다 모델이 하나씩 있거나 사용자마다 하나씩 있는 등의 방식이 아닙니다. 모델을 로드하는 데 **상당한 시간이 걸린다고 상상해 봅시다**, 왜냐하면 모델이 **디스크에서 많은 데이터를 읽어야** 하기 때문입니다. 그래서 모든 요청마다 이를 수행하고 싶지는 않습니다. @@ -24,7 +24,7 @@ ## Lifespan { #lifespan } -`FastAPI` 앱의 `lifespan` 매개변수와 "컨텍스트 매니저"를 사용하여 *시작*과 *종료* 로직을 정의할 수 있습니다(컨텍스트 매니저가 무엇인지 잠시 후에 보여드리겠습니다). +`FastAPI` 애플리케이션의 `lifespan` 매개변수와 "컨텍스트 매니저"를 사용하여 *시작*과 *종료* 로직을 정의할 수 있습니다(컨텍스트 매니저가 무엇인지 잠시 후에 보여드리겠습니다). 예제로 시작한 다음 자세히 살펴보겠습니다. @@ -32,7 +32,7 @@ {* ../../docs_src/events/tutorial003_py310.py hl[16,19] *} -여기서는 `yield` 이전에 (가짜) 모델 함수를 머신러닝 모델이 들어 있는 딕셔너리에 넣어 모델을 로드하는 비용이 큰 *시작* 작업을 시뮬레이션합니다. 이 코드는 애플리케이션이 **요청을 받기 시작하기 전**, *시작* 동안에 실행됩니다. +여기서는 `yield` 이전에 (가짜) 모델 함수를 머신러닝 모델들이 들어 있는 딕셔너리에 넣어 모델을 로드하는 비용이 큰 *시작* 작업을 시뮬레이션합니다. 이 코드는 애플리케이션이 **요청을 받기 시작하기 전**, *시작* 동안에 실행됩니다. 그리고 `yield` 직후에는 모델을 언로드합니다. 이 코드는 애플리케이션이 **요청 처리를 마친 후**, *종료* 직전에 실행됩니다. 예를 들어 메모리나 GPU 같은 자원을 해제할 수 있습니다. @@ -80,7 +80,7 @@ async with lifespan(app): 위의 코드 예제에서는 직접 사용하지 않고, FastAPI에 전달하여 FastAPI가 이를 사용하도록 합니다. -`FastAPI` 앱의 `lifespan` 매개변수는 **비동기 컨텍스트 매니저**를 받으므로, 새 `lifespan` 비동기 컨텍스트 매니저를 전달할 수 있습니다. +`FastAPI` 애플리케이션의 `lifespan` 매개변수는 **비동기 컨텍스트 매니저**를 받으므로, 새 `lifespan` 비동기 컨텍스트 매니저를 전달할 수 있습니다. {* ../../docs_src/events/tutorial003_py310.py hl[22] *} @@ -88,7 +88,7 @@ async with lifespan(app): /// warning | 경고 -*시작*과 *종료*를 처리하는 권장 방법은 위에서 설명한 대로 `FastAPI` 앱의 `lifespan` 매개변수를 사용하는 것입니다. `lifespan` 매개변수를 제공하면 `startup`과 `shutdown` 이벤트 핸들러는 더 이상 호출되지 않습니다. `lifespan`만 쓰거나 이벤트만 쓰거나 둘 중 하나이지, 둘 다는 아닙니다. +*시작*과 *종료*를 처리하는 권장 방법은 위에서 설명한 대로 `FastAPI` 애플리케이션의 `lifespan` 매개변수를 사용하는 것입니다. `lifespan` 매개변수를 제공하면 `startup`과 `shutdown` 이벤트 핸들러는 더 이상 호출되지 않습니다. `lifespan`만 쓰거나 이벤트만 쓰거나 둘 중 하나이지, 둘 다는 아닙니다. 이 부분은 아마 건너뛰셔도 됩니다. diff --git a/docs/ko/docs/advanced/generate-clients.md b/docs/ko/docs/advanced/generate-clients.md index f85db8cb9..9cbe46ff8 100644 --- a/docs/ko/docs/advanced/generate-clients.md +++ b/docs/ko/docs/advanced/generate-clients.md @@ -20,20 +20,6 @@ FastAPI는 **OpenAPI 3.1** 사양을 자동으로 생성하므로, 사용하는 /// -## FastAPI 스폰서의 SDK 생성기 { #sdk-generators-from-fastapi-sponsors } - -이 섹션에서는 FastAPI를 후원하는 회사들이 제공하는 **벤처 투자 기반** 및 **기업 지원** 솔루션을 소개합니다. 이 제품들은 고품질로 생성된 SDK에 더해 **추가 기능**과 **통합**을 제공합니다. - -✨ [**FastAPI 후원하기**](../help-fastapi.md#sponsor-the-author) ✨를 통해, 이 회사들은 프레임워크와 그 **생태계**가 건강하고 **지속 가능**하게 유지되도록 돕습니다. - -또한 이들의 후원은 FastAPI **커뮤니티**(여러분)에 대한 강한 헌신을 보여주며, **좋은 서비스**를 제공하는 것뿐 아니라, 견고하고 활발한 프레임워크인 FastAPI를 지원하는 데에도 관심이 있음을 나타냅니다. 🙇 - -예를 들어 다음을 사용해 볼 수 있습니다: - -* [Stainless](https://www.stainless.com/?utm_source=fastapi&utm_medium=referral) - -이 중 일부는 오픈 소스이거나 무료 티어를 제공하므로, 비용 부담 없이 사용해 볼 수 있습니다. 다른 상용 SDK 생성기도 있으며 온라인에서 찾을 수 있습니다. 🤓 - ## TypeScript SDK 만들기 { #create-a-typescript-sdk } 간단한 FastAPI 애플리케이션으로 시작해 보겠습니다: diff --git a/docs/ko/docs/advanced/json-base64-bytes.md b/docs/ko/docs/advanced/json-base64-bytes.md index b5e55a41a..b24acda86 100644 --- a/docs/ko/docs/advanced/json-base64-bytes.md +++ b/docs/ko/docs/advanced/json-base64-bytes.md @@ -4,7 +4,7 @@ ## Base64와 파일 { #base64-vs-files } -바이너리 데이터 업로드에는 [요청 파일](../tutorial/request-files.md)을, 바이너리 데이터 전송에는 [커스텀 응답 - FileResponse](./custom-response.md#fileresponse--fileresponse-)를 사용할 수 있는지 먼저 고려하세요. JSON으로 인코딩하는 대신 말입니다. +바이너리 데이터 업로드에는 [요청 파일](../tutorial/request-files.md)을, 바이너리 데이터 전송에는 [커스텀 응답 - FileResponse](./custom-response.md#fileresponse)를 사용할 수 있는지 먼저 고려하세요. JSON으로 인코딩하는 대신 말입니다. JSON은 UTF-8로 인코딩된 문자열만 포함할 수 있으므로, 원시 바이트를 그대로 담을 수 없습니다. diff --git a/docs/ko/docs/advanced/openapi-callbacks.md b/docs/ko/docs/advanced/openapi-callbacks.md index f9769209a..a44997ba2 100644 --- a/docs/ko/docs/advanced/openapi-callbacks.md +++ b/docs/ko/docs/advanced/openapi-callbacks.md @@ -165,7 +165,7 @@ https://www.external.org/events/invoices/2expen51ve ### 콜백 라우터 추가하기 { #add-the-callback-router } -이 시점에서, 위에서 만든 콜백 라우터 안에 *콜백 경로 처리(들)*(즉 *external developer*가 *external API*에 구현해야 하는 것들)을 준비했습니다. +이 시점에서, 위에서 만든 콜백 라우터 안에 *콜백 경로 처리(들)*(즉 *외부 개발자*가 *external API*에 구현해야 하는 것들)을 준비했습니다. 이제 *여러분의 API 경로 처리 데코레이터*에서 `callbacks` 파라미터를 사용해, 그 콜백 라우터의 `.routes` 속성을 전달합니다: diff --git a/docs/ko/docs/advanced/response-change-status-code.md b/docs/ko/docs/advanced/response-change-status-code.md index f30474917..5e54dc75e 100644 --- a/docs/ko/docs/advanced/response-change-status-code.md +++ b/docs/ko/docs/advanced/response-change-status-code.md @@ -1,5 +1,6 @@ # 응답 - 상태 코드 변경 { #response-change-status-code } + 기본 [응답 상태 코드 설정](../tutorial/response-status-code.md)이 가능하다는 걸 이미 알고 계실 겁니다. 하지만 경우에 따라 기본 설정과 다른 상태 코드를 반환해야 할 때가 있습니다. diff --git a/docs/ko/docs/advanced/response-cookies.md b/docs/ko/docs/advanced/response-cookies.md index b73d71969..f17046e7b 100644 --- a/docs/ko/docs/advanced/response-cookies.md +++ b/docs/ko/docs/advanced/response-cookies.md @@ -26,7 +26,7 @@ {* ../../docs_src/response_cookies/tutorial001_py310.py hl[10:12] *} -/// tip +/// tip | 팁 `Response` 매개변수를 사용하지 않고 응답을 직접 반환하는 경우, FastAPI는 이를 직접 반환한다는 점에 유의하세요. diff --git a/docs/ko/docs/advanced/response-headers.md b/docs/ko/docs/advanced/response-headers.md index e7157d8f4..769972967 100644 --- a/docs/ko/docs/advanced/response-headers.md +++ b/docs/ko/docs/advanced/response-headers.md @@ -1,5 +1,6 @@ # 응답 헤더 { #response-headers } + ## `Response` 매개변수 사용하기 { #use-a-response-parameter } 여러분은 *경로 처리 함수*에서 `Response` 타입의 매개변수를 선언할 수 있습니다 (쿠키와 같이 사용할 수 있습니다). diff --git a/docs/ko/docs/advanced/security/oauth2-scopes.md b/docs/ko/docs/advanced/security/oauth2-scopes.md index 6aed77f75..265f82aa7 100644 --- a/docs/ko/docs/advanced/security/oauth2-scopes.md +++ b/docs/ko/docs/advanced/security/oauth2-scopes.md @@ -4,9 +4,9 @@ 이를 통해 OAuth2 표준을 따르는 더 세밀한 권한 시스템을 OpenAPI 애플리케이션(및 API 문서)에 통합할 수 있습니다. -스코프를 사용하는 OAuth2는 Facebook, Google, GitHub, Microsoft, X(Twitter) 등 많은 대형 인증 제공자가 사용하는 메커니즘입니다. 이들은 이를 통해 사용자와 애플리케이션에 특정 권한을 제공합니다. +스코프를 사용하는 OAuth2는 Facebook, Google, GitHub, Microsoft, X (Twitter) 등 많은 대형 인증 제공자가 사용하는 메커니즘입니다. 이들은 이를 통해 사용자와 애플리케이션에 특정 권한을 제공합니다. -Facebook, Google, GitHub, Microsoft, X(Twitter)로 “로그인”할 때마다, 해당 애플리케이션은 스코프가 있는 OAuth2를 사용하고 있습니다. +Facebook, Google, GitHub, Microsoft, X (Twitter)로 “로그인”할 때마다, 해당 애플리케이션은 스코프가 있는 OAuth2를 사용하고 있습니다. 이 섹션에서는 **FastAPI** 애플리케이션에서 동일한 “스코프가 있는 OAuth2”로 인증(Authentication)과 인가(Authorization)를 관리하는 방법을 확인합니다. diff --git a/docs/ko/docs/advanced/settings.md b/docs/ko/docs/advanced/settings.md index 49a2b640e..f7e8c20e7 100644 --- a/docs/ko/docs/advanced/settings.md +++ b/docs/ko/docs/advanced/settings.md @@ -1,5 +1,6 @@ # 설정과 환경 변수 { #settings-and-environment-variables } + 많은 경우 애플리케이션에는 외부 설정이나 구성(예: secret key, 데이터베이스 자격 증명, 이메일 서비스 자격 증명 등)이 필요할 수 있습니다. 이러한 설정 대부분은 데이터베이스 URL처럼 변동 가능(변경될 수 있음)합니다. 그리고 많은 설정은 secret처럼 민감할 수 있습니다. diff --git a/docs/ko/docs/advanced/stream-data.md b/docs/ko/docs/advanced/stream-data.md index 33013fddd..94276876f 100644 --- a/docs/ko/docs/advanced/stream-data.md +++ b/docs/ko/docs/advanced/stream-data.md @@ -2,7 +2,7 @@ JSON으로 구조화할 수 있는 데이터를 스트리밍하려면 [JSON Lines 스트리밍](../tutorial/stream-json-lines.md)을 사용하세요. -하지만 순수 바이너리 데이터나 문자열을 스트리밍하려면 다음과 같이 하면 됩니다. +하지만 **순수 바이너리 데이터**나 문자열을 스트리밍하려면 다음과 같이 하면 됩니다. /// note | 참고 @@ -12,21 +12,21 @@ FastAPI 0.134.0에 추가되었습니다. ## 사용 예시 { #use-cases } -예를 들어 AI LLM 서비스의 출력에서 바로 순수 문자열을 스트리밍하고 싶다면 이를 사용할 수 있습니다. +예를 들어 **AI LLM** 서비스의 출력에서 바로 순수 문자열을 스트리밍하고 싶다면 이를 사용할 수 있습니다. -또한 큰 바이너리 파일을 스트리밍하는 데 사용할 수 있습니다. 한 번에 모두 메모리로 읽지 않고, 읽는 즉시 데이터 청크를 순차적으로 스트리밍합니다. +또한 **큰 바이너리 파일**을 스트리밍하는 데 사용할 수 있습니다. 한 번에 모두 메모리로 읽지 않고, 읽는 즉시 데이터 청크를 순차적으로 스트리밍합니다. -이 방식으로 비디오나 오디오를 스트리밍할 수도 있으며, 처리하면서 생성된 데이터를 곧바로 전송할 수도 있습니다. +이 방식으로 **비디오**나 **오디오**를 스트리밍할 수도 있으며, 처리하면서 생성된 데이터를 곧바로 전송할 수도 있습니다. ## `yield`와 함께 `StreamingResponse` 사용하기 { #a-streamingresponse-with-yield } -경로 처리 함수에서 `response_class=StreamingResponse`를 선언하면 `yield`를 사용해 데이터 청크를 순차적으로 보낼 수 있습니다. +*경로 처리 함수*에서 `response_class=StreamingResponse`를 선언하면 `yield`를 사용해 데이터 청크를 순차적으로 보낼 수 있습니다. {* ../../docs_src/stream_data/tutorial001_py310.py ln[1:23] hl[20,23] *} FastAPI는 각 데이터 청크를 있는 그대로 `StreamingResponse`에 전달하며, JSON 등으로 변환하려고 하지 않습니다. -### async가 아닌 경로 처리 함수 { #non-async-path-operation-functions } +### async가 아닌 *경로 처리 함수* { #non-async-path-operation-functions } `async`가 없는 일반 `def` 함수에서도 동일하게 `yield`를 사용할 수 있습니다. @@ -40,7 +40,7 @@ FastAPI는 데이터를 Pydantic으로 JSON으로 변환하거나 어떤 방식 {* ../../docs_src/stream_data/tutorial001_py310.py ln[32:35] hl[33] *} -이는 곧 `StreamingResponse`를 사용할 때 타입 애너테이션과 무관하게, 전송 기준에 맞춰 바이트 데이터를 생성하고 인코딩할 자유와 책임이 여러분에게 있음을 의미합니다. 🤓 +이는 곧 `StreamingResponse`를 사용할 때 타입 애너테이션과 무관하게, 전송 기준에 맞춰 바이트 데이터를 생성하고 인코딩할 **자유**와 **책임**이 여러분에게 있음을 의미합니다. 🤓 ### 바이트 스트리밍 { #stream-bytes } @@ -58,7 +58,7 @@ FastAPI는 데이터를 Pydantic으로 JSON으로 변환하거나 어떤 방식 {* ../../docs_src/stream_data/tutorial002_py310.py ln[6,19:20] hl[20] *} -그런 다음 경로 처리 함수에서 `response_class=PNGStreamingResponse`로 이 새 클래스를 사용할 수 있습니다: +그런 다음 *경로 처리 함수*에서 `response_class=PNGStreamingResponse`로 이 새 클래스를 사용할 수 있습니다: {* ../../docs_src/stream_data/tutorial002_py310.py ln[23:27] hl[23] *} @@ -98,7 +98,7 @@ FastAPI는 데이터를 Pydantic으로 JSON으로 변환하거나 어떤 방식 /// -이벤트 루프가 블로킹되는 것을 피하려면 경로 처리 함수를 `async def` 대신 일반 `def`로 선언하세요. 그러면 FastAPI가 스레드풀 워커에서 실행하여 메인 루프가 막히지 않도록 합니다. +이벤트 루프가 블로킹되는 것을 피하려면 *경로 처리 함수*를 `async def` 대신 일반 `def`로 선언하세요. 그러면 FastAPI가 스레드풀 워커에서 실행하여 메인 루프가 막히지 않도록 합니다. {* ../../docs_src/stream_data/tutorial002_py310.py ln[30:34] hl[31] *} diff --git a/docs/ko/docs/advanced/wsgi.md b/docs/ko/docs/advanced/wsgi.md index bd359661d..2b3012a46 100644 --- a/docs/ko/docs/advanced/wsgi.md +++ b/docs/ko/docs/advanced/wsgi.md @@ -42,7 +42,7 @@ Hello, World from Flask! ``` -그리고 [http://localhost:8000/v2](http://localhost:8000/v2)로 이동하면 **FastAPI**의 응답을 볼 수 있습니다: +그리고 [http://localhost:8000/v2](http://localhost:8000/v2)로 이동하면 FastAPI의 응답을 볼 수 있습니다: ```JSON { diff --git a/docs/ko/docs/alternatives.md b/docs/ko/docs/alternatives.md index ab92c0ea8..1bd0ba56a 100644 --- a/docs/ko/docs/alternatives.md +++ b/docs/ko/docs/alternatives.md @@ -24,7 +24,7 @@ ### [Django REST Framework](https://www.django-rest-framework.org/) { #django-rest-framework } -Django REST framework는 Django를 기반으로 Web API를 구축하기 위한 유연한 toolkit으로 만들어졌고, Django의 API 기능을 개선하기 위한 목적이었습니다. +Django REST Framework는 Django를 기반으로 Web API를 구축하기 위한 유연한 toolkit으로 만들어졌고, Django의 API 기능을 개선하기 위한 목적이었습니다. Mozilla, Red Hat, Eventbrite를 포함해 많은 회사에서 사용합니다. @@ -36,7 +36,7 @@ Django REST Framework는 Tom Christie가 만들었습니다. **FastAPI**의 기 /// -/// tip | 팁 +/// tip | **FastAPI**에 영감을 준 점 자동 API 문서화 웹 사용자 인터페이스를 제공하기. @@ -56,7 +56,7 @@ Flask는 "microframework"로, Django에 기본으로 포함된 데이터베이 Flask의 단순함을 고려하면 API를 구축하는 데 잘 맞는 것처럼 보였습니다. 다음으로 찾고자 했던 것은 Flask용 "Django REST Framework"였습니다. -/// tip | 팁 +/// tip | **FastAPI**에 영감을 준 점 micro-framework가 되기. 필요한 도구와 구성요소를 쉽게 조합할 수 있도록 하기. @@ -80,7 +80,7 @@ Requests는 매우 단순하고 직관적인 설계를 가졌고, 합리적인 그래서 공식 웹사이트에서 말하듯이: -> Requests is one of the most downloaded Python packages of all time +> Requests는 역대 가장 많이 다운로드된 Python 패키지 중 하나입니다 사용 방법은 매우 간단합니다. 예를 들어 `GET` 요청을 하려면 다음처럼 작성합니다: @@ -98,7 +98,7 @@ def read_url(): `requests.get(...)`와 `@app.get(...)`의 유사성을 확인해 보세요. -/// tip | 팁 +/// tip | **FastAPI**에 영감을 준 점 * 단순하고 직관적인 API를 갖기. * HTTP method 이름(operations)을 직접, 직관적이고 명확한 방식으로 사용하기. @@ -118,7 +118,7 @@ def read_url(): 그래서 2.0 버전을 이야기할 때는 "Swagger"라고 말하는 것이 일반적이고, 3+ 버전은 "OpenAPI"라고 말하는 것이 일반적입니다. -/// tip | 팁 +/// tip | **FastAPI**에 영감을 준 점 커스텀 schema 대신, API 사양을 위한 열린 표준을 채택하고 사용하기. @@ -147,7 +147,7 @@ API에 또 하나 크게 필요한 기능은 데이터 검증입니다. 특정 하지만 Python type hints가 존재하기 전에 만들어졌습니다. 그래서 각 스키마를 정의하려면 Marshmallow가 제공하는 특정 유틸리티와 클래스를 사용해야 합니다. -/// tip | 팁 +/// tip | **FastAPI**에 영감을 준 점 데이터 타입과 검증을 제공하는 "schema"를 코드로 정의하고, 이를 자동으로 활용하기. @@ -169,7 +169,7 @@ Webargs는 Marshmallow와 같은 개발자들이 만들었습니다. /// -/// tip | 팁 +/// tip | **FastAPI**에 영감을 준 점 들어오는 요청 데이터의 자동 검증을 갖기. @@ -199,7 +199,7 @@ APISpec은 Marshmallow와 같은 개발자들이 만들었습니다. /// -/// tip | 팁 +/// tip | **FastAPI**에 영감을 준 점 API를 위한 열린 표준인 OpenAPI를 지원하기. @@ -231,7 +231,7 @@ Flask-apispec은 Marshmallow와 같은 개발자들이 만들었습니다. /// -/// tip | 팁 +/// tip | **FastAPI**에 영감을 준 점 serialization과 validation을 정의하는 동일한 코드로부터 OpenAPI schema를 자동 생성하기. @@ -251,7 +251,7 @@ Angular 2에서 영감을 받은 의존성 주입 시스템이 통합되어 있 중첩 모델을 잘 처리하지 못합니다. 즉, 요청의 JSON body가 내부 필드를 가진 JSON 객체이고 그 내부 필드들이 다시 중첩된 JSON 객체인 경우, 제대로 문서화하고 검증할 수 없습니다. -/// tip | 팁 +/// tip | **FastAPI**에 영감을 준 점 Python 타입을 사용해 뛰어난 에디터 지원을 제공하기. @@ -271,7 +271,7 @@ Python 타입을 사용해 뛰어난 에디터 지원을 제공하기. /// -/// tip | 팁 +/// tip | **FastAPI**에 영감을 준 점 미친 성능을 낼 수 있는 방법을 찾기. @@ -283,11 +283,11 @@ Python 타입을 사용해 뛰어난 에디터 지원을 제공하기. Falcon은 또 다른 고성능 Python framework로, 최소한으로 설계되었고 Hug 같은 다른 framework의 기반으로 동작하도록 만들어졌습니다. -함수가 두 개의 파라미터(하나는 "request", 하나는 "response")를 받도록 설계되어 있습니다. 그런 다음 request에서 일부를 "읽고", response에 일부를 "작성"합니다. 이 설계 때문에, 표준 Python type hints를 함수 파라미터로 사용해 요청 파라미터와 body를 선언하는 것이 불가능합니다. +함수가 두 개의 파라미터(하나는 "요청", 하나는 "응답")를 받도록 설계되어 있습니다. 그런 다음 요청에서 일부를 "읽고", 응답에 일부를 "작성"합니다. 이 설계 때문에, 표준 Python type hints를 함수 파라미터로 사용해 요청 파라미터와 body를 선언하는 것이 불가능합니다. -따라서 데이터 검증, serialization, 문서화는 자동으로 되지 않고 코드로 해야 합니다. 또는 Hug처럼 Falcon 위에 framework를 얹어 구현해야 합니다. request 객체 하나와 response 객체 하나를 파라미터로 받는 Falcon의 설계에서 영감을 받은 다른 framework에서도 같은 구분이 나타납니다. +따라서 데이터 검증, serialization, 문서화는 자동으로 되지 않고 코드로 해야 합니다. 또는 Hug처럼 Falcon 위에 framework를 얹어 구현해야 합니다. 요청 객체 하나와 응답 객체 하나를 파라미터로 받는 Falcon의 설계에서 영감을 받은 다른 framework에서도 같은 구분이 나타납니다. -/// tip | 팁 +/// tip | **FastAPI**에 영감을 준 점 훌륭한 성능을 얻는 방법을 찾기. @@ -313,7 +313,7 @@ Pydantic 같은 서드파티 라이브러리를 사용해 데이터 검증/seria Route는 한 곳에서 선언하고, 다른 곳에 선언된 함수를 사용합니다(엔드포인트를 처리하는 함수 바로 위에 둘 수 있는 decorator를 사용하는 대신). 이는 Flask(및 Starlette)보다는 Django 방식에 가깝습니다. 코드에서 상대적으로 강하게 결합된 것들을 분리해 놓습니다. -/// tip | 팁 +/// tip | **FastAPI**에 영감을 준 점 모델 속성의 "default" 값으로 데이터 타입에 대한 추가 검증을 정의하기. 이는 에디터 지원을 개선하며, 이전에는 Pydantic에 없었습니다. @@ -341,7 +341,7 @@ Hug는 Timothy Crosley가 만들었습니다. Python 파일에서 import를 자 /// -/// tip | 팁 +/// tip | **FastAPI**에 영감을 준 아이디어 Hug는 APIStar의 일부에 영감을 주었고, 저는 APIStar와 함께 Hug를 가장 유망한 도구 중 하나로 보았습니다. @@ -385,7 +385,7 @@ APIStar는 Tom Christie가 만들었습니다. 다음을 만든 사람과 동일 /// -/// tip | 팁 +/// tip | **FastAPI**에 영감을 준 점 존재하게 만들기. @@ -409,7 +409,7 @@ Pydantic은 Python type hints를 기반으로 데이터 검증, serialization, Marshmallow와 비교할 수 있습니다. 다만 benchmark에서 Marshmallow보다 빠릅니다. 그리고 동일한 Python type hints를 기반으로 하므로 에디터 지원도 훌륭합니다. -/// tip | 팁 +/// tip | **FastAPI**는 이를 사용해 모든 데이터 검증, 데이터 serialization, 자동 모델 문서화(JSON Schema 기반)를 처리하기. @@ -430,7 +430,7 @@ Starlette는 경량 -Dockerfile Preview 👀 +Dockerfile 미리보기 👀 ```Dockerfile FROM python:3.14 @@ -46,7 +46,7 @@ CMD ["fastapi", "run", "app/main.py", "--port", "80"] **컨테이너**는 **컨테이너 이미지**에서 실행됩니다. -컨테이너 이미지는 컨테이너에 있어야 하는 모든 파일, 환경 변수, 기본 명령/프로그램의 **정적** 버전입니다. 여기서 **정적**이라는 것은 컨테이너 **이미지**가 실행 중이거나 수행되는 것이 아니라, 패키징된 파일과 메타데이터일 뿐이라는 뜻입니다. +컨테이너 이미지는 컨테이너에 있어야 하는 모든 파일, 환경 변수, 기본 명령어/프로그램의 **정적** 버전입니다. 여기서 **정적**이라는 것은 컨테이너 **이미지**가 실행 중이거나 수행되는 것이 아니라, 패키징된 파일과 메타데이터일 뿐이라는 뜻입니다. 저장된 정적 콘텐츠인 "**컨테이너 이미지**"와 달리, "**컨테이너**"는 보통 실행 중인 인스턴스, 즉 **실행되는** 대상을 의미합니다. @@ -62,7 +62,7 @@ Docker는 **컨테이너 이미지**와 **컨테이너**를 생성하고 관리 또한 [Docker Hub](https://hub.docker.com/)에는 다양한 도구, 환경, 데이터베이스, 애플리케이션을 위한 미리 만들어진 **공식 컨테이너 이미지**가 공개되어 있습니다. -예를 들어, 공식 [Python Image](https://hub.docker.com/_/python)가 있습니다. +예를 들어, 공식 [Python 이미지](https://hub.docker.com/_/python)가 있습니다. 그리고 데이터베이스 등 다양한 용도의 다른 이미지도 많이 있습니다. 예를 들면: @@ -81,11 +81,11 @@ Docker나 Kubernetes 같은 모든 컨테이너 관리 시스템에는 이러한 ## 컨테이너와 프로세스 { #containers-and-processes } -**컨테이너 이미지**는 보통 **컨테이너**가 시작될 때 실행되어야 하는 기본 프로그램/명령과 해당 프로그램에 전달할 매개변수를 메타데이터에 포함합니다. 커맨드 라인에서 실행할 때와 매우 유사합니다. +**컨테이너 이미지**는 보통 **컨테이너**가 시작될 때 실행되어야 하는 기본 프로그램/명령어와 해당 프로그램에 전달할 매개변수를 메타데이터에 포함합니다. 커맨드 라인에서 실행할 때와 매우 유사합니다. -**컨테이너**가 시작되면 해당 명령/프로그램을 실행합니다(다만 오버라이드하여 다른 명령/프로그램을 실행하게 할 수도 있습니다). +**컨테이너**가 시작되면 해당 명령어/프로그램을 실행합니다(다만 오버라이드하여 다른 명령어/프로그램을 실행하게 할 수도 있습니다). -컨테이너는 **메인 프로세스**(명령 또는 프로그램)가 실행되는 동안 실행됩니다. +컨테이너는 **메인 프로세스**(명령어 또는 프로그램)가 실행되는 동안 실행됩니다. 컨테이너는 보통 **단일 프로세스**를 가지지만, 메인 프로세스에서 서브프로세스를 시작할 수도 있으며, 그러면 같은 컨테이너에 **여러 프로세스**가 존재하게 됩니다. @@ -218,11 +218,11 @@ CMD ["fastapi", "run", "app/main.py", "--port", "80"] 따라서 컨테이너 이미지 빌드 시간을 최적화하려면 `Dockerfile`의 **끝부분 근처**에 두는 것이 중요합니다. -6. 내부적으로 Uvicorn을 사용하는 `fastapi run`을 사용하도록 **명령**을 설정합니다. +6. 내부적으로 Uvicorn을 사용하는 `fastapi run`을 사용하도록 **명령어**를 설정합니다. `CMD`는 문자열 리스트를 받으며, 각 문자열은 커맨드 라인에서 공백으로 구분해 입력하는 항목들입니다. - 이 명령은 **현재 작업 디렉터리**에서 실행되며, 이는 위에서 `WORKDIR /code`로 설정한 `/code` 디렉터리와 같습니다. + 이 명령어는 **현재 작업 디렉터리**에서 실행되며, 이는 위에서 `WORKDIR /code`로 설정한 `/code` 디렉터리와 같습니다. /// tip | 팁 @@ -258,7 +258,7 @@ FastAPI가 정상적으로 종료(graceful shutdown)되고 [lifespan 이벤트]( 자세한 내용은 [shell and exec form에 대한 Docker 문서](https://docs.docker.com/reference/dockerfile/#shell-and-exec-form)를 참고하세요. -이는 `docker compose`를 사용할 때 꽤 눈에 띌 수 있습니다. 좀 더 기술적인 상세 내용은 Docker Compose FAQ 섹션을 참고하세요: [Why do my services take 10 seconds to recreate or stop?](https://docs.docker.com/compose/faq/#why-do-my-services-take-10-seconds-to-recreate-or-stop). +이는 `docker compose`를 사용할 때 꽤 눈에 띌 수 있습니다. 좀 더 기술적인 상세 내용은 Docker Compose FAQ 섹션을 참고하세요: [왜 내 서비스는 다시 생성되거나 중지되는 데 10초가 걸리나요?](https://docs.docker.com/compose/faq/#why-do-my-services-take-10-seconds-to-recreate-or-stop). #### 디렉터리 구조 { #directory-structure } @@ -409,7 +409,7 @@ CMD ["fastapi", "run", "main.py", "--port", "80"] 2. 단일 파일 `main.py`에 있는 애플리케이션을 제공(serve)하기 위해 `fastapi run`을 사용합니다. -`fastapi run`에 파일을 전달하면, 이것이 패키지의 일부가 아닌 단일 파일이라는 것을 자동으로 감지하고, 어떻게 임포트해서 FastAPI 앱을 제공할지 알아냅니다. 😎 +`fastapi run`에 파일을 전달하면, 이것이 패키지의 일부가 아닌 단일 파일이라는 것을 자동으로 감지하고, 어떻게 임포트해서 FastAPI 애플리케이션을 제공할지 알아냅니다. 😎 ## 배포 개념 { #deployment-concepts } @@ -472,17 +472,17 @@ HTTPS에 사용되는 동일한 **TLS 종료 프록시** 컴포넌트가 **로 /// -또한 컨테이너로 작업할 때, 이를 시작하고 관리하는 시스템은 이미 해당 **로드 밸런서**(또는 **TLS 종료 프록시**)에서 여러분의 앱이 있는 컨테이너로 **네트워크 통신**(예: HTTP 요청)을 전달하는 내부 도구를 가지고 있습니다. +또한 컨테이너로 작업할 때, 이를 시작하고 관리하는 시스템은 이미 해당 **로드 밸런서**(또는 **TLS 종료 프록시**)에서 여러분의 애플리케이션이 있는 컨테이너로 **네트워크 통신**(예: HTTP 요청)을 전달하는 내부 도구를 가지고 있습니다. ### 하나의 로드 밸런서 - 여러 워커 컨테이너 { #one-load-balancer-multiple-worker-containers } -**Kubernetes** 같은 분산 컨테이너 관리 시스템에서는 내부 네트워킹 메커니즘을 통해, 메인 **포트**에서 대기하는 단일 **로드 밸런서**가 여러분의 앱을 실행하는 **여러 컨테이너**로 통신(요청)을 전달할 수 있습니다. +**Kubernetes** 같은 분산 컨테이너 관리 시스템에서는 내부 네트워킹 메커니즘을 통해, 메인 **포트**에서 대기하는 단일 **로드 밸런서**가 여러분의 애플리케이션을 실행하는 **여러 컨테이너**로 통신(요청)을 전달할 수 있습니다. -앱을 실행하는 각 컨테이너는 보통 **프로세스 하나만** 가집니다(예: FastAPI 애플리케이션을 실행하는 Uvicorn 프로세스). 모두 같은 것을 실행하는 **동일한 컨테이너**이지만, 각자 고유한 프로세스, 메모리 등을 가집니다. 이렇게 하면 CPU의 **서로 다른 코어** 또는 **서로 다른 머신**에서 **병렬화**의 이점을 얻을 수 있습니다. +애플리케이션을 실행하는 각 컨테이너는 보통 **프로세스 하나만** 가집니다(예: FastAPI 애플리케이션을 실행하는 Uvicorn 프로세스). 모두 같은 것을 실행하는 **동일한 컨테이너**이지만, 각자 고유한 프로세스, 메모리 등을 가집니다. 이렇게 하면 CPU의 **서로 다른 코어** 또는 **서로 다른 머신**에서 **병렬화**의 이점을 얻을 수 있습니다. -그리고 **로드 밸런서**가 있는 분산 컨테이너 시스템은 여러분의 앱을 실행하는 각 컨테이너에 **번갈아가며** 요청을 **분산**합니다. 따라서 각 요청은 여러분의 앱을 실행하는 여러 **복제된 컨테이너** 중 하나에서 처리될 수 있습니다. +그리고 **로드 밸런서**가 있는 분산 컨테이너 시스템은 여러분의 애플리케이션을 실행하는 각 컨테이너에 **번갈아가며** 요청을 **분산**합니다. 따라서 각 요청은 여러분의 애플리케이션을 실행하는 여러 **복제된 컨테이너** 중 하나에서 처리될 수 있습니다. -또한 보통 이 **로드 밸런서**는 클러스터 내 *다른* 앱으로 가는 요청(예: 다른 도메인, 또는 다른 URL 경로 접두사 아래로 가는 요청)도 처리할 수 있으며, 그 통신을 클러스터에서 실행 중인 *그 다른* 애플리케이션의 올바른 컨테이너로 전달할 수 있습니다. +또한 보통 이 **로드 밸런서**는 클러스터 내 *다른* 애플리케이션으로 가는 요청(예: 다른 도메인, 또는 다른 URL 경로 접두사 아래로 가는 요청)도 처리할 수 있으며, 그 통신을 클러스터에서 실행 중인 *그 다른* 애플리케이션의 올바른 컨테이너로 전달할 수 있습니다. ### 컨테이너당 하나의 프로세스 { #one-process-per-container } @@ -566,7 +566,7 @@ Kubernetes를 사용한다면, 이는 아마도 [Init Container](https://kuberne ### 단일 컨테이너 { #single-container } -**단일 컨테이너**에서 여러 **워커 프로세스**(또는 단일 프로세스)를 시작하는 단순한 셋업이라면, 앱이 있는 프로세스를 시작하기 직전에 같은 컨테이너에서 시작 전 사전 단계를 실행할 수 있습니다. +**단일 컨테이너**에서 여러 **워커 프로세스**(또는 단일 프로세스)를 시작하는 단순한 셋업이라면, 애플리케이션이 있는 프로세스를 시작하기 직전에 같은 컨테이너에서 시작 전 사전 단계를 실행할 수 있습니다. ### 베이스 도커 이미지 { #base-docker-image } @@ -582,7 +582,7 @@ Kubernetes를 사용한다면, 이는 아마도 [Init Container](https://kuberne 이 Docker 이미지는 Uvicorn이 죽은 워커를 관리하고 재시작하는 기능을 지원하지 않던 시기에 만들어졌습니다. 그래서 Gunicorn과 Uvicorn을 함께 사용해야 했고, Gunicorn이 Uvicorn 워커 프로세스를 관리하고 재시작하도록 하기 위해 상당한 복잡성이 추가되었습니다. -하지만 이제 Uvicorn(그리고 `fastapi` 명령)은 `--workers`를 지원하므로, 베이스 도커 이미지를 사용하는 대신 직접 이미지를 빌드하지 않을 이유가 없습니다(코드 양도 사실상 거의 같습니다 😅). +하지만 이제 Uvicorn(그리고 `fastapi` 명령어)은 `--workers`를 지원하므로, 베이스 도커 이미지를 사용하는 대신 직접 이미지를 빌드하지 않을 이유가 없습니다(코드 양도 사실상 거의 같습니다 😅). /// @@ -600,7 +600,7 @@ Kubernetes를 사용한다면, 이는 아마도 [Init Container](https://kuberne ## `uv`를 사용하는 도커 이미지 { #docker-image-with-uv } -프로젝트를 설치하고 관리하기 위해 [uv](https://github.com/astral-sh/uv)를 사용한다면, [uv Docker guide](https://docs.astral.sh/uv/guides/integration/docker/)를 따를 수 있습니다. +프로젝트를 설치하고 관리하기 위해 [uv](https://github.com/astral-sh/uv)를 사용한다면, [uv Docker 가이드](https://docs.astral.sh/uv/guides/integration/docker/)를 따를 수 있습니다. ## 요약 { #recap } diff --git a/docs/ko/docs/deployment/https.md b/docs/ko/docs/deployment/https.md index 06ac147cd..1db7dd25c 100644 --- a/docs/ko/docs/deployment/https.md +++ b/docs/ko/docs/deployment/https.md @@ -14,7 +14,7 @@ HTTPS는 그냥 “켜져 있거나” 아니면 “꺼져 있는” 것이라 이제 **개발자 관점**에서 HTTPS를 생각할 때 염두에 두어야 할 여러 가지가 있습니다: -* HTTPS를 사용하려면, **서버**가 **제3자**가 발급한 **"인증서(certificates)"**를 **보유**해야 합니다. +* HTTPS를 사용하려면, **서버**가 **제3자**가 생성한 **"인증서(certificates)"**를 **보유**해야 합니다. * 이 인증서는 실제로 '생성'되는 것이 아니라 제3자로부터 **발급/획득**하는 것입니다. * 인증서에는 **유효 기간**이 있습니다. * 즉, **만료**됩니다. diff --git a/docs/ko/docs/deployment/manually.md b/docs/ko/docs/deployment/manually.md index b2a91bd94..fbac8169f 100644 --- a/docs/ko/docs/deployment/manually.md +++ b/docs/ko/docs/deployment/manually.md @@ -1,6 +1,6 @@ # 서버를 수동으로 실행하기 { #run-a-server-manually } -## `fastapi run` 명령 사용하기 { #use-the-fastapi-run-command } +## `fastapi run` 명령어 사용하기 { #use-the-fastapi-run-command } 요약하면, `fastapi run`을 사용해 FastAPI 애플리케이션을 서비스하세요: @@ -40,7 +40,7 @@ $ fastapi run fastapi run ASGI라고 불리는, Python 웹 프레임워크와 서버를 만들기 위한 표준을 사용합니다. FastAPI는 ASGI 웹 프레임워크입니다. -원격 서버 머신에서 **FastAPI** 애플리케이션(또는 다른 ASGI 애플리케이션)을 실행하기 위해 필요한 핵심 요소는 **Uvicorn** 같은 ASGI 서버 프로그램입니다. `fastapi` 명령에는 기본으로 이것이 포함되어 있습니다. +원격 서버 머신에서 **FastAPI** 애플리케이션(또는 다른 ASGI 애플리케이션)을 실행하기 위해 필요한 핵심 요소는 **Uvicorn** 같은 ASGI 서버 프로그램입니다. `fastapi` 명령어에는 기본으로 이것이 포함되어 있습니다. 다음을 포함해 여러 대안이 있습니다: @@ -69,7 +69,7 @@ FastAPI는 -"_[...] 저는 요즘 **FastAPI**를 많이 사용하고 있습니다. [...] 사실 우리 팀의 **마이크로소프트 ML 서비스** 전부를 바꿀 계획입니다. 그중 일부는 핵심 **Windows**와 몇몇의 **Office** 제품들이 통합되고 있습니다._" +"_[...] 저는 요즘 **FastAPI**를 많이 사용하고 있습니다. [...] 사실 우리 팀의 **마이크로소프트 ML 서비스** 전부에 사용할 계획입니다. 그중 일부는 핵심 **Windows** 제품과 일부 **Office** 제품에 통합되고 있습니다._"
Kabir Khan - Microsoft (ref)
@@ -137,7 +137,7 @@ FastAPI는 현대적이고, 빠르며(고성능), 파이썬 표준 타입 힌트 --- -"_**Netflix**는 우리의 오픈 소스 배포판인 **위기 관리** 오케스트레이션 프레임워크를 발표할 수 있어 기쁩니다: 바로 **Dispatch**입니다! [**FastAPI**로 빌드]_" +"_**Netflix**는 우리의 **위기 관리** 오케스트레이션 프레임워크인 **Dispatch**의 오픈 소스 공개를 발표하게 되어 기쁩니다! [**FastAPI**로 빌드]_"
Kevin Glisson, Marc Vilanova, Forest Monsen - Netflix (ref)
@@ -192,7 +192,7 @@ $ pip install "fastapi[standard]"
-**Note**: 모든 터미널에서 동작하도록 `"fastapi[standard]"`를 따옴표로 감싸 넣었는지 확인하세요. +**참고**: 모든 터미널에서 동작하도록 `"fastapi[standard]"`를 따옴표로 감싸 넣었는지 확인하세요. ## 예제 { #example } @@ -237,9 +237,9 @@ async def read_item(item_id: int, q: str | None = None): return {"item_id": item_id, "q": q} ``` -**Note**: +**참고**: -잘 모르겠다면, ["급하세요?"](https://fastapi.tiangolo.com/ko/async/#in-a-hurry) 섹션을 확인해 보십시오. +잘 모르겠다면, 문서의 [`async`와 `await`](https://fastapi.tiangolo.com/ko/async/#in-a-hurry)에 관한 _"급하세요?"_ 섹션을 확인해 보십시오. diff --git a/docs/ko/docs/project-generation.md b/docs/ko/docs/project-generation.md index 774b03a19..3a5a9b940 100644 --- a/docs/ko/docs/project-generation.md +++ b/docs/ko/docs/project-generation.md @@ -1,5 +1,6 @@ # Full Stack FastAPI 템플릿 { #full-stack-fastapi-template } + 템플릿은 일반적으로 특정 설정과 함께 제공되지만, 유연하고 커스터마이징이 가능하게 디자인 되었습니다. 이 특성들은 여러분이 프로젝트의 요구사항에 맞춰 수정, 적용을 할 수 있게 해주고, 템플릿이 완벽한 시작점이 되게 해줍니다. 🏁 많은 초기 설정, 보안, 데이터베이스 및 일부 API 엔드포인트가 이미 준비되어 있으므로, 여러분은 이 템플릿을 시작하는 데 사용할 수 있습니다. diff --git a/docs/ko/docs/python-types.md b/docs/ko/docs/python-types.md index 10b74b228..a0216cd5b 100644 --- a/docs/ko/docs/python-types.md +++ b/docs/ko/docs/python-types.md @@ -124,7 +124,7 @@ John Doe 이것은 **FastAPI**와 함께 사용할 때도 주요 위치입니다. -### Simple 타입 { #simple-types } +### 간단한 타입 { #simple-types } `str`뿐 아니라 모든 파이썬 표준 타입을 선언할 수 있습니다. @@ -287,7 +287,7 @@ Pydantic 공식 문서의 예시: /// note | 참고 -Pydantic에 대해 더 알아보려면 [문서를 확인하세요](https://docs.pydantic.dev/). +더 알아보려면 [Pydantic 문서를 확인하세요](https://docs.pydantic.dev/). /// diff --git a/docs/ko/docs/tutorial/bigger-applications.md b/docs/ko/docs/tutorial/bigger-applications.md index f95286047..bb3637f75 100644 --- a/docs/ko/docs/tutorial/bigger-applications.md +++ b/docs/ko/docs/tutorial/bigger-applications.md @@ -17,16 +17,16 @@ Flask를 사용해 보셨다면, 이는 Flask의 Blueprints에 해당하는 개 ``` . ├── app -│   ├── __init__.py -│   ├── main.py -│   ├── dependencies.py -│   └── routers -│   │ ├── __init__.py -│   │ ├── items.py -│   │ └── users.py -│   └── internal -│   ├── __init__.py -│   └── admin.py +│ ├── __init__.py +│ ├── main.py +│ ├── dependencies.py +│ └── routers +│ │ ├── __init__.py +│ │ ├── items.py +│ │ └── users.py +│ └── internal +│ ├── __init__.py +│ └── admin.py ``` /// tip | 팁 @@ -75,11 +75,11 @@ from app.routers import items 사용자만 처리하는 전용 파일이 `/app/routers/users.py`의 submodule이라고 해봅시다. -코드를 정리하기 위해 사용자와 관련된 *path operations*를 나머지 코드와 분리해 두고 싶을 것입니다. +코드를 정리하기 위해 사용자와 관련된 *경로 처리*를 나머지 코드와 분리해 두고 싶을 것입니다. 하지만 이것은 여전히 같은 **FastAPI** 애플리케이션/웹 API의 일부입니다(같은 "Python Package"의 일부입니다). -`APIRouter`를 사용해 해당 모듈의 *path operations*를 만들 수 있습니다. +`APIRouter`를 사용해 해당 모듈의 *경로 처리*를 만들 수 있습니다. ### `APIRouter` import하기 { #import-apirouter } @@ -87,9 +87,9 @@ from app.routers import items {* ../../docs_src/bigger_applications/app_an_py310/routers/users.py hl[1,3] title["app/routers/users.py"] *} -### `APIRouter`로 *path operations* 만들기 { #path-operations-with-apirouter } +### `APIRouter`로 *경로 처리* 만들기 { #path-operations-with-apirouter } -그 다음 이를 사용해 *path operations*를 선언합니다. +그 다음 이를 사용해 *경로 처리*를 선언합니다. `FastAPI` 클래스를 사용할 때와 동일한 방식으로 사용합니다: @@ -107,7 +107,7 @@ from app.routers import items /// -이제 이 `APIRouter`를 메인 `FastAPI` 앱에 포함(include)할 것이지만, 먼저 dependencies와 다른 `APIRouter` 하나를 확인해 보겠습니다. +이제 이 `APIRouter`를 메인 `FastAPI` 애플리케이션에 포함(include)할 것이지만, 먼저 dependencies와 다른 `APIRouter` 하나를 확인해 보겠습니다. ## Dependencies { #dependencies } @@ -131,7 +131,7 @@ from app.routers import items 애플리케이션의 "items"를 처리하는 전용 endpoint들도 `app/routers/items.py` 모듈에 있다고 해봅시다. -여기에는 다음에 대한 *path operations*가 있습니다: +여기에는 다음에 대한 *경로 처리*가 있습니다: * `/items/` * `/items/{item_id}` @@ -140,18 +140,18 @@ from app.routers import items 하지만 우리는 조금 더 똑똑하게, 코드를 약간 단순화하고 싶습니다. -이 모듈의 모든 *path operations*에는 다음이 동일하게 적용됩니다: +이 모듈의 모든 *경로 처리*에는 다음이 동일하게 적용됩니다: * 경로 `prefix`: `/items`. * `tags`: (태그 하나: `items`). * 추가 `responses`. * `dependencies`: 모두 우리가 만든 `X-Token` dependency가 필요합니다. -따라서 각 *path operation*마다 매번 모두 추가하는 대신, `APIRouter`에 한 번에 추가할 수 있습니다. +따라서 각 *경로 처리*마다 매번 모두 추가하는 대신, `APIRouter`에 한 번에 추가할 수 있습니다. {* ../../docs_src/bigger_applications/app_an_py310/routers/items.py hl[5:10,16,21] title["app/routers/items.py"] *} -각 *path operation*의 경로는 다음처럼 `/`로 시작해야 하므로: +각 *경로 처리*의 경로는 다음처럼 `/`로 시작해야 하므로: ```Python hl_lines="1" @router.get("/{item_id}") @@ -163,13 +163,13 @@ async def read_item(item_id: str): 따라서 이 경우 prefix는 `/items`입니다. -또한 이 router에 포함된 모든 *path operations*에 적용될 `tags` 목록과 추가 `responses`도 넣을 수 있습니다. +또한 이 router에 포함된 모든 *경로 처리*에 적용될 `tags` 목록과 추가 `responses`도 넣을 수 있습니다. -그리고 router의 모든 *path operations*에 추가될 `dependencies` 목록도 추가할 수 있으며, 해당 경로들로 들어오는 각 요청마다 실행/해결됩니다. +그리고 router의 모든 *경로 처리*에 추가될 `dependencies` 목록도 추가할 수 있으며, 해당 경로들로 들어오는 각 요청마다 실행/해결됩니다. /// tip | 팁 -[*path operation decorator의 dependencies*](dependencies/dependencies-in-path-operation-decorators.md)와 마찬가지로, *path operation function*에 어떤 값도 전달되지 않습니다. +[*경로 처리 데코레이터*의 dependencies](dependencies/dependencies-in-path-operation-decorators.md)와 마찬가지로, *경로 처리 함수*에 어떤 값도 전달되지 않습니다. /// @@ -183,14 +183,14 @@ async def read_item(item_id: str): * 단일 문자열 `"items"`를 포함하는 태그 목록으로 표시됩니다. * 이 "tags"는 자동 대화형 문서 시스템(OpenAPI 사용)에 특히 유용합니다. * 모두 미리 정의된 `responses`를 포함합니다. -* 이 모든 *path operations*는 실행되기 전에 `dependencies` 목록이 평가/실행됩니다. - * 특정 *path operation*에 dependencies를 추가로 선언하면 **그것들도 실행됩니다**. - * router dependencies가 먼저 실행되고, 그 다음에 [decorator의 `dependencies`](dependencies/dependencies-in-path-operation-decorators.md), 그리고 일반 파라미터 dependencies가 실행됩니다. +* 이 모든 *경로 처리*는 실행되기 전에 `dependencies` 목록이 평가/실행됩니다. + * 특정 *경로 처리*에 dependencies를 추가로 선언하면 **그것들도 실행됩니다**. + * router dependencies가 먼저 실행되고, 그 다음에 [데코레이터의 `dependencies`](dependencies/dependencies-in-path-operation-decorators.md), 그리고 일반 파라미터 dependencies가 실행됩니다. * [`scopes`가 있는 `Security` dependencies](../advanced/security/oauth2-scopes.md)도 추가할 수 있습니다. /// tip | 팁 -`APIRouter`에 `dependencies`를 두는 것은 예를 들어 전체 *path operations* 그룹에 인증을 요구할 때 사용할 수 있습니다. 각 경로 처리에 개별적으로 dependencies를 추가하지 않아도 됩니다. +`APIRouter`에 `dependencies`를 두는 것은 예를 들어 전체 *경로 처리* 그룹에 인증을 요구할 때 사용할 수 있습니다. 각 경로 처리에 개별적으로 dependencies를 추가하지 않아도 됩니다. /// @@ -232,7 +232,7 @@ from .dependencies import get_token_header 하지만 그 파일은 존재하지 않습니다. dependencies는 `app/dependencies.py` 파일에 있습니다. -우리 앱/파일 구조를 다시 떠올려 보세요: +우리 애플리케이션/파일 구조를 다시 떠올려 보세요: @@ -271,13 +271,13 @@ from ...dependencies import get_token_header 이는 `app/` 위쪽의 어떤 package(자신의 `__init__.py` 파일 등을 가진)에 대한 참조가 됩니다. 하지만 우리는 그런 것이 없습니다. 그래서 이 예시에서는 에러가 발생합니다. 🚨 -이제 어떻게 동작하는지 알았으니, 앱이 얼마나 복잡하든 상대 import를 사용할 수 있습니다. 🤓 +이제 어떻게 동작하는지 알았으니, 애플리케이션이 얼마나 복잡하든 상대 import를 사용할 수 있습니다. 🤓 ### 커스텀 `tags`, `responses`, `dependencies` 추가하기 { #add-some-custom-tags-responses-and-dependencies } -`APIRouter`에 이미 prefix `/items`와 `tags=["items"]`를 추가했기 때문에 각 *path operation*에 이를 추가하지 않습니다. +`APIRouter`에 이미 prefix `/items`와 `tags=["items"]`를 추가했기 때문에 각 *경로 처리*에 이를 추가하지 않습니다. -하지만 특정 *path operation*에만 적용될 _추가_ `tags`를 더할 수도 있고, 그 *path operation* 전용의 추가 `responses`도 넣을 수 있습니다: +하지만 특정 *경로 처리*에만 적용될 _추가_ `tags`를 더할 수도 있고, 그 *경로 처리* 전용의 추가 `responses`도 넣을 수 있습니다: {* ../../docs_src/bigger_applications/app_an_py310/routers/items.py hl[30:31] title["app/routers/items.py"] *} @@ -416,13 +416,13 @@ router를 포함(include)할 때 성능을 걱정할 필요는 없습니다. 이제 조직에서 `app/internal/admin.py` 파일을 받았다고 가정해 봅시다. -여기에는 조직에서 여러 프로젝트 간에 공유하는 관리자용 *path operations*가 있는 `APIRouter`가 들어 있습니다. +여기에는 조직에서 여러 프로젝트 간에 공유하는 관리자용 *경로 처리*가 있는 `APIRouter`가 들어 있습니다. 이 예시에서는 매우 단순하게 만들겠습니다. 하지만 조직 내 다른 프로젝트와 공유되기 때문에, 이를 수정할 수 없어 `prefix`, `dependencies`, `tags` 등을 `APIRouter`에 직접 추가할 수 없다고 해봅시다: {* ../../docs_src/bigger_applications/app_an_py310/internal/admin.py hl[3] title["app/internal/admin.py"] *} -하지만 `APIRouter`를 포함할 때 커스텀 `prefix`를 지정해 모든 *path operations*가 `/admin`으로 시작하게 하고, 이 프로젝트에서 이미 가진 `dependencies`로 보호하고, `tags`와 `responses`도 포함하고 싶습니다. +하지만 `APIRouter`를 포함할 때 커스텀 `prefix`를 지정해 모든 *경로 처리*가 `/admin`으로 시작하게 하고, 이 프로젝트에서 이미 가진 `dependencies`로 보호하고, `tags`와 `responses`도 포함하고 싶습니다. 원래 `APIRouter`를 수정하지 않고도 `app.include_router()`에 파라미터를 전달해서 이를 선언할 수 있습니다: @@ -430,26 +430,26 @@ router를 포함(include)할 때 성능을 걱정할 필요는 없습니다. 이렇게 하면 원래 `APIRouter`는 수정되지 않으므로, 조직 내 다른 프로젝트에서도 동일한 `app/internal/admin.py` 파일을 계속 공유할 수 있습니다. -결과적으로 우리 앱에서 `admin` 모듈의 각 *path operations*는 다음을 갖게 됩니다: +결과적으로 우리 애플리케이션에서 `admin` 모듈의 각 *경로 처리*는 다음을 갖게 됩니다: * prefix `/admin`. * tag `admin`. * dependency `get_token_header`. * 응답 `418`. 🍵 -하지만 이는 우리 앱에서 그 `APIRouter`에만 영향을 주며, 이를 사용하는 다른 코드에는 영향을 주지 않습니다. +하지만 이는 우리 애플리케이션에서 그 `APIRouter`에만 영향을 주며, 이를 사용하는 다른 코드에는 영향을 주지 않습니다. 따라서 다른 프로젝트들은 같은 `APIRouter`를 다른 인증 방식으로 사용할 수도 있습니다. -### *path operation* 포함하기 { #include-a-path-operation } +### *경로 처리* 포함하기 { #include-a-path-operation } -*path operations*를 `FastAPI` 앱에 직접 추가할 수도 있습니다. +*경로 처리*를 `FastAPI` 애플리케이션에 직접 추가할 수도 있습니다. 여기서는 가능하다는 것을 보여주기 위해... 그냥 해봅니다 🤷: {* ../../docs_src/bigger_applications/app_an_py310/main.py hl[21:23] title["app/main.py"] *} -그리고 `app.include_router()`로 추가한 다른 모든 *path operations*와 함께 올바르게 동작합니다. +그리고 `app.include_router()`로 추가한 다른 모든 *경로 처리*와 함께 올바르게 동작합니다. /// note | 매우 기술적인 세부사항 @@ -459,9 +459,9 @@ router를 포함(include)할 때 성능을 걱정할 필요는 없습니다. `APIRouter`는 "mount"되는 것이 아니며, 애플리케이션의 나머지 부분과 격리되어 있지 않습니다. -이는 OpenAPI 스키마와 사용자 인터페이스에 그들의 *path operations*를 포함시키기 위함입니다. +이는 OpenAPI 스키마와 사용자 인터페이스에 그들의 *경로 처리*를 포함시키기 위함입니다. -FastAPI는 원래의 router와 *path operations*를 활성 상태로 유지하고, 요청을 처리하고 OpenAPI를 생성할 때 router의 prefix, dependencies, tags, responses 및 기타 메타데이터를 결합합니다. +FastAPI는 원래의 router와 경로 처리를 활성 상태로 유지하고, 요청을 처리하고 OpenAPI를 생성할 때 router의 prefix, dependencies, tags, responses 및 기타 메타데이터를 결합합니다. /// @@ -480,7 +480,7 @@ entrypoint = "app.main:app" from app.main import app ``` -이렇게 하면 `fastapi` 명령어가 여러분의 앱이 어디에 있는지 알 수 있습니다. +이렇게 하면 `fastapi` 명령어가 여러분의 애플리케이션이 어디에 있는지 알 수 있습니다. /// Note | 참고 @@ -498,7 +498,7 @@ $ fastapi dev app/main.py ## 자동 API 문서 확인하기 { #check-the-automatic-api-docs } -이제 앱을 실행하세요: +이제 애플리케이션을 실행하세요:
@@ -532,16 +532,16 @@ $ fastapi dev router.include_router(other_router) ``` -`router`를 `FastAPI` 앱에 포함하기 전이든 후든, 어느 시점에 해도 됩니다. FastAPI는 라우팅과 OpenAPI에 `other_router`의 *path operations*도 포함합니다. +`router`를 `FastAPI` 애플리케이션에 포함하기 전이든 후든, 어느 시점에 해도 됩니다. FastAPI는 라우팅과 OpenAPI에 `other_router`의 *경로 처리*도 포함합니다. -나중에 router들에 추가된 *path operations*도 동일하게 적용됩니다. 이전에 수행한 포함을 통해서도 보이게 됩니다. +나중에 router들에 추가된 *경로 처리*도 동일하게 적용됩니다. 이전에 수행한 포함을 통해서도 보이게 됩니다. /// warning | 기술 세부사항 router를 포함한 뒤에 `router.routes`를 직접 변형하는 것은 피하세요. FastAPI는 router 포함을 실시간으로 처리하므로, 원래 router와 그 routes는 라우팅과 OpenAPI 생성의 일부로 남아 있습니다. -경로와 router를 추가할 때는 path operation 데코레이터와 `.include_router()` 같은 문서화된 API를 사용하세요. +경로와 router를 추가할 때는 경로 처리 데코레이터와 `.include_router()` 같은 문서화된 API를 사용하세요. -`router.routes`는 최종 *path operations*의 평탄화된 목록이 아니라, route 정의와 포함된 router를 담는 하위 수준의 트리로 취급하고, 여기에 의존하지 마세요. +`router.routes`는 최종 *경로 처리*의 평탄화된 목록이 아니라, route 정의와 포함된 router를 담는 하위 수준의 트리로 취급하고, 여기에 의존하지 마세요. /// diff --git a/docs/ko/docs/tutorial/body-nested-models.md b/docs/ko/docs/tutorial/body-nested-models.md index e6c70d179..7ca6305c3 100644 --- a/docs/ko/docs/tutorial/body-nested-models.md +++ b/docs/ko/docs/tutorial/body-nested-models.md @@ -182,7 +182,7 @@ Pydantic 모델 대신 `dict`로 직접 작업한다면 이런 종류의 편집 또한 키는 어떤 타입이고 값은 다른 타입인 `dict`로 본문을 선언할 수 있습니다. -이렇게 하면 (Pydantic 모델을 사용하는 경우처럼) 유효한 필드/어트리뷰트 이름이 무엇인지 미리 알 필요가 없습니다. +이렇게 하면 (Pydantic 모델을 사용하는 경우와 달리) 유효한 필드/어트리뷰트 이름이 무엇인지 미리 알 필요가 없습니다. 아직 모르는 키를 받으려는 경우에 유용합니다. diff --git a/docs/ko/docs/tutorial/body.md b/docs/ko/docs/tutorial/body.md index e5a670baf..dde070807 100644 --- a/docs/ko/docs/tutorial/body.md +++ b/docs/ko/docs/tutorial/body.md @@ -10,7 +10,7 @@ /// note | 참고 -데이터를 보내기 위해, (좀 더 보편적인) `POST`, `PUT`, `DELETE` 혹은 `PATCH` 중에 하나를 사용하는 것이 좋습니다. +데이터를 보내기 위해, `POST` (가장 일반적), `PUT`, `DELETE` 혹은 `PATCH` 중에 하나를 사용하는 것이 좋습니다. `GET` 요청에 본문을 담아 보내는 것은 명세서에 정의되지 않은 행동입니다. 그럼에도 불구하고, 이 방식은 아주 복잡한/극한의 사용 상황에서만 FastAPI에 의해 지원됩니다. @@ -88,7 +88,7 @@ ## 편집기 지원 { #editor-support } -편집기에서, 함수 내에서 타입 힌트와 완성을 어디서나 (만약 Pydantic model 대신에 `dict`을 받을 경우 나타나지 않을 수 있습니다) 받을 수 있습니다: +편집기에서, 함수 내에서 타입 힌트와 완성을 어디서나 (만약 Pydantic 모델 대신에 `dict`을 받을 경우 나타나지 않을 수 있습니다) 받을 수 있습니다: @@ -141,14 +141,14 @@ **본문**, **경로** 그리고 **쿼리** 매개변수 모두 동시에 선언할 수도 있습니다. -**FastAPI**는 각각을 인지하고 데이터를 올바른 위치에 가져올 것입니다. +**FastAPI**는 각각을 인지하고 데이터를 올바른 위치에서 가져올 것입니다. {* ../../docs_src/body/tutorial004_py310.py hl[16] *} 함수 매개변수는 다음을 따라서 인지하게 됩니다: * 만약 매개변수가 **경로**에도 선언되어 있다면, 이는 경로 매개변수로 사용될 것입니다. -* 만약 매개변수가 (`int`, `float`, `str`, `bool` 등과 같은) **유일한 타입**으로 되어있으면, **쿼리** 매개변수로 해석될 것입니다. +* 만약 매개변수가 (`int`, `float`, `str`, `bool` 등과 같은) **단일 타입**으로 되어있으면, **쿼리** 매개변수로 해석될 것입니다. * 만약 매개변수가 **Pydantic 모델** 타입으로 선언되어 있으면, 요청 **본문**으로 해석될 것입니다. /// note | 참고 @@ -163,4 +163,4 @@ FastAPI는 `q`의 값이 필요없음을 기본 값 `= None` 때문에 알게 ## Pydantic없이 { #without-pydantic } -만약 Pydantic 모델을 사용하고 싶지 않다면, **Body** 매개변수를 사용할 수도 있습니다. [Body - Multiple Parameters: Singular values in body](body-multiple-params.md#singular-values-in-body) 문서를 확인하세요. +만약 Pydantic 모델을 사용하고 싶지 않다면, **Body** 매개변수를 사용할 수도 있습니다. [Body - 여러 매개변수: 본문의 단일 값](body-multiple-params.md#singular-values-in-body) 문서를 확인하세요. diff --git a/docs/ko/docs/tutorial/debugging.md b/docs/ko/docs/tutorial/debugging.md index f437286b2..c3d06c0b8 100644 --- a/docs/ko/docs/tutorial/debugging.md +++ b/docs/ko/docs/tutorial/debugging.md @@ -59,7 +59,7 @@ Python에 의해 자동으로 생성된 파일의 내부 변수 `__name__`은 ```Python from myapp import app -# Some more code +# 추가 코드 ``` 이 경우 `myapp.py` 내부의 자동 변수 `__name__`에는 값이 `"__main__"`이 들어가지 않습니다. @@ -99,7 +99,7 @@ from myapp import app --- -Pycharm을 사용하는 경우 다음을 수행할 수 있습니다 +PyCharm을 사용하는 경우 다음을 수행할 수 있습니다 * "Run" 메뉴를 엽니다. * "Debug..." 옵션을 선택합니다. diff --git a/docs/ko/docs/tutorial/dependencies/dependencies-with-yield.md b/docs/ko/docs/tutorial/dependencies/dependencies-with-yield.md index 61bb47d9d..67405ff6c 100644 --- a/docs/ko/docs/tutorial/dependencies/dependencies-with-yield.md +++ b/docs/ko/docs/tutorial/dependencies/dependencies-with-yield.md @@ -4,7 +4,7 @@ FastAPI는 diff --git a/docs/uk/docs/advanced/response-change-status-code.md b/docs/uk/docs/advanced/response-change-status-code.md index 167df8313..e52479228 100644 --- a/docs/uk/docs/advanced/response-change-status-code.md +++ b/docs/uk/docs/advanced/response-change-status-code.md @@ -1,5 +1,6 @@ # Відповідь - зміна коду статусу { #response-change-status-code } + Ймовірно, ви вже читали, що можна встановити типовий [код статусу відповіді](../tutorial/response-status-code.md). Але інколи потрібно повернути інший код статусу, ніж типовий. diff --git a/docs/uk/docs/advanced/response-cookies.md b/docs/uk/docs/advanced/response-cookies.md index f4a79fb98..2e062adff 100644 --- a/docs/uk/docs/advanced/response-cookies.md +++ b/docs/uk/docs/advanced/response-cookies.md @@ -26,7 +26,7 @@ {* ../../docs_src/response_cookies/tutorial001_py310.py hl[10:12] *} -/// tip +/// tip | Порада Майте на увазі, що якщо ви повертаєте відповідь безпосередньо замість використання параметра `Response`, FastAPI поверне її напряму. diff --git a/docs/uk/docs/advanced/response-headers.md b/docs/uk/docs/advanced/response-headers.md index 95ab57fe0..67f1f0c6a 100644 --- a/docs/uk/docs/advanced/response-headers.md +++ b/docs/uk/docs/advanced/response-headers.md @@ -38,4 +38,4 @@ Майте на увазі, що власні пропрієтарні заголовки можна додавати [за допомогою префікса `X-`](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers). -Але якщо у вас є власні заголовки, які клієнт у браузері має бачити, вам потрібно додати їх у вашу конфігурацію CORS (докладніше в [CORS (Cross-Origin Resource Sharing)](../tutorial/cors.md)), використовуючи параметр `expose_headers`, задокументований у [документації Starlette щодо CORS](https://www.starlette.dev/middleware/#corsmiddleware). +Але якщо у вас є власні заголовки, які клієнт у браузері має бачити, вам потрібно додати їх у вашу конфігурацію CORS (докладніше в [CORS (спільне використання ресурсів між різними джерелами)](../tutorial/cors.md)), використовуючи параметр `expose_headers`, задокументований у [документації Starlette щодо CORS](https://www.starlette.dev/middleware/#corsmiddleware). diff --git a/docs/uk/docs/advanced/security/oauth2-scopes.md b/docs/uk/docs/advanced/security/oauth2-scopes.md index 769365d24..7c898da70 100644 --- a/docs/uk/docs/advanced/security/oauth2-scopes.md +++ b/docs/uk/docs/advanced/security/oauth2-scopes.md @@ -76,7 +76,7 @@ OAuth2 зі scopes - це механізм, який використовуют Оскільки тепер ми оголошуємо ці scopes, вони з’являться в документації API, коли ви увійдете/авторизуєтеся. -І ви зможете обрати, які scopes надати доступ: `me` і `items`. +І ви зможете обрати, яким scopes надати доступ: `me` і `items`. Це той самий механізм, який використовується, коли ви надаєте дозволи під час входу через Facebook, Google, GitHub тощо: @@ -132,7 +132,7 @@ OAuth2 зі scopes - це механізм, який використовуют Але використовуючи `Security` замість `Depends`, **FastAPI** знатиме, що можна оголошувати scopes безпеки, використовувати їх внутрішньо та документувати API через OpenAPI. -Коли ви імпортуєте `Query`, `Path`, `Depends`, `Security` та інші з `fastapi`, це насправді функції, що повертають спеціальні класи. +Але коли ви імпортуєте `Query`, `Path`, `Depends`, `Security` та інші з `fastapi`, це насправді функції, що повертають спеціальні класи. /// @@ -152,7 +152,7 @@ OAuth2 зі scopes - це механізм, який використовуют {* ../../docs_src/security/tutorial005_an_py310.py hl[9,106] *} -## Використовуйте scopes { #use-the-scopes } +## Використовуйте `scopes` { #use-the-scopes } Параметр `security_scopes` матиме тип `SecurityScopes`. @@ -194,9 +194,9 @@ OAuth2 зі scopes - це механізм, який використовуют Ще раз розгляньмо дерево залежностей і scopes. -Оскільки залежність `get_current_active_user` має підзалежність `get_current_user`, scope «me», оголошений у `get_current_active_user`, буде включений до списку потрібних scopes у `security_scopes.scopes`, переданого до `get_current_user`. +Оскільки залежність `get_current_active_user` має підзалежність `get_current_user`, scope `"me"`, оголошений у `get_current_active_user`, буде включений до списку потрібних scopes у `security_scopes.scopes`, переданого до `get_current_user`. -Сама операція шляху також оголошує scope «items», отже він також буде у списку `security_scopes.scopes`, переданому до `get_current_user`. +Сама операція шляху також оголошує scope `"items"`, отже він також буде у списку `security_scopes.scopes`, переданому до `get_current_user`. Ось як виглядає ієрархія залежностей і scopes: diff --git a/docs/uk/docs/advanced/settings.md b/docs/uk/docs/advanced/settings.md index b369e2f12..867eb23b0 100644 --- a/docs/uk/docs/advanced/settings.md +++ b/docs/uk/docs/advanced/settings.md @@ -100,7 +100,7 @@ $ ADMIN_EMAIL="deadpool@example.com" APP_NAME="ChimichangApp" fastapi run main.p ## Налаштування в іншому модулі { #settings-in-another-module } -Ви можете розмістити ці налаштування в іншому модулі, як ви бачили в [Більші застосунки - кілька файлів](../tutorial/bigger-applications.md). +Ви можете розмістити ці налаштування в іншому файлі модуля, як ви бачили в [Більші застосунки - кілька файлів](../tutorial/bigger-applications.md). Наприклад, у вас може бути файл `config.py` з: @@ -297,6 +297,6 @@ participant execute as Execute function Ви можете використовувати Pydantic Settings для обробки налаштувань або конфігурацій вашого застосунку, з усією потужністю моделей Pydantic. -- Використовуючи залежність, ви можете спростити тестування. -- Ви можете використовувати з ним файли `.env`. -- Використання `@lru_cache` дає змогу уникнути повторного читання файла dotenv для кожного запиту, водночас дозволяючи переписувати його під час тестування. +* Використовуючи залежність, ви можете спростити тестування. +* Ви можете використовувати з ним файли `.env`. +* Використання `@lru_cache` дає змогу уникнути повторного читання файла dotenv для кожного запиту, водночас дозволяючи переписувати його під час тестування. diff --git a/docs/uk/docs/advanced/stream-data.md b/docs/uk/docs/advanced/stream-data.md index 8ddfa38fb..29d66739e 100644 --- a/docs/uk/docs/advanced/stream-data.md +++ b/docs/uk/docs/advanced/stream-data.md @@ -2,7 +2,7 @@ Якщо ви хочете передавати потоком дані, які можна структурувати як JSON, див. [Потокова передача JSON Lines](../tutorial/stream-json-lines.md). -Але якщо ви хочете передавати потоком чисті бінарні дані або строки, ось як це зробити. +Але якщо ви хочете передавати потоком **чисті бінарні дані** або строки, ось як це зробити. /// note | Примітка @@ -12,21 +12,21 @@ ## Варіанти використання { #use-cases } -Це можна використовувати, якщо ви хочете передавати потоком чисті строки, наприклад безпосередньо з виводу сервісу AI LLM. +Це можна використовувати, якщо ви хочете передавати потоком чисті строки, наприклад безпосередньо з виводу сервісу **AI LLM**. -Також це можна використати для потокової передачі великих бінарних файлів, коли ви надсилаєте кожний фрагмент даних під час читання, без потреби завантажувати все в пам'ять одразу. +Також це можна використати для потокової передачі **великих бінарних файлів**, коли ви надсилаєте кожний фрагмент даних під час читання, без потреби завантажувати все в пам'ять одразу. -Так само можна стрімити відео чи аудіо; їх навіть можна генерувати під час обробки та надсилання. +Так само можна стрімити **відео** чи **аудіо**; їх навіть можна генерувати під час обробки та надсилання. ## `StreamingResponse` з `yield` { #a-streamingresponse-with-yield } -Якщо ви оголосите `response_class=StreamingResponse` у вашій функції операції шляху, ви можете використовувати `yield`, щоб послідовно надсилати кожний фрагмент даних. +Якщо ви оголосите `response_class=StreamingResponse` у вашій *функції операції шляху*, ви можете використовувати `yield`, щоб послідовно надсилати кожний фрагмент даних. {* ../../docs_src/stream_data/tutorial001_py310.py ln[1:23] hl[20,23] *} FastAPI передаватиме кожний фрагмент даних до `StreamingResponse` як є; він не намагатиметься перетворити його на JSON чи щось подібне. -### Не-async функції операції шляху { #non-async-path-operation-functions } +### Не-async *функції операції шляху* { #non-async-path-operation-functions } Можна також використовувати звичайні функції `def` (без `async`) і так само застосовувати `yield`. @@ -40,7 +40,7 @@ FastAPI передаватиме кожний фрагмент даних до ` {* ../../docs_src/stream_data/tutorial001_py310.py ln[32:35] hl[33] *} -Це також означає, що з `StreamingResponse` у вас є свобода і відповідальність формувати та кодувати байти даних саме так, як їх потрібно надіслати, незалежно від анотацій типів. 🤓 +Це також означає, що з `StreamingResponse` у вас є **свобода** і **відповідальність** формувати та кодувати байти даних саме так, як їх потрібно надіслати, незалежно від анотацій типів. 🤓 ### Потік байтів { #stream-bytes } @@ -58,7 +58,7 @@ FastAPI передаватиме кожний фрагмент даних до ` {* ../../docs_src/stream_data/tutorial002_py310.py ln[6,19:20] hl[20] *} -Потім ви можете використати цей новий клас у `response_class=PNGStreamingResponse` у вашій функції операції шляху: +Потім ви можете використати цей новий клас у `response_class=PNGStreamingResponse` у вашій *функції операції шляху*: {* ../../docs_src/stream_data/tutorial002_py310.py ln[23:27] hl[23] *} @@ -98,7 +98,7 @@ FastAPI передаватиме кожний фрагмент даних до ` /// -Щоб уникнути блокування циклу подій, просто оголосіть функцію операції шляху зі звичайним `def` замість `async def`. Тоді FastAPI виконуватиме її в працівнику пулу потоків, щоб не блокувати головний цикл. +Щоб уникнути блокування циклу подій, просто оголосіть *функцію операції шляху* зі звичайним `def` замість `async def`. Тоді FastAPI виконуватиме її в працівнику пулу потоків, щоб не блокувати головний цикл. {* ../../docs_src/stream_data/tutorial002_py310.py ln[30:34] hl[31] *} diff --git a/docs/uk/docs/advanced/wsgi.md b/docs/uk/docs/advanced/wsgi.md index 51ca6f6fb..aa4dcb6b0 100644 --- a/docs/uk/docs/advanced/wsgi.md +++ b/docs/uk/docs/advanced/wsgi.md @@ -1,5 +1,6 @@ # Підключення WSGI - Flask, Django та інші { #including-wsgi-flask-django-others } + Ви можете монтувати застосунки WSGI, як ви бачили в [Підзастосунки - монтування](sub-applications.md), [За представником](behind-a-proxy.md). Для цього ви можете використати `WSGIMiddleware` і обгорнути ним ваш застосунок WSGI, наприклад Flask, Django тощо. diff --git a/docs/uk/docs/alternatives.md b/docs/uk/docs/alternatives.md index 155c727df..f903f3f20 100644 --- a/docs/uk/docs/alternatives.md +++ b/docs/uk/docs/alternatives.md @@ -44,11 +44,11 @@ Django REST Framework створив Том Крісті. Той самий тв ### [Flask](https://flask.palletsprojects.com) { #flask } -Flask — це «мікрофреймворк», він не включає інтеграцію бази даних, а також багато речей, які за замовчуванням є в Django. +Flask - це «мікрофреймворк», він не включає інтеграцію бази даних, а також багато речей, які за замовчуванням є в Django. Ця простота та гнучкість дозволяють використовувати бази даних NoSQL як основну систему зберігання даних. -Оскільки він дуже простий, він порівняно легкий та інтуїтивний для освоєння, хоча в деяких моментах документація стає дещо технічною. +Оскільки він дуже простий, він порівняно інтуїтивний для освоєння, хоча в деяких моментах документація стає дещо технічною. Він також зазвичай використовується для інших програм, яким не обов’язково потрібна база даних, керування користувачами або будь-яка з багатьох функцій, які є попередньо вбудованими в Django. Хоча багато з цих функцій можна додати за допомогою плагінів. @@ -72,7 +72,7 @@ Flask — це «мікрофреймворк», він не включає ін Але все ж FastAPI черпав натхнення з Requests. -**Requests** — це бібліотека для *взаємодії* з API (як клієнт), а **FastAPI** — це бібліотека для *створення* API (як сервер). +**Requests** - це бібліотека для *взаємодії* з API (як клієнт), а **FastAPI** - це бібліотека для *створення* API (як сервер). Вони більш-менш знаходяться на протилежних кінцях, доповнюючи одна одну. @@ -88,7 +88,7 @@ Requests мають дуже простий та інтуїтивно зрозу response = requests.get("http://example.com/some/url") ``` -Відповідна операція шляху API FastAPI може виглядати так: +Відповідна *операція шляху* API FastAPI може виглядати так: ```Python hl_lines="1" @app.get("/some/url") @@ -124,7 +124,7 @@ def read_url(): Інтегрувати інструменти інтерфейсу на основі стандартів: -* [Інтерфейс Swagger](https://github.com/swagger-api/swagger-ui) +* [Swagger UI](https://github.com/swagger-api/swagger-ui) * [ReDoc](https://github.com/Rebilly/ReDoc) Ці два було обрано через те, що вони досить популярні та стабільні, але, виконавши швидкий пошук, ви можете знайти десятки додаткових альтернативних інтерфейсів для OpenAPI (які можна використовувати з **FastAPI**). @@ -157,7 +157,7 @@ Marshmallow створено для забезпечення цих функці Іншою важливою функцією, необхідною для API, є аналіз даних із вхідних запитів. -Webargs — це інструмент, створений, щоб забезпечити це поверх кількох фреймворків, включаючи Flask. +Webargs - це інструмент, створений, щоб забезпечити це поверх кількох фреймворків, включаючи Flask. Він використовує Marshmallow в основі для перевірки даних. І створений тими ж розробниками. @@ -239,7 +239,7 @@ Flask-apispec був створений тими ж розробниками Mar ### [NestJS](https://nestjs.com/) (та [Angular](https://angular.io/)) { #nestjs-and-angular } -Це навіть не Python, NestJS — це фреймворк NodeJS JavaScript (TypeScript), натхненний Angular. +Це навіть не Python, NestJS - це фреймворк NodeJS JavaScript (TypeScript), натхненний Angular. Це досягає чогось подібного до того, що можна зробити з Flask-apispec. @@ -281,7 +281,7 @@ Flask-apispec був створений тими ж розробниками Mar ### [Falcon](https://falconframework.org/) { #falcon } -Falcon — ще один високопродуктивний фреймворк Python, він розроблений як мінімальний і працює як основа інших фреймворків, таких як Hug. +Falcon - ще один високопродуктивний фреймворк Python, він розроблений як мінімальний і працює як основа інших фреймворків, таких як Hug. Він розроблений таким чином, щоб мати функції, які отримують два параметри, один «запит» і один «відповідь». Потім ви «читаєте» частини запиту та «записуєте» частини у відповідь. Через такий дизайн неможливо оголосити параметри запиту та тіла за допомогою стандартних підказок типу Python як параметри функції. @@ -351,7 +351,7 @@ Hug надихнув **FastAPI** оголосити параметр `response` /// -### [APIStar](https://github.com/encode/apistar) (<= 0,5) { #apistar-0-5 } +### [APIStar](https://github.com/encode/apistar) (<= 0.5) { #apistar-0-5 } Безпосередньо перед тим, як вирішити створити **FastAPI**, я знайшов сервер **APIStar**. Він мав майже все, що я шукав, і мав чудовий дизайн. @@ -373,7 +373,7 @@ Hug надихнув **FastAPI** оголосити параметр `response` Це вже не був веб-фреймворк API, оскільки творцю потрібно було зосередитися на Starlette. -Тепер APIStar — це набір інструментів для перевірки специфікацій OpenAPI, а не веб-фреймворк. +Тепер APIStar - це набір інструментів для перевірки специфікацій OpenAPI, а не веб-фреймворк. /// note | Примітка @@ -403,7 +403,7 @@ APIStar створив Том Крісті. Той самий хлопець, я ### [Pydantic](https://docs.pydantic.dev/) { #pydantic } -Pydantic — це бібліотека для визначення перевірки даних, серіалізації та документації (за допомогою Схеми JSON) на основі підказок типу Python. +Pydantic - це бібліотека для визначення перевірки даних, серіалізації та документації (за допомогою Схеми JSON) на основі підказок типу Python. Це робить його надзвичайно інтуїтивним. @@ -419,7 +419,7 @@ Pydantic — це бібліотека для визначення переві ### [Starlette](https://www.starlette.dev/) { #starlette } -Starlette — це легкий фреймворк/набір інструментів ASGI, який ідеально підходить для створення високопродуктивних asyncio сервісів. +Starlette - це легкий фреймворк/набір інструментів ASGI, який ідеально підходить для створення високопродуктивних asyncio сервісів. Він дуже простий та інтуїтивно зрозумілий. Його розроблено таким чином, щоб його можна було легко розширювати та мати модульні компоненти. @@ -433,7 +433,7 @@ Starlette — це легкий фреймворк/набір інструмен * CORS, GZip, статичні файли, потокові відповіді. * Підтримку сеансів і кукі. * 100% покриття тестом. -* 100% анотовану кодову базу. +* 100% анотовану типами кодову базу. * Кілька жорстких залежностей. Starlette наразі є найшвидшим фреймворком Python із перевірених. Перевершує лише Uvicorn, який є не фреймворком, а сервером. @@ -446,7 +446,7 @@ Starlette надає всі основні функції веб-мікрофр /// note | Технічні деталі -ASGI — це новий «стандарт», який розробляється членами основної команди Django. Це ще не «стандарт Python» (PEP), хоча вони в процесі цього. +ASGI - це новий «стандарт», який розробляється членами основної команди Django. Це ще не «стандарт Python» (PEP), хоча вони в процесі цього. Тим не менш, він уже використовується як «стандарт» кількома інструментами. Це значно покращує сумісність, оскільки ви можете переключити Uvicorn на будь-який інший сервер ASGI (наприклад, Daphne або Hypercorn), або ви можете додати інструменти, сумісні з ASGI, як-от `python-socketio`. @@ -464,9 +464,9 @@ ASGI — це новий «стандарт», який розробляєтьс ### [Uvicorn](https://www.uvicorn.dev/) { #uvicorn } -Uvicorn — це блискавичний сервер ASGI, побудований на uvloop і httptools. +Uvicorn - це блискавичний сервер ASGI, побудований на uvloop і httptools. -Це не веб-фреймворк, а сервер. Наприклад, він не надає інструментів для маршрутизації. Це те, що фреймворк на кшталт Starlette (або **FastAPI**) забезпечить поверх нього. +Це не веб-фреймворк, а сервер. Наприклад, він не надає інструментів для маршрутизації за шляхами. Це те, що фреймворк на кшталт Starlette (або **FastAPI**) забезпечить поверх нього. Це рекомендований сервер для Starlette і **FastAPI**. diff --git a/docs/uk/docs/async.md b/docs/uk/docs/async.md index 72e29b3ea..9a9a90d12 100644 --- a/docs/uk/docs/async.md +++ b/docs/uk/docs/async.md @@ -1,6 +1,6 @@ # Рівночасність і async / await { #concurrency-and-async-await } -Деталі щодо синтаксису `async def` для функцій операції шляху і деякі відомості про асинхронний код, рівночасність і паралелізм. +Деталі щодо синтаксису `async def` для *функцій операції шляху* і деякі відомості про асинхронний код, рівночасність і паралелізм. ## Поспішаєте? { #in-a-hurry } @@ -12,7 +12,7 @@ results = await some_library() ``` -Тоді оголошуйте ваші функції операції шляху з `async def`, наприклад: +Тоді оголошуйте ваші *функції операції шляху* з `async def`, наприклад: ```Python hl_lines="2" @app.get('/') @@ -29,7 +29,7 @@ async def read_results(): --- -Якщо ви використовуєте сторонню бібліотеку, яка взаємодіє з чимось (база даних, API, файлова система тощо) і не підтримує використання `await` (наразі це стосується більшості бібліотек баз даних), тоді оголошуйте ваші функції операції шляху як зазвичай, просто з `def`, наприклад: +Якщо ви використовуєте сторонню бібліотеку, яка взаємодіє з чимось (база даних, API, файлова система тощо) і не підтримує використання `await` (наразі це стосується більшості бібліотек баз даних), тоді оголошуйте ваші *функції операції шляху* як зазвичай, просто з `def`, наприклад: ```Python hl_lines="2" @app.get('/') @@ -48,7 +48,7 @@ def results(): --- -Примітка: ви можете змішувати `def` і `async def` у ваших функціях операції шляху скільки завгодно і визначати кожну з них найкращим для вас способом. FastAPI зробить з ними все правильно. +**Примітка**: ви можете змішувати `def` і `async def` у ваших *функціях операції шляху* скільки завгодно і визначати кожну з них найкращим для вас способом. FastAPI зробить з ними все правильно. У будь-якому з наведених випадків FastAPI все одно працюватиме асинхронно і буде надзвичайно швидким. @@ -56,17 +56,17 @@ def results(): ## Технічні деталі { #technical-details } -Сучасні версії Python мають підтримку «асинхронного коду» за допомогою так званих «співпрограм» з синтаксисом **`async` і `await`**. +Сучасні версії Python мають підтримку **«асинхронного коду»** за допомогою так званих **«співпрограм»** з синтаксисом **`async` і `await`**. Розгляньмо цю фразу по частинах у секціях нижче: -- Асинхронний код -- `async` і `await` -- Співпрограми +- **Асинхронний код** +- **`async` і `await`** +- **Співпрограми** ## Асинхронний код { #asynchronous-code } -Асинхронний код означає, що мова 💬 має спосіб сказати комп’ютеру/програмі 🤖, що в певний момент у коді він 🤖 має почекати, поки «щось інше» завершиться десь ще. Скажімо, це «щось інше» називається «slow-file» 📝. +Асинхронний код означає, що мова 💬 має спосіб сказати комп’ютеру/програмі 🤖, що в певний момент у коді він 🤖 має почекати, поки *«щось інше»* завершиться десь ще. Скажімо, це *«щось інше»* називається «slow-file» 📝. Отже, в цей час комп’ютер може піти і зробити іншу роботу, доки «slow-file» 📝 завершується. @@ -97,9 +97,9 @@ def results(): Ідею **асинхронного** коду, описану вище, інколи також називають **«рівночасністю»**. Вона відрізняється від **«паралелізму»**. -І рівночасність, і паралелізм стосуються «різних речей, що відбуваються більш-менш одночасно». +**Рівночасність** і **паралелізм** стосуються «різних речей, що відбуваються більш-менш одночасно». -Але деталі між рівночасністю і паралелізмом досить різні. +Але деталі між *рівночасністю* і *паралелізмом* досить різні. Щоб побачити різницю, уявімо таку історію про бургери: @@ -257,7 +257,7 @@ def results(): Ні! Це не мораль історії. -Рівночасність відрізняється від паралелізму. І вона краща у конкретних сценаріях, що містять багато очікування. Через це зазвичай вона значно краща за паралелізм для розробки вебзастосунків. Але не для всього. +Рівночасність відрізняється від паралелізму. І вона краща у **конкретних** сценаріях, що містять багато очікування. Через це зазвичай вона значно краща за паралелізм для розробки вебзастосунків. Але не для всього. Щоб урівноважити це, уявімо коротку історію: @@ -273,15 +273,15 @@ def results(): Завершення займе той самий час із «чергами» чи без (рівночасність), і ви виконаєте той самий обсяг роботи. -Але в цьому випадку, якби ви могли привести 8 колишніх касирів/кухарів/тепер прибиральників, і кожен з них (разом із вами) взяв би свою зону будинку для прибирання, ви могли б виконати всю роботу паралельно — з додатковою допомогою — і завершити значно швидше. +Але в цьому випадку, якби ви могли привести 8 колишніх касирів/кухарів/тепер прибиральників, і кожен з них (разом із вами) взяв би свою зону будинку для прибирання, ви могли б виконати всю роботу **паралельно** - з додатковою допомогою - і завершити значно швидше. У цьому сценарії кожен з прибиральників (включно з вами) був би процесором, що виконує свою частину роботи. -І оскільки більшість часу виконання займає реальна робота (а не очікування), а роботу на комп’ютері виконує CPU, ці проблеми називають «CPU bound». +І оскільки більшість часу виконання займає реальна робота (а не очікування), а роботу на комп’ютері виконує CPU, ці проблеми називають **«CPU bound»**. --- -Поширені приклади «CPU bound» операцій - це речі, що потребують складної математичної обробки. +Поширені приклади **CPU bound** операцій - це речі, що потребують складної математичної обробки. Наприклад: @@ -294,7 +294,7 @@ def results(): З **FastAPI** ви можете скористатися рівночасністю, що дуже поширена у веброзробці (та ж головна принада NodeJS). -Але ви також можете використати переваги паралелізму і багатопроцесорності (наявність кількох процесів, що працюють паралельно) для навантажень «CPU bound», як у системах машинного навчання. +Але ви також можете використати переваги паралелізму і багатопроцесорності (наявність кількох процесів, що працюють паралельно) для навантажень **«CPU bound»**, як у системах машинного навчання. Це, плюс простий факт, що Python є основною мовою для **Data Science**, машинного навчання і особливо глибокого навчання, робить FastAPI дуже вдалим вибором для веб API та застосунків Data Science / машинного навчання (серед багатьох інших). @@ -340,7 +340,7 @@ burgers = get_burgers(2) --- -Отже, якщо ви використовуєте бібліотеку, яку можна викликати з `await`, вам потрібно створити функцію операції шляху, що її використовує, з `async def`, як тут: +Отже, якщо ви використовуєте бібліотеку, яку можна викликати з `await`, вам потрібно створити *функцію операції шляху*, що її використовує, з `async def`, як тут: ```Python hl_lines="2-3" @app.get('/burgers') @@ -357,7 +357,7 @@ async def read_burgers(): Тож як же викликати першу `async`-функцію - курка чи яйце? -Якщо ви працюєте з **FastAPI**, вам не потрібно про це турбуватися, адже цією «першою» функцією буде ваша функція операції шляху, і FastAPI знатиме, як учинити правильно. +Якщо ви працюєте з **FastAPI**, вам не потрібно про це турбуватися, адже цією «першою» функцією буде ваша *функція операції шляху*, і FastAPI знатиме, як учинити правильно. Але якщо ви хочете використовувати `async` / `await` без FastAPI, ви також можете це зробити. @@ -395,7 +395,7 @@ Starlette (і **FastAPI**) базуються на [AnyIO](https://anyio.readthe Погляньмо на ту саму фразу ще раз: -> Сучасні версії Python мають підтримку «асинхронного коду» за допомогою так званих «співпрограм», з синтаксисом **`async` і `await`**. +> Сучасні версії Python мають підтримку **«асинхронного коду»** за допомогою так званих **«співпрограм»**, з синтаксисом **`async` і `await`**. Тепер це має більше сенсу. ✨ @@ -415,11 +415,11 @@ Starlette (і **FastAPI**) базуються на [AnyIO](https://anyio.readthe ### Функції операції шляху { #path-operation-functions } -Коли ви оголошуєте функцію операції шляху зі звичайним `def` замість `async def`, вона виконується у зовнішньому пулі потоків (threadpool), який потім «очікується», замість прямого виклику (оскільки прямий виклик блокував би сервер). +Коли ви оголошуєте *функцію операції шляху* зі звичайним `def` замість `async def`, вона виконується у зовнішньому пулі потоків (threadpool), який потім «очікується», замість прямого виклику (оскільки прямий виклик блокував би сервер). -Якщо ви прийшли з іншого async-фреймворку, який не працює так, як описано вище, і звикли визначати тривіальні, лише обчислювальні функції операції шляху зі звичайним `def` заради крихітного виграшу у продуктивності (близько 100 наносекунд), зверніть увагу, що у **FastAPI** ефект буде протилежним. У таких випадках краще використовувати `async def`, якщо тільки ваші функції операції шляху не використовують код, що виконує блокуюче I/O. +Якщо ви прийшли з іншого async-фреймворку, який не працює так, як описано вище, і звикли визначати тривіальні, лише обчислювальні *функції операції шляху* зі звичайним `def` заради крихітного виграшу у продуктивності (близько 100 наносекунд), зверніть увагу, що у **FastAPI** ефект буде протилежним. У таких випадках краще використовувати `async def`, якщо тільки ваші *функції операції шляху* не використовують код, що виконує блокуюче I/O. -Втім, у будь-якій ситуації є велика ймовірність, що **FastAPI** [все одно буде швидшим](index.md#performance) (або принаймні порівнянним) за ваш попередній фреймворк. +Втім, в обох ситуаціях є велика ймовірність, що **FastAPI** [все одно буде швидшим](index.md#performance) (або принаймні порівнянним) за ваш попередній фреймворк. ### Залежності { #dependencies } @@ -433,7 +433,7 @@ Starlette (і **FastAPI**) базуються на [AnyIO](https://anyio.readthe Будь-яка інша допоміжна функція, яку ви викликаєте безпосередньо, може бути створена зі звичайним `def` або `async def`, і FastAPI не впливатиме на спосіб її виклику. -Це відрізняється від функцій, які FastAPI викликає за вас: функції операції шляху і залежності. +Це відрізняється від функцій, які FastAPI викликає за вас: *функції операції шляху* і залежності. Якщо ваша допоміжна функція є звичайною функцією з `def`, її буде викликано безпосередньо (як ви написали у своєму коді), не в пулі потоків; якщо функція створена з `async def`, тоді вам слід використовувати `await` при її виклику у вашому коді. diff --git a/docs/uk/docs/deployment/cloud.md b/docs/uk/docs/deployment/cloud.md index 97d972717..8c7259946 100644 --- a/docs/uk/docs/deployment/cloud.md +++ b/docs/uk/docs/deployment/cloud.md @@ -16,7 +16,7 @@ FastAPI Cloud є основним спонсором і джерелом фін ## Хмарні постачальники - спонсори { #cloud-providers-sponsors } -Деякі інші хмарні постачальники ✨ [**спонсорують FastAPI**](../help-fastapi.md#sponsor-the-author) ✨ також. 🙇 +Деякі інші хмарні постачальники ✨ [**спонсорують FastAPI**](https://github.com/sponsors/tiangolo) ✨ також. 🙇 Можливо, ви захочете розглянути їх, щоб дотримуватися їхніх інструкцій і спробувати їхні сервіси: diff --git a/docs/uk/docs/deployment/concepts.md b/docs/uk/docs/deployment/concepts.md index a6a5bc80e..cec4d8f01 100644 --- a/docs/uk/docs/deployment/concepts.md +++ b/docs/uk/docs/deployment/concepts.md @@ -5,11 +5,11 @@ Деякі важливі концепції: - Безпека - HTTPS -- Запуск під час старту +- Запуск під час запуску - Перезапуски - Реплікація (кількість запущених процесів) - Пам'ять -- Попередні кроки перед стартом +- Попередні кроки перед запуском Подивимось, як вони впливають на **розгортання**. @@ -88,7 +88,7 @@ Тепер, коли ми знаємо різницю між термінами **процес** і **програма**, продовжимо говорити про розгортання. -## Запуск під час старту { #running-on-startup } +## Запуск під час запуску { #running-on-startup } У більшості випадків, коли ви створюєте веб-API, ви хочете, щоб він **працював постійно**, без перерв, щоб клієнти завжди мали до нього доступ. Звісно, якщо немає особливих причин запускати його лише в певних ситуаціях. Але зазвичай ви хочете, щоб він постійно працював і був **доступний**. @@ -102,15 +102,15 @@ І якщо сервер буде перезавантажено (наприклад, після оновлень або міграцій у хмарного провайдера), ви, ймовірно, **не помітите цього**. І через це ви навіть не знатимете, що треба вручну перезапустити процес. У результаті ваш API просто залишиться «мертвим». 😱 -### Автоматичний запуск під час старту { #run-automatically-on-startup } +### Автоматичний запуск під час запуску { #run-automatically-on-startup } -Загалом ви, напевно, захочете, щоб серверна програма (наприклад, Uvicorn) запускалася автоматично під час старту сервера і без будь-якого **людського втручання**, щоб завжди був запущений процес із вашим API (наприклад, Uvicorn із вашим FastAPI-застосунком). +Загалом ви, напевно, захочете, щоб серверна програма (наприклад, Uvicorn) запускалася автоматично під час запуску сервера і без будь-якого **людського втручання**, щоб завжди був запущений процес із вашим API (наприклад, Uvicorn із вашим FastAPI-застосунком). ### Окрема програма { #separate-program } -Щоб цього досягти, зазвичай використовують **окрему програму**, яка гарантує запуск вашого застосунку під час старту. І в багатьох випадках вона також забезпечує запуск інших компонентів або застосунків, наприклад бази даних. +Щоб цього досягти, зазвичай використовують **окрему програму**, яка гарантує запуск вашого застосунку під час запуску. І в багатьох випадках вона також забезпечує запуск інших компонентів або застосунків, наприклад бази даних. -### Приклади інструментів для запуску під час старту { #example-tools-to-run-at-startup } +### Приклади інструментів для запуску під час запуску { #example-tools-to-run-at-startup } Приклади інструментів, які можуть це робити: @@ -127,7 +127,7 @@ ## Перезапуски { #restarts } -Подібно до забезпечення запуску застосунку під час старту системи, ви, ймовірно, також захочете гарантувати його **перезапуск** після збоїв. +Подібно до забезпечення запуску застосунку під час запуску системи, ви, ймовірно, також захочете гарантувати його **перезапуск** після збоїв. ### Ми помиляємося { #we-make-mistakes } @@ -163,7 +163,7 @@ ### Приклади інструментів для автоматичного перезапуску { #example-tools-to-restart-automatically } -У більшості випадків той самий інструмент, який використовується для **запуску програми під час старту**, також використовується для автоматичних **перезапусків**. +У більшості випадків той самий інструмент, який використовується для **запуску програми під час запуску**, також використовується для автоматичних **перезапусків**. Наприклад, це можуть забезпечувати: @@ -192,7 +192,7 @@ Пам'ятаєте з документації [Про HTTPS](https.md), що на сервері лише один процес може слухати певну комбінацію порту та IP-адреси? -Это досі так. +Це досі так. Отже, щоб мати **кілька процесів** одночасно, має бути **єдиний процес, який слухає порт**, і який далі якимось чином передає комунікацію кожному процесу-працівнику. @@ -247,9 +247,9 @@ /// -## Попередні кроки перед стартом { #previous-steps-before-starting } +## Попередні кроки перед запуском { #previous-steps-before-starting } -Є багато випадків, коли потрібно виконати деякі кроки **перед стартом** вашого застосунку. +Є багато випадків, коли потрібно виконати деякі кроки **перед запуском** вашого застосунку. Наприклад, ви можете захотіти запустити **міграції бази даних**. @@ -310,11 +310,11 @@ Тут ви прочитали про основні концепції, які, ймовірно, потрібно тримати в голові, вирішуючи, як розгортати ваш застосунок: - Безпека - HTTPS -- Запуск під час старту +- Запуск під час запуску - Перезапуски - Реплікація (кількість запущених процесів) - Пам'ять -- Попередні кроки перед стартом +- Попередні кроки перед запуском Розуміння цих ідей і того, як їх застосовувати, має дати вам інтуїцію, необхідну для прийняття рішень під час конфігурування і тонкого налаштування ваших розгортань. 🤓 diff --git a/docs/uk/docs/deployment/docker.md b/docs/uk/docs/deployment/docker.md index ead651b2d..83799a00f 100644 --- a/docs/uk/docs/deployment/docker.md +++ b/docs/uk/docs/deployment/docker.md @@ -1,8 +1,8 @@ # FastAPI у контейнерах - Docker { #fastapi-in-containers-docker } -Під час розгортання застосунків FastAPI поширений підхід - збирати образи контейнерів Linux. Зазвичай це робиться за допомогою [Docker](https://www.docker.com/). Потім ви можете розгорнути цей образ контейнера кількома різними способами. +Під час розгортання застосунків FastAPI поширений підхід - збирати **образи контейнерів Linux**. Зазвичай це робиться за допомогою [**Docker**](https://www.docker.com/). Потім ви можете розгорнути цей образ контейнера кількома різними способами. -Використання контейнерів Linux має кілька переваг, зокрема безпека, відтворюваність, простота та інші. +Використання контейнерів Linux має кілька переваг, зокрема **безпека**, **відтворюваність**, **простота** та інші. /// tip | Порада @@ -34,33 +34,33 @@ CMD ["fastapi", "run", "app/main.py", "--port", "80"] ## Що таке контейнер { #what-is-a-container } -Контейнери (переважно контейнери Linux) - це дуже легкий спосіб упакувати застосунки з усіма їхніми залежностями та потрібними файлами, ізолювавши їх від інших контейнерів (інших застосунків або компонентів) у тій самій системі. +Контейнери (переважно контейнери Linux) - це дуже **легкий** спосіб упакувати застосунки з усіма їхніми залежностями та потрібними файлами, ізолювавши їх від інших контейнерів (інших застосунків або компонентів) у тій самій системі. -Контейнери Linux працюють, використовуючи той самий ядро Linux, що й хост (машина, віртуальна машина, хмарний сервер тощо). Це означає, що вони дуже легкі (у порівнянні з повними віртуальними машинами, які емулюють цілу операційну систему). +Контейнери Linux працюють, використовуючи те саме ядро Linux, що й хост (машина, віртуальна машина, хмарний сервер тощо). Це означає, що вони дуже легкі (у порівнянні з повними віртуальними машинами, які емулюють цілу операційну систему). -Таким чином контейнери споживають мало ресурсів, приблизно як безпосередньо запущені процеси (віртуальна машина споживала б значно більше). +Таким чином контейнери споживають **мало ресурсів**, приблизно як безпосередньо запущені процеси (віртуальна машина споживала б значно більше). -У контейнерів також є власні ізольовані процеси виконання (зазвичай лише один процес), файлові системи та мережі, що спрощує розгортання, безпеку, розробку тощо. +У контейнерів також є власні **ізольовані** процеси виконання (зазвичай лише один процес), файлові системи та мережі, що спрощує розгортання, безпеку, розробку тощо. ## Що таке образ контейнера { #what-is-a-container-image } -Контейнер запускається з образу контейнера. +**Контейнер** запускається з **образу контейнера**. -Образ контейнера - це статична версія всіх файлів, змінних оточення та типова команда/програма, яка має бути присутня в контейнері. Тут «статична» означає, що образ контейнера не запущений, він не виконується, це лише упаковані файли та метадані. +Образ контейнера - це **статична** версія всіх файлів, змінних оточення та типова команда/програма, яка має бути присутня в контейнері. Тут **«статична»** означає, що **образ** контейнера не запущений, він не виконується, це лише упаковані файли та метадані. -На противагу «образу контейнера», що є збереженим статичним вмістом, «контейнер» зазвичай означає запущений екземпляр, те, що виконується. +На противагу «**образу контейнера**», що є збереженим статичним вмістом, «**контейнер**» зазвичай означає запущений екземпляр, те, що **виконується**. -Коли контейнер запущено (запущений з образу контейнера), він може створювати або змінювати файли, змінні оточення тощо. Ці зміни існуватимуть лише в цьому контейнері, але не збережуться в базовому образі контейнера (не будуть записані на диск). +Коли **контейнер** запущено (запущений з **образу контейнера**), він може створювати або змінювати файли, змінні оточення тощо. Ці зміни існуватимуть лише в цьому контейнері, але не збережуться в базовому образі контейнера (не будуть записані на диск). -Образ контейнера можна порівняти з файлом і вмістом програми, наприклад `python` і файлом `main.py`. +Образ контейнера можна порівняти з файлом і вмістом **програми**, наприклад `python` і файлом `main.py`. -А сам контейнер (на відміну від образу) - це фактично запущений екземпляр образу, порівнянний із процесом. Насправді контейнер працює лише тоді, коли в ньому працює процес (і зазвичай це один процес). Контейнер зупиняється, коли в ньому не працює жоден процес. +А сам **контейнер** (на відміну від **образу контейнера**) - це фактично запущений екземпляр образу, порівнянний із **процесом**. Насправді контейнер працює лише тоді, коли в ньому **працює процес** (і зазвичай це один процес). Контейнер зупиняється, коли в ньому не працює жоден процес. ## Образи контейнерів { #container-images } -Docker був одним з основних інструментів для створення та керування образами контейнерів і контейнерами. +Docker був одним з основних інструментів для створення та керування **образами контейнерів** і **контейнерами**. -Існує публічний [Docker Hub](https://hub.docker.com/) з готовими офіційними образами для багатьох інструментів, середовищ, баз даних і застосунків. +Існує публічний [Docker Hub](https://hub.docker.com/) з готовими **офіційними образами контейнерів** для багатьох інструментів, середовищ, баз даних і застосунків. Наприклад, є офіційний [образ Python](https://hub.docker.com/_/python). @@ -71,43 +71,43 @@ Docker був одним з основних інструментів для с * [MongoDB](https://hub.docker.com/_/mongo) * [Redis](https://hub.docker.com/_/redis) тощо. -Використовуючи готовий образ контейнера, дуже легко поєднувати та використовувати різні інструменти. Наприклад, щоб випробувати нову базу даних. У більшості випадків ви можете використати офіційні образи та просто налаштувати їх змінними оточення. +Використовуючи готовий образ контейнера, дуже легко **поєднувати** та використовувати різні інструменти. Наприклад, щоб випробувати нову базу даних. У більшості випадків ви можете використати **офіційні образи** та просто налаштувати їх змінними оточення. Таким чином, у багатьох випадках ви зможете навчитися працювати з контейнерами і Docker та повторно використати ці знання з багатьма різними інструментами і компонентами. -Тобто ви запускатимете кілька контейнерів з різними речами, як-от базу даних, застосунок на Python, вебсервер із фронтендом на React, і з’єднаєте їх через внутрішню мережу. +Тобто ви запускатимете **кілька контейнерів** з різними речами, як-от базу даних, застосунок на Python, вебсервер із фронтендом на React, і з’єднаєте їх через внутрішню мережу. Усі системи керування контейнерами (як Docker чи Kubernetes) мають ці мережеві можливості вбудовано. ## Контейнери і процеси { #containers-and-processes } -Образ контейнера зазвичай містить у своїх метаданих типову програму або команду, яку слід виконати під час запуску контейнера, і параметри для цієї програми. Дуже схоже на те, що ви б виконали в командному рядку. +**Образ контейнера** зазвичай містить у своїх метаданих типову програму або команду, яку слід виконати під час запуску **контейнера**, і параметри для цієї програми. Дуже схоже на те, що ви б виконали в командному рядку. -Коли контейнер запускається, він виконає цю команду/програму (хоча ви можете перевизначити її і запустити іншу команду/програму). +Коли **контейнер** запускається, він виконає цю команду/програму (хоча ви можете перевизначити її і запустити іншу команду/програму). -Контейнер працює доти, доки працює головний процес (команда або програма). +Контейнер працює доти, доки працює **головний процес** (команда або програма). -Зазвичай контейнер має один процес, але також можливо запускати підпроцеси з головного процесу, і таким чином у вас може бути кілька процесів у тому самому контейнері. +Зазвичай контейнер має **один процес**, але також можливо запускати підпроцеси з головного процесу, і таким чином у вас може бути **кілька процесів** у тому самому контейнері. -Але неможливо мати запущений контейнер без принаймні одного запущеного процесу. Якщо головний процес зупиняється, контейнер зупиняється. +Але неможливо мати запущений контейнер без **принаймні одного запущеного процесу**. Якщо головний процес зупиняється, контейнер зупиняється. ## Зібрати Docker-образ для FastAPI { #build-a-docker-image-for-fastapi } Гаразд, зберімо щось зараз! 🚀 -Я покажу вам, як зібрати образ Docker для FastAPI з нуля на основі офіційного образу Python. +Я покажу вам, як зібрати **образ Docker** для FastAPI **з нуля** на основі **офіційного образу Python**. -Це те, що ви захочете робити у більшості випадків, наприклад: +Це те, що ви захочете робити у **більшості випадків**, наприклад: -* Використання Kubernetes або подібних інструментів -* Під час запуску на Raspberry Pi +* Використання **Kubernetes** або подібних інструментів +* Під час запуску на **Raspberry Pi** * Використання хмарного сервісу, який запустить для вас образ контейнера тощо ### Вимоги до пакетів { #package-requirements } -Зазвичай ви маєте вимоги до пакетів для вашого застосунку в окремому файлі. +Зазвичай ви маєте **вимоги до пакетів** для вашого застосунку в окремому файлі. -Це залежить переважно від інструменту, який ви використовуєте для встановлення цих вимог. +Це залежить переважно від інструменту, який ви використовуєте для **встановлення** цих вимог. Найпоширеніший спосіб - мати файл `requirements.txt` з назвами пакетів і їхніми версіями, по одному на рядок. @@ -192,9 +192,9 @@ CMD ["fastapi", "run", "app/main.py", "--port", "80"] 3. Скопіюйте файл з вимогами в директорію `/code`. - Спочатку скопіюйте лише файл з вимогами, а не решту коду. + Спочатку скопіюйте **лише** файл з вимогами, а не решту коду. - Оскільки цей файл змінюється нечасто, Docker виявить це і використає кеш для цього кроку, що також увімкне кеш і для наступного кроку. + Оскільки цей файл **змінюється нечасто**, Docker виявить це і використає **кеш** для цього кроку, що також увімкне кеш і для наступного кроку. 4. Встановіть залежності пакетів із файлу вимог. @@ -208,21 +208,21 @@ CMD ["fastapi", "run", "app/main.py", "--port", "80"] Опція `--upgrade` каже `pip` оновити пакети, якщо вони вже встановлені. - Оскільки попередній крок копіювання файлу може бути виявлений кешем Docker, цей крок також використовуватиме кеш Docker, коли це можливо. + Оскільки попередній крок копіювання файлу може бути виявлений **кешем Docker**, цей крок також **використовуватиме кеш Docker**, коли це можливо. - Використання кешу на цьому кроці збереже вам багато часу під час повторних збірок образу в розробці, замість того щоб завжди завантажувати і встановлювати всі залежності. + Використання кешу на цьому кроці **збереже** вам багато **часу** під час повторних збірок образу в розробці, замість того щоб **завантажувати і встановлювати** всі залежності **щоразу**. 5. Скопіюйте директорію `./app` у директорію `/code`. - Оскільки тут увесь код, який змінюється найчастіше, кеш Docker не буде легко використаний для цього або будь-яких наступних кроків. + Оскільки тут увесь код, який **змінюється найчастіше**, **кеш** Docker не буде легко використаний для цього або будь-яких **наступних кроків**. - Тому важливо розмістити це ближче до кінця `Dockerfile`, щоб оптимізувати час збірки образу контейнера. + Тому важливо розмістити це **ближче до кінця** `Dockerfile`, щоб оптимізувати час збірки образу контейнера. -6. Встановіть команду для використання `fastapi run`, яка всередині використовує Uvicorn. +6. Встановіть **команду** для використання `fastapi run`, яка всередині використовує Uvicorn. `CMD` приймає список строк, кожна з яких - це те, що ви б набирали в командному рядку, розділене пробілами. - Ця команда буде виконана з поточної робочої директорії, тієї самої `/code`, яку ви вказали вище через `WORKDIR /code`. + Ця команда буде виконана з **поточної робочої директорії**, тієї самої `/code`, яку ви вказали вище через `WORKDIR /code`. /// tip | Порада @@ -232,7 +232,7 @@ CMD ["fastapi", "run", "app/main.py", "--port", "80"] /// warning | Попередження -Обов’язково завжди використовуйте exec form інструкції `CMD`, як пояснено нижче. +Обов’язково **завжди** використовуйте **exec form** інструкції `CMD`, як пояснено нижче. /// @@ -240,21 +240,21 @@ CMD ["fastapi", "run", "app/main.py", "--port", "80"] Інструкцію Docker [`CMD`](https://docs.docker.com/reference/dockerfile/#cmd) можна записати у двох формах: -✅ Exec form: +✅ **Exec** form: ```Dockerfile # ✅ Робіть так CMD ["fastapi", "run", "app/main.py", "--port", "80"] ``` -⛔️ Shell form: +⛔️ **Shell** form: ```Dockerfile # ⛔️ Не робіть так CMD fastapi run app/main.py --port 80 ``` -Обов’язково завжди використовуйте exec form, щоб FastAPI міг коректно завершувати роботу та щоб були викликані [події тривалості життя](../advanced/events.md). +Обов’язково завжди використовуйте **exec** form, щоб FastAPI міг коректно завершувати роботу та щоб були викликані [події тривалості життя](../advanced/events.md). Докладніше про це можна прочитати в [документації Docker про shell та exec form](https://docs.docker.com/reference/dockerfile/#shell-and-exec-form). @@ -283,31 +283,31 @@ CMD ["fastapi", "run", "app/main.py", "--proxy-headers", "--port", "80"] #### Кеш Docker { #docker-cache } -У цьому `Dockerfile` є важливий трюк: спочатку ми копіюємо лише файл із залежностями, а не решту коду. Ось чому. +У цьому `Dockerfile` є важливий трюк: спочатку ми копіюємо лише **файл із залежностями**, а не решту коду. Ось чому. ```Dockerfile COPY ./requirements.txt /code/requirements.txt ``` -Docker та інші інструменти збирають ці образи контейнерів інкрементально, додаючи один шар поверх іншого, починаючи з верхньої частини `Dockerfile` і додаючи будь-які файли, створені кожною інструкцією в `Dockerfile`. +Docker та інші інструменти **збирають** ці образи контейнерів **інкрементально**, додаючи **один шар поверх іншого**, починаючи з верхньої частини `Dockerfile` і додаючи будь-які файли, створені кожною інструкцією в `Dockerfile`. -Docker та подібні інструменти також використовують внутрішній кеш під час збірки образу. Якщо файл не змінювався з моменту останньої збірки, тоді він повторно використає той самий шар, створений востанє, замість копіювання файлу знову та створення нового шару з нуля. +Docker та подібні інструменти також використовують **внутрішній кеш** під час збірки образу. Якщо файл не змінювався з моменту останньої збірки, тоді він **повторно використає той самий шар**, створений востаннє, замість копіювання файлу знову та створення нового шару з нуля. -Просте уникнення копіювання файлів не обов’язково суттєво покращує ситуацію, але оскільки для цього кроку використано кеш, він може використати кеш і для наступного кроку. Наприклад, він може використати кеш для інструкції, яка встановлює залежності: +Просте уникнення копіювання файлів не обов’язково суттєво покращує ситуацію, але оскільки для цього кроку використано кеш, він може **використати кеш і для наступного кроку**. Наприклад, він може використати кеш для інструкції, яка встановлює залежності: ```Dockerfile RUN pip install --no-cache-dir --upgrade -r /code/requirements.txt ``` -Файл із вимогами до пакетів змінюватиметься нечасто. Отже, копіюючи лише цей файл, Docker зможе використати кеш для цього кроку. +Файл із вимогами до пакетів **змінюватиметься нечасто**. Отже, копіюючи лише цей файл, Docker зможе **використати кеш** для цього кроку. -А потім Docker зможе використати кеш і для наступного кроку, який завантажує та встановлює ці залежності. І саме тут ми заощаджуємо багато часу. ✨ ...і уникаємо нудного очікування. 😪😆 +А потім Docker зможе **використати кеш і для наступного кроку**, який завантажує та встановлює ці залежності. І саме тут ми **заощаджуємо багато часу**. ✨ ...і уникаємо нудного очікування. 😪😆 -Завантаження і встановлення залежностей пакетів може займати хвилини, але використання кешу займе максимум секунди. +Завантаження і встановлення залежностей пакетів **може займати хвилини**, але використання **кешу** займе **максимум секунди**. І оскільки ви збиратимете образ контейнера знову і знову під час розробки, щоб перевіряти, що зміни у вашому коді працюють, це заощадить багато накопиченого часу. -Потім, ближче до кінця `Dockerfile`, ми копіюємо весь код. Оскільки це те, що змінюється найчастіше, ми розміщуємо це ближче до кінця, адже майже завжди все після цього кроку не зможе використати кеш. +Потім, ближче до кінця `Dockerfile`, ми копіюємо весь код. Оскільки це те, що **змінюється найчастіше**, ми розміщуємо це ближче до кінця, адже майже завжди все після цього кроку не зможе використати кеш. ```Dockerfile COPY ./app /code/app @@ -415,11 +415,11 @@ CMD ["fastapi", "run", "main.py", "--port", "80"] Поговорімо знову про деякі з тих самих [Концепцій розгортання](concepts.md) у термінах контейнерів. -Контейнери - це переважно інструмент для спрощення процесу збирання та розгортання застосунку, але вони не нав’язують конкретний підхід до обробки цих концепцій розгортання, і існує кілька можливих стратегій. +Контейнери - це переважно інструмент для спрощення процесу **збирання та розгортання** застосунку, але вони не нав’язують конкретний підхід до обробки цих **концепцій розгортання**, і існує кілька можливих стратегій. -Гарна новина полягає в тому, що для кожної стратегії є спосіб покрити всі концепції розгортання. 🎉 +**Гарна новина** полягає в тому, що для кожної стратегії є спосіб покрити всі концепції розгортання. 🎉 -Розгляньмо ці концепції розгортання в контексті контейнерів: +Розгляньмо ці **концепції розгортання** в контексті контейнерів: * HTTPS * Автозапуск @@ -430,9 +430,9 @@ CMD ["fastapi", "run", "main.py", "--port", "80"] ## HTTPS { #https } -Якщо зосередитись лише на образі контейнера для застосунку FastAPI (а згодом на запущеному контейнері), HTTPS зазвичай обробляється зовнішнім іншим інструментом. +Якщо зосередитись лише на **образі контейнера** для застосунку FastAPI (а згодом на запущеному **контейнері**), HTTPS зазвичай обробляється **зовнішнім** іншим інструментом. -Це може бути інший контейнер, наприклад з [Traefik](https://traefik.io/), що обробляє HTTPS і автоматичне отримання сертифікатів. +Це може бути інший контейнер, наприклад з [Traefik](https://traefik.io/), що обробляє **HTTPS** і **автоматичне** отримання **сертифікатів**. /// tip | Порада @@ -444,57 +444,57 @@ Traefik має інтеграції з Docker, Kubernetes та іншими, т ## Автозапуск і перезапуски { #running-on-startup-and-restarts } -Зазвичай інший інструмент відповідає за запуск і виконання вашого контейнера. +Зазвичай інший інструмент відповідає за **запуск і виконання** вашого контейнера. -Це може бути безпосередньо Docker, Docker Compose, Kubernetes, хмарний сервіс тощо. +Це може бути безпосередньо **Docker**, **Docker Compose**, **Kubernetes**, **хмарний сервіс** тощо. У більшості (або всіх) випадків є проста опція, щоб увімкнути запуск контейнера при старті системи та перезапуски у разі збоїв. Наприклад, у Docker це опція командного рядка `--restart`. -Без використання контейнерів змусити застосунки запускатися при старті системи та з перезапусками може бути клопітно і складно. Але під час роботи з контейнерами у більшості випадків ця функціональність вбудована за замовчуванням. ✨ +Без використання контейнерів змусити застосунки запускатися при старті системи та з перезапусками може бути клопітно і складно. Але під час **роботи з контейнерами** у більшості випадків ця функціональність вбудована за замовчуванням. ✨ ## Реплікація - кількість процесів { #replication-number-of-processes } -Якщо у вас є кластер машин із Kubernetes, Docker Swarm Mode, Nomad або іншою подібною складною системою для керування розподіленими контейнерами на кількох машинах, тоді ви, ймовірно, захочете обробляти реплікацію на рівні кластера замість використання менеджера процесів (як-от Uvicorn з працівниками) у кожному контейнері. +Якщо у вас є кластер машин із **Kubernetes**, Docker Swarm Mode, Nomad або іншою подібною складною системою для керування розподіленими контейнерами на кількох машинах, тоді ви, ймовірно, захочете **обробляти реплікацію** на **рівні кластера** замість використання **менеджера процесів** (як-от Uvicorn з працівниками) у кожному контейнері. -Одна з таких розподілених систем керування контейнерами, як-от Kubernetes, зазвичай має інтегровані способи обробляти реплікацію контейнерів, підтримуючи водночас балансування навантаження для вхідних запитів. Усе це - на рівні кластера. +Одна з таких розподілених систем керування контейнерами, як-от Kubernetes, зазвичай має інтегровані способи обробляти **реплікацію контейнерів**, підтримуючи водночас **балансування навантаження** для вхідних запитів. Усе це - на **рівні кластера**. -У таких випадках ви, ймовірно, захочете зібрати Docker-образ з нуля, як [пояснено вище](#dockerfile), встановивши ваші залежності і запустивши один процес Uvicorn замість використання кількох працівників Uvicorn. +У таких випадках ви, ймовірно, захочете зібрати **Docker-образ з нуля**, як [пояснено вище](#dockerfile), встановивши ваші залежності і запустивши **один процес Uvicorn** замість використання кількох працівників Uvicorn. ### Балансувальник навантаження { #load-balancer } -При використанні контейнерів зазвичай є якийсь компонент, що слухає на головному порту. Це може бути інший контейнер, який також є представником з термінацією TLS для обробки HTTPS, або подібний інструмент. +При використанні контейнерів зазвичай є якийсь компонент, що **слухає на головному порту**. Це може бути інший контейнер, який також є **представником з термінацією TLS** для обробки **HTTPS**, або подібний інструмент. -Оскільки цей компонент приймає навантаження запитів і розподіляє його між працівниками (сподіваємось) збалансовано, його також часто називають балансувальником навантаження. +Оскільки цей компонент приймає **навантаження** запитів і розподіляє його між працівниками (сподіваємось) **збалансовано**, його також часто називають **балансувальником навантаження**. /// tip | Порада -Той самий компонент представника з термінацією TLS, що використовується для HTTPS, швидше за все, також буде балансувальником навантаження. +Той самий компонент **представника з термінацією TLS**, що використовується для HTTPS, швидше за все, також буде **балансувальником навантаження**. /// -І під час роботи з контейнерами та сама система, яку ви використовуєте для їх запуску і керування ними, вже матиме внутрішні інструменти для передавання мережевої комунікації (наприклад, HTTP-запитів) від цього балансувальника навантаження (який також може бути представником з термінацією TLS) до контейнерів із вашим застосунком. +І під час роботи з контейнерами та сама система, яку ви використовуєте для їх запуску і керування ними, вже матиме внутрішні інструменти для передавання **мережевої комунікації** (наприклад, HTTP-запитів) від цього **балансувальника навантаження** (який також може бути **представником з термінацією TLS**) до контейнерів із вашим застосунком. ### Один балансувальник навантаження - кілька контейнерів-працівників { #one-load-balancer-multiple-worker-containers } -Під час роботи з Kubernetes або подібними розподіленими системами керування контейнерами використання їхніх внутрішніх мережевих механізмів дозволяє єдиному балансувальнику навантаження, що слухає на головному порту, передавати комунікацію (запити) до кількох контейнерів, у яких запущено ваш застосунок. +Під час роботи з **Kubernetes** або подібними розподіленими системами керування контейнерами використання їхніх внутрішніх мережевих механізмів дозволяє єдиному **балансувальнику навантаження**, що слухає на головному **порту**, передавати комунікацію (запити) до кількох **контейнерів**, у яких запущено ваш застосунок. -Кожен з цих контейнерів із вашим застосунком зазвичай має лише один процес (наприклад, процес Uvicorn, що запускає ваш застосунок FastAPI). Усі вони будуть ідентичними контейнерами, які запускають те саме, але кожен зі своїм процесом, пам’яттю тощо. Таким чином ви використаєте переваги паралелізму на різних ядрах процесора або навіть на різних машинах. +Кожен з цих контейнерів із вашим застосунком зазвичай має **лише один процес** (наприклад, процес Uvicorn, що запускає ваш застосунок FastAPI). Усі вони будуть **ідентичними контейнерами**, які запускають те саме, але кожен зі своїм процесом, пам’яттю тощо. Таким чином ви використаєте переваги **паралелізації** на **різних ядрах** процесора або навіть на **різних машинах**. -А розподілена система контейнерів із балансувальником навантаження розподілятиме запити між кожним із контейнерів із вашим застосунком по черзі. Тож кожен запит може оброблятися одним із кількох реплікованих контейнерів, що запускають ваш застосунок. +А розподілена система контейнерів із **балансувальником навантаження** **розподілятиме запити** між кожним із контейнерів із вашим застосунком **по черзі**. Тож кожен запит може оброблятися одним із кількох **реплікованих контейнерів**, що запускають ваш застосунок. -І зазвичай цей балансувальник навантаження зможе обробляти запити, які йдуть до інших застосунків у вашому кластері (наприклад, до іншого домену або під іншим префіксом шляху URL), і передаватиме комунікацію до відповідних контейнерів для того іншого застосунку, що працює у вашому кластері. +І зазвичай цей **балансувальник навантаження** зможе обробляти запити, які йдуть до *інших* застосунків у вашому кластері (наприклад, до іншого домену або під іншим префіксом шляху URL), і передаватиме комунікацію до відповідних контейнерів для *того іншого* застосунку, що працює у вашому кластері. ### Один процес на контейнер { #one-process-per-container } -У такому сценарії ви, ймовірно, захочете мати один (Uvicorn) процес на контейнер, адже ви вже обробляєте реплікацію на рівні кластера. +У такому сценарії ви, ймовірно, захочете мати **один (Uvicorn) процес на контейнер**, адже ви вже обробляєте реплікацію на рівні кластера. -Тобто в цьому випадку ви не захочете мати кількох працівників у контейнері, наприклад через опцію командного рядка `--workers`. Ви захочете мати лише один процес Uvicorn на контейнер (але, ймовірно, кілька контейнерів). +Тобто в цьому випадку ви **не захочете** мати кількох працівників у контейнері, наприклад через опцію командного рядка `--workers`. Ви захочете мати лише **один процес Uvicorn** на контейнер (але, ймовірно, кілька контейнерів). -Наявність іншого менеджера процесів всередині контейнера (як це було б із кількома працівниками) лише додасть зайвої складності, яку, найімовірніше, ви вже вирішуєте на рівні кластера. +Наявність іншого менеджера процесів всередині контейнера (як це було б із кількома працівниками) лише додасть **зайвої складності**, яку, найімовірніше, ви вже вирішуєте на рівні кластера. -### Контейнери з кількоми процесами та особливі випадки { #containers-with-multiple-processes-and-special-cases } +### Контейнери з кількома процесами та особливі випадки { #containers-with-multiple-processes-and-special-cases } -Звісно, є особливі випадки, коли ви можете захотіти мати контейнер із кількома процесами-працівниками Uvicorn всередині. +Звісно, є **особливі випадки**, коли ви можете захотіти мати **контейнер** із кількома **процесами-працівниками Uvicorn** всередині. У таких випадках ви можете використати опцію командного рядка `--workers`, щоб задати кількість працівників, яких потрібно запустити: @@ -519,17 +519,17 @@ CMD ["fastapi", "run", "app/main.py", "--port", "80", "--workers", "4"] #### Простий застосунок { #a-simple-app } -Ви можете захотіти менеджер процесів у контейнері, якщо ваш застосунок достатньо простий, щоб запускати його на одному сервері, а не на кластері. +Ви можете захотіти менеджер процесів у контейнері, якщо ваш застосунок **достатньо простий**, щоб запускати його на **одному сервері**, а не на кластері. #### Docker Compose { #docker-compose } -Ви можете розгортати на одному сервері (не в кластері) за допомогою Docker Compose, тож у вас не буде простого способу керувати реплікацією контейнерів (у Docker Compose), зберігаючи спільну мережу та балансування навантаження. +Ви можете розгортати на **одному сервері** (не в кластері) за допомогою **Docker Compose**, тож у вас не буде простого способу керувати реплікацією контейнерів (у Docker Compose), зберігаючи спільну мережу та **балансування навантаження**. -Тоді ви можете захотіти мати один контейнер із менеджером процесів, що запускає кілька процесів-працівників всередині. +Тоді ви можете захотіти мати **один контейнер** із **менеджером процесів**, що запускає **кілька процесів-працівників** всередині. --- -Головна думка: це не правила, викарбувані в камені, яких потрібно сліпо дотримуватися. Ви можете використати ці ідеї, щоб оцінити власний кейс і вирішити, який підхід найкращий для вашої системи, розглядаючи, як керувати такими концепціями: +Головна думка: **жодне** з цього не є **правилами, викарбуваними в камені**, яких потрібно сліпо дотримуватися. Ви можете використати ці ідеї, щоб **оцінити власний кейс** і вирішити, який підхід найкращий для вашої системи, розглядаючи, як керувати такими концепціями: * Безпека - HTTPS * Автозапуск @@ -540,13 +540,13 @@ CMD ["fastapi", "run", "app/main.py", "--port", "80", "--workers", "4"] ## Пам’ять { #memory } -Якщо ви запускаєте один процес на контейнер, ви матимете більш-менш чітко визначений, стабільний і обмежений обсяг пам’яті, що споживається кожним із цих контейнерів (їх може бути більше одного, якщо вони репліковані). +Якщо ви запускаєте **один процес на контейнер**, ви матимете більш-менш чітко визначений, стабільний і обмежений обсяг пам’яті, що споживається кожним із цих контейнерів (їх може бути більше одного, якщо вони репліковані). -Потім ви можете встановити ті самі ліміти та вимоги до пам’яті у ваших конфігураціях для системи керування контейнерами (наприклад, у Kubernetes). Таким чином вона зможе реплікувати контейнери на доступних машинах, враховуючи обсяг пам’яті, потрібний їм, і обсяг доступної пам’яті на машинах у кластері. +Потім ви можете встановити ті самі ліміти та вимоги до пам’яті у ваших конфігураціях для системи керування контейнерами (наприклад, у **Kubernetes**). Таким чином вона зможе **реплікувати контейнери** на **доступних машинах**, враховуючи обсяг пам’яті, потрібний їм, і обсяг доступної пам’яті на машинах у кластері. -Якщо ваш застосунок простий, імовірно, це не буде проблемою, і вам може не знадобитися задавати жорсткі ліміти пам’яті. Але якщо ви використовуєте багато пам’яті (наприклад, із моделями машинного навчання), вам слід перевірити, скільки пам’яті ви споживаєте, і відкоригувати кількість контейнерів, що запускаються на кожній машині (і, можливо, додати більше машин у ваш кластер). +Якщо ваш застосунок **простий**, імовірно, це **не буде проблемою**, і вам може не знадобитися задавати жорсткі ліміти пам’яті. Але якщо ви **використовуєте багато пам’яті** (наприклад, із моделями **машинного навчання**), вам слід перевірити, скільки пам’яті ви споживаєте, і відкоригувати **кількість контейнерів**, що запускаються на **кожній машині** (і, можливо, додати більше машин у ваш кластер). -Якщо ви запускаєте кілька процесів на контейнер, вам потрібно переконатися, що кількість запущених процесів не споживає більше пам’яті, ніж доступно. +Якщо ви запускаєте **кілька процесів на контейнер**, вам потрібно переконатися, що кількість запущених процесів не **споживає більше пам’яті**, ніж доступно. ## Попередні кроки перед запуском і контейнери { #previous-steps-before-starting-and-containers } @@ -554,7 +554,7 @@ CMD ["fastapi", "run", "app/main.py", "--port", "80", "--workers", "4"] ### Кілька контейнерів { #multiple-containers } -Якщо у вас кілька контейнерів, імовірно кожен запускає один процес (наприклад, у кластері Kubernetes), тоді ви, ймовірно, захочете мати окремий контейнер, який виконає попередні кроки в одному контейнері, запустивши один процес, перед запуском реплікованих контейнерів-працівників. +Якщо у вас **кілька контейнерів**, імовірно кожен запускає **один процес** (наприклад, у кластері **Kubernetes**), тоді ви, ймовірно, захочете мати **окремий контейнер**, який виконає **попередні кроки** в одному контейнері, запустивши один процес, **перед** запуском реплікованих контейнерів-працівників. /// note | Примітка @@ -562,19 +562,19 @@ CMD ["fastapi", "run", "app/main.py", "--port", "80", "--workers", "4"] /// -Якщо у вашому випадку немає проблеми запускати ці попередні кроки кілька разів паралельно (наприклад, якщо ви не виконуєте міграції бази даних, а лише перевіряєте, чи база вже готова), тоді ви також можете просто помістити їх у кожен контейнер безпосередньо перед запуском головного процесу. +Якщо у вашому випадку немає проблеми запускати ці попередні кроки **кілька разів паралельно** (наприклад, якщо ви не виконуєте міграції бази даних, а лише перевіряєте, чи база вже готова), тоді ви також можете просто помістити їх у кожен контейнер безпосередньо перед запуском головного процесу. ### Один контейнер { #single-container } -Якщо у вас просте налаштування з одним контейнером, який потім запускає кілька процесів-працівників (або теж лише один процес), тоді ви можете виконати ці попередні кроки в тому ж контейнері безпосередньо перед запуском процесу із застосунком. +Якщо у вас просте налаштування з **одним контейнером**, який потім запускає кілька **процесів-працівників** (або теж лише один процес), тоді ви можете виконати ці попередні кроки в тому ж контейнері безпосередньо перед запуском процесу із застосунком. ### Базовий образ Docker { #base-docker-image } Колись існував офіційний образ Docker для FastAPI: [tiangolo/uvicorn-gunicorn-fastapi](https://github.com/tiangolo/uvicorn-gunicorn-fastapi-docker). Але зараз він застарілий. ⛔️ -Ймовірно, вам не слід використовувати цей базовий образ Docker (або будь-який інший подібний). +Ймовірно, вам **не** слід використовувати цей базовий образ Docker (або будь-який інший подібний). -Якщо ви використовуєте Kubernetes (або інші) і вже налаштовуєте реплікацію на рівні кластера з кількома контейнерами. У таких випадках краще зібрати образ з нуля, як описано вище: [Зібрати Docker-образ для FastAPI](#build-a-docker-image-for-fastapi). +Якщо ви використовуєте **Kubernetes** (або інші) і вже налаштовуєте **реплікацію** на рівні кластера з кількома **контейнерами**. У таких випадках краще **зібрати образ з нуля**, як описано вище: [Зібрати Docker-образ для FastAPI](#build-a-docker-image-for-fastapi). А якщо вам потрібно мати кілька працівників, ви можете просто використати опцію командного рядка `--workers`. @@ -592,8 +592,8 @@ CMD ["fastapi", "run", "app/main.py", "--port", "80", "--workers", "4"] Наприклад: -* З Docker Compose на одному сервері -* З кластером Kubernetes +* З **Docker Compose** на одному сервері +* З кластером **Kubernetes** * З кластером Docker Swarm Mode * З іншим інструментом, як-от Nomad * З хмарним сервісом, який бере ваш образ контейнера і розгортає його @@ -604,7 +604,7 @@ CMD ["fastapi", "run", "app/main.py", "--port", "80", "--workers", "4"] ## Підсумок { #recap } -Використовуючи системи контейнерів (наприклад, з Docker і Kubernetes), досить просто обробляти всі концепції розгортання: +Використовуючи системи контейнерів (наприклад, з **Docker** і **Kubernetes**), досить просто обробляти всі **концепції розгортання**: * HTTPS * Автозапуск @@ -613,6 +613,6 @@ CMD ["fastapi", "run", "app/main.py", "--port", "80", "--workers", "4"] * Пам’ять * Попередні кроки перед запуском -У більшості випадків ви, ймовірно, не захочете використовувати будь-який базовий образ, а натомість зібрати образ контейнера з нуля на основі офіційного образу Python для Docker. +У більшості випадків ви, ймовірно, не захочете використовувати будь-який базовий образ, а натомість **зібрати образ контейнера з нуля** на основі офіційного образу Python для Docker. -Дотримуючись порядку інструкцій у `Dockerfile` і використовуючи кеш Docker, ви можете мінімізувати час збірки, щоб максимізувати свою продуктивність (і уникнути нудьги). 😎 +Дотримуючись **порядку** інструкцій у `Dockerfile` і використовуючи **кеш Docker**, ви можете **мінімізувати час збірки**, щоб максимізувати свою продуктивність (і уникнути нудьги). 😎 diff --git a/docs/uk/docs/deployment/https.md b/docs/uk/docs/deployment/https.md index 439adf61e..fd5471470 100644 --- a/docs/uk/docs/deployment/https.md +++ b/docs/uk/docs/deployment/https.md @@ -14,8 +14,8 @@ Тепер, з **точки зору розробника**, ось кілька речей, які варто пам'ятати, розмірковуючи про HTTPS: -* Для HTTPS **сервер** має **мати «сертифікати»**, видані **третьою стороною**. - * Насправді ці сертифікати **«отримуються»** у третьої сторони, а не **«генеруються»**. +* Для HTTPS **сервер** має **мати «сертифікати»**, згенеровані **третьою стороною**. + * Насправді ці сертифікати **«отримуються»** у третьої сторони, а не **«згенеровані»**. * Сертифікати мають **строк дії**. * Їхній строк дії **спливає**. * І тоді їх потрібно **поновити**, **знову отримавши** у третьої сторони. @@ -190,15 +190,15 @@ TLS Termination Proxy використає узгоджене шифруванн Увесь цей процес поновлення, паралельно з обслуговуванням застосунку, - одна з головних причин, чому ви можете захотіти мати **окрему систему для обробки HTTPS** за допомогою TLS Termination Proxy замість того, щоб просто використовувати сертифікати TLS безпосередньо з сервером застосунку (наприклад, Uvicorn). -## Направлені заголовки проксі { #proxy-forwarded-headers } +## Направлені заголовки представника { #proxy-forwarded-headers } -Коли ви використовуєте проксі для обробки HTTPS, ваш **сервер застосунку** (наприклад, Uvicorn через FastAPI CLI) нічого не знає про процес HTTPS, він спілкується звичайним HTTP із **TLS Termination Proxy**. +Коли ви використовуєте представника для обробки HTTPS, ваш **сервер застосунку** (наприклад, Uvicorn через FastAPI CLI) нічого не знає про процес HTTPS, він спілкується звичайним HTTP із **TLS Termination Proxy**. -Цей **проксі** зазвичай динамічно встановлює деякі HTTP-заголовки перед передачею запиту **серверу застосунку**, щоб дати йому знати, що запит **направляється** проксі. +Цей **представник** зазвичай динамічно встановлює деякі HTTP-заголовки перед передачею запиту **серверу застосунку**, щоб дати йому знати, що запит **направляється** представником. /// note | Технічні деталі -Заголовки проксі: +Заголовки представника: * [X-Forwarded-For](https://developer.mozilla.org/en-US/docs/Web/HTTP/Reference/Headers/X-Forwarded-For) * [X-Forwarded-Proto](https://developer.mozilla.org/en-US/docs/Web/HTTP/Reference/Headers/X-Forwarded-Proto) @@ -206,11 +206,11 @@ TLS Termination Proxy використає узгоджене шифруванн /// -Втім, оскільки **сервер застосунку** не знає, що він стоїть за довіреним **проксі**, за замовчуванням він не довірятиме цим заголовкам. +Втім, оскільки **сервер застосунку** не знає, що він стоїть за довіреним **представником**, за замовчуванням він не довірятиме цим заголовкам. -Але ви можете налаштувати **сервер застосунку**, щоб довіряти направленим заголовкам, надісланим **проксі**. Якщо ви використовуєте FastAPI CLI, ви можете скористатися курсивною *опцією CLI* `--forwarded-allow-ips`, щоб повідомити, з яких IP-адрес слід довіряти цим направленим заголовкам. +Але ви можете налаштувати **сервер застосунку**, щоб довіряти *направленим* заголовкам, надісланим **представником**. Якщо ви використовуєте FastAPI CLI, ви можете скористатися *опцією CLI* `--forwarded-allow-ips`, щоб повідомити, з яких IP-адрес слід довіряти цим *направленим* заголовкам. -Наприклад, якщо **сервер застосунку** отримує комунікацію лише від довіреного **проксі**, ви можете встановити `--forwarded-allow-ips="*"`, щоб довіряти всім вхідним IP-адресам, оскільки він отримуватиме запити лише з тієї IP-адреси, яку використовує **проксі**. +Наприклад, якщо **сервер застосунку** отримує комунікацію лише від довіреного **представника**, ви можете встановити `--forwarded-allow-ips="*"`, щоб довіряти всім вхідним IP-адресам, оскільки він отримуватиме запити лише з тієї IP-адреси, яку використовує **представник**. Так застосунок зможе знати свою публічну URL-адресу, чи використовує він HTTPS, домен тощо. @@ -218,7 +218,7 @@ TLS Termination Proxy використає узгоджене шифруванн /// tip | Порада -Ви можете дізнатися більше про це в документації [За проксі - Увімкнути направлені заголовки проксі](../advanced/behind-a-proxy.md#enable-proxy-forwarded-headers) +Ви можете дізнатися більше про це в документації [За представником - Увімкнути направлені заголовки представника](../advanced/behind-a-proxy.md#enable-proxy-forwarded-headers) /// diff --git a/docs/uk/docs/deployment/manually.md b/docs/uk/docs/deployment/manually.md index 9a6507403..6692efd56 100644 --- a/docs/uk/docs/deployment/manually.md +++ b/docs/uk/docs/deployment/manually.md @@ -40,7 +40,7 @@ $ fastapi run @@ -142,7 +142,7 @@ Uvicorn та інші сервери підтримують опцію `--reload ## Концепції розгортання { #deployment-concepts } -Ці приклади запускають серверну програму (наприклад, Uvicorn), піднімаючи один процес, що слухає всі IP (`0.0.0.0`) на визначеному порту (наприклад, `80`). +Ці приклади запускають серверну програму (наприклад, Uvicorn), піднімаючи **один процес**, що слухає всі IP (`0.0.0.0`) на визначеному порту (наприклад, `80`). Це базова ідея. Але, ймовірно, вам знадобиться подбати ще про таке: diff --git a/docs/uk/docs/editor-support.md b/docs/uk/docs/editor-support.md index f0edf6297..cc4c2ccb7 100644 --- a/docs/uk/docs/editor-support.md +++ b/docs/uk/docs/editor-support.md @@ -1,5 +1,6 @@ # Підтримка редакторів { #editor-support } + Офіційне [FastAPI Extension](https://marketplace.visualstudio.com/items?itemName=FastAPILabs.fastapi-vscode) покращує ваш робочий процес розробки FastAPI завдяки виявленню й навігації по *операціях шляху*, а також розгортанню у FastAPI Cloud і потоковому передаванню журналів у реальному часі. Докладніше про розширення дивіться у README в [репозиторії GitHub](https://github.com/fastapi/fastapi-vscode). diff --git a/docs/uk/docs/environment-variables.md b/docs/uk/docs/environment-variables.md index 7b5223bc2..95c142c7c 100644 --- a/docs/uk/docs/environment-variables.md +++ b/docs/uk/docs/environment-variables.md @@ -6,13 +6,13 @@ /// -Змінна оточення (також відома як «env var») - це змінна, що існує поза кодом Python, в операційній системі, і може бути прочитана вашим кодом Python (а також іншими програмами). +Змінна оточення (також відома як «**env var**») - це змінна, що існує **поза** кодом Python, в **операційній системі**, і може бути прочитана вашим кодом Python (а також іншими програмами). -Змінні оточення корисні для роботи з налаштуваннями застосунку, як частина встановлення Python тощо. +Змінні оточення корисні для роботи з **налаштуваннями** застосунку, як частина **встановлення** Python тощо. ## Створення і використання змінних оточення { #create-and-use-env-vars } -Ви можете створювати і використовувати змінні оточення в оболонці (терміналі) без участі Python: +Ви можете **створювати** і використовувати змінні оточення в **оболонці (терміналі)** без участі Python: //// tab | Linux, macOS, Windows Bash @@ -52,7 +52,7 @@ Hello Wade Wilson ## Читання змінних оточення в Python { #read-env-vars-in-python } -Ви також можете створити змінні оточення поза Python, у терміналі (або будь-яким іншим способом), а потім зчитати їх у Python. +Ви також можете створити змінні оточення **поза** Python, у терміналі (або будь-яким іншим способом), а потім **зчитати їх у Python**. Наприклад, у вас може бути файл `main.py` з: @@ -127,9 +127,9 @@ Hello Wade Wilson from Python //// -Оскільки змінні оточення можна встановлювати поза кодом, але читати в коді, і їх не потрібно зберігати (фіксувати у `git`) разом з іншими файлами, їх часто використовують для конфігурацій або налаштувань. +Оскільки змінні оточення можна встановлювати поза кодом, але читати в коді, і їх не потрібно зберігати (фіксувати у `git`) разом з іншими файлами, їх часто використовують для конфігурацій або **налаштувань**. -Ви також можете створити змінну оточення лише для конкретного запуску програми, вона буде доступна тільки цій програмі і лише на час її виконання. +Ви також можете створити змінну оточення лише для **конкретного запуску програми**, вона буде доступна тільки цій програмі і лише на час її виконання. Щоб зробити це, створіть її безпосередньо перед командою запуску програми, в тому самому рядку: @@ -159,15 +159,15 @@ Hello World from Python ## Типи і перевірка { #types-and-validation } -Ці змінні оточення можуть містити лише текстові строки, оскільки вони зовнішні щодо Python і мають бути сумісними з іншими програмами та рештою системи (і навіть з різними операційними системами, як-от Linux, Windows, macOS). +Ці змінні оточення можуть містити лише **текстові строки**, оскільки вони зовнішні щодо Python і мають бути сумісними з іншими програмами та рештою системи (і навіть з різними операційними системами, як-от Linux, Windows, macOS). -Це означає, що будь-яке значення, прочитане в Python зі змінної оточення, буде `str`, а будь-яке перетворення до іншого типу або будь-яка перевірка має виконуватися в коді. +Це означає, що **будь-яке значення**, прочитане в Python зі змінної оточення, **буде `str`**, а будь-яке перетворення до іншого типу або будь-яка перевірка має виконуватися в коді. -Ви дізнаєтеся більше про використання змінних оточення для роботи з налаштуваннями застосунку в розділі [Просунутий посібник користувача - Налаштування і змінні оточення](./advanced/settings.md). +Ви дізнаєтеся більше про використання змінних оточення для роботи з **налаштуваннями застосунку** в розділі [Просунутий посібник користувача - Налаштування і змінні оточення](./advanced/settings.md). ## Змінна оточення `PATH` { #path-environment-variable } -Є спеціальна змінна оточення `PATH`, яку використовують операційні системи (Linux, macOS, Windows) для пошуку програм для запуску. +Є **спеціальна** змінна оточення **`PATH`**, яку використовують операційні системи (Linux, macOS, Windows) для пошуку програм для запуску. Значення змінної `PATH` - це довга строка, що складається з каталогів, розділених двокрапкою `:` у Linux і macOS та крапкою з комою `;` у Windows. @@ -203,11 +203,11 @@ C:\Program Files\Python312\Scripts;C:\Program Files\Python312;C:\Windows\System3 //// -Коли ви вводите команду в терміналі, операційна система шукає програму в кожному з тих каталогів, перелічених у змінній оточення `PATH`. +Коли ви вводите **команду** в терміналі, операційна система **шукає** програму в **кожному з тих каталогів**, перелічених у змінній оточення `PATH`. -Наприклад, коли ви вводите `python` у терміналі, операційна система шукає програму з назвою `python` у першому каталозі цього списку. +Наприклад, коли ви вводите `python` у терміналі, операційна система шукає програму з назвою `python` у **першому каталозі** цього списку. -Якщо знайде, вона використає її. Інакше продовжить пошук в інших каталогах. +Якщо знайде, вона **використає її**. Інакше продовжить пошук в **інших каталогах**. ### Встановлення Python і оновлення `PATH` { #installing-python-and-updating-the-path } @@ -255,7 +255,7 @@ $ python //// tab | Linux, macOS -Система знайде програму `python` у `/opt/custompython/bin` і запустить її. +Система **знайде** програму `python` у `/opt/custompython/bin` і запустить її. Це приблизно еквівалентно введенню: @@ -271,7 +271,7 @@ $ /opt/custompython/bin/python //// tab | Windows -Система знайде програму `python` у `C:\opt\custompython\bin\python` і запустить її. +Система **знайде** програму `python` у `C:\opt\custompython\bin\python` і запустить її. Це приблизно еквівалентно введенню: @@ -289,7 +289,7 @@ $ C:\opt\custompython\bin\python ## Висновок { #conclusion } -Тепер ви маєте базове розуміння того, що таке змінні оточення і як їх використовувати в Python. +Тепер ви маєте базове розуміння того, що таке **змінні оточення** і як їх використовувати в Python. Також можна прочитати більше у [Вікіпедії про змінну оточення](https://en.wikipedia.org/wiki/Environment_variable). diff --git a/docs/uk/docs/features.md b/docs/uk/docs/features.md index 2ee24181f..3f8b0049b 100644 --- a/docs/uk/docs/features.md +++ b/docs/uk/docs/features.md @@ -6,8 +6,8 @@ ### На основі відкритих стандартів { #based-on-open-standards } -* [**OpenAPI**](https://github.com/OAI/OpenAPI-Specification) для створення API, включаючи оголошення шляхів операцій, параметрів, тіл запитів, безпеки тощо. -* Автоматична документація моделей даних за допомогою [**JSON Schema**](https://json-schema.org/) (оскільки OpenAPI базується саме на JSON Schema). +* [**OpenAPI**](https://github.com/OAI/OpenAPI-Specification) для створення API, включаючи оголошення шляхових операцій, параметрів, тіл запитів, безпеки тощо. +* Автоматична документація моделей даних за допомогою [**Схеми JSON**](https://json-schema.org/) (оскільки OpenAPI базується саме на Схемі JSON). * Розроблено на основі цих стандартів після ретельного аналізу, а не як додатковий рівень поверх основної архітектури. * Це також дає змогу використовувати автоматичну **генерацію клієнтського коду** багатьма мовами. @@ -15,9 +15,9 @@ Інтерактивна документація API та вебінтерфейси для його дослідження. Оскільки фреймворк базується на OpenAPI, є кілька варіантів, 2 з яких включені за замовчуванням. -* [**Swagger UI**](https://github.com/swagger-api/swagger-ui) — з інтерактивним дослідженням, викликом і тестуванням вашого API прямо з браузера. +* [**Swagger UI**](https://github.com/swagger-api/swagger-ui) - з інтерактивним дослідженням, викликом і тестуванням вашого API прямо з браузера. -![Swagger UI interaction](https://fastapi.tiangolo.com/img/index/index-03-swagger-02.png) +![взаємодія Swagger UI](https://fastapi.tiangolo.com/img/index/index-03-swagger-02.png) * Альтернативна документація API за допомогою [**ReDoc**](https://github.com/Rebilly/ReDoc). @@ -27,7 +27,7 @@ Усе базується на стандартних оголошеннях **типів Python** (завдяки Pydantic). Жодного нового синтаксису для вивчення. Лише стандартний сучасний Python. -Якщо вам потрібно 2-хвилинне нагадування про те, як використовувати типи Python (навіть якщо ви не використовуєте FastAPI), перегляньте короткий підручник: [Типи Python](python-types.md). +Якщо вам потрібно 2-хвилинне нагадування про те, як використовувати типи Python (навіть якщо ви не використовуєте FastAPI), перегляньте короткий навчальний посібник: [Типи Python](python-types.md). Ви пишете стандартний Python з типами: @@ -85,13 +85,13 @@ my_second_user: User = User(**second_user_data) * у [Visual Studio Code](https://code.visualstudio.com/): -![editor support](https://fastapi.tiangolo.com/img/vscode-completion.png) +![підтримка редактора](https://fastapi.tiangolo.com/img/vscode-completion.png) * у [PyCharm](https://www.jetbrains.com/pycharm/): -![editor support](https://fastapi.tiangolo.com/img/pycharm-completion.png) +![підтримка редактора](https://fastapi.tiangolo.com/img/pycharm-completion.png) -Ви отримаєте автодоповнення в коді, який раніше могли вважати навіть неможливим. Наприклад, для ключа `price` всередині JSON body (який міг бути вкладеним), що надходить із запиту. +Ви отримаєте автодоповнення в коді, який раніше могли вважати навіть неможливим. Наприклад, для ключа `price` всередині тіла JSON (яке могло бути вкладеним), що надходить із запиту. Більше не доведеться вводити неправильні назви ключів, постійно повертатися до документації або прокручувати вгору-вниз, щоб знайти, чи ви зрештою використали `username` чи `user_name`. @@ -106,7 +106,7 @@ FastAPI має розумні **налаштування за замовчува * Підтримка валідації для більшості (або всіх?) **типів даних Python**, зокрема: * JSON-об'єктів (`dict`). * JSON-масивів (`list`) із визначенням типів елементів. - * Полів-рядків (`str`) із визначенням мінімальної та максимальної довжини. + * Полів-строк (`str`) із визначенням мінімальної та максимальної довжини. * Чисел (`int`, `float`) з мінімальними та максимальними значеннями тощо. * Валідація для більш екзотичних типів, як-от: @@ -124,30 +124,30 @@ FastAPI має розумні **налаштування за замовчува Підтримуються всі схеми безпеки, визначені в OpenAPI, включно з: * HTTP Basic. -* **OAuth2** (також із підтримкою **JWT tokens**). Перегляньте підручник: [OAuth2 із JWT](tutorial/security/oauth2-jwt.md). +* **OAuth2** (також із підтримкою **JWT tokens**). Перегляньте навчальний посібник: [OAuth2 із JWT](tutorial/security/oauth2-jwt.md). * Ключі API в: * Заголовках. * Параметрах запиту. - * Cookies тощо. + * Кукі тощо. -А також усі можливості безпеки від Starlette (зокрема **session cookies**). +А також усі можливості безпеки від Starlette (зокрема **сесійні кукі**). Усе це зроблено як багаторазові інструменти та компоненти, які легко інтегруються з вашими системами, сховищами даних, реляційними та NoSQL базами даних тощо. ### Впровадження залежностей { #dependency-injection } -FastAPI містить надзвичайно просту у використанні, але надзвичайно потужну систему Впровадження залежностей. +FastAPI містить надзвичайно просту у використанні, але надзвичайно потужну систему Впровадження залежностей. * Навіть залежності можуть мати власні залежності, утворюючи ієрархію або **«граф» залежностей**. * Усе **автоматично обробляється** фреймворком. * Усі залежності можуть вимагати дані із запитів і **розширювати обмеження операції шляху** та автоматичну документацію. -* **Автоматична валідація** навіть для *операції шляху*, визначених у залежностях. +* **Автоматична валідація** навіть для параметрів *операції шляху*, визначених у залежностях. * Підтримка складних систем автентифікації користувачів, **підключень до баз даних** тощо. * **Жодних компромісів** із базами даних, фронтендами тощо. Але проста інтеграція з усіма ними. ### Необмежені «плагіни» { #unlimited-plug-ins } -Інакше кажучи, вони не потрібні — імпортуйте та використовуйте код, який вам потрібен. +Інакше кажучи, вони не потрібні - імпортуйте та використовуйте код, який вам потрібен. Будь-яка інтеграція спроєктована так, щоб її було дуже просто використовувати (із залежностями), тож ви можете створити «плагін» для свого застосунку у 2 рядках коду, використовуючи ту саму структуру та синтаксис, що й для ваших *операцій шляху*. @@ -163,15 +163,15 @@ FastAPI містить надзвичайно просту у використа `FastAPI` фактично є підкласом `Starlette`. Тому, якщо ви вже знайомі зі Starlette або використовуєте його, більшість функціональності працюватиме так само. -З **FastAPI** ви отримуєте всі можливості **Starlette** (адже FastAPI — це просто Starlette на стероїдах): +З **FastAPI** ви отримуєте всі можливості **Starlette** (адже FastAPI - це просто Starlette на стероїдах): * Разюча продуктивність. Це [один із найшвидших доступних Python-фреймворків, на рівні з **NodeJS** і **Go**](https://github.com/encode/starlette#performance). * Підтримка **WebSocket**. * Фонові задачі у процесі. -* Події запуску та завершення роботи. +* Події запуску та вимкнення. * Клієнт для тестування, побудований на HTTPX. * Підтримка **CORS**, **GZip**, статичних файлів, потокових відповідей. -* Підтримка **сесій** і **cookie**. +* Підтримка **сесій і кукі**. * 100% покриття тестами. * 100% анотована типами кодова база. @@ -183,7 +183,7 @@ FastAPI містить надзвичайно просту у використа Це також означає, що в багатьох випадках ви можете передати той самий об'єкт, який отримуєте із запиту, **безпосередньо в базу даних**, оскільки все автоматично перевіряється. -Те саме застосовується й у зворотному напрямку — у багатьох випадках ви можете просто передати об'єкт, який отримуєте з бази даних, **безпосередньо клієнту**. +Те саме застосовується й у зворотному напрямку - у багатьох випадках ви можете просто передати об'єкт, який отримуєте з бази даних, **безпосередньо клієнту**. З **FastAPI** ви отримуєте всі можливості **Pydantic** (адже FastAPI базується на Pydantic для обробки всіх даних): @@ -193,8 +193,8 @@ FastAPI містить надзвичайно просту у використа * Легко працює з вашим **IDE/linter/мозком**: * Оскільки структури даних pydantic є просто екземплярами класів, які ви визначаєте; автодоповнення, лінтинг, mypy і ваша інтуїція повинні добре працювати з вашими перевіреними даними. * Валідує **складні структури**: - * Використання ієрархічних моделей Pydantic, Python `typing`’s `List` і `Dict` тощо. - * Валідатори дають змогу складні схеми даних чітко й просто визначати, перевіряти й документувати як JSON Schema. + * Використання ієрархічних моделей Pydantic, `List` і `Dict` з Python `typing` тощо. + * Валідатори дають змогу складні схеми даних чітко й просто визначати, перевіряти й документувати як Схему JSON. * Ви можете мати глибоко **вкладені JSON** об'єкти, і всі вони будуть валідовані та анотовані. * **Розширюваність**: * Pydantic дозволяє визначати користувацькі типи даних або ви можете розширити валідацію методами в моделі, позначеними декоратором validator. diff --git a/docs/uk/docs/help-fastapi.md b/docs/uk/docs/help-fastapi.md index e093bdece..fe1b35c47 100644 --- a/docs/uk/docs/help-fastapi.md +++ b/docs/uk/docs/help-fastapi.md @@ -6,7 +6,7 @@ ## Підпишіться на розсилку { #subscribe-to-the-newsletter } -Ви можете підписатися на (нечасту) розсилку [**FastAPI and friends**](newsletter.md), щоб бути в курсі: +Ви можете підписатися на (нечасту) [розсилку **FastAPI and friends**](newsletter.md), щоб бути в курсі: * Новин про FastAPI та друзів 🚀 * Посібників 📝 diff --git a/docs/uk/docs/how-to/configure-swagger-ui.md b/docs/uk/docs/how-to/configure-swagger-ui.md index 5fe47d12e..2322c67bc 100644 --- a/docs/uk/docs/how-to/configure-swagger-ui.md +++ b/docs/uk/docs/how-to/configure-swagger-ui.md @@ -67,4 +67,4 @@ presets: [ Це об’єкти **JavaScript**, а не строки, тому ви не можете передати їх безпосередньо з коду Python. -Якщо вам потрібно використати такі налаштування лише для JavaScript, скористайтеся одним із методів вище. Повністю перепишіть операцію шляху Swagger UI та вручну напишіть потрібний JavaScript. +Якщо вам потрібно використати такі налаштування лише для JavaScript, скористайтеся одним із методів вище. Повністю перепишіть *операцію шляху* Swagger UI та вручну напишіть потрібний JavaScript. diff --git a/docs/uk/docs/how-to/custom-request-and-route.md b/docs/uk/docs/how-to/custom-request-and-route.md index 6a46b5723..f45fc1eea 100644 --- a/docs/uk/docs/how-to/custom-request-and-route.md +++ b/docs/uk/docs/how-to/custom-request-and-route.md @@ -18,9 +18,9 @@ Деякі варіанти використання: -- Перетворення не-JSON тіл запитів на JSON (наприклад, [`msgpack`](https://msgpack.org/index.html)). -- Розпакування тіл запитів, стиснених gzip. -- Автоматичне логування всіх тіл запитів. +* Перетворення не-JSON тіл запитів на JSON (наприклад, [`msgpack`](https://msgpack.org/index.html)). +* Розпакування тіл запитів, стиснених gzip. +* Автоматичне логування всіх тіл запитів. ## Обробка користувацьких кодувань тіла запиту { #handling-custom-request-body-encodings } @@ -76,7 +76,7 @@ Після цього вся логіка обробки залишається тією самою. -А завдяки змінам у `GzipRequest.body` тіло запиту за потреби буде автоматично розпаковане під час завантаження **FastAPI**. +Але завдяки змінам у `GzipRequest.body` тіло запиту за потреби буде автоматично розпаковане, коли **FastAPI** завантажуватиме його. ## Доступ до тіла запиту в обробнику виключень { #accessing-the-request-body-in-an-exception-handler } diff --git a/docs/uk/docs/how-to/graphql.md b/docs/uk/docs/how-to/graphql.md index c070c7e0c..91fa3619d 100644 --- a/docs/uk/docs/how-to/graphql.md +++ b/docs/uk/docs/how-to/graphql.md @@ -1,22 +1,22 @@ # GraphQL { #graphql } -Оскільки FastAPI базується на стандарті ASGI, дуже просто інтегрувати будь-яку бібліотеку GraphQL, сумісну з ASGI. +Оскільки **FastAPI** базується на стандарті **ASGI**, дуже просто інтегрувати будь-яку бібліотеку **GraphQL**, сумісну з ASGI. Ви можете поєднувати звичайні *операції шляху* FastAPI з GraphQL в одному застосунку. /// tip | Порада -GraphQL розв’язує деякі дуже специфічні сценарії використання. +**GraphQL** розв’язує деякі дуже специфічні сценарії використання. -Порівняно зі звичайними веб-API він має переваги та недоліки. +Порівняно зі звичайними **веб-API** він має **переваги** та **недоліки**. -Переконайтеся, що переваги для вашого випадку використання переважають недоліки. 🤓 +Переконайтеся, що **переваги** для вашого випадку використання переважають **недоліки**. 🤓 /// ## Бібліотеки GraphQL { #graphql-libraries } -Ось деякі бібліотеки GraphQL з підтримкою ASGI. Ви можете використовувати їх із FastAPI: +Ось деякі бібліотеки **GraphQL** з підтримкою **ASGI**. Ви можете використовувати їх із **FastAPI**: * [Strawberry](https://strawberry.rocks/) 🍓 * З [документацією для FastAPI](https://strawberry.rocks/docs/integrations/fastapi) @@ -29,23 +29,23 @@ GraphQL розв’язує деякі дуже специфічні сцена ## GraphQL зі Strawberry { #graphql-with-strawberry } -Якщо вам потрібен або ви хочете використовувати GraphQL, [Strawberry](https://strawberry.rocks/) - рекомендована бібліотека, адже її дизайн найближчий до дизайну FastAPI; усе базується на анотаціях типів. +Якщо вам потрібен або ви хочете використовувати **GraphQL**, [**Strawberry**](https://strawberry.rocks/) - **рекомендована** бібліотека, адже її дизайн найближчий до дизайну **FastAPI**; усе базується на **анотаціях типів**. -Залежно від вашого сценарію використання ви можете надати перевагу іншій бібліотеці, але якби ви запитали мене, я, ймовірно, порадив би спробувати Strawberry. +Залежно від вашого сценарію використання ви можете надати перевагу іншій бібліотеці, але якби ви запитали мене, я, ймовірно, порадив би спробувати **Strawberry**. -Ось невеликий приклад того, як інтегрувати Strawberry з FastAPI: +Ось невеликий попередній перегляд того, як ви могли б інтегрувати Strawberry з FastAPI: {* ../../docs_src/graphql_/tutorial001_py310.py hl[3,22,25] *} Більше про Strawberry ви можете дізнатися в [документації Strawberry](https://strawberry.rocks/). -І також [документацію про Strawberry з FastAPI](https://strawberry.rocks/docs/integrations/fastapi). +І також документацію про [Strawberry з FastAPI](https://strawberry.rocks/docs/integrations/fastapi). ## Застарілий `GraphQLApp` зі Starlette { #older-graphqlapp-from-starlette } Попередні версії Starlette містили клас `GraphQLApp` для інтеграції з [Graphene](https://graphene-python.org/). -Його вилучено з Starlette як застарілий, але якщо у вас є код, що його використовував, ви можете легко мігрувати на [starlette-graphene3](https://github.com/ciscorn/starlette-graphene3), який покриває той самий сценарій використання та має майже ідентичний інтерфейс. +Його було оголошено застарілим у Starlette, але якщо у вас є код, що його використовував, ви можете легко **мігрувати** на [starlette-graphene3](https://github.com/ciscorn/starlette-graphene3), який покриває той самий сценарій використання та має **майже ідентичний інтерфейс**. /// tip | Порада @@ -55,6 +55,6 @@ GraphQL розв’язує деякі дуже специфічні сцена ## Дізнайтеся більше { #learn-more } -Ви можете дізнатися більше про GraphQL в [офіційній документації GraphQL](https://graphql.org/). +Ви можете дізнатися більше про **GraphQL** в [офіційній документації GraphQL](https://graphql.org/). -Також ви можете почитати більше про кожну з цих бібліотек за наведеними посиланнями. +Також ви можете почитати більше про кожну з цих бібліотек, описаних вище, за наведеними посиланнями. diff --git a/docs/uk/docs/how-to/migrate-from-pydantic-v1-to-pydantic-v2.md b/docs/uk/docs/how-to/migrate-from-pydantic-v1-to-pydantic-v2.md index c5519b98d..7f71df245 100644 --- a/docs/uk/docs/how-to/migrate-from-pydantic-v1-to-pydantic-v2.md +++ b/docs/uk/docs/how-to/migrate-from-pydantic-v1-to-pydantic-v2.md @@ -8,9 +8,11 @@ FastAPI версії 0.119.0 запровадив часткову підтри FastAPI 0.126.0 припинив підтримку Pydantic v1, водночас ще певний час підтримував `pydantic.v1`. +FastAPI 0.128.0 також припинив підтримку `pydantic.v1`, тому найновіші версії FastAPI вимагають Pydantic v2. + /// warning | Попередження -Команда Pydantic припинила підтримку Pydantic v1 для останніх версій Python, починаючи з Python 3.14. +Команда Pydantic припинила підтримку Pydantic v1 для останніх версій Python, починаючи з **Python 3.14**. Це стосується і `pydantic.v1`, який більше не підтримується в Python 3.14 і новіших. @@ -18,7 +20,7 @@ FastAPI 0.126.0 припинив підтримку Pydantic v1, водноча /// -Якщо у вас стара програма FastAPI з Pydantic v1, нижче я покажу, як мігрувати на Pydantic v2, а також можливості FastAPI 0.119.0, які допоможуть з поступовою міграцією. +Якщо у вас стара програма FastAPI з Pydantic v1, нижче я покажу, як мігрувати на Pydantic v2, а також **можливості FastAPI 0.119.0**, які допоможуть з поступовою міграцією. ## Офіційний посібник { #official-guide } @@ -54,6 +56,16 @@ Pydantic v2 містить усе з Pydantic v1 як підмодуль `pydant ### Підтримка FastAPI для Pydantic v1 у v2 { #fastapi-support-for-pydantic-v1-in-v2 } +/// warning | Попередження + +Цю підтримку FastAPI для моделей `pydantic.v1` було додано у **FastAPI 0.119.0** і видалено у **FastAPI 0.128.0**. Вона була задумана як тимчасова допомога для міграції на Pydantic v2. + +У поточних версіях FastAPI використання моделі `pydantic.v1` у вашій програмі спричинить помилку. + +Решта цього розділу описує тимчасову підтримку, доступну лише в тих старіших версіях. + +/// + Починаючи з FastAPI 0.119.0, також є часткова підтримка Pydantic v1 всередині Pydantic v2, щоб спростити перехід на v2. Тож ви можете оновити Pydantic до останньої версії 2 і змінити імпорти на використання підмодуля `pydantic.v1`, і в багатьох випадках усе просто запрацює. @@ -122,6 +134,12 @@ graph TB ### Покрокова міграція { #migrate-in-steps } +/// warning | Попередження + +Поступова міграція з використанням моделей Pydantic v1 і v2 в одній програмі, описана нижче, працює лише у **FastAPI 0.119.0 до 0.127.x**. Її було видалено у **FastAPI 0.128.0**, найновіші версії вимагають моделей **Pydantic v2**. + +/// + /// tip | Порада Спершу спробуйте `bump-pydantic`: якщо ваші тести проходять і все працює - ви впоралися однією командою. ✨ diff --git a/docs/uk/docs/how-to/separate-openapi-schemas.md b/docs/uk/docs/how-to/separate-openapi-schemas.md index 3903aac7f..3e9baead6 100644 --- a/docs/uk/docs/how-to/separate-openapi-schemas.md +++ b/docs/uk/docs/how-to/separate-openapi-schemas.md @@ -2,7 +2,7 @@ Відколи вийшов **Pydantic v2**, згенерований OpenAPI став трохи точнішим і більш **коректним**, ніж раніше. 😎 -Насправді подекуди буде навіть **дві схеми JSON** в OpenAPI для тієї самої моделі Pydantic: для введення та для виведення - залежно від наявності значень за замовчуванням. +Насправді подекуди буде навіть **дві Схеми JSON** в OpenAPI для тієї самої моделі Pydantic: для введення та для виведення - залежно від наявності **значень за замовчуванням**. Розгляньмо, як це працює, і як це змінити за потреби. @@ -18,7 +18,7 @@ {* ../../docs_src/separate_openapi_schemas/tutorial001_py310.py ln[1:15] hl[14] *} -…тоді поле `description` не буде обов'язковим, адже воно має значення за замовчуванням `None`. +…тоді поле `description` **не буде обов'язковим**. Адже воно має значення за замовчуванням `None`. ### Модель для введення в документації { #input-model-in-docs } @@ -34,7 +34,7 @@ {* ../../docs_src/separate_openapi_schemas/tutorial001_py310.py hl[19] *} -…тоді, оскільки `description` має значення за замовчуванням, якщо ви нічого не повернете для цього поля, воно все одно матиме це **значення за замовчуванням**. +…тоді, оскільки `description` має значення за замовчуванням, якщо ви **нічого не повернете** для цього поля, воно все одно матиме це **значення за замовчуванням**. ### Модель для даних відповіді при виведенні { #model-for-output-response-data } @@ -51,12 +51,13 @@ У OpenAPI це описується тим, що поле позначається як **обов'язкове**, адже воно завжди присутнє. Тому Схема JSON для моделі може відрізнятися залежно від того, чи використовується вона для **введення або виведення**: -- для **введення** `description` не буде обов'язковим -- для **виведення** воно буде **обов'язковим** (і можливо `None`, або в термінах JSON - `null`) + +* для **введення** `description` **не буде обов'язковим** +* для **виведення** воно буде **обов'язковим** (і можливо `None`, або в термінах JSON - `null`) ### Модель для виведення в документації { #model-for-output-in-docs } -У документації ви також можете перевірити модель для виведення: **і** `name`, і `description` позначені як **обов'язкові** червоною зірочкою: +У документації ви також можете перевірити модель для виведення: **і** `name`, і `description` позначені як **обов'язкові** **червоною зірочкою**:
diff --git a/docs/uk/docs/index.md b/docs/uk/docs/index.md index bcc429c7e..fe7d111d7 100644 --- a/docs/uk/docs/index.md +++ b/docs/uk/docs/index.md @@ -49,7 +49,7 @@ FastAPI - це сучасний, швидкий (високопродуктив * **Простий**: спроєктований так, щоб бути простим у використанні та вивченні. Менше часу на читання документації. * **Короткий**: мінімізує дублювання коду. Кілька можливостей з кожного оголошення параметра. Менше помилок. * **Надійний**: ви отримуєте код, готовий до продакшну. З автоматичною інтерактивною документацією. -* **Заснований на стандартах**: базується на (і повністю сумісний з) відкритими стандартами для API: [OpenAPI](https://github.com/OAI/OpenAPI-Specification) (раніше відомий як Swagger) та [JSON Schema](https://json-schema.org/). +* **Заснований на стандартах**: базується на (і повністю сумісний з) відкритими стандартами для API: [OpenAPI](https://github.com/OAI/OpenAPI-Specification) (раніше відомий як Swagger) та [Схема JSON](https://json-schema.org/). * оцінка на основі тестів, проведених внутрішньою командою розробників, що створює продакшн-застосунки. @@ -105,47 +105,47 @@ FastAPI - це сучасний, швидкий (високопродуктив
-
«Я дуже часто використовую FastAPI останнім часом. Я насправді планую використовувати його для всіх ML-сервісів моєї команди в Microsoft. Деякі з них інтегруються до основного продукту Windows і деякі з продуктів Office».
-
— Kabir Khan, Microsoft (ref)
+
«Я дуже часто використовую FastAPI останнім часом. Я насправді планую використовувати його для всіх ML-сервісів моєї команди в Microsoft. Деякі з них інтегруються до основного продукту Windows і деяких продуктів Office».
+
- Kabir Khan, Microsoft (джерело)
-"_[...] I'm using **FastAPI** a ton these days. [...] I'm actually planning to use it for all of my team's **ML services at Microsoft**. Some of them are getting integrated into the core **Windows** product and some **Office** products._" +"_[...] Я дуже часто використовую **FastAPI** останнім часом. [...] Я насправді планую використовувати його для всіх **ML-сервісів моєї команди в Microsoft**. Деякі з них інтегруються до основного продукту **Windows** і деяких продуктів **Office**._" -
Kabir Khan - Microsoft (ref)
+
Kabir Khan - Microsoft (джерело)
--- -"_We adopted the **FastAPI** library to spawn a **REST** server that can be queried to obtain **predictions**. [for Ludwig]_" +"_Ми прийняли бібліотеку **FastAPI**, щоб запустити сервер **REST**, до якого можна надсилати запити для отримання **прогнозів**. [для Ludwig]_" -
Piero Molino, Yaroslav Dudin, and Sai Sumanth Miryala - Uber (ref)
+
Piero Molino, Yaroslav Dudin, and Sai Sumanth Miryala - Uber (джерело)
--- -"_**Netflix** is pleased to announce the open-source release of our **crisis management** orchestration framework: **Dispatch**! [built with **FastAPI**]_" +"_**Netflix** із задоволенням оголошує про випуск з відкритим кодом нашого фреймворку оркестрації **керування кризами**: **Dispatch**! [побудовано з **FastAPI**]_" -
Kevin Glisson, Marc Vilanova, Forest Monsen - Netflix (ref)
+
Kevin Glisson, Marc Vilanova, Forest Monsen - Netflix (джерело)
--- -"_If anyone is looking to build a production Python API, I would highly recommend **FastAPI**. It is **beautifully designed**, **simple to use** and **highly scalable**, it has become a **key component** in our API first development strategy and is driving many automations and services such as our Virtual TAC Engineer._" +"_Якщо хтось хоче створювати продакшн-API на Python, я дуже рекомендую **FastAPI**. Він **чудово спроєктований**, **простий у використанні** і **дуже масштабований**, він став **ключовим компонентом** у нашій стратегії розробки з пріоритетом API і забезпечує багато автоматизацій та сервісів, як-от наш Virtual TAC Engineer._" -
Deon Pillsbury - Cisco (ref)
+
Deon Pillsbury - Cisco (джерело)
--- @@ -239,7 +239,7 @@ async def read_item(item_id: int, q: str | None = None): **Примітка**: -Якщо ви не знаєте, перегляньте розділ _"In a hurry?"_ про [`async` та `await` у документації](https://fastapi.tiangolo.com/uk/async/#in-a-hurry). +Якщо ви не знаєте, перегляньте розділ _«Поспішаєте?»_ про [`async` та `await` у документації](https://fastapi.tiangolo.com/uk/async/#in-a-hurry). @@ -412,10 +412,10 @@ item: Item * JSON. * Параметрів шляху. * Параметрів запиту. - * Cookies. - * Headers. - * Forms. - * Files. + * Кукі. + * Заголовків. + * Форм. + * Файлів. * Перетворення вихідних даних: перетворення з даних і типів Python у мережеві дані (як JSON): * Перетворення типів Python (`str`, `int`, `float`, `bool`, `list`, тощо). * Обʼєктів `datetime`. @@ -477,10 +477,10 @@ item: Item **Попередження про спойлер**: навчальний посібник - посібник користувача містить: -* Оголошення **параметрів** з інших різних місць, як-от: **headers**, **cookies**, **form fields** та **files**. +* Оголошення **параметрів** з інших різних місць, як-от: **заголовки**, **кукі**, **поля форми** та **файли**. * Як встановлювати **обмеження валідації** як `maximum_length` або `regex`. * Дуже потужну і просту у використанні систему **Впровадження залежностей**. -* Безпеку та автентифікацію, включно з підтримкою **OAuth2** з **JWT tokens** та **HTTP Basic** auth. +* Безпеку та автентифікацію, включно з підтримкою **OAuth2** з **токенами JWT** та **базовою автентифікацією HTTP**. * Досконаліші (але однаково прості) техніки для оголошення **глибоко вкладених моделей JSON** (завдяки Pydantic). * Інтеграцію **GraphQL** з [Strawberry](https://strawberry.rocks) та іншими бібліотеками. * Багато додаткових можливостей (завдяки Starlette) як-от: @@ -518,13 +518,13 @@ CLI автоматично визначить ваш застосунок FastAP Він спрощує процес **створення**, **розгортання** та **доступу** до API з мінімальними зусиллями. -Він забезпечує той самий **developer experience** створення застосунків на FastAPI під час їх **розгортання** у хмарі. 🎉 +Він забезпечує той самий **досвід розробника** створення застосунків на FastAPI під час їх **розгортання** у хмарі. 🎉 -FastAPI Cloud - основний спонсор і джерело фінансування open source проєктів *FastAPI and friends*. ✨ +FastAPI Cloud - основний спонсор і джерело фінансування проєктів з відкритим кодом *FastAPI and friends*. ✨ #### Розгортання в інших хмарних провайдерів { #deploy-to-other-cloud-providers } -FastAPI - open source проєкт і базується на стандартах. Ви можете розгортати застосунки FastAPI в будь-якому хмарному провайдері, який ви оберете. +FastAPI - проєкт з відкритим кодом і базується на стандартах. Ви можете розгортати застосунки FastAPI в будь-якому хмарному провайдері, який ви оберете. Дотримуйтеся інструкцій вашого хмарного провайдера, щоб розгорнути застосунки FastAPI у нього. 🤓 @@ -532,7 +532,7 @@ FastAPI - open source проєкт і базується на стандарта Незалежні тести TechEmpower показують застосунки **FastAPI**, які працюють під керуванням Uvicorn, як [одні з найшвидших доступних Python-фреймворків](https://www.techempower.com/benchmarks/#section=test&runid=7464e520-0dc2-473d-bd34-dbdfd7e85911&hw=ph&test=query&l=zijzen-7), поступаючись лише Starlette та Uvicorn (які внутрішньо використовуються в FastAPI). (*) -Щоб дізнатися більше, перегляньте розділ [Benchmarks](https://fastapi.tiangolo.com/uk/benchmarks/). +Щоб дізнатися більше, перегляньте розділ [Тести продуктивності](https://fastapi.tiangolo.com/uk/benchmarks/). ## Залежності { #dependencies } diff --git a/docs/uk/docs/project-generation.md b/docs/uk/docs/project-generation.md index 6e3781740..e4e825607 100644 --- a/docs/uk/docs/project-generation.md +++ b/docs/uk/docs/project-generation.md @@ -1,5 +1,6 @@ # Шаблон Full Stack FastAPI { #full-stack-fastapi-template } + Шаблони, хоча зазвичай постачаються з певним налаштуванням, спроєктовані бути гнучкими та налаштовуваними. Це дає змогу змінювати їх і адаптувати до вимог вашого проєкту, що робить їх чудовою відправною точкою. 🏁 Ви можете використати цей шаблон для старту, адже в ньому вже виконано значну частину початкового налаштування, безпеки, роботи з базою даних і деяких кінцевих точок API. diff --git a/docs/uk/docs/python-types.md b/docs/uk/docs/python-types.md index 332d78f21..06cc67f02 100644 --- a/docs/uk/docs/python-types.md +++ b/docs/uk/docs/python-types.md @@ -2,7 +2,7 @@ Python підтримує додаткові «підказки типів» (також звані «анотаціями типів»). -Ці **«підказки типів»** або анотації — це спеціальний синтаксис, що дозволяє оголошувати тип змінної. +Ці **«підказки типів»** або анотації - це спеціальний синтаксис, що дозволяє оголошувати тип змінної. За допомогою оголошення типів для ваших змінних редактори та інструменти можуть надати вам кращу підтримку. @@ -50,7 +50,7 @@ John Doe Це буде `upper`? Чи `uppercase`? `first_uppercase`? `capitalize`? -Тоді ви спробуєте давнього друга програміста — автозаповнення редактора коду. +Тоді ви спробуєте давнього друга програміста - автозаповнення редактора коду. Ви надрукуєте перший параметр функції, `first_name`, тоді крапку (`.`), а тоді натиснете `Ctrl+Space`, щоб запустити автозаповнення. @@ -147,20 +147,20 @@ def some_function(data: Any): print(data) ``` -### Generic типи { #generic-types } +### Узагальнені типи { #generic-types } Деякі типи можуть приймати «параметри типів» у квадратних дужках, щоб визначити їх внутрішні типи. Наприклад, «list строк» буде оголошений як `list[str]`. -Ці типи, які можуть приймати параметри типів, називаються **generic типами** або **generics**. +Ці типи, які можуть приймати параметри типів, називаються **узагальненими типами** або **дженериками**. -Ви можете використовувати ті самі вбудовані типи як generics (з квадратними дужками та типами всередині): +Ви можете використовувати ті самі вбудовані типи як дженерики (з квадратними дужками та типами всередині): * `list` * `tuple` * `set` * `dict` -#### List { #list } +#### Список { #list } Наприклад, давайте визначимо змінну, яка буде `list` із `str`. @@ -176,11 +176,11 @@ def some_function(data: Any): Ці внутрішні типи в квадратних дужках називаються «параметрами типу». -У цьому випадку `str` — це параметр типу, переданий у `list`. +У цьому випадку `str` - це параметр типу, переданий у `list`. /// -Це означає: «змінна `items` — це `list`, і кожен з елементів у цьому списку — `str`». +Це означає: «змінна `items` - це `list`, і кожен з елементів у цьому списку - `str`». Зробивши це, ваш редактор може надати підтримку навіть під час обробки елементів зі списку: @@ -192,7 +192,7 @@ def some_function(data: Any): І все ж редактор знає, що це `str`, і надає підтримку для цього. -#### Tuple and Set { #tuple-and-set } +#### Кортеж і множина { #tuple-and-set } Ви повинні зробити те ж саме, щоб оголосити `tuple` і `set`: @@ -200,10 +200,10 @@ def some_function(data: Any): Це означає: -* Змінна `items_t` — це `tuple` з 3 елементами: `int`, ще `int`, та `str`. -* Змінна `items_s` — це `set`, і кожен його елемент має тип `bytes`. +* Змінна `items_t` - це `tuple` з 3 елементами: `int`, ще `int`, та `str`. +* Змінна `items_s` - це `set`, і кожен його елемент має тип `bytes`. -#### Dict { #dict } +#### Словник { #dict } Щоб оголосити `dict`, вам потрібно передати 2 параметри типу, розділені комами. @@ -215,17 +215,17 @@ def some_function(data: Any): Це означає: -* Змінна `prices` — це `dict`: +* Змінна `prices` - це `dict`: * Ключі цього `dict` мають тип `str` (скажімо, назва кожного предмета). * Значення цього `dict` мають тип `float` (скажімо, ціна кожного предмета). -#### Union { #union } +#### Об’єднання { #union } Ви можете оголосити, що змінна може бути будь-яким із **кількох типів**, наприклад `int` або `str`. Щоб визначити це, використовуйте вертикальну риску (`|`), щоб розділити обидва типи. -Це називається «union», тому що змінна може бути чимось із об’єднання цих двох множин типів. +Це називається «об’єднанням», тому що змінна може бути чимось із об’єднання цих двох множин типів. ```Python hl_lines="1" {!> ../../docs_src/python_types/tutorial008b_py310.py!} @@ -263,11 +263,11 @@ def some_function(data: Any): -Зверніть увагу, що це означає: «`one_person` — це **екземпляр** класу `Person`». +Зверніть увагу, що це означає: «`one_person` - це **екземпляр** класу `Person`». -Це не означає: «`one_person` — це **клас** з назвою `Person`». +Це не означає: «`one_person` - це **клас** з назвою `Person`». -## Pydantic моделі { #pydantic-models } +## Моделі Pydantic { #pydantic-models } [Pydantic](https://docs.pydantic.dev/) — це бібліотека Python для валідації даних. @@ -295,7 +295,7 @@ def some_function(data: Any): ## Підказки типів з анотаціями метаданих { #type-hints-with-metadata-annotations } -У Python також є можливість додавати **додаткові метадані** до цих підказок типів за допомогою `Annotated`. +У Python також є можливість додавати **додаткові метадані** до цих підказок типів за допомогою `Annotated`. Ви можете імпортувати `Annotated` з `typing`. @@ -305,7 +305,7 @@ def some_function(data: Any): Але ви можете використати це місце в `Annotated`, щоб надати **FastAPI** додаткові метадані про те, як ви хочете, щоб ваш застосунок поводився. -Важливо пам’ятати, що **перший *параметр типу***, який ви передаєте в `Annotated`, — це **фактичний тип**. Решта — це лише метадані для інших інструментів. +Важливо пам’ятати, що **перший *параметр типу***, який ви передаєте в `Annotated`, - це **фактичний тип**. Решта - це лише метадані для інших інструментів. Наразі вам просто потрібно знати, що `Annotated` існує і що це стандартний Python. 😎 @@ -335,7 +335,7 @@ def some_function(data: Any): * **Перевірки даних**: що надходять від кожного запиту: * Генерування **автоматичних помилок**, що повертаються клієнту, коли дані недійсні. * **Документування** API за допомогою OpenAPI: - * який потім використовується для автоматичної інтерактивної документації користувальницьких інтерфейсів. + * що потім використовується автоматичними інтерактивними користувацькими інтерфейсами документації. Все це може здатися абстрактним. Не хвилюйтеся. Ви побачите все це в дії в [Навчальний посібник - Посібник користувача](tutorial/index.md). diff --git a/docs/uk/docs/tutorial/bigger-applications.md b/docs/uk/docs/tutorial/bigger-applications.md index db2bf11c6..85a6c66a0 100644 --- a/docs/uk/docs/tutorial/bigger-applications.md +++ b/docs/uk/docs/tutorial/bigger-applications.md @@ -17,16 +17,16 @@ ``` . ├── app -│   ├── __init__.py -│   ├── main.py -│   ├── dependencies.py -│   └── routers -│   │ ├── __init__.py -│   │ ├── items.py -│   │ └── users.py -│   └── internal -│   ├── __init__.py -│   └── admin.py +│ ├── __init__.py +│ ├── main.py +│ ├── dependencies.py +│ └── routers +│ │ ├── __init__.py +│ │ ├── items.py +│ │ └── users.py +│ └── internal +│ ├── __init__.py +│ └── admin.py ``` /// tip | Порада @@ -382,11 +382,11 @@ from .routers.users import router {* ../../docs_src/bigger_applications/app_an_py310/main.py hl[10:11] title["app/main.py"] *} -/// note | Технічні деталі +/// note | Примітка -FastAPI зберігає оригінальний `APIRouter` і його `APIRoute` активними після включення router'а до основного застосунку. +`users.router` містить `APIRouter` всередині файлу `app/routers/users.py`. -Це означає, що користувацькі підкласи `APIRouter` і `APIRoute` і надалі братимуть участь після включення router'а. +А `items.router` містить `APIRouter` всередині файлу `app/routers/items.py`. /// @@ -394,6 +394,14 @@ FastAPI зберігає оригінальний `APIRouter` і його `APIRo Це включить усі маршрути з цього router'а як частину застосунку. +/// note | Технічні деталі + +FastAPI зберігає оригінальний `APIRouter` і його `APIRoute` активними після включення router'а до основного застосунку. + +Це означає, що користувацькі підкласи `APIRouter` і `APIRoute` і надалі братимуть участь після включення router'а. + +/// + /// tip | Порада Вам не потрібно перейматися продуктивністю під час включення router'ів. @@ -445,7 +453,7 @@ FastAPI зберігає оригінальний `APIRouter` і його `APIRo /// note | Дуже технічні деталі -Примітка: це дуже технічна деталь, яку ви, ймовірно, можете просто пропустити. +**Примітка**: це дуже технічна деталь, яку ви, ймовірно, можете **просто пропустити**. --- @@ -510,7 +518,7 @@ $ fastapi dev ## Включайте той самий router кілька разів з різними `prefix` { #include-the-same-router-multiple-times-with-different-prefix } -Ви також можете використовувати `.include_router()` кілька разів з одним і тим самим router'ом, але з різними префіксами. +Ви також можете використовувати `.include_router()` кілька разів з *тим самим* router'ом, але з різними префіксами. Це може бути корисно, наприклад, щоб публікувати той самий API під різними префіксами, наприклад `/api/v1` і `/api/latest`. diff --git a/docs/uk/docs/tutorial/body-nested-models.md b/docs/uk/docs/tutorial/body-nested-models.md index 6919d3e11..c1daaf671 100644 --- a/docs/uk/docs/tutorial/body-nested-models.md +++ b/docs/uk/docs/tutorial/body-nested-models.md @@ -27,17 +27,17 @@ my_list: list[str] Використовуйте той самий стандартний синтаксис для атрибутів моделей з внутрішніми типами. -Отже, у нашому прикладі, ми можемо зробити `tags` саме «списком рядків»: +Отже, у нашому прикладі, ми можемо зробити `tags` саме «списком строк»: {* ../../docs_src/body_nested_models/tutorial002_py310.py hl[12] *} ## Типи множин { #set-types } -Але потім ми подумали, що теги не повинні повторюватися, вони, ймовірно, повинні бути унікальними рядками. +Але потім ми подумали, що теги не повинні повторюватися, вони, ймовірно, повинні бути унікальними строками. -І Python має спеціальний тип даних для множин унікальних елементів — це `set`. +І Python має спеціальний тип даних для множин унікальних елементів - це `set`. -Тому ми можемо оголосити `tags` як множину рядків: +Тому ми можемо оголосити `tags` як множину строк: {* ../../docs_src/body_nested_models/tutorial003_py310.py hl[12] *} @@ -45,7 +45,7 @@ my_list: list[str] І коли ви будете виводити ці дані, навіть якщо джерело містить дублікати, вони будуть виведені як множина унікальних елементів. -І це буде анотовано/документовано відповідно. +І це буде анотовано / документовано відповідно. ## Вкладені моделі { #nested-models } @@ -69,7 +69,7 @@ my_list: list[str] {* ../../docs_src/body_nested_models/tutorial004_py310.py hl[18] *} -Це означатиме, що **FastAPI** очікуватиме тіло запиту такого вигляду: +Це означатиме, що **FastAPI** очікуватиме тіло, подібне до: ```JSON { @@ -85,7 +85,7 @@ my_list: list[str] } ``` -Завдяки такій декларації у **FastAPI** ви отримуєте: +Знову ж, лише завдяки такому оголошенню, з **FastAPI** ви отримуєте: * Підтримку в редакторі (автозавершення тощо), навіть для вкладених моделей * Конвертацію даних @@ -94,23 +94,23 @@ my_list: list[str] ## Спеціальні типи та валідація { #special-types-and-validation } -Окрім звичайних типів, таких як `str`, `int`, `float`, та ін. ви можете використовувати складніші типи, які наслідують `str`. +Окрім звичайних одиничних типів, таких як `str`, `int`, `float`, та ін. ви можете використовувати складніші одиничні типи, які наслідують `str`. Щоб побачити всі доступні варіанти, ознайомтеся з [Оглядом типів у Pydantic](https://docs.pydantic.dev/latest/concepts/types/). Деякі приклади будуть у наступному розділі. -Наприклад, у моделі `Image` є поле `url`, тому ми можемо оголосити його як `HttpUrl` від Pydantic замість `str`: +Наприклад, оскільки в моделі `Image` є поле `url`, ми можемо оголосити його як екземпляр `HttpUrl` від Pydantic замість `str`: {* ../../docs_src/body_nested_models/tutorial005_py310.py hl[2,8] *} -Рядок буде перевірено як дійсну URL-адресу і задокументовано в JSON Schema / OpenAPI як URL. +Строку буде перевірено як дійсну URL-адресу і задокументовано в Схемі JSON / OpenAPI як таку. ## Атрибути зі списками підмоделей { #attributes-with-lists-of-submodels } -У Pydantic ви можете використовувати моделі як підтипи для `list`, `set` тощо: +У Pydantic ви також можете використовувати моделі як підтипи для `list`, `set` тощо: {* ../../docs_src/body_nested_models/tutorial006_py310.py hl[18] *} -Це означає, що **FastAPI** буде очікувати (конвертувати, валідувати, документувати тощо) JSON тіло запиту у вигляді: +Це очікуватиме (конвертуватиме, валідуватиме, документуватиме тощо) тіло JSON у вигляді: ```JSON hl_lines="11" { @@ -150,61 +150,61 @@ my_list: list[str] /// note | Примітка -Зверніть увагу, що в моделі `Offer` є список `Item`ів, які, своєю чергою, можуть мати необов'язковий список `Image`ів. +Зверніть увагу, що `Offer` має список `Item`ів, які, своєю чергою, мають необов'язковий список `Image`ів /// ## Тіла запитів, що складаються зі списків { #bodies-of-pure-lists } -Якщо верхній рівень JSON тіла, яке ви очікуєте, є JSON `масивом` (у Python — `list`), ви можете оголосити тип у параметрі функції, як і в моделях Pydantic: +Якщо значення верхнього рівня JSON тіла, яке ви очікуєте, є JSON `array` (Python `list`), ви можете оголосити тип у параметрі функції так само, як у моделях Pydantic: ```Python images: list[Image] ``` -наприклад: +як у: {* ../../docs_src/body_nested_models/tutorial008_py310.py hl[13] *} ## Підтримка в редакторі всюди { #editor-support-everywhere } -Ви отримаєте підтримку в редакторі всюди. +І ви отримаєте підтримку в редакторі всюди. Навіть для елементів у списках: -Ви не змогли б отримати таку підтримку в редакторі, якби працювали напряму зі `dict`, а не з моделями Pydantic. +Ви не змогли б отримати таку підтримку в редакторі, якби працювали напряму зі `dict`, а не з моделями Pydantic. -Але вам не потрібно турбуватися про це: вхідні dict'и автоматично конвертуються, а вихідні дані автоматично перетворюються в JSON. +Але вам також не потрібно турбуватися про них: вхідні словники автоматично конвертуються, а вихідні дані автоматично перетворюються в JSON. ## Тіла з довільними `dict` { #bodies-of-arbitrary-dicts } Ви також можете оголосити тіло як `dict` з ключами одного типу та значеннями іншого типу. -Це корисно, якщо ви не знаєте наперед, які імена полів будуть дійсними (як у випадку з моделями Pydantic). +Таким чином, вам не потрібно наперед знати, які імена полів/атрибутів є дійсними (як це було б у випадку з моделями Pydantic). Це буде корисно, якщо ви хочете приймати ключі, які заздалегідь невідомі. --- -Це також зручно, якщо ви хочете мати ключі іншого типу (наприклад, `int`). +Інший корисний випадок - коли ви хочете мати ключі іншого типу (наприклад, `int`). -Ось що ми розглянемо далі. +Ось що ми розглянемо тут. -У цьому випадку ви можете приймати будь-який `dict`, якщо його ключі — це `int`, а значення — `float`: +У цьому випадку ви можете приймати будь-який `dict`, якщо він має ключі `int` зі значеннями `float`: {* ../../docs_src/body_nested_models/tutorial009_py310.py hl[7] *} /// tip | Порада -Майте на увазі, що в JSON тілі ключі можуть бути лише рядками (`str`). +Майте на увазі, що JSON підтримує лише `str` як ключі. -Але Pydantic автоматично конвертує дані. +Але Pydantic має автоматичну конвертацію даних. -Це означає, що навіть якщо клієнти вашого API надсилатимуть ключі у вигляді рядків, якщо вони містять цілі числа, Pydantic конвертує їх і проведе валідацію. +Це означає, що навіть якщо клієнти вашого API можуть надсилати лише строки як ключі, якщо ці строки містять цілі числа, Pydantic конвертує їх і проведе валідацію. -Тобто `dict`, який ви отримаєте як `weights`, матиме ключі типу `int` та значення типу `float`. +І `dict`, який ви отримаєте як `weights`, фактично матиме ключі типу `int` та значення типу `float`. /// @@ -212,10 +212,10 @@ images: list[Image] З **FastAPI** ви маєте максимальну гнучкість завдяки моделям Pydantic, зберігаючи при цьому код простим, коротким та елегантним. -А також отримуєте всі переваги: +Але з усіма перевагами: -* Підтримка в редакторі (автодоповнення всюди!) -* Конвертація даних (парсинг/серіалізація) +* Підтримка в редакторі (автозавершення всюди!) +* Конвертація даних (також відома як парсинг / серіалізація) * Валідація даних * Документація схем -* Автоматичне створення документації +* Автоматична документація diff --git a/docs/uk/docs/tutorial/body.md b/docs/uk/docs/tutorial/body.md index bd1a8f128..64d9af95e 100644 --- a/docs/uk/docs/tutorial/body.md +++ b/docs/uk/docs/tutorial/body.md @@ -4,7 +4,7 @@ Тіло **запиту** - це дані, надіслані клієнтом до вашого API. Тіло **відповіді** - це дані, які ваш API надсилає клієнту. -Ваш API майже завжди має надсилати тіло **відповіді**. Але клієнтам не обов’язково потрібно постійно надсилати тіла **запитів** — інколи вони лише запитують шлях, можливо з деякими параметрами запиту, але не надсилають тіло. +Ваш API майже завжди має надсилати тіло **відповіді**. Але клієнтам не обов’язково потрібно постійно надсилати тіла **запитів** - інколи вони лише запитують шлях, можливо з деякими параметрами запиту, але не надсилають тіло. Щоб оголосити тіло **запиту**, ви використовуєте [Pydantic](https://docs.pydantic.dev/) моделі з усією їх потужністю та перевагами. diff --git a/docs/uk/docs/tutorial/debugging.md b/docs/uk/docs/tutorial/debugging.md index 821b55801..4d995698c 100644 --- a/docs/uk/docs/tutorial/debugging.md +++ b/docs/uk/docs/tutorial/debugging.md @@ -1,5 +1,6 @@ # Налагодження { #debugging } + Ви можете під'єднати дебагер у вашому редакторі коду, наприклад, у Visual Studio Code або PyCharm. ## Виклик `uvicorn` { #call-uvicorn } diff --git a/docs/uk/docs/tutorial/dependencies/dependencies-with-yield.md b/docs/uk/docs/tutorial/dependencies/dependencies-with-yield.md index 348cbf25b..9642cebe0 100644 --- a/docs/uk/docs/tutorial/dependencies/dependencies-with-yield.md +++ b/docs/uk/docs/tutorial/dependencies/dependencies-with-yield.md @@ -63,7 +63,7 @@ FastAPI підтримує залежності, які виконують де Ви можете мати підзалежності та «дерева» підзалежностей будь-якого розміру і форми, і будь-яка або всі з них можуть використовувати `yield`. -**FastAPI** гарантує, що «exit code» у кожній залежності з `yield` буде виконано в правильному порядку. +**FastAPI** гарантує, що «код виходу» у кожній залежності з `yield` буде виконано в правильному порядку. Наприклад, `dependency_c` може залежати від `dependency_b`, а `dependency_b` - від `dependency_a`: @@ -194,7 +194,7 @@ participant tasks as Background tasks `Depends()` приймає параметр `scope`, який може бути: -* `"function"`: запустити залежність перед *функцією операції шляху*, що обробляє запит, завершити залежність після завершення *функції операції шляху*, але **до** того, як відповідь буде відправлена клієнту. Тобто функція залежності буде виконуватися **навколо** *функції операції **шляху***. +* `"function"`: запустити залежність перед *функцією операції шляху*, що обробляє запит, завершити залежність після завершення *функції операції шляху*, але **до** того, як відповідь буде відправлена клієнту. Тобто функція залежності буде виконуватися **навколо** ***функції** операції шляху*. * `"request"`: запустити залежність перед *функцією операції шляху*, що обробляє запит (подібно до `"function"`), але завершити **після** того, як відповідь буде відправлена клієнту. Тобто функція залежності буде виконуватися **навколо** циклу **запиту** та відповіді. Якщо не вказано, і залежність має `yield`, за замовчуванням `scope` дорівнює `"request"`. @@ -234,6 +234,7 @@ participant operation as Path Operation Залежності з `yield` еволюціонували з часом, щоб покрити різні сценарії та виправити деякі проблеми. Якщо ви хочете дізнатися, що змінювалося в різних версіях FastAPI, прочитайте про це в просунутому посібнику користувача: [Розширені залежності - Залежності з `yield`, `HTTPException`, `except` і фоновими задачами](../../advanced/advanced-dependencies.md#dependencies-with-yield-httpexception-except-and-background-tasks). + ## Менеджери контексту { #context-managers } ### Що таке «Менеджери контексту» { #what-are-context-managers } diff --git a/docs/uk/docs/tutorial/extra-data-types.md b/docs/uk/docs/tutorial/extra-data-types.md index 26d7c306f..15e6b64a4 100644 --- a/docs/uk/docs/tutorial/extra-data-types.md +++ b/docs/uk/docs/tutorial/extra-data-types.md @@ -22,7 +22,7 @@ Ось додаткові типи даних для використання: * `UUID`: - * Стандартний "Універсальний унікальний ідентифікатор", який часто використовується як ID у багатьох базах даних та системах. + * Стандартний «Універсальний унікальний ідентифікатор», який часто використовується як ID у багатьох базах даних та системах. * У запитах та відповідях буде представлений як `str`. * `datetime.datetime`: * Пайтонівський `datetime.datetime`. @@ -36,16 +36,16 @@ * `datetime.timedelta`: * Пайтонівський `datetime.timedelta`. * У запитах та відповідях буде представлений як `float` загальної кількості секунд. - * Pydantic також дозволяє представляти це як "ISO 8601 time diff encoding", [дивіться документацію для отримання додаткової інформації](https://docs.pydantic.dev/latest/concepts/serialization/#custom-serializers). + * Pydantic також дозволяє представляти це як «ISO 8601 time diff encoding», [дивіться документацію для отримання додаткової інформації](https://docs.pydantic.dev/latest/concepts/serialization/#custom-serializers). * `frozenset`: * У запитах і відповідях це буде оброблено так само, як і `set`: * У запитах список буде зчитано, дублікати буде видалено, і його буде перетворено на `set`. * У відповідях `set` буде перетворено на `list`. - * Згенерована схема буде вказувати, що значення `set` є унікальними (з використанням JSON Schema's `uniqueItems`). + * Згенерована схема буде вказувати, що значення `set` є унікальними (з використанням `uniqueItems` Схеми JSON). * `bytes`: * Стандартний Пайтонівський `bytes`. * У запитах і відповідях це буде оброблено як `str`. - * Згенерована схема буде вказувати, що це `str` з "форматом" `binary`. + * Згенерована схема буде вказувати, що це `str` з «форматом» `binary`. * `Decimal`: * Стандартний Пайтонівський `Decimal`. * У запитах і відповідях це буде оброблено так само, як і `float`. diff --git a/docs/uk/docs/tutorial/extra-models.md b/docs/uk/docs/tutorial/extra-models.md index 271e553fd..564f9fc44 100644 --- a/docs/uk/docs/tutorial/extra-models.md +++ b/docs/uk/docs/tutorial/extra-models.md @@ -63,7 +63,7 @@ print(user_dict) #### Розпакування `dict` { #unpacking-a-dict } -Якщо взяти `dict`, наприклад `user_dict`, і передати його у функцію (або клас) як `**user_dict`, Python «розпакує» його. Ключі та значення `user_dict` будуть передані безпосередньо як іменовані аргументи. +Якщо взяти `dict`, наприклад `user_dict`, і передати його у функцію (або клас) як `**user_dict`, Python «розпакує» його. Ключі та значення `user_dict` будуть передані безпосередньо як аргументи ключ-значення. Отже, продовжуючи з `user_dict` вище, запис: @@ -176,7 +176,7 @@ UserInDB( У цьому прикладі ми передаємо `Union[PlaneItem, CarItem]` як значення аргументу `response_model`. -Оскільки ми передаємо його як значення аргументу, а не в анотації типу, потрібно використовувати `Union` навіть у Python 3.10. +Оскільки ми передаємо його як **значення аргументу**, а не розміщуємо в **анотації типу**, потрібно використовувати `Union` навіть у Python 3.10. Якби це була анотація типу, можна було б використати вертикальну риску, наприклад: @@ -184,7 +184,7 @@ UserInDB( some_variable: PlaneItem | CarItem ``` -Але якщо записати це як присвоєння `response_model=PlaneItem | CarItem`, отримаємо помилку, тому що Python спробує виконати невалідну операцію між `PlaneItem` і `CarItem`, замість того щоб трактувати це як анотацію типу. +Але якщо записати це як присвоєння `response_model=PlaneItem | CarItem`, отримаємо помилку, тому що Python спробує виконати **невалідну операцію** між `PlaneItem` і `CarItem`, замість того щоб трактувати це як анотацію типу. ## Список моделей { #list-of-models } @@ -208,4 +208,4 @@ some_variable: PlaneItem | CarItem Використовуйте кілька моделей Pydantic і вільно наслідуйте для кожного випадку. -Не обов’язково мати одну модель даних на сутність, якщо ця сутність може мати різні «стани». Як у випадку сутності користувача зі станами: з `password`, з `password_hash` і без пароля. +Не обов’язково мати одну модель даних на сутність, якщо ця сутність повинна мати різні «стани». «Сутність» **користувач** є прикладом зі станами, що включають `password`, `password_hash` або відсутність пароля. diff --git a/docs/uk/docs/tutorial/first-steps.md b/docs/uk/docs/tutorial/first-steps.md index 2557d646c..0469e6c4d 100644 --- a/docs/uk/docs/tutorial/first-steps.md +++ b/docs/uk/docs/tutorial/first-steps.md @@ -88,13 +88,13 @@ INFO: Uvicorn running on http://127.0.0.1:8000 (Press CTRL+C to quit) #### «Схема» { #schema } -«Схема» — це визначення або опис чогось. Це не код, який його реалізує, а просто абстрактний опис. +«Схема» - це визначення або опис чогось. Це не код, який його реалізує, а просто абстрактний опис. #### API «схема» { #api-schema } У цьому випадку, [OpenAPI](https://github.com/OAI/OpenAPI-Specification) є специфікацією, яка визначає, як описати схему вашого API. -Це визначення схеми включає шляхи (paths) вашого API, можливі параметри, які вони приймають, тощо. +Це визначення схеми включає шляхи вашого API, можливі параметри, які вони приймають, тощо. #### «Схема» даних { #data-schema } @@ -102,13 +102,13 @@ INFO: Uvicorn running on http://127.0.0.1:8000 (Press CTRL+C to quit) У цьому випадку це означає атрибути JSON і типи даних, які вони мають, тощо. -#### OpenAPI і JSON Schema { #openapi-and-json-schema } +#### OpenAPI і Схема JSON { #openapi-and-json-schema } -OpenAPI описує схему API для вашого API. І ця схема включає визначення (або «схеми») даних, що надсилаються та отримуються вашим API, за допомогою **JSON Schema**, стандарту для схем даних JSON. +OpenAPI описує схему API для вашого API. І ця схема включає визначення (або «схеми») даних, що надсилаються та отримуються вашим API, за допомогою **Схеми JSON**, стандарту для схем даних JSON. #### Перевірте `openapi.json` { #check-the-openapi-json } -Якщо вас цікавить, як виглядає «сирий» OpenAPI schema, FastAPI автоматично генерує JSON (schema) з описами всього вашого API. +Якщо вас цікавить, як виглядає «сирa» схема OpenAPI, FastAPI автоматично генерує JSON (схему) з описами всього вашого API. Ви можете побачити це напряму тут: [http://127.0.0.1:8000/openapi.json](http://127.0.0.1:8000/openapi.json). @@ -137,7 +137,7 @@ OpenAPI описує схему API для вашого API. І ця схема #### Для чого потрібний OpenAPI { #what-is-openapi-for } -OpenAPI schema — це те, на чому працюють дві включені системи інтерактивної документації. +Схема OpenAPI - це те, на чому працюють дві включені системи інтерактивної документації. Також існують десятки альтернатив, і всі вони засновані на OpenAPI. Ви можете легко додати будь-яку з цих альтернатив до вашого застосунку, створеного з **FastAPI**. @@ -226,11 +226,11 @@ CLI автоматично визначить ваш застосунок FastAP {* ../../docs_src/first_steps/tutorial001_py310.py hl[1] *} -`FastAPI` — це клас у Python, який надає всю функціональність для вашого API. +`FastAPI` - це клас у Python, який надає всю функціональність для вашого API. /// note | Технічні деталі -`FastAPI` — це клас, який успадковується безпосередньо від `Starlette`. +`FastAPI` - це клас, який успадковується безпосередньо від `Starlette`. Ви також можете використовувати всю функціональність [Starlette](https://www.starlette.dev/) у `FastAPI`. @@ -312,7 +312,7 @@ https://example.com/items/foo Декоратор `@app.get("/")` повідомляє **FastAPI**, що функція одразу нижче відповідає за обробку запитів, які надходять до: * шляху `/` -* використовуючи get операція +* використовуючи операцію get /// note | `@decorator` Інформація @@ -389,7 +389,7 @@ https://example.com/items/foo Також можна повернути моделі Pydantic (про це ви дізнаєтесь пізніше). -Існує багато інших обʼєктів і моделей, які будуть автоматично конвертовані в JSON (зокрема ORM тощо). Спробуйте використати свої улюблені — велика ймовірність, що вони вже підтримуються. +Існує багато інших обʼєктів і моделей, які будуть автоматично конвертовані в JSON (зокрема ORM тощо). Спробуйте використати свої улюблені - велика ймовірність, що вони вже підтримуються. ### Крок 6: розгорніть його { #step-6-deploy-it } @@ -403,11 +403,11 @@ https://example.com/items/foo Він переносить той самий **досвід розробника** зі створення застосунків на FastAPI на **розгортання** їх у хмарі. 🎉 -FastAPI Cloud — основний спонсор і джерело фінансування для open source проєктів *FastAPI and friends*. ✨ +FastAPI Cloud - основний спонсор і джерело фінансування для open source проєктів *FastAPI and friends*. ✨ #### Розгортання в інших хмарних провайдерах { #deploy-to-other-cloud-providers } -FastAPI — це open source і базується на стандартах. Ви можете розгортати FastAPI-застосунки у будь-якого хмарного провайдера на ваш вибір. +FastAPI - це open source і базується на стандартах. Ви можете розгортати FastAPI-застосунки у будь-якого хмарного провайдера на ваш вибір. Дотримуйтеся інструкцій вашого хмарного провайдера, щоб розгорнути FastAPI-застосунки з їхньою допомогою. 🤓 diff --git a/docs/uk/docs/tutorial/handling-errors.md b/docs/uk/docs/tutorial/handling-errors.md index 262efa0e0..381e65cc0 100644 --- a/docs/uk/docs/tutorial/handling-errors.md +++ b/docs/uk/docs/tutorial/handling-errors.md @@ -33,7 +33,7 @@ Оскільки це помилка Python, ви не `return` її, а `raise` її. -Це також означає, що якщо ви перебуваєте всередині допоміжної функції, яку викликаєте всередині своєї *функції операції шляху*, і там згенеруєте `HTTPException` всередині цієї допоміжної функції, то решта коду в *функції операції шляху* не буде виконана. Запит одразу завершиться, і HTTP-помилка з `HTTPException` буде надіслана клієнту. +Це також означає, що якщо ви перебваєте всередині допоміжної функції, яку викликаєте всередині своєї *функції операції шляху*, і там згенеруєте `HTTPException` всередині цієї допоміжної функції, то решта коду в *функції операції шляху* не буде виконана. Запит одразу завершиться, і HTTP-помилка з `HTTPException` буде надіслана клієнту. Перевага генерації виключення замість повернення значення стане більш очевидною в розділі про залежності та безпеку. diff --git a/docs/uk/docs/tutorial/index.md b/docs/uk/docs/tutorial/index.md index 629b71dec..f89656236 100644 --- a/docs/uk/docs/tutorial/index.md +++ b/docs/uk/docs/tutorial/index.md @@ -54,7 +54,7 @@ $ fastapi dev **ДУЖЕ радимо** написати або скопіювати код, відредагувати його та запустити локально. -Використання його у своєму редакторі – це те, що дійсно показує вам переваги FastAPI, бачите, як мало коду вам потрібно написати, всі перевірки типів, автозаповнення тощо. +Використання його у своєму редакторі - це те, що дійсно показує вам переваги FastAPI, бачите, як мало коду вам потрібно написати, всі перевірки типів, автозаповнення тощо. --- @@ -86,7 +86,7 @@ $ pip install "fastapi[standard]" /// tip | Порада -FastAPI має [офіційне розширення для VS Code](https://marketplace.visualstudio.com/items?itemName=FastAPILabs.fastapi-vscode) (та Cursor), яке надає багато можливостей, включно з переглядачем операцій шляху, пошуком операцій шляху, навігацією CodeLens у тестах (перехід до визначення з тестів), а також розгортанням і журналами FastAPI Cloud — усе безпосередньо з вашого редактора. +FastAPI має [офіційне розширення для VS Code](https://marketplace.visualstudio.com/items?itemName=FastAPILabs.fastapi-vscode) (та Cursor), яке надає багато можливостей, включно з переглядачем операцій шляху, пошуком операцій шляху, навігацією CodeLens у тестах (перехід до визначення з тестів), а також розгортанням і журналами FastAPI Cloud - усе безпосередньо з вашого редактора. /// diff --git a/docs/uk/docs/tutorial/metadata.md b/docs/uk/docs/tutorial/metadata.md index d34b83b38..fd7a13b72 100644 --- a/docs/uk/docs/tutorial/metadata.md +++ b/docs/uk/docs/tutorial/metadata.md @@ -11,7 +11,7 @@ | `title` | `str` | Назва API. | | `summary` | `str` | Короткий підсумок API. Доступно з OpenAPI 3.1.0, FastAPI 0.99.0. | | `description` | `str` | Короткий опис API. Може використовувати Markdown. | -| `version` | `string` | Версія API. Це версія вашого додатка, а не OpenAPI. Наприклад, `2.5.0`. | +| `version` | `str` | Версія API. Це версія вашого додатка, а не OpenAPI. Наприклад, `2.5.0`. | | `terms_of_service` | `str` | URL до умов використання API. Якщо вказано, має бути у форматі URL. | | `contact` | `dict` | Інформація для контакту з опублікованим API. Може містити кілька полів.
contact поля
ПараметрТипОпис
namestrІдентифікаційне ім'я контактної особи або організації.
urlstrURL, що вказує на контактну інформацію. МАЄ бути у форматі URL.
emailstrАдреса електронної пошти контактної особи або організації. МАЄ бути у форматі адреси електронної пошти.
| | `license_info` | `dict` | Інформація про ліцензію для опублікованого API. Може містити кілька полів.
license_info поля
ПараметрТипОпис
namestrОБОВ'ЯЗКОВО (якщо встановлено license_info). Назва ліцензії для API.
identifierstrЛіцензійний вираз за [SPDX](https://spdx.org/licenses/) для API. Поле identifier взаємовиключне з полем url. Доступно з OpenAPI 3.1.0, FastAPI 0.99.0.
urlstrURL до ліцензії, яка використовується для API. МАЄ бути у форматі URL.
| diff --git a/docs/uk/docs/tutorial/path-operation-configuration.md b/docs/uk/docs/tutorial/path-operation-configuration.md index 47ae65f3e..151e79d1e 100644 --- a/docs/uk/docs/tutorial/path-operation-configuration.md +++ b/docs/uk/docs/tutorial/path-operation-configuration.md @@ -12,7 +12,7 @@ Ви можете визначити (HTTP) `status_code`, який буде використано у відповіді вашої «операції шляху». -Можна передати безпосередньо цілий код, наприклад `404`. +Ви можете передати безпосередньо код `int`, наприклад `404`. Якщо ви не пам'ятаєте призначення числових кодів, скористайтеся скороченими константами в `status`: @@ -24,7 +24,7 @@ Ви також можете використати `from starlette import status`. -FastAPI надає той самий `starlette.status` як `fastapi.status` для вашої зручності як розробника. Але він походить безпосередньо зі Starlette. +**FastAPI** надає той самий `starlette.status` як `fastapi.status` для вашої зручності як розробника. Але він походить безпосередньо зі Starlette. /// @@ -40,11 +40,11 @@ FastAPI надає той самий `starlette.status` як `fastapi.status` д ### Мітки з переліками { #tags-with-enums } -У великому застосунку ви можете накопичити багато міток і захочете переконатися, що завжди використовуєте ту саму мітку для пов'язаних «операцій шляху». +У великому застосунку ви можете накопичити **багато міток** і захочете переконатися, що завжди використовуєте **ту саму мітку** для пов'язаних «операцій шляху». У таких випадках має сенс зберігати мітки в `Enum`. -FastAPI підтримує це так само, як і зі звичайними строками: +**FastAPI** підтримує це так само, як і зі звичайними строками: {* ../../docs_src/path_operation_configuration/tutorial002b_py310.py hl[1,8:10,13,18] *} @@ -56,7 +56,7 @@ FastAPI підтримує це так само, як і зі звичайним ## Опис зі строки документації { #description-from-docstring } -Оскільки описи зазвичай довгі та займають кілька рядків, ви можете оголосити опис «операції шляху» у строці документації функції, і FastAPI прочитає його звідти. +Оскільки описи зазвичай довгі та займають кілька рядків, ви можете оголосити опис «операції шляху» у строці документації функції, і **FastAPI** прочитає його звідти. Ви можете писати [Markdown](https://en.wikipedia.org/wiki/Markdown) у строці документації, його буде інтерпретовано та показано коректно (з урахуванням відступів у строці документації). @@ -82,7 +82,7 @@ FastAPI підтримує це так само, як і зі звичайним OpenAPI визначає, що кожна «операція шляху» потребує опису відповіді. -Тому, якщо ви його не надасте, FastAPI автоматично згенерує «Successful response». +Тому, якщо ви його не надасте, **FastAPI** автоматично згенерує «Successful response». /// @@ -98,7 +98,7 @@ OpenAPI визначає, що кожна «операція шляху» пот -Подивіться, як виглядають застарілі та незастарілі «операції шляху»: +Перевірте, як виглядають застарілі та незастарілі «операції шляху»: diff --git a/docs/uk/docs/tutorial/query-params-str-validations.md b/docs/uk/docs/tutorial/query-params-str-validations.md index bca5874c2..610e83f41 100644 --- a/docs/uk/docs/tutorial/query-params-str-validations.md +++ b/docs/uk/docs/tutorial/query-params-str-validations.md @@ -1,4 +1,4 @@ -# Query параметри та валідація рядків { #query-parameters-and-string-validations } +# Параметри запиту та валідація строк { #query-parameters-and-string-validations } **FastAPI** дозволяє оголошувати додаткову інформацію та виконувати валідацію для ваших параметрів. @@ -6,7 +6,7 @@ {* ../../docs_src/query_params_str_validations/tutorial001_py310.py hl[7] *} -Query параметр `q` має тип `str | None`, що означає, що він має тип `str`, але також може бути `None`, і справді, значення за замовчуванням — `None`, тож FastAPI знатиме, що він не є обов'язковим. +Параметр запиту `q` має тип `str | None`, що означає, що він має тип `str`, але також може бути `None`, і справді, значення за замовчуванням - `None`, тож FastAPI знатиме, що він не є обов'язковим. /// note | Примітка @@ -18,7 +18,7 @@ FastAPI знатиме, що значення `q` не є обов’язков ## Додаткова валідація { #additional-validation } -Ми хочемо, щоб навіть якщо `q` є необов’язковим, коли його передають, його довжина не перевищувала 50 символів. +Ми забезпечимо, що навіть якщо `q` є необов’язковим, коли його передають, **його довжина не перевищувала 50 символів**. ### Імпорт `Query` та `Annotated` { #import-query-and-annotated } @@ -45,7 +45,7 @@ FastAPI додав підтримку `Annotated` (і почав рекомен Зараз саме час використати його разом із FastAPI. 🚀 -Раніше ми мали таку анотацію типу: +Ми мали таку анотацію типу: ```Python q: str | None = None @@ -57,31 +57,31 @@ q: str | None = None q: Annotated[str | None] = None ``` -Обидві ці версії означають одне й те саме: `q` — це параметр, який може бути `str` або `None`, і за замовчуванням має значення `None`. +Обидві ці версії означають одне й те саме: `q` - це параметр, який може бути `str` або `None`, і за замовчуванням має значення `None`. А тепер переходимо до цікавого! 🎉 ## Додавання `Query` до `Annotated` у параметр `q` { #add-query-to-annotated-in-the-q-parameter } -Тепер, коли у нас є `Annotated`, де ми можемо додавати додаткову інформацію (у цьому випадку — додаткову валідацію), додамо `Query` всередину `Annotated` і встановимо параметр `max_length` у `50`: +Тепер, коли у нас є `Annotated`, де ми можемо додавати додаткову інформацію (у цьому випадку - додаткову валідацію), додамо `Query` всередину `Annotated` і встановимо параметр `max_length` у `50`: {* ../../docs_src/query_params_str_validations/tutorial002_an_py310.py hl[9] *} Зверніть увагу, що значення за замовчуванням усе ще `None`, тому параметр залишається необов'язковим. -Але тепер, додавши `Query(max_length=50)` всередину `Annotated`, ми повідомляємо FastAPI, що хочемо додаткову валідацію для цього значення: ми хочемо, щоб воно мало максимум 50 символів. 😎 +Але тепер, додавши `Query(max_length=50)` всередину `Annotated`, ми повідомляємо FastAPI, що хочемо **додаткову валідацію** для цього значення: ми хочемо, щоб воно мало максимум 50 символів. 😎 /// tip | Порада -Тут ми використовуємо `Query()`, оскільки це query параметр. Далі ми розглянемо інші варіанти, як-от `Path()`, `Body()`, `Header()` та `Cookie()`, які приймають ті самі аргументи, що й `Query()`. +Тут ми використовуємо `Query()`, оскільки це **параметр запиту**. Далі ми розглянемо інші варіанти, як-от `Path()`, `Body()`, `Header()` та `Cookie()`, які приймають ті самі аргументи, що й `Query()`. /// Тепер FastAPI: -* Перевірить дані, щоб переконатися, що їхня максимальна довжина — 50 символів -* Покажe чітку помилку клієнту, якщо дані недійсні -* Задокументує параметр в OpenAPI-схемі операції шляху (що відобразиться в автоматично згенерованій документації) +* **Перевірить** дані, щоб переконатися, що їхня максимальна довжина - 50 символів +* Покажe **чітку помилку** клієнту, якщо дані недійсні +* **Задокументує** параметр в *операції шляху* схеми OpenAPI (що відобразиться в **автоматичному інтерфейсі документації**) ## Альтернативний (застарілий) метод: `Query` як значення за замовчуванням { #alternative-old-query-as-the-default-value } @@ -93,7 +93,7 @@ q: Annotated[str | None] = None /// -Раніше ми писали `Query()` як значення за замовчуванням для параметра функції, встановлюючи `max_length` у 50: +Раніше ми писали `Query()` як значення за замовчуванням для параметра функції, встановлюючи параметр `max_length` у 50: {* ../../docs_src/query_params_str_validations/tutorial002_py310.py hl[7] *} @@ -107,19 +107,20 @@ q: str | None = Query(default=None) ...робить параметр необов’язковим зі значенням за замовчуванням `None`, що еквівалентно: + ```Python q: str | None = None ``` -Але у версії з `Query` ми явно вказуємо, що це query параметр. +Але у версії з `Query` ми явно вказуємо, що це параметр запиту. -Далі ми можемо передавати `Query` додаткові параметри. У цьому випадку — параметр `max_length`, який застосовується до рядків: +Далі ми можемо передавати `Query` додаткові параметри. У цьому випадку - параметр `max_length`, який застосовується до строк: ```Python q: str | None = Query(default=None, max_length=50) ``` -Це забезпечить валідацію даних, виведе зрозумілу помилку у разі недійсних даних і задокументує параметр у схемі OpenAPI операції шляху. +Це забезпечить валідацію даних, виведе зрозумілу помилку у разі недійсних даних і задокументує параметр у *операції шляху* схеми OpenAPI. ### `Query` як значення за замовчуванням або всередині `Annotated` { #query-as-the-default-value-or-in-annotated } @@ -149,13 +150,13 @@ q: str = Query(default="rick") ### Переваги використання `Annotated` { #advantages-of-annotated } -Використання `Annotated` є рекомендованим замість задання значення за замовчуванням у параметрах функції, оскільки воно краще з кількох причин. 🤓 +**Використання `Annotated` є рекомендованим** замість задання значення за замовчуванням у параметрах функції, оскільки воно **краще** з кількох причин. 🤓 -Значення за замовчуванням параметра функції є фактичним значенням за замовчуванням, що є більш інтуїтивним у Python загалом. 😌 +**Значення за замовчуванням** **параметра функції** є **фактичним значенням за замовчуванням**, що є більш інтуїтивним у Python загалом. 😌 -Ви можете викликати ту саму функцію в інших місцях без FastAPI, і вона працюватиме очікувано. Якщо параметр є обов’язковим (без значення за замовчуванням), ваш редактор повідомить про помилку, а Python також видасть помилку, якщо ви виконаєте функцію без передавання цього параметра. +Ви можете **викликати** ту саму функцію в **інших місцях** без FastAPI, і вона **працюватиме очікувано**. Якщо параметр є **обов’язковим** (без значення за замовчуванням), ваш **редактор** повідомить про помилку, а **Python** також видасть помилку, якщо ви виконаєте функцію без передавання обов’язкового параметра. -Якщо ви не використовуєте `Annotated`, а використовуєте (старий) стиль значень за замовчуванням, то при виклику цієї функції без FastAPI в інших місцях потрібно пам’ятати передати їй аргументи, щоб вона працювала коректно, інакше значення будуть відрізнятися від очікуваних (наприклад, ви отримаєте `QueryInfo` або щось подібне замість `str`). І ваш редактор не повідомить про помилку, і Python не скаржитиметься під час запуску цієї функції — лише коли операції всередині завершаться помилкою. +Якщо ви не використовуєте `Annotated`, а використовуєте **(старий) стиль значень за замовчуванням**, то при виклику цієї функції без FastAPI в **інших місцях** потрібно **пам’ятати** передати їй аргументи, щоб вона працювала коректно, інакше значення будуть відрізнятися від очікуваних (наприклад, ви отримаєте `QueryInfo` або щось подібне замість `str`). І ваш редактор не повідомить про помилку, і Python не скаржитиметься під час запуску цієї функції - лише коли операції всередині завершаться помилкою. Оскільки `Annotated` може містити кілька анотацій метаданих, тепер ви навіть можете використовувати ту саму функцію з іншими інструментами, такими як [Typer](https://typer.tiangolo.com/). 🚀 @@ -167,7 +168,7 @@ q: str = Query(default="rick") ## Додавання регулярних виразів { #add-regular-expressions } -Ви можете визначити регулярний вираз `pattern`, якому має відповідати параметр: +Ви можете визначити регулярний вираз `pattern`, якому має відповідати параметр: {* ../../docs_src/query_params_str_validations/tutorial004_an_py310.py hl[11] *} @@ -177,7 +178,7 @@ q: str = Query(default="rick") * `fixedquery`: точно відповідає значенню `fixedquery`. * `$`: закінчується тут, після `fixedquery` немає жодних символів. -Якщо ви почуваєтеся розгублено щодо **«regular expression»**, не хвилюйтеся. Це складна тема для багатьох людей. Ви все одно можете робити багато речей без використання регулярних виразів. +Якщо ви почуваєтеся розгублено щодо всіх цих ідей **«регулярного виразу»**, не хвилюйтеся. Це складна тема для багатьох людей. Ви все одно можете робити багато речей без потреби в регулярних виразах. Тепер ви знаєте, що коли вони знадобляться, їх можна застосовувати у **FastAPI**. @@ -185,19 +186,19 @@ q: str = Query(default="rick") Ви можете, звісно, використовувати значення за замовчуванням, відмінні від `None`. -Припустімо, що ви хочете оголосити query параметр `q` з `min_length` `3` і значенням за замовчуванням `"fixedquery"`: +Припустімо, що ви хочете оголосити параметр запиту `q` з `min_length` `3` і значенням за замовчуванням `"fixedquery"`: {* ../../docs_src/query_params_str_validations/tutorial005_an_py310.py hl[9] *} /// note | Примітка -Наявність значення за замовчуванням будь-якого типу, включаючи `None`, робить параметр необов’язковим (not required). +Наявність значення за замовчуванням будь-якого типу, включаючи `None`, робить параметр необов’язковим (не обов’язковим). /// ## Обов’язкові параметри { #required-parameters } -Якщо нам не потрібно оголошувати додаткові валідації або метадані, ми можемо зробити query параметр `q` обов’язковим, просто не вказуючи значення за замовчуванням, наприклад: +Якщо нам не потрібно оголошувати додаткові валідації або метадані, ми можемо зробити параметр запиту `q` обов’язковим, просто не вказуючи значення за замовчуванням, наприклад: ```Python q: str @@ -227,11 +228,11 @@ q: Annotated[str | None, Query(min_length=3)] = None {* ../../docs_src/query_params_str_validations/tutorial006c_an_py310.py hl[9] *} -## Список query параметрів / кілька значень { #query-parameter-list-multiple-values } +## Список параметрів запиту / кілька значень { #query-parameter-list-multiple-values } -Коли ви явно визначаєте query параметр за допомогою `Query`, ви також можете оголосити, що він має приймати список значень, або, іншими словами, кілька значень. +Коли ви явно визначаєте параметр запиту за допомогою `Query`, ви також можете оголосити, що він має приймати список значень, або, іншими словами, кілька значень. -Наприклад, щоб оголосити query параметр `q`, який може з’являтися в URL кілька разів, можна написати: +Наприклад, щоб оголосити параметр запиту `q`, який може з’являтися в URL кілька разів, можна написати: {* ../../docs_src/query_params_str_validations/tutorial011_an_py310.py hl[9] *} @@ -241,7 +242,7 @@ q: Annotated[str | None, Query(min_length=3)] = None http://localhost:8000/items/?q=foo&q=bar ``` -ви отримаєте кілька значень `q` query параметрів (`foo` і `bar`) у вигляді Python `list` у вашій функції операції шляху, у параметрі функції `q`. +ви отримаєте кілька значень *параметрів запиту* `q` (`foo` і `bar`) у вигляді Python `list` у вашій *функції операції шляху*, у *параметрі функції* `q`. Отже, відповідь на цей URL буде: @@ -256,7 +257,7 @@ http://localhost:8000/items/?q=foo&q=bar /// tip | Порада -Щоб оголосити query параметр з типом `list`, як у наведеному вище прикладі, потрібно явно використовувати `Query`, інакше він буде інтерпретований як тіло запиту. +Щоб оголосити параметр запиту з типом `list`, як у наведеному вище прикладі, потрібно явно використовувати `Query`, інакше він буде інтерпретований як тіло запиту. /// @@ -264,7 +265,7 @@ http://localhost:8000/items/?q=foo&q=bar -### Список query параметрів / кілька значень за замовчуванням { #query-parameter-list-multiple-values-with-defaults } +### Список параметрів запиту / кілька значень за замовчуванням { #query-parameter-list-multiple-values-with-defaults } Ви також можете визначити значення за замовчуванням `list`, якщо жодне значення не було передане: @@ -297,7 +298,7 @@ http://localhost:8000/items/ Майте на увазі, що в цьому випадку FastAPI не перевірятиме вміст списку. -Наприклад, `list[int]` перевірятиме (і документуватиме), що вміст списку — цілі числа. Але `list` без уточнення цього не робитиме. +Наприклад, `list[int]` перевірятиме (і документуватиме), що вміст списку - цілі числа. Але `list` без уточнення цього не робитиме. /// @@ -305,7 +306,7 @@ http://localhost:8000/items/ Ви можете додати більше інформації про параметр. -Ця інформація буде включена у згенерований OpenAPI та використана інтерфейсами документації та зовнішніми інструментами. +Ця інформація буде включена у згенерований OpenAPI та використана користувацькими інтерфейсами документації та зовнішніми інструментами. /// note | Примітка @@ -333,9 +334,9 @@ http://localhost:8000/items/ http://127.0.0.1:8000/items/?item-query=foobaritems ``` -Але `item-query` — це некоректна назва змінної в Python. +Але `item-query` - це некоректна назва змінної в Python. -Найближчий допустимий варіант — `item_query`. +Найближчий допустимий варіант - `item_query`. Проте вам потрібно, щоб параметр залишався саме `item-query`... @@ -359,17 +360,17 @@ http://127.0.0.1:8000/items/?item-query=foobaritems ## Виняток параметрів з OpenAPI { #exclude-parameters-from-openapi } -Щоб виключити query параметр зі згенерованої схеми OpenAPI (і, таким чином, з автоматичних систем документації), встановіть параметр `include_in_schema` для `Query` в `False`: +Щоб виключити параметр запиту зі згенерованої схеми OpenAPI (і, таким чином, з автоматичних систем документації), встановіть параметр `include_in_schema` для `Query` в `False`: {* ../../docs_src/query_params_str_validations/tutorial014_an_py310.py hl[10] *} ## Кастомна валідація { #custom-validation } -Можуть бути випадки, коли вам потрібно провести кастомну валідацію, яку не можна реалізувати за допомогою параметрів, показаних вище. +Можуть бути випадки, коли вам потрібно провести **кастомну валідацію**, яку не можна реалізувати за допомогою параметрів, показаних вище. -У таких випадках ви можете використати кастомну функцію-валідатор, яка буде застосована після звичайної валідації (наприклад, після перевірки, що значення є типом `str`). +У таких випадках ви можете використати **кастомну функцію-валідатор**, яка буде застосована після звичайної валідації (наприклад, після перевірки, що значення є типом `str`). -Це можна досягти за допомогою [Pydantic's `AfterValidator`](https://docs.pydantic.dev/latest/concepts/validators/#field-after-validator) в середині `Annotated`. +Це можна досягти за допомогою [Pydantic's `AfterValidator`](https://docs.pydantic.dev/latest/concepts/validators/#field-after-validator) всередині `Annotated`. /// tip | Порада @@ -377,7 +378,7 @@ Pydantic також має [`BeforeValidator`](https://docs.pydantic.dev/latest/ /// -Наприклад, цей кастомний валідатор перевіряє, чи починається ID елемента з `isbn-` для номера книги ISBN або з `imdb-` для ID URL фільму на IMDB: +Наприклад, цей кастомний валідатор перевіряє, чи починається ID предмета з `isbn-` для номера книги ISBN або з `imdb-` для ID URL фільму на IMDB: {* ../../docs_src/query_params_str_validations/tutorial015_an_py310.py hl[5,16:19,24] *} @@ -389,39 +390,39 @@ Pydantic також має [`BeforeValidator`](https://docs.pydantic.dev/latest/ /// tip | Порада -Якщо вам потрібно виконати будь-яку валідацію, яка вимагає взаємодії з будь-яким зовнішнім компонентом, таким як база даних чи інший API, замість цього слід використовувати FastAPI Dependencies — ви дізнаєтесь про них пізніше. +Якщо вам потрібно виконати будь-яку валідацію, яка вимагає взаємодії з будь-яким **зовнішнім компонентом**, таким як база даних чи інший API, замість цього слід використовувати **FastAPI Dependencies** - ви дізнаєтесь про них пізніше. -Ці кастомні валідатори використовуються для речей, які можна перевірити лише з тими самими даними, що надані в запиті. +Ці кастомні валідатори використовуються для речей, які можна перевірити **лише** з **тими самими даними**, що надані в запиті. /// ### Зрозумійте цей код { #understand-that-code } -Головний момент — це використання `AfterValidator` з функцією всередині `Annotated`. Можете пропустити цю частину, якщо хочете. 🤸 +Головний момент - це використання **`AfterValidator` з функцією всередині `Annotated`**. Можете пропустити цю частину, якщо хочете. 🤸 --- Але якщо вам цікаво розібратися в цьому конкретному прикладі коду і вам ще не набридло, ось кілька додаткових деталей. -#### Рядок із `value.startswith()` { #string-with-value-startswith } +#### Строка з `value.startswith()` { #string-with-value-startswith } -Звернули увагу? Рядок із `value.startswith()` може приймати кортеж, і тоді він перевірятиме кожне значення в кортежі: +Звернули увагу? Строка з `value.startswith()` може приймати кортеж, і тоді він перевірятиме кожне значення в кортежі: {* ../../docs_src/query_params_str_validations/tutorial015_an_py310.py ln[16:19] hl[17] *} -#### Випадковий елемент { #a-random-item } +#### Випадковий предмет { #a-random-item } -За допомогою `data.items()` ми отримуємо ітерабельний об'єкт із кортежами, що містять ключ і значення для кожного елемента словника. +За допомогою `data.items()` ми отримуємо ітерабельний об'єкт із кортежами, що містять ключ і значення для кожного предмета словника. Ми перетворюємо цей ітерабельний об'єкт у звичайний `list` за допомогою `list(data.items())`. -Потім, використовуючи `random.choice()`, ми можемо отримати випадкове значення зі списку, тобто отримуємо кортеж із `(id, name)`. Це може бути щось на зразок `("imdb-tt0371724", "The Hitchhiker's Guide to the Galaxy")`. +Потім, використовуючи `random.choice()`, ми можемо отримати **випадкове значення** зі списку, тобто отримуємо кортеж із `(id, name)`. Це може бути щось на зразок `("imdb-tt0371724", "The Hitchhiker's Guide to the Galaxy")`. -Далі ми присвоюємо ці два значення кортежу змінним `id` і `name`. +Далі ми **присвоюємо ці два значення** кортежу змінним `id` і `name`. -Тож, якщо користувач не вказав ID елемента, він все одно отримає випадкову рекомендацію. +Тож, якщо користувач не вказав ID предмета, він все одно отримає випадкову рекомендацію. -...ми робимо все це в одному простому рядку. 🤯 Хіба ви не любите Python? 🐍 +...ми робимо все це в **одному простому рядку**. 🤯 Хіба ви не любите Python? 🐍 {* ../../docs_src/query_params_str_validations/tutorial015_an_py310.py ln[22:30] hl[29] *} @@ -436,7 +437,7 @@ Pydantic також має [`BeforeValidator`](https://docs.pydantic.dev/latest/ * `description` * `deprecated` -Валідації, специфічні для рядків: +Валідації, специфічні для строк: * `min_length` * `max_length` diff --git a/docs/uk/docs/tutorial/query-params.md b/docs/uk/docs/tutorial/query-params.md index 755b9e21a..d70fb1fe3 100644 --- a/docs/uk/docs/tutorial/query-params.md +++ b/docs/uk/docs/tutorial/query-params.md @@ -1,10 +1,10 @@ -# Query параметри { #query-parameters } +# Параметри запиту { #query-parameters } -Коли ви оголошуєте інші параметри функції, які не є частиною параметрів шляху, вони автоматично інтерпретуються як параметри «query». +Коли ви оголошуєте інші параметри функції, які не є частиною параметрів шляху, вони автоматично інтерпретуються як параметри «запиту». {* ../../docs_src/query_params/tutorial001_py310.py hl[9] *} -Query — це набір пар ключ-значення, що йдуть після символу `?` в URL, розділені символами `&`. +Запит - це набір пар ключ-значення, що йдуть після символу `?` в URL, розділені символами `&`. Наприклад, в URL: @@ -12,25 +12,25 @@ Query — це набір пар ключ-значення, що йдуть пі http://127.0.0.1:8000/items/?skip=0&limit=10 ``` -...параметрами query є: +...параметрами запиту є: * `skip`: зі значенням `0` * `limit`: зі значенням `10` -Оскільки вони є частиною URL, вони «природно» є рядками. +Оскільки вони є частиною URL, вони «природно» є строками. Але коли ви оголошуєте їх із типами Python (у наведеному прикладі як `int`), вони перетворюються на цей тип і проходять перевірку відповідності. -Увесь той самий процес, який застосовується до параметрів шляху, також застосовується до параметрів query: +Увесь той самий процес, який застосовується до параметрів шляху, також застосовується до параметрів запиту: * Підтримка в редакторі (очевидно) -* «парсинг» даних +* «парсинг» даних * Валідація даних * Автоматична документація ## Значення за замовчуванням { #defaults } -Оскільки параметри query не є фіксованою частиною шляху, вони можуть бути необов’язковими та мати значення за замовчуванням. +Оскільки параметри запиту не є фіксованою частиною шляху, вони можуть бути необов’язковими та мати значення за замовчуванням. У наведеному вище прикладі вони мають значення за замовчуванням: `skip=0` і `limit=10`. @@ -59,7 +59,7 @@ http://127.0.0.1:8000/items/?skip=20 ## Необов'язкові параметри { #optional-parameters } -Так само ви можете оголосити необов’язкові параметри query, встановивши для них значення за замовчуванням `None`: +Так само ви можете оголосити необов’язкові параметри запиту, встановивши для них значення за замовчуванням `None`: {* ../../docs_src/query_params/tutorial002_py310.py hl[7] *} @@ -67,11 +67,11 @@ http://127.0.0.1:8000/items/?skip=20 /// tip | Порада -Також зверніть увагу, що **FastAPI** достатньо розумний, щоб визначити, що параметр шляху `item_id` є параметром шляху, а `q` — ні, отже, це параметр query. +Також зверніть увагу, що **FastAPI** достатньо розумний, щоб визначити, що параметр шляху `item_id` є параметром шляху, а `q` - ні, отже, це параметр запиту. /// -## Перетворення типу параметра query { #query-parameter-type-conversion } +## Перетворення типу параметра запиту { #query-parameter-type-conversion } Ви також можете оголошувати параметри типу `bool`, і вони будуть автоматично конвертовані: @@ -107,12 +107,12 @@ http://127.0.0.1:8000/items/foo?short=on http://127.0.0.1:8000/items/foo?short=yes ``` -або будь-який інший варіант написання (великі літери, перша літера велика тощо), ваша функція побачить параметр `short` зі значенням `True` типу `bool`. В іншому випадку — `False`. +або будь-який інший варіант написання (великі літери, перша літера велика тощо), ваша функція побачить параметр `short` зі значенням `True` типу `bool`. В іншому випадку - `False`. -## Кілька path і query параметрів { #multiple-path-and-query-parameters } +## Кілька параметрів шляху та запиту { #multiple-path-and-query-parameters } -Ви можете одночасно оголошувати кілька параметрів шляху та параметрів query, **FastAPI** знає, який з них який. +Ви можете одночасно оголошувати кілька параметрів шляху та параметрів запиту, **FastAPI** знає, який з них який. І вам не потрібно оголошувати їх у якомусь конкретному порядку. @@ -120,17 +120,17 @@ http://127.0.0.1:8000/items/foo?short=yes {* ../../docs_src/query_params/tutorial004_py310.py hl[6,8] *} -## Обов’язкові параметри query { #required-query-parameters } +## Обов’язкові параметри запиту { #required-query-parameters } -Коли ви оголошуєте значення за замовчуванням для не-path-параметрів (поки що ми бачили лише параметри query), тоді вони не є обов’язковими. +Коли ви оголошуєте значення за замовчуванням для параметрів, що не є параметрами шляху (поки що ми бачили лише параметри запиту), тоді вони не є обов’язковими. Якщо ви не хочете задавати конкретне значення, а просто зробити параметр необов’язковим, задайте `None` як значення за замовчуванням. -Але якщо ви хочете зробити параметр query обов’язковим, просто не вказуйте для нього значення за замовчуванням: +Але якщо ви хочете зробити параметр запиту обов’язковим, просто не вказуйте для нього значення за замовчуванням: {* ../../docs_src/query_params/tutorial005_py310.py hl[6:7] *} -Тут параметр query `needy` — обов’язковий параметр query типу `str`. +Тут параметр запиту `needy` - обов’язковий параметр запиту типу `str`. Якщо ви відкриєте у браузері URL-адресу: @@ -171,11 +171,11 @@ http://127.0.0.1:8000/items/foo-item?needy=sooooneedy } ``` -І звісно, ви можете визначити деякі параметри як обов’язкові, деякі — зі значенням за замовчуванням, а деякі — повністю необов’язкові: +І звісно, ви можете визначити деякі параметри як обов’язкові, деякі - зі значенням за замовчуванням, а деякі - повністю необов’язкові: {* ../../docs_src/query_params/tutorial006_py310.py hl[8] *} -У цьому випадку є 3 параметри query: +У цьому випадку є 3 параметри запиту: * `needy`, обов’язковий `str`. * `skip`, `int` зі значенням за замовчуванням `0`. diff --git a/docs/uk/docs/tutorial/request-files.md b/docs/uk/docs/tutorial/request-files.md index b7179c393..0785dd206 100644 --- a/docs/uk/docs/tutorial/request-files.md +++ b/docs/uk/docs/tutorial/request-files.md @@ -12,7 +12,7 @@ $ pip install python-multipart ``` -Це необхідно, оскільки завантажені файли передаються у вигляді «form data». +Це необхідно, оскільки завантажені файли передаються як «дані форми». /// @@ -30,7 +30,7 @@ $ pip install python-multipart /// note | Примітка -`File` — це клас, який безпосередньо успадковує `Form`. +`File` - це клас, який безпосередньо успадковує `Form`. Але пам’ятайте, що коли ви імпортуєте `Query`, `Path`, `File` та інші з `fastapi`, це насправді функції, які повертають спеціальні класи. @@ -42,7 +42,7 @@ $ pip install python-multipart /// -Файли будуть завантажені у вигляді «form data». +Файли будуть завантажені як «дані форми». Якщо ви оголосите тип параметра *функції операції шляху* як `bytes`, **FastAPI** прочитає файл за вас, і ви отримаєте його вміст у вигляді `bytes`. @@ -70,8 +70,8 @@ $ pip install python-multipart `UploadFile` має такі атрибути: -* `filename`: Рядок `str` з оригінальною назвою файлу, який був завантажений (наприклад, `myimage.jpg`). -* `content_type`: Рядок `str` з типом вмісту (MIME type / media type) (наприклад, `image/jpeg`). +* `filename`: Строка `str` з оригінальною назвою файлу, який був завантажений (наприклад, `myimage.jpg`). +* `content_type`: Строка `str` з типом вмісту (MIME type / media type) (наприклад, `image/jpeg`). * `file`: [`SpooledTemporaryFile`](https://docs.python.org/3/library/tempfile.html#tempfile.SpooledTemporaryFile) ([file-like](https://docs.python.org/3/glossary.html#term-file-like-object) об'єкт). Це фактичний файловий об'єкт Python, який ви можете передавати безпосередньо іншим функціям або бібліотекам, що очікують «file-like» об'єкт. `UploadFile` має такі асинхронні `async` методи. Вони всі викликають відповідні методи файлу під капотом (використовуючи внутрішній `SpooledTemporaryFile`). @@ -109,7 +109,7 @@ contents = myfile.file.read() /// -## Що таке «Form Data» { #what-is-form-data } +## Що таке «дані форми» { #what-is-form-data } Спосіб, у який HTML-форми (`
`) надсилають дані на сервер, зазвичай використовує «спеціальне» кодування для цих даних, відмінне від JSON. @@ -121,7 +121,7 @@ contents = myfile.file.read() Але якщо форма містить файли, вона кодується як `multipart/form-data`. Якщо ви використовуєте `File`, **FastAPI** знатиме, що потрібно отримати файли з правильної частини тіла. -Якщо ви хочете дізнатися більше про ці типи кодування та формові поля, ознайомтеся з [MDN web docs для `POST`](https://developer.mozilla.org/en-US/docs/Web/HTTP/Methods/POST). +Якщо ви хочете дізнатися більше про ці типи кодування та поля форми, ознайомтеся з [MDN web docs для `POST`](https://developer.mozilla.org/en-US/docs/Web/HTTP/Methods/POST). /// @@ -149,7 +149,7 @@ contents = myfile.file.read() Можна завантажувати кілька файлів одночасно. -Вони будуть пов’язані з одним і тим самим «form field», який передається у вигляді «form data». +Вони будуть пов’язані з одним і тим самим «полем форми», яке передається як «дані форми». Щоб це реалізувати, потрібно оголосити список `bytes` або `UploadFile`: @@ -173,4 +173,4 @@ contents = myfile.file.read() ## Підсумок { #recap } -Використовуйте `File`, `bytes` та `UploadFile`, щоб оголошувати файли для завантаження в запиті, надіслані у вигляді form data. +Використовуйте `File`, `bytes` та `UploadFile`, щоб оголошувати файли для завантаження в запиті, надіслані як дані форми. diff --git a/docs/uk/docs/tutorial/request-forms.md b/docs/uk/docs/tutorial/request-forms.md index 382826a40..311377908 100644 --- a/docs/uk/docs/tutorial/request-forms.md +++ b/docs/uk/docs/tutorial/request-forms.md @@ -34,7 +34,7 @@ $ pip install python-multipart /// note | Примітка -`Form` — це клас, який безпосередньо наслідується від `Body`. +`Form` - це клас, який безпосередньо наслідується від `Body`. /// diff --git a/docs/uk/docs/tutorial/response-status-code.md b/docs/uk/docs/tutorial/response-status-code.md index 3915a53ed..4e49cdc60 100644 --- a/docs/uk/docs/tutorial/response-status-code.md +++ b/docs/uk/docs/tutorial/response-status-code.md @@ -1,5 +1,6 @@ # Код статусу відповіді { #response-status-code } + Так само, як ви можете вказати модель відповіді, ви також можете оголосити HTTP код статусу, що використовується для відповіді, за допомогою параметра `status_code` в будь-якій з *операцій шляху*: * `@app.get()` diff --git a/docs/uk/docs/tutorial/schema-extra-example.md b/docs/uk/docs/tutorial/schema-extra-example.md index b63a2d253..734a06d1a 100644 --- a/docs/uk/docs/tutorial/schema-extra-example.md +++ b/docs/uk/docs/tutorial/schema-extra-example.md @@ -1,4 +1,4 @@ -# Декларування прикладів вхідних даних { #declare-request-example-data } +# Декларування прикладів даних запиту { #declare-request-example-data } Ви можете задати приклади даних, які ваш застосунок може отримувати. @@ -42,7 +42,7 @@ OpenAPI 3.1.0 (який використовується починаючи з F ## `examples` у Схемі JSON - OpenAPI { #examples-in-json-schema-openapi } -При використанні будь-кого з наступного: +Під час використання будь-чого з наведеного: * `Path()` * `Query()` @@ -109,7 +109,7 @@ OpenAPI 3.1.0 (який використовується починаючи з F * `value`: це сам приклад, який буде показано, наприклад `dict`. * `externalValue`: альтернатива `value`, URL-адреса, що вказує на приклад. Проте це може не підтримуватися такою кількістю інструментів, як `value`. -Використання виглядає так: +Ви можете використати це так: {* ../../docs_src/schema_extra_example/tutorial005_an_py310.py hl[23:49] *} diff --git a/docs/uk/docs/tutorial/security/first-steps.md b/docs/uk/docs/tutorial/security/first-steps.md index aa0d21e2e..7feee1c02 100644 --- a/docs/uk/docs/tutorial/security/first-steps.md +++ b/docs/uk/docs/tutorial/security/first-steps.md @@ -4,7 +4,7 @@ А **frontend** - на іншому домені або в іншому шляху того ж домену (або у мобільному застосунку). -І ви хочете, щоб frontend міг автентифікуватися в backend, використовуючи ім'я користувача та пароль. +І ви хочете, щоб frontend міг автентифікуватися в backend, використовуючи **ім'я користувача** та **пароль**. Ми можемо використати **OAuth2**, щоб збудувати це з **FastAPI**. @@ -40,7 +40,7 @@ $ pip install python-multipart /// -Запустіть приклад: +Запустіть приклад за допомогою:
@@ -60,7 +60,7 @@ $ fastapi dev -/// tip | Кнопка Authorize! +/// tip | Кнопка «Authorize»! У вас уже є нова блискуча кнопка «Authorize». @@ -78,7 +78,7 @@ $ fastapi dev /// -Звісно, це не frontend для кінцевих користувачів, але це чудовий інструмент для інтерактивної документації всього вашого API. +Звісно, це не frontend для кінцевих користувачів, але це чудовий автоматичний інструмент для інтерактивного документування всього вашого API. Ним може користуватися команда frontend (якою можете бути і ви самі). @@ -86,11 +86,11 @@ $ fastapi dev І ним також можете користуватися ви самі, щоб налагоджувати, перевіряти та тестувати той самий застосунок. -## Потік паролю { #the-password-flow } +## Потік `password` { #the-password-flow } Тепер повернімося трохи назад і розберімося, що це все таке. -`password` «flow» - це один зі способів («flows»), визначених в OAuth2, для обробки безпеки та автентифікації. +`password` «потік» - це один зі способів («потоків»), визначених в OAuth2, для обробки безпеки та автентифікації. OAuth2 був спроєктований так, щоб backend або API могли бути незалежними від сервера, який автентифікує користувача. @@ -100,7 +100,7 @@ OAuth2 був спроєктований так, щоб backend або API мо - Користувач вводить `username` і `password` у frontend і натискає `Enter`. - Frontend (у браузері користувача) надсилає ці `username` і `password` на специфічну URL-адресу нашого API (оголошену як `tokenUrl="token"`). -- API перевіряє ці `username` і `password` та повертає «токен» (ми ще нічого з цього не реалізували). +- API перевіряє ці `username` і `password` та відповідає «токеном» (ми ще нічого з цього не реалізували). - «Токен» - це просто строка з деяким вмістом, який ми можемо пізніше використати, щоб перевірити цього користувача. - Зазвичай токен налаштований на завершення строку дії через певний час. - Тож користувачу доведеться знову увійти пізніше. @@ -116,11 +116,11 @@ OAuth2 був спроєктований так, щоб backend або API мо **FastAPI** надає кілька інструментів на різних рівнях абстракції, щоб реалізувати ці функції безпеки. -У цьому прикладі ми використаємо **OAuth2** з потоком **Password**, використовуючи токен **Bearer**. Це робиться за допомогою класу `OAuth2PasswordBearer`. +У цьому прикладі ми використаємо **OAuth2** з потоком **Password**, використовуючи **токен носія**. Це робиться за допомогою класу `OAuth2PasswordBearer`. /// note | Примітка -«Bearer»-токен - не єдиний варіант. +«Токен носія» - не єдиний варіант. Але це найкращий для нашого сценарію. @@ -138,7 +138,7 @@ OAuth2 був спроєктований так, щоб backend або API мо Тут `tokenUrl="token"` відноситься до відносної URL-адреси `token`, яку ми ще не створили. Оскільки це відносна URL-адреса, вона еквівалентна `./token`. -Тому, якщо ваш API розміщений на `https://example.com/`, це буде `https://example.com/token`. А якщо на `https://example.com/api/v1/`, тоді це буде `https://example.com/api/v1/token`. +Оскільки ми використовуємо відносну URL-адресу, якщо ваш API розміщений на `https://example.com/`, це буде `https://example.com/token`. А якщо ваш API розміщений на `https://example.com/api/v1/`, тоді це буде `https://example.com/api/v1/token`. Використання відносної URL-адреси важливе, щоб ваша програма продовжувала працювати навіть у просунутому сценарії, як-от [За представником](../../advanced/behind-a-proxy.md). @@ -188,7 +188,7 @@ oauth2_scheme(some, parameters) Вона шукатиме в запиті заголовок `Authorization`, перевірить, чи його значення - це `Bearer ` плюс деякий токен, і поверне токен як `str`. -Якщо заголовка `Authorization` немає або значення не містить токена `Bearer `, вона одразу відповість помилкою зі статус-кодом 401 (`UNAUTHORIZED`). +Якщо заголовка `Authorization` немає або значення не містить токена `Bearer `, вона одразу відповість помилкою з кодом статусу 401 (`UNAUTHORIZED`). Вам навіть не потрібно перевіряти, чи існує токен, щоб повернути помилку. Ви можете бути певні: якщо ваша функція виконується, у параметрі токена буде `str`. diff --git a/docs/uk/docs/tutorial/security/get-current-user.md b/docs/uk/docs/tutorial/security/get-current-user.md index b3643a439..1cd308534 100644 --- a/docs/uk/docs/tutorial/security/get-current-user.md +++ b/docs/uk/docs/tutorial/security/get-current-user.md @@ -1,6 +1,6 @@ # Отримати поточного користувача { #get-current-user } -У попередньому розділі система безпеки (яка базується на системі впровадження залежностей) передавала функції операції шляху `token` як `str`: +У попередньому розділі система безпеки (яка базується на системі впровадження залежностей) передавала *функції операції шляху* `token` як `str`: {* ../../docs_src/security/tutorial001_an_py310.py hl[12] *} @@ -14,7 +14,7 @@ Так само, як ми використовуємо Pydantic для оголошення тіл, ми можемо використовувати його будь-де: -{* ../../docs_src/security/tutorial002_an_py310.py hl[5,12:6] *} +{* ../../docs_src/security/tutorial002_an_py310.py hl[5,12:16] *} ## Створити залежність `get_current_user` { #create-a-get-current-user-dependency } @@ -24,19 +24,19 @@ `get_current_user` матиме залежність із тим самим `oauth2_scheme`, який ми створили раніше. -Так само, як ми робили раніше безпосередньо в операції шляху, наша нова залежність `get_current_user` отримає `token` як `str` від підзалежності `oauth2_scheme`: +Так само, як ми робили раніше безпосередньо в *операції шляху*, наша нова залежність `get_current_user` отримає `token` як `str` від підзалежності `oauth2_scheme`: {* ../../docs_src/security/tutorial002_an_py310.py hl[25] *} ## Отримати користувача { #get-the-user } -`get_current_user` використає (фальшиву) утилітну функцію, яку ми створили, що приймає `token` як `str` і повертає нашу Pydantic-модель `User`: +`get_current_user` використає (фальшиву) утилітну функцію, яку ми створили, що приймає токен як `str` і повертає нашу Pydantic-модель `User`: {* ../../docs_src/security/tutorial002_an_py310.py hl[19:22,26:27] *} ## Впровадити поточного користувача { #inject-the-current-user } -Тепер ми можемо використати той самий `Depends` з нашим `get_current_user` в операції шляху: +Тепер ми можемо використати той самий `Depends` з нашим `get_current_user` в *операції шляху*: {* ../../docs_src/security/tutorial002_an_py310.py hl[31] *} @@ -62,13 +62,13 @@ ## Інші моделі { #other-models } -Тепер ви можете отримувати поточного користувача безпосередньо у функціях операцій шляху та працювати з механізмами безпеки на рівні **впровадження залежностей**, використовуючи `Depends`. +Тепер ви можете отримувати поточного користувача безпосередньо у *функціях операцій шляху* та працювати з механізмами безпеки на рівні **впровадження залежностей**, використовуючи `Depends`. І ви можете використовувати будь-яку модель або дані для вимог безпеки (у цьому випадку Pydantic-модель `User`). -Але ви не обмежені використанням якоїсь конкретної модели даних, класу чи типу. +Але ви не обмежені використанням якоїсь конкретної моделі даних, класу чи типу. -Хочете мати id та email і не мати жодного username у вашій моделі? Без проблем. Ви можете використовувати ті самі інструменти. +Хочете мати `id` та `email` і не мати жодного `username` у вашій моделі? Без проблем. Ви можете використовувати ті самі інструменти. Хочете мати просто `str`? Або лише `dict`? Або безпосередньо екземпляр класу моделі бази даних? Усе працює так само. @@ -78,7 +78,7 @@ ## Розмір коду { #code-size } -Цей приклад може здаватися багатослівним. Майте на увазі, що ми змішуємо безпеку, моделі даних, утилітні функції та операції шляху в одному файлі. +Цей приклад може здаватися багатослівним. Майте на увазі, що ми змішуємо безпеку, моделі даних, утилітні функції та *операції шляху* в одному файлі. Але ось ключовий момент. @@ -86,20 +86,20 @@ І ви можете зробити це настільки складним, наскільки потрібно. І все одно мати це написаним лише один раз, в одному місці. З усією гнучкістю. -Зате ви можете мати тисячі кінцевих точок (операцій шляху), що використовують одну й ту саму систему безпеки. +Зате ви можете мати тисячі кінцевих точок (*операцій шляху*), що використовують одну й ту саму систему безпеки. І всі вони (або будь-яка їхня частина, яку ви захочете) можуть скористатися повторним використанням цих залежностей або будь-яких інших, які ви створите. -І всі ці тисячі операцій шляху можуть бути всього у 3 рядки: +І всі ці тисячі *операцій шляху* можуть бути всього у 3 рядки: {* ../../docs_src/security/tutorial002_an_py310.py hl[30:32] *} ## Підсумок { #recap } -Тепер ви можете отримувати поточного користувача безпосередньо у вашій функції операції шляху. +Тепер ви можете отримувати поточного користувача безпосередньо у вашій *функції операції шляху*. Ми вже на півдорозі. -Потрібно лише додати операцію шляху, щоб користувач/клієнт міг фактично надіслати `username` і `password`. +Потрібно лише додати *операцію шляху*, щоб користувач/клієнт міг фактично надіслати `username` і `password`. Далі саме це. diff --git a/docs/uk/docs/tutorial/security/oauth2-jwt.md b/docs/uk/docs/tutorial/security/oauth2-jwt.md index 1213afe7b..1fb53ff41 100644 --- a/docs/uk/docs/tutorial/security/oauth2-jwt.md +++ b/docs/uk/docs/tutorial/security/oauth2-jwt.md @@ -10,7 +10,7 @@ JWT означає «JSON Web Tokens». -Це стандарт кодування об'єкта JSON у довгий щільний рядок без пробілів. Він виглядає так: +Це стандарт кодування об'єкта JSON у довгу щільну строку без пробілів. Він виглядає так: ``` eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c @@ -168,7 +168,7 @@ $ openssl rand -hex 32 {* ../../docs_src/security/tutorial004_an_py310.py hl[93:110] *} -## Оновіть операцію шляху `/token` { #update-the-token-path-operation } +## Оновіть *операцію шляху* `/token` { #update-the-token-path-operation } Створіть `timedelta` з часом життя токена. diff --git a/docs/uk/docs/tutorial/security/simple-oauth2.md b/docs/uk/docs/tutorial/security/simple-oauth2.md index 686839982..7500792cc 100644 --- a/docs/uk/docs/tutorial/security/simple-oauth2.md +++ b/docs/uk/docs/tutorial/security/simple-oauth2.md @@ -28,9 +28,9 @@ OAuth2 визначає, що під час використання «пото Їх зазвичай використовують для оголошення конкретних прав доступу, наприклад: -- `users:read` або `users:write` — поширені приклади. -- `instagram_basic` використовується Facebook / Instagram. -- `https://www.googleapis.com/auth/drive` використовується Google. +* `users:read` або `users:write` — поширені приклади. +* `instagram_basic` використовується Facebook / Instagram. +* `https://www.googleapis.com/auth/drive` використовується Google. /// note | Примітка @@ -56,21 +56,21 @@ OAuth2 визначає, що під час використання «пото `OAuth2PasswordRequestForm` — це клас залежності, що оголошує тіло форми з: -- `username`. -- `password`. -- Необов'язковим полем `scope` як великою строкою, складеною зі строк, розділених пробілами. -- Необов'язковим `grant_type`. +* `username`. +* `password`. +* Необов'язковим полем `scope` як великою строкою, складеною зі строк, розділених пробілами. +* Необов'язковим `grant_type`. /// tip | Порада -Специфікація OAuth2 насправді вимагає поле `grant_type` із фіксованим значенням `password`, але `OAuth2PasswordRequestForm` цього не примушує. +Специфікація OAuth2 насправді *вимагає* поле `grant_type` із фіксованим значенням `password`, але `OAuth2PasswordRequestForm` цього не примушує. Якщо вам потрібно це примусити, використовуйте `OAuth2PasswordRequestFormStrict` замість `OAuth2PasswordRequestForm`. /// -- Необов'язковим `client_id` (для нашого прикладу не потрібно). -- Необов'язковим `client_secret` (для нашого прикладу не потрібно). +* Необов'язковим `client_id` (для нашого прикладу не потрібно). +* Необов'язковим `client_secret` (для нашого прикладу не потрібно). /// note | Примітка @@ -132,7 +132,7 @@ OAuth2 визначає, що під час використання «пото `UserInDB(**user_dict)` означає: -Передати ключі та значення з `user_dict` безпосередньо як аргументи ключ-значення, еквівалентно до: +*Передати ключі та значення з `user_dict` безпосередньо як аргументи ключ-значення, еквівалентно до:* ```Python UserInDB( @@ -146,7 +146,7 @@ UserInDB( /// note | Примітка -Для повнішого пояснення `**user_dict` перегляньте [документацію для **Додаткових моделей**](../extra-models.md#about-user-in-dict). +Для повнішого пояснення `**user_dict` перегляньте [документацію для **Додаткових моделей**](../extra-models.md#about-user-in-model-dump). /// @@ -186,7 +186,7 @@ UserInDB( Тепер оновимо наші залежності. -Ми хочемо отримати `current_user` лише якщо цей користувач активний. +Ми хочемо отримати `current_user` *лише* якщо цей користувач активний. Тому створимо додаткову залежність `get_current_active_user`, яка своєю чергою використовує як залежність `get_current_user`. @@ -200,7 +200,7 @@ UserInDB( Додатковий заголовок `WWW-Authenticate` зі значенням `Bearer`, який ми тут повертаємо, також є частиною специфікації. -Будь-який HTTP (помилка) зі статус-кодом 401 «UNAUTHORIZED» також має повертати заголовок `WWW-Authenticate`. +Будь-який HTTP (помилка) з кодом статусу 401 «UNAUTHORIZED» також має повертати заголовок `WWW-Authenticate`. У випадку токенів носія (наш випадок) значенням цього заголовка має бути `Bearer`. diff --git a/docs/uk/docs/tutorial/sql-databases.md b/docs/uk/docs/tutorial/sql-databases.md index 57b67226a..ff294052c 100644 --- a/docs/uk/docs/tutorial/sql-databases.md +++ b/docs/uk/docs/tutorial/sql-databases.md @@ -1,6 +1,6 @@ # SQL (реляційні) бази даних { #sql-relational-databases } -**FastAPI** не вимагає від вас використовувати SQL (реляційну) базу даних. Але ви можете скористатися будь-якою базою даних, яку забажаєте. +**FastAPI** не вимагає від вас використовувати SQL (реляційну) базу даних. Але ви можете скористатися **будь-якою базою даних**, яку забажаєте. Тут ми розглянемо приклад з [SQLModel](https://sqlmodel.tiangolo.com/). @@ -8,7 +8,7 @@ /// tip | Порада -Ви можете використовувати будь-яку іншу бібліотеку для SQL або NoSQL баз (інколи їх називають "ORMs"), FastAPI нічого не нав’язує. 😎 +Ви можете використовувати будь-яку іншу бібліотеку для SQL або NoSQL баз (інколи їх називають «ORMs»), FastAPI нічого не нав’язує. 😎 /// @@ -65,7 +65,7 @@ $ pip install sqlmodel * `Field(primary_key=True)` каже SQLModel, що `id` - це **первинний ключ** у SQL базі даних (більше про первинні ключі в SQL див. у документації SQLModel). - Примітка: Ми використовуємо `int | None` для поля первинного ключа, щоб у Python-коді можна було створити об’єкт без `id` (`id=None`), припускаючи, що база даних згенерує його під час збереження. SQLModel розуміє, що `id` надасть база даних, і визначає стовпець як ненульовий `INTEGER` у схемі бази даних. Докладніше див. [документацію SQLModel про первинні ключі](https://sqlmodel.tiangolo.com/tutorial/create-db-and-table/#primary-key-id). + **Примітка:** Ми використовуємо `int | None` для поля первинного ключа, щоб у Python-коді можна було створити об’єкт без `id` (`id=None`), припускаючи, що база даних згенерує його під час збереження. SQLModel розуміє, що `id` надасть база даних, і визначає стовпець як ненульовий `INTEGER` у схемі бази даних. Докладніше див. [документацію SQLModel про первинні ключі](https://sqlmodel.tiangolo.com/tutorial/create-db-and-table/#primary-key-id). * `Field(index=True)` каже SQLModel створити **SQL-індекс** для цього стовпця, що дозволить швидше виконувати пошук у базі даних під час читання даних, відфільтрованих за цим стовпцем. diff --git a/docs/uk/docs/tutorial/static-files.md b/docs/uk/docs/tutorial/static-files.md index 2141744c3..26c3c592a 100644 --- a/docs/uk/docs/tutorial/static-files.md +++ b/docs/uk/docs/tutorial/static-files.md @@ -2,10 +2,18 @@ Ви можете автоматично надавати статичні файли з каталогу, використовуючи `StaticFiles`. +/// tip | Порада + +Якщо вам потрібно розмістити фронтенд, натомість використовуйте `app.frontend()`, прочитайте про це у [Frontend](frontend.md). + +`app.frontend()` використовує `StaticFiles` всередині, з кількома додатковими перевагами для фронтендів, як-от обробка клієнтської маршрутизації. + +/// + ## Використання `StaticFiles` { #use-staticfiles } * Імпортуйте `StaticFiles`. -* «Під'єднати» екземпляр `StaticFiles()` з вказанням необхідного шляху. +* «Змонтуйте» екземпляр `StaticFiles()` у певному шляху. {* ../../docs_src/static_files/tutorial001_py310.py hl[2,6] *} @@ -17,24 +25,24 @@ /// -### Що таке «Під'єднання» { #what-is-mounting } +### Що таке «Монтування» { #what-is-mounting } -«Під'єднання» означає додавання повноцінного «незалежного» застосунку за певним шляхом, який потім обробляє всі під шляхи. +«Монтування» означає додавання повноцінного «незалежного» застосунку за певним шляхом, який потім відповідає за обробку всіх підшляхів. -Це відрізняється від використання `APIRouter`, оскільки під'єднаний застосунок є повністю незалежним. OpenAPI та документація вашого основного застосунку не будуть знати нічого про ваш під'єднаний застосунок тощо. +Це відрізняється від використання `APIRouter`, оскільки змонтований застосунок є повністю незалежним. OpenAPI та документація вашого основного застосунку не включатимуть нічого зі змонтованого застосунку тощо. -Ви можете дізнатися більше про це в [Посібнику для просунутих користувачів](../advanced/index.md). +Ви можете дізнатися більше про це в [Просунутому посібнику користувача](../advanced/index.md). ## Деталі { #details } -Перше `"/static"` вказує на під шлях, за яким буде «під'єднано» цей новий «підзастосунок». Тому будь-який шлях, який починається з `"/static"`, буде оброблятися ним. +Перше `"/static"` стосується підшляху, на якому буде «змонтовано» цей «підзастосунок». Тому будь-який шлях, який починається з `"/static"`, буде оброблятися ним. `directory="static"` визначає назву каталогу, що містить ваші статичні файли. -`name="static"` це ім'я, яке можна використовувати всередині **FastAPI**. +`name="static"` надає йому ім'я, яке можна використовувати всередині **FastAPI**. Усі ці параметри можуть бути іншими за "`static`", налаштуйте їх відповідно до потреб і особливостей вашого застосунку. ## Додаткова інформація { #more-info } -Детальніше про налаштування та можливості можна дізнатися в [документації Starlette про статичні файли](https://www.starlette.dev/staticfiles/). +Для отримання додаткової інформації та параметрів перевірте [документацію Starlette про Static Files](https://www.starlette.dev/staticfiles/). diff --git a/docs/uk/docs/tutorial/testing.md b/docs/uk/docs/tutorial/testing.md index 059e5cec0..393855a0c 100644 --- a/docs/uk/docs/tutorial/testing.md +++ b/docs/uk/docs/tutorial/testing.md @@ -52,7 +52,7 @@ $ pip install httpx /// tip | Порада -Якщо ви хочете викликати `async`-функції у ваших тестах, окрім відправлення запитів до вашого застосунку FastAPI (наприклад, асинхронні функції роботи з базою даних), перегляньте [Async Tests](../advanced/async-tests.md) у розширеному керівництві. +Якщо ви хочете викликати `async`-функції у ваших тестах, окрім відправлення запитів до вашого застосунку FastAPI (наприклад, асинхронні функції роботи з базою даних), перегляньте [Асинхронні тести](../advanced/async-tests.md) у просунутому навчальному посібнику. /// @@ -64,7 +64,7 @@ $ pip install httpx ### Файл застосунку **FastAPI** { #fastapi-app-file } -Припустимо, у вас є структура файлів, описана в розділі [Bigger Applications](bigger-applications.md): +Припустимо, у вас є структура файлів, описана в розділі [Більші застосунки](bigger-applications.md): ``` . @@ -130,17 +130,17 @@ $ pip install httpx {* ../../docs_src/app_testing/app_b_an_py310/test_main.py *} -Коли вам потрібно передати клієнту інформацію в запиті, але ви не знаєте, як це зробити, ви можете пошукати (Google), як це зробити в `httpx`, або навіть як це зробити з `requests`, оскільки дизайн HTTPX базується на дизайні Requests. +Коли вам потрібно, щоб клієнт передав інформацію в запиті, але ви не знаєте, як це зробити, ви можете пошукати (Google), як це зробити в `httpx`, або навіть як це зробити з `requests`, оскільки дизайн HTTPX базується на дизайні Requests. Далі ви просто повторюєте ці ж дії у ваших тестах. Наприклад: -* Щоб передати *path* або *query* параметр, додайте його безпосередньо до URL. +* Щоб передати параметр *шляху* або *запиту*, додайте його безпосередньо до URL. * Щоб передати тіло JSON, передайте Python-об'єкт (наприклад, `dict`) у параметр `json`. -* Якщо потрібно надіслати *Form Data* замість JSON, використовуйте параметр `data`. -* Щоб передати заголовки *headers*, використовуйте `dict` у параметрі `headers`. -* Для *cookies* використовуйте `dict` у параметрі `cookies`. +* Якщо потрібно надіслати *дані форми* замість JSON, використовуйте параметр `data`. +* Щоб передати *заголовки*, використовуйте `dict` у параметрі `headers`. +* Для *кукі* використовуйте `dict` у параметрі `cookies`. Докладніше про передачу даних у бекенд (за допомогою `httpx` або `TestClient`) можна знайти в [документації HTTPX](https://www.python-httpx.org). @@ -148,7 +148,7 @@ $ pip install httpx Зверніть увагу, що `TestClient` отримує дані, які можна конвертувати в JSON, а не Pydantic-моделі. -Якщо у вас є Pydantic-модель у тесті, і ви хочете передати її дані в застосунок під час тестування, ви можете використати `jsonable_encoder`, описаний у розділі [JSON Compatible Encoder](encoder.md). +Якщо у вас є Pydantic-модель у тесті, і ви хочете передати її дані в застосунок під час тестування, ви можете використати `jsonable_encoder`, описаний у розділі [JSON-сумісний кодувальник](encoder.md). /// diff --git a/docs/uk/docs/virtual-environments.md b/docs/uk/docs/virtual-environments.md index 26ad6b0cb..57f3e90df 100644 --- a/docs/uk/docs/virtual-environments.md +++ b/docs/uk/docs/virtual-environments.md @@ -1,6 +1,6 @@ # Віртуальні середовища { #virtual-environments } -Коли ви працюєте над проєктами Python, вам, імовірно, слід використовувати віртуальне середовище (або схожий механізм), щоб ізолювати пакети, які ви встановлюєте для кожного проєкту. +Коли ви працюєте над проєктами Python, вам, імовірно, слід використовувати **віртуальне середовище** (або схожий механізм), щоб ізолювати пакети, які ви встановлюєте для кожного проєкту. /// note | Примітка @@ -10,19 +10,19 @@ /// tip | Порада -Віртуальне середовище відрізняється від змінної оточення. +**Віртуальне середовище** відрізняється від **змінної оточення**. -Змінна оточення - це змінна в системі, яку можуть використовувати програми. +**Змінна оточення** - це змінна в системі, яку можуть використовувати програми. -Віртуальне середовище - це каталог із файлами в ньому. +**Віртуальне середовище** - це каталог із файлами в ньому. /// /// note | Примітка -На цій сторінці ви дізнаєтеся, як використовувати віртуальні середовища і як вони працюють. +На цій сторінці ви дізнаєтеся, як використовувати **віртуальні середовища** і як вони працюють. -Якщо ви готові прийняти інструмент, що керує всім за вас (включно з установленням Python), спробуйте [uv](https://github.com/astral-sh/uv). +Якщо ви готові прийняти **інструмент, що керує всім** за вас (включно з установленням Python), спробуйте [uv](https://github.com/astral-sh/uv). /// @@ -53,11 +53,11 @@ $ cd awesome-project ## Створіть віртуальне середовище { #create-a-virtual-environment } -Коли ви починаєте працювати над проєктом Python уперше, створіть віртуальне середовище у вашому проєкті **у вашому проєкті**. +Коли ви починаєте працювати над проєктом Python **уперше**, створіть віртуальне середовище **у вашому проєкті**. /// tip | Порада -Це потрібно робити лише один раз на проєкт, не щоразу, коли ви працюєте. +Це потрібно робити лише **один раз на проєкт**, не щоразу, коли ви працюєте. /// @@ -120,7 +120,7 @@ $ uv venv /// tip | Порада -Робіть це щоразу, коли ви починаєте нову сесію термінала для роботи над проєктом. +Робіть це **щоразу**, коли ви починаєте **нову сесію термінала** для роботи над проєктом. /// @@ -164,9 +164,9 @@ $ source .venv/Scripts/activate /// tip | Порада -Кожного разу, коли ви встановлюєте новий пакет у це середовище, активуйте середовище знову. +Кожного разу, коли ви встановлюєте **новий пакет** у це середовище, **активуйте** середовище знову. -Це гарантує, що якщо ви використовуєте програму термінала (CLI), встановлену цим пакетом, ви використовуєте саме ту з вашого віртуального середовища, а не будь-яку іншу, яка може бути встановлена глобально, імовірно з іншою версією, ніж вам потрібно. +Це гарантує, що якщо ви використовуєте **програму термінала (CLI)**, встановлену цим пакетом, ви використовуєте саме ту з вашого віртуального середовища, а не будь-яку іншу, яка може бути встановлена глобально, імовірно з іншою версією, ніж вам потрібно. /// @@ -176,7 +176,7 @@ $ source .venv/Scripts/activate /// tip | Порада -Це необов'язково, але це гарний спосіб перевірити, що все працює як очікується і ви використовуєте саме те віртуальне середовище, яке планували. +Це **необов'язково**, але це гарний спосіб **перевірити**, що все працює як очікується і ви використовуєте саме те віртуальне середовище, яке планували. /// @@ -220,13 +220,13 @@ C:\Users\user\code\awesome-project\.venv\Scripts\python /// -Якщо ви використовуєте `pip` для встановлення пакетів (він іде за замовчуванням із Python), вам слід оновити його до найновішої версії. +Якщо ви використовуєте `pip` для встановлення пакетів (він іде за замовчуванням із Python), вам слід **оновити** його до найновішої версії. Багато дивних помилок під час встановлення пакета вирішуються тим, що спочатку оновлюють `pip`. /// tip | Порада -Зазвичай це роблять один раз, відразу після створення віртуального середовища. +Зазвичай це роблять **один раз**, відразу після створення віртуального середовища. /// @@ -264,7 +264,7 @@ $ python -m ensurepip --upgrade ## Додайте `.gitignore` { #add-gitignore } -Якщо ви використовуєте Git (варто це робити), додайте файл `.gitignore`, щоб виключити з Git усе у вашому `.venv`. +Якщо ви використовуєте **Git** (варто це робити), додайте файл `.gitignore`, щоб виключити з Git усе у вашому `.venv`. /// tip | Порада @@ -274,7 +274,7 @@ $ python -m ensurepip --upgrade /// tip | Порада -Зробіть це один раз, відразу після створення віртуального середовища. +Зробіть це **один раз**, відразу після створення віртуального середовища. /// @@ -308,9 +308,9 @@ $ echo "*" > .venv/.gitignore /// tip | Порада -Робіть це один раз під час встановлення або оновлення пакетів, потрібних вашому проєкту. +Робіть це **один раз** під час встановлення або оновлення пакетів, потрібних вашому проєкту. -Якщо вам потрібно оновити версію або додати новий пакет, ви зробите це знову. +Якщо вам потрібно оновити версію або додати новий пакет, ви **зробите це знову**. /// @@ -421,13 +421,13 @@ Hello World /// tip | Порада -Зазвичай це потрібно робити лише один раз, коли ви створюєте віртуальне середовище. +Зазвичай це потрібно робити лише **один раз**, коли ви створюєте віртуальне середовище. /// ## Деактивуйте віртуальне середовище { #deactivate-the-virtual-environment } -Коли ви завершили роботу над проєктом, ви можете деактивувати віртуальне середовище. +Коли ви завершили роботу над проєктом, ви можете **деактивувати** віртуальне середовище.
@@ -443,6 +443,8 @@ $ deactivate Тепер ви готові почати працювати над вашим проєктом. + + /// tip | Порада Хочете зрозуміти, що це все було вище? @@ -455,33 +457,33 @@ $ deactivate Щоб працювати з FastAPI, вам потрібно встановити [Python](https://www.python.org/). -Після цього вам потрібно буде встановити FastAPI та інші пакети, які ви хочете використовувати. +Після цього вам потрібно буде **встановити** FastAPI та інші **пакети**, які ви хочете використовувати. Для встановлення пакетів зазвичай використовують команду `pip`, що постачається з Python (або схожі альтернативи). -Однак, якщо ви просто користуватиметеся `pip` напряму, пакети встановлюватимуться у ваше глобальне середовище Python (глобальну інсталяцію Python). +Однак, якщо ви просто користуватиметеся `pip` напряму, пакети встановлюватимуться у ваше **глобальне середовище Python** (глобальну інсталяцію Python). ### Проблема { #the-problem } То в чому ж проблема встановлення пакетів у глобальне середовище Python? -З часом ви, вірогідно, писатимете багато різних програм, які залежать від різних пакетів. І деякі з цих ваших проєктів залежатимуть від різних версій одного й того ж пакета. 😱 +З часом ви, вірогідно, писатимете багато різних програм, які залежать від **різних пакетів**. І деякі з цих ваших проєктів залежатимуть від **різних версій** одного й того ж пакета. 😱 -Наприклад, ви можете створити проєкт із назвою `philosophers-stone`, ця програма залежить від іншого пакета з назвою `harry`, використовуючи версію `1`. Тож вам потрібно встановити `harry`. +Наприклад, ви можете створити проєкт із назвою `philosophers-stone`, ця програма залежить від іншого пакета з назвою **`harry`, використовуючи версію `1`**. Тож вам потрібно встановити `harry`. ```mermaid flowchart LR stone(philosophers-stone) -->|requires| harry-1[harry v1] ``` -Потім, трохи згодом, ви створюєте інший проєкт із назвою `prisoner-of-azkaban`, і цей проєкт також залежить від `harry`, але йому потрібна версія `harry` `3`. +Потім, трохи згодом, ви створюєте інший проєкт із назвою `prisoner-of-azkaban`, і цей проєкт також залежить від `harry`, але йому потрібна **версія `harry` `3`**. ```mermaid flowchart LR azkaban(prisoner-of-azkaban) --> |requires| harry-3[harry v3] ``` -Але тепер проблема в тому, що якщо ви встановлюєте пакети глобально (у глобальне середовище), а не у локальне віртуальне середовище, вам доведеться вибирати, яку версію `harry` встановити. +Але тепер проблема в тому, що якщо ви встановлюєте пакети глобально (у глобальне середовище), а не у локальне **віртуальне середовище**, вам доведеться вибирати, яку версію `harry` встановити. Якщо ви хочете запустити `philosophers-stone`, вам спочатку потрібно встановити `harry` версії `1`, наприклад, так: @@ -517,7 +519,7 @@ $ pip install "harry==3" У підсумку у вас буде встановлено `harry` версії `3` у глобальному середовищі Python. -А якщо ви знову спробуєте запустити `philosophers-stone`, є шанс, що він не працюватиме, тому що йому потрібен `harry` версії `1`. +А якщо ви знову спробуєте запустити `philosophers-stone`, є шанс, що він **не працюватиме**, тому що йому потрібен `harry` версії `1`. ```mermaid flowchart LR @@ -536,13 +538,13 @@ flowchart LR /// tip | Порада -У пакетах Python дуже поширена практика намагатися якнайкраще уникати несумісних змін у нових версіях, але краще підстрахуватися та встановлювати новіші версії свідомо і тоді, коли ви можете запустити тести, щоб перевірити, що все працює коректно. +У пакетах Python дуже поширена практика намагатися якнайкраще **уникати несумісних змін** у **нових версіях**, але краще підстрахуватися та встановлювати новіші версії свідомо і тоді, коли ви можете запустити тести, щоб перевірити, що все працює коректно. /// -Тепер уявіть те саме з багатьма іншими пакетами, від яких залежать усі ваші проєкти. Це дуже складно керувати. І ви, імовірно, запускатимете деякі проєкти з деякими несумісними версіями пакетів і не розумітимете, чому щось не працює. +Тепер уявіть те саме з **багатьма** іншими **пакетами**, від яких залежать усі ваші **проєкти**. Це дуже складно керувати. І ви, імовірно, запускатимете деякі проєкти з деякими **несумісними версіями** пакетів і не розумітимете, чому щось не працює. -Також, залежно від вашої операційної системи (напр., Linux, Windows, macOS), у ній може бути вже встановлений Python. І в такому разі, імовірно, уже будуть попередньо встановлені деякі пакети з певними версіями, потрібними вашій системі. Якщо ви встановлюєте пакети в глобальне середовище Python, ви можете зламати деякі програми, що постачаються з вашою операційною системою. +Також, залежно від вашої операційної системи (напр., Linux, Windows, macOS), у ній може бути вже встановлений Python. І в такому разі, імовірно, уже будуть попередньо встановлені деякі пакети з певними версіями, **потрібними вашій системі**. Якщо ви встановлюєте пакети в глобальне середовище Python, ви можете **зламати** деякі програми, що постачаються з вашою операційною системою. ## Де встановлюються пакети { #where-are-packages-installed } @@ -564,17 +566,17 @@ $ pip install "fastapi[standard]" Це завантажить стиснений файл з кодом FastAPI, зазвичай із [PyPI](https://pypi.org/project/fastapi/). -Також будуть завантажені файли для інших пакетів, від яких залежить FastAPI. +Також будуть **завантажені** файли для інших пакетів, від яких залежить FastAPI. -Потім усе це буде розпаковано та покладено в каталог на вашому комп'ютері. +Потім усе це буде **розпаковано** та покладено в каталог на вашому комп'ютері. -Типово ці завантажені та розпаковані файли будуть покладені в каталог, що постачається з вашою інсталяцією Python, це глобальне середовище. +Типово ці завантажені та розпаковані файли будуть покладені в каталог, що постачається з вашою інсталяцією Python, це **глобальне середовище**. ## Що таке віртуальні середовища { #what-are-virtual-environments } -Рішенням проблеми з наявністю всіх пакетів у глобальному середовищі є використання віртуального середовища для кожного проєкту, над яким ви працюєте. +Рішенням проблеми з наявністю всіх пакетів у глобальному середовищі є використання **віртуального середовища для кожного проєкту**, над яким ви працюєте. -Віртуальне середовище - це каталог, дуже схожий на глобальний, у якому ви можете встановлювати пакети для конкретного проєкту. +Віртуальне середовище - це **каталог**, дуже схожий на глобальний, у якому ви можете встановлювати пакети для конкретного проєкту. Таким чином кожен проєкт матиме власне віртуальне середовище (каталог `.venv`) із власними пакетами. @@ -637,7 +639,7 @@ $ source .venv/Scripts/activate //// -Ця команда створить або змінить деякі [Змінні оточення](environment-variables.md), які будуть доступні для наступних команд. +Ця команда створить або змінить деякі [змінні оточення](environment-variables.md), які будуть доступні для наступних команд. Однією з цих змінних є змінна `PATH`. @@ -728,7 +730,7 @@ C:\Users\user\code\awesome-project\.venv\Scripts\python //// -Важлива деталь: шлях до віртуального середовища буде додано на початок змінної `PATH`. Система знайде його раніше за будь-який інший доступний Python. Таким чином, коли ви запускаєте `python`, використовується саме Python із віртуального середовища, а не будь-який інший `python` (наприклад, з глобального середовища). +Важлива деталь: шлях до віртуального середовища буде додано на **початок** змінної `PATH`. Система знайде його **раніше** за будь-який інший доступний Python. Таким чином, коли ви запускаєте `python`, використовується саме Python **із віртуального середовища**, а не будь-який інший `python` (наприклад, з глобального середовища). Активація віртуального середовища також змінює ще кілька речей, але це одна з найважливіших. @@ -764,11 +766,11 @@ C:\Users\user\code\awesome-project\.venv\Scripts\python //// -Це означає, що програма `python`, яка буде використана, знаходиться у віртуальному середовищі. +Це означає, що програма `python`, яка буде використана, знаходиться **у віртуальному середовищі**. На Linux і macOS використовують `which`, а в Windows PowerShell - `Get-Command`. -Принцип роботи цієї команди в тому, що вона перевіряє змінну оточення `PATH`, проходячи по кожному шляху по порядку, шукаючи програму з назвою `python`. Щойно вона її знайде, вона покаже вам шлях до цієї програми. +Принцип роботи цієї команди в тому, що вона перевіряє змінну оточення `PATH`, проходячи по **кожному шляху по порядку**, шукаючи програму з назвою `python`. Щойно вона її знайде, вона **покаже вам шлях** до цієї програми. Найважливіше, що коли ви викликаєте `python`, це рівно той «`python`», який буде виконаний. @@ -776,9 +778,9 @@ C:\Users\user\code\awesome-project\.venv\Scripts\python /// tip | Порада -Легко активувати одне віртуальне середовище, отримати один Python, а потім перейти до іншого проєкту. +Легко активувати одне віртуальне середовище, отримати один Python, а потім **перейти до іншого проєкту**. -І другий проєкт не працюватиме, бо ви використовуєте некоректний Python з віртуального середовища іншого проєкту. +І другий проєкт **не працюватиме**, бо ви використовуєте **некоректний Python** з віртуального середовища іншого проєкту. Корисно вміти перевіряти, який саме `python` використовується. 🤓 @@ -786,9 +788,9 @@ C:\Users\user\code\awesome-project\.venv\Scripts\python ## Навіщо деактивувати віртуальне середовище { #why-deactivate-a-virtual-environment } -Наприклад, ви працюєте над проєктом `philosophers-stone`, активували його віртуальне середовище, встановили пакети та працюєте з цим середовищем. +Наприклад, ви працюєте над проєктом `philosophers-stone`, **активували його віртуальне середовище**, встановили пакети та працюєте з цим середовищем. -А потім ви хочете працювати над іншим проєктом `prisoner-of-azkaban`. +А потім ви хочете працювати над **іншим проєктом** `prisoner-of-azkaban`. Ви переходите до цього проєкту: @@ -840,23 +842,23 @@ I solemnly swear 🐺 ## Альтернативи { #alternatives } -Це простий посібник, щоб ви швидко стартували та зрозуміли, як усе працює «під капотом». +Це простий посібник, щоб ви швидко стартували та зрозуміли, як усе працює **«під капотом»**. -Існує багато альтернатив керування віртуальними середовищами, залежностями пакетів (вимогами), проєктами. +Існує багато **альтернатив** керування віртуальними середовищами, залежностями пакетів (вимогами), проєктами. -Коли будете готові й захочете використовувати інструмент для керування всім проєктом, залежностями пакетів, віртуальними середовищами тощо, я раджу спробувати [uv](https://github.com/astral-sh/uv). +Коли будете готові й захочете використовувати інструмент для **керування всім проєктом**, залежностями пакетів, віртуальними середовищами тощо, я раджу спробувати [uv](https://github.com/astral-sh/uv). `uv` уміє багато чого, зокрема: -* Встановлювати Python для вас, включно з різними версіями -* Керувати віртуальним середовищем ваших проєктів -* Встановлювати пакети -* Керувати залежностями пакетів і версіями у вашому проєкті -* Гарантувати, що у вас є точний набір пакетів і версій для встановлення, включно з їхніми залежностями, щоб ви були певні, що зможете запустити ваш проєкт у продакшені точно так само, як і на вашому комп'ютері під час розробки - це називається блокуванням +* **Встановлювати Python** для вас, включно з різними версіями +* Керувати **віртуальним середовищем** ваших проєктів +* Встановлювати **пакети** +* Керувати **залежностями і версіями** пакетів у вашому проєкті +* Гарантувати, що у вас є **точний** набір пакетів і версій для встановлення, включно з їхніми залежностями, щоб ви були певні, що зможете запустити ваш проєкт у продакшені точно так само, як і на вашому комп'ютері під час розробки - це називається **блокуванням** * І багато іншого ## Висновок { #conclusion } -Якщо ви все це прочитали й зрозуміли, тепер ви знаєте значно більше про віртуальні середовища, ніж багато розробників. 🤓 +Якщо ви все це прочитали й зрозуміли, тепер **ви знаєте значно більше** про віртуальні середовища, ніж багато розробників. 🤓 -Знання цих деталей, найімовірніше, стане в пригоді в майбутньому, коли ви налагоджуватимете щось, що виглядає складним, але ви знатимете, як усе працює «під капотом». 😎 +Знання цих деталей, найімовірніше, стане в пригоді в майбутньому, коли ви налагоджуватимете щось, що виглядає складним, але ви знатимете, **як усе працює «під капотом»**. 😎 From 2b5cf661cab461072b910f26bdc8d2e6512abe13 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Wed, 1 Jul 2026 13:27:56 +0000 Subject: [PATCH 365/462] =?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 4f71bbb5a..7aafc7f50 100644 --- a/docs/en/docs/release-notes.md +++ b/docs/en/docs/release-notes.md @@ -9,6 +9,7 @@ hide: ### Translations +* 🌐 Update translations for uk (update-outdated). PR [#15900](https://github.com/fastapi/fastapi/pull/15900) by [@tiangolo](https://github.com/tiangolo). * 🌐 Update translations for ko (update-outdated). PR [#15890](https://github.com/fastapi/fastapi/pull/15890) by [@tiangolo](https://github.com/tiangolo). * 🌐 Update translations for ru (update-outdated). PR [#15894](https://github.com/fastapi/fastapi/pull/15894) by [@tiangolo](https://github.com/tiangolo). * 🌐 Update translations for ko (add-missing). PR [#15888](https://github.com/fastapi/fastapi/pull/15888) by [@tiangolo](https://github.com/tiangolo). From 6119d875861a1ff1d4f4352fe6c87c42a8d820dc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebasti=C3=A1n=20Ram=C3=ADrez?= Date: Wed, 1 Jul 2026 15:35:53 +0200 Subject: [PATCH 366/462] =?UTF-8?q?=F0=9F=8C=90=20Update=20translations=20?= =?UTF-8?q?for=20zh=20(update-outdated)=20(#15898)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: github-actions[bot] Co-authored-by: Yurii Motov --- docs/zh/docs/_llm-test.md | 488 +++++++++--------- .../docs/advanced/additional-status-codes.md | 4 +- .../zh/docs/advanced/advanced-dependencies.md | 1 + docs/zh/docs/advanced/dataclasses.md | 1 + docs/zh/docs/advanced/events.md | 1 + docs/zh/docs/advanced/generate-clients.md | 26 +- docs/zh/docs/advanced/json-base64-bytes.md | 8 +- docs/zh/docs/advanced/openapi-callbacks.md | 106 ++-- .../advanced/response-change-status-code.md | 2 +- docs/zh/docs/advanced/response-cookies.md | 34 +- docs/zh/docs/advanced/response-headers.md | 1 + .../docs/advanced/security/oauth2-scopes.md | 4 +- docs/zh/docs/advanced/settings.md | 6 +- docs/zh/docs/advanced/stream-data.md | 10 +- docs/zh/docs/advanced/wsgi.md | 1 + docs/zh/docs/alternatives.md | 11 +- docs/zh/docs/async.md | 14 +- docs/zh/docs/deployment/cloud.md | 2 +- docs/zh/docs/deployment/concepts.md | 166 +++--- docs/zh/docs/deployment/docker.md | 1 + docs/zh/docs/deployment/https.md | 9 +- docs/zh/docs/deployment/manually.md | 26 +- docs/zh/docs/editor-support.md | 2 +- docs/zh/docs/environment-variables.md | 1 + docs/zh/docs/features.md | 28 +- docs/zh/docs/help-fastapi.md | 4 +- docs/zh/docs/how-to/configure-swagger-ui.md | 6 +- .../docs/how-to/custom-request-and-route.md | 4 +- docs/zh/docs/how-to/graphql.md | 2 +- ...migrate-from-pydantic-v1-to-pydantic-v2.md | 22 +- .../docs/how-to/separate-openapi-schemas.md | 1 + docs/zh/docs/index.md | 32 +- docs/zh/docs/project-generation.md | 1 + docs/zh/docs/python-types.md | 44 +- docs/zh/docs/tutorial/bigger-applications.md | 20 +- docs/zh/docs/tutorial/body-nested-models.md | 4 +- docs/zh/docs/tutorial/body.md | 12 +- docs/zh/docs/tutorial/debugging.md | 6 +- .../dependencies/dependencies-with-yield.md | 3 +- docs/zh/docs/tutorial/extra-data-types.md | 8 +- docs/zh/docs/tutorial/extra-models.md | 1 + docs/zh/docs/tutorial/first-steps.md | 1 + docs/zh/docs/tutorial/handling-errors.md | 18 +- docs/zh/docs/tutorial/index.md | 24 +- docs/zh/docs/tutorial/metadata.md | 26 +- .../tutorial/path-operation-configuration.md | 1 + .../tutorial/query-params-str-validations.md | 1 + docs/zh/docs/tutorial/query-params.md | 1 + docs/zh/docs/tutorial/request-files.md | 2 +- docs/zh/docs/tutorial/request-forms.md | 10 +- docs/zh/docs/tutorial/response-status-code.md | 8 +- docs/zh/docs/tutorial/schema-extra-example.md | 44 +- docs/zh/docs/tutorial/security/first-steps.md | 1 + .../tutorial/security/get-current-user.md | 6 +- docs/zh/docs/tutorial/security/oauth2-jwt.md | 4 +- .../docs/tutorial/security/simple-oauth2.md | 8 +- docs/zh/docs/tutorial/sql-databases.md | 8 +- docs/zh/docs/tutorial/static-files.md | 8 + docs/zh/docs/tutorial/testing.md | 20 +- docs/zh/docs/virtual-environments.md | 2 +- 60 files changed, 675 insertions(+), 641 deletions(-) diff --git a/docs/zh/docs/_llm-test.md b/docs/zh/docs/_llm-test.md index 0da76d43c..5748c0900 100644 --- a/docs/zh/docs/_llm-test.md +++ b/docs/zh/docs/_llm-test.md @@ -37,7 +37,7 @@ 昨天,我的朋友写道:"如果你把 incorrectly 拼对了,你就把它拼错了"。我回答:"没错,但 'incorrectly' 错的不是 '"incorrectly"'"。 -/// note +/// note | 注意 LLM 很可能会把这段翻错。我们只关心在重新翻译时它是否能保持修正后的译文。 @@ -124,24 +124,24 @@ works(foo="bar") # 这可行 🎉 //// tab | 测试 -/// note -Some text +/// note | 注意 +一些文本 /// /// note | 技术细节 -Some text +一些文本 /// -/// tip -Some text +/// tip | 提示 +一些文本 /// -/// warning -Some text +/// warning | 警告 +一些文本 /// -/// danger -Some text +/// danger | 危险 +一些文本 /// //// @@ -213,7 +213,7 @@ Some text ## HTML "dfn" 元素 { #html-dfn-elements } -* 集群 +* 集群 * 深度学习 ## 标题 { #headings } @@ -222,15 +222,15 @@ Some text ### 开发 Web 应用——教程 { #develop-a-webapp-a-tutorial } -Hello. +你好。 ### 类型提示与注解 { #type-hints-and-annotations } -Hello again. +再次你好。 ### 超类与子类 { #super-and-subclasses } -Hello again. +再次你好。 //// @@ -248,241 +248,241 @@ Hello again. //// tab | 测试 -* you -* your +* 你 +* 你的 -* e.g. -* etc. +* 例如 +* 等 -* `foo` as an `int` -* `bar` as a `str` -* `baz` as a `list` +* 作为 `int` 的 `foo` +* 作为 `str` 的 `bar` +* 作为 `list` 的 `baz` -* the Tutorial - User guide -* the Advanced User Guide -* the SQLModel docs -* the API docs -* the automatic docs +* 教程 - 用户指南 +* 高级用户指南 +* SQLModel 文档 +* API 文档 +* 自动文档 -* Data Science -* Deep Learning -* Machine Learning -* Dependency Injection -* HTTP Basic authentication +* 数据科学 +* 深度学习 +* 机器学习 +* 依赖注入 +* HTTP Basic 认证 * HTTP Digest -* ISO format -* the JSON Schema standard -* the JSON schema -* the schema definition -* Password Flow -* Mobile - -* deprecated -* designed -* invalid -* on the fly -* standard -* default -* case-sensitive -* case-insensitive - -* to serve the application -* to serve the page - -* the app -* the application - -* the request -* the response -* the error response - -* the path operation -* the path operation decorator -* the path operation function - -* the body -* the request body -* the response body -* the JSON body -* the form body -* the file body -* the function body - -* the parameter -* the body parameter -* the path parameter -* the query parameter -* the cookie parameter -* the header parameter -* the form parameter -* the function parameter - -* the event -* the startup event -* the startup of the server -* the shutdown event -* the lifespan event - -* the handler -* the event handler -* the exception handler -* to handle - -* the model -* the Pydantic model -* the data model -* the database model -* the form model -* the model object - -* the class -* the base class -* the parent class -* the subclass -* the child class -* the sibling class -* the class method - -* the header -* the headers -* the authorization header -* the `Authorization` header -* the forwarded header - -* the dependency injection system -* the dependency -* the dependable -* the dependant - -* I/O bound -* CPU bound -* concurrency -* parallelism -* multiprocessing - -* the env var -* the environment variable -* the `PATH` -* the `PATH` variable - -* the authentication -* the authentication provider -* the authorization -* the authorization form -* the authorization provider -* the user authenticates -* the system authenticates the user - -* the CLI -* the command line interface - -* the server -* the client - -* the cloud provider -* the cloud service - -* the development -* the development stages - -* the dict -* the dictionary -* the enumeration -* the enum -* the enum member - -* the encoder -* the decoder -* to encode -* to decode - -* the exception -* to raise - -* the expression -* the statement - -* the frontend -* the backend - -* the GitHub discussion -* the GitHub issue - -* the performance -* the performance optimization - -* the return type -* the return value - -* the security -* the security scheme - -* the task -* the background task -* the task function - -* the template -* the template engine - -* the type annotation -* the type hint - -* the server worker -* the Uvicorn worker -* the Gunicorn Worker -* the worker process -* the worker class -* the workload - -* the deployment -* to deploy - -* the SDK -* the software development kit - -* the `APIRouter` -* the `requirements.txt` -* the Bearer Token -* the breaking change -* the bug -* the button -* the callable -* the code -* the commit -* the context manager -* the coroutine -* the database session -* the disk -* the domain -* the engine -* the fake X -* the HTTP GET method -* the item -* the library -* the lifespan -* the lock -* the middleware -* the mobile application -* the module -* the mounting -* the network -* the origin -* the override -* the payload -* the processor -* the property -* the proxy -* the pull request -* the query -* the RAM -* the remote machine -* the status code -* the string -* the tag -* the web framework -* the wildcard -* to return -* to validate +* ISO 格式 +* JSON Schema 标准 +* JSON schema +* schema 定义 +* 密码流 +* 移动端 + +* 已弃用 +* 设计的 +* 无效 +* 动态地 +* 标准 +* 默认 +* 区分大小写 +* 不区分大小写 + +* 为应用提供服务 +* 为页面提供服务 + +* 应用 +* 应用程序 + +* 请求 +* 响应 +* 错误响应 + +* 路径操作 +* 路径操作装饰器 +* 路径操作函数 + +* 请求体 +* 请求体 +* 响应体 +* JSON 请求体 +* 表单体 +* 文件体 +* 函数体 + +* 参数 +* 请求体参数 +* 路径参数 +* 查询参数 +* Cookie 参数 +* Header 参数 +* 表单参数 +* 函数参数 + +* 事件 +* 启动事件 +* 服务器启动 +* 关闭事件 +* lifespan 事件 + +* 处理器 +* 事件处理器 +* 异常处理器 +* 处理 + +* 模型 +* Pydantic 模型 +* 数据模型 +* 数据库模型 +* 表单模型 +* 模型对象 + +* 类 +* 基类 +* 父类 +* 子类 +* 子类 +* 兄弟类 +* 类方法 + +* Header +* Headers +* 授权 Header +* `Authorization` header +* 转发 Header + +* 依赖注入系统 +* 依赖项 +* 可依赖项 +* 依赖方 + +* I/O 密集型 +* CPU 密集型 +* 并发 +* 并行 +* 多进程 + +* 环境变量 +* 环境变量 +* `PATH` +* `PATH` 变量 + +* 认证 +* 认证提供方 +* 授权 +* 授权表单 +* 授权提供方 +* 用户进行认证 +* 系统对用户进行认证 + +* CLI +* 命令行界面 + +* 服务器 +* 客户端 + +* 云服务提供商 +* 云服务 + +* 开发 +* 开发阶段 + +* dict +* 字典 +* 枚举 +* 枚举 +* 枚举成员 + +* 编码器 +* 解码器 +* 编码 +* 解码 + +* 异常 +* 抛出 + +* 表达式 +* 语句 + +* 前端 +* 后端 + +* GitHub 讨论 +* GitHub issue + +* 性能 +* 性能优化 + +* 返回类型 +* 返回值 + +* 安全 +* 安全方案 + +* 任务 +* 后台任务 +* 任务函数 + +* 模板 +* 模板引擎 + +* 类型注解 +* 类型提示 + +* 服务器 worker +* Uvicorn worker +* Gunicorn Worker +* worker 进程 +* worker 类 +* 工作负载 + +* 部署 +* 部署 + +* SDK +* 软件开发工具包 + +* `APIRouter` +* `requirements.txt` +* Bearer Token +* 破坏性变更 +* bug +* 按钮 +* 可调用对象 +* 代码 +* 提交 +* 上下文管理器 +* 协程 +* 数据库会话 +* 磁盘 +* 域名 +* 引擎 +* 虚假 X +* HTTP GET 方法 +* 项 +* 库 +* 生命周期 +* 锁 +* 中间件 +* 移动应用 +* 模块 +* 挂载 +* 网络 +* 源 +* 覆盖 +* 载荷 +* 处理器 +* 属性 +* 代理 +* Pull Request +* 查询 +* RAM +* 远程机器 +* 状态码 +* 字符串 +* 标签 +* Web 框架 +* 通配符 +* 返回 +* 校验 //// diff --git a/docs/zh/docs/advanced/additional-status-codes.md b/docs/zh/docs/advanced/additional-status-codes.md index af212ad8b..0f2e3d2ee 100644 --- a/docs/zh/docs/advanced/additional-status-codes.md +++ b/docs/zh/docs/advanced/additional-status-codes.md @@ -16,7 +16,7 @@ {* ../../docs_src/additional_status_codes/tutorial001_an_py310.py hl[4,25] *} -/// warning +/// warning | 警告 当你直接返回一个像上面例子中的 `Response` 对象时,它会直接返回。 @@ -38,4 +38,4 @@ 如果你直接返回额外的状态码和响应,它们不会包含在 OpenAPI 方案(API 文档)中,因为 FastAPI 没办法预先知道你要返回什么。 -但是你可以使用 [额外的响应](additional-responses.md) 在代码中记录这些内容。 +但是你可以使用:[额外的响应](additional-responses.md),在代码中记录这些内容。 diff --git a/docs/zh/docs/advanced/advanced-dependencies.md b/docs/zh/docs/advanced/advanced-dependencies.md index da299a6bf..12f2616c0 100644 --- a/docs/zh/docs/advanced/advanced-dependencies.md +++ b/docs/zh/docs/advanced/advanced-dependencies.md @@ -1,5 +1,6 @@ # 高级依赖项 { #advanced-dependencies } + ## 参数化的依赖项 { #parameterized-dependencies } 目前我们看到的依赖项都是固定的函数或类。 diff --git a/docs/zh/docs/advanced/dataclasses.md b/docs/zh/docs/advanced/dataclasses.md index a46615286..df94a7de7 100644 --- a/docs/zh/docs/advanced/dataclasses.md +++ b/docs/zh/docs/advanced/dataclasses.md @@ -1,5 +1,6 @@ # 使用数据类 { #using-dataclasses } + FastAPI 基于 **Pydantic** 构建,我已经向你展示过如何使用 Pydantic 模型声明请求与响应。 但 FastAPI 也支持以相同方式使用 [`dataclasses`](https://docs.python.org/3/library/dataclasses.html): diff --git a/docs/zh/docs/advanced/events.md b/docs/zh/docs/advanced/events.md index e1bb2ed60..49d497d3d 100644 --- a/docs/zh/docs/advanced/events.md +++ b/docs/zh/docs/advanced/events.md @@ -1,5 +1,6 @@ # 生命周期事件 { #lifespan-events } + 你可以定义在应用**启动**前执行的逻辑(代码)。这意味着在应用**开始接收请求**之前,这些代码只会被执行**一次**。 同样地,你可以定义在应用**关闭**时应执行的逻辑。在这种情况下,这段代码将在**处理可能的多次请求后**执行**一次**。 diff --git a/docs/zh/docs/advanced/generate-clients.md b/docs/zh/docs/advanced/generate-clients.md index 9feaf6cf5..dd15f0e9c 100644 --- a/docs/zh/docs/advanced/generate-clients.md +++ b/docs/zh/docs/advanced/generate-clients.md @@ -20,20 +20,6 @@ FastAPI 会自动生成 **OpenAPI 3.1** 规范,因此你使用的任何工具 /// -## 来自 FastAPI 赞助商的 SDK 生成器 { #sdk-generators-from-fastapi-sponsors } - -本节介绍的是由赞助 FastAPI 的公司提供的、具备**风险投资背景**或**公司支持**的方案。这些产品在高质量生成的 SDK 之上,提供了**更多特性**和**集成**。 - -通过 ✨ [**赞助 FastAPI**](../help-fastapi.md#sponsor-the-author) ✨,这些公司帮助确保框架及其**生态**保持健康并且**可持续**。 - -他们的赞助也体现了对 FastAPI **社区**(也就是你)的高度承诺,不仅关注提供**优秀的服务**,也支持一个**健壮且繁荣的框架**——FastAPI。🙇 - -例如,你可以尝试: - -* [Stainless](https://www.stainless.com/?utm_source=fastapi&utm_medium=referral) - -其中一些方案也可能是开源的或提供免费层级,你可以不花钱就先试用。其他商业 SDK 生成器也可在网上找到。🤓 - ## 创建一个 TypeScript SDK { #create-a-typescript-sdk } 先从一个简单的 FastAPI 应用开始: @@ -56,7 +42,7 @@ OpenAPI 中包含的这些模型信息就是用于**生成客户端代码**的 ### Hey API { #hey-api } -当我们有了带模型的 FastAPI 应用后,可以使用 Hey API 来生成 TypeScript 客户端。最快的方式是通过 npx: +当我们有了带模型的 FastAPI 应用后,可以使用 Hey API 来生成 TypeScript 客户端。最快的方式是通过 npx。 ```sh npx @hey-api/openapi-ts -i http://localhost:8000/openapi.json -o src/client @@ -119,9 +105,9 @@ npx @hey-api/openapi-ts -i http://localhost:8000/openapi.json -o src/client ItemsService.createItemItemsPost({name: "Plumbus", price: 5}) ``` -...这是因为客户端生成器会把每个*路径操作*的 OpenAPI 内部**操作 ID(operation ID)**用作方法名的一部分。 +...这是因为客户端生成器会使用每个*路径操作*的 OpenAPI 内部**操作 ID(operation ID)**。 -OpenAPI 要求每个操作 ID 在所有*路径操作*中都是唯一的,因此 FastAPI 会使用**函数名**、**路径**和**HTTP 方法/操作**来生成操作 ID,以确保其唯一性。 +OpenAPI 要求每个操作 ID 在所有*路径操作*中都是唯一的,因此 FastAPI 会使用**函数名**、**路径**和**HTTP 方法/操作**来生成操作 ID,因为这样可以确保操作 ID 是唯一的。 接下来我会告诉你如何改进。🤓 @@ -193,9 +179,9 @@ npx @hey-api/openapi-ts -i ./openapi.json -o src/client 使用自动生成的客户端时,你会获得以下内容的**自动补全**: -* 方法 -* 请求体中的数据、查询参数等 -* 响应数据 +* 方法。 +* 请求体中的数据、查询参数等。 +* 响应数据。 你还会为所有内容获得**内联错误**。 diff --git a/docs/zh/docs/advanced/json-base64-bytes.md b/docs/zh/docs/advanced/json-base64-bytes.md index 7792282c7..040957c69 100644 --- a/docs/zh/docs/advanced/json-base64-bytes.md +++ b/docs/zh/docs/advanced/json-base64-bytes.md @@ -4,7 +4,7 @@ ## Base64 与文件 { #base64-vs-files } -请先考虑是否可以使用 [请求文件](../tutorial/request-files.md) 来上传二进制数据,并使用 [自定义响应 - FileResponse](./custom-response.md#fileresponse--fileresponse-) 来发送二进制数据,而不是把它编码进 JSON。 +请先考虑是否可以使用 [请求文件](../tutorial/request-files.md) 来上传二进制数据,并使用 [自定义响应 - FileResponse](./custom-response.md#fileresponse) 来发送二进制数据,而不是把它编码进 JSON。 JSON 只能包含 UTF-8 编码的字符串,因此无法直接包含原始字节。 @@ -14,7 +14,7 @@ Base64 可以把二进制数据编码为字符串,但为此会使用比原始 ## Pydantic `bytes` { #pydantic-bytes } -你可以声明带有 `bytes` 字段的 Pydantic 模型,然后在模型配置中使用 `val_json_bytes` 指定用 base64 来验证输入的 JSON 数据;作为验证的一部分,它会将该 base64 字符串解码为字节。 +你可以声明带有 `bytes` 字段的 Pydantic 模型,然后在模型配置中使用 `val_json_bytes` 指定用 base64 来*验证*输入的 JSON 数据;作为验证的一部分,它会将该 base64 字符串解码为字节。 {* ../../docs_src/json_base64_bytes/tutorial001_py310.py ln[1:9,29:35] hl[9] *} @@ -52,12 +52,12 @@ Base64 可以把二进制数据编码为字符串,但为此会使用比原始 ## 用于输出数据的 Pydantic `bytes` { #pydantic-bytes-for-output-data } -对于输出数据,你也可以在模型配置中为 `bytes` 字段使用 `ser_json_bytes`,Pydantic 会在生成 JSON 响应时将字节以 base64 进行序列化。 +对于输出数据,你也可以在模型配置中为 `bytes` 字段使用 `ser_json_bytes`,Pydantic 会在生成 JSON 响应时将字节以 base64 进行*序列化*。 {* ../../docs_src/json_base64_bytes/tutorial001_py310.py ln[1:2,12:16,29,38:41] hl[16] *} ## 用于输入和输出数据的 Pydantic `bytes` { #pydantic-bytes-for-input-and-output-data } -当然,你也可以使用同一个配置了 base64 的模型,在接收和发送 JSON 数据时,同时处理输入(使用 `val_json_bytes` 进行验证)和输出(使用 `ser_json_bytes` 进行序列化)。 +当然,你也可以使用同一个配置了 base64 的模型,在接收和发送 JSON 数据时,同时处理输入(使用 `val_json_bytes` 进行*验证*)和输出(使用 `ser_json_bytes` 进行*序列化*)。 {* ../../docs_src/json_base64_bytes/tutorial001_py310.py ln[1:2,19:26,29,44:46] hl[23:26] *} diff --git a/docs/zh/docs/advanced/openapi-callbacks.md b/docs/zh/docs/advanced/openapi-callbacks.md index f4f2e7b81..3ca99b980 100644 --- a/docs/zh/docs/advanced/openapi-callbacks.md +++ b/docs/zh/docs/advanced/openapi-callbacks.md @@ -1,35 +1,35 @@ # OpenAPI 回调 { #openapi-callbacks } -您可以创建一个包含*路径操作*的 API,它会触发对别人创建的*外部 API*的请求(很可能就是那个会“使用”您 API 的同一个开发者)。 +你可以创建一个包含*路径操作*的 API,该*路径操作*可以触发对其他人创建的*外部 API*的请求(很可能就是那个会*使用*你的 API 的同一个开发者)。 -当您的 API 应用调用*外部 API*时,这个过程被称为“回调”。因为外部开发者编写的软件会先向您的 API 发送请求,然后您的 API 再进行*回调*,向*外部 API*发送请求(很可能也是该开发者创建的)。 +当你的 API 应用调用*外部 API*时,这个过程被称为“回调”。因为外部开发者编写的软件会先向你的 API 发送请求,然后你的 API 再*回调*,向*外部 API*发送请求(很可能也是该开发者创建的)。 -此时,我们需要存档外部 API 的*信息*,比如应该有哪些*路径操作*,请求体应该是什么,应该返回什么响应等。 +在这种情况下,你可能希望记录该外部 API *应该*是什么样子。它应该有哪些*路径操作*,应该接收什么请求体,应该返回什么响应等。 ## 使用回调的应用 { #an-app-with-callbacks } -示例如下。 +让我们通过一个例子来看这一切。 -假设要开发一个创建发票的应用。 +假设你开发一个可以创建发票的应用。 -发票包括 `id`、`title`(可选)、`customer`、`total` 等属性。 +这些发票会有 `id`、`title`(可选)、`customer` 和 `total`。 -API 的用户(外部开发者)要在您的 API 内使用 POST 请求创建一条发票记录。 +你的 API 用户(外部开发者)会通过 POST 请求在你的 API 中创建一张发票。 -(假设)您的 API 将: +然后你的 API 会(假设): -* 把发票发送至外部开发者的消费者 -* 归集现金 -* 把通知发送至 API 的用户(外部开发者) - * 通过(从您的 API)发送 POST 请求至外部 API(即**回调**)来完成 +* 将发票发送给外部开发者的某个客户。 +* 收款。 +* 向 API 用户(外部开发者)发回通知。 + * 这会通过(从*你的 API*)向该外部开发者提供的某个*外部 API*发送 POST 请求来完成(这就是“回调”)。 ## 常规 **FastAPI** 应用 { #the-normal-fastapi-app } -添加回调前,首先看下常规 API 应用是什么样子。 +我们先看看在添加回调之前,常规 API 应用会是什么样子。 -常规 API 应用包含接收 `Invoice` 请求体的*路径操作*,还有包含回调 URL 的查询参数 `callback_url`。 +它会有一个接收 `Invoice` 请求体的*路径操作*,以及一个包含回调 URL 的查询参数 `callback_url`。 -这部分代码很常规,您对绝大多数代码应该都比较熟悉了: +这部分很常规,大部分代码你应该已经很熟悉了: {* ../../docs_src/openapi_callbacks/tutorial001_py310.py hl[7:11,34:51] *} @@ -39,92 +39,92 @@ API 的用户(外部开发者)要在您的 API 内使用 POST 请求创建 /// -此处唯一比较新的内容是*路径操作装饰器*中的 `callbacks=invoices_callback_router.routes` 参数,下文介绍。 +唯一的新内容是*路径操作装饰器*中的参数 `callbacks=invoices_callback_router.routes`。接下来我们会看看它是什么。 -## 存档回调 { #documenting-the-callback } +## 为回调编写文档 { #documenting-the-callback } -实际的回调代码高度依赖于您自己的 API 应用。 +实际的回调代码会高度依赖你自己的 API 应用。 -并且可能每个应用都各不相同。 +而且很可能在不同应用之间差异很大。 -回调代码可能只有一两行,比如: +它可能只有一两行代码,例如: ```Python callback_url = "https://example.com/api/v1/invoices/events/" httpx.post(callback_url, json={"description": "Invoice paid", "paid": True}) ``` -但回调最重要的部分可能是,根据 API 要发送给回调请求体的数据等内容,确保您的 API 用户(外部开发者)正确地实现*外部 API*。 +但回调最重要的部分可能是确保你的 API 用户(外部开发者)正确实现*外部 API*,与*你的 API*将在回调请求体中发送的数据等相匹配。 -因此,我们下一步要做的就是添加代码,为从 API 接收回调的*外部 API*存档。 +因此,接下来我们要做的是添加代码,用来记录该*外部 API*应该是什么样子,才能接收来自*你的 API*的回调。 -这部分文档在 `/docs` 下的 Swagger UI 中显示,并且会告诉外部开发者如何构建*外部 API*。 +这份文档会显示在你的 API 的 `/docs` 下的 Swagger UI 中,并且会让外部开发者知道如何构建*外部 API*。 -本例没有实现回调本身(只是一行代码),只有文档部分。 +本例不实现回调本身(那可能只是一行代码),只实现文档部分。 /// tip | 提示 -实际的回调只是 HTTP 请求。 +实际的回调只是一个 HTTP 请求。 -实现回调时,要使用 [HTTPX](https://www.python-httpx.org) 或 [Requests](https://requests.readthedocs.io/)。 +自己实现回调时,你可以使用类似 [HTTPX](https://www.python-httpx.org) 或 [Requests](https://requests.readthedocs.io/) 的工具。 /// ## 编写回调文档代码 { #write-the-callback-documentation-code } -应用不执行这部分代码,只是用它来*记录 外部 API* 。 +这段代码不会在你的应用中执行,我们只需要用它来*记录*该*外部 API*应该是什么样子。 -但,您已经知道用 **FastAPI** 创建自动 API 文档有多简单了。 +不过,你已经知道如何使用 **FastAPI** 轻松为 API 创建自动文档了。 -我们要使用与存档*外部 API* 相同的知识...通过创建外部 API 要实现的*路径操作*(您的 API 要调用的)。 +因此,我们会使用相同的知识来记录该*外部 API*应该是什么样子...通过创建外部 API 应该实现的*路径操作*(也就是你的 API 将调用的那些)。 /// tip | 提示 -编写存档回调的代码时,假设您是*外部开发者*可能会用的上。并且您当前正在实现的是*外部 API*,不是*您自己的 API*。 +在编写用于记录回调的代码时,可以想象你就是那个*外部开发者*。而且你现在正在实现的是*外部 API*,不是*你的 API*。 -临时改变(为外部开发者的)视角能让您更清楚该如何放置*外部 API* 响应和请求体的参数与 Pydantic 模型等。 +临时采用这个(*外部开发者*的)视角,可以帮助你更清楚地判断该把参数、请求体的 Pydantic 模型、响应等放在该*外部 API*的什么位置。 /// -### 创建回调的 `APIRouter` { #create-a-callback-apirouter } +### 创建回调 `APIRouter` { #create-a-callback-apirouter } -首先,新建包含一些用于回调的 `APIRouter`。 +首先创建一个新的 `APIRouter`,它将包含一个或多个回调。 {* ../../docs_src/openapi_callbacks/tutorial001_py310.py hl[1,23] *} ### 创建回调*路径操作* { #create-the-callback-path-operation } -创建回调*路径操作*也使用之前创建的 `APIRouter`。 +要创建回调*路径操作*,请使用你在上面创建的同一个 `APIRouter`。 -它看起来和常规 FastAPI *路径操作*差不多: +它看起来应该就像普通的 FastAPI *路径操作*: -* 声明要接收的请求体,例如,`body: InvoiceEvent` -* 还要声明要返回的响应,例如,`response_model=InvoiceEventReceived` +* 它可能应该声明要接收的请求体,例如 `body: InvoiceEvent`。 +* 它也可以声明要返回的响应,例如 `response_model=InvoiceEventReceived`。 {* ../../docs_src/openapi_callbacks/tutorial001_py310.py hl[14:16,19:20,26:30] *} -回调*路径操作*与常规*路径操作*有两点主要区别: +它与普通*路径操作*有 2 个主要区别: -* 它不需要任何实际的代码,因为应用不会调用这段代码。它只是用于存档*外部 API*。因此,函数的内容只需要 `pass` 就可以了 -* *路径*可以包含 [OpenAPI 3 表达式](https://github.com/OAI/OpenAPI-Specification/blob/master/versions/3.1.0.md#key-expression)(详见下文),可以使用带参数的变量,以及发送至您的 API 的原始请求的部分 +* 它不需要任何实际代码,因为你的应用永远不会调用这段代码。它只用于记录*外部 API*。因此,函数可以只有 `pass`。 +* *路径*可以包含 [OpenAPI 3 表达式](https://github.com/OAI/OpenAPI-Specification/blob/master/versions/3.1.0.md#key-expression)(见下文),其中可以使用带参数的变量,以及发送到*你的 API*的原始请求的部分内容。 ### 回调路径表达式 { #the-callback-path-expression } -回调*路径*支持包含发送给您的 API 的原始请求的部分的 [OpenAPI 3 表达式](https://github.com/OAI/OpenAPI-Specification/blob/master/versions/3.1.0.md#key-expression)。 +回调*路径*可以有一个 [OpenAPI 3 表达式](https://github.com/OAI/OpenAPI-Specification/blob/master/versions/3.1.0.md#key-expression),其中可以包含发送到*你的 API*的原始请求的部分内容。 -本例中是 `str`: +在这个例子中,它是这个 `str`: ```Python "{$callback_url}/invoices/{$request.body.id}" ``` -因此,如果您的 API 用户(外部开发者)发送请求到您的 API: +所以,如果你的 API 用户(外部开发者)向*你的 API*发送请求到: ``` https://yourapi.com/invoices/?callback_url=https://www.external.org/events ``` -使用如下 JSON 请求体: +并带有如下 JSON 请求体: ```JSON { @@ -134,13 +134,13 @@ https://yourapi.com/invoices/?callback_url=https://www.external.org/events } ``` -然后,您的 API 就会处理发票,并在某个点之后,发送回调请求至 `callback_url`(外部 API): +那么*你的 API*会处理该发票,并在稍后的某个时间点,向 `callback_url`(*外部 API*)发送回调请求: ``` https://www.external.org/events/invoices/2expen51ve ``` -JSON 请求体包含如下内容: +并带有类似如下内容的 JSON 请求体: ```JSON { @@ -149,7 +149,7 @@ JSON 请求体包含如下内容: } ``` -它会预期*外部 API* 的响应包含如下 JSON 请求体: +它会预期该*外部 API*返回类似如下 JSON 请求体的响应: ```JSON { @@ -159,28 +159,28 @@ JSON 请求体包含如下内容: /// tip | 提示 -注意,回调 URL 包含 `callback_url`(`https://www.external.org/events`)中的查询参数,还有 JSON 请求体内部的发票 ID(`2expen51ve`)。 +请注意,使用的回调 URL 包含在 `callback_url` 中作为查询参数接收到的 URL(`https://www.external.org/events`),也包含 JSON 请求体内部的发票 `id`(`2expen51ve`)。 /// ### 添加回调路由 { #add-the-callback-router } -至此,在上文创建的回调路由里就包含了*回调路径操作*(外部开发者要在外部 API 中实现)。 +此时,你已经在上面创建的回调路由中拥有了所需的*回调路径操作*(即*外部开发者*应该在*外部 API*中实现的那些)。 -现在使用 API *路径操作装饰器*的参数 `callbacks`,从回调路由传递属性 `.routes`(实际上只是路由/路径操作的**列表**): +现在,在*你的 API 的路径操作装饰器*中使用参数 `callbacks`,传入该回调路由的 `.routes` 属性: {* ../../docs_src/openapi_callbacks/tutorial001_py310.py hl[33] *} /// tip | 提示 -注意,不能把路由本身(`invoices_callback_router`)传递给 `callbacks=`,要传递 `invoices_callback_router.routes` 中的 `.routes` 属性。FastAPI 会使用这些路由来生成回调的 OpenAPI 文档。 +请注意,你不是把路由本身(`invoices_callback_router`)传给 `callbacks=`,而是传它的 `.routes`,也就是 `invoices_callback_router.routes`。FastAPI 会使用这些路由来生成回调的 OpenAPI 文档。 /// ### 查看文档 { #check-the-docs } -现在,启动应用并打开 [http://127.0.0.1:8000/docs](http://127.0.0.1:8000/docs)。 +现在你可以启动应用并访问 [http://127.0.0.1:8000/docs](http://127.0.0.1:8000/docs)。 -就能看到文档的*路径操作*已经包含了**回调**的内容以及*外部 API*: +你会看到文档中为你的*路径操作*包含了一个 "Callbacks" 部分,展示了*外部 API*应该是什么样子: diff --git a/docs/zh/docs/advanced/response-change-status-code.md b/docs/zh/docs/advanced/response-change-status-code.md index 379afd4eb..4339875e4 100644 --- a/docs/zh/docs/advanced/response-change-status-code.md +++ b/docs/zh/docs/advanced/response-change-status-code.md @@ -22,7 +22,7 @@ {* ../../docs_src/response_change_status_code/tutorial001_py310.py hl[1,9,12] *} -然后你可以像平常一样返回任何你需要的对象(例如一个`dict`或者一个数据库模型)。 +然后你可以像平常一样返回任何你需要的对象(一个`dict`、一个数据库模型等)。 如果你声明了一个`response_model`,它仍然会被用来过滤和转换你返回的对象。 diff --git a/docs/zh/docs/advanced/response-cookies.md b/docs/zh/docs/advanced/response-cookies.md index 7fad89e5c..9a41b95e4 100644 --- a/docs/zh/docs/advanced/response-cookies.md +++ b/docs/zh/docs/advanced/response-cookies.md @@ -1,36 +1,38 @@ -# 响应Cookies { #response-cookies } +# 响应 Cookies { #response-cookies } ## 使用 `Response` 参数 { #use-a-response-parameter } -你可以在 *路径操作函数* 中定义一个类型为 `Response` 的参数,这样你就可以在这个临时响应对象中设置cookie了。 +你可以在*路径操作函数*中声明一个类型为 `Response` 的参数。 + +然后你可以在这个*临时*响应对象中设置 Cookie。 {* ../../docs_src/response_cookies/tutorial002_py310.py hl[1, 8:9] *} -而且你还可以根据你的需要响应不同的对象,比如常用的 `dict`,数据库model等。 +然后你可以像平常一样返回所需的任何对象(`dict`、数据库模型等)。 -如果你定义了 `response_model`,程序会自动根据`response_model`来过滤和转换你响应的对象。 +如果你声明了 `response_model`,它仍会用于过滤和转换你返回的对象。 -**FastAPI** 会使用这个 *临时* 响应对象去装在这些cookies信息 (同样还有headers和状态码等信息), 最终会将这些信息和通过`response_model`转化过的数据合并到最终的响应里。 +**FastAPI** 会使用这个*临时*响应来提取 Cookie(还有 header 和状态码),并将它们放入最终响应中;最终响应包含你返回的值,并经过任何 `response_model` 过滤。 -你也可以在依赖中定义`Response`参数,并设置cookie和header。 +你也可以在依赖项中声明 `Response` 参数,并在其中设置 Cookie(和 header)。 -## 直接响应 `Response` { #return-a-response-directly } +## 直接返回 `Response` { #return-a-response-directly } -你还可以在直接响应`Response`时直接创建cookies。 +在代码中直接返回 `Response` 时,你也可以创建 Cookie。 为此,你可以按照[直接返回 Response](response-directly.md)中的说明创建一个响应。 -然后设置Cookies,并返回: +然后在其中设置 Cookie,并返回它: {* ../../docs_src/response_cookies/tutorial001_py310.py hl[10:12] *} /// tip | 提示 -需要注意,如果你直接反馈一个response对象,而不是使用`Response`入参,FastAPI则会直接反馈你封装的response对象。 +请记住,如果你直接返回响应,而不是使用 `Response` 参数,FastAPI 会直接返回它。 -所以你需要确保你响应数据类型的正确性,如:你可以使用`JSONResponse`来兼容JSON的场景。 +因此,你必须确保你的数据类型正确。例如,如果你返回的是 `JSONResponse`,数据就需要兼容 JSON。 -同时,你也应当仅反馈通过`response_model`过滤过的数据。 +并且还要确保你没有发送本应由 `response_model` 过滤的数据。 /// @@ -38,12 +40,12 @@ /// note | 技术细节 -你也可以使用`from starlette.responses import Response` 或者 `from starlette.responses import JSONResponse`。 +你也可以使用 `from starlette.responses import Response` 或者 `from starlette.responses import JSONResponse`。 -为了方便开发者,**FastAPI** 封装了相同数据类型,如`starlette.responses` 和 `fastapi.responses`。不过大部分response对象都是直接引用自Starlette。 +**FastAPI** 为了方便开发者,提供了与 `starlette.responses` 相同的 `fastapi.responses`。但大多数可用的响应都直接来自 Starlette。 -因为`Response`对象可以非常便捷的设置headers和cookies,所以 **FastAPI** 同时也封装了`fastapi.Response`。 +由于 `Response` 经常用于设置 header 和 Cookie,**FastAPI** 也在 `fastapi.Response` 中提供了它。 /// -如果你想查看所有可用的参数和选项,可以参考 [Starlette 文档](https://www.starlette.dev/responses/#set-cookie)。 +要查看所有可用参数和选项,请查看 [Starlette 文档](https://www.starlette.dev/responses/#set-cookie)。 diff --git a/docs/zh/docs/advanced/response-headers.md b/docs/zh/docs/advanced/response-headers.md index ab99a4ece..89357058d 100644 --- a/docs/zh/docs/advanced/response-headers.md +++ b/docs/zh/docs/advanced/response-headers.md @@ -1,5 +1,6 @@ # 响应头 { #response-headers } + ## 使用 `Response` 参数 { #use-a-response-parameter } 你可以在你的*路径操作函数*中声明一个 `Response` 类型的参数(就像你可以为 cookies 做的那样)。 diff --git a/docs/zh/docs/advanced/security/oauth2-scopes.md b/docs/zh/docs/advanced/security/oauth2-scopes.md index db29e4916..fa0dd8eff 100644 --- a/docs/zh/docs/advanced/security/oauth2-scopes.md +++ b/docs/zh/docs/advanced/security/oauth2-scopes.md @@ -86,7 +86,7 @@ OAuth2 规范将“作用域”定义为由空格分隔的字符串列表。 现在,修改令牌的*路径操作*以返回请求的作用域。 -我们仍然使用 `OAuth2PasswordRequestForm`。它包含 `scopes` 属性,其值是 `list[str]`,包含请求中接收到的每个作用域。 +我们仍然使用 `OAuth2PasswordRequestForm`。它包含 `scopes` 属性,其值是 `list` of `str`,包含请求中接收到的每个作用域。 我们把这些作用域作为 JWT 令牌的一部分返回。 @@ -174,7 +174,7 @@ OAuth2 规范将“作用域”定义为由空格分隔的字符串列表。 为此,我们给 Pydantic 模型 `TokenData` 添加了一个新属性 `scopes`。 -通过用 Pydantic 验证数据,我们可以确保确实得到了例如一个由作用域组成的 `list[str]`,以及一个 `str` 类型的 `username`。 +通过用 Pydantic 验证数据,我们可以确保确实得到了例如一个由作用域组成的 `list` of `str`,以及一个 `str` 类型的 `username`。 而不是,例如得到一个 `dict` 或其它什么,这可能会在后续某个时刻破坏应用,形成安全风险。 diff --git a/docs/zh/docs/advanced/settings.md b/docs/zh/docs/advanced/settings.md index 31a7cc82d..2159ccb25 100644 --- a/docs/zh/docs/advanced/settings.md +++ b/docs/zh/docs/advanced/settings.md @@ -297,6 +297,6 @@ participant execute as Execute function 你可以使用 Pydantic Settings 来处理应用的设置或配置,享受 Pydantic 模型的全部能力。 -- 通过使用依赖项,你可以简化测试。 -- 你可以与它一起使用 `.env` 文件。 -- 使用 `@lru_cache` 可以避免为每个请求反复读取 dotenv 文件,同时允许你在测试时进行覆盖。 +* 通过使用依赖项,你可以简化测试。 +* 你可以与它一起使用 `.env` 文件。 +* 使用 `@lru_cache` 可以避免为每个请求反复读取 dotenv 文件,同时允许你在测试时进行覆盖。 diff --git a/docs/zh/docs/advanced/stream-data.md b/docs/zh/docs/advanced/stream-data.md index 366ab203b..44e005ace 100644 --- a/docs/zh/docs/advanced/stream-data.md +++ b/docs/zh/docs/advanced/stream-data.md @@ -2,7 +2,7 @@ 如果你要流式传输可以结构化为 JSON 的数据,你应该[流式传输 JSON Lines](../tutorial/stream-json-lines.md)。 -但如果你想流式传输纯二进制数据或字符串,可以按下面的方法操作。 +但如果你想**流式传输纯二进制数据**或字符串,可以按下面的方法操作。 /// note | 注意 @@ -12,11 +12,11 @@ ## 使用场景 { #use-cases } -如果你想流式传输纯字符串,例如直接来自某个 AI LLM 服务的输出,可以使用它。 +如果你想流式传输纯字符串,例如直接来自某个 **AI LLM** 服务的输出,可以使用它。 -你也可以用它来流式传输大型二进制文件,在读取的同时按块发送,无需一次性把所有内容读入内存。 +你也可以用它来流式传输**大型二进制文件**,在读取的同时按块发送,无需一次性把所有内容读入内存。 -你还可以用这种方式流式传输视频或音频,甚至可以在处理的同时生成并发送。 +你还可以用这种方式流式传输**视频**或**音频**,甚至可以在处理的同时生成并发送。 ## 使用 `yield` 的 `StreamingResponse` { #a-streamingresponse-with-yield } @@ -40,7 +40,7 @@ FastAPI 会将每个数据块原样交给 `StreamingResponse`,不会尝试将 {* ../../docs_src/stream_data/tutorial001_py310.py ln[32:35] hl[33] *} -这也意味着,使用 `StreamingResponse` 时,你拥有按需精确生成与编码字节数据的自由,同时也承担相应的责任,它与类型注解无关。🤓 +这也意味着,使用 `StreamingResponse` 时,你拥有按需精确生成与编码字节数据的**自由**,同时也承担相应的**责任**,它与类型注解无关。🤓 ### 流式传输字节 { #stream-bytes } diff --git a/docs/zh/docs/advanced/wsgi.md b/docs/zh/docs/advanced/wsgi.md index f665c371f..eb83a09b2 100644 --- a/docs/zh/docs/advanced/wsgi.md +++ b/docs/zh/docs/advanced/wsgi.md @@ -1,5 +1,6 @@ # 包含 WSGI - Flask,Django,其它 { #including-wsgi-flask-django-others } + 您可以挂载 WSGI 应用,正如您在 [子应用 - 挂载](sub-applications.md)、[在代理之后](behind-a-proxy.md) 中所看到的那样。 为此, 您可以使用 `WSGIMiddleware` 来包装你的 WSGI 应用,如:Flask,Django,等等。 diff --git a/docs/zh/docs/alternatives.md b/docs/zh/docs/alternatives.md index 08893fca7..20de25cbd 100644 --- a/docs/zh/docs/alternatives.md +++ b/docs/zh/docs/alternatives.md @@ -28,7 +28,7 @@ Django REST framework 作为一个灵活工具箱而创建,用于在底层使 它被包括 Mozilla、Red Hat、Eventbrite 在内的许多公司使用。 -它是最早的“自动 API 文档”的范例之一,这正是启发“寻找” **FastAPI** 的最初想法之一。 +它是最早的**自动 API 文档**的范例之一,这正是启发“寻找” **FastAPI** 的最初想法之一。 /// note | 注意 @@ -58,8 +58,9 @@ Flask 是一个“微框架”,它不包含数据库集成,也没有像 Djan /// tip | 启发 **FastAPI**: -- 成为微框架,便于按需组合所需的工具与组件。 -- 提供简单易用的路由系统。 +成为微框架。让按需组合所需的工具与组件变得容易。 + +提供简单易用的路由系统。 /// @@ -87,7 +88,7 @@ Requests 设计非常简单直观,易于使用,且有合理的默认值。 response = requests.get("http://example.com/some/url") ``` -对应地,FastAPI 的 API 路径操作可能看起来是这样的: +对应地,FastAPI 的 API *路径操作*可能看起来是这样的: ```Python hl_lines="1" @app.get("/some/url") @@ -282,7 +283,7 @@ Flask-apispec 由与 Marshmallow 相同的开发者创建。 Falcon 是另一个高性能 Python 框架,它被设计为精简且可作为 Hug 等其他框架的基础。 -它设计为接收两个参数的函数:一个“request”和一个“response”。然后从 request 中“读取”,向 response 中“写入”。由于这种设计,无法用标准的 Python 类型提示将请求参数和请求体声明为函数形参。 +它设计为接收两个参数的函数:一个“请求”和一个“响应”。然后从请求中“读取”,向响应中“写入”。由于这种设计,无法用标准的 Python 类型提示将请求参数和请求体声明为函数形参。 因此,数据校验、序列化与文档要么需要手写完成,无法自动化;要么需要在 Falcon 之上实现一个框架,例如 Hug。其他受 Falcon 设计启发、采用“一个 request 对象 + 一个 response 对象作为参数”的框架也有同样的区别。 diff --git a/docs/zh/docs/async.md b/docs/zh/docs/async.md index bee98fc8b..8645fd634 100644 --- a/docs/zh/docs/async.md +++ b/docs/zh/docs/async.md @@ -95,11 +95,11 @@ Python 的现代版本支持通过一种叫**“协程”**——使用 `async` ### 并发与汉堡 { #concurrency-and-burgers } -上述异步代码的思想有时也被称为“并发”,它不同于“并行”。 +上述**异步**代码的思想有时也被称为**“并发”**,它不同于**“并行”**。 -并发和并行都与“不同的事情或多或少同时发生”有关。 +**并发**和**并行**都与“不同的事情或多或少同时发生”有关。 -但是并发和并行之间的细节是完全不同的。 +但是*并发*和*并行*之间的细节是完全不同的。 要了解差异,请想象以下关于汉堡的故事: @@ -367,7 +367,7 @@ Starlette(和 **FastAPI**)是基于 [AnyIO](https://anyio.readthedocs.io/en/ 特别是,你可以直接使用 [AnyIO](https://anyio.readthedocs.io/en/stable/) 来处理高级的并发用例,这些用例需要在自己的代码中使用更高级的模式。 -即使你没有使用 **FastAPI**,你也可以使用 [AnyIO](https://anyio.readthedocs.io/en/stable/) 编写自己的异步程序,使其拥有较高的兼容性并获得一些好处(例如,结构化并发)。 +即使你没有使用 FastAPI,你也可以使用 [AnyIO](https://anyio.readthedocs.io/en/stable/) 编写自己的异步程序,使其拥有较高的兼容性并获得一些好处(例如,结构化并发)。 我基于 AnyIO 新建了一个库,作为一个轻量级的封装层,用来优化类型注解,同时提供了更好的**自动补全**、**内联错误提示**等功能。这个库还附带了一个友好的入门指南和教程,能帮助你**理解**并编写**自己的异步代码**:[Asyncer](https://asyncer.tiangolo.com/)。如果你有**结合使用异步代码和常规**(阻塞/同步)代码的需求,这个库会特别有用。 @@ -429,13 +429,13 @@ Starlette(和 **FastAPI**)是基于 [AnyIO](https://anyio.readthedocs.io/en/ 你可以拥有多个相互依赖的依赖以及[子依赖](tutorial/dependencies/sub-dependencies.md)(作为函数的参数),它们中的一些可能是通过 `async def` 声明,也可能是通过 `def` 声明。它们仍然可以正常工作,这些通过 `def` 声明的函数将会在外部线程中调用(来自线程池),而不是“被等待”。 -### 其他函数 { #other-utility-functions } +### 其他工具函数 { #other-utility-functions } -你可直接调用通过 `def` 或 `async def` 创建的任何其他函数,FastAPI 不会影响你调用它们的方式。 +你可直接调用通过 `def` 或 `async def` 创建的任何其他工具函数,FastAPI 不会影响你调用它们的方式。 这与 FastAPI 为你调用*路径操作函数*和依赖项的逻辑相反。 -如果你的函数是通过 `def` 声明的,它将被直接调用(在代码中编写的地方),而不会在线程池中;如果这个函数通过 `async def` 声明,当在代码中调用时,你就应该使用 `await` 等待函数的结果。 +如果你的工具函数是通过 `def` 声明的,它将被直接调用(在代码中编写的地方),而不会在线程池中;如果这个函数通过 `async def` 声明,当在代码中调用时,你就应该使用 `await` 等待函数的结果。 --- diff --git a/docs/zh/docs/deployment/cloud.md b/docs/zh/docs/deployment/cloud.md index 025715f52..d20cc3ce1 100644 --- a/docs/zh/docs/deployment/cloud.md +++ b/docs/zh/docs/deployment/cloud.md @@ -16,7 +16,7 @@ FastAPI Cloud 是 *FastAPI and friends* 开源项目的主要赞助方和资金 ## 云服务商 - 赞助商 { #cloud-providers-sponsors } -还有一些云服务商也会 ✨ [**赞助 FastAPI**](../help-fastapi.md#sponsor-the-author) ✨。🙇 +还有一些云服务商也会 ✨ [**赞助 FastAPI**](https://github.com/sponsors/tiangolo) ✨。🙇 你也可以考虑按照他们的指南尝试他们的服务: diff --git a/docs/zh/docs/deployment/concepts.md b/docs/zh/docs/deployment/concepts.md index dd5ba2ba8..4e7d69b41 100644 --- a/docs/zh/docs/deployment/concepts.md +++ b/docs/zh/docs/deployment/concepts.md @@ -1,6 +1,6 @@ # 部署概念 { #deployments-concepts } -在部署 **FastAPI** 应用程序或任何类型的 Web API 时,有几个概念值得了解,通过掌握这些概念您可以找到**最合适的**方法来**部署您的应用程序**。 +在部署 **FastAPI** 应用程序,或者实际上,任何类型的 Web API 时,有几个你可能会关心的概念,通过掌握这些概念你可以找到**最合适的**方法来**部署你的应用程序**。 一些重要的概念是: @@ -9,23 +9,23 @@ * 重新启动 * 复制(运行的进程数) * 内存 -* 开始前的先前步骤 +* 启动前的先前步骤 我们接下来了解它们将如何影响**部署**。 -我们的最终目标是能够以**安全**的方式**为您的 API 客户端**提供服务,同时要**避免中断**,并且尽可能高效地利用**计算资源**(例如远程服务器/虚拟机)。 🚀 +最终目标是能够以**安全**的方式**为你的 API 客户端**提供服务,同时**避免中断**,并且尽可能高效地利用**计算资源**(例如远程服务器/虚拟机)。 🚀 -我将在这里告诉您更多关于这些**概念**的信息,希望能给您提供**直觉**来决定如何在非常不同的环境中部署 API,甚至在是尚不存在的**未来**的环境里。 +我将在这里告诉你更多关于这些**概念**的信息,希望能给你提供**直觉**来决定如何在非常不同的环境中部署你的 API,甚至是在尚不存在的**未来**环境里。 -通过考虑这些概念,您将能够**评估和设计**部署**您自己的 API**的最佳方式。 +通过考虑这些概念,你将能够**评估和设计**部署**你自己的 API** 的最佳方式。 -在接下来的章节中,我将为您提供更多部署 FastAPI 应用程序的**具体方法**。 +在接下来的章节中,我将为你提供更多部署 FastAPI 应用程序的**具体方案**。 -但现在,让我们仔细看一下这些重要的**概念**。 这些概念也适用于任何其他类型的 Web API。 💡 +但现在,让我们仔细看一下这些重要的**概念性想法**。这些概念也适用于任何其他类型的 Web API。 💡 ## 安全性 - HTTPS { #security-https } -在[上一章有关 HTTPS](https.md) 中,我们了解了 HTTPS 如何为您的 API 提供加密。 +在[上一章有关 HTTPS](https.md) 中,我们了解了 HTTPS 如何为你的 API 提供加密。 我们还看到,HTTPS 通常由应用程序服务器的**外部**组件(**TLS 终止代理**)提供。 @@ -33,7 +33,7 @@ ### HTTPS 示例工具 { #example-tools-for-https } -您可以用作 TLS 终止代理的一些工具包括: +你可以用作 TLS 终止代理的一些工具包括: * Traefik * 自动处理证书更新 ✨ @@ -43,13 +43,13 @@ * 使用 Certbot 等外部组件进行证书更新 * HAProxy * 使用 Certbot 等外部组件进行证书更新 -* 带有 Ingress Controller(如 Nginx) 的 Kubernetes +* 带有 Ingress Controller(如 Nginx)的 Kubernetes * 使用诸如 cert-manager 之类的外部组件来进行证书更新 * 由云服务商内部处理,作为其服务的一部分(请阅读下文👇) -另一种选择是您可以使用**云服务**来完成更多工作,包括设置 HTTPS。 它可能有一些限制或向您收取更多费用等。但在这种情况下,您不必自己设置 TLS 终止代理。 +另一种选择是你可以使用**云服务**来完成更多工作,包括设置 HTTPS。它可能有一些限制或向你收取更多费用等。但在这种情况下,你不必自己设置 TLS 终止代理。 -我将在接下来的章节中向您展示一些具体示例。 +我将在接下来的章节中向你展示一些具体示例。 --- @@ -63,52 +63,52 @@ **程序**这个词通常用来描述很多东西: -* 您编写的 **代码**,**Python 文件**。 -* 操作系统可以**执行**的**文件**,例如:`python`、`python.exe`或`uvicorn`。 -* 在操作系统上**运行**、使用CPU 并将内容存储在内存上的特定程序。 这也被称为**进程**。 +* 你编写的 **代码**,**Python 文件**。 +* 操作系统可以**执行**的**文件**,例如:`python`、`python.exe` 或 `uvicorn`。 +* 在操作系统上**运行**、使用 CPU 并将内容存储在内存上的特定程序。这也被称为**进程**。 ### 什么是进程 { #what-is-a-process } -**进程** 这个词通常以更具体的方式使用,仅指在操作系统中运行的东西(如上面的最后一点): +**进程**这个词通常以更具体的方式使用,仅指在操作系统中运行的东西(如上面的最后一点): * 在操作系统上**运行**的特定程序。 * 这不是指文件,也不是指代码,它**具体**指的是操作系统正在**执行**和管理的东西。 -* 任何程序,任何代码,**只有在执行时才能做事**。 因此,是当有**进程正在运行**时。 -* 该进程可以由您或操作系统**终止**(或“杀死”)。 那时,它停止运行/被执行,并且它可以**不再做事情**。 -* 您计算机上运行的每个应用程序背后都有一些进程,每个正在运行的程序,每个窗口等。并且通常在计算机打开时**同时**运行许多进程。 +* 任何程序,任何代码,**只有在执行时才能做事**。因此,是当有**进程正在运行**时。 +* 该进程可以由你或操作系统**终止**(或“杀死”)。那时,它停止运行/被执行,并且它**不再能做事情**。 +* 你计算机上运行的每个应用程序背后都有一些进程,每个正在运行的程序,每个窗口等。并且通常在计算机打开时**同时**运行许多进程。 * **同一程序**可以有**多个进程**同时运行。 -如果您检查操作系统中的“任务管理器”或“系统监视器”(或类似工具),您将能够看到许多正在运行的进程。 +如果你检查操作系统中的“任务管理器”或“系统监视器”(或类似工具),你将能够看到许多正在运行的进程。 -例如,您可能会看到有多个进程运行同一个浏览器程序(Firefox、Chrome、Edge 等)。 他们通常每个tab运行一个进程,再加上一些其他额外的进程。 +例如,你可能会看到有多个进程运行同一个浏览器程序(Firefox、Chrome、Edge 等)。它们通常每个 tab 运行一个进程,再加上一些其他额外的进程。 --- -现在我们知道了术语“进程”和“程序”之间的区别,让我们继续讨论部署。 +现在我们知道了术语 **进程** 和 **程序** 之间的区别,让我们继续讨论部署。 ## 启动时运行 { #running-on-startup } -在大多数情况下,当您创建 Web API 时,您希望它**始终运行**、不间断,以便您的客户端始终可以访问它。 这是当然的,除非您有特定原因希望它仅在某些情况下运行,但大多数时候您希望它不断运行并且**可用**。 +在大多数情况下,当你创建 Web API 时,你希望它**始终运行**、不间断,以便你的客户端始终可以访问它。当然,除非你有特定原因希望它仅在某些情况下运行,但大多数时候你希望它不断运行并且**可用**。 ### 在远程服务器中 { #in-a-remote-server } -当您设置远程服务器(云服务器、虚拟机等)时,您可以做的最简单的事情就是使用 `fastapi run`(它使用 Uvicorn)或类似方式,手动运行,就像本地开发时一样。 +当你设置远程服务器(云服务器、虚拟机等)时,你可以做的最简单的事情就是使用 `fastapi run`(它使用 Uvicorn)或类似方式,手动运行,就像本地开发时一样。 -它将会在**开发过程中**发挥作用并发挥作用。 +它将会**在开发过程中**发挥作用并且很有用。 -但是,如果您与服务器的连接丢失,**正在运行的进程**可能会终止。 +但是,如果你与服务器的连接丢失,**正在运行的进程**可能会终止。 -如果服务器重新启动(例如更新后或从云提供商迁移后),您可能**不会注意到它**。 因此,您甚至不知道必须手动重新启动该进程。 所以,你的 API 将一直处于挂掉的状态。 😱 +如果服务器重新启动(例如更新后或从云提供商迁移后),你可能**不会注意到它**。因此,你甚至不知道必须手动重新启动该进程。所以,你的 API 将一直处于挂掉的状态。 😱 ### 启动时自动运行 { #run-automatically-on-startup } -一般来说,您可能希望服务器程序(例如 Uvicorn)在服务器启动时自动启动,并且不需要任何**人为干预**,让进程始终与您的 API 一起运行(例如 Uvicorn 运行您的 FastAPI 应用程序) 。 +一般来说,你可能希望服务器程序(例如 Uvicorn)在服务器启动时自动启动,并且不需要任何**人为干预**,让进程始终与你的 API 一起运行(例如 Uvicorn 运行你的 FastAPI 应用程序)。 ### 单独的程序 { #separate-program } -为了实现这一点,您通常会有一个**单独的程序**来确保您的应用程序在启动时运行。 在许多情况下,它还可以确保其他组件或应用程序也运行,例如数据库。 +为了实现这一点,你通常会有一个**单独的程序**来确保你的应用程序在启动时运行。在许多情况下,它还可以确保其他组件或应用程序也运行,例如数据库。 ### 启动时运行的示例工具 { #example-tools-to-run-at-startup } @@ -123,43 +123,43 @@ * 作为其服务的一部分由云提供商内部处理 * 其他的... -我将在接下来的章节中为您提供更具体的示例。 +我将在接下来的章节中为你提供更具体的示例。 ## 重新启动 { #restarts } -与确保应用程序在启动时运行类似,您可能还想确保它在挂掉后**重新启动**。 +与确保应用程序在启动时运行类似,你可能还想确保它在失败后**重新启动**。 ### 我们会犯错误 { #we-make-mistakes } -作为人类,我们总是会犯**错误**。 软件几乎*总是*在不同的地方隐藏着**bug**。 🐛 +作为人类,我们总是会犯**错误**。软件几乎*总是*在不同的地方隐藏着 **bug**。 🐛 -作为开发人员,当我们发现这些bug并实现新功能(也可能添加新bug😅)时,我们会不断改进代码。 +作为开发人员,当我们发现这些 bug 并实现新功能(也可能添加新 bug 😅)时,我们会不断改进代码。 ### 自动处理小错误 { #small-errors-automatically-handled } -使用 FastAPI 构建 Web API 时,如果我们的代码中存在错误,FastAPI 通常会将其包含到触发错误的单个请求中。 🛡 +使用 FastAPI 构建 Web API 时,如果我们的代码中存在错误,FastAPI 通常会将其限制在触发错误的单个请求中。 🛡 对于该请求,客户端将收到 **500 内部服务器错误**,但应用程序将继续处理下一个请求,而不是完全崩溃。 ### 更大的错误 - 崩溃 { #bigger-errors-crashes } -尽管如此,在某些情况下,我们编写的一些代码可能会导致整个应用程序崩溃,从而导致 Uvicorn 和 Python 崩溃。 💥 +尽管如此,在某些情况下,我们编写的一些代码可能会**导致整个应用程序崩溃**,从而导致 Uvicorn 和 Python 崩溃。 💥 -尽管如此,您可能不希望应用程序因为某个地方出现错误而保持死机状态,您可能希望它**继续运行**,至少对于未破坏的*路径操作*。 +尽管如此,你可能不希望应用程序因为某个地方出现错误而保持死机状态,你可能希望它**继续运行**,至少对于未损坏的*路径操作*。 ### 崩溃后重新启动 { #restart-after-crash } -但在那些严重错误导致正在运行的**进程**崩溃的情况下,您需要一个外部组件来负责**重新启动**进程,至少尝试几次... +但在那些严重错误导致正在运行的**进程**崩溃的情况下,你需要一个外部组件来负责**重新启动**进程,至少尝试几次... /// tip | 提示 -...尽管如果整个应用程序只是**立即崩溃**,那么永远重新启动它可能没有意义。 但在这些情况下,您可能会在开发过程中注意到它,或者至少在部署后立即注意到它。 +...尽管如果整个应用程序只是**立即崩溃**,那么永远重新启动它可能没有意义。但在这些情况下,你可能会在开发过程中注意到它,或者至少在部署后立即注意到它。 因此,让我们关注主要情况,在**未来**的某些特定情况下,它可能会完全崩溃,但重新启动它仍然有意义。 /// -您可能希望让这个东西作为 **外部组件** 负责重新启动您的应用程序,因为到那时,使用 Uvicorn 和 Python 的同一应用程序已经崩溃了,因此同一应用程序的相同代码中没有东西可以对此做出什么。 +你可能希望让这个负责重新启动你的应用程序的东西作为一个**外部组件**,因为到那时,使用 Uvicorn 和 Python 的同一应用程序已经崩溃了,因此同一应用程序的相同代码中没有任何东西可以对此做什么。 ### 自动重新启动的示例工具 { #example-tools-to-restart-automatically } @@ -178,19 +178,19 @@ ## 复制 - 进程和内存 { #replication-processes-and-memory } -对于 FastAPI 应用程序,使用像 `fastapi` 命令(运行 Uvicorn)这样的服务器程序,在**一个进程**中运行一次就可以同时为多个客户端提供服务。 +对于 FastAPI 应用程序,使用像运行 Uvicorn 的 `fastapi` 命令这样的服务器程序,在**一个进程**中运行一次就可以同时为多个客户端提供服务。 -但在许多情况下,您会希望同时运行多个工作进程。 +但在许多情况下,你会希望同时运行多个工作进程。 ### 多进程 - Workers { #multiple-processes-workers } -如果您的客户端数量多于单个进程可以处理的数量(例如,如果虚拟机不是太大),并且服务器的 CPU 中有 **多个核心**,那么您可以让 **多个进程** 同时运行同一个应用程序,并在它们之间分发所有请求。 +如果你的客户端数量多于单个进程可以处理的数量(例如,如果虚拟机不是太大),并且服务器的 CPU 中有**多个核心**,那么你可以让**多个进程**同时运行同一个应用程序,并在它们之间分发所有请求。 -当您运行同一 API 程序的**多个进程**时,它们通常称为 **workers**。 +当你运行同一 API 程序的**多个进程**时,它们通常称为 **workers**。 ### 工作进程和端口 { #worker-processes-and-ports } -还记得文档 [关于 HTTPS](https.md) 中只有一个进程可以侦听服务器中的端口和 IP 地址的一种组合吗? +还记得文档[关于 HTTPS](https.md) 中说的,在服务器中只有一个进程可以侦听端口和 IP 地址的一种组合吗? 现在仍然是对的。 @@ -198,124 +198,124 @@ ### 每个进程的内存 { #memory-per-process } -现在,当程序将内容加载到内存中时,例如,将机器学习模型加载到变量中,或者将大文件的内容加载到变量中,所有这些都会消耗服务器的一点内存 (RAM) 。 +现在,当程序将内容加载到内存中时,例如,将机器学习模型加载到变量中,或者将大文件的内容加载到变量中,所有这些都会**消耗服务器的一些内存 (RAM)**。 -多个进程通常**不共享任何内存**。 这意味着每个正在运行的进程都有自己的东西、变量和内存。 如果您的代码消耗了大量内存,**每个进程**将消耗等量的内存。 +多个进程通常**不共享任何内存**。这意味着每个正在运行的进程都有自己的东西、变量和内存。如果你的代码消耗了大量内存,**每个进程**将消耗等量的内存。 ### 服务器内存 { #server-memory } -例如,如果您的代码加载 **1 GB 大小**的机器学习模型,则当您使用 API 运行一个进程时,它将至少消耗 1 GB RAM。 如果您启动 **4 个进程**(4 个工作进程),每个进程将消耗 1 GB RAM。 因此,您的 API 总共将消耗 **4 GB RAM**。 +例如,如果你的代码加载**大小为 1 GB** 的机器学习模型,则当你使用 API 运行一个进程时,它将至少消耗 1 GB RAM。如果你启动 **4 个进程**(4 个工作进程),每个进程将消耗 1 GB RAM。因此,你的 API 总共将消耗 **4 GB RAM**。 -如果您的远程服务器或虚拟机只有 3 GB RAM,尝试加载超过 4 GB RAM 将导致问题。 🚨 +如果你的远程服务器或虚拟机只有 3 GB RAM,尝试加载超过 4 GB RAM 将导致问题。 🚨 ### 多进程 - 一个例子 { #multiple-processes-an-example } 在此示例中,有一个 **Manager Process** 启动并控制两个 **Worker Processes**。 -该管理器进程可能是监听 IP 中的 **端口** 的进程。 它将所有通信传输到工作进程。 +该管理器进程可能是监听 IP 中的**端口**的进程。它将所有通信传输到工作进程。 -这些工作进程将是运行您的应用程序的进程,它们将执行主要计算以接收 **请求** 并返回 **响应**,并且它们将加载您放入 RAM 中的变量中的任何内容。 +这些工作进程将是运行你的应用程序的进程,它们将执行主要计算以接收**请求**并返回**响应**,并且它们将加载你放入 RAM 中的变量中的任何内容。 -当然,除了您的应用程序之外,同一台机器可能还运行**其他进程**。 +当然,除了你的应用程序之外,同一台机器可能还运行**其他进程**。 一个有趣的细节是,随着时间的推移,每个进程使用的 **CPU 百分比**可能会发生很大变化,但**内存 (RAM)** 通常会或多或少保持**稳定**。 -如果您有一个每次执行相当数量的计算的 API,并且您有很多客户端,那么 **CPU 利用率** 可能也会保持稳定(而不是不断快速上升和下降)。 +如果你有一个每次执行相当数量的计算的 API,并且你有很多客户端,那么 **CPU 利用率** 可能*也会保持稳定*(而不是不断快速上升和下降)。 ### 复制工具和策略示例 { #examples-of-replication-tools-and-strategies } -可以通过多种方法来实现这一目标,我将在接下来的章节中向您详细介绍具体策略,例如在谈论 Docker 和容器时。 +可以通过多种方法来实现这一目标,我将在接下来的章节中向你详细介绍具体策略,例如在谈论 Docker 和容器时。 -要考虑的主要限制是必须有一个**单个**组件来处理**公共IP**中的**端口**。 然后它必须有一种方法将通信**传输**到复制的**进程/worker**。 +要考虑的主要限制是必须有一个**单个**组件来处理**公共 IP** 中的**端口**。然后它必须有一种方法将通信**传输**到复制的**进程/worker**。 以下是一些可能的组合和策略: * 带有 `--workers` 的 **Uvicorn** - * 一个 Uvicorn **进程管理器** 将监听 **IP** 和 **端口**,并且它将启动 **多个 Uvicorn 工作进程**。 -* **Kubernetes** 和其他分布式 **容器系统** - * **Kubernetes** 层中的某些东西将侦听 **IP** 和 **端口**。 复制将通过拥有**多个容器**,每个容器运行**一个 Uvicorn 进程**。 -* **云服务** 为您处理此问题 - * 云服务可能**为您处理复制**。 它可能会让您定义 **要运行的进程**,或要使用的 **容器映像**,在任何情况下,它很可能是 **单个 Uvicorn 进程**,并且云服务将负责复制它。 + * 一个 Uvicorn **进程管理器**将监听 **IP** 和**端口**,并且它将启动**多个 Uvicorn 工作进程**。 +* **Kubernetes** 和其他分布式**容器系统** + * **Kubernetes** 层中的某些东西将侦听 **IP** 和**端口**。复制将通过拥有**多个容器**来完成,每个容器运行**一个 Uvicorn 进程**。 +* **云服务** 为你处理此问题 + * 云服务可能**为你处理复制**。它可能会让你定义**要运行的进程**,或要使用的**容器镜像**,在任何情况下,它很可能是**单个 Uvicorn 进程**,并且云服务将负责复制它。 /// tip | 提示 -如果这些关于 **容器**、Docker 或 Kubernetes 的内容还没有多大意义,请不要担心。 +如果这些关于**容器**、Docker 或 Kubernetes 的内容还没有多大意义,请不要担心。 -我将在以后的章节中向您详细介绍容器镜像、Docker、Kubernetes 等:[容器中的 FastAPI - Docker](docker.md)。 +我将在以后的章节中向你详细介绍容器镜像、Docker、Kubernetes 等:[容器中的 FastAPI - Docker](docker.md)。 /// ## 启动之前的步骤 { #previous-steps-before-starting } -在很多情况下,您希望在**启动**应用程序之前执行一些步骤。 +在很多情况下,你希望在**启动**应用程序之前执行一些步骤。 -例如,您可能想要运行**数据库迁移**。 +例如,你可能想要运行**数据库迁移**。 -但在大多数情况下,您只想执行这些步骤**一次**。 +但在大多数情况下,你只想执行这些步骤**一次**。 -因此,在启动应用程序之前,您将需要一个**单个进程**来执行这些**前面的步骤**。 +因此,在启动应用程序之前,你将需要一个**单个进程**来执行这些**前面的步骤**。 -而且您必须确保它是运行前面步骤的单个进程, *即使*之后您为应用程序本身启动**多个进程**(多个worker)。 如果这些步骤由**多个进程**运行,它们会通过在**并行**运行来**重复**工作,并且如果这些步骤像数据库迁移一样需要小心处理,它们可能会导致每个进程和其他进程发生冲突。 +而且你必须确保它是运行前面步骤的单个进程,*即使*之后你为应用程序本身启动**多个进程**(多个 worker)。如果这些步骤由**多个进程**运行,它们会通过**并行**运行来**重复**工作,并且如果这些步骤像数据库迁移一样需要小心处理,它们可能会导致彼此之间发生冲突。 当然,也有一些情况,多次运行前面的步骤也没有问题,这样的话就好办多了。 /// tip | 提示 -另外,请记住,根据您的设置,在某些情况下,您在开始应用程序之前**可能甚至不需要任何先前的步骤**。 +另外,请记住,根据你的设置,在某些情况下,你在启动应用程序之前**可能甚至不需要任何先前的步骤**。 -在这种情况下,您就不必担心这些。 🤷 +在这种情况下,你就不必担心这些。 🤷 /// ### 前面步骤策略的示例 { #examples-of-previous-steps-strategies } -这将在**很大程度上取决于您部署系统的方式**,并且可能与您启动程序、处理重启等的方式有关。 +这将在**很大程度上取决于你部署系统的方式**,并且可能与你启动程序、处理重启等的方式有关。 以下是一些可能的想法: * Kubernetes 中的“Init Container”在应用程序容器之前运行 -* 一个 bash 脚本,运行前面的步骤,然后启动您的应用程序 - * 您仍然需要一种方法来启动/重新启动 bash 脚本、检测错误等。 +* 一个 bash 脚本,运行前面的步骤,然后启动你的应用程序 + * 你仍然需要一种方法来启动/重新启动*那个* bash 脚本、检测错误等。 /// tip | 提示 -我将在以后的章节中为您提供使用容器执行此操作的更具体示例:[容器中的 FastAPI - Docker](docker.md)。 +我将在以后的章节中为你提供使用容器执行此操作的更具体示例:[容器中的 FastAPI - Docker](docker.md)。 /// ## 资源利用率 { #resource-utilization } -您的服务器是一个**资源**,您可以通过您的程序消耗或**利用**CPU 上的计算时间以及可用的 RAM 内存。 +你的服务器是一个**资源**,你可以通过你的程序消耗或**利用** CPU 上的计算时间以及可用的 RAM 内存。 -您想要消耗/利用多少系统资源? 您可能很容易认为“不多”,但实际上,您可能希望在不崩溃的情况下**尽可能多地消耗**。 +你想要消耗/利用多少系统资源?你可能很容易认为“不多”,但实际上,你可能希望在不崩溃的情况下**尽可能多地消耗**。 -如果您支付了 3 台服务器的费用,但只使用了它们的一点点 RAM 和 CPU,那么您可能**浪费金钱** 💸,并且可能 **浪费服务器电力** 🌎,等等。 +如果你支付了 3 台服务器的费用,但只使用了它们的一点点 RAM 和 CPU,那么你可能**浪费金钱** 💸,并且可能**浪费服务器电力** 🌎,等等。 在这种情况下,最好只拥有 2 台服务器并使用更高比例的资源(CPU、内存、磁盘、网络带宽等)。 -另一方面,如果您有 2 台服务器,并且正在使用 **100% 的 CPU 和 RAM**,则在某些时候,一个进程会要求更多内存,并且服务器将不得不使用磁盘作为“内存” (这可能会慢数千倍),甚至**崩溃**。 或者一个进程可能需要执行一些计算,并且必须等到 CPU 再次空闲。 +另一方面,如果你有 2 台服务器,并且正在使用**它们 100% 的 CPU 和 RAM**,则在某些时候,一个进程会要求更多内存,并且服务器将不得不使用磁盘作为“内存”(这可能会慢数千倍),甚至**崩溃**。或者一个进程可能需要执行一些计算,并且必须等到 CPU 再次空闲。 在这种情况下,最好购买**一台额外的服务器**并在其上运行一些进程,以便它们都有**足够的 RAM 和 CPU 时间**。 -由于某种原因,您的 API 的使用量也有可能出现**激增**。 也许它像病毒一样传播开来,或者也许其他一些服务或机器人开始使用它。 在这些情况下,您可能需要额外的资源来保证安全。 +由于某种原因,你的 API 的使用量也有可能出现**激增**。也许它像病毒一样传播开来,或者也许其他一些服务或机器人开始使用它。在这些情况下,你可能需要额外的资源来保证安全。 -您可以将一个**任意数字**设置为目标,例如,资源利用率**在 50% 到 90%** 之间。 重点是,这些可能是您想要衡量和用来调整部署的主要内容。 +你可以将一个**任意数字**设置为目标,例如,资源利用率**在 50% 到 90%** 之间。重点是,这些可能是你想要衡量和用来调整部署的主要内容。 -您可以使用“htop”等简单工具来查看服务器中使用的 CPU 和 RAM 或每个进程使用的数量。 或者您可以使用更复杂的监控工具,这些工具可能分布在服务器等上。 +你可以使用 `htop` 等简单工具来查看服务器中使用的 CPU 和 RAM 或每个进程使用的数量。或者你可以使用更复杂的监控工具,这些工具可能分布在服务器等上。 ## 回顾 { #recap } -您在这里阅读了一些在决定如何部署应用程序时可能需要牢记的主要概念: +你在这里阅读了一些在决定如何部署应用程序时可能需要牢记的主要概念: * 安全性 - HTTPS * 启动时运行 * 重新启动 * 复制(运行的进程数) * 内存 -* 开始前的先前步骤 +* 启动前的先前步骤 -了解这些想法以及如何应用它们应该会给您足够的直觉在配置和调整部署时做出任何决定。 🤓 +了解这些想法以及如何应用它们应该会给你足够的直觉,以便在配置和调整部署时做出任何决定。 🤓 -在接下来的部分中,我将为您提供更具体的示例,说明您可以遵循的可能策略。 🚀 +在接下来的部分中,我将为你提供更具体的示例,说明你可以遵循的可能策略。 🚀 diff --git a/docs/zh/docs/deployment/docker.md b/docs/zh/docs/deployment/docker.md index c1b216953..5e3919bd2 100644 --- a/docs/zh/docs/deployment/docker.md +++ b/docs/zh/docs/deployment/docker.md @@ -1,5 +1,6 @@ # 容器中的 FastAPI - Docker { #fastapi-in-containers-docker } + 部署 FastAPI 应用时,常见做法是构建一个**Linux 容器镜像**。通常使用 [**Docker**](https://www.docker.com/) 实现。然后你可以用几种方式之一部署该镜像。 使用 Linux 容器有多种优势,包括**安全性**、**可复制性**、**简单性**等。 diff --git a/docs/zh/docs/deployment/https.md b/docs/zh/docs/deployment/https.md index 916fb46da..090c4ba59 100644 --- a/docs/zh/docs/deployment/https.md +++ b/docs/zh/docs/deployment/https.md @@ -67,7 +67,7 @@ 你可能拥有一个云服务器(虚拟机)或类似的东西,并且它会有一个固定 **公共IP地址**。 -在 DNS 服务器中,你可以配置一条记录(“A 记录”)以将 **你的域名** 指向你服务器的公共 **IP 地址**。 +在 DNS 服务器中,你可以配置一条记录(一个 `A record`)以将 **你的域名** 指向你服务器的公共 **IP 地址**。 这个操作一般只需要在最开始执行一次。 @@ -179,7 +179,7 @@ TLS 终止代理将使用协商好的加密算法**解密请求**,并将**( 因此,要更新证书,更新程序需要向权威机构(Let's Encrypt)**证明**它确实**“拥有”并控制该域名**。 -有多种方法可以做到这一点。 一些流行的方式是: +有多种方法可以做到这一点,并适应不同的应用需求。 一些流行的方式是: * **修改一些DNS记录**。 * 为此,续订程序需要支持 DNS 提供商的 API,因此,要看你使用的 DNS 提供商是否提供这一功能。 @@ -188,8 +188,7 @@ TLS 终止代理将使用协商好的加密算法**解密请求**,并将**( * 这就是当同一个 TLS 终止代理还负责证书续订过程时它非常有用的原因之一。 * 否则,你可能需要暂时停止 TLS 终止代理,启动续订程序以获取证书,然后使用 TLS 终止代理配置它们,然后重新启动 TLS 终止代理。 这并不理想,因为你的应用程序在 TLS 终止代理关闭期间将不可用。 -通过拥有一个**单独的系统来使用 TLS 终止代理来处理 HTTPS**, 而不是直接将 TLS 证书与应用程序服务器一起使用 (例如 Uvicorn),你可以在 -更新证书的过程中同时保持提供服务。 +在仍然为应用提供服务的同时完成整个更新流程,是你想要用 TLS 终止代理拥有一个**单独系统来处理 HTTPS**,而不是直接在应用服务器(例如 Uvicorn)上使用 TLS 证书的主要原因之一。 ## 代理转发请求头 { #proxy-forwarded-headers } @@ -209,7 +208,7 @@ TLS 终止代理将使用协商好的加密算法**解密请求**,并将**( 不过,由于**应用服务器**并不知道自己位于受信任的**代理**之后,默认情况下,它不会信任这些请求头。 -但你可以配置**应用服务器**去信任由**代理**发送的这些“转发”请求头。如果你在使用 FastAPI CLI,可以使用命令行选项 `--forwarded-allow-ips` 指定它应该信任哪些 IP 发来的这些“转发”请求头。 +但你可以配置**应用服务器**去信任由**代理**发送的这些*转发*请求头。如果你在使用 FastAPI CLI,可以使用 *CLI 选项* `--forwarded-allow-ips` 指定它应该信任哪些 IP 发来的这些*转发*请求头。 例如,如果**应用服务器**只接收来自受信任**代理**的通信,你可以设置 `--forwarded-allow-ips="*"`,让它信任所有传入的 IP,因为它只会接收来自**代理**所使用 IP 的请求。 diff --git a/docs/zh/docs/deployment/manually.md b/docs/zh/docs/deployment/manually.md index a395f96da..ee468f4e4 100644 --- a/docs/zh/docs/deployment/manually.md +++ b/docs/zh/docs/deployment/manually.md @@ -2,7 +2,7 @@ ## 使用 `fastapi run` 命令 { #use-the-fastapi-run-command } -简而言之,使用 `fastapi run` 来运行您的 FastAPI 应用程序: +简而言之,使用 `fastapi run` 来运行你的 FastAPI 应用程序:
@@ -40,7 +40,7 @@ $ fastapi run fastapi run ASGI。FastAPI 本质上是一个 ASGI Web 框架。 -要在远程服务器上运行 **FastAPI** 应用(或任何其他 ASGI 应用),您需要一个 ASGI 服务器程序,例如 **Uvicorn**。它是 `fastapi` 命令默认使用的 ASGI 服务器。 +要在远程服务器上运行 **FastAPI** 应用(或任何其他 ASGI 应用),你需要一个 ASGI 服务器程序,例如 **Uvicorn**。它是 `fastapi` 命令默认使用的 ASGI 服务器。 除此之外,还有其他一些可选的 ASGI 服务器,例如: @@ -63,17 +63,17 @@ FastAPI 使用了一种用于构建 Python Web 框架和服务器的标准,称 “**服务器**”一词通常用于指远程/云计算机(物理机或虚拟机)以及在该计算机上运行的程序(例如 Uvicorn)。 -请记住,当您一般读到“服务器”这个名词时,它可能指的是这两者之一。 +请记住,当你一般读到“服务器”这个名词时,它可能指的是这两者之一。 -当提到远程主机时,通常将其称为**服务器**,但也称为**机器**(machine)、**VM**(虚拟机)、**节点**。 这些都是指某种类型的远程计算机,通常运行 Linux,您可以在其中运行程序。 +当提到远程主机时,通常将其称为**服务器**,但也称为**机器**(machine)、**VM**(虚拟机)、**节点**。 这些都是指某种类型的远程计算机,通常运行 Linux,你可以在其中运行程序。 ## 安装服务器程序 { #install-the-server-program } -当您安装 FastAPI 时,它自带一个生产环境服务器——Uvicorn,并且您可以使用 `fastapi run` 命令来启动它。 +当你安装 FastAPI 时,它自带一个生产环境服务器——Uvicorn,并且你可以使用 `fastapi run` 命令来启动它。 -不过,您也可以手动安装 ASGI 服务器。 +不过,你也可以手动安装 ASGI 服务器。 -请确保您创建并激活一个[虚拟环境](../virtual-environments.md),然后再安装服务器应用程序。 +请确保你创建并激活一个[虚拟环境](../virtual-environments.md),然后再安装服务器应用程序。 例如,要安装 Uvicorn,可以运行以下命令: @@ -95,13 +95,13 @@ $ pip install "uvicorn[standard]" 其中包括 `uvloop`,这是 `asyncio` 的高性能替代方案,能够显著提升并发性能。 -当您使用 `pip install "fastapi[standard]"` 安装 FastAPI 时,实际上也会安装 `uvicorn[standard]`。 +当你使用 `pip install "fastapi[standard]"` 安装 FastAPI 时,实际上也会安装 `uvicorn[standard]`。 /// ## 运行服务器程序 { #run-the-server-program } -如果您手动安装了 ASGI 服务器,通常需要以特定格式传递一个导入字符串,以便服务器能够正确导入您的 FastAPI 应用: +如果你手动安装了 ASGI 服务器,通常需要以特定格式传递一个导入字符串,以便服务器能够正确导入你的 FastAPI 应用:
@@ -128,7 +128,7 @@ from main import app /// -每种 ASGI 服务器程序通常都会有类似的命令,您可以在它们的官方文档中找到更多信息。 +每种 ASGI 服务器程序通常都会有类似的命令,你可以在它们的官方文档中找到更多信息。 /// warning | 警告 @@ -144,7 +144,7 @@ Uvicorn 和其他服务器支持 `--reload` 选项,该选项在开发过程中 这些示例运行服务器程序(例如 Uvicorn),启动**单个进程**,在所有 IP(`0.0.0.0`)上监听预定义端口(例如`80`)。 -这是基本思路。 但您可能需要处理一些其他事情,例如: +这是基本思路。 但你可能需要处理一些其他事情,例如: * 安全性 - HTTPS * 启动时运行 @@ -153,4 +153,4 @@ Uvicorn 和其他服务器支持 `--reload` 选项,该选项在开发过程中 * 内存 * 开始前的步骤 -在接下来的章节中,我将向您详细介绍每个概念、如何思考它们,以及一些具体示例以及处理它们的策略。 🚀 +在接下来的章节中,我将向你详细介绍每个概念、如何思考它们,以及一些具体示例以及处理它们的策略。 🚀 diff --git a/docs/zh/docs/editor-support.md b/docs/zh/docs/editor-support.md index 5028c6c95..7caff801e 100644 --- a/docs/zh/docs/editor-support.md +++ b/docs/zh/docs/editor-support.md @@ -14,7 +14,7 @@ ## 功能 { #features } -- **Path Operation 资源管理器** - 侧边栏树状视图展示应用中的所有 *路径操作*。点击可跳转至任一路由或 APIRouter 的定义。 +- **Path Operation 资源管理器** - 侧边栏树状视图展示应用中的所有 *路径操作*。点击可跳转至任一路由或 router 的定义。 - **路由搜索** - 使用 Ctrl + Shift + E(macOS 上为 Cmd + Shift + E)按路径、方法或名称进行搜索。 - **CodeLens 导航** - 测试客户端调用(例如 `client.get('/items')`)上方的可点击链接,可跳转到匹配的*路径操作*,在测试与实现之间快速往返。 - **部署到 FastAPI Cloud** - 一键将你的应用部署到 [FastAPI Cloud](https://fastapicloud.com/)。 diff --git a/docs/zh/docs/environment-variables.md b/docs/zh/docs/environment-variables.md index 3a90ecde6..be6869e44 100644 --- a/docs/zh/docs/environment-variables.md +++ b/docs/zh/docs/environment-variables.md @@ -1,5 +1,6 @@ # 环境变量 { #environment-variables } + /// tip | 提示 如果你已经知道什么是“环境变量”并且知道如何使用它们,你可以放心跳过这一部分。 diff --git a/docs/zh/docs/features.md b/docs/zh/docs/features.md index 5fd9d48c4..1405bee46 100644 --- a/docs/zh/docs/features.md +++ b/docs/zh/docs/features.md @@ -19,11 +19,11 @@ ![Swagger UI interaction](https://fastapi.tiangolo.com/img/index/index-03-swagger-02.png) -* 另外的 API 文档:[**ReDoc**](https://github.com/Rebilly/ReDoc) +* 另外的 API 文档:[**ReDoc**](https://github.com/Rebilly/ReDoc)。 ![ReDoc](https://fastapi.tiangolo.com/img/index/index-06-redoc-02.png) -### 更主流的 Python { #just-modern-python } +### 就是现代 Python { #just-modern-python } 全部都基于标准的 **Python 类型** 声明(感谢 Pydantic)。没有新的语法需要学习。只需要标准的现代 Python。 @@ -98,7 +98,7 @@ my_second_user: User = User(**second_user_data) ### 简洁 { #short } -任何类型都有合理的**默认值**,任何和地方都有可选配置。所有的参数被微调,来满足你的需求,定义成你需要的 API。 +任何类型都有合理的**默认值**,任何地方都有可选配置。所有的参数被微调,来满足你的需求,定义成你需要的 API。 但是默认情况下,一切都能**“顺利工作”**。 @@ -110,7 +110,7 @@ my_second_user: User = User(**second_user_data) * 字符串 (`str`) 字段,定义最小或最大长度。 * 数字 (`int`, `float`) 有最大值和最小值,等等。 -* 校验外来类型,比如: +* 校验更特殊的类型,比如: * URL。 * Email。 * UUID。 @@ -120,9 +120,9 @@ my_second_user: User = User(**second_user_data) ### 安全性及身份验证 { #security-and-authentication } -集成了安全性和身份认证。杜绝数据库或者数据模型的渗透风险。 +集成了安全性和身份验证。不需要在数据库或数据模型上作出任何妥协。 -OpenAPI 中定义的安全模式,包括: +OpenAPI 中定义的所有安全模式,包括: * HTTP 基本认证。 * **OAuth2**(也使用 **JWT tokens**)。在 [使用 JWT 的 OAuth2](tutorial/security/oauth2-jwt.md) 查看教程。 @@ -131,7 +131,7 @@ OpenAPI 中定义的安全模式,包括: * 查询参数。 * Cookies,等等。 -加上来自 Starlette(包括 **session cookie**)的所有安全特性。 +加上来自 Starlette(包括 **session cookies**)的所有安全特性。 所有的这些都是可复用的工具和组件,可以轻松与你的系统,数据仓库,关系型以及 NoSQL 数据库等等集成。 @@ -142,7 +142,7 @@ FastAPI 有一个使用非常简单,但是非常强大的测试覆盖。 -* 代码库100% 类型注释。 +* 代码库100% 类型标注。 * 用于生产应用。 ## Starlette 特性 { #starlette-features } -**FastAPI** 和 [**Starlette**](https://www.starlette.dev/) 完全兼容(并基于)。所以,你有的其他的 Starlette 代码也能正常工作。`FastAPI` 实际上是 `Starlette` 的一个子类。所以,如果你已经知道或者使用 Starlette,大部分的功能会以相同的方式工作。 +**FastAPI** 与 [**Starlette**](https://www.starlette.dev/) 完全兼容(并基于它构建)。所以,你有的其他的 Starlette 代码也能正常工作。 + +`FastAPI` 实际上是 `Starlette` 的一个子类。所以,如果你已经知道或者使用 Starlette,大部分的功能会以相同的方式工作。 通过 **FastAPI** 你可以获得所有 **Starlette** 的特性(FastAPI 就像加强版的 Starlette): @@ -172,11 +174,11 @@ FastAPI 有一个使用非常简单,但是非常强大的IDE/linter/brain** 适配: * 因为 pydantic 数据结构仅仅是你定义的类的实例;自动补全,linting,mypy 以及你的直觉应该可以和你验证的数据一起正常工作。 * 验证**复杂结构**: diff --git a/docs/zh/docs/help-fastapi.md b/docs/zh/docs/help-fastapi.md index 2ff9752eb..1692d07ec 100644 --- a/docs/zh/docs/help-fastapi.md +++ b/docs/zh/docs/help-fastapi.md @@ -26,7 +26,7 @@ 你可以在 GitHub 上为 FastAPI 点亮「星标」(点击右上角的星形按钮):[https://github.com/fastapi/fastapi](https://github.com/fastapi/fastapi)。⭐️ -加星后,其他用户更容易发现它,并看到它已经对许多人有帮助。 +加星后,其他用户更容易发现它,并看到它已经对其他人有帮助。 ## 关注 GitHub 资源库的版本发布 { #watch-the-github-repository-for-releases } @@ -34,7 +34,7 @@ 在那里你可以选择「Releases only」。 -这样做之后,每当 **FastAPI** 发布新版本(包含修复和新功能),你都会收到通知(邮件)。 +这样做之后,每当 **FastAPI** 发布包含 Bug 修复和新功能的新版本时,你都会收到通知(邮件)。 ## 关注作者 { #follow-the-author } diff --git a/docs/zh/docs/how-to/configure-swagger-ui.md b/docs/zh/docs/how-to/configure-swagger-ui.md index 3dbc54911..d1909488a 100644 --- a/docs/zh/docs/how-to/configure-swagger-ui.md +++ b/docs/zh/docs/how-to/configure-swagger-ui.md @@ -16,11 +16,11 @@ FastAPI会将这些配置转换为 **JSON**,使其与 JavaScript 兼容,因 -但是你可以通过设置 `syntaxHighlight` 为 `False` 来禁用 Swagger UI 中的语法高亮: +但是你可以通过设置 `syntaxHighlight` 为 `False` 来禁用它: {* ../../docs_src/configure_swagger_ui/tutorial001_py310.py hl[3] *} -...在此之后,Swagger UI 将不会高亮代码: +...在此之后,Swagger UI 将不再显示语法高亮: @@ -30,7 +30,7 @@ FastAPI会将这些配置转换为 **JSON**,使其与 JavaScript 兼容,因 {* ../../docs_src/configure_swagger_ui/tutorial002_py310.py hl[3] *} -这个配置会改变语法高亮主题: +这个配置会改变语法高亮颜色主题: diff --git a/docs/zh/docs/how-to/custom-request-and-route.md b/docs/zh/docs/how-to/custom-request-and-route.md index 79860a562..4065818ea 100644 --- a/docs/zh/docs/how-to/custom-request-and-route.md +++ b/docs/zh/docs/how-to/custom-request-and-route.md @@ -72,7 +72,7 @@ 由 `GzipRequest.get_route_handler` 返回的函数唯一不同之处是把 `Request` 转换为 `GzipRequest`。 -这样,在传给我们的路径操作之前,`GzipRequest` 会(在需要时)负责解压数据。 +这样,在传给我们的*路径操作*之前,`GzipRequest` 会(在需要时)负责解压数据。 之后,其余处理逻辑完全相同。 @@ -104,6 +104,6 @@ {* ../../docs_src/custom_request_and_route/tutorial003_py310.py hl[26] *} -在此示例中,`router` 下的路径操作将使用自定义的 `TimedRoute` 类,响应中会多一个 `X-Response-Time` 头,包含生成响应所用的时间: +在此示例中,`router` 下的*路径操作*将使用自定义的 `TimedRoute` 类,响应中会多一个 `X-Response-Time` 头,包含生成响应所用的时间: {* ../../docs_src/custom_request_and_route/tutorial003_py310.py hl[13:20] *} diff --git a/docs/zh/docs/how-to/graphql.md b/docs/zh/docs/how-to/graphql.md index b33d6759f..31d15d3b4 100644 --- a/docs/zh/docs/how-to/graphql.md +++ b/docs/zh/docs/how-to/graphql.md @@ -2,7 +2,7 @@ 由于 **FastAPI** 基于 **ASGI** 标准,因此很容易集成任何也兼容 ASGI 的 **GraphQL** 库。 -你可以在同一个应用中将常规的 FastAPI 路径操作与 GraphQL 结合使用。 +你可以在同一个应用中将常规的 FastAPI *路径操作* 与 GraphQL 结合使用。 /// tip | 提示 diff --git a/docs/zh/docs/how-to/migrate-from-pydantic-v1-to-pydantic-v2.md b/docs/zh/docs/how-to/migrate-from-pydantic-v1-to-pydantic-v2.md index 3723eb032..ecfdd0278 100644 --- a/docs/zh/docs/how-to/migrate-from-pydantic-v1-to-pydantic-v2.md +++ b/docs/zh/docs/how-to/migrate-from-pydantic-v1-to-pydantic-v2.md @@ -8,9 +8,11 @@ FastAPI 0.119.0 引入了在 Pydantic v2 内部以 `pydantic.v1` 形式对 Pydan FastAPI 0.126.0 移除了对 Pydantic v1 的支持,但在一段时间内仍支持 `pydantic.v1`。 +FastAPI 0.128.0 也移除了对 `pydantic.v1` 的支持,因此最新版本的 FastAPI 需要 Pydantic v2。 + /// warning | 警告 -从 Python 3.14 开始,Pydantic 团队不再为最新的 Python 版本提供 Pydantic v1 的支持。 +从 **Python 3.14** 开始,Pydantic 团队不再为最新的 Python 版本提供 Pydantic v1 的支持。 这也包括 `pydantic.v1`,在 Python 3.14 及更高版本中不再受支持。 @@ -18,7 +20,7 @@ FastAPI 0.126.0 移除了对 Pydantic v1 的支持,但在一段时间内仍支 /// -如果你的旧 FastAPI 应用在用 Pydantic v1,这里将向你展示如何迁移到 Pydantic v2,以及 FastAPI 0.119.0 中可帮助你渐进式迁移的功能。 +如果你的旧 FastAPI 应用在用 Pydantic v1,这里将向你展示如何迁移到 Pydantic v2,以及 **FastAPI 0.119.0 中的功能** 可帮助你渐进式迁移。 ## 官方指南 { #official-guide } @@ -54,6 +56,16 @@ Pydantic v2 以子模块 `pydantic.v1` 的形式包含了 Pydantic v1 的全部 ### FastAPI 对 v2 中 Pydantic v1 的支持 { #fastapi-support-for-pydantic-v1-in-v2 } +/// warning | 警告 + +此 FastAPI 对 `pydantic.v1` 模型的支持是在 **FastAPI 0.119.0** 中添加的,并在 **FastAPI 0.128.0** 中移除。它原本是为了迁移到 Pydantic v2 而提供的临时辅助。 + +在当前版本的 FastAPI 中,在你的应用里使用 `pydantic.v1` 模型会引发错误。 + +本节其余部分描述的临时支持仅在那些较旧版本中可用。 + +/// + 自 FastAPI 0.119.0 起,FastAPI 也对 Pydantic v2 内的 Pydantic v1 提供了部分支持,以便迁移到 v2。 因此,你可以将 Pydantic 升级到最新的 v2,并将导入改为使用 `pydantic.v1` 子模块,在很多情况下就能直接工作。 @@ -122,6 +134,12 @@ graph TB ### 分步迁移 { #migrate-in-steps } +/// warning | 警告 + +下面描述的在同一应用中同时使用 Pydantic v1 和 v2 模型进行渐进式迁移,只适用于 **FastAPI 0.119.0 到 0.127.x**。它已在 **FastAPI 0.128.0** 中移除,最新版本需要 **Pydantic v2** 模型。 + +/// + /// tip | 提示 优先尝试 `bump-pydantic`,如果测试通过且可行,那么你就用一个命令完成了。✨ diff --git a/docs/zh/docs/how-to/separate-openapi-schemas.md b/docs/zh/docs/how-to/separate-openapi-schemas.md index 19d372b46..a7335143a 100644 --- a/docs/zh/docs/how-to/separate-openapi-schemas.md +++ b/docs/zh/docs/how-to/separate-openapi-schemas.md @@ -1,5 +1,6 @@ # 是否为输入和输出分别生成 OpenAPI JSON Schema { #separate-openapi-schemas-for-input-and-output-or-not } + 自从发布了 **Pydantic v2**,生成的 OpenAPI 比之前更精确、更**正确**了。😎 事实上,在某些情况下,对于同一个 Pydantic 模型,OpenAPI 中会根据是否带有**默认值**,为输入和输出分别生成**两个 JSON Schema**。 diff --git a/docs/zh/docs/index.md b/docs/zh/docs/index.md index 74b799e5c..6b75291fe 100644 --- a/docs/zh/docs/index.md +++ b/docs/zh/docs/index.md @@ -106,19 +106,19 @@ FastAPI 是一个用于构建 API 的现代、快速(高性能)的 Web 框
“我最近大量使用 FastAPI。我实际上计划把它用于我团队在 微软的机器学习(ML)服务。其中一些正在集成进核心 Windows 产品以及一些 Office 产品。”
-
— Kabir Khan,Microsoft (ref)
+
— Kabir Khan,Microsoft (参考)
@@ -127,25 +127,25 @@ FastAPI 是一个用于构建 API 的现代、快速(高性能)的 Web 框 「_[...] 我最近大量使用 **FastAPI**。[...] 我实际上计划把它用于我团队在 **微软的机器学习(ML)服务**。其中一些正在集成进核心 **Windows** 产品以及一些 **Office** 产品。_」 -
Kabir Khan - Microsoft (ref)
+
Kabir Khan - Microsoft (参考)
--- 「_我们采用 **FastAPI** 库来启动一个可查询以获取**预测结果**的 **REST** 服务器。[用于 Ludwig]_」 -
Piero Molino,Yaroslav Dudin,Sai Sumanth Miryala - Uber (ref)
+
Piero Molino,Yaroslav Dudin,Sai Sumanth Miryala - Uber (参考)
--- 「_**Netflix** 很高兴宣布开源我们的**危机管理**编排框架:**Dispatch**![使用 **FastAPI** 构建]_」 -
Kevin Glisson,Marc Vilanova,Forest Monsen - Netflix (ref)
+
Kevin Glisson,Marc Vilanova,Forest Monsen - Netflix (参考)
--- 「_如果有人正在构建生产级的 Python API,我强烈推荐 **FastAPI**。它**设计优雅**、**使用简单**且**高度可扩展**,它已经成为我们 API 优先开发战略中的**关键组件**,并驱动了许多自动化和服务,比如我们的 Virtual TAC Engineer。_」 -
Deon Pillsbury - Cisco (ref)
+
Deon Pillsbury - Cisco (参考)
--- @@ -192,7 +192,7 @@ $ pip install "fastapi[standard]"
-**Note**: 请确保把 `"fastapi[standard]"` 用引号包起来,以保证在所有终端中都能正常工作。 +**注意**: 请确保把 `"fastapi[standard]"` 用引号包起来,以保证在所有终端中都能正常工作。 ## 示例 { #example } @@ -237,7 +237,7 @@ async def read_item(item_id: int, q: str | None = None): return {"item_id": item_id, "q": q} ``` -**Note**: +**注意**: 如果你不确定,请查看文档中 _"In a hurry?"_ 章节的 [`async` 和 `await`](https://fastapi.tiangolo.com/zh/async/#in-a-hurry) 部分。 @@ -400,7 +400,7 @@ item_id: int item: Item ``` -……通过一次声明,你将获得: +...通过一次声明,你将获得: * 编辑器支持,包括: * 自动补全。 @@ -421,7 +421,7 @@ item: Item * `datetime` 对象。 * `UUID` 对象。 * 数据库模型。 - * ……以及更多。 + * ...以及更多。 * 自动生成的交互式 API 文档,包括两种可选的用户界面: * Swagger UI。 * ReDoc。 @@ -457,19 +457,19 @@ item: Item return {"item_name": item.name, "item_id": item_id} ``` -……从: +...从: ```Python ... "item_name": item.name ... ``` -……改为: +...改为: ```Python ... "item_price": item.price ... ``` -……看看你的编辑器如何自动补全属性并知道它们的类型: +...看看你的编辑器如何自动补全属性并知道它们的类型: ![editor support](https://fastapi.tiangolo.com/img/vscode-completion.png) @@ -488,7 +488,7 @@ item: Item * 基于 HTTPX 和 `pytest` 的极其简单的测试 * **CORS** * **Cookie Sessions** - * ……以及更多。 + * ...以及更多。 ### 部署你的应用(可选) { #deploy-your-app-optional } diff --git a/docs/zh/docs/project-generation.md b/docs/zh/docs/project-generation.md index 8cc50c096..371eb7319 100644 --- a/docs/zh/docs/project-generation.md +++ b/docs/zh/docs/project-generation.md @@ -1,5 +1,6 @@ # FastAPI全栈模板 { #full-stack-fastapi-template } + 模板通常带有特定的设置,但它们被设计为灵活且可定制。这样你可以根据项目需求进行修改和调整,使其成为很好的起点。🏁 你可以使用此模板开始,它已经为你完成了大量的初始设置、安全性、数据库以及一些 API 端点。 diff --git a/docs/zh/docs/python-types.md b/docs/zh/docs/python-types.md index 7901f9702..4d2c2749a 100644 --- a/docs/zh/docs/python-types.md +++ b/docs/zh/docs/python-types.md @@ -2,11 +2,11 @@ Python 支持可选的“类型提示”(也叫“类型注解”)。 -这些“类型提示”或注解是一种特殊语法,用来声明变量的类型。 +这些 **“类型提示”** 或注解是一种特殊语法,用来声明变量的类型。 通过为变量声明类型,编辑器和工具可以为你提供更好的支持。 -这只是一个关于 Python 类型提示的快速入门/复习。它只涵盖与 **FastAPI** 一起使用所需的最少部分...实际上非常少。 +这只是一个关于 Python 类型提示的**快速入门/复习**。它只涵盖与 **FastAPI** 一起使用所需的最少部分...实际上非常少。 **FastAPI** 完全基于这些类型提示构建,它们带来了许多优势和好处。 @@ -44,7 +44,7 @@ John Doe 但现在想象你要从零开始写它。 -在某个时刻你开始定义函数,并且准备好了参数…… +在某个时刻你开始定义函数,并且准备好了参数... 接下来你需要调用“那个把首字母变大写的方法”。 @@ -62,7 +62,7 @@ John Doe 我们来改前一个版本的一行代码。 -把函数参数从: +我们会把这个片段,也就是函数参数,从: ```Python first_name, last_name @@ -151,7 +151,7 @@ def some_function(data: Any): 有些类型可以在方括号中接收“类型参数”(type parameters),用于声明其内部值的类型。比如“字符串列表”可以写为 `list[str]`。 -这些能接收类型参数的类型称为“泛型类型”(Generic types)或“泛型”(Generics)。 +这些能接收类型参数的类型称为**泛型类型**(Generic types)或**泛型**(Generics)。 你可以把相同的内建类型作为泛型使用(带方括号和内部类型): @@ -221,7 +221,7 @@ def some_function(data: Any): #### Union { #union } -你可以声明一个变量可以是若干种类型中的任意一种,比如既可以是 `int` 也可以是 `str`。 +你可以声明一个变量可以是**若干种类型**中的任意一种,比如既可以是 `int` 也可以是 `str`。 定义时使用竖线(`|`)把两种类型分开。 @@ -263,9 +263,9 @@ def some_function(data: Any): -注意,这表示“`one_person` 是类 `Person` 的一个实例(instance)”。 +注意,这表示“`one_person` 是类 `Person` 的一个**实例**(instance)”。 -它并不表示“`one_person` 是名为 `Person` 的类本身(class)”。 +它并不表示“`one_person` 是名为 `Person` 的**类**(class)”。 ## Pydantic 模型 { #pydantic-models } @@ -285,7 +285,7 @@ def some_function(data: Any): /// note | 注意 -想了解更多关于 [Pydantic](https://docs.pydantic.dev/) 的信息,请查看其文档。 +要了解更多关于 [Pydantic 的信息,请查看其文档](https://docs.pydantic.dev/)。 /// @@ -295,7 +295,7 @@ def some_function(data: Any): ## 带元数据注解的类型提示 { #type-hints-with-metadata-annotations } -Python 还提供了一个特性,可以使用 `Annotated` 在这些类型提示中放入额外的元数据。 +Python 还提供了一个特性,可以使用 `Annotated` 在这些类型提示中放入**额外的元数据**。 你可以从 `typing` 导入 `Annotated`。 @@ -305,15 +305,15 @@ Python 本身不会对这个 `Annotated` 做任何处理。对于编辑器和其 但你可以在 `Annotated` 中为 **FastAPI** 提供额外的元数据,来描述你希望应用如何行为。 -重要的是要记住:传给 `Annotated` 的第一个类型参数才是实际类型。其余的只是给其他工具用的元数据。 +重要的是要记住:传给 `Annotated` 的**第一个*类型参数***才是**实际类型**。其余的只是给其他工具用的元数据。 现在你只需要知道 `Annotated` 的存在,并且它是标准 Python。😎 -稍后你会看到它有多么强大。 +稍后你会看到它有多么**强大**。 /// tip | 提示 -这是标准 Python,这意味着你仍然可以在编辑器里获得尽可能好的开发体验,并能和你用来分析、重构代码的工具良好协作等。✨ +这是**标准 Python**,这意味着你仍然可以在编辑器里获得**尽可能好的开发体验**,并能和你用来分析、重构代码的工具良好协作等。✨ 同时你的代码也能与许多其他 Python 工具和库高度兼容。🚀 @@ -325,16 +325,16 @@ Python 本身不会对这个 `Annotated` 做任何处理。对于编辑器和其 在 **FastAPI** 中,用类型提示来声明参数,你将获得: -* 编辑器支持。 -* 类型检查。 +* **编辑器支持**。 +* **类型检查**。 -……并且 **FastAPI** 会使用相同的声明来: +...并且 **FastAPI** 会使用相同的声明来: -* 定义要求:从请求路径参数、查询参数、请求头、请求体、依赖等。 -* 转换数据:把请求中的数据转换为所需类型。 -* 校验数据:对于每个请求: - * 当数据无效时,自动生成错误信息返回给客户端。 -* 使用 OpenAPI 记录 API: +* **定义要求**:从请求路径参数、查询参数、请求头、请求体、依赖等。 +* **转换数据**:把请求中的数据转换为所需类型。 +* **校验数据**:对于每个请求: + * 当数据无效时,自动生成返回给客户端的**错误**。 +* 使用 OpenAPI **记录** API: * 然后用于自动生成交互式文档界面。 这些听起来可能有点抽象。别担心。你会在[教程 - 用户指南](tutorial/index.md)中看到所有这些的实际效果。 @@ -343,6 +343,6 @@ Python 本身不会对这个 `Annotated` 做任何处理。对于编辑器和其 /// note | 注意 -如果你已经读完所有教程,又回来想进一步了解类型,一个不错的资源是 [`mypy` 的“速查表”](https://mypy.readthedocs.io/en/latest/cheat_sheet_py3.html)。 +如果你已经读完整个教程,又回来想进一步了解类型,一个不错的资源是 [`mypy` 的“速查表”](https://mypy.readthedocs.io/en/latest/cheat_sheet_py3.html)。 /// diff --git a/docs/zh/docs/tutorial/bigger-applications.md b/docs/zh/docs/tutorial/bigger-applications.md index 1be1be628..9bb4bea99 100644 --- a/docs/zh/docs/tutorial/bigger-applications.md +++ b/docs/zh/docs/tutorial/bigger-applications.md @@ -17,16 +17,16 @@ ``` . ├── app -│   ├── __init__.py -│   ├── main.py -│   ├── dependencies.py -│   └── routers -│   │ ├── __init__.py -│   │ ├── items.py -│   │ └── users.py -│   └── internal -│   ├── __init__.py -│   └── admin.py +│ ├── __init__.py +│ ├── main.py +│ ├── dependencies.py +│ └── routers +│ │ ├── __init__.py +│ │ ├── items.py +│ │ └── users.py +│ └── internal +│ ├── __init__.py +│ └── admin.py ``` /// tip | 提示 diff --git a/docs/zh/docs/tutorial/body-nested-models.md b/docs/zh/docs/tutorial/body-nested-models.md index 98e5168aa..ce10b74a9 100644 --- a/docs/zh/docs/tutorial/body-nested-models.md +++ b/docs/zh/docs/tutorial/body-nested-models.md @@ -137,7 +137,7 @@ Pydantic 模型的每个属性都具有类型。 /// note | 注意 -请注意 `images` 键现在具有一组 image 对象是如何发生的。 +请注意 `images` 键现在具有一个 image 对象列表是如何发生的。 /// @@ -149,7 +149,7 @@ Pydantic 模型的每个属性都具有类型。 /// note | 注意 -请注意 `Offer` 拥有一组 `Item` 而反过来 `Item` 又有一个可选的 `Image` 列表是如何发生的。 +请注意 `Offer` 拥有一个 `Item` 列表,而反过来 `Item` 又有一个可选的 `Image` 列表是如何发生的。 /// diff --git a/docs/zh/docs/tutorial/body.md b/docs/zh/docs/tutorial/body.md index ee4124e94..b32a5ac60 100644 --- a/docs/zh/docs/tutorial/body.md +++ b/docs/zh/docs/tutorial/body.md @@ -20,21 +20,22 @@ ## 导入 Pydantic 的 `BaseModel` { #import-pydantics-basemodel } -从 `pydantic` 中导入 `BaseModel`: +首先,你需要从 `pydantic` 中导入 `BaseModel`: {* ../../docs_src/body/tutorial001_py310.py hl[2] *} ## 创建数据模型 { #create-your-data-model } -把数据模型声明为继承 `BaseModel` 的类。 +然后,把数据模型声明为继承 `BaseModel` 的类。 使用 Python 标准类型声明所有属性: {* ../../docs_src/body/tutorial001_py310.py hl[5:9] *} + 与声明查询参数一样,包含默认值的模型属性是可选的,否则就是必选的。把默认值设为 `None` 可使其变为可选。 -例如,上述模型声明如下 JSON "object"(即 Python `dict`): +例如,上述模型声明如下 JSON "`object`"(即 Python `dict`): ```JSON { @@ -45,7 +46,7 @@ } ``` -...由于 `description` 和 `tax` 是可选的(默认值为 `None`),下面的 JSON "object" 也有效: +...由于 `description` 和 `tax` 是可选的(默认值为 `None`),下面的 JSON "`object`" 也有效: ```JSON { @@ -123,7 +124,7 @@ ## 使用模型 { #use-the-model } -在*路径操作*函数内部直接访问模型对象的所有属性: +在函数内部直接访问模型对象的所有属性: {* ../../docs_src/body/tutorial002_py310.py *} @@ -135,6 +136,7 @@ {* ../../docs_src/body/tutorial003_py310.py hl[15:16] *} + ## 请求体 + 路径 + 查询参数 { #request-body-path-query-parameters } 也可以同时声明**请求体**、**路径**和**查询**参数。 diff --git a/docs/zh/docs/tutorial/debugging.md b/docs/zh/docs/tutorial/debugging.md index 4f4503eef..0b1ada2de 100644 --- a/docs/zh/docs/tutorial/debugging.md +++ b/docs/zh/docs/tutorial/debugging.md @@ -62,7 +62,7 @@ from myapp import app # 其他一些代码 ``` -在这种情况下,`myapp.py` 内部的自动变量不会有值为 `"__main__"` 的变量 `__name__`。 +在这种情况下,`myapp.py` 内部自动创建的变量 `__name__` 不会有值 `"__main__"`。 所以,这一行: @@ -89,7 +89,7 @@ from myapp import app * 进入到「调试」面板。 * 「添加配置...」。 * 选中「Python」 -* 运行「Python:当前文件(集成终端)」选项的调试器。 +* 使用选项 "`Python: Current File (Integrated Terminal)`" 运行调试器。 然后它会使用你的 **FastAPI** 代码开启服务器,停在断点处,等等。 @@ -99,7 +99,7 @@ from myapp import app --- -如果使用 Pycharm,你可以: +如果使用 PyCharm,你可以: * 打开「运行」菜单。 * 选中「调试...」。 diff --git a/docs/zh/docs/tutorial/dependencies/dependencies-with-yield.md b/docs/zh/docs/tutorial/dependencies/dependencies-with-yield.md index 5beda5709..85510bbf4 100644 --- a/docs/zh/docs/tutorial/dependencies/dependencies-with-yield.md +++ b/docs/zh/docs/tutorial/dependencies/dependencies-with-yield.md @@ -267,7 +267,8 @@ with open("./somefile.txt") as f: 在 Python 中,你可以通过[创建一个带有 `__enter__()` 和 `__exit__()` 方法的类](https://docs.python.org/3/reference/datamodel.html#context-managers)来创建上下文管理器。 -你也可以在 **FastAPI** 的带有 `yield` 的依赖中,使用依赖函数内部的 `with` 或 `async with` 语句来使用它们: +你也可以在 **FastAPI** 的带有 `yield` 的依赖中通过在依赖函数内部使用 +`with` 或 `async with` 语句来使用它们: {* ../../docs_src/dependencies/tutorial010_py310.py hl[1:9,13] *} diff --git a/docs/zh/docs/tutorial/extra-data-types.md b/docs/zh/docs/tutorial/extra-data-types.md index 76748a7a3..441558285 100644 --- a/docs/zh/docs/tutorial/extra-data-types.md +++ b/docs/zh/docs/tutorial/extra-data-types.md @@ -1,15 +1,15 @@ # 额外数据类型 { #extra-data-types } -到目前为止,您一直在使用常见的数据类型,如: +到目前为止,你一直在使用常见的数据类型,如: * `int` * `float` * `str` * `bool` -但是您也可以使用更复杂的数据类型。 +但是你也可以使用更复杂的数据类型。 -您仍然会拥有现在已经看到的相同的特性: +你仍然会拥有现在已经看到的相同的特性: * 很棒的编辑器支持。 * 传入请求的数据转换。 @@ -49,7 +49,7 @@ * `Decimal`: * 标准的 Python `Decimal`。 * 在请求和响应中被当做 `float` 一样处理。 -* 您可以在这里检查所有有效的 Pydantic 数据类型: [Pydantic data types](https://docs.pydantic.dev/latest/usage/types/types/)。 +* 你可以在这里检查所有有效的 Pydantic 数据类型: [Pydantic data types](https://docs.pydantic.dev/latest/usage/types/types/)。 ## 例子 { #example } diff --git a/docs/zh/docs/tutorial/extra-models.md b/docs/zh/docs/tutorial/extra-models.md index 0ad35cc4f..60f66c5f1 100644 --- a/docs/zh/docs/tutorial/extra-models.md +++ b/docs/zh/docs/tutorial/extra-models.md @@ -1,5 +1,6 @@ # 更多模型 { #extra-models } + 书接上文,多个关联模型这种情况很常见。 特别是用户模型,因为: diff --git a/docs/zh/docs/tutorial/first-steps.md b/docs/zh/docs/tutorial/first-steps.md index 3eee0d44f..cadcac3e2 100644 --- a/docs/zh/docs/tutorial/first-steps.md +++ b/docs/zh/docs/tutorial/first-steps.md @@ -1,5 +1,6 @@ # 第一步 { #first-steps } + 最简单的 FastAPI 文件可能像下面这样: {* ../../docs_src/first_steps/tutorial001_py310.py *} diff --git a/docs/zh/docs/tutorial/handling-errors.md b/docs/zh/docs/tutorial/handling-errors.md index f3a23fab0..b77ca7a6c 100644 --- a/docs/zh/docs/tutorial/handling-errors.md +++ b/docs/zh/docs/tutorial/handling-errors.md @@ -6,16 +6,16 @@ 你可能需要告诉客户端: -- 客户端没有执行该操作的权限 -- 客户端没有访问该资源的权限 -- 客户端要访问的项目不存在 -- 等等 +* 客户端没有执行该操作的权限 +* 客户端没有访问该资源的权限 +* 客户端要访问的项目不存在 +* 等等 -遇到这些情况时,通常要返回 **4XX**(400 至 499)**HTTP 状态码**。 +遇到这些情况时,通常要返回 **400** 范围内(400 至 499)的 **HTTP 状态码**。 -这与表示请求成功的 **2XX**(200 至 299)HTTP 状态码类似。那些“200”状态码表示某种程度上的“成功”。 +这与 200 HTTP 状态码(200 至 299)类似。那些“200”状态码表示请求在某种程度上“成功”。 -而 **4XX** 状态码表示客户端发生了错误。 +而 400 范围内的状态码表示客户端发生了错误。 大家都知道**「404 Not Found」**错误,还有调侃这个错误的笑话吧? @@ -237,8 +237,8 @@ from starlette.exceptions import HTTPException as StarletteHTTPException ### 复用 **FastAPI** 的异常处理器 { #reuse-fastapis-exception-handlers } -如果你想在自定义处理后仍复用 **FastAPI** 的默认异常处理器,可以从 `fastapi.exception_handlers` 导入并复用这些默认处理器: +如果你想在使用该异常的同时使用 **FastAPI** 的相同默认异常处理器,可以从 `fastapi.exception_handlers` 导入并复用这些默认处理器: {* ../../docs_src/handling_errors/tutorial006_py310.py hl[2:5,15,21] *} -虽然本例只是用非常夸张的信息打印了错误,但足以说明:你可以先处理异常,然后再复用默认的异常处理器。 +虽然本例只是用非常夸张的信息打印了错误,但足以说明:你可以使用该异常,然后直接复用默认的异常处理器。 diff --git a/docs/zh/docs/tutorial/index.md b/docs/zh/docs/tutorial/index.md index 8d6cbc7a6..fde264d2c 100644 --- a/docs/zh/docs/tutorial/index.md +++ b/docs/zh/docs/tutorial/index.md @@ -1,10 +1,10 @@ # 教程 - 用户指南 { #tutorial-user-guide } -本教程将一步步向您展示如何使用 **FastAPI** 的绝大部分特性。 +本教程将一步步向你展示如何使用 **FastAPI** 的绝大部分特性。 -各个章节的内容循序渐进,但是又围绕着单独的主题,所以您可以直接跳转到某个章节以解决您的特定 API 需求。 +各个章节的内容循序渐进,但是又围绕着单独的主题,所以你可以直接跳转到某个章节以解决你的特定 API 需求。 -本教程同样可以作为将来的参考手册,所以您可以随时回到本教程并查阅您需要的内容。 +本教程同样可以作为将来的参考手册,所以你可以随时回到本教程并查阅你需要的内容。 ## 运行代码 { #run-the-code } @@ -52,7 +52,7 @@ $ fastapi dev
-**强烈建议**您在本地编写或复制代码,对其进行编辑并运行。 +**强烈建议**你在本地编写或复制代码,对其进行编辑并运行。 在编辑器中使用 FastAPI 会真正地展现出它的优势:只需要编写很少的代码,所有的类型检查,代码补全等等。 @@ -60,9 +60,9 @@ $ fastapi dev ## 安装 FastAPI { #install-fastapi } -第一个步骤是安装 FastAPI. +第一个步骤是安装 FastAPI。 -请确保您创建并激活一个[虚拟环境](../virtual-environments.md),然后**安装 FastAPI**: +请确保你创建并激活一个[虚拟环境](../virtual-environments.md),然后**安装 FastAPI**:
@@ -76,11 +76,11 @@ $ pip install "fastapi[standard]" /// note | 注意 -当您使用 `pip install "fastapi[standard]"` 安装时,它会附带一些默认的可选标准依赖项,其中包括 `fastapi-cloud-cli`,它可以让您部署到 [FastAPI Cloud](https://fastapicloud.com)。 +当你使用 `pip install "fastapi[standard]"` 安装时,它会附带一些默认的可选标准依赖项,其中包括 `fastapi-cloud-cli`,它可以让你部署到 [FastAPI Cloud](https://fastapicloud.com)。 -如果您不想安装这些可选依赖,可以选择安装 `pip install fastapi`。 +如果你不想安装这些可选依赖,可以选择安装 `pip install fastapi`。 -如果您想安装标准依赖但不包含 `fastapi-cloud-cli`,可以使用 `pip install "fastapi[standard-no-fastapi-cloud-cli]"` 安装。 +如果你想安装标准依赖但不包含 `fastapi-cloud-cli`,可以使用 `pip install "fastapi[standard-no-fastapi-cloud-cli]"` 安装。 /// @@ -92,10 +92,10 @@ FastAPI 提供了一个[VS Code 官方扩展](https://marketplace.visualstudio.c ## 进阶用户指南 { #advanced-user-guide } -在本**教程-用户指南**之后,您可以阅读**进阶用户指南**。 +在本**教程-用户指南**之后,你可以阅读**进阶用户指南**。 **进阶用户指南**以本教程为基础,使用相同的概念,并教授一些额外的特性。 -但是您应该先阅读**教程-用户指南**(即您现在正在阅读的内容)。 +但是你应该先阅读**教程-用户指南**(即你现在正在阅读的内容)。 -教程经过精心设计,使您可以仅通过**教程-用户指南**来开发一个完整的应用程序,然后根据您的需要,使用**进阶用户指南**中的一些其他概念,以不同的方式来扩展它。 +教程经过精心设计,使你可以仅通过**教程-用户指南**来开发一个完整的应用程序,然后根据你的需要,使用**进阶用户指南**中的一些其他概念,以不同的方式来扩展它。 diff --git a/docs/zh/docs/tutorial/metadata.md b/docs/zh/docs/tutorial/metadata.md index ba480637b..6518d096c 100644 --- a/docs/zh/docs/tutorial/metadata.md +++ b/docs/zh/docs/tutorial/metadata.md @@ -1,6 +1,6 @@ # 元数据和文档 URL { #metadata-and-docs-urls } -你可以在 FastAPI 应用程序中自定义多个元数据配置。 +你可以在 **FastAPI** 应用程序中自定义多个元数据配置。 ## API 元数据 { #metadata-for-api } @@ -11,7 +11,7 @@ | `title` | `str` | API 的标题。 | | `summary` | `str` | API 的简短摘要。 自 OpenAPI 3.1.0、FastAPI 0.99.0 起可用。 | | `description` | `str` | API 的简短描述。可以使用 Markdown。 | -| `version` | `string` | API 的版本。这是您自己的应用程序的版本,而不是 OpenAPI 的版本。例如 `2.5.0`。 | +| `version` | `str` | API 的版本。这是你自己的应用程序的版本,而不是 OpenAPI 的版本。例如 `2.5.0`。 | | `terms_of_service` | `str` | API 服务条款的 URL。如果提供,则必须是 URL。 | | `contact` | `dict` | 公开的 API 的联系信息。它可以包含多个字段。
contact 字段
参数类型描述
namestr联系人/组织的识别名称。
urlstr指向联系信息的 URL。必须采用 URL 格式。
emailstr联系人/组织的电子邮件地址。必须采用电子邮件地址的格式。
| | `license_info` | `dict` | 公开的 API 的许可证信息。它可以包含多个字段。
license_info 字段
参数类型描述
namestr必须(如果设置了 license_info)。用于 API 的许可证名称。
identifierstrAPI 的 [SPDX](https://spdx.org/licenses/) 许可证表达式。字段 identifier 与字段 url 互斥。自 OpenAPI 3.1.0、FastAPI 0.99.0 起可用。
urlstr用于 API 的许可证的 URL。必须采用 URL 格式。
| @@ -46,11 +46,11 @@ 每个字典可以包含: -- `name`(必填):一个 `str`,与在你的*路径操作*和 `APIRouter` 的 `tags` 参数中使用的标签名相同。 -- `description`:一个 `str`,该标签的简短描述。可以使用 Markdown,并会显示在文档 UI 中。 -- `externalDocs`:一个 `dict`,描述外部文档,包含: - - `description`:一个 `str`,该外部文档的简短描述。 - - `url`(必填):一个 `str`,该外部文档的 URL。 +* `name`(**必填**):一个 `str`,与在你的*路径操作*和 `APIRouter` 的 `tags` 参数中使用的标签名相同。 +* `description`:一个 `str`,该标签的简短描述。可以使用 Markdown,并会显示在文档 UI 中。 +* `externalDocs`:一个 `dict`,描述外部文档,包含: + * `description`:一个 `str`,该外部文档的简短描述。 + * `url`(**必填**):一个 `str`,该外部文档的 URL。 ### 创建标签元数据 { #create-metadata-for-tags } @@ -108,12 +108,12 @@ 你可以配置两个文档用户界面,包括: -- **Swagger UI**:服务于 `/docs`。 - - 可以使用参数 `docs_url` 设置它的 URL。 - - 可以通过设置 `docs_url=None` 禁用它。 -- **ReDoc**:服务于 `/redoc`。 - - 可以使用参数 `redoc_url` 设置它的 URL。 - - 可以通过设置 `redoc_url=None` 禁用它。 +* **Swagger UI**:服务于 `/docs`。 + * 可以使用参数 `docs_url` 设置它的 URL。 + * 可以通过设置 `docs_url=None` 禁用它。 +* **ReDoc**:服务于 `/redoc`。 + * 可以使用参数 `redoc_url` 设置它的 URL。 + * 可以通过设置 `redoc_url=None` 禁用它。 例如,设置 Swagger UI 服务于 `/documentation` 并禁用 ReDoc: diff --git a/docs/zh/docs/tutorial/path-operation-configuration.md b/docs/zh/docs/tutorial/path-operation-configuration.md index b813e38f8..f1aae0bc2 100644 --- a/docs/zh/docs/tutorial/path-operation-configuration.md +++ b/docs/zh/docs/tutorial/path-operation-configuration.md @@ -1,5 +1,6 @@ # 路径操作配置 { #path-operation-configuration } + *路径操作装饰器*支持多种配置参数。 /// warning | 警告 diff --git a/docs/zh/docs/tutorial/query-params-str-validations.md b/docs/zh/docs/tutorial/query-params-str-validations.md index 05cefc6e2..0164c27e6 100644 --- a/docs/zh/docs/tutorial/query-params-str-validations.md +++ b/docs/zh/docs/tutorial/query-params-str-validations.md @@ -1,5 +1,6 @@ # 查询参数和字符串校验 { #query-parameters-and-string-validations } + **FastAPI** 允许你为参数声明额外的信息和校验。 让我们以下面的应用为例: diff --git a/docs/zh/docs/tutorial/query-params.md b/docs/zh/docs/tutorial/query-params.md index c9cb2d26e..971dbb0ed 100644 --- a/docs/zh/docs/tutorial/query-params.md +++ b/docs/zh/docs/tutorial/query-params.md @@ -1,5 +1,6 @@ # 查询参数 { #query-parameters } + 声明的参数不是路径参数时,路径操作函数会把该参数自动解释为“查询”参数。 {* ../../docs_src/query_params/tutorial001_py310.py hl[9] *} diff --git a/docs/zh/docs/tutorial/request-files.md b/docs/zh/docs/tutorial/request-files.md index 102d42215..38c089ff3 100644 --- a/docs/zh/docs/tutorial/request-files.md +++ b/docs/zh/docs/tutorial/request-files.md @@ -147,7 +147,7 @@ HTML 表单(`
`)向服务器发送数据的方式通常会对数 ## 多文件上传 { #multiple-file-uploads } -FastAPI 支持同时上传多个文件。 +可以同时上传多个文件。 它们会被关联到同一个通过「表单数据」发送的「表单字段」。 diff --git a/docs/zh/docs/tutorial/request-forms.md b/docs/zh/docs/tutorial/request-forms.md index 3d305779f..0e7f19c70 100644 --- a/docs/zh/docs/tutorial/request-forms.md +++ b/docs/zh/docs/tutorial/request-forms.md @@ -2,7 +2,7 @@ 当你需要接收表单字段而不是 JSON 时,可以使用 `Form`。 -/// note +/// note | 注意 要使用表单,首先安装 [`python-multipart`](https://github.com/Kludex/python-multipart)。 @@ -32,13 +32,13 @@ $ pip install python-multipart 使用 `Form` 可以像使用 `Body`(以及 `Query`、`Path`、`Cookie`)一样声明相同的配置,包括校验、示例、别名(例如将 `username` 写成 `user-name`)等。 -/// note +/// note | 注意 `Form` 是直接继承自 `Body` 的类。 /// -/// tip +/// tip | 提示 要声明表单请求体,必须显式使用 `Form`,否则这些参数会被当作查询参数或请求体(JSON)参数。 @@ -60,9 +60,9 @@ HTML 表单(`
`)向服务器发送数据时通常会对数据使 /// -/// warning +/// warning | 警告 -你可以在一个路径操作中声明多个 `Form` 参数,但不能同时再声明要接收为 JSON 的 `Body` 字段,因为此时请求体会使用 `application/x-www-form-urlencoded` 而不是 `application/json` 进行编码。 +你可以在一个*路径操作*中声明多个 `Form` 参数,但不能同时再声明要接收为 JSON 的 `Body` 字段,因为此时请求体会使用 `application/x-www-form-urlencoded` 而不是 `application/json` 进行编码。 这不是 **FastAPI** 的限制,而是 HTTP 协议的一部分。 diff --git a/docs/zh/docs/tutorial/response-status-code.md b/docs/zh/docs/tutorial/response-status-code.md index 411ece71c..c06e67e6f 100644 --- a/docs/zh/docs/tutorial/response-status-code.md +++ b/docs/zh/docs/tutorial/response-status-code.md @@ -6,7 +6,7 @@ * `@app.post()` * `@app.put()` * `@app.delete()` -* 等... +* 等。 {* ../../docs_src/response_status_code/tutorial001_py310.py hl[6] *} @@ -27,13 +27,13 @@ 它可以: * 在响应中返回状态码 -* 在 OpenAPI 概图(及用户界面)中存档: +* 在 OpenAPI schema(以及用户界面)中将其记录为该状态码: /// note | 注意 -某些响应状态码表示响应没有响应体(参阅下一章)。 +某些响应状态码表示响应没有响应体(参阅下一节)。 FastAPI 可以进行识别,并生成表明无响应体的 OpenAPI 文档。 @@ -43,7 +43,7 @@ FastAPI 可以进行识别,并生成表明无响应体的 OpenAPI 文档。 /// note | 注意 -如果已经了解 HTTP 状态码,请跳到下一章。 +如果已经了解 HTTP 状态码,请跳到下一节。 /// diff --git a/docs/zh/docs/tutorial/schema-extra-example.md b/docs/zh/docs/tutorial/schema-extra-example.md index 2ea590c86..b18e69641 100644 --- a/docs/zh/docs/tutorial/schema-extra-example.md +++ b/docs/zh/docs/tutorial/schema-extra-example.md @@ -10,7 +10,7 @@ {* ../../docs_src/schema_extra_example/tutorial001_py310.py hl[13:24] *} -这些额外信息会原样添加到该模型输出的 JSON Schema 中,并会在 API 文档中使用。 +这些额外信息会原样添加到该模型输出的 **JSON Schema** 中,并会在 API 文档中使用。 你可以使用属性 `model_config`,它接收一个 `dict`,详见 [Pydantic 文档:配置](https://docs.pydantic.dev/latest/api/config/)。 @@ -26,7 +26,7 @@ /// note | 注意 -OpenAPI 3.1.0(自 FastAPI 0.99.0 起使用)增加了对 `examples` 的支持,它是 JSON Schema 标准的一部分。 +OpenAPI 3.1.0(自 FastAPI 0.99.0 起使用)增加了对 `examples` 的支持,它是 **JSON Schema** 标准的一部分。 在此之前,只支持使用单个示例的关键字 `example`。OpenAPI 3.1.0 仍然支持它,但它已被弃用,并不属于 JSON Schema 标准。因此,建议你把 `example` 迁移到 `examples`。🤓 @@ -52,7 +52,7 @@ OpenAPI 3.1.0(自 FastAPI 0.99.0 起使用)增加了对 `examples` 的支持 - `Form()` - `File()` -你也可以声明一组 `examples`,这些带有附加信息的示例将被添加到它们在 OpenAPI 中的 JSON Schema 里。 +你也可以声明一组 `examples`,这些带有附加信息的示例将被添加到它们在 **OpenAPI** 中的 **JSON Schema** 里。 ### 带有 `examples` 的 `Body` { #body-with-examples } @@ -72,21 +72,21 @@ OpenAPI 3.1.0(自 FastAPI 0.99.0 起使用)增加了对 `examples` 的支持 {* ../../docs_src/schema_extra_example/tutorial004_an_py310.py hl[23:38] *} -这样做时,这些示例会成为该请求体数据内部 JSON Schema 的一部分。 +这样做时,这些示例会成为该请求体数据内部 **JSON Schema** 的一部分。 -不过,在撰写本文时,用于展示文档 UI 的 Swagger UI 并不支持显示 JSON Schema 中数据的多个示例。但请继续阅读,下面有一种变通方法。 +不过,在撰写本文时,用于展示文档 UI 的 Swagger UI 并不支持显示 **JSON Schema** 中数据的多个示例。但请继续阅读,下面有一种变通方法。 ### OpenAPI 特定的 `examples` { #openapi-specific-examples } -在 JSON Schema 支持 `examples` 之前,OpenAPI 就已支持一个同名但不同的字段 `examples`。 +在 **JSON Schema** 支持 `examples` 之前,OpenAPI 就已支持一个同名但不同的字段 `examples`。 -这个面向 OpenAPI 的 `examples` 位于 OpenAPI 规范的另一处。它放在每个路径操作的详细信息中,而不是每个 JSON Schema 里。 +这个 **OpenAPI 特定的** `examples` 位于 OpenAPI 规范的另一处。它放在**每个*路径操作*的详细信息**中,而不是每个 JSON Schema 里。 -而 Swagger UI 早就支持这个特定的 `examples` 字段。因此,你可以用它在文档 UI 中展示不同的示例。 +而 Swagger UI 早就支持这个特定的 `examples` 字段。因此,你可以用它在文档 UI 中**展示**不同的**示例**。 -这个 OpenAPI 特定字段 `examples` 的结构是一个包含多个示例的 `dict`(而不是一个 `list`),每个示例都包含会被添加到 OpenAPI 的额外信息。 +这个 OpenAPI 特定字段 `examples` 的结构是一个包含**多个示例**的 `dict`(而不是一个 `list`),每个示例都包含会被添加到 **OpenAPI** 的额外信息。 -这不放在 OpenAPI 内部包含的各个 JSON Schema 里,而是直接放在路径操作上。 +这不放在 OpenAPI 内部包含的各个 JSON Schema 里,而是直接放在*路径操作*上。 ### 使用 `openapi_examples` 参数 { #using-the-openapi-examples-parameter } @@ -123,23 +123,23 @@ OpenAPI 3.1.0(自 FastAPI 0.99.0 起使用)增加了对 `examples` 的支持 /// tip | 提示 -如果你已经在使用 FastAPI 版本 0.99.0 或更高版本,你大概率可以跳过这些细节。 +如果你已经在使用 **FastAPI** 版本 **0.99.0 或更高版本**,你大概率可以**跳过**这些细节。 它们对更早版本(OpenAPI 3.1.0 尚不可用之前)更相关。 -你可以把这当作一堂简短的 OpenAPI 和 JSON Schema 历史课。🤓 +你可以把这当作一堂简短的 OpenAPI 和 JSON Schema **历史课**。🤓 /// /// warning | 警告 -以下是关于 JSON Schema 和 OpenAPI 标准的非常技术性的细节。 +以下是关于 **JSON Schema** 和 **OpenAPI** 标准的非常技术性的细节。 如果上面的思路对你已经足够可用,你可能不需要这些细节,可以直接跳过。 /// -在 OpenAPI 3.1.0 之前,OpenAPI 使用的是一个更旧且经过修改的 JSON Schema 版本。 +在 OpenAPI 3.1.0 之前,OpenAPI 使用的是一个更旧且经过修改的 **JSON Schema** 版本。 当时 JSON Schema 没有 `examples`,所以 OpenAPI 在它修改过的版本中添加了自己的 `example` 字段。 @@ -169,7 +169,7 @@ OpenAPI 还在规范的其他部分添加了 `example` 和 `examples` 字段: 现在,这个新的 `examples` 字段优先于旧的单个(且自定义的)`example` 字段,后者已被弃用。 -JSON Schema 中这个新的 `examples` 字段只是一个由示例组成的 `list`,而不是像上面提到的 OpenAPI 其他位置那样带有额外元数据的 `dict`。 +在 JSON Schema 中,这个新的 `examples` 字段**只是一个由示例组成的 `list`**,而不是像上面提到的 OpenAPI 其他位置那样带有额外元数据的 `dict`。 /// note | 注意 @@ -181,22 +181,22 @@ JSON Schema 中这个新的 `examples` 字段只是一个由示例组成的 `lis ### Pydantic 与 FastAPI 的 `examples` { #pydantic-and-fastapi-examples } -当你在 Pydantic 模型中添加 `examples`,通过 `schema_extra` 或 `Field(examples=["something"])`,这些示例会被添加到该 Pydantic 模型的 JSON Schema 中。 +当你在 Pydantic 模型中添加 `examples`,通过 `schema_extra` 或 `Field(examples=["something"])`,这些示例会被添加到该 Pydantic 模型的 **JSON Schema** 中。 -这个 Pydantic 模型的 JSON Schema 会被包含到你的 API 的 OpenAPI 中,然后在文档 UI 中使用。 +这个 Pydantic 模型的 **JSON Schema** 会被包含到你的 API 的 **OpenAPI** 中,然后在文档 UI 中使用。 -在 FastAPI 0.99.0 之前的版本(0.99.0 及以上使用更新的 OpenAPI 3.1.0),当你在其他工具(`Query()`、`Body()` 等)中使用 `example` 或 `examples` 时,这些示例不会被添加到描述该数据的 JSON Schema 中(甚至不会添加到 OpenAPI 自己的 JSON Schema 版本中),而是会直接添加到 OpenAPI 的路径操作声明中(在 OpenAPI 使用 JSON Schema 的部分之外)。 +在 FastAPI 0.99.0 之前的版本(0.99.0 及以上使用更新的 OpenAPI 3.1.0),当你在其他工具(`Query()`、`Body()` 等)中使用 `example` 或 `examples` 时,这些示例不会被添加到描述该数据的 JSON Schema 中(甚至不会添加到 OpenAPI 自己的 JSON Schema 版本中),而是会直接添加到 OpenAPI 的*路径操作*声明中(在 OpenAPI 使用 JSON Schema 的部分之外)。 但现在 FastAPI 0.99.0 及以上使用 OpenAPI 3.1.0(其使用 JSON Schema 2020-12)以及 Swagger UI 5.0.0 及以上后,一切更加一致,示例会包含在 JSON Schema 中。 ### Swagger UI 与 OpenAPI 特定的 `examples` { #swagger-ui-and-openapi-specific-examples } -此前,由于 Swagger UI 不支持多个 JSON Schema 示例(截至 2023-08-26),用户无法在文档中展示多个示例。 +由于截至 2023-08-26,Swagger UI 不支持多个 JSON Schema 示例,用户无法在文档中展示多个示例。 -为了解决这个问题,FastAPI `0.103.0` 通过新增参数 `openapi_examples`,为声明同样的旧式 OpenAPI 特定 `examples` 字段提供了支持。🤓 +为了解决这个问题,FastAPI `0.103.0` **增加了支持**,可以通过新参数 `openapi_examples` 声明同样的旧式 **OpenAPI 特定的** `examples` 字段。🤓 ### 总结 { #summary } -我曾经说我不太喜欢历史……结果现在在这儿上“技术史”课。😅 +我曾经说我不太喜欢历史... 结果现在在这儿上“技术史”课。😅 -简而言之,升级到 FastAPI 0.99.0 或更高版本,一切会更简单、一致、直观,你也不必了解这些历史细节。😎 +简而言之,**升级到 FastAPI 0.99.0 或更高版本**,一切会更**简单、一致、直观**,你也不必了解这些历史细节。😎 diff --git a/docs/zh/docs/tutorial/security/first-steps.md b/docs/zh/docs/tutorial/security/first-steps.md index e274d513a..ca3ef8352 100644 --- a/docs/zh/docs/tutorial/security/first-steps.md +++ b/docs/zh/docs/tutorial/security/first-steps.md @@ -1,5 +1,6 @@ # 安全 - 第一步 { #security-first-steps } + 假设你的**后端** API 位于某个域名下。 而**前端**在另一个域名,或同一域名的不同路径(或在移动应用中)。 diff --git a/docs/zh/docs/tutorial/security/get-current-user.md b/docs/zh/docs/tutorial/security/get-current-user.md index e8a1de9d5..dc8c70014 100644 --- a/docs/zh/docs/tutorial/security/get-current-user.md +++ b/docs/zh/docs/tutorial/security/get-current-user.md @@ -8,14 +8,13 @@ 接下来,我们学习如何返回当前用户。 - ## 创建用户模型 { #create-a-user-model } 首先,创建 Pydantic 用户模型。 与使用 Pydantic 声明请求体相同,并且可在任何位置使用: -{* ../../docs_src/security/tutorial002_an_py310.py hl[5,12:6] *} +{* ../../docs_src/security/tutorial002_an_py310.py hl[5,12:16] *} ## 创建 `get_current_user` 依赖项 { #create-a-get-current-user-dependency } @@ -55,7 +54,7 @@ /// tip | 提示 -依赖系统的这种设计方式可以支持不同的依赖项返回同一个 `User` 模型。 +依赖系统的这种设计方式可以支持不同的依赖项(不同的“可依赖项”)返回同一个 `User` 模型。 而不是局限于只能有一个返回该类型数据的依赖项。 @@ -77,7 +76,6 @@ 尽管使用应用所需的任何模型、类、数据库。**FastAPI** 通过依赖注入系统都能帮您搞定。 - ## 代码大小 { #code-size } 这个示例看起来有些冗长。毕竟这个文件同时包含了安全、数据模型的工具函数,以及路径操作等代码。 diff --git a/docs/zh/docs/tutorial/security/oauth2-jwt.md b/docs/zh/docs/tutorial/security/oauth2-jwt.md index e0cbdf685..418b3b97d 100644 --- a/docs/zh/docs/tutorial/security/oauth2-jwt.md +++ b/docs/zh/docs/tutorial/security/oauth2-jwt.md @@ -120,7 +120,7 @@ pwdlib 也支持 bcrypt 哈希算法,但不包含遗留算法——如果需 当使用一个在数据库中不存在的用户名调用 `authenticate_user` 时,我们仍然会针对一个虚拟哈希运行 `verify_password`。 -这可以确保无论用户名是否有效,端点的响应时间大致相同,从而防止可用于枚举已存在用户名的“时间攻击”(timing attacks)。 +这可以确保无论用户名是否有效,端点的响应时间大致相同,从而防止可用于枚举已存在用户名的**时序攻击**。 /// note | 注意 @@ -168,7 +168,7 @@ $ openssl rand -hex 32 {* ../../docs_src/security/tutorial004_an_py310.py hl[93:110] *} -## 更新 `/token` 路径操作 { #update-the-token-path-operation } +## 更新 `/token` *路径操作* { #update-the-token-path-operation } 用令牌的过期时间创建一个 `timedelta`。 diff --git a/docs/zh/docs/tutorial/security/simple-oauth2.md b/docs/zh/docs/tutorial/security/simple-oauth2.md index 6ebf77e36..92cf02dd2 100644 --- a/docs/zh/docs/tutorial/security/simple-oauth2.md +++ b/docs/zh/docs/tutorial/security/simple-oauth2.md @@ -6,7 +6,7 @@ 首先,使用 **FastAPI** 安全工具获取 `username` 和 `password`。 -OAuth2 规范要求使用“密码流”时,客户端或用户必须以表单数据形式发送 `username` 和 `password` 字段。 +OAuth2 规范要求使用“密码流”(也就是我们正在使用的流程)时,客户端或用户必须以表单数据形式发送 `username` 和 `password` 字段。 并且,这两个字段必须命名为 `username` 和 `password`,不能使用 `user-name` 或 `email` 等其它名称。 @@ -80,7 +80,7 @@ OAuth2 中,**作用域**只是声明指定权限的字符串。 但 `OAuth2PasswordRequestForm` 只是可以自行编写的类依赖项,也可以直接声明 `Form` 参数。 -但由于这种用例很常见,FastAPI 为了简便,就直接提供了对它的支持。 +但由于这种用例很常见,**FastAPI** 为了简便,就直接提供了对它的支持。 /// @@ -146,7 +146,7 @@ UserInDB( /// note | 注意 -`user_dict` 的说明,详见[**更多模型**一章](../extra-models.md#about-user-in-dict)。 +关于 `**user_dict` 的更完整说明,详见[**更多模型**文档](../extra-models.md#about-user-in-model-dump)。 /// @@ -208,7 +208,7 @@ UserInDB( 之所以在此提供这个附加响应头,是为了符合规范的要求。 -说不定什么时候,就有工具用得上它,而且,开发者或用户也可能用得上。 +此外,现在或将来,可能会有工具期望并使用它,而且现在或将来这也可能对你或你的用户有用。 这就是遵循标准的好处... diff --git a/docs/zh/docs/tutorial/sql-databases.md b/docs/zh/docs/tutorial/sql-databases.md index 9004983b1..1d6a3cd34 100644 --- a/docs/zh/docs/tutorial/sql-databases.md +++ b/docs/zh/docs/tutorial/sql-databases.md @@ -8,7 +8,7 @@ /// tip | 提示 -你可以使用任意其他你想要的 SQL 或 NoSQL 数据库库(在某些情况下称为 "ORMs"),FastAPI 不会强迫你使用任何东西。😎 +你可以使用任意其他你想要的 SQL 或 NoSQL 数据库类库(在某些情况下称为 "ORMs"),FastAPI 不会强迫你使用任何东西。😎 /// @@ -57,7 +57,7 @@ $ pip install sqlmodel {* ../../docs_src/sql_databases/tutorial001_an_py310.py ln[1:11] hl[7:11] *} -`Hero` 类与 Pydantic 模型非常相似(实际上,从底层来看,它确实就是一个 Pydantic 模型)。 +`Hero` 类与 Pydantic 模型非常相似(实际上,从底层来看,它*确实就是一个 Pydantic 模型*)。 有一些区别: @@ -65,7 +65,7 @@ $ pip install sqlmodel * `Field(primary_key=True)` 会告诉 SQLModel `id` 是 SQL 数据库中的**主键**(你可以在 SQLModel 文档中了解更多关于 SQL 主键的信息)。 - **注意:** 我们为主键字段使用 `int | None`,这样在 Python 代码中我们可以在没有 `id`(`id=None`)的情况下创建对象,并假定数据库在保存时会生成它。SQLModel 会理解数据库会提供 `id`,并在数据库模式中将该列定义为非空的 `INTEGER`。详见 [SQLModel 关于主键的文档](https://sqlmodel.tiangolo.com/tutorial/create-db-and-table/#primary-key-id)。 + **注意:** 我们为主键字段使用 `int | None`,这样在 Python 代码中我们可以*在没有 `id` 的情况下创建对象*(`id=None`),并假定数据库会*在保存时生成它*。SQLModel 会理解数据库会提供 `id`,并在数据库模式中*将该列定义为非空的 `INTEGER`*。详见 [SQLModel 关于主键的文档](https://sqlmodel.tiangolo.com/tutorial/create-db-and-table/#primary-key-id)。 * `Field(index=True)` 会告诉 SQLModel 应该为此列创建一个 **SQL 索引**,这样在读取按此列过滤的数据时,程序能在数据库中进行更快的查找。 @@ -292,7 +292,7 @@ $ fastapi dev /// tip | 提示 -现在我们使用 `response_model=HeroPublic` 来代替**返回类型注解** `-> HeroPublic`,因为我们返回的值实际上并不是 `HeroPublic`。 +现在我们使用 `response_model=HeroPublic` 来代替**返回类型注解** `-> HeroPublic`,因为我们返回的值实际上*并不是* `HeroPublic`。 如果我们声明了 `-> HeroPublic`,你的编辑器和代码检查工具会(理所应当地)抱怨你返回了一个 `Hero` 而不是一个 `HeroPublic`。 diff --git a/docs/zh/docs/tutorial/static-files.md b/docs/zh/docs/tutorial/static-files.md index 65262bdb4..b700f46d6 100644 --- a/docs/zh/docs/tutorial/static-files.md +++ b/docs/zh/docs/tutorial/static-files.md @@ -2,6 +2,14 @@ 你可以使用 `StaticFiles` 从目录中自动提供静态文件。 +/// tip | 提示 + +如果你需要托管前端,请改用 `app.frontend()`,可在[前端](frontend.md)中阅读相关内容。 + +`app.frontend()` 底层使用 `StaticFiles`,并为前端提供了几个额外优势,例如处理客户端路由。 + +/// + ## 使用 `StaticFiles` { #use-staticfiles } * 导入 `StaticFiles`。 diff --git a/docs/zh/docs/tutorial/testing.md b/docs/zh/docs/tutorial/testing.md index 50e1d8f2d..79e5044c9 100644 --- a/docs/zh/docs/tutorial/testing.md +++ b/docs/zh/docs/tutorial/testing.md @@ -52,7 +52,7 @@ $ pip install httpx /// tip | 提示 -除了发送请求之外,如果你还想测试时在FastAPI应用中调用 `async` 函数(例如异步数据库函数), 可以在高级教程中看下 [Async Tests](../advanced/async-tests.md) 。 +除了发送请求之外,如果你还想测试时在FastAPI应用中调用 `async` 函数(例如异步数据库函数), 可以在高级教程中看下[异步测试](../advanced/async-tests.md)。 /// @@ -60,7 +60,7 @@ $ pip install httpx 在实际应用中,你可能会把你的测试放在另一个文件里。 -您的**FastAPI**应用程序也可能由一些文件/模块组成等等。 +你的**FastAPI**应用程序也可能由一些文件/模块组成等等。 ### **FastAPI** app 文件 { #fastapi-app-file } @@ -80,7 +80,7 @@ $ pip install httpx ### 测试文件 { #testing-file } -然后你会有一个包含测试的文件 `test_main.py` 。app可以像Python包那样存在(一样是目录,但有个 `__init__.py` 文件): +然后你会有一个包含测试的文件 `test_main.py` 。它可以位于同一个 Python 包中(一样是目录,但有个 `__init__.py` 文件): ``` hl_lines="5" . @@ -94,6 +94,7 @@ $ pip install httpx {* ../../docs_src/app_testing/app_a_py310/test_main.py hl[3] *} + ...然后测试代码和之前一样的。 ## 测试:扩展示例 { #testing-extended-example } @@ -114,20 +115,21 @@ $ pip install httpx 假设现在包含**FastAPI** app的文件 `main.py` 有些其他**路径操作**。 -有个 `GET` 操作会返回错误。 +有个 `GET` 操作可能返回一个错误。 -有个 `POST` 操作会返回一些错误。 +有个 `POST` 操作可能返回多个错误。 -所有*路径操作* 都需要一个`X-Token` 头。 +两个*路径操作* 都需要一个`X-Token` 头。 {* ../../docs_src/app_testing/app_b_an_py310/main.py *} ### 扩展后的测试文件 { #extended-testing-file } -然后您可以使用扩展后的测试更新`test_main.py`: +然后你可以使用扩展后的测试更新`test_main.py`: {* ../../docs_src/app_testing/app_b_an_py310/test_main.py *} + 每当你需要客户端在请求中传递信息,但你不知道如何传递时,你可以通过搜索(谷歌)如何用 `httpx` 做,或者是用 `requests` 做,毕竟HTTPX的设计是基于Requests的设计的。 接着只需在测试中同样操作。 @@ -146,7 +148,7 @@ $ pip install httpx 注意 `TestClient` 接收可以被转化为JSON的数据,而不是Pydantic模型。 -如果你在测试中有一个Pydantic模型,并且你想在测试时发送它的数据给应用,你可以使用在[JSON Compatible Encoder](encoder.md)介绍的`jsonable_encoder` 。 +如果你在测试中有一个Pydantic模型,并且你想在测试时发送它的数据给应用,你可以使用在[JSON 兼容编码器](encoder.md)介绍的`jsonable_encoder` 。 /// @@ -166,7 +168,7 @@ $ pip install pytest
-他会自动检测文件和测试,执行测试,然后向你报告结果。 +它会自动检测文件和测试,执行测试,然后向你报告结果。 执行测试: diff --git a/docs/zh/docs/virtual-environments.md b/docs/zh/docs/virtual-environments.md index d10251dbe..a31240d9f 100644 --- a/docs/zh/docs/virtual-environments.md +++ b/docs/zh/docs/virtual-environments.md @@ -861,4 +861,4 @@ I solemnly swear 🐺 如果你读过并理解了所有这些,现在**你对虚拟环境的了解比很多开发者都要多**。🤓 -在未来当你调看看起来复杂的东西时,了解这些细节很可能会有用,你会知道**它是如何在底层工作的**。😎 +在未来当你调试看起来复杂的东西时,了解这些细节很可能会有用,你会知道**它是如何在底层工作的**。😎 From 59d335d200a9d39256b521038f7ae58535eb75b0 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Wed, 1 Jul 2026 13:36:20 +0000 Subject: [PATCH 367/462] =?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 7aafc7f50..d00065b7d 100644 --- a/docs/en/docs/release-notes.md +++ b/docs/en/docs/release-notes.md @@ -9,6 +9,7 @@ hide: ### Translations +* 🌐 Update translations for zh (update-outdated). PR [#15898](https://github.com/fastapi/fastapi/pull/15898) by [@tiangolo](https://github.com/tiangolo). * 🌐 Update translations for uk (update-outdated). PR [#15900](https://github.com/fastapi/fastapi/pull/15900) by [@tiangolo](https://github.com/tiangolo). * 🌐 Update translations for ko (update-outdated). PR [#15890](https://github.com/fastapi/fastapi/pull/15890) by [@tiangolo](https://github.com/tiangolo). * 🌐 Update translations for ru (update-outdated). PR [#15894](https://github.com/fastapi/fastapi/pull/15894) by [@tiangolo](https://github.com/tiangolo). From 48dd913e5648cda943bc28cccfbbc4c93f2a5859 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebasti=C3=A1n=20Ram=C3=ADrez?= Date: Wed, 1 Jul 2026 15:45:25 +0200 Subject: [PATCH 368/462] =?UTF-8?q?=F0=9F=8C=90=20Update=20translations=20?= =?UTF-8?q?for=20pt=20(update-outdated)=20(#15893)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: github-actions[bot] Co-authored-by: Yurii Motov --- docs/pt/docs/_llm-test.md | 14 +- .../docs/advanced/additional-status-codes.md | 6 +- .../pt/docs/advanced/advanced-dependencies.md | 1 + docs/pt/docs/advanced/dataclasses.md | 2 +- docs/pt/docs/advanced/events.md | 1 + docs/pt/docs/advanced/generate-clients.md | 24 +--- docs/pt/docs/advanced/json-base64-bytes.md | 2 +- docs/pt/docs/advanced/openapi-callbacks.md | 28 ++-- .../advanced/response-change-status-code.md | 4 +- docs/pt/docs/advanced/response-cookies.md | 2 +- docs/pt/docs/advanced/response-headers.md | 1 + .../docs/advanced/security/oauth2-scopes.md | 22 +-- docs/pt/docs/advanced/settings.md | 1 + docs/pt/docs/advanced/stream-data.md | 20 +-- docs/pt/docs/advanced/wsgi.md | 1 + docs/pt/docs/alternatives.md | 8 +- docs/pt/docs/async.md | 54 +++---- docs/pt/docs/deployment/cloud.md | 2 +- docs/pt/docs/deployment/concepts.md | 44 +++--- docs/pt/docs/deployment/docker.md | 36 ++--- docs/pt/docs/deployment/https.md | 136 +++++++++--------- docs/pt/docs/deployment/manually.md | 4 +- docs/pt/docs/editor-support.md | 2 +- docs/pt/docs/environment-variables.md | 2 +- docs/pt/docs/features.md | 40 +++--- docs/pt/docs/help-fastapi.md | 2 +- docs/pt/docs/how-to/configure-swagger-ui.md | 1 + .../docs/how-to/custom-request-and-route.md | 6 +- docs/pt/docs/how-to/graphql.md | 1 + ...migrate-from-pydantic-v1-to-pydantic-v2.md | 18 +++ .../docs/how-to/separate-openapi-schemas.md | 1 + docs/pt/docs/index.md | 6 +- docs/pt/docs/project-generation.md | 22 +-- docs/pt/docs/python-types.md | 70 ++++----- docs/pt/docs/tutorial/bigger-applications.md | 34 +++-- docs/pt/docs/tutorial/body-nested-models.md | 20 +-- docs/pt/docs/tutorial/body.md | 1 + docs/pt/docs/tutorial/debugging.md | 2 +- .../dependencies/dependencies-with-yield.md | 7 +- docs/pt/docs/tutorial/extra-data-types.md | 8 +- docs/pt/docs/tutorial/extra-models.md | 2 +- docs/pt/docs/tutorial/first-steps.md | 32 ++--- docs/pt/docs/tutorial/handling-errors.md | 110 +++++++------- docs/pt/docs/tutorial/index.md | 12 +- docs/pt/docs/tutorial/metadata.md | 4 +- .../tutorial/path-operation-configuration.md | 2 +- .../tutorial/query-params-str-validations.md | 48 +++---- docs/pt/docs/tutorial/query-params.md | 9 +- docs/pt/docs/tutorial/request-files.md | 22 +-- docs/pt/docs/tutorial/request-forms.md | 2 +- docs/pt/docs/tutorial/response-status-code.md | 6 +- docs/pt/docs/tutorial/schema-extra-example.md | 1 + docs/pt/docs/tutorial/security/first-steps.md | 10 +- .../tutorial/security/get-current-user.md | 2 +- docs/pt/docs/tutorial/security/oauth2-jwt.md | 8 +- .../docs/tutorial/security/simple-oauth2.md | 12 +- docs/pt/docs/tutorial/sql-databases.md | 47 +++--- docs/pt/docs/tutorial/static-files.md | 8 ++ docs/pt/docs/tutorial/testing.md | 10 +- docs/pt/docs/virtual-environments.md | 20 +-- 60 files changed, 530 insertions(+), 493 deletions(-) diff --git a/docs/pt/docs/_llm-test.md b/docs/pt/docs/_llm-test.md index 714c121b4..2e20e5b58 100644 --- a/docs/pt/docs/_llm-test.md +++ b/docs/pt/docs/_llm-test.md @@ -11,7 +11,7 @@ Use da seguinte forma: * Verifique se está tudo certo na tradução. * Se necessário, melhore seu prompt específico do idioma, o prompt geral ou o documento em inglês. * Em seguida, corrija manualmente os problemas restantes na tradução, para que fique uma boa tradução. -* Retraduzir, tendo a boa tradução no lugar. O resultado ideal seria que o LLM não fizesse mais mudanças na tradução. Isso significa que o prompt geral e o seu prompt específico do idioma estão tão bons quanto possível (às vezes fará algumas mudanças aparentemente aleatórias, a razão é que [LLMs não são algoritmos determinísticos](https://doublespeak.chat/#/handbook#deterministic-output)). +* Retraduza, tendo a boa tradução no lugar. O resultado ideal seria que o LLM não fizesse mais mudanças na tradução. Isso significa que o prompt geral e o seu prompt específico do idioma estão tão bons quanto possível (às vezes fará algumas mudanças aparentemente aleatórias, a razão é que [LLMs não são algoritmos determinísticos](https://doublespeak.chat/#/handbook#deterministic-output)). Os testes: @@ -189,15 +189,15 @@ Aqui estão algumas coisas envolvidas em elementos HTML "abbr" (algumas são inv ### O abbr fornece uma frase completa { #the-abbr-gives-a-full-phrase } -* GTD -* lt -* XWT -* PSGI +* GTD +* lt +* XWT +* PSGI ### O abbr fornece uma frase completa e uma explicação { #the-abbr-gives-a-full-phrase-and-an-explanation } -* MDN -* I/O. +* MDN +* I/O. //// diff --git a/docs/pt/docs/advanced/additional-status-codes.md b/docs/pt/docs/advanced/additional-status-codes.md index af1cefaf2..b702b8b41 100644 --- a/docs/pt/docs/advanced/additional-status-codes.md +++ b/docs/pt/docs/advanced/additional-status-codes.md @@ -30,12 +30,12 @@ Garanta que ele tenha toda informação que você deseja, e que os valores sejam Você também pode utilizar `from starlette.responses import JSONResponse`. -O **FastAPI** disponibiliza o `starlette.responses` como `fastapi.responses` apenas por conveniência para você, o programador. Porém a maioria dos retornos disponíveis vem diretamente do Starlette. O mesmo com `status`. +O **FastAPI** disponibiliza o `starlette.responses` como `fastapi.responses` apenas por conveniência para você, o programador. Porém a maioria das respostas disponíveis vem diretamente do Starlette. O mesmo com `status`. /// ## OpenAPI e documentação da API { #openapi-and-api-docs } -Se você retorna códigos de status adicionais e retornos diretamente, eles não serão incluídos no esquema do OpenAPI (a documentação da API), porque o FastAPI não tem como saber de antemão o que será retornado. +Se você retorna códigos de status adicionais e respostas diretamente, eles não serão incluídos no esquema do OpenAPI (a documentação da API), porque o FastAPI não tem como saber de antemão o que será retornado. -Mas você pode documentar isso no seu código, utilizando: [Retornos Adicionais](additional-responses.md). +Mas você pode documentar isso no seu código, utilizando: [Respostas Adicionais](additional-responses.md). diff --git a/docs/pt/docs/advanced/advanced-dependencies.md b/docs/pt/docs/advanced/advanced-dependencies.md index 15a78afec..21c1490ff 100644 --- a/docs/pt/docs/advanced/advanced-dependencies.md +++ b/docs/pt/docs/advanced/advanced-dependencies.md @@ -1,5 +1,6 @@ # Dependências avançadas { #advanced-dependencies } + ## Dependências parametrizadas { #parameterized-dependencies } Todas as dependências que vimos até agora são funções ou classes fixas. diff --git a/docs/pt/docs/advanced/dataclasses.md b/docs/pt/docs/advanced/dataclasses.md index 7956196c7..f1cc5a070 100644 --- a/docs/pt/docs/advanced/dataclasses.md +++ b/docs/pt/docs/advanced/dataclasses.md @@ -8,7 +8,7 @@ Mas o FastAPI também suporta o uso de [`dataclasses`](https://docs.python.org/3 Isso ainda é suportado graças ao **Pydantic**, pois ele tem [suporte interno para `dataclasses`](https://docs.pydantic.dev/latest/concepts/dataclasses/#use-of-stdlib-dataclasses-with-basemodel). -Então, mesmo com o código acima que não usa Pydantic explicitamente, o FastAPI está usando Pydantic para converter essas dataclasses padrão para a versão do Pydantic. +Então, mesmo com o código acima que não usa Pydantic explicitamente, o FastAPI está usando Pydantic para converter essas dataclasses padrão para a própria versão de dataclasses do Pydantic. E claro, ele suporta o mesmo: diff --git a/docs/pt/docs/advanced/events.md b/docs/pt/docs/advanced/events.md index a6262d8da..eee4dc880 100644 --- a/docs/pt/docs/advanced/events.md +++ b/docs/pt/docs/advanced/events.md @@ -1,5 +1,6 @@ # Eventos de lifespan { #lifespan-events } + Você pode definir a lógica (código) que deve ser executada antes da aplicação **inicializar**. Isso significa que esse código será executado **uma vez**, **antes** de a aplicação **começar a receber requisições**. Da mesma forma, você pode definir a lógica (código) que deve ser executada quando a aplicação estiver **encerrando**. Nesse caso, esse código será executado **uma vez**, **depois** de possivelmente ter tratado **várias requisições**. diff --git a/docs/pt/docs/advanced/generate-clients.md b/docs/pt/docs/advanced/generate-clients.md index 89f2a89f4..975fb902d 100644 --- a/docs/pt/docs/advanced/generate-clients.md +++ b/docs/pt/docs/advanced/generate-clients.md @@ -20,27 +20,13 @@ O FastAPI gera automaticamente especificações **OpenAPI 3.1**, então qualquer /// -## Geradores de SDK dos patrocinadores do FastAPI { #sdk-generators-from-fastapi-sponsors } - -Esta seção destaca soluções **financiadas por investimento** e **com suporte de empresas** que patrocinam o FastAPI. Esses produtos fornecem **funcionalidades adicionais** e **integrações** além de SDKs gerados com alta qualidade. - -Ao ✨ [**patrocinar o FastAPI**](../help-fastapi.md#sponsor-the-author) ✨, essas empresas ajudam a garantir que o framework e seu **ecossistema** continuem saudáveis e **sustentáveis**. - -O patrocínio também demonstra um forte compromisso com a **comunidade** FastAPI (você), mostrando que elas se importam não apenas em oferecer um **ótimo serviço**, mas também em apoiar um **framework robusto e próspero**, o FastAPI. 🙇 - -Por exemplo, você pode querer experimentar: - -* [Stainless](https://www.stainless.com/?utm_source=fastapi&utm_medium=referral) - -Algumas dessas soluções também podem ser open source ou oferecer planos gratuitos, para que você possa testá-las sem compromisso financeiro. Outros geradores comerciais de SDK estão disponíveis e podem ser encontrados online. 🤓 - ## Crie um SDK em TypeScript { #create-a-typescript-sdk } Vamos começar com uma aplicação FastAPI simples: {* ../../docs_src/generate_clients/tutorial001_py310.py hl[7:9,12:13,16:17,21] *} -Observe que as *operações de rota* definem os modelos que usam para o corpo da requisição e o corpo da resposta, usando os modelos `Item` e `ResponseMessage`. +Observe que as *operações de rota* definem os modelos que usam para o payload da requisição e o payload da resposta, usando os modelos `Item` e `ResponseMessage`. ### Documentação da API { #api-docs } @@ -72,7 +58,7 @@ Agora você pode importar e usar o código do cliente. Poderia ser assim, observ -Você também obterá preenchimento automático para o corpo a ser enviado: +Você também obterá preenchimento automático para o payload a enviar: @@ -121,7 +107,7 @@ ItemsService.createItemItemsPost({name: "Plumbus", price: 5}) ...isso ocorre porque o gerador de clientes usa o **ID de operação interno do OpenAPI** para cada *operação de rota*. -O OpenAPI exige que cada ID de operação seja único em todas as *operações de rota*, então o FastAPI usa o **nome da função**, o **path** e o **método HTTP** para gerar esse ID de operação, porque dessa forma ele pode garantir que os IDs de operação sejam únicos. +O OpenAPI exige que cada ID de operação seja único em todas as *operações de rota*, então o FastAPI usa o **nome da função**, o **path** e o **método/operação HTTP** para gerar esse ID de operação, porque dessa forma ele pode garantir que os IDs de operação sejam únicos. Mas eu vou te mostrar como melhorar isso a seguir. 🤓 @@ -194,8 +180,8 @@ Depois de gerar o novo cliente, você terá agora **nomes de métodos “limpos Ao usar os clientes gerados automaticamente, você terá **preenchimento automático** para: * Métodos. -* Corpos de requisições, parâmetros de query, etc. -* Corpos de respostas. +* Payloads de requisições no body, parâmetros de query, etc. +* Payloads de respostas. Você também terá **erros em linha** para tudo. diff --git a/docs/pt/docs/advanced/json-base64-bytes.md b/docs/pt/docs/advanced/json-base64-bytes.md index cc956da4f..8034430ab 100644 --- a/docs/pt/docs/advanced/json-base64-bytes.md +++ b/docs/pt/docs/advanced/json-base64-bytes.md @@ -4,7 +4,7 @@ Se sua aplicação precisa receber e enviar dados JSON, mas você precisa inclui ## Base64 vs Arquivos { #base64-vs-files } -Primeiro, considere se você pode usar [Arquivos na request](../tutorial/request-files.md) para fazer upload de dados binários e [Response personalizada - FileResponse](./custom-response.md#fileresponse--fileresponse-) para enviar dados binários, em vez de codificá-los em JSON. +Primeiro, considere se você pode usar [Arquivos na request](../tutorial/request-files.md) para fazer upload de dados binários e [Response personalizada - FileResponse](./custom-response.md#fileresponse) para enviar dados binários, em vez de codificá-los em JSON. JSON só pode conter strings codificadas em UTF-8, portanto não pode conter bytes puros. diff --git a/docs/pt/docs/advanced/openapi-callbacks.md b/docs/pt/docs/advanced/openapi-callbacks.md index 1403425a9..08877e4f7 100644 --- a/docs/pt/docs/advanced/openapi-callbacks.md +++ b/docs/pt/docs/advanced/openapi-callbacks.md @@ -1,16 +1,16 @@ # Callbacks na OpenAPI { #openapi-callbacks } -Você poderia criar uma API com uma *operação de rota* que poderia acionar um request a uma *API externa* criada por outra pessoa (provavelmente o mesmo desenvolvedor que estaria *usando* sua API). +Você poderia criar uma API com uma *operação de rota* que poderia acionar um request para uma *API externa* criada por outra pessoa (provavelmente o mesmo desenvolvedor que estaria *usando* sua API). O processo que acontece quando sua aplicação de API chama a *API externa* é chamado de "callback". Porque o software que o desenvolvedor externo escreveu envia um request para sua API e então sua API *chama de volta*, enviando um request para uma *API externa* (que provavelmente foi criada pelo mesmo desenvolvedor). Nesse caso, você poderia querer documentar como essa API externa *deveria* ser. Que *operação de rota* ela deveria ter, que corpo ela deveria esperar, que resposta ela deveria retornar, etc. -## Um aplicativo com callbacks { #an-app-with-callbacks } +## Uma aplicação com callbacks { #an-app-with-callbacks } Vamos ver tudo isso com um exemplo. -Imagine que você desenvolve um aplicativo que permite criar faturas. +Imagine que você desenvolve uma aplicação que permite criar faturas. Essas faturas terão um `id`, `title` (opcional), `customer` e `total`. @@ -23,11 +23,11 @@ Então sua API irá (vamos imaginar): * Enviar a notificação de volta para o usuário da API (o desenvolvedor externo). * Isso será feito enviando um request POST (de *sua API*) para alguma *API externa* fornecida por esse desenvolvedor externo (este é o "callback"). -## O aplicativo **FastAPI** normal { #the-normal-fastapi-app } +## A aplicação **FastAPI** normal { #the-normal-fastapi-app } -Vamos primeiro ver como o aplicativo da API normal se pareceria antes de adicionar o callback. +Vamos primeiro ver como a aplicação da API normal se pareceria antes de adicionar o callback. -Ele terá uma *operação de rota* que receberá um corpo `Invoice`, e um parâmetro de consulta `callback_url` que conterá a URL para o callback. +Ela terá uma *operação de rota* que receberá um corpo `Invoice`, e um parâmetro de consulta `callback_url` que conterá a URL para o callback. Essa parte é bastante normal, a maior parte do código provavelmente já é familiar para você: @@ -45,7 +45,7 @@ A única novidade é o `callbacks=invoices_callback_router.routes` como argument O código real do callback dependerá muito da sua própria aplicação de API. -E provavelmente variará muito de um aplicativo para o outro. +E provavelmente variará muito de uma aplicação para outra. Poderia ser apenas uma ou duas linhas de código, como: @@ -72,7 +72,7 @@ Ao implementar o callback por conta própria, você pode usar algo como [HTTPX]( ## Escreva o código de documentação do callback { #write-the-callback-documentation-code } -Esse código não será executado em seu aplicativo, nós só precisamos dele para *documentar* como essa *API externa* deveria ser. +Esse código não será executado em sua aplicação, nós só precisamos dele para *documentar* como essa *API externa* deveria ser. Mas, você já sabe como criar facilmente documentação automática para uma API com o **FastAPI**. @@ -105,7 +105,7 @@ Ela deve parecer exatamente como uma *operação de rota* normal do FastAPI: Há 2 diferenças principais de uma *operação de rota* normal: -* Ela não necessita ter nenhum código real, porque seu aplicativo nunca chamará esse código. Ele é usado apenas para documentar a *API externa*. Então, a função poderia ter apenas `pass`. +* Ela não necessita ter nenhum código real, porque sua aplicação nunca chamará esse código. Ele é usado apenas para documentar a *API externa*. Então, a função poderia ter apenas `pass`. * O *path* pode conter uma [expressão OpenAPI 3](https://github.com/OAI/OpenAPI-Specification/blob/master/versions/3.1.0.md#key-expression) (veja mais abaixo) em que pode usar variáveis com parâmetros e partes do request original enviado para *sua API*. ### A expressão do path do callback { #the-callback-path-expression } @@ -163,23 +163,23 @@ Perceba como a URL de callback usada contém a URL recebida como um parâmetro d /// -### Adicione o roteador de callback { #add-the-callback-router } +### Adicione o router de callback { #add-the-callback-router } -Nesse ponto você tem a(s) *operação(ões) de rota de callback* necessária(s) (a(s) que o *desenvolvedor externo* deveria implementar na *API externa*) no roteador de callback que você criou acima. +Nesse ponto você tem a(s) *operação(ões) de rota de callback* necessária(s) (a(s) que o *desenvolvedor externo* deveria implementar na *API externa*) no router de callback que você criou acima. -Agora use o parâmetro `callbacks` no decorador da *operação de rota da sua API* para passar o atributo `.routes` do roteador de callback: +Agora use o parâmetro `callbacks` no decorador da *operação de rota da sua API* para passar o atributo `.routes` desse router de callback: {* ../../docs_src/openapi_callbacks/tutorial001_py310.py hl[33] *} /// tip | Dica -Perceba que você não está passando o roteador em si (`invoices_callback_router`) para `callbacks=`, mas o atributo `.routes`, como em `invoices_callback_router.routes`. O FastAPI usará essas rotas para gerar a documentação OpenAPI do callback. +Perceba que você não está passando o router em si (`invoices_callback_router`) para `callbacks=`, mas seu `.routes`, como em `invoices_callback_router.routes`. FastAPI usará essas rotas para gerar a documentação OpenAPI do callback. /// ### Verifique a documentação { #check-the-docs } -Agora você pode iniciar seu aplicativo e ir para [http://127.0.0.1:8000/docs](http://127.0.0.1:8000/docs). +Agora você pode iniciar sua aplicação e ir para [http://127.0.0.1:8000/docs](http://127.0.0.1:8000/docs). Você verá sua documentação incluindo uma seção "Callbacks" para sua *operação de rota* que mostra como a *API externa* deveria ser: diff --git a/docs/pt/docs/advanced/response-change-status-code.md b/docs/pt/docs/advanced/response-change-status-code.md index 44ca6062a..1e902338b 100644 --- a/docs/pt/docs/advanced/response-change-status-code.md +++ b/docs/pt/docs/advanced/response-change-status-code.md @@ -18,7 +18,7 @@ Para estes casos, você pode utilizar um parâmetro `Response`. Você pode declarar um parâmetro do tipo `Response` em sua *função de operação de rota* (assim como você pode fazer para cookies e headers). -E então você pode definir o `status_code` neste objeto de retorno *temporal*. +E então você pode definir o `status_code` neste objeto de retorno *temporário*. {* ../../docs_src/response_change_status_code/tutorial001_py310.py hl[1,9,12] *} @@ -26,6 +26,6 @@ E então você pode retornar qualquer objeto que você precise, como você faria E se você declarar um `response_model`, ele ainda será utilizado para filtrar e converter o objeto que você retornou. -O **FastAPI** utilizará este retorno *temporal* para extrair o código de status (e também cookies e headers), e irá colocá-los no retorno final que contém o valor que você retornou, filtrado por qualquer `response_model`. +O **FastAPI** utilizará este retorno *temporário* para extrair o código de status (e também cookies e headers), e irá colocá-los no retorno final que contém o valor que você retornou, filtrado por qualquer `response_model`. Você também pode declarar o parâmetro `Response` nas dependências, e definir o código de status nelas. Mas lembre-se que o último que for definido é o que prevalecerá. diff --git a/docs/pt/docs/advanced/response-cookies.md b/docs/pt/docs/advanced/response-cookies.md index 691bd1b9c..e77502750 100644 --- a/docs/pt/docs/advanced/response-cookies.md +++ b/docs/pt/docs/advanced/response-cookies.md @@ -30,7 +30,7 @@ Então, defina os cookies nela e a retorne: Lembre-se de que se você retornar uma resposta diretamente em vez de usar o parâmetro `Response`, FastAPI a retornará diretamente. -Portanto, você terá que garantir que seus dados sejam do tipo correto. E.g. será compatível com JSON se você estiver retornando um `JSONResponse`. +Portanto, você terá que garantir que seus dados sejam do tipo correto. Por exemplo, será compatível com JSON se você estiver retornando um `JSONResponse`. E também que você não esteja enviando nenhum dado que deveria ter sido filtrado por um `response_model`. diff --git a/docs/pt/docs/advanced/response-headers.md b/docs/pt/docs/advanced/response-headers.md index 7235b5eb8..08a1b6708 100644 --- a/docs/pt/docs/advanced/response-headers.md +++ b/docs/pt/docs/advanced/response-headers.md @@ -1,5 +1,6 @@ # Cabeçalhos de resposta { #response-headers } + ## Use um parâmetro `Response` { #use-a-response-parameter } Você pode declarar um parâmetro do tipo `Response` na sua *função de operação de rota* (assim como você pode fazer para cookies). diff --git a/docs/pt/docs/advanced/security/oauth2-scopes.md b/docs/pt/docs/advanced/security/oauth2-scopes.md index 9dfa6aaf6..b0b9e8348 100644 --- a/docs/pt/docs/advanced/security/oauth2-scopes.md +++ b/docs/pt/docs/advanced/security/oauth2-scopes.md @@ -2,9 +2,9 @@ Você pode utilizar escopos do OAuth2 diretamente com o **FastAPI**, eles são integrados para funcionar perfeitamente. -Isso permitiria que você tivesse um sistema de permissionamento mais refinado, seguindo o padrão do OAuth2 integrado na sua aplicação OpenAPI (e as documentações da API). +Isso permitiria que você tivesse um sistema de permissionamento mais refinado, seguindo o padrão OAuth2, integrado na sua aplicação OpenAPI (e a documentação da API). -OAuth2 com escopos é o mecanismo utilizado por muitos provedores de autenticação, como o Facebook, Google, GitHub, Microsoft, X (Twitter), etc. Eles utilizam isso para prover permissões específicas para os usuários e aplicações. +OAuth2 com escopos é o mecanismo utilizado por muitos grandes provedores de autenticação, como o Facebook, Google, GitHub, Microsoft, X (Twitter), etc. Eles utilizam isso para prover permissões específicas para os usuários e aplicações. Toda vez que você "se autentica com" Facebook, Google, GitHub, Microsoft, X (Twitter), aquela aplicação está utilizando o OAuth2 com escopos. @@ -34,7 +34,7 @@ O conteúdo de cada uma dessas strings pode ter qualquer formato, mas não devem Estes escopos representam "permissões". -No OpenAPI (e.g. os documentos da API), você pode definir "esquemas de segurança". +No OpenAPI (por exemplo, a documentação da API), você pode definir "esquemas de segurança". Quando um desses esquemas de segurança utiliza OAuth2, você pode também declarar e utilizar escopos. @@ -42,7 +42,7 @@ Cada "escopo" é apenas uma string (sem espaços). Eles são normalmente utilizados para declarar permissões de segurança específicas, como por exemplo: -* `users:read` or `users:write` são exemplos comuns. +* `users:read` ou `users:write` são exemplos comuns. * `instagram_basic` é utilizado pelo Facebook / Instagram. * `https://www.googleapis.com/auth/drive` é utilizado pelo Google. @@ -60,7 +60,7 @@ Para o OAuth2, eles são apenas strings. ## Visão global { #global-view } -Primeiro, vamos olhar rapidamente as partes que mudam dos exemplos do **Tutorial - Guia de Usuário** para [OAuth2 com Senha (e hash), Bearer com tokens JWT](../../tutorial/security/oauth2-jwt.md). Agora utilizando escopos OAuth2: +Primeiro, vamos olhar rapidamente as partes que mudam dos exemplos no **Tutorial - Guia de Usuário** principal para [OAuth2 com Senha (e hash), Bearer com tokens JWT](../../tutorial/security/oauth2-jwt.md). Agora utilizando escopos OAuth2: {* ../../docs_src/security/tutorial005_an_py310.py hl[5,9,13,47,65,106,108:116,122:126,130:136,141,157] *} @@ -74,7 +74,7 @@ O parâmetro `scopes` recebe um `dict` contendo cada escopo como chave e a descr {* ../../docs_src/security/tutorial005_an_py310.py hl[63:66] *} -Pelo motivo de estarmos declarando estes escopos, eles aparecerão nos documentos da API quando você se autenticar/autorizar. +Pelo motivo de estarmos declarando estes escopos, eles aparecerão na documentação da API quando você se autenticar/autorizar. E você poderá selecionar quais escopos você deseja dar acesso: `me` e `items`. @@ -108,7 +108,7 @@ Para isso, nós importamos e utilizamos `Security` de `fastapi`. Você pode utilizar `Security` para declarar dependências (assim como `Depends`), porém o `Security` também recebe o parâmetro `scopes` com uma lista de escopos (strings). -Neste caso, nós passamos a função `get_current_active_user` como dependência para `Security` (da mesma forma que nós faríamos com `Depends`). +Neste caso, nós passamos a função de dependência `get_current_active_user` para `Security` (da mesma forma que nós faríamos com `Depends`). Mas nós também passamos uma `list` de escopos, neste caso com apenas um escopo: `items` (poderia ter mais). @@ -142,7 +142,7 @@ Agora atualize a dependência `get_current_user`. Este é o usado pelas dependências acima. -Aqui é onde estamos utilizando o mesmo esquema OAuth2 que nós declaramos antes, declarando-o como uma dependência: `oauth2_scheme`. +Aqui é onde estamos utilizando o mesmo esquema OAuth2 que nós criamos antes, declarando-o como uma dependência: `oauth2_scheme`. Porque esta função de dependência não possui nenhum requerimento de escopo, nós podemos utilizar `Depends` com o `oauth2_scheme`. Nós não precisamos utilizar `Security` quando nós não precisamos especificar escopos de segurança. @@ -235,7 +235,7 @@ Todos eles serão validados independentemente para cada *operação de rota*. ## Verifique { #check-it } -Se você abrir os documentos da API, você pode autenticar e especificar quais escopos você quer autorizar. +Se você abrir a documentação da API, você pode autenticar e especificar quais escopos você quer autorizar. @@ -249,11 +249,11 @@ Isso é o que aconteceria se uma aplicação terceira que tentou acessar uma des Neste exemplo nós estamos utilizando o fluxo de senha do OAuth2. -Isso é apropriado quando nós estamos autenticando em nossa própria aplicação, provavelmente com o nosso próprio "*frontend*". +Isso é apropriado quando nós estamos autenticando em nossa própria aplicação, provavelmente com o nosso próprio frontend. Porque nós podemos confiar nele para receber o `username` e o `password`, pois nós controlamos isso. -Mas se nós estamos construindo uma aplicação OAuth2 que outros poderiam conectar (i.e., se você está construindo um provedor de autenticação equivalente ao Facebook, Google, GitHub, etc.) você deveria utilizar um dos outros fluxos. +Mas se nós estamos construindo uma aplicação OAuth2 que outros poderiam conectar (ou seja, se você está construindo um provedor de autenticação equivalente ao Facebook, Google, GitHub, etc.) você deveria utilizar um dos outros fluxos. O mais comum é o fluxo implícito. diff --git a/docs/pt/docs/advanced/settings.md b/docs/pt/docs/advanced/settings.md index 371d5711b..029290aed 100644 --- a/docs/pt/docs/advanced/settings.md +++ b/docs/pt/docs/advanced/settings.md @@ -1,5 +1,6 @@ # Configurações e Variáveis de Ambiente { #settings-and-environment-variables } + Em muitos casos, sua aplicação pode precisar de configurações externas, por exemplo chaves secretas, credenciais de banco de dados, credenciais para serviços de e-mail, etc. A maioria dessas configurações é variável (pode mudar), como URLs de banco de dados. E muitas podem ser sensíveis, como segredos. diff --git a/docs/pt/docs/advanced/stream-data.md b/docs/pt/docs/advanced/stream-data.md index c71d2ca42..1a9284a91 100644 --- a/docs/pt/docs/advanced/stream-data.md +++ b/docs/pt/docs/advanced/stream-data.md @@ -2,7 +2,7 @@ Se você quer transmitir dados que podem ser estruturados como JSON, você deveria [Transmitir JSON Lines](../tutorial/stream-json-lines.md). -Mas se você quer transmitir dados binários puros ou strings, veja como fazer. +Mas se você quer **transmitir dados binários puros** ou strings, veja como fazer. /// note | Nota @@ -12,15 +12,15 @@ Adicionado no FastAPI 0.134.0. ## Casos de uso { #use-cases } -Você pode usar isto para transmitir strings puras, por exemplo diretamente da saída de um serviço de AI LLM. +Você pode usar isto para transmitir strings puras, por exemplo diretamente da saída de um serviço de **AI LLM**. -Você também pode usá-lo para transmitir arquivos binários grandes, enviando cada bloco de dados à medida que o lê, sem precisar carregar tudo na memória de uma vez. +Você também pode usá-lo para transmitir **arquivos binários grandes**, enviando cada bloco de dados à medida que o lê, sem precisar carregar tudo na memória de uma vez. -Você também pode transmitir vídeo ou áudio desta forma; pode até ser gerado enquanto você processa e envia. +Você também pode transmitir **vídeo** ou **áudio** desta forma; pode até ser gerado enquanto você processa e envia. ## Um `StreamingResponse` com `yield` { #a-streamingresponse-with-yield } -Se você declarar `response_class=StreamingResponse` na sua função de operação de rota, você pode usar `yield` para enviar cada bloco de dados em sequência. +Se você declarar `response_class=StreamingResponse` na sua *função de operação de rota*, você pode usar `yield` para enviar cada bloco de dados em sequência. {* ../../docs_src/stream_data/tutorial001_py310.py ln[1:23] hl[20,23] *} @@ -40,7 +40,7 @@ Como o FastAPI não tentará converter os dados para JSON com Pydantic nem seria {* ../../docs_src/stream_data/tutorial001_py310.py ln[32:35] hl[33] *} -Isso também significa que, com `StreamingResponse`, você tem a liberdade e a responsabilidade de produzir e codificar os bytes exatamente como precisam ser enviados, independentemente das anotações de tipo. 🤓 +Isso também significa que, com `StreamingResponse`, você tem a **liberdade** e a **responsabilidade** de produzir e codificar os bytes exatamente como precisam ser enviados, independentemente das anotações de tipo. 🤓 ### Transmitir bytes { #stream-bytes } @@ -50,7 +50,7 @@ Um dos principais casos de uso é transmitir `bytes` em vez de strings; você po ## Um `PNGStreamingResponse` personalizado { #a-custom-pngstreamingresponse } -Nos exemplos acima, os bytes eram transmitidos, mas a resposta não tinha um cabeçalho `Content-Type`, então o cliente não sabia que tipo de dado estava recebendo. +Nos exemplos acima, os bytes eram transmitidos, mas a response não tinha um cabeçalho `Content-Type`, então o cliente não sabia que tipo de dado estava recebendo. Você pode criar uma subclasse personalizada de `StreamingResponse` que define o cabeçalho `Content-Type` para o tipo de dado que você está transmitindo. @@ -58,7 +58,7 @@ Por exemplo, você pode criar um `PNGStreamingResponse` que define o cabeçalho {* ../../docs_src/stream_data/tutorial002_py310.py ln[6,19:20] hl[20] *} -Em seguida, você pode usar essa nova classe em `response_class=PNGStreamingResponse` na sua função de operação de rota: +Em seguida, você pode usar essa nova classe em `response_class=PNGStreamingResponse` na sua *função de operação de rota*: {* ../../docs_src/stream_data/tutorial002_py310.py ln[23:27] hl[23] *} @@ -78,7 +78,7 @@ Apenas para que possa viver no mesmo arquivo deste exemplo e você possa copiar /// -Ao usar um bloco `with`, garantimos que o objeto semelhante a arquivo seja fechado após a função geradora (a função com `yield`) terminar. Ou seja, após terminar de enviar a resposta. +Ao usar um bloco `with`, garantimos que o objeto semelhante a arquivo seja fechado após a função geradora (a função com `yield`) terminar. Ou seja, após terminar de enviar a response. Isso não seria tão importante neste exemplo específico porque é um arquivo falso em memória (com `io.BytesIO`), mas com um arquivo real, seria importante garantir que o arquivo fosse fechado ao final do trabalho. @@ -98,7 +98,7 @@ Mas, em muitos casos, ler um arquivo ou um objeto semelhante a arquivo bloqueari /// -Para evitar bloquear o loop de eventos, você pode simplesmente declarar a função de operação de rota com `def` normal em vez de `async def`. Assim, o FastAPI a executará em um worker de threadpool, evitando bloquear o loop principal. +Para evitar bloquear o loop de eventos, você pode simplesmente declarar a *função de operação de rota* com `def` normal em vez de `async def`. Assim, o FastAPI a executará em um worker de threadpool, evitando bloquear o loop principal. {* ../../docs_src/stream_data/tutorial002_py310.py ln[30:34] hl[31] *} diff --git a/docs/pt/docs/advanced/wsgi.md b/docs/pt/docs/advanced/wsgi.md index 30e8a3b2c..fafa147fa 100644 --- a/docs/pt/docs/advanced/wsgi.md +++ b/docs/pt/docs/advanced/wsgi.md @@ -1,5 +1,6 @@ # Adicionando WSGI - Flask, Django, entre outros { #including-wsgi-flask-django-others } + Como você viu em [Subaplicações - Montagens](sub-applications.md) e [Atrás de um Proxy](behind-a-proxy.md), você pode montar aplicações WSGI. Para isso, você pode utilizar o `WSGIMiddleware` para encapsular a sua aplicação WSGI, como por exemplo Flask, Django, etc. diff --git a/docs/pt/docs/alternatives.md b/docs/pt/docs/alternatives.md index b32b260c3..8a63a3073 100644 --- a/docs/pt/docs/alternatives.md +++ b/docs/pt/docs/alternatives.md @@ -18,13 +18,13 @@ Mas em algum momento, não havia outra opção senão criar algo que fornecesse É o framework Python mais popular e amplamente confiável. É utilizado para construir sistemas como o Instagram. -É relativamente bem acoplado com bancos de dados relacionais (como MySQL ou PostgreSQL), então, ter um banco de dados NoSQL (como Couchbase, MongoDB, Cassandra, etc.) como mecanismo principal de armazenamento não é muito fácil. +É relativamente fortemente acoplado com bancos de dados relacionais (como MySQL ou PostgreSQL), então, ter um banco de dados NoSQL (como Couchbase, MongoDB, Cassandra, etc.) como mecanismo principal de armazenamento não é muito fácil. Foi criado para gerar o HTML no backend, não para criar APIs usadas por um frontend moderno (como React, Vue.js e Angular) ou por outros sistemas (como dispositivos IoT) comunicando com ele. ### [Django REST Framework](https://www.django-rest-framework.org/) { #django-rest-framework } -Django REST framework foi criado para ser uma caixa de ferramentas flexível para construção de APIs Web utilizando Django por baixo, para melhorar suas capacidades de API. +Django REST Framework foi criado para ser uma caixa de ferramentas flexível para construção de APIs Web utilizando Django por baixo, para melhorar suas capacidades de API. Ele é utilizado por muitas empresas incluindo Mozilla, Red Hat e Eventbrite. @@ -88,7 +88,7 @@ O jeito de usar é muito simples. Por exemplo, para fazer uma requisição `GET` response = requests.get("http://example.com/some/url") ``` -A contra-parte na aplicação FastAPI, a operação de rota, poderia ficar assim: +A *operação de rota* da API equivalente no FastAPI poderia ficar assim: ```Python hl_lines="1" @app.get("/some/url") @@ -377,7 +377,7 @@ Agora APIStar é um conjunto de ferramentas para validar especificações OpenAP /// note | Nota -APIStar foi criado por Tom Christie. O mesmo cara que criou: +APIStar foi criado por Tom Christie. A mesma pessoa que criou: * Django REST Framework * Starlette (no qual **FastAPI** é baseado) diff --git a/docs/pt/docs/async.md b/docs/pt/docs/async.md index 8c497d451..3fa92b085 100644 --- a/docs/pt/docs/async.md +++ b/docs/pt/docs/async.md @@ -44,11 +44,11 @@ Se sua aplicação (de alguma forma) não tem que se comunicar com nada mais e e --- -Se você simplesmente não sabe, use apenas `def`. +Se você simplesmente não sabe, use `def` normal. --- -**Note**: Você pode misturar `def` e `async def` nas suas *funções de operação de rota* tanto quanto necessário e definir cada função usando a melhor opção para você. FastAPI irá fazer a coisa certa com elas. +**Nota**: Você pode misturar `def` e `async def` nas suas *funções de operação de rota* tanto quanto necessário e definir cada função usando a melhor opção para você. FastAPI irá fazer a coisa certa com elas. De qualquer forma, em ambos os casos acima, FastAPI irá trabalhar assincronamente e ser extremamente rápido. @@ -82,10 +82,10 @@ Esse "esperar por algo" normalmente se refere a operações I/O, essas operações são chamadas operações "limitadas por I/O". +Como 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" 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. @@ -109,7 +109,7 @@ Você vai com seu _crush_ na lanchonete, e fica na fila enquanto o caixa pega os -Então chega a sua vez, você pede dois saborosos hambúrgueres para você e seu _crush_. 🍔🍔 +Então chega a sua vez, você pede dois saborosos hambúrgueres para você e seu _crush_. 🍔🍔 @@ -189,17 +189,17 @@ Você espera, na frente do balcão 🕙, para que ninguém pegue seus hambúrgue 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 os der 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_. -Vocês comem os hambúrgueres, e o trabalho está terminado. ⏹ +Vocês apenas os comem, e o trabalho está terminado. ⏹ @@ -213,15 +213,15 @@ Belas ilustrações de [Ketrina Thompson](https://www.instagram.com/ketrinadraws --- -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. +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 ⏯ a "esperar no balcão" 🕙 por um bom tempo. -A lanchonete paralela tem 8 processadores (caixas / cozinheiros), enquanto a lanchonete dos hambúrgueres concorrentes tinha apenas 2 (um caixa e um cozinheiro). +A lanchonete tem 8 processadores (caixas/cozinheiros). Enquanto a lanchonete dos hambúrgueres concorrentes poderia ter apenas 2 (um caixa e um cozinheiro). Ainda assim, a experiência final não foi a melhor. 😞 --- -Essa seria o equivalente paralelo à história dos hambúrgueres. 🍔 +Essa seria a história equivalente paralela para hambúrgueres. 🍔 Para um exemplo "mais real", imagine um banco. @@ -231,15 +231,15 @@ 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. -Você provavelmente não gostaria de levar seu _crush_ 😍 com você para um rolezinho no banco 🏦. +Você provavelmente não gostaria de levar seu _crush_ 😍 com você para resolver assuntos no banco 🏦. ### Conclusão dos hambúrgueres { #burger-conclusion } -Nesse cenário dos "hambúrgueres com seu _crush_", como tem muita espera, faz mais sentido ter um sistema concorrente ⏸🔀⏯. +Nesse cenário dos "hambúrgueres de fast food com seu _crush_", como tem muita espera 🕙, faz mais sentido ter um sistema concorrente ⏸🔀⏯. Esse é o caso da maioria das aplicações web. -Muitos, muitos usuários, mas seu servidor está esperando 🕙 pela sua conexão não tão boa enviar suas requisições. +Muitos, muitos usuários, mas seu servidor está esperando 🕙 pela conexão não tão boa deles enviar suas requisições. E então esperando 🕙 novamente as respostas voltarem. @@ -269,11 +269,11 @@ Então, para equilibrar tudo, imagine a seguinte historinha: 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 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. +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 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. +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. @@ -285,18 +285,18 @@ Exemplos comuns de operações limitadas por CPU são coisas que exigem processa Por exemplo: -* **Processamento de áudio** ou **imagem** -* **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 -* **Aprendizado de Máquina**: 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 Aprendizado de Máquina, 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. +* **Processamento de áudio** ou **imagem**. +* **Visão Computacional**: uma imagem é composta por milhões de pixels, cada pixel tem 3 valores / cores, processar isso normalmente exige alguma computação nesses pixels, todos ao mesmo tempo. +* **Aprendizado de Máquina**: 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 Aprendizado de Máquina, então, o mesmo se aplica. A diferença é que não há apenas uma 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 + Aprendizado de Máquina { #concurrency-parallelism-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 **limitados por CPU** como aqueles em sistemas de Aprendizado de Máquina. +Mas você também pode explorar os benefícios do paralelismo e multiprocessamento (tendo múltiplos processos rodando em paralelo) para trabalhos **limitados por CPU** como aqueles em sistemas de Aprendizado de Máquina. -Isso, somado ao simples fato que Python é a principal linguagem para **Data Science**, Aprendizado de Máquina e especialmente Deep Learning, faz do FastAPI uma ótima escolha para APIs web e aplicações com Data Science / Aprendizado de Máquina (entre muitas outras). +Isso, somado ao simples fato que Python é a principal linguagem para **Data Science**, Aprendizado de Máquina e especialmente Deep Learning, faz do FastAPI uma ótima escolha para APIs web e aplicações de Data Science / Aprendizado de Máquina (entre muitas outras). Para ver como alcançar esse paralelismo em produção veja a seção sobre [Implantação](deployment/index.md). @@ -340,7 +340,7 @@ burgers = get_burgers(2) --- -Então, se você está usando uma biblioteca que diz que você pode chamá-la com `await`, você precisa criar as *funções de operação de rota* com `async def`, como em: +Então, se você está usando uma biblioteca que diz que você pode chamá-la com `await`, você precisa criar as *funções de operação de rota* que a utilizam com `async def`, como em: ```Python hl_lines="2-3" @app.get('/burgers') @@ -355,9 +355,9 @@ Você deve ter observado que `await` pode ser usado somente dentro de funções Mas ao mesmo tempo, funções definidas com `async def` têm que ser "aguardadas". Então, funções com `async def` podem 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? +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. +Se você estiver 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, você também pode fazê-lo. @@ -423,7 +423,7 @@ Ainda, em ambas as situações, as chances são que o **FastAPI** [ainda será m ### Dependências { #dependencies } -O mesmo se aplica para as [dependências](tutorial/dependencies/index.md). 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). Se uma dependência é uma função `def` padrão ao invés de `async def`, ela é rodada no threadpool externo. ### Sub-dependências { #sub-dependencies } @@ -435,7 +435,7 @@ Qualquer outra função de utilidade que você chame diretamente pode ser criada Isso está em contraste às funções que o FastAPI chama para você: *funções de operação de rota* e dependências. -Se sua função de utilidade é uma função normal com `def`, ela será chamada diretamente (como você a escreve no código), não em uma threadpool, se a função é criada com `async def` então você deve esperar por essa função quando você chamá-la no seu código. +Se sua função de utilidade é uma função normal com `def`, ela será chamada diretamente (como você a escreve no código), não em uma threadpool, se a função é criada com `async def` então você deveria usar `await` nessa função quando você chamá-la no seu código. --- diff --git a/docs/pt/docs/deployment/cloud.md b/docs/pt/docs/deployment/cloud.md index 4b0eb9553..68a2fd003 100644 --- a/docs/pt/docs/deployment/cloud.md +++ b/docs/pt/docs/deployment/cloud.md @@ -16,7 +16,7 @@ FastAPI Cloud é o patrocinador principal e provedor de financiamento dos projet ## Provedores de Nuvem - Patrocinadores { #cloud-providers-sponsors } -Alguns outros provedores de nuvem ✨ [**patrocinam o FastAPI**](../help-fastapi.md#sponsor-the-author) ✨ também. 🙇 +Alguns outros provedores de nuvem ✨ [**patrocinam o FastAPI**](https://github.com/sponsors/tiangolo) ✨ também. 🙇 Você também pode considerá-los para seguir seus tutoriais e experimentar seus serviços: diff --git a/docs/pt/docs/deployment/concepts.md b/docs/pt/docs/deployment/concepts.md index e6338d5ea..0625c6d64 100644 --- a/docs/pt/docs/deployment/concepts.md +++ b/docs/pt/docs/deployment/concepts.md @@ -1,6 +1,6 @@ # Conceitos de Implantações { #deployments-concepts } -Ao implantar um aplicativo **FastAPI**, ou na verdade, qualquer tipo de API da web, há vários conceitos com os quais você provavelmente se importa e, usando-os, você pode encontrar a maneira **mais apropriada** de **implantar seu aplicativo**. +Ao implantar uma aplicação **FastAPI**, ou na verdade, qualquer tipo de API da web, há vários conceitos com os quais você provavelmente se importa e, usando-os, você pode encontrar a maneira **mais apropriada** de **implantar sua aplicação**. Alguns dos conceitos importantes são: @@ -19,7 +19,7 @@ Vou lhe contar um pouco mais sobre esses **conceitos** aqui, e espero que isso l Ao considerar esses conceitos, você será capaz de **avaliar e projetar** a melhor maneira de implantar **suas próprias APIs**. -Nos próximos capítulos, darei a você mais **receitas concretas** para implantar aplicativos FastAPI. +Nos próximos capítulos, darei a você mais **receitas concretas** para implantar aplicações FastAPI. Mas por enquanto, vamos verificar essas importantes **ideias conceituais**. Esses conceitos também se aplicam a qualquer outro tipo de API da web. 💡 @@ -27,7 +27,7 @@ Mas por enquanto, vamos verificar essas importantes **ideias conceituais**. Esse No [capítulo anterior sobre HTTPS](https.md) aprendemos como o HTTPS fornece criptografia para sua API. -Também vimos que o HTTPS normalmente é fornecido por um componente **externo** ao seu servidor de aplicativos, um **Proxy de terminação TLS**. +Também vimos que o HTTPS normalmente é fornecido por um componente **externo** ao seu servidor de aplicações, um **Proxy de terminação TLS**. E tem que haver algo responsável por **renovar os certificados HTTPS**, pode ser o mesmo componente ou pode ser algo diferente. @@ -75,7 +75,7 @@ A palavra **processo** normalmente é usada de forma mais específica, referindo * Isso não se refere ao arquivo, nem ao código, refere-se **especificamente** à coisa que está sendo **executada** e gerenciada pelo sistema operacional. * Qualquer programa, qualquer código, **só pode fazer coisas** quando está sendo **executado**. Então, quando há um **processo em execução**. * O processo pode ser **terminado** (ou "morto") por você, ou pelo sistema operacional. Nesse ponto, ele para de rodar/ser executado, e ele **não pode mais fazer coisas**. -* Cada aplicativo que você tem em execução no seu computador tem algum processo por trás dele, cada programa em execução, cada janela, etc. E normalmente há muitos processos em execução **ao mesmo tempo** enquanto um computador está ligado. +* Cada aplicação que você tem em execução no seu computador tem algum processo por trás dela, cada programa em execução, cada janela, etc. E normalmente há muitos processos em execução **ao mesmo tempo** enquanto um computador está ligado. * Pode haver **vários processos** do **mesmo programa** em execução ao mesmo tempo. Se você verificar o "gerenciador de tarefas" ou o "monitor do sistema" (ou ferramentas semelhantes) no seu sistema operacional, poderá ver muitos desses processos em execução. @@ -104,11 +104,11 @@ E se o servidor for reiniciado (por exemplo, após atualizações ou migrações ### Executar automaticamente na inicialização { #run-automatically-on-startup } -Em geral, você provavelmente desejará que o programa do servidor (por exemplo, Uvicorn) seja iniciado automaticamente na inicialização do servidor e, sem precisar de nenhuma **intervenção humana**, tenha um processo sempre em execução com sua API (por exemplo, Uvicorn executando seu aplicativo FastAPI). +Em geral, você provavelmente desejará que o programa do servidor (por exemplo, Uvicorn) seja iniciado automaticamente na inicialização do servidor e, sem precisar de nenhuma **intervenção humana**, tenha um processo sempre em execução com sua API (por exemplo, Uvicorn executando sua aplicação FastAPI). ### Programa separado { #separate-program } -Para conseguir isso, você normalmente terá um **programa separado** que garantiria que seu aplicativo fosse executado na inicialização. E em muitos casos, ele também garantiria que outros componentes ou aplicativos também fossem executados, por exemplo, um banco de dados. +Para conseguir isso, você normalmente terá um **programa separado** que garantiria que sua aplicação fosse executada na inicialização. E em muitos casos, ele também garantiria que outros componentes ou aplicações também fossem executados, por exemplo, um banco de dados. ### Ferramentas de exemplo para executar na inicialização { #example-tools-to-run-at-startup } @@ -127,7 +127,7 @@ Darei exemplos mais concretos nos próximos capítulos. ## Reinicializações { #restarts } -Semelhante a garantir que seu aplicativo seja executado na inicialização, você provavelmente também deseja garantir que ele seja **reiniciado** após falhas. +Semelhante a garantir que sua aplicação seja executada na inicialização, você provavelmente também deseja garantir que ela seja **reiniciada** após falhas. ### Nós cometemos erros { #we-make-mistakes } @@ -137,15 +137,15 @@ E nós, como desenvolvedores, continuamos aprimorando o código à medida que en ### Pequenos erros são tratados automaticamente { #small-errors-automatically-handled } -Ao criar APIs da web com FastAPI, se houver um erro em nosso código, o FastAPI normalmente o conterá na única solicitação que acionou o erro. 🛡 +Ao criar APIs da web com FastAPI, se houver um erro em nosso código, o FastAPI normalmente o conterá na única request que acionou o erro. 🛡 -O cliente receberá um **Erro Interno do Servidor 500** para essa solicitação, mas o aplicativo continuará funcionando para as próximas solicitações em vez de travar completamente. +O cliente receberá um **Erro Interno do Servidor 500** para essa request, mas a aplicação continuará funcionando para as próximas requests em vez de travar completamente. ### Erros maiores - Travamentos { #bigger-errors-crashes } -No entanto, pode haver casos em que escrevemos algum código que **trava todo o aplicativo**, fazendo com que o Uvicorn e o Python travem. 💥 +No entanto, pode haver casos em que escrevemos algum código que **trava toda a aplicação**, fazendo com que o Uvicorn e o Python travem. 💥 -E ainda assim, você provavelmente não gostaria que o aplicativo permanecesse inativo porque houve um erro em um lugar, você provavelmente quer que ele **continue em execução** pelo menos para as *operações de rota* que não estão quebradas. +E ainda assim, você provavelmente não gostaria que a aplicação permanecesse inativa porque houve um erro em um lugar, você provavelmente quer que ela **continue em execução** pelo menos para as *operações de rota* que não estão quebradas. ### Reiniciar após falha { #restart-after-crash } @@ -153,13 +153,13 @@ Mas nos casos com erros realmente graves que travam o **processo** em execução /// tip | Dica -...Embora se o aplicativo inteiro estiver **travando imediatamente**, provavelmente não faça sentido reiniciá-lo para sempre. Mas nesses casos, você provavelmente notará isso durante o desenvolvimento, ou pelo menos logo após a implantação. +...Embora se a aplicação inteira estiver **travando imediatamente**, provavelmente não faça sentido reiniciá-la para sempre. Mas nesses casos, você provavelmente notará isso durante o desenvolvimento, ou pelo menos logo após a implantação. -Então, vamos nos concentrar nos casos principais, onde ele pode travar completamente em alguns casos específicos **no futuro**, e ainda faz sentido reiniciá-lo. +Então, vamos nos concentrar nos casos principais, onde ela pode travar completamente em alguns casos específicos **no futuro**, e ainda faz sentido reiniciá-la. /// -Você provavelmente gostaria de ter a coisa responsável por reiniciar seu aplicativo como um **componente externo**, porque a essa altura, o mesmo aplicativo com Uvicorn e Python já havia travado, então não há nada no mesmo código do mesmo aplicativo que possa fazer algo a respeito. +Você provavelmente gostaria de ter a coisa responsável por reiniciar sua aplicação como um **componente externo**, porque a essa altura, a mesma aplicação com Uvicorn e Python já havia travado, então não há nada no mesmo código da mesma aplicação que possa fazer algo a respeito. ### Ferramentas de exemplo para reiniciar automaticamente { #example-tools-to-restart-automatically } @@ -178,13 +178,13 @@ Por exemplo, isso poderia ser resolvido por: ## Replicação - Processos e Memória { #replication-processes-and-memory } -Com um aplicativo FastAPI, usando um programa de servidor como o comando `fastapi` que executa o Uvicorn, executá-lo uma vez em **um processo** pode atender a vários clientes simultaneamente. +Com uma aplicação FastAPI, usando um programa de servidor como o comando `fastapi` que executa o Uvicorn, executá-lo uma vez em **um processo** pode atender a vários clientes simultaneamente. Mas em muitos casos, você desejará executar vários processos de trabalho ao mesmo tempo. ### Processos Múltiplos - Trabalhadores { #multiple-processes-workers } -Se você tiver mais clientes do que um único processo pode manipular (por exemplo, se a máquina virtual não for muito grande) e tiver **vários núcleos** na CPU do servidor, você poderá ter **vários processos** em execução com o mesmo aplicativo ao mesmo tempo e distribuir todas as solicitações entre eles. +Se você tiver mais clientes do que um único processo pode manipular (por exemplo, se a máquina virtual não for muito grande) e tiver **vários núcleos** na CPU do servidor, você poderá ter **vários processos** em execução com a mesma aplicação ao mesmo tempo e distribuir todas as requests entre eles. Quando você executa **vários processos** do mesmo programa de API, eles são comumente chamados de **trabalhadores**. @@ -214,11 +214,11 @@ Neste exemplo, há um **Processo Gerenciador** que inicia e controla dois **Proc Este Processo de Gerenciador provavelmente seria o que escutaria na **porta** no IP. E ele transmitiria toda a comunicação para os processos de trabalho. -Esses processos de trabalho seriam aqueles que executariam seu aplicativo, eles executariam os cálculos principais para receber uma **solicitação** e retornar uma **resposta**, e carregariam qualquer coisa que você colocasse em variáveis ​​na RAM. +Esses processos de trabalho seriam aqueles que executariam sua aplicação, eles executariam os cálculos principais para receber uma **request** e retornar uma **resposta**, e carregariam qualquer coisa que você colocasse em variáveis ​​na RAM. -E, claro, a mesma máquina provavelmente teria **outros processos** em execução, além do seu aplicativo. +E, claro, a mesma máquina provavelmente teria **outros processos** em execução, além da sua aplicação. Um detalhe interessante é que a porcentagem da **CPU usada** por cada processo pode **variar** muito ao longo do tempo, mas a **memória (RAM)** normalmente fica mais ou menos **estável**. @@ -255,9 +255,9 @@ Por exemplo, você pode querer executar **migrações de banco de dados**. Mas na maioria dos casos, você precisará executar essas etapas apenas **uma vez**. -Portanto, você vai querer ter um **processo único** para executar essas **etapas anteriores** antes de iniciar o aplicativo. +Portanto, você vai querer ter um **processo único** para executar essas **etapas anteriores** antes de iniciar a aplicação. -E você terá que se certificar de que é um único processo executando essas etapas anteriores *mesmo* se depois, você iniciar **vários processos** (vários trabalhadores) para o próprio aplicativo. Se essas etapas fossem executadas por **vários processos**, eles **duplicariam** o trabalho executando-o em **paralelo**, e se as etapas fossem algo delicado como uma migração de banco de dados, elas poderiam causar conflitos entre si. +E você terá que se certificar de que é um único processo executando essas etapas anteriores *mesmo* se depois, você iniciar **vários processos** (vários trabalhadores) para a própria aplicação. Se essas etapas fossem executadas por **vários processos**, eles **duplicariam** o trabalho executando-o em **paralelo**, e se as etapas fossem algo delicado como uma migração de banco de dados, elas poderiam causar conflitos entre si. Claro, há alguns casos em que não há problema em executar as etapas anteriores várias vezes; nesse caso, é muito mais fácil de lidar. @@ -276,7 +276,7 @@ Isso **dependerá muito** da maneira como você **implanta seu sistema** e prova Aqui estão algumas ideias possíveis: * Um "Init Container" no Kubernetes que roda antes do seu app container -* Um script bash que roda os passos anteriores e então inicia seu aplicativo +* Um script bash que roda os passos anteriores e então inicia sua aplicação * Você ainda precisaria de uma maneira de iniciar/reiniciar *aquele* script bash, detectar erros, etc. /// tip | Dica @@ -307,7 +307,7 @@ Você pode usar ferramentas simples como `htop` para ver a CPU e a RAM usadas no ## Recapitular { #recap } -Você leu aqui alguns dos principais conceitos que provavelmente precisa ter em mente ao decidir como implantar seu aplicativo: +Você leu aqui alguns dos principais conceitos que provavelmente precisa ter em mente ao decidir como implantar sua aplicação: * Segurança - HTTPS * Executando na inicialização diff --git a/docs/pt/docs/deployment/docker.md b/docs/pt/docs/deployment/docker.md index e14870d7c..f68784855 100644 --- a/docs/pt/docs/deployment/docker.md +++ b/docs/pt/docs/deployment/docker.md @@ -50,7 +50,7 @@ Uma imagem de contêiner é uma versão **estática** de todos os arquivos, vari Em contraste com a "**imagem de contêiner**" que contém os conteúdos estáticos armazenados, um "**contêiner**" normalmente se refere à instância rodando, a coisa que está sendo **executada**. -Quando o **contêiner** é iniciado e está rodando (iniciado a partir de uma **imagem de contêiner**), ele pode criar ou modificar arquivos, variáveis de ambiente, etc. Essas mudanças vão existir somente nesse contêiner, mas não persistirão na imagem subjacente do container (não serão salvas no disco). +Quando o **contêiner** é iniciado e está rodando (iniciado a partir de uma **imagem de contêiner**), ele pode criar ou modificar arquivos, variáveis de ambiente, etc. Essas mudanças vão existir somente nesse contêiner, mas não persistirão na imagem subjacente do contêiner (não serão salvas no disco). Uma imagem de contêiner é comparável ao arquivo de **programa** e seus conteúdos, ex.: `python` e algum arquivo `main.py`. @@ -64,7 +64,7 @@ E existe um [Docker Hub](https://hub.docker.com/) público com **imagens de cont Por exemplo, há uma [Imagem Python](https://hub.docker.com/_/python) oficial. -E existe muitas outras imagens para diferentes coisas, como bancos de dados, por exemplo: +E existem muitas outras imagens para diferentes coisas, como bancos de dados, por exemplo: * [PostgreSQL](https://hub.docker.com/_/postgres) * [MySQL](https://hub.docker.com/_/mysql) @@ -87,11 +87,11 @@ Quando um **contêiner** é iniciado, ele irá rodar esse comando/programa (embo Um contêiner está rodando enquanto o **processo principal** (comando ou programa) estiver rodando. -Um contêiner normalmente tem um **único processo**, mas também é possível iniciar sub-processos a partir do processo principal, e dessa forma você terá **vários processos** no mesmo contêiner. +Um contêiner normalmente tem um **único processo**, mas também é possível iniciar subprocessos a partir do processo principal, e dessa forma você terá **vários processos** no mesmo contêiner. Mas não é possível ter um contêiner rodando sem **pelo menos um processo rodando**. Se o processo principal parar, o contêiner também para. -## Construir uma Imagem Docker para FastAPI { #build-a-docker-image-for-fastapi } +## Construa uma Imagem Docker para FastAPI { #build-a-docker-image-for-fastapi } Okay, vamos construir algo agora! 🚀 @@ -262,7 +262,7 @@ Isso pode ser bem perceptível ao usar `docker compose`. Veja esta seção de FA #### Estrutura de diretórios { #directory-structure } -Agora você deve haver uma estrutura de diretório como: +Agora você deveria ter uma estrutura de diretório como: ``` . @@ -275,7 +275,7 @@ Agora você deve haver uma estrutura de diretório como: #### Por trás de um Proxy de Terminação TLS { #behind-a-tls-termination-proxy } -Se você está executando seu contêiner atrás de um Proxy de Terminação TLS (load balancer) como Nginx ou Traefik, adicione a opção `--proxy-headers`, isso fará com que o Uvicorn (pela CLI do FastAPI) confie nos cabeçalhos enviados por esse proxy, informando que o aplicativo está sendo executado atrás do HTTPS, etc. +Se você está executando seu contêiner atrás de um Proxy de Terminação TLS (balanceador de carga) como Nginx ou Traefik, adicione a opção `--proxy-headers`, isso fará com que o Uvicorn (pela CLI do FastAPI) confie nos cabeçalhos enviados por esse proxy, informando que o aplicativo está sendo executado atrás do HTTPS, etc. ```Dockerfile CMD ["fastapi", "run", "app/main.py", "--proxy-headers", "--port", "80"] @@ -289,7 +289,7 @@ Existe um truque importante nesse `Dockerfile`, primeiro copiamos o **arquivo co COPY ./requirements.txt /code/requirements.txt ``` -Docker e outras ferramentas **constróem** essas imagens de contêiner **incrementalmente**, adicionando **uma camada em cima da outra**, começando do topo do `Dockerfile` e adicionando qualquer arquivo criado por cada uma das instruções do `Dockerfile`. +Docker e outras ferramentas **constroem** essas imagens de contêiner **incrementalmente**, adicionando **uma camada em cima da outra**, começando do topo do `Dockerfile` e adicionando qualquer arquivo criado por cada uma das instruções do `Dockerfile`. Docker e ferramentas similares também usam um **cache interno** ao construir a imagem, se um arquivo não mudou desde a última vez que a imagem do contêiner foi construída, então ele irá **reutilizar a mesma camada** criada na última vez, ao invés de copiar o arquivo novamente e criar uma nova camada do zero. @@ -352,7 +352,7 @@ $ docker run -d --name mycontainer -p 80:80 myimage ## Verifique { #check-it } -Você deve ser capaz de verificar isso no URL do seu contêiner Docker, por exemplo: [http://192.168.99.100/items/5?q=somequery](http://192.168.99.100/items/5?q=somequery) ou [http://127.0.0.1/items/5?q=somequery](http://127.0.0.1/items/5?q=somequery) (ou equivalente, usando seu host Docker). +Você deveria conseguir verificar isso no URL do seu contêiner Docker, por exemplo: [http://192.168.99.100/items/5?q=somequery](http://192.168.99.100/items/5?q=somequery) ou [http://127.0.0.1/items/5?q=somequery](http://127.0.0.1/items/5?q=somequery) (ou equivalente, usando seu host Docker). Você verá algo como: @@ -376,9 +376,9 @@ Você verá a documentação alternativa automática (fornecida pelo [ReDoc](htt ![ReDoc](https://fastapi.tiangolo.com/img/index/index-02-redoc-simple.png) -## Construa uma Imagem Docker com um FastAPI de Arquivo Único { #build-a-docker-image-with-a-single-file-fastapi } +## Construa uma Imagem Docker com uma aplicação FastAPI de Arquivo Único { #build-a-docker-image-with-a-single-file-fastapi } -Se seu FastAPI for um único arquivo, por exemplo, `main.py` sem um diretório `./app`, sua estrutura de arquivos poderia ser assim: +Se sua aplicação FastAPI for um único arquivo, por exemplo, `main.py` sem um diretório `./app`, sua estrutura de arquivos poderia ser assim: ``` . @@ -456,7 +456,7 @@ Sem usar contêineres, fazer aplicativos executarem na inicialização e com rei Se você tiver um cluster de máquinas com **Kubernetes**, Docker Swarm Mode, Nomad ou outro sistema complexo semelhante para gerenciar contêineres distribuídos em várias máquinas, então provavelmente desejará **lidar com a replicação** no **nível do cluster** em vez de usar um **gerenciador de processos** (como Uvicorn com workers) em cada contêiner. -Um desses sistemas de gerenciamento de contêineres distribuídos como o Kubernetes normalmente tem alguma maneira integrada de lidar com a **replicação de contêineres** enquanto ainda oferece **balanceamento de carga** para as solicitações recebidas. Tudo no **nível do cluster**. +Um desses sistemas de gerenciamento de contêineres distribuídos como o Kubernetes normalmente tem alguma maneira integrada de lidar com a **replicação de contêineres** enquanto ainda oferece **balanceamento de carga** para os requests recebidos. Tudo no **nível do cluster**. Nesses casos, você provavelmente desejará criar uma **imagem Docker do zero** como [explicado acima](#dockerfile), instalando suas dependências e executando **um único processo Uvicorn** em vez de usar múltiplos workers do Uvicorn. @@ -464,7 +464,7 @@ Nesses casos, você provavelmente desejará criar uma **imagem Docker do zero** Quando usando contêineres, normalmente você terá algum componente **escutando na porta principal**. Poderia ser outro contêiner que também é um **Proxy de Terminação TLS** para lidar com **HTTPS** ou alguma ferramenta semelhante. -Como esse componente assumiria a **carga** de solicitações e distribuiria isso entre os workers de uma maneira (esperançosamente) **balanceada**, ele também é comumente chamado de **Balanceador de Carga**. +Como esse componente assumiria a **carga** de requests e distribuiria isso entre os workers de uma maneira (esperançosamente) **balanceada**, ele também é comumente chamado de **Balanceador de Carga**. /// tip | Dica @@ -472,17 +472,17 @@ O mesmo componente **Proxy de Terminação TLS** usado para HTTPS provavelmente /// -E quando trabalhar com contêineres, o mesmo sistema que você usa para iniciar e gerenciá-los já terá ferramentas internas para transmitir a **comunicação de rede** (por exemplo, solicitações HTTP) do **balanceador de carga** (que também pode ser um **Proxy de Terminação TLS**) para o(s) contêiner(es) com seu aplicativo. +E quando trabalhar com contêineres, o mesmo sistema que você usa para iniciar e gerenciá-los já terá ferramentas internas para transmitir a **comunicação de rede** (por exemplo, requests HTTP) do **balanceador de carga** (que também pode ser um **Proxy de Terminação TLS**) para o(s) contêiner(es) com seu aplicativo. ### Um Balanceador de Carga - Múltiplos Contêineres de Workers { #one-load-balancer-multiple-worker-containers } -Quando trabalhando com **Kubernetes** ou sistemas similares de gerenciamento de contêiner distribuído, usar seus mecanismos de rede internos permite que o único **balanceador de carga** que está escutando na **porta principal** transmita a comunicação (solicitações) para possivelmente **múltiplos contêineres** executando seu aplicativo. +Quando trabalhando com **Kubernetes** ou sistemas similares de gerenciamento de contêiner distribuído, usar seus mecanismos de rede internos permite que o único **balanceador de carga** que está escutando na **porta principal** transmita a comunicação (requests) para possivelmente **múltiplos contêineres** executando seu aplicativo. Cada um desses contêineres executando seu aplicativo normalmente teria **apenas um processo** (ex.: um processo Uvicorn executando seu aplicativo FastAPI). Todos seriam **contêineres idênticos**, executando a mesma coisa, mas cada um com seu próprio processo, memória, etc. Dessa forma, você aproveitaria a **paralelização** em **núcleos diferentes** da CPU, ou até mesmo em **máquinas diferentes**. -E o sistema de contêiner com o **balanceador de carga** iria **distribuir as solicitações** para cada um dos contêineres com seu aplicativo **em turnos**. Portanto, cada solicitação poderia ser tratada por um dos múltiplos **contêineres replicados** executando seu aplicativo. +E o sistema de contêiner com o **balanceador de carga** iria **distribuir os requests** para cada um dos contêineres com seu aplicativo **em turnos**. Portanto, cada request poderia ser tratado por um dos múltiplos **contêineres replicados** executando seu aplicativo. -E normalmente esse **balanceador de carga** seria capaz de lidar com solicitações que vão para *outros* aplicativos em seu cluster (por exemplo, para um domínio diferente, ou sob um prefixo de URL diferente), e transmitiria essa comunicação para os contêineres certos para *esse outro* aplicativo em execução em seu cluster. +E normalmente esse **balanceador de carga** seria capaz de lidar com requests que vão para *outros* aplicativos em seu cluster (por exemplo, para um domínio diferente, ou sob um prefixo de path de URL diferente), e transmitiria essa comunicação para os contêineres certos para *esse outro* aplicativo em execução em seu cluster. ### Um Processo por Contêiner { #one-process-per-container } @@ -544,7 +544,7 @@ Se você executar **um único processo por contêiner**, terá uma quantidade ma E então você pode definir esses mesmos limites e requisitos de memória em suas configurações para seu sistema de gerenciamento de contêineres (por exemplo, no **Kubernetes**). Dessa forma, ele poderá **replicar os contêineres** nas **máquinas disponíveis** levando em consideração a quantidade de memória necessária por eles e a quantidade disponível nas máquinas no cluster. -Se sua aplicação for **simples**, isso provavelmente **não será um problema**, e você pode não precisar especificar limites de memória rígidos. Mas se você estiver **usando muita memória** (por exemplo, com **modelos de aprendizado de máquina**), deve verificar quanta memória está consumindo e ajustar o **número de contêineres** que executa em **cada máquina** (e talvez adicionar mais máquinas ao seu cluster). +Se sua aplicação for **simples**, isso provavelmente **não será um problema**, e você pode não precisar especificar limites de memória rígidos. Mas se você estiver **usando muita memória** (por exemplo, com modelos de **Aprendizado de Máquina**), você deveria verificar quanta memória está consumindo e ajustar o **número de contêineres** que executa em **cada máquina** (e talvez adicionar mais máquinas ao seu cluster). Se você executar **múltiplos processos por contêiner**, deve garantir que o número de processos iniciados não **consuma mais memória** do que o disponível. @@ -572,7 +572,7 @@ Se você tiver uma configuração simples, com um **único contêiner** que ent Antes havia uma imagem oficial do FastAPI para Docker: [tiangolo/uvicorn-gunicorn-fastapi](https://github.com/tiangolo/uvicorn-gunicorn-fastapi-docker). Mas agora ela está descontinuada. ⛔️ -Você provavelmente **não** deve usar essa imagem base do Docker (ou qualquer outra semelhante). +Você provavelmente **não** deveria usar essa imagem base do Docker (ou qualquer outra semelhante). Se você está usando **Kubernetes** (ou outros) e já está definindo a **replicação** no nível do cluster, com vários **contêineres**. Nesses casos, é melhor **construir uma imagem do zero** como descrito acima: [Construir uma Imagem Docker para FastAPI](#build-a-docker-image-for-fastapi). diff --git a/docs/pt/docs/deployment/https.md b/docs/pt/docs/deployment/https.md index 0e8ae2ba6..d89e0bbff 100644 --- a/docs/pt/docs/deployment/https.md +++ b/docs/pt/docs/deployment/https.md @@ -10,31 +10,31 @@ Se você está com pressa ou não se importa, continue com as seções seguintes /// -Para aprender o básico de HTTPS do ponto de vista do consumidor, verifique [https://howhttps.works/](https://howhttps.works/). - -Agora, a partir de uma perspectiva do desenvolvedor, aqui estão algumas coisas para ter em mente ao pensar em HTTPS: - -* Para HTTPS, o servidor precisa ter "certificados" gerados por um terceiro. - * Esses certificados são na verdade adquiridos de um terceiro, eles não são simplesmente "gerados". -* Certificados têm um tempo de vida. - * Eles expiram. - * E então eles precisam ser renovados, adquirindo-os novamente de um terceiro. -* A criptografia da conexão acontece no nível TCP. - * Essa é uma camada abaixo do HTTP. - * Portanto, o manuseio do certificado e da criptografia é feito antes do HTTP. -* O TCP não sabe sobre "domínios". Apenas sobre endereços IP. - * As informações sobre o domínio específico solicitado vão nos dados HTTP. -* Os certificados HTTPS “certificam” um determinado domínio, mas o protocolo e a encriptação acontecem ao nível do TCP, antes de sabermos de que domínio se trata. -* Por padrão, isso significa que você só pode ter um certificado HTTPS por endereço IP. +Para **aprender o básico de HTTPS**, do ponto de vista do consumidor, verifique [https://howhttps.works/](https://howhttps.works/). + +Agora, a partir de uma **perspectiva do desenvolvedor**, aqui estão algumas coisas para ter em mente ao pensar em HTTPS: + +* Para HTTPS, **o servidor** precisa **ter "certificados"** gerados por um **terceiro**. + * Esses certificados são na verdade **adquiridos** de um terceiro, eles não são simplesmente "gerados". +* Certificados têm um **tempo de vida**. + * Eles **expiram**. + * E então eles precisam ser **renovados**, **adquiridos novamente** de um terceiro. +* A criptografia da conexão acontece no **nível TCP**. + * Essa é uma camada **abaixo do HTTP**. + * Portanto, o manuseio do **certificado e da criptografia** é feito **antes do HTTP**. +* **O TCP não sabe sobre "domínios"**. Apenas sobre endereços IP. + * As informações sobre o **domínio específico** solicitado vão nos **dados HTTP**. +* Os **certificados HTTPS** “certificam” um **determinado domínio**, mas o protocolo e a encriptação acontecem ao nível do TCP, **antes de sabermos** de que domínio se trata. +* **Por padrão**, isso significa que você só pode ter **um certificado HTTPS por endereço IP**. * Não importa o tamanho do seu servidor ou quão pequeno cada aplicativo que você tem nele possa ser. - * No entanto, existe uma solução para isso. -* Há uma extensão para o protocolo TLS (aquele que lida com a criptografia no nível TCP, antes do HTTP) chamada [SNI](https://en.wikipedia.org/wiki/Server_Name_Indication). - * Esta extensão SNI permite que um único servidor (com um único endereço IP) tenha vários certificados HTTPS e atenda a vários domínios / aplicativos HTTPS. - * Para que isso funcione, um único componente (programa) em execução no servidor, ouvindo no endereço IP público, deve ter todos os certificados HTTPS no servidor. -* Depois de obter uma conexão segura, o protocolo de comunicação ainda é HTTP. - * Os conteúdos são criptografados, embora sejam enviados com o protocolo HTTP. + * No entanto, existe uma **solução** para isso. +* Há uma **extensão** para o protocolo **TLS** (aquele que lida com a criptografia no nível TCP, antes do HTTP) chamada **[SNI](https://en.wikipedia.org/wiki/Server_Name_Indication)**. + * Esta extensão SNI permite que um único servidor (com um **único endereço IP**) tenha **vários certificados HTTPS** e atenda a **vários domínios / aplicativos HTTPS**. + * Para que isso funcione, um **único** componente (programa) em execução no servidor, ouvindo no **endereço IP público**, deve ter **todos os certificados HTTPS** no servidor. +* **Depois** de obter uma conexão segura, o protocolo de comunicação ainda é **HTTP**. + * Os conteúdos são **criptografados**, embora sejam enviados com o **protocolo HTTP**. -É uma prática comum ter um programa/servidor HTTP em execução no servidor (máquina, host, etc.) e gerenciar todas as partes HTTPS: recebendo as requisições HTTPS encriptadas, enviando as solicitações HTTP descriptografadas para o aplicativo HTTP real em execução no mesmo servidor (a aplicação FastAPI, neste caso), pegar a resposta HTTP do aplicativo, criptografá-la usando o certificado HTTPS apropriado e enviá-la de volta ao cliente usando HTTPS. Este servidor é frequentemente chamado de [Proxy de Terminação TLS](https://en.wikipedia.org/wiki/TLS_termination_proxy). +É uma prática comum ter **um programa/servidor HTTP** em execução no servidor (máquina, host, etc.) e **gerenciar todas as partes HTTPS**: recebendo as **requisições HTTPS encriptadas**, enviando as **solicitações HTTP descriptografadas** para o aplicativo HTTP real em execução no mesmo servidor (a aplicação **FastAPI**, neste caso), pegar a **resposta HTTP** do aplicativo, **criptografá-la** usando o **certificado HTTPS** apropriado e enviá-la de volta ao cliente usando **HTTPS**. Este servidor é frequentemente chamado de **[Proxy de Terminação TLS](https://en.wikipedia.org/wiki/TLS_termination_proxy)**. Algumas das opções que você pode usar como Proxy de Terminação TLS são: @@ -45,17 +45,17 @@ Algumas das opções que você pode usar como Proxy de Terminação TLS são: ## Let's Encrypt { #lets-encrypt } -Antes de Let's Encrypt, esses certificados HTTPS eram vendidos por terceiros confiáveis. +Antes de Let's Encrypt, esses **certificados HTTPS** eram vendidos por terceiros confiáveis. O processo de aquisição de um desses certificados costumava ser complicado, exigia bastante papelada e os certificados eram bastante caros. -Mas então o [Let's Encrypt](https://letsencrypt.org/) foi criado. +Mas então o **[Let's Encrypt](https://letsencrypt.org/)** foi criado. -Ele é um projeto da Linux Foundation que fornece certificados HTTPS gratuitamente. De forma automatizada. Esses certificados usam toda a segurança criptográfica padrão e têm vida curta (cerca de 3 meses), então a segurança é, na verdade, melhor por causa do seu lifespan reduzido. +Ele é um projeto da Linux Foundation. Ele fornece **certificados HTTPS gratuitamente**, de forma automatizada. Esses certificados usam toda a segurança criptográfica padrão e têm vida curta (cerca de 3 meses), então a **segurança é, na verdade, melhor** por causa do seu lifespan reduzido. Os domínios são verificados com segurança e os certificados são gerados automaticamente. Isso também permite automatizar a renovação desses certificados. -A ideia é automatizar a aquisição e renovação desses certificados, para que você tenha HTTPS seguro, de graça e para sempre. +A ideia é automatizar a aquisição e renovação desses certificados, para que você tenha **HTTPS seguro, de graça e para sempre**. ## HTTPS para Desenvolvedores { #https-for-developers } @@ -63,11 +63,11 @@ Aqui está um exemplo de como uma API HTTPS poderia ser estruturada, passo a pas ### Nome do domínio { #domain-name } -A etapa inicial provavelmente seria adquirir algum nome de domínio. Então, você iria configurá-lo em um servidor DNS (possivelmente no mesmo provedor em nuvem). +A etapa inicial provavelmente seria **adquirir** algum **nome de domínio**. Então, você iria configurá-lo em um servidor DNS (possivelmente no mesmo provedor em nuvem). -Você provavelmente usaria um servidor em nuvem (máquina virtual) ou algo parecido, e ele teria um fixo Endereço IP público. +Você provavelmente usaria um servidor em nuvem (máquina virtual) ou algo parecido, e ele teria um **endereço IP público** fixo. -No(s) servidor(es) DNS, você configuraria um registro (um `A record`) para apontar seu domínio para o endereço IP público do seu servidor. +No(s) servidor(es) DNS, você configuraria um registro (um "`A record`") para apontar **seu domínio** para o **endereço IP público do seu servidor**. Você provavelmente fará isso apenas uma vez, na primeira vez em que tudo estiver sendo configurado. @@ -81,120 +81,120 @@ Essa parte do Nome do Domínio se dá muito antes do HTTPS, mas como tudo depend Agora vamos focar em todas as partes que realmente fazem parte do HTTPS. -Primeiro, o navegador iria verificar com os servidores DNS qual o IP do domínio, nesse caso, `someapp.example.com`. +Primeiro, o navegador iria verificar com os **servidores DNS** qual o **IP do domínio**, nesse caso, `someapp.example.com`. -Os servidores DNS iriam informar o navegador para utilizar algum endereço IP específico. Esse seria o endereço IP público em uso no seu servidor, que você configurou nos servidores DNS. +Os servidores DNS iriam informar o navegador para utilizar algum **endereço IP** específico. Esse seria o endereço IP público em uso no seu servidor, que você configurou nos servidores DNS. ### Início do Handshake TLS { #tls-handshake-start } -O navegador então irá comunicar-se com esse endereço IP na porta 443 (a porta HTTPS). +O navegador então irá comunicar-se com esse endereço IP na **porta 443** (a porta HTTPS). A primeira parte dessa comunicação é apenas para estabelecer a conexão entre o cliente e o servidor e para decidir as chaves criptográficas a serem utilizadas, etc. -Esse interação entre o cliente e o servidor para estabelecer uma conexão TLS é chamada de Handshake TLS. +Esse interação entre o cliente e o servidor para estabelecer uma conexão TLS é chamada de **Handshake TLS**. ### TLS com a Extensão SNI { #tls-with-sni-extension } -Apenas um processo no servidor pode se conectar a uma porta em um endereço IP. Poderiam existir outros processos conectados em outras portas desse mesmo endereço IP, mas apenas um para cada combinação de endereço IP e porta. +**Apenas um processo** no servidor pode se conectar a uma **porta** em um **endereço IP**. Poderiam existir outros processos conectados em outras portas desse mesmo endereço IP, mas apenas um para cada combinação de endereço IP e porta. TLS (HTTPS) usa a porta `443` por padrão. Então essa é a porta que precisamos. -Como apenas um único processo pode se comunicar com essa porta, o processo que faria isso seria o Proxy de Terminação TLS. +Como apenas um único processo pode se comunicar com essa porta, o processo que faria isso seria o **Proxy de Terminação TLS**. -O Proxy de Terminação TLS teria acesso a um ou mais certificados TLS (certificados HTTPS). +O Proxy de Terminação TLS teria acesso a um ou mais **certificados TLS** (certificados HTTPS). -Utilizando a extensão SNI discutida acima, o Proxy de Terminação TLS iria checar qual dos certificados TLS (HTTPS) disponíveis deve ser usado para essa conexão, utilizando o que corresponda ao domínio esperado pelo cliente. +Utilizando a **extensão SNI** discutida acima, o Proxy de Terminação TLS iria checar qual dos certificados TLS (HTTPS) disponíveis deve ser usado para essa conexão, utilizando o que corresponda ao domínio esperado pelo cliente. Nesse caso, ele usaria o certificado para `someapp.example.com`. -O cliente já confia na entidade que gerou o certificado TLS (nesse caso, o Let's Encrypt, mas veremos sobre isso mais tarde), então ele pode verificar que o certificado é válido. +O cliente já **confia** na entidade que gerou o certificado TLS (nesse caso, o Let's Encrypt, mas veremos sobre isso mais tarde), então ele pode **verificar** que o certificado é válido. -Então, utilizando o certificado, o cliente e o Proxy de Terminação TLS decidem como encriptar o resto da comunicação TCP. Isso completa a parte do Handshake TLS. +Então, utilizando o certificado, o cliente e o Proxy de Terminação TLS **decidem como encriptar** o resto da **comunicação TCP**. Isso completa a parte do **Handshake TLS**. -Após isso, o cliente e o servidor possuem uma conexão TCP encriptada, que é provida pelo TLS. E então eles podem usar essa conexão para começar a comunicação HTTP propriamente dita. +Após isso, o cliente e o servidor possuem uma **conexão TCP encriptada**, que é provida pelo TLS. E então eles podem usar essa conexão para começar a **comunicação HTTP** propriamente dita. -E isso resume o que é HTTPS, apenas HTTP simples dentro de uma conexão TLS segura em vez de uma conexão TCP pura (não encriptada). +E isso resume o que é **HTTPS**, apenas **HTTP** simples dentro de uma **conexão TLS segura** em vez de uma conexão TCP pura (não encriptada). /// tip | Dica -Percebe que a encriptação da comunicação acontece no nível do TCP, não no nível do HTTP. +Perceba que a encriptação da comunicação acontece no **nível do TCP**, não no nível do HTTP. /// ### Solicitação HTTPS { #https-request } -Agora que o cliente e servidor (especialmente o navegador e o Proxy de Terminação TLS) possuem uma conexão TCP encriptada, eles podem iniciar a comunicação HTTP. +Agora que o cliente e servidor (especialmente o navegador e o Proxy de Terminação TLS) possuem uma **conexão TCP encriptada**, eles podem iniciar a **comunicação HTTP**. -Então, o cliente envia uma solicitação HTTPS. Que é apenas uma solicitação HTTP sobre uma conexão TLS encriptada. +Então, o cliente envia uma **solicitação HTTPS**. Que é apenas uma solicitação HTTP sobre uma conexão TLS encriptada. ### Desencripte a Solicitação { #decrypt-the-request } -O Proxy de Terminação TLS então usaria a encriptação combinada para desencriptar a solicitação, e transmitiria a solicitação básica (desencriptada) para o processo executando a aplicação (por exemplo, um processo com Uvicorn executando a aplicação FastAPI). +O Proxy de Terminação TLS então usaria a encriptação combinada para **desencriptar a solicitação**, e transmitiria a **solicitação HTTP básica (desencriptada)** para o processo executando a aplicação (por exemplo, um processo com Uvicorn executando a aplicação FastAPI). ### Resposta HTTP { #http-response } -A aplicação processaria a solicitação e retornaria uma resposta HTTP básica (não encriptada) para o Proxy de Terminação TLS. +A aplicação processaria a solicitação e retornaria uma **resposta HTTP básica (não encriptada)** para o Proxy de Terminação TLS. ### Resposta HTTPS { #https-response } -O Proxy de Terminação TLS iria encriptar a resposta utilizando a criptografia combinada anteriormente (que foi definida com o certificado para `someapp.example.com`), e devolveria para o navegador. +O Proxy de Terminação TLS iria **encriptar a resposta** utilizando a criptografia combinada anteriormente (que foi definida com o certificado para `someapp.example.com`), e devolveria para o navegador. -No próximo passo, o navegador verifica que a resposta é válida e encriptada com a chave criptográfica correta, etc. E depois desencripta a resposta e a processa. +No próximo passo, o navegador verifica que a resposta é válida e encriptada com a chave criptográfica correta, etc. E depois **desencripta a resposta** e a processa. -O cliente (navegador) saberá que a resposta vem do servidor correto por que ela usa a criptografia que foi combinada entre eles usando o certificado HTTPS anterior. +O cliente (navegador) saberá que a resposta vem do servidor correto por que ela usa a criptografia que foi combinada entre eles usando o **certificado HTTPS** anterior. ### Múltiplas Aplicações { #multiple-applications } -Podem existir múltiplas aplicações em execução no mesmo servidor (ou servidores), por exemplo: outras APIs ou um banco de dados. +Podem existir **múltiplas aplicações** em execução no mesmo servidor (ou servidores), por exemplo: outras APIs ou um banco de dados. -Apenas um processo pode estar vinculado a um IP e porta (o Proxy de Terminação TLS, por exemplo), mas outras aplicações/processos também podem estar em execução no(s) servidor(es), desde que não tentem usar a mesma combinação de IP público e porta. +Apenas um processo pode estar vinculado a um IP e porta (o Proxy de Terminação TLS, por exemplo), mas outras aplicações/processos também podem estar em execução no(s) servidor(es), desde que não tentem usar a mesma **combinação de IP público e porta**. -Dessa forma, o Proxy de Terminação TLS pode gerenciar o HTTPS e os certificados de múltiplos domínios, para múltiplas aplicações, e então transmitir as requisições para a aplicação correta em cada caso. +Dessa forma, o Proxy de Terminação TLS pode gerenciar o HTTPS e os certificados de **múltiplos domínios**, para múltiplas aplicações, e então transmitir as requisições para a aplicação correta em cada caso. ### Renovação de Certificados { #certificate-renewal } -Em algum momento futuro, cada certificado irá expirar (aproximadamente 3 meses após a aquisição). +Em algum momento futuro, cada certificado irá **expirar** (aproximadamente 3 meses após a aquisição). -E então, haverá outro programa (em alguns casos pode ser o próprio Proxy de Terminação TLS) que irá interagir com o Let's Encrypt e renovar o(s) certificado(s). +E então, haverá outro programa (em alguns casos é outro programa, em alguns casos pode ser o próprio Proxy de Terminação TLS) que irá interagir com o Let's Encrypt e renovar o(s) certificado(s). -Os certificados TLS são associados com um nome de domínio, e não a um endereço IP. +Os **certificados TLS** são **associados com um nome de domínio**, e não a um endereço IP. -Então para renovar os certificados, o programa de renovação precisa provar para a autoridade (Let's Encrypt) que ele realmente "possui" e controla esse domínio. +Então para renovar os certificados, o programa de renovação precisa **provar** para a autoridade (Let's Encrypt) que ele realmente **"possui" e controla esse domínio**. Para fazer isso, e acomodar as necessidades de diferentes aplicações, existem diferentes opções para esse programa. Algumas escolhas populares são: -* Modificar alguns registros DNS +* **Modificar alguns registros DNS**. * Para isso, o programa de renovação precisa ter suporte às APIs do provedor DNS, então, dependendo do provedor DNS que você utilize, isso pode ou não ser uma opção viável. -* Executar como um servidor (ao menos durante o processo de aquisição do certificado) no endereço IP público associado com o domínio. +* **Executar como um servidor** (ao menos durante o processo de aquisição do certificado) no endereço IP público associado com o domínio. * Como dito anteriormente, apenas um processo pode estar ligado a uma porta e IP específicos. * Essa é uma dos motivos que fazem utilizar o mesmo Proxy de Terminação TLS para gerenciar a renovação de certificados ser tão útil. * Caso contrário, você pode ter que parar a execução do Proxy de Terminação TLS momentaneamente, inicializar o programa de renovação para adquirir os certificados, depois configurá-los com o Proxy de Terminação TLS, e então reiniciar o Proxy de Terminação TLS. Isso não é o ideal, já que sua(s) aplicação(ões) não vão estar disponíveis enquanto o Proxy de Terminação TLS estiver desligado. -Todo esse processo de renovação, enquanto o aplicativo ainda funciona, é uma das principais razões para preferir um sistema separado para gerenciar HTTPS com um Proxy de Terminação TLS em vez de usar os certificados TLS no servidor da aplicação diretamente (e.g. com o Uvicorn). +Todo esse processo de renovação, enquanto o aplicativo ainda funciona, é uma das principais razões para preferir um **sistema separado para gerenciar HTTPS** com um Proxy de Terminação TLS em vez de usar os certificados TLS no servidor da aplicação diretamente (e.g. com o Uvicorn). ## Cabeçalhos encaminhados por Proxy { #proxy-forwarded-headers } -Ao usar um proxy para lidar com HTTPS, seu servidor de aplicação (por exemplo, Uvicorn via FastAPI CLI) não sabe nada sobre o processo de HTTPS; ele se comunica com HTTP simples com o Proxy de Terminação TLS. +Ao usar um proxy para lidar com HTTPS, seu **servidor de aplicação** (por exemplo, Uvicorn via FastAPI CLI) não sabe nada sobre o processo de HTTPS; ele se comunica com HTTP simples com o **Proxy de Terminação TLS**. -Esse proxy normalmente define alguns cabeçalhos HTTP dinamicamente antes de transmitir a requisição para o servidor de aplicação, para informar ao servidor de aplicação que a requisição está sendo encaminhada pelo proxy. +Esse **proxy** normalmente define alguns cabeçalhos HTTP dinamicamente antes de transmitir a requisição para o **servidor de aplicação**, para informar ao servidor de aplicação que a requisição está sendo **encaminhada** pelo proxy. /// note | Detalhes Técnicos @@ -206,11 +206,11 @@ Os cabeçalhos do proxy são: /// -No entanto, como o servidor de aplicação não sabe que está atrás de um proxy confiável, por padrão ele não confiaria nesses cabeçalhos. +No entanto, como o **servidor de aplicação** não sabe que está atrás de um **proxy** confiável, por padrão ele não confiaria nesses cabeçalhos. -Mas você pode configurar o servidor de aplicação para confiar nos cabeçalhos encaminhados enviados pelo proxy. Se você estiver usando o FastAPI CLI, pode usar a opção de CLI `--forwarded-allow-ips` para dizer de quais IPs ele deve confiar nesses cabeçalhos encaminhados. +Mas você pode configurar o **servidor de aplicação** para confiar nos cabeçalhos *encaminhados* enviados pelo **proxy**. Se você estiver usando o FastAPI CLI, pode usar a *Opção de CLI* `--forwarded-allow-ips` para dizer de quais IPs ele deve confiar nesses cabeçalhos *encaminhados*. -Por exemplo, se o servidor de aplicação só estiver recebendo comunicação do proxy confiável, você pode defini-lo como `--forwarded-allow-ips="*"` para fazê-lo confiar em todos os IPs de entrada, já que ele só receberá requisições de seja lá qual for o IP usado pelo proxy. +Por exemplo, se o **servidor de aplicação** só estiver recebendo comunicação do **proxy** confiável, você pode defini-lo como `--forwarded-allow-ips="*"` para fazê-lo confiar em todos os IPs de entrada, já que ele só receberá requisições de seja lá qual for o IP usado pelo **proxy**. Dessa forma, a aplicação seria capaz de saber qual é sua própria URL pública, se está usando HTTPS, o domínio, etc. @@ -224,8 +224,8 @@ Você pode saber mais sobre isso na documentação em [Atrás de um Proxy - Habi ## Recapitulando { #recap } -Possuir HTTPS habilitado na sua aplicação é bastante importante, e até crítico na maioria dos casos. A maior parte do esforço que você tem que colocar sobre o HTTPS como desenvolvedor está em entender esses conceitos e como eles funcionam. +Possuir **HTTPS** habilitado na sua aplicação é bastante importante, e até **crítico** na maioria dos casos. A maior parte do esforço que você tem que colocar sobre o HTTPS como desenvolvedor está em **entender esses conceitos** e como eles funcionam. -Mas uma vez que você saiba o básico de HTTPS para desenvolvedores, você pode combinar e configurar diferentes ferramentas facilmente para gerenciar tudo de uma forma simples. +Mas uma vez que você saiba o básico de **HTTPS para desenvolvedores**, você pode combinar e configurar diferentes ferramentas facilmente para gerenciar tudo de uma forma simples. -Em alguns dos próximos capítulos, eu mostrarei para você vários exemplos concretos de como configurar o HTTPS para aplicações FastAPI. 🔒 +Em alguns dos próximos capítulos, eu mostrarei para você vários exemplos concretos de como configurar o **HTTPS** para aplicações **FastAPI**. 🔒 diff --git a/docs/pt/docs/deployment/manually.md b/docs/pt/docs/deployment/manually.md index 8f34e37d0..0c8db162e 100644 --- a/docs/pt/docs/deployment/manually.md +++ b/docs/pt/docs/deployment/manually.md @@ -53,7 +53,7 @@ A principal coisa que você precisa para executar uma aplicação **FastAPI** (o Existem diversas alternativas, incluindo: * [Uvicorn](https://www.uvicorn.dev/): um servidor ASGI de alta performance. -* [Hypercorn](https://hypercorn.readthedocs.io/): um servidor ASGI compatível com HTTP/2, Trio e outros recursos. +* [Hypercorn](https://hypercorn.readthedocs.io/): um servidor ASGI compatível com HTTP/2, Trio e outras funcionalidades. * [Daphne](https://github.com/django/daphne): servidor ASGI construído para Django Channels. * [Granian](https://github.com/emmett-framework/granian): um servidor HTTP Rust para aplicações Python. @@ -136,7 +136,7 @@ Uvicorn e outros servidores suportam a opção `--reload` que é útil durante o A opção `--reload` consome muito mais recursos, é mais instável, etc. -Ela ajuda muito durante o **desenvolvimento**, mas você **não deve** usá-la em **produção**. +Ela ajuda muito durante o **desenvolvimento**, mas você **não deveria** usá-la em **produção**. /// diff --git a/docs/pt/docs/editor-support.md b/docs/pt/docs/editor-support.md index 7eedd3908..de02c5d7c 100644 --- a/docs/pt/docs/editor-support.md +++ b/docs/pt/docs/editor-support.md @@ -1,6 +1,6 @@ # Suporte a Editores { #editor-support } -A [FastAPI Extension](https://marketplace.visualstudio.com/items?itemName=FastAPILabs.fastapi-vscode) oficial melhora seu fluxo de trabalho de desenvolvimento com descoberta e navegação de *operação de rota*, além de implantação no FastAPI Cloud e transmissão ao vivo de logs. +A [FastAPI Extension](https://marketplace.visualstudio.com/items?itemName=FastAPILabs.fastapi-vscode) oficial melhora seu fluxo de trabalho de desenvolvimento FastAPI com descoberta e navegação de *operação de rota*, além de implantação no FastAPI Cloud e transmissão ao vivo de logs. Para mais detalhes sobre a extensão, consulte o README no [repositório do GitHub](https://github.com/fastapi/fastapi-vscode). diff --git a/docs/pt/docs/environment-variables.md b/docs/pt/docs/environment-variables.md index a464becee..ebf037faa 100644 --- a/docs/pt/docs/environment-variables.md +++ b/docs/pt/docs/environment-variables.md @@ -289,7 +289,7 @@ Essas informações serão úteis ao aprender sobre [Ambientes Virtuais](virtual ## Conclusão { #conclusion } -Com isso, você deve ter uma compreensão básica do que são **variáveis ​​de ambiente** e como usá-las em Python. +Com isso, você deveria ter uma compreensão básica do que são **variáveis ​​de ambiente** e como usá-las em Python. Você também pode ler mais sobre elas na [Wikipedia para Variáveis ​​de Ambiente](https://en.wikipedia.org/wiki/Environment_variable). diff --git a/docs/pt/docs/features.md b/docs/pt/docs/features.md index 8b14c5fea..846bc7f94 100644 --- a/docs/pt/docs/features.md +++ b/docs/pt/docs/features.md @@ -1,15 +1,15 @@ -# Recursos { #features } +# Funcionalidades { #features } -## Recursos do FastAPI { #fastapi-features } +## Funcionalidades do FastAPI { #fastapi-features } **FastAPI** te oferece o seguinte: ### Baseado em padrões abertos { #based-on-open-standards } -* [**OpenAPI**](https://github.com/OAI/OpenAPI-Specification) para criação de APIs, incluindo declarações de caminho operações, parâmetros, requisições de corpo, segurança etc. +* [**OpenAPI**](https://github.com/OAI/OpenAPI-Specification) para criação de APIs, incluindo declarações de path operações, parâmetros, corpos de requisição, segurança etc. * Documentação automática de modelos de dados com [**JSON Schema**](https://json-schema.org/) (já que o OpenAPI em si é baseado no JSON Schema). * Projetado em torno desses padrões, após um estudo meticuloso. Em vez de uma camada improvisada por cima. -* Isso também permite o uso de **geração de código do cliente** automaticamente em muitas linguagens. +* Isso também permite o uso de **geração de código de cliente** automaticamente em muitas linguagens. ### Documentação automática { #automatic-docs } @@ -75,7 +75,7 @@ Passe as chaves e valores do dicionário `second_user_data` diretamente como arg Todo o framework foi projetado para ser fácil e intuitivo de usar, todas as decisões foram testadas em vários editores antes do início do desenvolvimento, para garantir a melhor experiência de desenvolvimento. -Na pesquisa de desenvolvedores Python, ficou claro [que um dos recursos mais utilizados é o "preenchimento automático"](https://www.jetbrains.com/research/python-developers-survey-2017/#tools-and-features). +Nas pesquisas de desenvolvedores Python, ficou claro [que uma das funcionalidades mais utilizadas é o "preenchimento automático"](https://www.jetbrains.com/research/python-developers-survey-2017/#tools-and-features). Todo o framework **FastAPI** é feito para satisfazer isso. O preenchimento automático funciona em todos os lugares. @@ -97,9 +97,9 @@ Sem a necessidade de digitar nomes de chaves erroneamente, ir e voltar entre doc ### Breve { #short } -Há **padrões** sensíveis para tudo, com configurações adicionais em todos os lugares. Todos os parâmetros podem ser regulados para fazer o que você precisa e para definir a API que você necessita. +Há **valores padrão** sensíveis para tudo, com configurações adicionais em todos os lugares. Todos os parâmetros podem ser regulados para fazer o que você precisa e para definir a API que você necessita. -Por padrão, tudo **"simplesmente funciona"**. +Mas, por padrão, tudo **"simplesmente funciona"**. ### Validação { #validation } @@ -121,7 +121,7 @@ Toda a validação é controlada pelo robusto e bem estabelecido **Pydantic**. Segurança e autenticação integradas. Sem nenhum compromisso com bancos de dados ou modelos de dados. -Todos os esquemas de seguranças definidos no OpenAPI, incluindo: +Todos os esquemas de segurança definidos no OpenAPI, incluindo: * HTTP Basic. * **OAuth2** (também com **tokens JWT**). Confira o tutorial em [OAuth2 com JWT](tutorial/security/oauth2-jwt.md). @@ -130,9 +130,9 @@ Todos os esquemas de seguranças definidos no OpenAPI, incluindo: * parâmetros da Query. * Cookies etc. -Além disso, todos os recursos de segurança do Starlette (incluindo **cookies de sessão**). +Além disso, todas as funcionalidades de segurança do Starlette (incluindo **cookies de sessão**). -Tudo construído como ferramentas e componentes reutilizáveis que são fáceis de integrar com seus sistemas, armazenamento de dados, banco de dados relacionais e não-relacionais etc. +Tudo construído como ferramentas e componentes reutilizáveis que são fáceis de integrar com seus sistemas, armazenamentos de dados, bancos de dados relacionais e NoSQL etc. ### Injeção de dependência { #dependency-injection } @@ -142,40 +142,40 @@ FastAPI inclui um sistema de @@ -52,9 +52,9 @@ $ fastapi dev
-É **ALTAMENTE recomendado** que você escreva ou copie o código, edite-o e rode-o localmente. +É **ALTAMENTE recomendado** que você escreva ou copie o código, edite-o e execute-o localmente. -Usá-lo em seu editor é o que realmente te mostra os benefícios do FastAPI, ver quão pouco código você tem que escrever, todas as conferências de tipo, preenchimento automático, etc. +Usá-lo em seu editor é o que realmente mostra os benefícios do FastAPI, vendo quão pouco código você tem que escrever, todas as verificações de tipo, preenchimento automático, etc. --- @@ -94,7 +94,7 @@ O FastAPI tem uma [extensão oficial para o VS Code](https://marketplace.visuals Há também um **Guia Avançado de Usuário** que você pode ler após esse **Tutorial - Guia de Usuário**. -O **Guia Avançado de Usuário** constrói sobre esse, usa os mesmos conceitos e te ensina algumas funcionalidades extras. +O **Guia Avançado de Usuário** constrói sobre esse, usa os mesmos conceitos e ensina algumas funcionalidades extras. Mas você deveria ler primeiro o **Tutorial - Guia de Usuário** (que você está lendo agora). diff --git a/docs/pt/docs/tutorial/metadata.md b/docs/pt/docs/tutorial/metadata.md index 022e622ca..c6f76d215 100644 --- a/docs/pt/docs/tutorial/metadata.md +++ b/docs/pt/docs/tutorial/metadata.md @@ -11,7 +11,7 @@ Você pode definir os seguintes campos que são usados na especificação OpenAP | `title` | `str` | O título da API. | | `summary` | `str` | Um breve resumo da API. Disponível desde OpenAPI 3.1.0, FastAPI 0.99.0. | | `description` | `str` | Uma breve descrição da API. Pode usar Markdown. | -| `version` | `string` | A versão da API. Esta é a versão da sua aplicação, não do OpenAPI. Por exemplo, `2.5.0`. | +| `version` | `str` | A versão da API. Esta é a versão da sua aplicação, não do OpenAPI. Por exemplo, `2.5.0`. | | `terms_of_service` | `str` | Uma URL para os Termos de Serviço da API. Se fornecido, deve ser uma URL. | | `contact` | `dict` | As informações de contato da API exposta. Pode conter vários campos.
Campos de contact
ParâmetroTipoDescrição
namestrO nome identificador da pessoa/organização de contato.
urlstrA URL que aponta para as informações de contato. DEVE estar no formato de uma URL.
emailstrO endereço de e-mail da pessoa/organização de contato. DEVE estar no formato de um endereço de e-mail.
| | `license_info` | `dict` | As informações de licença para a API exposta. Ela pode conter vários campos.
Campos de license_info
ParâmetroTipoDescrição
namestrOBRIGATÓRIO (se um license_info for definido). O nome da licença usada para a API.
identifierstrUma expressão de licença [SPDX](https://spdx.org/licenses/) para a API. O campo identifier é mutuamente exclusivo do campo url. Disponível desde OpenAPI 3.1.0, FastAPI 0.99.0.
urlstrUma URL para a licença usada para a API. DEVE estar no formato de uma URL.
| @@ -80,7 +80,7 @@ Leia mais sobre tags em [Configuração de operação de rota](path-operation-co /// -### Cheque os documentos { #check-the-docs } +### Verifique a documentação { #check-the-docs } Agora, se você verificar a documentação, ela exibirá todos os metadados adicionais: diff --git a/docs/pt/docs/tutorial/path-operation-configuration.md b/docs/pt/docs/tutorial/path-operation-configuration.md index 3559667bd..cce159fa6 100644 --- a/docs/pt/docs/tutorial/path-operation-configuration.md +++ b/docs/pt/docs/tutorial/path-operation-configuration.md @@ -40,7 +40,7 @@ Eles serão adicionados ao esquema OpenAPI e usados pelas interfaces de document ### Tags com Enums { #tags-with-enums } -Se você tem uma grande aplicação, você pode acabar acumulando **várias tags**, e você gostaria de ter certeza de que você sempre usa a ** mesma tag** para *operações de rota* relacionadas. +Se você tem uma grande aplicação, você pode acabar acumulando **várias tags**, e você gostaria de ter certeza de que você sempre usa a **mesma tag** para *operações de rota* relacionadas. Nestes casos, pode fazer sentido armazenar as tags em um `Enum`. diff --git a/docs/pt/docs/tutorial/query-params-str-validations.md b/docs/pt/docs/tutorial/query-params-str-validations.md index fe703c624..d37db2875 100644 --- a/docs/pt/docs/tutorial/query-params-str-validations.md +++ b/docs/pt/docs/tutorial/query-params-str-validations.md @@ -18,7 +18,7 @@ Ter `str | None` permitirá que seu editor lhe ofereça melhor suporte e detecte ## Validação adicional { #additional-validation } -Vamos impor que, embora `q` seja opcional, sempre que for fornecido, seu comprimento não exceda 50 caracteres. +Vamos impor que, embora `q` seja opcional, sempre que for fornecido, **seu comprimento não exceda 50 caracteres**. ### Importe `Query` e `Annotated` { #import-query-and-annotated } @@ -69,19 +69,19 @@ Agora que temos esse `Annotated` onde podemos colocar mais informações (neste Perceba que o valor padrão continua sendo `None`, então o parâmetro ainda é opcional. -Mas agora, com `Query(max_length=50)` dentro de `Annotated`, estamos dizendo ao FastAPI que queremos validação adicional para este valor, queremos que tenha no máximo 50 caracteres. 😎 +Mas agora, com `Query(max_length=50)` dentro de `Annotated`, estamos dizendo ao FastAPI que queremos **validação adicional** para este valor, queremos que tenha no máximo 50 caracteres. 😎 /// tip | Dica -Aqui estamos usando `Query()` porque este é um parâmetro de consulta. Mais adiante veremos outros como `Path()`, `Body()`, `Header()` e `Cookie()`, que também aceitam os mesmos argumentos que `Query()`. +Aqui estamos usando `Query()` porque este é um **parâmetro de consulta**. Mais adiante veremos outros como `Path()`, `Body()`, `Header()` e `Cookie()`, que também aceitam os mesmos argumentos que `Query()`. /// Agora o FastAPI vai: -* Validar os dados garantindo que o comprimento máximo seja de 50 caracteres -* Mostrar um erro claro para o cliente quando os dados não forem válidos -* Documentar o parâmetro na operação de rota do esquema OpenAPI (então ele aparecerá na UI de docs automática) +* **Validar** os dados garantindo que o comprimento máximo seja de 50 caracteres +* Mostrar um **erro claro** para o cliente quando os dados não forem válidos +* **Documentar** o parâmetro na *operação de rota* do esquema OpenAPI (então ele aparecerá na **UI de documentação automática**) ## Alternativa (antiga): `Query` como valor padrão { #alternative-old-query-as-the-default-value } @@ -120,7 +120,7 @@ Então, podemos passar mais parâmetros para `Query`. Neste caso, o parâmetro ` q: str | None = Query(default=None, max_length=50) ``` -Isso validará os dados, mostrará um erro claro quando os dados não forem válidos e documentará o parâmetro na operação de rota do esquema OpenAPI. +Isso validará os dados, mostrará um erro claro quando os dados não forem válidos e documentará o parâmetro na *operação de rota* do esquema OpenAPI. ### `Query` como valor padrão ou em `Annotated` { #query-as-the-default-value-or-in-annotated } @@ -150,13 +150,13 @@ q: str = Query(default="rick") ### Vantagens de `Annotated` { #advantages-of-annotated } -Usar `Annotated` é recomendado em vez do valor padrão nos parâmetros da função, é melhor por vários motivos. 🤓 +**Usar `Annotated` é recomendado** em vez do valor padrão nos parâmetros da função, é **melhor** por vários motivos. 🤓 -O valor padrão do parâmetro da função é o valor padrão real, isso é mais intuitivo com Python em geral. 😌 +O valor **padrão** do **parâmetro da função** é o valor **padrão real**, isso é mais intuitivo com Python em geral. 😌 -Você poderia chamar essa mesma função em outros lugares sem FastAPI, e ela funcionaria como esperado. Se houver um parâmetro obrigatório (sem valor padrão), seu editor vai avisar com um erro, e o Python também reclamará se você executá-la sem passar o parâmetro obrigatório. +Você poderia **chamar** essa mesma função em **outros lugares** sem FastAPI, e ela **funcionaria como esperado**. Se houver um parâmetro **obrigatório** (sem valor padrão), seu **editor** vai avisar com um erro, e o **Python** também reclamará se você executá-la sem passar o parâmetro obrigatório. -Quando você não usa `Annotated` e em vez disso usa o estilo de valor padrão (antigo), se você chamar essa função sem FastAPI em outros lugares, terá que lembrar de passar os argumentos para a função para que funcione corretamente, caso contrário os valores serão diferentes do esperado (por exemplo, `QueryInfo` ou algo parecido em vez de `str`). E seu editor não vai avisar, e o Python também não vai reclamar ao executar a função, apenas quando as operações internas falharem. +Quando você não usa `Annotated` e em vez disso usa o **estilo de valor padrão (antigo)**, se você chamar essa função sem FastAPI em **outros lugares**, terá que **lembrar** de passar os argumentos para a função para que funcione corretamente, caso contrário os valores serão diferentes do esperado (por exemplo, `QueryInfo` ou algo parecido em vez de `str`). E seu editor não vai avisar, e o Python também não vai reclamar ao executar a função, apenas quando as operações internas falharem. Como `Annotated` pode ter mais de uma anotação de metadados, você agora pode até usar a mesma função com outras ferramentas, como o [Typer](https://typer.tiangolo.com/). 🚀 @@ -168,7 +168,7 @@ Você também pode adicionar um parâmetro `min_length`: ## Adicione expressões regulares { #add-regular-expressions } -Você pode definir um `pattern` de expressão regular que o parâmetro deve corresponder: +Você pode definir um `pattern` de expressão regular que o parâmetro deve corresponder: {* ../../docs_src/query_params_str_validations/tutorial004_an_py310.py hl[11] *} @@ -178,9 +178,9 @@ Esse padrão específico de expressão regular verifica se o valor recebido no p * `fixedquery`: tem exatamente o valor `fixedquery`. * `$`: termina ali, não tem mais caracteres depois de `fixedquery`. -Se você se sentir perdido com essas ideias de "expressão regular", não se preocupe. Esse é um assunto difícil para muitas pessoas. Você ainda pode fazer muitas coisas sem precisar de expressões regulares por enquanto. +Se você se sentir perdido com essas ideias de **"expressão regular"**, não se preocupe. Esse é um assunto difícil para muitas pessoas. Você ainda pode fazer muitas coisas sem precisar de expressões regulares por enquanto. -Agora você sabe que, sempre que precisar delas, pode usá-las no FastAPI. +Agora você sabe que, sempre que precisar delas, pode usá-las no **FastAPI**. ## Valores padrão { #default-values } @@ -242,7 +242,7 @@ Então, com uma URL como: http://localhost:8000/items/?q=foo&q=bar ``` -você receberia os múltiplos valores dos parâmetros de consulta `q` (`foo` e `bar`) em uma `list` Python dentro da sua função de operação de rota, no parâmetro da função `q`. +você receberia os múltiplos valores dos *parâmetros de consulta* `q` (`foo` e `bar`) em uma `list` Python dentro da sua *função de operação de rota*, no *parâmetro da função* `q`. Assim, a resposta para essa URL seria: @@ -360,15 +360,15 @@ A documentação vai mostrar assim: ## Excluir parâmetros do OpenAPI { #exclude-parameters-from-openapi } -Para excluir um parâmetro de consulta do OpenAPI gerado (e portanto, dos sistemas de documentação automáticos), defina o parâmetro `include_in_schema` de `Query` como `False`: +Para excluir um parâmetro de consulta do esquema OpenAPI gerado (e portanto, dos sistemas de documentação automáticos), defina o parâmetro `include_in_schema` de `Query` como `False`: {* ../../docs_src/query_params_str_validations/tutorial014_an_py310.py hl[10] *} ## Validação personalizada { #custom-validation } -Podem existir casos em que você precise fazer alguma validação personalizada que não pode ser feita com os parâmetros mostrados acima. +Podem existir casos em que você precise fazer alguma **validação personalizada** que não pode ser feita com os parâmetros mostrados acima. -Nesses casos, você pode usar uma função validadora personalizada que é aplicada após a validação normal (por exemplo, depois de validar que o valor é uma `str`). +Nesses casos, você pode usar uma **função validadora personalizada** que é aplicada após a validação normal (por exemplo, depois de validar que o valor é uma `str`). Você pode fazer isso usando o [`AfterValidator` do Pydantic](https://docs.pydantic.dev/latest/concepts/validators/#field-after-validator) dentro de `Annotated`. @@ -390,15 +390,15 @@ Isso está disponível com a versão 2 do Pydantic ou superior. 😎 /// tip | Dica -Se você precisar fazer qualquer tipo de validação que exija comunicação com algum componente externo, como um banco de dados ou outra API, você deveria usar Dependências do FastAPI em vez disso; você aprenderá sobre elas mais adiante. +Se você precisar fazer qualquer tipo de validação que exija comunicação com algum **componente externo**, como um banco de dados ou outra API, você deveria usar **Dependências do FastAPI** em vez disso; você aprenderá sobre elas mais adiante. -Esses validadores personalizados são para coisas que podem ser verificadas apenas com os mesmos dados fornecidos na requisição. +Esses validadores personalizados são para coisas que podem ser verificadas **apenas** com os **mesmos dados** fornecidos na requisição. /// ### Entenda esse código { #understand-that-code } -O ponto importante é apenas usar `AfterValidator` com uma função dentro de `Annotated`. Sinta-se à vontade para pular esta parte. 🤸 +O ponto importante é apenas usar **`AfterValidator` com uma função dentro de `Annotated`**. Sinta-se à vontade para pular esta parte. 🤸 --- @@ -416,13 +416,13 @@ Com `data.items()` obtemos um `) enviam os dados para o servidor normalmente usa uma codificação "especial" para esses dados, a qual é diferente do JSON. @@ -119,9 +119,9 @@ O jeito que os formulários HTML (`
`) enviam os dados para o servid Dados de formulários normalmente são codificados usando o "media type" `application/x-www-form-urlencoded` quando não incluem arquivos. -Mas quando o formulário inclui arquivos, ele é codificado como `multipart/form-data`. Se você usar `File`, o **FastAPI** saberá que tem que pegar os arquivos da parte correta do corpo da requisição. +Mas quando o formulário inclui arquivos, ele é codificado como `multipart/form-data`. Se você usar `File`, o **FastAPI** saberá que tem que pegar os arquivos da parte correta do corpo. -Se você quiser ler mais sobre essas codificações e campos de formulário, vá para a [MDN web docs para `POST`](https://developer.mozilla.org/en-US/docs/Web/HTTP/Methods/POST). +Se você quiser ler mais sobre essas codificações e campos de formulário, vá para a [documentação web da MDN para `POST`](https://developer.mozilla.org/en-US/docs/Web/HTTP/Methods/POST). /// diff --git a/docs/pt/docs/tutorial/request-forms.md b/docs/pt/docs/tutorial/request-forms.md index d99c51650..bfca3562a 100644 --- a/docs/pt/docs/tutorial/request-forms.md +++ b/docs/pt/docs/tutorial/request-forms.md @@ -56,7 +56,7 @@ Os dados dos formulários são normalmente codificados usando o "media type" `ap Mas quando o formulário inclui arquivos, ele é codificado como `multipart/form-data`. Você lerá sobre como lidar com arquivos no próximo capítulo. -Se você quiser ler mais sobre essas codificações e campos de formulário, vá para o [MDN web docs para `POST`](https://developer.mozilla.org/en-US/docs/Web/HTTP/Methods/POST). +Se você quiser ler mais sobre essas codificações e campos de formulário, vá para a [documentação web da MDN para `POST`](https://developer.mozilla.org/en-US/docs/Web/HTTP/Methods/POST). /// diff --git a/docs/pt/docs/tutorial/response-status-code.md b/docs/pt/docs/tutorial/response-status-code.md index f02aeb0b4..aeeaf225d 100644 --- a/docs/pt/docs/tutorial/response-status-code.md +++ b/docs/pt/docs/tutorial/response-status-code.md @@ -12,7 +12,7 @@ Da mesma forma que você pode especificar um modelo de resposta, você também p /// note | Nota -Observe que `status_code` é um parâmetro do método "decorador" (`get`, `post`, etc). Não da sua função de *operação de rota*, como todos os parâmetros e corpo. +Observe que `status_code` é um parâmetro do método "decorador" (`get`, `post`, etc). Não da sua *função de operação de rota*, como todos os parâmetros e corpo. /// @@ -35,7 +35,7 @@ Dessa forma: Alguns códigos de resposta (consulte a próxima seção) indicam que a resposta não possui um corpo. -O FastAPI sabe disso e produzirá documentos OpenAPI informando que não há corpo de resposta. +O FastAPI sabe disso e produzirá documentação OpenAPI informando que não há corpo de resposta. /// @@ -84,7 +84,7 @@ Você pode usar as variáveis de conveniência de `fastapi.status`. {* ../../docs_src/response_status_code/tutorial002_py310.py hl[1,6] *} -Eles são apenas uma conveniência, eles possuem o mesmo número, mas dessa forma você pode usar o preenchimento automático do editor para encontrá-los: +Eles são apenas uma conveniência, eles possuem o mesmo número, mas dessa forma você pode usar o autocompletar do editor para encontrá-los: diff --git a/docs/pt/docs/tutorial/schema-extra-example.md b/docs/pt/docs/tutorial/schema-extra-example.md index 2feeb5438..6e10c5857 100644 --- a/docs/pt/docs/tutorial/schema-extra-example.md +++ b/docs/pt/docs/tutorial/schema-extra-example.md @@ -1,5 +1,6 @@ # Declare dados de exemplo da requisição { #declare-request-example-data } + Você pode declarar exemplos dos dados que sua aplicação pode receber. Aqui estão várias maneiras de fazer isso. diff --git a/docs/pt/docs/tutorial/security/first-steps.md b/docs/pt/docs/tutorial/security/first-steps.md index fe5b4e704..9780f8a69 100644 --- a/docs/pt/docs/tutorial/security/first-steps.md +++ b/docs/pt/docs/tutorial/security/first-steps.md @@ -62,9 +62,9 @@ Você verá algo deste tipo: /// tip | Botão Autorizar! -Você já tem um novo botão 'Authorize'. +Você já tem um novo e brilhante botão "Authorize". -E sua operação de rota tem um pequeno cadeado no canto superior direito em que você pode clicar. +E sua *operação de rota* tem um pequeno cadeado no canto superior direito em que você pode clicar. /// @@ -80,7 +80,7 @@ Não importa o que você digite no formulário, ainda não vai funcionar. Mas n Claro que este não é o frontend para os usuários finais, mas é uma ótima ferramenta automática para documentar interativamente toda a sua API. -Pode ser usada pelo time de frontend (que pode ser você mesmo). +Pode ser usada pela equipe de frontend (que pode ser você mesmo). Pode ser usada por aplicações e sistemas de terceiros. @@ -106,7 +106,7 @@ Então, vamos rever de um ponto de vista simplificado: * Então, o usuário terá que fazer login novamente em algum momento. * E se o token for roubado, o risco é menor. Não é como uma chave permanente que funcionará para sempre (na maioria dos casos). * O frontend armazena esse token temporariamente em algum lugar. -* O usuário clica no frontend para ir para outra seção do aplicativo web. +* O usuário clica no frontend para ir para outra seção da aplicação web do frontend. * O frontend precisa buscar mais dados da API. * Mas precisa de autenticação para aquele endpoint específico. * Então, para autenticar com nossa API, ele envia um header `Authorization` com o valor `Bearer ` mais o token. @@ -144,7 +144,7 @@ Usar uma URL relativa é importante para garantir que sua aplicação continue f /// -Esse parâmetro não cria aquele endpoint/operação de rota, mas declara que a URL `/token` será aquela que o client deve usar para obter o token. Essa informação é usada no OpenAPI e depois nos sistemas de documentação interativa da API. +Esse parâmetro não cria aquele endpoint / *operação de rota*, mas declara que a URL `/token` será aquela que o client deve usar para obter o token. Essa informação é usada no OpenAPI e depois nos sistemas de documentação interativa da API. Em breve também criaremos a operação de rota real. diff --git a/docs/pt/docs/tutorial/security/get-current-user.md b/docs/pt/docs/tutorial/security/get-current-user.md index 2c505f148..d56de4f8f 100644 --- a/docs/pt/docs/tutorial/security/get-current-user.md +++ b/docs/pt/docs/tutorial/security/get-current-user.md @@ -14,7 +14,7 @@ Primeiro, vamos criar um modelo de usuário com Pydantic. Da mesma forma que usamos o Pydantic para declarar corpos, podemos usá-lo em qualquer outro lugar: -{* ../../docs_src/security/tutorial002_an_py310.py hl[5,12:6] *} +{* ../../docs_src/security/tutorial002_an_py310.py hl[5,12:16] *} ## Criar uma dependência `get_current_user` { #create-a-get-current-user-dependency } diff --git a/docs/pt/docs/tutorial/security/oauth2-jwt.md b/docs/pt/docs/tutorial/security/oauth2-jwt.md index a571b799d..dbbbdc79d 100644 --- a/docs/pt/docs/tutorial/security/oauth2-jwt.md +++ b/docs/pt/docs/tutorial/security/oauth2-jwt.md @@ -1,6 +1,6 @@ # OAuth2 com Senha (e hashing), Bearer com tokens JWT { #oauth2-with-password-and-hashing-bearer-with-jwt-tokens } -Agora que temos todo o fluxo de segurança, vamos tornar a aplicação realmente segura, usando tokens JWT e hashing de senhas seguras. +Agora que temos todo o fluxo de segurança, vamos tornar a aplicação realmente segura, usando tokens JWT e hashing seguro de senhas. Este código é algo que você pode realmente usar na sua aplicação, salvar os hashes das senhas no seu banco de dados, etc. @@ -44,7 +44,7 @@ $ pip install pyjwt /// note | Nota -Se você pretende utilizar algoritmos de assinatura digital como o RSA ou o ECDSA, você deve instalar a dependência da biblioteca de criptografia `pyjwt[crypto]`. +Se você pretende utilizar algoritmos de assinatura digital como o RSA ou o ECDSA, você deveria instalar a dependência da biblioteca de criptografia `pyjwt[crypto]`. Você pode ler mais sobre isso na [documentação de instalação do PyJWT](https://pyjwt.readthedocs.io/en/latest/installation.html). @@ -88,7 +88,7 @@ $ pip install "pwdlib[argon2]" Com o `pwdlib`, você poderia até configurá-lo para ser capaz de ler senhas criadas pelo **Django**, um plug-in de segurança do **Flask** ou muitos outros. -Assim, você poderia, por exemplo, compartilhar os mesmos dados de um aplicativo Django em um banco de dados com um aplicativo FastAPI. Ou migrar gradualmente uma aplicação Django usando o mesmo banco de dados. +Assim, você poderia, por exemplo, compartilhar os mesmos dados de uma aplicação Django em um banco de dados com uma aplicação FastAPI. Ou migrar gradualmente uma aplicação Django usando o mesmo banco de dados. E seus usuários poderiam fazer login tanto pela sua aplicação Django quanto pela sua aplicação **FastAPI**, ao mesmo tempo. @@ -260,7 +260,7 @@ Com o que você viu até agora, você pode configurar uma aplicação **FastAPI* Em quase qualquer framework, lidar com a segurança se torna rapidamente um assunto bastante complexo. -Muitos pacotes que simplificam bastante isso precisam fazer muitas concessões com o modelo de dados, o banco de dados e os recursos disponíveis. E alguns desses pacotes que simplificam demais na verdade têm falhas de segurança subjacentes. +Muitos pacotes que simplificam bastante isso precisam fazer muitas concessões com o modelo de dados, o banco de dados e as funcionalidades disponíveis. E alguns desses pacotes que simplificam demais na verdade têm falhas de segurança subjacentes. --- diff --git a/docs/pt/docs/tutorial/security/simple-oauth2.md b/docs/pt/docs/tutorial/security/simple-oauth2.md index fdfe21a26..802879a53 100644 --- a/docs/pt/docs/tutorial/security/simple-oauth2.md +++ b/docs/pt/docs/tutorial/security/simple-oauth2.md @@ -6,7 +6,7 @@ Agora vamos construir a partir do capítulo anterior e adicionar as partes que f Vamos usar os utilitários de segurança da **FastAPI** para obter o `username` e a `password`. -OAuth2 especifica que ao usar o "password flow" (fluxo de senha), que estamos usando, o cliente/usuário deve enviar os campos `username` e `password` como dados do formulário. +OAuth2 especifica que, ao usar o "fluxo de senha" (que estamos usando), o cliente/usuário deve enviar os campos `username` e `password` como dados do formulário. E a especificação diz que os campos devem ser nomeados assim. Portanto, `user-name` ou `email` não funcionariam. @@ -29,7 +29,7 @@ Cada “scope” é apenas uma string (sem espaços). Normalmente são usados para declarar permissões de segurança específicas, por exemplo: * `users:read` ou `users:write` são exemplos comuns. -* `instagram_basic` é usado pelo Facebook e Instagram. +* `instagram_basic` é usado pelo Facebook / Instagram. * `https://www.googleapis.com/auth/drive` é usado pelo Google. /// note | Nota @@ -78,7 +78,7 @@ O `OAuth2PasswordRequestForm` não é uma classe especial para **FastAPI** como `OAuth2PasswordBearer` faz com que **FastAPI** saiba que é um esquema de segurança. Portanto, é adicionado dessa forma ao OpenAPI. -Mas `OAuth2PasswordRequestForm` é apenas uma dependência de classe que você mesmo poderia ter escrito ou poderia ter declarado os parâmetros do `Form` (formulário) diretamente. +Mas `OAuth2PasswordRequestForm` é apenas uma dependência de classe que você mesmo poderia ter escrito ou poderia ter declarado os parâmetros de `Form` diretamente. Mas como é um caso de uso comum, ele é fornecido diretamente pelo **FastAPI**, apenas para facilitar. @@ -108,7 +108,7 @@ Neste ponto temos os dados do usuário do nosso banco de dados, mas não verific Vamos colocar esses dados primeiro no modelo `UserInDB` do Pydantic. -Você nunca deve salvar senhas em texto simples, portanto, usaremos o sistema de hashing de senhas (falsas). +Você nunca deveria salvar senhas em texto simples, portanto, usaremos o sistema (falso) de hashing de senhas. Se as senhas não corresponderem, retornaremos o mesmo erro. @@ -120,7 +120,7 @@ Sempre que você passa exatamente o mesmo conteúdo (exatamente a mesma senha), Mas você não pode converter a sequência aleatória de caracteres de volta para a senha. -##### Porque usar hashing de senha { #why-use-password-hashing } +##### Por que usar hashing de senha { #why-use-password-hashing } Se o seu banco de dados for roubado, o ladrão não terá as senhas em texto simples dos seus usuários, apenas os hashes. @@ -146,7 +146,7 @@ UserInDB( /// note | Nota -Para uma explicação mais completa de `**user_dict`, verifique [a documentação para **Extra Models**](../extra-models.md#about-user-in-dict). +Para uma explicação mais completa de `**user_dict`, verifique [a documentação para **Extra Models**](../extra-models.md#about-user-in-model-dump). /// diff --git a/docs/pt/docs/tutorial/sql-databases.md b/docs/pt/docs/tutorial/sql-databases.md index 10be4c865..e715007eb 100644 --- a/docs/pt/docs/tutorial/sql-databases.md +++ b/docs/pt/docs/tutorial/sql-databases.md @@ -4,7 +4,7 @@ Aqui veremos um exemplo usando [SQLModel](https://sqlmodel.tiangolo.com/). -**SQLModel** é construído sobre [SQLAlchemy](https://www.sqlalchemy.org/) e Pydantic. Ele foi criado pelo mesmo autor do **FastAPI** para ser o par perfeito para aplicações **FastAPI** que precisam usar **bancos de dados SQL**. +**SQLModel** é construído sobre [SQLAlchemy](https://www.sqlalchemy.org/) e Pydantic. Ele foi criado pelo mesmo autor do **FastAPI** para ser o par perfeito para aplicações FastAPI que precisam usar **bancos de dados SQL**. /// tip | Dica @@ -32,7 +32,7 @@ Existe um gerador de projetos oficial com **FastAPI** e **PostgreSQL** incluindo Este é um tutorial muito simples e curto, se você quiser aprender sobre bancos de dados em geral, sobre SQL ou recursos mais avançados, acesse a [documentação do SQLModel](https://sqlmodel.tiangolo.com/). -## Instalar o `SQLModel` { #install-sqlmodel } +## Instale o `SQLModel` { #install-sqlmodel } Primeiro, certifique-se de criar seu [ambiente virtual](../virtual-environments.md), ativá-lo e, em seguida, instalar o `sqlmodel`: @@ -45,13 +45,13 @@ $ pip install sqlmodel
-## Crear o App com um Único Modelo { #create-the-app-with-a-single-model } +## Crie o App com um Único Modelo { #create-the-app-with-a-single-model } Vamos criar a primeira versão mais simples do app com um único modelo **SQLModel**. Depois, vamos melhorá-lo aumentando a segurança e versatilidade com **múltiplos modelos** abaixo. 🤓 -### Criar Modelos { #create-models } +### Crie Modelos { #create-models } Importe o `SQLModel` e crie um modelo de banco de dados: @@ -71,7 +71,8 @@ Existem algumas diferenças: O SQLModel saberá que algo declarado como `str` será uma coluna SQL do tipo `TEXT` (ou `VARCHAR`, dependendo do banco de dados). -### Criar um Engine { #create-an-engine } +### Crie um Engine { #create-an-engine } + Um `engine` SQLModel (por baixo dos panos, ele é na verdade um `engine` do SQLAlchemy) é o que **mantém as conexões** com o banco de dados. Você teria **um único objeto `engine`** para todo o seu código se conectar ao mesmo banco de dados. @@ -82,13 +83,13 @@ Usar `check_same_thread=False` permite que o FastAPI use o mesmo banco de dados Não se preocupe, com a forma como o código está estruturado, garantiremos que usamos **uma única *sessão* SQLModel por requisição** mais tarde, isso é realmente o que o `check_same_thread` está tentando conseguir. -### Criar as Tabelas { #create-the-tables } +### Crie as Tabelas { #create-the-tables } Em seguida, adicionamos uma função que usa `SQLModel.metadata.create_all(engine)` para **criar as tabelas** para todos os *modelos de tabela*. {* ../../docs_src/sql_databases/tutorial001_an_py310.py ln[21:22] hl[21:22] *} -### Criar uma Dependência de Sessão { #create-a-session-dependency } +### Crie uma Dependência de Sessão { #create-a-session-dependency } Uma **`Session`** é o que armazena os **objetos na memória** e acompanha as alterações necessárias nos dados, para então **usar o `engine`** para se comunicar com o banco de dados. @@ -98,7 +99,7 @@ Então, criamos uma dependência `Annotated` chamada `SessionDep` para simplific {* ../../docs_src/sql_databases/tutorial001_an_py310.py ln[25:30] hl[25:27,30] *} -### Criar Tabelas de Banco de Dados na Inicialização { #create-database-tables-on-startup } +### Crie Tabelas de Banco de Dados na Inicialização { #create-database-tables-on-startup } Vamos criar as tabelas do banco de dados quando o aplicativo for iniciado. @@ -114,7 +115,7 @@ O SQLModel terá utilitários de migração envolvendo o Alembic, mas por enquan /// -### Criar um Hero { #create-a-hero } +### Crie um Hero { #create-a-hero } Como cada modelo SQLModel também é um modelo Pydantic, você pode usá-lo nas mesmas **anotações de tipo** que usaria para modelos Pydantic. @@ -126,25 +127,25 @@ Da mesma forma, você pode declará-lo como o **tipo de retorno** da função, e Aqui, usamos a dependência `SessionDep` (uma `Session`) para adicionar o novo `Hero` à instância `Session`, fazer commit das alterações no banco de dados, atualizar os dados no `hero` e então retorná-lo. -### Ler Heroes { #read-heroes } +### Leia Heroes { #read-heroes } Podemos **ler** `Hero`s do banco de dados usando um `select()`. Podemos incluir um `limit` e `offset` para paginar os resultados. {* ../../docs_src/sql_databases/tutorial001_an_py310.py ln[48:55] hl[51:52,54] *} -### Ler um Único Hero { #read-one-hero } +### Leia um Único Hero { #read-one-hero } Podemos **ler** um único `Hero`. {* ../../docs_src/sql_databases/tutorial001_an_py310.py ln[58:63] hl[60] *} -### Deletar um Hero { #delete-a-hero } +### Delete um Hero { #delete-a-hero } Também podemos **deletar** um `Hero`. {* ../../docs_src/sql_databases/tutorial001_an_py310.py ln[66:73] hl[71] *} -### Executar o App { #run-the-app } +### Execute o App { #run-the-app } Você pode executar o app: @@ -164,19 +165,19 @@ Então, vá para a interface `/docs`, você verá que o **FastAPI** está usando
-## Atualizar o App com Múltiplos Modelos { #update-the-app-with-multiple-models } +## Atualize o App com Múltiplos Modelos { #update-the-app-with-multiple-models } Agora vamos **refatorar** este app um pouco para aumentar a **segurança** e **versatilidade**. -Se você verificar o app anterior, na interface você pode ser que, até agora, ele permite que o cliente decida o `id` do `Hero` a ser criado. 😱 +Se você verificar o app anterior, na interface você pode ver que, até agora, ele permite que o cliente decida o `id` do `Hero` a ser criado. 😱 -Não deveríamos deixar isso acontecer, eles poderiam sobrescrever um `id` que já atribuimos na base de dados. Decidir o `id` deve ser feito pelo **backend** ou pelo **banco de dados**, **não pelo cliente**. +Não deveríamos deixar isso acontecer, eles poderiam sobrescrever um `id` que já atribuímos no banco de dados. Decidir o `id` deve ser feito pelo **backend** ou pelo **banco de dados**, **não pelo cliente**. Além disso, criamos um `secret_name` para o hero, mas até agora estamos retornando ele em todos os lugares, isso não é muito **secreto**... 😅 Vamos corrigir essas coisas adicionando alguns **modelos extras**. Aqui é onde o SQLModel vai brilhar. ✨ -### Criar Múltiplos Modelos { #create-multiple-models } +### Crie Múltiplos Modelos { #create-multiple-models } No **SQLModel**, qualquer classe de modelo que tenha `table=True` é um **modelo de tabela**. @@ -277,7 +278,7 @@ Os campos de `HeroUpdate` são: {* ../../docs_src/sql_databases/tutorial002_an_py310.py ln[7:28] hl[25:28] *} -### Criar com `HeroCreate` e retornar um `HeroPublic` { #create-with-herocreate-and-return-a-heropublic } +### Crie com `HeroCreate` e retorne um `HeroPublic` { #create-with-herocreate-and-return-a-heropublic } Agora que temos **múltiplos modelos**, podemos atualizar as partes do app que os utilizam. @@ -299,19 +300,19 @@ Ao declará-lo no `response_model`, estamos dizendo ao **FastAPI** para fazer o /// -### Ler Heroes com `HeroPublic` { #read-heroes-with-heropublic } +### Leia Heroes com `HeroPublic` { #read-heroes-with-heropublic } Podemos fazer o mesmo que antes para **ler** `Hero`s, novamente, usamos `response_model=list[HeroPublic]` para garantir que os dados sejam validados e serializados corretamente. {* ../../docs_src/sql_databases/tutorial002_an_py310.py ln[65:72] hl[65] *} -### Ler Um Hero com `HeroPublic` { #read-one-hero-with-heropublic } +### Leia Um Hero com `HeroPublic` { #read-one-hero-with-heropublic } Podemos **ler** um único herói: {* ../../docs_src/sql_databases/tutorial002_an_py310.py ln[75:80] hl[77] *} -### Atualizar um Hero com `HeroUpdate` { #update-a-hero-with-heroupdate } +### Atualize um Hero com `HeroUpdate` { #update-a-hero-with-heroupdate } Podemos **atualizar um hero**. Para isso, usamos uma operação HTTP `PATCH`. @@ -321,7 +322,7 @@ Em seguida, usamos `hero_db.sqlmodel_update(hero_data)` para atualizar o `hero_d {* ../../docs_src/sql_databases/tutorial002_an_py310.py ln[83:93] hl[83:84,88:89] *} -### Deletar um Hero Novamente { #delete-a-hero-again } +### Delete um Hero Novamente { #delete-a-hero-again } **Deletar** um hero permanece praticamente o mesmo. @@ -329,7 +330,7 @@ Não vamos satisfazer o desejo de refatorar tudo neste aqui. 😅 {* ../../docs_src/sql_databases/tutorial002_an_py310.py ln[96:103] hl[101] *} -### Executar o App Novamente { #run-the-app-again } +### Execute o App Novamente { #run-the-app-again } Você pode executar o app novamente: diff --git a/docs/pt/docs/tutorial/static-files.md b/docs/pt/docs/tutorial/static-files.md index e9150facd..4e8d4319a 100644 --- a/docs/pt/docs/tutorial/static-files.md +++ b/docs/pt/docs/tutorial/static-files.md @@ -2,6 +2,14 @@ Você pode servir arquivos estáticos automaticamente a partir de um diretório usando `StaticFiles`. +/// tip | Dica + +Se você precisar hospedar um frontend, use `app.frontend()` em vez disso, leia sobre isso em [Frontend](frontend.md). + +`app.frontend()` usa `StaticFiles` por baixo, com várias vantagens adicionais para frontends, como lidar com roteamento do lado do cliente. + +/// + ## Use `StaticFiles` { #use-staticfiles } * Importe `StaticFiles`. diff --git a/docs/pt/docs/tutorial/testing.md b/docs/pt/docs/tutorial/testing.md index e185102ae..9d94cddcd 100644 --- a/docs/pt/docs/tutorial/testing.md +++ b/docs/pt/docs/tutorial/testing.md @@ -52,7 +52,7 @@ Você também pode usar `from starlette.testclient import TestClient`. /// tip | Dica -Se você quiser chamar funções `async` em seus testes além de enviar solicitações à sua aplicação FastAPI (por exemplo, funções de banco de dados assíncronas), dê uma olhada em [Testes assíncronos](../advanced/async-tests.md) no tutorial avançado. +Se você quiser chamar funções `async` em seus testes além de enviar requests à sua aplicação FastAPI (por exemplo, funções de banco de dados assíncronas), dê uma olhada em [Testes assíncronos](../advanced/async-tests.md) no tutorial avançado. /// @@ -94,6 +94,7 @@ Como esse arquivo está no mesmo pacote, você pode usar importações relativas {* ../../docs_src/app_testing/app_a_py310/test_main.py hl[3] *} + ...e ter o código para os testes como antes. ## Testando: exemplo estendido { #testing-extended-example } @@ -112,13 +113,13 @@ Vamos continuar com a mesma estrutura de arquivo de antes: │   └── test_main.py ``` -Digamos que agora o arquivo `main.py` com sua aplicação **FastAPI** tenha algumas outras **operações de rotas**. +Digamos que agora o arquivo `main.py` com sua aplicação **FastAPI** tenha algumas outras **operações de rota**. Ele tem uma operação `GET` que pode retornar um erro. Ele tem uma operação `POST` que pode retornar vários erros. -Ambas as *operações de rotas* requerem um cabeçalho `X-Token`. +Ambas as *operações de rota* requerem um cabeçalho `X-Token`. {* ../../docs_src/app_testing/app_b_an_py310/main.py *} @@ -128,6 +129,7 @@ Você pode então atualizar `test_main.py` com os testes estendidos: {* ../../docs_src/app_testing/app_b_an_py310/test_main.py *} + Sempre que você precisar que o cliente passe informações na requisição e não souber como, você pode pesquisar (no Google) como fazer isso no `httpx`, ou até mesmo como fazer isso com `requests`, já que o design do HTTPX é baseado no design do Requests. Depois é só fazer o mesmo nos seus testes. @@ -146,7 +148,7 @@ Para mais informações sobre como passar dados para o backend (usando `httpx` o Observe que o `TestClient` recebe dados que podem ser convertidos para JSON, não para modelos Pydantic. -Se você tiver um modelo Pydantic em seu teste e quiser enviar seus dados para o aplicativo durante o teste, poderá usar o `jsonable_encoder` descrito em [Codificador compatível com JSON](encoder.md). +Se você tiver um modelo Pydantic em seu teste e quiser enviar seus dados para a aplicação durante o teste, poderá usar o `jsonable_encoder` descrito em [Codificador compatível com JSON](encoder.md). /// diff --git a/docs/pt/docs/virtual-environments.md b/docs/pt/docs/virtual-environments.md index 245919608..121032d6c 100644 --- a/docs/pt/docs/virtual-environments.md +++ b/docs/pt/docs/virtual-environments.md @@ -26,7 +26,7 @@ Se você estiver pronto para adotar uma **ferramenta que gerencia tudo** para vo /// -## Criar um Projeto { #create-a-project } +## Crie um Projeto { #create-a-project } Primeiro, crie um diretório para seu projeto. @@ -212,7 +212,7 @@ Se ele mostrar o binário `python` em `.venv\Scripts\python`, dentro do seu proj //// -## Atualizar `pip` { #upgrade-pip } +## Atualize `pip` { #upgrade-pip } /// tip | Dica @@ -262,7 +262,7 @@ Esse comando instalará o pip caso ele ainda não esteja instalado e também gar /// -## Adicionar `.gitignore` { #add-gitignore } +## Adicione `.gitignore` { #add-gitignore } Se você estiver usando **Git** (você deveria), adicione um arquivo `.gitignore` para excluir tudo em seu `.venv` do Git. @@ -302,7 +302,7 @@ Esse comando criará um arquivo `.gitignore` com o conteúdo: /// -## Instalar Pacotes { #install-packages } +## Instale Pacotes { #install-packages } Após ativar o ambiente, você pode instalar pacotes nele. @@ -314,7 +314,7 @@ Se precisar atualizar uma versão ou adicionar um novo pacote, você **fará iss /// -### Instalar pacotes diretamente { #install-packages-directly } +### Instale pacotes diretamente { #install-packages-directly } Se estiver com pressa e não quiser usar um arquivo para declarar os requisitos de pacote do seu projeto, você pode instalá-los diretamente. @@ -353,7 +353,7 @@ $ uv pip install "fastapi[standard]" //// -### Instalar a partir de `requirements.txt` { #install-from-requirements-txt } +### Instale a partir de `requirements.txt` { #install-from-requirements-txt } Se você tiver um `requirements.txt`, agora poderá usá-lo para instalar seus pacotes. @@ -425,7 +425,7 @@ Normalmente, você só precisa fazer isso **uma vez**, ao criar o ambiente virtu /// -## Desativar o ambiente virtual { #deactivate-the-virtual-environment } +## Desative o ambiente virtual { #deactivate-the-virtual-environment } Quando terminar de trabalhar no seu projeto, você pode **desativar** o ambiente virtual. @@ -768,7 +768,7 @@ C:\Users\user\code\awesome-project\.venv\Scripts\python Isso significa que o programa `python` que será usado é aquele **no ambiente virtual**. -você usa `which` no Linux e macOS e `Get-Command` no Windows PowerShell. +Você usa `which` no Linux e macOS e `Get-Command` no Windows PowerShell. A maneira como esse comando funciona é que ele vai e verifica na variável de ambiente `PATH`, passando por **cada caminho em ordem**, procurando pelo programa chamado `python`. Uma vez que ele o encontre, ele **mostrará o caminho** para esse programa. @@ -811,7 +811,7 @@ $ cd ~/code/prisoner-of-azkaban $ python main.py -// Erro ao importar o Sirius, ele não está instalado 😱 +// Erro ao importar sirius, ele não está instalado 😱 Traceback (most recent call last): File "main.py", line 1, in import sirius @@ -861,4 +861,4 @@ Quando estiver pronto e quiser usar uma ferramenta para **gerenciar todo o proje Se você leu e entendeu tudo isso, agora **você sabe muito mais** sobre ambientes virtuais do que muitos desenvolvedores por aí. 🤓 -Saber esses detalhes provavelmente será útil no futuro, quando você estiver depurando algo que parece complexo, mas você saberá **como tudo funciona**. 😎 +Saber esses detalhes provavelmente será útil no futuro, quando você estiver depurando algo que parece complexo, mas você saberá **como tudo funciona por baixo**. 😎 From 50ab217bc6f2fc2d2ecd05af8329591c55e9d5fe Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Wed, 1 Jul 2026 13:45:51 +0000 Subject: [PATCH 369/462] =?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 d00065b7d..1f1c25b0a 100644 --- a/docs/en/docs/release-notes.md +++ b/docs/en/docs/release-notes.md @@ -9,6 +9,7 @@ hide: ### Translations +* 🌐 Update translations for pt (update-outdated). PR [#15893](https://github.com/fastapi/fastapi/pull/15893) by [@tiangolo](https://github.com/tiangolo). * 🌐 Update translations for zh (update-outdated). PR [#15898](https://github.com/fastapi/fastapi/pull/15898) by [@tiangolo](https://github.com/tiangolo). * 🌐 Update translations for uk (update-outdated). PR [#15900](https://github.com/fastapi/fastapi/pull/15900) by [@tiangolo](https://github.com/tiangolo). * 🌐 Update translations for ko (update-outdated). PR [#15890](https://github.com/fastapi/fastapi/pull/15890) by [@tiangolo](https://github.com/tiangolo). From e7324a77db4a9f4d38e4673850ed10ab1de0cb96 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebasti=C3=A1n=20Ram=C3=ADrez?= Date: Wed, 1 Jul 2026 15:46:01 +0200 Subject: [PATCH 370/462] =?UTF-8?q?=F0=9F=8C=90=20Update=20translations=20?= =?UTF-8?q?for=20tr=20(update-outdated)=20(#15891)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: github-actions[bot] Co-authored-by: Yurii Motov --- docs/tr/docs/_llm-test.md | 10 +-- .../docs/advanced/additional-status-codes.md | 1 + .../tr/docs/advanced/advanced-dependencies.md | 2 +- docs/tr/docs/advanced/dataclasses.md | 1 + docs/tr/docs/advanced/events.md | 2 +- docs/tr/docs/advanced/generate-clients.md | 14 ---- docs/tr/docs/advanced/json-base64-bytes.md | 2 +- docs/tr/docs/advanced/openapi-callbacks.md | 4 +- .../advanced/response-change-status-code.md | 4 +- docs/tr/docs/advanced/response-cookies.md | 2 +- docs/tr/docs/advanced/response-headers.md | 1 + .../docs/advanced/security/oauth2-scopes.md | 1 + docs/tr/docs/advanced/settings.md | 1 + docs/tr/docs/advanced/stream-data.md | 4 +- docs/tr/docs/advanced/wsgi.md | 1 + docs/tr/docs/alternatives.md | 66 ++++++++++--------- docs/tr/docs/async.md | 12 ++-- docs/tr/docs/deployment/cloud.md | 2 +- docs/tr/docs/deployment/concepts.md | 1 + docs/tr/docs/deployment/docker.md | 6 +- docs/tr/docs/deployment/https.md | 4 +- docs/tr/docs/deployment/manually.md | 1 + docs/tr/docs/editor-support.md | 2 +- docs/tr/docs/environment-variables.md | 34 +++++----- docs/tr/docs/features.md | 4 +- docs/tr/docs/help-fastapi.md | 4 +- docs/tr/docs/how-to/configure-swagger-ui.md | 4 +- .../docs/how-to/custom-request-and-route.md | 1 + docs/tr/docs/how-to/graphql.md | 1 + ...migrate-from-pydantic-v1-to-pydantic-v2.md | 18 +++++ .../docs/how-to/separate-openapi-schemas.md | 2 +- docs/tr/docs/index.md | 6 +- docs/tr/docs/project-generation.md | 1 + docs/tr/docs/python-types.md | 1 + docs/tr/docs/tutorial/bigger-applications.md | 32 ++++----- docs/tr/docs/tutorial/body-nested-models.md | 1 + docs/tr/docs/tutorial/body.md | 1 + docs/tr/docs/tutorial/debugging.md | 2 +- .../dependencies/dependencies-with-yield.md | 5 +- docs/tr/docs/tutorial/extra-data-types.md | 2 +- docs/tr/docs/tutorial/extra-models.md | 1 + docs/tr/docs/tutorial/first-steps.md | 1 + docs/tr/docs/tutorial/handling-errors.md | 2 +- docs/tr/docs/tutorial/index.md | 4 +- docs/tr/docs/tutorial/metadata.md | 2 +- .../tutorial/path-operation-configuration.md | 1 + .../tutorial/query-params-str-validations.md | 1 + docs/tr/docs/tutorial/query-params.md | 4 +- docs/tr/docs/tutorial/request-files.md | 2 +- docs/tr/docs/tutorial/request-forms.md | 1 + docs/tr/docs/tutorial/response-status-code.md | 4 +- docs/tr/docs/tutorial/schema-extra-example.md | 8 +-- docs/tr/docs/tutorial/security/first-steps.md | 2 +- .../tutorial/security/get-current-user.md | 2 +- docs/tr/docs/tutorial/security/oauth2-jwt.md | 4 +- .../docs/tutorial/security/simple-oauth2.md | 2 +- docs/tr/docs/tutorial/sql-databases.md | 2 +- docs/tr/docs/tutorial/static-files.md | 8 +++ docs/tr/docs/tutorial/testing.md | 3 + docs/tr/docs/virtual-environments.md | 6 +- 60 files changed, 181 insertions(+), 142 deletions(-) diff --git a/docs/tr/docs/_llm-test.md b/docs/tr/docs/_llm-test.md index bc3dc8977..049aa2676 100644 --- a/docs/tr/docs/_llm-test.md +++ b/docs/tr/docs/_llm-test.md @@ -37,7 +37,7 @@ Code snippet'lerin içeriği olduğu gibi bırakılmalıdır. Dün bir arkadaşım şunu yazdı: "If you spell incorrectly correctly, you have spelled it incorrectly". Ben de şunu yanıtladım: "Correct, but 'incorrectly' is incorrectly not '"incorrectly"'". -/// note +/// note | Not LLM muhtemelen bunu yanlış çevirecektir. Yeniden çeviri yapıldığında düzeltilmiş çeviriyi koruyup korumadığı önemlidir. @@ -124,7 +124,7 @@ Code block'ların içindeki code değiştirilmemelidir; tek istisna yorumlardır //// tab | Test -/// note +/// note | Not Bazı metin /// @@ -132,15 +132,15 @@ Bazı metin Bazı metin /// -/// tip +/// tip | İpucu Bazı metin /// -/// warning +/// warning | Uyarı Bazı metin /// -/// danger +/// danger | Tehlike Bazı metin /// diff --git a/docs/tr/docs/advanced/additional-status-codes.md b/docs/tr/docs/advanced/additional-status-codes.md index 6db570aef..21d113ffe 100644 --- a/docs/tr/docs/advanced/additional-status-codes.md +++ b/docs/tr/docs/advanced/additional-status-codes.md @@ -1,5 +1,6 @@ # Ek Status Code'ları { #additional-status-codes } + Varsayılan olarak **FastAPI**, response'ları bir `JSONResponse` kullanarak döndürür; *path operation*'ınızdan döndürdüğünüz içeriği bu `JSONResponse`'un içine yerleştirir. Varsayılan status code'u veya *path operation* içinde sizin belirlediğiniz status code'u kullanır. diff --git a/docs/tr/docs/advanced/advanced-dependencies.md b/docs/tr/docs/advanced/advanced-dependencies.md index 5a75042e6..86a15a6c1 100644 --- a/docs/tr/docs/advanced/advanced-dependencies.md +++ b/docs/tr/docs/advanced/advanced-dependencies.md @@ -78,7 +78,7 @@ Bu detaylar, özellikle 0.121.0'dan eski bir FastAPI uygulamanız varsa ve `yiel ### `yield` ve `scope` ile dependency'ler { #dependencies-with-yield-and-scope } -0.121.0 sürümünde FastAPI, `Depends(scope="function")` desteğini ekledi. +0.121.0 sürümünde FastAPI, `yield` kullanan dependency'ler için `Depends(scope="function")` desteğini ekledi. `Depends(scope="function")` kullanıldığında, `yield` sonrasındaki çıkış kodu, *path operation function* biter bitmez, response client'a geri gönderilmeden önce çalıştırılır. diff --git a/docs/tr/docs/advanced/dataclasses.md b/docs/tr/docs/advanced/dataclasses.md index 150d0080a..9f79a6cbe 100644 --- a/docs/tr/docs/advanced/dataclasses.md +++ b/docs/tr/docs/advanced/dataclasses.md @@ -1,5 +1,6 @@ # Dataclass Kullanımı { #using-dataclasses } + FastAPI, **Pydantic** üzerine inşa edilmiştir ve request/response tanımlamak için Pydantic model'lerini nasıl kullanacağınızı gösteriyordum. Ancak FastAPI, [`dataclasses`](https://docs.python.org/3/library/dataclasses.html) kullanmayı da aynı şekilde destekler: diff --git a/docs/tr/docs/advanced/events.md b/docs/tr/docs/advanced/events.md index bc3b0ef58..4c96b2296 100644 --- a/docs/tr/docs/advanced/events.md +++ b/docs/tr/docs/advanced/events.md @@ -2,7 +2,7 @@ Uygulama **başlamadan** önce çalıştırılması gereken mantığı (kodu) tanımlayabilirsiniz. Bu, bu kodun **bir kez**, uygulama **request almaya başlamadan önce** çalıştırılacağı anlamına gelir. -Benzer şekilde, uygulama **kapanırken** çalıştırılması gereken mantığı (kodu) da tanımlayabilirsiniz. Bu durumda bu kod, muhtemelen **çok sayıda request** işlendi **sonra**, **bir kez** çalıştırılır. +Benzer şekilde, uygulama **kapanırken** çalıştırılması gereken mantığı (kodu) da tanımlayabilirsiniz. Bu durumda bu kod, muhtemelen **çok sayıda request** işlendikten **sonra**, **bir kez** çalıştırılır. Bu kod, uygulama request almaya **başlamadan** önce ve request’leri işlemeyi **bitirdikten** hemen sonra çalıştığı için, uygulamanın tüm **lifespan**’ını (birazdan "lifespan" kelimesi önemli olacak 😉) kapsar. diff --git a/docs/tr/docs/advanced/generate-clients.md b/docs/tr/docs/advanced/generate-clients.md index 68cb4ab0d..6e12efe3c 100644 --- a/docs/tr/docs/advanced/generate-clients.md +++ b/docs/tr/docs/advanced/generate-clients.md @@ -20,20 +20,6 @@ FastAPI otomatik olarak **OpenAPI 3.1** spesifikasyonları üretir; bu yüzden k /// -## FastAPI Sponsorlarından SDK Üreteçleri { #sdk-generators-from-fastapi-sponsors } - -Bu bölüm, FastAPI'yi sponsorlayan şirketlerin sunduğu **yatırım destekli** ve **şirket destekli** çözümleri öne çıkarır. Bu ürünler, yüksek kaliteli üretilen SDK'ların üzerine **ek özellikler** ve **entegrasyonlar** sağlar. - -✨ [**FastAPI'ye sponsor olarak**](../help-fastapi.md#sponsor-the-author) ✨ bu şirketler, framework'ün ve **ekosisteminin** sağlıklı ve **sürdürülebilir** kalmasına yardımcı olur. - -Sponsor olmaları aynı zamanda FastAPI **topluluğuna** (size) güçlü bir bağlılığı da gösterir; yalnızca **iyi bir hizmet** sunmayı değil, aynı zamanda **güçlü ve gelişen bir framework** olan FastAPI'yi desteklemeyi de önemsediklerini gösterir. 🙇 - -Örneğin şunları deneyebilirsiniz: - -* [Stainless](https://www.stainless.com/?utm_source=fastapi&utm_medium=referral) - -Bu çözümlerin bazıları açık kaynak olabilir veya ücretsiz katman sunabilir; yani finansal bir taahhüt olmadan deneyebilirsiniz. Başka ticari SDK üreteçleri de vardır ve internette bulunabilir. 🤓 - ## TypeScript SDK Oluşturma { #create-a-typescript-sdk } Basit bir FastAPI uygulamasıyla başlayalım: diff --git a/docs/tr/docs/advanced/json-base64-bytes.md b/docs/tr/docs/advanced/json-base64-bytes.md index 68e1cba7a..b7712194c 100644 --- a/docs/tr/docs/advanced/json-base64-bytes.md +++ b/docs/tr/docs/advanced/json-base64-bytes.md @@ -4,7 +4,7 @@ Uygulamanız JSON veri alıp gönderiyorsa ve bunun içine ikili (binary) veri e ## Base64 ve Dosyalar { #base64-vs-files } -İkili veriyi JSON içinde encode etmek yerine, yükleme için [Request Files](../tutorial/request-files.md) ve gönderim için [Custom Response - FileResponse](./custom-response.md#fileresponse--fileresponse-) kullanıp kullanamayacağınıza önce bir bakın. +İkili veriyi JSON içinde encode etmek yerine, yükleme için [Request Files](../tutorial/request-files.md) ve gönderim için [Custom Response - FileResponse](./custom-response.md#fileresponse) kullanıp kullanamayacağınıza önce bir bakın. JSON sadece UTF-8 ile encode edilmiş string'ler içerebilir, dolayısıyla ham bytes içeremez. diff --git a/docs/tr/docs/advanced/openapi-callbacks.md b/docs/tr/docs/advanced/openapi-callbacks.md index 023d97587..91ff84411 100644 --- a/docs/tr/docs/advanced/openapi-callbacks.md +++ b/docs/tr/docs/advanced/openapi-callbacks.md @@ -167,13 +167,13 @@ Callback URL'sinin, `callback_url` içindeki query parametresi olarak alınan UR Bu noktada, yukarıda oluşturduğunuz callback router'ında gerekli callback *path operation*'ları (external geliştiricinin *external API*'de implemente etmesi gerekenler) hazır. -Şimdi sizin API'nizin *path operation decorator*'ında `callbacks` parametresini kullanarak, callback router'ının `.routes` attribute'unu (bu aslında route/*path operation*'lardan oluşan bir `list`) geçin: +Şimdi sizin API'nizin *path operation decorator*'ında `callbacks` parametresini kullanarak, callback router'ının `.routes` attribute'unu geçin: {* ../../docs_src/openapi_callbacks/tutorial001_py310.py hl[33] *} /// tip | İpucu -`callback=` içine router'ın kendisini (`invoices_callback_router`) değil, `invoices_callback_router.routes` şeklinde `.routes` attribute'unu verdiğinize dikkat edin. FastAPI bu route'ları callback OpenAPI dokümantasyonunu üretmek için kullanacaktır. +`callbacks=` içine router'ın kendisini (`invoices_callback_router`) değil, `invoices_callback_router.routes` şeklinde `.routes` attribute'unu verdiğinize dikkat edin. FastAPI bu route'ları callback OpenAPI dokümantasyonunu üretmek için kullanacaktır. /// diff --git a/docs/tr/docs/advanced/response-change-status-code.md b/docs/tr/docs/advanced/response-change-status-code.md index f15ed77f5..552daa0b2 100644 --- a/docs/tr/docs/advanced/response-change-status-code.md +++ b/docs/tr/docs/advanced/response-change-status-code.md @@ -18,7 +18,7 @@ Bu tür durumlarda bir `Response` parametresi kullanabilirsiniz. *Path operation function* içinde `Response` tipinde bir parametre tanımlayabilirsiniz (cookie ve header'lar için yapabildiğiniz gibi). -Ardından bu *geçici (temporal)* `Response` nesnesi üzerinde `status_code` değerini ayarlayabilirsiniz. +Ardından bu *geçici* `Response` nesnesi üzerinde `status_code` değerini ayarlayabilirsiniz. {* ../../docs_src/response_change_status_code/tutorial001_py310.py hl[1,9,12] *} @@ -26,6 +26,6 @@ Sonrasında, normalde yaptığınız gibi ihtiyacınız olan herhangi bir nesney Ve eğer bir `response_model` tanımladıysanız, döndürdüğünüz nesneyi filtrelemek ve dönüştürmek için yine kullanılacaktır. -**FastAPI**, status code'u (ayrıca cookie ve header'ları) bu *geçici (temporal)* response'tan alır ve `response_model` ile filtrelenmiş, sizin döndürdüğünüz değeri içeren nihai response'a yerleştirir. +**FastAPI**, status code'u (ayrıca cookie ve header'ları) bu *geçici* response'tan alır ve `response_model` ile filtrelenmiş, sizin döndürdüğünüz değeri içeren nihai response'a yerleştirir. Ayrıca `Response` parametresini dependency'lerde de tanımlayıp status code'u orada ayarlayabilirsiniz. Ancak unutmayın, en son ayarlanan değer geçerli olur. diff --git a/docs/tr/docs/advanced/response-cookies.md b/docs/tr/docs/advanced/response-cookies.md index 3d3b978bc..a33d4ef37 100644 --- a/docs/tr/docs/advanced/response-cookies.md +++ b/docs/tr/docs/advanced/response-cookies.md @@ -26,7 +26,7 @@ Sonra bunun içinde Cookie'leri set edin ve response'u döndürün: {* ../../docs_src/response_cookies/tutorial001_py310.py hl[10:12] *} -/// tip +/// tip | İpucu `Response` parametresini kullanmak yerine doğrudan bir response döndürürseniz, FastAPI onu olduğu gibi (doğrudan) döndürür. diff --git a/docs/tr/docs/advanced/response-headers.md b/docs/tr/docs/advanced/response-headers.md index d61e24da3..c4a654792 100644 --- a/docs/tr/docs/advanced/response-headers.md +++ b/docs/tr/docs/advanced/response-headers.md @@ -1,5 +1,6 @@ # Response Header'ları { #response-headers } + ## Bir `Response` parametresi kullanın { #use-a-response-parameter } *Path operation function* içinde (cookie'lerde yapabildiğiniz gibi) tipi `Response` olan bir parametre tanımlayabilirsiniz. diff --git a/docs/tr/docs/advanced/security/oauth2-scopes.md b/docs/tr/docs/advanced/security/oauth2-scopes.md index c5de15f8d..1d1dcb3cf 100644 --- a/docs/tr/docs/advanced/security/oauth2-scopes.md +++ b/docs/tr/docs/advanced/security/oauth2-scopes.md @@ -1,5 +1,6 @@ # OAuth2 scope'ları { #oauth2-scopes } + OAuth2 scope'larını **FastAPI** ile doğrudan kullanabilirsiniz; sorunsuz çalışacak şekilde entegre edilmiştir. Bu sayede OAuth2 standardını takip eden, daha ince taneli bir izin sistemini OpenAPI uygulamanıza (ve API dokümanlarınıza) entegre edebilirsiniz. diff --git a/docs/tr/docs/advanced/settings.md b/docs/tr/docs/advanced/settings.md index a39e28a92..5734387fe 100644 --- a/docs/tr/docs/advanced/settings.md +++ b/docs/tr/docs/advanced/settings.md @@ -1,5 +1,6 @@ # Ayarlar ve Ortam Değişkenleri { #settings-and-environment-variables } + Birçok durumda uygulamanızın bazı harici ayarlara veya konfigürasyonlara ihtiyacı olabilir; örneğin secret key'ler, veritabanı kimlik bilgileri, e-posta servisleri için kimlik bilgileri vb. Bu ayarların çoğu değişkendir (değişebilir); örneğin veritabanı URL'leri. Ayrıca birçoğu hassas olabilir; örneğin secret'lar. diff --git a/docs/tr/docs/advanced/stream-data.md b/docs/tr/docs/advanced/stream-data.md index a71bb3217..9b58d962b 100644 --- a/docs/tr/docs/advanced/stream-data.md +++ b/docs/tr/docs/advanced/stream-data.md @@ -2,7 +2,7 @@ Veriyi JSON olarak yapılandırabiliyorsanız, [JSON Lines Akışı](../tutorial/stream-json-lines.md) kullanın. -Ancak saf ikili (binary) veri ya da string akıtmak istiyorsanız, bunu şöyle yapabilirsiniz. +Ancak **saf ikili (binary) veri** ya da string akıtmak istiyorsanız, bunu şöyle yapabilirsiniz. /// note | Not @@ -40,7 +40,7 @@ FastAPI veriyi Pydantic ile JSON'a çevirmeye veya herhangi bir şekilde serile {* ../../docs_src/stream_data/tutorial001_py310.py ln[32:35] hl[33] *} -Bu aynı zamanda `StreamingResponse` ile veriyi tam olarak ihtiyaç duyduğunuz biçimde üretme ve encode etme konusunda hem bir özgürlük hem de bir sorumluluk verdiği anlamına gelir; tip annotasyonlarından bağımsızdır. 🤓 +Bu aynı zamanda `StreamingResponse` ile veriyi tam olarak ihtiyaç duyduğunuz biçimde üretme ve encode etme konusunda hem bir **özgürlük** hem de bir **sorumluluk** verdiği anlamına gelir; tip annotasyonlarından bağımsızdır. 🤓 ### Bytes Akışı { #stream-bytes } diff --git a/docs/tr/docs/advanced/wsgi.md b/docs/tr/docs/advanced/wsgi.md index 84eb7981a..6e61aff6a 100644 --- a/docs/tr/docs/advanced/wsgi.md +++ b/docs/tr/docs/advanced/wsgi.md @@ -1,5 +1,6 @@ # WSGI'yi Dahil Etme - Flask, Django ve Diğerleri { #including-wsgi-flask-django-others } + WSGI uygulamalarını [Alt Uygulamalar - Mount Etme](sub-applications.md), [Bir Proxy Arkasında](behind-a-proxy.md) bölümlerinde gördüğünüz gibi mount edebilirsiniz. Bunun için `WSGIMiddleware`'ı kullanabilir ve bunu WSGI uygulamanızı (örneğin Flask, Django vb.) sarmalamak için kullanabilirsiniz. diff --git a/docs/tr/docs/alternatives.md b/docs/tr/docs/alternatives.md index 556e7abbe..e214907b5 100644 --- a/docs/tr/docs/alternatives.md +++ b/docs/tr/docs/alternatives.md @@ -10,7 +10,7 @@ Başkalarının daha önceki çalışmaları olmasaydı, **FastAPI** var olmazd Yıllarca yeni bir framework oluşturmaktan kaçındım. Önce **FastAPI**’ın bugün kapsadığı özelliklerin tamamını, birçok farklı framework, eklenti ve araçla çözmeyi denedim. -Namun bir noktada, geçmişteki araçlardan en iyi fikirleri alıp, mümkün olan en iyi şekilde birleştiren ve daha önce mevcut olmayan dil özelliklerini (Python 3.6+ tip belirteçleri) kullanarak tüm bu özellikleri sağlayan bir şey geliştirmekten başka seçenek kalmadı. +Ancak bir noktada, geçmişteki araçlardan en iyi fikirleri alıp, mümkün olan en iyi şekilde birleştiren ve daha önce mevcut olmayan dil özelliklerini (Python 3.6+ tip belirteçleri) kullanarak tüm bu özellikleri sağlayan bir şey geliştirmekten başka seçenek kalmadı. ## Daha Önce Geliştirilen Araçlar { #previous-tools } @@ -60,7 +60,7 @@ Flask’ın sadeliği göz önüne alındığında, API geliştirmek için iyi b Gereken araç ve parçaları kolayca eşleştirip birleştirmeyi sağlayan bir mikroframework olmak. -Basit ve kullanımı kolay bir yönlendirme (routing) sistemine sahip olmak. +Basit ve kullanımı kolay bir routing sistemine sahip olmak. /// @@ -72,7 +72,7 @@ Hatta bir FastAPI uygulamasının içinde Requests kullanmak yaygındır. Yine de FastAPI, Requests’ten epey ilham almıştır. -**Requests** bir kütüphane olarak API’larla (istemci olarak) etkileşime geçmeye yararken, **FastAPI** API’lar (sunucu olarak) geliştirmeye yarar. +**Requests** bir kütüphane olarak API’larla (client olarak) etkileşime geçmeye yararken, **FastAPI** API’lar (server olarak) geliştirmeye yarar. Yani daha çok zıt uçlardadırlar ama birbirlerini tamamlarlar. @@ -82,7 +82,7 @@ Bu yüzden resmi web sitesinde de söylendiği gibi: > Requests, tüm zamanların en çok indirilen Python paketlerinden biridir -Kullanımı çok basittir. Örneğin bir `GET` isteği yapmak için: +Kullanımı çok basittir. Örneğin bir `GET` request'i yapmak için: ```Python response = requests.get("http://example.com/some/url") @@ -137,9 +137,9 @@ Birçok Flask REST framework’ü var; ancak zaman ayırıp inceledikten sonra ### [Marshmallow](https://marshmallow.readthedocs.io/en/stable/) { #marshmallow } -API sistemlerinin ihtiyaç duyduğu temel özelliklerden biri, koddan (Python) veriyi alıp ağ üzerinden gönderilebilecek bir şeye dönüştürmek, yani veri “dönüşüm”üdür. Örneğin, bir veritabanından gelen verileri içeren bir objeyi JSON objesine dönüştürmek, `datetime` objelerini string’e çevirmek vb. +API sistemlerinin ihtiyaç duyduğu temel özelliklerden biri, koddan (Python) veriyi alıp ağ üzerinden gönderilebilecek bir şeye dönüştürmek, yani veri “serileştirme”dir. Örneğin, bir veritabanından gelen verileri içeren bir objeyi JSON objesine dönüştürmek, `datetime` objelerini string’e çevirmek vb. -API’ların ihtiyaç duyduğu bir diğer önemli özellik, veri doğrulamadır; belirli parametreler göz önüne alındığında verinin geçerli olduğundan emin olmak. Örneğin, bir alanın `int` olması ve rastgele bir metin olmaması. Bu özellikle dışarıdan gelen veriler için kullanışlıdır. +API’ların ihtiyaç duyduğu bir diğer önemli özellik, veri doğrulamadır; belirli parametreler göz önüne alındığında verinin geçerli olduğundan emin olmak. Örneğin, bir alanın `int` olması ve rastgele bir metin olmaması. Bu özellikle gelen veriler için kullanışlıdır. Bir veri doğrulama sistemi olmadan, tüm bu kontrolleri kod içinde el ile yapmanız gerekir. @@ -155,7 +155,7 @@ Kodla, veri tiplerini ve doğrulamayı otomatik sağlayan “şemalar” tanıml ### [Webargs](https://webargs.readthedocs.io/en/latest/) { #webargs } -API’ların ihtiyaç duyduğu bir diğer büyük özellik, gelen isteklerden veriyi ayrıştırmadır. +API’ların ihtiyaç duyduğu bir diğer büyük özellik, gelen request'lerden veriyi ayrıştırmadır. Webargs, Flask dahil birkaç framework’ün üzerinde bunu sağlamak için geliştirilmiş bir araçtır. @@ -163,7 +163,7 @@ Veri doğrulama için arka planda Marshmallow’u kullanır. Aynı geliştiricil **FastAPI**’dan önce benim de çok kullandığım harika bir araçtır. -/// info | Bilgi +/// note | Not Webargs, Marshmallow geliştiricileri tarafından oluşturuldu. @@ -171,13 +171,13 @@ Webargs, Marshmallow geliştiricileri tarafından oluşturuldu. /// tip | **FastAPI**'ye ilham olan -Gelen istek verisini otomatik doğrulamak. +Gelen request verisini otomatik doğrulamak. /// ### [APISpec](https://apispec.readthedocs.io/en/stable/) { #apispec } -Marshmallow ve Webargs; doğrulama, ayrıştırma ve dönüşümü eklenti olarak sağlar. +Marshmallow ve Webargs; doğrulama, ayrıştırma ve serileştirmeyi eklenti olarak sağlar. Ama dökümantasyon eksikti. Sonra APISpec geliştirildi. @@ -193,7 +193,7 @@ Ancak yine, Python metni içinde (kocaman bir YAML) mikro bir söz dizimi sorunu Editör bu konuda pek yardımcı olamaz. Parametreleri veya Marshmallow şemalarını değiştirip docstring’teki YAML’ı güncellemeyi unutursak, üretilen şema geçerliliğini yitirir. -/// info | Bilgi +/// note | Not APISpec, Marshmallow geliştiricileri tarafından oluşturuldu. @@ -225,7 +225,7 @@ Bunu kullanmak, birkaç Flask full‑stack üreticisinin ortaya çıkmasına yol Aynı full‑stack üreticiler, [**FastAPI** Proje Üreticileri](project-generation.md)’nin de temelini oluşturdu. -/// info | Bilgi +/// note | Not Flask-apispec, Marshmallow geliştiricileri tarafından oluşturuldu. @@ -233,7 +233,7 @@ Flask-apispec, Marshmallow geliştiricileri tarafından oluşturuldu. /// tip | **FastAPI**'ye ilham olan -Veri dönüşümü ve doğrulamayı tanımlayan aynı koddan, OpenAPI şemasını otomatik üretmek. +Serileştirme ve doğrulamayı tanımlayan aynı koddan, OpenAPI şemasını otomatik üretmek. /// @@ -247,9 +247,9 @@ Angular 2’den esinlenen, entegre bir bağımlılık enjeksiyonu sistemi vardı Parametreler TypeScript tipleriyle (Python tip belirteçlerine benzer) açıklandığından, editör desteği oldukça iyidir. -Ancak TypeScript tip bilgisi JavaScript’e derlemeden sonra korunmadığından, aynı anda tiplere dayanarak doğrulama, dönüşüm ve dökümantasyon tanımlanamaz. Bu ve bazı tasarım kararları nedeniyle doğrulama, dönüşüm ve otomatik şema üretimi için birçok yere dekoratör eklemek gerekir; proje oldukça ayrıntılı hâle gelir. +Ancak TypeScript tip bilgisi JavaScript’e derlemeden sonra korunmadığından, aynı anda tiplere dayanarak doğrulama, serileştirme ve dökümantasyon tanımlanamaz. Bu ve bazı tasarım kararları nedeniyle doğrulama, serileştirme ve otomatik şema üretimi için birçok yere dekoratör eklemek gerekir; proje oldukça ayrıntılı hâle gelir. -İçiçe modelleri çok iyi işleyemez. Yani istek gövdesindeki JSON, içinde başka alanları ve onlar da içiçe JSON objelerini içeriyorsa, doğru şekilde dökümante edilip doğrulanamaz. +İç içe modelleri çok iyi işleyemez. Yani request'teki JSON body, içinde başka alanları ve onlar da iç içe JSON objelerini içeriyorsa, doğru şekilde dökümante edilip doğrulanamaz. /// tip | **FastAPI**'ye ilham olan @@ -283,15 +283,17 @@ Bu yüzden **FastAPI**, en hızlı framework olduğu için (üçüncü parti kı Falcon, başka bir yüksek performanslı Python framework’üdür; minimal olacak şekilde tasarlanmış ve Hug gibi diğer framework’lere temel olmuştur. -İki parametre alan fonksiyonlar etrafında tasarlanmıştır: “request” ve “response”. İstekten parçalar “okur”, cevaba parçalar “yazarsınız”. Bu tasarım nedeniyle, fonksiyon parametreleriyle standart Python tip belirteçlerini kullanarak istek parametrelerini ve gövdelerini ilan etmek mümkün değildir. +İki parametre alan fonksiyonlar etrafında tasarlanmıştır: bir “request” ve bir “response”. Sonra request'ten parçalar “okur”, response'a parçalar “yazarsınız”. Bu tasarım nedeniyle, fonksiyon parametreleriyle standart Python tip belirteçlerini kullanarak request parametrelerini ve body'lerini ilan etmek mümkün değildir. -Dolayısıyla veri doğrulama, dönüşüm ve dökümantasyon kodda yapılmalı; otomatik olmaz. Ya da Hug’da olduğu gibi Falcon’un üzerine bir framework olarak uygulanmalıdır. Falcon’un tasarımından etkilenen ve tek bir request objesi ile response objesini parametre olarak alan diğer framework’lerde de aynı ayrım vardır. +Dolayısıyla veri doğrulama, serileştirme ve dökümantasyon kodda yapılmalı; otomatik olmaz. Ya da Hug’da olduğu gibi Falcon’un üzerine bir framework olarak uygulanmalıdır. Falcon’un tasarımından etkilenen ve tek bir request objesi ile response objesini parametre olarak alan diğer framework’lerde de aynı ayrım vardır. /// tip | **FastAPI**'ye ilham olan Harika performans elde etmenin yollarını bulmak. -Hug ile birlikte (Hug, Falcon’a dayanır) **FastAPI**'de fonksiyonlarda opsiyonel bir `response` parametresi ilan edilmesi fikrine ilham vermek. FastAPI'de bu parametre çoğunlukla header, cookie ve alternatif durum kodlarını ayarlamak için kullanılır. +Hug ile birlikte (Hug, Falcon’a dayanır) **FastAPI**'de fonksiyonlarda bir `response` parametresi ilan edilmesi fikrine ilham vermek. + +FastAPI'de bu parametre opsiyoneldir ve çoğunlukla header, cookie ve alternatif durum kodlarını ayarlamak için kullanılır. /// @@ -303,7 +305,7 @@ Hug ile birlikte (Hug, Falcon’a dayanır) **FastAPI**'de fonksiyonlarda opsiyo * Bu tiplere bağlı doğrulama ve dökümantasyon sağlar. * Bağımlılık enjeksiyonu sistemi vardır. -Pydantic gibi doğrulama, dönüşüm ve dökümantasyon için üçüncü parti bir kütüphane kullanmaz; kendi içinde sağlar. Bu yüzden bu veri tipi tanımlarını tekrar kullanmak o kadar kolay olmaz. +Pydantic gibi doğrulama, serileştirme ve dökümantasyon için üçüncü parti bir kütüphane kullanmaz; kendi içinde sağlar. Bu yüzden bu veri tipi tanımlarını tekrar kullanmak o kadar kolay olmaz. Biraz daha ayrıntılı yapılandırma ister. Ve ASGI yerine WSGI tabanlı olduğundan, Uvicorn, Starlette ve Sanic gibi araçların yüksek performansından faydalanmaya yönelik tasarlanmamıştır. @@ -333,7 +335,7 @@ Nadir bir özelliği daha vardı: aynı framework ile hem API’lar hem de CLI Senkron Python web framework’leri için önceki standart olan WSGI’ye dayandığından, WebSocket vb. şeyleri işleyemez, ancak yine de yüksek performansa sahiptir. -/// info | Bilgi +/// note | Not Hug, Python dosyalarındaki import’ları otomatik sıralayan harika bir araç olan [`isort`](https://github.com/timothycrosley/isort)’un geliştiricisi Timothy Crosley tarafından geliştirildi. @@ -353,11 +355,11 @@ Ayrıca header ve cookie ayarlamak için fonksiyonlarda `response` parametresi i **FastAPI**’yi inşa etmeye karar vermeden hemen önce **APIStar** sunucusunu buldum. Aradığım şeylerin neredeyse hepsine sahipti ve harika bir tasarımı vardı. -Python tip belirteçleriyle parametreleri ve istekleri ilan eden bir framework’ün gördüğüm ilk örneklerindendi (NestJS ve Molten’dan önce). Aşağı yukarı Hug ile aynı zamanlarda buldum; ancak APIStar, OpenAPI standardını kullanıyordu. +Python tip belirteçleriyle parametreleri ve request'leri ilan eden bir framework’ün gördüğüm ilk örneklerindendi (NestJS ve Molten’dan önce). Aşağı yukarı Hug ile aynı zamanlarda buldum; ancak APIStar, OpenAPI standardını kullanıyordu. -Farklı yerlerdeki aynı tip belirteçlerine dayanarak otomatik veri doğrulama, veri dönüşümü ve OpenAPI şeması üretimi vardı. +Farklı yerlerdeki aynı tip belirteçlerine dayanarak otomatik veri doğrulama, veri serileştirme ve OpenAPI şeması üretimi vardı. -Gövde şema tanımları Pydantic’tekiyle aynı Python tip belirteçlerini kullanmıyordu; biraz daha Marshmallow’a benziyordu. Bu yüzden editör desteği o kadar iyi olmazdı; yine de APIStar mevcut en iyi seçenekti. +Body şema tanımları Pydantic’tekiyle aynı Python tip belirteçlerini kullanmıyordu; biraz daha Marshmallow’a benziyordu. Bu yüzden editör desteği o kadar iyi olmazdı; yine de APIStar mevcut en iyi seçenekti. O dönem kıyaslamalarda en iyi performansa sahipti (sadece Starlette tarafından geçiliyordu). @@ -373,7 +375,7 @@ Artık bir API web framework’ü değildi; geliştirici Starlette’e odaklanma Şimdi APIStar, bir web framework’ü değil, OpenAPI spesifikasyonlarını doğrulamak için araçlar takımından ibaret. -/// info | Bilgi +/// note | Not APIStar, aşağıdakilerin de yaratıcısı olan Tom Christie tarafından geliştirildi: @@ -387,7 +389,7 @@ APIStar, aşağıdakilerin de yaratıcısı olan Tom Christie tarafından geliş Var olmak. -Aynı Python tipleriyle (hem veri doğrulama, dönüşüm ve dökümantasyon) birden çok şeyi ilan etmek ve aynı anda harika editör desteği sağlamak, bence dahiyane bir fikirdi. +Aynı Python tipleriyle (hem veri doğrulama, serileştirme ve dökümantasyon) birden çok şeyi ilan etmek ve aynı anda harika editör desteği sağlamak, bence dahiyane bir fikirdi. Uzun süre benzer bir framework arayıp birçok alternatifi denedikten sonra, APIStar mevcut en iyi seçenekti. @@ -401,7 +403,7 @@ Sonra APIStar bir sunucu olarak var olmaktan çıktı ve Starlette oluşturuldu; ### [Pydantic](https://docs.pydantic.dev/) { #pydantic } -Pydantic, Python tip belirteçlerine dayalı olarak veri doğrulama, dönüşüm ve dökümantasyon (JSON Schema kullanarak) tanımlamak için bir kütüphanedir. +Pydantic, Python tip belirteçlerine dayalı olarak veri doğrulama, serileştirme ve dökümantasyon (JSON Schema kullanarak) tanımlamak için bir kütüphanedir. Bu onu aşırı sezgisel kılar. @@ -409,7 +411,7 @@ Marshmallow ile karşılaştırılabilir. Kıyaslamalarda Marshmallow’dan daha /// tip | **FastAPI** bunu şurada kullanır -Tüm veri doğrulama, veri dönüşümü ve JSON Schema tabanlı otomatik model dökümantasyonunu halletmekte. +Tüm veri doğrulama, veri serileştirme ve JSON Schema tabanlı otomatik model dökümantasyonunu halletmekte. **FastAPI** daha sonra bu JSON Schema verisini alır ve (yaptığı diğer şeylerin yanı sıra) OpenAPI içine yerleştirir. @@ -427,9 +429,9 @@ Starlette, yüksek performanslı asyncio servisleri oluşturmak için ideal, haf * WebSocket desteği. * Süreç içi arka plan görevleri. * Başlatma ve kapatma olayları. -* HTTPX üzerinde geliştirilmiş test istemcisi. -* CORS, GZip, Statik Dosyalar, Streaming cevaplar. -* Oturum (Session) ve Cookie desteği. +* HTTPX üzerinde geliştirilmiş test client'ı. +* CORS, GZip, Statik Dosyalar, Streaming response'lar. +* Session ve Cookie desteği. * %100 test kapsamı. * %100 tip anotasyonlu kod tabanı. * Az sayıda zorunlu bağımlılık. @@ -438,7 +440,7 @@ Starlette, şu anda test edilen en hızlı Python framework’üdür. Yalnızca Starlette, temel web mikroframework işlevselliğinin tamamını sağlar. -Ancak otomatik veri doğrulama, dönüşüm veya dökümantasyon sağlamaz. +Ancak otomatik veri doğrulama, serileştirme veya dökümantasyon sağlamaz. **FastAPI**’nin bunun üzerine eklediği ana şeylerden biri, Pydantic kullanarak, bütünüyle Python tip belirteçlerine dayalı bu özelliklerdir. Buna ek olarak bağımlılık enjeksiyonu sistemi, güvenlik yardımcıları, OpenAPI şema üretimi vb. gelir. @@ -464,7 +466,7 @@ Dolayısıyla Starlette ile yapabildiğiniz her şeyi, adeta “turbo şarjlı S Uvicorn, uvloop ve httptools üzerinde inşa edilmiş, ışık hızında bir ASGI sunucusudur. -Bir web framework’ü değil, bir sunucudur. Örneğin path’lere göre yönlendirme araçları sağlamaz; bunu Starlette (veya **FastAPI**) gibi bir framework üstte sağlar. +Bir web framework’ü değil, bir sunucudur. Örneğin path’lere göre routing araçları sağlamaz; bunu Starlette (veya **FastAPI**) gibi bir framework üstte sağlar. Starlette ve **FastAPI** için önerilen sunucudur. diff --git a/docs/tr/docs/async.md b/docs/tr/docs/async.md index 5acf5c145..b65756587 100644 --- a/docs/tr/docs/async.md +++ b/docs/tr/docs/async.md @@ -82,12 +82,12 @@ Bu "başka bir şeyi beklemek" genelde işlemci ve RAM hızına kıyasla nispete * programınızın sisteme verdiği içeriğin diske yazılması * uzak bir API işlemi * bir veritabanı işleminin bitmesi -* bir veritabanı sorgusunun sonuç döndürmesi +* bir veritabanı query'sinin sonuç döndürmesi * vb. Çalışma süresi çoğunlukla I/O işlemlerini beklemekle geçtiğinden, bunlara "I/O bound" işlemler denir. -"Bunun" asenkron" denmesinin sebebi, bilgisayarın / programın yavaş görevle "senkronize" olmak, görev tam bittiği anda orada olup görev sonucunu almak ve işe devam etmek için hiçbir şey yapmadan beklemek zorunda olmamasıdır. +Buna "asenkron" denmesinin sebebi, bilgisayarın / programın yavaş görevle "senkronize" olmak, görev tam bittiği anda orada olup görev sonucunu almak ve işe devam etmek için hiçbir şey yapmadan beklemek zorunda olmamasıdır. Bunun yerine "asenkron" bir sistem olarak, görev bittiğinde, bilgisayarın / programın o sırada yaptığı işi bitirmesi için biraz (birkaç mikrosaniye) sırada bekleyebilir ve sonra sonuçları almak üzere geri dönüp onlarla çalışmaya devam edebilir. @@ -139,7 +139,7 @@ Aşkınla burgerleri yiyip güzel vakit geçiriyorsunuz. ✨ -/// note | Bilgi +/// note | Not Harika çizimler: [Ketrina Thompson](https://www.instagram.com/ketrinadrawsalot). 🎨 @@ -205,7 +205,7 @@ Sadece yiyorsunuz ve iş bitiyor. ⏹ Vaktin çoğu tezgâhın önünde 🕙 beklemekle geçtiğinden, pek konuşma ya da flört olmadı. 😞 -/// note | Bilgi +/// note | Not Harika çizimler: [Ketrina Thompson](https://www.instagram.com/ketrinadrawsalot). 🎨 @@ -239,9 +239,9 @@ Muhtemelen, bankada 🏦 işlerini hallederken aşkını 😍 yanında götürme Bu, çoğu web uygulaması için de geçerlidir. -Çok fazla kullanıcı vardır; ancak sunucunuz, iyi olmayan bağlantılarından gelen istekleri 🕙 bekler. +Çok fazla kullanıcı vardır; ancak sunucunuz, onların pek iyi olmayan bağlantıları üzerinden request'lerin gelmesini 🕙 bekler. -Ve sonra yanıtların geri gelmesini yine 🕙 bekler. +Ardından response'ların geri gelmesini yine 🕙 bekler. Bu "beklemeler" 🕙 mikrosaniyelerle ölçülür; ama hepsi toplandığında sonuçta oldukça fazla bekleme olur. diff --git a/docs/tr/docs/deployment/cloud.md b/docs/tr/docs/deployment/cloud.md index b263ecc57..92a631734 100644 --- a/docs/tr/docs/deployment/cloud.md +++ b/docs/tr/docs/deployment/cloud.md @@ -16,7 +16,7 @@ FastAPI Cloud, *FastAPI and friends* açık kaynak projelerinin birincil sponsor ## Bulut Sağlayıcılar - Sponsorlar { #cloud-providers-sponsors } -Diğer bazı bulut sağlayıcılar da ✨ [**FastAPI'ye sponsor olur**](../help-fastapi.md#sponsor-the-author) ✨. 🙇 +Diğer bazı bulut sağlayıcılar da ✨ [**FastAPI'ye sponsor olur**](https://github.com/sponsors/tiangolo) ✨. 🙇 Kılavuzlarını takip etmek ve servislerini denemek için onları da değerlendirmek isteyebilirsiniz: diff --git a/docs/tr/docs/deployment/concepts.md b/docs/tr/docs/deployment/concepts.md index 211e2ab51..ee62ef647 100644 --- a/docs/tr/docs/deployment/concepts.md +++ b/docs/tr/docs/deployment/concepts.md @@ -1,5 +1,6 @@ # Deployment Kavramları { #deployments-concepts } + Bir **FastAPI** uygulamasını (hatta genel olarak herhangi bir web API'yi) deploy ederken, muhtemelen önemseyeceğiniz bazı kavramlar vardır. Bu kavramları kullanarak, **uygulamanızı deploy etmek** için **en uygun** yöntemi bulabilirsiniz. Önemli kavramlardan bazıları şunlardır: diff --git a/docs/tr/docs/deployment/docker.md b/docs/tr/docs/deployment/docker.md index 3f73ec1ef..aebde767b 100644 --- a/docs/tr/docs/deployment/docker.md +++ b/docs/tr/docs/deployment/docker.md @@ -26,7 +26,7 @@ COPY ./app /code/app CMD ["fastapi", "run", "app/main.py", "--port", "80"] -# If running behind a proxy like Nginx or Traefik add --proxy-headers +# Nginx veya Traefik gibi bir proxy arkasında çalıştırıyorsanız --proxy-headers ekleyin # CMD ["fastapi", "run", "app/main.py", "--port", "80", "--proxy-headers"] ``` @@ -243,14 +243,14 @@ Aşağıda açıklandığı gibi `CMD` talimatının **her zaman** **exec form** ✅ **Exec** form: ```Dockerfile -# ✅ Do this +# ✅ Bunu yapın CMD ["fastapi", "run", "app/main.py", "--port", "80"] ``` ⛔️ **Shell** form: ```Dockerfile -# ⛔️ Don't do this +# ⛔️ Bunu yapmayın CMD fastapi run app/main.py --port 80 ``` diff --git a/docs/tr/docs/deployment/https.md b/docs/tr/docs/deployment/https.md index 1b8f34e5c..98fd9a230 100644 --- a/docs/tr/docs/deployment/https.md +++ b/docs/tr/docs/deployment/https.md @@ -17,7 +17,7 @@ Bir kullanıcı gözüyle **HTTPS’in temellerini öğrenmek** için [https://h * HTTPS için **server**’ın, **üçüncü bir taraf** tarafından verilen **"sertifikalara"** sahip olması gerekir. * Bu sertifikalar aslında üçüncü tarafça "üretilmez", üçüncü taraftan **temin edilir**. * Sertifikaların bir **geçerlilik süresi** vardır. - * Süresi **dolar**. + * Süreleri **sona erer**. * Sonrasında **yenilenmeleri**, üçüncü taraftan **yeniden temin edilmeleri** gerekir. * Bağlantının şifrelenmesi **TCP seviyesinde** gerçekleşir. * Bu, **HTTP’nin bir katman altıdır**. @@ -169,7 +169,7 @@ Bu şekilde TLS Termination Proxy, birden fazla uygulama için **birden fazla do ### Sertifika Yenileme { #certificate-renewal } -Gelecekte bir noktada, her sertifikanın süresi **dolar** (temin edildikten yaklaşık 3 ay sonra). +Gelecekte bir noktada, her sertifikanın süresi **sona erer** (temin edildikten yaklaşık 3 ay sonra). Ardından başka bir program (bazı durumlarda ayrı bir programdır, bazı durumlarda aynı TLS Termination Proxy olabilir) Let's Encrypt ile konuşup sertifika(ları) yeniler. diff --git a/docs/tr/docs/deployment/manually.md b/docs/tr/docs/deployment/manually.md index de3d14348..2a2b16818 100644 --- a/docs/tr/docs/deployment/manually.md +++ b/docs/tr/docs/deployment/manually.md @@ -1,5 +1,6 @@ # Bir Sunucuyu Manuel Olarak Çalıştırın { #run-a-server-manually } + ## `fastapi run` Komutunu Kullanın { #use-the-fastapi-run-command } Kısacası, FastAPI uygulamanızı sunmak için `fastapi run` kullanın: diff --git a/docs/tr/docs/editor-support.md b/docs/tr/docs/editor-support.md index 47182834e..d279152cb 100644 --- a/docs/tr/docs/editor-support.md +++ b/docs/tr/docs/editor-support.md @@ -2,7 +2,7 @@ Resmi [FastAPI Extension](https://marketplace.visualstudio.com/items?itemName=FastAPILabs.fastapi-vscode), FastAPI geliştirme akışınızı iyileştirir: *path operation* keşfi, gezinme, FastAPI Cloud’a deploy ve canlı log akışı. -Daha fazla ayrıntı için, GitHub deposundaki README’ye bakın: [GitHub repository](https://github.com/fastapi/fastapi-vscode). +Daha fazla ayrıntı için, GitHub deposundaki README’ye bakın: [GitHub deposu](https://github.com/fastapi/fastapi-vscode). ## Kurulum ve Yükleme { #setup-and-installation } diff --git a/docs/tr/docs/environment-variables.md b/docs/tr/docs/environment-variables.md index f34c859e0..b54e1cbfd 100644 --- a/docs/tr/docs/environment-variables.md +++ b/docs/tr/docs/environment-variables.md @@ -19,10 +19,10 @@ Python’a ihtiyaç duymadan, **shell (terminal)** içinde ortam değişkenleri
```console -// You could create an env var MY_NAME with +// MY_NAME adlı bir env var'ı şöyle oluşturabilirsiniz $ export MY_NAME="Wade Wilson" -// Then you could use it with other programs, like +// Sonra bunu diğer programlarla şöyle kullanabilirsiniz $ echo "Hello $MY_NAME" Hello Wade Wilson @@ -37,10 +37,10 @@ Hello Wade Wilson
```console -// Create an env var MY_NAME +// MY_NAME adlı bir env var oluşturun $ $Env:MY_NAME = "Wade Wilson" -// Use it with other programs, like +// Bunu diğer programlarla şöyle kullanın $ echo "Hello $Env:MY_NAME" Hello Wade Wilson @@ -78,20 +78,20 @@ Sonrasında bu Python programını çalıştırabilirsiniz:
```console -// Here we don't set the env var yet +// Burada env var'ı henüz ayarlamıyoruz $ python main.py -// As we didn't set the env var, we get the default value +// Env var'ı ayarlamadığımız için varsayılan değeri alırız Hello World from Python -// But if we create an environment variable first +// Ama önce bir ortam değişkeni oluşturursak $ export MY_NAME="Wade Wilson" -// And then call the program again +// Sonra programı tekrar çağırırsak $ python main.py -// Now it can read the environment variable +// Artık ortam değişkenini okuyabilir Hello Wade Wilson from Python ``` @@ -105,20 +105,20 @@ Hello Wade Wilson from Python
```console -// Here we don't set the env var yet +// Burada env var'ı henüz ayarlamıyoruz $ python main.py -// As we didn't set the env var, we get the default value +// Env var'ı ayarlamadığımız için varsayılan değeri alırız Hello World from Python -// But if we create an environment variable first +// Ama önce bir ortam değişkeni oluşturursak $ $Env:MY_NAME = "Wade Wilson" -// And then call the program again +// Sonra programı tekrar çağırırsak $ python main.py -// Now it can read the environment variable +// Artık ortam değişkenini okuyabilir Hello Wade Wilson from Python ``` @@ -136,14 +136,14 @@ Bunu yapmak için, program komutunun hemen öncesinde ve aynı satırda tanımla
```console -// Create an env var MY_NAME in line for this program call +// Bu program çağrısı için aynı satırda MY_NAME adlı bir env var oluşturun $ MY_NAME="Wade Wilson" python main.py -// Now it can read the environment variable +// Artık ortam değişkenini okuyabilir Hello Wade Wilson from Python -// The env var no longer exists afterwards +// Sonrasında env var artık mevcut değildir $ python main.py Hello World from Python diff --git a/docs/tr/docs/features.md b/docs/tr/docs/features.md index 1f034d690..9a85863b7 100644 --- a/docs/tr/docs/features.md +++ b/docs/tr/docs/features.md @@ -99,7 +99,7 @@ Artık anahtar adlarını yanlış yazmak, dokümana gidip gelmek ya da sonunda Her şey için mantıklı **varsayılanlar** ve her yerde isteğe bağlı yapılandırmalar vardır. Tüm parametreler, ihtiyacınızı karşılayacak şekilde ince ayar yapılarak tanımlamak istediğiniz API’yi oluşturabilir. -Ancak varsayılan hâliyle hepsi **“hemen çalışır”**. +Ancak varsayılan hâliyle hepsi **"hemen çalışır"**. ### Doğrulama { #validation } @@ -149,7 +149,7 @@ FastAPI, son derece kolay kullanımlı ama son derece güçlü bir - Supported Python versions + Supported Python versions

@@ -45,11 +45,11 @@ Temel özellikleri şunlardır: * **Hızlı**: Çok yüksek performanslı, **NodeJS** ve **Go** ile eşit düzeyde (Starlette ve Pydantic sayesinde). [Mevcut en hızlı Python framework'lerinden biri](#performance). * **Kodlaması Hızlı**: Özellik geliştirme hızını yaklaşık %200 ile %300 aralığında artırır. * * **Daha az hata**: İnsan (geliştirici) kaynaklı hataları yaklaşık %40 azaltır. * -* **Sezgisel**: Harika bir editör desteği. Her yerde Tamamlama. Hata ayıklamaya daha az zaman. +* **Sezgisel**: Harika bir editör desteği. Her yerde Tamamlama. Hata ayıklamaya daha az zaman. * **Kolay**: Kullanımı ve öğrenmesi kolay olacak şekilde tasarlandı. Doküman okumaya daha az zaman. * **Kısa**: Kod tekrarını minimize eder. Her parametre tanımından birden fazla özellik. Daha az hata. * **Sağlam**: Production'a hazır kod elde edersiniz. Otomatik etkileşimli dokümantasyon ile birlikte. -* **Standardlara dayalı**: API'lar için açık standartlara dayalıdır (ve tamamen uyumludur); [OpenAPI](https://github.com/OAI/OpenAPI-Specification) (önceden Swagger olarak biliniyordu) ve [JSON Schema](https://json-schema.org/). +* **Standartlara dayalı**: API'lar için açık standartlara dayalıdır (ve tamamen uyumludur); [OpenAPI](https://github.com/OAI/OpenAPI-Specification) (önceden Swagger olarak biliniyordu) ve [JSON Schema](https://json-schema.org/). * tahmin, production uygulamalar geliştiren dahili bir geliştirme ekibinin yaptığı testlere dayanmaktadır. diff --git a/docs/tr/docs/project-generation.md b/docs/tr/docs/project-generation.md index 6c73a942d..3dfe7a9a7 100644 --- a/docs/tr/docs/project-generation.md +++ b/docs/tr/docs/project-generation.md @@ -1,5 +1,6 @@ # Full Stack FastAPI Şablonu { #full-stack-fastapi-template } + Şablonlar genellikle belirli bir kurulumla gelir, ancak esnek ve özelleştirilebilir olacak şekilde tasarlanırlar. Bu sayede şablonu projenizin gereksinimlerine göre değiştirip uyarlayabilir, çok iyi bir başlangıç noktası olarak kullanabilirsiniz. 🏁 Bu şablonu başlangıç için kullanabilirsiniz; çünkü ilk kurulumun, güvenliğin, veritabanının ve bazı API endpoint'lerinin önemli bir kısmı sizin için zaten hazırlanmıştır. diff --git a/docs/tr/docs/python-types.md b/docs/tr/docs/python-types.md index f3a3447f1..69f256d00 100644 --- a/docs/tr/docs/python-types.md +++ b/docs/tr/docs/python-types.md @@ -1,5 +1,6 @@ # Python Tiplerine Giriş { #python-types-intro } + Python, isteğe bağlı "type hints" (diğer adıyla "type annotations") desteğine sahiptir. Bu **"type hints"** veya annotations, bir değişkenin tip'ini bildirmeye yarayan özel bir sözdizimidir. diff --git a/docs/tr/docs/tutorial/bigger-applications.md b/docs/tr/docs/tutorial/bigger-applications.md index b44d5bb9b..81866e8f7 100644 --- a/docs/tr/docs/tutorial/bigger-applications.md +++ b/docs/tr/docs/tutorial/bigger-applications.md @@ -17,16 +17,16 @@ Diyelim ki şöyle bir dosya yapınız var: ``` . ├── app -│   ├── __init__.py -│   ├── main.py -│   ├── dependencies.py -│   └── routers -│   │ ├── __init__.py -│   │ ├── items.py -│   │ └── users.py -│   └── internal -│   ├── __init__.py -│   └── admin.py +│ ├── __init__.py +│ ├── main.py +│ ├── dependencies.py +│ └── routers +│ │ ├── __init__.py +│ │ ├── items.py +│ │ └── users.py +│ └── internal +│ ├── __init__.py +│ └── admin.py ``` /// tip | İpucu @@ -77,7 +77,7 @@ Diyelim ki sadece kullanıcıları yönetmeye ayrılmış dosyanız `/app/router Kullanıcılarla ilgili *path operation*’ları, kodun geri kalanından ayrı tutmak istiyorsunuz; böylece düzenli kalır. -Namun bu hâlâ aynı **FastAPI** uygulaması/web API’sinin bir parçasıdır (aynı "Python Package" içinde). +Ancak bu hâlâ aynı **FastAPI** uygulaması/web API’sinin bir parçasıdır (aynı "Python Package" içinde). Bu module için *path operation*’ları `APIRouter` kullanarak oluşturabilirsiniz. @@ -123,7 +123,7 @@ Bu yüzden onları ayrı bir `dependencies` module’üne koyuyoruz (`app/depend Örneği basit tutmak için uydurma bir header kullanıyoruz. -Namun gerçek senaryolarda, entegre [Security yardımcı araçlarını](security/index.md) kullanarak daha iyi sonuç alırsınız. +Ancak gerçek senaryolarda, entegre [Security yardımcı araçlarını](security/index.md) kullanarak daha iyi sonuç alırsınız. /// @@ -138,7 +138,7 @@ Diyelim ki uygulamanızdaki "items" ile ilgili endpoint'ler de `app/routers/item Bu, `app/routers/users.py` ile aynı yapıdadır. -Namun biraz daha akıllı davranıp kodu sadeleştirmek istiyoruz. +Ancak biraz daha akıllı davranıp kodu sadeleştirmek istiyoruz. Bu module’deki tüm *path operation*’ların şu ortak özelliklere sahip olduğunu biliyoruz: @@ -230,7 +230,7 @@ from .dependencies import get_token_header * `dependencies` module’ünü bul (`app/routers/dependencies.py` gibi hayali bir dosya)... * ve oradan `get_token_header` function’ını import et. -Namun o dosya yok; bizim dependency’lerimiz `app/dependencies.py` dosyasında. +Ancak o dosya yok; bizim dependency’lerimiz `app/dependencies.py` dosyasında. Uygulama/dosya yapımızın nasıl göründüğünü hatırlayın: @@ -437,7 +437,7 @@ Sonuç olarak, uygulamamızda `admin` module’ündeki her bir *path operation* * `get_token_header` dependency’si. * `418` response’u. 🍵 -Namun bu sadece bizim uygulamamızdaki o `APIRouter` için geçerlidir; onu kullanan diğer kodlar için değil. +Ancak bu sadece bizim uygulamamızdaki o `APIRouter` için geçerlidir; onu kullanan diğer kodlar için değil. Dolayısıyla örneğin diğer projeler aynı `APIRouter`’ı farklı bir authentication yöntemiyle kullanabilir. @@ -490,7 +490,7 @@ Komuta dosya yolunu da verebilirsiniz, örneğin: $ fastapi dev app/main.py ``` -Namun o zaman her `fastapi` komutunu çalıştırdığınızda doğru yolu hatırlayıp geçirmeniz gerekir. +Ancak o zaman her `fastapi` komutunu çalıştırdığınızda doğru yolu hatırlayıp geçirmeniz gerekir. Ayrıca, diğer araçlar uygulamayı bulamayabilir; örneğin [VS Code Eklentisi](../editor-support.md) veya [FastAPI Cloud](https://fastapicloud.com). Bu yüzden `pyproject.toml` içinde `entrypoint` kullanmanız önerilir. diff --git a/docs/tr/docs/tutorial/body-nested-models.md b/docs/tr/docs/tutorial/body-nested-models.md index bcf3057ef..d9f30c862 100644 --- a/docs/tr/docs/tutorial/body-nested-models.md +++ b/docs/tr/docs/tutorial/body-nested-models.md @@ -1,5 +1,6 @@ # Body - İç İçe Modeller { #body-nested-models } + **FastAPI** ile (Pydantic sayesinde) istediğiniz kadar derin iç içe geçmiş modelleri tanımlayabilir, doğrulayabilir, dokümante edebilir ve kullanabilirsiniz. ## List alanları { #list-fields } diff --git a/docs/tr/docs/tutorial/body.md b/docs/tr/docs/tutorial/body.md index 74b3d3707..d05bd54ec 100644 --- a/docs/tr/docs/tutorial/body.md +++ b/docs/tr/docs/tutorial/body.md @@ -1,5 +1,6 @@ # Request Body { #request-body } + Bir client'ten (örneğin bir tarayıcıdan) API'nize veri göndermeniz gerektiğinde, bunu **request body** olarak gönderirsiniz. Bir **request** body, client'in API'nize gönderdiği veridir. Bir **response** body ise API'nizin client'e gönderdiği veridir. diff --git a/docs/tr/docs/tutorial/debugging.md b/docs/tr/docs/tutorial/debugging.md index 48f99e99c..b73d65137 100644 --- a/docs/tr/docs/tutorial/debugging.md +++ b/docs/tr/docs/tutorial/debugging.md @@ -59,7 +59,7 @@ Yani örneğin `importer.py` adında başka bir dosyanız var ve içinde şunlar ```Python from myapp import app -# Some more code +# Biraz daha kod ``` bu durumda `myapp.py` içindeki otomatik oluşturulan `__name__` değişkeni `"__main__"` değerine sahip olmaz. diff --git a/docs/tr/docs/tutorial/dependencies/dependencies-with-yield.md b/docs/tr/docs/tutorial/dependencies/dependencies-with-yield.md index 7f56a95c7..be9588297 100644 --- a/docs/tr/docs/tutorial/dependencies/dependencies-with-yield.md +++ b/docs/tr/docs/tutorial/dependencies/dependencies-with-yield.md @@ -111,7 +111,7 @@ Ama ihtiyaç duyarsanız diye burada. 🤓 {* ../../docs_src/dependencies/tutorial008b_an_py310.py hl[18:22,31] *} -Exception yakalayıp buna göre özel bir response oluşturmak istiyorsanız bir [Custom Exception Handler](../handling-errors.md#install-custom-exception-handlers) oluşturun. +Exception yakalayıp buna göre özel bir response oluşturmak istiyorsanız bir [Özel Exception Handler](../handling-errors.md#install-custom-exception-handlers) oluşturun. ## `yield` ve `except` ile Dependency'ler { #dependencies-with-yield-and-except } @@ -233,7 +233,8 @@ participant operation as Path Operation `yield` kullanan dependency'ler, zaman içinde farklı kullanım senaryolarını kapsamak ve bazı sorunları düzeltmek için gelişti. -FastAPI'nin farklı sürümlerinde nelerin değiştiğini görmek isterseniz, advanced guide'da şu bölümü okuyabilirsiniz: [Advanced Dependencies - Dependencies with `yield`, `HTTPException`, `except` and Background Tasks](../../advanced/advanced-dependencies.md#dependencies-with-yield-httpexception-except-and-background-tasks). +FastAPI'nin farklı sürümlerinde nelerin değiştiğini görmek isterseniz, gelişmiş kılavuzda şu bölümü okuyabilirsiniz: [Gelişmiş Dependency'ler - `yield`, `HTTPException`, `except` ve Background Tasks ile Dependency'ler](../../advanced/advanced-dependencies.md#dependencies-with-yield-httpexception-except-and-background-tasks). + ## Context Managers { #context-managers } ### "Context Managers" Nedir? { #what-are-context-managers } diff --git a/docs/tr/docs/tutorial/extra-data-types.md b/docs/tr/docs/tutorial/extra-data-types.md index 93ae034b2..da0aab01b 100644 --- a/docs/tr/docs/tutorial/extra-data-types.md +++ b/docs/tr/docs/tutorial/extra-data-types.md @@ -53,7 +53,7 @@ Kullanabileceğiniz ek veri tiplerinden bazıları şunlardır: ## Örnek { #example } -Yukarıdaki tiplerden bazılarını kullanan parametrelere sahip bir örnek *path operation* şöyle: +Yukarıdaki tiplerden bazılarını kullanan parametrelere sahip bir örnek *path operation*: {* ../../docs_src/extra_data_types/tutorial001_an_py310.py hl[1,3,12:16] *} diff --git a/docs/tr/docs/tutorial/extra-models.md b/docs/tr/docs/tutorial/extra-models.md index d25a80aad..9a499b30b 100644 --- a/docs/tr/docs/tutorial/extra-models.md +++ b/docs/tr/docs/tutorial/extra-models.md @@ -1,5 +1,6 @@ # Ek Modeller { #extra-models } + Önceki örnekten devam edersek, birbiriyle ilişkili birden fazla modelin olması oldukça yaygındır. Bu durum özellikle kullanıcı modellerinde sık görülür, çünkü: diff --git a/docs/tr/docs/tutorial/first-steps.md b/docs/tr/docs/tutorial/first-steps.md index 1d5cf6fbc..5147f2577 100644 --- a/docs/tr/docs/tutorial/first-steps.md +++ b/docs/tr/docs/tutorial/first-steps.md @@ -1,5 +1,6 @@ # İlk Adımlar { #first-steps } + En sade FastAPI dosyası şu şekilde görünür: {* ../../docs_src/first_steps/tutorial001_py310.py *} diff --git a/docs/tr/docs/tutorial/handling-errors.md b/docs/tr/docs/tutorial/handling-errors.md index b90e186a6..0339bde14 100644 --- a/docs/tr/docs/tutorial/handling-errors.md +++ b/docs/tr/docs/tutorial/handling-errors.md @@ -93,7 +93,7 @@ Ve bu exception’ı FastAPI ile global olarak handle etmek istiyorsunuz. Burada `/unicorns/yolo` için request atarsanız, *path operation* bir `UnicornException` `raise` eder. -Namun bu, `unicorn_exception_handler` tarafından handle edilir. +Ancak bu, `unicorn_exception_handler` tarafından handle edilir. Böylece HTTP status code’u `418` olan, JSON içeriği şu şekilde temiz bir hata response’u alırsınız: diff --git a/docs/tr/docs/tutorial/index.md b/docs/tr/docs/tutorial/index.md index 5dacd280a..e30f3bfbb 100644 --- a/docs/tr/docs/tutorial/index.md +++ b/docs/tr/docs/tutorial/index.md @@ -76,11 +76,11 @@ $ pip install "fastapi[standard]" /// note | Not -`pip install "fastapi[standard]"` ile kurduğunuzda, bazı varsayılan opsiyonel standard bağımlılıklarla birlikte gelir. Bunlara `fastapi-cloud-cli` da dahildir; bu sayede [FastAPI Cloud](https://fastapicloud.com)'a deploy edebilirsiniz. +`pip install "fastapi[standard]"` ile kurduğunuzda, bazı varsayılan opsiyonel standart bağımlılıklarla birlikte gelir. Bunlara `fastapi-cloud-cli` da dahildir; bu sayede [FastAPI Cloud](https://fastapicloud.com)'a deploy edebilirsiniz. Bu opsiyonel bağımlılıkları istemiyorsanız bunun yerine `pip install fastapi` kurabilirsiniz. -Standard bağımlılıkları kurmak istiyor ama `fastapi-cloud-cli` olmasın diyorsanız, `pip install "fastapi[standard-no-fastapi-cloud-cli]"` ile kurabilirsiniz. +Standart bağımlılıkları kurmak istiyor ama `fastapi-cloud-cli` olmasın diyorsanız, `pip install "fastapi[standard-no-fastapi-cloud-cli]"` ile kurabilirsiniz. /// diff --git a/docs/tr/docs/tutorial/metadata.md b/docs/tr/docs/tutorial/metadata.md index 5ed3f8580..8b97505e4 100644 --- a/docs/tr/docs/tutorial/metadata.md +++ b/docs/tr/docs/tutorial/metadata.md @@ -11,7 +11,7 @@ OpenAPI spesifikasyonunda ve otomatik API doküman arayüzlerinde kullanılan ş | `title` | `str` | API'nin başlığı. | | `summary` | `str` | API'nin kısa özeti. OpenAPI 3.1.0, FastAPI 0.99.0 sürümünden itibaren mevcut. | | `description` | `str` | API'nin kısa açıklaması. Markdown kullanabilir. | -| `version` | `string` | API'nin sürümü. Bu, OpenAPI'nin değil, kendi uygulamanızın sürümüdür. Örneğin `2.5.0`. | +| `version` | `str` | API'nin sürümü. Bu, OpenAPI'nin değil, kendi uygulamanızın sürümüdür. Örneğin `2.5.0`. | | `terms_of_service` | `str` | API'nin Kullanım Koşulları (Terms of Service) için bir URL. Verilirse, URL formatında olmalıdır. | | `contact` | `dict` | Yayınlanan API için iletişim bilgileri. Birden fazla alan içerebilir.
contact alanları
ParametreTipAçıklama
namestrİletişim kişisi/kuruluşunu tanımlayan ad.
urlstrİletişim bilgilerine işaret eden URL. URL formatında OLMALIDIR.
emailstrİletişim kişisi/kuruluşunun e-posta adresi. E-posta adresi formatında OLMALIDIR.
| | `license_info` | `dict` | Yayınlanan API için lisans bilgileri. Birden fazla alan içerebilir.
license_info alanları
ParametreTipAçıklama
namestrZORUNLU (license_info ayarlanmışsa). API için kullanılan lisans adı.
identifierstrAPI için bir [SPDX](https://spdx.org/licenses/) lisans ifadesi. identifier alanı, url alanıyla karşılıklı olarak dışlayıcıdır (ikisi aynı anda kullanılamaz). OpenAPI 3.1.0, FastAPI 0.99.0 sürümünden itibaren mevcut.
urlstrAPI için kullanılan lisansa ait URL. URL formatında OLMALIDIR.
| diff --git a/docs/tr/docs/tutorial/path-operation-configuration.md b/docs/tr/docs/tutorial/path-operation-configuration.md index 75057bb26..ee4bc8739 100644 --- a/docs/tr/docs/tutorial/path-operation-configuration.md +++ b/docs/tr/docs/tutorial/path-operation-configuration.md @@ -1,5 +1,6 @@ # Path Operation Yapılandırması { #path-operation-configuration } + Onu yapılandırmak için *path operation decorator*’ınıza geçebileceğiniz çeşitli parametreler vardır. /// warning | Uyarı diff --git a/docs/tr/docs/tutorial/query-params-str-validations.md b/docs/tr/docs/tutorial/query-params-str-validations.md index 7abea5a2f..831cfcb1d 100644 --- a/docs/tr/docs/tutorial/query-params-str-validations.md +++ b/docs/tr/docs/tutorial/query-params-str-validations.md @@ -1,5 +1,6 @@ # Query Parametreleri ve String Doğrulamaları { #query-parameters-and-string-validations } + **FastAPI**, parametreleriniz için ek bilgi ve doğrulamalar (validation) tanımlamanıza izin verir. Örnek olarak şu uygulamayı ele alalım: diff --git a/docs/tr/docs/tutorial/query-params.md b/docs/tr/docs/tutorial/query-params.md index 56e191f05..4f12c4fad 100644 --- a/docs/tr/docs/tutorial/query-params.md +++ b/docs/tr/docs/tutorial/query-params.md @@ -1,4 +1,4 @@ -# Sorgu Parametreleri { #query-parameters } +# Query Parametreleri { #query-parameters } Fonksiyonda path parametrelerinin parçası olmayan diğer parametreleri tanımladığınızda, bunlar otomatik olarak "query" parametreleri olarak yorumlanır. @@ -71,7 +71,7 @@ Ayrıca, **FastAPI** path parametresi olan `item_id`'nin bir path parametresi ol /// -## Sorgu parametresi tip dönüşümü { #query-parameter-type-conversion } +## Query parametresi tip dönüşümü { #query-parameter-type-conversion } `bool` tipleri de tanımlayabilirsiniz, ve bunlar dönüştürülür: diff --git a/docs/tr/docs/tutorial/request-files.md b/docs/tr/docs/tutorial/request-files.md index d1f4656d9..ab54cfd39 100644 --- a/docs/tr/docs/tutorial/request-files.md +++ b/docs/tr/docs/tutorial/request-files.md @@ -64,7 +64,7 @@ Tipi `UploadFile` olan bir dosya parametresi tanımlayın: * Bu sayede görüntüler, videolar, büyük binary’ler vb. gibi büyük dosyalarda tüm belleği tüketmeden iyi çalışır. * Upload edilen dosyadan metadata alabilirsiniz. * [file-like](https://docs.python.org/3/glossary.html#term-file-like-object) bir `async` arayüze sahiptir. -* [`SpooledTemporaryFile`](https://docs.python.org/3/library/tempfile.html#tempfile.SpooledTemporaryFile) nesnesini dışa açar; bunu, file-like nesne bekleyen diğer library’lere doğrudan geçebilirsiniz. +* Gerçek bir Python [`SpooledTemporaryFile`](https://docs.python.org/3/library/tempfile.html#tempfile.SpooledTemporaryFile) nesnesini dışa açar; bunu, file-like nesne bekleyen diğer library’lere doğrudan geçebilirsiniz. ### `UploadFile` { #uploadfile } diff --git a/docs/tr/docs/tutorial/request-forms.md b/docs/tr/docs/tutorial/request-forms.md index 12139992f..57f10fb1b 100644 --- a/docs/tr/docs/tutorial/request-forms.md +++ b/docs/tr/docs/tutorial/request-forms.md @@ -1,5 +1,6 @@ # Form Verisi { #form-data } + JSON yerine form alanlarını almanız gerektiğinde `Form` kullanabilirsiniz. /// note | Not diff --git a/docs/tr/docs/tutorial/response-status-code.md b/docs/tr/docs/tutorial/response-status-code.md index fa028265b..7acba44ed 100644 --- a/docs/tr/docs/tutorial/response-status-code.md +++ b/docs/tr/docs/tutorial/response-status-code.md @@ -1,4 +1,4 @@ -# Response Status Code { #response-status-code } +# Response Status Code'u { #response-status-code } Bir response model tanımlayabildiğiniz gibi, herhangi bir *path operation* içinde `status_code` parametresiyle response için kullanılacak HTTP status code'u da belirtebilirsiniz: @@ -18,7 +18,7 @@ Bir response model tanımlayabildiğiniz gibi, herhangi bir *path operation* iç `status_code` parametresi, HTTP status code'u içeren bir sayı alır. -/// note | Bilgi +/// note | Not Alternatif olarak `status_code`, Python'un [`http.HTTPStatus`](https://docs.python.org/3/library/http.html#http.HTTPStatus)'ı gibi bir `IntEnum` da alabilir. diff --git a/docs/tr/docs/tutorial/schema-extra-example.md b/docs/tr/docs/tutorial/schema-extra-example.md index 5c886f862..03f9eac9c 100644 --- a/docs/tr/docs/tutorial/schema-extra-example.md +++ b/docs/tr/docs/tutorial/schema-extra-example.md @@ -24,7 +24,7 @@ Aynı tekniği JSON Schema’yı genişletmek ve kendi özel ek bilgilerinizi ek /// -/// note | Bilgi +/// note | Not OpenAPI 3.1.0 (FastAPI 0.99.0’dan beri kullanılıyor), **JSON Schema** standardının bir parçası olan `examples` için destek ekledi. @@ -123,7 +123,7 @@ FastAPI’de OpenAPI’ye özel `examples`’ı, şu araçlar için `openapi_exa /// tip | İpucu -Zaten **FastAPI** sürümü **0.99.0 veya üzerini** kullanıyorsanız, büyük olasılıkla bu detayları **atlanabilirsiniz**. +Zaten **FastAPI** sürümü **0.99.0 veya üzerini** kullanıyorsanız, büyük olasılıkla bu detayları **atlayabilirsiniz**. Bunlar daha çok OpenAPI 3.1.0’ın henüz mevcut olmadığı eski sürümler için geçerlidir. @@ -155,7 +155,7 @@ OpenAPI ayrıca spesifikasyonun diğer bölümlerine de `example` ve `examples` * `File()` * `Form()` -/// note | Bilgi +/// note | Not Bu eski OpenAPI’ye özel `examples` parametresi, FastAPI `0.103.0` sürümünden beri `openapi_examples` olarak kullanılıyor. @@ -171,7 +171,7 @@ Ve artık, deprecated olan eski tekil (ve özel) `example` alanına kıyasla bu JSON Schema’daki bu yeni `examples` alanı, OpenAPI’de başka yerlerde kullanılan (yukarıda anlatılan) metadata’lı `dict` yapısından farklı olarak **sadece örneklerden oluşan bir `list`**’tir. -/// note | Bilgi +/// note | Not OpenAPI 3.1.0, JSON Schema ile bu yeni ve daha basit entegrasyonla yayımlandıktan sonra bile bir süre, otomatik dokümantasyonu sağlayan araç Swagger UI OpenAPI 3.1.0’ı desteklemiyordu (5.0.0 sürümünden beri destekliyor 🎉). diff --git a/docs/tr/docs/tutorial/security/first-steps.md b/docs/tr/docs/tutorial/security/first-steps.md index 457f53e8e..0d19aa0ec 100644 --- a/docs/tr/docs/tutorial/security/first-steps.md +++ b/docs/tr/docs/tutorial/security/first-steps.md @@ -26,7 +26,7 @@ Güvenliği yönetmek için **FastAPI**’nin sunduğu araçları kullanalım. /// note | Not -The [`python-multipart`](https://github.com/Kludex/python-multipart) paketi, `pip install "fastapi[standard]"` komutunu çalıştırdığınızda **FastAPI** ile birlikte otomatik olarak kurulur. +[`python-multipart`](https://github.com/Kludex/python-multipart) paketi, `pip install "fastapi[standard]"` komutunu çalıştırdığınızda **FastAPI** ile birlikte otomatik olarak kurulur. Ancak `pip install fastapi` komutunu kullanırsanız, `python-multipart` paketi varsayılan olarak dahil edilmez. diff --git a/docs/tr/docs/tutorial/security/get-current-user.md b/docs/tr/docs/tutorial/security/get-current-user.md index 429f6dcc9..2883c06fe 100644 --- a/docs/tr/docs/tutorial/security/get-current-user.md +++ b/docs/tr/docs/tutorial/security/get-current-user.md @@ -14,7 +14,7 @@ Bize mevcut kullanıcıyı verecek şekilde düzenleyelim. Body'leri bildirmek için Pydantic'i nasıl kullanıyorsak, aynı şekilde onu başka her yerde de kullanabiliriz: -{* ../../docs_src/security/tutorial002_an_py310.py hl[5,12:6] *} +{* ../../docs_src/security/tutorial002_an_py310.py hl[5,12:16] *} ## `get_current_user` dependency'si oluşturun { #create-a-get-current-user-dependency } diff --git a/docs/tr/docs/tutorial/security/oauth2-jwt.md b/docs/tr/docs/tutorial/security/oauth2-jwt.md index 077d23f1b..df893ec82 100644 --- a/docs/tr/docs/tutorial/security/oauth2-jwt.md +++ b/docs/tr/docs/tutorial/security/oauth2-jwt.md @@ -18,7 +18,7 @@ eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4 Şifrelenmiş değildir; yani herkes içeriğindeki bilgiyi geri çıkarabilir. -Namun imzalanmıştır. Bu yüzden, sizin ürettiğiniz bir token'ı aldığınızda, gerçekten onu sizin ürettiğinizi doğrulayabilirsiniz. +Ancak imzalanmıştır. Bu yüzden, sizin ürettiğiniz bir token'ı aldığınızda, gerçekten onu sizin ürettiğinizi doğrulayabilirsiniz. Bu şekilde, örneğin 1 haftalık süre sonu (expiration) olan bir token oluşturabilirsiniz. Sonra kullanıcı ertesi gün token ile geri geldiğinde, kullanıcının hâlâ sisteminizde oturum açmış olduğunu bilirsiniz. @@ -120,7 +120,7 @@ Bir tane de kullanıcıyı authenticate edip geri döndüren bir yardımcı fonk `authenticate_user`, veritabanında var olmayan bir username ile çağrıldığında, yine de sahte (dummy) bir hash'e karşı `verify_password` çalıştırıyoruz. -Bu, username geçerli olsun ya da olmasın endpoint'in yaklaşık aynı sürede yanıt vermesini sağlar; böylece mevcut username'leri saymaya yarayabilecek zamanlama saldırılarını (timing attacks) engeller. +Bu, username geçerli olsun ya da olmasın endpoint'in yaklaşık aynı sürede yanıt vermesini sağlar; böylece mevcut username'leri saymaya yarayabilecek **timing attacks** saldırılarını engeller. /// note | Not diff --git a/docs/tr/docs/tutorial/security/simple-oauth2.md b/docs/tr/docs/tutorial/security/simple-oauth2.md index 961e70400..fdc318019 100644 --- a/docs/tr/docs/tutorial/security/simple-oauth2.md +++ b/docs/tr/docs/tutorial/security/simple-oauth2.md @@ -146,7 +146,7 @@ UserInDB( /// note | Not -`**user_dict` için daha kapsamlı bir açıklama için [**Extra Models** dokümantasyonundaki ilgili bölüme](../extra-models.md#about-user-in-dict) geri dönüp bakın. +`**user_dict` için daha kapsamlı bir açıklama için [**Extra Models** dokümantasyonundaki ilgili bölüme](../extra-models.md#about-user-in-model-dump) geri dönüp bakın. /// diff --git a/docs/tr/docs/tutorial/sql-databases.md b/docs/tr/docs/tutorial/sql-databases.md index ea4b9ebc4..1145c209a 100644 --- a/docs/tr/docs/tutorial/sql-databases.md +++ b/docs/tr/docs/tutorial/sql-databases.md @@ -352,6 +352,6 @@ $ fastapi dev ## Özet { #recap } -Bir SQL veritabanıyla etkileşim kurmak için [**SQLModel**](https://sqlmodel.tiangolo.com/) kullanabilir ve *data model* ile *table model* yaklaşımıyla kodu sadeleştirebilirsiniz. +Bir SQL veritabanıyla etkileşim kurmak için [**SQLModel**](https://sqlmodel.tiangolo.com/) kullanabilir ve *data model*’ler ile *table model*’ler kullanarak kodu sadeleştirebilirsiniz. **SQLModel** dokümantasyonunda çok daha fazlasını öğrenebilirsiniz; **FastAPI** ile SQLModel kullanımı için daha uzun bir mini [tutorial](https://sqlmodel.tiangolo.com/tutorial/fastapi/) da bulunuyor. 🚀 diff --git a/docs/tr/docs/tutorial/static-files.md b/docs/tr/docs/tutorial/static-files.md index 13c20cfa9..b271139a2 100644 --- a/docs/tr/docs/tutorial/static-files.md +++ b/docs/tr/docs/tutorial/static-files.md @@ -2,6 +2,14 @@ `StaticFiles` kullanarak bir dizindeki statik dosyaları otomatik olarak sunabilirsiniz. +/// tip | İpucu + +Bir frontend host etmeniz gerekiyorsa, bunun yerine `app.frontend()` kullanın; bununla ilgili bilgileri [Frontend](frontend.md) bölümünde okuyabilirsiniz. + +`app.frontend()`, altında `StaticFiles` kullanır ve frontend'ler için client-side routing'i handle etmek gibi ek avantajlar sağlar. + +/// + ## `StaticFiles` Kullanımı { #use-staticfiles } * `StaticFiles`'ı import edin. diff --git a/docs/tr/docs/tutorial/testing.md b/docs/tr/docs/tutorial/testing.md index 4e223d983..df5248ff4 100644 --- a/docs/tr/docs/tutorial/testing.md +++ b/docs/tr/docs/tutorial/testing.md @@ -75,6 +75,7 @@ Ayrıca **FastAPI** uygulamanız birden fazla dosya/modül vb. ile de oluşturul `main.py` dosyasında **FastAPI** uygulamanız bulunuyor olsun: + {* ../../docs_src/app_testing/app_a_py310/main.py *} ### Test Dosyası { #testing-file } @@ -93,6 +94,7 @@ Bu dosya aynı package içinde olduğu için, `main` modülünden (`main.py`) `a {* ../../docs_src/app_testing/app_a_py310/test_main.py hl[3] *} + ...ve test kodunu da öncekiyle aynı şekilde yazabilirsiniz. ## Test Etme: Genişletilmiş Örnek { #testing-extended-example } @@ -127,6 +129,7 @@ Sonrasında `test_main.py` dosyanızı genişletilmiş testlerle güncelleyebili {* ../../docs_src/app_testing/app_b_an_py310/test_main.py *} + Client'ın request içinde bir bilgi göndermesi gerektiğinde ve bunu nasıl yapacağınızı bilemediğinizde, `httpx` ile nasıl yapılacağını aratabilirsiniz (Google) ya da HTTPX’in tasarımı Requests’e dayandığı için `requests` ile nasıl yapıldığını da arayabilirsiniz. Sonra testlerinizde aynısını uygularsınız. diff --git a/docs/tr/docs/virtual-environments.md b/docs/tr/docs/virtual-environments.md index 4db3b132f..60494ac12 100644 --- a/docs/tr/docs/virtual-environments.md +++ b/docs/tr/docs/virtual-environments.md @@ -53,7 +53,7 @@ $ cd awesome-project ## Virtual Environment Oluşturun { #create-a-virtual-environment } -Bir Python projesi üzerinde **ilk kez** çalışmaya başladığınızda, **virtual environment**'i projenizin içinde oluşturun. +Bir Python projesi üzerinde **ilk kez** çalışmaya başladığınızda, virtual environment'i **projenizin içinde** oluşturun. /// tip | İpucu @@ -443,6 +443,8 @@ Böylece `python` çalıştırdığınızda, o virtual environment içinden (ve Artık projeniz üzerinde çalışmaya başlayabilirsiniz. + + /// tip | İpucu Yukarıdaki her şeyin aslında ne olduğunu anlamak ister misiniz? @@ -517,7 +519,7 @@ $ pip install "harry==3" Sonuç olarak global Python environment'ınızda `harry` versiyon `3` kurulu olur. -Ve `philosophers-stone`'u tekrar çalıştırmaya kalkarsanız, `harry` versiyon `1`e ihtiyaç duyduğu için **çalışmama** ihtimali vardır. +Ve `philosophers-stone`'u tekrar çalıştırmaya kalkarsanız, `harry` versiyon `1`'e ihtiyaç duyduğu için **çalışmama** ihtimali vardır. ```mermaid flowchart LR From 60237faadb926f616b2b8947e1f793779844d22a Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Wed, 1 Jul 2026 13:47:39 +0000 Subject: [PATCH 371/462] =?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 1f1c25b0a..548310c7d 100644 --- a/docs/en/docs/release-notes.md +++ b/docs/en/docs/release-notes.md @@ -9,6 +9,7 @@ hide: ### Translations +* 🌐 Update translations for tr (update-outdated). PR [#15891](https://github.com/fastapi/fastapi/pull/15891) by [@tiangolo](https://github.com/tiangolo). * 🌐 Update translations for pt (update-outdated). PR [#15893](https://github.com/fastapi/fastapi/pull/15893) by [@tiangolo](https://github.com/tiangolo). * 🌐 Update translations for zh (update-outdated). PR [#15898](https://github.com/fastapi/fastapi/pull/15898) by [@tiangolo](https://github.com/tiangolo). * 🌐 Update translations for uk (update-outdated). PR [#15900](https://github.com/fastapi/fastapi/pull/15900) by [@tiangolo](https://github.com/tiangolo). From c2cdfcbcdd0394c8b4dcf3bd30fca535091e5524 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebasti=C3=A1n=20Ram=C3=ADrez?= Date: Wed, 1 Jul 2026 15:50:11 +0200 Subject: [PATCH 372/462] =?UTF-8?q?=F0=9F=8C=90=20Update=20translations=20?= =?UTF-8?q?for=20es=20(update-outdated)=20(#15892)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: github-actions[bot] Co-authored-by: Yurii Motov --- docs/es/docs/_llm-test.md | 4 +- .../docs/advanced/additional-status-codes.md | 1 + .../es/docs/advanced/advanced-dependencies.md | 4 +- docs/es/docs/advanced/dataclasses.md | 2 +- docs/es/docs/advanced/events.md | 6 +-- docs/es/docs/advanced/generate-clients.md | 18 +------ docs/es/docs/advanced/json-base64-bytes.md | 8 ++-- docs/es/docs/advanced/openapi-callbacks.md | 2 +- .../advanced/response-change-status-code.md | 2 +- docs/es/docs/advanced/response-cookies.md | 6 +-- docs/es/docs/advanced/response-headers.md | 1 + .../docs/advanced/security/oauth2-scopes.md | 1 + docs/es/docs/advanced/settings.md | 22 ++++----- docs/es/docs/advanced/stream-data.md | 10 ++-- docs/es/docs/advanced/wsgi.md | 1 + docs/es/docs/alternatives.md | 16 +++---- docs/es/docs/async.md | 8 ++-- docs/es/docs/deployment/cloud.md | 2 +- docs/es/docs/deployment/concepts.md | 1 + docs/es/docs/deployment/docker.md | 1 + docs/es/docs/deployment/https.md | 2 +- docs/es/docs/deployment/manually.md | 2 +- docs/es/docs/editor-support.md | 2 +- docs/es/docs/environment-variables.md | 1 + docs/es/docs/features.md | 4 +- docs/es/docs/help-fastapi.md | 2 +- docs/es/docs/how-to/configure-swagger-ui.md | 8 ++-- .../docs/how-to/custom-request-and-route.md | 12 ++--- docs/es/docs/how-to/graphql.md | 2 +- ...migrate-from-pydantic-v1-to-pydantic-v2.md | 18 +++++++ .../docs/how-to/separate-openapi-schemas.md | 2 +- docs/es/docs/index.md | 4 +- docs/es/docs/project-generation.md | 18 +++---- docs/es/docs/python-types.md | 24 +++++----- docs/es/docs/tutorial/bigger-applications.md | 30 ++++++------ docs/es/docs/tutorial/body-nested-models.md | 2 +- docs/es/docs/tutorial/body.md | 1 + docs/es/docs/tutorial/debugging.md | 1 + .../dependencies/dependencies-with-yield.md | 1 + docs/es/docs/tutorial/extra-data-types.md | 1 + docs/es/docs/tutorial/extra-models.md | 2 +- docs/es/docs/tutorial/first-steps.md | 8 ++-- docs/es/docs/tutorial/handling-errors.md | 16 +++---- docs/es/docs/tutorial/index.md | 2 +- docs/es/docs/tutorial/metadata.md | 6 +-- .../tutorial/path-operation-configuration.md | 6 +-- .../tutorial/query-params-str-validations.md | 48 +++++++++---------- docs/es/docs/tutorial/query-params.md | 1 + docs/es/docs/tutorial/request-files.md | 6 +-- docs/es/docs/tutorial/request-forms.md | 6 +-- docs/es/docs/tutorial/response-status-code.md | 1 + docs/es/docs/tutorial/schema-extra-example.md | 2 +- docs/es/docs/tutorial/security/first-steps.md | 6 +-- .../tutorial/security/get-current-user.md | 8 ++-- docs/es/docs/tutorial/security/oauth2-jwt.md | 1 + .../docs/tutorial/security/simple-oauth2.md | 2 +- docs/es/docs/tutorial/sql-databases.md | 6 +-- docs/es/docs/tutorial/static-files.md | 8 ++++ docs/es/docs/tutorial/testing.md | 4 +- docs/es/docs/virtual-environments.md | 12 +++-- 60 files changed, 217 insertions(+), 187 deletions(-) diff --git a/docs/es/docs/_llm-test.md b/docs/es/docs/_llm-test.md index d0ffcc540..e5191d9da 100644 --- a/docs/es/docs/_llm-test.md +++ b/docs/es/docs/_llm-test.md @@ -197,7 +197,7 @@ Aquí algunas cosas envueltas en elementos HTML "abbr" (algunas son inventadas): ### El abbr da una frase completa y una explicación { #the-abbr-gives-a-full-phrase-and-an-explanation } * MDN -* I/O. +* I/O. //// @@ -464,7 +464,7 @@ Para instrucciones específicas del idioma, mira p. ej. la sección `### Heading * el middleware * la aplicación móvil * el módulo -* el mount +* el mounting * la red * el origen * el override diff --git a/docs/es/docs/advanced/additional-status-codes.md b/docs/es/docs/advanced/additional-status-codes.md index 5c0ab6980..ea6db5feb 100644 --- a/docs/es/docs/advanced/additional-status-codes.md +++ b/docs/es/docs/advanced/additional-status-codes.md @@ -1,5 +1,6 @@ # Códigos de Estado Adicionales { #additional-status-codes } + Por defecto, **FastAPI** devolverá los responses usando un `JSONResponse`, colocando el contenido que devuelves desde tu *path operation* dentro de ese `JSONResponse`. Usará el código de estado por defecto o el que configures en tu *path operation*. diff --git a/docs/es/docs/advanced/advanced-dependencies.md b/docs/es/docs/advanced/advanced-dependencies.md index f3053ffe3..47e9d72a0 100644 --- a/docs/es/docs/advanced/advanced-dependencies.md +++ b/docs/es/docs/advanced/advanced-dependencies.md @@ -10,7 +10,7 @@ Imaginemos que queremos tener una dependencia que revise si el parámetro de que Pero queremos poder parametrizar ese contenido fijo. -## Una *instance* "callable" { #a-callable-instance } +## Una instance "callable" { #a-callable-instance } En Python hay una forma de hacer que una instance de una clase sea un "callable". @@ -108,7 +108,7 @@ Como verás abajo, esto es muy similar al comportamiento anterior a la versión Hay algunos casos de uso con condiciones específicas que podrían beneficiarse del comportamiento antiguo de ejecutar el código de salida de dependencias con `yield` antes de enviar la response. -Por ejemplo, imagina que tienes código que usa una sesión de base de datos en una dependencia con `yield` solo para verificar un usuario, pero la sesión de base de datos no se vuelve a usar en la *path operation function*, solo en la dependencia, y la response tarda mucho en enviarse, como un `StreamingResponse` que envía datos lentamente, pero que por alguna razón no usa la base de datos. +Por ejemplo, imagina que tienes código que usa una sesión de base de datos en una dependencia con `yield` solo para verificar un usuario, pero la sesión de base de datos no se vuelve a usar en la *path operation function*, solo en la dependencia, **y** la response tarda mucho en enviarse, como un `StreamingResponse` que envía datos lentamente, pero que por alguna razón no usa la base de datos. En este caso, la sesión de base de datos se mantendría hasta que la response termine de enviarse, pero si no la usas, entonces no sería necesario mantenerla. diff --git a/docs/es/docs/advanced/dataclasses.md b/docs/es/docs/advanced/dataclasses.md index e49cada43..9c988dc37 100644 --- a/docs/es/docs/advanced/dataclasses.md +++ b/docs/es/docs/advanced/dataclasses.md @@ -82,7 +82,7 @@ En ese caso, simplemente puedes intercambiar los `dataclasses` estándar con `py Puedes combinar `dataclasses` con otras anotaciones de tipos en muchas combinaciones diferentes para formar estructuras de datos complejas. -Revisa las anotaciones en el código arriba para ver más detalles específicos. +Revisa los consejos de anotación en el código arriba para ver más detalles específicos. ## Aprende Más { #learn-more } diff --git a/docs/es/docs/advanced/events.md b/docs/es/docs/advanced/events.md index e69d6b054..1d221e033 100644 --- a/docs/es/docs/advanced/events.md +++ b/docs/es/docs/advanced/events.md @@ -6,13 +6,13 @@ De la misma manera, puedes definir lógica (código) que debería ser ejecutada Debido a que este código se ejecuta antes de que la aplicación **comience** a tomar requests, y justo después de que **termine** de manejarlos, cubre todo el **lifespan** de la aplicación (la palabra "lifespan" será importante en un momento 😉). -Esto puede ser muy útil para configurar **recursos** que necesitas usar para toda la app, y que son **compartidos** entre requests, y/o que necesitas **limpiar** después. Por ejemplo, un pool de conexiones a una base de datos, o cargando un modelo de machine learning compartido. +Esto puede ser muy útil para configurar **recursos** que necesitas usar para toda la app, y que son **compartidos** entre requests, y/o que necesitas **limpiar** después. Por ejemplo, un pool de conexiones a una base de datos, o cargando un modelo de Machine Learning compartido. ## Caso de Uso { #use-case } Empecemos con un ejemplo de **caso de uso** y luego veamos cómo resolverlo con esto. -Imaginemos que tienes algunos **modelos de machine learning** que quieres usar para manejar requests. 🤖 +Imaginemos que tienes algunos **modelos de Machine Learning** que quieres usar para manejar requests. 🤖 Los mismos modelos son compartidos entre requests, por lo que no es un modelo por request, o uno por usuario o algo similar. @@ -32,7 +32,7 @@ Creamos una función asíncrona `lifespan()` con `yield` así: {* ../../docs_src/events/tutorial003_py310.py hl[16,19] *} -Aquí estamos simulando la operación costosa de *startup* de cargar el modelo poniendo la función del (falso) modelo en el diccionario con modelos de machine learning antes del `yield`. Este código será ejecutado **antes** de que la aplicación **comience a tomar requests**, durante el *startup*. +Aquí estamos simulando la operación costosa de *startup* de cargar el modelo poniendo la función del (falso) modelo en el diccionario con modelos de Machine Learning antes del `yield`. Este código será ejecutado **antes** de que la aplicación **comience a tomar requests**, durante el *startup*. Y luego, justo después del `yield`, quitaremos el modelo de memoria. Este código será ejecutado **después** de que la aplicación **termine de manejar requests**, justo antes del *shutdown*. Esto podría, por ejemplo, liberar recursos como la memoria o una GPU. diff --git a/docs/es/docs/advanced/generate-clients.md b/docs/es/docs/advanced/generate-clients.md index 51834d89c..a44c92294 100644 --- a/docs/es/docs/advanced/generate-clients.md +++ b/docs/es/docs/advanced/generate-clients.md @@ -20,20 +20,6 @@ FastAPI genera automáticamente especificaciones **OpenAPI 3.1**, así que cualq /// -## Generadores de SDKs de sponsors de FastAPI { #sdk-generators-from-fastapi-sponsors } - -Esta sección destaca soluciones **respaldadas por empresas** y **venture-backed** de compañías que sponsor FastAPI. Estos productos ofrecen **funcionalidades adicionales** e **integraciones** además de SDKs generados de alta calidad. - -Al ✨ [**ser sponsor de FastAPI**](../help-fastapi.md#sponsor-the-author) ✨, estas compañías ayudan a asegurar que el framework y su **ecosistema** se mantengan saludables y **sustentables**. - -Su sponsorship también demuestra un fuerte compromiso con la **comunidad** de FastAPI (tú), mostrando que no solo les importa ofrecer un **gran servicio**, sino también apoyar un **framework robusto y próspero**, FastAPI. 🙇 - -Por ejemplo, podrías querer probar: - -* [Stainless](https://www.stainless.com/?utm_source=fastapi&utm_medium=referral) - -Algunas de estas soluciones también pueden ser open source u ofrecer niveles gratuitos, así que puedes probarlas sin un compromiso financiero. Hay otros generadores de SDK comerciales disponibles y se pueden encontrar en línea. 🤓 - ## Crea un SDK de TypeScript { #create-a-typescript-sdk } Empecemos con una aplicación simple de FastAPI: @@ -52,7 +38,7 @@ Puedes ver esos esquemas porque fueron declarados con los modelos en la app. Esa información está disponible en el **OpenAPI schema** de la app, y luego se muestra en la documentación de la API. -Y esa misma información de los modelos que está incluida en OpenAPI es lo que puede usarse para **generar el código del cliente**. +Esa misma información de los modelos que está incluida en OpenAPI es lo que puede usarse para **generar el código del cliente**. ### Hey API { #hey-api } @@ -131,7 +117,7 @@ Puedes **modificar** la forma en que estos operation IDs son **generados** para En este caso tendrás que asegurarte de que cada operation ID sea **único** de alguna otra manera. -Por ejemplo, podrías asegurarte de que cada *path operation* tenga un tag, y luego generar el operation ID basado en el **tag** y el **name** de la *path operation* (el nombre de la función). +Por ejemplo, podrías asegurarte de que cada *path operation* tenga un tag, y luego generar el operation ID basado en el **tag** y el **nombre** de la *path operation* (el nombre de la función). ### Función personalizada para generar ID único { #custom-generate-unique-id-function } diff --git a/docs/es/docs/advanced/json-base64-bytes.md b/docs/es/docs/advanced/json-base64-bytes.md index 12936722c..8c0bcfe09 100644 --- a/docs/es/docs/advanced/json-base64-bytes.md +++ b/docs/es/docs/advanced/json-base64-bytes.md @@ -4,7 +4,7 @@ Si tu app necesita recibir y enviar datos JSON, pero necesitas incluir datos bin ## Base64 vs Archivos { #base64-vs-files } -Considera primero si puedes usar [Archivos en request](../tutorial/request-files.md) para subir datos binarios y [Response personalizada - FileResponse](./custom-response.md#fileresponse--fileresponse-) para enviar datos binarios, en lugar de codificarlos en JSON. +Considera primero si puedes usar [Archivos en request](../tutorial/request-files.md) para subir datos binarios y [Response personalizada - FileResponse](./custom-response.md#fileresponse) para enviar datos binarios, en lugar de codificarlos en JSON. JSON solo puede contener strings codificados en UTF-8, así que no puede contener bytes crudos. @@ -14,7 +14,7 @@ Usa base64 solo si definitivamente necesitas incluir datos binarios en JSON y no ## Pydantic `bytes` { #pydantic-bytes } -Puedes declarar un modelo de Pydantic con campos `bytes`, y luego usar `val_json_bytes` en la configuración del modelo para indicarle que use base64 para validar datos JSON de entrada; como parte de esa validación decodificará el string base64 en bytes. +Puedes declarar un modelo de Pydantic con campos `bytes`, y luego usar `val_json_bytes` en la configuración del modelo para indicarle que use base64 para *validar* datos JSON de entrada; como parte de esa validación decodificará el string base64 en bytes. {* ../../docs_src/json_base64_bytes/tutorial001_py310.py ln[1:9,29:35] hl[9] *} @@ -52,12 +52,12 @@ Recibirás una response como: ## Pydantic `bytes` para datos de salida { #pydantic-bytes-for-output-data } -También puedes usar campos `bytes` con `ser_json_bytes` en la configuración del modelo para datos de salida, y Pydantic serializará los bytes como base64 al generar la response JSON. +También puedes usar campos `bytes` con `ser_json_bytes` en la configuración del modelo para datos de salida, y Pydantic *serializará* los bytes como base64 al generar la response JSON. {* ../../docs_src/json_base64_bytes/tutorial001_py310.py ln[1:2,12:16,29,38:41] hl[16] *} ## Pydantic `bytes` para datos de entrada y salida { #pydantic-bytes-for-input-and-output-data } -Y por supuesto, puedes usar el mismo modelo configurado para usar base64 para manejar tanto la entrada (*validate*) con `val_json_bytes` como la salida (*serialize*) con `ser_json_bytes` al recibir y enviar datos JSON. +Y por supuesto, puedes usar el mismo modelo configurado para usar base64 para manejar tanto la entrada (*validar*) con `val_json_bytes` como la salida (*serializar*) con `ser_json_bytes` al recibir y enviar datos JSON. {* ../../docs_src/json_base64_bytes/tutorial001_py310.py ln[1:2,19:26,29,44:46] hl[23:26] *} diff --git a/docs/es/docs/advanced/openapi-callbacks.md b/docs/es/docs/advanced/openapi-callbacks.md index 49896b64b..6b04f2da0 100644 --- a/docs/es/docs/advanced/openapi-callbacks.md +++ b/docs/es/docs/advanced/openapi-callbacks.md @@ -173,7 +173,7 @@ Ahora usa el parámetro `callbacks` en el *decorador de path operation de tu API /// tip | Consejo -Observa que no estás pasando el router en sí (`invoices_callback_router`) a `callbacks=`, sino su `.routes`, como en `invoices_callback_router.routes`. **FastAPI** usará esas rutas para generar la documentación OpenAPI del callback. +Observa que no estás pasando el router en sí (`invoices_callback_router`) a `callbacks=`, sino su `.routes`, como en `invoices_callback_router.routes`. FastAPI usará esas rutas para generar la documentación OpenAPI del callback. /// diff --git a/docs/es/docs/advanced/response-change-status-code.md b/docs/es/docs/advanced/response-change-status-code.md index 859f484de..aa3c8bf42 100644 --- a/docs/es/docs/advanced/response-change-status-code.md +++ b/docs/es/docs/advanced/response-change-status-code.md @@ -2,7 +2,7 @@ Probablemente leíste antes que puedes establecer un [Código de Estado de Response](../tutorial/response-status-code.md) por defecto. -Pero en algunos casos necesitas devolver un código de estado diferente al predeterminado. +Pero en algunos casos necesitas devolver un código de estado diferente al por defecto. ## Caso de uso { #use-case } diff --git a/docs/es/docs/advanced/response-cookies.md b/docs/es/docs/advanced/response-cookies.md index e40a19129..917072cbe 100644 --- a/docs/es/docs/advanced/response-cookies.md +++ b/docs/es/docs/advanced/response-cookies.md @@ -1,6 +1,6 @@ # Cookies de Response { #response-cookies } -## Usar un parámetro `Response` { #use-a-response-parameter } +## Usa un parámetro `Response` { #use-a-response-parameter } Puedes declarar un parámetro de tipo `Response` en tu *path operation function*. @@ -16,11 +16,11 @@ Y si declaraste un `response_model`, todavía se utilizará para filtrar y conve También puedes declarar el parámetro `Response` en las dependencias, y establecer cookies (y headers) en ellas. -## Devolver una `Response` directamente { #return-a-response-directly } +## Devuelve una `Response` directamente { #return-a-response-directly } También puedes crear cookies al devolver una `Response` directamente en tu código. -Para hacer eso, puedes crear un response como se describe en [Devolver un Response Directamente](response-directly.md). +Para hacer eso, puedes crear un response como se describe en [Devuelve un Response Directamente](response-directly.md). Luego establece Cookies en ella, y luego devuélvela: diff --git a/docs/es/docs/advanced/response-headers.md b/docs/es/docs/advanced/response-headers.md index 06107eb2d..e2eb8f550 100644 --- a/docs/es/docs/advanced/response-headers.md +++ b/docs/es/docs/advanced/response-headers.md @@ -1,5 +1,6 @@ # Headers de Response { #response-headers } + ## Usa un parámetro `Response` { #use-a-response-parameter } Puedes declarar un parámetro de tipo `Response` en tu *path operation function* (como puedes hacer para cookies). diff --git a/docs/es/docs/advanced/security/oauth2-scopes.md b/docs/es/docs/advanced/security/oauth2-scopes.md index f9ddd19e3..e399cd855 100644 --- a/docs/es/docs/advanced/security/oauth2-scopes.md +++ b/docs/es/docs/advanced/security/oauth2-scopes.md @@ -1,5 +1,6 @@ # Scopes de OAuth2 { #oauth2-scopes } + Puedes usar scopes de OAuth2 directamente con **FastAPI**, están integrados para funcionar de manera fluida. Esto te permitiría tener un sistema de permisos más detallado, siguiendo el estándar de OAuth2, integrado en tu aplicación OpenAPI (y la documentación de la API). diff --git a/docs/es/docs/advanced/settings.md b/docs/es/docs/advanced/settings.md index 2411ddc45..e61229f0d 100644 --- a/docs/es/docs/advanced/settings.md +++ b/docs/es/docs/advanced/settings.md @@ -20,7 +20,7 @@ Eso significa que cualquier valor leído en Python desde una variable de entorno ## Pydantic `Settings` { #pydantic-settings } -Afortunadamente, Pydantic proporciona una gran utilidad para manejar estas configuraciones provenientes de variables de entorno con [Pydantic: Settings management](https://docs.pydantic.dev/latest/concepts/pydantic_settings/). +Afortunadamente, Pydantic proporciona una gran utilidad para manejar estas configuraciones provenientes de variables de entorno con [Pydantic: Gestión de Settings](https://docs.pydantic.dev/latest/concepts/pydantic_settings/). ### Instalar `pydantic-settings` { #install-pydantic-settings } @@ -120,7 +120,7 @@ También necesitarías un archivo `__init__.py` como viste en [Aplicaciones Más En algunas ocasiones podría ser útil proporcionar las configuraciones desde una dependencia, en lugar de tener un objeto global con `settings` que se use en todas partes. -Esto podría ser especialmente útil durante las pruebas, ya que es muy fácil sobrescribir una dependencia con tus propias configuraciones personalizadas. +Esto podría ser especialmente útil al escribir pruebas, ya que es muy fácil sobrescribir una dependencia con tus propias configuraciones personalizadas. ### El archivo de configuración { #the-config-file } @@ -148,9 +148,9 @@ Y luego podemos requerirlo desde la *path operation function* como una dependenc {* ../../docs_src/settings/app02_an_py310/main.py hl[17,19:21] *} -### Configuraciones y pruebas { #settings-and-testing } +### Configuraciones y escribir pruebas { #settings-and-testing } -Luego sería muy fácil proporcionar un objeto de configuraciones diferente durante las pruebas al crear una sobrescritura de dependencia para `get_settings`: +Luego sería muy fácil proporcionar un objeto de configuraciones diferente al escribir pruebas creando una sobrescritura de dependencia para `get_settings`: {* ../../docs_src/settings/app02_an_py310/test_main.py hl[9:10,13,21] *} @@ -160,7 +160,7 @@ Luego podemos probar que se está usando. ## Leer un archivo `.env` { #reading-a-env-file } -Si tienes muchas configuraciones que posiblemente cambien mucho, tal vez en diferentes entornos, podría ser útil ponerlos en un archivo y luego leerlos desde allí como si fueran variables de entorno. +Si tienes muchas configuraciones que posiblemente cambien mucho, tal vez en diferentes entornos, podría ser útil ponerlas en un archivo y luego leerlas desde allí como si fueran variables de entorno. Esta práctica es lo suficientemente común que tiene un nombre, estas variables de entorno generalmente se colocan en un archivo `.env`, y el archivo se llama un "dotenv". @@ -172,7 +172,7 @@ Pero un archivo dotenv realmente no tiene que tener ese nombre exacto. /// -Pydantic tiene soporte para leer desde estos tipos de archivos usando un paquete externo. Puedes leer más en [Pydantic Settings: Dotenv (.env) support](https://docs.pydantic.dev/latest/concepts/pydantic_settings/#dotenv-env-support). +Pydantic tiene soporte para leer desde estos tipos de archivos usando un paquete externo. Puedes leer más en [Pydantic Settings: soporte para Dotenv (.env)](https://docs.pydantic.dev/latest/concepts/pydantic_settings/#dotenv-env-support). /// tip | Consejo @@ -197,7 +197,7 @@ Y luego actualizar tu `config.py` con: /// tip | Consejo -El atributo `model_config` se usa solo para configuración de Pydantic. Puedes leer más en [Pydantic: Concepts: Configuration](https://docs.pydantic.dev/latest/concepts/config/). +El atributo `model_config` se usa solo para configuración de Pydantic. Puedes leer más en [Pydantic: Conceptos: Configuración](https://docs.pydantic.dev/latest/concepts/config/). /// @@ -289,14 +289,14 @@ participant execute as Ejecutar función En el caso de nuestra dependencia `get_settings()`, la función ni siquiera toma argumentos, por lo que siempre devuelve el mismo valor. -De esa manera, se comporta casi como si fuera solo una variable global. Pero como usa una función de dependencia, entonces podemos sobrescribirla fácilmente para las pruebas. +De esa manera, se comporta casi como si fuera solo una variable global. Pero como usa una función de dependencia, entonces podemos sobrescribirla fácilmente al escribir pruebas. -`@lru_cache` es parte de `functools`, que es parte del paquete estándar de Python, puedes leer más sobre él en las [docs de Python para `@lru_cache`](https://docs.python.org/3/library/functools.html#functools.lru_cache). +`@lru_cache` es parte de `functools`, que es parte del paquete estándar de Python, puedes leer más sobre él en la [documentación de Python para `@lru_cache`](https://docs.python.org/3/library/functools.html#functools.lru_cache). ## Resumen { #recap } Puedes usar Pydantic Settings para manejar las configuraciones o ajustes de tu aplicación, con todo el poder de los modelos de Pydantic. -* Al usar una dependencia, puedes simplificar las pruebas. +* Al usar una dependencia, puedes simplificar la escritura de pruebas. * Puedes usar archivos `.env` con él. -* Usar `@lru_cache` te permite evitar leer el archivo dotenv una y otra vez para cada request, mientras te permite sobrescribirlo durante las pruebas. +* Usar `@lru_cache` te permite evitar leer el archivo dotenv una y otra vez para cada request, mientras te permite sobrescribirlo al escribir pruebas. diff --git a/docs/es/docs/advanced/stream-data.md b/docs/es/docs/advanced/stream-data.md index 2db037e0a..68c89ce44 100644 --- a/docs/es/docs/advanced/stream-data.md +++ b/docs/es/docs/advanced/stream-data.md @@ -2,7 +2,7 @@ Si quieres transmitir datos que se puedan estructurar como JSON, deberías [Transmitir JSON Lines](../tutorial/stream-json-lines.md). -Pero si quieres transmitir datos binarios puros o strings, aquí tienes cómo hacerlo. +Pero si quieres **transmitir datos binarios puros** o strings, aquí tienes cómo hacerlo. /// note | Nota @@ -12,11 +12,11 @@ Añadido en FastAPI 0.134.0. ## Casos de uso { #use-cases } -Podrías usar esto si quieres transmitir strings puros, por ejemplo directamente de la salida de un servicio de AI LLM. +Podrías usar esto si quieres transmitir strings puros, por ejemplo directamente de la salida de un servicio de **AI LLM**. -También podrías usarlo para transmitir archivos binarios grandes, donde transmites cada bloque de datos a medida que lo lees, sin tener que leerlo todo en memoria de una sola vez. +También podrías usarlo para transmitir **archivos binarios grandes**, donde transmites cada bloque de datos a medida que lo lees, sin tener que leerlo todo en memoria de una sola vez. -También podrías transmitir video o audio de esta manera; incluso podría generarse mientras lo procesas y lo envías. +También podrías transmitir **video** o **audio** de esta manera; incluso podría generarse mientras lo procesas y lo envías. ## Un `StreamingResponse` con `yield` { #a-streamingresponse-with-yield } @@ -40,7 +40,7 @@ Como FastAPI no intentará convertir los datos a JSON con Pydantic ni serializar {* ../../docs_src/stream_data/tutorial001_py310.py ln[32:35] hl[33] *} -Esto también significa que con `StreamingResponse` tienes la libertad y la responsabilidad de producir y codificar los bytes de datos exactamente como necesites enviarlos, independientemente de las anotaciones de tipos. 🤓 +Esto también significa que con `StreamingResponse` tienes la **libertad** y la **responsabilidad** de producir y codificar los bytes de datos exactamente como necesites enviarlos, independientemente de las anotaciones de tipos. 🤓 ### Transmitir bytes { #stream-bytes } diff --git a/docs/es/docs/advanced/wsgi.md b/docs/es/docs/advanced/wsgi.md index 8afe215a1..c85b8cc89 100644 --- a/docs/es/docs/advanced/wsgi.md +++ b/docs/es/docs/advanced/wsgi.md @@ -1,5 +1,6 @@ # Incluyendo WSGI - Flask, Django, otros { #including-wsgi-flask-django-others } + Puedes montar aplicaciones WSGI como viste con [Sub Aplicaciones - Mounts](sub-applications.md), [Detrás de un Proxy](behind-a-proxy.md). Para eso, puedes usar el `WSGIMiddleware` y usarlo para envolver tu aplicación WSGI, por ejemplo, Flask, Django, etc. diff --git a/docs/es/docs/alternatives.md b/docs/es/docs/alternatives.md index 3bc1bf969..693e4d511 100644 --- a/docs/es/docs/alternatives.md +++ b/docs/es/docs/alternatives.md @@ -24,7 +24,7 @@ Fue creado para generar el HTML en el backend, no para crear APIs utilizadas por ### [Django REST Framework](https://www.django-rest-framework.org/) { #django-rest-framework } -El framework Django REST fue creado para ser un kit de herramientas flexible para construir APIs Web utilizando Django, mejorando sus capacidades API. +Django REST Framework fue creado para ser un toolkit flexible para construir APIs Web usando Django por debajo, para mejorar sus capacidades de API. Es utilizado por muchas empresas, incluidas Mozilla, Red Hat y Eventbrite. @@ -88,7 +88,7 @@ La forma en que lo usas es muy sencilla. Por ejemplo, para hacer un `GET` reques response = requests.get("http://example.com/some/url") ``` -La operación de path equivalente en FastAPI podría verse como: +La *path operation* API equivalente de FastAPI podría verse como: ```Python hl_lines="1" @app.get("/some/url") @@ -183,7 +183,7 @@ Pero la documentación todavía falta. Entonces APISpec fue creado. Es un plug-in para muchos frameworks (y hay un plug-in para Starlette también). -La manera en que funciona es que escribes la definición del esquema usando el formato YAML dentro del docstring de cada función que maneja un path. +La manera en que funciona es que escribes la definición del esquema usando el formato YAML dentro del docstring de cada función que maneja una ruta. Y genera esquemas OpenAPI. @@ -245,11 +245,11 @@ Logra algo algo similar a lo que se puede hacer con Flask-apispec. Tiene un sistema de inyección de dependencias integrado, inspirado por Angular 2. Requiere pre-registrar los "inyectables" (como todos los otros sistemas de inyección de dependencias que conozco), por lo que añade a la verbosidad y repetición de código. -Como los parámetros se describen con tipos de TypeScript (similar a las anotaciones de tipos en Python), el soporte editorial es bastante bueno. +Como los parámetros se describen con tipos de TypeScript (similar a las anotaciones de tipos en Python), el soporte del editor es bastante bueno. Pero como los datos de TypeScript no se preservan después de la compilación a JavaScript, no puede depender de los tipos para definir validación, serialización y documentación al mismo tiempo. Debido a esto y algunas decisiones de diseño, para obtener validación, serialización y generación automática del esquema, es necesario agregar decoradores en muchos lugares. Por lo tanto, se vuelve bastante verboso. -No puede manejar muy bien modelos anidados. Entonces, si el cuerpo JSON en la request es un objeto JSON que tiene campos internos que a su vez son objetos JSON anidados, no puede ser documentado y validado apropiadamente. +No puede manejar muy bien modelos anidados. Entonces, si el body JSON en la request es un objeto JSON que tiene campos internos que a su vez son objetos JSON anidados, no puede ser documentado y validado apropiadamente. /// tip | Inspiró a **FastAPI** a @@ -311,11 +311,11 @@ Requiere configuraciones un poquito más verbosas. Y dado que se basa en WSGI (e El sistema de inyección de dependencias requiere pre-registrar las dependencias y las dependencias se resuelven en base a los tipos declarados. Por lo tanto, no es posible declarar más de un "componente" que proporcione cierto tipo. -Los paths se declaran en un solo lugar, usando funciones declaradas en otros lugares (en lugar de usar decoradores que pueden colocarse justo encima de la función que maneja el endpoint). Esto se acerca más a cómo lo hace Django que a cómo lo hace Flask (y Starlette). Separa en el código cosas que están relativamente acopladas. +Las rutas se declaran en un solo lugar, usando funciones declaradas en otros lugares (en lugar de usar decoradores que pueden colocarse justo encima de la función que maneja el endpoint). Esto se acerca más a cómo lo hace Django que a cómo lo hace Flask (y Starlette). Separa en el código cosas que están relativamente acopladas. /// tip | Inspiró a **FastAPI** a -Definir validaciones extra para tipos de datos usando el valor "default" de los atributos del modelo. Esto mejora el soporte del editor y no estaba disponible en Pydantic antes. +Definir validaciones extra para tipos de datos usando el valor "por defecto" de los atributos del modelo. Esto mejora el soporte del editor y no estaba disponible en Pydantic antes. Esto en realidad inspiró la actualización de partes de Pydantic, para soportar el mismo estilo de declaración de validación (toda esta funcionalidad ya está disponible en Pydantic). @@ -433,7 +433,7 @@ Tiene: * CORS, GZip, Archivos estáticos, Responses en streaming. * Soporte para sesiones y cookies. * Cobertura de tests del 100%. -* code base 100% tipada. +* codebase 100% con anotaciones de tipos. * Pocas dependencias obligatorias. Starlette es actualmente el framework de Python más rápido probado. Solo superado por Uvicorn, que no es un framework, sino un servidor. diff --git a/docs/es/docs/async.md b/docs/es/docs/async.md index 299bd83e3..be64f4cbe 100644 --- a/docs/es/docs/async.md +++ b/docs/es/docs/async.md @@ -89,7 +89,7 @@ Como el tiempo de ejecución se consume principalmente esperando operaciones de Se llama "asíncrono" porque la computadora / programa no tiene que estar "sincronizado" con la tarea lenta, esperando el momento exacto en que la tarea termine, sin hacer nada, para poder tomar el resultado de la tarea y continuar el trabajo. -En lugar de eso, al ser un sistema "asíncrono", una vez terminado, la tarea puede esperar un poco en la cola (algunos microsegundos) para que la computadora / programa termine lo que salió a hacer, y luego regrese para tomar los resultados y continuar trabajando con ellos. +En lugar de eso, al ser un sistema "asíncrono", una vez terminado, la tarea puede esperar un poquito en la cola (algunos microsegundos) para que la computadora / programa termine lo que salió a hacer, y luego regrese para tomar los resultados y continuar trabajando con ellos. Para el "sincrónico" (contrario al "asíncrono") comúnmente también usan el término "secuencial", porque la computadora / programa sigue todos los pasos en secuencia antes de cambiar a una tarea diferente, incluso si esos pasos implican esperar. @@ -151,7 +151,7 @@ Imagina que eres la computadora / programa 🤖 en esa historia. Mientras estás en la fila, estás inactivo 😴, esperando tu turno, sin hacer nada muy "productivo". Pero la fila es rápida porque el cajero solo está tomando los pedidos (no preparándolos), así que está bien. -Luego, cuando es tu turno, haces un trabajo realmente "productivo", procesas el menú, decides lo que quieres, obtienes la elección de tu crush, pagas, verificas que das el billete o tarjeta correctos, verificas que te cobren correctamente, verificas que el pedido tenga los artículos correctos, etc. +Luego, cuando es tu turno, haces un trabajo realmente "productivo", procesas el menú, decides lo que quieres, obtienes la elección de tu crush, pagas, revisas que das el billete o tarjeta correctos, revisas que te cobren correctamente, revisas que el pedido tenga los artículos correctos, etc. Pero luego, aunque todavía no tienes tus hamburguesas, tu trabajo con el cajero está "en pausa" ⏸, porque tienes que esperar 🕙 a que tus hamburguesas estén listas. @@ -387,7 +387,7 @@ En versiones previas de NodeJS / JavaScript en el Navegador, habrías usado "cal ## Coroutines { #coroutines } -**Coroutines** es simplemente el término muy elegante para la cosa que devuelve una función `async def`. Python sabe que es algo parecido a una función, que puede comenzar y que terminará en algún momento, pero que podría pausar ⏸ internamente también, siempre que haya un `await` dentro de él. +**Coroutine** es simplemente el término muy elegante para la cosa que devuelve una función `async def`. Python sabe que es algo parecido a una función, que puede comenzar y que terminará en algún momento, pero que podría pausar ⏸ internamente también, siempre que haya un `await` dentro de él. Pero toda esta funcionalidad de usar código asíncrono con `async` y `await` a menudo se resume como utilizar "coroutines". Es comparable a la funcionalidad clave principal de Go, las "Goroutines". @@ -417,7 +417,7 @@ Si tienes bastante conocimiento técnico (coroutines, hilos, bloqueo, etc.) y ti Cuando declaras una *path operation function* con `def` normal en lugar de `async def`, se ejecuta en un threadpool externo que luego es esperado, en lugar de ser llamado directamente (ya que bloquearía el servidor). -Si vienes de otro framework async que no funciona de la manera descrita anteriormente y estás acostumbrado a definir funciones de *path operation* solo de cómputo trivial con `def` normal para una pequeña ganancia de rendimiento (alrededor de 100 nanosegundos), ten en cuenta que en **FastAPI** el efecto sería bastante opuesto. En estos casos, es mejor usar `async def` a menos que tus *path operation functions* usen código que realice I/O de bloqueo. +Si vienes de otro framework async que no funciona de la manera descrita anteriormente y estás acostumbrado a definir *path operation functions* solo de cómputo trivial con `def` normal para una pequeña ganancia de rendimiento (alrededor de 100 nanosegundos), ten en cuenta que en **FastAPI** el efecto sería bastante opuesto. En estos casos, es mejor usar `async def` a menos que tus *path operation functions* usen código que realice I/O de bloqueo. Aun así, en ambas situaciones, es probable que **FastAPI** [siga siendo más rápida](index.md#performance) que (o al menos comparable a) tu framework anterior. diff --git a/docs/es/docs/deployment/cloud.md b/docs/es/docs/deployment/cloud.md index 266d3cfd2..64711455d 100644 --- a/docs/es/docs/deployment/cloud.md +++ b/docs/es/docs/deployment/cloud.md @@ -16,7 +16,7 @@ FastAPI Cloud es el sponsor principal y proveedor de financiamiento de los proye ## Proveedores de Nube - Sponsors { #cloud-providers-sponsors } -Otros proveedores de nube ✨ [**son sponsors de FastAPI**](../help-fastapi.md#sponsor-the-author) ✨ también. 🙇 +Algunos otros proveedores de nube ✨ [**son sponsors de FastAPI**](https://github.com/sponsors/tiangolo) ✨ también. 🙇 También podrías considerarlos para seguir sus guías y probar sus servicios: diff --git a/docs/es/docs/deployment/concepts.md b/docs/es/docs/deployment/concepts.md index 9b3ac0a34..6a2d20a35 100644 --- a/docs/es/docs/deployment/concepts.md +++ b/docs/es/docs/deployment/concepts.md @@ -1,5 +1,6 @@ # Conceptos de Implementación { #deployments-concepts } + Cuando implementas una aplicación **FastAPI**, o en realidad, cualquier tipo de API web, hay varios conceptos que probablemente te importen, y al entenderlos, puedes encontrar la **forma más adecuada** de **implementar tu aplicación**. Algunos de los conceptos importantes son: diff --git a/docs/es/docs/deployment/docker.md b/docs/es/docs/deployment/docker.md index f62db5e70..e54f0c205 100644 --- a/docs/es/docs/deployment/docker.md +++ b/docs/es/docs/deployment/docker.md @@ -1,5 +1,6 @@ # FastAPI en Contenedores - Docker { #fastapi-in-containers-docker } + Al desplegar aplicaciones de FastAPI, un enfoque común es construir una **imagen de contenedor de Linux**. Normalmente se realiza usando [**Docker**](https://www.docker.com/). Luego puedes desplegar esa imagen de contenedor de varias formas. Usar contenedores de Linux tiene varias ventajas, incluyendo **seguridad**, **replicabilidad**, **simplicidad**, y otras. diff --git a/docs/es/docs/deployment/https.md b/docs/es/docs/deployment/https.md index 227aab0d6..32f0fc28c 100644 --- a/docs/es/docs/deployment/https.md +++ b/docs/es/docs/deployment/https.md @@ -32,7 +32,7 @@ Ahora, desde una **perspectiva de desarrollador**, aquí hay varias cosas a tene * Esta extensión SNI permite que un solo servidor (con una **sola dirección IP**) tenga **varios certificados HTTPS** y sirva **múltiples dominios/aplicaciones HTTPS**. * Para que esto funcione, un componente (programa) **único** que se ejecute en el servidor, escuchando en la **dirección IP pública**, debe tener **todos los certificados HTTPS** en el servidor. * **Después** de obtener una conexión segura, el protocolo de comunicación sigue siendo **HTTP**. - * Los contenidos están **encriptados**, aunque se envién con el **protocolo HTTP**. + * Los contenidos están **encriptados**, aunque se envíen con el **protocolo HTTP**. Es una práctica común tener **un programa/servidor HTTP** ejecutándose en el servidor (la máquina, host, etc.) y **gestionando todas las partes de HTTPS**: recibiendo los **requests HTTPS encriptados**, enviando los **requests HTTP desencriptados** a la aplicación HTTP real que se ejecuta en el mismo servidor (la aplicación **FastAPI**, en este caso), tomando el **response HTTP** de la aplicación, **encriptándolo** usando el **certificado HTTPS** adecuado y enviándolo de vuelta al cliente usando **HTTPS**. Este servidor a menudo se llama un **[TLS Termination Proxy](https://en.wikipedia.org/wiki/TLS_termination_proxy)**. diff --git a/docs/es/docs/deployment/manually.md b/docs/es/docs/deployment/manually.md index 361a57c8f..90e25ecb4 100644 --- a/docs/es/docs/deployment/manually.md +++ b/docs/es/docs/deployment/manually.md @@ -93,7 +93,7 @@ Un proceso similar se aplicaría a cualquier otro programa de servidor ASGI. Al añadir `standard`, Uvicorn instalará y usará algunas dependencias adicionales recomendadas. -Eso incluye `uvloop`, el reemplazo de alto rendimiento para `asyncio`, que proporciona un gran impulso de rendimiento en concurrencia. +Eso incluye `uvloop`, el reemplazo directo de alto rendimiento para `asyncio`, que proporciona un gran impulso de rendimiento en concurrencia. Cuando instalas FastAPI con algo como `pip install "fastapi[standard]"` ya obtienes `uvicorn[standard]` también. diff --git a/docs/es/docs/editor-support.md b/docs/es/docs/editor-support.md index fa552db23..9c9abdd5e 100644 --- a/docs/es/docs/editor-support.md +++ b/docs/es/docs/editor-support.md @@ -10,7 +10,7 @@ La **Extensión de FastAPI** está disponible tanto para [VS Code](https://code. ### Descubrimiento de la aplicación { #application-discovery } -Por defecto, la extensión descubrirá automáticamente aplicaciones FastAPI en tu espacio de trabajo escaneando archivos que creen un instance de `FastAPI()`. Si la detección automática no funciona con la estructura de tu proyecto, puedes especificar un punto de entrada mediante `[tool.fastapi]` en `pyproject.toml` o la configuración de VS Code `fastapi.entryPoint` usando notación de módulo (p. ej. `myapp.main:app`). +Por defecto, la extensión descubrirá automáticamente aplicaciones FastAPI en tu espacio de trabajo escaneando archivos que crean un instance de `FastAPI()`. Si la detección automática no funciona con la estructura de tu proyecto, puedes especificar un punto de entrada mediante `[tool.fastapi]` en `pyproject.toml` o la configuración de VS Code `fastapi.entryPoint` usando notación de módulo (p. ej. `myapp.main:app`). ## Funcionalidades { #features } diff --git a/docs/es/docs/environment-variables.md b/docs/es/docs/environment-variables.md index 5c58771d9..aab76ebe6 100644 --- a/docs/es/docs/environment-variables.md +++ b/docs/es/docs/environment-variables.md @@ -1,5 +1,6 @@ # Variables de Entorno { #environment-variables } + /// tip | Consejo Si ya sabes qué son las "variables de entorno" y cómo usarlas, siéntete libre de saltarte esto. diff --git a/docs/es/docs/features.md b/docs/es/docs/features.md index 799af26e9..1feed92bd 100644 --- a/docs/es/docs/features.md +++ b/docs/es/docs/features.md @@ -130,7 +130,7 @@ Todos los esquemas de seguridad definidos en OpenAPI, incluyendo: * Parámetros de query. * Cookies, etc. -Además de todas las características de seguridad de Starlette (incluyendo **cookies de sesión**). +Además de todas las funcionalidades de seguridad de Starlette (incluyendo **cookies de sesión**). Todo construido como herramientas y componentes reutilizables que son fáciles de integrar con tus sistemas, almacenes de datos, bases de datos relacionales y NoSQL, etc. @@ -179,7 +179,7 @@ Con **FastAPI** obtienes todas las funcionalidades de **Starlette** (ya que Fast **FastAPI** es totalmente compatible con (y está basado en) [**Pydantic**](https://docs.pydantic.dev/). Por lo tanto, cualquier código adicional de Pydantic que tengas, también funcionará. -Incluyendo paquetes externos también basados en Pydantic, como ORMs, ODMs para bases de datos. +Incluyendo paquetes externos también basados en Pydantic, como ORMs y ODMs para bases de datos. Esto también significa que, en muchos casos, puedes pasar el mismo objeto que obtienes de un request **directamente a la base de datos**, ya que todo se valida automáticamente. diff --git a/docs/es/docs/help-fastapi.md b/docs/es/docs/help-fastapi.md index 71e872d50..e1a8d1a52 100644 --- a/docs/es/docs/help-fastapi.md +++ b/docs/es/docs/help-fastapi.md @@ -68,7 +68,7 @@ Puedes [crear una nueva pregunta](https://github.com/fastapi/fastapi/discussions ## Únete al chat { #join-the-chat } -Únete al servidor de chat 👥 [Discord](https://discord.gg/VQjSZaeJmf) 👥 y charla con otros en la comunidad de FastAPI. +Únete al 👥 [servidor de chat de Discord](https://discord.gg/VQjSZaeJmf) 👥 y charla con otros en la comunidad de FastAPI. /// tip | Consejo diff --git a/docs/es/docs/how-to/configure-swagger-ui.md b/docs/es/docs/how-to/configure-swagger-ui.md index 8230f4a14..7ff728eef 100644 --- a/docs/es/docs/how-to/configure-swagger-ui.md +++ b/docs/es/docs/how-to/configure-swagger-ui.md @@ -1,4 +1,4 @@ -# Configurar Swagger UI { #configure-swagger-ui } +# Configura Swagger UI { #configure-swagger-ui } Puedes configurar algunos [parámetros adicionales de Swagger UI](https://swagger.io/docs/open-source-tools/swagger-ui/usage/configuration/). @@ -8,7 +8,7 @@ Para configurarlos, pasa el argumento `swagger_ui_parameters` al crear el objeto FastAPI convierte las configuraciones a **JSON** para hacerlas compatibles con JavaScript, ya que eso es lo que Swagger UI necesita. -## Desactivar el resaltado de sintaxis { #disable-syntax-highlighting } +## Desactiva el resaltado de sintaxis { #disable-syntax-highlighting } Por ejemplo, podrías desactivar el resaltado de sintaxis en Swagger UI. @@ -24,7 +24,7 @@ Pero puedes desactivarlo estableciendo `syntaxHighlight` en `False`: -## Cambiar el tema { #change-the-theme } +## Cambia el tema { #change-the-theme } De la misma manera, podrías configurar el tema del resaltado de sintaxis con la clave `"syntaxHighlight.theme"` (ten en cuenta que tiene un punto en el medio): @@ -34,7 +34,7 @@ Esa configuración cambiaría el tema de color del resaltado de sintaxis: -## Cambiar los parámetros por defecto de Swagger UI { #change-default-swagger-ui-parameters } +## Cambia los parámetros por defecto de Swagger UI { #change-default-swagger-ui-parameters } FastAPI incluye algunos parámetros de configuración por defecto apropiados para la mayoría de los casos de uso. diff --git a/docs/es/docs/how-to/custom-request-and-route.md b/docs/es/docs/how-to/custom-request-and-route.md index 56013a5c7..5b4d8570f 100644 --- a/docs/es/docs/how-to/custom-request-and-route.md +++ b/docs/es/docs/how-to/custom-request-and-route.md @@ -18,8 +18,8 @@ Si apenas estás comenzando con **FastAPI**, quizás quieras saltar esta secció Algunos casos de uso incluyen: -* Convertir cuerpos de requests no-JSON a JSON (por ejemplo, [`msgpack`](https://msgpack.org/index.html)). -* Descomprimir cuerpos de requests comprimidos con gzip. +* Convertir request bodies no-JSON a JSON (por ejemplo, [`msgpack`](https://msgpack.org/index.html)). +* Descomprimir request bodies comprimidos con gzip. * Registrar automáticamente todos los request bodies. ## Manejo de codificaciones personalizadas de request body { #handling-custom-request-body-encodings } @@ -32,7 +32,7 @@ Y una subclase de `APIRoute` para usar esa clase de request personalizada. /// tip | Consejo -Este es un ejemplo sencillo para demostrar cómo funciona. Si necesitas soporte para Gzip, puedes usar el [`GzipMiddleware`](../advanced/middleware.md#gzipmiddleware) proporcionado. +Este es un ejemplo de juguete para demostrar cómo funciona, si necesitas soporte para Gzip, puedes usar el [`GzipMiddleware`](../advanced/middleware.md#gzipmiddleware) proporcionado. /// @@ -60,11 +60,11 @@ Aquí lo usamos para crear un `GzipRequest` a partir del request original. Un `Request` tiene un atributo `request.scope`, que es simplemente un `dict` de Python que contiene los metadatos relacionados con el request. -Un `Request` también tiene un `request.receive`, que es una función para "recibir" el request body. +Un `Request` también tiene un `request.receive`, que es una función para "recibir" el body del request. El `dict` `scope` y la función `receive` son ambos parte de la especificación ASGI. -Y esas dos cosas, `scope` y `receive`, son lo que se necesita para crear una nueva *Request instance*. +Y esas dos cosas, `scope` y `receive`, son lo que se necesita para crear una nueva instance de `Request`. Para aprender más sobre el `Request`, revisa [la documentación de Starlette sobre Requests](https://www.starlette.dev/requests/). @@ -94,7 +94,7 @@ Todo lo que necesitamos hacer es manejar el request dentro de un bloque `try`/`e {* ../../docs_src/custom_request_and_route/tutorial002_an_py310.py hl[14,16] *} -Si ocurre una excepción, la `Request instance` aún estará en el alcance, así que podemos leer y hacer uso del request body cuando manejamos el error: +Si ocurre una excepción, el instance de `Request` todavía estará en el alcance, así que podemos leer y hacer uso del request body cuando manejamos el error: {* ../../docs_src/custom_request_and_route/tutorial002_an_py310.py hl[17:19] *} diff --git a/docs/es/docs/how-to/graphql.md b/docs/es/docs/how-to/graphql.md index 11c0cc23c..a58a11764 100644 --- a/docs/es/docs/how-to/graphql.md +++ b/docs/es/docs/how-to/graphql.md @@ -29,7 +29,7 @@ Aquí algunos de los paquetes de **GraphQL** que tienen soporte **ASGI**. Podrí ## GraphQL con Strawberry { #graphql-with-strawberry } -Si necesitas o quieres trabajar con **GraphQL**, [**Strawberry**](https://strawberry.rocks/) es el paquete **recomendado** ya que tiene un diseño muy similar al diseño de **FastAPI**, todo basado en **anotaciones de tipos**. +Si necesitas o quieres trabajar con **GraphQL**, [**Strawberry**](https://strawberry.rocks/) es el paquete **recomendado** ya que tiene el diseño más cercano al diseño de **FastAPI**, todo basado en **anotaciones de tipos**. Dependiendo de tu caso de uso, podrías preferir usar un paquete diferente, pero si me preguntas, probablemente te sugeriría probar **Strawberry**. diff --git a/docs/es/docs/how-to/migrate-from-pydantic-v1-to-pydantic-v2.md b/docs/es/docs/how-to/migrate-from-pydantic-v1-to-pydantic-v2.md index 22d51674d..571554cad 100644 --- a/docs/es/docs/how-to/migrate-from-pydantic-v1-to-pydantic-v2.md +++ b/docs/es/docs/how-to/migrate-from-pydantic-v1-to-pydantic-v2.md @@ -8,6 +8,8 @@ FastAPI versión 0.119.0 introdujo compatibilidad parcial con Pydantic v1 desde FastAPI 0.126.0 eliminó la compatibilidad con Pydantic v1, aunque siguió soportando `pydantic.v1` por un poquito más de tiempo. +FastAPI 0.128.0 también eliminó la compatibilidad con `pydantic.v1`, así que las versiones más recientes de FastAPI requieren Pydantic v2. + /// warning | Advertencia El equipo de Pydantic dejó de dar soporte a Pydantic v1 para las versiones más recientes de Python, comenzando con **Python 3.14**. @@ -54,6 +56,16 @@ Esto significa que puedes instalar la versión más reciente de Pydantic v2 e im ### Compatibilidad de FastAPI con Pydantic v1 en v2 { #fastapi-support-for-pydantic-v1-in-v2 } +/// warning | Advertencia + +Esta compatibilidad de FastAPI con modelos de `pydantic.v1` se añadió en **FastAPI 0.119.0** y se eliminó en **FastAPI 0.128.0**. Estaba pensada para ser una ayuda temporal para la migración a Pydantic v2. + +En las versiones actuales de FastAPI, usar un modelo de `pydantic.v1` en tu app generará un error. + +El resto de esta sección describe la compatibilidad temporal disponible solo en esas versiones antiguas. + +/// + Desde FastAPI 0.119.0, también hay compatibilidad parcial para Pydantic v1 desde dentro de Pydantic v2, para facilitar la migración a v2. Así que podrías actualizar Pydantic a la última versión 2 y cambiar los imports para usar el submódulo `pydantic.v1`, y en muchos casos simplemente funcionaría. @@ -122,6 +134,12 @@ Si necesitas usar algunas de las herramientas específicas de FastAPI para pará ### Migra por pasos { #migrate-in-steps } +/// warning | Advertencia + +La migración gradual usando tanto modelos de Pydantic v1 como de v2 en la misma app descrita abajo solo funciona en **FastAPI 0.119.0 a 0.127.x**. Se eliminó en **FastAPI 0.128.0**, las versiones más recientes requieren modelos de **Pydantic v2**. + +/// + /// tip | Consejo Primero prueba con `bump-pydantic`, si tus tests pasan y eso funciona, entonces terminaste con un solo comando. ✨ diff --git a/docs/es/docs/how-to/separate-openapi-schemas.md b/docs/es/docs/how-to/separate-openapi-schemas.md index 1026085e0..14990a79a 100644 --- a/docs/es/docs/how-to/separate-openapi-schemas.md +++ b/docs/es/docs/how-to/separate-openapi-schemas.md @@ -77,7 +77,7 @@ Pero para `Item-Output`, `description` **es requerido**, tiene un asterisco rojo Con esta funcionalidad de **Pydantic v2**, la documentación de tu API es más **precisa**, y si tienes clientes y SDKs autogenerados, también serán más precisos, con una mejor **experiencia para desarrolladores** y consistencia. 🎉 -## No Separar Esquemas { #do-not-separate-schemas } +## No separes esquemas { #do-not-separate-schemas } Ahora, hay algunos casos donde podrías querer tener el **mismo esquema para entrada y salida**. diff --git a/docs/es/docs/index.md b/docs/es/docs/index.md index 58d534eef..7a9caec51 100644 --- a/docs/es/docs/index.md +++ b/docs/es/docs/index.md @@ -45,7 +45,7 @@ Las funcionalidades clave son: * **Rápido**: Muy alto rendimiento, a la par con **NodeJS** y **Go** (gracias a Starlette y Pydantic). [Uno de los frameworks Python más rápidos disponibles](#performance). * **Rápido de programar**: Aumenta la velocidad para desarrollar funcionalidades en aproximadamente un 200% a 300%. * * **Menos bugs**: Reduce en aproximadamente un 40% los errores inducidos por humanos (desarrolladores). * -* **Intuitivo**: Gran soporte para editores. Autocompletado en todas partes. Menos tiempo depurando. +* **Intuitivo**: Gran soporte para editores. Autocompletado en todas partes. Menos tiempo depurando. * **Fácil**: Diseñado para ser fácil de usar y aprender. Menos tiempo leyendo documentación. * **Corto**: Minimiza la duplicación de código. Múltiples funcionalidades desde cada declaración de parámetro. Menos bugs. * **Robusto**: Obtén código listo para producción. Con documentación interactiva automática. @@ -479,7 +479,7 @@ Para un ejemplo más completo incluyendo más funcionalidades, ve al Inyección de Dependencias
** muy poderoso y fácil de usar. +* Un sistema de **Inyección de Dependencias** muy poderoso y fácil de usar. * Seguridad y autenticación, incluyendo soporte para **OAuth2** con **tokens JWT** y autenticación **HTTP Basic**. * Técnicas más avanzadas (pero igualmente fáciles) para declarar **modelos JSON profundamente anidados** (gracias a Pydantic). * Integración con **GraphQL** usando [Strawberry](https://strawberry.rocks) y otros paquetes. diff --git a/docs/es/docs/project-generation.md b/docs/es/docs/project-generation.md index 11a560eba..fd0fd7017 100644 --- a/docs/es/docs/project-generation.md +++ b/docs/es/docs/project-generation.md @@ -9,18 +9,18 @@ Repositorio de GitHub: [Plantilla Full Stack FastAPI](https://github.com/tiangol ## Plantilla Full Stack FastAPI - Stack de tecnología y funcionalidades { #full-stack-fastapi-template-technology-stack-and-features } - ⚡ [**FastAPI**](https://fastapi.tiangolo.com/es) para la API del backend en Python. - - 🧰 [SQLModel](https://sqlmodel.tiangolo.com) para las interacciones con bases de datos SQL en Python (ORM). - - 🔍 [Pydantic](https://docs.pydantic.dev), utilizado por FastAPI, para la validación de datos y gestión de configuraciones. - - 💾 [PostgreSQL](https://www.postgresql.org) como base de datos SQL. + - 🧰 [SQLModel](https://sqlmodel.tiangolo.com) para las interacciones con bases de datos SQL en Python (ORM). + - 🔍 [Pydantic](https://docs.pydantic.dev), utilizado por FastAPI, para la validación de datos y gestión de configuraciones. + - 💾 [PostgreSQL](https://www.postgresql.org) como base de datos SQL. - 🚀 [React](https://react.dev) para el frontend. - - 💃 Usando TypeScript, hooks, Vite, y otras partes de una stack moderna de frontend. - - 🎨 [Tailwind CSS](https://tailwindcss.com) y [shadcn/ui](https://ui.shadcn.com) para los componentes del frontend. - - 🤖 Un cliente de frontend generado automáticamente. - - 🧪 [Playwright](https://playwright.dev) para escribir pruebas End-to-End. - - 🦇 Soporte para modo oscuro. + - 💃 Usando TypeScript, hooks, Vite, y otras partes de una stack moderna de frontend. + - 🎨 [Tailwind CSS](https://tailwindcss.com) y [shadcn/ui](https://ui.shadcn.com) para los componentes del frontend. + - 🤖 Un cliente de frontend generado automáticamente. + - 🧪 [Playwright](https://playwright.dev) para escribir pruebas End-to-End. + - 🦇 Soporte para modo oscuro. - 🐋 [Docker Compose](https://www.docker.com) para desarrollo y producción. - 🔒 Hashing seguro de contraseñas por defecto. -- 🔑 Autenticación con tokens JWT. +- 🔑 Autenticación con JWT (JSON Web Token). - 📫 Recuperación de contraseñas basada en email. - ✅ Pruebas con [Pytest](https://pytest.org). - 📞 [Traefik](https://traefik.io) como proxy inverso / load balancer. diff --git a/docs/es/docs/python-types.md b/docs/es/docs/python-types.md index 878c8be03..6a13b97eb 100644 --- a/docs/es/docs/python-types.md +++ b/docs/es/docs/python-types.md @@ -1,8 +1,8 @@ # Introducción a Tipos en Python { #python-types-intro } -Python tiene soporte para "anotaciones de tipos" opcionales (también llamadas "type hints"). +Python tiene soporte para "anotaciones de tipos" opcionales (también llamadas "anotaciones de tipos"). -Estas **"anotaciones de tipos"** o type hints son una sintaxis especial que permite declarar el tipo de una variable. +Estas **"anotaciones de tipos"** o anotaciones son una sintaxis especial que permite declarar el tipo de una variable. Al declarar tipos para tus variables, los editores y herramientas te pueden proporcionar un mejor soporte. @@ -44,7 +44,7 @@ Es un programa muy simple. Pero ahora imagina que lo escribieras desde cero. -En algún momento habrías empezado la definición de la función, tenías los parámetros listos... +En algún momento empiezas a definir la función, y tienes los parámetros listos... Pero luego tienes que llamar "ese método que convierte la primera letra a mayúscula". @@ -58,7 +58,7 @@ Pero, tristemente, no obtienes nada útil: -### Añadir tipos { #add-types } +### Añade tipos { #add-types } Modifiquemos una sola línea de la versión anterior. @@ -120,7 +120,7 @@ Ahora sabes que debes corregirlo, convertir `age` a un string con `str(age)`: Acabas de ver el lugar principal para declarar anotaciones de tipos. Como parámetros de función. -Este también es el lugar principal donde los utilizarías con **FastAPI**. +Este también es el lugar principal donde las utilizarías con **FastAPI**. ### Tipos simples { #simple-types } @@ -137,7 +137,7 @@ Puedes usar, por ejemplo: ### Módulo `typing` { #typing-module } -Para algunos casos adicionales, podrías necesitar importar algunas cosas del módulo `typing` de la standard library, por ejemplo cuando quieres declarar que algo tiene "cualquier tipo", puedes usar `Any` de `typing`: +Para algunos casos adicionales, podrías necesitar importar algunas cosas del módulo `typing` del paquete estándar, por ejemplo cuando quieres declarar que algo tiene "cualquier tipo", puedes usar `Any` de `typing`: ```python from typing import Any @@ -149,7 +149,7 @@ def some_function(data: Any): ### Tipos genéricos { #generic-types } -Algunos tipos pueden tomar "parámetros de tipo" entre corchetes, para definir sus tipos internos, por ejemplo una "lista de strings" se declararía `list[str]`. +Algunos tipos pueden tomar "parámetros de tipo" entre corchetes, para definir sus tipos internos, por ejemplo una "list de strings" se declararía `list[str]`. Estos tipos que pueden tomar parámetros de tipo se llaman **Tipos Genéricos** o **Genéricos**. @@ -160,7 +160,7 @@ Puedes usar los mismos tipos integrados como genéricos (con corchetes y tipos d * `set` * `dict` -#### Lista { #list } +#### List { #list } Por ejemplo, vamos a definir una variable para ser una `list` de `str`. @@ -168,7 +168,7 @@ Declara la variable, con la misma sintaxis de dos puntos (`:`). Como tipo, pon `list`. -Como la lista es un tipo que contiene algunos tipos internos, los pones entre corchetes: +Como la `list` es un tipo que contiene algunos tipos internos, los pones entre corchetes: {* ../../docs_src/python_types/tutorial006_py310.py hl[1] *} @@ -180,15 +180,15 @@ En este caso, `str` es el parámetro de tipo pasado a `list`. /// -Eso significa: "la variable `items` es una `list`, y cada uno de los ítems en esta lista es un `str`". +Eso significa: "la variable `items` es una `list`, y cada uno de los ítems en esta `list` es un `str`". -Al hacer eso, tu editor puede proporcionar soporte incluso mientras procesa elementos de la lista: +Al hacer eso, tu editor puede proporcionar soporte incluso mientras procesa elementos de la `list`: Sin tipos, eso es casi imposible de lograr. -Nota que la variable `item` es uno de los elementos en la lista `items`. +Nota que la variable `item` es uno de los elementos en la `list` `items`. Y aún así, el editor sabe que es un `str` y proporciona soporte para eso. diff --git a/docs/es/docs/tutorial/bigger-applications.md b/docs/es/docs/tutorial/bigger-applications.md index f45b4912a..31688d8ab 100644 --- a/docs/es/docs/tutorial/bigger-applications.md +++ b/docs/es/docs/tutorial/bigger-applications.md @@ -17,16 +17,16 @@ Digamos que tienes una estructura de archivos como esta: ``` . ├── app -│   ├── __init__.py -│   ├── main.py -│   ├── dependencies.py -│   └── routers -│   │ ├── __init__.py -│   │ ├── items.py -│   │ └── users.py -│   └── internal -│   ├── __init__.py -│   └── admin.py +│ ├── __init__.py +│ ├── main.py +│ ├── dependencies.py +│ └── routers +│ │ ├── __init__.py +│ │ ├── items.py +│ │ └── users.py +│ └── internal +│ ├── __init__.py +│ └── admin.py ``` /// tip | Consejo @@ -181,12 +181,12 @@ El resultado final es que los paths de item son ahora: ...como pretendíamos. * Serán marcados con una lista de tags que contiene un solo string `"items"`. - * Estos "tags" son especialmente útiles para los sistemas de documentación interactiva automática (usando OpenAPI). + * Estos "tags" son especialmente útiles para los sistemas de documentación interactiva automática (usando OpenAPI). * Todos incluirán las `responses` predefinidas. * Todas estas *path operations* tendrán la lista de `dependencies` evaluadas/ejecutadas antes de ellas. - * Si también declaras dependencias en una *path operation* específica, **también se ejecutarán**. - * Las dependencias del router se ejecutan primero, luego las [`dependencies` en el decorador](dependencies/dependencies-in-path-operation-decorators.md), y luego las dependencias de parámetros normales. - * También puedes agregar [dependencias de `Security` con `scopes`](../advanced/security/oauth2-scopes.md). + * Si también declaras dependencias en una *path operation* específica, **también se ejecutarán**. + * Las dependencias del router se ejecutan primero, luego las [`dependencies` en el decorador](dependencies/dependencies-in-path-operation-decorators.md), y luego las dependencias de parámetros normales. + * También puedes agregar [dependencias de `Security` con `scopes`](../advanced/security/oauth2-scopes.md). /// tip | Consejo @@ -461,7 +461,7 @@ Los `APIRouter`s no están "montados", no están aislados del resto de la aplica Esto se debe a que queremos incluir sus *path operations* en el esquema de OpenAPI y las interfaces de usuario. -FastAPI mantiene los routers y *path operations* originales activos, y combina los prefijos del router, dependencias, tags, responses y otros metadatos al manejar requests y generar OpenAPI. +FastAPI mantiene los routers y path operations originales activos, y combina los prefijos del router, dependencias, tags, responses y otros metadatos al manejar requests y generar OpenAPI. /// diff --git a/docs/es/docs/tutorial/body-nested-models.md b/docs/es/docs/tutorial/body-nested-models.md index 14151a036..3ca586014 100644 --- a/docs/es/docs/tutorial/body-nested-models.md +++ b/docs/es/docs/tutorial/body-nested-models.md @@ -23,7 +23,7 @@ pasa el/los tipo(s) interno(s) como "parámetros de tipo" usando corchetes: `[` my_list: list[str] ``` -Eso es toda la sintaxis estándar de Python para declaraciones de tipo. +Esa es toda la sintaxis estándar de Python para declaraciones de tipo. Usa esa misma sintaxis estándar para atributos de modelos con tipos internos. diff --git a/docs/es/docs/tutorial/body.md b/docs/es/docs/tutorial/body.md index a87512da2..a71b81a40 100644 --- a/docs/es/docs/tutorial/body.md +++ b/docs/es/docs/tutorial/body.md @@ -1,5 +1,6 @@ # Request Body { #request-body } + Cuando necesitas enviar datos desde un cliente (digamos, un navegador) a tu API, los envías como un **request body**. Un **request** body es un dato enviado por el cliente a tu API. Un **response** body es el dato que tu API envía al cliente. diff --git a/docs/es/docs/tutorial/debugging.md b/docs/es/docs/tutorial/debugging.md index d91a32616..95e19c149 100644 --- a/docs/es/docs/tutorial/debugging.md +++ b/docs/es/docs/tutorial/debugging.md @@ -1,5 +1,6 @@ # Depuración { #debugging } + Puedes conectar el depurador en tu editor, por ejemplo con Visual Studio Code o PyCharm. ## Llama a `uvicorn` { #call-uvicorn } diff --git a/docs/es/docs/tutorial/dependencies/dependencies-with-yield.md b/docs/es/docs/tutorial/dependencies/dependencies-with-yield.md index 552c98ed0..aab8eca7b 100644 --- a/docs/es/docs/tutorial/dependencies/dependencies-with-yield.md +++ b/docs/es/docs/tutorial/dependencies/dependencies-with-yield.md @@ -234,6 +234,7 @@ participant operation as Path Operation Las dependencias con `yield` han evolucionado con el tiempo para cubrir diferentes casos de uso y corregir algunos problemas. Si quieres ver qué ha cambiado en diferentes versiones de FastAPI, puedes leer más al respecto en la guía avanzada, en [Dependencias avanzadas - Dependencias con `yield`, `HTTPException`, `except` y Tareas en Background](../../advanced/advanced-dependencies.md#dependencies-with-yield-httpexception-except-and-background-tasks). + ## Context Managers { #context-managers } ### Qué son los "Context Managers" { #what-are-context-managers } diff --git a/docs/es/docs/tutorial/extra-data-types.md b/docs/es/docs/tutorial/extra-data-types.md index b92d0fcd4..bd5fdc073 100644 --- a/docs/es/docs/tutorial/extra-data-types.md +++ b/docs/es/docs/tutorial/extra-data-types.md @@ -1,5 +1,6 @@ # Tipos de Datos Extra { #extra-data-types } + Hasta ahora, has estado usando tipos de datos comunes, como: * `int` diff --git a/docs/es/docs/tutorial/extra-models.md b/docs/es/docs/tutorial/extra-models.md index 4a3b75b5b..903a13c70 100644 --- a/docs/es/docs/tutorial/extra-models.md +++ b/docs/es/docs/tutorial/extra-models.md @@ -208,4 +208,4 @@ En este caso, puedes usar `dict`: Usa múltiples modelos Pydantic y hereda libremente para cada caso. -No necesitas tener un solo modelo de datos por entidad si esa entidad debe poder tener diferentes "estados". Como el caso con la "entidad" usuario con un estado que incluye `password`, `password_hash` y sin contraseña. +No necesitas tener un solo modelo de datos por entidad si esa entidad debe poder tener diferentes "estados". La "entidad" **usuario** es un ejemplo, con estados que incluyen `password`, `password_hash` o ninguna contraseña. diff --git a/docs/es/docs/tutorial/first-steps.md b/docs/es/docs/tutorial/first-steps.md index 5aaf8bdfa..61e5f4099 100644 --- a/docs/es/docs/tutorial/first-steps.md +++ b/docs/es/docs/tutorial/first-steps.md @@ -90,13 +90,13 @@ Verás la documentación alternativa automática (proporcionada por [ReDoc](http Un "esquema" es una definición o descripción de algo. No el código que lo implementa, sino solo una descripción abstracta. -#### Esquema de la API { #api-schema } +#### "Esquema" de la API { #api-schema } En este caso, [OpenAPI](https://github.com/OAI/OpenAPI-Specification) es una especificación que dicta cómo definir un esquema de tu API. Esta definición de esquema incluye los paths de tu API, los posibles parámetros que toman, etc. -#### Esquema de Datos { #data-schema } +#### "Esquema" de datos { #data-schema } El término "esquema" también podría referirse a la forma de algunos datos, como el contenido JSON. @@ -194,7 +194,7 @@ O, también puedes pasar la opción `--entrypoint` al comando `fastapi dev`: $ fastapi dev --entrypoint main:app ``` -Pero tendrías que recordar pasar el path o entrypoint correctos cada vez que llames al comando `fastapi`. +Pero tendrías que recordar pasar el path\entrypoint correcto cada vez que llames al comando `fastapi`. Además, otras herramientas podrían no ser capaces de encontrarlo, por ejemplo la [Extensión de VS Code](../editor-support.md) o [FastAPI Cloud](https://fastapicloud.com), así que se recomienda usar el `entrypoint` en `pyproject.toml`. @@ -301,7 +301,7 @@ Normalmente usas: * `PUT`: para actualizar datos. * `DELETE`: para eliminar datos. -Así que, en OpenAPI, cada uno de los métodos HTTP se llama una "operation". +Así que, en OpenAPI, cada uno de los métodos HTTP se llama una "operación". Vamos a llamarlas "**operaciones**" también. diff --git a/docs/es/docs/tutorial/handling-errors.md b/docs/es/docs/tutorial/handling-errors.md index 737c43e41..f64064231 100644 --- a/docs/es/docs/tutorial/handling-errors.md +++ b/docs/es/docs/tutorial/handling-errors.md @@ -101,7 +101,7 @@ Así que recibirás un error limpio, con un código de estado HTTP de `418` y un {"message": "Oops! yolo did something. There goes a rainbow..."} ``` -/// note | Nota Técnica +/// note | Detalles Técnicos También podrías usar `from starlette.requests import Request` y `from starlette.responses import JSONResponse`. @@ -109,11 +109,11 @@ También podrías usar `from starlette.requests import Request` y `from starlett /// -## Sobrescribir los manejadores de excepciones predeterminados { #override-the-default-exception-handlers } +## Sobrescribir los manejadores de excepciones por defecto { #override-the-default-exception-handlers } -**FastAPI** tiene algunos manejadores de excepciones predeterminados. +**FastAPI** tiene algunos manejadores de excepciones por defecto. -Estos manejadores se encargan de devolver los responses JSON predeterminadas cuando lanzas un `HTTPException` y cuando el request tiene datos inválidos. +Estos manejadores se encargan de devolver los responses JSON por defecto cuando lanzas un `HTTPException` y cuando el request tiene datos inválidos. Puedes sobrescribir estos manejadores de excepciones con los tuyos propios. @@ -121,7 +121,7 @@ Puedes sobrescribir estos manejadores de excepciones con los tuyos propios. Cuando un request contiene datos inválidos, **FastAPI** lanza internamente un `RequestValidationError`. -Y también incluye un manejador de excepciones predeterminado para ello. +Y también incluye un manejador de excepciones por defecto para ello. Para sobrescribirlo, importa el `RequestValidationError` y úsalo con `@app.exception_handler(RequestValidationError)` para decorar el manejador de excepciones. @@ -161,7 +161,7 @@ Por ejemplo, podrías querer devolver un response de texto plano en lugar de JSO {* ../../docs_src/handling_errors/tutorial004_py310.py hl[3:4,9:11,25] *} -/// note | Nota Técnica +/// note | Detalles Técnicos También podrías usar `from starlette.responses import PlainTextResponse`. @@ -237,8 +237,8 @@ from starlette.exceptions import HTTPException as StarletteHTTPException ### Reutilizar los manejadores de excepciones de **FastAPI** { #reuse-fastapis-exception-handlers } -Si quieres usar la excepción junto con los mismos manejadores de excepciones predeterminados de **FastAPI**, puedes importar y reutilizar los manejadores de excepciones predeterminados de `fastapi.exception_handlers`: +Si quieres usar la excepción junto con los mismos manejadores de excepciones por defecto de **FastAPI**, puedes importar y reutilizar los manejadores de excepciones por defecto de `fastapi.exception_handlers`: {* ../../docs_src/handling_errors/tutorial006_py310.py hl[2:5,15,21] *} -En este ejemplo solo estás `print`eando el error con un mensaje muy expresivo, pero te haces una idea. Puedes usar la excepción y luego simplemente reutilizar los manejadores de excepciones predeterminados. +En este ejemplo solo estás `print`eando el error con un mensaje muy expresivo, pero te haces una idea. Puedes usar la excepción y luego simplemente reutilizar los manejadores de excepciones por defecto. diff --git a/docs/es/docs/tutorial/index.md b/docs/es/docs/tutorial/index.md index 414e865b2..59b9e4164 100644 --- a/docs/es/docs/tutorial/index.md +++ b/docs/es/docs/tutorial/index.md @@ -54,7 +54,7 @@ $ fastapi dev Es **ALTAMENTE recomendable** que escribas o copies el código, lo edites y lo ejecutes localmente. -Usarlo en tu editor es lo que realmente te muestra los beneficios de FastAPI, al ver cuán poco código tienes que escribir, todos los chequeos de tipos, autocompletado, etc. +Usarlo en tu editor es lo que realmente te muestra los beneficios de FastAPI, al ver cuán poco código tienes que escribir, todo el chequeo de tipos, autocompletado, etc. --- diff --git a/docs/es/docs/tutorial/metadata.md b/docs/es/docs/tutorial/metadata.md index 9dd9088da..d8b7176d5 100644 --- a/docs/es/docs/tutorial/metadata.md +++ b/docs/es/docs/tutorial/metadata.md @@ -1,4 +1,4 @@ -# Metadata y URLs de Docs { #metadata-and-docs-urls } +# Metadata y URLs de documentación { #metadata-and-docs-urls } Puedes personalizar varias configuraciones de metadata en tu aplicación **FastAPI**. @@ -11,7 +11,7 @@ Puedes establecer los siguientes campos que se usan en la especificación OpenAP | `title` | `str` | El título de la API. | | `summary` | `str` | Un resumen corto de la API. Disponible desde OpenAPI 3.1.0, FastAPI 0.99.0. | | `description` | `str` | Una breve descripción de la API. Puede usar Markdown. | -| `version` | `string` | La versión de la API. Esta es la versión de tu propia aplicación, no de OpenAPI. Por ejemplo, `2.5.0`. | +| `version` | `str` | La versión de la API. Esta es la versión de tu propia aplicación, no de OpenAPI. Por ejemplo, `2.5.0`. | | `terms_of_service` | `str` | Una URL a los Términos de Servicio para la API. Si se proporciona, debe ser una URL. | | `contact` | `dict` | La información de contacto para la API expuesta. Puede contener varios campos.
contact fields
ParámetroTipoDescripción
namestrEl nombre identificativo de la persona/organización de contacto.
urlstrLa URL que apunta a la información de contacto. DEBE tener el formato de una URL.
emailstrLa dirección de correo electrónico de la persona/organización de contacto. DEBE tener el formato de una dirección de correo.
| | `license_info` | `dict` | La información de la licencia para la API expuesta. Puede contener varios campos.
license_info fields
ParámetroTipoDescripción
namestrREQUERIDO (si se establece un license_info). El nombre de la licencia utilizada para la API.
identifierstrUna expresión de licencia [SPDX](https://spdx.org/licenses/) para la API. El campo identifier es mutuamente excluyente del campo url. Disponible desde OpenAPI 3.1.0, FastAPI 0.99.0.
urlstrUna URL a la licencia utilizada para la API. DEBE tener el formato de una URL.
| @@ -104,7 +104,7 @@ Por ejemplo, para configurarlo para que se sirva en `/api/v1/openapi.json`: Si quieres deshabilitar el esquema OpenAPI completamente, puedes establecer `openapi_url=None`, eso también deshabilitará las interfaces de usuario de documentación que lo usan. -## URLs de Docs { #docs-urls } +## URLs de documentación { #docs-urls } Puedes configurar las dos interfaces de usuario de documentación incluidas: diff --git a/docs/es/docs/tutorial/path-operation-configuration.md b/docs/es/docs/tutorial/path-operation-configuration.md index 30dc9c19f..7331b0f3a 100644 --- a/docs/es/docs/tutorial/path-operation-configuration.md +++ b/docs/es/docs/tutorial/path-operation-configuration.md @@ -56,7 +56,7 @@ Puedes añadir un `summary` y `description`: ## Descripción desde docstring { #description-from-docstring } -Como las descripciones tienden a ser largas y cubrir múltiples líneas, puedes declarar la descripción de la *path operation* en la docstring de la función y **FastAPI** la leerá desde allí. +Como las descripciones tienden a ser largas y cubrir múltiples líneas, puedes declarar la descripción de la *path operation* en la docstring de la función y **FastAPI** la leerá desde allí. Puedes escribir [Markdown](https://en.wikipedia.org/wiki/Markdown) en el docstring, se interpretará y mostrará correctamente (teniendo en cuenta la indentación del docstring). @@ -90,11 +90,11 @@ Entonces, si no proporcionas una, **FastAPI** generará automáticamente una de ## Deprecar una *path operation* { #deprecate-a-path-operation } -Si necesitas marcar una *path operation* como deprecated, pero sin eliminarla, pasa el parámetro `deprecated`: +Si necesitas marcar una *path operation* como obsoleta, pero sin eliminarla, pasa el parámetro `deprecated`: {* ../../docs_src/path_operation_configuration/tutorial006_py310.py hl[16] *} -Se marcará claramente como deprecado en la documentación interactiva: +Se marcará claramente como deprecated en la documentación interactiva: diff --git a/docs/es/docs/tutorial/query-params-str-validations.md b/docs/es/docs/tutorial/query-params-str-validations.md index 01c2e4051..fab02dd35 100644 --- a/docs/es/docs/tutorial/query-params-str-validations.md +++ b/docs/es/docs/tutorial/query-params-str-validations.md @@ -18,7 +18,7 @@ Tener `str | None` permitirá que tu editor te dé un mejor soporte y detecte er ## Validaciones adicionales { #additional-validation } -Vamos a hacer que, aunque `q` sea opcional, siempre que se proporcione, su longitud no exceda los 50 caracteres. +Vamos a hacer que, aunque `q` sea opcional, siempre que se proporcione, **su longitud no exceda los 50 caracteres**. ### Importar `Query` y `Annotated` { #import-query-and-annotated } @@ -69,7 +69,7 @@ Ahora que tenemos este `Annotated` donde podemos poner más información (en est Nota que el valor por defecto sigue siendo `None`, por lo que el parámetro sigue siendo opcional. -Pero ahora, al tener `Query(max_length=50)` dentro de `Annotated`, le estamos diciendo a FastAPI que queremos que tenga validación adicional para este valor, queremos que tenga un máximo de 50 caracteres. 😎 +Pero ahora, al tener `Query(max_length=50)` dentro de `Annotated`, le estamos diciendo a FastAPI que queremos que tenga **validación adicional** para este valor, queremos que tenga un máximo de 50 caracteres. 😎 /// tip | Consejo @@ -79,9 +79,9 @@ Aquí estamos usando `Query()` porque este es un **parámetro de query**. Más a FastAPI ahora: -* Validará los datos asegurándose de que la longitud máxima sea de 50 caracteres -* Mostrará un error claro para el cliente cuando los datos no sean válidos -* Documentará el parámetro en el OpenAPI esquema *path operation* (así aparecerá en la UI de documentación automática) +* **Validará** los datos asegurándose de que la longitud máxima sea de 50 caracteres +* Mostrará un **error claro** para el cliente cuando los datos no sean válidos +* **Documentará** el parámetro en el esquema de OpenAPI *path operation* (así aparecerá en la **UI de documentación automática**) ## Alternativa (antigua): `Query` como valor por defecto { #alternative-old-query-as-the-default-value } @@ -120,7 +120,7 @@ Luego, podemos pasar más parámetros a `Query`. En este caso, el parámetro `ma q: str | None = Query(default=None, max_length=50) ``` -Esto validará los datos, mostrará un error claro cuando los datos no sean válidos, y documentará el parámetro en el esquema del *path operation* de OpenAPI. +Esto validará los datos, mostrará un error claro cuando los datos no sean válidos, y documentará el parámetro en el esquema de OpenAPI *path operation*. ### `Query` como valor por defecto o en `Annotated` { #query-as-the-default-value-or-in-annotated } @@ -150,13 +150,13 @@ q: str = Query(default="rick") ### Ventajas de `Annotated` { #advantages-of-annotated } -Usar `Annotated` es recomendado en lugar del valor por defecto en los parámetros de función, es mejor por múltiples razones. 🤓 +**Usar `Annotated` es recomendado** en lugar del valor por defecto en los parámetros de función, es **mejor** por múltiples razones. 🤓 -El valor por defecto del parámetro de función es el valor real por defecto, eso es más intuitivo con Python en general. 😌 +El valor **por defecto** del **parámetro de función** es el **valor real por defecto**, eso es más intuitivo con Python en general. 😌 -Podrías llamar a esa misma función en otros lugares sin FastAPI, y funcionaría como se espera. Si hay un parámetro requerido (sin un valor por defecto), tu editor te avisará con un error, Python también se quejará si lo ejecutas sin pasar el parámetro requerido. +Podrías **llamar** a esa misma función en **otros lugares** sin FastAPI, y **funcionaría como se espera**. Si hay un parámetro **requerido** (sin un valor por defecto), tu **editor** te avisará con un error, **Python** también se quejará si lo ejecutas sin pasar el parámetro requerido. -Cuando no usas `Annotated` y en su lugar usas el estilo de valor por defecto (antiguo), si llamas a esa función sin FastAPI en otros lugares, tienes que recordar pasar los argumentos a la función para que funcione correctamente, de lo contrario, los valores serán diferentes de lo que esperas (por ejemplo, `QueryInfo` o algo similar en lugar de `str`). Y tu editor no se quejará, y Python no se quejará al ejecutar esa función, solo cuando los errores dentro de las operaciones hagan que funcione incorrectamente. +Cuando no usas `Annotated` y en su lugar usas el **estilo de valor por defecto (antiguo)**, si llamas a esa función sin FastAPI en **otros lugares**, tienes que **recordar** pasar los argumentos a la función para que funcione correctamente, de lo contrario, los valores serán diferentes de lo que esperas (por ejemplo, `QueryInfo` o algo similar en lugar de `str`). Y tu editor no se quejará, y Python no se quejará al ejecutar esa función, solo cuando las operaciones internas generen errores. Dado que `Annotated` puede tener más de una anotación de metadato, ahora podrías incluso usar la misma función con otras herramientas, como [Typer](https://typer.tiangolo.com/). 🚀 @@ -172,13 +172,13 @@ Puedes definir una ISBN o con `imdb-` para un ID de URL de película de IMDB: +Por ejemplo, este validador personalizado revisa que el ID del ítem empiece con `isbn-` para un número de libro ISBN o con `imdb-` para un ID de URL de película de IMDB: {* ../../docs_src/query_params_str_validations/tutorial015_an_py310.py hl[5,16:19,24] *} @@ -390,15 +390,15 @@ Esto está disponible con Pydantic versión 2 o superior. 😎 /// tip | Consejo -Si necesitas hacer cualquier tipo de validación que requiera comunicarte con algún componente externo, como una base de datos u otra API, deberías usar Dependencias de FastAPI, las aprenderás más adelante. +Si necesitas hacer cualquier tipo de validación que requiera comunicarte con algún **componente externo**, como una base de datos u otra API, deberías usar **Dependencias de FastAPI**, las aprenderás más adelante. -Estos validadores personalizados son para cosas que pueden comprobarse solo con los mismos datos provistos en el request. +Estos validadores personalizados son para cosas que pueden revisarse **solo** con los **mismos datos** provistos en el request. /// ### Entiende ese código { #understand-that-code } -El punto importante es solo usar `AfterValidator` con una función dentro de `Annotated`. Si quieres, sáltate esta parte. 🤸 +El punto importante es solo usar **`AfterValidator` con una función dentro de `Annotated`**. Si quieres, sáltate esta parte. 🤸 --- @@ -406,7 +406,7 @@ Pero si te da curiosidad este ejemplo de código específico y sigues entretenid #### String con `value.startswith()` { #string-with-value-startswith } -¿Lo notaste? un string usando `value.startswith()` puede recibir una tupla, y comprobará cada valor en la tupla: +¿Lo notaste? Un string usando `value.startswith()` puede recibir una tupla, y revisará cada valor en la tupla: {* ../../docs_src/query_params_str_validations/tutorial015_an_py310.py ln[16:19] hl[17] *} @@ -416,13 +416,13 @@ Con `data.items()` obtenemos un `) envían los datos al /// note | Detalles Técnicos -Los datos de los forms normalmente se codifican usando el "media type" `application/x-www-form-urlencoded` cuando no incluyen archivos. +Los datos de los formularios normalmente se codifican usando el "media type" `application/x-www-form-urlencoded` cuando no incluyen archivos. Pero cuando el formulario incluye archivos, se codifica como `multipart/form-data`. Si usas `File`, **FastAPI** sabrá que tiene que obtener los archivos de la parte correcta del cuerpo. diff --git a/docs/es/docs/tutorial/request-forms.md b/docs/es/docs/tutorial/request-forms.md index 60722a261..640e02282 100644 --- a/docs/es/docs/tutorial/request-forms.md +++ b/docs/es/docs/tutorial/request-forms.md @@ -14,13 +14,13 @@ $ pip install python-multipart /// -## Importar `Form` { #import-form } +## Importa `Form` { #import-form } -Importar `Form` desde `fastapi`: +Importa `Form` desde `fastapi`: {* ../../docs_src/request_forms/tutorial001_an_py310.py hl[3] *} -## Definir parámetros de `Form` { #define-form-parameters } +## Define parámetros de `Form` { #define-form-parameters } Crea parámetros de formulario de la misma manera que lo harías para `Body` o `Query`: diff --git a/docs/es/docs/tutorial/response-status-code.md b/docs/es/docs/tutorial/response-status-code.md index 4b9f0e234..2e0b88c5d 100644 --- a/docs/es/docs/tutorial/response-status-code.md +++ b/docs/es/docs/tutorial/response-status-code.md @@ -1,5 +1,6 @@ # Código de Estado del Response { #response-status-code } + De la misma manera que puedes especificar un modelo de response, también puedes declarar el código de estado HTTP usado para el response con el parámetro `status_code` en cualquiera de las *path operations*: * `@app.get()` diff --git a/docs/es/docs/tutorial/schema-extra-example.md b/docs/es/docs/tutorial/schema-extra-example.md index fba7215ef..310697d0b 100644 --- a/docs/es/docs/tutorial/schema-extra-example.md +++ b/docs/es/docs/tutorial/schema-extra-example.md @@ -1,4 +1,4 @@ -# Declarar Datos de Ejemplo de Request { #declare-request-example-data } +# Declara Datos de Ejemplo de Request { #declare-request-example-data } Puedes declarar ejemplos de los datos que tu aplicación puede recibir. diff --git a/docs/es/docs/tutorial/security/first-steps.md b/docs/es/docs/tutorial/security/first-steps.md index e4755f951..a8df7e9a5 100644 --- a/docs/es/docs/tutorial/security/first-steps.md +++ b/docs/es/docs/tutorial/security/first-steps.md @@ -146,7 +146,7 @@ Usar una URL relativa es importante para asegurarse de que tu aplicación siga f Este parámetro no crea ese endpoint / *path operation*, pero declara que la URL `/token` será la que el cliente deberá usar para obtener el token. Esa información se usa en OpenAPI, y luego en los sistemas de documentación interactiva del API. -Pronto también crearemos la verdadera *path operation*. +Pronto también crearemos la path operation real. /// note | Nota @@ -174,13 +174,13 @@ Ahora puedes pasar ese `oauth2_scheme` en una dependencia con `Depends`. Esta dependencia proporcionará un `str` que se asigna al parámetro `token` de la *path operation function*. -**FastAPI** sabrá que puede usar esta dependencia para definir un "security scheme" en el esquema OpenAPI (y en los docs automáticos del API). +**FastAPI** sabrá que puede usar esta dependencia para definir un "security scheme" en el esquema OpenAPI (y en la documentación automática de la API). /// note | Detalles técnicos **FastAPI** sabrá que puede usar la clase `OAuth2PasswordBearer` (declarada en una dependencia) para definir el esquema de seguridad en OpenAPI porque hereda de `fastapi.security.oauth2.OAuth2`, que a su vez hereda de `fastapi.security.base.SecurityBase`. -Todas las utilidades de seguridad que se integran con OpenAPI (y los docs automáticos del API) heredan de `SecurityBase`, así es como **FastAPI** puede saber cómo integrarlas en OpenAPI. +Todas las utilidades de seguridad que se integran con OpenAPI (y la documentación automática de la API) heredan de `SecurityBase`, así es como **FastAPI** puede saber cómo integrarlas en OpenAPI. /// diff --git a/docs/es/docs/tutorial/security/get-current-user.md b/docs/es/docs/tutorial/security/get-current-user.md index fd331f68e..a47cfb0bc 100644 --- a/docs/es/docs/tutorial/security/get-current-user.md +++ b/docs/es/docs/tutorial/security/get-current-user.md @@ -4,7 +4,9 @@ En el capítulo anterior, el sistema de seguridad (que se basa en el sistema de {* ../../docs_src/security/tutorial001_an_py310.py hl[12] *} -Pero eso aún no es tan útil. Vamos a hacer que nos dé el usuario actual. +Pero eso aún no es tan útil. + +Vamos a hacer que nos dé el usuario actual. ## Crear un modelo de usuario { #create-a-user-model } @@ -12,7 +14,7 @@ Primero, vamos a crear un modelo de usuario con Pydantic. De la misma manera que usamos Pydantic para declarar cuerpos, podemos usarlo en cualquier otra parte: -{* ../../docs_src/security/tutorial002_an_py310.py hl[5,12:6] *} +{* ../../docs_src/security/tutorial002_an_py310.py hl[5,12:16] *} ## Crear una dependencia `get_current_user` { #create-a-get-current-user-dependency } @@ -66,7 +68,7 @@ Y puedes usar cualquier modelo o datos para los requisitos de seguridad (en este Pero no estás limitado a usar algún modelo de datos, clase o tipo específico. -¿Quieres tener un `id` y `email` y no tener un `username` en tu modelo? Claro. Puedes usar estas mismas herramientas. +¿Quieres tener un `id` y `email` y no tener ningún `username` en tu modelo? Claro. Puedes usar estas mismas herramientas. ¿Quieres solo tener un `str`? ¿O solo un `dict`? ¿O un instance de clase modelo de base de datos directamente? Todo funciona de la misma manera. diff --git a/docs/es/docs/tutorial/security/oauth2-jwt.md b/docs/es/docs/tutorial/security/oauth2-jwt.md index efd309df9..5b74ffd11 100644 --- a/docs/es/docs/tutorial/security/oauth2-jwt.md +++ b/docs/es/docs/tutorial/security/oauth2-jwt.md @@ -1,5 +1,6 @@ # OAuth2 con Password (y hashing), Bearer con tokens JWT { #oauth2-with-password-and-hashing-bearer-with-jwt-tokens } + Ahora que tenemos todo el flujo de seguridad, hagamos que la aplicación sea realmente segura, usando tokens JWT y hashing de contraseñas seguras. Este código es algo que puedes usar realmente en tu aplicación, guardar los hashes de las contraseñas en tu base de datos, etc. diff --git a/docs/es/docs/tutorial/security/simple-oauth2.md b/docs/es/docs/tutorial/security/simple-oauth2.md index 2a98fff6c..d3e2bd2cb 100644 --- a/docs/es/docs/tutorial/security/simple-oauth2.md +++ b/docs/es/docs/tutorial/security/simple-oauth2.md @@ -146,7 +146,7 @@ UserInDB( /// note | Nota -Para una explicación más completa de `**user_dict` revisa en [la documentación para **Extra Models**](../extra-models.md#about-user-in-dict). +Para una explicación más completa de `**user_dict` revisa en [la documentación para **Extra Models**](../extra-models.md#about-user-in-model-dump). /// diff --git a/docs/es/docs/tutorial/sql-databases.md b/docs/es/docs/tutorial/sql-databases.md index 7131716ee..3bb3209b2 100644 --- a/docs/es/docs/tutorial/sql-databases.md +++ b/docs/es/docs/tutorial/sql-databases.md @@ -65,7 +65,7 @@ Hay algunas diferencias: * `Field(primary_key=True)` le dice a SQLModel que `id` es la **clave primaria** en la base de datos SQL (puedes aprender más sobre claves primarias de SQL en la documentación de SQLModel). - Nota: Usamos `int | None` para el campo de clave primaria para que en el código Python podamos *crear un objeto sin un `id`* (`id=None`), asumiendo que la base de datos lo *generará al guardar*. SQLModel entiende que la base de datos proporcionará el `id` y *define la columna como un `INTEGER` no nulo* en el esquema de la base de datos. Consulta la [documentación de SQLModel sobre claves primarias](https://sqlmodel.tiangolo.com/tutorial/create-db-and-table/#primary-key-id) para más detalles. + **Nota:** Usamos `int | None` para el campo de clave primaria para que en el código Python podamos *crear un objeto sin un `id`* (`id=None`), asumiendo que la base de datos lo *generará al guardar*. SQLModel entiende que la base de datos proporcionará el `id` y *define la columna como un `INTEGER` no nulo* en el esquema de la base de datos. Consulta la [documentación de SQLModel sobre claves primarias](https://sqlmodel.tiangolo.com/tutorial/create-db-and-table/#primary-key-id) para más detalles. * `Field(index=True)` le dice a SQLModel que debe crear un **índice SQL** para esta columna, lo que permitirá búsquedas más rápidas en la base de datos cuando se lean datos filtrados por esta columna. @@ -181,7 +181,7 @@ Arreglaremos estas cosas añadiendo unos **modelos extra**. Aquí es donde SQLMo En **SQLModel**, cualquier clase de modelo que tenga `table=True` es un **modelo de tabla**. -Y cualquier clase de modelo que no tenga `table=True` es un **modelo de datos**, estos son en realidad solo modelos de Pydantic (con un par de características extra pequeñas). 🤓 +Y cualquier clase de modelo que no tenga `table=True` es un **modelo de datos**, estos son en realidad solo modelos de Pydantic (con un par de pequeñas funcionalidades extra). 🤓 Con SQLModel, podemos usar **herencia** para **evitar duplicar** todos los campos en todos los casos. @@ -296,7 +296,7 @@ Ahora usamos `response_model=HeroPublic` en lugar de la **anotación de tipo de Si hubiéramos declarado `-> HeroPublic`, tu editor y linter se quejarían (con razón) de que estás devolviendo un `Hero` en lugar de un `HeroPublic`. -Al declararlo en `response_model` le estamos diciendo a **FastAPI** que haga lo suyo, sin interferir con las anotaciones de tipo y la ayuda de tu editor y otras herramientas. +Al declararlo en `response_model` le estamos diciendo a **FastAPI** que haga lo suyo, sin interferir con las anotaciones de tipos y la ayuda de tu editor y otras herramientas. /// diff --git a/docs/es/docs/tutorial/static-files.md b/docs/es/docs/tutorial/static-files.md index b99ed5f9c..177be6302 100644 --- a/docs/es/docs/tutorial/static-files.md +++ b/docs/es/docs/tutorial/static-files.md @@ -2,6 +2,14 @@ Puedes servir archivos estáticos automáticamente desde un directorio utilizando `StaticFiles`. +/// tip | Consejo + +Si necesitas alojar un frontend, usa `app.frontend()` en su lugar, lee sobre ello en [Frontend](frontend.md). + +`app.frontend()` usa `StaticFiles` por debajo, con varias ventajas adicionales para frontends, como manejar el routing del lado del cliente. + +/// + ## Usa `StaticFiles` { #use-staticfiles } * Importa `StaticFiles`. diff --git a/docs/es/docs/tutorial/testing.md b/docs/es/docs/tutorial/testing.md index 9612b6cba..9c4ff69b8 100644 --- a/docs/es/docs/tutorial/testing.md +++ b/docs/es/docs/tutorial/testing.md @@ -28,7 +28,7 @@ Crea funciones con un nombre que comience con `test_` (esta es la convención es Usa el objeto `TestClient` de la misma manera que con `httpx`. -Escribe declaraciones `assert` simples con las expresiones estándar de Python que necesites revisar (otra vez, estándar de `pytest`). +Escribe statements `assert` simples con las expresiones estándar de Python que necesites revisar (otra vez, estándar de `pytest`). {* ../../docs_src/app_testing/tutorial001_py310.py hl[2,12,15:18] *} @@ -90,7 +90,7 @@ Entonces podrías tener un archivo `test_main.py` con tus pruebas. Podría estar │   └── test_main.py ``` -Debido a que este archivo está en el mismo paquete, puedes usar importaciones relativas para importar el objeto `app` desde el módulo `main` (`main.py`): +Debido a que este archivo está en el mismo paquete, puedes usar imports relativos para importar el objeto `app` desde el módulo `main` (`main.py`): {* ../../docs_src/app_testing/app_a_py310/test_main.py hl[3] *} diff --git a/docs/es/docs/virtual-environments.md b/docs/es/docs/virtual-environments.md index 1679fd02b..92cb83ba2 100644 --- a/docs/es/docs/virtual-environments.md +++ b/docs/es/docs/virtual-environments.md @@ -288,8 +288,8 @@ $ echo "*" > .venv/.gitignore /// details | Qué significa ese comando -* `echo "*"`: "imprimirá" el texto `*` en el terminal (la siguiente parte cambia eso un poco) -* `>`: cualquier cosa impresa en el terminal por el comando a la izquierda de `>` no debería imprimirse, sino escribirse en el archivo que va a la derecha de `>` +* `echo "*"`: "imprimirá" el texto `*` en la terminal (la siguiente parte cambia eso un poco) +* `>`: cualquier cosa impresa en la terminal por el comando a la izquierda de `>` no debería imprimirse, sino escribirse en el archivo que va a la derecha de `>` * `.gitignore`: el nombre del archivo donde debería escribirse el texto Y `*` para Git significa "todo". Así que, ignorará todo en el directorio `.venv`. @@ -443,6 +443,8 @@ De esta manera, cuando ejecutes `python` no intentará ejecutarse desde ese ento Ahora estás listo para empezar a trabajar en tu proyecto. + + /// tip | Consejo ¿Quieres entender todo lo anterior? @@ -694,7 +696,7 @@ Eso significa que el sistema ahora comenzará a buscar primero los programas en: antes de buscar en los otros directorios. -Así que, cuando escribas `python` en el terminal, el sistema encontrará el programa Python en +Así que, cuando escribas `python` en la terminal, el sistema encontrará el programa Python en ```plaintext /home/user/code/awesome-project/.venv/bin/python @@ -718,7 +720,7 @@ C:\Users\user\code\awesome-project\.venv\Scripts antes de buscar en los otros directorios. -Así que, cuando escribas `python` en el terminal, el sistema encontrará el programa Python en +Así que, cuando escribas `python` en la terminal, el sistema encontrará el programa Python en ```plaintext C:\Users\user\code\awesome-project\.venv\Scripts\python @@ -800,7 +802,7 @@ $ cd ~/code/prisoner-of-azkaban
-Si no desactivas el entorno virtual para `philosophers-stone`, cuando ejecutes `python` en el terminal, intentará usar el Python de `philosophers-stone`. +Si no desactivas el entorno virtual para `philosophers-stone`, cuando ejecutes `python` en la terminal, intentará usar el Python de `philosophers-stone`.
From e23813a9b537672a882b589290ca128c0a55c95d Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Wed, 1 Jul 2026 13:50:58 +0000 Subject: [PATCH 373/462] =?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 548310c7d..9d6eacc89 100644 --- a/docs/en/docs/release-notes.md +++ b/docs/en/docs/release-notes.md @@ -9,6 +9,7 @@ hide: ### Translations +* 🌐 Update translations for es (update-outdated). PR [#15892](https://github.com/fastapi/fastapi/pull/15892) by [@tiangolo](https://github.com/tiangolo). * 🌐 Update translations for tr (update-outdated). PR [#15891](https://github.com/fastapi/fastapi/pull/15891) by [@tiangolo](https://github.com/tiangolo). * 🌐 Update translations for pt (update-outdated). PR [#15893](https://github.com/fastapi/fastapi/pull/15893) by [@tiangolo](https://github.com/tiangolo). * 🌐 Update translations for zh (update-outdated). PR [#15898](https://github.com/fastapi/fastapi/pull/15898) by [@tiangolo](https://github.com/tiangolo). From 512a3e7825dc7f9c4e08c350851d06ab005b18cc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebasti=C3=A1n=20Ram=C3=ADrez?= Date: Wed, 1 Jul 2026 15:57:35 +0200 Subject: [PATCH 374/462] =?UTF-8?q?=F0=9F=8C=90=20Update=20translations=20?= =?UTF-8?q?for=20de=20(update-outdated)=20(#15899)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: github-actions[bot] Co-authored-by: Yurii Motov --- docs/de/docs/_llm-test.md | 18 ++--- .../docs/advanced/additional-status-codes.md | 1 + .../de/docs/advanced/advanced-dependencies.md | 1 + docs/de/docs/advanced/dataclasses.md | 1 + docs/de/docs/advanced/events.md | 6 +- docs/de/docs/advanced/generate-clients.md | 14 ---- docs/de/docs/advanced/json-base64-bytes.md | 2 +- docs/de/docs/advanced/openapi-callbacks.md | 10 +-- .../advanced/response-change-status-code.md | 1 + docs/de/docs/advanced/response-cookies.md | 1 + docs/de/docs/advanced/response-headers.md | 2 +- .../docs/advanced/security/oauth2-scopes.md | 6 +- docs/de/docs/advanced/settings.md | 20 +++--- docs/de/docs/advanced/stream-data.md | 8 +-- docs/de/docs/advanced/wsgi.md | 1 + docs/de/docs/alternatives.md | 10 +-- docs/de/docs/async.md | 6 +- docs/de/docs/deployment/cloud.md | 2 +- docs/de/docs/deployment/concepts.md | 20 +++--- docs/de/docs/deployment/docker.md | 32 ++++----- docs/de/docs/deployment/https.md | 6 +- docs/de/docs/deployment/manually.md | 6 +- docs/de/docs/editor-support.md | 14 ++-- docs/de/docs/environment-variables.md | 8 +-- docs/de/docs/features.md | 68 +++++++++---------- docs/de/docs/help-fastapi.md | 1 + docs/de/docs/how-to/configure-swagger-ui.md | 2 +- .../docs/how-to/custom-request-and-route.md | 1 + docs/de/docs/how-to/graphql.md | 1 + ...migrate-from-pydantic-v1-to-pydantic-v2.md | 18 +++++ .../docs/how-to/separate-openapi-schemas.md | 1 + docs/de/docs/index.md | 2 +- docs/de/docs/project-generation.md | 2 +- docs/de/docs/python-types.md | 26 +++---- docs/de/docs/tutorial/bigger-applications.md | 20 +++--- docs/de/docs/tutorial/body-nested-models.md | 55 +++++++-------- docs/de/docs/tutorial/body.md | 13 ++-- docs/de/docs/tutorial/debugging.md | 2 +- .../dependencies/dependencies-with-yield.md | 12 ++-- docs/de/docs/tutorial/extra-data-types.md | 1 + docs/de/docs/tutorial/extra-models.md | 6 +- docs/de/docs/tutorial/first-steps.md | 14 ++-- docs/de/docs/tutorial/handling-errors.md | 20 +++--- docs/de/docs/tutorial/index.md | 1 + docs/de/docs/tutorial/metadata.md | 2 +- .../tutorial/path-operation-configuration.md | 8 +-- .../tutorial/query-params-str-validations.md | 18 ++--- docs/de/docs/tutorial/query-params.md | 19 +++--- docs/de/docs/tutorial/request-files.md | 30 ++++---- docs/de/docs/tutorial/request-forms.md | 1 + docs/de/docs/tutorial/response-status-code.md | 1 + docs/de/docs/tutorial/schema-extra-example.md | 8 +-- docs/de/docs/tutorial/security/first-steps.md | 1 + .../tutorial/security/get-current-user.md | 2 +- docs/de/docs/tutorial/security/oauth2-jwt.md | 4 +- .../docs/tutorial/security/simple-oauth2.md | 12 ++-- docs/de/docs/tutorial/sql-databases.md | 6 +- docs/de/docs/tutorial/static-files.md | 8 +++ docs/de/docs/tutorial/testing.md | 8 +-- docs/de/docs/virtual-environments.md | 12 ++-- 60 files changed, 318 insertions(+), 284 deletions(-) diff --git a/docs/de/docs/_llm-test.md b/docs/de/docs/_llm-test.md index 81e8e25f5..3fec41817 100644 --- a/docs/de/docs/_llm-test.md +++ b/docs/de/docs/_llm-test.md @@ -1,17 +1,17 @@ # LLM-Testdatei { #llm-test-file } -Dieses Dokument testet, ob das LLM, das die Dokumentation übersetzt, den `general_prompt` in `scripts/translate.py` und den sprachspezifischen Prompt in `docs/{language code}/llm-prompt.md` versteht. Der sprachsspezifische Prompt wird an `general_prompt` angehängt. +Dieses Dokument testet, ob das LLM, das die Dokumentation übersetzt, den `general_prompt` in `scripts/translate.py` und den sprachspezifischen Prompt in `docs/{language code}/llm-prompt.md` versteht. Der sprachspezifische Prompt wird an `general_prompt` angehängt. -Hier hinzugefügte Tests werden von allen Erstellern sprachsspezifischer Prompts gesehen. +Hier hinzugefügte Tests werden von allen Erstellern sprachspezifischer Prompts gesehen. So verwenden: -* Einen sprachsspezifischen Prompt haben – `docs/{language code}/llm-prompt.md`. +* Einen sprachspezifischen Prompt haben – `docs/{language code}/llm-prompt.md`. * Eine frische Übersetzung dieses Dokuments in die gewünschte Zielsprache durchführen (siehe z. B. das Kommando `translate-page` der `translate.py`). Dadurch wird die Übersetzung unter `docs/{language code}/docs/_llm-test.md` erstellt. * Prüfen Sie, ob in der Übersetzung alles in Ordnung ist. -* Verbessern Sie bei Bedarf Ihren sprachsspezifischen Prompt, den allgemeinen Prompt oder das englische Dokument. +* Verbessern Sie bei Bedarf Ihren sprachspezifischen Prompt, den allgemeinen Prompt oder das englische Dokument. * Beheben Sie anschließend manuell die verbleibenden Probleme in der Übersetzung, sodass es eine gute Übersetzung ist. -* Übersetzen Sie erneut, nachdem die gute Übersetzung vorliegt. Das ideale Ergebnis wäre, dass das LLM an der Übersetzung keine Änderungen mehr vornimmt. Das bedeutet, dass der allgemeine Prompt und Ihr sprachsspezifischer Prompt so gut sind, wie sie sein können (Es wird manchmal ein paar scheinbar zufällige Änderungen machen, der Grund ist, dass [LLMs keine deterministischen Algorithmen sind](https://doublespeak.chat/#/handbook#deterministic-output)). +* Übersetzen Sie erneut, nachdem die gute Übersetzung vorliegt. Das ideale Ergebnis wäre, dass das LLM an der Übersetzung keine Änderungen mehr vornimmt. Das bedeutet, dass der allgemeine Prompt und Ihr sprachspezifischer Prompt so gut sind, wie sie sein können (Es wird manchmal ein paar scheinbar zufällige Änderungen machen, der Grund ist, dass [LLMs keine deterministischen Algorithmen sind](https://doublespeak.chat/#/handbook#deterministic-output)). Die Tests: @@ -211,7 +211,7 @@ Siehe Abschnitt `### HTML abbr elements` im allgemeinen Prompt in `scripts/trans //// -## HTML „dfn“-Elemente { #html-dfn-elements } +## HTML-„dfn“-Elemente { #html-dfn-elements } * Cluster * Deep Learning @@ -240,7 +240,7 @@ Die einzige strenge Regel für Überschriften ist, dass das LLM den Hash-Teil in Siehe Abschnitt `### Headings` im allgemeinen Prompt in `scripts/translate.py`. -Für einige sprachsspezifische Anweisungen, siehe z. B. den Abschnitt `### Headings` in `docs/de/llm-prompt.md`. +Für einige sprachspezifische Anweisungen, siehe z. B. den Abschnitt `### Headings` in `docs/de/llm-prompt.md`. //// @@ -363,12 +363,12 @@ Für einige sprachsspezifische Anweisungen, siehe z. B. den Abschnitt `### Headi * die Umgebungsvariable * die Umgebungsvariable * der `PATH` -* die `PATH`-Umgebungsvariable +* die `PATH`-Variable * die Authentifizierung * der Authentifizierungsanbieter * die Autorisierung -* das Anmeldeformular +* das Autorisierungsformular * der Autorisierungsanbieter * der Benutzer authentisiert sich * das System authentifiziert den Benutzer diff --git a/docs/de/docs/advanced/additional-status-codes.md b/docs/de/docs/advanced/additional-status-codes.md index f1a74a32c..6f0114cc1 100644 --- a/docs/de/docs/advanced/additional-status-codes.md +++ b/docs/de/docs/advanced/additional-status-codes.md @@ -1,5 +1,6 @@ # Zusätzliche Statuscodes { #additional-status-codes } + Standardmäßig liefert **FastAPI** die Responses als `JSONResponse` zurück und fügt den Inhalt, den Sie aus Ihrer *Pfadoperation* zurückgeben, in diese `JSONResponse` ein. Es wird der Default-Statuscode oder derjenige verwendet, den Sie in Ihrer *Pfadoperation* festgelegt haben. diff --git a/docs/de/docs/advanced/advanced-dependencies.md b/docs/de/docs/advanced/advanced-dependencies.md index 580a9a874..da06794a9 100644 --- a/docs/de/docs/advanced/advanced-dependencies.md +++ b/docs/de/docs/advanced/advanced-dependencies.md @@ -1,5 +1,6 @@ # Fortgeschrittene Abhängigkeiten { #advanced-dependencies } + ## Parametrisierte Abhängigkeiten { #parameterized-dependencies } Alle Abhängigkeiten, die wir bisher gesehen haben, waren festgelegte Funktionen oder Klassen. diff --git a/docs/de/docs/advanced/dataclasses.md b/docs/de/docs/advanced/dataclasses.md index ed8f13e72..bacf9d162 100644 --- a/docs/de/docs/advanced/dataclasses.md +++ b/docs/de/docs/advanced/dataclasses.md @@ -1,5 +1,6 @@ # Datenklassen verwenden { #using-dataclasses } + FastAPI basiert auf **Pydantic**, und ich habe Ihnen gezeigt, wie Sie Pydantic-Modelle verwenden können, um Requests und Responses zu deklarieren. Aber FastAPI unterstützt auf die gleiche Weise auch die Verwendung von [`dataclasses`](https://docs.python.org/3/library/dataclasses.html): diff --git a/docs/de/docs/advanced/events.md b/docs/de/docs/advanced/events.md index 7e2def32d..6efe96809 100644 --- a/docs/de/docs/advanced/events.md +++ b/docs/de/docs/advanced/events.md @@ -102,7 +102,7 @@ Diese Funktionen können mit `async def` oder normalem `def` deklariert werden. ### `startup`-Event { #startup-event } -Um eine Funktion hinzuzufügen, die vor dem Start der Anwendung ausgeführt werden soll, deklarieren Sie diese mit dem Event `startup`: +Um eine Funktion hinzuzufügen, die vor dem Start der Anwendung ausgeführt werden soll, deklarieren Sie diese mit dem Event `"startup"`: {* ../../docs_src/events/tutorial001_py310.py hl[8] *} @@ -114,7 +114,7 @@ Und Ihre Anwendung empfängt erst dann Requests, wenn alle `startup`-Eventhandle ### `shutdown`-Event { #shutdown-event } -Um eine Funktion hinzuzufügen, die beim Shutdown der Anwendung ausgeführt werden soll, deklarieren Sie sie mit dem Event `shutdown`: +Um eine Funktion hinzuzufügen, die beim Shutdown der Anwendung ausgeführt werden soll, deklarieren Sie sie mit dem Event `"shutdown"`: {* ../../docs_src/events/tutorial002_py310.py hl[6] *} @@ -150,7 +150,7 @@ Aus diesem Grund wird jetzt empfohlen, stattdessen `lifespan` wie oben erläuter Nur ein technisches Detail für die neugierigen Nerds. 🤓 -In der technischen ASGI-Spezifikation ist dies Teil des [Lifespan Protokolls](https://asgi.readthedocs.io/en/latest/specs/lifespan.html) und definiert Events namens `startup` und `shutdown`. +In der technischen ASGI-Spezifikation ist dies Teil des [Lifespan-Protokolls](https://asgi.readthedocs.io/en/latest/specs/lifespan.html) und definiert Events namens `startup` und `shutdown`. /// note | Hinweis diff --git a/docs/de/docs/advanced/generate-clients.md b/docs/de/docs/advanced/generate-clients.md index 7c418226a..d93641bd3 100644 --- a/docs/de/docs/advanced/generate-clients.md +++ b/docs/de/docs/advanced/generate-clients.md @@ -20,20 +20,6 @@ FastAPI generiert automatisch **OpenAPI 3.1**-Spezifikationen, daher muss jedes /// -## SDK-Generatoren von FastAPI-Sponsoren { #sdk-generators-from-fastapi-sponsors } - -Dieser Abschnitt hebt **venture-unterstützte** und **firmengestützte** Lösungen hervor, die von Unternehmen entwickelt werden, welche FastAPI sponsern. Diese Produkte bieten **zusätzliche Funktionen** und **Integrationen** zusätzlich zu hochwertig generierten SDKs. - -Durch das ✨ [**Sponsoring von FastAPI**](../help-fastapi.md#sponsor-the-author) ✨ helfen diese Unternehmen sicherzustellen, dass das Framework und sein **Ökosystem** gesund und **nachhaltig** bleiben. - -Ihr Sponsoring zeigt auch ein starkes Engagement für die FastAPI-**Community** (Sie), was bedeutet, dass sie nicht nur einen **großartigen Service** bieten möchten, sondern auch ein **robustes und florierendes Framework**, FastAPI, unterstützen möchten. 🙇 - -Zum Beispiel könnten Sie ausprobieren: - -* [Stainless](https://www.stainless.com/?utm_source=fastapi&utm_medium=referral) - -Einige dieser Lösungen sind möglicherweise auch Open Source oder bieten kostenlose Tarife an, sodass Sie diese ohne finanzielle Verpflichtung ausprobieren können. Andere kommerzielle SDK-Generatoren sind online verfügbar und können dort gefunden werden. 🤓 - ## Ein TypeScript-SDK erstellen { #create-a-typescript-sdk } Beginnen wir mit einer einfachen FastAPI-Anwendung: diff --git a/docs/de/docs/advanced/json-base64-bytes.md b/docs/de/docs/advanced/json-base64-bytes.md index 26c7e7089..618bbd1a9 100644 --- a/docs/de/docs/advanced/json-base64-bytes.md +++ b/docs/de/docs/advanced/json-base64-bytes.md @@ -4,7 +4,7 @@ Wenn Ihre App JSON-Daten empfangen und senden muss, Sie darin aber Binärdaten e ## Base64 vs Dateien { #base64-vs-files } -Prüfen Sie zunächst, ob Sie [Request Files](../tutorial/request-files.md) zum Hochladen von Binärdaten und [Benutzerdefinierte Response – FileResponse](./custom-response.md#fileresponse--fileresponse-) zum Senden von Binärdaten verwenden können, anstatt sie in JSON zu kodieren. +Prüfen Sie zunächst, ob Sie [Requestdateien](../tutorial/request-files.md) zum Hochladen von Binärdaten und [Benutzerdefinierte Response – FileResponse](./custom-response.md#fileresponse) zum Senden von Binärdaten verwenden können, anstatt sie in JSON zu kodieren. JSON kann nur UTF-8-kodierte Strings enthalten, es kann daher keine rohen Bytes enthalten. diff --git a/docs/de/docs/advanced/openapi-callbacks.md b/docs/de/docs/advanced/openapi-callbacks.md index 989f8a1b0..b5d49c7e8 100644 --- a/docs/de/docs/advanced/openapi-callbacks.md +++ b/docs/de/docs/advanced/openapi-callbacks.md @@ -12,7 +12,7 @@ Sehen wir uns das alles anhand eines Beispiels an. Stellen Sie sich vor, Sie entwickeln eine Anwendung, mit der Sie Rechnungen erstellen können. -Diese Rechnungen haben eine `id`, einen optionalen `title`, einen `customer` (Kunde) und ein `total` (Gesamtsumme). +Diese Rechnungen haben eine `id`, einen `title` (optional), einen `customer` und ein `total`. Der Benutzer Ihrer API (ein externer Entwickler) erstellt mit einem POST-Request eine Rechnung in Ihrer API. @@ -118,13 +118,13 @@ In diesem Fall ist es der `str`: "{$callback_url}/invoices/{$request.body.id}" ``` -Wenn Ihr API-Benutzer (der externe Entwickler) also einen Request an *Ihre API* sendet, via: +Wenn Ihr API-Benutzer (der externe Entwickler) also einen Request an *Ihre API* sendet, an: ``` https://yourapi.com/invoices/?callback_url=https://www.external.org/events ``` -mit einem JSON-Körper: +mit einem JSON-Body: ```JSON { @@ -167,13 +167,13 @@ Beachten Sie, dass die verwendete Callback-URL die URL enthält, die als Query-P An diesem Punkt haben Sie die benötigte(n) *Callback-Pfadoperation(en)* (diejenige(n), die der *externe Entwickler* in der *externen API* implementieren sollte) im Callback-Router, den Sie oben erstellt haben. -Verwenden Sie nun den Parameter `callbacks` im *Pfadoperation-Dekorator Ihrer API*, um das Attribut `.routes` (das ist eigentlich nur eine `list`e von Routen/*Pfadoperationen*) dieses Callback-Routers zu übergeben: +Verwenden Sie nun den Parameter `callbacks` im *Pfadoperation-Dekorator Ihrer API*, um das Attribut `.routes` dieses Callback-Routers zu übergeben: {* ../../docs_src/openapi_callbacks/tutorial001_py310.py hl[33] *} /// tip | Tipp -Beachten Sie, dass Sie nicht den Router selbst (`invoices_callback_router`) an `callback=` übergeben, sondern das Attribut `.routes`, wie in `invoices_callback_router.routes`. FastAPI wird diese Routen verwenden, um die Callback-OpenAPI-Dokumentation zu generieren. +Beachten Sie, dass Sie nicht den Router selbst (`invoices_callback_router`) an `callbacks=` übergeben, sondern dessen `.routes`, wie in `invoices_callback_router.routes`. FastAPI wird diese Routen verwenden, um die Callback-OpenAPI-Dokumentation zu generieren. /// diff --git a/docs/de/docs/advanced/response-change-status-code.md b/docs/de/docs/advanced/response-change-status-code.md index a0d90fe80..a334cc0bb 100644 --- a/docs/de/docs/advanced/response-change-status-code.md +++ b/docs/de/docs/advanced/response-change-status-code.md @@ -1,5 +1,6 @@ # Response – Statuscode ändern { #response-change-status-code } + Sie haben wahrscheinlich schon vorher gelesen, dass Sie einen Default-[Response-Statuscode](../tutorial/response-status-code.md) festlegen können. In manchen Fällen müssen Sie jedoch einen anderen als den Default-Statuscode zurückgeben. diff --git a/docs/de/docs/advanced/response-cookies.md b/docs/de/docs/advanced/response-cookies.md index 672bbbe78..34eb6cfe9 100644 --- a/docs/de/docs/advanced/response-cookies.md +++ b/docs/de/docs/advanced/response-cookies.md @@ -1,5 +1,6 @@ # Response-Cookies { #response-cookies } + ## Einen `Response`-Parameter verwenden { #use-a-response-parameter } Sie können einen Parameter vom Typ `Response` in Ihrer *Pfadoperation-Funktion* deklarieren. diff --git a/docs/de/docs/advanced/response-headers.md b/docs/de/docs/advanced/response-headers.md index bcec04be8..baf5715a3 100644 --- a/docs/de/docs/advanced/response-headers.md +++ b/docs/de/docs/advanced/response-headers.md @@ -38,4 +38,4 @@ Und da die `Response` häufig zum Setzen von Headern und Cookies verwendet wird, Beachten Sie, dass benutzerdefinierte proprietäre Header [mit dem Präfix `X-`](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers) hinzugefügt werden können. -Wenn Sie jedoch benutzerdefinierte Header haben, die ein Client in einem Browser sehen können soll, müssen Sie diese zu Ihrer CORS-Konfiguration hinzufügen (weitere Informationen finden Sie unter [CORS (Cross-Origin Resource Sharing)](../tutorial/cors.md)), unter Verwendung des Parameters `expose_headers`, dokumentiert in [Starlettes CORS-Dokumentation](https://www.starlette.dev/middleware/#corsmiddleware). +Wenn Sie jedoch benutzerdefinierte Header haben, die ein Client in einem Browser sehen können soll, müssen Sie diese zu Ihren CORS-Konfigurationen hinzufügen (weitere Informationen finden Sie unter [CORS (Cross-Origin Resource Sharing)](../tutorial/cors.md)), unter Verwendung des Parameters `expose_headers`, dokumentiert in [Starlettes CORS-Dokumentation](https://www.starlette.dev/middleware/#corsmiddleware). diff --git a/docs/de/docs/advanced/security/oauth2-scopes.md b/docs/de/docs/advanced/security/oauth2-scopes.md index 6a459524c..74457b40d 100644 --- a/docs/de/docs/advanced/security/oauth2-scopes.md +++ b/docs/de/docs/advanced/security/oauth2-scopes.md @@ -247,7 +247,7 @@ Das würde einer Drittanbieteranwendung passieren, die versucht, auf eine dieser ## Über Integrationen von Drittanbietern { #about-third-party-integrations } -In diesem Beispiel verwenden wir den OAuth2-Flow „Password“. +In diesem Beispiel verwenden wir den OAuth2-Flow „password“. Das ist angemessen, wenn wir uns bei unserer eigenen Anwendung anmelden, wahrscheinlich mit unserem eigenen Frontend. @@ -255,9 +255,9 @@ Weil wir darauf vertrauen können, dass es den `username` und das `password` erh Wenn Sie jedoch eine OAuth2-Anwendung erstellen, mit der andere eine Verbindung herstellen würden (d.h. wenn Sie einen Authentifizierungsanbieter erstellen, der Facebook, Google, GitHub usw. entspricht), sollten Sie einen der anderen Flows verwenden. -Am häufigsten ist der „Implicit“-Flow. +Am häufigsten ist der implicit Flow. -Am sichersten ist der „Code“-Flow, die Implementierung ist jedoch komplexer, da mehr Schritte erforderlich sind. Da er komplexer ist, schlagen viele Anbieter letztendlich den „Implicit“-Flow vor. +Am sichersten ist der code Flow, die Implementierung ist jedoch komplexer, da mehr Schritte erforderlich sind. Da er komplexer ist, schlagen viele Anbieter letztendlich den implicit Flow vor. /// note | Hinweis diff --git a/docs/de/docs/advanced/settings.md b/docs/de/docs/advanced/settings.md index 1df74802b..993e5ae71 100644 --- a/docs/de/docs/advanced/settings.md +++ b/docs/de/docs/advanced/settings.md @@ -14,13 +14,13 @@ Um Umgebungsvariablen zu verstehen, können Sie [Umgebungsvariablen](../environm ## Typen und Validierung { #types-and-validation } -Diese Umgebungsvariablen können nur Text-Zeichenketten verarbeiten, da sie außerhalb von Python liegen und mit anderen Programmen und dem Rest des Systems (und sogar mit verschiedenen Betriebssystemen wie Linux, Windows, macOS) kompatibel sein müssen. +Diese Umgebungsvariablen können nur Text-Strings verarbeiten, da sie außerhalb von Python liegen und mit anderen Programmen und dem Rest des Systems (und sogar mit verschiedenen Betriebssystemen wie Linux, Windows, macOS) kompatibel sein müssen. Das bedeutet, dass jeder in Python aus einer Umgebungsvariablen gelesene Wert ein `str` ist und jede Konvertierung in einen anderen Typ oder jede Validierung im Code erfolgen muss. ## Pydantic `Settings` { #pydantic-settings } -Glücklicherweise bietet Pydantic ein großartiges Werkzeug zur Verarbeitung dieser Einstellungen, die von Umgebungsvariablen stammen, mit [Pydantic: Settings Management](https://docs.pydantic.dev/latest/concepts/pydantic_settings/). +Glücklicherweise bietet Pydantic ein großartiges Werkzeug zur Verarbeitung dieser Einstellungen, die von Umgebungsvariablen stammen, mit [Pydantic: Settings-Verwaltung](https://docs.pydantic.dev/latest/concepts/pydantic_settings/). ### `pydantic-settings` installieren { #install-pydantic-settings } @@ -92,9 +92,9 @@ Um mehrere Umgebungsvariablen für einen einzelnen Befehl festzulegen, trennen S /// -Und dann würde die Einstellung `admin_email` auf „deadpool@example.com“ gesetzt. +Und dann würde die Einstellung `admin_email` auf `"deadpool@example.com"` gesetzt. -Der `app_name` wäre „ChimichangApp“. +Der `app_name` wäre `"ChimichangApp"`. Und `items_per_user` würde seinen Defaultwert von `50` behalten. @@ -128,7 +128,7 @@ Ausgehend vom vorherigen Beispiel könnte Ihre Datei `config.py` so aussehen: {* ../../docs_src/settings/app02_an_py310/config.py hl[10] *} -Beachten Sie, dass wir jetzt keine Standardinstanz `settings = Settings()` erstellen. +Beachten Sie, dass wir jetzt keine Defaultinstanz `settings = Settings()` erstellen. ### Die Haupt-Anwendungsdatei { #the-main-app-file } @@ -158,7 +158,7 @@ Bei der Abhängigkeitsüberschreibung legen wir einen neuen Wert für `admin_ema Dann können wir testen, ob das verwendet wird. -## Lesen einer `.env`-Datei { #reading-a-env-file } +## Eine `.env`-Datei lesen { #reading-a-env-file } Wenn Sie viele Einstellungen haben, die sich möglicherweise oft ändern, vielleicht in verschiedenen Umgebungen, kann es nützlich sein, diese in eine Datei zu schreiben und sie dann daraus zu lesen, als wären sie Umgebungsvariablen. @@ -172,7 +172,7 @@ Aber eine dotenv-Datei muss nicht unbedingt genau diesen Dateinamen haben. /// -Pydantic unterstützt das Lesen dieser Dateitypen mithilfe einer externen Bibliothek. Weitere Informationen finden Sie unter [Pydantic Settings: Dotenv (.env) support](https://docs.pydantic.dev/latest/concepts/pydantic_settings/#dotenv-env-support). +Pydantic unterstützt das Lesen dieser Dateitypen mithilfe einer externen Bibliothek. Weitere Informationen finden Sie unter [Pydantic Settings: Dotenv (.env)-Unterstützung](https://docs.pydantic.dev/latest/concepts/pydantic_settings/#dotenv-env-support). /// tip | Tipp @@ -197,13 +197,13 @@ Und dann aktualisieren Sie Ihre `config.py` mit: /// tip | Tipp -Das Attribut `model_config` wird nur für die Pydantic-Konfiguration verwendet. Weitere Informationen finden Sie unter [Pydantic: Concepts: Configuration](https://docs.pydantic.dev/latest/concepts/config/). +Das Attribut `model_config` wird nur für die Pydantic-Konfiguration verwendet. Weitere Informationen finden Sie unter [Pydantic: Konzepte: Konfiguration](https://docs.pydantic.dev/latest/concepts/config/). /// Hier definieren wir die Konfiguration `env_file` innerhalb Ihrer Pydantic-`Settings`-Klasse und setzen den Wert auf den Dateinamen mit der dotenv-Datei, die wir verwenden möchten. -### Die `Settings` nur einmal laden mittels `lru_cache` { #creating-the-settings-only-once-with-lru-cache } +### Die `Settings` nur einmal mittels `lru_cache` erstellen { #creating-the-settings-only-once-with-lru-cache } Das Lesen einer Datei von der Festplatte ist normalerweise ein kostspieliger (langsamer) Vorgang, daher möchten Sie ihn wahrscheinlich nur einmal ausführen und dann dasselbe Einstellungsobjekt erneut verwenden, anstatt es für jeden Request zu lesen. @@ -291,7 +291,7 @@ Im Fall unserer Abhängigkeit `get_settings()` akzeptiert die Funktion nicht ein Auf diese Weise verhält es sich fast so, als wäre es nur eine globale Variable. Da es jedoch eine Abhängigkeitsfunktion verwendet, können wir diese zu Testzwecken problemlos überschreiben. -`@lru_cache` ist Teil von `functools`, welches Teil von Pythons Standardbibliothek ist. Weitere Informationen dazu finden Sie in der [Python Dokumentation für `@lru_cache`](https://docs.python.org/3/library/functools.html#functools.lru_cache). +`@lru_cache` ist Teil von `functools`, welches Teil von Pythons Standardbibliothek ist. Weitere Informationen dazu finden Sie in der [Python-Dokumentation für `@lru_cache`](https://docs.python.org/3/library/functools.html#functools.lru_cache). ## Zusammenfassung { #recap } diff --git a/docs/de/docs/advanced/stream-data.md b/docs/de/docs/advanced/stream-data.md index 500970029..16ff73e78 100644 --- a/docs/de/docs/advanced/stream-data.md +++ b/docs/de/docs/advanced/stream-data.md @@ -20,13 +20,13 @@ Sie könnten auf diese Weise auch **Video** oder **Audio** streamen, es könnte ## Eine `StreamingResponse` mit `yield` { #a-streamingresponse-with-yield } -Wenn Sie in Ihrer Pfadoperation-Funktion ein `response_class=StreamingResponse` deklarieren, können Sie `yield` verwenden, um nacheinander jeden Datenchunk zu senden. +Wenn Sie in Ihrer *Pfadoperation-Funktion* ein `response_class=StreamingResponse` deklarieren, können Sie `yield` verwenden, um nacheinander jeden Datenchunk zu senden. {* ../../docs_src/stream_data/tutorial001_py310.py ln[1:23] hl[20,23] *} FastAPI übergibt jeden Datenchunk unverändert an die `StreamingResponse`, es wird nicht versucht, ihn in JSON oder etwas Ähnliches zu konvertieren. -### Nicht-async-Pfadoperation-Funktionen { #non-async-path-operation-functions } +### Nicht-async-*Pfadoperation-Funktionen* { #non-async-path-operation-functions } Sie können auch reguläre `def`-Funktionen (ohne `async`) verwenden und `yield` auf die gleiche Weise einsetzen. @@ -58,7 +58,7 @@ Zum Beispiel können Sie eine `PNGStreamingResponse` erstellen, die den `Content {* ../../docs_src/stream_data/tutorial002_py310.py ln[6,19:20] hl[20] *} -Dann können Sie diese neue Klasse mit `response_class=PNGStreamingResponse` in Ihrer Pfadoperation-Funktion verwenden: +Dann können Sie diese neue Klasse mit `response_class=PNGStreamingResponse` in Ihrer *Pfadoperation-Funktion* verwenden: {* ../../docs_src/stream_data/tutorial002_py310.py ln[23:27] hl[23] *} @@ -98,7 +98,7 @@ Aber in vielen Fällen würde das Lesen einer Datei oder eines dateiähnlichen O /// -Um die Event-Loop nicht zu blockieren, können Sie die Pfadoperation-Funktion einfach mit normalem `def` statt `async def` deklarieren, dadurch führt FastAPI sie in einem Threadpool-Worker aus, um die Haupt-Event-Loop nicht zu blockieren. +Um die Event-Loop nicht zu blockieren, können Sie die *Pfadoperation-Funktion* einfach mit normalem `def` statt `async def` deklarieren, dadurch führt FastAPI sie in einem Threadpool-Worker aus, um die Haupt-Event-Loop nicht zu blockieren. {* ../../docs_src/stream_data/tutorial002_py310.py ln[30:34] hl[31] *} diff --git a/docs/de/docs/advanced/wsgi.md b/docs/de/docs/advanced/wsgi.md index 19d002886..353734a3a 100644 --- a/docs/de/docs/advanced/wsgi.md +++ b/docs/de/docs/advanced/wsgi.md @@ -1,5 +1,6 @@ # WSGI inkludieren – Flask, Django und andere { #including-wsgi-flask-django-others } + Sie können WSGI-Anwendungen mounten, wie Sie es in [Unteranwendungen – Mounts](sub-applications.md), [Hinter einem Proxy](behind-a-proxy.md) gesehen haben. Dazu können Sie die `WSGIMiddleware` verwenden und damit Ihre WSGI-Anwendung wrappen, zum Beispiel Flask, Django usw. diff --git a/docs/de/docs/alternatives.md b/docs/de/docs/alternatives.md index 70948e499..5a814cb55 100644 --- a/docs/de/docs/alternatives.md +++ b/docs/de/docs/alternatives.md @@ -283,7 +283,7 @@ Aus diesem Grund basiert **FastAPI** auf Starlette, da dieses das schnellste ver Falcon ist ein weiteres leistungsstarkes Python-Framework. Es ist minimalistisch konzipiert und dient als Grundlage für andere Frameworks wie Hug. -Es ist so konzipiert, dass es über Funktionen verfügt, welche zwei Parameter empfangen, einen „Request“ und eine „Response“. Dann „lesen“ Sie Teile des Requests und „schreiben“ Teile der Response. Aufgrund dieses Designs ist es nicht möglich, Request-Parameter und -Bodys mit Standard-Python-Typhinweisen als Funktionsparameter zu deklarieren. +Es ist so konzipiert, dass es über Funktionen verfügt, welche zwei Parameter empfangen, einen „Request“ und eine „Response“. Dann „lesen“ Sie Teile des Requests und „schreiben“ Teile der Response. Aufgrund dieses Designs ist es nicht möglich, Request-Parameter und Requestbodys mit Standard-Python-Typhinweisen als Funktionsparameter zu deklarieren. Daher müssen Datenvalidierung, Serialisierung und Dokumentation im Code und nicht automatisch erfolgen. Oder sie müssen als Framework oberhalb von Falcon implementiert werden, so wie Hug. Dieselbe Unterscheidung findet auch in anderen Frameworks statt, die vom Design von Falcon inspiriert sind und ein Requestobjekt und ein Responseobjekt als Parameter haben. @@ -351,11 +351,11 @@ Hug inspirierte **FastAPI** dazu, einen `response`-Parameter in Funktionen zu de /// -### [APIStar](https://github.com/encode/apistar) (≦ 0.5) { #apistar-0-5 } +### [APIStar](https://github.com/encode/apistar) (<= 0.5) { #apistar-0-5 } Kurz bevor ich mich entschied, **FastAPI** zu erstellen, fand ich den **APIStar**-Server. Er hatte fast alles, was ich suchte, und ein tolles Design. -Er war eine der ersten Implementierungen eines Frameworks, die ich je gesehen hatte (vor NestJS und Molten), welches Python-Typhinweise zur Deklaration von Parametern und Requests verwendeten. Ich habe ihn mehr oder weniger zeitgleich mit Hug gefunden. Aber APIStar nutzte den OpenAPI-Standard. +Er war eine der ersten Implementierungen eines Frameworks, die ich je gesehen hatte (vor NestJS und Molten), das Python-Typhinweise zur Deklaration von Parametern und Requests verwendete. Ich habe ihn mehr oder weniger zeitgleich mit Hug gefunden. Aber APIStar nutzte den OpenAPI-Standard. Er verfügte an mehreren Stellen über automatische Datenvalidierung, Datenserialisierung und OpenAPI-Schemagenerierung, basierend auf denselben Typhinweisen. @@ -433,7 +433,7 @@ Es bietet: * CORS, GZip, statische Dateien, Responses streamen. * Session- und Cookie-Unterstützung. * 100 % Testabdeckung. -* 100 % Typannotierte Codebasis. +* 100 % typannotierte Codebasis. * Wenige starke Abhängigkeiten. Starlette ist derzeit das schnellste getestete Python-Framework. Nur übertroffen von Uvicorn, welches kein Framework, sondern ein Server ist. @@ -448,7 +448,7 @@ Das ist eines der wichtigsten Dinge, welche **FastAPI** hinzufügt, alles basier ASGI ist ein neuer „Standard“, welcher von Mitgliedern des Django-Kernteams entwickelt wird. Es handelt sich immer noch nicht um einen „Python-Standard“ (ein PEP), obwohl sie gerade dabei sind, das zu tun. -Dennoch wird es bereits von mehreren Tools als „Standard“ verwendet. Das verbessert die Interoperabilität erheblich, da Sie Uvicorn mit jeden anderen ASGI-Server (wie Daphne oder Hypercorn) tauschen oder ASGI-kompatible Tools wie `python-socketio` hinzufügen können. +Dennoch wird es bereits von mehreren Tools als „Standard“ verwendet. Das verbessert die Interoperabilität erheblich, da Sie Uvicorn mit jedem anderen ASGI-Server (wie Daphne oder Hypercorn) tauschen oder ASGI-kompatible Tools wie `python-socketio` hinzufügen können. /// diff --git a/docs/de/docs/async.md b/docs/de/docs/async.md index d2a3a1de2..060e39bf9 100644 --- a/docs/de/docs/async.md +++ b/docs/de/docs/async.md @@ -44,7 +44,7 @@ Wenn Ihre Anwendung (irgendwie) nicht mit etwas anderem kommunizieren und auf de --- -Wenn Sie sich unsicher sind, verwenden Sie einfach `def`. +Wenn Sie sich unsicher sind, verwenden Sie normales `def`. --- @@ -70,7 +70,7 @@ Asynchroner Code bedeutet lediglich, dass die Sprache 💬 eine Möglichkeit hat Während der Zeit, die „Langsam-Datei“ 📝 benötigt, kann das System also andere Aufgaben erledigen. -Dann kommt der Computer / das Programm 🤖 bei jeder Gelegenheit zurück, weil es entweder wieder wartet oder wann immer es 🤖 die ganze Arbeit erledigt hat, die zu diesem Zeitpunkt zu tun war. Und es 🤖 wird nachschauen, ob eine der Aufgaben, auf die es gewartet hat, fertig ist. +Dann kommt der Computer / das Programm 🤖 bei jeder Gelegenheit zurück, weil es entweder wieder wartet oder wann immer es 🤖 die ganze Arbeit erledigt hat, die zu diesem Zeitpunkt zu tun war. Und es 🤖 wird nachschauen, ob eine der Aufgaben, auf die es gewartet hat, bereits fertig ist, und tun, was es zu tun hatte. Dann nimmt es 🤖 die erste erledigte Aufgabe (sagen wir, unsere „Langsam-Datei“ 📝) und bearbeitet sie weiter. @@ -361,7 +361,7 @@ Wenn Sie mit **FastAPI** arbeiten, müssen Sie sich darüber keine Sorgen machen Wenn Sie jedoch `async` / `await` ohne FastAPI verwenden möchten, können Sie dies auch tun. -### Schreiben Sie Ihren eigenen asynchronen Code { #write-your-own-async-code } +### Ihren eigenen asynchronen Code schreiben { #write-your-own-async-code } Starlette (und **FastAPI**) basieren auf [AnyIO](https://anyio.readthedocs.io/en/stable/), was bedeutet, dass es sowohl kompatibel mit der Python-Standardbibliothek [asyncio](https://docs.python.org/3/library/asyncio-task.html) als auch mit [Trio](https://trio.readthedocs.io/en/stable/) ist. diff --git a/docs/de/docs/deployment/cloud.md b/docs/de/docs/deployment/cloud.md index 2c8fe85c4..75f7ef881 100644 --- a/docs/de/docs/deployment/cloud.md +++ b/docs/de/docs/deployment/cloud.md @@ -16,7 +16,7 @@ FastAPI Cloud ist der Hauptsponsor und Finanzierungsgeber für die *FastAPI and ## Cloudanbieter – Sponsoren { #cloud-providers-sponsors } -Einige andere Cloudanbieter ✨ [**sponsern FastAPI**](../help-fastapi.md#sponsor-the-author) ✨ ebenfalls. 🙇 +Einige andere Cloudanbieter ✨ [**sponsern FastAPI**](https://github.com/sponsors/tiangolo) ✨ ebenfalls. 🙇 Sie könnten diese ebenfalls in Betracht ziehen, deren Anleitungen folgen und ihre Dienste ausprobieren: diff --git a/docs/de/docs/deployment/concepts.md b/docs/de/docs/deployment/concepts.md index be00b2260..487ad6392 100644 --- a/docs/de/docs/deployment/concepts.md +++ b/docs/de/docs/deployment/concepts.md @@ -1,6 +1,6 @@ # Deployment-Konzepte { #deployments-concepts } -Bei dem Deployment – der Bereitstellung – einer **FastAPI**-Anwendung, oder eigentlich jeder Art von Web-API, gibt es mehrere Konzepte, die Sie wahrscheinlich interessieren, und mithilfe der Sie die **am besten geeignete** Methode zum **Deployment Ihrer Anwendung** finden können. +Beim Deployment einer **FastAPI**-Anwendung, oder eigentlich jeder Art von Web-API, gibt es mehrere Konzepte, die Sie wahrscheinlich interessieren, und mithilfe derer Sie die **am besten geeignete** Methode zum **Deployment Ihrer Anwendung** finden können. Einige wichtige Konzepte sind: @@ -59,7 +59,7 @@ Die nächsten zu berücksichtigenden Konzepte drehen sich dann um das Programm, Wir werden viel über den laufenden „**Prozess**“ sprechen, daher ist es nützlich, Klarheit darüber zu haben, was das bedeutet und was der Unterschied zum Wort „**Programm**“ ist. -### Was ist ein Programm { #what-is-a-program } +### Was ein Programm ist { #what-is-a-program } Das Wort **Programm** wird häufig zur Beschreibung vieler Dinge verwendet: @@ -67,14 +67,14 @@ Das Wort **Programm** wird häufig zur Beschreibung vieler Dinge verwendet: * Die **Datei**, die vom Betriebssystem **ausgeführt** werden kann, zum Beispiel: `python`, `python.exe` oder `uvicorn`. * Ein bestimmtes Programm, während es auf dem Betriebssystem **läuft**, die CPU nutzt und Dinge im Arbeitsspeicher ablegt. Dies wird auch als **Prozess** bezeichnet. -### Was ist ein Prozess { #what-is-a-process } +### Was ein Prozess ist { #what-is-a-process } Das Wort **Prozess** wird normalerweise spezifischer verwendet und bezieht sich nur auf das, was im Betriebssystem ausgeführt wird (wie im letzten Punkt oben): * Ein bestimmtes Programm, während es auf dem Betriebssystem **ausgeführt** wird. * Dies bezieht sich weder auf die Datei noch auf den Code, sondern **speziell** auf das, was vom Betriebssystem **ausgeführt** und verwaltet wird. -* Jedes Programm, jeder Code **kann nur dann Dinge tun**, wenn er **ausgeführt** wird, wenn also ein **Prozess läuft**. -* Der Prozess kann von Ihnen oder vom Betriebssystem **terminiert** („beendet“, „gekillt“) werden. An diesem Punkt hört es auf zu laufen/ausgeführt zu werden und kann **keine Dinge mehr tun**. +* Jedes Programm, jeder Code **kann nur dann Dinge tun**, wenn er **ausgeführt** wird. Also dann, wenn ein **Prozess läuft**. +* Der Prozess kann von Ihnen oder vom Betriebssystem **terminiert** („beendet“, „gekillt“) werden. An diesem Punkt hört er auf zu laufen/ausgeführt zu werden und kann **keine Dinge mehr tun**. * Hinter jeder Anwendung, die Sie auf Ihrem Computer ausführen, steckt ein Prozess, jedes laufende Programm, jedes Fenster usw. Und normalerweise laufen viele Prozesse **gleichzeitig**, während ein Computer eingeschaltet ist. * Es können **mehrere Prozesse** desselben **Programms** gleichzeitig ausgeführt werden. @@ -117,7 +117,7 @@ Einige Beispiele für Tools, die diese Aufgabe übernehmen können, sind: * Docker * Kubernetes * Docker Compose -* Docker im Schwarm-Modus +* Docker im Swarm-Modus * Systemd * Supervisor * Es wird intern von einem Cloudanbieter im Rahmen seiner Dienste verwaltet @@ -137,7 +137,7 @@ Und wir als Entwickler verbessern den Code ständig, wenn wir diese Bugs finden ### Kleine Fehler automatisch handhaben { #small-errors-automatically-handled } -Wenn beim Erstellen von Web-APIs mit FastAPI ein Fehler in unserem Code auftritt, wird FastAPI ihn normalerweise dem einzelnen Request zurückgeben, der den Fehler ausgelöst hat. 🛡 +Wenn beim Erstellen von Web-APIs mit FastAPI ein Fehler in unserem Code auftritt, wird FastAPI ihn normalerweise auf den einzelnen Request beschränken, der den Fehler ausgelöst hat. 🛡 Der Client erhält für diesen Request einen **500 Internal Server Error**, aber die Anwendung arbeitet bei den nächsten Requests weiter, anstatt einfach komplett abzustürzen. @@ -170,7 +170,7 @@ Dies könnte zum Beispiel erledigt werden durch: * Docker * Kubernetes * Docker Compose -* Docker im Schwarm-Modus +* Docker im Swarm-Modus * Systemd * Supervisor * Intern von einem Cloudanbieter im Rahmen seiner Dienste @@ -178,7 +178,7 @@ Dies könnte zum Beispiel erledigt werden durch: ## Replikation – Prozesse und Arbeitsspeicher { #replication-processes-and-memory } -Wenn Sie eine FastAPI-Anwendung verwenden und ein Serverprogramm wie den `fastapi`-Befehl, der Uvicorn ausführt, kann **ein einzelner Prozess** an mehrere Clients gleichzeitig ausliefern. +Wenn Sie eine FastAPI-Anwendung verwenden und ein Serverprogramm wie den `fastapi`-Befehl, der Uvicorn ausführt, kann die Ausführung in **einem Prozess** mehrere Clients gleichzeitig versorgen. In vielen Fällen möchten Sie jedoch mehrere Workerprozesse gleichzeitig ausführen. @@ -200,7 +200,7 @@ Um also **mehrere Prozesse** gleichzeitig zu haben, muss es einen **einzelnen Pr Wenn das Programm nun Dinge in den Arbeitsspeicher lädt, zum Beispiel ein Modell für maschinelles Lernen in einer Variablen oder den Inhalt einer großen Datei in einer Variablen, verbraucht das alles **einen Teil des Arbeitsspeichers (RAM – Random Access Memory)** des Servers. -Und mehrere Prozesse teilen sich normalerweise keinen Speicher. Das bedeutet, dass jeder laufende Prozess seine eigenen Dinge, eigenen Variablen und eigenen Speicher hat. Und wenn Sie in Ihrem Code viel Speicher verbrauchen, verbraucht **jeder Prozess** die gleiche Menge Speicher. +Und mehrere Prozesse **teilen sich normalerweise keinen Speicher**. Das bedeutet, dass jeder laufende Prozess seine eigenen Dinge, eigenen Variablen und eigenen Speicher hat. Und wenn Sie in Ihrem Code viel Speicher verbrauchen, verbraucht **jeder Prozess** die gleiche Menge Speicher. ### Serverspeicher { #server-memory } diff --git a/docs/de/docs/deployment/docker.md b/docs/de/docs/deployment/docker.md index db249f74f..0ab886c46 100644 --- a/docs/de/docs/deployment/docker.md +++ b/docs/de/docs/deployment/docker.md @@ -36,7 +36,7 @@ CMD ["fastapi", "run", "app/main.py", "--port", "80"] Container (hauptsächlich Linux-Container) sind eine sehr **leichtgewichtige** Möglichkeit, Anwendungen einschließlich aller ihrer Abhängigkeiten und erforderlichen Dateien zu verpacken und sie gleichzeitig von anderen Containern (anderen Anwendungen oder Komponenten) im selben System isoliert zu halten. -Linux-Container werden mit demselben Linux-Kernel des Hosts (Maschine, virtuellen Maschine, Cloud-Servers, usw.) ausgeführt. Das bedeutet einfach, dass sie sehr leichtgewichtig sind (im Vergleich zu vollständigen virtuellen Maschinen, die ein gesamtes Betriebssystem emulieren). +Linux-Container werden mit demselben Linux-Kernel des Hosts (Maschine, virtueller Maschine, Cloud-Server usw.) ausgeführt. Das bedeutet einfach, dass sie sehr leichtgewichtig sind (im Vergleich zu vollständigen virtuellen Maschinen, die ein gesamtes Betriebssystem emulieren). Auf diese Weise verbrauchen Container **wenig Ressourcen**, eine Menge vergleichbar mit der direkten Ausführung der Prozesse (eine virtuelle Maschine würde viel mehr verbrauchen). @@ -46,7 +46,7 @@ Container verfügen außerdem über ihre eigenen **isoliert** laufenden Prozesse Ein **Container** wird von einem **Containerimage** ausgeführt. -Ein Containerimage ist eine **statische** Version aller Dateien, Umgebungsvariablen und des Standardbefehls/-programms, welche in einem Container vorhanden sein sollten. **Statisch** bedeutet hier, dass das Container-**Image** nicht läuft, nicht ausgeführt wird, sondern nur die gepackten Dateien und Metadaten enthält. +Ein Containerimage ist eine **statische** Version aller Dateien, Umgebungsvariablen und des Standardbefehls/-programms, die in einem Container vorhanden sein sollten. **Statisch** bedeutet hier, dass das Container-**Image** nicht läuft, nicht ausgeführt wird, sondern nur die gepackten Dateien und Metadaten enthält. Im Gegensatz zu einem „**Containerimage**“, bei dem es sich um den gespeicherten statischen Inhalt handelt, bezieht sich ein „**Container**“ normalerweise auf die laufende Instanz, das Ding, das **ausgeführt** wird. @@ -89,7 +89,7 @@ Ein Container läuft, solange der **Hauptprozess** (Befehl oder Programm) läuft Ein Container hat normalerweise einen **einzelnen Prozess**, aber es ist auch möglich, Unterprozesse vom Hauptprozess aus zu starten, und auf diese Weise haben Sie **mehrere Prozesse** im selben Container. -Es ist jedoch nicht möglich, einen laufenden Container, ohne **mindestens einen laufenden Prozess** zu haben. Wenn der Hauptprozess stoppt, stoppt der Container. +Es ist jedoch nicht möglich, einen laufenden Container ohne **mindestens einen laufenden Prozess** zu haben. Wenn der Hauptprozess stoppt, stoppt der Container. ## Ein Docker-Image für FastAPI erstellen { #build-a-docker-image-for-fastapi } @@ -184,19 +184,19 @@ COPY ./app /code/app CMD ["fastapi", "run", "app/main.py", "--port", "80"] ``` -1. Beginne mit dem offiziellen Python-Basisimage. +1. Beginnen Sie mit dem offiziellen Python-Basisimage. -2. Setze das aktuelle Arbeitsverzeichnis auf `/code`. +2. Setzen Sie das aktuelle Arbeitsverzeichnis auf `/code`. Hier platzieren wir die Datei `requirements.txt` und das Verzeichnis `app`. -3. Kopiere die Datei mit den Paketanforderungen in das Verzeichnis `/code`. +3. Kopieren Sie die Datei mit den Paketanforderungen in das Verzeichnis `/code`. Kopieren Sie zuerst **nur** die Datei mit den Anforderungen, nicht den Rest des Codes. Da sich diese Datei **nicht oft ändert**, erkennt Docker das und verwendet den **Cache** für diesen Schritt, wodurch der Cache auch für den nächsten Schritt aktiviert wird. -4. Installiere die Paketabhängigkeiten aus der Anforderungsdatei. +4. Installieren Sie die Paketabhängigkeiten aus der Anforderungsdatei. Die Option `--no-cache-dir` weist `pip` an, die heruntergeladenen Pakete nicht lokal zu speichern, da dies nur benötigt wird, sollte `pip` erneut ausgeführt werden, um dieselben Pakete zu installieren, aber das ist beim Arbeiten mit Containern nicht der Fall. @@ -212,13 +212,13 @@ CMD ["fastapi", "run", "app/main.py", "--port", "80"] Durch die Verwendung des Caches in diesem Schritt **sparen** Sie viel **Zeit**, wenn Sie das Image während der Entwicklung immer wieder erstellen, anstatt **jedes Mal** alle Abhängigkeiten **herunterzuladen und zu installieren**. -5. Kopiere das Verzeichnis `./app` in das Verzeichnis `/code`. +5. Kopieren Sie das Verzeichnis `./app` in das Verzeichnis `/code`. Da hier der gesamte Code enthalten ist, der sich **am häufigsten ändert**, wird der Docker-**Cache** nicht ohne weiteres für diesen oder andere **folgende Schritte** verwendet. Daher ist es wichtig, dies **nahe dem Ende** des `Dockerfile`s zu platzieren, um die Erstellungszeiten des Containerimages zu optimieren. -6. Lege den **Befehl** fest, um `fastapi run` zu nutzen, welches Uvicorn darunter verwendet. +6. Legen Sie den **Befehl** fest, um `fastapi run` zu nutzen, welches Uvicorn darunter verwendet. `CMD` nimmt eine Liste von Zeichenfolgen entgegen. Jede dieser Zeichenfolgen entspricht dem, was Sie durch Leerzeichen getrennt in die Befehlszeile eingeben würden. @@ -405,7 +405,7 @@ COPY ./main.py /code/ CMD ["fastapi", "run", "main.py", "--port", "80"] ``` -1. Kopiere die Datei `main.py` direkt in das Verzeichnis `/code` (ohne ein Verzeichnis `./app`). +1. Kopieren Sie die Datei `main.py` direkt in das Verzeichnis `/code` (ohne ein Verzeichnis `./app`). 2. Verwenden Sie `fastapi run`, um Ihre Anwendung in der einzelnen Datei `main.py` bereitzustellen. @@ -440,7 +440,7 @@ Traefik verfügt über Integrationen mit Docker, Kubernetes und anderen, sodass /// -Alternativ könnte HTTPS von einem Cloud-Anbieter als einer seiner Dienste gehandhabt werden (während die Anwendung weiterhin in einem Container ausgeführt wird). +Alternativ könnte HTTPS von einem Cloudanbieter als einer seiner Dienste gehandhabt werden (während die Anwendung weiterhin in einem Container ausgeführt wird). ## Beim Hochfahren ausführen und Neustarts { #running-on-startup-and-restarts } @@ -488,7 +488,7 @@ Und normalerweise wäre dieser **Load Balancer** in der Lage, Requests zu verarb In einem solchen Szenario möchten Sie wahrscheinlich **einen einzelnen (Uvicorn-)Prozess pro Container** haben, da Sie die Replikation bereits auf Cluster-Ebene durchführen würden. -In diesem Fall möchten Sie also **nicht** mehrere Worker im Container haben, z. B. mit der `--workers` Befehlszeilenoption. Sie möchten nur einen **einzelnen Uvicorn-Prozess** pro Container haben (wahrscheinlich aber mehrere Container). +In diesem Fall möchten Sie also **nicht** mehrere Worker im Container haben, z. B. mit der `--workers`-Befehlszeilenoption. Sie möchten nur einen **einzelnen Uvicorn-Prozess** pro Container haben (wahrscheinlich aber mehrere Container). Ein weiterer Prozessmanager im Container (wie es bei mehreren Workern der Fall wäre) würde nur **unnötige Komplexität** hinzufügen, um welche Sie sich höchstwahrscheinlich bereits mit Ihrem Clustersystem kümmern. @@ -496,7 +496,7 @@ Ein weiterer Prozessmanager im Container (wie es bei mehreren Workern der Fall w Natürlich gibt es **Sonderfälle**, in denen Sie **einen Container** mit mehreren **Uvicorn-Workerprozessen** haben möchten. -In diesen Fällen können Sie die `--workers` Befehlszeilenoption verwenden, um die Anzahl der zu startenden Worker festzulegen: +In diesen Fällen können Sie die `--workers`-Befehlszeilenoption verwenden, um die Anzahl der zu startenden Worker festzulegen: ```{ .dockerfile .annotate } FROM python:3.14 @@ -513,7 +513,7 @@ COPY ./app /code/app CMD ["fastapi", "run", "app/main.py", "--port", "80", "--workers", "4"] ``` -1. Hier verwenden wir die `--workers` Befehlszeilenoption, um die Anzahl der Worker auf 4 festzulegen. +1. Hier verwenden wir die `--workers`-Befehlszeilenoption, um die Anzahl der Worker auf 4 festzulegen. Hier sind einige Beispiele, wann das sinnvoll sein könnte: @@ -529,7 +529,7 @@ Dann möchten Sie vielleicht **einen einzelnen Container** mit einem **Prozessma --- -Der Hauptpunkt ist, dass **keine** dieser Regeln **in Stein gemeißelt** ist, der man blind folgen muss. Sie können diese Ideen verwenden, um **Ihren eigenen Anwendungsfall zu evaluieren**, zu entscheiden, welcher Ansatz für Ihr System am besten geeignet ist und herauszufinden, wie Sie folgende Konzepte verwalten: +Der Hauptpunkt ist, dass **keine** dieser Regeln **in Stein gemeißelt** ist, der man blind folgen muss. Sie können diese Ideen verwenden, um **I Ihren eigenen Anwendungsfall zu evaluieren**, zu entscheiden, welcher Ansatz für Ihr System am besten geeignet ist und herauszufinden, wie Sie folgende Konzepte verwalten: * Sicherheit – HTTPS * Beim Hochfahren ausführen @@ -576,7 +576,7 @@ Sie sollten wahrscheinlich **nicht** dieses Basis-Docker-Image (oder ein anderes Wenn Sie **Kubernetes** (oder andere) verwenden und bereits **Replikation** auf Cluster-Ebene mit mehreren **Containern** eingerichtet haben. In diesen Fällen ist es besser, **ein Image von Grund auf neu zu erstellen**, wie oben beschrieben: [Ein Docker-Image für FastAPI erstellen](#build-a-docker-image-for-fastapi). -Und wenn Sie mehrere Worker benötigen, können Sie einfach die `--workers` Befehlszeilenoption verwenden. +Und wenn Sie mehrere Worker benötigen, können Sie einfach die `--workers`-Befehlszeilenoption verwenden. /// note | Technische Details diff --git a/docs/de/docs/deployment/https.md b/docs/de/docs/deployment/https.md index 0f97909c2..b4c49ff4d 100644 --- a/docs/de/docs/deployment/https.md +++ b/docs/de/docs/deployment/https.md @@ -21,10 +21,10 @@ Aus **Sicht des Entwicklers** sollten Sie beim Nachdenken über HTTPS Folgendes * Und dann müssen sie vom Dritten **erneuert**, **erneut erworben** werden. * Die Verschlüsselung der Verbindung erfolgt auf **TCP-Ebene**. * Das ist eine Schicht **unter HTTP**. - * Die Handhabung von **Zertifikaten und Verschlüsselung** erfolgt also **vor HTTP**. + * Die **Zertifikats- und Verschlüsselungs**-Handhabung erfolgt also **vor HTTP**. * **TCP weiß nichts über „Domains“**. Nur über IP-Adressen. * Die Informationen über die angeforderte **spezifische Domain** befinden sich in den **HTTP-Daten**. -* Die **HTTPS-Zertifikate** „zertifizieren“ eine **bestimmte Domain**, aber das Protokoll und die Verschlüsselung erfolgen auf TCP-Ebene, **ohne zu wissen**, um welche Domain es sich handelt. +* Die **HTTPS-Zertifikate** „zertifizieren“ eine **bestimmte Domain**, aber das Protokoll und die Verschlüsselung erfolgen auf TCP-Ebene, **bevor bekannt ist**, um welche Domain es sich handelt. * **Standardmäßig** bedeutet das, dass Sie nur **ein HTTPS-Zertifikat pro IP-Adresse** haben können. * Ganz gleich, wie groß Ihr Server ist oder wie klein die einzelnen Anwendungen darauf sind. * Hierfür gibt es jedoch eine **Lösung**. @@ -194,7 +194,7 @@ Dieser ganze Erneuerungsprozess, während die Anwendung weiterhin bereitgestellt Wenn Sie einen Proxy zur Verarbeitung von HTTPS verwenden, weiß Ihr **Anwendungsserver** (z. B. Uvicorn über das FastAPI CLI) nichts über den HTTPS-Prozess, er kommuniziert per einfachem HTTP mit dem **TLS-Terminierungsproxy**. -Dieser **Proxy** würde normalerweise unmittelbar vor dem Übermitteln der Anfrage an den **Anwendungsserver** einige HTTP-Header dynamisch setzen, um dem Anwendungsserver mitzuteilen, dass der Request vom Proxy **weitergeleitet** wird. +Dieser **Proxy** würde normalerweise unmittelbar vor dem Übermitteln des Requests an den **Anwendungsserver** einige HTTP-Header dynamisch setzen, um dem Anwendungsserver mitzuteilen, dass der Request vom Proxy **weitergeleitet** wird. /// note | Technische Details diff --git a/docs/de/docs/deployment/manually.md b/docs/de/docs/deployment/manually.md index eae850a69..fa8a9c963 100644 --- a/docs/de/docs/deployment/manually.md +++ b/docs/de/docs/deployment/manually.md @@ -55,7 +55,7 @@ Es gibt mehrere Alternativen, einschließlich: * [Uvicorn](https://www.uvicorn.dev/): ein hochperformanter ASGI-Server. * [Hypercorn](https://hypercorn.readthedocs.io/): ein ASGI-Server, der unter anderem kompatibel mit HTTP/2 und Trio ist. * [Daphne](https://github.com/django/daphne): der für Django Channels entwickelte ASGI-Server. -* [Granian](https://github.com/emmett-framework/granian): Ein Rust HTTP-Server für Python-Anwendungen. +* [Granian](https://github.com/emmett-framework/granian): Ein Rust-HTTP-Server für Python-Anwendungen. ## Servermaschine und Serverprogramm { #server-machine-and-server-program } @@ -65,11 +65,11 @@ Das Wort „**Server**“ wird häufig verwendet, um sowohl den entfernten/Cloud Denken Sie einfach daran, dass sich „Server“ im Allgemeinen auf eines dieser beiden Dinge beziehen kann. -Wenn man sich auf die entfernte Maschine bezieht, wird sie üblicherweise als **Server**, aber auch als **Maschine**, **VM** (virtuelle Maschine) oder **Knoten** bezeichnet. Diese Begriffe beziehen sich auf irgendeine Art von entfernten Rechner, normalerweise unter Linux, auf dem Sie Programme ausführen. +Wenn man sich auf die entfernte Maschine bezieht, wird sie üblicherweise als **Server**, aber auch als **Maschine**, **VM** (virtuelle Maschine) oder **Knoten** bezeichnet. Diese Begriffe beziehen sich auf irgendeine Art von entferntem Rechner, normalerweise unter Linux, auf dem Sie Programme ausführen. ## Das Serverprogramm installieren { #install-the-server-program } -Wenn Sie FastAPI installieren, wird es mit einem Produktionsserver, Uvicorn, geliefert, und Sie können ihn mit dem `fastapi run` Befehl starten. +Wenn Sie FastAPI installieren, wird es mit einem Produktionsserver, Uvicorn, geliefert, und Sie können ihn mit dem `fastapi run`-Befehl starten. Aber Sie können auch ein ASGI-Serverprogramm manuell installieren. diff --git a/docs/de/docs/editor-support.md b/docs/de/docs/editor-support.md index 97782f54f..f93dd5346 100644 --- a/docs/de/docs/editor-support.md +++ b/docs/de/docs/editor-support.md @@ -1,6 +1,6 @@ # Editor-Unterstützung { #editor-support } -Die offizielle [FastAPI-Erweiterung](https://marketplace.visualstudio.com/items?itemName=FastAPILabs.fastapi-vscode) verbessert Ihren FastAPI-Entwicklungsworkflow mit Pfadoperation-Erkennung und -Navigation sowie FastAPI-Cloud-Deployment und Live-Logstreaming. +Die offizielle [FastAPI-Erweiterung](https://marketplace.visualstudio.com/items?itemName=FastAPILabs.fastapi-vscode) verbessert Ihren FastAPI-Entwicklungsworkflow mit *Pfadoperation*-Erkennung und -Navigation sowie FastAPI-Cloud-Deployment und Live-Logstreaming. Weitere Details zur Erweiterung finden Sie im README im [GitHub-Repository](https://github.com/fastapi/fastapi-vscode). @@ -14,10 +14,10 @@ Standardmäßig erkennt die Erweiterung FastAPI-Anwendungen in Ihrem Workspace a ## Funktionen { #features } -- Pfadoperation-Explorer – Eine Baumansicht in der Seitenleiste aller *Pfadoperationen* in Ihrer Anwendung. Klicken Sie, um zu einer beliebigen Route- oder Router-Definition zu springen. -- Routensuche – Suchen Sie nach Pfad, Methode oder Namen mit Ctrl + Shift + E (unter macOS: Cmd + Shift + E). -- CodeLens-Navigation – Anklickbare Links oberhalb von Testclient-Aufrufen (z. B. `client.get('/items')`), die zur passenden Pfadoperation springen und so eine schnelle Navigation zwischen Tests und Implementierung ermöglichen. -- Zu FastAPI Cloud deployen – Deployment Ihrer App mit einem Klick auf [FastAPI Cloud](https://fastapicloud.com/). -- Anwendungslogs streamen – Echtzeit-Logstreaming Ihrer auf FastAPI Cloud deployten Anwendung mit Loglevel-Filterung und Textsuche. +- **Pfadoperation-Explorer** – Eine Baumansicht in der Seitenleiste aller *Pfadoperationen* in Ihrer Anwendung. Klicken Sie, um zu einer beliebigen Route- oder Router-Definition zu springen. +- **Routensuche** – Suchen Sie nach Pfad, Methode oder Namen mit Ctrl + Shift + E (unter macOS: Cmd + Shift + E). +- **CodeLens-Navigation** – Anklickbare Links oberhalb von Testclient-Aufrufen (z. B. `client.get('/items')`), die zur passenden *Pfadoperation* springen und so eine schnelle Navigation zwischen Tests und Implementierung ermöglichen. +- **Zu FastAPI Cloud deployen** – Deployment Ihrer App mit einem Klick auf [FastAPI Cloud](https://fastapicloud.com/). +- **Anwendungslogs streamen** – Echtzeit-Logstreaming Ihrer auf FastAPI Cloud deployten Anwendung mit Loglevel-Filterung und Textsuche. -Wenn Sie sich mit den Funktionen der Erweiterung vertraut machen möchten, können Sie den Erweiterungs‑Walkthrough aufrufen, indem Sie die Befehlspalette öffnen (Ctrl + Shift + P oder unter macOS: Cmd + Shift + P) und „Welcome: Open walkthrough …“ auswählen und anschließend den Walkthrough „Get started with FastAPI“ wählen. +Wenn Sie sich mit den Funktionen der Erweiterung vertraut machen möchten, können Sie den Erweiterungs‑Walkthrough aufrufen, indem Sie die Befehlspalette öffnen (Ctrl + Shift + P oder unter macOS: Cmd + Shift + P) und „Welcome: Open walkthrough ...“ auswählen und anschließend den Walkthrough „Get started with FastAPI“ wählen. diff --git a/docs/de/docs/environment-variables.md b/docs/de/docs/environment-variables.md index 7bff442cd..1678ead27 100644 --- a/docs/de/docs/environment-variables.md +++ b/docs/de/docs/environment-variables.md @@ -12,7 +12,7 @@ Umgebungsvariablen können nützlich sein, um **Einstellungen** der Anwendung zu ## Umgebungsvariablen erstellen und verwenden { #create-and-use-env-vars } -Sie können Umgebungsvariablen in der **Shell (Terminal)** erstellen und verwenden, ohne Python zu benötigen: +Sie können Umgebungsvariablen in der **Shell (Terminal)** **erstellen** und verwenden, ohne Python zu benötigen: //// tab | Linux, macOS, Windows Bash @@ -67,7 +67,7 @@ print(f"Hello {name} from Python") Das zweite Argument von [`os.getenv()`](https://docs.python.org/3.8/library/os.html#os.getenv) ist der Defaultwert, der zurückgegeben wird. -Wenn er nicht angegeben wird, ist er standardmäßig `None`. Hier geben wir „World“ als den zu verwendenden Defaultwert an. +Wenn er nicht angegeben wird, ist er standardmäßig `None`. Hier geben wir `"World"` als den zu verwendenden Defaultwert an. /// @@ -255,7 +255,7 @@ $ python //// tab | Linux, macOS -Das System wird das `python` Programm in `/opt/custompython/bin` **finden** und es ausführen. +Das System wird das `python`-Programm in `/opt/custompython/bin` **finden** und es ausführen. Es wäre ungefähr gleichbedeutend mit der Eingabe von: @@ -271,7 +271,7 @@ $ /opt/custompython/bin/python //// tab | Windows -Das System wird das `python` Programm in `C:\opt\custompython\bin\python` **finden** und es ausführen. +Das System wird das `python`-Programm in `C:\opt\custompython\bin\python` **finden** und es ausführen. Es wäre ungefähr gleichbedeutend mit der Eingabe von: diff --git a/docs/de/docs/features.md b/docs/de/docs/features.md index 73fa876a9..f24ec2426 100644 --- a/docs/de/docs/features.md +++ b/docs/de/docs/features.md @@ -1,10 +1,10 @@ # Merkmale { #features } -## FastAPI Merkmale { #fastapi-features } +## FastAPI-Merkmale { #fastapi-features } **FastAPI** ermöglicht Ihnen Folgendes: -### Basiert auf offenen Standards { #based-on-open-standards } +### Auf offenen Standards basieren { #based-on-open-standards } * [**OpenAPI**](https://github.com/OAI/OpenAPI-Specification) für die Erstellung von APIs, inklusive Deklarationen von Pfad-Operationen, Parametern, Requestbodys, Sicherheit, usw. * Automatische Dokumentation der Datenmodelle mit [**JSON Schema**](https://json-schema.org/) (da OpenAPI selbst auf JSON Schema basiert). @@ -15,7 +15,7 @@ Interaktive API-Dokumentation und erkundbare Web-Benutzeroberflächen. Da das Framework auf OpenAPI basiert, gibt es mehrere Optionen, zwei sind standardmäßig vorhanden. -* [**Swagger UI**](https://github.com/swagger-api/swagger-ui), bietet interaktive Erkundung, testen und rufen Sie Ihre API direkt im Webbrowser auf. +* [**Swagger UI**](https://github.com/swagger-api/swagger-ui), mit interaktiver Erkundung, rufen Sie Ihre API direkt vom Browser aus auf und testen Sie sie. ![Swagger UI Interaktion](https://fastapi.tiangolo.com/img/index/index-03-swagger-02.png) @@ -36,7 +36,7 @@ from datetime import date from pydantic import BaseModel -# Deklarieren Sie eine Variable als ein str +# Deklarieren Sie eine Variable vom Typ str # und bekommen Sie Editor-Unterstützung innerhalb der Funktion def main(user_id: str): return user_id @@ -67,11 +67,11 @@ my_second_user: User = User(**second_user_data) `**second_user_data` bedeutet: -Nimm die Schlüssel-Wert-Paare des `second_user_data` Dicts und übergebe sie direkt als Schlüsselwort-Argumente. Äquivalent zu: `User(id=4, name="Mary", joined="2018-11-30")` +Übergeben Sie die Schlüssel und Werte des `second_user_data` Dicts direkt als Schlüssel-Wert-Argumente, äquivalent zu: `User(id=4, name="Mary", joined="2018-11-30")` /// -### Editor Unterstützung { #editor-support } +### Editorunterstützung { #editor-support } Das ganze Framework wurde so entworfen, dass es einfach und intuitiv zu benutzen ist; alle Entscheidungen wurden auf mehreren Editoren getestet, sogar vor der Implementierung, um die bestmögliche Entwicklererfahrung zu gewährleisten. @@ -85,31 +85,31 @@ So kann Ihr Editor Sie unterstützen: * in [Visual Studio Code](https://code.visualstudio.com/): -![Editor Unterstützung](https://fastapi.tiangolo.com/img/vscode-completion.png) +![Editorunterstützung](https://fastapi.tiangolo.com/img/vscode-completion.png) * in [PyCharm](https://www.jetbrains.com/pycharm/): -![Editor Unterstützung](https://fastapi.tiangolo.com/img/pycharm-completion.png) +![Editorunterstützung](https://fastapi.tiangolo.com/img/pycharm-completion.png) -Sie bekommen sogar Autovervollständigung an Stellen, an denen Sie dies vorher nicht für möglich gehalten hätten. Zum Beispiel der `price` Schlüssel in einem JSON Datensatz (dieser könnte auch verschachtelt sein), der aus einem Request kommt. +Sie bekommen sogar Autovervollständigung an Stellen, an denen Sie dies vorher nicht für möglich gehalten hätten. Zum Beispiel der `price`-Schlüssel innerhalb eines JSON-Bodys (dieser könnte auch verschachtelt sein), der aus einem Request kommt. Nie wieder falsche Schlüsselnamen tippen, Hin und Herhüpfen zwischen der Dokumentation, Hoch- und Runterscrollen, um herauszufinden, ob es `username` oder `user_name` war. ### Kompakt { #short } -Es gibt für alles sensible **Defaultwerte**, mit optionaler Konfiguration überall. Alle Parameter können feinjustiert werden, damit sie tun, was Sie benötigen, und die API definieren, die Sie brauchen. +Es gibt für alles sinnvolle **Defaultwerte**, mit optionaler Konfiguration überall. Alle Parameter können feinjustiert werden, damit sie tun, was Sie benötigen, und die API definieren, die Sie brauchen. Aber standardmäßig **„funktioniert einfach alles“**. ### Validierung { #validation } * Validierung für die meisten (oder alle?) Python-**Datentypen**, hierzu gehören: - * JSON Objekte (`dict`). - * JSON Listen (`list`), die den Typ ihrer Elemente definieren. - * Strings (`str`) mit definierter minimaler und maximaler Länge. + * JSON-Objekte (`dict`). + * JSON-Array (`list`), das Elementtypen definiert. + * String-Felder (`str`) mit definierter minimaler und maximaler Länge. * Zahlen (`int`, `float`) mit Mindest- und Maximalwerten, usw. -* Validierung für mehr exotische Typen, wie: +* Validierung für exotischere Typen, wie: * URL. * E-Mail. * UUID. @@ -124,42 +124,42 @@ Sicherheit und Authentifizierung sind integriert. Ohne Kompromisse bei Datenbank Alle in OpenAPI definierten Sicherheitsschemas, inklusive: * HTTP Basic. -* **OAuth2** (auch mit **JWT Tokens**). Siehe dazu das Tutorial zu [OAuth2 mit JWT](tutorial/security/oauth2-jwt.md). -* API Schlüssel in: +* **OAuth2** (auch mit **JWT-Tokens**). Siehe dazu das Tutorial zu [OAuth2 mit JWT](tutorial/security/oauth2-jwt.md). +* API-Schlüssel in: * Headern. * Query-Parametern. * Cookies, usw. -Zusätzlich alle Sicherheitsfunktionen von Starlette (inklusive **Session Cookies**). +Zusätzlich alle Sicherheitsfunktionen von Starlette (inklusive **Session-Cookies**). -Alles als wiederverwendbare Tools und Komponenten gebaut, die einfach in Ihre Systeme, Datenspeicher, relationale und nicht-relationale Datenbanken, usw., integriert werden können. +Alles als wiederverwendbare Tools und Komponenten gebaut, die einfach in Ihre Systeme, Datenspeicher, relationale und NoSQL-Datenbanken, usw., integriert werden können. ### Dependency Injection { #dependency-injection } -FastAPI enthält ein extrem einfach zu verwendendes, aber extrem mächtiges Dependency Injection System. +FastAPI enthält ein extrem einfach zu verwendendes, aber extrem mächtiges Dependency Injection-System. * Selbst Abhängigkeiten können Abhängigkeiten haben, woraus eine Hierarchie oder ein **„Graph“ von Abhängigkeiten** entsteht. * Alles **automatisch gehandhabt** durch das Framework. -* Alle Abhängigkeiten können Daten von Requests anfordern und das Verhalten von **Pfadoperationen** und der automatisierten Dokumentation **modifizieren**. +* Alle Abhängigkeiten können Daten von Requests anfordern und die Einschränkungen der **Pfadoperationen** sowie die automatische Dokumentation **erweitern**. * **Automatische Validierung** selbst für solche Parameter von *Pfadoperationen*, welche in Abhängigkeiten definiert sind. -* Unterstützung für komplexe Authentifizierungssysteme, **Datenbankverbindungen**, usw. +* Unterstützung für komplexe Benutzerauthentifizierungssysteme, **Datenbankverbindungen**, usw. * **Keine Kompromisse** bei Datenbanken, Frontends, usw., sondern einfache Integration mit allen. -### Unbegrenzte Erweiterungen { #unlimited-plug-ins } +### Unbegrenzte „Plug-ins“ { #unlimited-plug-ins } Oder mit anderen Worten, sie werden nicht benötigt. Importieren und nutzen Sie den Code, den Sie brauchen. -Jede Integration wurde so entworfen, dass sie so einfach zu nutzen ist (mit Abhängigkeiten), dass Sie eine Erweiterung für Ihre Anwendung mit nur zwei Zeilen Code erstellen können. Hierbei nutzen Sie die gleiche Struktur und Syntax, wie bei *Pfadoperationen*. +Jede Integration wurde so entworfen, dass sie so einfach zu nutzen ist (mit Abhängigkeiten), dass Sie ein „Plug-in“ für Ihre Anwendung mit nur 2 Zeilen Code erstellen können. Hierbei nutzen Sie die gleiche Struktur und Syntax, wie bei *Pfadoperationen*. ### Getestet { #tested } * 100 % Testabdeckung. -* 100 % Typen annotiert. +* Zu 100 % typannotierte Codebasis. * Verwendet in Produktionsanwendungen. -## Starlette Merkmale { #starlette-features } +## Starlette-Merkmale { #starlette-features } -**FastAPI** ist vollkommen kompatibel (und basiert auf) [**Starlette**](https://www.starlette.dev/). Das bedeutet, wenn Sie eigenen Starlette Quellcode haben, funktioniert der. +**FastAPI** ist vollkommen kompatibel (und basiert auf) [**Starlette**](https://www.starlette.dev/). Das bedeutet, wenn Sie eigenen Starlette-Quellcode haben, funktioniert dieser auch. `FastAPI` ist tatsächlich eine Unterklasse von `Starlette`. Wenn Sie also bereits Starlette kennen oder benutzen, das meiste funktioniert genau so. @@ -173,11 +173,11 @@ Mit **FastAPI** bekommen Sie alles von **Starlette** (da FastAPI nur Starlette a * **CORS**, GZip, statische Dateien, Responses streamen. * **Sitzungs- und Cookie**-Unterstützung. * 100 % Testabdeckung. -* 100 % Typen annotierte Codebasis. +* Zu 100 % typannotierte Codebasis. -## Pydantic Merkmale { #pydantic-features } +## Pydantic-Merkmale { #pydantic-features } -**FastAPI** ist vollkommen kompatibel (und basiert auf) [**Pydantic**](https://docs.pydantic.dev/). Das bedeutet, wenn Sie eigenen Pydantic Quellcode haben, funktioniert der. +**FastAPI** ist vollkommen kompatibel (und basiert auf) [**Pydantic**](https://docs.pydantic.dev/). Das bedeutet, wenn Sie eigenen Pydantic-Quellcode haben, funktioniert dieser auch. Inklusive externer Bibliotheken, die auf Pydantic basieren, wie ORMs, ODMs für Datenbanken. @@ -188,14 +188,14 @@ Das gleiche gilt auch für die andere Richtung: Sie können in vielen Fällen da Mit **FastAPI** bekommen Sie alle Funktionen von **Pydantic** (da FastAPI für die gesamte Datenverarbeitung Pydantic nutzt): * **Kein Kopfzerbrechen**: - * Keine neue Schemadefinition-Mikrosprache zu lernen. + * Keine neue Schemadefinitions-Mikrosprache zu lernen. * Wenn Sie Pythons Typen kennen, wissen Sie, wie man Pydantic verwendet. * Gutes Zusammenspiel mit Ihrer/Ihrem **IDE/Linter/Gehirn**: * Weil Pydantics Datenstrukturen einfach nur Instanzen ihrer definierten Klassen sind; Autovervollständigung, Linting, mypy und Ihre Intuition sollten alle einwandfrei mit Ihren validierten Daten funktionieren. * Validierung von **komplexen Strukturen**: - * Benutzung von hierarchischen Pydantic-Modellen, Python-`typing`s `List` und `Dict`, etc. - * Die Validierer erlauben es, komplexe Datenschemen klar und einfach zu definieren, überprüft und dokumentiert als JSON Schema. - * Sie können tief **verschachtelte JSON** Objekte haben, die alle validiert und annotiert sind. + * Benutzung von hierarchischen Pydantic-Modellen, Python-`typing`s `List` und `Dict`, usw. + * Die Validierer erlauben es, komplexe Datenschemas klar und einfach zu definieren, überprüft und dokumentiert als JSON Schema. + * Sie können tief **verschachtelte JSON**-Objekte haben, die alle validiert und annotiert sind. * **Erweiterbar**: - * Pydantic erlaubt die Definition von eigenen Datentypen oder sie können die Validierung mit einer `validator`-dekorierten Methode im Modell erweitern. + * Pydantic erlaubt die Definition von eigenen Datentypen oder Sie können die Validierung mit Methoden in einem Modell erweitern, die mit dem Validator-Dekorator dekoriert sind. * 100 % Testabdeckung. diff --git a/docs/de/docs/help-fastapi.md b/docs/de/docs/help-fastapi.md index 83d015739..4a8687562 100644 --- a/docs/de/docs/help-fastapi.md +++ b/docs/de/docs/help-fastapi.md @@ -1,5 +1,6 @@ # Helfen { #help } + Möchten Sie FastAPI helfen oder Hilfe zu FastAPI erhalten? Es gibt sehr einfache Möglichkeiten, zu helfen und Hilfe zu bekommen. diff --git a/docs/de/docs/how-to/configure-swagger-ui.md b/docs/de/docs/how-to/configure-swagger-ui.md index 2f8904be7..d25062615 100644 --- a/docs/de/docs/how-to/configure-swagger-ui.md +++ b/docs/de/docs/how-to/configure-swagger-ui.md @@ -67,4 +67,4 @@ presets: [ Dabei handelt es sich um **JavaScript**-Objekte, nicht um Strings, daher können Sie diese nicht direkt vom Python-Code aus übergeben. -Wenn Sie solche JavaScript-Konfigurationen verwenden müssen, können Sie einen der früher genannten Wege verwenden. Überschreiben Sie alle *Pfadoperationen* der Swagger-Oberfläche und schreiben Sie manuell jedes benötigte JavaScript. +Wenn Sie solche Nur-JavaScript-Konfigurationen verwenden müssen, können Sie einen der früher genannten Wege verwenden. Überschreiben Sie die gesamte *Pfadoperation* der Swagger-Oberfläche und schreiben Sie manuell jedes benötigte JavaScript. diff --git a/docs/de/docs/how-to/custom-request-and-route.md b/docs/de/docs/how-to/custom-request-and-route.md index 5e2dee95d..60fe71ed3 100644 --- a/docs/de/docs/how-to/custom-request-and-route.md +++ b/docs/de/docs/how-to/custom-request-and-route.md @@ -1,5 +1,6 @@ # Benutzerdefinierte Request- und APIRoute-Klasse { #custom-request-and-apiroute-class } + In einigen Fällen möchten Sie möglicherweise die von den Klassen `Request` und `APIRoute` verwendete Logik überschreiben. Das kann insbesondere eine gute Alternative zur Logik in einer Middleware sein. diff --git a/docs/de/docs/how-to/graphql.md b/docs/de/docs/how-to/graphql.md index bf1490f70..cb1891b63 100644 --- a/docs/de/docs/how-to/graphql.md +++ b/docs/de/docs/how-to/graphql.md @@ -1,5 +1,6 @@ # GraphQL { #graphql } + Da **FastAPI** auf dem **ASGI**-Standard basiert, ist es sehr einfach, jede **GraphQL**-Bibliothek zu integrieren, die auch mit ASGI kompatibel ist. Sie können normale FastAPI-*Pfadoperationen* mit GraphQL in derselben Anwendung kombinieren. diff --git a/docs/de/docs/how-to/migrate-from-pydantic-v1-to-pydantic-v2.md b/docs/de/docs/how-to/migrate-from-pydantic-v1-to-pydantic-v2.md index c252b3e0f..5ea3b9561 100644 --- a/docs/de/docs/how-to/migrate-from-pydantic-v1-to-pydantic-v2.md +++ b/docs/de/docs/how-to/migrate-from-pydantic-v1-to-pydantic-v2.md @@ -8,6 +8,8 @@ FastAPI Version 0.119.0 führte eine teilweise Unterstützung für Pydantic v1 i FastAPI 0.126.0 entfernte die Unterstützung für Pydantic v1, während `pydantic.v1` noch eine Weile unterstützt wurde. +FastAPI 0.128.0 entfernte ebenfalls die Unterstützung für `pydantic.v1`, daher erfordern die neuesten Versionen von FastAPI Pydantic v2. + /// warning | Achtung Das Pydantic-Team hat die Unterstützung für Pydantic v1 in den neuesten Python-Versionen eingestellt, beginnend mit **Python 3.14**. @@ -54,6 +56,16 @@ Das bedeutet, Sie können die neueste Version von Pydantic v2 installieren und d ### FastAPI-Unterstützung für Pydantic v1 in v2 { #fastapi-support-for-pydantic-v1-in-v2 } +/// warning | Achtung + +Diese FastAPI-Unterstützung für `pydantic.v1`-Modelle wurde in **FastAPI 0.119.0** hinzugefügt und in **FastAPI 0.128.0** entfernt. Sie war als temporäre Hilfe für die Migration zu Pydantic v2 gedacht. + +In aktuellen Versionen von FastAPI löst die Verwendung eines `pydantic.v1`-Modells in Ihrer App einen Fehler aus. + +Der Rest dieses Abschnitts beschreibt die temporäre Unterstützung, die nur in diesen älteren Versionen verfügbar ist. + +/// + Seit FastAPI 0.119.0 gibt es außerdem eine teilweise Unterstützung für Pydantic v1 innerhalb von Pydantic v2, um die Migration auf v2 zu erleichtern. Sie könnten also Pydantic auf die neueste Version 2 aktualisieren und die Importe so ändern, dass das Untermodul `pydantic.v1` verwendet wird, und in vielen Fällen würde es einfach funktionieren. @@ -122,6 +134,12 @@ Wenn Sie einige der FastAPI-spezifischen Tools für Parameter wie `Body`, `Query ### In Schritten migrieren { #migrate-in-steps } +/// warning | Achtung + +Die unten beschriebene schrittweise Migration mit sowohl Pydantic‑v1‑ als auch Pydantic‑v2‑Modellen in derselben App funktioniert nur in **FastAPI 0.119.0 bis 0.127.x**. Sie wurde in **FastAPI 0.128.0** entfernt, die neuesten Versionen erfordern **Pydantic‑v2**-Modelle. + +/// + /// tip | Tipp Probieren Sie zuerst `bump-pydantic` aus. Wenn Ihre Tests erfolgreich sind und das funktioniert, sind Sie mit einem einzigen Befehl fertig. ✨ diff --git a/docs/de/docs/how-to/separate-openapi-schemas.md b/docs/de/docs/how-to/separate-openapi-schemas.md index 3752ffb10..ae1df6176 100644 --- a/docs/de/docs/how-to/separate-openapi-schemas.md +++ b/docs/de/docs/how-to/separate-openapi-schemas.md @@ -1,5 +1,6 @@ # Separate OpenAPI-Schemas für Eingabe und Ausgabe oder nicht { #separate-openapi-schemas-for-input-and-output-or-not } + Seit der Veröffentlichung von **Pydantic v2** ist die generierte OpenAPI etwas genauer und **korrekter** als zuvor. 😎 Tatsächlich gibt es in einigen Fällen sogar **zwei JSON-Schemas** in OpenAPI für dasselbe Pydantic-Modell, für Eingabe und Ausgabe, je nachdem, ob sie **Defaultwerte** haben. diff --git a/docs/de/docs/index.md b/docs/de/docs/index.md index 32fe63ca8..9922e7621 100644 --- a/docs/de/docs/index.md +++ b/docs/de/docs/index.md @@ -167,7 +167,7 @@ Es gibt einen [FastAPI-Mini-Dokumentarfilm](https://www.youtube.com/watch?v=mpR8 -Wenn Sie eine CLI-Anwendung für das Terminal erstellen, anstelle einer Web-API, schauen Sie sich [**Typer**](https://typer.tiangolo.com/) an. +Wenn Sie eine CLI-Anwendung für das Terminal erstellen, anstelle einer Web-API, schauen Sie sich [**Typer**](https://typer.tiangolo.com/) an. **Typer** ist die kleine Schwester von FastAPI. Und es soll das **FastAPI der CLIs** sein. ⌨️ 🚀 diff --git a/docs/de/docs/project-generation.md b/docs/de/docs/project-generation.md index fd754906a..d2dbadbc9 100644 --- a/docs/de/docs/project-generation.md +++ b/docs/de/docs/project-generation.md @@ -17,7 +17,7 @@ GitHub-Repository: [Full Stack FastAPI Template](https://github.com/tiangolo/ful - 🎨 [Tailwind CSS](https://tailwindcss.com) und [shadcn/ui](https://ui.shadcn.com) für die Frontend-Komponenten. - 🤖 Ein automatisch generierter Frontend-Client. - 🧪 [Playwright](https://playwright.dev) für End-to-End-Tests. - - 🦇 „Dark-Mode“-Unterstützung. + - 🦇 Dark-Mode-Unterstützung. - 🐋 [Docker Compose](https://www.docker.com) für Entwicklung und Produktion. - 🔒 Sicheres Passwort-Hashing standardmäßig. - 🔑 JWT (JSON Web Token)-Authentifizierung. diff --git a/docs/de/docs/python-types.md b/docs/de/docs/python-types.md index aee30fc2f..a67b8b309 100644 --- a/docs/de/docs/python-types.md +++ b/docs/de/docs/python-types.md @@ -44,7 +44,7 @@ Es ist ein sehr einfaches Programm. Aber nun stellen Sie sich vor, Sie würden es selbst schreiben. -Irgendwann sind die Funktions-Parameter fertig, Sie starten mit der Definition des Körpers ... +Irgendwann beginnen Sie, die Funktion zu definieren, und haben die Parameter bereit ... Aber dann müssen Sie „diese Methode aufrufen, die den ersten Buchstaben in Großbuchstaben umwandelt“. @@ -52,7 +52,7 @@ War es `upper`? War es `uppercase`? `first_uppercase`? `capitalize`? Dann versuchen Sie es mit dem langjährigen Freund des Programmierers, der Editor-Autovervollständigung. -Sie geben den ersten Parameter der Funktion ein, `first_name`, dann einen Punkt (`.`) und drücken `Strg+Leertaste`, um die Vervollständigung auszulösen. +Sie geben den ersten Parameter der Funktion ein, `first_name`, dann einen Punkt (`.`) und drücken `Ctrl+Space`, um die Vervollständigung auszulösen. Aber leider erhalten Sie nichts Nützliches: @@ -62,7 +62,7 @@ Aber leider erhalten Sie nichts Nützliches: Lassen Sie uns eine einzelne Zeile aus der vorherigen Version ändern. -Wir ändern den folgenden Teil, die Parameter der Funktion, von: +Wir ändern genau dieses Fragment, die Parameter der Funktion, von: ```Python first_name, last_name @@ -94,7 +94,7 @@ Und das Hinzufügen von Typhinweisen ändert normalerweise nichts an dem, was oh Aber jetzt stellen Sie sich vor, Sie sind wieder mitten in der Erstellung dieser Funktion, aber mit Typhinweisen. -An derselben Stelle versuchen Sie, die Autovervollständigung mit „Strg+Leertaste“ auszulösen, und Sie sehen: +An derselben Stelle versuchen Sie, die Autovervollständigung mit `Ctrl+Space` auszulösen, und Sie sehen: @@ -116,7 +116,7 @@ Jetzt, da Sie wissen, dass Sie das reparieren müssen, konvertieren Sie `age` mi {* ../../docs_src/python_types/tutorial004_py310.py hl[2] *} -## Deklarieren von Typen { #declaring-types } +## Typen deklarieren { #declaring-types } Sie haben gerade den Haupt-Einsatzort für die Deklaration von Typhinweisen gesehen. Als Funktionsparameter. @@ -180,7 +180,7 @@ In diesem Fall ist `str` der Typ-Parameter, der an `list` übergeben wird. /// -Das bedeutet: Die Variable `items` ist eine Liste – `list` – und jedes der Elemente in dieser Liste ist ein String – `str`. +Das bedeutet: „Die Variable `items` ist eine `list`, und jedes der Elemente in dieser Liste ist ein `str`“. Auf diese Weise kann Ihr Editor Sie auch bei der Bearbeitung von Einträgen aus der Liste unterstützen: @@ -263,9 +263,9 @@ Und wiederum bekommen Sie die volle Editor-Unterstützung: -Beachten Sie, das bedeutet: „`one_person` ist eine **Instanz** der Klasse `Person`“. +Beachten Sie, dass das bedeutet: „`one_person` ist eine **Instanz** der Klasse `Person`“. -Es bedeutet nicht: „`one_person` ist die **Klasse** genannt `Person`“. +Es bedeutet nicht: „`one_person` ist die **Klasse** namens `Person`“. ## Pydantic-Modelle { #pydantic-models } @@ -279,7 +279,7 @@ Dann erzeugen Sie eine Instanz dieser Klasse mit einigen Werten, und Pydantic va Und Sie erhalten volle Editor-Unterstützung für dieses Objekt. -Ein Beispiel aus der offiziellen Pydantic Dokumentation: +Ein Beispiel aus der offiziellen Pydantic-Dokumentation: {* ../../docs_src/python_types/tutorial011_py310.py *} @@ -301,11 +301,11 @@ Sie können `Annotated` von `typing` importieren. {* ../../docs_src/python_types/tutorial013_py310.py hl[1,4] *} -Python selbst macht nichts mit `Annotated`. Für Editoren und andere Tools ist der Typ immer noch `str`. +Python selbst macht nichts mit diesem `Annotated`. Für Editoren und andere Tools ist der Typ immer noch `str`. -Aber Sie können `Annotated` nutzen, um **FastAPI** mit Metadaten zu versorgen, die ihm sagen, wie sich Ihre Anwendung verhalten soll. +Aber Sie können diesen Platz in `Annotated` nutzen, um **FastAPI** zusätzliche Metadaten darüber bereitzustellen, wie sich Ihre Anwendung verhalten soll. -Wichtig ist, dass **der erste *Typ-Parameter***, den Sie `Annotated` übergeben, der **tatsächliche Typ** ist. Der Rest sind Metadaten für andere Tools. +Wichtig ist, dass **der erste *Typ-Parameter***, den Sie `Annotated` übergeben, der **tatsächliche Typ** ist. Der Rest sind nur Metadaten für andere Tools. Im Moment müssen Sie nur wissen, dass `Annotated` existiert, und dass es Standard-Python ist. 😎 @@ -335,7 +335,7 @@ Mit **FastAPI** deklarieren Sie Parameter mit Typhinweisen, und Sie erhalten: * **Daten zu validieren**: aus jedem Request: * **Automatische Fehler** generieren, die an den Client zurückgegeben werden, wenn die Daten ungültig sind. * Die API mit OpenAPI zu **dokumentieren**: - * Die dann von den Benutzeroberflächen der automatisch generierten interaktiven Dokumentation verwendet wird. + * die dann von den Benutzeroberflächen der automatisch generierten interaktiven Dokumentation verwendet wird. Das mag alles abstrakt klingen. Machen Sie sich keine Sorgen. Sie werden all das in Aktion sehen im [Tutorial – Benutzerhandbuch](tutorial/index.md). diff --git a/docs/de/docs/tutorial/bigger-applications.md b/docs/de/docs/tutorial/bigger-applications.md index d119bb019..119f3e8c0 100644 --- a/docs/de/docs/tutorial/bigger-applications.md +++ b/docs/de/docs/tutorial/bigger-applications.md @@ -17,16 +17,16 @@ Nehmen wir an, Sie haben eine Dateistruktur wie diese: ``` . ├── app -│   ├── __init__.py -│   ├── main.py -│   ├── dependencies.py -│   └── routers -│   │ ├── __init__.py -│   │ ├── items.py -│   │ └── users.py -│   └── internal -│   ├── __init__.py -│   └── admin.py +│ ├── __init__.py +│ ├── main.py +│ ├── dependencies.py +│ └── routers +│ │ ├── __init__.py +│ │ ├── items.py +│ │ └── users.py +│ └── internal +│ ├── __init__.py +│ └── admin.py ``` /// tip | Tipp diff --git a/docs/de/docs/tutorial/body-nested-models.md b/docs/de/docs/tutorial/body-nested-models.md index 0c5e84de2..f95b65e57 100644 --- a/docs/de/docs/tutorial/body-nested-models.md +++ b/docs/de/docs/tutorial/body-nested-models.md @@ -4,7 +4,7 @@ Mit **FastAPI** können Sie (dank Pydantic) beliebig tief verschachtelte Modelle ## Listen als Felder { #list-fields } -Sie können ein Attribut als Kindtyp definieren, zum Beispiel eine Python-`list`. +Sie können ein Attribut als Kindtyp definieren. Zum Beispiel eine Python-`list`: {* ../../docs_src/body_nested_models/tutorial001_py310.py hl[12] *} @@ -12,11 +12,12 @@ Das bewirkt, dass `tags` eine Liste ist, wenngleich es nichts über den Typ der ## Listen mit Typ-Parametern als Felder { #list-fields-with-type-parameter } -Aber Python erlaubt es, Listen mit inneren Typen, auch „Typ-Parameter“ genannt, zu deklarieren. +Aber Python hat eine spezifische Möglichkeit, Listen mit inneren Typen, auch „Typ-Parameter“ genannt, zu deklarieren: ### Eine `list` mit einem Typ-Parameter deklarieren { #declare-a-list-with-a-type-parameter } -Um Typen zu deklarieren, die Typ-Parameter (innere Typen) haben, wie `list`, `dict`, `tuple`, übergeben Sie den/die inneren Typ(en) als „Typ-Parameter“ in eckigen Klammern: `[` und `]` +Um Typen zu deklarieren, die Typ-Parameter (innere Typen) haben, wie `list`, `dict`, `tuple`, +übergeben Sie den/die inneren Typ(en) als „Typ-Parameter“ in eckigen Klammern: `[` und `]` ```Python my_list: list[str] @@ -32,19 +33,19 @@ In unserem Beispiel können wir also bewirken, dass `tags` spezifisch eine „Li ## Set-Typen { #set-types } -Aber dann denken wir darüber nach und stellen fest, dass sich die Tags nicht wiederholen sollen, es sollen eindeutige Strings sein. +Aber dann denken wir darüber nach und stellen fest, dass sich die Tags nicht wiederholen sollten, sie wären wahrscheinlich eindeutige Strings. -Python hat einen Datentyp speziell für Mengen eindeutiger Dinge: das `set`. +Und Python hat einen speziellen Datentyp für Mengen eindeutiger Elemente, das `set`. -Deklarieren wir also `tags` als Set von Strings. +Dann können wir `tags` als Set von Strings deklarieren: {* ../../docs_src/body_nested_models/tutorial003_py310.py hl[12] *} -Jetzt, selbst wenn Sie einen Request mit duplizierten Daten erhalten, werden diese zu einem Set eindeutiger Dinge konvertiert. +Damit wird, selbst wenn Sie einen Request mit duplizierten Daten erhalten, dieser zu einem Set eindeutiger Elemente konvertiert. -Und wann immer Sie diese Daten ausgeben, selbst wenn die Quelle Duplikate hatte, wird es als Set von eindeutigen Dingen ausgegeben. +Und wann immer Sie diese Daten ausgeben, selbst wenn die Quelle Duplikate hatte, wird es als Set von eindeutigen Elementen ausgegeben. -Und es wird entsprechend annotiert/dokumentiert. +Und es wird entsprechend annotiert / dokumentiert. ## Verschachtelte Modelle { #nested-models } @@ -52,13 +53,13 @@ Jedes Attribut eines Pydantic-Modells hat einen Typ. Aber dieser Typ kann selbst ein anderes Pydantic-Modell sein. -Sie können also tief verschachtelte JSON-„Objekte“ deklarieren, mit spezifischen Attributnamen, -typen, und -validierungen. +Sie können also tief verschachtelte JSON-„Objekte“ deklarieren, mit spezifischen Attributnamen, Typen und Validierungen. Alles das beliebig tief verschachtelt. ### Ein Kindmodell definieren { #define-a-submodel } -Für ein Beispiel können wir ein `Image`-Modell definieren. +Zum Beispiel können wir ein `Image`-Modell definieren: {* ../../docs_src/body_nested_models/tutorial004_py310.py hl[7:9] *} @@ -68,7 +69,7 @@ Und dann können wir es als Typ eines Attributes verwenden: {* ../../docs_src/body_nested_models/tutorial004_py310.py hl[18] *} -Das würde bedeuten, dass **FastAPI** einen Body wie folgt erwartet: +Das würde bedeuten, dass **FastAPI** einen Body ähnlich dem folgenden erwartet: ```JSON { @@ -84,7 +85,7 @@ Das würde bedeuten, dass **FastAPI** einen Body wie folgt erwartet: } ``` -Wiederum, nur mit dieser Deklaration erhalten Sie von **FastAPI**: +Wiederum, nur mit dieser Deklaration erhalten Sie mit **FastAPI**: * Editor-Unterstützung (Codevervollständigung, usw.), selbst für verschachtelte Modelle * Datenkonvertierung @@ -105,7 +106,7 @@ Es wird getestet, ob der String eine gültige URL ist, und als solche wird er in ## Attribute mit Listen von Kindmodellen { #attributes-with-lists-of-submodels } -Sie können Pydantic-Modelle auch als Typen innerhalb von `list`, `set`, usw. verwenden: +Sie können Pydantic-Modelle auch als Kindtypen von `list`, `set`, usw. verwenden: {* ../../docs_src/body_nested_models/tutorial006_py310.py hl[18] *} @@ -149,13 +150,13 @@ Sie können beliebig tief verschachtelte Modelle definieren: /// note | Hinweis -Beachten Sie, wie `Offer` eine Liste von `Item`s hat, die ihrerseits eine optionale Liste von `Image`s haben. +Beachten Sie, wie `Offer` eine Liste von `Item`s hat, die ihrerseits eine optionale Liste von `Image`s haben /// ## Bodys aus reinen Listen { #bodies-of-pure-lists } -Wenn das äußerste Element des JSON-Bodys, das Sie erwarten, ein JSON-`array` (eine Python-`list`) ist, können Sie den Typ im Funktionsparameter deklarieren, mit der gleichen Syntax wie in Pydantic-Modellen: +Wenn der Wert auf oberster Ebene des JSON-Bodys, den Sie erwarten, ein JSON-`array` (eine Python-`list`) ist, können Sie den Typ im Parameter der Funktion deklarieren, genau wie in Pydantic-Modellen: ```Python images: list[Image] @@ -169,29 +170,29 @@ so wie in: Und Sie erhalten Editor-Unterstützung überall. -Selbst für Dinge in Listen: +Selbst für Elemente innerhalb von Listen: -Sie würden diese Editor-Unterstützung nicht erhalten, wenn Sie direkt mit `dict`, statt mit Pydantic-Modellen arbeiten würden. +Sie würden diese Art von Editor-Unterstützung nicht erhalten, wenn Sie direkt mit `dict`, statt mit Pydantic-Modellen arbeiten würden. -Aber Sie müssen sich auch nicht weiter um die Modelle kümmern, hereinkommende Dicts werden automatisch in sie konvertiert. Und was Sie zurückgeben, wird automatisch nach JSON konvertiert. +Aber Sie müssen sich auch nicht um diese kümmern, hereinkommende Dicts werden automatisch konvertiert und Ihre Ausgabe wird ebenfalls automatisch nach JSON konvertiert. ## Bodys mit beliebigen `dict`s { #bodies-of-arbitrary-dicts } Sie können einen Body auch als `dict` deklarieren, mit Schlüsseln eines Typs und Werten eines anderen Typs. -So brauchen Sie vorher nicht zu wissen, wie die Feld-/Attributnamen lauten (wie es bei Pydantic-Modellen der Fall wäre). +So brauchen Sie vorher nicht zu wissen, wie die gültigen Feld-/Attributnamen lauten (wie es bei Pydantic-Modellen der Fall wäre). -Das ist nützlich, wenn Sie Schlüssel empfangen, deren Namen Sie nicht bereits kennen. +Das ist nützlich, wenn Sie Schlüssel empfangen wollen, die Sie nicht bereits kennen. --- Ein anderer nützlicher Anwendungsfall ist, wenn Sie Schlüssel eines anderen Typs haben wollen, z. B. `int`. -Das schauen wir uns mal an. +Das schauen wir uns hier an. -Im folgenden Beispiel akzeptieren Sie irgendein `dict`, solange es `int`-Schlüssel und `float`-Werte hat: +In diesem Fall akzeptieren Sie irgendein `dict`, solange es `int`-Schlüssel mit `float`-Werten hat: {* ../../docs_src/body_nested_models/tutorial009_py310.py hl[7] *} @@ -201,9 +202,9 @@ Bedenken Sie, dass JSON nur `str` als Schlüssel unterstützt. Aber Pydantic hat automatische Datenkonvertierung. -Das bedeutet, dass Ihre API-Clients nur Strings senden können, aber solange diese Strings nur Zahlen enthalten, wird Pydantic sie konvertieren und validieren. +Das bedeutet, dass Ihre API-Clients zwar nur Strings als Schlüssel senden können, Pydantic diese aber konvertieren und validieren wird, solange diese Strings nur Ganzzahlen enthalten. -Und das `dict`, welches Sie als `weights` erhalten, wird `int`-Schlüssel und `float`-Werte haben. +Und das `dict`, welches Sie als `weights` erhalten, wird tatsächlich `int`-Schlüssel und `float`-Werte haben. /// @@ -213,8 +214,8 @@ Mit **FastAPI** haben Sie die maximale Flexibilität von Pydantic-Modellen, wäh Aber mit all den Vorzügen: -* Editor-Unterstützung (Codevervollständigung überall) -* Datenkonvertierung (auch bekannt als Parsen, Serialisierung) +* Editor-Unterstützung (Codevervollständigung überall!) +* Datenkonvertierung (auch bekannt als Parsen / Serialisierung) * Datenvalidierung * Schema-Dokumentation * Automatische Dokumentation diff --git a/docs/de/docs/tutorial/body.md b/docs/de/docs/tutorial/body.md index 656b55c63..6ced5f732 100644 --- a/docs/de/docs/tutorial/body.md +++ b/docs/de/docs/tutorial/body.md @@ -14,7 +14,7 @@ Um Daten zu senden, sollten Sie eines von: `POST` (meistverwendet), `PUT`, `DELE Das Senden eines Bodys mit einem `GET`-Request hat ein undefiniertes Verhalten in den Spezifikationen, wird aber dennoch von FastAPI unterstützt, nur für sehr komplexe/extreme Anwendungsfälle. -Da davon abgeraten wird, zeigt die interaktive Dokumentation mit Swagger-Benutzeroberfläche die Dokumentation für den Body nicht an, wenn `GET` verwendet wird, und zwischengeschaltete Proxys unterstützen es möglicherweise nicht. +Da davon abgeraten wird, zeigt die interaktive Dokumentation mit Swagger UI die Dokumentation für den Body nicht an, wenn `GET` verwendet wird, und zwischengeschaltete Proxys unterstützen es möglicherweise nicht. /// @@ -32,6 +32,7 @@ Verwenden Sie Standard-Python-Typen für alle Attribute: {* ../../docs_src/body/tutorial001_py310.py hl[5:9] *} + Wie auch bei der Deklaration von Query-Parametern gilt: Wenn ein Modellattribut einen Defaultwert hat, ist das Attribut nicht erforderlich. Andernfalls ist es erforderlich. Verwenden Sie `None`, um es einfach optional zu machen. Zum Beispiel deklariert das obige Modell ein JSON „`object`“ (oder Python-`dict`) wie dieses: @@ -45,7 +46,7 @@ Zum Beispiel deklariert das obige Modell ein JSON „`object`“ (oder Python-zusätzliche Schritte nach Abschluss ausführen. -Verwenden Sie dazu `yield` statt `return` und schreiben Sie die zusätzlichen Schritte / den zusätzlichen Code danach. +Verwenden Sie dazu `yield` statt `return` und schreiben Sie die zusätzlichen Schritte (Code) danach. /// tip | Tipp @@ -77,7 +77,7 @@ Und wiederum benötigt `dependency_b` den Wert von `dependency_a` (hier `dep_a` {* ../../docs_src/dependencies/tutorial008_an_py310.py hl[18:19,26:27] *} -Auf die gleiche Weise könnten Sie einige Abhängigkeiten mit `yield` und einige andere Abhängigkeiten mit `return` haben, und alle können beliebig voneinander abhängen. +Auf die gleiche Weise könnten Sie einige Abhängigkeiten mit `yield` und einige andere Abhängigkeiten mit `return` haben, und einige davon von einigen der anderen abhängen lassen. Und Sie könnten eine einzelne Abhängigkeit haben, die auf mehreren ge`yield`eten Abhängigkeiten basiert, usw. @@ -234,6 +234,7 @@ participant operation as Pfadoperation Abhängigkeiten mit `yield` haben sich im Laufe der Zeit weiterentwickelt, um verschiedene Anwendungsfälle abzudecken und einige Probleme zu beheben. Wenn Sie sehen möchten, was sich in verschiedenen Versionen von FastAPI geändert hat, lesen Sie mehr dazu im fortgeschrittenen Teil, unter [Fortgeschrittene Abhängigkeiten – Abhängigkeiten mit `yield`, `HTTPException`, `except` und Hintergrundtasks](../../advanced/advanced-dependencies.md#dependencies-with-yield-httpexception-except-and-background-tasks). + ## Kontextmanager { #context-managers } ### Was sind „Kontextmanager“ { #what-are-context-managers } @@ -266,18 +267,19 @@ Wenn Sie gerade erst mit **FastAPI** beginnen, möchten Sie das vielleicht vorer In Python können Sie Kontextmanager erstellen, indem Sie [eine Klasse mit zwei Methoden erzeugen: `__enter__()` und `__exit__()`](https://docs.python.org/3/reference/datamodel.html#context-managers). -Sie können solche auch innerhalb von **FastAPI**-Abhängigkeiten mit `yield` verwenden, indem Sie `with`- oder `async with`-Anweisungen innerhalb der Abhängigkeits-Funktion verwenden: +Sie können solche auch innerhalb von **FastAPI**-Abhängigkeiten mit `yield` verwenden, indem Sie +`with`- oder `async with`-Anweisungen innerhalb der Abhängigkeits-Funktion verwenden: {* ../../docs_src/dependencies/tutorial010_py310.py hl[1:9,13] *} /// tip | Tipp -Andere Möglichkeiten, einen Kontextmanager zu erstellen, sind: +Eine weitere Möglichkeit, einen Kontextmanager zu erstellen, ist: * [`@contextlib.contextmanager`](https://docs.python.org/3/library/contextlib.html#contextlib.contextmanager) oder * [`@contextlib.asynccontextmanager`](https://docs.python.org/3/library/contextlib.html#contextlib.asynccontextmanager) -Verwenden Sie diese, um eine Funktion zu dekorieren, die ein einziges `yield` hat. +indem Sie damit eine Funktion dekorieren, die ein einziges `yield` hat. Das ist es auch, was **FastAPI** intern für Abhängigkeiten mit `yield` verwendet. diff --git a/docs/de/docs/tutorial/extra-data-types.md b/docs/de/docs/tutorial/extra-data-types.md index 92401172b..d1feab1a0 100644 --- a/docs/de/docs/tutorial/extra-data-types.md +++ b/docs/de/docs/tutorial/extra-data-types.md @@ -1,5 +1,6 @@ # Zusätzliche Datentypen { #extra-data-types } + Bisher haben Sie gängige Datentypen verwendet, wie zum Beispiel: * `int` diff --git a/docs/de/docs/tutorial/extra-models.md b/docs/de/docs/tutorial/extra-models.md index 59580d73a..8e0b094ad 100644 --- a/docs/de/docs/tutorial/extra-models.md +++ b/docs/de/docs/tutorial/extra-models.md @@ -63,7 +63,7 @@ würden wir ein Python-`dict` erhalten mit: #### Ein `dict` entpacken { #unpacking-a-dict } -Wenn wir ein `dict` wie `user_dict` nehmen und es einer Funktion (oder Klasse) mit `**user_dict` übergeben, wird Python es „entpacken“. Es wird die Schlüssel und Werte von `user_dict` direkt als Schlüsselwort-Argumente übergeben. +Wenn wir ein `dict` wie `user_dict` nehmen und es einer Funktion (oder Klasse) mit `**user_dict` übergeben, wird Python es „entpacken“. Es wird die Schlüssel und Werte von `user_dict` direkt als Schlüssel-Wert-Argumente übergeben. Setzen wir also das `user_dict` von oben ein: @@ -196,7 +196,7 @@ Dafür verwenden Sie Pythons Standard-`list`: ## Response mit beliebigem `dict` { #response-with-arbitrary-dict } -Sie können auch eine Response deklarieren, die ein beliebiges `dict` zurückgibt, indem Sie nur die Typen der Schlüssel und Werte ohne ein Pydantic-Modell deklarieren. +Sie können auch eine Response deklarieren, die ein einfaches beliebiges `dict` verwendet, indem Sie nur den Typ der Schlüssel und Werte deklarieren, ohne ein Pydantic-Modell zu verwenden. Dies ist nützlich, wenn Sie die gültigen Feld-/Attributnamen nicht im Voraus kennen (die für ein Pydantic-Modell benötigt werden würden). @@ -208,4 +208,4 @@ In diesem Fall können Sie `dict` verwenden: Verwenden Sie gerne mehrere Pydantic-Modelle und vererben Sie je nach Bedarf. -Sie brauchen kein einzelnes Datenmodell pro Einheit, wenn diese Einheit in der Lage sein muss, verschiedene „Zustände“ zu haben. Wie im Fall der Benutzer-„Einheit“ mit einem Zustand einschließlich `password`, `password_hash` und ohne Passwort. +Sie brauchen kein einzelnes Datenmodell pro Entität, wenn diese Entität in der Lage sein muss, verschiedene „Zustände“ zu haben. Die **Benutzer**-„Entität“ ist ein Beispiel, mit Zuständen, die `password`, `password_hash` oder kein Passwort umfassen. diff --git a/docs/de/docs/tutorial/first-steps.md b/docs/de/docs/tutorial/first-steps.md index f605c5540..8e97b5b5d 100644 --- a/docs/de/docs/tutorial/first-steps.md +++ b/docs/de/docs/tutorial/first-steps.md @@ -236,7 +236,7 @@ Sie können alle [Starlette](https://www.starlette.dev/)-Funktionalitäten auch /// -### Schritt 2: Erzeugen einer `FastAPI`-„Instanz“ { #step-2-create-a-fastapi-instance } +### Schritt 2: Eine `FastAPI`-„Instanz“ erstellen { #step-2-create-a-fastapi-instance } {* ../../docs_src/first_steps/tutorial001_py310.py hl[3] *} @@ -244,7 +244,7 @@ In diesem Beispiel ist die Variable `app` eine „Instanz“ der Klasse `FastAPI Dies wird der Hauptinteraktionspunkt für die Erstellung all Ihrer APIs sein. -### Schritt 3: Erstellen einer *Pfadoperation* { #step-3-create-a-path-operation } +### Schritt 3: Eine *Pfadoperation* erstellen { #step-3-create-a-path-operation } #### Pfad { #path } @@ -305,7 +305,7 @@ In OpenAPI wird folglich jede dieser HTTP-Methoden als „Operation“ bezeichne Wir werden sie auch „**Operationen**“ nennen. -#### Definieren eines *Pfadoperation-Dekorators* { #define-a-path-operation-decorator } +#### Einen *Pfadoperation-Dekorator* definieren { #define-a-path-operation-decorator } {* ../../docs_src/first_steps/tutorial001_py310.py hl[6] *} @@ -353,7 +353,7 @@ Wenn Sie beispielsweise GraphQL verwenden, führen Sie normalerweise alle Aktion /// -### Schritt 4: Definieren der **Pfadoperation-Funktion** { #step-4-define-the-path-operation-function } +### Schritt 4: Die **Pfadoperation-Funktion** definieren { #step-4-define-the-path-operation-function } Das ist unsere „**Pfadoperation-Funktion**“: @@ -399,11 +399,11 @@ Stellen Sie Ihre App in der **[FastAPI Cloud](https://fastapicloud.com)** mit ei **[FastAPI Cloud](https://fastapicloud.com)** wird vom selben Autor und Team hinter **FastAPI** entwickelt. -Es vereinfacht den Prozess des Erstellens, Deployens und des Zugriffs auf eine API mit minimalem Aufwand. +Es vereinfacht den Prozess des **Erstellens**, **Deployens** und des **Zugriffs** auf eine API mit minimalem Aufwand. Es bringt die gleiche **Developer-Experience** beim Erstellen von Apps mit FastAPI auch zum **Deployment** in der Cloud. 🎉 -FastAPI Cloud ist der Hauptsponsor und Finanzierer der „FastAPI and friends“ Open-Source-Projekte. ✨ +FastAPI Cloud ist der Hauptsponsor und Finanzierer der *FastAPI and friends*-Open-Source-Projekte. ✨ #### Zu anderen Cloudanbietern deployen { #deploy-to-other-cloud-providers } @@ -414,7 +414,7 @@ Folgen Sie den Anleitungen Ihres Cloudanbieters, um dort FastAPI-Apps bereitzust ## Zusammenfassung { #recap } * Importieren Sie `FastAPI`. -* Erstellen Sie eine `app` Instanz. +* Erstellen Sie eine `app`-Instanz. * Schreiben Sie einen **Pfadoperation-Dekorator** unter Verwendung von Dekoratoren wie `@app.get("/")`. * Definieren Sie eine **Pfadoperation-Funktion**, zum Beispiel `def root(): ...`. * Starten Sie den Entwicklungsserver mit dem Befehl `fastapi dev`. diff --git a/docs/de/docs/tutorial/handling-errors.md b/docs/de/docs/tutorial/handling-errors.md index 261831a8e..17e2767fe 100644 --- a/docs/de/docs/tutorial/handling-errors.md +++ b/docs/de/docs/tutorial/handling-errors.md @@ -8,12 +8,12 @@ Sie könnten dem Client mitteilen müssen, dass: * Der Client nicht genügend Berechtigungen für diese Operation hat. * Der Client keinen Zugriff auf diese Ressource hat. -* Die Ressource, auf die der Client versucht hat, zuzugreifen, nicht existiert. +* Das Item, auf das der Client versucht hat zuzugreifen, nicht existiert. * usw. In diesen Fällen würden Sie normalerweise einen **HTTP-Statuscode** im Bereich **400** (von 400 bis 499) zurückgeben. -Dies ist vergleichbar mit den HTTP-Statuscodes im Bereich 200 (von 200 bis 299). Diese „200“-Statuscodes bedeuten, dass der Request in irgendeiner Weise erfolgreich war. +Dies ist vergleichbar mit den HTTP-Statuscodes im Bereich 200 (von 200 bis 299). Diese „200“-Statuscodes bedeuten, dass der Request irgendwie ein „Erfolg“ war. Die Statuscodes im Bereich 400 bedeuten hingegen, dass es einen Fehler seitens des Clients gab. @@ -37,7 +37,7 @@ Das bedeutet auch, wenn Sie sich innerhalb einer Hilfsfunktion befinden, die Sie Der Vorteil des Auslösens einer Exception gegenüber dem Zurückgeben eines Wertes wird im Abschnitt über Abhängigkeiten und Sicherheit deutlicher werden. -In diesem Beispiel lösen wir eine Exception mit einem Statuscode von `404` aus, wenn der Client einen Artikel mit einer nicht existierenden ID anfordert: +In diesem Beispiel lösen wir eine Exception mit einem Statuscode von `404` aus, wenn der Client ein Item mit einer nicht existierenden ID anfordert: {* ../../docs_src/handling_errors/tutorial001_py310.py hl[11] *} @@ -51,7 +51,7 @@ Wenn der Client `http://example.com/items/foo` anfordert (ein `item_id` `"foo"`) } ``` -Aber wenn der Client `http://example.com/items/bar` anfordert (ein nicht-existierendes `item_id` `"bar"`), erhält er einen HTTP-Statuscode 404 (der „Not Found“-Error) und eine JSON-Response wie: +Aber wenn der Client `http://example.com/items/bar` anfordert (ein nicht-existierendes `item_id` `"bar"`), erhält er einen HTTP-Statuscode 404 (der „not found“-Error) und eine JSON-Response wie: ```JSON { @@ -71,7 +71,7 @@ Diese werden von **FastAPI** automatisch gehandhabt und in JSON konvertiert. ## Benutzerdefinierte Header hinzufügen { #add-custom-headers } -Es gibt Situationen, in denen es nützlich ist, dem HTTP-Error benutzerdefinierte Header hinzuzufügen. Zum Beispiel in einigen Sicherheitsszenarien. +Es gibt Situationen, in denen es nützlich ist, dem HTTP-Error benutzerdefinierte Header hinzuzufügen. Zum Beispiel für einige Arten von Sicherheit. Sie werden es wahrscheinlich nicht direkt in Ihrem Code verwenden müssen. @@ -117,7 +117,7 @@ Diese Handler sind dafür verantwortlich, die Default-JSON-Responses zurückzuge Sie können diese Exceptionhandler mit Ihren eigenen überschreiben. -### Überschreiben von Request-Validierungs-Exceptions { #override-request-validation-exceptions } +### Request-Validierungs-Exceptions überschreiben { #override-request-validation-exceptions } Wenn ein Request ungültige Daten enthält, löst **FastAPI** intern einen `RequestValidationError` aus. @@ -153,7 +153,7 @@ Validation errors: Field: ('path', 'item_id'), Error: Input should be a valid integer, unable to parse string as an integer ``` -### Überschreiben des `HTTPException`-Fehlerhandlers { #override-the-httpexception-error-handler } +### Den `HTTPException`-Fehlerhandler überschreiben { #override-the-httpexception-error-handler } Auf die gleiche Weise können Sie den `HTTPException`-Handler überschreiben. @@ -177,7 +177,7 @@ Das bedeutet aber auch, dass, wenn Sie ihn einfach in einen String umwandeln und /// -### Verwenden des `RequestValidationError`-Bodys { #use-the-requestvalidationerror-body } +### Den `RequestValidationError`-Body verwenden { #use-the-requestvalidationerror-body } Der `RequestValidationError` enthält den empfangenen `body` mit den ungültigen Daten. @@ -185,7 +185,7 @@ Sie könnten diesen während der Entwicklung Ihrer Anwendung verwenden, um den B {* ../../docs_src/handling_errors/tutorial005_py310.py hl[14] *} -Versuchen Sie nun, einen ungültigen Artikel zu senden: +Versuchen Sie nun, ein ungültiges Item zu senden: ```JSON { @@ -194,7 +194,7 @@ Versuchen Sie nun, einen ungültigen Artikel zu senden: } ``` -Sie erhalten eine Response, die Ihnen sagt, dass die Daten ungültig sind und die den empfangenen Body enthält: +Sie erhalten eine Response, die Ihnen sagt, dass die Daten ungültig sind, und die den empfangenen Body enthält: ```JSON hl_lines="12-15" { diff --git a/docs/de/docs/tutorial/index.md b/docs/de/docs/tutorial/index.md index 4b5272ebd..c0f25c916 100644 --- a/docs/de/docs/tutorial/index.md +++ b/docs/de/docs/tutorial/index.md @@ -1,5 +1,6 @@ # Tutorial – Benutzerhandbuch { #tutorial-user-guide } + Dieses Tutorial zeigt Ihnen Schritt für Schritt, wie Sie **FastAPI** mit den meisten seiner Funktionen verwenden können. Jeder Abschnitt baut schrittweise auf den vorhergehenden auf, ist jedoch in einzelne Themen gegliedert, sodass Sie direkt zu einem bestimmten Thema übergehen können, um Ihre spezifischen API-Anforderungen zu lösen. diff --git a/docs/de/docs/tutorial/metadata.md b/docs/de/docs/tutorial/metadata.md index a0d79786e..e6549aa3c 100644 --- a/docs/de/docs/tutorial/metadata.md +++ b/docs/de/docs/tutorial/metadata.md @@ -11,7 +11,7 @@ Sie können die folgenden Felder festlegen, die in der OpenAPI-Spezifikation und | `title` | `str` | Der Titel der API. | | `summary` | `str` | Eine kurze Zusammenfassung der API. Verfügbar seit OpenAPI 3.1.0, FastAPI 0.99.0. | | `description` | `str` | Eine kurze Beschreibung der API. Kann Markdown verwenden. | -| `version` | `string` | Die Version der API. Das ist die Version Ihrer eigenen Anwendung, nicht die von OpenAPI. Zum Beispiel `2.5.0`. | +| `version` | `str` | Die Version der API. Das ist die Version Ihrer eigenen Anwendung, nicht die von OpenAPI. Zum Beispiel `2.5.0`. | | `terms_of_service` | `str` | Eine URL zu den Nutzungsbedingungen für die API. Falls angegeben, muss es sich um eine URL handeln. | | `contact` | `dict` | Die Kontaktinformationen für die freigegebene API. Kann mehrere Felder enthalten.
contact-Felder
ParameterTypBeschreibung
namestrDer identifizierende Name der Kontaktperson/Organisation.
urlstrDie URL, die auf die Kontaktinformationen verweist. MUSS im Format einer URL vorliegen.
emailstrDie E-Mail-Adresse der Kontaktperson/Organisation. MUSS im Format einer E-Mail-Adresse vorliegen.
| | `license_info` | `dict` | Die Lizenzinformationen für die freigegebene API. Kann mehrere Felder enthalten.
license_info-Felder
ParameterTypBeschreibung
namestrERFORDERLICH (wenn eine license_info festgelegt ist). Der für die API verwendete Lizenzname.
identifierstrEin [SPDX](https://spdx.org/licenses/)-Lizenzausdruck für die API. Das Feld identifier und das Feld url schließen sich gegenseitig aus. Verfügbar seit OpenAPI 3.1.0, FastAPI 0.99.0.
urlstrEine URL zur Lizenz, die für die API verwendet wird. MUSS im Format einer URL vorliegen.
| diff --git a/docs/de/docs/tutorial/path-operation-configuration.md b/docs/de/docs/tutorial/path-operation-configuration.md index 9fd381b7e..56c8a69e7 100644 --- a/docs/de/docs/tutorial/path-operation-configuration.md +++ b/docs/de/docs/tutorial/path-operation-configuration.md @@ -38,11 +38,11 @@ Diese werden zum OpenAPI-Schema hinzugefügt und von den automatischen Dokumenta -### Tags mittels Enumeration { #tags-with-enums } +### Tags mit Enums { #tags-with-enums } -Wenn Sie eine große Anwendung haben, können sich am Ende **viele Tags** anhäufen, und Sie möchten sicherstellen, dass Sie für verwandte *Pfadoperationen* immer den **gleichen Tag** verwenden. +Wenn Sie eine große Anwendung haben, können sich am Ende **mehrere Tags** anhäufen, und Sie möchten sicherstellen, dass Sie für verwandte *Pfadoperationen* immer den **gleichen Tag** verwenden. -In diesem Fall macht es Sinn, die Tags in einem `Enum` zu speichern. +In diesen Fällen kann es sinnvoll sein, die Tags in einem `Enum` zu speichern. **FastAPI** unterstützt das auf die gleiche Weise wie einfache Strings: @@ -104,4 +104,4 @@ Vergleichen Sie, wie deprecatete und nicht-deprecatete *Pfadoperationen* aussehe ## Zusammenfassung { #recap } -Sie können auf einfache Weise Metadaten für Ihre *Pfadoperationen* definieren, indem Sie den *Pfadoperation-Dekoratoren* Parameter hinzufügen. +Sie können Ihre *Pfadoperationen* einfach konfigurieren und Metadaten hinzufügen, indem Sie den *Pfadoperation-Dekoratoren* Parameter übergeben. diff --git a/docs/de/docs/tutorial/query-params-str-validations.md b/docs/de/docs/tutorial/query-params-str-validations.md index a00596f08..bec5f574a 100644 --- a/docs/de/docs/tutorial/query-params-str-validations.md +++ b/docs/de/docs/tutorial/query-params-str-validations.md @@ -81,7 +81,7 @@ FastAPI wird nun: * Die Daten **validieren**, um sicherzustellen, dass die Länge maximal 50 Zeichen beträgt * Einen **klaren Fehler** für den Client anzeigen, wenn die Daten ungültig sind -* Den Parameter in der OpenAPI-Schema-*Pfadoperation* **dokumentieren** (sodass er in der **automatischen Dokumentation** angezeigt wird) +* Den Parameter in der OpenAPI-Schema-*Pfadoperation* **dokumentieren** (sodass er in der **automatischen Dokumentationsoberfläche** angezeigt wird) ## Alternative (alt): `Query` als Defaultwert { #alternative-old-query-as-the-default-value } @@ -179,7 +179,7 @@ Dieses spezielle Suchmuster im regulären Ausdruck überprüft, dass der erhalte Wenn Sie sich mit all diesen **„regulärer Ausdruck“**-Ideen verloren fühlen, keine Sorge. Sie sind ein schwieriges Thema für viele Menschen. Sie können noch viele Dinge tun, ohne reguläre Ausdrücke direkt zu benötigen. -Aber nun wissen Sie, dass Sie sie in **FastAPI** immer dann verwenden können, wenn Sie sie brauchen. +Nun wissen Sie, dass Sie sie in **FastAPI** immer dann verwenden können, wenn Sie sie brauchen. ## Defaultwerte { #default-values } @@ -276,7 +276,7 @@ Wenn Sie zu: http://localhost:8000/items/ ``` -gehen, wird der Default für `q` sein: `["foo", "bar"]`, und Ihre Response wird sein: +gehen, wird der Defaultwert für `q` sein: `["foo", "bar"]`, und Ihre Response wird sein: ```JSON { @@ -311,7 +311,7 @@ Diese Informationen werden in das generierte OpenAPI aufgenommen und von den Dok Beachten Sie, dass verschiedene Tools möglicherweise unterschiedliche Unterstützungslevels für OpenAPI haben. -Einige davon könnten noch nicht alle zusätzlichen Informationen anzuzeigen, die Sie erklärten, obwohl in den meisten Fällen die fehlende Funktionalität bereits in der Entwicklung geplant ist. +Einige davon könnten noch nicht alle zusätzlichen Informationen anzeigen, die Sie deklariert haben, obwohl in den meisten Fällen die fehlende Funktionalität bereits in der Entwicklung geplant ist. /// @@ -335,7 +335,7 @@ http://127.0.0.1:8000/items/?item-query=foobaritems Aber `item-query` ist kein gültiger Name für eine Variable in Python. -Der am ähnlichsten wäre `item_query`. +Am ähnlichsten wäre `item_query`. Aber Sie benötigen dennoch, dass er genau `item-query` ist ... @@ -347,7 +347,7 @@ Dann können Sie ein `alias` deklarieren, und dieser Alias wird verwendet, um de Nehmen wir an, Ihnen gefällt dieser Parameter nicht mehr. -Sie müssen ihn eine Weile dort belassen, da es Clients gibt, die ihn verwenden, aber Sie möchten, dass die Dokumentation ihn klar als deprecatet anzeigt. +Sie müssen ihn eine Weile dort belassen, da es Clients gibt, die ihn verwenden, aber Sie möchten, dass die Dokumentation ihn klar als deprecatet anzeigt. Dann übergeben Sie den Parameter `deprecated=True` an `Query`: @@ -395,7 +395,7 @@ Diese benutzerdefinierten Validatoren sind für Dinge gedacht, die einfach mit d /// -### Dieses Codebeispiel verstehen { #understand-that-code } +### Diesen Code verstehen { #understand-that-code } Der wichtige Punkt ist einfach die Verwendung von **`AfterValidator` mit einer Funktion innerhalb von `Annotated`**. Fühlen Sie sich frei, diesen Teil zu überspringen. 🤸 @@ -403,9 +403,9 @@ Der wichtige Punkt ist einfach die Verwendung von **`AfterValidator` mit einer F Aber wenn Sie neugierig auf dieses spezielle Codebeispiel sind und immer noch Spaß haben, hier sind einige zusätzliche Details. -#### Zeichenkette mit `value.startswith()` { #string-with-value-startswith } +#### String mit `value.startswith()` { #string-with-value-startswith } -Haben Sie bemerkt? Eine Zeichenkette mit `value.startswith()` kann ein Tuple übernehmen, und es wird jeden Wert im Tuple überprüfen: +Haben Sie bemerkt? Ein String mit `value.startswith()` kann ein Tuple übernehmen, und es wird jeden Wert im Tuple überprüfen: {* ../../docs_src/query_params_str_validations/tutorial015_an_py310.py ln[16:19] hl[17] *} diff --git a/docs/de/docs/tutorial/query-params.md b/docs/de/docs/tutorial/query-params.md index d386bc718..86ec9f4ab 100644 --- a/docs/de/docs/tutorial/query-params.md +++ b/docs/de/docs/tutorial/query-params.md @@ -23,7 +23,7 @@ Aber wenn Sie sie mit Python-Typen deklarieren (im obigen Beispiel als `int`), w Die gleichen Prozesse, die für Pfad-Parameter gelten, werden auch auf Query-Parameter angewendet: -* Editor Unterstützung (natürlich) +* Editor-Unterstützung (natürlich) * Daten-„Parsen“ * Datenvalidierung * Automatische Dokumentation @@ -67,17 +67,17 @@ In diesem Fall wird der Funktionsparameter `q` optional und standardmäßig `Non /// tip | Tipp -Beachten Sie auch, dass **FastAPI** intelligent genug ist, um zu erkennen, dass `item_id` ein Pfad-Parameter ist und `q` keiner, daher muss letzteres ein Query-Parameter sein. +Beachten Sie auch, dass **FastAPI** intelligent genug ist, um zu erkennen, dass der Pfad-Parameter `item_id` ein Pfad-Parameter ist und `q` keiner, daher muss letzteres ein Query-Parameter sein. /// -## Query-Parameter Typkonvertierung { #query-parameter-type-conversion } +## Typkonvertierung von Query-Parametern { #query-parameter-type-conversion } Sie können auch `bool`-Typen deklarieren, und sie werden konvertiert: {* ../../docs_src/query_params/tutorial003_py310.py hl[7] *} -Wenn Sie nun zu: +Wenn Sie in diesem Fall zu: ``` http://127.0.0.1:8000/items/foo?short=1 @@ -109,6 +109,7 @@ http://127.0.0.1:8000/items/foo?short=yes gehen, oder zu irgendeiner anderen Variante der Groß-/Kleinschreibung (Alles groß, Anfangsbuchstabe groß, usw.), dann wird Ihre Funktion den Parameter `short` mit dem `bool`-Wert `True` sehen, ansonsten mit dem Wert `False`. + ## Mehrere Pfad- und Query-Parameter { #multiple-path-and-query-parameters } Sie können mehrere Pfad-Parameter und Query-Parameter gleichzeitig deklarieren, **FastAPI** weiß, welches welcher ist. @@ -121,7 +122,7 @@ Parameter werden anhand ihres Namens erkannt: ## Erforderliche Query-Parameter { #required-query-parameters } -Wenn Sie einen Defaultwert für Nicht-Pfad-Parameter deklarieren (Bis jetzt haben wir nur Query-Parameter gesehen), dann ist der Parameter nicht erforderlich. +Wenn Sie einen Defaultwert für Nicht-Pfad-Parameter deklarieren (bis jetzt haben wir nur Query-Parameter gesehen), dann ist der Parameter nicht erforderlich. Wenn Sie keinen spezifischen Wert haben wollen, sondern der Parameter einfach optional sein soll, dann setzen Sie den Defaultwert auf `None`. @@ -129,7 +130,7 @@ Aber wenn Sie wollen, dass ein Query-Parameter erforderlich ist, vergeben Sie ei {* ../../docs_src/query_params/tutorial005_py310.py hl[6:7] *} -Hier ist `needy` ein erforderlicher Query-Parameter vom Typ `str`. +Hier ist der Query-Parameter `needy` ein erforderlicher Query-Parameter vom Typ `str`. Wenn Sie in Ihrem Browser eine URL wie: @@ -137,7 +138,7 @@ Wenn Sie in Ihrem Browser eine URL wie: http://127.0.0.1:8000/items/foo-item ``` -... öffnen, ohne den benötigten Parameter `needy`, dann erhalten Sie einen Fehler wie den folgenden: +... öffnen, ohne den erforderlichen Parameter `needy` hinzuzufügen, dann erhalten Sie einen Fehler wie den folgenden: ```JSON { @@ -161,7 +162,7 @@ Da `needy` ein erforderlicher Parameter ist, müssen Sie ihn in der URL setzen: http://127.0.0.1:8000/items/foo-item?needy=sooooneedy ``` -... Das funktioniert: +... das funktioniert: ```JSON { @@ -174,7 +175,7 @@ Und natürlich können Sie einige Parameter als erforderlich, einige mit Default {* ../../docs_src/query_params/tutorial006_py310.py hl[8] *} -In diesem Fall gibt es drei Query-Parameter: +In diesem Fall gibt es 3 Query-Parameter: * `needy`, ein erforderlicher `str`. * `skip`, ein `int` mit einem Defaultwert `0`. diff --git a/docs/de/docs/tutorial/request-files.md b/docs/de/docs/tutorial/request-files.md index f2a234c3b..7a344604a 100644 --- a/docs/de/docs/tutorial/request-files.md +++ b/docs/de/docs/tutorial/request-files.md @@ -24,7 +24,7 @@ Importieren Sie `File` und `UploadFile` von `fastapi`: ## `File`-Parameter definieren { #define-file-parameters } -Erstellen Sie Datei-Parameter, so wie Sie es auch mit `Body` und `Form` machen würden: +Erstellen Sie Datei-Parameter, so wie Sie es auch mit `Body` oder `Form` machen würden: {* ../../docs_src/request_files/tutorial001_an_py310.py hl[9] *} @@ -44,7 +44,7 @@ Um Dateibodys zu deklarieren, müssen Sie `File` verwenden, da diese Parameter s Die Dateien werden als „Formulardaten“ hochgeladen. -Wenn Sie den Typ Ihrer *Pfadoperation-Funktion* als `bytes` deklarieren, wird **FastAPI** die Datei für Sie auslesen, und Sie erhalten den Inhalt als `bytes`. +Wenn Sie den Typ des Parameters Ihrer *Pfadoperation-Funktion* als `bytes` deklarieren, wird **FastAPI** die Datei für Sie auslesen, und Sie erhalten den Inhalt als `bytes`. Bedenken Sie, dass das bedeutet, dass sich der gesamte Inhalt der Datei im Arbeitsspeicher befindet. Das wird für kleinere Dateien gut funktionieren. @@ -63,27 +63,27 @@ Definieren Sie einen Datei-Parameter mit dem Typ `UploadFile`: * Eine Datei, die bis zu einem bestimmten Größen-Limit im Arbeitsspeicher behalten wird, und wenn das Limit überschritten wird, auf der Festplatte gespeichert wird. * Das bedeutet, es wird für große Dateien wie Bilder, Videos, große Binärdateien, usw. gut funktionieren, ohne den ganzen Arbeitsspeicher aufzubrauchen. * Sie können Metadaten aus der hochgeladenen Datei auslesen. -* Es hat eine [dateiartige](https://docs.python.org/3/glossary.html#term-file-like-object) `async`hrone Schnittstelle. +* Es hat eine [dateiartige](https://docs.python.org/3/glossary.html#term-file-like-object) `async`-Schnittstelle. * Es stellt ein tatsächliches Python-[`SpooledTemporaryFile`](https://docs.python.org/3/library/tempfile.html#tempfile.SpooledTemporaryFile)-Objekt bereit, welches Sie direkt anderen Bibliotheken übergeben können, die ein dateiartiges Objekt erwarten. ### `UploadFile` { #uploadfile } `UploadFile` hat die folgenden Attribute: -* `filename`: Ein `str` mit dem ursprünglichen Namen der hochgeladenen Datei (z. B. `meinbild.jpg`). +* `filename`: Ein `str` mit dem ursprünglichen Namen der hochgeladenen Datei (z. B. `myimage.jpg`). * `content_type`: Ein `str` mit dem Inhaltstyp (MIME-Typ / Medientyp) (z. B. `image/jpeg`). -* `file`: Ein [`SpooledTemporaryFile`](https://docs.python.org/3/library/tempfile.html#tempfile.SpooledTemporaryFile) (ein [dateiartiges](https://docs.python.org/3/glossary.html#term-file-like-object) Objekt). Das ist das tatsächliche Python-Objekt, das Sie direkt anderen Funktionen oder Bibliotheken übergeben können, welche ein „file-like“-Objekt erwarten. +* `file`: Ein [`SpooledTemporaryFile`](https://docs.python.org/3/library/tempfile.html#tempfile.SpooledTemporaryFile) (ein [dateiartiges](https://docs.python.org/3/glossary.html#term-file-like-object) Objekt). Das ist das tatsächliche Python-Dateiobjekt, das Sie direkt anderen Funktionen oder Bibliotheken übergeben können, welche ein „file-like“-Objekt erwarten. -`UploadFile` hat die folgenden `async`hronen Methoden. Sie alle rufen die entsprechenden Methoden des darunterliegenden Datei-Objekts auf (wobei intern `SpooledTemporaryFile` verwendet wird). +`UploadFile` hat die folgenden `async`-Methoden. Sie alle rufen die entsprechenden Methoden des darunterliegenden Datei-Objekts auf (wobei intern `SpooledTemporaryFile` verwendet wird). -* `write(daten)`: Schreibt `daten` (`str` oder `bytes`) in die Datei. -* `read(anzahl)`: Liest `anzahl` (`int`) bytes/Zeichen aus der Datei. -* `seek(versatz)`: Geht zur Position `versatz` (`int`) in der Datei. +* `write(data)`: Schreibt `data` (`str` oder `bytes`) in die Datei. +* `read(size)`: Liest `size` (`int`) Bytes/Zeichen aus der Datei. +* `seek(offset)`: Geht zur Byte-Position `offset` (`int`) in der Datei. * z. B. würde `await myfile.seek(0)` zum Anfang der Datei gehen. * Das ist besonders dann nützlich, wenn Sie `await myfile.read()` einmal ausführen und dann diese Inhalte erneut auslesen müssen. * `close()`: Schließt die Datei. -Da alle diese Methoden `async`hron sind, müssen Sie sie „await“en („erwarten“). +Da alle diese Methoden `async`-Methoden sind, müssen Sie sie „await“en („erwarten“). Zum Beispiel können Sie innerhalb einer `async` *Pfadoperation-Funktion* den Inhalt wie folgt auslesen: @@ -105,7 +105,7 @@ Wenn Sie die `async`-Methoden verwenden, führt **FastAPI** die Datei-Methoden i /// note | Technische Details zu Starlette -FastAPIs `UploadFile` erbt direkt von Starlettes `UploadFile`, fügt aber ein paar notwendige Teile hinzu, um es kompatibel mit **Pydantic** und anderen Teilen von FastAPI zu machen. +**FastAPI**s `UploadFile` erbt direkt von **Starlette**s `UploadFile`, fügt aber ein paar notwendige Teile hinzu, um es kompatibel mit **Pydantic** und anderen Teilen von FastAPI zu machen. /// @@ -113,15 +113,15 @@ FastAPIs `UploadFile` erbt direkt von Starlettes `UploadFile`, fügt aber ein pa Der Weg, wie HTML-Formulare (`
`) die Daten zum Server senden, verwendet normalerweise eine „spezielle“ Kodierung für diese Daten. Diese unterscheidet sich von JSON. -**FastAPI** stellt sicher, dass diese Daten korrekt ausgelesen werden, statt JSON zu erwarten. +**FastAPI** stellt sicher, dass diese Daten von der richtigen Stelle ausgelesen werden, statt JSON zu erwarten. /// note | Technische Details -Daten aus Formularen werden, wenn es keine Dateien sind, normalerweise mit dem „media type“ `application/x-www-form-urlencoded` kodiert. +Daten aus Formularen werden, wenn sie keine Dateien enthalten, normalerweise mit dem „media type“ `application/x-www-form-urlencoded` kodiert. Sollte das Formular aber Dateien enthalten, dann werden diese mit `multipart/form-data` kodiert. Wenn Sie `File` verwenden, wird **FastAPI** wissen, dass es die Dateien vom korrekten Teil des Bodys holen muss. -Wenn Sie mehr über diese Kodierungen und Formularfelder lesen möchten, besuchen Sie die [MDN-Webdokumentation für `POST`](https://developer.mozilla.org/en-US/docs/Web/HTTP/Methods/POST). +Wenn Sie mehr über diese Kodierungen und Formularfelder lesen möchten, besuchen Sie die [MDN-Webdokumentation für `POST`](https://developer.mozilla.org/en-US/docs/Web/HTTP/Methods/POST). /// @@ -149,7 +149,7 @@ Sie können auch `File()` mit `UploadFile` verwenden, um zum Beispiel zusätzlic Es ist auch möglich, mehrere Dateien gleichzeitig hochzuladen. -Diese werden demselben Formularfeld zugeordnet, welches mit den Formulardaten gesendet wird. +Diese werden demselben „Formularfeld“ zugeordnet, welches mittels „Formulardaten“ gesendet wird. Um das zu machen, deklarieren Sie eine Liste von `bytes` oder `UploadFile`s: diff --git a/docs/de/docs/tutorial/request-forms.md b/docs/de/docs/tutorial/request-forms.md index 815de0dce..aedcd4a51 100644 --- a/docs/de/docs/tutorial/request-forms.md +++ b/docs/de/docs/tutorial/request-forms.md @@ -1,5 +1,6 @@ # Formulardaten { #form-data } + Wenn Sie Felder aus Formularen statt JSON empfangen müssen, können Sie `Form` verwenden. /// note | Hinweis diff --git a/docs/de/docs/tutorial/response-status-code.md b/docs/de/docs/tutorial/response-status-code.md index 63f1870e8..63962829d 100644 --- a/docs/de/docs/tutorial/response-status-code.md +++ b/docs/de/docs/tutorial/response-status-code.md @@ -1,5 +1,6 @@ # Response-Statuscode { #response-status-code } + Genauso wie Sie ein Responsemodell angeben können, können Sie auch den HTTP-Statuscode für die Response mit dem Parameter `status_code` in jeder der *Pfadoperationen* deklarieren: * `@app.get()` diff --git a/docs/de/docs/tutorial/schema-extra-example.md b/docs/de/docs/tutorial/schema-extra-example.md index a34f8097b..9bf0eafec 100644 --- a/docs/de/docs/tutorial/schema-extra-example.md +++ b/docs/de/docs/tutorial/schema-extra-example.md @@ -14,7 +14,7 @@ Diese zusätzlichen Informationen werden unverändert zum für dieses Modell aus Sie können das Attribut `model_config` verwenden, das ein `dict` akzeptiert, wie beschrieben in [Pydantic-Dokumentation: Configuration](https://docs.pydantic.dev/latest/api/config/). -Sie können `json_schema_extra` setzen, mit einem `dict`, das alle zusätzlichen Daten enthält, die im generierten JSON-Schema angezeigt werden sollen, einschließlich `examples`. +Sie können `"json_schema_extra"` setzen, mit einem `dict`, das alle zusätzlichen Daten enthält, die im generierten JSON-Schema angezeigt werden sollen, einschließlich `examples`. /// tip | Tipp @@ -88,7 +88,7 @@ Das Format dieses OpenAPI-spezifischen Felds `examples` ist ein `dict` mit **meh Dies erfolgt nicht innerhalb jedes in OpenAPI enthaltenen JSON-Schemas, sondern außerhalb, in der *Pfadoperation*. -### Verwendung des Parameters `openapi_examples` { #using-the-openapi-examples-parameter } +### Den Parameter `openapi_examples` verwenden { #using-the-openapi-examples-parameter } Sie können die OpenAPI-spezifischen `examples` in FastAPI mit dem Parameter `openapi_examples` deklarieren, für: @@ -189,9 +189,9 @@ In Versionen von FastAPI vor 0.99.0 (0.99.0 und höher verwenden das neuere Open Aber jetzt, da FastAPI 0.99.0 und höher, OpenAPI 3.1.0 verwendet, das JSON Schema 2020-12 verwendet, und Swagger UI 5.0.0 und höher, ist alles konsistenter und die Beispiele sind in JSON Schema enthalten. -### Swagger-Benutzeroberfläche und OpenAPI-spezifische `examples` { #swagger-ui-and-openapi-specific-examples } +### Swagger UI und OpenAPI-spezifische `examples` { #swagger-ui-and-openapi-specific-examples } -Da die Swagger-Benutzeroberfläche derzeit nicht mehrere JSON Schema Beispiele unterstützt (Stand: 26.08.2023), hatten Benutzer keine Möglichkeit, mehrere Beispiele in der Dokumentation anzuzeigen. +Da Swagger UI derzeit nicht mehrere JSON Schema Beispiele unterstützt (Stand: 26.08.2023), hatten Benutzer keine Möglichkeit, mehrere Beispiele in der Dokumentation anzuzeigen. Um dieses Problem zu lösen, hat FastAPI `0.103.0` **Unterstützung** für die Deklaration desselben alten **OpenAPI-spezifischen** `examples`-Felds mit dem neuen Parameter `openapi_examples` hinzugefügt. 🤓 diff --git a/docs/de/docs/tutorial/security/first-steps.md b/docs/de/docs/tutorial/security/first-steps.md index 2fa587184..69e8abec0 100644 --- a/docs/de/docs/tutorial/security/first-steps.md +++ b/docs/de/docs/tutorial/security/first-steps.md @@ -1,5 +1,6 @@ # Sicherheit – Erste Schritte { #security-first-steps } + Stellen wir uns vor, dass Sie Ihre **Backend**-API auf einer Domain haben. Und Sie haben ein **Frontend** auf einer anderen Domain oder in einem anderen Pfad derselben Domain (oder in einer Mobile-Anwendung). diff --git a/docs/de/docs/tutorial/security/get-current-user.md b/docs/de/docs/tutorial/security/get-current-user.md index 5178de9b0..1bcccfd82 100644 --- a/docs/de/docs/tutorial/security/get-current-user.md +++ b/docs/de/docs/tutorial/security/get-current-user.md @@ -14,7 +14,7 @@ Erstellen wir zunächst ein Pydantic-Benutzermodell. So wie wir Pydantic zum Deklarieren von Bodys verwenden, können wir es auch überall sonst verwenden: -{* ../../docs_src/security/tutorial002_an_py310.py hl[5,12:6] *} +{* ../../docs_src/security/tutorial002_an_py310.py hl[5,12:16] *} ## Eine `get_current_user`-Abhängigkeit erstellen { #create-a-get-current-user-dependency } diff --git a/docs/de/docs/tutorial/security/oauth2-jwt.md b/docs/de/docs/tutorial/security/oauth2-jwt.md index 1a42eb6f3..d04bd00d4 100644 --- a/docs/de/docs/tutorial/security/oauth2-jwt.md +++ b/docs/de/docs/tutorial/security/oauth2-jwt.md @@ -120,7 +120,7 @@ Und noch eine, um einen Benutzer zu authentifizieren und zurückzugeben. Wenn `authenticate_user` mit einem Benutzernamen aufgerufen wird, der in der Datenbank nicht existiert, führen wir dennoch `verify_password` gegen einen Dummy-Hash aus. -So stellt man sicher, dass der Endpunkt ungefähr gleich viel Zeit für die Antwort benötigt, unabhängig davon, ob der Benutzername gültig ist oder nicht. Dadurch werden Timing-Angriffe verhindert, mit denen vorhandene Benutzernamen ermittelt werden könnten. +So stellt man sicher, dass der Endpunkt ungefähr gleich viel Zeit für die Antwort benötigt, unabhängig davon, ob der Benutzername gültig ist oder nicht. Dadurch werden **Timing-Angriffe** verhindert, mit denen vorhandene Benutzernamen ermittelt werden könnten. /// note | Hinweis @@ -168,7 +168,7 @@ Wenn der Token ungültig ist, geben Sie sofort einen HTTP-Fehler zurück. {* ../../docs_src/security/tutorial004_an_py310.py hl[93:110] *} -## Die *Pfadoperation* `/token` aktualisieren { #update-the-token-path-operation } +## Die `/token`-*Pfadoperation* aktualisieren { #update-the-token-path-operation } Erstellen Sie ein `timedelta` mit der Ablaufzeit des Tokens. diff --git a/docs/de/docs/tutorial/security/simple-oauth2.md b/docs/de/docs/tutorial/security/simple-oauth2.md index f5304bd32..b7b041bc1 100644 --- a/docs/de/docs/tutorial/security/simple-oauth2.md +++ b/docs/de/docs/tutorial/security/simple-oauth2.md @@ -20,7 +20,7 @@ Die Spezifikation besagt auch, dass `username` und `password` als Formulardaten ### `scope` { #scope } -Ferner sagt die Spezifikation, dass der Client ein weiteres Formularfeld "`scope`" („Geltungsbereich“) senden kann. +Ferner sagt die Spezifikation, dass der Client ein weiteres Formularfeld „`scope`“ senden kann. Der Name des Formularfelds lautet `scope` (im Singular), tatsächlich handelt es sich jedoch um einen langen String mit durch Leerzeichen getrennten „Scopes“. @@ -120,7 +120,7 @@ Immer wenn Sie genau den gleichen Inhalt (genau das gleiche Passwort) übergeben Sie können jedoch nicht vom Kauderwelsch zurück zum Passwort konvertieren. -##### Warum Passwort-Hashing verwenden? { #why-use-password-hashing } +##### Warum Passwort-Hashing verwenden { #why-use-password-hashing } Wenn Ihre Datenbank gestohlen wird, hat der Dieb nicht die Klartext-Passwörter Ihrer Benutzer, sondern nur die Hashes. @@ -146,7 +146,7 @@ UserInDB( /// note | Hinweis -Eine ausführlichere Erklärung von `**user_dict` finden Sie in [der Dokumentation für **Extra Modelle**](../extra-models.md#about-user-in-dict). +Eine ausführlichere Erklärung von `**user_dict` finden Sie in [der Dokumentation für **Extra Modelle**](../extra-models.md#about-user-in-model-dump). /// @@ -226,7 +226,7 @@ Verwenden Sie die Anmeldedaten: Benutzer: `johndoe` -Passwort: `secret`. +Passwort: `secret` @@ -264,9 +264,9 @@ Wenn Sie auf das Schlosssymbol klicken und sich abmelden und dann den gleichen V Versuchen Sie es nun mit einem inaktiven Benutzer und authentisieren Sie sich mit: -Benutzer: `alice`. +Benutzer: `alice` -Passwort: `secret2`. +Passwort: `secret2` Und versuchen Sie, die Operation `GET` mit dem Pfad `/users/me` zu verwenden. diff --git a/docs/de/docs/tutorial/sql-databases.md b/docs/de/docs/tutorial/sql-databases.md index d7988f9a2..3c7aabae3 100644 --- a/docs/de/docs/tutorial/sql-databases.md +++ b/docs/de/docs/tutorial/sql-databases.md @@ -8,7 +8,7 @@ Hier werden wir ein Beispiel mit [SQLModel](https://sqlmodel.tiangolo.com/) sehe /// tip | Tipp -Sie könnten jede andere SQL- oder NoSQL-Datenbankbibliothek verwenden, die Sie möchten (in einigen Fällen als „ORMs“ bezeichnet), FastAPI zwingt Sie nicht, irgendetwas zu verwenden. 😎 +Sie könnten jede andere SQL- oder NoSQL-Datenbankbibliothek verwenden, die Sie möchten (in einigen Fällen als „ORMs“ bezeichnet), FastAPI zwingt Sie nicht, irgendetwas zu verwenden. 😎 /// @@ -121,7 +121,7 @@ Da jedes SQLModel-Modell auch ein Pydantic-Modell ist, können Sie es in denselb Wenn Sie beispielsweise einen Parameter vom Typ `Hero` deklarieren, wird er aus dem **JSON-Body** gelesen. -Auf die gleiche Weise können Sie es als **Rückgabetyp** der Funktion deklarieren, und dann wird die Form der Daten in der automatischen API-Dokumentation angezeigt. +Auf die gleiche Weise können Sie es als **Rückgabetyp** der Funktion deklarieren, und dann wird die Form der Daten in der automatischen API-Dokumentations-UI angezeigt. {* ../../docs_src/sql_databases/tutorial001_an_py310.py ln[40:45] hl[40:45] *} @@ -266,7 +266,7 @@ In der vorherigen Version der App hatten wir keine Möglichkeit, einen Helden ** Das `HeroUpdate`-*Datenmodell* ist etwas Besonderes, es hat **die selben Felder**, die benötigt werden, um einen neuen Helden zu erstellen, aber alle Felder sind **optional** (sie haben alle einen Defaultwert). Auf diese Weise, wenn Sie einen Helden aktualisieren, können Sie nur die Felder senden, die Sie aktualisieren möchten. -Da sich tatsächlich **alle Felder ändern** (der Typ enthält jetzt `None` und sie haben jetzt einen Standardwert von `None`), müssen wir sie erneut **deklarieren**. +Da sich tatsächlich **alle Felder ändern** (der Typ enthält jetzt `None` und sie haben jetzt einen Defaultwert von `None`), müssen wir sie erneut **deklarieren**. Wir müssen wirklich nicht von `HeroBase` erben, weil wir alle Felder neu deklarieren. Ich lasse es aus Konsistenzgründen erben, aber das ist nicht notwendig. Es ist mehr eine Frage des persönlichen Geschmacks. 🤷 diff --git a/docs/de/docs/tutorial/static-files.md b/docs/de/docs/tutorial/static-files.md index 8fb4c1908..ef75ca91a 100644 --- a/docs/de/docs/tutorial/static-files.md +++ b/docs/de/docs/tutorial/static-files.md @@ -2,6 +2,14 @@ Mit `StaticFiles` können Sie statische Dateien aus einem Verzeichnis automatisch bereitstellen. +/// tip | Tipp + +Wenn Sie ein Frontend hosten müssen, verwenden Sie stattdessen `app.frontend()`; lesen Sie mehr dazu unter [Frontend](frontend.md). + +`app.frontend()` verwendet darunter `StaticFiles`, mit mehreren zusätzlichen Vorteilen für Frontends, wie der Handhabung von clientseitigem Routing. + +/// + ## `StaticFiles` verwenden { #use-staticfiles } * Importieren Sie `StaticFiles`. diff --git a/docs/de/docs/tutorial/testing.md b/docs/de/docs/tutorial/testing.md index 73dc14860..59d0be6bb 100644 --- a/docs/de/docs/tutorial/testing.md +++ b/docs/de/docs/tutorial/testing.md @@ -24,7 +24,7 @@ Importieren Sie `TestClient`. Erstellen Sie einen `TestClient`, indem Sie ihm Ihre **FastAPI**-Anwendung übergeben. -Erstellen Sie Funktionen mit einem Namen, der mit `test_` beginnt (das sind `pytest`-Konventionen). +Erstellen Sie Funktionen mit einem Namen, der mit `test_` beginnt (das ist eine Standard-`pytest`-Konvention). Verwenden Sie das `TestClient`-Objekt auf die gleiche Weise wie `httpx`. @@ -36,7 +36,7 @@ Schreiben Sie einfache `assert`-Anweisungen mit den Standard-Python-Ausdrücken, Beachten Sie, dass die Testfunktionen normal `def` und nicht `async def` sind. -Und die Anrufe an den Client sind ebenfalls normale Anrufe, die nicht `await` verwenden. +Und die Aufrufe an den Client sind ebenfalls normale Aufrufe, die nicht `await` verwenden. Dadurch können Sie `pytest` ohne Komplikationen direkt nutzen. @@ -62,7 +62,7 @@ In einer echten Anwendung würden Sie Ihre Tests wahrscheinlich in einer anderen Und Ihre **FastAPI**-Anwendung könnte auch aus mehreren Dateien/Modulen, usw. bestehen. -### **FastAPI** Anwendungsdatei { #fastapi-app-file } +### **FastAPI**-Anwendungsdatei { #fastapi-app-file } Nehmen wir an, Sie haben eine Dateistruktur wie in [Größere Anwendungen](bigger-applications.md) beschrieben: @@ -131,7 +131,7 @@ Anschließend könnten Sie `test_main.py` mit den erweiterten Tests aktualisiere {* ../../docs_src/app_testing/app_b_an_py310/test_main.py *} -Wenn Sie möchten, dass der Client Informationen im Request übergibt und Sie nicht wissen, wie das geht, können Sie suchen (googeln), wie es mit `httpx` gemacht wird, oder sogar, wie es mit `requests` gemacht wird, da das Design von HTTPX auf dem Design von Requests basiert. +Immer wenn der Client Informationen im Request übergeben soll und Sie nicht wissen, wie, können Sie danach suchen (googeln), wie es mit `httpx` gemacht wird, oder sogar, wie es mit `requests` gemacht wird, da das Design von HTTPX auf dem Design von Requests basiert. Dann machen Sie in Ihren Tests einfach das gleiche. diff --git a/docs/de/docs/virtual-environments.md b/docs/de/docs/virtual-environments.md index 81d13cc91..782d1cdcf 100644 --- a/docs/de/docs/virtual-environments.md +++ b/docs/de/docs/virtual-environments.md @@ -443,6 +443,8 @@ Auf diese Weise, wenn Sie `python` ausführen, wird nicht versucht, es aus diese Jetzt sind Sie bereit, mit Ihrem Projekt zu arbeiten. + + /// tip | Tipp Möchten Sie verstehen, was das alles oben bedeutet? @@ -455,7 +457,7 @@ Lesen Sie weiter. 👇🤓 Um mit FastAPI zu arbeiten, müssen Sie [Python](https://www.python.org/) installieren. -Danach müssen Sie FastAPI und alle anderen Pakete, die Sie verwenden möchten, **installieren**. +Danach müssen Sie FastAPI und alle anderen **Pakete**, die Sie verwenden möchten, **installieren**. Um Pakete zu installieren, würden Sie normalerweise den `pip`-Befehl verwenden, der mit Python geliefert wird (oder ähnliche Alternativen). @@ -639,7 +641,7 @@ $ source .venv/Scripts/activate Dieser Befehl erstellt oder ändert einige [Umgebungsvariablen](environment-variables.md), die für die nächsten Befehle verfügbar sein werden. -Eine dieser Variablen ist die `PATH`-Umgebungsvariable. +Eine dieser Variablen ist die `PATH`-Variable. /// tip | Tipp @@ -649,7 +651,7 @@ Sie können mehr über die `PATH`-Umgebungsvariable im Abschnitt [Umgebungsvaria Das Aktivieren einer virtuellen Umgebung fügt deren Pfad `.venv/bin` (auf Linux und macOS) oder `.venv\Scripts` (auf Windows) zur `PATH`-Umgebungsvariable hinzu. -Angenommen, die `PATH`-Umgebungsvariable sah vor dem Aktivieren der Umgebung so aus: +Angenommen, die `PATH`-Variable sah vor dem Aktivieren der Umgebung so aus: //// tab | Linux, macOS @@ -678,7 +680,7 @@ Das bedeutet, dass das System nach Programmen sucht in: //// -Nach dem Aktivieren der virtuellen Umgebung würde die `PATH`-Umgebungsvariable folgendermaßen aussehen: +Nach dem Aktivieren der virtuellen Umgebung würde die `PATH`-Variable folgendermaßen aussehen: //// tab | Linux, macOS @@ -728,7 +730,7 @@ finden und dieses verwenden. //// -Ein wichtiger Punkt ist, dass es den Pfad der virtuellen Umgebung am **Anfang** der `PATH`-Umgebungsvariable platziert. Das System wird es **vor** allen anderen verfügbaren Pythons finden. Auf diese Weise, wenn Sie `python` ausführen, wird das Python **aus der virtuellen Umgebung** verwendet anstelle eines anderen `python` (zum Beispiel, einem `python` aus einer globalen Umgebung). +Ein wichtiger Punkt ist, dass es den Pfad der virtuellen Umgebung am **Anfang** der `PATH`-Variable platziert. Das System wird es **vor** allen anderen verfügbaren Pythons finden. Auf diese Weise, wenn Sie `python` ausführen, wird das Python **aus der virtuellen Umgebung** verwendet anstelle eines anderen `python` (zum Beispiel, einem `python` aus einer globalen Umgebung). Das Aktivieren einer virtuellen Umgebung ändert auch ein paar andere Dinge, aber dies ist eines der wichtigsten Dinge, die es tut. From a49e35172dcfc064f8b3a6e0758442da774a977d Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Wed, 1 Jul 2026 13:58:04 +0000 Subject: [PATCH 375/462] =?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 9d6eacc89..24f97509a 100644 --- a/docs/en/docs/release-notes.md +++ b/docs/en/docs/release-notes.md @@ -9,6 +9,7 @@ hide: ### Translations +* 🌐 Update translations for de (update-outdated). PR [#15899](https://github.com/fastapi/fastapi/pull/15899) by [@tiangolo](https://github.com/tiangolo). * 🌐 Update translations for es (update-outdated). PR [#15892](https://github.com/fastapi/fastapi/pull/15892) by [@tiangolo](https://github.com/tiangolo). * 🌐 Update translations for tr (update-outdated). PR [#15891](https://github.com/fastapi/fastapi/pull/15891) by [@tiangolo](https://github.com/tiangolo). * 🌐 Update translations for pt (update-outdated). PR [#15893](https://github.com/fastapi/fastapi/pull/15893) by [@tiangolo](https://github.com/tiangolo). From 28c93900e71f69ac536ebdd317c476003750a8de Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebasti=C3=A1n=20Ram=C3=ADrez?= Date: Wed, 1 Jul 2026 15:59:00 +0200 Subject: [PATCH 376/462] =?UTF-8?q?=F0=9F=8C=90=20Update=20translations=20?= =?UTF-8?q?for=20ja=20(update-outdated)=20(#15895)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: github-actions[bot] Co-authored-by: Yurii Motov --- docs/ja/docs/_llm-test.md | 1 + .../docs/advanced/additional-status-codes.md | 2 +- .../ja/docs/advanced/advanced-dependencies.md | 6 +-- docs/ja/docs/advanced/dataclasses.md | 4 +- docs/ja/docs/advanced/events.md | 6 +-- docs/ja/docs/advanced/generate-clients.md | 14 ------ docs/ja/docs/advanced/json-base64-bytes.md | 2 +- docs/ja/docs/advanced/openapi-callbacks.md | 8 ++-- .../advanced/response-change-status-code.md | 1 + docs/ja/docs/advanced/response-cookies.md | 1 + docs/ja/docs/advanced/response-headers.md | 1 + .../docs/advanced/security/oauth2-scopes.md | 1 + docs/ja/docs/advanced/settings.md | 2 +- docs/ja/docs/advanced/stream-data.md | 22 +++++----- docs/ja/docs/advanced/wsgi.md | 1 + docs/ja/docs/alternatives.md | 20 ++++----- docs/ja/docs/async.md | 2 +- docs/ja/docs/deployment/cloud.md | 4 +- docs/ja/docs/deployment/concepts.md | 43 +++++++------------ docs/ja/docs/deployment/docker.md | 10 ++--- docs/ja/docs/deployment/https.md | 14 +++--- docs/ja/docs/deployment/manually.md | 2 +- docs/ja/docs/editor-support.md | 2 +- docs/ja/docs/environment-variables.md | 6 +-- docs/ja/docs/features.md | 4 +- docs/ja/docs/help-fastapi.md | 1 + docs/ja/docs/how-to/configure-swagger-ui.md | 2 +- .../docs/how-to/custom-request-and-route.md | 2 +- docs/ja/docs/how-to/graphql.md | 1 + ...migrate-from-pydantic-v1-to-pydantic-v2.md | 18 ++++++++ .../docs/how-to/separate-openapi-schemas.md | 4 +- docs/ja/docs/index.md | 20 ++++----- docs/ja/docs/project-generation.md | 2 +- docs/ja/docs/python-types.md | 6 +-- docs/ja/docs/tutorial/bigger-applications.md | 20 ++++----- docs/ja/docs/tutorial/body-nested-models.md | 1 + docs/ja/docs/tutorial/body.md | 1 + docs/ja/docs/tutorial/debugging.md | 2 +- .../dependencies/dependencies-with-yield.md | 1 + docs/ja/docs/tutorial/extra-data-types.md | 1 + docs/ja/docs/tutorial/extra-models.md | 2 +- docs/ja/docs/tutorial/first-steps.md | 5 ++- docs/ja/docs/tutorial/handling-errors.md | 1 + docs/ja/docs/tutorial/index.md | 1 + docs/ja/docs/tutorial/metadata.md | 6 +-- .../tutorial/path-operation-configuration.md | 1 + .../tutorial/query-params-str-validations.md | 4 +- docs/ja/docs/tutorial/query-params.md | 1 + docs/ja/docs/tutorial/request-files.md | 1 + docs/ja/docs/tutorial/request-forms.md | 2 +- docs/ja/docs/tutorial/response-status-code.md | 1 + docs/ja/docs/tutorial/schema-extra-example.md | 1 + docs/ja/docs/tutorial/security/first-steps.md | 4 +- .../tutorial/security/get-current-user.md | 2 +- docs/ja/docs/tutorial/security/oauth2-jwt.md | 8 ++-- .../docs/tutorial/security/simple-oauth2.md | 16 +++---- docs/ja/docs/tutorial/sql-databases.md | 1 + docs/ja/docs/tutorial/static-files.md | 8 ++++ docs/ja/docs/tutorial/testing.md | 8 ++-- docs/ja/docs/virtual-environments.md | 10 ++--- 60 files changed, 181 insertions(+), 163 deletions(-) diff --git a/docs/ja/docs/_llm-test.md b/docs/ja/docs/_llm-test.md index 4edaa93bf..91eeffd0c 100644 --- a/docs/ja/docs/_llm-test.md +++ b/docs/ja/docs/_llm-test.md @@ -1,5 +1,6 @@ # LLM テストファイル { #llm-test-file } + このドキュメントは、ドキュメントを翻訳する LLM が、`scripts/translate.py` の `general_prompt` と、`docs/{language code}/llm-prompt.md` の言語固有プロンプトを理解しているかをテストします。言語固有プロンプトは `general_prompt` の末尾に追加されます。 ここに追加したテストは、すべての言語固有プロンプトの設計者が参照します。 diff --git a/docs/ja/docs/advanced/additional-status-codes.md b/docs/ja/docs/advanced/additional-status-codes.md index ad9bd57dc..0c19abd49 100644 --- a/docs/ja/docs/advanced/additional-status-codes.md +++ b/docs/ja/docs/advanced/additional-status-codes.md @@ -16,7 +16,7 @@ {* ../../docs_src/additional_status_codes/tutorial001_an_py310.py hl[4,25] *} -/// warning +/// warning | 注意 上の例のように `Response` を直接返すと、それはそのまま返されます。 diff --git a/docs/ja/docs/advanced/advanced-dependencies.md b/docs/ja/docs/advanced/advanced-dependencies.md index 13c796373..e06ca4721 100644 --- a/docs/ja/docs/advanced/advanced-dependencies.md +++ b/docs/ja/docs/advanced/advanced-dependencies.md @@ -10,9 +10,9 @@ ただし、その固定の内容はパラメータ化できるようにしたいです。 -## "callable" なインスタンス { #a-callable-instance } +## 「callable」なインスタンス { #a-callable-instance } -Python には、クラスのインスタンスを "callable" にする方法があります。 +Python には、クラスのインスタンスを「callable」にする方法があります。 クラス自体(これはすでに callable です)ではなく、そのクラスのインスタンスです。 @@ -146,7 +146,7 @@ FastAPI 0.110.0 より前では、`yield` を持つ依存関係を使い、そ FastAPI 0.106.0 より前では、`yield` の後で例外を送出することはできませんでした。`yield` を持つ依存関係の終了コードはレスポンス送信「後」に実行されるため、[例外ハンドラ](../tutorial/handling-errors.md#install-custom-exception-handlers)はすでに実行済みでした。 -これは主に、依存関係が "yield" した同じオブジェクトをバックグラウンドタスク内で利用できるようにするための設計でした。終了コードはバックグラウンドタスク完了後に実行されるからです。 +これは主に、依存関係が「yield」した同じオブジェクトをバックグラウンドタスク内で利用できるようにするための設計でした。終了コードはバックグラウンドタスク完了後に実行されるからです。 これは、レスポンスがネットワーク上を移動するのを待っている間にリソースを保持しないようにする意図で、FastAPI 0.106.0 で変更されました。 diff --git a/docs/ja/docs/advanced/dataclasses.md b/docs/ja/docs/advanced/dataclasses.md index 42627c4ed..2cfe8e905 100644 --- a/docs/ja/docs/advanced/dataclasses.md +++ b/docs/ja/docs/advanced/dataclasses.md @@ -74,7 +74,7 @@ dataclass は自動的に Pydantic の dataclass に変換されます。 いつもどおり、FastAPI では必要に応じて `def` と `async def` を組み合わせられます。 - どちらをいつ使うかの復習が必要な場合は、[`async` と `await`](../async.md#in-a-hurry) に関するドキュメントの _"In a hurry?"_ セクションを参照してください。 + どちらをいつ使うかの復習が必要な場合は、[`async` と `await`](../async.md#in-a-hurry) に関するドキュメントの _「急いでいますか?」_ セクションを参照してください。 9. この *path operation 関数* は(可能ではありますが)dataclass 自体は返さず、内部データを持つ辞書のリストを返しています。 @@ -82,7 +82,7 @@ dataclass は自動的に Pydantic の dataclass に変換されます。 `dataclasses` は他の型注釈と多様な組み合わせが可能で、複雑なデータ構造を構成できます。 -上記のコード内コメントのヒントを参照して、より具体的な詳細を確認してください。 +上記のコード内の注釈のヒントを参照して、より具体的な詳細を確認してください。 ## さらに学ぶ { #learn-more } diff --git a/docs/ja/docs/advanced/events.md b/docs/ja/docs/advanced/events.md index f7dcf3b58..12064f948 100644 --- a/docs/ja/docs/advanced/events.md +++ b/docs/ja/docs/advanced/events.md @@ -120,7 +120,7 @@ async with lifespan(app): ここでは、`shutdown` のイベントハンドラ関数が、テキスト行 `"Application shutdown"` をファイル `log.txt` に書き込みます。 -/// note | 情報 +/// note | 備考 `open()` 関数の `mode="a"` は「追加」(append)を意味します。つまり、そのファイルに既にある内容を上書きせず、行が後ろに追記されます。 @@ -140,7 +140,7 @@ async with lifespan(app): ### `startup` と `shutdown` をまとめて { #startup-and-shutdown-together } -起動時とシャットダウン時のロジックは関連していることが多いです。何かを開始してから終了したい、リソースを獲得してから解放したい、などです. +起動時とシャットダウン時のロジックは関連していることが多いです。何かを開始してから終了したい、リソースを獲得してから解放したい、などです。 共有するロジックや変数のない別々の関数でそれを行うのは難しく、グローバル変数などに値を保存する必要が出てきます。 @@ -152,7 +152,7 @@ async with lifespan(app): 内部的には、ASGI の技術仕様において、これは [Lifespan プロトコル](https://asgi.readthedocs.io/en/latest/specs/lifespan.html) の一部であり、`startup` と `shutdown` というイベントが定義されています。 -/// note | 情報 +/// note | 備考 Starlette の `lifespan` ハンドラについては、[Starlette の Lifespan ドキュメント](https://www.starlette.dev/lifespan/)で詳しく読むことができます。 diff --git a/docs/ja/docs/advanced/generate-clients.md b/docs/ja/docs/advanced/generate-clients.md index 42a60b787..196ec5280 100644 --- a/docs/ja/docs/advanced/generate-clients.md +++ b/docs/ja/docs/advanced/generate-clients.md @@ -20,20 +20,6 @@ FastAPI は自動的に **OpenAPI 3.1** の仕様を生成します。したが /// -## FastAPI スポンサーによる SDK ジェネレータ { #sdk-generators-from-fastapi-sponsors } - -このセクションでは、FastAPI をスポンサーしている企業による、**ベンチャー支援**および**企業支援**のソリューションを紹介します。これらの製品は、高品質な生成 SDK に加えて、**追加機能**や**統合**を提供します。 - -✨ [**FastAPI をスポンサーする**](../help-fastapi.md#sponsor-the-author) ✨ ことで、これらの企業はフレームワークとその**エコシステム**の健全性と**持続可能性**を支援しています。 - -この支援は、FastAPI の**コミュニティ**(皆さん)への強いコミットメントの表明でもあり、**優れたサービス**の提供だけでなく、堅牢で発展するフレームワーク FastAPI を支える姿勢を示しています。🙇 - -例えば、次のようなものがあります: - -* [Stainless](https://www.stainless.com/?utm_source=fastapi&utm_medium=referral) - -これらのソリューションの中にはオープンソースや無料枠を提供するものもあり、金銭的コミットメントなしで試すことができます。他の商用 SDK ジェネレータも存在し、オンラインで見つけられます。🤓 - ## TypeScript SDK を作成する { #create-a-typescript-sdk } まずは簡単な FastAPI アプリから始めます: diff --git a/docs/ja/docs/advanced/json-base64-bytes.md b/docs/ja/docs/advanced/json-base64-bytes.md index c3c361a96..214ce14c6 100644 --- a/docs/ja/docs/advanced/json-base64-bytes.md +++ b/docs/ja/docs/advanced/json-base64-bytes.md @@ -4,7 +4,7 @@ ## Base64 とファイル { #base64-vs-files } -バイナリデータのアップロードにはまず、JSON にエンコードする代わりに [Request Files](../tutorial/request-files.md) を、バイナリデータの送信には [カスタムレスポンス - FileResponse](./custom-response.md#fileresponse--fileresponse-) を使えるか検討してください。 +バイナリデータのアップロードにはまず、JSON にエンコードする代わりに [リクエストファイル](../tutorial/request-files.md) を、バイナリデータの送信には [カスタムレスポンス - FileResponse](./custom-response.md#fileresponse) を使えるか検討してください。 JSON は UTF-8 でエンコードされた文字列のみを含められるため、生のバイト列は含められません。 diff --git a/docs/ja/docs/advanced/openapi-callbacks.md b/docs/ja/docs/advanced/openapi-callbacks.md index 5bc90c68e..e3ddeab98 100644 --- a/docs/ja/docs/advanced/openapi-callbacks.md +++ b/docs/ja/docs/advanced/openapi-callbacks.md @@ -23,7 +23,7 @@ * API 利用者(外部開発者)に通知を送り返します。 * これは(あなたの API から)外部開発者が提供する *外部 API* に POST リクエストを送ることで行われます(これが「コールバック」です)。 -## 通常の FastAPI アプリ { #the-normal-fastapi-app } +## 通常の **FastAPI** アプリ { #the-normal-fastapi-app } まず、コールバックを追加する前の通常の API アプリがどうなるか見てみましょう。 @@ -76,7 +76,7 @@ httpx.post(callback_url, json={"description": "Invoice paid", "paid": True}) しかし、あなたはすでに **FastAPI** で API の自動ドキュメントを簡単に作る方法を知っています。 -その知識を使って、*外部 API* がどうあるべきかをドキュメント化します……つまり、外部 API が実装すべき *path operation(s)*(あなたの API が呼び出すもの)を作成します。 +その知識を使って、*外部 API* がどうあるべきかをドキュメント化します... つまり、外部 API が実装すべき *path operation(s)*(あなたの API が呼び出すもの)を作成します。 /// tip | 豆知識 @@ -86,13 +86,13 @@ httpx.post(callback_url, json={"description": "Invoice paid", "paid": True}) /// -### コールバック用 APIRouter を作成 { #create-a-callback-apirouter } +### コールバック用 `APIRouter` を作成 { #create-a-callback-apirouter } まず、1 つ以上のコールバックを含む新しい `APIRouter` を作成します。 {* ../../docs_src/openapi_callbacks/tutorial001_py310.py hl[1,23] *} -### コールバックの path operation を作成 { #create-the-callback-path-operation } +### コールバックの *path operation* を作成 { #create-the-callback-path-operation } 上で作成したのと同じ `APIRouter` を使って、コールバックの *path operation* を作成します。 diff --git a/docs/ja/docs/advanced/response-change-status-code.md b/docs/ja/docs/advanced/response-change-status-code.md index 22f5f3701..35fcc5bbd 100644 --- a/docs/ja/docs/advanced/response-change-status-code.md +++ b/docs/ja/docs/advanced/response-change-status-code.md @@ -1,5 +1,6 @@ # レスポンス - ステータスコードの変更 { #response-change-status-code } + すでに、デフォルトの[レスポンスのステータスコード](../tutorial/response-status-code.md)を設定できることをご存知かもしれません。 しかし場合によっては、デフォルトとは異なるステータスコードを返す必要があります。 diff --git a/docs/ja/docs/advanced/response-cookies.md b/docs/ja/docs/advanced/response-cookies.md index c395b09c6..912181554 100644 --- a/docs/ja/docs/advanced/response-cookies.md +++ b/docs/ja/docs/advanced/response-cookies.md @@ -1,5 +1,6 @@ # レスポンスの Cookie { #response-cookies } + ## `Response` パラメータを使う { #use-a-response-parameter } *path operation 関数*で `Response` 型のパラメータを宣言できます。 diff --git a/docs/ja/docs/advanced/response-headers.md b/docs/ja/docs/advanced/response-headers.md index 3a61f5742..d5f6f31a3 100644 --- a/docs/ja/docs/advanced/response-headers.md +++ b/docs/ja/docs/advanced/response-headers.md @@ -1,5 +1,6 @@ # レスポンスヘッダー { #response-headers } + ## `Response` パラメータを使う { #use-a-response-parameter } (Cookie と同様に)*path operation 関数*で `Response` 型のパラメータを宣言できます。 diff --git a/docs/ja/docs/advanced/security/oauth2-scopes.md b/docs/ja/docs/advanced/security/oauth2-scopes.md index cab7f8deb..b01bd01ca 100644 --- a/docs/ja/docs/advanced/security/oauth2-scopes.md +++ b/docs/ja/docs/advanced/security/oauth2-scopes.md @@ -1,5 +1,6 @@ # OAuth2 のスコープ { #oauth2-scopes } + OAuth2 のスコープは **FastAPI** で直接利用でき、シームレスに統合されています。 これにより、OAuth2 標準に従った、よりきめ細かな権限システムを、OpenAPI 対応アプリケーション(および API ドキュメント)に統合できます。 diff --git a/docs/ja/docs/advanced/settings.md b/docs/ja/docs/advanced/settings.md index e42ec845c..b3fd89a46 100644 --- a/docs/ja/docs/advanced/settings.md +++ b/docs/ja/docs/advanced/settings.md @@ -52,7 +52,7 @@ Pydantic から `BaseSettings` をインポートして、そのサブクラス Pydantic モデルと同様に、型アノテーションと(必要なら)デフォルト値を持つクラス属性を宣言します。 -`Field()` による追加バリデーションなど、Pydantic モデルで使えるのと同じバリデーション機能をすべて利用できます。 +異なるデータ型や `Field()` による追加バリデーションなど、Pydantic モデルで使えるのと同じバリデーション機能とツールをすべて利用できます。 {* ../../docs_src/settings/tutorial001_py310.py hl[2,5:8,11] *} diff --git a/docs/ja/docs/advanced/stream-data.md b/docs/ja/docs/advanced/stream-data.md index 820f2d8b6..6360cdab5 100644 --- a/docs/ja/docs/advanced/stream-data.md +++ b/docs/ja/docs/advanced/stream-data.md @@ -2,9 +2,9 @@ JSON として構造化できるデータをストリームしたい場合は、[JSON Lines をストリームする](../tutorial/stream-json-lines.md) を参照してください。 -しかし、純粋なバイナリデータや文字列をストリームしたい場合は、次のようにできます。 +しかし、**純粋なバイナリデータ**や文字列をストリームしたい場合は、次のようにできます。 -/// note | 情報 +/// note | 備考 FastAPI 0.134.0 で追加されました。 @@ -12,21 +12,21 @@ FastAPI 0.134.0 で追加されました。 ## ユースケース { #use-cases } -例えば、AI LLM サービスの出力をそのまま、純粋な文字列としてストリームしたい場合に使えます。 +例えば、**AI LLM** サービスの出力をそのまま、純粋な文字列としてストリームしたい場合に使えます。 -メモリに一度に全て読み込むことなく、読み込みながらチャンクごとに送ることで、巨大なバイナリファイルをストリームすることにも使えます。 +メモリに一度に全て読み込むことなく、読み込みながらチャンクごとに送ることで、**巨大なバイナリファイル**をストリームすることにも使えます。 -同様に、動画や音声をストリームすることもできます。処理しながら生成し、そのまま送信することも可能です。 +同様に、**動画**や**音声**をストリームすることもできます。処理しながら生成し、そのまま送信することも可能です。 ## `yield` を使った `StreamingResponse` { #a-streamingresponse-with-yield } -path operation 関数で `response_class=StreamingResponse` を宣言すると、`yield` を使ってデータをチャンクごとに順次送信できます。 +*path operation 関数*で `response_class=StreamingResponse` を宣言すると、`yield` を使ってデータをチャンクごとに順次送信できます。 {* ../../docs_src/stream_data/tutorial001_py310.py ln[1:23] hl[20,23] *} FastAPI は各データチャンクをそのまま `StreamingResponse` に渡し、JSON などに変換しようとはしません。 -### 非 async な path operation 関数 { #non-async-path-operation-functions } +### 非 async な *path operation 関数* { #non-async-path-operation-functions } `async` なしの通常の `def` 関数でも同様に `yield` を使えます。 @@ -40,7 +40,7 @@ FastAPI は各データチャンクをそのまま `StreamingResponse` に渡し {* ../../docs_src/stream_data/tutorial001_py310.py ln[32:35] hl[33] *} -つまり、`StreamingResponse` では型アノテーションに依存せず、送信したい形式に合わせてバイト列を生成・エンコードする「自由」と「責任」があなたにあります。 🤓 +つまり、`StreamingResponse` では型アノテーションに依存せず、送信したい形式に合わせてバイト列を生成・エンコードする**自由**と**責任**があなたにあります。 🤓 ### バイト列をストリームする { #stream-bytes } @@ -58,7 +58,7 @@ FastAPI は各データチャンクをそのまま `StreamingResponse` に渡し {* ../../docs_src/stream_data/tutorial002_py310.py ln[6,19:20] hl[20] *} -その後、path operation 関数で `response_class=PNGStreamingResponse` としてこの新しいクラスを使用できます: +その後、*path operation 関数*で `response_class=PNGStreamingResponse` としてこの新しいクラスを使用できます: {* ../../docs_src/stream_data/tutorial002_py310.py ln[23:27] hl[23] *} @@ -90,7 +90,7 @@ FastAPI は各データチャンクをそのまま `StreamingResponse` に渡し また、多くの場合、ディスクやネットワークから読み出すため、読み取りはブロッキング(イベントループをブロックし得る)処理になります。 -/// note | 情報 +/// note | 備考 上記の例は例外で、`io.BytesIO` は既にメモリ上にあるため、読み取りが何かをブロックすることはありません。 @@ -98,7 +98,7 @@ FastAPI は各データチャンクをそのまま `StreamingResponse` に渡し /// -イベントループのブロッキングを避けるには、path operation 関数を `async def` ではなく通常の `def` で宣言してください。そうすると FastAPI はその関数をスレッドプールワーカー上で実行し、メインループのブロッキングを避けます。 +イベントループのブロッキングを避けるには、*path operation 関数*を `async def` ではなく通常の `def` で宣言してください。そうすると FastAPI はその関数をスレッドプールワーカー上で実行し、メインループのブロッキングを避けます。 {* ../../docs_src/stream_data/tutorial002_py310.py ln[30:34] hl[31] *} diff --git a/docs/ja/docs/advanced/wsgi.md b/docs/ja/docs/advanced/wsgi.md index bab1ae3bf..40511398d 100644 --- a/docs/ja/docs/advanced/wsgi.md +++ b/docs/ja/docs/advanced/wsgi.md @@ -1,5 +1,6 @@ # WSGI の組み込み - Flask、Django など { #including-wsgi-flask-django-others } + [サブアプリケーション - マウント](sub-applications.md)、[プロキシの背後](behind-a-proxy.md) で見たように、WSGI アプリケーションをマウントできます。 そのために `WSGIMiddleware` を使用して、Flask や Django などの WSGI アプリをラップできます。 diff --git a/docs/ja/docs/alternatives.md b/docs/ja/docs/alternatives.md index b1b3874a7..3b3140ed8 100644 --- a/docs/ja/docs/alternatives.md +++ b/docs/ja/docs/alternatives.md @@ -88,7 +88,7 @@ Requestsは非常にシンプルかつ直感的なデザインで使いやすく response = requests.get("http://example.com/some/url") ``` -対応するFastAPIのAPIのpath operationはこのようになります: +対応するFastAPI側のAPI *path operation* はこのようになります: ```Python hl_lines="1" @app.get("/some/url") @@ -96,12 +96,12 @@ def read_url(): return {"message": "Hello World"} ``` - `requests.get(...)` と`@app.get(...)` には類似点が見受けられます。 +`requests.get(...)` と`@app.get(...)` には類似点が見受けられます。 /// tip | **FastAPI**へ与えたインスピレーション * シンプルで直感的なAPIを持っている点。 -* HTTPメソッド名を直接利用し、単純で直感的である。 +* HTTPメソッド名 (operation) を直接利用し、単純で直感的である。 * 適切なデフォルト値を持ちつつ、強力なカスタマイズ性を持っている。 /// @@ -223,7 +223,7 @@ Flask、Flask-apispec、Marshmallow、Webargsの組み合わせは、**FastAPI** * [https://github.com/tiangolo/full-stack-flask-couchbase](https://github.com/tiangolo/full-stack-flask-couchbase) * [https://github.com/tiangolo/full-stack-flask-couchdb](https://github.com/tiangolo/full-stack-flask-couchdb) -そして、これらのフルスタックジェネレーターは、[**FastAPI** Project Generators](project-generation.md)の元となっていました。 +そして、これらのフルスタックジェネレーターは、[**FastAPI** プロジェクトジェネレーター](project-generation.md)の元となっていました。 /// note | 備考 @@ -247,7 +247,7 @@ Angular 2にインスピレーションを受けた、統合された依存性 パラメータはTypeScriptの型で記述されるので (Pythonの型ヒントに似ています) 、エディタのサポートはとても良いです。 -しかし、TypeScriptのデータはJavaScriptへのコンパイル後には残されないため、バリデーション、シリアライゼーション、ドキュメント化を同時に定義するのに型に頼ることはできません。そのため、バリデーション、シリアライゼーション、スキーマの自動生成を行うためには、多くの場所でデコレータを追加する必要があり、非常に冗長になります。 +しかし、TypeScriptのデータはJavaScriptへのコンパイル後には残されないため、バリデーション、シリアライゼーション、ドキュメント化を同時に定義するのに型に頼ることはできません。このことといくつかの設計上の判断により、バリデーション、シリアライゼーション、スキーマの自動生成を行うためには、多くの場所でデコレータを追加する必要があり、非常に冗長になります。 入れ子になったモデルをうまく扱えません。そのため、リクエストのJSONボディが内部フィールドを持つJSONオブジェクトで、それが順番にネストされたJSONオブジェクトになっている場合、適切にドキュメント化やバリデーションをすることができません。 @@ -333,15 +333,15 @@ OpenAPIやJSON Schemaのような標準に基づいたものではありませ 同じフレームワークを使ってAPIとCLIを作成できる、面白く珍しい機能を持っています。 -以前のPythonの同期型Webフレームワーク標準 (WSGI) をベースにしているため、Websocketなどは扱えませんが、それでも高性能です。 +以前のPythonの同期型Webフレームワーク標準 (WSGI) をベースにしているため、WebSocketなどは扱えませんが、それでも高性能です。 /// note | 備考 -HugはTimothy Crosleyにより作成されました。彼は[`isort`](https://github.com/timothycrosley/isort)など、Pythonのファイル内のインポートの並び替えを自動的におこうなう素晴らしいツールの開発者です。 +HugはTimothy Crosleyにより作成されました。彼は[`isort`](https://github.com/timothycrosley/isort)など、Pythonのファイル内のインポートの並び替えを自動的に行う素晴らしいツールの開発者です。 /// -/// tip | **FastAPI**へ与えたインスピレーション +/// tip | **FastAPI**にインスピレーションを与えたアイデア HugはAPIStarに部分的なインスピレーションを与えており、私が発見した中ではAPIStarと同様に最も期待の持てるツールの一つでした。 @@ -430,7 +430,7 @@ Starletteは、軽量なCtrl + Shift + P、macOS: Cmd + Shift + P)を開き、"Welcome: Open walkthrough..." を選択してから、"Get started with FastAPI" のウォークスルーを選んでください。 +拡張機能の機能に慣れるには、コマンドパレット(Ctrl + Shift + P、macOS: Cmd + Shift + P)を開き、「Welcome: Open walkthrough...」を選択してから、「Get started with FastAPI」のウォークスルーを選んでください。 diff --git a/docs/ja/docs/environment-variables.md b/docs/ja/docs/environment-variables.md index 846f32846..eb20d3a58 100644 --- a/docs/ja/docs/environment-variables.md +++ b/docs/ja/docs/environment-variables.md @@ -163,7 +163,7 @@ Hello World from Python つまり、環境変数からPythonで読み取る**あらゆる値**は **`str`になり**、他の型への変換やバリデーションはコード内で行う必要があります。 -環境変数を使って**アプリケーション設定**を扱う方法については、[高度なユーザーガイド - Settings and Environment Variables](./advanced/settings.md)で詳しく学べます。 +環境変数を使って**アプリケーション設定**を扱う方法については、[高度なユーザーガイド - 設定と環境変数](./advanced/settings.md)で詳しく学べます。 ## `PATH`環境変数 { #path-environment-variable } @@ -285,7 +285,7 @@ $ C:\opt\custompython\bin\python //// -この情報は、[Virtual Environments](virtual-environments.md)について学ぶ際にも役立ちます。 +この情報は、[仮想環境](virtual-environments.md)について学ぶ際にも役立ちます。 ## まとめ { #conclusion } @@ -295,4 +295,4 @@ $ C:\opt\custompython\bin\python 多くの場合、環境変数がどのように役立ち、すぐに適用できるのかはあまり明確ではありません。しかし、開発中のさまざまなシナリオで何度も登場するため、知っておくとよいでしょう。 -例えば、次のセクションの[Virtual Environments](virtual-environments.md)でこの情報が必要になります。 +例えば、次のセクションの[仮想環境](virtual-environments.md)でこの情報が必要になります。 diff --git a/docs/ja/docs/features.md b/docs/ja/docs/features.md index 607a59c4d..930988428 100644 --- a/docs/ja/docs/features.md +++ b/docs/ja/docs/features.md @@ -99,7 +99,7 @@ Python 開発者調査では、[最もよく使われる機能の 1 つが「オ すべてに妥当な **デフォルト** があり、どこでもオプションで構成できます。必要に応じてすべてのパラメータを微調整して、求める API を定義できます。 -しかしデフォルトのままでも、すべて **うまく動きます**。 +しかしデフォルトのままでも、すべて **「うまく動きます」**。 ### 検証 { #validation } @@ -140,7 +140,7 @@ FastAPI には、非常に使いやすく、かつ非常に強力な - +
つまりそのフィールドには **常に値があります**。値が `None`(JSON では `null`)になることがあるだけです。 @@ -72,7 +72,7 @@ 一方、`Item-Output` では、`description` は **必須**(赤いアスタリスクあり)です。
- +
この **Pydantic v2** の機能により、API ドキュメントはより **正確** になり、自動生成されたクライアントや SDK もより正確になります。これにより、より良い **開発者エクスペリエンス** と一貫性が得られます。🎉 diff --git a/docs/ja/docs/index.md b/docs/ja/docs/index.md index 0c588e59c..97ee2f5a4 100644 --- a/docs/ja/docs/index.md +++ b/docs/ja/docs/index.md @@ -49,15 +49,15 @@ FastAPI は、Python の標準である型ヒントに基づいて Python で AP * **簡単**: 簡単に利用・習得できるようにデザインされています。ドキュメントを読む時間を削減します。 * **短い**: コードの重複を最小限にします。各パラメータ宣言から複数の機能を得られます。バグも減ります。 * **堅牢性**: 自動対話型ドキュメントにより、本番環境向けのコードが得られます。 -* **Standards-based**: API のオープンスタンダードに基づいており(そして完全に互換性があります)、[OpenAPI](https://github.com/OAI/OpenAPI-Specification)(以前は Swagger として知られていました)や [JSON Schema](https://json-schema.org/) をサポートします。 +* **標準準拠**: API のオープンスタンダードに基づいており(そして完全に互換性があります)、[OpenAPI](https://github.com/OAI/OpenAPI-Specification)(以前は Swagger として知られていました)や [JSON Schema](https://json-schema.org/) をサポートします。 * 本番アプリケーションを構築している社内開発チームのテストに基づく見積もりです。 -## Sponsors { #sponsors } +## スポンサー { #sponsors } -### Keystone Sponsor { #keystone-sponsor } +### Keystone スポンサー { #keystone-sponsor }
{% for sponsor in sponsors.keystone -%} @@ -65,7 +65,7 @@ FastAPI は、Python の標準である型ヒントに基づいて Python で AP {% endfor -%}
-### Gold Sponsors { #gold-sponsors } +### Gold スポンサー { #gold-sponsors }
{% for sponsor in sponsors.gold -%} @@ -73,7 +73,7 @@ FastAPI は、Python の標準である型ヒントに基づいて Python で AP {% endfor -%}
-### Silver Sponsors { #silver-sponsors } +### Silver スポンサー { #silver-sponsors }
{% for sponsor in sponsors.silver -%} @@ -125,7 +125,7 @@ FastAPI は、Python の標準である型ヒントに基づいて Python で AP
-fastapi dev コマンドについて +fastapi dev コマンドについて... `fastapi dev` コマンドは `main.py` ファイルを自動的に読み取り、その中の **FastAPI** アプリを検出し、[Uvicorn](https://www.uvicorn.dev) を使用してサーバーを起動します。 @@ -471,11 +471,11 @@ item: Item ...に変更し、エディタが属性を自動補完し、その型を知ることを確認してください。 -![editor support](https://fastapi.tiangolo.com/img/vscode-completion.png) +![エディタサポート](https://fastapi.tiangolo.com/img/vscode-completion.png) -より多くの機能を含む、より完全な例については、Tutorial - User Guide を参照してください。 +より多くの機能を含む、より完全な例については、チュートリアル - ユーザーガイド を参照してください。 -**ネタバレ注意**: tutorial - user guide には以下が含まれます。 +**ネタバレ注意**: チュートリアル - ユーザーガイドには以下が含まれます。 * **ヘッダー**、**Cookie**、**フォームフィールド**、**ファイル**など、他のさまざまな場所からの **パラメータ** 宣言。 * `maximum_length` や `regex` のような **検証制約** を設定する方法。 diff --git a/docs/ja/docs/project-generation.md b/docs/ja/docs/project-generation.md index b6550e3ac..829d6a608 100644 --- a/docs/ja/docs/project-generation.md +++ b/docs/ja/docs/project-generation.md @@ -2,7 +2,7 @@ テンプレートは通常、特定のセットアップが含まれていますが、柔軟でカスタマイズできるように設計されています。これにより、プロジェクトの要件に合わせて変更・適応でき、優れた出発点になります。🏁 -このテンプレートを使って開始できます。初期セットアップ、セキュリティ、データベース、いくつかのAPIエンドポイントがすでに用意されています。 +このテンプレートを使って開始できます。初期セットアップの多く、セキュリティ、データベース、いくつかのAPIエンドポイントがすでに用意されています。 GitHubリポジトリ: [Full Stack FastAPI Template](https://github.com/tiangolo/full-stack-fastapi-template) diff --git a/docs/ja/docs/python-types.md b/docs/ja/docs/python-types.md index 2399503fc..e6ff3c25d 100644 --- a/docs/ja/docs/python-types.md +++ b/docs/ja/docs/python-types.md @@ -151,7 +151,7 @@ def some_function(data: Any): 一部の型は、角括弧内で「型パラメータ」を受け取り、内部の型を定義できます。例えば「文字列のリスト」は `list[str]` として宣言します。 -このように型パラメータを取れる型は **Generic types**(ジェネリクス)と呼ばれます。 +このように型パラメータを取れる型は **Generic types** または **Generics**(ジェネリクス)と呼ばれます。 次の組み込み型をジェネリクスとして(角括弧と内部の型で)使えます: @@ -265,7 +265,7 @@ def some_function(data: Any): これは「`one_person` はクラス `Person` の **インスタンス** である」ことを意味します。 -「`one_person` は `Person` という名前の **クラ ス** である」という意味ではありません。 +「`one_person` は `Person` という名前の **クラス** である」という意味ではありません。 ## Pydantic のモデル { #pydantic-models } @@ -343,6 +343,6 @@ Python 自体は、この `Annotated` で何かをするわけではありませ /// note | 備考 -すでにすべてのチュートリアルを終えて、型についての詳細を見るためにこのページに戻ってきた場合は、良いリソースとして [`mypy` の「チートシート`](https://mypy.readthedocs.io/en/latest/cheat_sheet_py3.html) があります。 +すでにすべてのチュートリアルを終えて、型についての詳細を見るためにこのページに戻ってきた場合は、良いリソースとして [`mypy` の「チートシート」](https://mypy.readthedocs.io/en/latest/cheat_sheet_py3.html) があります。 /// diff --git a/docs/ja/docs/tutorial/bigger-applications.md b/docs/ja/docs/tutorial/bigger-applications.md index 9d4239449..51ea7be51 100644 --- a/docs/ja/docs/tutorial/bigger-applications.md +++ b/docs/ja/docs/tutorial/bigger-applications.md @@ -17,16 +17,16 @@ Flask 出身であれば、Flask の Blueprint に相当します。 ``` . ├── app -│   ├── __init__.py -│   ├── main.py -│   ├── dependencies.py -│   └── routers -│   │ ├── __init__.py -│   │ ├── items.py -│   │ └── users.py -│   └── internal -│   ├── __init__.py -│   └── admin.py +│ ├── __init__.py +│ ├── main.py +│ ├── dependencies.py +│ └── routers +│ │ ├── __init__.py +│ │ ├── items.py +│ │ └── users.py +│ └── internal +│ ├── __init__.py +│ └── admin.py ``` /// tip | 豆知識 diff --git a/docs/ja/docs/tutorial/body-nested-models.md b/docs/ja/docs/tutorial/body-nested-models.md index a92df6b7a..d926189ff 100644 --- a/docs/ja/docs/tutorial/body-nested-models.md +++ b/docs/ja/docs/tutorial/body-nested-models.md @@ -1,5 +1,6 @@ # ボディ - ネストされたモデル { #body-nested-models } + **FastAPI** を使用すると、深くネストされた任意のモデルを定義、検証、文書化、使用することができます(Pydanticのおかげです)。 ## リストのフィールド { #list-fields } diff --git a/docs/ja/docs/tutorial/body.md b/docs/ja/docs/tutorial/body.md index 78fcf5f0a..c26198d3b 100644 --- a/docs/ja/docs/tutorial/body.md +++ b/docs/ja/docs/tutorial/body.md @@ -1,5 +1,6 @@ # リクエストボディ { #request-body } + クライアント(例えばブラウザ)からAPIにデータを送信する必要がある場合、**リクエストボディ**として送信します。 **リクエスト**ボディは、クライアントからAPIへ送信されるデータです。**レスポンス**ボディは、APIがクライアントに送信するデータです。 diff --git a/docs/ja/docs/tutorial/debugging.md b/docs/ja/docs/tutorial/debugging.md index a5b0c9016..1a02e1933 100644 --- a/docs/ja/docs/tutorial/debugging.md +++ b/docs/ja/docs/tutorial/debugging.md @@ -99,7 +99,7 @@ from myapp import app --- -Pycharmを使用する場合、次のことが可能です: +PyCharmを使用する場合、次のことが可能です: * 「実行」メニューをオープン。 * オプション「デバッグ...」を選択。 diff --git a/docs/ja/docs/tutorial/dependencies/dependencies-with-yield.md b/docs/ja/docs/tutorial/dependencies/dependencies-with-yield.md index 2c310607c..b4ddfe7f8 100644 --- a/docs/ja/docs/tutorial/dependencies/dependencies-with-yield.md +++ b/docs/ja/docs/tutorial/dependencies/dependencies-with-yield.md @@ -234,6 +234,7 @@ participant operation as Path Operation `yield`を持つ依存関係は、さまざまなユースケースをカバーし、いくつかの問題を修正するために、時間とともに進化してきました。 FastAPIの異なるバージョンで何が変わったのかを知りたい場合は、上級ガイドの[上級の依存関係 - `yield`、`HTTPException`、`except`、バックグラウンドタスクを持つ依存関係](../../advanced/advanced-dependencies.md#dependencies-with-yield-httpexception-except-and-background-tasks)で詳しく読めます。 + ## コンテキストマネージャ { #context-managers } ### 「コンテキストマネージャ」とは { #what-are-context-managers } diff --git a/docs/ja/docs/tutorial/extra-data-types.md b/docs/ja/docs/tutorial/extra-data-types.md index 1bbfeb71e..b63e3fe1a 100644 --- a/docs/ja/docs/tutorial/extra-data-types.md +++ b/docs/ja/docs/tutorial/extra-data-types.md @@ -1,5 +1,6 @@ # 追加データ型 { #extra-data-types } + 今まで、以下のような一般的なデータ型を使用してきました: * `int` diff --git a/docs/ja/docs/tutorial/extra-models.md b/docs/ja/docs/tutorial/extra-models.md index 20883068c..d9548500e 100644 --- a/docs/ja/docs/tutorial/extra-models.md +++ b/docs/ja/docs/tutorial/extra-models.md @@ -208,4 +208,4 @@ some_variable: PlaneItem | CarItem 複数のPydanticモデルを使用し、ケースごとに自由に継承します。 -エンティティが異なる「状態」を持たなければならない場合は、エンティティごとに単一のデータモデルを持つ必要はありません。`password`、`password_hash`、パスワードなしを含む状態を持つユーザー「エンティティ」の場合と同様です。 +エンティティが異なる「状態」を持たなければならない場合は、エンティティごとに単一のデータモデルを持つ必要はありません。`password`、`password_hash`、パスワードなしを含む状態を持つ**ユーザー**「エンティティ」の場合と同様です。 diff --git a/docs/ja/docs/tutorial/first-steps.md b/docs/ja/docs/tutorial/first-steps.md index 75d100871..ae0556d15 100644 --- a/docs/ja/docs/tutorial/first-steps.md +++ b/docs/ja/docs/tutorial/first-steps.md @@ -78,7 +78,7 @@ INFO: Uvicorn running on http://127.0.0.1:8000 (Press CTRL+C to quit) 次に、[http://127.0.0.1:8000/redoc](http://127.0.0.1:8000/redoc)にアクセスします。 -先ほどとは異なる、自動生成された対話的APIドキュメントが表示されます([ReDoc](https://github.com/Rebilly/ReDoc)によって提供): +代替の自動生成ドキュメントが表示されます([ReDoc](https://github.com/Rebilly/ReDoc)によって提供): ![ReDoc](https://fastapi.tiangolo.com/img/index/index-02-redoc-simple.png) @@ -104,7 +104,7 @@ INFO: Uvicorn running on http://127.0.0.1:8000 (Press CTRL+C to quit) #### OpenAPIおよびJSONスキーマ { #openapi-and-json-schema } -OpenAPIはAPIのためのAPIスキーマを定義します。そして、そのスキーマは**JSONデータスキーマ**の標準規格である**JSON Schema**を利用するAPIによって送受されるデータの定義(または「スキーマ」)を含んでいます。 +OpenAPIはAPIのためのAPIスキーマを定義します。そして、そのスキーマには、JSONデータスキーマの標準である**JSON Schema**を使用して、APIによって送受信されるデータの定義(または「スキーマ」)が含まれます。 #### `openapi.json`を確認 { #check-the-openapi-json } @@ -239,6 +239,7 @@ CLIはFastAPIアプリケーションを自動検出してクラウドにデプ ### Step 2: `FastAPI`の「インスタンス」を生成 { #step-2-create-a-fastapi-instance } {* ../../docs_src/first_steps/tutorial001_py310.py hl[3] *} + ここで、`app`変数が`FastAPI`クラスの「インスタンス」になります。 これが、すべてのAPIを作成するための主要なポイントになります。 diff --git a/docs/ja/docs/tutorial/handling-errors.md b/docs/ja/docs/tutorial/handling-errors.md index 8d0190cb0..491b72da2 100644 --- a/docs/ja/docs/tutorial/handling-errors.md +++ b/docs/ja/docs/tutorial/handling-errors.md @@ -1,5 +1,6 @@ # エラーハンドリング { #handling-errors } + APIを使用しているクライアントにエラーを通知する必要がある状況はたくさんあります。 このクライアントは、フロントエンドを持つブラウザ、誰かのコード、IoTデバイスなどが考えられます。 diff --git a/docs/ja/docs/tutorial/index.md b/docs/ja/docs/tutorial/index.md index 8182c92ae..42b0eb523 100644 --- a/docs/ja/docs/tutorial/index.md +++ b/docs/ja/docs/tutorial/index.md @@ -1,5 +1,6 @@ # チュートリアル - ユーザーガイド { #tutorial-user-guide } + このチュートリアルでは、**FastAPI**のほとんどの機能を使う方法を段階的に紹介します。 各セクションは前のセクションを踏まえた内容になっています。しかし、トピックごとに分割されているので、特定のAPIのニーズを満たすために、任意の特定のトピックに直接進めるようになっています。 diff --git a/docs/ja/docs/tutorial/metadata.md b/docs/ja/docs/tutorial/metadata.md index 6a426d530..0f5f0cb6c 100644 --- a/docs/ja/docs/tutorial/metadata.md +++ b/docs/ja/docs/tutorial/metadata.md @@ -11,10 +11,10 @@ OpenAPI仕様および自動APIドキュメントUIで使用される次のフ | `title` | `str` | APIのタイトルです。 | | `summary` | `str` | APIの短い要約です。 OpenAPI 3.1.0、FastAPI 0.99.0 以降で利用できます。 | | `description` | `str` | APIの短い説明です。Markdownを使用できます。 | -| `version` | `string` | APIのバージョンです。これはOpenAPIのバージョンではなく、あなた自身のアプリケーションのバージョンです。たとえば `2.5.0` です。 | +| `version` | `str` | APIのバージョンです。これはOpenAPIのバージョンではなく、あなた自身のアプリケーションのバージョンです。たとえば `2.5.0` です。 | | `terms_of_service` | `str` | APIの利用規約へのURLです。指定する場合、URLである必要があります。 | -| `contact` | `dict` | 公開されるAPIの連絡先情報です。複数のフィールドを含められます。
contact fields
ParameterTypeDescription
namestr連絡先の個人/組織を識別する名前です。
urlstr連絡先情報を指すURLです。URL形式である必要があります。
emailstr連絡先の個人/組織のメールアドレスです。メールアドレス形式である必要があります。
| -| `license_info` | `dict` | 公開されるAPIのライセンス情報です。複数のフィールドを含められます。
license_info fields
ParameterTypeDescription
namestr必須license_info が設定されている場合)。APIに使用されるライセンス名です。
identifierstrAPIの [SPDX](https://spdx.org/licenses/) ライセンス式です。identifier フィールドは url フィールドと同時に指定できません。 OpenAPI 3.1.0、FastAPI 0.99.0 以降で利用できます。
urlstrAPIに使用されるライセンスへのURLです。URL形式である必要があります。
| +| `contact` | `dict` | 公開されるAPIの連絡先情報です。複数のフィールドを含められます。
contact のフィールド
パラメータ説明
namestr連絡先の個人/組織を識別する名前です。
urlstr連絡先情報を指すURLです。URL形式である必要があります。
emailstr連絡先の個人/組織のメールアドレスです。メールアドレス形式である必要があります。
| +| `license_info` | `dict` | 公開されるAPIのライセンス情報です。複数のフィールドを含められます。
license_info のフィールド
パラメータ説明
namestr必須license_info が設定されている場合)。APIに使用されるライセンス名です。
identifierstrAPIの [SPDX](https://spdx.org/licenses/) ライセンス式です。identifier フィールドは url フィールドと同時に指定できません。 OpenAPI 3.1.0、FastAPI 0.99.0 以降で利用できます。
urlstrAPIに使用されるライセンスへのURLです。URL形式である必要があります。
| 以下のように設定できます: diff --git a/docs/ja/docs/tutorial/path-operation-configuration.md b/docs/ja/docs/tutorial/path-operation-configuration.md index a5f34128a..05bf9208e 100644 --- a/docs/ja/docs/tutorial/path-operation-configuration.md +++ b/docs/ja/docs/tutorial/path-operation-configuration.md @@ -1,5 +1,6 @@ # Path Operationの設定 { #path-operation-configuration } + *path operationデコレータ*を設定するためのパラメータがいくつかあります。 /// warning | 注意 diff --git a/docs/ja/docs/tutorial/query-params-str-validations.md b/docs/ja/docs/tutorial/query-params-str-validations.md index a113cb4a7..38d2b5c68 100644 --- a/docs/ja/docs/tutorial/query-params-str-validations.md +++ b/docs/ja/docs/tutorial/query-params-str-validations.md @@ -41,7 +41,7 @@ FastAPI はバージョン 0.95.0 で `Annotated` のサポートを追加し( ## `q` パラメータの型で `Annotated` を使う { #use-annotated-in-the-type-for-the-q-parameter } -以前、[Python Types Intro](../python-types.md#type-hints-with-metadata-annotations) で `Annotated` を使ってパラメータにメタデータを追加できると説明したことを覚えていますか? +以前、[Python 型入門](../python-types.md#type-hints-with-metadata-annotations) で `Annotated` を使ってパラメータにメタデータを追加できると説明したことを覚えていますか? いよいよ FastAPI で使うときです。 🚀 @@ -242,7 +242,7 @@ q: Annotated[str | None, Query(min_length=3)] = None http://localhost:8000/items/?q=foo&q=bar ``` -*path operation function* 内の *function parameter* `q` で、複数の `q` *query parameters'* 値(`foo` と `bar`)を Python の `list` として受け取ります。 +*path operation function* 内の *function parameter* `q` で、複数の `q` *クエリパラメータ*の値(`foo` と `bar`)を Python の `list` として受け取ります。 そのため、このURLのレスポンスは以下のようになります: diff --git a/docs/ja/docs/tutorial/query-params.md b/docs/ja/docs/tutorial/query-params.md index 24320cc77..2bca43a95 100644 --- a/docs/ja/docs/tutorial/query-params.md +++ b/docs/ja/docs/tutorial/query-params.md @@ -1,5 +1,6 @@ # クエリパラメータ { #query-parameters } + パスパラメータではない関数パラメータを宣言すると、それらは自動的に「クエリ」パラメータとして解釈されます。 {* ../../docs_src/query_params/tutorial001_py310.py hl[9] *} diff --git a/docs/ja/docs/tutorial/request-files.md b/docs/ja/docs/tutorial/request-files.md index 82bafb776..f4bd2314b 100644 --- a/docs/ja/docs/tutorial/request-files.md +++ b/docs/ja/docs/tutorial/request-files.md @@ -1,5 +1,6 @@ # リクエストファイル { #request-files } + `File` を使って、クライアントがアップロードするファイルを定義できます。 /// note | 備考 diff --git a/docs/ja/docs/tutorial/request-forms.md b/docs/ja/docs/tutorial/request-forms.md index 022f13208..0478a5439 100644 --- a/docs/ja/docs/tutorial/request-forms.md +++ b/docs/ja/docs/tutorial/request-forms.md @@ -70,4 +70,4 @@ HTMLフォーム(`
`)がサーバにデータを送信する方 ## まとめ { #recap } -フォームデータの入力パラメータを宣言するには、`Form`を使用する。 +フォームデータの入力パラメータを宣言するには、`Form`を使用します。 diff --git a/docs/ja/docs/tutorial/response-status-code.md b/docs/ja/docs/tutorial/response-status-code.md index a04add113..e4239e11a 100644 --- a/docs/ja/docs/tutorial/response-status-code.md +++ b/docs/ja/docs/tutorial/response-status-code.md @@ -1,5 +1,6 @@ # レスポンスステータスコード { #response-status-code } + レスポンスモデルを指定するのと同じ方法で、レスポンスに使用されるHTTPステータスコードを以下の*path operations*のいずれかの`status_code`パラメータで宣言することもできます。 * `@app.get()` diff --git a/docs/ja/docs/tutorial/schema-extra-example.md b/docs/ja/docs/tutorial/schema-extra-example.md index 742106037..e44e2471d 100644 --- a/docs/ja/docs/tutorial/schema-extra-example.md +++ b/docs/ja/docs/tutorial/schema-extra-example.md @@ -1,5 +1,6 @@ # リクエストのExampleデータの宣言 { #declare-request-example-data } + アプリが受け取れるデータの例を宣言できます。 ここでは、それを行ういくつかの方法を紹介します。 diff --git a/docs/ja/docs/tutorial/security/first-steps.md b/docs/ja/docs/tutorial/security/first-steps.md index 386adbed8..e5d7c58b5 100644 --- a/docs/ja/docs/tutorial/security/first-steps.md +++ b/docs/ja/docs/tutorial/security/first-steps.md @@ -109,7 +109,7 @@ OAuth2は、バックエンドやAPIがユーザーを認証するサーバー * ユーザーがフロントエンドでクリックして、フロントエンドのWebアプリの別のセクションに移動します。 * フロントエンドはAPIからさらにデータを取得する必要があります。 * しかし、特定のエンドポイントの認証が必要です。 - * したがって、APIで認証するため、HTTPヘッダー`Authorization`に`Bearer`の文字列とトークンを加えた値を送信します。 + * したがって、APIで認証するため、HTTPヘッダー`Authorization`に`Bearer `の文字列とトークンを加えた値を送信します。 * トークンに`foobar`が含まれている場合、`Authorization`ヘッダーの内容は次のようになります: `Bearer foobar`。 ## **FastAPI**の`OAuth2PasswordBearer` { #fastapis-oauth2passwordbearer } @@ -178,7 +178,7 @@ oauth2_scheme(some, parameters) /// note | 技術詳細 -**FastAPI**は、`OAuth2PasswordBearer` クラス (依存関係で宣言されている) を使用してOpenAPIのセキュリティスキームを定義できることを知っています。これは`fastapi.security.oauth2.OAuth2`、`fastapi.security.base.SecurityBase`を継承しているからです。 +**FastAPI**は、`OAuth2PasswordBearer` クラス (依存関係で宣言されている) を使用してOpenAPIのセキュリティスキームを定義できることを知っています。これは、このクラスが`fastapi.security.oauth2.OAuth2`を継承しており、さらにそれが`fastapi.security.base.SecurityBase`を継承しているからです。 OpenAPIと統合するセキュリティユーティリティ (および自動APIドキュメント) はすべて`SecurityBase`を継承しています。それにより、**FastAPI**はそれらをOpenAPIに統合する方法を知ることができます。 diff --git a/docs/ja/docs/tutorial/security/get-current-user.md b/docs/ja/docs/tutorial/security/get-current-user.md index 1e77c9f65..f8e4295bf 100644 --- a/docs/ja/docs/tutorial/security/get-current-user.md +++ b/docs/ja/docs/tutorial/security/get-current-user.md @@ -14,7 +14,7 @@ ボディを宣言するのにPydanticを使用するのと同じやり方で、Pydanticを別のどんなところでも使うことができます: -{* ../../docs_src/security/tutorial002_an_py310.py hl[5,12:6] *} +{* ../../docs_src/security/tutorial002_an_py310.py hl[5,12:16] *} ## 依存関係 `get_current_user` を作成 { #create-a-get-current-user-dependency } diff --git a/docs/ja/docs/tutorial/security/oauth2-jwt.md b/docs/ja/docs/tutorial/security/oauth2-jwt.md index 7e41326e3..40cefad9d 100644 --- a/docs/ja/docs/tutorial/security/oauth2-jwt.md +++ b/docs/ja/docs/tutorial/security/oauth2-jwt.md @@ -1,6 +1,6 @@ # パスワード(およびハッシュ化)によるOAuth2、JWTトークンによるBearer { #oauth2-with-password-and-hashing-bearer-with-jwt-tokens } -これでセキュリティの流れが全てわかったので、JWTトークンと安全なパスワードのハッシュ化を使用して、実際にアプリケーションを安全にしてみましょう。 +これでセキュリティの流れが全てわかったので、JWTトークンと安全なパスワードのハッシュ化を使用して、実際にアプリケーションを安全にしてみましょう。 このコードは、アプリケーションで実際に使用したり、パスワードハッシュをデータベースに保存するといった用途に利用できます。 @@ -46,7 +46,7 @@ $ pip install pyjwt RSAやECDSAのようなデジタル署名アルゴリズムを使用する予定がある場合は、cryptographyライブラリの依存関係`pyjwt[crypto]`をインストールしてください。 -詳細は[PyJWT Installation docs](https://pyjwt.readthedocs.io/en/latest/installation.html)で確認できます。 +詳細は[PyJWT インストールに関するドキュメント](https://pyjwt.readthedocs.io/en/latest/installation.html)で確認できます。 /// @@ -120,7 +120,7 @@ pwdlibはbcryptハッシュアルゴリズムもサポートしていますが `authenticate_user` がデータベースに存在しないユーザー名で呼び出された場合でも、ダミーのハッシュを使って `verify_password` を実行します。 -これにより、ユーザー名が有効かどうかに関わらずエンドポイントの応答時間がおおよそ同じになり、既存のユーザー名を列挙するために悪用されうる「タイミング攻撃」を防止できます。 +これにより、ユーザー名が有効かどうかに関わらずエンドポイントの応答時間がおおよそ同じになり、既存のユーザー名を列挙するために悪用されうる**タイミング攻撃**を防止できます。 /// note | 備考 @@ -215,7 +215,7 @@ Password: `secret` /// tip | 豆知識 -コードのどこにも平文のパスワード"`secret`"はなく、ハッシュ化されたものしかないことを確認してください。 +コードのどこにも平文のパスワード「`secret`」はなく、ハッシュ化されたものしかないことを確認してください。 /// diff --git a/docs/ja/docs/tutorial/security/simple-oauth2.md b/docs/ja/docs/tutorial/security/simple-oauth2.md index 9e9487d86..84f6101b7 100644 --- a/docs/ja/docs/tutorial/security/simple-oauth2.md +++ b/docs/ja/docs/tutorial/security/simple-oauth2.md @@ -14,7 +14,7 @@ OAuth2 では、「password flow」(ここで使用するフロー)を使う また、データベースのモデルでは任意の別名を使って構いません。 -しかし、ログイン用の path operation では、仕様との互換性を保つ(たとえば組み込みのAPIドキュメントシステムを使えるようにする)ために、これらの名前を使う必要があります。 +しかし、ログイン用の *path operation* では、仕様との互換性を保つ(たとえば組み込みのAPIドキュメントシステムを使えるようにする)ために、これらの名前を使う必要があります。 また、仕様では `username` と `password` はフォームデータとして送らなければならない(つまり、ここではJSONは使わない)ことも定められています。 @@ -50,7 +50,7 @@ OAuth2 にとっては単なる文字列です。 ### `OAuth2PasswordRequestForm` { #oauth2passwordrequestform } -まず、`OAuth2PasswordRequestForm` をインポートし、`/token` の path operation に `Depends` で依存関係として使います: +まず、`OAuth2PasswordRequestForm` をインポートし、`/token` の *path operation* に `Depends` で依存関係として使います: {* ../../docs_src/security/tutorial003_an_py310.py hl[4,78] *} @@ -132,7 +132,7 @@ OAuth2 の仕様では、固定値 `password` を持つフィールド `grant_ty `UserInDB(**user_dict)` は次を意味します: -`user_dict` のキーと値を、そのままキーワード引数として渡します。つまり次と同等です: +*`user_dict` のキーと値を、そのままキーワード引数として渡します。つまり次と同等です:* ```Python UserInDB( @@ -146,7 +146,7 @@ UserInDB( /// note | 備考 -`**user_dict` のより完全な解説は、[**追加モデル**のドキュメント](../extra-models.md#about-user-in-dict)を参照してください。 +`**user_dict` のより完全な解説は、[**追加モデル**のドキュメント](../extra-models.md#about-user-in-model-dump)を参照してください。 /// @@ -188,7 +188,7 @@ UserInDB( アクティブなユーザーの場合にのみ `current_user` を取得したいとします。 -そこで、`get_current_active_user` を依存関係として利用する追加の依存関係 `get_current_active_user` を作成します。 +そこで、今度は `get_current_user` を依存関係として利用する追加の依存関係 `get_current_active_user` を作成します。 これら2つの依存関係は、ユーザーが存在しない、または非アクティブである場合に、HTTPエラーを返すだけです。 @@ -236,7 +236,7 @@ Password: `secret` ### 自分のユーザーデータを取得 { #get-your-own-user-data } -`GET` の path `/users/me` を使います。 +今度は path `/users/me` で operation `GET` を使います。 次のようなユーザーデータが取得できます: @@ -268,7 +268,7 @@ User: `alice` Password: `secret2` -そして `GET` の path `/users/me` を使います。 +そして path `/users/me` で operation `GET` を使ってみます。 次のような「Inactive user」エラーになります: @@ -284,6 +284,6 @@ Password: `secret2` これらの道具を使えば、任意のデータベース、任意のユーザー/データモデルと互換性のあるセキュリティシステムを構築できます。 -ただし、実際にはまだ「安全」ではありません。 +唯一欠けている点は、実際にはまだ「安全」ではないことです。 次の章では、安全なパスワードハッシュライブラリと JWT トークンの使い方を見ていきます。 diff --git a/docs/ja/docs/tutorial/sql-databases.md b/docs/ja/docs/tutorial/sql-databases.md index 13c71fdb2..190eedbbb 100644 --- a/docs/ja/docs/tutorial/sql-databases.md +++ b/docs/ja/docs/tutorial/sql-databases.md @@ -1,5 +1,6 @@ # SQL(リレーショナル)データベース { #sql-relational-databases } + FastAPI は SQL(リレーショナル)データベースの使用を必須にはしません。必要であれば、任意のデータベースを使用できます。 ここでは [SQLModel](https://sqlmodel.tiangolo.com/) を使った例を見ていきます。 diff --git a/docs/ja/docs/tutorial/static-files.md b/docs/ja/docs/tutorial/static-files.md index 81f281c2e..fd0d47e9c 100644 --- a/docs/ja/docs/tutorial/static-files.md +++ b/docs/ja/docs/tutorial/static-files.md @@ -2,6 +2,14 @@ `StaticFiles` を使用して、ディレクトリから静的ファイルを自動的に提供できます。 +/// tip | 豆知識 + +フロントエンドをホストする必要がある場合は、代わりに `app.frontend()` を使用してください。詳しくは [フロントエンド](frontend.md) を読んでください。 + +`app.frontend()` は内部で `StaticFiles` を使用しており、client-side routing の処理など、フロントエンド向けの追加の利点がいくつかあります。 + +/// + ## `StaticFiles` の使用 { #use-staticfiles } * `StaticFiles` をインポート。 diff --git a/docs/ja/docs/tutorial/testing.md b/docs/ja/docs/tutorial/testing.md index 57dcd86c9..e82fc261e 100644 --- a/docs/ja/docs/tutorial/testing.md +++ b/docs/ja/docs/tutorial/testing.md @@ -22,7 +22,7 @@ $ pip install httpx `TestClient` をインポートします。 -`TestClient` を作成し、**FastAPI** に渡します。 +**FastAPI** アプリケーションを渡して `TestClient` を作成します。 `test_` から始まる名前の関数を作成します (これは `pytest` の標準的なコンベンションです)。 @@ -52,7 +52,7 @@ $ pip install httpx /// tip | 豆知識 -FastAPIアプリケーションへのリクエストの送信とは別に、テストで `async` 関数 (非同期データベース関数など) を呼び出したい場合は、高度なチュートリアルの[Async Tests](../advanced/async-tests.md) を参照してください。 +FastAPIアプリケーションへのリクエストの送信とは別に、テストで `async` 関数 (非同期データベース関数など) を呼び出したい場合は、高度なチュートリアルの[非同期テスト](../advanced/async-tests.md) を参照してください。 /// @@ -64,7 +64,7 @@ FastAPIアプリケーションへのリクエストの送信とは別に、テ ### **FastAPI** アプリファイル { #fastapi-app-file } -[Bigger Applications](bigger-applications.md) で説明されている、次のようなファイル構成があるとします: +[大規模なアプリケーション](bigger-applications.md) で説明されている、次のようなファイル構成があるとします: ``` . @@ -113,7 +113,7 @@ FastAPIアプリケーションへのリクエストの送信とは別に、テ │   └── test_main.py ``` -ここで、**FastAPI** アプリがある `main.py` ファイルには、他の path operation があります。 +ここで、**FastAPI** アプリがある `main.py` ファイルには、他の **path operations** がいくつかあります。 エラーを返す可能性のある `GET` オペレーションがあります。 diff --git a/docs/ja/docs/virtual-environments.md b/docs/ja/docs/virtual-environments.md index 633825b64..19325fa1d 100644 --- a/docs/ja/docs/virtual-environments.md +++ b/docs/ja/docs/virtual-environments.md @@ -35,15 +35,15 @@ Pythonプロジェクトの作業では、**仮想環境**(または類似の
```console -// Go to the home directory +// ホームディレクトリに移動 $ cd -// Create a directory for all your code projects +// すべてのコードプロジェクト用のディレクトリを作成 $ mkdir code -// Enter into that code directory +// その code ディレクトリに入る $ cd code -// Create a directory for this project +// このプロジェクト用のディレクトリを作成 $ mkdir awesome-project -// Enter into that project directory +// そのプロジェクトディレクトリに入る $ cd awesome-project ``` From c80355b65eda4e636aff4463d159c1bdc2029982 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebasti=C3=A1n=20Ram=C3=ADrez?= Date: Wed, 1 Jul 2026 15:59:24 +0200 Subject: [PATCH 377/462] =?UTF-8?q?=F0=9F=8C=90=20Update=20translations=20?= =?UTF-8?q?for=20zh-hant=20(update-outdated)=20(#15896)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: github-actions[bot] Co-authored-by: Yurii Motov --- docs/zh-hant/docs/_llm-test.md | 36 ++-- .../docs/advanced/additional-status-codes.md | 1 + .../docs/advanced/advanced-dependencies.md | 1 + docs/zh-hant/docs/advanced/dataclasses.md | 6 +- docs/zh-hant/docs/advanced/events.md | 1 + .../zh-hant/docs/advanced/generate-clients.md | 18 +- .../docs/advanced/json-base64-bytes.md | 8 +- .../docs/advanced/openapi-callbacks.md | 6 +- .../advanced/response-change-status-code.md | 1 + .../zh-hant/docs/advanced/response-cookies.md | 10 +- .../zh-hant/docs/advanced/response-headers.md | 6 +- .../docs/advanced/security/oauth2-scopes.md | 76 ++++----- docs/zh-hant/docs/advanced/settings.md | 6 +- docs/zh-hant/docs/advanced/stream-data.md | 10 +- docs/zh-hant/docs/advanced/wsgi.md | 1 + docs/zh-hant/docs/alternatives.md | 4 +- docs/zh-hant/docs/async.md | 160 +++++++++--------- docs/zh-hant/docs/deployment/cloud.md | 2 +- docs/zh-hant/docs/deployment/concepts.md | 1 + docs/zh-hant/docs/deployment/docker.md | 6 +- docs/zh-hant/docs/deployment/https.md | 1 + docs/zh-hant/docs/deployment/manually.md | 12 +- docs/zh-hant/docs/editor-support.md | 1 + docs/zh-hant/docs/environment-variables.md | 1 + docs/zh-hant/docs/features.md | 96 ++++++----- docs/zh-hant/docs/help-fastapi.md | 1 + .../docs/how-to/configure-swagger-ui.md | 4 +- .../docs/how-to/custom-request-and-route.md | 2 +- docs/zh-hant/docs/how-to/graphql.md | 20 +-- ...migrate-from-pydantic-v1-to-pydantic-v2.md | 20 ++- .../docs/how-to/separate-openapi-schemas.md | 36 ++-- docs/zh-hant/docs/index.md | 6 +- docs/zh-hant/docs/project-generation.md | 1 + docs/zh-hant/docs/python-types.md | 38 ++--- .../docs/tutorial/bigger-applications.md | 22 +-- .../docs/tutorial/body-nested-models.md | 1 + docs/zh-hant/docs/tutorial/body.md | 2 + docs/zh-hant/docs/tutorial/debugging.md | 1 + .../dependencies/dependencies-with-yield.md | 1 + .../zh-hant/docs/tutorial/extra-data-types.md | 1 + docs/zh-hant/docs/tutorial/extra-models.md | 14 +- docs/zh-hant/docs/tutorial/first-steps.md | 30 ++-- docs/zh-hant/docs/tutorial/handling-errors.md | 4 +- docs/zh-hant/docs/tutorial/index.md | 2 +- docs/zh-hant/docs/tutorial/metadata.md | 12 +- .../tutorial/path-operation-configuration.md | 1 + .../tutorial/query-params-str-validations.md | 85 +++++----- docs/zh-hant/docs/tutorial/query-params.md | 5 +- docs/zh-hant/docs/tutorial/request-files.md | 1 + docs/zh-hant/docs/tutorial/request-forms.md | 1 + .../docs/tutorial/response-status-code.md | 1 + .../docs/tutorial/schema-extra-example.md | 4 +- .../docs/tutorial/security/first-steps.md | 44 ++--- .../tutorial/security/get-current-user.md | 2 +- .../docs/tutorial/security/oauth2-jwt.md | 4 +- .../docs/tutorial/security/simple-oauth2.md | 4 +- docs/zh-hant/docs/tutorial/sql-databases.md | 122 ++++++------- docs/zh-hant/docs/tutorial/static-files.md | 8 + docs/zh-hant/docs/tutorial/testing.md | 12 +- docs/zh-hant/docs/virtual-environments.md | 10 +- 60 files changed, 515 insertions(+), 478 deletions(-) diff --git a/docs/zh-hant/docs/_llm-test.md b/docs/zh-hant/docs/_llm-test.md index 0ea674cd8..09efe8377 100644 --- a/docs/zh-hant/docs/_llm-test.md +++ b/docs/zh-hant/docs/_llm-test.md @@ -35,7 +35,7 @@ //// tab | 測試 -Yesterday, my friend wrote: "If you spell incorrectly correctly, you have spelled it incorrectly". To which I answered: "Correct, but 'incorrectly' is incorrectly not '"incorrectly"'". +昨天,我的朋友寫道:「如果你正確地拼寫 incorrectly,你就把它拼成 incorrectly 了」。我回答:「正確,但 'incorrectly' 錯在它不是 '"incorrectly"'"」。 /// note | 注意 @@ -59,7 +59,7 @@ LLM 很可能會把這段翻譯錯。重點只在於重新翻譯時是否能保 `pip install "foo[bar]"` -程式碼片段中字串常值的例子:"this"、'that'。 +程式碼片段中字串常值的例子:`"this"`、`'that'`。 較難的程式碼片段中字串常值例子:`f"I like {'oranges' if orange else "apples"}"` @@ -125,23 +125,23 @@ works(foo="bar") # 這可以運作 🎉 //// tab | 測試 /// note | 注意 -Some text +一些文字 /// /// note | 技術細節 -Some text +一些文字 /// /// tip | 提示 -Some text +一些文字 /// /// warning | 警告 -Some text +一些文字 /// /// danger | 危險 -Some text +一些文字 /// //// @@ -222,15 +222,15 @@ Some text ### 開發網頁應用程式 - 教學 { #develop-a-webapp-a-tutorial } -Hello. +你好。 ### 型別提示與註解 { #type-hints-and-annotations } -Hello again. +再次你好。 ### 超類與子類別 { #super-and-subclasses } -Hello again. +再次你好。 //// @@ -248,15 +248,15 @@ Hello again. //// tab | 測試 -* you -* your +* 你 +* 你的 -* e.g. -* etc. +* 例如 +* 等等 -* `foo` as an `int` -* `bar` as a `str` -* `baz` as a `list` +* `foo` 作為 `int` +* `bar` 作為 `str` +* `baz` 作為 `list` * 教學 - 使用者指南 * 進階使用者指南 @@ -283,7 +283,7 @@ Hello again. * 即時 * 標準 * 預設 -* 区分大小寫 +* 區分大小寫 * 不區分大小寫 * 提供應用程式服務 diff --git a/docs/zh-hant/docs/advanced/additional-status-codes.md b/docs/zh-hant/docs/advanced/additional-status-codes.md index 0e5941a8d..bbb4f57dc 100644 --- a/docs/zh-hant/docs/advanced/additional-status-codes.md +++ b/docs/zh-hant/docs/advanced/additional-status-codes.md @@ -1,5 +1,6 @@ # 額外的狀態碼 { #additional-status-codes } + 在預設情況下,**FastAPI** 會使用 `JSONResponse` 傳回回應,並把你從你的「路徑操作(path operation)」回傳的內容放進該 `JSONResponse` 中。 它會使用預設的狀態碼,或你在路徑操作中設定的狀態碼。 diff --git a/docs/zh-hant/docs/advanced/advanced-dependencies.md b/docs/zh-hant/docs/advanced/advanced-dependencies.md index 880d92ce9..92dabdaf1 100644 --- a/docs/zh-hant/docs/advanced/advanced-dependencies.md +++ b/docs/zh-hant/docs/advanced/advanced-dependencies.md @@ -1,5 +1,6 @@ # 進階相依 { #advanced-dependencies } + ## 參數化的相依 { #parameterized-dependencies } 到目前為止看到的相依都是固定的函式或類別。 diff --git a/docs/zh-hant/docs/advanced/dataclasses.md b/docs/zh-hant/docs/advanced/dataclasses.md index 0a673889e..64ba7dde2 100644 --- a/docs/zh-hant/docs/advanced/dataclasses.md +++ b/docs/zh-hant/docs/advanced/dataclasses.md @@ -63,12 +63,12 @@ FastAPI 建立在 **Pydantic** 之上,我之前示範過如何使用 Pydantic 7. 這裡 `response_model` 使用的是「`Author` dataclass 的清單」這種型別註記。 同樣地,你可以把 `dataclasses` 與標準型別註記組合使用。 -8. 注意這個「路徑操作函式」使用的是一般的 `def` 而非 `async def`。 +8. 注意這個*路徑操作函式*使用的是一般的 `def` 而非 `async def`。 一如往常,在 FastAPI 中你可以視需要混用 `def` 與 `async def`。 - 如果需要複習何時用哪個,請參考文件中關於 [`async` 與 `await`](../async.md#in-a-hurry) 的章節「In a hurry?」。 -9. 這個「路徑操作函式」回傳的不是 dataclass(雖然也可以),而是一個包含內部資料的字典清單。 + 如果需要複習何時用哪個,請參考文件中關於 [`async` 與 `await`](../async.md#in-a-hurry) 的章節 _「趕時間?」_。 +9. 這個*路徑操作函式*回傳的不是 dataclass(雖然也可以),而是一個包含內部資料的字典清單。 FastAPI 會使用 `response_model` 參數(其中包含 dataclass)來轉換回應。 diff --git a/docs/zh-hant/docs/advanced/events.md b/docs/zh-hant/docs/advanced/events.md index 60014a90a..e132d9f3d 100644 --- a/docs/zh-hant/docs/advanced/events.md +++ b/docs/zh-hant/docs/advanced/events.md @@ -1,5 +1,6 @@ # 生命週期事件 { #lifespan-events } + 你可以定義在應用程式**啟動**之前要執行的邏輯(程式碼)。也就是說,這段程式碼會在應用開始接收請求**之前**、**只執行一次**。 同樣地,你也可以定義在應用程式**關閉**時要執行的邏輯(程式碼)。在這種情況下,這段程式碼會在處理了**許多請求**之後、**只執行一次**。 diff --git a/docs/zh-hant/docs/advanced/generate-clients.md b/docs/zh-hant/docs/advanced/generate-clients.md index a56877ccd..cc7a6865a 100644 --- a/docs/zh-hant/docs/advanced/generate-clients.md +++ b/docs/zh-hant/docs/advanced/generate-clients.md @@ -20,20 +20,6 @@ FastAPI 會自動產生 **OpenAPI 3.1** 規格,因此你使用的任何工具 /// -## 來自 FastAPI 贊助商的 SDK 產生器 { #sdk-generators-from-fastapi-sponsors } - -本節重點介紹由贊助 FastAPI 的公司提供的**創投支持**與**公司維運**的解決方案。這些產品在高品質的自動產生 SDK 之外,還提供**額外功能**與**整合**。 - -透過 ✨ [**贊助 FastAPI**](../help-fastapi.md#sponsor-the-author) ✨,這些公司幫助確保框架與其**生態系**維持健康且**永續**。 - -他們的贊助也展現對 FastAPI **社群**(你)的高度承諾,不僅關心提供**優良服務**,也支持 **FastAPI** 作為一個**穩健且蓬勃的框架**。🙇 - -例如,你可以嘗試: - -* [Stainless](https://www.stainless.com/?utm_source=fastapi&utm_medium=referral) - -其中有些方案也可能是開源或提供免費方案,讓你不需財務承諾就能試用。其他商業的 SDK 產生器也不少,你可以在網路上找到。🤓 - ## 建立 TypeScript SDK { #create-a-typescript-sdk } 先從一個簡單的 FastAPI 應用開始: @@ -56,7 +42,7 @@ FastAPI 會自動產生 **OpenAPI 3.1** 規格,因此你使用的任何工具 ### Hey API { #hey-api } -當我們有含模型的 FastAPI 應用後,就能用 Hey API 來產生 TypeScript 用戶端。最快的方法是透過 npx: +當我們有含模型的 FastAPI 應用後,就能用 Hey API 來產生 TypeScript 用戶端。最快的方法是透過 npx。 ```sh npx @hey-api/openapi-ts -i http://localhost:8000/openapi.json -o src/client @@ -194,7 +180,7 @@ npx @hey-api/openapi-ts -i ./openapi.json -o src/client 使用自動產生的用戶端時,你會得到以下項目的**自動完成**: * 方法 -* 本文中的請求有效載荷、查詢參數等 +* Body 中的請求有效載荷、查詢參數等 * 回應的有效載荷 你也會對所有內容獲得**行內錯誤**提示。 diff --git a/docs/zh-hant/docs/advanced/json-base64-bytes.md b/docs/zh-hant/docs/advanced/json-base64-bytes.md index 9f1ecfa2e..bdf146b8c 100644 --- a/docs/zh-hant/docs/advanced/json-base64-bytes.md +++ b/docs/zh-hant/docs/advanced/json-base64-bytes.md @@ -4,7 +4,7 @@ ## Base64 與檔案 { #base64-vs-files } -請先考慮是否能用 [請求檔案](../tutorial/request-files.md) 來上傳二進位資料,並用 [自訂回應 - FileResponse](./custom-response.md#fileresponse--fileresponse-) 來傳送二進位資料,而不是把它們編碼進 JSON。 +請先考慮是否能用 [請求檔案](../tutorial/request-files.md) 來上傳二進位資料,並用 [自訂回應 - FileResponse](./custom-response.md#fileresponse) 來傳送二進位資料,而不是把它們編碼進 JSON。 JSON 只能包含 UTF-8 編碼的字串,因此無法直接包含原始位元組。 @@ -14,7 +14,7 @@ Base64 可以把二進位資料編碼成字串,但為此會使用比原始二 ## Pydantic `bytes` { #pydantic-bytes } -你可以宣告含有 `bytes` 欄位的 Pydantic 模型,並在模型設定中使用 `val_json_bytes`,使其在驗證輸入的 JSON 資料時使用 base64;在驗證過程中,它會將 base64 字串解碼為位元組。 +你可以宣告含有 `bytes` 欄位的 Pydantic 模型,並在模型設定中使用 `val_json_bytes`,使其在*驗證*輸入的 JSON 資料時使用 base64;在驗證過程中,它會將 base64 字串解碼為位元組。 {* ../../docs_src/json_base64_bytes/tutorial001_py310.py ln[1:9,29:35] hl[9] *} @@ -52,12 +52,12 @@ Base64 可以把二進位資料編碼成字串,但為此會使用比原始二 ## Pydantic `bytes` 用於輸出資料 { #pydantic-bytes-for-output-data } -你也可以在模型設定中搭配 `ser_json_bytes` 使用 `bytes` 欄位來處理輸出資料;當產生 JSON 回應時,Pydantic 會將位元組以 base64 進行序列化。 +你也可以在模型設定中搭配 `ser_json_bytes` 使用 `bytes` 欄位來處理輸出資料;當產生 JSON 回應時,Pydantic 會將位元組以 base64 進行*序列化*。 {* ../../docs_src/json_base64_bytes/tutorial001_py310.py ln[1:2,12:16,29,38:41] hl[16] *} ## Pydantic `bytes` 用於輸入與輸出資料 { #pydantic-bytes-for-input-and-output-data } -當然,你也可以使用同一個以 base64 設定的模型,同時處理輸入(以 `val_json_bytes` 驗證)與輸出(以 `ser_json_bytes` 序列化)的 JSON 資料。 +當然,你也可以使用同一個以 base64 設定的模型,同時處理接收與傳送 JSON 資料時的輸入(以 `val_json_bytes` *驗證*)與輸出(以 `ser_json_bytes` *序列化*)。 {* ../../docs_src/json_base64_bytes/tutorial001_py310.py ln[1:2,19:26,29,44:46] hl[23:26] *} diff --git a/docs/zh-hant/docs/advanced/openapi-callbacks.md b/docs/zh-hant/docs/advanced/openapi-callbacks.md index 8b4af6dd3..6ab869acc 100644 --- a/docs/zh-hant/docs/advanced/openapi-callbacks.md +++ b/docs/zh-hant/docs/advanced/openapi-callbacks.md @@ -4,7 +4,7 @@ 當你的 API 應用呼叫「外部 API」時發生的過程稱為「回呼(callback)」。因為外部開發者撰寫的軟體會先向你的 API 發出請求,接著你的 API 再「回呼」,也就是向(可能同一位開發者建立的)外部 API 發送請求。 -在這種情況下,你可能想要文件化說明該外部 API 應該長什麼樣子。它應該有哪些「路徑操作」、應該接受什麼 body、應該回傳什麼 response,等等。 +在這種情況下,你可能想要文件化說明該外部 API 應該長什麼樣子。它應該有哪些「路徑操作」、應該接受什麼 body、應該回傳什麼回應,等等。 ## 帶有回呼的應用 { #an-app-with-callbacks } @@ -82,7 +82,7 @@ httpx.post(callback_url, json={"description": "Invoice paid", "paid": True}) 在撰寫回呼的文件化程式碼時,把自己想像成那位「外部開發者」會很有幫助。而且你現在是在實作「外部 API」,不是「你的 API」。 -暫時採用這個(外部開發者)的視角,有助於讓你更直覺地決定該把參數、body 的 Pydantic 模型、response 的模型等放在哪裡,對於那個「外部 API」會更清楚。 +暫時採用這個(外部開發者)的視角,有助於讓你更直覺地決定該把參數、body 的 Pydantic 模型、回應模型等放在哪裡,對於那個「外部 API」會更清楚。 /// @@ -99,7 +99,7 @@ httpx.post(callback_url, json={"description": "Invoice paid", "paid": True}) 它看起來就像一般的 FastAPI「路徑操作」: * 可能需要宣告它應該接收的 body,例如 `body: InvoiceEvent`。 -* 也可以宣告它應該回傳的 response,例如 `response_model=InvoiceEventReceived`。 +* 也可以宣告它應該回傳的回應,例如 `response_model=InvoiceEventReceived`。 {* ../../docs_src/openapi_callbacks/tutorial001_py310.py hl[14:16,19:20,26:30] *} diff --git a/docs/zh-hant/docs/advanced/response-change-status-code.md b/docs/zh-hant/docs/advanced/response-change-status-code.md index 31b688512..ee6373a30 100644 --- a/docs/zh-hant/docs/advanced/response-change-status-code.md +++ b/docs/zh-hant/docs/advanced/response-change-status-code.md @@ -1,5 +1,6 @@ # 回應 - 變更狀態碼 { #response-change-status-code } + 你可能已經讀過,可以設定預設的[回應狀態碼](../tutorial/response-status-code.md)。 但有些情況你需要回傳與預設不同的狀態碼。 diff --git a/docs/zh-hant/docs/advanced/response-cookies.md b/docs/zh-hant/docs/advanced/response-cookies.md index 2ba14c3f6..b27552330 100644 --- a/docs/zh-hant/docs/advanced/response-cookies.md +++ b/docs/zh-hant/docs/advanced/response-cookies.md @@ -2,9 +2,9 @@ ## 使用 `Response` 參數 { #use-a-response-parameter } -你可以在路徑操作函式(path operation function)中宣告一個型別為 `Response` 的參數。 +你可以在你的*路徑操作函式*(path operation function)中宣告一個型別為 `Response` 的參數。 -接著你可以在那個「暫時」的 `Response` 物件上設定 Cookie。 +接著你可以在那個*暫時*的 `Response` 物件上設定 Cookie。 {* ../../docs_src/response_cookies/tutorial002_py310.py hl[1, 8:9] *} @@ -12,7 +12,7 @@ 如果你宣告了 `response_model`,它仍會用來過濾並轉換你回傳的物件。 -FastAPI 會使用那個暫時的 `Response` 取出 Cookie(以及標頭與狀態碼),並將它們放入最終回應;最終回應包含你回傳的值,且會套用任何 `response_model` 的過濾。 +**FastAPI** 會使用那個*暫時*的 `Response` 取出 Cookie(以及標頭與狀態碼),並將它們放入最終回應;最終回應包含你回傳的值,且會套用任何 `response_model` 的過濾。 你也可以在相依項(dependencies)中宣告 `Response` 參數,並在其中設定 Cookie(與標頭)。 @@ -42,9 +42,9 @@ FastAPI 會使用那個暫時的 `Response` 取出 Cookie(以及標頭與狀 你也可以使用 `from starlette.responses import Response` 或 `from starlette.responses import JSONResponse`。 -為了方便開發者,FastAPI 也將相同的 `starlette.responses` 透過 `fastapi.responses` 提供。不過,大多數可用的回應類別都直接來自 Starlette。 +**FastAPI** 為了方便你這位開發者,也將相同的 `starlette.responses` 透過 `fastapi.responses` 提供。不過,大多數可用的回應類別都直接來自 Starlette。 -另外由於 `Response` 常用於設定標頭與 Cookie,FastAPI 也在 `fastapi.Response` 提供了它。 +另外由於 `Response` 常用於設定標頭與 Cookie,**FastAPI** 也在 `fastapi.Response` 提供了它。 /// diff --git a/docs/zh-hant/docs/advanced/response-headers.md b/docs/zh-hant/docs/advanced/response-headers.md index 4f7494a8b..002fb0e54 100644 --- a/docs/zh-hant/docs/advanced/response-headers.md +++ b/docs/zh-hant/docs/advanced/response-headers.md @@ -12,7 +12,7 @@ 如果你宣告了 `response_model`,它仍會用來過濾並轉換你回傳的物件。 -FastAPI 會使用那個暫時性的回應來擷取標頭(還有 Cookie 與狀態碼),並把它們放到最終回應中;最終回應包含你回傳的值,且會依任何 `response_model` 進行過濾。 +**FastAPI** 會使用那個暫時性的回應來擷取標頭(還有 Cookie 與狀態碼),並把它們放到最終回應中;最終回應包含你回傳的值,且會依任何 `response_model` 進行過濾。 你也可以在依賴中宣告 `Response` 參數,並在其中設定標頭(與 Cookie)。 @@ -28,9 +28,9 @@ FastAPI 會使用那個暫時性的回應來擷取標頭(還有 Cookie 與狀 你也可以使用 `from starlette.responses import Response` 或 `from starlette.responses import JSONResponse`。 -為了方便開發者,FastAPI 提供與 `starlette.responses` 相同的內容於 `fastapi.responses`。但大多數可用的回應類型其實直接來自 Starlette。 +為了方便開發者,**FastAPI** 提供與 `starlette.responses` 相同的內容於 `fastapi.responses`。但大多數可用的回應類型其實直接來自 Starlette。 -由於 `Response` 常用來設定標頭與 Cookie,FastAPI 也在 `fastapi.Response` 提供了它。 +由於 `Response` 常用來設定標頭與 Cookie,**FastAPI** 也在 `fastapi.Response` 提供了它。 /// diff --git a/docs/zh-hant/docs/advanced/security/oauth2-scopes.md b/docs/zh-hant/docs/advanced/security/oauth2-scopes.md index d0a6ad014..bfd9260e3 100644 --- a/docs/zh-hant/docs/advanced/security/oauth2-scopes.md +++ b/docs/zh-hant/docs/advanced/security/oauth2-scopes.md @@ -1,6 +1,6 @@ # OAuth2 範圍(scopes) { #oauth2-scopes } -你可以直接在 FastAPI 中使用 OAuth2 的 scopes,已整合可無縫運作。 +你可以直接在 **FastAPI** 中使用 OAuth2 的 scopes,已整合可無縫運作。 這能讓你在 OpenAPI 應用(以及 API 文件)中,依照 OAuth2 標準,實作更細粒度的權限系統。 @@ -8,7 +8,7 @@ 每次你「使用」Facebook、Google、GitHub、Microsoft、X(Twitter)「登入」時,那個應用就是在使用帶有 scopes 的 OAuth2。 -在本節中,你將看到如何在你的 FastAPI 應用中,用同樣的帶有 scopes 的 OAuth2 管理驗證與授權。 +在本節中,你將看到如何在你的 **FastAPI** 應用中,用同樣的帶有 scopes 的 OAuth2 管理驗證與授權。 /// warning @@ -42,9 +42,9 @@ OAuth2 規格將「scopes」定義為以空白分隔的一串字串列表。 它們通常用來宣告特定的安全性權限,例如: -- `users:read` 或 `users:write` 是常見的例子。 -- `instagram_basic` 是 Facebook / Instagram 使用的。 -- `https://www.googleapis.com/auth/drive` 是 Google 使用的。 +* `users:read` 或 `users:write` 是常見的例子。 +* `instagram_basic` 是 Facebook / Instagram 使用的。 +* `https://www.googleapis.com/auth/drive` 是 Google 使用的。 /// note @@ -58,9 +58,9 @@ OAuth2 規格將「scopes」定義為以空白分隔的一串字串列表。 /// -## 全局概觀 { #global-view } +## 全域概觀 { #global-view } -先快速看看相對於主教學「使用密碼(與雜湊)、Bearer 與 JWT token 的 OAuth2」的差異([OAuth2 with Password (and hashing), Bearer with JWT tokens](../../tutorial/security/oauth2-jwt.md))。現在加入了 OAuth2 scopes: +先快速看看主要 **教學 - 使用者指南** 中 [OAuth2 with Password (and hashing), Bearer with JWT tokens](../../tutorial/security/oauth2-jwt.md) 範例的變更部分。現在加入了 OAuth2 scopes: {* ../../docs_src/security/tutorial005_an_py310.py hl[5,9,13,47,65,106,108:116,122:126,130:136,141,157] *} @@ -84,7 +84,7 @@ OAuth2 規格將「scopes」定義為以空白分隔的一串字串列表。 ## 內含 scopes 的 JWT token { #jwt-token-with-scopes } -現在,修改 token 的路徑操作以回傳所請求的 scopes。 +現在,修改 token 的*路徑操作*以回傳所請求的 scopes。 我們仍然使用相同的 `OAuth2PasswordRequestForm`。它包含屬性 `scopes`,其為 `list` 的 `str`,列出請求中收到的每個 scope。 @@ -100,9 +100,9 @@ OAuth2 規格將「scopes」定義為以空白分隔的一串字串列表。 {* ../../docs_src/security/tutorial005_an_py310.py hl[157] *} -## 在路徑操作與相依性中宣告 scopes { #declare-scopes-in-path-operations-and-dependencies } +## 在*路徑操作*與相依性中宣告 scopes { #declare-scopes-in-path-operations-and-dependencies } -現在我們宣告 `/users/me/items/` 這個路徑操作需要 `items` 這個 scope。 +現在我們宣告 `/users/me/items/` 這個*路徑操作*需要 `items` 這個 scope。 為此,我們從 `fastapi` 匯入並使用 `Security`。 @@ -120,7 +120,7 @@ OAuth2 規格將「scopes」定義為以空白分隔的一串字串列表。 你不一定需要在不同地方加上不同的 scopes。 -我們在這裡這樣做,是為了示範 FastAPI 如何處理在不同層級宣告的 scopes。 +我們在這裡這樣做,是為了示範 **FastAPI** 如何處理在不同層級宣告的 scopes。 /// @@ -130,7 +130,7 @@ OAuth2 規格將「scopes」定義為以空白分隔的一串字串列表。 `Security` 其實是 `Depends` 的子類別,僅多了一個我們稍後會看到的參數。 -改用 `Security` 而不是 `Depends`,能讓 FastAPI 知道可以宣告安全性 scopes、在內部使用它們,並用 OpenAPI 文件化 API。 +改用 `Security` 而不是 `Depends`,能讓 **FastAPI** 知道可以宣告安全性 scopes、在內部使用它們,並用 OpenAPI 文件化 API。 另外,當你從 `fastapi` 匯入 `Query`、`Path`、`Depends`、`Security` 等時,實際上它們是回傳特殊類別的函式。 @@ -184,7 +184,7 @@ OAuth2 規格將「scopes」定義為以空白分隔的一串字串列表。 ## 驗證 `scopes` { #verify-the-scopes } -我們現在要驗證,此相依性與所有相依者(包含路徑操作)所要求的所有 scopes,是否都包含在收到的 token 內所提供的 scopes 中;否則就丟出 `HTTPException`。 +我們現在要驗證,此相依性與所有相依者(包含*路徑操作*)所要求的所有 scopes,是否都包含在收到的 token 內所提供的 scopes 中;否則就丟出 `HTTPException`。 為此,我們使用 `security_scopes.scopes`,其中包含一個 `list`,列出所有這些 `str` 形式的 scopes。 @@ -196,30 +196,30 @@ OAuth2 規格將「scopes」定義為以空白分隔的一串字串列表。 由於 `get_current_active_user` 相依於 `get_current_user`,因此在 `get_current_active_user` 宣告的 `"me"` 這個 scope 會包含在傳給 `get_current_user` 的 `security_scopes.scopes` 的必須 scopes 清單中。 -路徑操作本身也宣告了 `"items"` 這個 scope,因此它也會包含在傳給 `get_current_user` 的 `security_scopes.scopes` 中。 +*路徑操作*本身也宣告了 `"items"` 這個 scope,因此它也會包含在傳給 `get_current_user` 的 `security_scopes.scopes` 中。 以下是相依性與 scopes 的階層關係: -- 路徑操作 `read_own_items` 具有: - - 需要的 scopes `["items"]`,並有相依性: - - `get_current_active_user`: - - 相依函式 `get_current_active_user` 具有: - - 需要的 scopes `["me"]`,並有相依性: - - `get_current_user`: - - 相依函式 `get_current_user` 具有: - - 自身沒有需要的 scopes。 - - 一個使用 `oauth2_scheme` 的相依性。 - - 一個型別為 `SecurityScopes` 的 `security_scopes` 參數: - - 這個 `security_scopes` 參數有屬性 `scopes`,其為一個 `list`,包含了上面宣告的所有 scopes,因此: - - 對於路徑操作 `read_own_items`,`security_scopes.scopes` 會包含 `["me", "items"]`。 - - 對於路徑操作 `read_users_me`,因為它在相依性 `get_current_active_user` 中被宣告,`security_scopes.scopes` 會包含 `["me"]`。 - - 對於路徑操作 `read_system_status`,因為它沒有宣告任何帶 `scopes` 的 `Security`,且其相依性 `get_current_user` 也未宣告任何 `scopes`,所以 `security_scopes.scopes` 會包含 `[]`(空)。 +* *路徑操作* `read_own_items` 具有: + * 需要的 scopes `["items"]`,並有相依性: + * `get_current_active_user`: + * 相依函式 `get_current_active_user` 具有: + * 需要的 scopes `["me"]`,並有相依性: + * `get_current_user`: + * 相依函式 `get_current_user` 具有: + * 自身沒有需要的 scopes。 + * 一個使用 `oauth2_scheme` 的相依性。 + * 一個型別為 `SecurityScopes` 的 `security_scopes` 參數: + * 這個 `security_scopes` 參數有屬性 `scopes`,其為一個 `list`,包含了上面宣告的所有 scopes,因此: + * 對於*路徑操作* `read_own_items`,`security_scopes.scopes` 會包含 `["me", "items"]`。 + * 對於*路徑操作* `read_users_me`,因為它在相依性 `get_current_active_user` 中被宣告,`security_scopes.scopes` 會包含 `["me"]`。 + * 對於*路徑操作* `read_system_status`,因為它沒有宣告任何帶 `scopes` 的 `Security`,且其相依性 `get_current_user` 也未宣告任何 `scopes`,所以 `security_scopes.scopes` 會包含 `[]`(空)。 /// tip -這裡重要且「神奇」的是:`get_current_user` 在每個路徑操作中,會有不同的 `scopes` 清單需要檢查。 +這裡重要且「神奇」的是:`get_current_user` 在每個*路徑操作*中,會有不同的 `scopes` 清單需要檢查。 -這完全取決於該路徑操作與其相依性樹中每個相依性所宣告的 `scopes`。 +這完全取決於該特定*路徑操作*與其相依性樹中每個相依性所宣告的 `scopes`。 /// @@ -227,11 +227,11 @@ OAuth2 規格將「scopes」定義為以空白分隔的一串字串列表。 你可以在任意位置、多個地方使用 `SecurityScopes`,它不需要位於「根」相依性。 -它會永遠帶有對於「該特定」路徑操作與「該特定」相依性樹中,目前 `Security` 相依性所宣告的安全性 scopes(以及所有相依者): +它會永遠帶有對於**該特定***路徑操作*與**該特定**相依性樹中,目前 `Security` 相依性所宣告的安全性 scopes(以及所有相依者)。 -因為 `SecurityScopes` 會擁有由相依者宣告的所有 scopes,你可以在一個集中式相依函式中用它來驗證 token 是否具有所需 scopes,然後在不同路徑操作中宣告不同的 scope 要求。 +因為 `SecurityScopes` 會擁有由相依者宣告的所有 scopes,你可以在一個集中式相依函式中用它來驗證 token 是否具有所需 scopes,然後在不同*路徑操作*中宣告不同的 scope 要求。 -它們會在每個路徑操作被各自獨立檢查。 +它們會在每個*路徑操作*被各自獨立檢查。 ## 試用看看 { #check-it } @@ -241,9 +241,9 @@ OAuth2 規格將「scopes」定義為以空白分隔的一串字串列表。 如果你沒有選任何 scope,你仍會「通過驗證」,但當你嘗試存取 `/users/me/` 或 `/users/me/items/` 時,會收到沒有足夠權限的錯誤。你仍能存取 `/status/`。 -若你只選了 `me` 而未選 `items`,你能存取 `/users/me/`,但無法存取 `/users/me/items/`。 +若你只選了 `me` 這個 scope 而未選 `items` 這個 scope,你能存取 `/users/me/`,但無法存取 `/users/me/items/`。 -這就是第三方應用在取得使用者提供的 token 後,嘗試存取上述路徑操作時,會依使用者授與該應用的權限多寡而有不同結果。 +這就是第三方應用在取得使用者提供的 token 後,嘗試存取上述其中一個*路徑操作*時,會依使用者授與該應用的權限多寡而有不同結果。 ## 關於第三方整合 { #about-third-party-integrations } @@ -255,9 +255,9 @@ OAuth2 規格將「scopes」定義為以空白分隔的一串字串列表。 但如果你要打造一個讓他人連接的 OAuth2 應用(也就是你要建立一個相當於 Facebook、Google、GitHub 等的身分驗證提供者),你應該使用其他流程之一。 -最常見的是 Implicit Flow(隱式流程)。 +最常見的是 implicit flow(隱式流程)。 -最安全的是 Authorization Code Flow(授權碼流程),但它需要更多步驟、實作也更複雜。因為較複雜,許多提供者最後會建議使用隱式流程。 +最安全的是 code flow(授權碼流程),但它需要更多步驟、實作也更複雜。因為較複雜,許多提供者最後會建議使用隱式流程。 /// note @@ -267,7 +267,7 @@ OAuth2 規格將「scopes」定義為以空白分隔的一串字串列表。 /// -FastAPI 在 `fastapi.security.oauth2` 中提供了所有這些 OAuth2 驗證流程的工具。 +**FastAPI** 在 `fastapi.security.oauth2` 中提供了所有這些 OAuth2 驗證流程的工具。 ## 在裝飾器 `dependencies` 中使用 `Security` { #security-in-decorator-dependencies } diff --git a/docs/zh-hant/docs/advanced/settings.md b/docs/zh-hant/docs/advanced/settings.md index 9892f8f00..4ec1ea672 100644 --- a/docs/zh-hant/docs/advanced/settings.md +++ b/docs/zh-hant/docs/advanced/settings.md @@ -297,6 +297,6 @@ participant execute as Execute function 你可以使用 Pydantic Settings 來處理應用程式的設定或組態,並享有 Pydantic model 的全部能力。 -- 透過相依可以讓測試更容易。 -- 你可以搭配 `.env` 檔使用。 -- 使用 `@lru_cache` 可以避免每個請求都重複讀取 dotenv 檔,同時仍可在測試時覆寫設定。 +* 透過相依可以讓測試更容易。 +* 你可以搭配 `.env` 檔使用。 +* 使用 `@lru_cache` 可以避免每個請求都重複讀取 dotenv 檔,同時仍可在測試時覆寫設定。 diff --git a/docs/zh-hant/docs/advanced/stream-data.md b/docs/zh-hant/docs/advanced/stream-data.md index d28cd35ec..c38c48faf 100644 --- a/docs/zh-hant/docs/advanced/stream-data.md +++ b/docs/zh-hant/docs/advanced/stream-data.md @@ -2,7 +2,7 @@ 如果你要串流可用 JSON 結構化的資料,應該[串流 JSON Lines](../tutorial/stream-json-lines.md)。 -但如果你想串流純二進位資料或字串,以下是做法。 +但如果你想**串流純二進位資料**或字串,以下是做法。 /// note @@ -12,11 +12,11 @@ ## 使用情境 { #use-cases } -當你想串流純字串時可以用這個機制,例如直接轉發來自 AI LLM 服務的輸出。 +當你想串流純字串時可以用這個機制,例如直接轉發來自 **AI LLM** 服務的輸出。 -你也可以用它來串流大型二進位檔案,邊讀邊將每個區塊(chunk)串流出去,而不必一次把整個檔案載入記憶體。 +你也可以用它來串流**大型二進位檔案**,邊讀邊將每個區塊(chunk)串流出去,而不必一次把整個檔案載入記憶體。 -你也可以用同樣方式串流視訊或音訊,甚至可以在處理的同時即時產生並傳送。 +你也可以用同樣方式串流**視訊**或**音訊**,甚至可以在處理的同時即時產生並傳送。 ## 使用 `yield` 的 `StreamingResponse` { #a-streamingresponse-with-yield } @@ -40,7 +40,7 @@ FastAPI 會如實將每個資料區塊交給 `StreamingResponse`,不會嘗試 {* ../../docs_src/stream_data/tutorial001_py310.py ln[32:35] hl[33] *} -這也意味著使用 `StreamingResponse` 時,你擁有自由與責任,需依需求自行產生並編碼要傳送的位元組資料,與型別註解無關。 🤓 +這也意味著使用 `StreamingResponse` 時,你擁有**自由**與**責任**,需依需求自行產生並編碼要傳送的位元組資料,與型別註解無關。 🤓 ### 串流位元組 { #stream-bytes } diff --git a/docs/zh-hant/docs/advanced/wsgi.md b/docs/zh-hant/docs/advanced/wsgi.md index 944720bb6..161496a98 100644 --- a/docs/zh-hant/docs/advanced/wsgi.md +++ b/docs/zh-hant/docs/advanced/wsgi.md @@ -1,5 +1,6 @@ # 包含 WSGI:Flask、Django 等 { #including-wsgi-flask-django-others } + 你可以像在 [子應用程式 - 掛載](sub-applications.md)、[在 Proxy 後方](behind-a-proxy.md) 中所見那樣掛載 WSGI 應用。 為此,你可以使用 `WSGIMiddleware` 來包住你的 WSGI 應用,例如 Flask、Django 等。 diff --git a/docs/zh-hant/docs/alternatives.md b/docs/zh-hant/docs/alternatives.md index fc3f7b38e..d9573892e 100644 --- a/docs/zh-hant/docs/alternatives.md +++ b/docs/zh-hant/docs/alternatives.md @@ -80,7 +80,7 @@ Requests 設計非常簡單直觀、容易使用,且有合理的預設值。 因此,如其官網所言: -> Requests is one of the most downloaded Python packages of all time +> Requests 是有史以來下載次數最多的 Python 套件之一 用法非常簡單。例如,發出一個 `GET` 請求,你會寫: @@ -213,7 +213,7 @@ APISpec 由與 Marshmallow 相同的開發者創建。 它是個很棒但被低估的工具。它理應比許多 Flask 外掛更受歡迎,可能因為它的文件過於簡潔與抽象。 -這解決了在 Python 文件字串中撰寫 YAML(另一種語法)的问题。 +這解決了在 Python 文件字串中撰寫 YAML(另一種語法)的問題。 在打造 **FastAPI** 前,我最喜歡的後端技術組合就是 Flask、Flask-apispec、Marshmallow 與 Webargs。 diff --git a/docs/zh-hant/docs/async.md b/docs/zh-hant/docs/async.md index 74eb8081d..cad99a5a6 100644 --- a/docs/zh-hant/docs/async.md +++ b/docs/zh-hant/docs/async.md @@ -2,7 +2,7 @@ 有關*路徑操作函式*的 `async def` 語法的細節與非同步 (asynchronous) 程式碼、並行 (concurrency) 與平行 (parallelism) 的一些背景知識。 -## 趕時間嗎? { #in-a-hurry } +## 趕時間嗎 { #in-a-hurry } TL;DR: @@ -14,7 +14,6 @@ results = await some_library() 然後,使用 `async def` 宣告你的*路徑操作函式*: - ```Python hl_lines="2" @app.get('/') async def read_results(): @@ -49,7 +48,7 @@ def results(): --- -**注意**:你可以在*路徑操作函式*中混合使用 `def` 和 `async def` ,並使用最適合你需求的方式來定義每個函式。FastAPI 會幫你做正確的處理。 +**注意**:你可以在*路徑操作函式*中混合使用 `def` 和 `async def`,並使用最適合你需求的方式來定義每個函式。FastAPI 會幫你做正確的處理。 無論如何,在上述哪種情況下,FastAPI 仍將以非同步方式運行,並且速度非常快。 @@ -57,7 +56,7 @@ def results(): ## 技術細節 { #technical-details } -現代版本的 Python 支援使用 **「協程」** 的 **`async` 和 `await`** 語法來寫 **「非同步程式碼」**。 +現代版本的 Python 支援使用稱為 **「協程」** 的東西,透過 **`async` 和 `await`** 語法來寫 **「非同步程式碼」**。 接下來我們逐一介紹: @@ -67,39 +66,40 @@ def results(): ## 非同步程式碼 { #asynchronous-code } -非同步程式碼僅意味著程式語言 💬 有辦法告訴電腦/程式 🤖 在程式碼中的某個點,它 🤖 需要等待某些事情完成。讓我們假設這些事情被稱為「慢速檔案」📝。 +非同步程式碼僅意味著程式語言 💬 有辦法告訴電腦 / 程式 🤖 在程式碼中的某個點,它 🤖 需要等待其他地方的*某些事情*完成。讓我們假設這個*某些事情*被稱為「慢速檔案」📝。 + +因此,在「慢速檔案」📝 完成的這段時間,電腦可以去處理一些其他工作。 -因此,在等待「慢速檔案」📝 完成的這段時間,電腦可以去處理一些其他工作。 +接著電腦 / 程式 🤖 會在每次有機會時回來,因為它又在等待,或是在它 🤖 完成當時手上的所有工作時回來。然後它 🤖 會查看是否有任何等待中的任務已經完成,並執行必要的後續操作。 -接著程式 🤖 會在有空檔時回來查看是否有等待的工作已經完成,並執行必要的後續操作。 +接下來,它 🤖 取得第一個完成的任務(例如我們的「慢速檔案」📝),並繼續執行與之相關的所有操作。 -接下來,它 🤖 完成第一個工作(例如我們的「慢速檔案」📝)並繼續執行相關的所有操作。 -這個「等待其他事情」通常指的是一些相對較慢的(與處理器和 RAM 記憶體的速度相比)的 I/O 操作,比如說: +這個「等待其他事情」通常指的是一些相對較慢的(與處理器和 RAM 記憶體的速度相比)的 I/O 操作,比如說等待: * 透過網路傳送來自用戶端的資料 -* 從網路接收來自用戶端的資料 -* 從磁碟讀取檔案內容 -* 將內容寫入磁碟 +* 你的程式傳送的資料透過網路被用戶端接收 +* 系統從磁碟讀取檔案內容並提供給你的程式 +* 你的程式交給系統的內容被寫入磁碟 * 遠端 API 操作 -* 資料庫操作 -* 資料庫查詢 +* 資料庫操作完成 +* 資料庫查詢回傳結果 * 等等 -由於大部分的執行時間都消耗在等待 I/O 操作上,因此這些操作被稱為 "I/O 密集型" 操作。 +由於大部分的執行時間都消耗在等待 I/O 操作上,因此這些操作被稱為 "I/O bound" 操作。 -之所以稱為「非同步」,是因為電腦/程式不需要與那些耗時的任務「同步」,等待任務完成的精確時間,然後才能取得結果並繼續工作。 +之所以稱為「非同步」,是因為電腦 / 程式不需要與那些耗時的任務「同步」,在什麼都不做的情況下等待任務完成的精確時間,才能取得任務結果並繼續工作。 -相反地,非同步系統在任務完成後,可以讓任務稍微等一下(幾微秒),等待電腦/程式完成手頭上的其他工作,然後再回來取得結果繼續進行。 +相反地,作為一個「非同步」系統,任務完成後,可以讓任務稍微排隊等一下(幾微秒),等待電腦 / 程式完成手頭上的其他工作,然後再回來取得結果繼續進行。 -相對於「非同步」(asynchronous),「同步」(synchronous)也常被稱作「順序性」(sequential),因為電腦/程式會依序執行所有步驟,即便這些步驟涉及等待,才會切換到其他任務。 +相對於「非同步」(asynchronous),「同步」(synchronous)也常被稱作「順序性」(sequential),因為電腦 / 程式會依序執行所有步驟,即便這些步驟涉及等待,才會切換到其他任務。 ### 並行與漢堡 { #concurrency-and-burgers } -上述非同步程式碼的概念有時也被稱為「並行」,它不同於「平行」。 +上述**非同步**程式碼的概念有時也被稱為**「並行」**,它不同於**「平行」**。 -並行和平行都與 "不同的事情或多或少同時發生" 有關。 +**並行**和平行都與 "不同的事情或多或少同時發生" 有關。 -但並行和平行之間的細節是完全不同的。 +但*並行*和平行之間的細節是完全不同的。 為了理解差異,請想像以下有關漢堡的故事: @@ -113,7 +113,7 @@ def results(): -收銀員通知廚房準備你的漢堡(儘管他們還在為前面其他顧客準備食物)。 +收銀員通知廚房的廚師,讓他們知道需要準備你的漢堡(儘管他們還在為前面其他顧客準備食物)。 @@ -125,7 +125,7 @@ def results(): 在等待漢堡的同時,你可以與戀人選一張桌子,然後坐下來聊很長一段時間(因為漢堡十分豪華,準備特別費工。) -這段時間,你還能欣賞你的戀人有多麼的可愛、聰明與迷人。✨😍✨ +當你和戀人坐在桌邊等待漢堡時,你可以把這段時間拿來欣賞你的戀人有多麼棒、可愛又聰明 ✨😍✨。 @@ -135,7 +135,7 @@ def results(): -你和戀人享用這頓大餐,整個過程十分開心✨ +你和戀人享用這頓大餐,整個過程十分開心。✨ @@ -147,21 +147,21 @@ def results(): --- -想像你是故事中的電腦或程式 🤖。 +想像你是故事中的電腦 / 程式 🤖。 當你排隊時,你在放空😴,等待輪到你,沒有做任何「生產性」的事情。但這沒關係,因為收銀員只是接單(而不是準備食物),所以排隊速度很快。 -然後,當輪到你時,你開始做真正「有生產力」的工作,處理菜單,決定你想要什麼,替戀人選擇餐點,付款,確認你給了正確的帳單或信用卡,檢查你是否被正確收費,確認訂單中的項目是否正確等等。 +然後,當輪到你時,你開始做真正「有生產力」的工作,處理菜單,決定你想要什麼,取得戀人的選擇,付款,確認你給了正確的帳單或信用卡,檢查你是否被正確收費,確認訂單中的項目是否正確等等。 但是,即使你還沒有拿到漢堡,你與收銀員的工作已經「暫停」了 ⏸,因為你必須等待 🕙 漢堡準備好。 但當你離開櫃檯,坐到桌子旁,拿著屬於你的號碼等待時,你可以把注意力 🔀 轉移到戀人身上,並開始「工作」⏯ 🤓——也就是和戀人調情 😍。這時你又開始做一些非常「有生產力」的事情。 -接著,收銀員 💁 將你的號碼顯示在櫃檯螢幕上,並告訴你「漢堡已經做好了」。但你不會瘋狂地立刻跳起來,因為顯示的號碼變成了你的。你知道沒有人會搶走你的漢堡,因為你有自己的號碼,他們也有他們的號碼。 +接著,收銀員 💁 透過把你的號碼顯示在櫃檯螢幕上,表示「漢堡已經做好了」,但你不會在顯示的號碼變成你的號碼時就瘋狂地立刻跳起來。你知道沒有人會搶走你的漢堡,因為你有自己的號碼,他們也有他們的號碼。 -所以你會等戀人講完故事(完成當前的工作 ⏯/正在進行的任務 🤓),然後微笑著溫柔地說你要去拿漢堡了 ⏸。 +所以你會等戀人講完故事(完成當前的工作 ⏯ / 正在進行的任務 🤓),然後微笑著溫柔地說你要去拿漢堡了 ⏸。 -然後你走向櫃檯 🔀,回到已經完成的最初任務 ⏯,拿起漢堡,說聲謝謝,並帶回桌上。這就結束了與櫃檯的互動步驟/任務 ⏹,接下來會產生一個新的任務,「吃漢堡」 🔀 ⏯,而先前的「拿漢堡」任務已經完成了 ⏹。 +然後你走向櫃檯 🔀,回到已經完成的最初任務 ⏯,拿起漢堡,說聲謝謝,並帶回桌上。這就結束了與櫃檯互動的步驟 / 任務 ⏹。接著,這又產生了一個新的任務,「吃漢堡」🔀 ⏯,而先前的「拿漢堡」任務已經完成了 ⏹。 ### 平行漢堡 { #parallel-burgers } @@ -181,19 +181,19 @@ def results(): -收銀員走進廚房準備食物。 +收銀員走進廚房。 你站在櫃檯前等待 🕙,以免其他人先拿走你的漢堡,因為這裡沒有號碼牌系統。 -由於你和戀人都忙著不讓別人搶走你的漢堡,等漢堡準備好時,你根本無法專心和戀人互動。😞 +由於你和戀人都忙著不讓別人插到你前面並在漢堡送來時拿走你的漢堡,你根本無法專心和戀人互動。😞 -這是「同步」(synchronous)工作,你和收銀員/廚師 👨‍🍳 是「同步化」的。你必須等到 🕙 收銀員/廚師 👨‍🍳 完成漢堡並交給你的那一刻,否則別人可能會拿走你的餐點。 +這是「同步」(synchronous)工作,你和收銀員 / 廚師 👨‍🍳 是「同步化」的。你必須等到 🕙 收銀員 / 廚師 👨‍🍳 完成漢堡並交給你的那一刻,否則別人可能會拿走你的餐點。 -最終,經過長時間的等待 🕙,收銀員/廚師 👨‍🍳 拿著漢堡回來了。 +最終,經過長時間在櫃檯前的等待 🕙,收銀員 / 廚師 👨‍🍳 拿著漢堡回來了。 @@ -203,7 +203,7 @@ def results(): -整個過程中沒有太多的談情說愛,因為大部分時間 🕙 都花在櫃檯前等待。😞 +整個過程中沒有太多聊天或談情說愛,因為大部分時間 🕙 都花在櫃檯前等待。😞 /// note | 注意 @@ -213,15 +213,15 @@ def results(): --- -在這個平行漢堡的情境下,你是一個程式 🤖 且有兩個處理器(你和戀人),兩者都在等待 🕙 並專注於等待櫃檯上的餐點 🕙,等待的時間非常長。 +在這個平行漢堡的情境下,你是一個程式 🤖 且有兩個處理器(你和戀人),兩者都在等待 🕙 並專注 ⏯ 於在櫃檯前等待 🕙,等待的時間非常長。 -這家速食店有 8 個處理器(收銀員/廚師)。而並行漢堡店可能只有 2 個處理器(一位收銀員和一位廚師)。 +這家速食店有 8 個處理器(收銀員 / 廚師)。而並行漢堡店可能只有 2 個處理器(一位收銀員和一位廚師)。 儘管如此,最終的體驗並不是最理想的。😞 --- -這是與漢堡類似的故事。🍔 +這是與漢堡類似的平行版本故事。🍔 一個更「現實」的例子,想像一間銀行。 @@ -241,29 +241,29 @@ def results(): 許多用戶正在使用你的應用程式,而你的伺服器則在等待 🕙 這些用戶不那麼穩定的網路來傳送請求。 -接著,再次等待 🕙 回應。 +接著,再次等待 🕙 回應回來。 -這種「等待」 🕙 通常以微秒來衡量,但累加起來,最終還是花費了很多等待時間。 +這種「等待」🕙 通常以微秒來衡量,但累加起來,最終還是花費了很多等待時間。 -這就是為什麼對於 Web API 來說,使用非同步程式碼 ⏸🔀⏯ 是非常有意味的。 +這就是為什麼對於 Web API 來說,使用非同步程式碼 ⏸🔀⏯ 是非常有意義的。 這種類型的非同步性正是 NodeJS 成功的原因(儘管 NodeJS 不是平行的),這也是 Go 語言作為程式語言的一個強大優勢。 -這與 **FastAPI** 所能提供的性能水平相同。 +這與 **FastAPI** 所能提供的效能水準相同。 -你可以同時利用並行性和平行性,進一步提升效能,這比大多數已測試的 NodeJS 框架都更快,並且與 Go 語言相當,而 Go 是一種更接近 C 的編譯語言([感謝 Starlette](https://www.techempower.com/benchmarks/#section=data-r17&hw=ph&test=query&l=zijmkf-1))。 +你可以同時利用平行性和非同步性,進一步提升效能,這比大多數已測試的 NodeJS 框架都更快,並且與 Go 語言相當,而 Go 是一種更接近 C 的編譯語言([這都要歸功於 Starlette](https://www.techempower.com/benchmarks/#section=data-r17&hw=ph&test=query&l=zijmkf-1))。 -### 並行比平行更好嗎? { #is-concurrency-better-than-parallelism } +### 並行比平行更好嗎 { #is-concurrency-better-than-parallelism } 不是的!這不是故事的本意。 並行與平行不同。並行在某些 **特定** 的需要大量等待的情境下表現更好。正因如此,並行在 Web 應用程式開發中通常比平行更有優勢。但並不是所有情境都如此。 -因此,為了平衡報導,想像下面這個短故事 +因此,為了平衡報導,想像下面這個短故事: > 你需要打掃一間又大又髒的房子。 -*是的,這就是全部的故事。* +*是的,這就是全部的故事*。 --- @@ -273,32 +273,32 @@ def results(): 無論輪流執行與否(並行),你都需要相同的工時完成任務,同時需要執行相同工作量。 -但是,在這種情境下,如果你可以邀請8位前收銀員/廚師(現在是清潔工)來幫忙,每個人(加上你)負責房子的某個區域,這樣你就可以 **平行** 地更快完成工作。 +但是,在這種情境下,如果你可以邀請 8 位前收銀員 / 廚師(現在是清潔工)來幫忙,每個人(加上你)負責房子的某個區域,這樣你就可以在額外協助下 **平行** 地更快完成工作。 在這個場景中,每個清潔工(包括你)都是一個處理器,完成工作的一部分。 -由於大多數的執行時間都花在實際的工作上(而不是等待),而電腦中的工作由 CPU 完成,因此這些問題被稱為「CPU 密集型」。 +由於大多數的執行時間都花在實際的工作上(而不是等待),而電腦中的工作由 CPU 完成,因此這些問題被稱為「CPU bound」。 --- -常見的 CPU 密集型操作範例包括那些需要進行複雜數學計算的任務。 +常見的 CPU bound 操作範例包括那些需要進行複雜數學計算的任務。 例如: -* **音訊**或**圖像處理**; -* **電腦視覺**:一張圖片由數百萬個像素組成,每個像素有 3 個值/顏色,處理這些像素通常需要同時進行大量計算; -* **機器學習**: 通常需要大量的「矩陣」和「向量」運算。想像一個包含數字的巨大電子表格,並所有的數字同時相乘; -* **深度學習**: 這是機器學習的子領域,同樣適用。只不過這不僅僅是一張數字表格,而是大量的數據集合,並且在很多情況下,你會使用特殊的處理器來構建或使用這些模型。 +* **音訊**或**圖像處理**。 +* **電腦視覺**:一張圖片由數百萬個像素組成,每個像素有 3 個值 / 顏色,處理這些像素通常需要同時進行大量計算。 +* **機器學習**:通常需要大量的「矩陣」和「向量」運算。想像一個包含數字的巨大電子表格,並將所有數字同時相乘。 +* **深度學習**:這是機器學習的子領域,同樣適用。只不過這不僅僅是一張要相乘的數字表格,而是大量的數據集合,並且在很多情況下,你會使用特殊的處理器來構建及 / 或使用這些模型。 ### 並行 + 平行: Web + 機器學習 { #concurrency-parallelism-web-machine-learning } 使用 **FastAPI**,你可以利用並行的優勢,這在 Web 開發中非常常見(這也是 NodeJS 的最大吸引力)。 -但你也可以利用平行與多行程 (multiprocessing)(讓多個行程同時運行) 的優勢來處理機器學習系統中的 **CPU 密集型**工作。 +但你也可以利用平行與多行程 (multiprocessing)(讓多個行程同時運行) 的優勢來處理機器學習系統中的 **CPU bound** 工作。 -這一點,再加上 Python 是 **資料科學**、機器學習,尤其是深度學習的主要語言,讓 **FastAPI** 成為資料科學/機器學習 Web API 和應用程式(以及許多其他應用程式)的絕佳選擇。 +這一點,再加上 Python 是 **資料科學**、機器學習,尤其是深度學習的主要語言,讓 **FastAPI** 成為資料科學 / 機器學習 Web API 和應用程式(以及許多其他應用程式)的絕佳選擇。 -想了解如何在生產環境中實現這種平行性,請參見 [部屬](deployment/index.md)。 +想了解如何在生產環境中實現這種平行性,請參見 [部署](deployment/index.md)。 ## `async` 和 `await` { #async-and-await } @@ -310,37 +310,37 @@ def results(): burgers = await get_burgers(2) ``` -這裡的關鍵是 `await`。它告訴 Python 必須等待 ⏸ `get_burgers(2)` 完成它的工作 🕙, 然後將結果儲存在 `burgers` 中。如此,Python 就可以在此期間去處理其他事情 🔀 ⏯ (例如接收另一個請求)。 +這裡的關鍵是 `await`。它告訴 Python 必須等待 ⏸ `get_burgers(2)` 完成它的工作 🕙,然後將結果儲存在 `burgers` 中。如此,Python 就可以在此期間去處理其他事情 🔀 ⏯(例如接收另一個請求)。 -要讓 `await` 運作,它必須位於支持非同步功能的函式內。為此,只需使用 `async def` 宣告函式: +要讓 `await` 運作,它必須位於支援非同步功能的函式內。為此,只需使用 `async def` 宣告函式: ```Python hl_lines="1" async def get_burgers(number: int): - # Do some asynchronous stuff to create the burgers + # 做一些非同步的事情來製作漢堡 return burgers ``` -...而不是 `def`: +...而不是 `def`: ```Python hl_lines="2" -# This is not asynchronous +# 這不是非同步的 def get_sequential_burgers(number: int): - # Do some sequential stuff to create the burgers + # 做一些循序的事情來製作漢堡 return burgers ``` -使用 `async def`,Python 知道在該函式內需要注意 `await`,並且它可以「暫停」 ⏸ 執行該函式,然後執行其他任務 🔀 後回來。 +使用 `async def`,Python 知道在該函式內需要注意 `await` 運算式,並且它可以「暫停」⏸ 執行該函式,然後執行其他任務 🔀 後回來。 當你想要呼叫 `async def` 函式時,必須使用「await」。因此,這樣寫將無法運行: ```Python -# This won't work, because get_burgers was defined with: async def +# 這不會運作,因為 get_burgers 是用 async def 定義的 burgers = get_burgers(2) ``` --- -如果你正在使用某個函式庫,它告訴你可以使用 `await` 呼叫它,那麼你需要用 `async def` 定義*路徑操作函式*,如: +如果你正在使用某個函式庫,它告訴你可以使用 `await` 呼叫它,那麼你需要用 `async def` 建立使用它的*路徑操作函式*,如: ```Python hl_lines="2-3" @app.get('/burgers') @@ -357,7 +357,7 @@ async def read_burgers(): 那麼,這就像「先有雞還是先有蛋」的問題,要如何呼叫第一個 `async` 函式呢? -如果你使用 FastAPI,無需擔心這個問題,因為「第一個」函式將是你的*路徑操作函式*,FastAPI 會知道如何正確處理這個問題。 +如果你使用 **FastAPI**,無需擔心這個問題,因為「第一個」函式將是你的*路徑操作函式*,FastAPI 會知道如何正確處理這個問題。 但如果你想在沒有 FastAPI 的情況下使用 `async` / `await`,你也可以這樣做。 @@ -367,9 +367,9 @@ Starlette(和 **FastAPI**)是基於 [AnyIO](https://anyio.readthedocs.io/en/ 特別是,你可以直接使用 [AnyIO](https://anyio.readthedocs.io/en/stable/) 來處理更複雜的並行使用案例,這些案例需要你在自己的程式碼中使用更高階的模式。 -即使你不使用 **FastAPI**,你也可以使用 [AnyIO](https://anyio.readthedocs.io/en/stable/) 來撰寫自己的非同步應用程式,並獲得高相容性及一些好處(例如「結構化並行」)。 +即使你不使用 FastAPI,你也可以使用 [AnyIO](https://anyio.readthedocs.io/en/stable/) 來撰寫自己的非同步應用程式,並獲得高相容性及一些好處(例如*結構化並行*)。 -我另外在 AnyIO 之上做了一個薄封裝的函式庫,稍微改進型別註解以獲得更好的**自動補全**、**即時錯誤**等。同時它也提供友善的介紹與教學,幫助你**理解**並撰寫**自己的非同步程式碼**:[Asyncer](https://asyncer.tiangolo.com/)。當你需要**將非同步程式碼與一般**(阻塞/同步)**程式碼整合**時,它特別實用。 +我另外在 AnyIO 之上做了一個薄封裝的函式庫,稍微改進型別註解以獲得更好的**自動補全**、**即時錯誤**等。同時它也提供友善的介紹與教學,幫助你**理解**並撰寫**自己的非同步程式碼**:[Asyncer](https://asyncer.tiangolo.com/)。當你需要**將非同步程式碼與一般**(阻塞 / 同步)**程式碼整合**時,它特別實用。 ### 其他形式的非同步程式碼 { #other-forms-of-asynchronous-code } @@ -381,21 +381,21 @@ Starlette(和 **FastAPI**)是基於 [AnyIO](https://anyio.readthedocs.io/en/ 但在此之前,處理非同步程式碼要更加複雜和困難。 -在較舊的 Python 版本中,你可能會使用多執行緒或 [Gevent](https://www.gevent.org/)。但這些程式碼要更難以理解、調試和思考。 +在較舊的 Python 版本中,你可能會使用多執行緒或 [Gevent](https://www.gevent.org/)。但這些程式碼要更難以理解、偵錯和思考。 -在較舊的 NodeJS / 瀏覽器 JavaScript 中,你會使用「回呼」,這可能會導致“回呼地獄”。 +在較舊的 NodeJS / 瀏覽器 JavaScript 中,你會使用「回呼」。這可能會導致「回呼地獄」。 ## 協程 { #coroutines } -「協程」只是 `async def` 函式所回傳的非常特殊的事物名稱。Python 知道它是一個類似函式的東西,可以啟動它,並且在某個時刻它會結束,但它也可能在內部暫停 ⏸,只要遇到 `await`。 +**協程**只是 `async def` 函式所回傳的非常特殊的事物名稱。Python 知道它是一個類似函式的東西,可以啟動它,並且在某個時刻它會結束,但它也可能在內部暫停 ⏸,只要遇到 `await`。 -這種使用 `async` 和 `await` 的非同步程式碼功能通常被概括為「協程」。這與 Go 語言的主要特性「Goroutines」相似。 +但這種使用 `async` 和 `await` 的非同步程式碼功能,通常被概括為使用「協程」。這與 Go 語言的主要特性「Goroutines」相似。 ## 結論 { #conclusion } 讓我們再次回顧之前的句子: -> 現代版本的 Python 支持使用 **"協程"** 的 **`async` 和 `await`** 語法來寫 **"非同步程式碼"**。 +> 現代版本的 Python 支援使用稱為 **「協程」** 的東西,透過 **`async` 和 `await`** 語法來寫 **「非同步程式碼」**。 現在應該能明白其含意了。✨ @@ -407,7 +407,7 @@ Starlette(和 **FastAPI**)是基於 [AnyIO](https://anyio.readthedocs.io/en/ 你大概可以跳過這段。 -這裡是有關 FastAPI 內部技術細節。 +這裡是有關 **FastAPI** 底層如何運作的非常技術性的細節。 如果你有相當多的技術背景(例如協程、執行緒、阻塞等),並且對 FastAPI 如何處理 `async def` 與常規 `def` 感到好奇,請繼續閱讀。 @@ -415,9 +415,9 @@ Starlette(和 **FastAPI**)是基於 [AnyIO](https://anyio.readthedocs.io/en/ ### 路徑操作函式 { #path-operation-functions } -當你使用 `def` 而不是 `async def` 宣告*路徑操作函式*時,該函式會在外部的執行緒池(threadpool)中執行,然後等待結果,而不是直接呼叫(因為這樣會阻塞伺服器)。 +當你使用一般的 `def` 而不是 `async def` 宣告*路徑操作函式*時,該函式會在外部的執行緒池(threadpool)中執行,然後等待結果,而不是直接呼叫(因為這樣會阻塞伺服器)。 -如果你來自於其他不以這種方式運作的非同步框架,而且你習慣於使用普通的 `def` 定義僅進行簡單計算的*路徑操作函式*,目的是獲得微小的性能增益(大約 100 奈秒),請注意,在 FastAPI 中,效果會完全相反。在這些情況下,最好使用 `async def`,除非你的*路徑操作函式*執行阻塞的 I/O 的程式碼。 +如果你來自於其他不以這種方式運作的非同步框架,而且你習慣於使用普通的 `def` 定義僅進行簡單計算的*路徑操作函式*,目的是獲得微小的效能增益(大約 100 奈秒),請注意,在 **FastAPI** 中,效果會完全相反。在這些情況下,最好使用 `async def`,除非你的*路徑操作函式*執行阻塞的 I/O 的程式碼。 不過,在這兩種情況下,**FastAPI** [仍然很快](index.md#performance),至少與你之前的框架相當(或者更快)。 @@ -427,18 +427,18 @@ Starlette(和 **FastAPI**)是基於 [AnyIO](https://anyio.readthedocs.io/en/ ### 子依賴項 { #sub-dependencies } -你可以擁有多個相互依賴的依賴項和[子依賴項](tutorial/dependencies/sub-dependencies.md)(作為函式定義的參數),其中一些可能是用 `async def` 宣告,也可能是用 `def` 宣告。它們仍然可以正常運作,用 `def` 定義的那些將會在外部的執行緒中呼叫(來自執行緒池),而不是被「等待」。 +你可以擁有多個相互依賴的依賴項和[子依賴項](tutorial/dependencies/sub-dependencies.md)(作為函式定義的參數),其中一些可能是用 `async def` 宣告,也可能是用一般的 `def` 宣告。它們仍然可以正常運作,用一般的 `def` 定義的那些將會在外部的執行緒中呼叫(來自執行緒池),而不是被「等待」。 ### 其他輔助函式 { #other-utility-functions } -你可以直接呼叫任何使用 `def` 或 `async def` 建立的其他輔助函式,FastAPI 不會影響你呼叫它們的方式。 +你可以直接呼叫任何使用一般的 `def` 或 `async def` 建立的其他輔助函式,FastAPI 不會影響你呼叫它們的方式。 -這與 FastAPI 為你呼叫*路徑操作函式*和依賴項的邏輯有所不同。 +這與 FastAPI 為你呼叫的函式有所不同:*路徑操作函式*和依賴項。 -如果你的輔助函式是用 `def` 宣告的,它將會被直接呼叫(按照你在程式碼中撰寫的方式),而不是在執行緒池中。如果該函式是用 `async def` 宣告,那麼你在呼叫時應該使用 `await` 等待其結果。 +如果你的輔助函式是用 `def` 宣告的一般函式,它將會被直接呼叫(按照你在程式碼中撰寫的方式),而不是在執行緒池中。如果該函式是用 `async def` 宣告,那麼你在程式碼中呼叫它時應該使用 `await` 等待其結果。 --- 再一次強調,這些都是非常技術性的細節,如果你特地在尋找這些資訊,這些內容可能會對你有幫助。 -否則,只需遵循上面提到的指引即可:趕時間嗎?。 +否則,只需遵循上面提到章節的指引即可:趕時間嗎?。 diff --git a/docs/zh-hant/docs/deployment/cloud.md b/docs/zh-hant/docs/deployment/cloud.md index 86d216ca6..caf05ec16 100644 --- a/docs/zh-hant/docs/deployment/cloud.md +++ b/docs/zh-hant/docs/deployment/cloud.md @@ -16,7 +16,7 @@ FastAPI Cloud 是 *FastAPI and friends* 開源專案的主要贊助與資金提 ## 雲端供應商 - 贊助商 { #cloud-providers-sponsors } -其他一些雲端供應商也會 ✨ [**贊助 FastAPI**](../help-fastapi.md#sponsor-the-author) ✨。🙇 +其他一些雲端供應商也會 ✨ [**贊助 FastAPI**](https://github.com/sponsors/tiangolo) ✨。🙇 你也可以參考他們的指南並試用其服務: diff --git a/docs/zh-hant/docs/deployment/concepts.md b/docs/zh-hant/docs/deployment/concepts.md index 0b8677bfd..070bcf544 100644 --- a/docs/zh-hant/docs/deployment/concepts.md +++ b/docs/zh-hant/docs/deployment/concepts.md @@ -1,5 +1,6 @@ # 部署概念 { #deployments-concepts } + 當你要部署一個 FastAPI 應用,或其實任何類型的 Web API 時,有幾個你可能在意的概念。掌握這些概念後,你就能找出最適合部署你應用的方式。 一些重要的概念包括: diff --git a/docs/zh-hant/docs/deployment/docker.md b/docs/zh-hant/docs/deployment/docker.md index 650873887..b10299def 100644 --- a/docs/zh-hant/docs/deployment/docker.md +++ b/docs/zh-hant/docs/deployment/docker.md @@ -258,7 +258,7 @@ CMD fastapi run app/main.py --port 80 你可以在 [Docker 關於 shell 與 exec 形式的文件](https://docs.docker.com/reference/dockerfile/#shell-and-exec-form) 閱讀更多。 -使用 `docker compose` 時這會特別明顯。技術細節請見這段 Docker Compose 常見問題:[為什麼我的服務要花 10 秒才重新建立或停止?](https://docs.docker.com/compose/faq/#why-do-my-services-take-10-seconds-to-recreate-or-stop) +使用 `docker compose` 時這會特別明顯。技術細節請見這段 Docker Compose 常見問題:[為什麼我的服務要花 10 秒才重新建立或停止?](https://docs.docker.com/compose/faq/#why-do-my-services-take-10-seconds-to-recreate-or-stop)。 #### 目錄結構 { #directory-structure } @@ -454,7 +454,7 @@ Traefik 與 Docker、Kubernetes 等整合良好,因此為你的容器設定與 ## 複本 - 行程數量 { #replication-number-of-processes } -如果你在有 Kubernetes、Docker Swarm Mode、Nomad,或其他類似的分散式容器管理系統的「叢集」上運作,那你大概會希望在「叢集層級」處理「複本」,而不是在每個容器內使用「行程管理器」(例如帶有 workers 的 Uvicorn)。 +如果你在有 Kubernetes、Docker Swarm Mode、Nomad,或其他類似的分散式容器管理系統的「叢集」上運作,那你大概會希望在「叢集層級」處理「複本」,而不是在每個容器內使用「行程管理器」(例如帶有 workers 的 Uvicorn)。 像 Kubernetes 這類的分散式容器管理系統,通常內建處理「容器複本」以及支援進入請求的「負載平衡」的能力——全部都在「叢集層級」。 @@ -574,7 +574,7 @@ CMD ["fastapi", "run", "app/main.py", "--port", "80", "--workers", "4"] 你大概「不應該」使用這個基底 Docker 映像(或其他類似的)。 -如果你使用 Kubernetes(或其他)並已在叢集層級設定「複本」、使用多個「容器」。在這些情況下,更好的做法是如上所述[從零建置映像](#build-a-docker-image-for-fastapi)。 +如果你使用 Kubernetes(或其他)並已在叢集層級設定「複本」、使用多個「容器」。在這些情況下,更好的做法是如上所述「從零建置映像」:[為 FastAPI 建置 Docker 映像](#build-a-docker-image-for-fastapi)。 若你需要多個 workers,只要使用 `--workers` 命令列選項即可。 diff --git a/docs/zh-hant/docs/deployment/https.md b/docs/zh-hant/docs/deployment/https.md index ddafcb34b..fead5a4b9 100644 --- a/docs/zh-hant/docs/deployment/https.md +++ b/docs/zh-hant/docs/deployment/https.md @@ -1,5 +1,6 @@ # 關於 HTTPS { #about-https } + 人們很容易以為 HTTPS 只是「啟用或未啟用」的功能。 但實際上複雜得多。 diff --git a/docs/zh-hant/docs/deployment/manually.md b/docs/zh-hant/docs/deployment/manually.md index 2260f6942..590d0b011 100644 --- a/docs/zh-hant/docs/deployment/manually.md +++ b/docs/zh-hant/docs/deployment/manually.md @@ -40,7 +40,7 @@ $ fastapi run fastapi run ASGI。FastAPI 是一個 ASGI 網頁框架。 -在遠端伺服器機器上執行 FastAPI 應用(或任何 ASGI 應用)所需的關鍵是 ASGI 伺服器程式,例如 Uvicorn;`fastapi` 指令預設就是使用它。 +在遠端伺服器機器上執行 **FastAPI** 應用(或任何 ASGI 應用)所需的關鍵是 ASGI 伺服器程式,例如 **Uvicorn**;`fastapi` 指令預設就是使用它。 有數個替代方案,包括: @@ -61,11 +61,11 @@ FastAPI 採用建立 Python 網頁框架與伺服器的標準 路徑、操作、參數、請求內文、安全性等宣告。 +* 使用 [**OpenAPI**](https://github.com/OAI/OpenAPI-Specification) 來建立 API,包含 路徑 操作、參數、請求內文、安全性等宣告。 * 使用 [**JSON Schema**](https://json-schema.org/)(因為 OpenAPI 本身就是基於 JSON Schema)自動生成資料模型文件。 * 經過縝密的研究後圍繞這些標準進行設計,而不是事後在已有系統上附加的一層功能。 * 這也讓我們在多種語言中可以使用自動**用戶端程式碼生成**。 ### 能夠自動生成文件 { #automatic-docs } -FastAPI 能生成互動式 API 文件和探索性的 Web 使用者介面。由於該框架基於 OpenAPI,因此有多種選擇,預設提供了兩種。 +互動式 API 文件與探索用的 Web 使用者介面。由於該框架基於 OpenAPI,因此有多種選擇,預設包含 2 種。 * [**Swagger UI**](https://github.com/swagger-api/swagger-ui) 提供互動式探索,讓你可以直接從瀏覽器呼叫並測試你的 API 。 @@ -27,22 +27,22 @@ FastAPI 能生成互動式 API 文件和探索性的 Web 使用者介面。由 這一切都基於標準的 **Python 型別**宣告(感謝 Pydantic)。無需學習新的語法,只需使用標準的現代 Python。 -如果你需要 2 分鐘來學習如何使用 Python 型別(即使你不使用 FastAPI),可以看看這個簡短的教學:[Python 型別](python-types.md)。 +如果你需要 2 分鐘來複習如何使用 Python 型別(即使你不使用 FastAPI),可以看看這個簡短的教學:[Python 型別](python-types.md)。 -如果你寫帶有 Python 型別的程式碼: +你撰寫帶有型別的標準 Python: ```Python from datetime import date from pydantic import BaseModel -# 宣告一個變數為 string -# 並在函式中獲得 editor support +# 將變數宣告為 str +# 並在函式內取得 editor support def main(user_id: str): return user_id -# 宣告一個 Pydantic model +# 一個 Pydantic model class User(BaseModel): id: int name: str @@ -65,9 +65,9 @@ my_second_user: User = User(**second_user_data) /// note -`**second_user_data` 意思是: +`**second_user_data` 意思是: -將 `second_user_data` 字典直接作為 key-value 引數傳遞,等同於:`User(id=4, name="Mary", joined="2018-11-30")` +將 `second_user_data` dict 的 keys 和 values 直接作為 key-value 引數傳遞,等同於:`User(id=4, name="Mary", joined="2018-11-30")` /// @@ -75,31 +75,31 @@ my_second_user: User = User(**second_user_data) 整個框架的設計是為了讓使用變得簡單且直觀,在開始開發之前,所有決策都在多個編輯器上進行了測試,以確保提供最佳的開發體驗。 -在最近的 Python 開發者調查中,我們能看到[被使用最多的功能是 autocompletion](https://www.jetbrains.com/research/python-developers-survey-2017/#tools-and-features)。 +在 Python 開發者調查中,我們能清楚看到[最常用的功能之一是「autocompletion」](https://www.jetbrains.com/research/python-developers-survey-2017/#tools-and-features)。 整個 **FastAPI** 框架就是基於這一點,任何地方都可以進行自動補齊。 -你幾乎不需要經常來回看文件。 +你很少需要回來查看文件。 在這裡,你的編輯器可能會這樣幫助你: -* 在 [Visual Studio Code](https://code.visualstudio.com/) 中: +* 在 [Visual Studio Code](https://code.visualstudio.com/) 中: ![editor support](https://fastapi.tiangolo.com/img/vscode-completion.png) -* 在 [PyCharm](https://www.jetbrains.com/pycharm/) 中: +* 在 [PyCharm](https://www.jetbrains.com/pycharm/) 中: ![editor support](https://fastapi.tiangolo.com/img/pycharm-completion.png) -你將能進行程式碼補齊,這是在之前你可能曾認為不可能的事。例如,請求 JSON body(可能是巢狀的)中的鍵 `price`。 +你將能進行程式碼補齊,這是在之前你可能曾認為不可能的事。例如,來自請求的 JSON body(可能是巢狀的)中的鍵 `price`。 這樣比較不會輸錯鍵名,不用來回翻看文件,也不用來回滾動尋找你最後使用的 `username` 或者 `user_name`。 ### 簡潔 { #short } -FastAPI 為你提供了**預設值**,讓你不必在初期進行繁瑣的配置,一切都可以自動運作。如果你有更具體的需求,則可以進行調整和自定義。 +它為所有內容提供合理的**預設值**,並且每處都可選擇性設定。所有參數都可以微調,以完成你需要的行為並定義你需要的 API。 -但預設情況下,一切都「直接可用」。 +但預設情況下,一切都 **「直接可用」**。 ### 驗證 { #validation } @@ -109,47 +109,47 @@ FastAPI 為你提供了**預設值**,讓你不必在初期進行繁瑣的配 * 字串 (`str`) 欄位,定義最小或最大長度。 * 數字 (`int`, `float`) 與其最大值和最小值等。 -* 驗證外來的型別,比如: - * URL - * Email - * UUID +* 驗證較特殊的型別,比如: + * URL。 + * Email。 + * UUID。 * ...等等。 所有的驗證都由完善且強大的 **Pydantic** 處理。 ### 安全性及身份驗證 { #security-and-authentication } -FastAPI 已經整合了安全性和身份驗證的功能,但不會強制與特定的資料庫或資料模型進行綁定。 +FastAPI 已經整合了安全性和身份驗證的功能。不需在資料庫或資料模型上妥協。 -OpenAPI 中定義的安全模式,包括: +OpenAPI 中定義的所有安全模式,包括: * HTTP 基本認證。 * **OAuth2**(也使用 **JWT tokens**)。在 [OAuth2 with JWT](tutorial/security/oauth2-jwt.md) 查看教學。 * API 密鑰,在: - * 標頭(Header) - * 查詢參數 + * 標頭。 + * 查詢參數。 * Cookies,等等。 -加上來自 Starlette(包括 **session cookie**)的所有安全特性。 +加上來自 Starlette(包括 **session cookies**)的所有安全特性。 -所有的這些都是可重複使用的工具和套件,可以輕鬆與你的系統、資料儲存(Data Stores)、關聯式資料庫(RDBMS)以及非關聯式資料庫(NoSQL)等等整合。 +所有的這些都是可重複使用的工具和元件,可以輕鬆與你的系統、資料儲存、關聯式和 NoSQL 資料庫等整合。 ### 依賴注入(Dependency Injection) { #dependency-injection } FastAPI 有一個使用簡單,但是非常強大的 依賴注入 系統。 -* 依賴項甚至可以有自己的依賴,從而形成一個層級或**依賴圖**的結構。 +* 依賴項甚至可以有自己的依賴,從而形成一個層級或**依賴項的「圖」**結構。 * 所有**自動化處理**都由框架完成。 -* 依賴項不僅能從請求中提取資料,還能**對 API 的路徑操作進行強化**,並自動生成文檔。 -* 即使是依賴項中定義的*路徑操作參數*,也會**自動進行驗證**。 -* 支持複雜的用戶身份驗證系統、**資料庫連接**等。 -* 不與資料庫、前端等進行強制綁定,但能輕鬆整合它們。 +* 所有依賴項都可以從請求中要求資料,並**擴充路徑操作**的限制條件與自動文件。 +* 即使是依賴項中定義的*路徑操作*參數,也會**自動進行驗證**。 +* 支援複雜的使用者身份驗證系統、**資料庫連接**等。 +* **不需妥協**資料庫、前端等。但能輕鬆整合它們。 ### 無限制「擴充功能」 { #unlimited-plug-ins } -或者說,無需其他額外配置,直接導入並使用你所需要的程式碼。 +或者說,其實不需要它們,匯入並使用你需要的程式碼即可。 -任何整合都被設計得非常簡單易用(通過依賴注入),你只需用與*路徑操作*相同的結構和語法,用兩行程式碼就能為你的應用程式建立一個「擴充功能」。 +任何整合都被設計得非常簡單易用(通過依賴),你只需用與*路徑操作*相同的結構和語法,用 2 行程式碼就能為你的應用程式建立一個「plug-in」。 ### 測試 { #tested } @@ -159,7 +159,9 @@ FastAPI 有一個使用簡單,但是非常強大的 ORMs、ODMs。 +相容包括同樣基於 Pydantic 的外部函式庫,例如用於資料庫的 ORMs 和 ODMs。 -這也意味著在很多情況下,你可以把從請求中獲得的物件**直接傳到資料庫**,因為所有資料都會自動進行驗證。 +這也意味著在很多情況下,你可以把從請求中獲得的相同物件**直接傳到資料庫**,因為所有資料都會自動進行驗證。 反之亦然,在很多情況下,你也可以把從資料庫中獲取的物件**直接傳給客戶端**。 通過 **FastAPI** 你可以獲得所有 **Pydantic** 的特性(FastAPI 基於 Pydantic 做了所有的資料處理): -* **更簡單**: - * 不需要學習新的 micro-language 來定義結構。 +* **不傷腦筋**: + * 不需要學習新的 schema 定義 micro-language。 * 如果你知道 Python 型別,你就知道如何使用 Pydantic。 -* 和你的 **IDE/linter/brain** 都能好好配合: - * 因為 Pydantic 的資料結構其實就是你自己定義的類別實例,所以自動補齊、linting、mypy 以及你的直覺都能很好地在經過驗證的資料上發揮作用。 +* 和你的 **IDE/linter/brain** 都能好好配合: + * 因為 pydantic 的資料結構其實就是你自己定義的類別實例,所以自動補齊、linting、mypy 以及你的直覺都能很好地在經過驗證的資料上發揮作用。 * 驗證**複雜結構**: - * 使用 Pydantic 模型時,你可以把資料結構分層設計,並且用 Python 的 `List` 和 `Dict` 等型別來定義。 + * 使用階層式 Pydantic 模型、Python `typing` 的 `List` 和 `Dict` 等。 * 驗證器讓我們可以輕鬆地定義和檢查複雜的資料結構,並把它們轉換成 JSON Schema 進行記錄。 - * 你可以擁有深層**巢狀的 JSON** 物件,並對它們進行驗證和註釋。 -* **可擴展**: - * Pydantic 讓我們可以定義客製化的資料型別,或者你可以使用帶有 validator 裝飾器的方法來擴展模型中的驗證功能。 + * 你可以擁有深層**巢狀的 JSON** 物件,並對它們進行驗證和註解。 +* **可擴充**: + * Pydantic 讓我們可以定義客製化的資料型別,或者你可以使用帶有 validator 裝飾器的方法來擴充模型中的驗證功能。 * 100% 測試覆蓋率。 diff --git a/docs/zh-hant/docs/help-fastapi.md b/docs/zh-hant/docs/help-fastapi.md index 69af48a56..4a4a4fda5 100644 --- a/docs/zh-hant/docs/help-fastapi.md +++ b/docs/zh-hant/docs/help-fastapi.md @@ -1,5 +1,6 @@ # 協助 { #help } + 你想要協助 FastAPI,或取得關於 FastAPI 的協助嗎? 有一些非常簡單的方式可以提供協助並取得協助。 diff --git a/docs/zh-hant/docs/how-to/configure-swagger-ui.md b/docs/zh-hant/docs/how-to/configure-swagger-ui.md index cbb63ef5e..37d9487b4 100644 --- a/docs/zh-hant/docs/how-to/configure-swagger-ui.md +++ b/docs/zh-hant/docs/how-to/configure-swagger-ui.md @@ -65,6 +65,6 @@ presets: [ ] ``` -這些是 JavaScript 物件,而不是字串,因此無法直接從 Python 程式碼傳遞。 +這些是 **JavaScript** 物件,而不是字串,因此無法直接從 Python 程式碼傳遞。 -若需要使用這類僅限 JavaScript 的設定,你可以使用上面介紹的方法:覆寫所有 Swagger UI 的路徑操作(path operation),並手動撰寫所需的 JavaScript。 +若需要使用這類僅限 JavaScript 的設定,你可以使用上述其中一種方法。覆寫整個 Swagger UI *路徑操作*,並手動撰寫所需的 JavaScript。 diff --git a/docs/zh-hant/docs/how-to/custom-request-and-route.md b/docs/zh-hant/docs/how-to/custom-request-and-route.md index 00031fcaa..afd097f51 100644 --- a/docs/zh-hant/docs/how-to/custom-request-and-route.md +++ b/docs/zh-hant/docs/how-to/custom-request-and-route.md @@ -104,6 +104,6 @@ {* ../../docs_src/custom_request_and_route/tutorial003_py310.py hl[26] *} -在此範例中,`router` 底下的路徑操作會使用自訂的 `TimedRoute` 類別,並在回應中多加上一個 `X-Response-Time` 標頭,標示產生該回應所花費的時間: +在此範例中,`router` 底下的 *路徑操作* 會使用自訂的 `TimedRoute` 類別,並在回應中多加上一個 `X-Response-Time` 標頭,標示產生該回應所花費的時間: {* ../../docs_src/custom_request_and_route/tutorial003_py310.py hl[13:20] *} diff --git a/docs/zh-hant/docs/how-to/graphql.md b/docs/zh-hant/docs/how-to/graphql.md index 24e4d8979..fce5f4119 100644 --- a/docs/zh-hant/docs/how-to/graphql.md +++ b/docs/zh-hant/docs/how-to/graphql.md @@ -1,22 +1,22 @@ # GraphQL { #graphql } -由於 FastAPI 基於 ASGI 標準,整合任何與 ASGI 相容的 GraphQL 函式庫都很容易。 +由於 **FastAPI** 基於 **ASGI** 標準,整合任何也相容於 ASGI 的 **GraphQL** 函式庫都很容易。 -你可以在同一個應用程式中同時使用一般的 FastAPI 路徑操作 (path operation) 與 GraphQL。 +你可以在同一個應用程式中同時使用一般的 FastAPI *路徑操作 (path operation)* 與 GraphQL。 /// tip -GraphQL 解決某些非常特定的使用情境。 +**GraphQL** 解決某些非常特定的使用情境。 -與一般的 Web API 相比,它有優點也有缺點。 +與一般的 **Web API** 相比,它有**優點**也有**缺點**。 -請確認在你的使用情境中,這些效益是否足以彌補其限制。 🤓 +請確認在你的使用情境中,這些**效益**是否足以彌補其**限制**。 🤓 /// ## GraphQL 函式庫 { #graphql-libraries } -下面是支援 ASGI 的部分 GraphQL 函式庫,你可以與 FastAPI 一起使用: +下面是支援 **ASGI** 的部分 **GraphQL** 函式庫,你可以與 **FastAPI** 一起使用: * [Strawberry](https://strawberry.rocks/) 🍓 * 提供 [FastAPI 文件](https://strawberry.rocks/docs/integrations/fastapi) @@ -29,9 +29,9 @@ GraphQL 解決某些非常特定的使用情境。 ## 使用 Strawberry 的 GraphQL { #graphql-with-strawberry } -如果你需要或想使用 GraphQL,[Strawberry](https://strawberry.rocks/) 是推薦的函式庫,因為它的設計與 FastAPI 最接近,全部都基於型別註解 (type annotations)。 +如果你需要或想使用 **GraphQL**,[**Strawberry**](https://strawberry.rocks/) 是**推薦的**函式庫,因為它的設計最接近 **FastAPI** 的設計,全部都基於**型別註解**。 -視你的使用情境而定,你可能會偏好其他函式庫,但如果你問我,我大概會建議你先試試 Strawberry。 +視你的使用情境而定,你可能會偏好其他函式庫,但如果你問我,我大概會建議你先試試 **Strawberry**。 以下是如何將 Strawberry 與 FastAPI 整合的一個小例子: @@ -45,7 +45,7 @@ GraphQL 解決某些非常特定的使用情境。 早期版本的 Starlette 提供 `GraphQLApp` 類別以整合 [Graphene](https://graphene-python.org/)。 -它已在 Starlette 中被棄用,但如果你的程式碼使用了它,可以輕鬆遷移到 [starlette-graphene3](https://github.com/ciscorn/starlette-graphene3),涵蓋相同的使用情境,且介面幾乎相同。 +它已在 Starlette 中被棄用,但如果你的程式碼使用了它,可以輕鬆**遷移**到 [starlette-graphene3](https://github.com/ciscorn/starlette-graphene3),涵蓋相同的使用情境,且介面**幾乎相同**。 /// tip @@ -55,6 +55,6 @@ GraphQL 解決某些非常特定的使用情境。 ## 進一步了解 { #learn-more } -你可以在 [官方 GraphQL 文件](https://graphql.org/) 中進一步了解 GraphQL。 +你可以在 [官方 GraphQL 文件](https://graphql.org/) 中進一步了解 **GraphQL**。 你也可以透過上述連結閱讀各個函式庫的更多內容。 diff --git a/docs/zh-hant/docs/how-to/migrate-from-pydantic-v1-to-pydantic-v2.md b/docs/zh-hant/docs/how-to/migrate-from-pydantic-v1-to-pydantic-v2.md index 4495e3dd7..77a58251e 100644 --- a/docs/zh-hant/docs/how-to/migrate-from-pydantic-v1-to-pydantic-v2.md +++ b/docs/zh-hant/docs/how-to/migrate-from-pydantic-v1-to-pydantic-v2.md @@ -8,6 +8,8 @@ FastAPI 0.119.0 透過 Pydantic v2 內的 `pydantic.v1` 提供對 Pydantic v1 FastAPI 0.126.0 移除了對 Pydantic v1 的支援,但在一段時間內仍支援 `pydantic.v1`。 +FastAPI 0.128.0 也移除了對 `pydantic.v1` 的支援,因此最新版本的 FastAPI 需要 Pydantic v2。 + /// warning Pydantic 團隊自 **Python 3.14** 起,已停止在最新的 Python 版本中支援 Pydantic v1。 @@ -46,7 +48,7 @@ Pydantic 提供從 v1 遷移到 v2 的官方[遷移指南](https://docs.pydantic ## v2 中的 Pydantic v1 { #pydantic-v1-in-v2 } -Pydantic v2 內含子模組 `pydantic.v1`,提供 Pydantic v1 的所有內容。但在 Python 3.13 以上版本不再支援。 +Pydantic v2 內含子模組 `pydantic.v1`,提供 Pydantic v1 的所有內容。但在 Python 3.13 之後的版本不再支援。 這表示你可以安裝最新的 Pydantic v2,並從該子模組匯入並使用舊的 Pydantic v1 元件,就像安裝了舊版 Pydantic v1 一樣。 @@ -54,6 +56,16 @@ Pydantic v2 內含子模組 `pydantic.v1`,提供 Pydantic v1 的所有內容 ### FastAPI 對 v2 中 Pydantic v1 的支援 { #fastapi-support-for-pydantic-v1-in-v2 } +/// warning + +FastAPI 對 `pydantic.v1` 模型的支援是在 **FastAPI 0.119.0** 加入,並在 **FastAPI 0.128.0** 移除。這原本是為了遷移到 Pydantic v2 而提供的臨時協助。 + +在目前版本的 FastAPI 中,在你的應用使用 `pydantic.v1` 模型會引發錯誤。 + +本節其餘內容描述的是只在那些較舊版本中可用的臨時支援。 + +/// + 自 FastAPI 0.119.0 起,也支援透過 Pydantic v2 內的 Pydantic v1(部分)以協助遷移至 v2。 因此,你可以先升級到最新的 Pydantic v2,並將匯入改為使用 `pydantic.v1` 子模組,在多數情況下即可正常運作。 @@ -122,6 +134,12 @@ graph TB ### 分步遷移 { #migrate-in-steps } +/// warning + +以下描述的,在同一應用中同時使用 Pydantic v1 與 v2 模型進行漸進式遷移,只適用於 **FastAPI 0.119.0 到 0.127.x**。這項支援已在 **FastAPI 0.128.0** 移除,最新版本需要 **Pydantic v2** 模型。 + +/// + /// tip 先嘗試使用 `bump-pydantic`,如果測試通過且一切正常,你就能用一條指令完成遷移。✨ diff --git a/docs/zh-hant/docs/how-to/separate-openapi-schemas.md b/docs/zh-hant/docs/how-to/separate-openapi-schemas.md index 12fb7b8e8..72a806b4c 100644 --- a/docs/zh-hant/docs/how-to/separate-openapi-schemas.md +++ b/docs/zh-hant/docs/how-to/separate-openapi-schemas.md @@ -1,8 +1,8 @@ # 是否將輸入與輸出使用不同的 OpenAPI 結構描述 { #separate-openapi-schemas-for-input-and-output-or-not } -自從 Pydantic v2 發佈後,生成的 OpenAPI 比以往更精確也更正確。😎 +自從 **Pydantic v2** 發佈後,生成的 OpenAPI 比以往更精確也更**正確**。😎 -實際上,在某些情況下,同一個 Pydantic 模型在 OpenAPI 中會同時有兩個 JSON Schema:分別用於輸入與輸出,這取決於它是否有預設值。 +實際上,在某些情況下,同一個 Pydantic 模型在 OpenAPI 中會同時有**兩個 JSON Schema**:分別用於輸入與輸出,這取決於它是否有**預設值**。 來看看它如何運作,以及若需要時該如何調整。 @@ -18,11 +18,11 @@ {* ../../docs_src/separate_openapi_schemas/tutorial001_py310.py ln[1:15] hl[14] *} -...則 `description` 欄位將不是必填。因為它的預設值是 `None`。 +...則 `description` 欄位將**不是必填**。因為它的預設值是 `None`。 ### 文件中的輸入模型 { #input-model-in-docs } -你可以在文件中確認,`description` 欄位沒有紅色星號,表示不是必填: +你可以在文件中確認,`description` 欄位沒有**紅色星號**,表示不是必填:
@@ -34,7 +34,7 @@ {* ../../docs_src/separate_openapi_schemas/tutorial001_py310.py hl[19] *} -...由於 `description` 有預設值,就算你沒有為該欄位回傳任何內容,它仍會有那個預設值。 +...由於 `description` 有預設值,就算你**沒有為該欄位回傳任何內容**,它仍會有那個**預設值**。 ### 輸出回應資料的模型 { #model-for-output-response-data } @@ -44,20 +44,20 @@
-這代表該欄位一定會有值,只是有時候值可能是 `None`(在 JSON 中為 `null`)。 +這代表該欄位**一定會有值**,只是有時候值可能是 `None`(在 JSON 中為 `null`)。 -因此,使用你 API 的用戶端不必檢查值是否存在,可以假設該欄位一定存在;只是有些情況下它的值會是預設的 `None`。 +因此,使用你 API 的用戶端不必檢查值是否存在,可以**假設該欄位一定存在**;只是有些情況下它的值會是預設的 `None`。 -在 OpenAPI 中,描述這種情況的方式是將該欄位標記為必填,因為它一定存在。 +在 OpenAPI 中,描述這種情況的方式是將該欄位標記為**必填**,因為它一定存在。 -因此,同一個模型的 JSON Schema 會依用於輸入或輸出而不同: +因此,同一個模型的 JSON Schema 會依用於**輸入或輸出**而不同: -- 用於輸入時,`description` 不是必填 -- 用於輸出時,`description` 是必填(且可能為 `None`,在 JSON 中為 `null`) +* 用於**輸入**時,`description` **不是必填** +* 用於**輸出**時,`description` 是**必填**(且可能為 `None`,在 JSON 中為 `null`) ### 文件中的輸出模型 { #model-for-output-in-docs } -你也可以在文件中檢視輸出模型,`name` 與 `description` 都以紅色星號標示為必填: +你也可以在文件中檢視輸出模型,`name` 與 `description` **兩者**都以**紅色星號**標示為**必填**:
@@ -67,23 +67,23 @@ 如果你查看 OpenAPI 中所有可用的結構描述(JSON Schema),會看到有兩個:`Item-Input` 與 `Item-Output`。 -對於 `Item-Input`,`description` 不是必填,沒有紅色星號。 +對於 `Item-Input`,`description` **不是必填**,沒有紅色星號。 -但對於 `Item-Output`,`description` 是必填,有紅色星號。 +但對於 `Item-Output`,`description` 是**必填**,有紅色星號。
-有了 Pydantic v2 的這個特性,你的 API 文件會更精確;若你有自動產生的用戶端與 SDK,它們也會更精確,提供更好的開發者體驗與一致性。🎉 +有了 **Pydantic v2** 的這個特性,你的 API 文件會更**精確**;若你有自動產生的用戶端與 SDK,它們也會更精確,提供更好的**開發者體驗**與一致性。🎉 ## 不要分開結構描述 { #do-not-separate-schemas } -不過,在某些情況下,你可能會希望輸入與輸出使用相同的結構描述。 +不過,在某些情況下,你可能會希望**輸入與輸出使用相同的結構描述**。 最常見的情境是:你已經有一些自動產生的用戶端程式碼/SDK,目前還不想全部更新;也許之後會做,但不是現在。 -在這種情況下,你可以在 FastAPI 中透過參數 `separate_input_output_schemas=False` 停用這個功能。 +在這種情況下,你可以在 **FastAPI** 中透過參數 `separate_input_output_schemas=False` 停用這個功能。 /// note @@ -95,7 +95,7 @@ ### 文件中輸入與輸出使用相同結構描述的模型 { #same-schema-for-input-and-output-models-in-docs } -此時輸入與輸出將共用同一個模型結構描述,只有 `Item`,其中 `description` 不是必填: +此時輸入與輸出將共用同一個模型結構描述,只有 `Item`,其中 `description` **不是必填**:
diff --git a/docs/zh-hant/docs/index.md b/docs/zh-hant/docs/index.md index 5a45a69c7..743357b96 100644 --- a/docs/zh-hant/docs/index.md +++ b/docs/zh-hant/docs/index.md @@ -277,7 +277,7 @@ INFO: Application startup complete.
關於指令 fastapi dev... -指令 `fastapi dev` 會讀取你的 `main.py`,偵測其中的 **FastAPI** 應用,並使用 [Uvicorn](https://www.uvicorn.dev) 啟動伺服器。 +指令 `fastapi dev` 會自動讀取你的 `main.py`,偵測其中的 **FastAPI** 應用,並使用 [Uvicorn](https://www.uvicorn.dev) 啟動伺服器。 預設情況下,`fastapi dev` 會在本機開發時啟用自動重新載入。 @@ -473,7 +473,7 @@ item: Item ![editor support](https://fastapi.tiangolo.com/img/vscode-completion.png) -若想看包含更多功能的完整範例,請參考 Tutorial - User Guide。 +若想看包含更多功能的完整範例,請參考 教學 - 使用者指南。 **劇透警告**:教學 - 使用者指南包含: @@ -520,7 +520,7 @@ CLI 會自動偵測你的 FastAPI 應用並將其部署到雲端。若你尚未 它把用 FastAPI 開發應用的**開發者體驗**帶到**部署**到雲端的流程中。🎉 -FastAPI Cloud 是「FastAPI 與好朋友們」這些開源專案的主要贊助與資金來源。✨ +FastAPI Cloud 是 *FastAPI 與好朋友們* 這些開源專案的主要贊助與資金來源。✨ #### 部署到其他雲端供應商 { #deploy-to-other-cloud-providers } diff --git a/docs/zh-hant/docs/project-generation.md b/docs/zh-hant/docs/project-generation.md index fc5c8e465..862417aff 100644 --- a/docs/zh-hant/docs/project-generation.md +++ b/docs/zh-hant/docs/project-generation.md @@ -1,5 +1,6 @@ # 全端 FastAPI 範本 { #full-stack-fastapi-template } + 範本通常附帶特定的設定,但設計上具有彈性且可自訂。這讓你可以依專案需求調整與擴充,因此非常適合作為起點。🏁 你可以使用此範本快速起步,裡面已替你完成大量初始設定、安全性、資料庫,以及部分 API 端點。 diff --git a/docs/zh-hant/docs/python-types.md b/docs/zh-hant/docs/python-types.md index dc7160261..295921760 100644 --- a/docs/zh-hant/docs/python-types.md +++ b/docs/zh-hant/docs/python-types.md @@ -2,11 +2,11 @@ Python 支援可選用的「型別提示」(也稱為「型別註記」)。 -這些「型別提示」或註記是一種特殊語法,用來宣告變數的型別。 +這些 **「型別提示」** 或註記是一種特殊語法,用來宣告變數的型別。 為你的變數宣告型別後,編輯器與工具就能提供更好的支援。 -這裡只是關於 Python 型別提示的快速教學/複習。它只涵蓋使用在 **FastAPI** 時所需的最低限度...其實非常少。 +這裡只是關於 Python 型別提示的**快速教學/複習**。它只涵蓋使用在 **FastAPI** 時所需的最低限度...其實非常少。 **FastAPI** 完全是以這些型別提示為基礎,並因此帶來許多優勢與好處。 @@ -137,7 +137,7 @@ John Doe ### `typing` 模組 { #typing-module } -在一些其他情境中,你可能需要從標準程式庫的 `typing` 模組匯入一些東西,比如當你想宣告某個東西可以是「任何型別」時,可以用 `typing` 裡的 `Any`: +在一些其他情境中,你可能需要從標準程式庫的 `typing` 模組匯入一些東西,比如當你想宣告某個東西可以是「任何型別」時,可以用 `Any`: ```python from typing import Any @@ -151,7 +151,7 @@ def some_function(data: Any): 有些型別可以在方括號中接收「型別參數」,以定義其內部元素的型別,例如「字串的 list」可以宣告為 `list[str]`。 -這些能接收型別參數的型別稱為「泛型(Generic types)」或「Generics」。 +這些能接收型別參數的型別稱為 **泛型(Generic types)** 或 **Generics**。 你可以將相同的內建型別用作泛型(使用方括號並在裡面放型別): @@ -221,7 +221,7 @@ def some_function(data: Any): #### Union { #union } -你可以宣告一個變數可以是「多種型別」中的任一種,例如 `int` 或 `str`。 +你可以宣告一個變數可以是**多種型別**中的任一種,例如 `int` 或 `str`。 要這麼定義,你使用豎線(`|`)來分隔兩種型別。 @@ -263,9 +263,9 @@ def some_function(data: Any): -請注意,這表示「`one_person` 是類別 `Person` 的『實例(instance)』」。 +請注意,這表示「`one_person` 是類別 `Person` 的**實例(instance)**」。 -並不是「`one_person` 就是名為 `Person` 的『類別(class)』」。 +並不是「`one_person` 就是名為 `Person` 的**類別(class)**」。 ## Pydantic 模型 { #pydantic-models } @@ -295,7 +295,7 @@ def some_function(data: Any): ## 含中繼資料的型別提示 { #type-hints-with-metadata-annotations } -Python 也有一個功能,允許使用 `Annotated` 在這些型別提示中放入額外的中繼資料。 +Python 也有一個功能,允許使用 `Annotated` 在這些型別提示中放入**額外的中繼資料**。 你可以從 `typing` 匯入 `Annotated`。 @@ -305,15 +305,15 @@ Python 本身不會對這個 `Annotated` 做任何事。對編輯器與其他工 但你可以利用 `Annotated` 這個空間,來提供 **FastAPI** 額外的中繼資料,告訴它你希望應用程式如何運作。 -重要的是要記住,傳給 `Annotated` 的「第一個型別參數」才是「真正的型別」。其餘的,都是給其他工具用的中繼資料。 +重要的是要記住,傳給 `Annotated` 的**第一個*型別參數***才是**實際型別**。其餘的,都是給其他工具用的中繼資料。 目前你只需要知道 `Annotated` 的存在,而且它是標準的 Python。😎 -之後你會看到它有多「強大」。 +之後你會看到它有多**強大**。 /// tip | 提示 -因為這是「標準 Python」,所以你在編輯器、分析與重構程式碼的工具等方面,仍然能獲得「最佳的開發體驗」。✨ +因為這是**標準 Python**,所以你在編輯器、分析與重構程式碼的工具等方面,仍然能獲得**最佳的開發體驗**。✨ 而且你的程式碼也會與許多其他 Python 工具與程式庫非常相容。🚀 @@ -325,17 +325,17 @@ Python 本身不會對這個 `Annotated` 做任何事。對編輯器與其他工 在 **FastAPI** 中,你用型別提示來宣告參數,然後你會得到: -* 編輯器支援 -* 型別檢查 +* **編輯器支援**。 +* **型別檢查**。 ...而 **FastAPI** 也會用同樣的宣告來: -* 定義需求:來自請求的路徑參數、查詢參數、標頭、主體(body)、相依性等 -* 轉換資料:把請求中的資料轉成所需型別 -* 驗證資料:來自每個請求的資料: - * 當資料無效時,自動產生錯誤並回傳給用戶端 -* 使用 OpenAPI 書寫 API 文件: - * 之後會由自動的互動式文件介面所使用 +* **定義需求**:來自請求的路徑參數、查詢參數、標頭、主體(body)、相依性等。 +* **轉換資料**:把請求中的資料轉成所需型別。 +* **驗證資料**:來自每個請求的資料: + * 當資料無效時,產生回傳給用戶端的**自動錯誤**。 +* 使用 OpenAPI **記錄** API: + * 之後會由自動的互動式文件介面所使用。 這些現在聽起來可能有點抽象。別擔心。你會在[教學 - 使用者指南](tutorial/index.md)中看到它們的實際運作。 diff --git a/docs/zh-hant/docs/tutorial/bigger-applications.md b/docs/zh-hant/docs/tutorial/bigger-applications.md index 60dd4f350..624b2c2bc 100644 --- a/docs/zh-hant/docs/tutorial/bigger-applications.md +++ b/docs/zh-hant/docs/tutorial/bigger-applications.md @@ -17,16 +17,16 @@ FastAPI 提供了一個方便的工具,讓你在維持彈性的同時,幫你 ``` . ├── app -│   ├── __init__.py -│   ├── main.py -│   ├── dependencies.py -│   └── routers -│   │ ├── __init__.py -│   │ ├── items.py -│   │ └── users.py -│   └── internal -│   ├── __init__.py -│   └── admin.py +│ ├── __init__.py +│ ├── main.py +│ ├── dependencies.py +│ └── routers +│ │ ├── __init__.py +│ │ ├── items.py +│ │ └── users.py +│ └── internal +│ ├── __init__.py +│ └── admin.py ``` /// tip | 提示 @@ -542,6 +542,6 @@ router.include_router(other_router) 請使用有文件記載的 API,例如路徑操作的裝飾器與 `.include_router()` 來新增路由與 routers。 -把 `router.routes` 視為較低階的路由樹結構,它可能同時包含路由定義與被納入的 routers,避免將它當成最終路徑操作的平lat清單來依賴。 +把 `router.routes` 視為較低階的路由樹結構,它可能同時包含路由定義與被納入的 routers,避免將它當成最終路徑操作的扁平清單來依賴。 /// diff --git a/docs/zh-hant/docs/tutorial/body-nested-models.md b/docs/zh-hant/docs/tutorial/body-nested-models.md index 161920acd..4e2e6427c 100644 --- a/docs/zh-hant/docs/tutorial/body-nested-models.md +++ b/docs/zh-hant/docs/tutorial/body-nested-models.md @@ -1,5 +1,6 @@ # Body - 巢狀模型 { #body-nested-models } + 使用 **FastAPI**,你可以定義、驗證、文件化,並使用任意深度的巢狀模型(感謝 Pydantic)。 ## 列表欄位 { #list-fields } diff --git a/docs/zh-hant/docs/tutorial/body.md b/docs/zh-hant/docs/tutorial/body.md index aff55730b..f1ba8e954 100644 --- a/docs/zh-hant/docs/tutorial/body.md +++ b/docs/zh-hant/docs/tutorial/body.md @@ -32,6 +32,7 @@ {* ../../docs_src/body/tutorial001_py310.py hl[5:9] *} + 就和宣告查詢參數時一樣,當模型屬性有預設值時,它就不是必填;否則就是必填。使用 `None` 可使其成為選填。 例如,上述模型對應的 JSON「`object`」(或 Python `dict`)如下: @@ -135,6 +136,7 @@ {* ../../docs_src/body/tutorial003_py310.py hl[15:16] *} + ## 請求本文 + 路徑 + 查詢參數 { #request-body-path-query-parameters } 你也可以同時宣告**本文**、**路徑**與**查詢**參數。 diff --git a/docs/zh-hant/docs/tutorial/debugging.md b/docs/zh-hant/docs/tutorial/debugging.md index 9501dec5c..a3254e3d1 100644 --- a/docs/zh-hant/docs/tutorial/debugging.md +++ b/docs/zh-hant/docs/tutorial/debugging.md @@ -1,5 +1,6 @@ # 偵錯 { #debugging } + 你可以在編輯器中連接偵錯器,例如 Visual Studio Code 或 PyCharm。 ## 呼叫 `uvicorn` { #call-uvicorn } diff --git a/docs/zh-hant/docs/tutorial/dependencies/dependencies-with-yield.md b/docs/zh-hant/docs/tutorial/dependencies/dependencies-with-yield.md index 59d575fb0..c41f3ba7d 100644 --- a/docs/zh-hant/docs/tutorial/dependencies/dependencies-with-yield.md +++ b/docs/zh-hant/docs/tutorial/dependencies/dependencies-with-yield.md @@ -234,6 +234,7 @@ participant operation as Path Operation 含 `yield` 的相依隨時間演進,以涵蓋不同的使用情境並修正一些問題。 如果你想了解在不同 FastAPI 版本中改了哪些內容,可以在進階指南中閱讀:[進階相依 — 含 `yield`、`HTTPException`、`except` 與背景任務的相依](../../advanced/advanced-dependencies.md#dependencies-with-yield-httpexception-except-and-background-tasks)。 + ## 情境管理器 { #context-managers } ### 什麼是「情境管理器」 { #what-are-context-managers } diff --git a/docs/zh-hant/docs/tutorial/extra-data-types.md b/docs/zh-hant/docs/tutorial/extra-data-types.md index a5573379d..23c753232 100644 --- a/docs/zh-hant/docs/tutorial/extra-data-types.md +++ b/docs/zh-hant/docs/tutorial/extra-data-types.md @@ -1,5 +1,6 @@ # 額外的資料型別 { #extra-data-types } + 到目前為止,你一直在使用常見的資料型別,例如: * `int` diff --git a/docs/zh-hant/docs/tutorial/extra-models.md b/docs/zh-hant/docs/tutorial/extra-models.md index f5509f531..162325e9d 100644 --- a/docs/zh-hant/docs/tutorial/extra-models.md +++ b/docs/zh-hant/docs/tutorial/extra-models.md @@ -4,9 +4,9 @@ 對使用者模型尤其如此,因為: -* 「輸入模型」需要能包含密碼。 -* 「輸出模型」不應包含密碼。 -* 「資料庫模型」通常需要儲存雜湊後的密碼。 +* **輸入模型**需要能包含密碼。 +* **輸出模型**不應包含密碼。 +* **資料庫模型**通常需要儲存雜湊後的密碼。 /// danger @@ -140,7 +140,7 @@ UserInDB( ## 減少重複 { #reduce-duplication } -減少程式碼重複是 FastAPI 的核心理念之一。 +減少程式碼重複是 **FastAPI** 的核心理念之一。 因為重複的程式碼會提高發生錯誤、安全性問題、程式不同步(某處更新但其他處未更新)等風險。 @@ -176,7 +176,7 @@ UserInDB( 此範例中,我們將 `Union[PlaneItem, CarItem]` 作為引數 `response_model` 的值。 -由於這裡是把它當作引數的「值」傳入,而非用於型別註記,因此即使在 Python 3.10 也必須使用 `Union`。 +由於這裡是把它當作**引數的值**傳入,而非放在**型別註記**中,因此即使在 Python 3.10 也必須使用 `Union`。 若用於型別註記,則可以使用直線(|),如下: @@ -184,7 +184,7 @@ UserInDB( some_variable: PlaneItem | CarItem ``` -但若寫成指定值 `response_model=PlaneItem | CarItem` 會發生錯誤,因為 Python 會嘗試在 `PlaneItem` 與 `CarItem` 之間執行「無效運算」,而非將其視為型別註記。 +但若寫成指定值 `response_model=PlaneItem | CarItem` 會發生錯誤,因為 Python 會嘗試在 `PlaneItem` 與 `CarItem` 之間執行**無效運算**,而非將其視為型別註記。 ## 模型的清單 { #list-of-models } @@ -208,4 +208,4 @@ some_variable: PlaneItem | CarItem 依情境使用多個 Pydantic 模型並靈活繼承。 -當一個實體需要呈現不同「狀態」時,不必侷限於一個資料模型。例如使用者這個實體,可能有包含 `password`、包含 `password_hash`,或不含密碼等不同狀態。 +當一個實體需要呈現不同「狀態」時,不必侷限於一個資料模型。**使用者**「實體」是一個例子,可能有包含 `password`、包含 `password_hash`,或不含密碼等不同狀態。 diff --git a/docs/zh-hant/docs/tutorial/first-steps.md b/docs/zh-hant/docs/tutorial/first-steps.md index 8d644abd1..bc023cc39 100644 --- a/docs/zh-hant/docs/tutorial/first-steps.md +++ b/docs/zh-hant/docs/tutorial/first-steps.md @@ -137,9 +137,9 @@ OpenAPI 為你的 API 定義了 API 的 schema。而該 schema 會包含你的 A #### OpenAPI 的用途 { #what-is-openapi-for } -OpenAPI schema 驅動了兩個互動式文件系統。 +OpenAPI schema 驅動了內建的兩個互動式文件系統。 -而且有許多替代方案,所有這些都是基於 OpenAPI。你可以輕鬆地將任何這些替代方案添加到使用 **FastAPI** 建置的應用程式中。 +而且有數十種替代方案,所有這些都是基於 OpenAPI。你可以輕鬆地將任何這些替代方案加入到使用 **FastAPI** 建置的應用程式中。 你也可以用它自動生成程式碼,讓用戶端與你的 API 通訊。例如前端、手機或物聯網(IoT)應用程式。 @@ -226,7 +226,7 @@ CLI 會自動偵測你的 FastAPI 應用並將它部署到雲端。若你尚未 {* ../../docs_src/first_steps/tutorial001_py310.py hl[1] *} -`FastAPI` 是一個 Python 類別,提供所有 API 的全部功能。 +`FastAPI` 是一個 Python 類別,提供你的 API 所需的所有功能。 /// note | 技術細節 @@ -244,7 +244,7 @@ CLI 會自動偵測你的 FastAPI 應用並將它部署到雲端。若你尚未 這將是你建立所有 API 的主要互動點。 -### 第三步:建立一個「路徑操作」 { #step-3-create-a-path-operation } +### 第三步:建立一個*路徑操作* { #step-3-create-a-path-operation } #### 路徑 { #path } @@ -256,7 +256,7 @@ CLI 會自動偵測你的 FastAPI 應用並將它部署到雲端。若你尚未 https://example.com/items/foo ``` -……的路徑將會是: +...的路徑將會是: ``` /items/foo @@ -281,7 +281,7 @@ https://example.com/items/foo * `PUT` * `DELETE` -……以及更少見的: +...以及更少見的: * `OPTIONS` * `HEAD` @@ -305,14 +305,14 @@ https://example.com/items/foo 我們將會稱它們為「**操作**」。 -#### 定義一個「路徑操作裝飾器」 { #define-a-path-operation-decorator } +#### 定義一個*路徑操作裝飾器* { #define-a-path-operation-decorator } {* ../../docs_src/first_steps/tutorial001_py310.py hl[6] *} -`@app.get("/")` 告訴 **FastAPI** 那個函式負責處理請求: +`@app.get("/")` 告訴 **FastAPI** 正下方的函式負責處理前往以下位置的請求: * 路徑 `/` -* 使用 get 操作 +* 使用 get 操作 /// note | `@decorator` 說明 @@ -353,7 +353,7 @@ Python 中的 `@something` 語法被稱為「裝飾器」。 /// -### 第四步:定義「路徑操作函式」 { #step-4-define-the-path-operation-function } +### 第四步:定義**路徑操作函式** { #step-4-define-the-path-operation-function } 這是我們的「**路徑操作函式**」: @@ -377,7 +377,7 @@ Python 中的 `@something` 語法被稱為「裝飾器」。 /// note -如果你不知道差別,請查看 [Async: *"In a hurry?"*](../async.md#in-a-hurry)。 +如果你不知道差別,請查看 [Async:*「很趕時間?」*](../async.md#in-a-hurry)。 /// @@ -399,11 +399,11 @@ Python 中的 `@something` 語法被稱為「裝飾器」。 **[FastAPI Cloud](https://fastapicloud.com)** 由 **FastAPI** 的作者與團隊打造。 -它讓你以最小的成本完成 API 的**建置**、**部署**與**存取**流程。 +它讓你以最少的心力簡化 API 的**建置**、**部署**與**存取**流程。 它把用 FastAPI 開發應用的同樣**開發者體驗**帶到將應用**部署**到雲端的流程中。🎉 -FastAPI Cloud 也是「FastAPI 與其好友」這些開源專案的主要贊助與資金提供者。✨ +FastAPI Cloud 也是 *FastAPI 與其好友* 這些開源專案的主要贊助與資金提供者。✨ #### 部署到其他雲端供應商 { #deploy-to-other-cloud-providers } @@ -415,7 +415,7 @@ FastAPI 是開源並基於標準的。你可以把 FastAPI 應用部署到你選 * 引入 `FastAPI`。 * 建立一個 `app` 實例。 -* 寫一個「路徑操作裝飾器」,像是 `@app.get("/")`。 -* 定義一個「路徑操作函式」;例如,`def root(): ...`。 +* 寫一個**路徑操作裝飾器**,像是 `@app.get("/")`。 +* 定義一個**路徑操作函式**;例如,`def root(): ...`。 * 使用命令 `fastapi dev` 執行開發伺服器。 * 可選:使用 `fastapi deploy` 部署你的應用程式。 diff --git a/docs/zh-hant/docs/tutorial/handling-errors.md b/docs/zh-hant/docs/tutorial/handling-errors.md index b1ffd3e03..dc6d7a7cc 100644 --- a/docs/zh-hant/docs/tutorial/handling-errors.md +++ b/docs/zh-hant/docs/tutorial/handling-errors.md @@ -11,13 +11,13 @@ * 用戶端嘗試存取的項目不存在。 * 等等。 -在這些情況下,通常會回傳範圍為 400(400 到 499)的 HTTP 狀態碼。 +在這些情況下,通常會回傳範圍為 **400**(400 到 499)的 **HTTP 狀態碼**。 這類似於 200 範圍的 HTTP 狀態碼(200 到 299)。那些「200」狀態碼表示請求在某種程度上是「成功」的。 400 範圍的狀態碼表示用戶端錯誤。 -還記得那些「404 Not Found」錯誤(和梗)嗎? +還記得那些 **「404 Not Found」** 錯誤(和梗)嗎? ## 使用 `HTTPException` { #use-httpexception } diff --git a/docs/zh-hant/docs/tutorial/index.md b/docs/zh-hant/docs/tutorial/index.md index e19121511..e20c9ca24 100644 --- a/docs/zh-hant/docs/tutorial/index.md +++ b/docs/zh-hant/docs/tutorial/index.md @@ -98,4 +98,4 @@ FastAPI 提供了 [VS Code 官方擴充功能](https://marketplace.visualstudio. 但首先你應該閱讀**教學 - 使用者指南**(你正在閱讀的內容)。 -它被設計成你可以使用**教學 - 使用者指南**來建立一個完整的應用程式,然後根據你的需求,使用一些額外的想法來擴展它。 +它被設計成你可以使用**教學 - 使用者指南**來建立一個完整的應用程式,然後根據你的需求,使用**進階使用者指南**中的一些額外想法,以不同方式擴展它。 diff --git a/docs/zh-hant/docs/tutorial/metadata.md b/docs/zh-hant/docs/tutorial/metadata.md index 6a54724a5..55fa4bdbf 100644 --- a/docs/zh-hant/docs/tutorial/metadata.md +++ b/docs/zh-hant/docs/tutorial/metadata.md @@ -1,6 +1,6 @@ # 中繼資料與文件 URL { #metadata-and-docs-urls } -你可以在你的 FastAPI 應用程式中自訂多項中繼資料設定。 +你可以在你的 **FastAPI** 應用程式中自訂多項中繼資料設定。 ## API 的中繼資料 { #metadata-for-api } @@ -11,7 +11,7 @@ | `title` | `str` | API 的標題。 | | `summary` | `str` | API 的簡短摘要。自 OpenAPI 3.1.0、FastAPI 0.99.0 起可用。 | | `description` | `str` | API 的簡短說明。可使用 Markdown。 | -| `version` | `string` | API 的版本號。這是你自己的應用程式版本,不是 OpenAPI 的版本,例如 `2.5.0`。 | +| `version` | `str` | API 的版本號。這是你自己的應用程式版本,不是 OpenAPI 的版本,例如 `2.5.0`。 | | `terms_of_service` | `str` | 指向 API 服務條款的 URL。若提供,必須是 URL。 | | `contact` | `dict` | 對外公開的 API 聯絡資訊。可包含多個欄位。
contact 欄位
參數型別說明
namestr聯絡人/組織的識別名稱。
urlstr指向聯絡資訊的 URL。必須是 URL 格式。
emailstr聯絡人/組織的電子郵件地址。必須是電子郵件格式。
| | `license_info` | `dict` | 對外公開的 API 授權資訊。可包含多個欄位。
license_info 欄位
參數型別說明
namestr必填(若有設定 license_info)。API 使用的授權名稱。
identifierstrAPI 的 [SPDX](https://spdx.org/licenses/) 授權表示式。identifier 欄位與 url 欄位互斥。自 OpenAPI 3.1.0、FastAPI 0.99.0 起可用。
urlstrAPI 所採用授權的 URL。必須是 URL 格式。
| @@ -46,7 +46,7 @@ 每個 dictionary 可包含: -* `name`(**必填**):一個 `str`,其值需與你在路徑操作與 `APIRouter`s 的 `tags` 參數中使用的標籤名稱相同。 +* `name`(**必填**):一個 `str`,其值需與你在*路徑操作*與 `APIRouter`s 的 `tags` 參數中使用的標籤名稱相同。 * `description`:一個 `str`,為該標籤的簡短描述。可使用 Markdown,並會顯示在文件介面中。 * `externalDocs`:一個 `dict`,描述外部文件,包含: * `description`:一個 `str`,外部文件的簡短描述。 @@ -70,7 +70,7 @@ ### 使用你的標籤 { #use-your-tags } -在你的路徑操作(以及 `APIRouter`s)上使用 `tags` 參數,將它們歸類到不同標籤下: +在你的*路徑操作*(以及 `APIRouter`s)上使用 `tags` 參數,將它們歸類到不同標籤下: {* ../../docs_src/metadata/tutorial004_py310.py hl[21,26] *} @@ -108,10 +108,10 @@ 你可以設定內建的兩個文件使用者介面: -* Swagger UI:提供於 `/docs`。 +* **Swagger UI**:提供於 `/docs`。 * 可用 `docs_url` 參數設定其 URL。 * 設定 `docs_url=None` 可停用。 -* ReDoc:提供於 `/redoc`。 +* **ReDoc**:提供於 `/redoc`。 * 可用 `redoc_url` 參數設定其 URL。 * 設定 `redoc_url=None` 可停用。 diff --git a/docs/zh-hant/docs/tutorial/path-operation-configuration.md b/docs/zh-hant/docs/tutorial/path-operation-configuration.md index 8461f2521..edd10178c 100644 --- a/docs/zh-hant/docs/tutorial/path-operation-configuration.md +++ b/docs/zh-hant/docs/tutorial/path-operation-configuration.md @@ -1,5 +1,6 @@ # 路徑操作設定 { #path-operation-configuration } + 你可以在你的「路徑操作裝飾器」中傳入多個參數來進行設定。 /// warning | 警告 diff --git a/docs/zh-hant/docs/tutorial/query-params-str-validations.md b/docs/zh-hant/docs/tutorial/query-params-str-validations.md index 1c247b0f8..99690708e 100644 --- a/docs/zh-hant/docs/tutorial/query-params-str-validations.md +++ b/docs/zh-hant/docs/tutorial/query-params-str-validations.md @@ -1,6 +1,6 @@ # 查詢參數與字串驗證 { #query-parameters-and-string-validations } -FastAPI 允許你為參數宣告額外的資訊與驗證。 +**FastAPI** 允許你為參數宣告額外的資訊與驗證。 以下面這個應用為例: @@ -18,14 +18,14 @@ FastAPI 會因為預設值是 `= None` 而知道 `q` 不是必填。 ## 額外驗證 { #additional-validation } -我們要強制:即使 `q` 是可選,只要提供了,長度就不能超過 50 個字元。 +我們要強制:即使 `q` 是可選,只要提供了,**長度就不能超過 50 個字元**。 ### 匯入 `Query` 與 `Annotated` { #import-query-and-annotated } 要達成這點,先匯入: -- 從 `fastapi` 匯入 `Query` -- 從 `typing` 匯入 `Annotated` +* 從 `fastapi` 匯入 `Query` +* 從 `typing` 匯入 `Annotated` {* ../../docs_src/query_params_str_validations/tutorial002_an_py310.py hl[1,3] *} @@ -69,19 +69,19 @@ q: Annotated[str | None] = None 注意預設值仍然是 `None`,所以這個參數仍是可選。 -不過,現在在 `Annotated` 裡有 `Query(max_length=50)`,我們就告訴 FastAPI 要對這個值做「額外驗證」,最多 50 個字元即可。😎 +不過,現在在 `Annotated` 裡有 `Query(max_length=50)`,我們就告訴 FastAPI 要對這個值做**額外驗證**,最多 50 個字元即可。😎 /// tip | 提示 -這裡用的是 `Query()`,因為這是「查詢參數」。稍後你會看到 `Path()`、`Body()`、`Header()`、`Cookie()` 等,它們也接受與 `Query()` 相同的參數。 +這裡用的是 `Query()`,因為這是**查詢參數**。稍後你會看到 `Path()`、`Body()`、`Header()`、`Cookie()` 等,它們也接受與 `Query()` 相同的參數。 /// FastAPI 現在會: -- 驗證資料,確保長度最多 50 個字元 -- 當資料不合法時,回給用戶端清楚的錯誤 -- 在 OpenAPI 的路徑操作中文件化該參數(因此會出現在自動文件 UI) +* **驗證**資料,確保長度最多 50 個字元 +* 當資料不合法時,回給用戶端**清楚的錯誤** +* 在 OpenAPI schema *路徑操作*中**文件化**該參數(因此會出現在**自動文件 UI**) ## 替代方式(舊):將 `Query` 作為預設值 { #alternative-old-query-as-the-default-value } @@ -105,7 +105,8 @@ FastAPI 現在會: q: str | None = Query(default=None) ``` -…會讓參數變為可選、預設值是 `None`,等同於: +...會讓參數變為可選、預設值是 `None`,等同於: + ```Python q: str | None = None @@ -119,7 +120,7 @@ q: str | None = None q: str | None = Query(default=None, max_length=50) ``` -這一樣會驗證資料、在資料不合法時顯示清楚錯誤,並在 OpenAPI 的路徑操作中文件化該參數。 +這一樣會驗證資料、在資料不合法時顯示清楚錯誤,並在 OpenAPI schema *路徑操作*中文件化該參數。 ### 將 `Query` 作為預設值或放在 `Annotated` 中 { #query-as-the-default-value-or-in-annotated } @@ -133,7 +134,7 @@ q: str | None = Query(default=None, max_length=50) q: Annotated[str, Query(default="rick")] = "morty" ``` -…因為不清楚預設值到底該是 `"rick"` 還是 `"morty"`。 +...因為不清楚預設值到底該是 `"rick"` 還是 `"morty"`。 因此,你可以(且更推薦)這樣寫: @@ -141,7 +142,7 @@ q: Annotated[str, Query(default="rick")] = "morty" q: Annotated[str, Query()] = "rick" ``` -…或在較舊的程式碼中你會看到: +...或在較舊的程式碼中你會看到: ```Python q: str = Query(default="rick") @@ -149,13 +150,13 @@ q: str = Query(default="rick") ### `Annotated` 的優點 { #advantages-of-annotated } -建議使用 `Annotated`,而不是在函式參數上使用(舊式的)預設值寫法,理由很多,且更好。🤓 +建議**使用 `Annotated`**,而不是在函式參數上使用預設值寫法,理由很多,且**更好**。🤓 -函式參數的「預設值」就是「實際的預設值」,這在 Python 的直覺上更一致。😌 +函式參數的**預設值**就是**實際的預設值**,這在 Python 的直覺上更一致。😌 -你也可以在沒有 FastAPI 的其他地方「直接呼叫」同一個函式,而且能「如預期」運作。若有「必填」參數(沒有預設值),你的「編輯器」會提示錯誤,「Python」在執行時也會抱怨你未傳遞必填參數。 +你也可以在沒有 FastAPI 的**其他地方**「**呼叫**」同一個函式,而且能「**如預期**」運作。若有**必填**參數(沒有預設值),你的**編輯器**會提示錯誤,**Python** 在執行時也會抱怨你未傳遞必填參數。 -若不使用 `Annotated`、改用「(舊式)預設值」寫法,你在沒有 FastAPI 的「其他地方」呼叫該函式時,就得「記得」傳入正確參數,否則值會和預期不同(例如會得到 `QueryInfo` 或類似的東西,而不是 `str`)。你的編輯器不會提示,Python 執行該函式時也不會抱怨,只有在內部操作失敗時才會出錯。 +若不使用 `Annotated`、改用**(舊式)預設值**寫法,你在沒有 FastAPI 的**其他地方**呼叫該函式時,就得**記得**傳入正確參數,否則值會和預期不同(例如會得到 `QueryInfo` 或類似的東西,而不是 `str`)。你的編輯器不會提示,Python 執行該函式時也不會抱怨,只有在內部操作失敗時才會出錯。 因為 `Annotated` 可以有多個中繼資料註解,你甚至可以用同一個函式配合其他工具,例如 [Typer](https://typer.tiangolo.com/)。🚀 @@ -167,19 +168,19 @@ q: str = Query(default="rick") ## 加入正規表示式 { #add-regular-expressions } -你可以定義參數必須符合的 正規表示式 `pattern`: +你可以定義參數必須符合的 正規表示式 `pattern`: {* ../../docs_src/query_params_str_validations/tutorial004_an_py310.py hl[11] *} 這個特定的正規表示式樣式會檢查收到的參數值是否: -- `^`:以後續的字元開頭,前面不能有其他字元。 -- `fixedquery`:必須正好等於 `fixedquery`。 -- `$`:在此結束,`fixedquery` 後面不能再有其他字元。 +* `^`:以後續的字元開頭,前面不能有其他字元。 +* `fixedquery`:必須正好等於 `fixedquery`。 +* `$`:在此結束,`fixedquery` 後面不能再有其他字元。 -如果你對「正規表示式」感到困惑,別擔心。這對很多人來說都不容易。你仍然可以先不使用正規表示式就完成很多事情。 +如果你對所有這些**「正規表示式」**概念感到困惑,別擔心。這對很多人來說都不容易。你仍然可以先不使用正規表示式就完成很多事情。 -現在你知道,當你需要它們時,可以在 FastAPI 中使用它們。 +現在你知道,當你需要它們時,可以在 **FastAPI** 中使用它們。 ## 預設值 { #default-values } @@ -235,13 +236,13 @@ q: Annotated[str | None, Query(min_length=3)] = None {* ../../docs_src/query_params_str_validations/tutorial011_an_py310.py hl[9] *} -若使用這樣的 URL: +接著,若使用這樣的 URL: ``` http://localhost:8000/items/?q=foo&q=bar ``` -你會在路徑操作函式的參數 `q` 中,收到多個 `q` 查詢參數的值(`foo` 與 `bar`),以 Python 的 `list` 形式。 +你會在*路徑操作函式*的*函式參數* `q` 中,收到多個 `q` *查詢參數*的值(`foo` 與 `bar`),以 Python 的 `list` 形式。 因此,對該 URL 的回應會是: @@ -276,7 +277,7 @@ http://localhost:8000/items/?q=foo&q=bar http://localhost:8000/items/ ``` -`q` 的預設值會是:`["foo", "bar"]`,而回應會是: +`q` 的預設值會是:`["foo", "bar"]`,而你的回應會是: ```JSON { @@ -359,15 +360,15 @@ http://127.0.0.1:8000/items/?item-query=foobaritems ## 從 OpenAPI 排除參數 { #exclude-parameters-from-openapi } -若要把某個查詢參數從產生的 OpenAPI(以及自動文件系統)中排除,將 `Query` 的 `include_in_schema` 設為 `False`: +若要把某個查詢參數從產生的 OpenAPI schema(以及自動文件系統)中排除,將 `Query` 的 `include_in_schema` 設為 `False`: {* ../../docs_src/query_params_str_validations/tutorial014_an_py310.py hl[10] *} ## 自訂驗證 { #custom-validation } -有時你需要做一些上述參數無法處理的「自訂驗證」。 +有時你需要做一些上述參數無法處理的**自訂驗證**。 -這種情況下,你可以使用「自訂驗證函式」,它會在一般驗證之後套用(例如先確認值是 `str` 之後)。 +這種情況下,你可以使用**自訂驗證函式**,它會在一般驗證之後套用(例如先確認值是 `str` 之後)。 你可以在 `Annotated` 中使用 [Pydantic 的 `AfterValidator`](https://docs.pydantic.dev/latest/concepts/validators/#field-after-validator) 來達成。 @@ -389,15 +390,15 @@ Pydantic 也有 [`BeforeValidator`](https://docs.pydantic.dev/latest/concepts/va /// tip | 提示 -如果你需要做任何需要與「外部元件」溝通的驗證(例如資料庫或其他 API),應該改用「FastAPI 依賴」(FastAPI Dependencies),你稍後會學到。 +如果你需要做任何需要與**外部元件**溝通的驗證(例如資料庫或其他 API),應該改用 **FastAPI Dependencies**,你稍後會學到。 -這些自訂驗證器適用於只需使用請求中「同一份資料」即可完成的檢查。 +這些自訂驗證器適用於只需使用請求中**同一份資料**即可完成的檢查。 /// ### 理解這段程式碼 { #understand-that-code } -重點就是在 `Annotated` 中使用「`AfterValidator` 搭配函式」。如果你願意,可以略過這一節。🤸 +重點就是在 `Annotated` 中使用 **`AfterValidator` 搭配函式**。如果你願意,可以略過這一節。🤸 --- @@ -415,13 +416,13 @@ Pydantic 也有 [`BeforeValidator`](https://docs.pydantic.dev/latest/concepts/va 我們用 `list(data.items())` 把這個可疊代物件轉成正式的 `list`。 -接著用 `random.choice()` 從清單中取得一個「隨機值」,也就是一個 `(id, name)` 的 tuple。可能像是 `("imdb-tt0371724", "The Hitchhiker's Guide to the Galaxy")`。 +接著用 `random.choice()` 從清單中取得一個**隨機值**,也就是一個 `(id, name)` 的 tuple。可能像是 `("imdb-tt0371724", "The Hitchhiker's Guide to the Galaxy")`。 -然後把這個 tuple 的兩個值分別指定給變數 `id` 和 `name`。 +然後把這個 tuple 的**兩個值分別指定**給變數 `id` 和 `name`。 因此,即使使用者沒有提供 item ID,仍然會收到一個隨機建議。 -……而這全部只用一行簡單的程式碼完成。🤯 你不愛 Python 嗎?🐍 +...而這全部只用**一行簡單的程式碼**完成。🤯 你不愛 Python 嗎?🐍 {* ../../docs_src/query_params_str_validations/tutorial015_an_py310.py ln[22:30] hl[29] *} @@ -431,16 +432,16 @@ Pydantic 也有 [`BeforeValidator`](https://docs.pydantic.dev/latest/concepts/va 通用的驗證與中繼資料: -- `alias` -- `title` -- `description` -- `deprecated` +* `alias` +* `title` +* `description` +* `deprecated` 字串專用的驗證: -- `min_length` -- `max_length` -- `pattern` +* `min_length` +* `max_length` +* `pattern` 使用 `AfterValidator` 的自訂驗證。 diff --git a/docs/zh-hant/docs/tutorial/query-params.md b/docs/zh-hant/docs/tutorial/query-params.md index 24b0cb404..86cf60a5a 100644 --- a/docs/zh-hant/docs/tutorial/query-params.md +++ b/docs/zh-hant/docs/tutorial/query-params.md @@ -67,7 +67,7 @@ http://127.0.0.1:8000/items/?skip=20 /// tip | 提示 -另外請注意,FastAPI 能辨識出路徑參數 `item_id` 是路徑參數,而 `q` 不是,因此 `q` 會被當作查詢參數。 +另外請注意,**FastAPI** 能辨識出路徑參數 `item_id` 是路徑參數,而 `q` 不是,因此 `q` 會被當作查詢參數。 /// @@ -109,9 +109,10 @@ http://127.0.0.1:8000/items/foo?short=yes 或任何其他大小寫變化(全大寫、首字母大寫等),你的函式會將參數 `short` 視為 `bool` 值 `True`。否則為 `False`。 + ## 多個路徑與查詢參數 { #multiple-path-and-query-parameters } -你可以同時宣告多個路徑參數與查詢參數,FastAPI 會自動分辨。 +你可以同時宣告多個路徑參數與查詢參數,**FastAPI** 會自動分辨。 而且不必按特定順序宣告。 diff --git a/docs/zh-hant/docs/tutorial/request-files.md b/docs/zh-hant/docs/tutorial/request-files.md index 1d95bf0cd..979a579eb 100644 --- a/docs/zh-hant/docs/tutorial/request-files.md +++ b/docs/zh-hant/docs/tutorial/request-files.md @@ -1,5 +1,6 @@ # 請求中的檔案 { #request-files } + 你可以使用 `File` 定義由用戶端上傳的檔案。 /// note diff --git a/docs/zh-hant/docs/tutorial/request-forms.md b/docs/zh-hant/docs/tutorial/request-forms.md index 28d50c3af..590779168 100644 --- a/docs/zh-hant/docs/tutorial/request-forms.md +++ b/docs/zh-hant/docs/tutorial/request-forms.md @@ -1,5 +1,6 @@ # 表單資料 { #form-data } + 當你需要接收表單欄位而不是 JSON 時,可以使用 `Form`。 /// note diff --git a/docs/zh-hant/docs/tutorial/response-status-code.md b/docs/zh-hant/docs/tutorial/response-status-code.md index 9ed047fa5..d649dc785 100644 --- a/docs/zh-hant/docs/tutorial/response-status-code.md +++ b/docs/zh-hant/docs/tutorial/response-status-code.md @@ -1,5 +1,6 @@ # 回應狀態碼 { #response-status-code } + 就像你可以指定回應模型一樣,你也可以在任一個「路徑操作(path operation)」的參數 `status_code` 中宣告回應所使用的 HTTP 狀態碼: * `@app.get()` diff --git a/docs/zh-hant/docs/tutorial/schema-extra-example.md b/docs/zh-hant/docs/tutorial/schema-extra-example.md index 01c4a217a..8cca5003a 100644 --- a/docs/zh-hant/docs/tutorial/schema-extra-example.md +++ b/docs/zh-hant/docs/tutorial/schema-extra-example.md @@ -10,7 +10,7 @@ {* ../../docs_src/schema_extra_example/tutorial001_py310.py hl[13:24] *} -這些額外資訊會原封不動加入該模型輸出的 JSON Schema,並且會用在 API 文件裡。 +這些額外資訊會原封不動加入該模型輸出的 **JSON Schema**,並且會用在 API 文件裡。 你可以使用屬性 `model_config`(接收一個 `dict`),詳見 [Pydantic 文件:Configuration](https://docs.pydantic.dev/latest/api/config/)。 @@ -135,7 +135,7 @@ OpenAPI 3.1.0(自 FastAPI 0.99.0 起使用)新增了對 `examples` 的支援 以下是關於 **JSON Schema** 與 **OpenAPI** 標準的技術細節。 -如果上面的做法對你已經足夠可用,就不需要這些細節,儘管直接跳過。 +如果上面的做法對你已經足夠可用,就不需要這些細節,可以直接跳過。 /// diff --git a/docs/zh-hant/docs/tutorial/security/first-steps.md b/docs/zh-hant/docs/tutorial/security/first-steps.md index b7db93b50..7640a4556 100644 --- a/docs/zh-hant/docs/tutorial/security/first-steps.md +++ b/docs/zh-hant/docs/tutorial/security/first-steps.md @@ -1,16 +1,16 @@ # 安全性 - 入門 { #security-first-steps } -想像你有一個部署在某個網域的後端 API。 +想像你有一個部署在某個網域的 **後端** API。 -還有一個前端在另一個網域,或同一網域的不同路徑(或是行動應用程式)。 +還有一個 **前端** 在另一個網域,或同一網域的不同路徑(或是行動應用程式)。 -你希望前端能用使用者名稱與密碼向後端進行身分驗證。 +你希望前端能用**使用者名稱**與**密碼**向後端進行身分驗證。 -我們可以用 OAuth2 搭配 FastAPI 來實作。 +我們可以用 **OAuth2** 搭配 **FastAPI** 來實作。 但不必通讀整份冗長規格只為了找出你需要的幾個重點。 -就用 FastAPI 提供的工具處理安全性。 +就用 **FastAPI** 提供的工具處理安全性。 ## 看起來如何 { #how-it-looks } @@ -26,7 +26,7 @@ /// note -當你使用 `pip install "fastapi[standard]"` 指令安裝時,[`python-multipart`](https://github.com/Kludex/python-multipart) 套件會隨 FastAPI 自動安裝。 +當你使用 `pip install "fastapi[standard]"` 指令安裝時,[`python-multipart`](https://github.com/Kludex/python-multipart) 套件會隨 **FastAPI** 自動安裝。 不過若只執行 `pip install fastapi`,預設不會包含 `python-multipart`。 @@ -36,7 +36,7 @@ $ pip install python-multipart ``` -因為 OAuth2 會以「form data」傳送 `username` 與 `password`。 +因為 **OAuth2** 會以「form data」傳送 `username` 與 `password`。 /// @@ -62,9 +62,9 @@ $ fastapi dev /// tip | Authorize 按鈕! -你會看到一個新的「Authorize」按鈕。 +你已經有一個亮眼的全新「Authorize」按鈕。 -而你的「路徑操作」右上角也會出現一個小鎖頭可以點擊。 +而你的 *路徑操作* 右上角也會出現一個小鎖頭可以點擊。 /// @@ -94,29 +94,29 @@ $ fastapi dev OAuth2 的設計讓後端或 API 可以獨立於執行使用者驗證的伺服器。 -但在這個例子中,同一個 FastAPI 應用會同時處理 API 與驗證。 +但在這個例子中,同一個 **FastAPI** 應用會同時處理 API 與驗證。 簡化來看流程如下: - 使用者在前端輸入 `username` 與 `password`,按下 `Enter`。 - 前端(在使用者的瀏覽器中執行)把 `username` 與 `password` 傳到我們 API 的特定 URL(在程式中宣告為 `tokenUrl="token"`)。 -- API 檢查 `username` 與 `password`,並回傳一個「token(權杖)」(我們還沒實作這部分)。 +- API 檢查 `username` 與 `password`,並回應一個「token(權杖)」(我們還沒實作這部分)。 - 「token(權杖)」就是一段字串,之後可用來識別並驗證此使用者。 - 通常 token 會設定一段時間後失效。 - 因此使用者之後需要重新登入。 - 若 token 被竊取,風險也較低;它不像永遠有效的萬用鑰匙(多數情況下)。 - 前端會暫存這個 token。 -- 使用者在前端點擊前往其他頁面/區段。 +- 使用者在前端點擊,前往前端網頁應用程式的另一個區段。 - 前端需要再向 API 取得資料。 - 但該端點需要驗證。 - 因此為了向 API 驗證,請求會帶上一個 `Authorization` 標頭,值為 `Bearer ` 加上 token。 - 例如 token 是 `foobar`,則 `Authorization` 標頭內容為:`Bearer foobar`。 -## FastAPI 的 `OAuth2PasswordBearer` { #fastapis-oauth2passwordbearer } +## **FastAPI** 的 `OAuth2PasswordBearer` { #fastapis-oauth2passwordbearer } -FastAPI 提供多層抽象的工具來實作這些安全機制。 +**FastAPI** 提供多層抽象的工具來實作這些安全機制。 -本例將使用 OAuth2 的 Password 流程,並以 Bearer token 進行驗證;我們會用 `OAuth2PasswordBearer` 類別來完成。 +本例將使用 **OAuth2** 的 **Password** 流程,並以 **Bearer** token 進行驗證;我們會用 `OAuth2PasswordBearer` 類別來完成。 /// note @@ -126,7 +126,7 @@ FastAPI 提供多層抽象的工具來實作這些安全機制。 通常對多數情境也足夠,除非你是 OAuth2 專家並確信有更適合你的選項。 -在那種情況下,FastAPI 也提供相應工具讓你自行組合。 +在那種情況下,**FastAPI** 也提供相應工具讓你自行組合。 /// @@ -144,7 +144,7 @@ FastAPI 提供多層抽象的工具來實作這些安全機制。 /// -這個參數不會建立該端點/「路徑操作」,而是宣告 `/token` 將是客戶端用來取得 token 的 URL。這些資訊會出現在 OpenAPI,並被互動式 API 文件系統使用。 +這個參數不會建立該端點 / *路徑操作*,而是宣告 `/token` 將是客戶端用來取得 token 的 URL。這些資訊會出現在 OpenAPI,並被互動式 API 文件系統使用。 我們很快也會建立實際的路徑操作。 @@ -172,15 +172,15 @@ oauth2_scheme(some, parameters) {* ../../docs_src/security/tutorial001_an_py310.py hl[12] *} -此相依性會提供一個 `str`,指派給「路徑操作函式」的參數 `token`。 +此相依性會提供一個 `str`,指派給 *路徑操作函式* 的參數 `token`。 -FastAPI 會知道可以使用這個相依性,在 OpenAPI(以及自動產生的 API 文件)中定義一個「安全性方案」。 +**FastAPI** 會知道可以使用這個相依性,在 OpenAPI schema(以及自動產生的 API 文件)中定義一個「安全性方案」。 /// note | 技術細節 -FastAPI 之所以知道可以用(相依性中宣告的)`OAuth2PasswordBearer` 類別,在 OpenAPI 中定義安全性方案,是因為它繼承自 `fastapi.security.oauth2.OAuth2`,而後者又繼承自 `fastapi.security.base.SecurityBase`。 +**FastAPI** 之所以知道可以用(相依性中宣告的)`OAuth2PasswordBearer` 類別,在 OpenAPI 中定義安全性方案,是因為它繼承自 `fastapi.security.oauth2.OAuth2`,而後者又繼承自 `fastapi.security.base.SecurityBase`。 -所有能與 OpenAPI(以及自動 API 文件)整合的安全工具都繼承自 `SecurityBase`,FastAPI 才能知道如何把它們整合進 OpenAPI。 +所有能與 OpenAPI(以及自動 API 文件)整合的安全工具都繼承自 `SecurityBase`,**FastAPI** 才能知道如何把它們整合進 OpenAPI。 /// @@ -188,7 +188,7 @@ FastAPI 之所以知道可以用(相依性中宣告的)`OAuth2PasswordBearer 它會從請求中尋找 `Authorization` 標頭,檢查其值是否為 `Bearer ` 加上一段 token,並將該 token 以 `str` 回傳。 -若未找到 `Authorization` 標頭,或其值不是 `Bearer ` token,則會直接回傳 401(`UNAUTHORIZED`)錯誤。 +若未找到 `Authorization` 標頭,或其值不是 `Bearer ` token,則會直接回應 401 狀態碼錯誤(`UNAUTHORIZED`)。 你不必再自行檢查 token 是否存在;你可以確信只要你的函式被執行,該 token 參數就一定會是 `str`。 diff --git a/docs/zh-hant/docs/tutorial/security/get-current-user.md b/docs/zh-hant/docs/tutorial/security/get-current-user.md index c17b6468e..5309d78c0 100644 --- a/docs/zh-hant/docs/tutorial/security/get-current-user.md +++ b/docs/zh-hant/docs/tutorial/security/get-current-user.md @@ -14,7 +14,7 @@ 就像用 Pydantic 宣告請求體一樣,我們也可以在其他地方使用它: -{* ../../docs_src/security/tutorial002_an_py310.py hl[5,12:6] *} +{* ../../docs_src/security/tutorial002_an_py310.py hl[5,12:16] *} ## 建立 `get_current_user` 依賴 { #create-a-get-current-user-dependency } diff --git a/docs/zh-hant/docs/tutorial/security/oauth2-jwt.md b/docs/zh-hant/docs/tutorial/security/oauth2-jwt.md index dba108c74..dc75092b4 100644 --- a/docs/zh-hant/docs/tutorial/security/oauth2-jwt.md +++ b/docs/zh-hant/docs/tutorial/security/oauth2-jwt.md @@ -120,7 +120,7 @@ pwdlib 也支援 bcrypt 雜湊演算法,但不包含傳統(legacy)演算 當以不存在於資料庫的使用者名稱呼叫 `authenticate_user` 時,我們仍然會拿一個假的雜湊去跑一次 `verify_password`。 -這可確保無論使用者名稱是否有效,端點的回應時間都大致相同,避免可用來枚舉既有使用者名稱的「計時攻擊」(timing attacks)。 +這可確保無論使用者名稱是否有效,端點的回應時間都大致相同,避免可用來枚舉既有使用者名稱的 **計時攻擊**(timing attacks)。 /// note | 注意 @@ -168,7 +168,7 @@ $ openssl rand -hex 32 {* ../../docs_src/security/tutorial004_an_py310.py hl[93:110] *} -## 更新 `/token` 路徑操作 { #update-the-token-path-operation } +## 更新 `/token` *路徑操作* { #update-the-token-path-operation } 用權杖有效期建立一個 `timedelta`。 diff --git a/docs/zh-hant/docs/tutorial/security/simple-oauth2.md b/docs/zh-hant/docs/tutorial/security/simple-oauth2.md index de0fe386d..2b29daa0d 100644 --- a/docs/zh-hant/docs/tutorial/security/simple-oauth2.md +++ b/docs/zh-hant/docs/tutorial/security/simple-oauth2.md @@ -132,7 +132,7 @@ OAuth2 規範中,當使用「password flow」(我們現在使用的)時, `UserInDB(**user_dict)` 的意思是: -把 `user_dict` 的鍵和值直接當作具名參數傳入,等同於: +*把 `user_dict` 的鍵和值直接當作具名參數傳入,等同於:* ```Python UserInDB( @@ -146,7 +146,7 @@ UserInDB( /// note -想更完整地了解 `**user_dict`,請回到[**額外模型** 的文件](../extra-models.md#about-user-in-dict)。 +想更完整地了解 `**user_dict`,請回到[**額外模型** 的文件](../extra-models.md#about-user-in-model-dump)。 /// diff --git a/docs/zh-hant/docs/tutorial/sql-databases.md b/docs/zh-hant/docs/tutorial/sql-databases.md index a37e16432..3a0e43d84 100644 --- a/docs/zh-hant/docs/tutorial/sql-databases.md +++ b/docs/zh-hant/docs/tutorial/sql-databases.md @@ -1,10 +1,10 @@ # SQL(關聯式)資料庫 { #sql-relational-databases } -FastAPI 不強制你使用 SQL(關聯式)資料庫。你可以使用任何你想要的資料庫。 +**FastAPI** 不強制你使用 SQL(關聯式)資料庫。但你可以使用**任何你想要的資料庫**。 這裡我們會用 [SQLModel](https://sqlmodel.tiangolo.com/) 作為範例。 -SQLModel 建立在 [SQLAlchemy](https://www.sqlalchemy.org/) 與 Pydantic 之上。它由 FastAPI 的作者開發,非常適合需要使用 SQL 資料庫的 FastAPI 應用。 +**SQLModel** 建立在 [SQLAlchemy](https://www.sqlalchemy.org/) 與 Pydantic 之上。它由 **FastAPI** 的作者開發,非常適合需要使用 **SQL 資料庫**的 FastAPI 應用。 /// tip | 提示 @@ -12,7 +12,7 @@ SQLModel 建立在 [SQLAlchemy](https://www.sqlalchemy.org/) 與 Pydantic 之上 /// -因為 SQLModel 建立在 SQLAlchemy 之上,你可以輕鬆使用 SQLAlchemy 所支援的任何資料庫(因此 SQLModel 也支援),例如: +因為 SQLModel 建立在 SQLAlchemy 之上,你可以輕鬆使用 SQLAlchemy 所支援的**任何資料庫**(因此 SQLModel 也支援),例如: * PostgreSQL * MySQL @@ -20,17 +20,17 @@ SQLModel 建立在 [SQLAlchemy](https://www.sqlalchemy.org/) 與 Pydantic 之上 * Oracle * Microsoft SQL Server,等等。 -在這個範例中,我們會使用 SQLite,因為它只用到單一檔案,而且 Python 內建支援。你可以直接複製這個範例並原樣執行。 +在這個範例中,我們會使用 **SQLite**,因為它只用到單一檔案,而且 Python 內建支援。你可以直接複製這個範例並原樣執行。 -之後,在你的正式環境應用中,你可能會想使用像 PostgreSQL 這類的資料庫伺服器。 +之後,在你的正式環境應用中,你可能會想使用像 **PostgreSQL** 這類的資料庫伺服器。 /// tip | 提示 -有一個包含 FastAPI 與 PostgreSQL 的官方專案腳手架,還有前端與更多工具:[https://github.com/fastapi/full-stack-fastapi-template](https://github.com/fastapi/full-stack-fastapi-template) +有一個包含 **FastAPI** 與 **PostgreSQL** 的官方專案產生器,還有前端與更多工具:[https://github.com/fastapi/full-stack-fastapi-template](https://github.com/fastapi/full-stack-fastapi-template) /// -這是一份非常簡短的教學,如果你想更全面學習資料庫、SQL,或更進階的功能,請參考 [SQLModel 文件](https://sqlmodel.tiangolo.com/)。 +這是一份非常簡單且簡短的教學,如果你想更全面學習資料庫、SQL,或更進階的功能,請參考 [SQLModel 文件](https://sqlmodel.tiangolo.com/)。 ## 安裝 `SQLModel` { #install-sqlmodel } @@ -47,9 +47,9 @@ $ pip install sqlmodel ## 建立只有單一模型的應用 { #create-the-app-with-a-single-model } -我們先用單一 SQLModel 模型建立這個應用的最簡版。 +我們先用單一 **SQLModel** 模型建立這個應用的最簡版。 -接著我們會在下方用多個模型來提升安全性與彈性。🤓 +接著我們會在下方用**多個模型**來提升安全性與彈性。🤓 ### 建立模型 { #create-models } @@ -57,43 +57,43 @@ $ pip install sqlmodel {* ../../docs_src/sql_databases/tutorial001_an_py310.py ln[1:11] hl[7:11] *} -`Hero` 類別與 Pydantic 模型非常相似(事實上,在底層它就是一個 Pydantic 模型)。 +`Hero` 類別與 Pydantic 模型非常相似(事實上,在底層它其實*就是一個 Pydantic 模型*)。 有幾點差異: -* `table=True` 告訴 SQLModel 這是一個「資料表模型」(table model),它應該代表 SQL 資料庫中的一個資料表,而不僅僅是「資料模型」(就像一般的 Pydantic 類別)。 +* `table=True` 告訴 SQLModel 這是一個*資料表模型*(table model),它應該代表 SQL 資料庫中的一個**資料表**,而不僅僅是*資料模型*(就像一般的 Pydantic 類別)。 -* `Field(primary_key=True)` 告訴 SQLModel,`id` 是 SQL 資料庫中的「主鍵」。 (你可以在 SQLModel 文件中進一步了解 SQL 主鍵) +* `Field(primary_key=True)` 告訴 SQLModel,`id` 是 SQL 資料庫中的**主鍵**(你可以在 SQLModel 文件中進一步了解 SQL 主鍵)。 - 注意:我們在主鍵欄位使用 `int | None`,這樣在 Python 程式碼中我們可以「在沒有 `id` 的情況下建立物件」(`id=None`),假設資料庫在儲存時會「自動產生」。SQLModel 瞭解資料庫會提供 `id`,並且在資料庫綱要中「將該欄位定義為非空的 `INTEGER`」。詳情請見 [SQLModel 文件:主鍵](https://sqlmodel.tiangolo.com/tutorial/create-db-and-table/#primary-key-id)。 + **注意:** 我們在主鍵欄位使用 `int | None`,這樣在 Python 程式碼中我們可以*在沒有 `id` 的情況下建立物件*(`id=None`),假設資料庫在儲存時會*自動產生*。SQLModel 瞭解資料庫會提供 `id`,並且在資料庫綱要中*將該欄位定義為非空的 `INTEGER`*。詳情請見 [SQLModel 文件:主鍵](https://sqlmodel.tiangolo.com/tutorial/create-db-and-table/#primary-key-id)。 -* `Field(index=True)` 告訴 SQLModel 應為此欄位建立「SQL 索引」,以便在用此欄位過濾讀取資料時更快查詢。 +* `Field(index=True)` 告訴 SQLModel 應為此欄位建立 **SQL 索引**,以便在用此欄位過濾讀取資料時更快查詢。 SQLModel 會知道宣告為 `str` 的欄位在 SQL 中會是 `TEXT`(或 `VARCHAR`,依資料庫而定)。 ### 建立引擎 { #create-an-engine } -SQLModel 的 `engine`(底層實際上是 SQLAlchemy 的 `engine`)是用來「維護與資料庫連線」的東西。 +SQLModel 的 `engine`(底層實際上是 SQLAlchemy 的 `engine`)是用來**維護與資料庫連線**的東西。 -你的程式中應該只有「單一 `engine` 物件」來連到同一個資料庫。 +你的程式中應該只有**單一 `engine` 物件**來連到同一個資料庫。 {* ../../docs_src/sql_databases/tutorial001_an_py310.py ln[14:18] hl[14:15,17:18] *} -使用 `check_same_thread=False` 允許 FastAPI 在不同執行緒中使用同一個 SQLite 資料庫。這是必要的,因為「單一請求」可能會使用「多個執行緒」(例如在依賴項中)。 +使用 `check_same_thread=False` 允許 FastAPI 在不同執行緒中使用同一個 SQLite 資料庫。這是必要的,因為**單一請求**可能會使用**多個執行緒**(例如在依賴項中)。 -別擔心,依照我們的程式結構,稍後我們會確保「每個請求只使用單一 SQLModel 的 session」,這其實就是 `check_same_thread` 想要達成的事。 +別擔心,依照我們的程式結構,稍後我們會確保**每個請求只使用單一 SQLModel 的 *session***,這其實就是 `check_same_thread` 想要達成的事。 ### 建立資料表 { #create-the-tables } -接著我們新增一個函式,使用 `SQLModel.metadata.create_all(engine)` 為所有「資料表模型」建立資料表。 +接著我們新增一個函式,使用 `SQLModel.metadata.create_all(engine)` 為所有*資料表模型* **建立資料表**。 {* ../../docs_src/sql_databases/tutorial001_an_py310.py ln[21:22] hl[21:22] *} ### 建立 Session 依賴 { #create-a-session-dependency } -「`Session`」會在記憶體中保存物件並追蹤資料需要的任何變更,然後透過「`engine`」與資料庫溝通。 +**`Session`** 會在記憶體中保存**物件**並追蹤資料需要的任何變更,然後透過 **`engine`** 與資料庫溝通。 -我們會用 `yield` 建立一個 FastAPI 的「依賴」,為每個請求提供一個新的 `Session`。這可確保每個請求只使用單一的 session。🤓 +我們會用 `yield` 建立一個 FastAPI 的**依賴**,為每個請求提供一個新的 `Session`。這可確保每個請求只使用單一的 session。🤓 接著我們建立一個 `Annotated` 的依賴 `SessionDep`,讓後續使用這個依賴的程式碼更簡潔。 @@ -117,11 +117,11 @@ SQLModel 之後會提供包裝 Alembic 的遷移工具,但目前你可以直 ### 建立 Hero { #create-a-hero } -因為每個 SQLModel 模型同時也是一個 Pydantic 模型,你可以在「型別標註」中像使用 Pydantic 模型一樣使用它。 +因為每個 SQLModel 模型同時也是一個 Pydantic 模型,你可以在與 Pydantic 模型相同的**型別標註**中使用它。 -例如,如果你宣告一個參數型別為 `Hero`,它會從「JSON body」中讀取。 +例如,如果你宣告一個參數型別為 `Hero`,它會從 **JSON body** 中讀取。 -同樣地,你也可以將它宣告為函式的「回傳型別」,然後在自動產生的 API 文件 UI 中就會顯示其資料結構。 +同樣地,你也可以將它宣告為函式的**回傳型別**,然後在自動產生的 API 文件 UI 中就會顯示其資料結構。 {* ../../docs_src/sql_databases/tutorial001_an_py310.py ln[40:45] hl[40:45] *} @@ -129,19 +129,19 @@ SQLModel 之後會提供包裝 Alembic 的遷移工具,但目前你可以直 ### 讀取多個 Hero { #read-heroes } -我們可以用 `select()` 從資料庫「讀取」多個 `Hero`。可以加入 `limit` 與 `offset` 來分頁。 +我們可以用 `select()` 從資料庫**讀取**多個 `Hero`。可以加入 `limit` 與 `offset` 來分頁。 {* ../../docs_src/sql_databases/tutorial001_an_py310.py ln[48:55] hl[51:52,54] *} ### 讀取單一 Hero { #read-one-hero } -我們可以「讀取」單一的 `Hero`。 +我們可以**讀取**單一的 `Hero`。 {* ../../docs_src/sql_databases/tutorial001_an_py310.py ln[58:63] hl[60] *} ### 刪除 Hero { #delete-a-hero } -我們也可以「刪除」一個 `Hero`。 +我們也可以**刪除**一個 `Hero`。 {* ../../docs_src/sql_databases/tutorial001_an_py310.py ln[66:73] hl[71] *} @@ -159,7 +159,7 @@ $ fastapi dev
-然後前往 `/docs` 的 UI,你會看到 FastAPI 使用這些模型來「文件化」API,也會用它們來「序列化」與「驗證」資料。 +然後前往 `/docs` 的 UI,你會看到 **FastAPI** 使用這些**模型**來**文件化** API,也會用它們來**序列化**與**驗證**資料。
@@ -167,27 +167,27 @@ $ fastapi dev ## 用多個模型更新應用 { #update-the-app-with-multiple-models } -現在我們稍微「重構」一下這個應用,以提升「安全性」與「彈性」。 +現在我們稍微**重構**一下這個應用,以提升**安全性**與**彈性**。 如果你檢查前一版的應用,在 UI 中你會看到,到目前為止它讓用戶端自己決定要建立的 `Hero` 的 `id`。😱 -我們不該允許這樣,因為他們可能會覆蓋資料庫中我們已分配的 `id`。決定 `id` 應該由「後端」或「資料庫」來做,「不是用戶端」。 +我們不該允許這樣,因為他們可能會覆蓋資料庫中我們已分配的 `id`。決定 `id` 應該由**後端**或**資料庫**來做,**不是用戶端**。 -另外,我們為 hero 建立了 `secret_name`,但目前我們在各處都把它回傳出去,這一點都不「保密」... 😅 +另外,我們為 hero 建立了 `secret_name`,但目前我們在各處都把它回傳出去,這一點都不**保密**... 😅 -我們會透過加入一些「額外模型」來修正這些問題。這正是 SQLModel 大放異彩的地方。✨ +我們會透過加入一些**額外模型**來修正這些問題。這正是 SQLModel 大放異彩的地方。✨ ### 建立多個模型 { #create-multiple-models } -在 SQLModel 中,任何設了 `table=True` 的模型類別都是「資料表模型」。 +在 **SQLModel** 中,任何設了 `table=True` 的模型類別都是**資料表模型**。 -而沒有設 `table=True` 的模型類別就是「資料模型」,這些其實就是 Pydantic 模型(只有一點小增強)。🤓 +而沒有設 `table=True` 的模型類別就是**資料模型**,這些其實就是 Pydantic 模型(只有一點小增強)。🤓 -使用 SQLModel,我們可以利用「繼承」來「避免重複」在各種情況下一再宣告所有欄位。 +使用 SQLModel,我們可以利用**繼承**來**避免重複**在各種情況下一再宣告所有欄位。 #### `HeroBase` - 基底類別 { #herobase-the-base-class } -先從 `HeroBase` 模型開始,它包含所有模型「共享」的欄位: +先從 `HeroBase` 模型開始,它包含所有模型**共享**的欄位: * `name` * `age` @@ -196,12 +196,12 @@ $ fastapi dev #### `Hero` - 資料表模型 { #hero-the-table-model } -接著建立 `Hero`,也就是實際的「資料表模型」,它包含不一定會出現在其他模型中的「額外欄位」: +接著建立 `Hero`,也就是實際的*資料表模型*,它包含不一定會出現在其他模型中的**額外欄位**: * `id` * `secret_name` -因為 `Hero` 繼承自 `HeroBase`,它「也」擁有 `HeroBase` 中宣告的「欄位」,因此 `Hero` 的完整欄位為: +因為 `Hero` 繼承自 `HeroBase`,它**也**擁有 `HeroBase` 中宣告的**欄位**,因此 `Hero` 的完整欄位為: * `id` * `name` @@ -212,19 +212,19 @@ $ fastapi dev #### `HeroPublic` - 公開的資料模型 { #heropublic-the-public-data-model } -接下來建立 `HeroPublic` 模型,它是要「回傳」給 API 用戶端的模型。 +接下來建立 `HeroPublic` 模型,它是要**回傳**給 API 用戶端的模型。 它擁有與 `HeroBase` 相同的欄位,因此不會包含 `secret_name`。 終於,我們英雄的真實身分受保護了!🥷 -它也重新宣告了 `id: int`。這麼做是與 API 用戶端訂立一個「契約」,讓他們可以確定 `id` 一定存在而且是 `int`(不會是 `None`)。 +它也重新宣告了 `id: int`。這麼做是與 API 用戶端訂立一個**契約**,讓他們可以確定 `id` 一定存在而且是 `int`(不會是 `None`)。 /// tip | 提示 讓回傳模型保證某個值一定存在、而且一定是 `int`(不是 `None`),對 API 用戶端非常有幫助。他們在有這個確信下可以寫出更簡單的程式碼。 -此外,透過「自動產生的客戶端」也會有更簡潔的介面,讓要使用你 API 的開發者能有更好的開發體驗。😎 +此外,透過**自動產生的客戶端**也會有更簡潔的介面,讓要使用你 API 的開發者能有更好的開發體驗。😎 /// @@ -238,17 +238,17 @@ $ fastapi dev #### `HeroCreate` - 用於建立 Hero 的資料模型 { #herocreate-the-data-model-to-create-a-hero } -現在我們建立 `HeroCreate` 模型,這是用來「驗證」用戶端送來資料的模型。 +現在我們建立 `HeroCreate` 模型,這是用來**驗證**用戶端送來資料的模型。 它具有與 `HeroBase` 相同的欄位,並且還有 `secret_name`。 -接下來,當用戶端「建立新 hero」時,他們會送上 `secret_name`,它會被儲存在資料庫中,但這些祕密名稱不會在 API 中回傳給用戶端。 +接下來,當用戶端**建立新 hero** 時,他們會送上 `secret_name`,它會被儲存在資料庫中,但這些祕密名稱不會在 API 中回傳給用戶端。 /// tip | 提示 -這也就是你處理「密碼」的方式。接收它們,但不要在 API 中回傳。 +這也就是你處理**密碼**的方式。接收它們,但不要在 API 中回傳。 -你也應該在儲存前先對密碼做「雜湊」,「永遠不要以明文儲存」。 +你也應該在儲存前先對密碼做**雜湊**,**永遠不要以明文儲存**。 /// @@ -262,11 +262,11 @@ $ fastapi dev #### `HeroUpdate` - 用於更新 Hero 的資料模型 { #heroupdate-the-data-model-to-update-a-hero } -在前一版的應用中,我們沒有「更新 hero」的方式,但現在有了「多個模型」,我們就能做到。🎉 +在前一版的應用中,我們沒有**更新 hero** 的方式,但現在有了**多個模型**,我們就能做到。🎉 -`HeroUpdate` 這個資料模型有點特別,它包含「建立新 hero 所需的所有欄位」,但所有欄位都是「可選的」(都有預設值)。這樣在更新時,你只需要送出想要更新的欄位即可。 +`HeroUpdate` 這個*資料模型*有點特別,它包含**建立新 hero 所需的所有欄位**,但所有欄位都是**可選的**(都有預設值)。這樣在更新時,你只需要送出想要更新的欄位即可。 -因為所有欄位的「型別其實都改變了」(型別現在包含 `None`,而且預設值為 `None`),我們需要「重新宣告」它們。 +因為所有**欄位其實都改變了**(型別現在包含 `None`,而且預設值為 `None`),我們需要**重新宣告**它們。 其實不一定要繼承 `HeroBase`,因為我們會重新宣告所有欄位。我這裡保留繼承只是為了一致性,並非必要。這主要是個人偏好的問題。🤷 @@ -280,43 +280,43 @@ $ fastapi dev ### 用 `HeroCreate` 建立並回傳 `HeroPublic` { #create-with-herocreate-and-return-a-heropublic } -現在我們有了「多個模型」,可以更新應用中使用它們的部分。 +現在我們有了**多個模型**,可以更新應用中使用它們的部分。 -我們在請求中接收 `HeroCreate`(資料模型),並由它建立一個 `Hero`(資料表模型)。 +我們在請求中接收 `HeroCreate` *資料模型*,並由它建立一個 `Hero` *資料表模型*。 -這個新的資料表模型 `Hero` 會有用戶端傳來的欄位,並且會由資料庫產生一個 `id`。 +這個新的*資料表模型* `Hero` 會有用戶端傳來的欄位,並且會由資料庫產生一個 `id`。 -然後我們直接從函式回傳這個資料表模型 `Hero`。但因為我們用 `HeroPublic` 當作 `response_model`,FastAPI 會用 `HeroPublic` 來驗證與序列化資料。 +然後我們直接從函式回傳這個*資料表模型* `Hero`。但因為我們用 `HeroPublic` *資料模型*當作 `response_model`,**FastAPI** 會用 `HeroPublic` 來驗證與序列化資料。 {* ../../docs_src/sql_databases/tutorial002_an_py310.py ln[56:62] hl[56:58] *} /// tip | 提示 -現在我們用 `response_model=HeroPublic`,而不是用回傳型別標註 `-> HeroPublic`,因為我們實際回傳的值其實「不是」`HeroPublic`。 +現在我們用 `response_model=HeroPublic`,而不是用**回傳型別標註** `-> HeroPublic`,因為我們實際回傳的值其實*不是* `HeroPublic`。 如果我們宣告 `-> HeroPublic`,你的編輯器與 linter 會(理所當然地)抱怨你回傳的是 `Hero` 而不是 `HeroPublic`。 -在 `response_model` 中宣告,就是要讓 FastAPI 去做它該做的事,而不影響型別標註,以及你的編輯器與其他工具提供的協助。 +在 `response_model` 中宣告,就是要讓 **FastAPI** 去做它該做的事,而不影響型別標註,以及你的編輯器與其他工具提供的協助。 /// ### 使用 `HeroPublic` 讀取多個 Hero { #read-heroes-with-heropublic } -我們可以像先前一樣「讀取」多個 `Hero`。同樣地,我們使用 `response_model=list[HeroPublic]` 來確保資料被正確驗證與序列化。 +我們可以像先前一樣**讀取**多個 `Hero`。同樣地,我們使用 `response_model=list[HeroPublic]` 來確保資料被正確驗證與序列化。 {* ../../docs_src/sql_databases/tutorial002_an_py310.py ln[65:72] hl[65] *} ### 使用 `HeroPublic` 讀取單一 Hero { #read-one-hero-with-heropublic } -我們可以「讀取」單一 hero: +我們可以**讀取**單一 hero: {* ../../docs_src/sql_databases/tutorial002_an_py310.py ln[75:80] hl[77] *} ### 使用 `HeroUpdate` 更新 Hero { #update-a-hero-with-heroupdate } -我們可以「更新 hero」。為此我們使用 HTTP 的 `PATCH` 操作。 +我們可以**更新 hero**。為此我們使用 HTTP 的 `PATCH` 操作。 -在程式碼中,我們會取得一個只包含用戶端有傳送的資料的 `dict`,不包含只是因為有預設值而存在的欄位。為了達成這點,我們使用 `exclude_unset=True`。這是關鍵。🪄 +在程式碼中,我們會取得一個只包含用戶端有傳送的資料的 `dict`,**只包含用戶端傳送的資料**,不包含只是因為有預設值而存在的欄位。為了達成這點,我們使用 `exclude_unset=True`。這是關鍵。🪄 然後我們使用 `hero_db.sqlmodel_update(hero_data)` 以 `hero_data` 的資料更新 `hero_db`。 @@ -324,7 +324,7 @@ $ fastapi dev ### 再次刪除 Hero { #delete-a-hero-again } -「刪除」 hero 基本上維持不變。 +**刪除** hero 基本上維持不變。 我們不會為了重構而重構一切。😅 @@ -352,6 +352,6 @@ $ fastapi dev ## 總結 { #recap } -你可以使用 [SQLModel](https://sqlmodel.tiangolo.com/) 與 SQL 資料庫互動,並用「資料模型」與「資料表模型」讓程式碼更簡潔。 +你可以使用 [**SQLModel**](https://sqlmodel.tiangolo.com/) 與 SQL 資料庫互動,並用*資料模型*與*資料表模型*讓程式碼更簡潔。 -你可以在 SQLModel 文件學到更多內容,這裡還有一份更長的 [使用 SQLModel 與 FastAPI 的教學](https://sqlmodel.tiangolo.com/tutorial/fastapi/)。🚀 +你可以在 **SQLModel** 文件學到更多內容,這裡還有一份更長的 [使用 SQLModel 與 **FastAPI** 的教學](https://sqlmodel.tiangolo.com/tutorial/fastapi/)。🚀 diff --git a/docs/zh-hant/docs/tutorial/static-files.md b/docs/zh-hant/docs/tutorial/static-files.md index 1b9e92a1c..0d6369eef 100644 --- a/docs/zh-hant/docs/tutorial/static-files.md +++ b/docs/zh-hant/docs/tutorial/static-files.md @@ -2,6 +2,14 @@ 你可以使用 `StaticFiles` 從某個目錄自動提供靜態檔案。 +/// tip + +如果你需要託管前端,請改用 `app.frontend()`,請在 [前端](frontend.md) 閱讀相關內容。 + +`app.frontend()` 底層使用 `StaticFiles`,並為前端提供幾項額外優勢,例如處理客戶端路由。 + +/// + ## 使用 `StaticFiles` { #use-staticfiles } - 匯入 `StaticFiles`。 diff --git a/docs/zh-hant/docs/tutorial/testing.md b/docs/zh-hant/docs/tutorial/testing.md index ab9dac93c..09f6c0ec7 100644 --- a/docs/zh-hant/docs/tutorial/testing.md +++ b/docs/zh-hant/docs/tutorial/testing.md @@ -113,13 +113,13 @@ $ pip install httpx │   └── test_main.py ``` -假設現在你的 **FastAPI** 應用所在的 `main.py` 有一些其他的路徑操作(path operations)。 +假設現在你的 **FastAPI** 應用所在的 `main.py` 有一些其他的 **路徑操作**。 它有一個可能回傳錯誤的 `GET` 操作。 它有一個可能回傳多種錯誤的 `POST` 操作。 -兩個路徑操作都需要一個 `X-Token` 標頭(header)。 +兩個 *路徑操作* 都需要一個 `X-Token` 標頭(header)。 {* ../../docs_src/app_testing/app_b_an_py310/main.py *} @@ -136,11 +136,11 @@ $ pip install httpx 例如: -* 要傳遞路徑或查詢參數,直接把它加在 URL 上。 +* 要傳遞 *path* 或 *query* 參數,直接把它加在 URL 上。 * 要傳遞 JSON 本文,將 Python 物件(例如 `dict`)傳給 `json` 參數。 -* 如果需要送出表單資料(Form Data)而不是 JSON,改用 `data` 參數。 -* 要傳遞標頭(headers),在 `headers` 參數中放一個 `dict`。 -* 對於 Cookie(cookies),在 `cookies` 參數中放一個 `dict`。 +* 如果需要送出 *Form Data* 而不是 JSON,改用 `data` 參數。 +* 要傳遞 *headers*,在 `headers` 參數中放一個 `dict`。 +* 對於 *cookies*,在 `cookies` 參數中放一個 `dict`。 關於如何把資料傳給後端(使用 `httpx` 或 `TestClient`),更多資訊請參考 [HTTPX 文件](https://www.python-httpx.org)。 diff --git a/docs/zh-hant/docs/virtual-environments.md b/docs/zh-hant/docs/virtual-environments.md index a4d649c13..550363413 100644 --- a/docs/zh-hant/docs/virtual-environments.md +++ b/docs/zh-hant/docs/virtual-environments.md @@ -73,7 +73,7 @@ $ python -m venv .venv
-/// details | 上述命令的含義 +/// details | 上述指令的含義 * `python`: 使用名為 `python` 的程式 * `-m`: 以腳本的方式呼叫一個模組,我們將告訴它接下來使用哪個模組 @@ -106,7 +106,7 @@ $ uv venv //// -這個命令會在一個名為 `.venv` 的目錄中建立一個新的虛擬環境。 +這個指令會在一個名為 `.venv` 的目錄中建立一個新的虛擬環境。 /// details | `.venv`,或是其他名稱 @@ -164,7 +164,7 @@ $ source .venv/Scripts/activate /// tip -每次你在這個環境中安裝一個**新的套件**時,都需要**重新啟動**這個環境。 +每次你在這個環境中安裝一個**新的套件**時,都需要**再次啟用**這個環境。 這麼做確保了當你使用一個由這個套件安裝的**終端(CLI)程式**時,你使用的是你的虛擬環境中的程式,而不是全域安裝、可能版本不同的程式。 @@ -242,7 +242,7 @@ $ python -m pip install --upgrade pip
-/// tip | 注意 +/// tip 有時你在嘗試升級 pip 時,可能會遇到 **`No module named pip`** 的錯誤。 @@ -544,7 +544,7 @@ Python 套件在推出**新版本**時通常會儘量**避免破壞性更改** 現在,想像一下如果有**許多**其他**套件**,它們都是你的**專案所依賴的**。這樣是非常難以管理的。你可能會發現有些專案使用了一些**不相容的套件版本**,而無法得知為什麼某些程式無法正常運作。 -此外,取決於你的操作系統(例如 Linux、Windows、macOS),它可能已經預先安裝了 Python。在這種情況下,它可能已經有一些系統所需的套件和特定版本。如果你在全域 Python 環境中安裝套件,可能會**破壞**某些隨作業系統一起安裝的程式。 +此外,取決於你的作業系統(例如 Linux、Windows、macOS),它可能已經預先安裝了 Python。在這種情況下,它可能已經有一些系統所需的套件和特定版本。如果你在全域 Python 環境中安裝套件,可能會**破壞**某些隨作業系統一起安裝的程式。 ## 套件安裝在哪裡 { #where-are-packages-installed } From 704927a066baaf3d680446bdee700b9b8e16c13e Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Wed, 1 Jul 2026 13:59:57 +0000 Subject: [PATCH 378/462] =?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 24f97509a..f6809c6fb 100644 --- a/docs/en/docs/release-notes.md +++ b/docs/en/docs/release-notes.md @@ -9,6 +9,7 @@ hide: ### Translations +* 🌐 Update translations for zh-hant (update-outdated). PR [#15896](https://github.com/fastapi/fastapi/pull/15896) by [@tiangolo](https://github.com/tiangolo). * 🌐 Update translations for de (update-outdated). PR [#15899](https://github.com/fastapi/fastapi/pull/15899) by [@tiangolo](https://github.com/tiangolo). * 🌐 Update translations for es (update-outdated). PR [#15892](https://github.com/fastapi/fastapi/pull/15892) by [@tiangolo](https://github.com/tiangolo). * 🌐 Update translations for tr (update-outdated). PR [#15891](https://github.com/fastapi/fastapi/pull/15891) by [@tiangolo](https://github.com/tiangolo). From 8dc852df4713efa998d126c5194302e9f06e7675 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Wed, 1 Jul 2026 13:59:58 +0000 Subject: [PATCH 379/462] =?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 f6809c6fb..38f3ef0d5 100644 --- a/docs/en/docs/release-notes.md +++ b/docs/en/docs/release-notes.md @@ -9,6 +9,7 @@ hide: ### Translations +* 🌐 Update translations for ja (update-outdated). PR [#15895](https://github.com/fastapi/fastapi/pull/15895) by [@tiangolo](https://github.com/tiangolo). * 🌐 Update translations for zh-hant (update-outdated). PR [#15896](https://github.com/fastapi/fastapi/pull/15896) by [@tiangolo](https://github.com/tiangolo). * 🌐 Update translations for de (update-outdated). PR [#15899](https://github.com/fastapi/fastapi/pull/15899) by [@tiangolo](https://github.com/tiangolo). * 🌐 Update translations for es (update-outdated). PR [#15892](https://github.com/fastapi/fastapi/pull/15892) by [@tiangolo](https://github.com/tiangolo). From 9d7d7febd3a66844f948254c1ba4745b6cc16f40 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebasti=C3=A1n=20Ram=C3=ADrez?= Date: Wed, 1 Jul 2026 16:06:27 +0200 Subject: [PATCH 380/462] =?UTF-8?q?=F0=9F=8C=90=20Update=20translations=20?= =?UTF-8?q?for=20fr=20(update-outdated)=20(#15897)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: github-actions[bot] Co-authored-by: Yurii Motov --- docs/fr/docs/_llm-test.md | 2 +- .../docs/advanced/additional-status-codes.md | 2 +- .../fr/docs/advanced/advanced-dependencies.md | 2 +- docs/fr/docs/advanced/dataclasses.md | 4 +- docs/fr/docs/advanced/events.md | 6 +- docs/fr/docs/advanced/generate-clients.md | 16 +- docs/fr/docs/advanced/json-base64-bytes.md | 8 +- docs/fr/docs/advanced/openapi-callbacks.md | 32 +-- .../advanced/response-change-status-code.md | 2 +- docs/fr/docs/advanced/response-cookies.md | 1 + docs/fr/docs/advanced/response-headers.md | 6 +- .../docs/advanced/security/oauth2-scopes.md | 14 +- docs/fr/docs/advanced/settings.md | 2 +- docs/fr/docs/advanced/stream-data.md | 8 +- docs/fr/docs/advanced/wsgi.md | 1 + docs/fr/docs/alternatives.md | 81 ++++--- docs/fr/docs/async.md | 200 +++++++++--------- docs/fr/docs/deployment/cloud.md | 4 +- docs/fr/docs/deployment/concepts.md | 1 + docs/fr/docs/deployment/docker.md | 4 +- docs/fr/docs/deployment/https.md | 6 +- docs/fr/docs/deployment/manually.md | 10 +- docs/fr/docs/editor-support.md | 2 +- docs/fr/docs/environment-variables.md | 28 +-- docs/fr/docs/features.md | 8 +- docs/fr/docs/help-fastapi.md | 1 + docs/fr/docs/how-to/configure-swagger-ui.md | 4 +- .../docs/how-to/custom-request-and-route.md | 2 +- docs/fr/docs/how-to/graphql.md | 6 +- ...migrate-from-pydantic-v1-to-pydantic-v2.md | 18 ++ .../docs/how-to/separate-openapi-schemas.md | 10 +- docs/fr/docs/index.md | 6 +- docs/fr/docs/project-generation.md | 1 + docs/fr/docs/python-types.md | 8 +- docs/fr/docs/tutorial/bigger-applications.md | 30 +-- docs/fr/docs/tutorial/body-nested-models.md | 8 +- docs/fr/docs/tutorial/body.md | 26 +-- docs/fr/docs/tutorial/debugging.md | 20 +- .../dependencies/dependencies-with-yield.md | 13 +- docs/fr/docs/tutorial/extra-data-types.md | 2 +- docs/fr/docs/tutorial/extra-models.md | 46 ++-- docs/fr/docs/tutorial/first-steps.md | 32 +-- docs/fr/docs/tutorial/handling-errors.md | 4 +- docs/fr/docs/tutorial/index.md | 1 + docs/fr/docs/tutorial/metadata.md | 2 +- .../tutorial/path-operation-configuration.md | 1 + .../tutorial/query-params-str-validations.md | 8 +- docs/fr/docs/tutorial/query-params.md | 3 +- docs/fr/docs/tutorial/request-files.md | 1 + docs/fr/docs/tutorial/request-forms.md | 2 +- docs/fr/docs/tutorial/response-status-code.md | 1 + docs/fr/docs/tutorial/schema-extra-example.md | 14 +- docs/fr/docs/tutorial/security/first-steps.md | 36 ++-- .../tutorial/security/get-current-user.md | 2 +- docs/fr/docs/tutorial/security/oauth2-jwt.md | 12 +- .../docs/tutorial/security/simple-oauth2.md | 18 +- docs/fr/docs/tutorial/sql-databases.md | 14 +- docs/fr/docs/tutorial/static-files.md | 8 + docs/fr/docs/tutorial/testing.md | 4 +- docs/fr/docs/virtual-environments.md | 104 ++++----- 60 files changed, 471 insertions(+), 447 deletions(-) diff --git a/docs/fr/docs/_llm-test.md b/docs/fr/docs/_llm-test.md index 9ee61126e..02092c89d 100644 --- a/docs/fr/docs/_llm-test.md +++ b/docs/fr/docs/_llm-test.md @@ -148,7 +148,7 @@ Du texte //// tab | Info -Les onglets et les blocs « Info »/« Note »/« Warning »/etc. doivent avoir la traduction de leur titre ajoutée après une barre verticale (« | »). +Les onglets et les blocs « Info »/« Note »/« Warning »/etc. doivent avoir la traduction de leur titre ajoutée après une barre verticale (`|`). Voir les sections `### Special blocks` et `### Tab blocks` dans l’invite générale dans `scripts/translate.py`. diff --git a/docs/fr/docs/advanced/additional-status-codes.md b/docs/fr/docs/advanced/additional-status-codes.md index 59e8c3eae..5d50666f5 100644 --- a/docs/fr/docs/advanced/additional-status-codes.md +++ b/docs/fr/docs/advanced/additional-status-codes.md @@ -1,6 +1,6 @@ # Codes HTTP supplémentaires { #additional-status-codes } -Par défaut, **FastAPI** renverra les réponses à l'aide d'une structure de données `JSONResponse`, en plaçant la réponse de votre *chemin d'accès* à l'intérieur de cette `JSONResponse`. +Par défaut, **FastAPI** renverra les réponses en utilisant une `JSONResponse`, en plaçant le contenu que vous renvoyez depuis votre *chemin d'accès* à l'intérieur de cette `JSONResponse`. Il utilisera le code HTTP par défaut ou celui que vous avez défini dans votre *chemin d'accès*. diff --git a/docs/fr/docs/advanced/advanced-dependencies.md b/docs/fr/docs/advanced/advanced-dependencies.md index 4ff72581c..e0003552d 100644 --- a/docs/fr/docs/advanced/advanced-dependencies.md +++ b/docs/fr/docs/advanced/advanced-dependencies.md @@ -36,7 +36,7 @@ Nous pouvons créer une instance de cette classe avec : {* ../../docs_src/dependencies/tutorial011_an_py310.py hl[18] *} -Et de cette façon, nous pouvons « paramétrer » notre dépendance, qui contient maintenant « bar », en tant qu’attribut `checker.fixed_content`. +Et de cette façon, nous pouvons « paramétrer » notre dépendance, qui contient maintenant `"bar"`, en tant qu’attribut `checker.fixed_content`. ## Utiliser l'instance comme dépendance { #use-the-instance-as-a-dependency } diff --git a/docs/fr/docs/advanced/dataclasses.md b/docs/fr/docs/advanced/dataclasses.md index 057e49df2..01d136910 100644 --- a/docs/fr/docs/advanced/dataclasses.md +++ b/docs/fr/docs/advanced/dataclasses.md @@ -6,7 +6,7 @@ Mais FastAPI prend aussi en charge l'utilisation de [`dataclasses`](https://docs {* ../../docs_src/dataclasses_/tutorial001_py310.py hl[1,6:11,18:19] *} -Cela fonctionne grâce à **Pydantic**, qui offre une [prise en charge interne des `dataclasses`](https://docs.pydantic.dev/latest/concepts/dataclasses/#use-of-stdlib-dataclasses-with-basemodel). +C'est toujours pris en charge grâce à **Pydantic**, qui offre une [prise en charge interne des `dataclasses`](https://docs.pydantic.dev/latest/concepts/dataclasses/#use-of-stdlib-dataclasses-with-basemodel). Ainsi, même avec le code ci‑dessus qui n'emploie pas explicitement Pydantic, FastAPI utilise Pydantic pour convertir ces dataclasses standard en la variante de dataclasses de Pydantic. @@ -20,7 +20,7 @@ Cela fonctionne de la même manière qu'avec les modèles Pydantic. Et, en réal /// note | Remarque -Gardez à l'esprit que les dataclasses ne peuvent pas tout ce que peuvent faire les modèles Pydantic. +Gardez à l'esprit que les dataclasses ne peuvent pas faire tout ce que peuvent faire les modèles Pydantic. Vous pourriez donc avoir encore besoin d'utiliser des modèles Pydantic. diff --git a/docs/fr/docs/advanced/events.md b/docs/fr/docs/advanced/events.md index 5b90c7b2e..4ab175239 100644 --- a/docs/fr/docs/advanced/events.md +++ b/docs/fr/docs/advanced/events.md @@ -102,7 +102,7 @@ Ces fonctions peuvent être déclarées avec `async def` ou un `def` normal. ### Événement `startup` { #startup-event } -Pour ajouter une fonction qui doit être exécutée avant le démarrage de l'application, déclarez-la avec l'événement « startup » : +Pour ajouter une fonction qui doit être exécutée avant le démarrage de l'application, déclarez-la avec l'événement `"startup"` : {* ../../docs_src/events/tutorial001_py310.py hl[8] *} @@ -114,11 +114,11 @@ Et votre application ne commencera pas à recevoir des requêtes avant que tous ### Événement `shutdown` { #shutdown-event } -Pour ajouter une fonction qui doit être exécutée lorsque l'application s'arrête, déclarez-la avec l'événement « shutdown » : +Pour ajouter une fonction qui doit être exécutée lorsque l'application s'arrête, déclarez-la avec l'événement `"shutdown"` : {* ../../docs_src/events/tutorial002_py310.py hl[6] *} -Ici, la fonction gestionnaire de l'événement `shutdown` écrira une ligne de texte « Application shutdown » dans un fichier `log.txt`. +Ici, la fonction gestionnaire de l'événement `shutdown` écrira une ligne de texte `"Application shutdown"` dans un fichier `log.txt`. /// note | Remarque diff --git a/docs/fr/docs/advanced/generate-clients.md b/docs/fr/docs/advanced/generate-clients.md index 5625b0648..7aa0a5150 100644 --- a/docs/fr/docs/advanced/generate-clients.md +++ b/docs/fr/docs/advanced/generate-clients.md @@ -20,20 +20,6 @@ FastAPI génère automatiquement des spécifications **OpenAPI 3.1**, donc tout /// -## Générateurs de SDK par les sponsors de FastAPI { #sdk-generators-from-fastapi-sponsors } - -Cette section met en avant des solutions **soutenues par des fonds** et **par des entreprises** qui sponsorisent FastAPI. Ces produits offrent **des fonctionnalités supplémentaires** et **des intégrations** en plus de SDK de haute qualité générés. - -En ✨ [**sponsorisant FastAPI**](../help-fastapi.md#sponsor-the-author) ✨, ces entreprises contribuent à garantir que le framework et son **écosystème** restent sains et **durables**. - -Leur sponsoring démontre également un fort engagement envers la **communauté** FastAPI (vous), montrant qu’elles se soucient non seulement d’offrir un **excellent service**, mais aussi de soutenir un **framework robuste et florissant**, FastAPI. 🙇 - -Par exemple, vous pourriez essayer : - -* [Stainless](https://www.stainless.com/?utm_source=fastapi&utm_medium=referral) - -Certaines de ces solutions peuvent aussi être open source ou proposer des niveaux gratuits, afin que vous puissiez les essayer sans engagement financier. D’autres générateurs de SDK commerciaux existent et peuvent être trouvés en ligne. 🤓 - ## Créer un SDK TypeScript { #create-a-typescript-sdk } Commençons par une application FastAPI simple : @@ -56,7 +42,7 @@ Ces mêmes informations issues des modèles, incluses dans OpenAPI, peuvent êtr ### Hey API { #hey-api } -Une fois que vous avez une application FastAPI avec les modèles, vous pouvez utiliser Hey API pour générer un client TypeScript. Le moyen le plus rapide de le faire est via npx. +Une fois que nous avons une application FastAPI avec les modèles, nous pouvons utiliser Hey API pour générer un client TypeScript. Le moyen le plus rapide de le faire est via npx. ```sh npx @hey-api/openapi-ts -i http://localhost:8000/openapi.json -o src/client diff --git a/docs/fr/docs/advanced/json-base64-bytes.md b/docs/fr/docs/advanced/json-base64-bytes.md index 1b5acb081..4d9bdd602 100644 --- a/docs/fr/docs/advanced/json-base64-bytes.md +++ b/docs/fr/docs/advanced/json-base64-bytes.md @@ -4,7 +4,7 @@ Si votre application doit recevoir et envoyer des données JSON, mais que vous d ## Base64 vs fichiers { #base64-vs-files } -Envisagez d'abord d'utiliser [Fichiers de requête](../tutorial/request-files.md) pour téléverser des données binaires et [Réponse personnalisée - FileResponse](./custom-response.md#fileresponse--fileresponse-) pour envoyer des données binaires, plutôt que de les encoder dans du JSON. +Envisagez d'abord d'utiliser [Fichiers de requête](../tutorial/request-files.md) pour téléverser des données binaires et [Réponse personnalisée - FileResponse](./custom-response.md#fileresponse) pour envoyer des données binaires, plutôt que de les encoder dans du JSON. JSON ne peut contenir que des chaînes encodées en UTF-8, il ne peut donc pas contenir d'octets bruts. @@ -14,7 +14,7 @@ N'utilisez base64 que si vous devez absolument inclure des données binaires dan ## Pydantic `bytes` { #pydantic-bytes } -Vous pouvez déclarer un modèle Pydantic avec des champs `bytes`, puis utiliser `val_json_bytes` dans la configuration du modèle pour lui indiquer d'utiliser base64 pour valider les données JSON en entrée ; dans le cadre de cette validation, il décodera la chaîne base64 en octets. +Vous pouvez déclarer un modèle Pydantic avec des champs `bytes`, puis utiliser `val_json_bytes` dans la configuration du modèle pour lui indiquer d'utiliser base64 pour *valider* les données JSON en entrée ; dans le cadre de cette validation, il décodera la chaîne base64 en octets. {* ../../docs_src/json_base64_bytes/tutorial001_py310.py ln[1:9,29:35] hl[9] *} @@ -52,12 +52,12 @@ Vous recevrez une réponse comme : ## Pydantic `bytes` pour les données de sortie { #pydantic-bytes-for-output-data } -Vous pouvez également utiliser des champs `bytes` avec `ser_json_bytes` dans la configuration du modèle pour les données de sortie ; Pydantic sérialisera alors les octets en base64 lors de la génération de la réponse JSON. +Vous pouvez également utiliser des champs `bytes` avec `ser_json_bytes` dans la configuration du modèle pour les données de sortie ; Pydantic *sérialisera* alors les octets en base64 lors de la génération de la réponse JSON. {* ../../docs_src/json_base64_bytes/tutorial001_py310.py ln[1:2,12:16,29,38:41] hl[16] *} ## Pydantic `bytes` pour les données d'entrée et de sortie { #pydantic-bytes-for-input-and-output-data } -Et bien sûr, vous pouvez utiliser le même modèle configuré pour utiliser base64 afin de gérer à la fois l'entrée (valider) avec `val_json_bytes` et la sortie (sérialiser) avec `ser_json_bytes` lors de la réception et de l'envoi de données JSON. +Et bien sûr, vous pouvez utiliser le même modèle configuré pour utiliser base64 afin de gérer à la fois l'entrée (*valider*) avec `val_json_bytes` et la sortie (*sérialiser*) avec `ser_json_bytes` lors de la réception et de l'envoi de données JSON. {* ../../docs_src/json_base64_bytes/tutorial001_py310.py ln[1:2,19:26,29,44:46] hl[23:26] *} diff --git a/docs/fr/docs/advanced/openapi-callbacks.md b/docs/fr/docs/advanced/openapi-callbacks.md index e21254bc1..54f8e3ff7 100644 --- a/docs/fr/docs/advanced/openapi-callbacks.md +++ b/docs/fr/docs/advanced/openapi-callbacks.md @@ -1,10 +1,10 @@ # Callbacks OpenAPI { #openapi-callbacks } -Vous pourriez créer une API avec un *chemin d'accès* qui déclenche une requête vers une *API externe* créée par quelqu'un d'autre (probablement la même personne développeuse qui utiliserait votre API). +Vous pourriez créer une API avec un *chemin d'accès* qui déclenche une requête vers une *API externe* créée par quelqu'un d'autre (probablement la même personne développeuse qui *utiliserait* votre API). -Le processus qui se produit lorsque votre application API appelle l’*API externe* s’appelle un « callback ». Parce que le logiciel écrit par la personne développeuse externe envoie une requête à votre API puis votre API « rappelle », en envoyant une requête à une *API externe* (probablement créée par la même personne développeuse). +Le processus qui se produit lorsque votre application API appelle l’*API externe* s’appelle un « callback ». Parce que le logiciel écrit par la personne développeuse externe envoie une requête à votre API puis votre API *rappelle*, en envoyant une requête à une *API externe* (probablement créée par la même personne développeuse). -Dans ce cas, vous pourriez vouloir documenter à quoi cette API externe devrait ressembler. Quel *chemin d'accès* elle devrait avoir, quel corps elle devrait attendre, quelle réponse elle devrait renvoyer, etc. +Dans ce cas, vous pourriez vouloir documenter à quoi cette API externe *devrait* ressembler. Quel *chemin d'accès* elle devrait avoir, quel corps elle devrait attendre, quelle réponse elle devrait renvoyer, etc. ## Une application avec des callbacks { #an-app-with-callbacks } @@ -47,7 +47,7 @@ Le code réel du callback dépendra fortement de votre application API. Et il variera probablement beaucoup d’une application à l’autre. -Cela pourrait être seulement une ou deux lignes de code, comme : +Cela pourrait être seulement une ou deux lignes de code, comme : ```Python callback_url = "https://example.com/api/v1/invoices/events/" @@ -96,35 +96,35 @@ Commencez par créer un nouveau `APIRouter` qui contiendra un ou plusieurs callb Pour créer le *chemin d'accès* du callback, utilisez le même `APIRouter` que vous avez créé ci-dessus. -Il devrait ressembler exactement à un *chemin d'accès* FastAPI normal : +Il devrait ressembler exactement à un *chemin d'accès* FastAPI normal : * Il devrait probablement déclarer le corps qu’il doit recevoir, par exemple `body: InvoiceEvent`. * Et il pourrait aussi déclarer la réponse qu’il doit renvoyer, par exemple `response_model=InvoiceEventReceived`. {* ../../docs_src/openapi_callbacks/tutorial001_py310.py hl[14:16,19:20,26:30] *} -Il y a 2 principales différences par rapport à un *chemin d'accès* normal : +Il y a 2 principales différences par rapport à un *chemin d'accès* normal : * Il n’a pas besoin d’avoir de code réel, car votre application n’appellera jamais ce code. Il sert uniquement à documenter l’*API externe*. La fonction peut donc simplement contenir `pass`. -* Le *chemin* peut contenir une [expression OpenAPI 3](https://github.com/OAI/OpenAPI-Specification/blob/master/versions/3.1.0.md#key-expression) (voir plus bas) où il peut utiliser des variables avec des paramètres et des parties de la requête originale envoyée à *votre API*. +* Le *chemin* peut contenir une [expression OpenAPI 3](https://github.com/OAI/OpenAPI-Specification/blob/master/versions/3.1.0.md#key-expression) (voir plus bas) où il peut utiliser des variables avec des paramètres et des parties de la requête originale envoyée à *votre API*. ### L’expression du chemin de callback { #the-callback-path-expression } -Le *chemin* du callback peut contenir une [expression OpenAPI 3](https://github.com/OAI/OpenAPI-Specification/blob/master/versions/3.1.0.md#key-expression) qui peut inclure des parties de la requête originale envoyée à *votre API*. +Le *chemin* du callback peut contenir une [expression OpenAPI 3](https://github.com/OAI/OpenAPI-Specification/blob/master/versions/3.1.0.md#key-expression) qui peut inclure des parties de la requête originale envoyée à *votre API*. -Dans ce cas, c’est la `str` : +Dans ce cas, c’est la `str` : ```Python "{$callback_url}/invoices/{$request.body.id}" ``` -Ainsi, si l’utilisateur de votre API (la personne développeuse externe) envoie une requête à *votre API* vers : +Ainsi, si l’utilisateur de votre API (la personne développeuse externe) envoie une requête à *votre API* vers : ``` https://yourapi.com/invoices/?callback_url=https://www.external.org/events ``` -avec un corps JSON : +avec un corps JSON : ```JSON { @@ -134,13 +134,13 @@ avec un corps JSON : } ``` -alors *votre API* traitera la facture et, à un moment ultérieur, enverra une requête de callback à `callback_url` (l’*API externe*) : +alors *votre API* traitera la facture et, à un moment ultérieur, enverra une requête de callback à `callback_url` (l’*API externe*) : ``` https://www.external.org/events/invoices/2expen51ve ``` -avec un corps JSON contenant quelque chose comme : +avec un corps JSON contenant quelque chose comme : ```JSON { @@ -149,7 +149,7 @@ avec un corps JSON contenant quelque chose comme : } ``` -et elle s’attendra à une réponse de cette *API externe* avec un corps JSON comme : +et elle s’attendrait à une réponse de cette *API externe* avec un corps JSON comme : ```JSON { @@ -167,7 +167,7 @@ Remarquez que l’URL de callback utilisée contient l’URL reçue en paramètr À ce stade, vous avez le(s) *chemin(s) d'accès de callback* nécessaire(s) (celui/ceux que la *personne développeuse externe* doit implémenter dans l’*API externe*) dans le routeur de callback que vous avez créé ci-dessus. -Utilisez maintenant le paramètre `callbacks` dans *le décorateur de chemin d'accès de votre API* pour passer l’attribut `.routes` depuis ce routeur de callback : +Utilisez maintenant le paramètre `callbacks` dans *le décorateur de chemin d'accès de votre API* pour passer l’attribut `.routes` depuis ce routeur de callback : {* ../../docs_src/openapi_callbacks/tutorial001_py310.py hl[33] *} @@ -181,6 +181,6 @@ Remarquez que vous ne passez pas le routeur lui-même (`invoices_callback_router Vous pouvez maintenant démarrer votre application et aller sur [http://127.0.0.1:8000/docs](http://127.0.0.1:8000/docs). -Vous verrez votre documentation incluant une section « Callbacks » pour votre *chemin d'accès* qui montre à quoi l’*API externe* devrait ressembler : +Vous verrez votre documentation incluant une section « Callbacks » pour votre *chemin d'accès* qui montre à quoi l’*API externe* devrait ressembler : diff --git a/docs/fr/docs/advanced/response-change-status-code.md b/docs/fr/docs/advanced/response-change-status-code.md index 222825702..317fcb03d 100644 --- a/docs/fr/docs/advanced/response-change-status-code.md +++ b/docs/fr/docs/advanced/response-change-status-code.md @@ -16,7 +16,7 @@ Pour ces cas, vous pouvez utiliser un paramètre `Response`. ## Utiliser un paramètre `Response` { #use-a-response-parameter } -Vous pouvez déclarer un paramètre de type `Response` dans votre fonction de chemin d'accès (comme vous pouvez le faire pour les cookies et les en-têtes). +Vous pouvez déclarer un paramètre de type `Response` dans votre *fonction de chemin d'accès* (comme vous pouvez le faire pour les cookies et les en-têtes). Vous pouvez ensuite définir le `status_code` dans cet objet de réponse *temporaire*. diff --git a/docs/fr/docs/advanced/response-cookies.md b/docs/fr/docs/advanced/response-cookies.md index 174c9a72d..9efa045b1 100644 --- a/docs/fr/docs/advanced/response-cookies.md +++ b/docs/fr/docs/advanced/response-cookies.md @@ -1,5 +1,6 @@ # Cookies de réponse { #response-cookies } + ## Utiliser un paramètre `Response` { #use-a-response-parameter } Vous pouvez déclarer un paramètre de type `Response` dans votre *fonction de chemin d'accès*. diff --git a/docs/fr/docs/advanced/response-headers.md b/docs/fr/docs/advanced/response-headers.md index b7568b51f..e319ffefb 100644 --- a/docs/fr/docs/advanced/response-headers.md +++ b/docs/fr/docs/advanced/response-headers.md @@ -2,9 +2,9 @@ ## Utiliser un paramètre `Response` { #use-a-response-parameter } -Vous pouvez déclarer un paramètre de type `Response` dans votre fonction de chemin d'accès (comme vous pouvez le faire pour les cookies). +Vous pouvez déclarer un paramètre de type `Response` dans votre *fonction de chemin d'accès* (comme vous pouvez le faire pour les cookies). -Vous pouvez ensuite définir des en-têtes dans cet objet de réponse temporaire. +Vous pouvez ensuite définir des en-têtes dans cet objet de réponse *temporaire*. {* ../../docs_src/response_headers/tutorial002_py310.py hl[1, 7:8] *} @@ -12,7 +12,7 @@ Ensuite, vous pouvez renvoyer n'importe quel objet dont vous avez besoin, comme Et si vous avez déclaré un `response_model`, il sera toujours utilisé pour filtrer et convertir l'objet que vous avez renvoyé. -**FastAPI** utilisera cette réponse temporaire pour extraire les en-têtes (ainsi que les cookies et le code de statut), et les placera dans la réponse finale qui contient la valeur que vous avez renvoyée, filtrée par tout `response_model`. +**FastAPI** utilisera cette réponse *temporaire* pour extraire les en-têtes (ainsi que les cookies et le code de statut), et les placera dans la réponse finale qui contient la valeur que vous avez renvoyée, filtrée par tout `response_model`. Vous pouvez également déclarer le paramètre `Response` dans des dépendances, et y définir des en-têtes (et des cookies). diff --git a/docs/fr/docs/advanced/security/oauth2-scopes.md b/docs/fr/docs/advanced/security/oauth2-scopes.md index af63ce553..a193aeacd 100644 --- a/docs/fr/docs/advanced/security/oauth2-scopes.md +++ b/docs/fr/docs/advanced/security/oauth2-scopes.md @@ -2,11 +2,11 @@ Vous pouvez utiliser des scopes OAuth2 directement avec **FastAPI**, ils sont intégrés pour fonctionner de manière transparente. -Cela vous permettrait d’avoir un système d’autorisations plus fin, conforme au standard OAuth2, intégré à votre application OpenAPI (et à la documentation de l’API). +Cela vous permettrait d’avoir un système d’autorisations plus fin, conforme au standard OAuth2, intégré à votre application OpenAPI (et aux documents de l’API). OAuth2 avec scopes est le mécanisme utilisé par de nombreux grands fournisseurs d’authentification, comme Facebook, Google, GitHub, Microsoft, X (Twitter), etc. Ils l’utilisent pour fournir des permissions spécifiques aux utilisateurs et aux applications. -Chaque fois que vous « log in with » Facebook, Google, GitHub, Microsoft, X (Twitter), cette application utilise OAuth2 avec scopes. +Chaque fois que vous utilisez « se connecter avec » Facebook, Google, GitHub, Microsoft, X (Twitter), cette application utilise OAuth2 avec scopes. Dans cette section, vous verrez comment gérer l’authentification et l’autorisation avec le même OAuth2 avec scopes dans votre application **FastAPI**. @@ -16,7 +16,7 @@ C’est une section plus ou moins avancée. Si vous débutez, vous pouvez la pas Vous n’avez pas nécessairement besoin des scopes OAuth2, et vous pouvez gérer l’authentification et l’autorisation comme vous le souhaitez. -Mais OAuth2 avec scopes peut s’intégrer élégamment à votre API (avec OpenAPI) et à votre documentation d’API. +Mais OAuth2 avec scopes peut s’intégrer élégamment à votre API (avec OpenAPI) et à vos documents d’API. Néanmoins, c’est toujours à vous de faire appliquer ces scopes, ou toute autre exigence de sécurité/autorisation, selon vos besoins, dans votre code. @@ -34,7 +34,7 @@ Le contenu de chacune de ces chaînes peut avoir n’importe quel format, mais n Ces scopes représentent des « permissions ». -Dans OpenAPI (par ex. la documentation de l’API), vous pouvez définir des « schémas de sécurité ». +Dans OpenAPI (par ex. les documents de l’API), vous pouvez définir des « schémas de sécurité ». Lorsqu’un de ces schémas de sécurité utilise OAuth2, vous pouvez aussi déclarer et utiliser des scopes. @@ -74,7 +74,7 @@ Le paramètre `scopes` reçoit un `dict` avec chaque scope en clé et la descrip {* ../../docs_src/security/tutorial005_an_py310.py hl[63:66] *} -Comme nous déclarons maintenant ces scopes, ils apparaîtront dans la documentation de l’API lorsque vous vous authentifiez/autorisez. +Comme nous déclarons maintenant ces scopes, ils apparaîtront dans les documents de l’API lorsque vous vous authentifiez/autorisez. Et vous pourrez sélectionner à quels scopes vous souhaitez accorder l’accès : `me` et `items`. @@ -235,11 +235,11 @@ Elles seront vérifiées indépendamment pour chaque *chemin d’accès*. ## Tester { #check-it } -Si vous ouvrez la documentation de l’API, vous pouvez vous authentifier et spécifier quels scopes vous voulez autoriser. +Si vous ouvrez les documents de l’API, vous pouvez vous authentifier et spécifier quels scopes vous voulez autoriser. -Si vous ne sélectionnez aucun scope, vous serez « authenticated », mais lorsque vous essayerez d’accéder à `/users/me/` ou `/users/me/items/`, vous obtiendrez une erreur indiquant que vous n’avez pas suffisamment de permissions. Vous pourrez toujours accéder à `/status/`. +Si vous ne sélectionnez aucun scope, vous serez « authentifié », mais lorsque vous essayerez d’accéder à `/users/me/` ou `/users/me/items/`, vous obtiendrez une erreur indiquant que vous n’avez pas suffisamment de permissions. Vous pourrez toujours accéder à `/status/`. Et si vous sélectionnez le scope `me` mais pas le scope `items`, vous pourrez accéder à `/users/me/` mais pas à `/users/me/items/`. diff --git a/docs/fr/docs/advanced/settings.md b/docs/fr/docs/advanced/settings.md index e6eb52a4e..722274d57 100644 --- a/docs/fr/docs/advanced/settings.md +++ b/docs/fr/docs/advanced/settings.md @@ -144,7 +144,7 @@ Pour l'instant, vous pouvez supposer que `get_settings()` est une fonction norma /// -Nous pouvons ensuite l'exiger depuis la fonction de chemin d'accès comme dépendance et l'utiliser où nous en avons besoin. +Nous pouvons ensuite l'exiger depuis la *fonction de chemin d'accès* comme dépendance et l'utiliser où nous en avons besoin. {* ../../docs_src/settings/app02_an_py310/main.py hl[17,19:21] *} diff --git a/docs/fr/docs/advanced/stream-data.md b/docs/fr/docs/advanced/stream-data.md index e4939f256..23884b2f0 100644 --- a/docs/fr/docs/advanced/stream-data.md +++ b/docs/fr/docs/advanced/stream-data.md @@ -2,7 +2,7 @@ Si vous voulez diffuser des données pouvant être structurées en JSON, vous devez [Diffuser des JSON Lines](../tutorial/stream-json-lines.md). -Mais si vous voulez diffuser des données binaires pures ou des chaînes, voici comment procéder. +Mais si vous voulez **diffuser des données binaires pures** ou des chaînes, voici comment procéder. /// note | Remarque @@ -14,7 +14,7 @@ Ajouté dans FastAPI 0.134.0. Vous pouvez l'utiliser si vous souhaitez diffuser des chaînes pures, par exemple directement depuis la sortie d'un service d'**IA LLM**. -Vous pouvez également l'utiliser pour diffuser de gros fichiers binaires, en envoyant chaque bloc de données au fur et à mesure de la lecture, sans tout charger en mémoire d'un coup. +Vous pouvez également l'utiliser pour diffuser de **gros fichiers binaires**, en envoyant chaque bloc de données au fur et à mesure de la lecture, sans tout charger en mémoire d'un coup. Vous pouvez aussi diffuser de la **vidéo** ou de l'**audio** de cette manière ; cela peut même être généré au fil du traitement et de l'envoi. @@ -26,7 +26,7 @@ Si vous déclarez un `response_class=StreamingResponse` dans votre *fonction de FastAPI transmettra chaque bloc de données à la `StreamingResponse` tel quel ; il n'essaiera pas de le convertir en JSON ni autre chose similaire. -### Fonctions de chemin d'accès non async { #non-async-path-operation-functions } +### *Fonctions de chemin d'accès* non async { #non-async-path-operation-functions } Vous pouvez également utiliser des fonctions `def` classiques (sans `async`), et utiliser `yield` de la même manière. @@ -40,7 +40,7 @@ Comme FastAPI n'essaiera pas de convertir les données en JSON avec Pydantic ni {* ../../docs_src/stream_data/tutorial001_py310.py ln[32:35] hl[33] *} -Cela signifie aussi qu'avec `StreamingResponse` vous avez la liberté — et la responsabilité — de produire et d'encoder les octets de données exactement comme vous avez besoin de les envoyer, indépendamment des annotations de type. 🤓 +Cela signifie aussi qu'avec `StreamingResponse` vous avez la **liberté** et la **responsabilité** de produire et d'encoder les octets de données exactement comme vous avez besoin de les envoyer, indépendamment des annotations de type. 🤓 ### Diffuser des bytes { #stream-bytes } diff --git a/docs/fr/docs/advanced/wsgi.md b/docs/fr/docs/advanced/wsgi.md index a1e56a45d..6e6ce85c8 100644 --- a/docs/fr/docs/advanced/wsgi.md +++ b/docs/fr/docs/advanced/wsgi.md @@ -1,5 +1,6 @@ # Inclure WSGI - Flask, Django, autres { #including-wsgi-flask-django-others } + Vous pouvez monter des applications WSGI comme vous l'avez vu avec [Sous-applications - Montages](sub-applications.md), [Derrière un proxy](behind-a-proxy.md). Pour cela, vous pouvez utiliser `WSGIMiddleware` et l'utiliser pour envelopper votre application WSGI, par exemple Flask, Django, etc. diff --git a/docs/fr/docs/alternatives.md b/docs/fr/docs/alternatives.md index b56d10481..91a81e2dc 100644 --- a/docs/fr/docs/alternatives.md +++ b/docs/fr/docs/alternatives.md @@ -39,19 +39,19 @@ premières idées qui a inspiré « la recherche de » **FastAPI**. /// note | Remarque -Django REST Framework a été créé par Tom Christie. Le créateur de Starlette et Uvicorn, sur lesquels **FastAPI** est basé. +Django REST Framework a été créé par Tom Christie. Le même créateur de Starlette et Uvicorn, sur lesquels **FastAPI** est basé. /// /// tip | A inspiré **FastAPI** à -Avoir une interface de documentation automatique de l'API. +Avoir une interface utilisateur web de documentation automatique de l'API. /// ### [Flask](https://flask.palletsprojects.com) { #flask } -Flask est un « micro‑framework », il ne comprend pas d'intégrations de bases de données ni beaucoup de choses qui sont fournies par défaut dans Django. +Flask est un « microframework », il ne comprend pas d'intégrations de bases de données ni beaucoup de choses qui sont fournies par défaut dans Django. Cette simplicité et cette flexibilité permettent d'utiliser des bases de données NoSQL comme principal système de stockage de données. @@ -60,22 +60,22 @@ technique par moments. Il est aussi couramment utilisé pour d'autres applications qui n'ont pas nécessairement besoin d'une base de données, de gestion des utilisateurs ou de l'une des nombreuses fonctionnalités préinstallées dans Django. Bien que beaucoup de ces fonctionnalités puissent être ajoutées avec des plug-ins. -Ce découplage des parties, et le fait d'être un « micro‑framework » qui puisse être étendu pour couvrir exactement ce +Ce découplage des parties, et le fait d'être un « microframework » qui puisse être étendu pour couvrir exactement ce qui est nécessaire, était une caractéristique clé que je voulais conserver. Compte tenu de la simplicité de Flask, il semblait bien adapté à la création d'API. La prochaine chose à trouver était un « Django REST Framework » pour Flask. /// tip | A inspiré **FastAPI** à -Être un micro‑framework. Il est donc facile de combiner les outils et les pièces nécessaires. +Être un micro-framework. Il est donc facile de combiner les outils et les pièces nécessaires. -Proposer un système de routage simple et facile à utiliser. +Proposer un système de routing simple et facile à utiliser. /// ### [Requests](https://requests.readthedocs.io) { #requests } -**FastAPI** n'est pas réellement une alternative à **Requests**. Leur cadre est très différent. +**FastAPI** n'est pas réellement une alternative à **Requests**. Leur portée est très différente. Il serait en fait plus courant d'utiliser Requests _à l'intérieur_ d'une application FastAPI. @@ -85,7 +85,7 @@ Mais quand même, FastAPI s'est inspiré de Requests. Ils sont, plus ou moins, aux extrémités opposées, se complétant l'un l'autre. -Requests a un design très simple et intuitif, il est très facile à utiliser, avec des valeurs par défaut raisonnables, tout en étant très puissant et personnalisable. +Requests a un design très simple et intuitif, il est très facile à utiliser, avec des valeurs par défaut raisonnables. Mais en même temps, il est très puissant et personnalisable. C'est pourquoi, comme le dit le site officiel : @@ -97,7 +97,7 @@ La façon dont vous l'utilisez est très simple. Par exemple, pour faire une req response = requests.get("http://example.com/some/url") ``` -L’opération de chemin d'accès correspondante dans **FastAPI** pourrait ressembler à ceci : +Le *chemin d'accès* d'API correspondant dans **FastAPI** pourrait ressembler à ceci : ```Python hl_lines="1" @app.get("/some/url") @@ -117,7 +117,7 @@ Notez les similitudes entre `requests.get(...)` et `@app.get(...)`. ### [Swagger](https://swagger.io/) / [OpenAPI](https://github.com/OAI/OpenAPI-Specification/) { #swagger-openapi } -La principale fonctionnalité que j'ai emprunté à Django REST Framework était la documentation automatique des API. +La principale fonctionnalité que j'ai empruntée à Django REST Framework était la documentation automatique des API. Puis j'ai découvert qu'il existait une norme pour documenter les API, en utilisant JSON (ou YAML, une extension de JSON) appelée Swagger. @@ -132,12 +132,12 @@ C'est pourquoi, lorsqu'on parle de la version 2.0, il est courant de dire « Swa Adopter et utiliser une norme ouverte pour les spécifications des API, au lieu d'un schéma personnalisé. -Intégrer des outils d'interface utilisateur basés sur des normes : +Et intégrer des outils d'interface utilisateur basés sur des normes : * [Swagger UI](https://github.com/swagger-api/swagger-ui) * [ReDoc](https://github.com/Rebilly/ReDoc) -Ces deux-là ont été choisis parce qu'ils sont populaires et stables, mais en faisant une recherche rapide, vous pourriez trouver des dizaines d'alternatives supplémentaires pour OpenAPI (que vous pouvez utiliser avec **FastAPI**). +Ces deux-là ont été choisis parce qu'ils sont populaires et stables, mais en faisant une recherche rapide, vous pourriez trouver des dizaines d'interfaces utilisateur alternatives pour OpenAPI (que vous pouvez utiliser avec **FastAPI**). /// @@ -149,14 +149,13 @@ permanents qui les rendent inadaptés. ### [Marshmallow](https://marshmallow.readthedocs.io/en/stable/) { #marshmallow } -L'une des principales fonctionnalités nécessaires aux systèmes API est la « sérialisation » des données, qui consiste à prendre les données du code (Python) et à +L'une des principales fonctionnalités nécessaires aux systèmes API est la « sérialisation » des données, qui consiste à prendre les données du code (Python) et à les convertir en quelque chose qui peut être envoyé sur le réseau. Par exemple, convertir un objet contenant des données provenant d'une base de données en un objet JSON. Convertir des objets `datetime` en strings, etc. La validation des données est une autre fonctionnalité importante dont ont besoin les API. Elle permet de s'assurer que les données sont valides, compte tenu de certains paramètres. Par exemple, qu'un champ est un `int`, et non un -string. -Ceci est particulièrement utile pour les données entrantes. +string. Ceci est particulièrement utile pour les données entrantes. Sans un système de validation des données, vous devriez effectuer toutes les vérifications à la main, dans le code. @@ -182,7 +181,7 @@ C'est un outil formidable et je l'ai beaucoup utilisé aussi, avant d'avoir **Fa /// note | Remarque -Webargs a été créé par les développeurs de Marshmallow. +Webargs a été créé par les mêmes développeurs de Marshmallow. /// @@ -206,13 +205,13 @@ Et il génère des schémas OpenAPI. C'est ainsi que cela fonctionne dans Flask, Starlette, Responder, etc. -Mais alors, nous avons à nouveau le problème d'avoir une micro-syntaxe, dans une docstring Python (un gros morceau de YAML). +Mais alors, nous avons à nouveau le problème d'avoir une micro-syntaxe, dans une string Python (un gros morceau de YAML). L'éditeur ne peut guère aider en la matière. Et si nous modifions les paramètres ou les schémas Marshmallow et que nous oublions de modifier également cette docstring YAML, le schéma généré deviendrait obsolète. /// note | Remarque -APISpec a été créé par les développeurs de Marshmallow. +APISpec a été créé par les mêmes développeurs de Marshmallow. /// @@ -241,11 +240,11 @@ j'ai (ainsi que plusieurs équipes externes) utilisées jusqu'à présent : * [https://github.com/tiangolo/full-stack-flask-couchbase](https://github.com/tiangolo/full-stack-flask-couchbase) * [https://github.com/tiangolo/full-stack-flask-couchdb](https://github.com/tiangolo/full-stack-flask-couchdb) -Ces mêmes générateurs full-stack ont servi de base aux [Générateurs de projets pour **FastAPI**](project-generation.md). +Et ces mêmes générateurs full-stack ont servi de base aux [Générateurs de projets **FastAPI**](project-generation.md). /// note | Remarque -Flask-apispec a été créé par les développeurs de Marshmallow. +Flask-apispec a été créé par les mêmes développeurs de Marshmallow. /// @@ -284,9 +283,9 @@ C'était l'un des premiers frameworks Python extrêmement rapides basés sur `as /// note | Détails techniques -Il utilisait [`uvloop`](https://github.com/MagicStack/uvloop) au lieu du système par défaut de Python `asyncio`. C'est ce qui l'a rendu si rapide. +Il utilisait [`uvloop`](https://github.com/MagicStack/uvloop) au lieu de la boucle par défaut de Python `asyncio`. C'est ce qui l'a rendu si rapide. -Il a clairement inspiré Uvicorn et Starlette, qui sont actuellement plus rapides que Sanic dans les benchmarks. +Il a clairement inspiré Uvicorn et Starlette, qui sont actuellement plus rapides que Sanic dans les benchmarks ouverts. /// @@ -304,7 +303,7 @@ Falcon est un autre framework Python haute performance, il est conçu pour être Il est conçu pour avoir des fonctions qui reçoivent deux paramètres, une « requête » et une « réponse ». Ensuite, vous « lisez » des parties de la requête et « écrivez » des parties dans la réponse. En raison de cette conception, il n'est -pas possible de déclarer des paramètres de requête et des corps avec des indications de type Python standard comme paramètres de fonction. +pas possible de déclarer des paramètres de requête et des corps avec des annotations de type Python standard comme paramètres de fonction. Ainsi, la validation, la sérialisation et la documentation des données doivent être effectuées dans le code, et non pas automatiquement. Ou bien elles doivent être implémentées comme un framework au-dessus de Falcon, comme Hug. Cette même distinction se retrouve dans d'autres frameworks qui s'inspirent de la conception de Falcon, qui consiste à avoir un objet de requête et un objet de réponse comme paramètres. @@ -326,7 +325,7 @@ J'ai découvert Molten lors des premières étapes de développement de **FastAP * Validation et documentation via ces types. * Système d'injection de dépendances. -Il n'utilise pas une librairie tiers de validation, sérialisation et de documentation tel que Pydantic, il utilise son propre système. Ainsi, ces définitions de types de données ne sont pas réutilisables aussi facilement. +Il n'utilise pas une librairie tierce de validation, sérialisation et de documentation telle que Pydantic, il utilise son propre système. Ainsi, ces définitions de types de données ne sont pas réutilisables aussi facilement. Il nécessite une configuration un peu plus verbeuse. Et comme il est basé sur WSGI (au lieu d'ASGI), il n'est pas conçu pour profiter des hautes performances fournies par des outils comme Uvicorn, Starlette et Sanic. @@ -363,7 +362,7 @@ Comme il est basé sur l'ancienne norme pour les frameworks web Python synchrone /// note | Remarque -Hug a été créé par Timothy Crosley, le créateur de [`isort`](https://github.com/timothycrosley/isort), un excellent outil pour trier automatiquement les imports dans les fichiers Python. +Hug a été créé par Timothy Crosley, le même créateur de [`isort`](https://github.com/timothycrosley/isort), un excellent outil pour trier automatiquement les imports dans les fichiers Python. /// @@ -388,11 +387,11 @@ et les requêtes que j'ai vues (avant NestJS et Molten). Je l'ai trouvé plus ou Il disposait de la validation automatique, sérialisation des données et d'une génération de schéma OpenAPI basée sur les mêmes annotations de type à plusieurs endroits. -La définition du schéma de corps de requête n'utilisait pas les mêmes annotations de type Python que Pydantic, il était un peu plus proche de Marshmallow, donc le support de l'éditeur n'était pas aussi bon, mais APIStar était quand même la meilleure option disponible. +Les définitions de schéma de corps n'utilisaient pas les mêmes annotations de type Python que Pydantic, c'était un peu plus proche de Marshmallow, donc le support de l'éditeur n'était pas aussi bon, mais APIStar était quand même la meilleure option disponible. Il avait les meilleures performances d'après les benchmarks de l'époque (seulement surpassé par Starlette). -Au départ, il ne disposait pas d'une interface web de documentation automatique de l'API, mais je savais que je pouvais lui ajouter une interface Swagger. +Au départ, il ne disposait pas d'une interface utilisateur web de documentation automatique de l'API, mais je savais que je pouvais lui ajouter Swagger UI. Il avait un système d'injection de dépendances. Il nécessitait un pré-enregistrement des composants, comme d'autres outils discutés ci-dessus. Mais c'était quand même une excellente fonctionnalité. @@ -422,7 +421,7 @@ L'idée de déclarer plusieurs choses (validation des données, sérialisation e Et après avoir longtemps cherché un framework similaire et testé de nombreuses alternatives, APIStar était la meilleure option disponible. -Puis APIStar a cessé d'exister en tant que serveur et Starlette a été créé, et a constitué une meilleure base pour un tel système. Ce fut l'inspiration finale pour construire **FastAPI**. +Puis APIStar a cessé d'exister en tant que serveur et Starlette a été créé, et a constitué une nouvelle base meilleure pour un tel système. Ce fut l'inspiration finale pour construire **FastAPI**. Je considère **FastAPI** comme un « successeur spirituel » d'APIStar, tout en améliorant et en augmentant les fonctionnalités, le système de typage et d'autres parties, sur la base des enseignements tirés de tous ces outils précédents. @@ -441,7 +440,7 @@ basé sur les mêmes annotations de type Python, le support de l'éditeur est gr /// tip | **FastAPI** l'utilise pour -Gérer toute la validation des données, leur sérialisation et la documentation automatique du modèle (basée sur le schéma JSON). +Gérer toute la validation des données, leur sérialisation et la documentation automatique du modèle (basée sur JSON Schema). **FastAPI** prend ensuite ces données JSON Schema et les place dans OpenAPI, en plus de toutes les autres choses qu'il fait. @@ -455,20 +454,20 @@ Il est très simple et intuitif. Il est conçu pour être facilement extensible Il offre : -- Des performances vraiment impressionnantes. -- Le support des WebSockets. -- Les tâches d'arrière-plan. -- Les événements de démarrage et d'arrêt. -- Un client de test basé sur HTTPX. -- CORS, GZip, fichiers statiques, streaming des réponses. -- Le support des sessions et des cookies. -- Une couverture de test à 100 %. -- 100 % de la base de code avec des annotations de type. -- Peu de dépendances strictes. +* Des performances vraiment impressionnantes. +* Le support de WebSocket. +* Les tâches d'arrière-plan in-process. +* Les événements de démarrage et d'arrêt. +* Un client de test basé sur HTTPX. +* CORS, GZip, fichiers statiques, streaming des réponses. +* Le support des sessions et des cookies. +* Une couverture de test à 100 %. +* 100 % de la base de code avec des annotations de type. +* Peu de dépendances strictes. Starlette est actuellement le framework Python le plus rapide testé. Seulement dépassé par Uvicorn, qui n'est pas un framework, mais un serveur. -Starlette fournit toutes les fonctionnalités de base d'un micro‑framework web. +Starlette fournit toutes les fonctionnalités de base d'un microframework web. Mais il ne fournit pas de validation automatique des données, de sérialisation ou de documentation. @@ -496,7 +495,7 @@ Ainsi, tout ce que vous pouvez faire avec Starlette, vous pouvez le faire direct Uvicorn est un serveur ASGI rapide comme l'éclair, basé sur uvloop et httptools. -Il ne s'agit pas d'un framework web, mais d'un serveur. Par exemple, il ne fournit pas d'outils pour le routing. C'est +Il ne s'agit pas d'un framework web, mais d'un serveur. Par exemple, il ne fournit pas d'outils pour le routing par chemins. C'est quelque chose qu'un framework comme Starlette (ou **FastAPI**) fournirait par-dessus. C'est le serveur recommandé pour Starlette et **FastAPI**. diff --git a/docs/fr/docs/async.md b/docs/fr/docs/async.md index b3fc9169a..ccd176072 100644 --- a/docs/fr/docs/async.md +++ b/docs/fr/docs/async.md @@ -44,19 +44,19 @@ Si votre application (d'une certaine manière) n'a pas à communiquer avec une a --- -Si vous ne savez pas, utilisez seulement `def`. +Si vous ne savez pas, utilisez un `def` normal. --- -Note : vous pouvez mélanger `def` et `async def` dans vos *fonctions de chemin d'accès* autant que nécessaire, et définir chacune avec l’option la plus adaptée pour vous. FastAPI fera ce qu'il faut avec elles. +**Remarque** : vous pouvez mélanger `def` et `async def` dans vos *fonctions de chemin d'accès* autant que nécessaire, et définir chacune avec l’option la plus adaptée pour vous. FastAPI fera ce qu'il faut avec elles. Au final, peu importe le cas parmi ceux ci-dessus, FastAPI fonctionnera de manière asynchrone et sera extrêmement rapide. -Mais si vous suivez bien les instructions ci-dessus, il pourra effectuer quelques optimisations et ainsi améliorer les performances. +Mais si vous suivez bien les étapes ci-dessus, il pourra effectuer quelques optimisations de performance. ## Détails techniques { #technical-details } -Les versions modernes de Python supportent le **code asynchrone** grâce aux **« coroutines »** avec les syntaxes **`async` et `await`**. +Les versions modernes de Python supportent le **« code asynchrone »** en utilisant quelque chose appelé **« coroutines »**, avec la syntaxe **`async` et `await`**. Analysons les différentes parties de cette phrase dans les sections suivantes : @@ -70,7 +70,7 @@ Faire du code asynchrone signifie que le langage 💬 est capable de dire à l'o Donc, pendant ce temps, l'ordinateur pourra effectuer d'autres tâches, pendant que « slow-file » 📝 se termine. -Ensuite l'ordinateur / le programme 🤖 reviendra à chaque fois qu'il en a la chance que ce soit parce qu'il attend à nouveau, ou car il 🤖 a fini tout le travail qu'il avait à faire. Il 🤖 regardera donc si les tâches qu'il attend ont terminé d'être effectuées. +Ensuite l'ordinateur / le programme 🤖 reviendra à chaque fois qu'il en a la chance, parce qu'il attend à nouveau, ou quand il 🤖 a fini tout le travail qu'il avait à faire à ce moment-là. Et il 🤖 regardera si des tâches qu'il attendait ont déjà terminé, en faisant ce qu'il devait faire. Ensuite, il 🤖 prendra la première tâche à finir (disons, notre « slow-file » 📝) et continuera à faire avec cette dernière ce qu'il était censé. @@ -80,18 +80,18 @@ Ce « attendre quelque chose d'autre » fait généralement référence à des o * de la donnée envoyée depuis votre programme soit reçue par le client à travers le réseau * le contenu d'un fichier sur le disque soit lu par le système et passé à votre programme * le contenu que votre programme a passé au système soit écrit sur le disque -* une opération effectuée à distance par une API se termine +* une opération effectuée à distance par une API * une opération en base de données se termine * une requête à une base de données renvoie un résultat * etc. Le temps d'exécution étant consommé majoritairement par l'attente d'opérations I/O, on appelle ceci des opérations « I/O bound ». -Ce concept se nomme « asynchrone » car l'ordinateur / le programme n'a pas besoin d'être « synchronisé » avec la tâche, attendant le moment exact où cette dernière se terminera en ne faisant rien, pour être capable de récupérer le résultat de la tâche et l'utiliser dans la suite des opérations. +Ce concept se nomme « asynchrone » car l'ordinateur / le programme n'a pas besoin d'être « synchronisé » avec la tâche lente, attendant le moment exact où cette dernière se terminera en ne faisant rien, pour être capable de récupérer le résultat de la tâche et l'utiliser dans la suite des opérations. -À la place, en étant « asynchrone », une fois terminée, une tâche peut légèrement attendre (quelques microsecondes) que l'ordinateur / le programme finisse ce qu'il était en train de faire, et revienne récupérer le résultat. +À la place, en étant un système « asynchrone », une fois terminée, la tâche peut attendre un peu dans la file (quelques microsecondes) que l'ordinateur / le programme finisse ce qu'il était en train de faire, puis revienne récupérer les résultats et continue à travailler avec eux. -Pour parler de tâches « synchrones » (en opposition à « asynchrones »), on utilise souvent le terme « séquentiel », car l'ordinateur / le programme va effectuer toutes les étapes d'une tâche séquentiellement avant de passer à une autre tâche, même si ces étapes impliquent de l'attente. +Pour parler de tâches « synchrones » (en opposition à « asynchrones »), on utilise souvent aussi le terme « séquentiel », car l'ordinateur / le programme va effectuer toutes les étapes d'une tâche séquentiellement avant de passer à une autre tâche, même si ces étapes impliquent de l'attente. ### Concurrence et Burgers { #concurrency-and-burgers } @@ -99,49 +99,49 @@ L'idée de code **asynchrone** décrite ci-dessus est parfois aussi appelée ** La **concurrence** et le **parallélisme** sont tous deux liés à l'idée de « différentes choses arrivant plus ou moins au même moment ». -Mais les détails entre la **concurrence** et le **parallélisme** diffèrent sur de nombreux points. +Mais les détails entre la *concurrence* et le *parallélisme* sont assez différents. -Pour expliquer la différence, voici une histoire de burgers : +Pour expliquer la différence, imaginez l'histoire suivante à propos de burgers : ### Burgers concurrents { #concurrent-burgers } -Vous amenez votre crush 😍 dans votre fast food 🍔 favori, et faites la queue pendant que le serveur 💁 prend les commandes des personnes devant vous. +Vous allez avec votre crush chercher de la nourriture dans un fast food, vous faites la queue pendant que le caissier prend les commandes des personnes devant vous. 😍 -Puis vient votre tour, vous commandez alors 2 magnifiques burgers 🍔 pour votre crush 😍 et vous. +Puis vient votre tour, vous commandez alors 2 burgers très sophistiqués pour votre crush et vous. 🍔🍔 -Le serveur 💁 dit quelque chose à son collègue dans la cuisine 👨‍🍳 pour qu'il sache qu'il doit préparer vos burgers 🍔 (bien qu'il soit déjà en train de préparer ceux des clients précédents). +Le caissier dit quelque chose au cuisinier dans la cuisine pour qu'il sache qu'il doit préparer vos burgers (bien qu'il soit déjà en train de préparer ceux des clients précédents). -Vous payez 💸. +Vous payez. 💸 -Le serveur 💁 vous donne le numéro assigné à votre commande. +Le caissier vous donne le numéro de votre tour. -Pendant que vous attendez, vous allez choisir une table avec votre crush 😍, vous discutez avec votre crush 😍 pendant un long moment (les burgers étant « magnifiques » ils sont très longs à préparer ✨🍔✨). +Pendant que vous attendez, vous allez choisir une table avec votre crush, vous vous asseyez et discutez avec votre crush pendant un long moment (vos burgers étant très sophistiqués, ils prennent du temps à préparer). -Pendant que vous êtes assis à table, en attendant que les burgers 🍔 soient prêts, vous pouvez passer ce temps à admirer à quel point votre crush 😍 est géniale, mignonne et intelligente ✨😍✨. +Pendant que vous êtes assis à table avec votre crush, en attendant les burgers, vous pouvez passer ce temps à admirer à quel point votre crush est géniale, mignonne et intelligente ✨😍✨. -Pendant que vous discutez avec votre crush 😍, de temps en temps vous jetez un coup d’œil au nombre affiché au-dessus du comptoir pour savoir si c'est à votre tour d'être servis. +Pendant que vous attendez et discutez avec votre crush, de temps en temps, vous jetez un coup d’œil au nombre affiché au-dessus du comptoir pour savoir si c'est déjà votre tour. -Jusqu'au moment où c'est (enfin) votre tour. Vous allez au comptoir, récupérez vos burgers 🍔 et revenez à votre table. +Puis, à un moment, c'est enfin votre tour. Vous allez au comptoir, récupérez vos burgers et revenez à votre table. -Vous et votre crush 😍 mangez les burgers 🍔 et passez un bon moment ✨. +Vous et votre crush mangez les burgers et passez un bon moment. ✨ /// note | Remarque -Illustrations proposées par [Ketrina Thompson](https://www.instagram.com/ketrinadrawsalot). 🎨 +Belles illustrations par [Ketrina Thompson](https://www.instagram.com/ketrinadrawsalot). 🎨 /// @@ -149,103 +149,103 @@ Illustrations proposées par [Ketrina Thompson](https://www.instagram.com/ketrin Imaginez que vous êtes l'ordinateur / le programme 🤖 dans cette histoire. -Pendant que vous faites la queue, vous être simplement inactif 😴, attendant votre tour, ne faisant rien de « productif ». Mais la queue est rapide car le serveur 💁 prend seulement les commandes (et ne les prépare pas), donc tout va bien. +Pendant que vous faites la queue, vous êtes simplement inactif 😴, attendant votre tour, ne faisant rien de très « productif ». Mais la queue est rapide car le caissier prend seulement les commandes (et ne les prépare pas), donc tout va bien. -Ensuite, quand c'est votre tour, vous faites des actions « productives » 🤓, vous étudiez le menu, décidez ce que vous voulez, demandez à votre crush 😍 son choix, payez 💸, vérifiez que vous utilisez la bonne carte de crédit, vérifiez que le montant débité sur la carte est correct, vérifiez que la commande contient les bons produits, etc. +Ensuite, quand c'est votre tour, vous faites du vrai travail « productif », vous étudiez le menu, décidez ce que vous voulez, demandez à votre crush son choix, payez, vérifiez que vous donnez le bon billet ou la bonne carte, vérifiez que le montant débité est correct, vérifiez que la commande contient les bons produits, etc. -Mais ensuite, même si vous n'avez pas encore vos burgers 🍔, votre travail avec le serveur 💁 est « en pause » ⏸, car vous devez attendre 🕙 que vos burgers soient prêts. +Mais ensuite, même si vous n'avez toujours pas vos burgers, votre travail avec le caissier est « en pause » ⏸, car vous devez attendre 🕙 que vos burgers soient prêts. -Après vous être écarté du comptoir et vous être assis à votre table avec le numéro de votre commande, vous pouvez tourner 🔀 votre attention vers votre crush 😍, et « travailler » ⏯ 🤓 là-dessus. Vous êtes donc à nouveau en train de faire quelque chose de « productif » 🤓, vous flirtez avec votre crush 😍. +Mais lorsque vous vous écartez du comptoir et vous asseyez à table avec un numéro pour votre tour, vous pouvez tourner 🔀 votre attention vers votre crush, et « travailler » ⏯ 🤓 là-dessus. Vous êtes donc à nouveau en train de faire quelque chose de très « productif », comme flirter avec votre crush 😍. -Puis le serveur 💁 dit « J'ai fini de préparer les burgers » 🍔 en mettant votre numéro sur l'affichage du comptoir, mais vous ne courez pas immédiatement au moment où votre numéro s'affiche. Vous savez que personne ne volera vos burgers 🍔 car vous avez votre numéro et les autres clients ont le leur. +Puis le caissier 💁 dit « J'ai fini de faire les burgers » en mettant votre numéro sur l'affichage du comptoir, mais vous ne sautez pas comme un fou immédiatement quand le numéro affiché change pour devenir votre numéro. Vous savez que personne ne volera vos burgers car vous avez le numéro de votre tour, et les autres ont le leur. -Vous attendez donc que votre crush 😍 finisse son histoire, souriez gentiment et dites que vous allez chercher les burgers ⏸. +Vous attendez donc que votre crush finisse son histoire (termine le travail actuel ⏯ / la tâche en cours de traitement 🤓), souriez gentiment et dites que vous allez chercher les burgers ⏸. -Pour finir vous allez au comptoir 🔀, vers la tâche initiale qui est désormais terminée ⏯, récupérez les burgers 🍔, remerciez le serveur et ramenez les burgers 🍔 à votre table. Ceci termine l'étape / la tâche d'interaction avec le comptoir ⏹. Ce qui ensuite, crée une nouvelle tâche de « manger les burgers » 🔀 ⏯, mais la précédente, « récupérer les burgers » est terminée ⏹. +Puis vous allez au comptoir 🔀, vers la tâche initiale qui est désormais terminée ⏯, récupérez les burgers, remerciez et ramenez les burgers à votre table. Ceci termine l'étape / la tâche d'interaction avec le comptoir ⏹. Ce qui ensuite crée une nouvelle tâche, « manger les burgers » 🔀 ⏯, mais la précédente, « récupérer les burgers », est terminée ⏹. ### Burgers parallèles { #parallel-burgers } -Imaginons désormais que ce ne sont pas des « burgers concurrents » mais des « burgers parallèles ». +Imaginons désormais que ce ne sont pas des « Burgers concurrents » mais des « Burgers parallèles ». -Vous allez avec votre crush 😍 dans un fast food 🍔 parallélisé. +Vous allez avec votre crush chercher de la nourriture dans un fast food parallèle. -Vous attendez pendant que plusieurs (disons 8) serveurs qui sont aussi des cuisiniers 👨‍🍳👨‍🍳👨‍🍳👨‍🍳👨‍🍳👨‍🍳👨‍🍳👨‍🍳 prennent les commandes des personnes devant vous. +Vous attendez pendant que plusieurs (disons 8) caissiers qui sont en même temps cuisiniers prennent les commandes des personnes devant vous. -Chaque personne devant vous attend 🕙 que son burger 🍔 soit prêt avant de quitter le comptoir car chacun des 8 serveurs va lui-même préparer le burger directement avant de prendre la commande suivante. +Chaque personne devant vous attend que son burger soit prêt avant de quitter le comptoir car chacun des 8 caissiers va préparer le burger directement avant de prendre la commande suivante. -Puis c'est enfin votre tour, vous commandez 2 magnifiques burgers 🍔 pour vous et votre crush 😍. +Puis c'est enfin votre tour, vous commandez 2 burgers très sophistiqués pour vous et votre crush. Vous payez 💸. -Le serveur va dans la cuisine 👨‍🍳. +Le caissier va dans la cuisine. -Vous attendez devant le comptoir afin que personne ne prenne vos burgers 🍔 avant vous, vu qu'il n'y a pas de numéro de commande. +Vous attendez, debout devant le comptoir 🕙, afin que personne d'autre ne prenne vos burgers avant vous, vu qu'il n'y a pas de numéros pour les tours. -Vous et votre crush 😍 étant occupés à vérifier que personne ne passe devant vous prendre vos burgers au moment où ils arriveront 🕙, vous ne pouvez pas vous préoccuper de votre crush 😞. +Vous et votre crush étant occupés à ne laisser personne passer devant vous et prendre vos burgers au moment où ils arriveront, vous ne pouvez pas prêter attention à votre crush. 😞 -C'est du travail « synchrone », vous être « synchronisés » avec le serveur/cuisinier 👨‍🍳. Vous devez attendre 🕙 et être présent au moment exact où le serveur/cuisinier 👨‍🍳 finira les burgers 🍔 et vous les donnera, sinon quelqu'un risque de vous les prendre. +C'est du travail « synchrone », vous être « synchronisés » avec le caissier/cuisinier 👨‍🍳. Vous devez attendre 🕙 et être présent au moment exact où le caissier/cuisinier 👨‍🍳 finira les burgers et vous les donnera, sinon quelqu'un d'autre risque de vous les prendre. -Puis le serveur/cuisinier 👨‍🍳 revient enfin avec vos burgers 🍔, après un long moment d'attente 🕙 devant le comptoir. +Puis votre caissier/cuisinier 👨‍🍳 revient enfin avec vos burgers, après un long moment d'attente 🕙 devant le comptoir. -Vous prenez vos burgers 🍔 et allez à une table avec votre crush 😍 +Vous prenez vos burgers et allez à une table avec votre crush. -Vous les mangez, et vous avez terminé 🍔 ⏹. +Vous les mangez simplement, et vous avez terminé. ⏹ -Durant tout ce processus, il n'y a presque pas eu de discussions ou de flirts car la plupart de votre temps à été passé à attendre 🕙 devant le comptoir 😞. +Il n'y a pas eu beaucoup de discussions ou de flirts car la plupart du temps a été passé à attendre 🕙 devant le comptoir. 😞 /// note | Remarque -Illustrations proposées par [Ketrina Thompson](https://www.instagram.com/ketrinadrawsalot). 🎨 +Belles illustrations par [Ketrina Thompson](https://www.instagram.com/ketrinadrawsalot). 🎨 /// --- -Dans ce scénario de burgers parallèles, vous êtes un ordinateur / programme 🤖 avec deux processeurs (vous et votre crush 😍) attendant 🕙 à deux et dédiant votre attention ⏯ à « attendre devant le comptoir » 🕙 pour une longue durée. +Dans ce scénario de burgers parallèles, vous êtes un ordinateur / programme 🤖 avec deux processeurs (vous et votre crush), tous deux attendant 🕙 et dédiant leur attention ⏯ à « attendre devant le comptoir » 🕙 pour une longue durée. -Le fast-food a 8 processeurs (serveurs/cuisiniers) 👨‍🍳👨‍🍳👨‍🍳👨‍🍳👨‍🍳👨‍🍳👨‍🍳👨‍🍳. Alors que le fast-food de burgers concurrents en avait 2 (un serveur et un cuisinier). +Le fast food a 8 processeurs (caissiers/cuisiniers). Alors que le fast food de burgers concurrents aurait pu n'en avoir que 2 (un caissier et un cuisinier). -Et pourtant l'expérience finale n'est pas meilleure 😞. +Mais tout de même, l'expérience finale n'est pas la meilleure. 😞 --- -C'est donc l'histoire équivalente parallèle pour les burgers 🍔. +Ce serait donc l'histoire équivalente parallèle pour les burgers. 🍔 -Pour un exemple plus courant dans la « vie réelle », imaginez une banque. +Pour un exemple plus « vie réelle », imaginez une banque. -Jusqu'à récemment, la plupart des banques avaient plusieurs caisses (et banquiers) 👨‍💼👨‍💼👨‍💼👨‍💼 et une unique file d'attente 🕙🕙🕙🕙🕙🕙🕙🕙. +Jusqu'à récemment, la plupart des banques avaient plusieurs caissiers 👨‍💼👨‍💼👨‍💼👨‍💼 et une grande file d'attente 🕙🕙🕙🕙🕙🕙🕙🕙. -Tous les banquiers faisaient l'intégralité du travail avec chaque client avant de passer au suivant 👨‍💼⏯. +Tous les caissiers faisaient tout le travail avec chaque client avant de passer au suivant 👨‍💼⏯. -Et vous deviez attendre 🕙 dans la file pendant un long moment ou vous perdiez votre place. +Et vous devez attendre 🕙 dans la file pendant un long moment ou vous perdez votre tour. -Vous n'auriez donc probablement pas envie d'amener votre crush 😍 avec vous à la banque 🏦. +Vous n'auriez donc probablement pas envie d'amener votre crush 😍 avec vous pour faire des démarches à la banque 🏦. ### Conclusion sur les burgers { #burger-conclusion } -Dans ce scénario des « burgers du fast-food avec votre crush », comme il y a beaucoup d'attente 🕙, il est très logique d'avoir un système concurrent ⏸🔀⏯. +Dans ce scénario des « burgers de fast food avec votre crush », comme il y a beaucoup d'attente 🕙, il est beaucoup plus logique d'avoir un système concurrent ⏸🔀⏯. -Et c'est le cas pour la plupart des applications web. +C'est le cas pour la plupart des applications web. -Vous aurez de nombreux, nombreux utilisateurs, mais votre serveur attendra 🕙 que leur connexion peu performante envoie des requêtes. +De très, très nombreux utilisateurs, mais votre serveur attend 🕙 que leur connexion pas très bonne envoie leurs requêtes. -Puis vous attendrez 🕙 de nouveau que leurs réponses reviennent. +Puis attend 🕙 de nouveau que les réponses reviennent. -Cette « attente » 🕙 se mesure en microsecondes, mais tout de même, en cumulé cela fait beaucoup d'attente. +Cette « attente » 🕙 se mesure en microsecondes, mais tout de même, en les cumulant toutes, cela fait beaucoup d'attente au final. -C'est pourquoi il est logique d'utiliser du code asynchrone ⏸🔀⏯ pour des APIs web. +C'est pourquoi il est très logique d'utiliser du code asynchrone ⏸🔀⏯ pour des APIs web. Ce type d'asynchronicité est ce qui a rendu NodeJS populaire (bien que NodeJS ne soit pas parallèle) et c'est la force de Go en tant que langage de programmation. @@ -255,11 +255,11 @@ Et comme on peut avoir du parallélisme et de l'asynchronicité en même temps, ### Est-ce que la concurrence est mieux que le parallélisme ? { #is-concurrency-better-than-parallelism } -Nope ! C'est ça la morale de l'histoire. +Nope ! Ce n'est pas la morale de l'histoire. -La concurrence est différente du parallélisme. C'est mieux sur des scénarios **spécifiques** qui impliquent beaucoup d'attente. À cause de ça, c'est généralement bien meilleur que le parallélisme pour le développement d'applications web. Mais pas pour tout. +La concurrence est différente du parallélisme. Et c'est mieux dans des scénarios **spécifiques** qui impliquent beaucoup d'attente. À cause de ça, c'est généralement bien meilleur que le parallélisme pour le développement d'applications web. Mais pas pour tout. -Donc pour équilibrer tout ça, imaginez l'histoire suivante : +Donc pour équilibrer tout ça, imaginez l'histoire courte suivante : > Vous devez nettoyer une grande et sale maison. @@ -269,42 +269,42 @@ Donc pour équilibrer tout ça, imaginez l'histoire suivante : Il n'y a plus d'attente 🕙 nulle part, juste beaucoup de travail à effectuer, dans différentes pièces de la maison. -Vous pourriez diviser en différentes sections comme avec les burgers, d'abord le salon, puis la cuisine, etc. Mais vous n'attendez 🕙 rien, vous ne faites que nettoyer et nettoyer, la séparation en sections ne changerait rien au final. +Vous pourriez avoir des tours comme dans l'exemple des burgers, d'abord le salon, puis la cuisine, mais comme vous n'attendez 🕙 rien, vous ne faites que nettoyer et nettoyer, les tours ne changeraient rien. -Cela prendrait autant de temps pour finir avec ou sans sections (concurrence) et vous auriez effectué la même quantité de travail. +Cela prendrait autant de temps pour finir avec ou sans tours (concurrence) et vous auriez effectué la même quantité de travail. -Mais dans ce cas, si pouviez amener 8 ex-serveurs/cuisiniers/devenus-nettoyeurs 👨‍🍳👨‍🍳👨‍🍳👨‍🍳👨‍🍳👨‍🍳👨‍🍳👨‍🍳, et que chacun d'eux (plus vous) pouvait prendre une zone de la maison pour la nettoyer, vous pourriez faire tout le travail en parallèle, et finir plus tôt. +Mais dans ce cas, si vous pouviez amener les 8 ex-caissiers/cuisiniers/désormais-nettoyeurs, et que chacun d'eux (plus vous) pouvait prendre une zone de la maison pour la nettoyer, vous pourriez faire tout le travail en **parallèle**, avec l'aide supplémentaire, et finir beaucoup plus tôt. Dans ce scénario, chacun des nettoyeurs (vous y compris) serait un processeur, faisant sa partie du travail. -Et comme la plupart du temps d'exécution est pris par du « vrai » travail (et non de l'attente), et que le travail dans un ordinateur est fait par un CPU, ce sont des problèmes dits « CPU bound ». +Et comme la plupart du temps d'exécution est pris par du vrai travail (et non de l'attente), et que le travail dans un ordinateur est fait par un CPU, ce sont des problèmes dits « CPU bound ». --- -Des exemples communs d'opérations « CPU bound » sont les procédés qui requièrent des traitements mathématiques complexes. +Des exemples communs d'opérations CPU bound sont les choses qui requièrent des traitements mathématiques complexes. Par exemple : -* Traitements d'**audio** et d'**images**. -* La **vision par ordinateur** : une image est composée de millions de pixels, chaque pixel ayant 3 valeurs / couleurs, les traiter tous va nécessiter d'effectuer des traitements sur chaque pixel, et de préférence tous en même temps. -* L'apprentissage automatique (ou **Machine Learning**) : cela nécessite de nombreuses multiplications de matrices et vecteurs. Imaginez une énorme feuille de calcul remplie de nombres que vous multiplierez entre eux tous au même moment. -* L'apprentissage profond (ou **Deep Learning**) : est un sous-domaine du **Machine Learning**, donc les mêmes raisons s'appliquent. Avec la différence qu'il n'y a pas une unique feuille de calcul de nombres à multiplier, mais une énorme quantité d'entre elles, et dans de nombreux cas, on utilise un processeur spécial pour construire et / ou utiliser ces modèles. +* Traitements d'**audio** ou d'**images**. +* **Computer vision** : une image est composée de millions de pixels, chaque pixel ayant 3 valeurs / couleurs, les traiter nécessite normalement d'effectuer des calculs sur ces pixels, tous en même temps. +* **Machine Learning** : cela nécessite normalement de nombreuses multiplications de « matrices » et de « vecteurs ». Imaginez une énorme feuille de calcul remplie de nombres et les multiplier tous ensemble au même moment. +* **Deep Learning** : c'est un sous-domaine du Machine Learning, donc les mêmes raisons s'appliquent. C'est juste qu'il n'y a pas une unique feuille de calcul de nombres à multiplier, mais une énorme quantité d'entre elles, et dans de nombreux cas, on utilise un processeur spécial pour construire et / ou utiliser ces modèles. ### Concurrence + Parallélisme : Web + Machine Learning { #concurrency-parallelism-web-machine-learning } -Avec **FastAPI** vous pouvez bénéficier de la concurrence qui est très courante en développement web (c'est l'attrait principal de NodeJS). +Avec **FastAPI** vous pouvez bénéficier de la concurrence qui est très courante en développement web (le même attrait principal de NodeJS). -Mais vous pouvez aussi profiter du parallélisme et du multiprocessing (plusieurs processus s'exécutant en parallèle) afin de gérer des charges **CPU bound** qui sont récurrentes dans les systèmes de *Machine Learning*. +Mais vous pouvez aussi profiter du parallélisme et du multiprocessing (plusieurs processus s'exécutant en parallèle) afin de gérer des charges **CPU bound** comme celles des systèmes de Machine Learning. -Ça, ajouté au fait que Python soit le langage le plus populaire pour la **Data Science**, le **Machine Learning** et surtout le **Deep Learning**, font de **FastAPI** un très bon choix pour les APIs et applications de **Data Science** / **Machine Learning**. +Ça, ajouté au simple fait que Python soit le langage principal pour la **Data Science**, le Machine Learning et surtout le Deep Learning, fait de FastAPI un très bon choix pour les APIs web et applications de Data Science / Machine Learning (entre autres). -Pour comprendre comment mettre en place ce parallélisme en production, allez lire la section [Déploiement](deployment/index.md). +Pour comprendre comment mettre en place ce parallélisme en production, consultez la section sur le [Déploiement](deployment/index.md). ## `async` et `await` { #async-and-await } -Les versions modernes de Python ont une manière très intuitive de définir le code asynchrone, tout en gardant une apparence de code « séquentiel » classique en laissant Python faire l'attente pour vous au bon moment. +Les versions modernes de Python ont une manière très intuitive de définir le code asynchrone. Cela le fait ressembler à du code « séquentiel » normal et effectue l'« attente » pour vous aux bons moments. -Pour une opération qui nécessite de l'attente avant de donner un résultat et qui supporte ces nouvelles fonctionnalités Python, vous pouvez l'utiliser comme tel : +Pour une opération qui nécessite de l'attente avant de donner un résultat et qui supporte ces nouvelles fonctionnalités Python, vous pouvez l'écrire comme ceci : ```Python burgers = await get_burgers(2) @@ -312,7 +312,7 @@ burgers = await get_burgers(2) Le mot-clé important ici est `await`. Il informe Python qu'il faut attendre ⏸ que `get_burgers(2)` finisse d'effectuer ses opérations 🕙 avant de stocker les résultats dans la variable `burgers`. Grâce à cela, Python saura qu'il peut aller effectuer d'autres opérations 🔀 ⏯ pendant ce temps (comme par exemple recevoir une autre requête). -Pour que `await` fonctionne, il doit être placé dans une fonction qui supporte l'asynchronicité. Pour que ça soit le cas, il faut déclarer cette dernière avec `async def` : +Pour que `await` fonctionne, il doit être placé dans une fonction qui supporte cette asynchronicité. Pour que ça soit le cas, il faut déclarer cette dernière avec `async def` : ```Python hl_lines="1" async def get_burgers(number: int): @@ -320,7 +320,7 @@ async def get_burgers(number: int): return burgers ``` -... et non `def` : +... au lieu de `def` : ```Python hl_lines="2" # Ceci n'est pas asynchrone @@ -331,16 +331,16 @@ def get_sequential_burgers(number: int): Avec `async def`, Python sait que dans cette fonction il doit prendre en compte les expressions `await`, et qu'il peut mettre en pause ⏸ l'exécution de la fonction pour aller faire autre chose 🔀 avant de revenir. -Pour appeler une fonction définie avec `async def`, vous devez utiliser `await`. Donc ceci ne marche pas : +Lorsque vous voulez appeler une fonction `async def`, vous devez l'« attendre ». Donc ceci ne marche pas : ```Python -# Ceci ne fonctionne pas, car get_burgers a été défini avec async def +# Ceci ne fonctionne pas, car get_burgers a été défini avec : async def burgers = get_burgers(2) ``` --- -Donc, si vous utilisez une bibliothèque qui nécessite que ses fonctions soient appelées avec `await`, vous devez définir la *fonction de chemin d'accès* en utilisant `async def` comme dans : +Donc, si vous utilisez une bibliothèque qui vous indique que vous pouvez l'appeler avec `await`, vous devez créer les *fonctions de chemin d'accès* qui l'utilisent avec `async def`, comme dans : ```Python hl_lines="2-3" @app.get('/burgers') @@ -351,13 +351,13 @@ async def read_burgers(): ### Plus de détails techniques { #more-technical-details } -Vous avez donc compris que `await` peut seulement être utilisé dans des fonctions définies avec `async def`. +Vous avez peut-être remarqué que `await` peut seulement être utilisé dans des fonctions définies avec `async def`. -Mais en même temps, les fonctions définies avec `async def` doivent être appelées avec `await` et donc dans des fonctions définies elles aussi avec `async def`. +Mais en même temps, les fonctions définies avec `async def` doivent être « attendues ». Donc, les fonctions avec `async def` peuvent seulement être appelées à l'intérieur de fonctions définies elles aussi avec `async def`. -Vous avez donc remarqué ce paradoxe d'œuf et de la poule, comment appelle-t-on la première fonction `async` ? +Donc, à propos de l'œuf et de la poule, comment appelle-t-on la première fonction `async` ? -Si vous utilisez **FastAPI**, pas besoin de vous en inquiéter, car cette « première » fonction sera votre *fonction de chemin d'accès* ; et **FastAPI** saura comment arriver au résultat attendu. +Si vous utilisez **FastAPI**, pas besoin de vous en inquiéter, car cette « première » fonction sera votre *fonction de chemin d'accès*, et FastAPI saura comment faire ce qu'il faut. Mais si vous souhaitez utiliser `async` / `await` sans FastAPI, vous pouvez également le faire. @@ -367,7 +367,7 @@ Starlette (et **FastAPI**) s’appuie sur [AnyIO](https://anyio.readthedocs.io/e En particulier, vous pouvez utiliser directement [AnyIO](https://anyio.readthedocs.io/en/stable/) pour vos cas d’usage de concurrence avancés qui nécessitent des schémas plus élaborés dans votre propre code. -Et même si vous n’utilisiez pas FastAPI, vous pourriez aussi écrire vos propres applications async avec [AnyIO](https://anyio.readthedocs.io/en/stable/) pour une grande compatibilité et pour bénéficier de ses avantages (par ex. la « structured concurrency »). +Et même si vous n’utilisiez pas FastAPI, vous pourriez aussi écrire vos propres applications async avec [AnyIO](https://anyio.readthedocs.io/en/stable/) pour une grande compatibilité et pour bénéficier de ses avantages (par ex. la *structured concurrency*). J’ai créé une autre bibliothèque au-dessus d’AnyIO, comme une fine surcouche, pour améliorer un peu les annotations de type et obtenir une meilleure **autocomplétion**, des **erreurs en ligne**, etc. Elle propose également une introduction et un tutoriel accessibles pour vous aider à **comprendre** et écrire **votre propre code async** : [Asyncer](https://asyncer.tiangolo.com/). Elle sera particulièrement utile si vous devez **combiner du code async avec du code classique** (bloquant/synchrone). @@ -377,25 +377,25 @@ L'utilisation d'`async` et `await` est relativement nouvelle dans ce langage. Mais cela rend la programmation asynchrone bien plus simple. -Cette même syntaxe (ou presque) a aussi été incluse récemment dans les versions modernes de JavaScript (dans les navigateurs et NodeJS). +Cette même syntaxe (ou presque) a aussi été incluse récemment dans les versions modernes de JavaScript (dans le navigateur et NodeJS). Mais avant ça, gérer du code asynchrone était bien plus complexe et difficile. -Dans les versions précédentes de Python, vous auriez utilisé des threads ou [Gevent](https://www.gevent.org/). Mais le code aurait été bien plus difficile à comprendre, débugger, et concevoir. +Dans les versions précédentes de Python, vous auriez pu utiliser des threads ou [Gevent](https://www.gevent.org/). Mais le code est bien plus difficile à comprendre, débugger, et concevoir. -Dans les versions précédentes de JavaScript côté navigateur / NodeJS, vous auriez utilisé des « callbacks ». Menant potentiellement à ce que l'on appelle le « callback hell ». +Dans les versions précédentes de NodeJS / JavaScript de navigateur, vous auriez utilisé des « callbacks ». Ce qui mène au « callback hell ». ## Coroutines { #coroutines } -« Coroutine » est juste un terme élaboré pour désigner ce qui est retourné par une fonction définie avec `async def`. Python sait que c'est comme une fonction classique qui va démarrer à un moment et terminer à un autre, mais qu'elle peut aussi être mise en pause ⏸, du moment qu'il y a un `await` dans son contenu. +**Coroutine** est juste un terme élaboré pour désigner ce qui est retourné par une fonction définie avec `async def`. Python sait que c'est comme une fonction, qui peut démarrer et qui se terminera à un moment, mais qu'elle peut aussi être mise en pause ⏸ en interne, quand il y a un `await` à l'intérieur. Mais toutes ces fonctionnalités d'utilisation de code asynchrone avec `async` et `await` sont souvent résumées comme l'utilisation des « coroutines ». On peut comparer cela à la principale fonctionnalité clé de Go, les « Goroutines ». ## Conclusion { #conclusion } -Reprenons la phrase du début de la page : +Reprenons la même phrase ci-dessus : -> Les versions modernes de Python supportent le **code asynchrone** grâce aux **« coroutines »** avec les syntaxes **`async` et `await`**. +> Les versions modernes de Python supportent le **« code asynchrone »** en utilisant quelque chose appelé **« coroutines »**, avec la syntaxe **`async` et `await`**. Ceci devrait être plus compréhensible désormais. ✨ @@ -409,25 +409,25 @@ Vous pouvez probablement ignorer cela. Ce sont des détails très poussés sur comment **FastAPI** fonctionne en arrière-plan. -Si vous avez de bonnes connaissances techniques (coroutines, threads, code bloquant, etc.) et êtes curieux de comment **FastAPI** gère `async def` versus le `def` classique, cette partie est faite pour vous. +Si vous avez de bonnes connaissances techniques (coroutines, threads, code bloquant, etc.) et êtes curieux de comment FastAPI gère `async def` versus le `def` classique, cette partie est faite pour vous. /// ### Fonctions de chemin d'accès { #path-operation-functions } -Quand vous déclarez une *fonction de chemin d'accès* avec un `def` normal et non `async def`, elle est exécutée dans un groupe de threads (threadpool) externe qui est ensuite attendu, plutôt que d'être appelée directement (car cela bloquerait le serveur). +Quand vous déclarez une *fonction de chemin d'accès* avec un `def` normal et non `async def`, elle est exécutée dans une threadpool externe qui est ensuite attendue, plutôt que d'être appelée directement (car cela bloquerait le serveur). -Si vous venez d'un autre framework asynchrone qui ne fonctionne pas comme de la façon décrite ci-dessus et que vous êtes habitué à définir des *fonctions de chemin d'accès* basiques et purement calculatoires avec un simple `def` pour un faible gain de performance (environ 100 nanosecondes), veuillez noter que dans **FastAPI**, l'effet serait plutôt contraire. Dans ces cas-là, il vaut mieux utiliser `async def` à moins que votre *fonction de chemin d'accès* utilise du code qui effectue des opérations I/O bloquantes. +Si vous venez d'un autre framework async qui ne fonctionne pas de la façon décrite ci-dessus et que vous êtes habitué à définir des *fonctions de chemin d'accès* triviales faisant uniquement du calcul avec un simple `def` pour un faible gain de performance (environ 100 nanosecondes), veuillez noter que dans **FastAPI**, l'effet serait plutôt contraire. Dans ces cas-là, il vaut mieux utiliser `async def` à moins que vos *fonctions de chemin d'accès* utilisent du code qui effectue des opérations I/O bloquantes. -Au final, dans les deux situations, il est fort probable que **FastAPI** soit tout de même [plus rapide](index.md#performance) que (ou au moins de vitesse égale à) votre framework précédent. +Au final, dans les deux situations, il est fort probable que **FastAPI** soit [tout de même plus rapide](index.md#performance) que (ou au moins comparable à) votre framework précédent. ### Dépendances { #dependencies } -La même chose s'applique aux [dépendances](tutorial/dependencies/index.md). Si une dépendance est définie avec `def` plutôt que `async def`, elle est exécutée dans la threadpool externe. +La même chose s'applique aux [dépendances](tutorial/dependencies/index.md). Si une dépendance est une fonction standard `def` plutôt qu'`async def`, elle est exécutée dans la threadpool externe. ### Sous-dépendances { #sub-dependencies } -Vous pouvez avoir de multiples dépendances et [sous-dépendances](tutorial/dependencies/sub-dependencies.md) dépendant les unes des autres (en tant que paramètres de la définition de la *fonction de chemin d'accès*), certaines créées avec `async def` et d'autres avec `def`. Cela fonctionnerait aussi, et celles définies avec un simple `def` seraient exécutées sur un thread externe (venant de la threadpool) plutôt que d'être « attendues ». +Vous pouvez avoir de multiples dépendances et [sous-dépendances](tutorial/dependencies/sub-dependencies.md) dépendant les unes des autres (en tant que paramètres des définitions des fonctions), certaines créées avec `async def` et d'autres avec un `def` normal. Cela fonctionnerait aussi, et celles définies avec un `def` normal seraient appelées sur un thread externe (venant de la threadpool) plutôt que d'être « attendues ». ### Autres fonctions utilitaires { #other-utility-functions } @@ -435,10 +435,10 @@ Toute autre fonction utilitaire que vous appelez directement peut être créée Contrairement aux fonctions que FastAPI appelle pour vous : les *fonctions de chemin d'accès* et dépendances. -Si votre fonction utilitaire est une fonction classique définie avec `def`, elle sera appelée directement (telle qu'écrite dans votre code), pas dans une threadpool ; si la fonction est définie avec `async def` alors vous devrez attendre (avec `await`) que cette fonction se termine avant de passer à la suite du code. +Si votre fonction utilitaire est une fonction classique définie avec `def`, elle sera appelée directement (telle qu'écrite dans votre code), pas dans une threadpool ; si la fonction est définie avec `async def` alors vous devez `await` cette fonction lorsque vous l'appelez dans votre code. --- Encore une fois, ce sont des détails très techniques qui peuvent être utiles si vous venez ici les chercher. -Sinon, les instructions de la section Vous êtes pressés ? ci-dessus sont largement suffisantes. +Sinon, les instructions de la section ci-dessus sont largement suffisantes : Vous êtes pressés ?. diff --git a/docs/fr/docs/deployment/cloud.md b/docs/fr/docs/deployment/cloud.md index 1ed030f0a..368966372 100644 --- a/docs/fr/docs/deployment/cloud.md +++ b/docs/fr/docs/deployment/cloud.md @@ -1,6 +1,6 @@ # Déployer FastAPI sur des fournisseurs cloud { #deploy-fastapi-on-cloud-providers } -Vous pouvez utiliser pratiquement n'importe quel fournisseur cloud pour déployer votre application FastAPI. +Vous pouvez utiliser pratiquement **n'importe quel fournisseur cloud** pour déployer votre application FastAPI. Dans la plupart des cas, les principaux fournisseurs cloud proposent des guides pour déployer FastAPI avec leurs services. @@ -16,7 +16,7 @@ FastAPI Cloud est le sponsor principal et le financeur des projets open source * ## Fournisseurs cloud - Sponsors { #cloud-providers-sponsors } -D'autres fournisseurs cloud ✨ [**parrainent FastAPI**](../help-fastapi.md#sponsor-the-author) ✨ également. 🙇 +Certains autres fournisseurs cloud ✨ [**parrainent FastAPI**](https://github.com/sponsors/tiangolo) ✨ également. 🙇 Vous pouvez également envisager ces fournisseurs pour suivre leurs guides et essayer leurs services : diff --git a/docs/fr/docs/deployment/concepts.md b/docs/fr/docs/deployment/concepts.md index 1d5497d93..d6940c683 100644 --- a/docs/fr/docs/deployment/concepts.md +++ b/docs/fr/docs/deployment/concepts.md @@ -1,5 +1,6 @@ # Concepts de déploiement { #deployments-concepts } + Lorsque vous déployez une application **FastAPI**, ou en fait n'importe quel type de web API, il existe plusieurs concepts qui vous importent probablement, et en les utilisant vous pouvez trouver la manière la **plus appropriée** de **déployer votre application**. Parmi les concepts importants, on trouve : diff --git a/docs/fr/docs/deployment/docker.md b/docs/fr/docs/deployment/docker.md index 5184d51df..688f3b5d8 100644 --- a/docs/fr/docs/deployment/docker.md +++ b/docs/fr/docs/deployment/docker.md @@ -232,7 +232,7 @@ Passez en revue ce que fait chaque ligne en cliquant sur chaque bulle numéroté /// warning | Alertes -Vous devez vous assurer d'utiliser **toujours** la **forme exec** de l'instruction `CMD`, comme expliqué ci-dessous. +Vous devez **toujours** utiliser la **forme exec** de l'instruction `CMD`, comme expliqué ci-dessous. /// @@ -254,7 +254,7 @@ CMD ["fastapi", "run", "app/main.py", "--port", "80"] CMD fastapi run app/main.py --port 80 ``` -Assurez-vous d'utiliser toujours la forme **exec** pour garantir que FastAPI peut s'arrêter proprement et que les [événements de cycle de vie](../advanced/events.md) sont déclenchés. +Vous devez toujours utiliser la forme **exec** pour garantir que FastAPI peut s'arrêter proprement et que les [événements de cycle de vie](../advanced/events.md) sont déclenchés. Vous pouvez en lire davantage dans la [documentation Docker sur les formes shell et exec](https://docs.docker.com/reference/dockerfile/#shell-and-exec-form). diff --git a/docs/fr/docs/deployment/https.md b/docs/fr/docs/deployment/https.md index 34922f168..5150ecdeb 100644 --- a/docs/fr/docs/deployment/https.md +++ b/docs/fr/docs/deployment/https.md @@ -10,9 +10,9 @@ Si vous êtes pressé ou si cela ne vous intéresse pas, continuez avec les sect /// -Pour apprendre les bases du HTTPS, du point de vue d'un utilisateur, consultez [https://howhttps.works/](https://howhttps.works/). +Pour **apprendre les bases du HTTPS**, du point de vue d'un utilisateur, consultez [https://howhttps.works/](https://howhttps.works/). -Maintenant, du point de vue d'un développeur, voici plusieurs choses à avoir en tête en pensant au HTTPS : +Maintenant, du **point de vue d'un développeur**, voici plusieurs choses à avoir en tête en pensant au HTTPS : * Pour le HTTPS, **le serveur** doit **disposer de « certificats »** générés par une **tierce partie**. * Ces certificats sont en réalité **acquis** auprès de la tierce partie, et non « générés ». @@ -65,7 +65,7 @@ Voici un exemple de ce à quoi pourrait ressembler une API HTTPS, étape par ét Tout commencerait probablement par le fait que vous **acquériez** un **nom de domaine**. Ensuite, vous le configureriez dans un serveur DNS (possiblement le même que votre fournisseur cloud). -Vous obtiendriez probablement un serveur cloud (une machine virtuelle) ou quelque chose de similaire, et il aurait une adresse IP publique fixe. +Vous obtiendriez probablement un serveur cloud (une machine virtuelle) ou quelque chose de similaire, et il aurait une **adresse IP publique** fixe. Dans le ou les serveurs DNS, vous configureriez un enregistrement (un « `A record` ») pour faire pointer **votre domaine** vers l'**adresse IP publique de votre serveur**. diff --git a/docs/fr/docs/deployment/manually.md b/docs/fr/docs/deployment/manually.md index 90dd31d85..2d9cc4f8f 100644 --- a/docs/fr/docs/deployment/manually.md +++ b/docs/fr/docs/deployment/manually.md @@ -40,7 +40,7 @@ $ fastapi run ASGI. FastAPI est un framework web ASGI. -La principale chose dont vous avez besoin pour exécuter une application **FastAPI** (ou toute autre application ASGI) sur une machine serveur distante est un programme serveur ASGI comme **Uvicorn**, c'est celui utilisé par défaut par la commande `fastapi`. +La principale chose dont vous avez besoin pour exécuter une application **FastAPI** (ou toute autre application ASGI) sur une machine serveur distante est un programme serveur ASGI comme **Uvicorn**, c'est celui fourni par défaut avec la commande `fastapi`. Il existe plusieurs alternatives, notamment : @@ -61,9 +61,9 @@ Il existe plusieurs alternatives, notamment : Il y a un petit détail sur les noms à garder à l'esprit. 💡 -Le mot « serveur » est couramment utilisé pour désigner à la fois l'ordinateur distant/cloud (la machine physique ou virtuelle) et également le programme qui s'exécute sur cette machine (par exemple, Uvicorn). +Le mot « **serveur** » est couramment utilisé pour désigner à la fois l'ordinateur distant/cloud (la machine physique ou virtuelle) et également le programme qui s'exécute sur cette machine (par exemple, Uvicorn). -Gardez cela à l'esprit lorsque vous lisez « serveur » en général, cela pourrait faire référence à l'une de ces deux choses. +Gardez simplement à l'esprit que lorsque vous lisez « serveur » en général, cela pourrait faire référence à l'une de ces deux choses. Lorsqu'on se réfère à la machine distante, il est courant de l'appeler **serveur**, mais aussi **machine**, **VM** (machine virtuelle), **nœud**. Tout cela fait référence à un type de machine distante, exécutant normalement Linux, sur laquelle vous exécutez des programmes. @@ -117,7 +117,7 @@ $ uvicorn main:app --host 0.0.0.0 --port 80 La commande `uvicorn main:app` fait référence à : -* `main` : le fichier `main.py` (le « module » Python). +* `main` : le fichier `main.py` (le « module » Python). * `app` : l'objet créé dans `main.py` avec la ligne `app = FastAPI()`. C'est équivalent à : diff --git a/docs/fr/docs/editor-support.md b/docs/fr/docs/editor-support.md index 59e0b3f15..a29b3b261 100644 --- a/docs/fr/docs/editor-support.md +++ b/docs/fr/docs/editor-support.md @@ -1,6 +1,6 @@ # Prise en charge des éditeurs { #editor-support } -L’extension officielle [Extension FastAPI](https://marketplace.visualstudio.com/items?itemName=FastAPILabs.fastapi-vscode) améliore votre flux de développement FastAPI grâce à la découverte des chemins d'accès, à la navigation, ainsi qu’au déploiement sur FastAPI Cloud et à la diffusion en direct des journaux. +L’extension officielle [Extension FastAPI](https://marketplace.visualstudio.com/items?itemName=FastAPILabs.fastapi-vscode) améliore votre flux de développement FastAPI grâce à la découverte des *chemins d'accès*, à la navigation, ainsi qu’au déploiement sur FastAPI Cloud et à la diffusion en direct des journaux. Pour plus de détails sur l’extension, reportez-vous au README sur le [référentiel GitHub](https://github.com/fastapi/fastapi-vscode). diff --git a/docs/fr/docs/environment-variables.md b/docs/fr/docs/environment-variables.md index 7f052f27f..065194700 100644 --- a/docs/fr/docs/environment-variables.md +++ b/docs/fr/docs/environment-variables.md @@ -6,13 +6,13 @@ Si vous savez déjà ce que sont les « variables d'environnement » et comment /// -Une variable d'environnement (également appelée « env var ») est une variable qui vit en dehors du code Python, dans le système d'exploitation, et qui peut être lue par votre code Python (ou par d'autres programmes également). +Une variable d'environnement (également appelée « **env var** ») est une variable qui vit **en dehors** du code Python, dans le **système d'exploitation**, et qui peut être lue par votre code Python (ou par d'autres programmes également). Les variables d'environnement peuvent être utiles pour gérer des **paramètres** d'application, dans le cadre de l'**installation** de Python, etc. ## Créer et utiliser des variables d'environnement { #create-and-use-env-vars } -Vous pouvez créer et utiliser des variables d'environnement dans le **shell (terminal)**, sans avoir besoin de Python : +Vous pouvez **créer** et utiliser des variables d'environnement dans le **shell (terminal)**, sans avoir besoin de Python : //// tab | Linux, macOS, Windows Bash @@ -54,7 +54,7 @@ Hello Wade Wilson Vous pouvez également créer des variables d'environnement **en dehors** de Python, dans le terminal (ou par tout autre moyen), puis les **lire en Python**. -Par exemple, vous pouvez avoir un fichier `main.py` contenant : +Par exemple, vous pouvez avoir un fichier `main.py` contenant : ```Python hl_lines="3" import os @@ -71,7 +71,7 @@ S'il n'est pas fourni, c'est `None` par défaut ; ici, nous fournissons `"World" /// -Vous pouvez ensuite exécuter ce programme Python : +Vous pouvez ensuite exécuter ce programme Python : //// tab | Linux, macOS, Windows Bash @@ -131,7 +131,7 @@ Comme les variables d'environnement peuvent être définies en dehors du code, m Vous pouvez également créer une variable d'environnement uniquement pour l'**invocation d'un programme spécifique**, qui ne sera disponible que pour ce programme et uniquement pendant sa durée d'exécution. -Pour cela, créez-la juste avant le programme, sur la même ligne : +Pour cela, créez-la juste avant le programme, sur la même ligne :
@@ -159,7 +159,7 @@ Vous pouvez en lire davantage sur [The Twelve-Factor App : Config](https://12fac ## Gérer les types et la validation { #types-and-validation } -Ces variables d'environnement ne peuvent gérer que des **chaînes de texte**, car elles sont externes à Python et doivent être compatibles avec les autres programmes et le reste du système (et même avec différents systèmes d'exploitation, comme Linux, Windows, macOS). +Ces variables d'environnement ne peuvent gérer que des **chaînes de texte**, car elles sont externes à Python et doivent être compatibles avec les autres programmes et le reste du système (et même avec différents systèmes d'exploitation, comme Linux, Windows et macOS). Cela signifie que **toute valeur** lue en Python à partir d'une variable d'environnement **sera une `str`**, et que toute conversion vers un autre type ou toute validation doit être effectuée dans le code. @@ -167,11 +167,11 @@ Vous en apprendrez davantage sur l'utilisation des variables d'environnement pou ## Variable d'environnement `PATH` { #path-environment-variable } -Il existe une **variable d'environnement spéciale** appelée **`PATH`** qui est utilisée par les systèmes d'exploitation (Linux, macOS, Windows) pour trouver les programmes à exécuter. +Il existe une variable d'environnement **spéciale** appelée **`PATH`** qui est utilisée par les systèmes d'exploitation (Linux, macOS, Windows) pour trouver les programmes à exécuter. La valeur de la variable `PATH` est une longue chaîne composée de répertoires séparés par deux-points `:` sous Linux et macOS, et par point-virgule `;` sous Windows. -Par exemple, la variable d'environnement `PATH` peut ressembler à ceci : +Par exemple, la variable d'environnement `PATH` peut ressembler à ceci : //// tab | Linux, macOS @@ -179,7 +179,7 @@ Par exemple, la variable d'environnement `PATH` peut ressembler à ceci : /usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbin ``` -Cela signifie que le système doit rechercher les programmes dans les répertoires : +Cela signifie que le système doit rechercher les programmes dans les répertoires : * `/usr/local/bin` * `/usr/bin` @@ -195,7 +195,7 @@ Cela signifie que le système doit rechercher les programmes dans les répertoir C:\Program Files\Python312\Scripts;C:\Program Files\Python312;C:\Windows\System32 ``` -Cela signifie que le système doit rechercher les programmes dans les répertoires : +Cela signifie que le système doit rechercher les programmes dans les répertoires : * `C:\Program Files\Python312\Scripts` * `C:\Program Files\Python312` @@ -219,7 +219,7 @@ Supposons que vous installiez Python et qu'il se retrouve dans un répertoire `/ Si vous acceptez de mettre à jour la variable d'environnement `PATH`, l'installateur ajoutera `/opt/custompython/bin` à la variable d'environnement `PATH`. -Cela pourrait ressembler à ceci : +Cela pourrait ressembler à ceci : ```plaintext /usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbin:/opt/custompython/bin @@ -243,7 +243,7 @@ Ainsi, lorsque vous tapez `python` dans le terminal, le système trouvera le pro //// -Ainsi, si vous tapez : +Ainsi, si vous tapez :
@@ -257,7 +257,7 @@ $ python Le système va **trouver** le programme `python` dans `/opt/custompython/bin` et l'exécuter. -Cela reviendrait à peu près à taper : +Cela reviendrait à peu près à taper :
@@ -273,7 +273,7 @@ $ /opt/custompython/bin/python Le système va **trouver** le programme `python` dans `C:\opt\custompython\bin\python` et l'exécuter. -Cela reviendrait à peu près à taper : +Cela reviendrait à peu près à taper :
diff --git a/docs/fr/docs/features.md b/docs/fr/docs/features.md index 0bb16b343..4ded18206 100644 --- a/docs/fr/docs/features.md +++ b/docs/fr/docs/features.md @@ -17,7 +17,7 @@ Documentation d'API interactive et interfaces web d'exploration. Comme le framew * [**Swagger UI**](https://github.com/swagger-api/swagger-ui), avec exploration interactive, appelez et testez votre API directement depuis le navigateur. -![Swagger UI interaction](https://fastapi.tiangolo.com/img/index/index-03-swagger-02.png) +![interaction avec Swagger UI](https://fastapi.tiangolo.com/img/index/index-03-swagger-02.png) * Documentation d'API alternative avec [**ReDoc**](https://github.com/Rebilly/ReDoc). @@ -85,11 +85,11 @@ Voici comment votre éditeur peut vous aider : * dans [Visual Studio Code](https://code.visualstudio.com/) : -![editor support](https://fastapi.tiangolo.com/img/vscode-completion.png) +![support de l'éditeur](https://fastapi.tiangolo.com/img/vscode-completion.png) * dans [PyCharm](https://www.jetbrains.com/pycharm/) : -![editor support](https://fastapi.tiangolo.com/img/pycharm-completion.png) +![support de l'éditeur](https://fastapi.tiangolo.com/img/pycharm-completion.png) Vous obtiendrez de l'autocomplétion dans du code que vous auriez pu considérer impossible auparavant. Par exemple, la clé `price` à l'intérieur d'un corps JSON (qui aurait pu être imbriqué) provenant d'une requête. @@ -105,7 +105,7 @@ Mais par défaut, tout **« just works »**. * Validation pour la plupart (ou tous ?) des **types de données** Python, y compris : * objets JSON (`dict`). - * tableaux JSON (`list`) définissant les types d'éléments. + * tableau JSON (`list`) définissant les types d'éléments. * champs String (`str`), définition des longueurs minimale et maximale. * nombres (`int`, `float`) avec valeurs minimale et maximale, etc. diff --git a/docs/fr/docs/help-fastapi.md b/docs/fr/docs/help-fastapi.md index 7a6da3c08..db46bcbc1 100644 --- a/docs/fr/docs/help-fastapi.md +++ b/docs/fr/docs/help-fastapi.md @@ -1,5 +1,6 @@ # Aider { #help } + Souhaitez-vous aider FastAPI ou obtenir de l'aide à propos de FastAPI ? Il existe des moyens très simples d'aider et d'obtenir de l'aide. diff --git a/docs/fr/docs/how-to/configure-swagger-ui.md b/docs/fr/docs/how-to/configure-swagger-ui.md index 34db05558..e4f876323 100644 --- a/docs/fr/docs/how-to/configure-swagger-ui.md +++ b/docs/fr/docs/how-to/configure-swagger-ui.md @@ -50,11 +50,11 @@ Par exemple, pour désactiver `deepLinking`, vous pourriez passer ces paramètre ## Autres paramètres de Swagger UI { #other-swagger-ui-parameters } -Pour voir toutes les autres configurations possibles que vous pouvez utiliser, lisez les [documents officiels pour les paramètres de Swagger UI](https://swagger.io/docs/open-source-tools/swagger-ui/usage/configuration/). +Pour voir toutes les autres configurations possibles que vous pouvez utiliser, lisez les documents officiels [pour les paramètres de Swagger UI](https://swagger.io/docs/open-source-tools/swagger-ui/usage/configuration/). ## Paramètres JavaScript uniquement { #javascript-only-settings } -Swagger UI permet également d'autres configurations qui sont des objets réservés à JavaScript (par exemple, des fonctions JavaScript). +Swagger UI permet également d'autres configurations qui sont des objets **réservés à JavaScript** (par exemple, des fonctions JavaScript). FastAPI inclut aussi ces paramètres `presets` réservés à JavaScript : diff --git a/docs/fr/docs/how-to/custom-request-and-route.md b/docs/fr/docs/how-to/custom-request-and-route.md index 4acb6464f..0b3ab88b9 100644 --- a/docs/fr/docs/how-to/custom-request-and-route.md +++ b/docs/fr/docs/how-to/custom-request-and-route.md @@ -66,7 +66,7 @@ Le `dict` `scope` et la fonction `receive` font tous deux partie de la spécific Et ces deux éléments, `scope` et `receive`, sont ce dont on a besoin pour créer une nouvelle instance de `Request`. -Pour en savoir plus sur `Request`, consultez [la documentation de Starlette sur les requêtes](https://www.starlette.dev/requests/). +Pour en savoir plus sur `Request`, consultez [les documents de Starlette sur les requêtes](https://www.starlette.dev/requests/). /// diff --git a/docs/fr/docs/how-to/graphql.md b/docs/fr/docs/how-to/graphql.md index 912608a98..10fa6be8a 100644 --- a/docs/fr/docs/how-to/graphql.md +++ b/docs/fr/docs/how-to/graphql.md @@ -19,9 +19,9 @@ Assurez-vous d'évaluer si les **bénéfices** pour votre cas d'utilisation comp Voici quelques bibliothèques **GraphQL** qui prennent en charge **ASGI**. Vous pouvez les utiliser avec **FastAPI** : * [Strawberry](https://strawberry.rocks/) 🍓 - * Avec [la documentation pour FastAPI](https://strawberry.rocks/docs/integrations/fastapi) + * Avec [les documents pour FastAPI](https://strawberry.rocks/docs/integrations/fastapi) * [Ariadne](https://ariadnegraphql.org/) - * Avec [la documentation pour FastAPI](https://ariadnegraphql.org/docs/fastapi-integration) + * Avec [les documents pour FastAPI](https://ariadnegraphql.org/docs/fastapi-integration) * [Tartiflette](https://tartiflette.io/) * Avec [Tartiflette ASGI](https://tartiflette.github.io/tartiflette-asgi/) pour fournir l'intégration ASGI * [Graphene](https://graphene-python.org/) @@ -39,7 +39,7 @@ Voici un petit aperçu de la manière dont vous pouvez intégrer Strawberry avec Vous pouvez en apprendre davantage sur Strawberry dans la [documentation de Strawberry](https://strawberry.rocks/). -Et également la documentation sur [Strawberry avec FastAPI](https://strawberry.rocks/docs/integrations/fastapi). +Et également les documents sur [Strawberry avec FastAPI](https://strawberry.rocks/docs/integrations/fastapi). ## Ancien `GraphQLApp` de Starlette { #older-graphqlapp-from-starlette } diff --git a/docs/fr/docs/how-to/migrate-from-pydantic-v1-to-pydantic-v2.md b/docs/fr/docs/how-to/migrate-from-pydantic-v1-to-pydantic-v2.md index 99d68ba81..48d4b3f2e 100644 --- a/docs/fr/docs/how-to/migrate-from-pydantic-v1-to-pydantic-v2.md +++ b/docs/fr/docs/how-to/migrate-from-pydantic-v1-to-pydantic-v2.md @@ -8,6 +8,8 @@ FastAPI version 0.119.0 a introduit une prise en charge partielle de Pydantic v1 FastAPI 0.126.0 a supprimé la prise en charge de Pydantic v1, tout en continuant à prendre en charge `pydantic.v1` pendant un certain temps. +FastAPI 0.128.0 a également supprimé la prise en charge de `pydantic.v1`, donc les dernières versions de FastAPI nécessitent Pydantic v2. + /// warning | Alertes L'équipe Pydantic a arrêté la prise en charge de Pydantic v1 pour les dernières versions de Python, à partir de **Python 3.14**. @@ -54,6 +56,16 @@ Cela signifie que vous pouvez installer la dernière version de Pydantic v2 et i ### Prise en charge de FastAPI pour Pydantic v1 dans v2 { #fastapi-support-for-pydantic-v1-in-v2 } +/// warning | Alertes + +Cette prise en charge FastAPI des modèles `pydantic.v1` a été ajoutée dans **FastAPI 0.119.0** et supprimée dans **FastAPI 0.128.0**. Elle était destinée à être une aide temporaire pour la migration vers Pydantic v2. + +Dans les versions actuelles de FastAPI, l'utilisation d'un modèle `pydantic.v1` dans votre application lèvera une erreur. + +Le reste de cette section décrit la prise en charge temporaire disponible uniquement dans ces anciennes versions. + +/// + Depuis FastAPI 0.119.0, il existe également une prise en charge partielle de Pydantic v1 depuis l'intérieur de Pydantic v2, pour faciliter la migration vers v2. Vous pouvez donc mettre à niveau Pydantic vers la dernière version 2 et modifier les imports pour utiliser le sous-module `pydantic.v1`, et dans de nombreux cas cela fonctionnera tel quel. @@ -122,6 +134,12 @@ Si vous devez utiliser certains des outils spécifiques à FastAPI pour les para ### Migrer par étapes { #migrate-in-steps } +/// warning | Alertes + +La migration progressive utilisant à la fois des modèles Pydantic v1 et v2 dans la même application décrite ci-dessous ne fonctionne que dans **FastAPI 0.119.0 à 0.127.x**. Elle a été supprimée dans **FastAPI 0.128.0**, les dernières versions nécessitent des modèles **Pydantic v2**. + +/// + /// tip | Astuce Essayez d'abord avec `bump-pydantic` ; si vos tests passent et que cela fonctionne, vous avez tout terminé en une seule commande. ✨ diff --git a/docs/fr/docs/how-to/separate-openapi-schemas.md b/docs/fr/docs/how-to/separate-openapi-schemas.md index aef467ed6..4cb92c1df 100644 --- a/docs/fr/docs/how-to/separate-openapi-schemas.md +++ b/docs/fr/docs/how-to/separate-openapi-schemas.md @@ -34,7 +34,7 @@ Mais si vous utilisez le même modèle en sortie, comme ici : {* ../../docs_src/separate_openapi_schemas/tutorial001_py310.py hl[19] *} -... alors, comme `description` a une valeur par défaut, si vous ne retournez rien pour ce champ, il aura tout de même cette **valeur par défaut**. +... alors, comme `description` a une valeur par défaut, si vous **ne retournez rien** pour ce champ, il aura tout de même cette **valeur par défaut**. ### Modèle pour les données de réponse en sortie { #model-for-output-response-data } @@ -52,8 +52,8 @@ La manière de décrire cela dans OpenAPI est de marquer ce champ comme **requis Pour cette raison, le schéma JSON d'un modèle peut être différent selon qu'il est utilisé pour **l'entrée ou la sortie** : -- pour **l'entrée**, `description` ne sera **pas requis** -- pour **la sortie**, il sera **requis** (et éventuellement `None`, ou en termes JSON, `null`) +* pour **l'entrée**, `description` ne sera **pas requis** +* pour **la sortie**, il sera **requis** (et éventuellement `None`, ou en termes JSON, `null`) ### Modèle de sortie dans les documents { #model-for-output-in-docs } @@ -79,7 +79,7 @@ Avec cette fonctionnalité de **Pydantic v2**, la documentation de votre API est ## Ne pas séparer les schémas { #do-not-separate-schemas } -Il existe des cas où vous pourriez vouloir avoir le **même schéma pour l'entrée et la sortie**. +Maintenant, il existe des cas où vous pourriez vouloir avoir le **même schéma pour l'entrée et la sortie**. Le cas d'usage principal est probablement que vous avez déjà du code client/SDKs générés automatiquement et que vous ne souhaitez pas encore mettre à jour tout ce code client/ces SDKs générés automatiquement ; vous le ferez sans doute à un moment donné, mais peut‑être pas tout de suite. @@ -95,7 +95,7 @@ La prise en charge de `separate_input_output_schemas` a été ajoutée dans Fast ### Utiliser le même schéma pour les modèles d'entrée et de sortie dans les documents { #same-schema-for-input-and-output-models-in-docs } -Désormais, il n'y aura qu'un seul schéma pour l'entrée et la sortie du modèle, uniquement `Item`, et `description` ne sera pas requis : +Désormais, il n'y aura qu'un seul schéma pour l'entrée et la sortie du modèle, uniquement `Item`, et `description` sera **non requis** :
diff --git a/docs/fr/docs/index.md b/docs/fr/docs/index.md index 3cfcdfd29..ccc00236a 100644 --- a/docs/fr/docs/index.md +++ b/docs/fr/docs/index.md @@ -45,7 +45,7 @@ Les principales fonctionnalités sont : * **Rapide** : très hautes performances, au niveau de **NodeJS** et **Go** (grâce à Starlette et Pydantic). [L'un des frameworks Python les plus rapides](#performance). * **Rapide à coder** : augmente la vitesse de développement des fonctionnalités d'environ 200 % à 300 %. * * **Moins de bugs** : réduit d'environ 40 % les erreurs induites par le développeur. * -* **Intuitif** : excellente compatibilité avec les éditeurs. Autocomplétion partout. Moins de temps passé à déboguer. +* **Intuitif** : excellente compatibilité avec les éditeurs. Autocomplétion partout. Moins de temps passé à déboguer. * **Facile** : conçu pour être facile à utiliser et à apprendre. Moins de temps passé à lire les documents. * **Concis** : diminue la duplication de code. Plusieurs fonctionnalités à partir de chaque déclaration de paramètre. Moins de bugs. * **Robuste** : obtenez un code prêt pour la production. Avec une documentation interactive automatique. @@ -192,7 +192,7 @@ $ pip install "fastapi[standard]"
-**Remarque** : Vous devez vous assurer de mettre « fastapi[standard] » entre guillemets pour garantir que cela fonctionne dans tous les terminaux. +**Remarque** : Vous devez vous assurer de mettre `"fastapi[standard]"` entre guillemets pour garantir que cela fonctionne dans tous les terminaux. ## Exemple { #example } @@ -239,7 +239,7 @@ async def read_item(item_id: int, q: str | None = None): **Remarque** : -Si vous ne savez pas, consultez la section « Vous êtes pressés ? » à propos de [`async` et `await` dans la documentation](https://fastapi.tiangolo.com/fr/async/#in-a-hurry). +Si vous ne savez pas, consultez la section « Vous êtes pressés ? » à propos de [`async` et `await` dans les documents](https://fastapi.tiangolo.com/fr/async/#in-a-hurry).
diff --git a/docs/fr/docs/project-generation.md b/docs/fr/docs/project-generation.md index e0636bfe5..b1f3f6cc4 100644 --- a/docs/fr/docs/project-generation.md +++ b/docs/fr/docs/project-generation.md @@ -1,5 +1,6 @@ # Modèle Full Stack FastAPI { #full-stack-fastapi-template } + Les modèles, bien qu'ils soient généralement livrés avec une configuration spécifique, sont conçus pour être flexibles et personnalisables. Cela vous permet de les modifier et de les adapter aux exigences de votre projet, ce qui en fait un excellent point de départ. 🏁 Vous pouvez utiliser ce modèle pour démarrer, car il inclut une grande partie de la configuration initiale, la sécurité, la base de données et quelques endpoints d'API déjà prêts pour vous. diff --git a/docs/fr/docs/python-types.md b/docs/fr/docs/python-types.md index 55bc8bdc9..8e9dbc598 100644 --- a/docs/fr/docs/python-types.md +++ b/docs/fr/docs/python-types.md @@ -44,7 +44,7 @@ C'est un programme très simple. Mais maintenant imaginez que vous l'écriviez de zéro. -À un certain moment, vous auriez commencé la définition de la fonction, vous aviez les paramètres prêts ... +À un moment donné, vous commencez à définir la fonction, et vous avez les paramètres prêts ... Mais ensuite vous devez appeler « cette méthode qui convertit la première lettre en majuscule ». @@ -279,13 +279,13 @@ Ensuite, vous créez une instance de cette classe avec certaines valeurs et elle Et vous obtenez tout le support de l'éditeur avec cet objet résultant. -Un exemple tiré de la documentation officielle de Pydantic : +Un exemple tiré des documents officiels de Pydantic : {* ../../docs_src/python_types/tutorial011_py310.py *} /// note | Remarque -Pour en savoir plus à propos de [Pydantic, consultez sa documentation](https://docs.pydantic.dev/). +Pour en savoir plus à propos de [Pydantic, consultez ses documents](https://docs.pydantic.dev/). /// @@ -305,7 +305,7 @@ Python lui-même ne fait rien avec ce `Annotated`. Et pour les éditeurs et autr Mais vous pouvez utiliser cet espace dans `Annotated` pour fournir à **FastAPI** des métadonnées supplémentaires sur la façon dont vous voulez que votre application se comporte. -L'important à retenir est que **le premier « paramètre de type »** que vous passez à `Annotated` est le **type réel**. Le reste n'est que des métadonnées pour d'autres outils. +L'important à retenir est que **le premier *paramètre de type*** que vous passez à `Annotated` est le **type réel**. Le reste n'est que des métadonnées pour d'autres outils. Pour l'instant, vous avez juste besoin de savoir que `Annotated` existe, et que c'est du Python standard. 😎 diff --git a/docs/fr/docs/tutorial/bigger-applications.md b/docs/fr/docs/tutorial/bigger-applications.md index 0e331e139..92976bca0 100644 --- a/docs/fr/docs/tutorial/bigger-applications.md +++ b/docs/fr/docs/tutorial/bigger-applications.md @@ -17,16 +17,16 @@ Supposons que vous ayez une structure de fichiers comme ceci : ``` . ├── app -│   ├── __init__.py -│   ├── main.py -│   ├── dependencies.py -│   └── routers -│   │ ├── __init__.py -│   │ ├── items.py -│   │ └── users.py -│   └── internal -│   ├── __init__.py -│   └── admin.py +│ ├── __init__.py +│ ├── main.py +│ ├── dependencies.py +│ └── routers +│ │ ├── __init__.py +│ │ ├── items.py +│ │ └── users.py +│ └── internal +│ ├── __init__.py +│ └── admin.py ``` /// tip | Astuce @@ -283,7 +283,7 @@ Mais nous pouvons toujours ajouter _davantage_ de `tags` qui seront appliqués /// tip | Astuce -Ce dernier *chemin d'accès* aura la combinaison de tags : `["items", "custom"]`. +Ce dernier chemin d'accès aura la combinaison de tags : `["items", "custom"]`. Et il aura également les deux réponses dans la documentation, une pour `404` et une pour `403`. @@ -453,7 +453,7 @@ et cela fonctionnera correctement, avec tous les autres *chemins d'accès* ajout /// note | Détails très techniques -Note : c'est un détail très technique que vous pouvez probablement **simplement ignorer**. +**Remarque** : c'est un détail très technique que vous pouvez probablement **simplement ignorer**. --- @@ -490,13 +490,13 @@ Vous pourriez aussi passer le chemin à la commande, comme : $ fastapi dev app/main.py ``` -Mais vous devriez vous rappeler de passer le bon chemin à chaque fois que vous appelez la commande `fastapi`. +Mais vous devez vous rappeler de passer le bon chemin à chaque fois que vous appelez la commande `fastapi`. En outre, d'autres outils pourraient ne pas être en mesure de la trouver, par exemple l'[Extension VS Code](../editor-support.md) ou [FastAPI Cloud](https://fastapicloud.com), il est donc recommandé d'utiliser l'`entrypoint` dans `pyproject.toml`. /// -## Consulter la documentation API automatique { #check-the-automatic-api-docs } +## Consulter les documents d'API automatiques { #check-the-automatic-api-docs } Maintenant, exécutez votre application : @@ -512,7 +512,7 @@ $ fastapi dev Et ouvrez les documents à [http://127.0.0.1:8000/docs](http://127.0.0.1:8000/docs). -Vous verrez la documentation API automatique, incluant les chemins de tous les sous-modules, utilisant les bons chemins (et préfixes) et les bons tags : +Vous verrez les documents d'API automatiques, incluant les chemins de tous les sous-modules, utilisant les bons chemins (et préfixes) et les bons tags : diff --git a/docs/fr/docs/tutorial/body-nested-models.md b/docs/fr/docs/tutorial/body-nested-models.md index 014551bc7..051317a8c 100644 --- a/docs/fr/docs/tutorial/body-nested-models.md +++ b/docs/fr/docs/tutorial/body-nested-models.md @@ -1,6 +1,6 @@ # Corps - Modèles imbriqués { #body-nested-models } -Avec FastAPI, vous pouvez définir, valider, documenter et utiliser des modèles imbriqués à n'importe quelle profondeur (grâce à Pydantic). +Avec **FastAPI**, vous pouvez définir, valider, documenter et utiliser des modèles imbriqués à n'importe quelle profondeur (grâce à Pydantic). ## Déclarer des champs de liste { #list-fields } @@ -69,7 +69,7 @@ Nous pouvons ensuite l'utiliser comme type d'un attribut : {* ../../docs_src/body_nested_models/tutorial004_py310.py hl[18] *} -Cela signifie que FastAPI attendrait un corps similaire à : +Cela signifie que **FastAPI** attendrait un corps similaire à : ```JSON { @@ -85,7 +85,7 @@ Cela signifie que FastAPI attendrait un corps similaire à : } ``` -Là encore, avec cette simple déclaration, avec FastAPI vous obtenez : +Là encore, avec cette simple déclaration, avec **FastAPI** vous obtenez : - Prise en charge par l'éditeur (autocomplétion, etc.), même pour les modèles imbriqués - Conversion des données @@ -209,7 +209,7 @@ Et le `dict` que vous recevez dans `weights` aura en réalité des clés `int` e ## Récapitulatif { #recap } -Avec FastAPI, vous bénéficiez de la flexibilité maximale fournie par les modèles Pydantic, tout en gardant votre code simple, concis et élégant. +Avec **FastAPI**, vous bénéficiez de la flexibilité maximale fournie par les modèles Pydantic, tout en gardant votre code simple, concis et élégant. Mais avec tous les avantages : diff --git a/docs/fr/docs/tutorial/body.md b/docs/fr/docs/tutorial/body.md index 55d184259..2ff716125 100644 --- a/docs/fr/docs/tutorial/body.md +++ b/docs/fr/docs/tutorial/body.md @@ -1,18 +1,18 @@ # Corps de la requête { #request-body } -Quand vous avez besoin d'envoyer de la donnée depuis un client (comme un navigateur) vers votre API, vous l'envoyez en tant que **corps de requête**. +Quand vous avez besoin d'envoyer de la donnée depuis un client (comme un navigateur) vers votre API, vous l'envoyez en tant que **corps de la requête**. Le corps d'une **requête** est de la donnée envoyée par le client à votre API. Le corps d'une **réponse** est la donnée envoyée par votre API au client. -Votre API aura presque toujours à envoyer un corps de **réponse**. Mais un client n'a pas toujours à envoyer un **corps de requête** : parfois il demande seulement un chemin, peut-être avec quelques paramètres de requête, mais n'envoie pas de corps. +Votre API aura presque toujours à envoyer un corps de **réponse**. Mais un client n'a pas toujours à envoyer un **corps de la requête** : parfois il demande seulement un chemin, peut-être avec quelques paramètres de requête, mais n'envoie pas de corps. Pour déclarer un corps de **requête**, on utilise les modèles de [Pydantic](https://docs.pydantic.dev/) en profitant de tous leurs avantages et fonctionnalités. /// note | Remarque -Pour envoyer de la donnée, vous devez utiliser : `POST` (le plus populaire), `PUT`, `DELETE` ou `PATCH`. +Pour envoyer de la donnée, vous devez utiliser l'une de ces méthodes : `POST` (le plus populaire), `PUT`, `DELETE` ou `PATCH`. -Envoyer un corps dans une requête `GET` a un comportement non défini dans les spécifications, cela est néanmoins supporté par **FastAPI**, seulement pour des cas d'utilisation très complexes/extrêmes. +Envoyer un corps dans une requête `GET` a un comportement non défini dans les spécifications, cela est néanmoins supporté par FastAPI, seulement pour des cas d'utilisation très complexes/extrêmes. Ceci étant découragé, la documentation interactive générée par Swagger UI ne montrera pas de documentation pour le corps d'une requête `GET`, et les proxys intermédiaires risquent de ne pas le supporter. @@ -32,6 +32,7 @@ Utilisez les types Python standard pour tous les attributs : {* ../../docs_src/body/tutorial001_py310.py hl[5:9] *} + Tout comme pour la déclaration de paramètres de requête, quand un attribut de modèle a une valeur par défaut, il n'est pas nécessaire. Sinon, il est requis. Utilisez `None` pour le rendre simplement optionnel. Par exemple, le modèle ci-dessus déclare un JSON « `object` » (ou `dict` Python) tel que : @@ -73,7 +74,7 @@ En utilisant uniquement les déclarations de type Python, **FastAPI** réussit * Passer la donnée reçue dans le paramètre `item`. * Ce paramètre ayant été déclaré dans la fonction comme étant de type `Item`, vous aurez aussi tout le support offert par l'éditeur (autocomplétion, etc.) pour tous les attributs de ce paramètre et les types de ces attributs. * Générer des définitions [JSON Schema](https://json-schema.org) pour votre modèle ; vous pouvez également les utiliser partout ailleurs si cela a du sens pour votre projet. -* Ces schémas participeront à la constitution du schéma généré OpenAPI, et seront utilisés par les documentations automatiques UIs. +* Ces schémas feront partie du schéma OpenAPI généré, et seront utilisés par les UIs de la documentation automatique. ## Documentation automatique { #automatic-docs } @@ -97,11 +98,11 @@ Et vous obtenez aussi des vérifications d'erreurs pour les opérations de types Ce n'est pas un hasard, ce framework entier a été bâti avec ce design comme objectif. -Et cela a été rigoureusement testé durant la phase de design, avant toute implémentation, pour vous assurer que cela fonctionnerait avec tous les éditeurs. +Et cela a été rigoureusement testé durant la phase de design, avant toute implémentation, pour s'assurer que cela fonctionnerait avec tous les éditeurs. Des changements sur Pydantic ont même été faits pour supporter cela. -Les captures d'écran précédentes ont été prises sur [Visual Studio Code](https://code.visualstudio.com). +Les captures d'écran précédentes ont été prises avec [Visual Studio Code](https://code.visualstudio.com). Mais vous auriez le même support de l'éditeur avec [PyCharm](https://www.jetbrains.com/pycharm/) et la majorité des autres éditeurs de code Python : @@ -129,15 +130,16 @@ Dans la fonction, vous pouvez accéder à tous les attributs de l'objet du modè ## Corps de la requête + paramètres de chemin { #request-body-path-parameters } -Vous pouvez déclarer des paramètres de chemin et un corps de requête pour la même *chemin d'accès*. +Vous pouvez déclarer des paramètres de chemin et le corps de la requête en même temps. -**FastAPI** est capable de reconnaître que les paramètres de la fonction qui correspondent aux paramètres de chemin doivent être **récupérés depuis le chemin**, et que les paramètres de fonctions déclarés comme modèles Pydantic devraient être **récupérés depuis le corps de la requête**. +**FastAPI** est capable de reconnaître que les paramètres de la fonction qui correspondent aux paramètres de chemin doivent être **récupérés depuis le chemin**, et que les paramètres de la fonction déclarés comme modèles Pydantic devraient être **récupérés depuis le corps de la requête**. {* ../../docs_src/body/tutorial003_py310.py hl[15:16] *} + ## Corps de la requête + paramètres de chemin et de requête { #request-body-path-query-parameters } -Vous pouvez aussi déclarer un **corps**, et des paramètres de **chemin** et de **requête** dans la même *chemin d'accès*. +Vous pouvez aussi déclarer un **corps**, et des paramètres de **chemin** et de **requête**, tous en même temps. **FastAPI** saura reconnaître chacun d'entre eux et récupérer la bonne donnée au bon endroit. @@ -151,9 +153,9 @@ Les paramètres de la fonction seront reconnus comme tel : /// note | Remarque -**FastAPI** saura que la valeur de `q` n'est pas requise grâce à la valeur par défaut `= None`. +FastAPI saura que la valeur de `q` n'est pas requise grâce à la valeur par défaut `= None`. -L'annotation de type `str | None` n'est pas utilisée par **FastAPI** pour déterminer que la valeur n'est pas requise, il le saura parce qu'elle a une valeur par défaut `= None`. +L'annotation de type `str | None` n'est pas utilisée par FastAPI pour déterminer que la valeur n'est pas requise, il le saura parce qu'elle a une valeur par défaut `= None`. Mais ajouter ces annotations de type permettra à votre éditeur de vous offrir un meilleur support et de détecter des erreurs. diff --git a/docs/fr/docs/tutorial/debugging.md b/docs/fr/docs/tutorial/debugging.md index 1a3e9c509..cdcfe702e 100644 --- a/docs/fr/docs/tutorial/debugging.md +++ b/docs/fr/docs/tutorial/debugging.md @@ -74,7 +74,7 @@ ne sera pas exécutée. /// note | Remarque -Pour plus d'informations, consultez [la documentation officielle de Python](https://docs.python.org/3/library/__main__.html). +Pour plus d'informations, consultez [les documents officiels de Python](https://docs.python.org/3/library/__main__.html). /// @@ -86,10 +86,10 @@ Parce que vous exécutez le serveur Uvicorn directement depuis votre code, vous Par exemple, dans Visual Studio Code, vous pouvez : -- Allez dans le panneau « Debug ». -- « Add configuration ... ». -- Sélectionnez « Python ». -- Lancez le débogueur avec l'option « Python: Current File (Integrated Terminal) ». +* Allez dans le panneau « Debug ». +* « Add configuration... ». +* Sélectionnez « Python ». +* Lancez le débogueur avec l'option « `Python: Current File (Integrated Terminal)` ». Il démarrera alors le serveur avec votre code **FastAPI**, s'arrêtera à vos points d'arrêt, etc. @@ -99,12 +99,12 @@ Voici à quoi cela pourrait ressembler : --- -Si vous utilisez Pycharm, vous pouvez : +Si vous utilisez PyCharm, vous pouvez : -- Ouvrez le menu « Run ». -- Sélectionnez l'option « Debug ... ». -- Un menu contextuel s'affiche alors. -- Sélectionnez le fichier à déboguer (dans ce cas, `main.py`). +* Ouvrez le menu « Run ». +* Sélectionnez l'option « Debug... ». +* Un menu contextuel s'affiche alors. +* Sélectionnez le fichier à déboguer (dans ce cas, `main.py`). Il démarrera alors le serveur avec votre code **FastAPI**, s'arrêtera à vos points d'arrêt, etc. diff --git a/docs/fr/docs/tutorial/dependencies/dependencies-with-yield.md b/docs/fr/docs/tutorial/dependencies/dependencies-with-yield.md index 8da931d11..23114c0cb 100644 --- a/docs/fr/docs/tutorial/dependencies/dependencies-with-yield.md +++ b/docs/fr/docs/tutorial/dependencies/dependencies-with-yield.md @@ -1,6 +1,6 @@ # Utiliser des dépendances avec `yield` { #dependencies-with-yield } -FastAPI prend en charge des dépendances qui effectuent des étapes supplémentaires après l'exécution. +FastAPI prend en charge des dépendances qui effectuent des étapes supplémentaires après l'exécution. Pour cela, utilisez `yield` au lieu de `return`, et écrivez les étapes supplémentaires (code) après. @@ -194,16 +194,16 @@ Mais si vous savez que vous n'aurez pas besoin d'utiliser la dépendance après `Depends()` reçoit un paramètre `scope` qui peut être : -* « function » : démarrer la dépendance avant la *fonction de chemin d'accès* qui gère la requête, terminer la dépendance après la fin de la *fonction de chemin d'accès*, mais **avant** que la réponse ne soit renvoyée au client. Ainsi, la fonction de dépendance sera exécutée **autour** de la *fonction de chemin d'accès*. -* « request » : démarrer la dépendance avant la *fonction de chemin d'accès* qui gère la requête (similaire à l'utilisation de « function »), mais terminer **après** que la réponse a été renvoyée au client. Ainsi, la fonction de dépendance sera exécutée **autour** du cycle **requête** et réponse. +* `"function"` : démarrer la dépendance avant la *fonction de chemin d'accès* qui gère la requête, terminer la dépendance après la fin de la *fonction de chemin d'accès*, mais **avant** que la réponse ne soit renvoyée au client. Ainsi, la fonction de dépendance sera exécutée **autour** de la *fonction de chemin d'accès*. +* `"request"` : démarrer la dépendance avant la *fonction de chemin d'accès* qui gère la requête (similaire à l'utilisation de `"function"`), mais terminer **après** que la réponse a été renvoyée au client. Ainsi, la fonction de dépendance sera exécutée **autour** du cycle **requête** et réponse. -S'il n'est pas spécifié et que la dépendance utilise `yield`, le `scope` sera par défaut « request ». +S'il n'est pas spécifié et que la dépendance utilise `yield`, le `scope` sera par défaut `"request"`. ### Définir `scope` pour les sous-dépendances { #scope-for-sub-dependencies } -Lorsque vous déclarez une dépendance avec un `scope="request"` (par défaut), toute sous-dépendance doit également avoir un `scope` de « request ». +Lorsque vous déclarez une dépendance avec un `scope="request"` (par défaut), toute sous-dépendance doit également avoir un `scope` de `"request"`. -Mais une dépendance avec un `scope` de « function » peut avoir des dépendances avec un `scope` de « function » et un `scope` de « request ». +Mais une dépendance avec un `scope` de `"function"` peut avoir des dépendances avec un `scope` de `"function"` et un `scope` de `"request"`. Cela vient du fait que toute dépendance doit pouvoir exécuter son code de sortie avant ses sous-dépendances, car elle pourrait encore avoir besoin de les utiliser pendant son code de sortie. @@ -234,6 +234,7 @@ participant operation as Path Operation Les dépendances avec `yield` ont évolué au fil du temps pour couvrir différents cas d'utilisation et corriger certains problèmes. Si vous souhaitez voir ce qui a changé dans différentes versions de FastAPI, vous pouvez en savoir plus dans le guide avancé, dans [Dépendances avancées - Dépendances avec `yield`, `HTTPException`, `except` et Background Tasks](../../advanced/advanced-dependencies.md#dependencies-with-yield-httpexception-except-and-background-tasks). + ## Gestionnaires de contexte { #context-managers } ### Que sont les « Context Managers » { #what-are-context-managers } diff --git a/docs/fr/docs/tutorial/extra-data-types.md b/docs/fr/docs/tutorial/extra-data-types.md index 7ee6816c8..c0c4df137 100644 --- a/docs/fr/docs/tutorial/extra-data-types.md +++ b/docs/fr/docs/tutorial/extra-data-types.md @@ -36,7 +36,7 @@ Voici quelques types de données supplémentaires que vous pouvez utiliser : * `datetime.timedelta` : * Un `datetime.timedelta` Python. * Dans les requêtes et les réponses, il sera représenté sous forme de `float` de secondes totales. - * Pydantic permet aussi de le représenter sous la forme d'un « encodage de différence de temps ISO 8601 », [voir la documentation pour plus d'informations](https://docs.pydantic.dev/latest/concepts/serialization/#custom-serializers). + * Pydantic permet aussi de le représenter sous la forme d'un « encodage de différence de temps ISO 8601 », [voir les documents pour plus d'informations](https://docs.pydantic.dev/latest/concepts/serialization/#custom-serializers). * `frozenset` : * Dans les requêtes et les réponses, traité de la même manière qu'un `set` : * Dans les requêtes, une liste sera lue, les doublons éliminés, puis convertie en `set`. diff --git a/docs/fr/docs/tutorial/extra-models.md b/docs/fr/docs/tutorial/extra-models.md index 24a3fa31b..7d542955b 100644 --- a/docs/fr/docs/tutorial/extra-models.md +++ b/docs/fr/docs/tutorial/extra-models.md @@ -4,9 +4,9 @@ En poursuivant l'exemple précédent, il est courant d'avoir plusieurs modèles C'est particulièrement vrai pour les modèles d'utilisateur, car : -* Le modèle d'entrée doit pouvoir contenir un mot de passe. -* Le modèle de sortie ne doit pas avoir de mot de passe. -* Le modèle de base de données devra probablement avoir un mot de passe haché. +* Le **modèle d'entrée** doit pouvoir contenir un mot de passe. +* Le **modèle de sortie** ne doit pas avoir de mot de passe. +* Le **modèle de base de données** aurait probablement besoin d'avoir un mot de passe haché. /// danger | Danger @@ -30,13 +30,13 @@ Voici une idée générale de l'apparence des modèles avec leurs champs de mot Les modèles Pydantic ont une méthode `.model_dump()` qui renvoie un `dict` avec les données du modèle. -Ainsi, si nous créons un objet Pydantic `user_in` comme : +Ainsi, si nous créons un objet Pydantic `user_in` comme : ```Python user_in = UserIn(username="john", password="secret", email="john.doe@example.com") ``` -et que nous appelons ensuite : +et que nous appelons ensuite : ```Python user_dict = user_in.model_dump() @@ -44,13 +44,13 @@ user_dict = user_in.model_dump() nous avons maintenant un `dict` avec les données dans la variable `user_dict` (c'est un `dict` au lieu d'un objet modèle Pydantic). -Et si nous appelons : +Et si nous appelons : ```Python print(user_dict) ``` -nous obtiendrions un `dict` Python contenant : +nous obtiendrions un `dict` Python contenant : ```Python { @@ -63,15 +63,15 @@ nous obtiendrions un `dict` Python contenant : #### Déballer un `dict` { #unpacking-a-dict } -Si nous prenons un `dict` comme `user_dict` et que nous le passons à une fonction (ou une classe) avec `**user_dict`, Python va « déballer » ce `dict`. Il passera les clés et valeurs de `user_dict` directement comme arguments nommés. +Si nous prenons un `dict` comme `user_dict` et que nous le passons à une fonction (ou une classe) avec `**user_dict`, Python va « déballer » ce `dict`. Il passera les clés et valeurs de `user_dict` directement comme arguments clé-valeur. -Ainsi, en reprenant `user_dict` ci-dessus, écrire : +Ainsi, en reprenant `user_dict` ci-dessus, écrire : ```Python UserInDB(**user_dict) ``` -aurait pour résultat quelque chose d'équivalent à : +aurait pour résultat quelque chose d'équivalent à : ```Python UserInDB( @@ -82,7 +82,7 @@ UserInDB( ) ``` -Ou plus exactement, en utilisant `user_dict` directement, quels que soient ses contenus futurs : +Ou plus exactement, en utilisant `user_dict` directement, quels que soient ses contenus futurs : ```Python UserInDB( @@ -95,14 +95,14 @@ UserInDB( #### Créer un modèle Pydantic à partir du contenu d'un autre { #a-pydantic-model-from-the-contents-of-another } -Comme dans l'exemple ci-dessus nous avons obtenu `user_dict` depuis `user_in.model_dump()`, ce code : +Comme dans l'exemple ci-dessus nous avons obtenu `user_dict` depuis `user_in.model_dump()`, ce code : ```Python user_dict = user_in.model_dump() UserInDB(**user_dict) ``` -serait équivalent à : +serait équivalent à : ```Python UserInDB(**user_in.model_dump()) @@ -114,13 +114,13 @@ Ainsi, nous obtenons un modèle Pydantic à partir des données d'un autre modè #### Déballer un `dict` et ajouter des mots-clés supplémentaires { #unpacking-a-dict-and-extra-keywords } -Et en ajoutant ensuite l'argument nommé supplémentaire `hashed_password=hashed_password`, comme ici : +Et en ajoutant ensuite l'argument nommé supplémentaire `hashed_password=hashed_password`, comme ici : ```Python UserInDB(**user_in.model_dump(), hashed_password=hashed_password) ``` -... revient à : +... revient à : ```Python UserInDB( @@ -152,7 +152,7 @@ Nous pouvons déclarer un modèle `UserBase` qui sert de base à nos autres mod Toutes les conversions de données, validations, documentation, etc., fonctionneront comme d'habitude. -De cette façon, nous pouvons ne déclarer que les différences entre les modèles (avec `password` en clair, avec `hashed_password` et sans mot de passe) : +De cette façon, nous pouvons ne déclarer que les différences entre les modèles (avec `password` en clair, avec `hashed_password` et sans mot de passe) : {* ../../docs_src/extra_models/tutorial002_py310.py hl[7,13:14,17:18,21:22] *} @@ -162,7 +162,7 @@ Vous pouvez déclarer qu'une réponse est l'`Union` de deux types ou plus, ce qu Cela sera défini dans OpenAPI avec `anyOf`. -Pour ce faire, utilisez l'annotation de type Python standard [`typing.Union`](https://docs.python.org/3/library/typing.html#typing.Union) : +Pour ce faire, utilisez l'annotation de type Python standard [`typing.Union`](https://docs.python.org/3/library/typing.html#typing.Union) : /// note | Remarque @@ -176,21 +176,21 @@ Lors de la définition d'une [`Union`](https://docs.pydantic.dev/latest/concepts Dans cet exemple, nous passons `Union[PlaneItem, CarItem]` comme valeur de l'argument `response_model`. -Comme nous le passons comme valeur d'un argument au lieu de l'utiliser dans une annotation de type, nous devons utiliser `Union` même en Python 3.10. +Comme nous le passons comme **valeur à un argument** au lieu de l'utiliser dans une **annotation de type**, nous devons utiliser `Union` même en Python 3.10. -S'il s'agissait d'une annotation de type, nous pourrions utiliser la barre verticale, comme : +S'il s'agissait d'une annotation de type, nous pourrions utiliser la barre verticale, comme : ```Python some_variable: PlaneItem | CarItem ``` -Mais si nous écrivons cela dans l'affectation `response_model=PlaneItem | CarItem`, nous obtiendrons une erreur, car Python essaierait d'effectuer une « opération invalide » entre `PlaneItem` et `CarItem` au lieu de l'interpréter comme une annotation de type. +Mais si nous écrivons cela dans l'affectation `response_model=PlaneItem | CarItem`, nous obtiendrons une erreur, car Python essaierait d'effectuer une **opération invalide** entre `PlaneItem` et `CarItem` au lieu de l'interpréter comme une annotation de type. ## Liste de modèles { #list-of-models } De la même manière, vous pouvez déclarer des réponses contenant des listes d'objets. -Pour cela, utilisez le `list` Python standard : +Pour cela, utilisez le `list` Python standard : {* ../../docs_src/extra_models/tutorial004_py310.py hl[18] *} @@ -200,7 +200,7 @@ Vous pouvez également déclarer une réponse en utilisant un simple `dict` arbi C'est utile si vous ne connaissez pas à l'avance les noms de champs/attributs valides (qui seraient nécessaires pour un modèle Pydantic). -Dans ce cas, vous pouvez utiliser `dict` : +Dans ce cas, vous pouvez utiliser `dict` : {* ../../docs_src/extra_models/tutorial005_py310.py hl[6] *} @@ -208,4 +208,4 @@ Dans ce cas, vous pouvez utiliser `dict` : Utilisez plusieurs modèles Pydantic et héritez librement selon chaque cas. -Vous n'avez pas besoin d'avoir un seul modèle de données par entité si cette entité doit pouvoir avoir différents « états ». Comme pour l'« entité » utilisateur, avec un état incluant `password`, `password_hash` et sans mot de passe. +Vous n'avez pas besoin d'avoir un seul modèle de données par entité si cette entité doit pouvoir avoir différents « états ». L'« entité » **utilisateur** est un exemple, avec des états qui incluent `password`, `password_hash`, ou aucun mot de passe. diff --git a/docs/fr/docs/tutorial/first-steps.md b/docs/fr/docs/tutorial/first-steps.md index 3d88fe5a9..9e31e2b55 100644 --- a/docs/fr/docs/tutorial/first-steps.md +++ b/docs/fr/docs/tutorial/first-steps.md @@ -145,20 +145,20 @@ Vous pourriez également l’utiliser pour générer du code automatiquement, po ### Configurer le `entrypoint` de l’application dans `pyproject.toml` { #configure-the-app-entrypoint-in-pyproject-toml } -Vous pouvez configurer l’emplacement de votre application dans un fichier `pyproject.toml` comme : +Vous pouvez configurer l’emplacement de votre application dans un fichier `pyproject.toml` comme : ```toml [tool.fastapi] entrypoint = "main:app" ``` -Ce `entrypoint` indiquera à la commande `fastapi` qu’elle doit importer l’application comme : +Ce `entrypoint` indiquera à la commande `fastapi` qu’elle doit importer l’application comme : ```python from main import app ``` -Si votre code est structuré comme : +Si votre code est structuré comme : ``` . @@ -167,14 +167,14 @@ Si votre code est structuré comme : │   ├── __init__.py ``` -Alors vous définiriez le `entrypoint` comme : +Alors vous définiriez le `entrypoint` comme : ```toml [tool.fastapi] entrypoint = "backend.main:app" ``` -ce qui équivaudrait à : +ce qui équivaudrait à : ```python from backend.main import app @@ -182,19 +182,19 @@ from backend.main import app ### `fastapi dev` avec un chemin ou avec l’option CLI `--entrypoint` { #fastapi-dev-with-path-or-with-entrypoint-cli-option } -Vous pouvez également passer le chemin du fichier à la commande `fastapi dev`, et elle devinera l’objet d’application FastAPI à utiliser : +Vous pouvez également passer le chemin du fichier à la commande `fastapi dev`, et elle devinera l’objet d’application FastAPI à utiliser : ```console $ fastapi dev main.py ``` -Ou bien, vous pouvez aussi passer l’option `--entrypoint` à la commande `fastapi dev` : +Ou bien, vous pouvez aussi passer l’option `--entrypoint` à la commande `fastapi dev` : ```console $ fastapi dev --entrypoint main:app ``` -Mais vous devrez vous souvenir de passer le chemin\entrypoint correct à chaque exécution de la commande `fastapi`. +Mais vous devez vous souvenir de passer le chemin\entrypoint correct à chaque exécution de la commande `fastapi`. De plus, d’autres outils pourraient ne pas être capables de le trouver, par exemple l’[Extension VS Code](../editor-support.md) ou [FastAPI Cloud](https://fastapicloud.com), il est donc recommandé d’utiliser le `entrypoint` dans `pyproject.toml`. @@ -244,7 +244,7 @@ Ici, la variable `app` sera une « instance » de la classe `FastAPI`. Ce sera le point principal d’interaction pour créer toute votre API. -### Étape 3 : créer un « chemin d’accès » { #step-3-create-a-path-operation } +### Étape 3 : créer un *chemin d’accès* { #step-3-create-a-path-operation } #### Chemin { #path } @@ -305,11 +305,11 @@ Donc, dans OpenAPI, chacune des méthodes HTTP est appelée une « opération » Nous allons donc aussi les appeler « opérations ». -#### Définir un « décorateur de chemin d’accès » { #define-a-path-operation-decorator } +#### Définir un *décorateur de chemin d’accès* { #define-a-path-operation-decorator } {* ../../docs_src/first_steps/tutorial001_py310.py hl[6] *} -Le `@app.get("/")` indique à **FastAPI** que la fonction juste en dessous est chargée de gérer les requêtes qui vont vers : +Le `@app.get("/")` indique à **FastAPI** que la fonction juste en dessous est chargée de gérer les requêtes qui vont vers : * le chemin `/` * en utilisant une get opération @@ -318,13 +318,13 @@ Le `@app.get("/")` indique à **FastAPI** que la fonction juste en dessous est c Cette syntaxe `@something` en Python est appelée un « décorateur ». -Vous la mettez au-dessus d’une fonction. Comme un joli chapeau décoratif (j’imagine que c’est de là que vient le terme 🤷🏻‍♂). +Vous la mettez au-dessus d’une fonction. Comme un joli chapeau décoratif (j’imagine que c’est de là que vient le terme). Un « décorateur » prend la fonction en dessous et fait quelque chose avec. Dans notre cas, ce décorateur indique à **FastAPI** que la fonction en dessous correspond au **chemin** `/` avec une **opération** `get`. -C’est le « décorateur de chemin d’accès ». +C’est le **« décorateur de chemin d’accès »**. /// @@ -355,7 +355,7 @@ Par exemple, lorsque vous utilisez GraphQL, vous effectuez normalement toutes le ### Étape 4 : définir la **fonction de chemin d’accès** { #step-4-define-the-path-operation-function } -Voici notre « fonction de chemin d’accès » : +Voici notre **« fonction de chemin d’accès »** : * **chemin** : `/`. * **opération** : `get`. @@ -365,7 +365,7 @@ Voici notre « fonction de chemin d’accès » : C’est une fonction Python. -Elle sera appelée par **FastAPI** chaque fois qu’il recevra une requête vers l’URL « / » en utilisant une opération `GET`. +Elle sera appelée par **FastAPI** chaque fois qu’il recevra une requête vers l’URL « `/` » en utilisant une opération `GET`. Dans ce cas, c’est une fonction `async`. @@ -377,7 +377,7 @@ Vous pouvez aussi la définir comme une fonction normale au lieu de `async def` /// note | Remarque -Si vous ne connaissez pas la différence, consultez [Asynchrone : « Pressé ? »](../async.md#in-a-hurry). +Si vous ne connaissez pas la différence, consultez [Asynchrone : *« Pressé ? »*](../async.md#in-a-hurry). /// diff --git a/docs/fr/docs/tutorial/handling-errors.md b/docs/fr/docs/tutorial/handling-errors.md index a697571f3..5c52e7be1 100644 --- a/docs/fr/docs/tutorial/handling-errors.md +++ b/docs/fr/docs/tutorial/handling-errors.md @@ -43,7 +43,7 @@ Dans cet exemple, lorsque le client demande un élément par un ID qui n'existe ### Réponse résultante { #the-resulting-response } -Si le client demande `http://example.com/items/foo` (un `item_id` « foo »), il recevra un code d'état HTTP 200 et une réponse JSON : +Si le client demande `http://example.com/items/foo` (un `item_id` `"foo"`), il recevra un code d'état HTTP 200 et une réponse JSON : ```JSON { @@ -51,7 +51,7 @@ Si le client demande `http://example.com/items/foo` (un `item_id` « foo »), il } ``` -Mais si le client demande `http://example.com/items/bar` (un `item_id` inexistant « bar »), il recevra un code d'état HTTP 404 (l'erreur « not found ») et une réponse JSON : +Mais si le client demande `http://example.com/items/bar` (un `item_id` inexistant `"bar"`), il recevra un code d'état HTTP 404 (l'erreur « not found ») et une réponse JSON : ```JSON { diff --git a/docs/fr/docs/tutorial/index.md b/docs/fr/docs/tutorial/index.md index 2fc177ed9..1e28cfc6d 100644 --- a/docs/fr/docs/tutorial/index.md +++ b/docs/fr/docs/tutorial/index.md @@ -1,5 +1,6 @@ # Tutoriel - Guide utilisateur { #tutorial-user-guide } + Ce tutoriel vous montre comment utiliser **FastAPI** avec la plupart de ses fonctionnalités, étape par étape. Chaque section s'appuie progressivement sur les précédentes, mais elle est structurée de manière à séparer les sujets, afin que vous puissiez aller directement à l'un d'entre eux pour répondre à vos besoins spécifiques d'API. diff --git a/docs/fr/docs/tutorial/metadata.md b/docs/fr/docs/tutorial/metadata.md index 75a8542f8..1f1859eed 100644 --- a/docs/fr/docs/tutorial/metadata.md +++ b/docs/fr/docs/tutorial/metadata.md @@ -11,7 +11,7 @@ Vous pouvez définir les champs suivants qui sont utilisés dans la spécificati | `title` | `str` | Le titre de l’API. | | `summary` | `str` | Un court résumé de l’API. Disponible depuis OpenAPI 3.1.0, FastAPI 0.99.0. | | `description` | `str` | Une brève description de l’API. Elle peut utiliser Markdown. | -| `version` | `string` | La version de l’API. C’est la version de votre propre application, pas d’OpenAPI. Par exemple `2.5.0`. | +| `version` | `str` | La version de l’API. C’est la version de votre propre application, pas d’OpenAPI. Par exemple `2.5.0`. | | `terms_of_service` | `str` | Une URL vers les Conditions d’utilisation de l’API. Le cas échéant, il doit s’agir d’une URL. | | `contact` | `dict` | Les informations de contact pour l’API exposée. Cela peut contenir plusieurs champs.
champs de contact
ParamètreTypeDescription
namestrLe nom identifiant de la personne/organisation de contact.
urlstrL’URL pointant vers les informations de contact. DOIT être au format d’une URL.
emailstrL’adresse e-mail de la personne/organisation de contact. DOIT être au format d’une adresse e-mail.
| | `license_info` | `dict` | Les informations de licence pour l’API exposée. Cela peut contenir plusieurs champs.
champs de license_info
ParamètreTypeDescription
namestrOBLIGATOIRE (si un license_info est défini). Le nom de la licence utilisée pour l’API.
identifierstrUne expression de licence [SPDX](https://spdx.org/licenses/) pour l’API. Le champ identifier est mutuellement exclusif du champ url. Disponible depuis OpenAPI 3.1.0, FastAPI 0.99.0.
urlstrUne URL vers la licence utilisée pour l’API. DOIT être au format d’une URL.
| diff --git a/docs/fr/docs/tutorial/path-operation-configuration.md b/docs/fr/docs/tutorial/path-operation-configuration.md index 572d38e01..bd9aed879 100644 --- a/docs/fr/docs/tutorial/path-operation-configuration.md +++ b/docs/fr/docs/tutorial/path-operation-configuration.md @@ -1,5 +1,6 @@ # Configurer les chemins d'accès { #path-operation-configuration } + Vous pouvez passer plusieurs paramètres à votre *décorateur de chemin d'accès* pour le configurer. /// warning | Alertes diff --git a/docs/fr/docs/tutorial/query-params-str-validations.md b/docs/fr/docs/tutorial/query-params-str-validations.md index fc979334e..1b0fa88b3 100644 --- a/docs/fr/docs/tutorial/query-params-str-validations.md +++ b/docs/fr/docs/tutorial/query-params-str-validations.md @@ -81,7 +81,7 @@ FastAPI va maintenant : - **Valider** les données en s’assurant que la longueur maximale est de 50 caractères - Afficher une **erreur claire** au client quand les données ne sont pas valides -- **Documenter** le paramètre dans la *chemin d'accès* du schéma OpenAPI (il apparaîtra donc dans l’**interface de documentation automatique**) +- **Documenter** le paramètre dans le *chemin d'accès* du schéma OpenAPI (il apparaîtra donc dans l’**interface de documentation automatique**) ## Alternative (ancienne) : `Query` comme valeur par défaut { #alternative-old-query-as-the-default-value } @@ -89,7 +89,7 @@ Les versions précédentes de FastAPI (avant 0.95.0MDN web docs pour `POST`](https://developer.mozilla.org/en-US/docs/Web/HTTP/Methods/POST). +Si vous voulez en savoir plus sur ces encodages et les champs de formulaire, consultez les [documents web de la MDN pour `POST`](https://developer.mozilla.org/en-US/docs/Web/HTTP/Methods/POST). /// diff --git a/docs/fr/docs/tutorial/response-status-code.md b/docs/fr/docs/tutorial/response-status-code.md index e4a666ebf..398d1f1a1 100644 --- a/docs/fr/docs/tutorial/response-status-code.md +++ b/docs/fr/docs/tutorial/response-status-code.md @@ -1,5 +1,6 @@ # Code d'état de la réponse { #response-status-code } + De la même manière que vous pouvez spécifier un modèle de réponse, vous pouvez également déclarer le code d'état HTTP utilisé pour la réponse avec le paramètre `status_code` dans n'importe lequel des chemins d'accès : * `@app.get()` diff --git a/docs/fr/docs/tutorial/schema-extra-example.md b/docs/fr/docs/tutorial/schema-extra-example.md index 6f254aafe..85905f5f5 100644 --- a/docs/fr/docs/tutorial/schema-extra-example.md +++ b/docs/fr/docs/tutorial/schema-extra-example.md @@ -1,6 +1,6 @@ # Déclarer des exemples de données de requête { #declare-request-example-data } -Vous pouvez déclarer des exemples des données que votre application peut recevoir. +Vous pouvez déclarer des exemples de données que votre application peut recevoir. Voici plusieurs façons de le faire. @@ -10,9 +10,9 @@ Vous pouvez déclarer `examples` pour un modèle Pydantic qui seront ajoutés au {* ../../docs_src/schema_extra_example/tutorial001_py310.py hl[13:24] *} -Ces informations supplémentaires seront ajoutées telles quelles au **JSON Schema** de sortie pour ce modèle, et elles seront utilisées dans la documentation de l'API. +Ces informations supplémentaires seront ajoutées telles quelles au **JSON Schema** de sortie pour ce modèle, et elles seront utilisées dans les documents de l'API. -Vous pouvez utiliser l'attribut `model_config` qui accepte un `dict` comme décrit dans [Documentation de Pydantic : Configuration](https://docs.pydantic.dev/latest/api/config/). +Vous pouvez utiliser l'attribut `model_config` qui accepte un `dict` comme décrit dans [documents de Pydantic : Configuration](https://docs.pydantic.dev/latest/api/config/). Vous pouvez définir `"json_schema_extra"` avec un `dict` contenant toutes les données supplémentaires que vous souhaitez voir apparaître dans le JSON Schema généré, y compris `examples`. @@ -28,7 +28,7 @@ Par exemple, vous pourriez l'utiliser pour ajouter des métadonnées pour une in OpenAPI 3.1.0 (utilisé depuis FastAPI 0.99.0) a ajouté la prise en charge de `examples`, qui fait partie du standard **JSON Schema**. -Avant cela, seule la clé `example` avec un exemple unique était prise en charge. Elle l'est toujours par OpenAPI 3.1.0, mais elle est dépréciée et ne fait pas partie du standard JSON Schema. Vous êtes donc encouragé à migrer de `example` vers `examples`. 🤓 +Avant cela, seul le mot-clé `example` avec un exemple unique était pris en charge. Il l'est toujours par OpenAPI 3.1.0, mais il est déprécié et ne fait pas partie du standard JSON Schema. Vous êtes donc encouragé à migrer de `example` vers `examples`. 🤓 Vous pouvez en lire davantage à la fin de cette page. @@ -173,7 +173,7 @@ Ce nouveau champ `examples` dans JSON Schema est **juste une `list`** d'exemples /// note | Remarque -Même après la sortie d'OpenAPI 3.1.0 avec cette nouvelle intégration plus simple avec JSON Schema, pendant un temps, Swagger UI, l'outil qui fournit la documentation automatique, ne prenait pas en charge OpenAPI 3.1.0 (il le fait depuis la version 5.0.0 🎉). +Même après la sortie d'OpenAPI 3.1.0 avec cette nouvelle intégration plus simple avec JSON Schema, pendant un temps, Swagger UI, l'outil qui fournit les documents automatiques, ne prenait pas en charge OpenAPI 3.1.0 (il le fait depuis la version 5.0.0 🎉). À cause de cela, les versions de FastAPI antérieures à 0.99.0 utilisaient encore des versions d'OpenAPI inférieures à 3.1.0. @@ -183,7 +183,7 @@ Même après la sortie d'OpenAPI 3.1.0 avec cette nouvelle intégration plus sim Lorsque vous ajoutez `examples` dans un modèle Pydantic, en utilisant `schema_extra` ou `Field(examples=["something"])`, cet exemple est ajouté au **JSON Schema** de ce modèle Pydantic. -Et ce **JSON Schema** du modèle Pydantic est inclus dans l'**OpenAPI** de votre API, puis il est utilisé dans l'interface de la documentation. +Et ce **JSON Schema** du modèle Pydantic est inclus dans l'**OpenAPI** de votre API, puis il est utilisé dans l'interface des documents. Dans les versions de FastAPI antérieures à 0.99.0 (0.99.0 et supérieures utilisent le nouveau OpenAPI 3.1.0), lorsque vous utilisiez `example` ou `examples` avec l'une des autres utilitaires (`Query()`, `Body()`, etc.), ces exemples n'étaient pas ajoutés au JSON Schema qui décrit ces données (pas même à la version de JSON Schema propre à OpenAPI), ils étaient ajoutés directement à la déclaration du *chemin d'accès* dans OpenAPI (en dehors des parties d'OpenAPI qui utilisent JSON Schema). @@ -191,7 +191,7 @@ Mais maintenant que FastAPI 0.99.0 et supérieures utilisent OpenAPI 3.1.0, qui ### Swagger UI et `examples` spécifiques à OpenAPI { #swagger-ui-and-openapi-specific-examples } -Comme Swagger UI ne prenait pas en charge plusieurs exemples JSON Schema (au 2023-08-26), les utilisateurs n'avaient pas de moyen d'afficher plusieurs exemples dans les documents. +Maintenant, comme Swagger UI ne prenait pas en charge plusieurs exemples JSON Schema (au 2023-08-26), les utilisateurs n'avaient pas de moyen d'afficher plusieurs exemples dans les documents. Pour résoudre cela, FastAPI `0.103.0` a **ajouté la prise en charge** de la déclaration du même ancien champ `examples` **spécifique à OpenAPI** avec le nouveau paramètre `openapi_examples`. 🤓 diff --git a/docs/fr/docs/tutorial/security/first-steps.md b/docs/fr/docs/tutorial/security/first-steps.md index 73cf4f38c..66005d907 100644 --- a/docs/fr/docs/tutorial/security/first-steps.md +++ b/docs/fr/docs/tutorial/security/first-steps.md @@ -54,7 +54,7 @@ $ fastapi dev ## Vérifier { #check-it } -Allez à la documentation interactive à l'adresse : [http://127.0.0.1:8000/docs](http://127.0.0.1:8000/docs). +Allez aux documents interactifs à l'adresse : [http://127.0.0.1:8000/docs](http://127.0.0.1:8000/docs). Vous verrez quelque chose comme ceci : @@ -98,19 +98,19 @@ Mais dans ce cas, la même application **FastAPI** gérera l'API et l'authentifi Voyons cela selon ce point de vue simplifié : -- L'utilisateur saisit le `username` et le `password` dans le frontend, puis appuie sur Entrée. -- Le frontend (exécuté dans le navigateur de l'utilisateur) envoie ce `username` et ce `password` vers une URL spécifique de notre API (déclarée avec `tokenUrl="token"`). -- L'API vérifie ce `username` et ce `password`, et répond avec un « token » (nous n'avons encore rien implémenté de tout cela). - - Un « token » n'est qu'une chaîne contenant des informations que nous pouvons utiliser plus tard pour vérifier cet utilisateur. - - Normalement, un token est configuré pour expirer après un certain temps. - - Ainsi, l'utilisateur devra se reconnecter à un moment donné. - - Et si le token est volé, le risque est moindre. Ce n'est pas une clé permanente qui fonctionnerait indéfiniment (dans la plupart des cas). -- Le frontend stocke ce token temporairement quelque part. -- L'utilisateur clique dans le frontend pour aller vers une autre section de l'application web frontend. -- Le frontend doit récupérer d'autres données depuis l'API. - - Mais cela nécessite une authentification pour cet endpoint spécifique. - - Donc, pour s'authentifier auprès de notre API, il envoie un en-tête `Authorization` avec une valeur `Bearer ` suivie du token. - - Si le token contient `foobar`, le contenu de l'en-tête `Authorization` serait : `Bearer foobar`. +* L'utilisateur saisit le `username` et le `password` dans le frontend, puis appuie sur Entrée. +* Le frontend (exécuté dans le navigateur de l'utilisateur) envoie ce `username` et ce `password` vers une URL spécifique de notre API (déclarée avec `tokenUrl="token"`). +* L'API vérifie ce `username` et ce `password`, et répond avec un « token » (nous n'avons encore rien implémenté de tout cela). + * Un « token » n'est qu'une chaîne contenant des informations que nous pouvons utiliser plus tard pour vérifier cet utilisateur. + * Normalement, un token est configuré pour expirer après un certain temps. + * Ainsi, l'utilisateur devra se reconnecter à un moment donné. + * Et si le token est volé, le risque est moindre. Ce n'est pas une clé permanente qui fonctionnerait indéfiniment (dans la plupart des cas). +* Le frontend stocke ce token temporairement quelque part. +* L'utilisateur clique dans le frontend pour aller vers une autre section de l'application web frontend. +* Le frontend doit récupérer d'autres données depuis l'API. + * Mais cela nécessite une authentification pour cet endpoint spécifique. + * Donc, pour s'authentifier auprès de notre API, il envoie un en-tête `Authorization` avec une valeur `Bearer ` suivie du token. + * Si le token contient `foobar`, le contenu de l'en-tête `Authorization` serait : `Bearer foobar`. ## Le `OAuth2PasswordBearer` de **FastAPI** { #fastapis-oauth2passwordbearer } @@ -172,15 +172,15 @@ Vous pouvez maintenant passer ce `oauth2_scheme` en dépendance avec `Depends`. {* ../../docs_src/security/tutorial001_an_py310.py hl[12] *} -Cette dépendance fournira une `str` qui est affectée au paramètre `token` de la fonction de *chemin d'accès*. +Cette dépendance fournira une `str` qui est affectée au paramètre `token` de la *fonction de chemin d'accès*. -**FastAPI** saura qu'il peut utiliser cette dépendance pour définir un « schéma de sécurité » dans le schéma OpenAPI (et la documentation API automatique). +**FastAPI** saura qu'il peut utiliser cette dépendance pour définir un « schéma de sécurité » dans le schéma OpenAPI (et les documents automatiques de l'API). /// note | Détails techniques **FastAPI** saura qu'il peut utiliser la classe `OAuth2PasswordBearer` (déclarée dans une dépendance) pour définir le schéma de sécurité dans OpenAPI parce qu'elle hérite de `fastapi.security.oauth2.OAuth2`, qui hérite à son tour de `fastapi.security.base.SecurityBase`. -Tous les utilitaires de sécurité qui s'intègrent à OpenAPI (et à la documentation API automatique) héritent de `SecurityBase`, c'est ainsi que **FastAPI** sait comment les intégrer dans OpenAPI. +Tous les utilitaires de sécurité qui s'intègrent à OpenAPI (et aux documents automatiques de l'API) héritent de `SecurityBase`, c'est ainsi que **FastAPI** sait comment les intégrer dans OpenAPI. /// @@ -192,7 +192,7 @@ S'il ne voit pas d'en-tête `Authorization`, ou si la valeur n'a pas de token `B Vous n'avez même pas à vérifier si le token existe pour renvoyer une erreur. Vous pouvez être sûr que si votre fonction est exécutée, elle aura une `str` dans ce token. -Vous pouvez déjà l'essayer dans la documentation interactive : +Vous pouvez déjà l'essayer dans les documents interactifs : diff --git a/docs/fr/docs/tutorial/security/get-current-user.md b/docs/fr/docs/tutorial/security/get-current-user.md index 97cffc666..664814bc3 100644 --- a/docs/fr/docs/tutorial/security/get-current-user.md +++ b/docs/fr/docs/tutorial/security/get-current-user.md @@ -14,7 +14,7 @@ Commençons par créer un modèle d'utilisateur Pydantic. De la même manière que nous utilisons Pydantic pour déclarer des corps de requête, nous pouvons l'utiliser ailleurs : -{* ../../docs_src/security/tutorial002_an_py310.py hl[5,12:6] *} +{* ../../docs_src/security/tutorial002_an_py310.py hl[5,12:16] *} ## Créer une dépendance `get_current_user` { #create-a-get-current-user-dependency } diff --git a/docs/fr/docs/tutorial/security/oauth2-jwt.md b/docs/fr/docs/tutorial/security/oauth2-jwt.md index 810f1eef1..f92fd75a6 100644 --- a/docs/fr/docs/tutorial/security/oauth2-jwt.md +++ b/docs/fr/docs/tutorial/security/oauth2-jwt.md @@ -58,7 +58,7 @@ Chaque fois que vous fournissez exactement le même contenu (exactement le même Mais vous ne pouvez pas convertir le charabia en sens inverse vers le mot de passe. -### Pourquoi utiliser le hachage de mot passe { #why-use-password-hashing } +### Pourquoi utiliser le hachage de mot de passe { #why-use-password-hashing } Si votre base de données est volée, le voleur n'aura pas les mots de passe en clair de vos utilisateurs, seulement les hachages. @@ -120,7 +120,7 @@ Et une autre pour authentifier et renvoyer un utilisateur. Lorsque `authenticate_user` est appelée avec un nom d'utilisateur qui n'existe pas dans la base de données, nous exécutons tout de même `verify_password` contre un hachage factice. -Cela garantit que le point de terminaison met approximativement le même temps à répondre que le nom d'utilisateur soit valide ou non, empêchant des **attaques temporelles** qui pourraient être utilisées pour énumérer les noms d'utilisateur existants. +Cela garantit que l'endpoint met approximativement le même temps à répondre que le nom d'utilisateur soit valide ou non, empêchant des **attaques temporelles** qui pourraient être utilisées pour énumérer les noms d'utilisateur existants. /// note | Remarque @@ -152,7 +152,7 @@ Créez une variable `ALGORITHM` avec l'algorithme utilisé pour signer le jeton Créez une variable pour l'expiration du jeton. -Définissez un modèle Pydantic qui sera utilisé dans le point de terminaison du jeton pour la réponse. +Définissez un modèle Pydantic qui sera utilisé dans l'endpoint du jeton pour la réponse. Créez une fonction utilitaire pour générer un nouveau jeton d'accès. @@ -200,7 +200,7 @@ L'important à garder à l'esprit est que la clé `sub` doit contenir un identif ## Vérifier { #check-it } -Lancez le serveur et allez à la documentation : [http://127.0.0.1:8000/docs](http://127.0.0.1:8000/docs). +Lancez le serveur et accédez aux documents : [http://127.0.0.1:8000/docs](http://127.0.0.1:8000/docs). Vous verrez l'interface utilisateur suivante : @@ -215,13 +215,13 @@ Mot de passe : `secret` /// tip | Astuce -Remarquez qu'à aucun endroit du code le mot de passe en clair « secret » n'apparaît, nous n'avons que la version hachée. +Remarquez qu'à aucun endroit du code le mot de passe en clair « `secret` » n'apparaît, nous n'avons que la version hachée. /// -Appelez le point de terminaison `/users/me/`, vous obtiendrez la réponse suivante : +Appelez l'endpoint `/users/me/`, vous obtiendrez la réponse suivante : ```JSON { diff --git a/docs/fr/docs/tutorial/security/simple-oauth2.md b/docs/fr/docs/tutorial/security/simple-oauth2.md index b0f974f0d..1ee9e61ec 100644 --- a/docs/fr/docs/tutorial/security/simple-oauth2.md +++ b/docs/fr/docs/tutorial/security/simple-oauth2.md @@ -14,13 +14,13 @@ Mais ne vous inquiétez pas, vous pouvez l'afficher comme vous le souhaitez à v Et vos modèles de base de données peuvent utiliser les noms que vous voulez. -Mais pour le chemin d'accès de connexion, nous devons utiliser ces noms pour être compatibles avec la spécification (et pouvoir, par exemple, utiliser le système de documentation API intégré). +Mais pour le *chemin d'accès* de connexion, nous devons utiliser ces noms pour être compatibles avec la spécification (et pouvoir, par exemple, utiliser le système de documentation API intégré). La spécification précise également que `username` et `password` doivent être envoyés en données de formulaire (donc pas de JSON ici). ### `scope` { #scope } -La spécification indique aussi que le client peut envoyer un autre champ de formulaire « scope ». +La spécification indique aussi que le client peut envoyer un autre champ de formulaire « `scope` ». Le nom du champ de formulaire est `scope` (au singulier), mais il s'agit en fait d'une longue chaîne contenant des « scopes » séparés par des espaces. @@ -50,7 +50,7 @@ Utilisons maintenant les utilités fournies par **FastAPI** pour gérer cela. ### `OAuth2PasswordRequestForm` { #oauth2passwordrequestform } -Tout d'abord, importez `OAuth2PasswordRequestForm`, et utilisez-la en tant que dépendance avec `Depends` dans le chemin d'accès pour `/token` : +Tout d'abord, importez `OAuth2PasswordRequestForm`, et utilisez-la en tant que dépendance avec `Depends` dans le *chemin d'accès* pour `/token` : {* ../../docs_src/security/tutorial003_an_py310.py hl[4,78] *} @@ -63,7 +63,7 @@ Tout d'abord, importez `OAuth2PasswordRequestForm`, et utilisez-la en tant que d /// tip | Astuce -La spécification OAuth2 exige en réalité un champ `grant_type` avec la valeur fixe `password`, mais `OAuth2PasswordRequestForm` ne l'impose pas. +La spécification OAuth2 *exige* en réalité un champ `grant_type` avec la valeur fixe `password`, mais `OAuth2PasswordRequestForm` ne l'impose pas. Si vous avez besoin de l'imposer, utilisez `OAuth2PasswordRequestFormStrict` au lieu de `OAuth2PasswordRequestForm`. @@ -132,7 +132,7 @@ Ainsi, il ne pourra pas essayer d'utiliser ces mêmes mots de passe dans un autr `UserInDB(**user_dict)` signifie : -Passez les clés et valeurs de `user_dict` directement comme arguments clé‑valeur, équivalent à : +*Passez les clés et valeurs de `user_dict` directement comme arguments clé‑valeur, équivalent à :* ```Python UserInDB( @@ -146,7 +146,7 @@ UserInDB( /// note | Remarque -Pour une explication plus complète de `**user_dict`, consultez [la documentation pour **Modèles supplémentaires**](../extra-models.md#about-user-in-dict). +Pour une explication plus complète de `**user_dict`, consultez [la documentation pour **Modèles supplémentaires**](../extra-models.md#about-user-in-model-dump). /// @@ -154,7 +154,7 @@ Pour une explication plus complète de `**user_dict`, consultez [la documentatio La réponse de l'endpoint `token` doit être un objet JSON. -Il doit contenir un `token_type`. Dans notre cas, comme nous utilisons des jetons « Bearer », le type de jeton doit être « bearer ». +Il doit contenir un `token_type`. Dans notre cas, comme nous utilisons des jetons « Bearer », le type de jeton doit être « `bearer` ». Et il doit contenir un `access_token`, avec une chaîne contenant notre jeton d'accès. @@ -186,7 +186,7 @@ Pour le reste, **FastAPI** s'en charge pour vous. Nous allons maintenant mettre à jour nos dépendances. -Nous voulons obtenir `current_user` uniquement si cet utilisateur est actif. +Nous voulons obtenir `current_user` *uniquement* si cet utilisateur est actif. Nous créons donc une dépendance supplémentaire `get_current_active_user` qui utilise à son tour `get_current_user` comme dépendance. @@ -216,7 +216,7 @@ C'est l'avantage des standards ... ## Voir en action { #see-it-in-action } -Ouvrez la documentation interactive : [http://127.0.0.1:8000/docs](http://127.0.0.1:8000/docs). +Ouvrez les documents interactifs : [http://127.0.0.1:8000/docs](http://127.0.0.1:8000/docs). ### S'authentifier { #authenticate } diff --git a/docs/fr/docs/tutorial/sql-databases.md b/docs/fr/docs/tutorial/sql-databases.md index 70e5b1dba..2f6aad3a9 100644 --- a/docs/fr/docs/tutorial/sql-databases.md +++ b/docs/fr/docs/tutorial/sql-databases.md @@ -30,7 +30,7 @@ Il existe un générateur de projet officiel avec **FastAPI** et **PostgreSQL**, /// -Il s'agit d'un tutoriel très simple et court ; si vous souhaitez apprendre sur les bases de données en général, sur SQL, ou des fonctionnalités plus avancées, allez voir la [documentation SQLModel](https://sqlmodel.tiangolo.com/). +Il s'agit d'un tutoriel très simple et court ; si vous souhaitez apprendre sur les bases de données en général, sur SQL, ou des fonctionnalités plus avancées, allez voir les [documents de SQLModel](https://sqlmodel.tiangolo.com/). ## Installer `SQLModel` { #install-sqlmodel } @@ -57,15 +57,15 @@ Importez `SQLModel` et créez un modèle de base de données : {* ../../docs_src/sql_databases/tutorial001_an_py310.py ln[1:11] hl[7:11] *} -La classe `Hero` est très similaire à un modèle Pydantic (en fait, en dessous, c'est réellement un modèle Pydantic). +La classe `Hero` est très similaire à un modèle Pydantic (en fait, en dessous, c'est réellement *un modèle Pydantic*). Il y a quelques différences : * `table=True` indique à SQLModel qu'il s'agit d'un *modèle de table*, il doit représenter une **table** dans la base SQL, ce n'est pas seulement un *modèle de données* (comme le serait n'importe quelle autre classe Pydantic classique). -* `Field(primary_key=True)` indique à SQLModel que `id` est la **clé primaire** dans la base SQL (vous pouvez en savoir plus sur les clés primaires SQL dans la documentation SQLModel). +* `Field(primary_key=True)` indique à SQLModel que `id` est la **clé primaire** dans la base SQL (vous pouvez en savoir plus sur les clés primaires SQL dans les documents de SQLModel). - Remarque : nous utilisons `int | None` pour le champ clé primaire afin qu'en Python nous puissions *créer un objet sans `id`* (`id=None`), en supposant que la base *le génère à l'enregistrement*. SQLModel comprend que la base fournira l'`id` et *définit la colonne comme un `INTEGER` non nul* dans le schéma de base. Voir la [documentation SQLModel sur les clés primaires](https://sqlmodel.tiangolo.com/tutorial/create-db-and-table/#primary-key-id) pour plus de détails. + **Remarque :** nous utilisons `int | None` pour le champ clé primaire afin qu'en Python nous puissions *créer un objet sans `id`* (`id=None`), en supposant que la base *le génère à l'enregistrement*. SQLModel comprend que la base fournira l'`id` et *définit la colonne comme un `INTEGER` non nul* dans le schéma de base. Voir les [documents de SQLModel sur les clés primaires](https://sqlmodel.tiangolo.com/tutorial/create-db-and-table/#primary-key-id) pour plus de détails. * `Field(index=True)` indique à SQLModel qu'il doit créer un **index SQL** pour cette colonne, ce qui permettra des recherches plus rapides dans la base lors de la lecture de données filtrées par cette colonne. @@ -121,7 +121,7 @@ Comme chaque modèle SQLModel est aussi un modèle Pydantic, vous pouvez l'utili Par exemple, si vous déclarez un paramètre de type `Hero`, il sera lu depuis le **corps JSON**. -De la même manière, vous pouvez le déclarer comme **type de retour** de la fonction, et alors la forme des données apparaîtra dans l'UI automatique de documentation de l'API. +De la même manière, vous pouvez le déclarer comme **type de retour** de la fonction, et alors la forme des données apparaîtra dans l'UI automatique des documents de l'API. {* ../../docs_src/sql_databases/tutorial001_an_py310.py ln[40:45] hl[40:45] *} @@ -173,7 +173,7 @@ Si vous vérifiez l'application précédente, dans l'UI vous pouvez voir que, ju Nous ne devrions pas laisser cela se produire, ils pourraient écraser un `id` que nous avons déjà attribué dans la base. Décider de l'`id` doit être fait par le **backend** ou la **base**, **pas par le client**. -De plus, nous créons un `secret_name` pour le héros, mais jusqu'ici, nous le renvoyons partout, ce n'est pas très « secret » ... 😅 +De plus, nous créons un `secret_name` pour le héros, mais jusqu'ici, nous le renvoyons partout, ce n'est pas très **secret** ... 😅 Nous allons corriger ces choses en ajoutant quelques **modèles supplémentaires**. C'est là que SQLModel brille. ✨ @@ -354,4 +354,4 @@ Si vous allez sur l'UI `/docs` de l'API, vous verrez qu'elle est maintenant à j Vous pouvez utiliser [**SQLModel**](https://sqlmodel.tiangolo.com/) pour interagir avec une base SQL et simplifier le code avec des *modèles de données* et des *modèles de table*. -Vous pouvez en apprendre beaucoup plus dans la documentation **SQLModel**, il y a un mini [tutoriel plus long sur l'utilisation de SQLModel avec **FastAPI**](https://sqlmodel.tiangolo.com/tutorial/fastapi/). 🚀 +Vous pouvez en apprendre beaucoup plus dans les documents de **SQLModel**, il y a un mini [tutoriel plus long sur l'utilisation de SQLModel avec **FastAPI**](https://sqlmodel.tiangolo.com/tutorial/fastapi/). 🚀 diff --git a/docs/fr/docs/tutorial/static-files.md b/docs/fr/docs/tutorial/static-files.md index 6a54840af..cfbbe86b9 100644 --- a/docs/fr/docs/tutorial/static-files.md +++ b/docs/fr/docs/tutorial/static-files.md @@ -2,6 +2,14 @@ Vous pouvez servir des fichiers statiques automatiquement à partir d'un répertoire en utilisant `StaticFiles`. +/// tip | Astuce + +Si vous devez héberger un frontend, utilisez plutôt `app.frontend()`, lisez-en davantage dans [Frontend](frontend.md). + +`app.frontend()` utilise `StaticFiles` en interne, avec plusieurs avantages supplémentaires pour les frontends, comme la gestion du routing côté client. + +/// + ## Utiliser `StaticFiles` { #use-staticfiles } - Importer `StaticFiles`. diff --git a/docs/fr/docs/tutorial/testing.md b/docs/fr/docs/tutorial/testing.md index 517603425..883a61155 100644 --- a/docs/fr/docs/tutorial/testing.md +++ b/docs/fr/docs/tutorial/testing.md @@ -12,7 +12,7 @@ Avec cela, vous pouvez utiliser [pytest](https://docs.pytest.org/) directement a Pour utiliser `TestClient`, installez d’abord [`httpx`](https://www.python-httpx.org). -Vous devez créer un [environnement virtuel](../virtual-environments.md), l’activer, puis y installer le paquet, par exemple : +Vous devez vous assurer de créer un [environnement virtuel](../virtual-environments.md), de l’activer, puis d’y installer le paquet, par exemple : ```console $ pip install httpx @@ -156,7 +156,7 @@ Si vous avez un modèle Pydantic dans votre test et que vous souhaitez envoyer s Après cela, vous avez simplement besoin d’installer `pytest`. -Vous devez créer un [environnement virtuel](../virtual-environments.md), l’activer, puis y installer le paquet, par exemple : +Vous devez vous assurer de créer un [environnement virtuel](../virtual-environments.md), de l’activer, puis d’y installer le paquet, par exemple :
diff --git a/docs/fr/docs/virtual-environments.md b/docs/fr/docs/virtual-environments.md index c9eefb37b..f2a9f47da 100644 --- a/docs/fr/docs/virtual-environments.md +++ b/docs/fr/docs/virtual-environments.md @@ -1,6 +1,6 @@ # Environnements virtuels { #virtual-environments } -Lorsque vous travaillez sur des projets Python, vous devriez probablement utiliser un environnement virtuel (ou un mécanisme similaire) pour isoler les packages que vous installez pour chaque projet. +Lorsque vous travaillez sur des projets Python, vous devriez probablement utiliser un **environnement virtuel** (ou un mécanisme similaire) pour isoler les packages que vous installez pour chaque projet. /// note | Remarque @@ -10,19 +10,19 @@ Si vous connaissez déjà les environnements virtuels, comment les créer et les /// tip | Astuce -Un environnement virtuel est différent d’une variable d’environnement. +Un **environnement virtuel** est différent d’une **variable d’environnement**. -Une variable d’environnement est une variable du système qui peut être utilisée par des programmes. +Une **variable d’environnement** est une variable du système qui peut être utilisée par des programmes. -Un environnement virtuel est un répertoire contenant certains fichiers. +Un **environnement virtuel** est un répertoire contenant certains fichiers. /// /// note | Remarque -Cette page vous apprendra à utiliser les environnements virtuels et à comprendre leur fonctionnement. +Cette page vous apprendra à utiliser les **environnements virtuels** et à comprendre leur fonctionnement. -Si vous êtes prêt à adopter un outil qui gère tout pour vous (y compris l’installation de Python), essayez [uv](https://github.com/astral-sh/uv). +Si vous êtes prêt à adopter un **outil qui gère tout** pour vous (y compris l’installation de Python), essayez [uv](https://github.com/astral-sh/uv). /// @@ -53,11 +53,11 @@ $ cd awesome-project ## Créer un environnement virtuel { #create-a-virtual-environment } -Lorsque vous commencez à travailler sur un projet Python pour la première fois, créez un environnement virtuel dans votre projet. +Lorsque vous commencez à travailler sur un projet Python **pour la première fois**, créez un environnement virtuel **dans votre projet**. /// tip | Astuce -Vous n’avez besoin de faire cela qu’une seule fois par projet, pas à chaque fois que vous travaillez. +Vous n’avez besoin de faire cela qu’**une seule fois par projet**, pas à chaque fois que vous travaillez. /// @@ -120,7 +120,7 @@ Activez le nouvel environnement virtuel afin que toute commande Python que vous /// tip | Astuce -Faites cela à chaque fois que vous démarrez une nouvelle session de terminal pour travailler sur le projet. +Faites cela **chaque fois** que vous démarrez une **nouvelle session de terminal** pour travailler sur le projet. /// @@ -164,9 +164,9 @@ $ source .venv/Scripts/activate /// tip | Astuce -Chaque fois que vous installez un nouveau package dans cet environnement, activez de nouveau l’environnement. +Chaque fois que vous installez un **nouveau package** dans cet environnement, **activez** de nouveau l’environnement. -Vous vous assurez ainsi que si vous utilisez un programme de terminal (CLI) installé par ce package, vous utilisez celui de votre environnement virtuel et non un autre qui pourrait être installé globalement, probablement avec une version différente de celle dont vous avez besoin. +Vous vous assurez ainsi que si vous utilisez un **programme de terminal (CLI)** installé par ce package, vous utilisez celui de votre environnement virtuel et non un autre qui pourrait être installé globalement, probablement avec une version différente de celle dont vous avez besoin. /// @@ -176,7 +176,7 @@ Vérifiez que l’environnement virtuel est actif (la commande précédente a fo /// tip | Astuce -C’est facultatif, mais c’est une bonne manière de vérifier que tout fonctionne comme prévu et que vous utilisez l’environnement virtuel voulu. +C’est **facultatif**, mais c’est une bonne manière de **vérifier** que tout fonctionne comme prévu et que vous utilisez l’environnement virtuel voulu. /// @@ -220,13 +220,13 @@ Si vous utilisez [`uv`](https://github.com/astral-sh/uv), vous l’utiliserez po /// -Si vous utilisez `pip` pour installer des packages (il est fourni par défaut avec Python), vous devez le mettre à niveau vers la dernière version. +Si vous utilisez `pip` pour installer des packages (il est fourni par défaut avec Python), vous devez le **mettre à niveau** vers la dernière version. Beaucoup d’erreurs exotiques lors de l’installation d’un package se résolvent simplement en mettant d’abord `pip` à niveau. /// tip | Astuce -Vous feriez normalement cela une seule fois, juste après avoir créé l’environnement virtuel. +Vous feriez normalement cela **une seule fois**, juste après avoir créé l’environnement virtuel. /// @@ -264,7 +264,7 @@ Cette commande installera pip s’il n’est pas déjà installé et garantit au ## Ajouter `.gitignore` { #add-gitignore } -Si vous utilisez Git (vous devriez), ajoutez un fichier `.gitignore` pour exclure tout ce qui se trouve dans votre `.venv` de Git. +Si vous utilisez **Git** (vous devriez), ajoutez un fichier `.gitignore` pour exclure tout ce qui se trouve dans votre `.venv` de Git. /// tip | Astuce @@ -274,7 +274,7 @@ Si vous avez utilisé [`uv`](https://github.com/astral-sh/uv) pour créer l’en /// tip | Astuce -Faites cela une seule fois, juste après avoir créé l’environnement virtuel. +Faites cela **une seule fois**, juste après avoir créé l’environnement virtuel. /// @@ -308,19 +308,19 @@ Après avoir activé l’environnement, vous pouvez y installer des packages. /// tip | Astuce -Faites cela une seule fois lorsque vous installez ou mettez à niveau les packages nécessaires à votre projet. +Faites cela **une seule fois** lorsque vous installez ou mettez à niveau les packages nécessaires à votre projet. -Si vous devez mettre à niveau une version ou ajouter un nouveau package, vous le referez. +Si vous devez mettre à niveau une version ou ajouter un nouveau package, vous le **referez**. /// ### Installer des packages directement { #install-packages-directly } -Si vous êtes pressé et ne souhaitez pas utiliser un fichier pour déclarer les dépendances de votre projet, vous pouvez les installer directement. +Si vous êtes pressé et ne souhaitez pas utiliser un fichier pour déclarer les dépendances de packages de votre projet, vous pouvez les installer directement. /// tip | Astuce -C’est une très bonne idée de placer les packages et leurs versions nécessaires à votre programme dans un fichier (par exemple `requirements.txt` ou `pyproject.toml`). +C’est une (très) bonne idée de placer les packages et leurs versions nécessaires à votre programme dans un fichier (par exemple `requirements.txt` ou `pyproject.toml`). /// @@ -421,13 +421,13 @@ Par exemple : /// tip | Astuce -Vous devez normalement faire cela une seule fois, lorsque vous créez l’environnement virtuel. +Vous devez normalement faire cela seulement **une fois**, lorsque vous créez l’environnement virtuel. /// ## Désactiver l’environnement virtuel { #deactivate-the-virtual-environment } -Une fois que vous avez fini de travailler sur votre projet, vous pouvez désactiver l’environnement virtuel. +Une fois que vous avez fini de travailler sur votre projet, vous pouvez **désactiver** l’environnement virtuel.
@@ -457,17 +457,17 @@ Continuez la lecture. 👇🤓 Pour travailler avec FastAPI, vous devez installer [Python](https://www.python.org/). -Ensuite, vous devrez installer FastAPI et tout autre package que vous souhaitez utiliser. +Ensuite, vous devez **installer** FastAPI et tout autre **package** que vous souhaitez utiliser. Pour installer des packages, vous utiliseriez normalement la commande `pip` fournie avec Python (ou des alternatives similaires). -Néanmoins, si vous utilisez simplement `pip` directement, les packages seraient installés dans votre environnement Python global (l’installation globale de Python). +Néanmoins, si vous utilisez simplement `pip` directement, les packages seraient installés dans votre **environnement Python global** (l’installation globale de Python). ### Le problème { #the-problem } Alors, quel est le problème d’installer des packages dans l’environnement Python global ? -À un moment donné, vous finirez probablement par écrire de nombreux programmes différents qui dépendent de packages différents. Et certains de ces projets sur lesquels vous travaillez dépendront de versions différentes du même package. 😱 +À un moment donné, vous finirez probablement par écrire de nombreux programmes différents qui dépendent de **packages différents**. Et certains de ces projets sur lesquels vous travaillez dépendront de **versions différentes** du même package. 😱 Par exemple, vous pourriez créer un projet appelé `philosophers-stone`, ce programme dépend d’un autre package appelé **`harry`, en version `1`**. Vous devez donc installer `harry`. @@ -483,7 +483,7 @@ flowchart LR azkaban(prisoner-of-azkaban) --> |requires| harry-3[harry v3] ``` -Mais maintenant, le problème est que, si vous installez les packages globalement (dans l’environnement global) au lieu de dans un environnement virtuel local, vous devrez choisir quelle version de `harry` installer. +Mais maintenant, le problème est que, si vous installez les packages globalement (dans l’environnement global) au lieu de dans un **environnement virtuel** local, vous devrez choisir quelle version de `harry` installer. Si vous voulez exécuter `philosophers-stone`, vous devrez d’abord installer `harry` en version `1`, par exemple avec : @@ -519,7 +519,7 @@ $ pip install "harry==3" Et vous vous retrouverez alors avec `harry` version `3` installé dans votre environnement Python global. -Et si vous essayez d’exécuter à nouveau `philosophers-stone`, il y a une chance que cela ne fonctionne pas car il a besoin de `harry` version `1`. +Et si vous essayez d’exécuter à nouveau `philosophers-stone`, il y a une chance que cela **ne fonctionne pas** car il a besoin de `harry` version `1`. ```mermaid flowchart LR @@ -538,13 +538,13 @@ flowchart LR /// tip | Astuce -Il est très courant que les packages Python fassent de leur mieux pour éviter les changements cassants dans les nouvelles versions, mais il vaut mieux jouer la sécurité et installer de nouvelles versions intentionnellement et lorsque vous pouvez exécuter les tests pour vérifier que tout fonctionne correctement. +Il est très courant que les packages Python fassent de leur mieux pour **éviter les changements cassants** dans les **nouvelles versions**, mais il vaut mieux jouer la sécurité et installer de nouvelles versions intentionnellement et lorsque vous pouvez exécuter les tests pour vérifier que tout fonctionne correctement. /// -Maintenant, imaginez cela avec beaucoup d’autres packages dont tous vos projets dépendent. C’est très difficile à gérer. Et vous finiriez probablement par exécuter certains projets avec des versions incompatibles des packages, sans savoir pourquoi quelque chose ne fonctionne pas. +Maintenant, imaginez cela avec **beaucoup** d’autres **packages** dont tous vos **projets dépendent**. C’est très difficile à gérer. Et vous finiriez probablement par exécuter certains projets avec des **versions incompatibles** des packages, sans savoir pourquoi quelque chose ne fonctionne pas. -De plus, selon votre système d’exploitation (par exemple Linux, Windows, macOS), il se peut qu’il soit livré avec Python déjà installé. Et dans ce cas, il avait probablement des packages préinstallés avec des versions spécifiques nécessaires à votre système. Si vous installez des packages dans l’environnement Python global, vous pourriez finir par casser certains des programmes fournis avec votre système d’exploitation. +De plus, selon votre système d’exploitation (par exemple Linux, Windows, macOS), il se peut qu’il soit livré avec Python déjà installé. Et dans ce cas, il avait probablement des packages préinstallés avec des versions spécifiques **nécessaires à votre système**. Si vous installez des packages dans l’environnement Python global, vous pourriez finir par **casser** certains des programmes fournis avec votre système d’exploitation. ## Où les packages sont-ils installés { #where-are-packages-installed } @@ -566,17 +566,17 @@ $ pip install "fastapi[standard]" Cela téléchargera un fichier compressé avec le code de FastAPI, normalement depuis [PyPI](https://pypi.org/project/fastapi/). -Il téléchargera également des fichiers pour d’autres packages dont FastAPI dépend. +Il **téléchargera** également des fichiers pour d’autres packages dont FastAPI dépend. -Ensuite, il extraira tous ces fichiers et les placera dans un répertoire de votre ordinateur. +Ensuite, il **extraira** tous ces fichiers et les placera dans un répertoire de votre ordinateur. -Par défaut, il placera ces fichiers téléchargés et extraits dans le répertoire fourni avec votre installation de Python, c’est l’environnement global. +Par défaut, il placera ces fichiers téléchargés et extraits dans le répertoire fourni avec votre installation de Python, c’est l’**environnement global**. ## Qu’est-ce qu’un environnement virtuel { #what-are-virtual-environments } -La solution aux problèmes posés par le fait d’avoir tous les packages dans l’environnement global est d’utiliser un environnement virtuel pour chaque projet sur lequel vous travaillez. +La solution aux problèmes posés par le fait d’avoir tous les packages dans l’environnement global est d’utiliser un **environnement virtuel pour chaque projet** sur lequel vous travaillez. -Un environnement virtuel est un répertoire, très similaire à celui global, où vous pouvez installer les packages pour un projet. +Un environnement virtuel est un **répertoire**, très similaire à celui global, où vous pouvez installer les packages pour un projet. De cette manière, chaque projet aura son propre environnement virtuel (répertoire `.venv`) avec ses propres packages. @@ -730,7 +730,7 @@ et utilisera celui-ci. //// -Un détail important est qu’il placera le chemin de l’environnement virtuel au début de la variable `PATH`. Le système le trouvera avant de trouver tout autre Python disponible. Ainsi, lorsque vous exécutez `python`, il utilisera le Python de l’environnement virtuel au lieu de tout autre `python` (par exemple, un `python` d’un environnement global). +Un détail important est qu’il placera le chemin de l’environnement virtuel au **début** de la variable `PATH`. Le système le trouvera **avant** de trouver tout autre Python disponible. Ainsi, lorsque vous exécutez `python`, il utilisera le Python **de l’environnement virtuel** au lieu de tout autre `python` (par exemple, un `python` d’un environnement global). Activer un environnement virtuel change aussi deux ou trois autres choses, mais c’est l’un des points les plus importants. @@ -766,11 +766,11 @@ C:\Users\user\code\awesome-project\.venv\Scripts\python //// -Cela signifie que le programme `python` qui sera utilisé est celui dans l’environnement virtuel. +Cela signifie que le programme `python` qui sera utilisé est celui **dans l’environnement virtuel**. Vous utilisez `which` sous Linux et macOS et `Get-Command` sous Windows PowerShell. -La façon dont cette commande fonctionne est qu’elle va vérifier la variable d’environnement `PATH`, en parcourant chaque chemin dans l’ordre, à la recherche du programme nommé `python`. Une fois trouvé, elle vous affichera le chemin vers ce programme. +La façon dont cette commande fonctionne est qu’elle va vérifier la variable d’environnement `PATH`, en parcourant **chaque chemin dans l’ordre**, à la recherche du programme nommé `python`. Une fois trouvé, elle vous **affichera le chemin** vers ce programme. La partie la plus importante est que lorsque vous appelez `python`, c’est exactement « `python` » qui sera exécuté. @@ -778,9 +778,9 @@ Ainsi, vous pouvez confirmer si vous êtes dans le bon environnement virtuel. /// tip | Astuce -Il est facile d’activer un environnement virtuel, d’obtenir un Python, puis d’aller vers un autre projet. +Il est facile d’activer un environnement virtuel, d’obtenir un Python, puis d’**aller vers un autre projet**. -Et le second projet ne fonctionnerait pas parce que vous utilisez le Python incorrect, provenant d’un environnement virtuel d’un autre projet. +Et le second projet **ne fonctionnerait pas** parce que vous utilisez le **Python incorrect**, provenant d’un environnement virtuel d’un autre projet. Il est utile de pouvoir vérifier quel `python` est utilisé. 🤓 @@ -788,9 +788,9 @@ Il est utile de pouvoir vérifier quel `python` est utilisé. 🤓 ## Pourquoi désactiver un environnement virtuel { #why-deactivate-a-virtual-environment } -Par exemple, vous pourriez travailler sur un projet `philosophers-stone`, activer cet environnement virtuel, installer des packages et travailler avec cet environnement. +Par exemple, vous pourriez travailler sur un projet `philosophers-stone`, **activer cet environnement virtuel**, installer des packages et travailler avec cet environnement. -Puis vous souhaitez travailler sur un autre projet `prisoner-of-azkaban`. +Puis vous souhaitez travailler sur **un autre projet** `prisoner-of-azkaban`. Vous allez vers ce projet : @@ -842,23 +842,23 @@ I solemnly swear 🐺 ## Alternatives { #alternatives } -Ceci est un guide simple pour vous lancer et vous montrer comment tout fonctionne en dessous. +Ceci est un guide simple pour vous lancer et vous montrer comment tout fonctionne **en dessous**. -Il existe de nombreuses alternatives pour gérer les environnements virtuels, les dépendances de packages (requirements), les projets. +Il existe de nombreuses **alternatives** pour gérer les environnements virtuels, les dépendances de packages (requirements), les projets. -Lorsque vous êtes prêt et souhaitez utiliser un outil pour gérer l’ensemble du projet, les dépendances, les environnements virtuels, etc., je vous suggère d’essayer [uv](https://github.com/astral-sh/uv). +Lorsque vous êtes prêt et souhaitez utiliser un outil pour **gérer l’ensemble du projet**, les dépendances de packages, les environnements virtuels, etc., je vous suggère d’essayer [uv](https://github.com/astral-sh/uv). `uv` peut faire beaucoup de choses, il peut : -* Installer Python pour vous, y compris différentes versions -* Gérer l’environnement virtuel pour vos projets -* Installer des packages -* Gérer les dépendances de packages et leurs versions pour votre projet -* Vous assurer d’avoir un ensemble exact de packages et de versions à installer, y compris leurs dépendances, afin que vous puissiez être certain d’exécuter votre projet en production exactement comme sur votre ordinateur pendant le développement, cela s’appelle le locking +* **Installer Python** pour vous, y compris différentes versions +* Gérer l’**environnement virtuel** pour vos projets +* Installer des **packages** +* Gérer les **dépendances et versions** de packages pour votre projet +* Vous assurer d’avoir un ensemble **exact** de packages et de versions à installer, y compris leurs dépendances, afin que vous puissiez être certain d’exécuter votre projet en production exactement comme sur votre ordinateur pendant le développement, cela s’appelle le **locking** * Et bien d’autres choses ## Conclusion { #conclusion } -Si vous avez lu et compris tout cela, vous en savez maintenant bien plus sur les environnements virtuels que beaucoup de développeurs. 🤓 +Si vous avez lu et compris tout cela, vous en savez maintenant **bien plus** sur les environnements virtuels que beaucoup de développeurs. 🤓 -Connaître ces détails vous sera très probablement utile à l’avenir lorsque vous déboguerez quelque chose qui semble complexe, mais vous saurez comment tout fonctionne en dessous. 😎 +Connaître ces détails vous sera très probablement utile à l’avenir lorsque vous déboguerez quelque chose qui semble complexe, mais vous saurez **comment tout fonctionne en dessous**. 😎 From ec2a6adaf14c440bdcd0fd3f4ca203daa8c3ba6a Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Wed, 1 Jul 2026 14:07:01 +0000 Subject: [PATCH 381/462] =?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 38f3ef0d5..e72483955 100644 --- a/docs/en/docs/release-notes.md +++ b/docs/en/docs/release-notes.md @@ -9,6 +9,7 @@ hide: ### Translations +* 🌐 Update translations for fr (update-outdated). PR [#15897](https://github.com/fastapi/fastapi/pull/15897) by [@tiangolo](https://github.com/tiangolo). * 🌐 Update translations for ja (update-outdated). PR [#15895](https://github.com/fastapi/fastapi/pull/15895) by [@tiangolo](https://github.com/tiangolo). * 🌐 Update translations for zh-hant (update-outdated). PR [#15896](https://github.com/fastapi/fastapi/pull/15896) by [@tiangolo](https://github.com/tiangolo). * 🌐 Update translations for de (update-outdated). PR [#15899](https://github.com/fastapi/fastapi/pull/15899) by [@tiangolo](https://github.com/tiangolo). From fd6ece32eeb27c9ce164bd9170f9d8e1db1dacff Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebasti=C3=A1n=20Ram=C3=ADrez?= Date: Wed, 1 Jul 2026 16:23:18 +0200 Subject: [PATCH 382/462] =?UTF-8?q?=F0=9F=91=A5=20Update=20FastAPI=20GitHu?= =?UTF-8?q?b=20topic=20repositories=20(#15906)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: github-actions[bot] --- docs/en/data/topic_repos.yml | 370 +++++++++++++++++------------------ 1 file changed, 185 insertions(+), 185 deletions(-) diff --git a/docs/en/data/topic_repos.yml b/docs/en/data/topic_repos.yml index 9013ebc1c..ecfad6cb4 100644 --- a/docs/en/data/topic_repos.yml +++ b/docs/en/data/topic_repos.yml @@ -1,186 +1,191 @@ +- name: headroom + html_url: https://github.com/headroomlabs-ai/headroom + stars: 55017 + owner_login: headroomlabs-ai + owner_html_url: https://github.com/headroomlabs-ai - name: full-stack-fastapi-template html_url: https://github.com/fastapi/full-stack-fastapi-template - stars: 43447 + stars: 43994 owner_login: fastapi owner_html_url: https://github.com/fastapi - name: Hello-Python html_url: https://github.com/mouredev/Hello-Python - stars: 35831 + stars: 36226 owner_login: mouredev owner_html_url: https://github.com/mouredev - name: serve html_url: https://github.com/jina-ai/serve - stars: 21864 + stars: 21862 owner_login: jina-ai owner_html_url: https://github.com/jina-ai - name: HivisionIDPhotos html_url: https://github.com/Zeyi-Lin/HivisionIDPhotos - stars: 21144 + stars: 21212 owner_login: Zeyi-Lin owner_html_url: https://github.com/Zeyi-Lin - name: Douyin_TikTok_Download_API html_url: https://github.com/Evil0ctal/Douyin_TikTok_Download_API - stars: 18122 + stars: 18599 owner_login: Evil0ctal owner_html_url: https://github.com/Evil0ctal - name: sqlmodel html_url: https://github.com/fastapi/sqlmodel - stars: 17987 + stars: 18156 owner_login: fastapi owner_html_url: https://github.com/fastapi - name: fastapi-best-practices html_url: https://github.com/zhanymkanov/fastapi-best-practices - stars: 17401 + stars: 17608 owner_login: zhanymkanov owner_html_url: https://github.com/zhanymkanov - name: SurfSense html_url: https://github.com/MODSetter/SurfSense - stars: 14374 + stars: 15161 owner_login: MODSetter owner_html_url: https://github.com/MODSetter - name: machine-learning-zoomcamp html_url: https://github.com/DataTalksClub/machine-learning-zoomcamp - stars: 13169 + stars: 13445 owner_login: DataTalksClub owner_html_url: https://github.com/DataTalksClub +- name: peewee + html_url: https://github.com/coleifer/peewee + stars: 11976 + owner_login: coleifer + owner_html_url: https://github.com/coleifer - name: fastapi_mcp html_url: https://github.com/tadata-org/fastapi_mcp - stars: 11885 + stars: 11932 owner_login: tadata-org owner_html_url: https://github.com/tadata-org -- name: awesome-fastapi - html_url: https://github.com/mjhea0/awesome-fastapi - stars: 11406 - owner_login: mjhea0 - owner_html_url: https://github.com/mjhea0 - name: XHS-Downloader html_url: https://github.com/JoeanAmier/XHS-Downloader - stars: 11375 + stars: 11768 owner_login: JoeanAmier owner_html_url: https://github.com/JoeanAmier +- name: awesome-fastapi + html_url: https://github.com/mjhea0/awesome-fastapi + stars: 11478 + owner_login: mjhea0 + owner_html_url: https://github.com/mjhea0 - name: polar html_url: https://github.com/polarsource/polar - stars: 9894 + stars: 9999 owner_login: polarsource owner_html_url: https://github.com/polarsource - name: pycaret html_url: https://github.com/pycaret/pycaret - stars: 9801 + stars: 9818 owner_login: pycaret owner_html_url: https://github.com/pycaret - name: FastUI html_url: https://github.com/pydantic/FastUI - stars: 8966 + stars: 8970 owner_login: pydantic owner_html_url: https://github.com/pydantic - name: FileCodeBox html_url: https://github.com/vastsa/FileCodeBox - stars: 8305 + stars: 8376 owner_login: vastsa owner_html_url: https://github.com/vastsa - name: nonebot2 html_url: https://github.com/nonebot/nonebot2 - stars: 7544 + stars: 7593 owner_login: nonebot owner_html_url: https://github.com/nonebot - name: hatchet html_url: https://github.com/hatchet-dev/hatchet - stars: 7258 + stars: 7441 owner_login: hatchet-dev owner_html_url: https://github.com/hatchet-dev - name: fastapi-users html_url: https://github.com/fastapi-users/fastapi-users - stars: 6152 + stars: 6182 owner_login: fastapi-users owner_html_url: https://github.com/fastapi-users -- name: serge - html_url: https://github.com/serge-chat/serge - stars: 5726 - owner_login: serge-chat - owner_html_url: https://github.com/serge-chat - name: Yuxi html_url: https://github.com/xerrors/Yuxi - stars: 5323 + stars: 5926 owner_login: xerrors owner_html_url: https://github.com/xerrors +- name: serge + html_url: https://github.com/serge-chat/serge + stars: 5723 + owner_login: serge-chat + owner_html_url: https://github.com/serge-chat +- name: honcho + html_url: https://github.com/plastic-labs/honcho + stars: 5680 + owner_login: plastic-labs + owner_html_url: https://github.com/plastic-labs - name: Kokoro-FastAPI html_url: https://github.com/remsky/Kokoro-FastAPI - stars: 4936 + stars: 5085 owner_login: remsky owner_html_url: https://github.com/remsky - name: devpush html_url: https://github.com/hunvreus/devpush - stars: 4664 + stars: 4693 owner_login: hunvreus owner_html_url: https://github.com/hunvreus - name: strawberry html_url: https://github.com/strawberry-graphql/strawberry - stars: 4663 + stars: 4677 owner_login: strawberry-graphql owner_html_url: https://github.com/strawberry-graphql -- name: honcho - html_url: https://github.com/plastic-labs/honcho - stars: 4606 - owner_login: plastic-labs - owner_html_url: https://github.com/plastic-labs - name: poem html_url: https://github.com/poem-web/poem - stars: 4398 + stars: 4415 owner_login: poem-web owner_html_url: https://github.com/poem-web -- name: dynaconf - html_url: https://github.com/dynaconf/dynaconf - stars: 4302 - owner_login: dynaconf - owner_html_url: https://github.com/dynaconf - name: logfire html_url: https://github.com/pydantic/logfire - stars: 4276 + stars: 4340 owner_login: pydantic owner_html_url: https://github.com/pydantic +- name: dynaconf + html_url: https://github.com/dynaconf/dynaconf + stars: 4310 + owner_login: dynaconf + owner_html_url: https://github.com/dynaconf - name: chatgpt-web-share html_url: https://github.com/chatpire/chatgpt-web-share - stars: 4273 + stars: 4269 owner_login: chatpire owner_html_url: https://github.com/chatpire - name: huma html_url: https://github.com/danielgtaylor/huma - stars: 4133 + stars: 4203 owner_login: danielgtaylor owner_html_url: https://github.com/danielgtaylor - name: atrilabs-engine html_url: https://github.com/Atri-Labs/atrilabs-engine - stars: 4073 + stars: 4071 owner_login: Atri-Labs owner_html_url: https://github.com/Atri-Labs +- name: mcp-context-forge + html_url: https://github.com/IBM/mcp-context-forge + stars: 3989 + owner_login: IBM + owner_html_url: https://github.com/IBM - name: datamodel-code-generator html_url: https://github.com/koxudaxi/datamodel-code-generator - stars: 3918 + stars: 3952 owner_login: koxudaxi owner_html_url: https://github.com/koxudaxi - name: LitServe html_url: https://github.com/Lightning-AI/LitServe - stars: 3886 + stars: 3901 owner_login: Lightning-AI owner_html_url: https://github.com/Lightning-AI -- name: mcp-context-forge - html_url: https://github.com/IBM/mcp-context-forge - stars: 3797 - owner_login: IBM - owner_html_url: https://github.com/IBM - name: fastapi-admin html_url: https://github.com/fastapi-admin/fastapi-admin - stars: 3784 + stars: 3799 owner_login: fastapi-admin owner_html_url: https://github.com/fastapi-admin -- name: headroom - html_url: https://github.com/chopratejas/headroom - stars: 3701 - owner_login: chopratejas - owner_html_url: https://github.com/chopratejas - name: tracecat html_url: https://github.com/TracecatHQ/tracecat - stars: 3624 + stars: 3703 owner_login: TracecatHQ owner_html_url: https://github.com/TracecatHQ - name: farfalle @@ -188,139 +193,159 @@ stars: 3535 owner_login: rashadphz owner_html_url: https://github.com/rashadphz +- name: Rapid-MLX + html_url: https://github.com/raullenchai/Rapid-MLX + stars: 3155 + owner_login: raullenchai + owner_html_url: https://github.com/raullenchai - name: opyrator html_url: https://github.com/ml-tooling/opyrator - stars: 3136 + stars: 3133 owner_login: ml-tooling owner_html_url: https://github.com/ml-tooling - name: docarray html_url: https://github.com/docarray/docarray - stars: 3119 + stars: 3121 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: 3110 + stars: 3109 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: 2910 + stars: 2914 owner_login: tiangolo owner_html_url: https://github.com/tiangolo +- name: any-auto-register + html_url: https://github.com/lxf746/any-auto-register + stars: 2832 + owner_login: lxf746 + owner_html_url: https://github.com/lxf746 - name: FastAPI-template html_url: https://github.com/s3rius/FastAPI-template - stars: 2800 + stars: 2810 owner_login: s3rius owner_html_url: https://github.com/s3rius - name: YC-Killer html_url: https://github.com/sahibzada-allahyar/YC-Killer - stars: 2770 + stars: 2779 owner_login: sahibzada-allahyar owner_html_url: https://github.com/sahibzada-allahyar - name: sqladmin html_url: https://github.com/smithyhq/sqladmin - stars: 2739 + stars: 2759 owner_login: smithyhq owner_html_url: https://github.com/smithyhq - name: best-of-web-python html_url: https://github.com/ml-tooling/best-of-web-python - stars: 2723 + stars: 2731 owner_login: ml-tooling owner_html_url: https://github.com/ml-tooling -- name: Rapid-MLX - html_url: https://github.com/raullenchai/Rapid-MLX - stars: 2640 - owner_login: raullenchai - owner_html_url: https://github.com/raullenchai +- name: NoteDiscovery + html_url: https://github.com/gamosoft/NoteDiscovery + stars: 2595 + owner_login: gamosoft + owner_html_url: https://github.com/gamosoft - name: fastapi-react html_url: https://github.com/Buuntu/fastapi-react stars: 2588 owner_login: Buuntu owner_html_url: https://github.com/Buuntu -- name: any-auto-register - html_url: https://github.com/lxf746/any-auto-register - stars: 2542 - owner_login: lxf746 - owner_html_url: https://github.com/lxf746 -- name: NoteDiscovery - html_url: https://github.com/gamosoft/NoteDiscovery - stars: 2531 - owner_login: gamosoft - owner_html_url: https://github.com/gamosoft - name: supabase-py html_url: https://github.com/supabase/supabase-py - stars: 2518 + stars: 2530 owner_login: supabase owner_html_url: https://github.com/supabase - name: 30-Days-of-Python html_url: https://github.com/codingforentrepreneurs/30-Days-of-Python - stars: 2470 + stars: 2483 owner_login: codingforentrepreneurs owner_html_url: https://github.com/codingforentrepreneurs - name: RasaGPT html_url: https://github.com/paulpierre/RasaGPT - stars: 2466 + stars: 2462 owner_login: paulpierre owner_html_url: https://github.com/paulpierre -- name: AIstudioProxyAPI - html_url: https://github.com/CJackHwang/AIstudioProxyAPI - stars: 2396 - owner_login: CJackHwang - owner_html_url: https://github.com/CJackHwang - name: fastapi-langgraph-agent-production-ready-template html_url: https://github.com/wassim249/fastapi-langgraph-agent-production-ready-template - stars: 2338 + stars: 2456 owner_login: wassim249 owner_html_url: https://github.com/wassim249 +- name: AIstudioProxyAPI + html_url: https://github.com/CJackHwang/AIstudioProxyAPI + stars: 2445 + owner_login: CJackHwang + owner_html_url: https://github.com/CJackHwang - name: nextpy html_url: https://github.com/dot-agent/nextpy - stars: 2336 + stars: 2341 owner_login: dot-agent owner_html_url: https://github.com/dot-agent - name: langserve html_url: https://github.com/langchain-ai/langserve - stars: 2330 + stars: 2329 owner_login: langchain-ai owner_html_url: https://github.com/langchain-ai -- name: fastapi-utils - html_url: https://github.com/fastapiutils/fastapi-utils - stars: 2310 - owner_login: fastapiutils - owner_html_url: https://github.com/fastapiutils - name: fastapi-best-architecture html_url: https://github.com/fastapi-practices/fastapi-best-architecture - stars: 2256 + stars: 2318 owner_login: fastapi-practices owner_html_url: https://github.com/fastapi-practices -- name: solara - html_url: https://github.com/widgetti/solara - stars: 2162 - owner_login: widgetti - owner_html_url: https://github.com/widgetti +- name: fastapi-utils + html_url: https://github.com/fastapiutils/fastapi-utils + stars: 2308 + owner_login: fastapiutils + owner_html_url: https://github.com/fastapiutils - name: vue-fastapi-admin html_url: https://github.com/mizhexiaoxiao/vue-fastapi-admin - stars: 2148 + stars: 2184 owner_login: mizhexiaoxiao owner_html_url: https://github.com/mizhexiaoxiao +- name: solara + html_url: https://github.com/widgetti/solara + stars: 2166 + owner_login: widgetti + owner_html_url: https://github.com/widgetti - name: mangum html_url: https://github.com/Kludex/mangum - stars: 2119 + stars: 2125 owner_login: Kludex owner_html_url: https://github.com/Kludex +- name: codex-lb + html_url: https://github.com/Soju06/codex-lb + stars: 2122 + owner_login: Soju06 + owner_html_url: https://github.com/Soju06 +- name: kiro-gateway + html_url: https://github.com/jwadow/kiro-gateway + stars: 2068 + owner_login: jwadow + owner_html_url: https://github.com/jwadow +- name: open-wearables + html_url: https://github.com/the-momentum/open-wearables + stars: 2036 + owner_login: the-momentum + owner_html_url: https://github.com/the-momentum - name: slowapi html_url: https://github.com/laurentS/slowapi - stars: 2000 + stars: 2022 owner_login: laurentS owner_html_url: https://github.com/laurentS - name: xhs_ai_publisher html_url: https://github.com/BetaStreetOmnis/xhs_ai_publisher - stars: 1980 + stars: 2004 owner_login: BetaStreetOmnis owner_html_url: https://github.com/BetaStreetOmnis +- name: FastAPI-boilerplate + html_url: https://github.com/benavlabs/FastAPI-boilerplate + stars: 1984 + owner_login: benavlabs + owner_html_url: https://github.com/benavlabs - name: openapi-python-client html_url: https://github.com/openapi-generators/openapi-python-client - stars: 1960 + stars: 1967 owner_login: openapi-generators owner_html_url: https://github.com/openapi-generators - name: agentkit @@ -328,34 +353,24 @@ stars: 1944 owner_login: BCG-X-Official owner_html_url: https://github.com/BCG-X-Official -- name: FastAPI-boilerplate - html_url: https://github.com/benavlabs/FastAPI-boilerplate - stars: 1931 - owner_login: benavlabs - owner_html_url: https://github.com/benavlabs - name: piccolo html_url: https://github.com/piccolo-orm/piccolo - stars: 1904 + stars: 1922 owner_login: piccolo-orm owner_html_url: https://github.com/piccolo-orm - name: manage-fastapi html_url: https://github.com/ycd/manage-fastapi - stars: 1903 + stars: 1905 owner_login: ycd owner_html_url: https://github.com/ycd - name: fastapi-cache html_url: https://github.com/long2ice/fastapi-cache - stars: 1865 + stars: 1866 owner_login: long2ice owner_html_url: https://github.com/long2ice -- name: kiro-gateway - html_url: https://github.com/jwadow/kiro-gateway - stars: 1853 - owner_login: jwadow - owner_html_url: https://github.com/jwadow - name: ormar html_url: https://github.com/ormar-orm/ormar - stars: 1809 + stars: 1806 owner_login: ormar-orm owner_html_url: https://github.com/ormar-orm - name: python-week-2022 @@ -363,39 +378,29 @@ stars: 1806 owner_login: rochacbruno owner_html_url: https://github.com/rochacbruno -- name: open-wearables - html_url: https://github.com/the-momentum/open-wearables - stars: 1782 - owner_login: the-momentum - owner_html_url: https://github.com/the-momentum +- name: WebRPA + html_url: https://github.com/pmh1314520/WebRPA + stars: 1781 + owner_login: pmh1314520 + owner_html_url: https://github.com/pmh1314520 - name: termpair html_url: https://github.com/cs01/termpair stars: 1735 owner_login: cs01 owner_html_url: https://github.com/cs01 -- name: WebRPA - html_url: https://github.com/pmh1314520/WebRPA - stars: 1718 - owner_login: pmh1314520 - owner_html_url: https://github.com/pmh1314520 -- name: codex-lb - html_url: https://github.com/Soju06/codex-lb - stars: 1709 - owner_login: Soju06 - owner_html_url: https://github.com/Soju06 - name: fastapi-crudrouter html_url: https://github.com/awtkns/fastapi-crudrouter - stars: 1692 + stars: 1694 owner_login: awtkns owner_html_url: https://github.com/awtkns - name: bracket html_url: https://github.com/evroon/bracket - stars: 1682 + stars: 1694 owner_login: evroon owner_html_url: https://github.com/evroon - name: fastapi-pagination html_url: https://github.com/uriyyo/fastapi-pagination - stars: 1658 + stars: 1670 owner_login: uriyyo owner_html_url: https://github.com/uriyyo - name: langchain-serve @@ -405,91 +410,86 @@ owner_html_url: https://github.com/jina-ai - name: awesome-fastapi-projects html_url: https://github.com/Kludex/awesome-fastapi-projects - stars: 1603 + stars: 1608 owner_login: Kludex owner_html_url: https://github.com/Kludex - name: coronavirus-tracker-api html_url: https://github.com/ExpDev07/coronavirus-tracker-api - stars: 1567 + stars: 1568 owner_login: ExpDev07 owner_html_url: https://github.com/ExpDev07 - name: fastapi-amis-admin html_url: https://github.com/amisadmin/fastapi-amis-admin - stars: 1554 + stars: 1559 owner_login: amisadmin owner_html_url: https://github.com/amisadmin - name: fastcrud html_url: https://github.com/benavlabs/fastcrud - stars: 1519 + stars: 1531 owner_login: benavlabs owner_html_url: https://github.com/benavlabs - name: tavily-key-generator html_url: https://github.com/skernelx/tavily-key-generator - stars: 1507 + stars: 1526 owner_login: skernelx owner_html_url: https://github.com/skernelx - name: fastapi-boilerplate html_url: https://github.com/teamhide/fastapi-boilerplate - stars: 1490 + stars: 1491 owner_login: teamhide owner_html_url: https://github.com/teamhide +- name: full-stack-ai-agent-template + html_url: https://github.com/vstorm-co/full-stack-ai-agent-template + stars: 1484 + owner_login: vstorm-co + owner_html_url: https://github.com/vstorm-co - name: prometheus-fastapi-instrumentator html_url: https://github.com/trallnag/prometheus-fastapi-instrumentator - stars: 1458 + stars: 1471 owner_login: trallnag owner_html_url: https://github.com/trallnag - name: awesome-python-resources html_url: https://github.com/DjangoEx/awesome-python-resources - stars: 1448 + stars: 1451 owner_login: DjangoEx owner_html_url: https://github.com/DjangoEx -- name: fastapi-tutorial - html_url: https://github.com/liaogx/fastapi-tutorial - stars: 1404 - owner_login: liaogx - owner_html_url: https://github.com/liaogx -- name: fastapi-code-generator - html_url: https://github.com/koxudaxi/fastapi-code-generator - stars: 1397 - owner_login: koxudaxi - owner_html_url: https://github.com/koxudaxi - name: aktools html_url: https://github.com/akfamily/aktools - stars: 1394 + stars: 1431 owner_login: akfamily owner_html_url: https://github.com/akfamily - name: RuoYi-Vue3-FastAPI html_url: https://github.com/insistence/RuoYi-Vue3-FastAPI - stars: 1364 + stars: 1419 owner_login: insistence owner_html_url: https://github.com/insistence +- name: fastapi-tutorial + html_url: https://github.com/liaogx/fastapi-tutorial + stars: 1418 + owner_login: liaogx + owner_html_url: https://github.com/liaogx +- name: fastapi-code-generator + html_url: https://github.com/koxudaxi/fastapi-code-generator + stars: 1396 + owner_login: koxudaxi + owner_html_url: https://github.com/koxudaxi +- name: yubal + html_url: https://github.com/guillevc/yubal + stars: 1388 + owner_login: guillevc + owner_html_url: https://github.com/guillevc - name: budgetml html_url: https://github.com/ebhy/budgetml - stars: 1345 + stars: 1343 owner_login: ebhy owner_html_url: https://github.com/ebhy -- name: full-stack-ai-agent-template - html_url: https://github.com/vstorm-co/full-stack-ai-agent-template - stars: 1316 - owner_login: vstorm-co - owner_html_url: https://github.com/vstorm-co -- name: bolt-python - html_url: https://github.com/slackapi/bolt-python - stars: 1308 - owner_login: slackapi - owner_html_url: https://github.com/slackapi -- name: bedrock-chat - html_url: https://github.com/aws-samples/bedrock-chat - stars: 1304 - owner_login: aws-samples - owner_html_url: https://github.com/aws-samples +- name: Chatterbox-TTS-Server + html_url: https://github.com/devnen/Chatterbox-TTS-Server + stars: 1328 + owner_login: devnen + owner_html_url: https://github.com/devnen - name: restish html_url: https://github.com/rest-sh/restish - stars: 1303 + stars: 1321 owner_login: rest-sh owner_html_url: https://github.com/rest-sh -- name: yubal - html_url: https://github.com/guillevc/yubal - stars: 1302 - owner_login: guillevc - owner_html_url: https://github.com/guillevc From 122f1b58f4e0fabfefef3710a8c8247bb2bd820b Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Wed, 1 Jul 2026 14:23:45 +0000 Subject: [PATCH 383/462] =?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 e72483955..eb72ce6f7 100644 --- a/docs/en/docs/release-notes.md +++ b/docs/en/docs/release-notes.md @@ -34,6 +34,7 @@ hide: ### Internal +* 👥 Update FastAPI GitHub topic repositories. PR [#15906](https://github.com/fastapi/fastapi/pull/15906) by [@tiangolo](https://github.com/tiangolo). * 👥 Update FastAPI People - Contributors and Translators. PR [#15878](https://github.com/fastapi/fastapi/pull/15878) by [@tiangolo](https://github.com/tiangolo). * 👷 Remove not needed `allow-unsafe-pr-checkout: true`. PR [#15876](https://github.com/fastapi/fastapi/pull/15876) by [@YuriiMotov](https://github.com/YuriiMotov). * ⬆ Bump the github-actions group with 5 updates. PR [#15872](https://github.com/fastapi/fastapi/pull/15872) by [@dependabot[bot]](https://github.com/apps/dependabot). From d30a3ebfc7d7fd7851ba4243677266c53cb9f154 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebasti=C3=A1n=20Ram=C3=ADrez?= Date: Wed, 1 Jul 2026 17:53:31 +0200 Subject: [PATCH 384/462] =?UTF-8?q?=F0=9F=91=A5=20Update=20FastAPI=20Peopl?= =?UTF-8?q?e=20-=20Experts=20(#15909)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: github-actions[bot] --- docs/en/data/people.yml | 404 +++++++++++++++++++++++----------------- 1 file changed, 230 insertions(+), 174 deletions(-) diff --git a/docs/en/data/people.yml b/docs/en/data/people.yml index 6a2b2eca6..b22d5371b 100644 --- a/docs/en/data/people.yml +++ b/docs/en/data/people.yml @@ -1,15 +1,15 @@ maintainers: - login: tiangolo - answers: 1929 + answers: 1931 avatarUrl: https://avatars.githubusercontent.com/u/1326112?u=cb5d06e73a9e1998141b1641aa88e443c6717651&v=4 url: https://github.com/tiangolo experts: - login: tiangolo - count: 1929 + count: 1931 avatarUrl: https://avatars.githubusercontent.com/u/1326112?u=cb5d06e73a9e1998141b1641aa88e443c6717651&v=4 url: https://github.com/tiangolo - login: YuriiMotov - count: 1178 + count: 1198 avatarUrl: https://avatars.githubusercontent.com/u/109919500?u=bc48be95c429989224786106b027f3c5e40cc354&v=4 url: https://github.com/YuriiMotov - login: github-actions @@ -17,7 +17,7 @@ experts: avatarUrl: https://avatars.githubusercontent.com/in/15368?v=4 url: https://github.com/apps/github-actions - login: Kludex - count: 657 + count: 656 avatarUrl: https://avatars.githubusercontent.com/u/7353520?u=df8a3f06ba8f55ae1967a3e2d5ed882903a4e330&v=4 url: https://github.com/Kludex - login: jgould22 @@ -49,15 +49,15 @@ experts: avatarUrl: https://avatars.githubusercontent.com/u/10519440?u=f09cdd745e5bf16138f29b42732dd57c7f02bee1&v=4 url: https://github.com/iudeen - login: phy25 - count: 126 + count: 125 avatarUrl: https://avatars.githubusercontent.com/u/331403?v=4 url: https://github.com/phy25 - login: JavierSanchezCastro - count: 109 + count: 110 avatarUrl: https://avatars.githubusercontent.com/u/72013291?u=ae5679e6bd971d9d98cd5e76e8683f83642ba950&v=4 url: https://github.com/JavierSanchezCastro - login: luzzodev - count: 107 + count: 109 avatarUrl: https://avatars.githubusercontent.com/u/27291415?u=5607ae1ce75c5f54f09500ca854227f7bfd2033b&v=4 url: https://github.com/luzzodev - login: raphaelauv @@ -246,82 +246,138 @@ experts: url: https://github.com/abhint last_month_experts: - login: YuriiMotov - count: 14 + count: 21 avatarUrl: https://avatars.githubusercontent.com/u/109919500?u=bc48be95c429989224786106b027f3c5e40cc354&v=4 url: https://github.com/YuriiMotov -- login: yudin-s - count: 5 - avatarUrl: https://avatars.githubusercontent.com/u/781481?u=8c1ab221edbe051eb55310747ebe39574e808118&v=4 - url: https://github.com/yudin-s -- login: BitWeaverDev - count: 3 - avatarUrl: https://avatars.githubusercontent.com/u/288751066?v=4 - url: https://github.com/BitWeaverDev -- login: Zawwarsami16 +- login: Raphasha27 + count: 6 + avatarUrl: https://avatars.githubusercontent.com/u/220842167?u=a9e66fe06965e3830aecb82be4a442874950babe&v=4 + url: https://github.com/Raphasha27 +- login: svlandeg + count: 4 + avatarUrl: https://avatars.githubusercontent.com/u/8796347?u=556c97650c27021911b0b9447ec55e75987b0e8a&v=4 + url: https://github.com/svlandeg +- login: sueun-dev count: 3 - avatarUrl: https://avatars.githubusercontent.com/u/105767627?u=5bb2b7a639a9207a5ded536f963a4c7bd6d04d21&v=4 - url: https://github.com/Zawwarsami16 + avatarUrl: https://avatars.githubusercontent.com/u/57546981?u=0b0483bdcc7d521e85c06f28d2fc64e258bd466f&v=4 + url: https://github.com/sueun-dev - login: tiangolo - count: 2 + count: 3 avatarUrl: https://avatars.githubusercontent.com/u/1326112?u=cb5d06e73a9e1998141b1641aa88e443c6717651&v=4 url: https://github.com/tiangolo -- login: mg1986jp +- login: vincere-mori + count: 3 + avatarUrl: https://avatars.githubusercontent.com/u/57835745?u=37d4cd4a763163dd03f29eff4975c2f1fa2a2d72&v=4 + url: https://github.com/vincere-mori +- login: thanos07 count: 2 - avatarUrl: https://avatars.githubusercontent.com/u/20254686?u=6da9cdad3ecf8a4f3cbc33a518c3998ed0ac685a&v=4 - url: https://github.com/mg1986jp -- login: Bogdusik + avatarUrl: https://avatars.githubusercontent.com/u/68923656?u=dab6d4d9a6800f7d44d8c6df0b9904e17c2ecdb7&v=4 + url: https://github.com/thanos07 +- login: luzzodev count: 2 - avatarUrl: https://avatars.githubusercontent.com/u/166155258?u=11440b02966a3f5e5eeebc21d67b7bbb7d370487&v=4 - url: https://github.com/Bogdusik + avatarUrl: https://avatars.githubusercontent.com/u/27291415?u=5607ae1ce75c5f54f09500ca854227f7bfd2033b&v=4 + url: https://github.com/luzzodev +- login: MajorDallas + count: 2 + avatarUrl: https://avatars.githubusercontent.com/u/79329882?u=e611ed986e4a37fd16ab69116a4600d95bfff294&v=4 + url: https://github.com/MajorDallas +- login: Francis1998 + count: 2 + avatarUrl: https://avatars.githubusercontent.com/u/66462431?u=20bdf51356ee7d99a8c8755c09460950d2b84fd0&v=4 + url: https://github.com/Francis1998 +- login: abdurrahman310303 + count: 2 + avatarUrl: https://avatars.githubusercontent.com/u/121820588?u=73c72a59ca082ceb8507bb1e2b559e59bdf2358f&v=4 + url: https://github.com/abdurrahman310303 +- login: Hassanmahmood4 + count: 2 + avatarUrl: https://avatars.githubusercontent.com/u/193066885?u=0e05f82009f99c53b16781d06a7f8d5fea8cc433&v=4 + url: https://github.com/Hassanmahmood4 three_months_experts: - login: YuriiMotov - count: 57 + count: 47 avatarUrl: https://avatars.githubusercontent.com/u/109919500?u=bc48be95c429989224786106b027f3c5e40cc354&v=4 url: https://github.com/YuriiMotov - login: Firatasi count: 7 avatarUrl: https://avatars.githubusercontent.com/u/112112161?u=3219914a49a4a604b3626007823db7de049b6d66&v=4 url: https://github.com/Firatasi +- login: Raphasha27 + count: 6 + avatarUrl: https://avatars.githubusercontent.com/u/220842167?u=a9e66fe06965e3830aecb82be4a442874950babe&v=4 + url: https://github.com/Raphasha27 - login: yudin-s - count: 5 + count: 6 avatarUrl: https://avatars.githubusercontent.com/u/781481?u=8c1ab221edbe051eb55310747ebe39574e808118&v=4 url: https://github.com/yudin-s +- login: svlandeg + count: 5 + avatarUrl: https://avatars.githubusercontent.com/u/8796347?u=556c97650c27021911b0b9447ec55e75987b0e8a&v=4 + url: https://github.com/svlandeg - login: tiangolo - count: 4 + count: 5 avatarUrl: https://avatars.githubusercontent.com/u/1326112?u=cb5d06e73a9e1998141b1641aa88e443c6717651&v=4 url: https://github.com/tiangolo -- login: BitWeaverDev +- login: luzzodev + count: 4 + avatarUrl: https://avatars.githubusercontent.com/u/27291415?u=5607ae1ce75c5f54f09500ca854227f7bfd2033b&v=4 + url: https://github.com/luzzodev +- login: sueun-dev + count: 4 + avatarUrl: https://avatars.githubusercontent.com/u/57546981?u=0b0483bdcc7d521e85c06f28d2fc64e258bd466f&v=4 + url: https://github.com/sueun-dev +- login: cookesan count: 3 - avatarUrl: https://avatars.githubusercontent.com/u/288751066?v=4 - url: https://github.com/BitWeaverDev + avatarUrl: https://avatars.githubusercontent.com/u/6601329?u=7bfc9b017198a9fa50929ae8ae0a787632424ffd&v=4 + url: https://github.com/cookesan - login: ericgitangu count: 3 avatarUrl: https://avatars.githubusercontent.com/u/11472845?u=9d916cf0f5c80e63cb1d753b8b50dcb8ced3b883&v=4 url: https://github.com/ericgitangu +- login: BitWeaverDev + count: 3 + avatarUrl: https://avatars.githubusercontent.com/u/288751066?u=60ef471e6d3822b99c9a3e7624d510b911004434&v=4 + url: https://github.com/BitWeaverDev +- login: vincere-mori + count: 3 + avatarUrl: https://avatars.githubusercontent.com/u/57835745?u=37d4cd4a763163dd03f29eff4975c2f1fa2a2d72&v=4 + url: https://github.com/vincere-mori - login: Zawwarsami16 count: 3 avatarUrl: https://avatars.githubusercontent.com/u/105767627?u=5bb2b7a639a9207a5ded536f963a4c7bd6d04d21&v=4 url: https://github.com/Zawwarsami16 -- login: luzzodev - count: 3 - avatarUrl: https://avatars.githubusercontent.com/u/27291415?u=5607ae1ce75c5f54f09500ca854227f7bfd2033b&v=4 - url: https://github.com/luzzodev +- login: thanos07 + count: 2 + avatarUrl: https://avatars.githubusercontent.com/u/68923656?u=dab6d4d9a6800f7d44d8c6df0b9904e17c2ecdb7&v=4 + url: https://github.com/thanos07 +- login: MajorDallas + count: 2 + avatarUrl: https://avatars.githubusercontent.com/u/79329882?u=e611ed986e4a37fd16ab69116a4600d95bfff294&v=4 + url: https://github.com/MajorDallas +- login: Francis1998 + count: 2 + avatarUrl: https://avatars.githubusercontent.com/u/66462431?u=20bdf51356ee7d99a8c8755c09460950d2b84fd0&v=4 + url: https://github.com/Francis1998 +- login: RichieB2B + count: 2 + avatarUrl: https://avatars.githubusercontent.com/u/1461970?u=edaa57d1077705244ea5c9244f4783d94ff11f12&v=4 + url: https://github.com/RichieB2B +- login: abdurrahman310303 + count: 2 + avatarUrl: https://avatars.githubusercontent.com/u/121820588?u=73c72a59ca082ceb8507bb1e2b559e59bdf2358f&v=4 + url: https://github.com/abdurrahman310303 +- login: Hassanmahmood4 + count: 2 + avatarUrl: https://avatars.githubusercontent.com/u/193066885?u=0e05f82009f99c53b16781d06a7f8d5fea8cc433&v=4 + url: https://github.com/Hassanmahmood4 - login: mg1986jp count: 2 avatarUrl: https://avatars.githubusercontent.com/u/20254686?u=6da9cdad3ecf8a4f3cbc33a518c3998ed0ac685a&v=4 url: https://github.com/mg1986jp -- login: sueun-dev - count: 2 - avatarUrl: https://avatars.githubusercontent.com/u/57546981?u=0b0483bdcc7d521e85c06f28d2fc64e258bd466f&v=4 - url: https://github.com/sueun-dev - login: Bogdusik count: 2 avatarUrl: https://avatars.githubusercontent.com/u/166155258?u=11440b02966a3f5e5eeebc21d67b7bbb7d370487&v=4 url: https://github.com/Bogdusik -- login: cookesan - count: 2 - avatarUrl: https://avatars.githubusercontent.com/u/6601329?u=7bfc9b017198a9fa50929ae8ae0a787632424ffd&v=4 - url: https://github.com/cookesan - login: coleifer count: 2 avatarUrl: https://avatars.githubusercontent.com/u/119974?u=b3a546c94ee1105e792e0acad2c4743d800e7975&v=4 @@ -330,55 +386,51 @@ three_months_experts: count: 2 avatarUrl: https://avatars.githubusercontent.com/u/34988899?u=b8e3c0cf26f4bd1faea265d2f5f66f564af63463&v=4 url: https://github.com/Bahtya -- login: saitarrun - count: 2 - avatarUrl: https://avatars.githubusercontent.com/u/116748905?u=3433afbaf06676a482ebf4ba33b08ddb3fc5c5bf&v=4 - url: https://github.com/saitarrun -- login: JavierSanchezCastro - count: 2 - avatarUrl: https://avatars.githubusercontent.com/u/72013291?u=ae5679e6bd971d9d98cd5e76e8683f83642ba950&v=4 - url: https://github.com/JavierSanchezCastro -- login: christiansousadev - count: 2 - avatarUrl: https://avatars.githubusercontent.com/u/103544118?u=690f3f76d1dc4d0929de5020679d5604f860acbc&v=4 - url: https://github.com/christiansousadev - login: DoctorJohn count: 2 avatarUrl: https://avatars.githubusercontent.com/u/14076775?u=ec43fe79a98dbc864b428afc7220753e25ca3af2&v=4 url: https://github.com/DoctorJohn six_months_experts: - login: YuriiMotov - count: 145 + count: 127 avatarUrl: https://avatars.githubusercontent.com/u/109919500?u=bc48be95c429989224786106b027f3c5e40cc354&v=4 url: https://github.com/YuriiMotov -- login: tiangolo - count: 13 - avatarUrl: https://avatars.githubusercontent.com/u/1326112?u=cb5d06e73a9e1998141b1641aa88e443c6717651&v=4 - url: https://github.com/tiangolo - login: JavierSanchezCastro - count: 9 + count: 10 avatarUrl: https://avatars.githubusercontent.com/u/72013291?u=ae5679e6bd971d9d98cd5e76e8683f83642ba950&v=4 url: https://github.com/JavierSanchezCastro +- login: tiangolo + count: 10 + avatarUrl: https://avatars.githubusercontent.com/u/1326112?u=cb5d06e73a9e1998141b1641aa88e443c6717651&v=4 + url: https://github.com/tiangolo +- login: luzzodev + count: 7 + avatarUrl: https://avatars.githubusercontent.com/u/27291415?u=5607ae1ce75c5f54f09500ca854227f7bfd2033b&v=4 + url: https://github.com/luzzodev - login: Firatasi count: 7 avatarUrl: https://avatars.githubusercontent.com/u/112112161?u=3219914a49a4a604b3626007823db7de049b6d66&v=4 url: https://github.com/Firatasi +- login: Raphasha27 + count: 6 + avatarUrl: https://avatars.githubusercontent.com/u/220842167?u=a9e66fe06965e3830aecb82be4a442874950babe&v=4 + url: https://github.com/Raphasha27 - login: yudin-s - count: 5 + count: 6 avatarUrl: https://avatars.githubusercontent.com/u/781481?u=8c1ab221edbe051eb55310747ebe39574e808118&v=4 url: https://github.com/yudin-s -- login: valentinDruzhinin +- login: svlandeg count: 5 - avatarUrl: https://avatars.githubusercontent.com/u/12831905?u=aae1ebc675c91e8fa582df4fcc4fc4128106344d&v=4 - url: https://github.com/valentinDruzhinin + avatarUrl: https://avatars.githubusercontent.com/u/8796347?u=556c97650c27021911b0b9447ec55e75987b0e8a&v=4 + url: https://github.com/svlandeg +- login: sueun-dev + count: 5 + avatarUrl: https://avatars.githubusercontent.com/u/57546981?u=0b0483bdcc7d521e85c06f28d2fc64e258bd466f&v=4 + url: https://github.com/sueun-dev - login: Toygarmetu count: 5 avatarUrl: https://avatars.githubusercontent.com/u/92878791?u=538530cb6d5554e71f9c28709d794db9a74d23d9&v=4 url: https://github.com/Toygarmetu -- login: luzzodev - count: 5 - avatarUrl: https://avatars.githubusercontent.com/u/27291415?u=5607ae1ce75c5f54f09500ca854227f7bfd2033b&v=4 - url: https://github.com/luzzodev - login: ceb10n count: 5 avatarUrl: https://avatars.githubusercontent.com/u/235213?u=edcce471814a1eba9f0cdaa4cd0de18921a940a6&v=4 @@ -387,18 +439,26 @@ six_months_experts: count: 4 avatarUrl: https://avatars.githubusercontent.com/u/1461970?u=edaa57d1077705244ea5c9244f4783d94ff11f12&v=4 url: https://github.com/RichieB2B -- login: sachinh35 - count: 4 - avatarUrl: https://avatars.githubusercontent.com/u/21972708?u=8560b97b8b41e175f476270b56de8a493b84f302&v=4 - url: https://github.com/sachinh35 -- login: BitWeaverDev +- login: cookesan count: 3 - avatarUrl: https://avatars.githubusercontent.com/u/288751066?v=4 - url: https://github.com/BitWeaverDev + avatarUrl: https://avatars.githubusercontent.com/u/6601329?u=7bfc9b017198a9fa50929ae8ae0a787632424ffd&v=4 + url: https://github.com/cookesan - login: ericgitangu count: 3 avatarUrl: https://avatars.githubusercontent.com/u/11472845?u=9d916cf0f5c80e63cb1d753b8b50dcb8ced3b883&v=4 url: https://github.com/ericgitangu +- login: BitWeaverDev + count: 3 + avatarUrl: https://avatars.githubusercontent.com/u/288751066?u=60ef471e6d3822b99c9a3e7624d510b911004434&v=4 + url: https://github.com/BitWeaverDev +- login: vincere-mori + count: 3 + avatarUrl: https://avatars.githubusercontent.com/u/57835745?u=37d4cd4a763163dd03f29eff4975c2f1fa2a2d72&v=4 + url: https://github.com/vincere-mori +- login: valentinDruzhinin + count: 3 + avatarUrl: https://avatars.githubusercontent.com/u/12831905?u=aae1ebc675c91e8fa582df4fcc4fc4128106344d&v=4 + url: https://github.com/valentinDruzhinin - login: Zawwarsami16 count: 3 avatarUrl: https://avatars.githubusercontent.com/u/105767627?u=5bb2b7a639a9207a5ded536f963a4c7bd6d04d21&v=4 @@ -407,6 +467,26 @@ six_months_experts: count: 3 avatarUrl: https://avatars.githubusercontent.com/u/142030687?u=ab131d5ad4670280a978f489babe71c9bf9c1097&v=4 url: https://github.com/EmmanuelNiyonshuti +- login: thanos07 + count: 2 + avatarUrl: https://avatars.githubusercontent.com/u/68923656?u=dab6d4d9a6800f7d44d8c6df0b9904e17c2ecdb7&v=4 + url: https://github.com/thanos07 +- login: MajorDallas + count: 2 + avatarUrl: https://avatars.githubusercontent.com/u/79329882?u=e611ed986e4a37fd16ab69116a4600d95bfff294&v=4 + url: https://github.com/MajorDallas +- login: Francis1998 + count: 2 + avatarUrl: https://avatars.githubusercontent.com/u/66462431?u=20bdf51356ee7d99a8c8755c09460950d2b84fd0&v=4 + url: https://github.com/Francis1998 +- login: abdurrahman310303 + count: 2 + avatarUrl: https://avatars.githubusercontent.com/u/121820588?u=73c72a59ca082ceb8507bb1e2b559e59bdf2358f&v=4 + url: https://github.com/abdurrahman310303 +- login: Hassanmahmood4 + count: 2 + avatarUrl: https://avatars.githubusercontent.com/u/193066885?u=0e05f82009f99c53b16781d06a7f8d5fea8cc433&v=4 + url: https://github.com/Hassanmahmood4 - login: Kludex count: 2 avatarUrl: https://avatars.githubusercontent.com/u/7353520?u=df8a3f06ba8f55ae1967a3e2d5ed882903a4e330&v=4 @@ -415,18 +495,14 @@ six_months_experts: count: 2 avatarUrl: https://avatars.githubusercontent.com/u/20254686?u=6da9cdad3ecf8a4f3cbc33a518c3998ed0ac685a&v=4 url: https://github.com/mg1986jp -- login: sueun-dev - count: 2 - avatarUrl: https://avatars.githubusercontent.com/u/57546981?u=0b0483bdcc7d521e85c06f28d2fc64e258bd466f&v=4 - url: https://github.com/sueun-dev - login: Bogdusik count: 2 avatarUrl: https://avatars.githubusercontent.com/u/166155258?u=11440b02966a3f5e5eeebc21d67b7bbb7d370487&v=4 url: https://github.com/Bogdusik -- login: cookesan +- login: sachinh35 count: 2 - avatarUrl: https://avatars.githubusercontent.com/u/6601329?u=7bfc9b017198a9fa50929ae8ae0a787632424ffd&v=4 - url: https://github.com/cookesan + avatarUrl: https://avatars.githubusercontent.com/u/21972708?u=8560b97b8b41e175f476270b56de8a493b84f302&v=4 + url: https://github.com/sachinh35 - login: coleifer count: 2 avatarUrl: https://avatars.githubusercontent.com/u/119974?u=b3a546c94ee1105e792e0acad2c4743d800e7975&v=4 @@ -451,83 +527,59 @@ six_months_experts: count: 2 avatarUrl: https://avatars.githubusercontent.com/u/46934916?u=18d7aacc6ce59f054749209645d11cfe77b52f90&v=4 url: https://github.com/gaardhus -- login: y2kbugger - count: 2 - avatarUrl: https://avatars.githubusercontent.com/u/6101677?u=1d50077e29582dc01fcbdff846f04fe7ec73fe2e&v=4 - url: https://github.com/y2kbugger -- login: davidbrochart - count: 2 - avatarUrl: https://avatars.githubusercontent.com/u/4711805?u=d39696d995a9e02ec3613ffb2f62b20b14f92f26&v=4 - url: https://github.com/davidbrochart -- login: CharlieReitzel - count: 2 - avatarUrl: https://avatars.githubusercontent.com/u/20848272?v=4 - url: https://github.com/CharlieReitzel - login: dotmitsu count: 2 avatarUrl: https://avatars.githubusercontent.com/u/42657211?u=3bccc9a2f386a3f24230ec393080f8904fe2a5b2&v=4 url: https://github.com/dotmitsu -- login: dolfinus - count: 2 - avatarUrl: https://avatars.githubusercontent.com/u/4661021?u=ed5ddadcf36d9b943ebe61febe0b96ee34e5425d&v=4 - url: https://github.com/dolfinus -- login: florentx - count: 2 - avatarUrl: https://avatars.githubusercontent.com/u/142113?u=bf10f10080026346b092633c380977b61cee0d9c&v=4 - url: https://github.com/florentx one_year_experts: - login: YuriiMotov - count: 647 + count: 344 avatarUrl: https://avatars.githubusercontent.com/u/109919500?u=bc48be95c429989224786106b027f3c5e40cc354&v=4 url: https://github.com/YuriiMotov -- login: luzzodev - count: 35 - avatarUrl: https://avatars.githubusercontent.com/u/27291415?u=5607ae1ce75c5f54f09500ca854227f7bfd2033b&v=4 - url: https://github.com/luzzodev - login: tiangolo - count: 32 + count: 34 avatarUrl: https://avatars.githubusercontent.com/u/1326112?u=cb5d06e73a9e1998141b1641aa88e443c6717651&v=4 url: https://github.com/tiangolo -- login: valentinDruzhinin +- login: luzzodev count: 31 + avatarUrl: https://avatars.githubusercontent.com/u/27291415?u=5607ae1ce75c5f54f09500ca854227f7bfd2033b&v=4 + url: https://github.com/luzzodev +- login: valentinDruzhinin + count: 19 avatarUrl: https://avatars.githubusercontent.com/u/12831905?u=aae1ebc675c91e8fa582df4fcc4fc4128106344d&v=4 url: https://github.com/valentinDruzhinin - login: JavierSanchezCastro count: 17 avatarUrl: https://avatars.githubusercontent.com/u/72013291?u=ae5679e6bd971d9d98cd5e76e8683f83642ba950&v=4 url: https://github.com/JavierSanchezCastro -- login: sachinh35 - count: 8 - avatarUrl: https://avatars.githubusercontent.com/u/21972708?u=8560b97b8b41e175f476270b56de8a493b84f302&v=4 - url: https://github.com/sachinh35 -- login: Firatasi - count: 7 - avatarUrl: https://avatars.githubusercontent.com/u/112112161?u=3219914a49a4a604b3626007823db7de049b6d66&v=4 - url: https://github.com/Firatasi -- login: DoctorJohn - count: 7 - avatarUrl: https://avatars.githubusercontent.com/u/14076775?u=ec43fe79a98dbc864b428afc7220753e25ca3af2&v=4 - url: https://github.com/DoctorJohn - login: svlandeg - count: 6 + count: 10 avatarUrl: https://avatars.githubusercontent.com/u/8796347?u=556c97650c27021911b0b9447ec55e75987b0e8a&v=4 url: https://github.com/svlandeg - login: RichieB2B - count: 6 + count: 7 avatarUrl: https://avatars.githubusercontent.com/u/1461970?u=edaa57d1077705244ea5c9244f4783d94ff11f12&v=4 url: https://github.com/RichieB2B -- login: raceychan - count: 6 - avatarUrl: https://avatars.githubusercontent.com/u/75417963?u=060c62870ec5a791765e63ac20d8885d11143786&v=4 - url: https://github.com/raceychan -- login: yinziyan1206 +- login: Firatasi + count: 7 + avatarUrl: https://avatars.githubusercontent.com/u/112112161?u=3219914a49a4a604b3626007823db7de049b6d66&v=4 + url: https://github.com/Firatasi +- login: Raphasha27 count: 6 - avatarUrl: https://avatars.githubusercontent.com/u/37829370?u=da44ca53aefd5c23f346fab8e9fd2e108294c179&v=4 - url: https://github.com/yinziyan1206 + avatarUrl: https://avatars.githubusercontent.com/u/220842167?u=a9e66fe06965e3830aecb82be4a442874950babe&v=4 + url: https://github.com/Raphasha27 - login: yudin-s - count: 5 + count: 6 avatarUrl: https://avatars.githubusercontent.com/u/781481?u=8c1ab221edbe051eb55310747ebe39574e808118&v=4 url: https://github.com/yudin-s +- login: sueun-dev + count: 5 + avatarUrl: https://avatars.githubusercontent.com/u/57546981?u=0b0483bdcc7d521e85c06f28d2fc64e258bd466f&v=4 + url: https://github.com/sueun-dev +- login: sachinh35 + count: 5 + avatarUrl: https://avatars.githubusercontent.com/u/21972708?u=8560b97b8b41e175f476270b56de8a493b84f302&v=4 + url: https://github.com/sachinh35 - login: Toygarmetu count: 5 avatarUrl: https://avatars.githubusercontent.com/u/92878791?u=538530cb6d5554e71f9c28709d794db9a74d23d9&v=4 @@ -536,6 +588,10 @@ one_year_experts: count: 5 avatarUrl: https://avatars.githubusercontent.com/u/235213?u=edcce471814a1eba9f0cdaa4cd0de18921a940a6&v=4 url: https://github.com/ceb10n +- login: yinziyan1206 + count: 5 + avatarUrl: https://avatars.githubusercontent.com/u/37829370?u=da44ca53aefd5c23f346fab8e9fd2e108294c179&v=4 + url: https://github.com/yinziyan1206 - login: JunjieAraoXiong count: 5 avatarUrl: https://avatars.githubusercontent.com/u/167785867?u=b69afe090c8bf5fd73f2d23fc3a887b28f68f192&v=4 @@ -560,18 +616,26 @@ one_year_experts: count: 4 avatarUrl: https://avatars.githubusercontent.com/u/157279130?u=16d6466476cf7dbc55a4cd575b6ea920ebdd81e1&v=4 url: https://github.com/isgin01 +- login: cookesan + count: 3 + avatarUrl: https://avatars.githubusercontent.com/u/6601329?u=7bfc9b017198a9fa50929ae8ae0a787632424ffd&v=4 + url: https://github.com/cookesan +- login: ericgitangu + count: 3 + avatarUrl: https://avatars.githubusercontent.com/u/11472845?u=9d916cf0f5c80e63cb1d753b8b50dcb8ced3b883&v=4 + url: https://github.com/ericgitangu - login: BitWeaverDev count: 3 - avatarUrl: https://avatars.githubusercontent.com/u/288751066?v=4 + avatarUrl: https://avatars.githubusercontent.com/u/288751066?u=60ef471e6d3822b99c9a3e7624d510b911004434&v=4 url: https://github.com/BitWeaverDev +- login: vincere-mori + count: 3 + avatarUrl: https://avatars.githubusercontent.com/u/57835745?u=37d4cd4a763163dd03f29eff4975c2f1fa2a2d72&v=4 + url: https://github.com/vincere-mori - login: Kludex count: 3 avatarUrl: https://avatars.githubusercontent.com/u/7353520?u=df8a3f06ba8f55ae1967a3e2d5ed882903a4e330&v=4 url: https://github.com/Kludex -- login: ericgitangu - count: 3 - avatarUrl: https://avatars.githubusercontent.com/u/11472845?u=9d916cf0f5c80e63cb1d753b8b50dcb8ced3b883&v=4 - url: https://github.com/ericgitangu - login: Zawwarsami16 count: 3 avatarUrl: https://avatars.githubusercontent.com/u/105767627?u=5bb2b7a639a9207a5ded536f963a4c7bd6d04d21&v=4 @@ -584,10 +648,6 @@ one_year_experts: count: 3 avatarUrl: https://avatars.githubusercontent.com/u/4661021?u=ed5ddadcf36d9b943ebe61febe0b96ee34e5425d&v=4 url: https://github.com/dolfinus -- login: jymchng - count: 3 - avatarUrl: https://avatars.githubusercontent.com/u/27895426?u=fb88c47775147d62a395fdb895d1af4148c7b566&v=4 - url: https://github.com/jymchng - login: simone-trubian count: 3 avatarUrl: https://avatars.githubusercontent.com/u/5606840?u=65703af3c605feca61ce49e4009bb4e26495b425&v=4 @@ -604,30 +664,42 @@ one_year_experts: count: 3 avatarUrl: https://avatars.githubusercontent.com/u/210023470?u=c25d66addf36a747bd9fab773c4a6e7b238f45d4&v=4 url: https://github.com/Jelle-tenB +- login: thanos07 + count: 2 + avatarUrl: https://avatars.githubusercontent.com/u/68923656?u=dab6d4d9a6800f7d44d8c6df0b9904e17c2ecdb7&v=4 + url: https://github.com/thanos07 +- login: MajorDallas + count: 2 + avatarUrl: https://avatars.githubusercontent.com/u/79329882?u=e611ed986e4a37fd16ab69116a4600d95bfff294&v=4 + url: https://github.com/MajorDallas +- login: Francis1998 + count: 2 + avatarUrl: https://avatars.githubusercontent.com/u/66462431?u=20bdf51356ee7d99a8c8755c09460950d2b84fd0&v=4 + url: https://github.com/Francis1998 +- login: Garrett-R + count: 2 + avatarUrl: https://avatars.githubusercontent.com/u/6614695?u=c128fd775002882f6e391bda5a89d1bdc5bdf45f&v=4 + url: https://github.com/Garrett-R +- login: abdurrahman310303 + count: 2 + avatarUrl: https://avatars.githubusercontent.com/u/121820588?u=73c72a59ca082ceb8507bb1e2b559e59bdf2358f&v=4 + url: https://github.com/abdurrahman310303 +- login: Hassanmahmood4 + count: 2 + avatarUrl: https://avatars.githubusercontent.com/u/193066885?u=0e05f82009f99c53b16781d06a7f8d5fea8cc433&v=4 + url: https://github.com/Hassanmahmood4 - login: mg1986jp count: 2 avatarUrl: https://avatars.githubusercontent.com/u/20254686?u=6da9cdad3ecf8a4f3cbc33a518c3998ed0ac685a&v=4 url: https://github.com/mg1986jp -- login: sueun-dev - count: 2 - avatarUrl: https://avatars.githubusercontent.com/u/57546981?u=0b0483bdcc7d521e85c06f28d2fc64e258bd466f&v=4 - url: https://github.com/sueun-dev - login: Bogdusik count: 2 avatarUrl: https://avatars.githubusercontent.com/u/166155258?u=11440b02966a3f5e5eeebc21d67b7bbb7d370487&v=4 url: https://github.com/Bogdusik -- login: cookesan - count: 2 - avatarUrl: https://avatars.githubusercontent.com/u/6601329?u=7bfc9b017198a9fa50929ae8ae0a787632424ffd&v=4 - url: https://github.com/cookesan - login: coleifer count: 2 avatarUrl: https://avatars.githubusercontent.com/u/119974?u=b3a546c94ee1105e792e0acad2c4743d800e7975&v=4 url: https://github.com/coleifer -- login: henrymcl - count: 2 - avatarUrl: https://avatars.githubusercontent.com/u/26480299?v=4 - url: https://github.com/henrymcl - login: Bahtya count: 2 avatarUrl: https://avatars.githubusercontent.com/u/34988899?u=b8e3c0cf26f4bd1faea265d2f5f66f564af63463&v=4 @@ -644,6 +716,10 @@ one_year_experts: count: 2 avatarUrl: https://avatars.githubusercontent.com/u/103544118?u=690f3f76d1dc4d0929de5020679d5604f860acbc&v=4 url: https://github.com/christiansousadev +- login: DoctorJohn + count: 2 + avatarUrl: https://avatars.githubusercontent.com/u/14076775?u=ec43fe79a98dbc864b428afc7220753e25ca3af2&v=4 + url: https://github.com/DoctorJohn - login: gaardhus count: 2 avatarUrl: https://avatars.githubusercontent.com/u/46934916?u=18d7aacc6ce59f054749209645d11cfe77b52f90&v=4 @@ -652,22 +728,10 @@ one_year_experts: count: 2 avatarUrl: https://avatars.githubusercontent.com/u/6101677?u=1d50077e29582dc01fcbdff846f04fe7ec73fe2e&v=4 url: https://github.com/y2kbugger -- login: Garrett-R - count: 2 - avatarUrl: https://avatars.githubusercontent.com/u/6614695?u=c128fd775002882f6e391bda5a89d1bdc5bdf45f&v=4 - url: https://github.com/Garrett-R -- login: TaigoFr - count: 2 - avatarUrl: https://avatars.githubusercontent.com/u/17792131?u=372b27056ec82f1ae03d8b3f37ef55b04a7cfdd1&v=4 - url: https://github.com/TaigoFr - login: stan-dot count: 2 avatarUrl: https://avatars.githubusercontent.com/u/56644812?u=a7dd773084f1c17c5f05019cc25a984e24873691&v=4 url: https://github.com/stan-dot -- login: Damon0603 - count: 2 - avatarUrl: https://avatars.githubusercontent.com/u/110039208?u=f24bf5c30317bc4959118d1b919587c473a865b6&v=4 - url: https://github.com/Damon0603 - login: huynguyengl99 count: 2 avatarUrl: https://avatars.githubusercontent.com/u/49433085?u=7b626115686c5d97a2a32a03119f5300e425cc9f&v=4 @@ -688,10 +752,6 @@ one_year_experts: count: 2 avatarUrl: https://avatars.githubusercontent.com/u/42657211?u=3bccc9a2f386a3f24230ec393080f8904fe2a5b2&v=4 url: https://github.com/dotmitsu -- login: Brikas - count: 2 - avatarUrl: https://avatars.githubusercontent.com/u/80290187?u=2b72e497ca4444ecec1f9dc2d1b8d5437a27b83f&v=4 - url: https://github.com/Brikas - login: usiqwerty count: 2 avatarUrl: https://avatars.githubusercontent.com/u/37992525?u=0c6e91d7b3887aa558755f4225ce74a003cbe852&v=4 @@ -712,7 +772,3 @@ one_year_experts: count: 2 avatarUrl: https://avatars.githubusercontent.com/u/236391583?u=7f51ff690e3a5711f845a115903c39e21c8af938&v=4 url: https://github.com/bughuntr7 -- login: purepani - count: 2 - avatarUrl: https://avatars.githubusercontent.com/u/7587353?v=4 - url: https://github.com/purepani From 66a90f6ee9c0cf58ec61b14f8925344d6f16eae5 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Wed, 1 Jul 2026 15:54:16 +0000 Subject: [PATCH 385/462] =?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 eb72ce6f7..f33f13c36 100644 --- a/docs/en/docs/release-notes.md +++ b/docs/en/docs/release-notes.md @@ -34,6 +34,7 @@ hide: ### Internal +* 👥 Update FastAPI People - Experts. PR [#15909](https://github.com/fastapi/fastapi/pull/15909) by [@tiangolo](https://github.com/tiangolo). * 👥 Update FastAPI GitHub topic repositories. PR [#15906](https://github.com/fastapi/fastapi/pull/15906) by [@tiangolo](https://github.com/tiangolo). * 👥 Update FastAPI People - Contributors and Translators. PR [#15878](https://github.com/fastapi/fastapi/pull/15878) by [@tiangolo](https://github.com/tiangolo). * 👷 Remove not needed `allow-unsafe-pr-checkout: true`. PR [#15876](https://github.com/fastapi/fastapi/pull/15876) by [@YuriiMotov](https://github.com/YuriiMotov). From 319be508ce7db9ee5f52c3b9baa68c6cc1037c10 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebasti=C3=A1n=20Ram=C3=ADrez?= Date: Wed, 1 Jul 2026 18:12:33 +0200 Subject: [PATCH 386/462] =?UTF-8?q?=E2=9C=A8=20Support=20dependencies=20in?= =?UTF-8?q?=20`app.frontend()`,=20e.g.=20for=20automatic=20cookie=20authen?= =?UTF-8?q?tication=20for=20the=20frontend=20(#15908)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docs/en/docs/tutorial/frontend.md | 6 + fastapi/routing.py | 279 ++++++++++++++++++------ tests/test_frontend.py | 345 +++++++++++++++++++++++++++++- 3 files changed, 563 insertions(+), 67 deletions(-) diff --git a/docs/en/docs/tutorial/frontend.md b/docs/en/docs/tutorial/frontend.md index 4cbc21fa1..433cea275 100644 --- a/docs/en/docs/tutorial/frontend.md +++ b/docs/en/docs/tutorial/frontend.md @@ -126,6 +126,12 @@ In this example, frontend paths are served under `/app`. Any regular *path operations* in the app will still take precedence, including in other routers. +## Dependencies and Middleware { #dependencies-and-middleware } + +Frontend responses run inside the normal **FastAPI** application, so HTTP middleware applies to them. + +Dependencies from the app, from an `APIRouter`, and from `include_router()` also apply to frontend responses. This can be useful for protecting a frontend with cookie authentication or similar. + ## Static Build Output Only { #static-build-output-only } `app.frontend()` serves files already generated by your frontend build. diff --git a/fastapi/routing.py b/fastapi/routing.py index e41ef6a59..c442b122b 100644 --- a/fastapi/routing.py +++ b/fastapi/routing.py @@ -797,17 +797,14 @@ class APIWebSocketRoute(routing.WebSocketRoute): self.name = get_name(endpoint) if name is None else name self.dependencies = list(dependencies or []) self.path_regex, self.path_format, self.param_convertors = compile_path(path) - self.dependant = get_dependant( - path=self.path_format, call=self.endpoint, scope="function" - ) - for depends in self.dependencies[::-1]: - self.dependant.dependencies.insert( - 0, - get_parameterless_sub_dependant(depends=depends, path=self.path_format), - ) - self._flat_dependant = get_flat_dependant(self.dependant) - self._embed_body_fields = _should_embed_body_fields( - self._flat_dependant.body_params + ( + self.dependant, + self._flat_dependant, + self._embed_body_fields, + ) = _build_dependant_with_parameterless_dependencies( + path=self.path_format, + call=self.endpoint, + dependencies=self.dependencies, ) self.app = websocket_session( get_websocket_app( @@ -827,6 +824,7 @@ class APIWebSocketRoute(routing.WebSocketRoute): _FASTAPI_SCOPE_KEY = "fastapi" _FASTAPI_EFFECTIVE_ROUTE_CONTEXT_KEY = "effective_route_context" _FASTAPI_FRONTEND_PATH_KEY = "frontend_path" +_FASTAPI_FRONTEND_SPECIFICITY_KEY = "frontend_specificity" _FASTAPI_INCLUDED_ROUTER_KEY = "included_router" _effective_route_context_var: ContextVar[Any | None] = ContextVar( "fastapi_effective_route_context", default=None @@ -834,6 +832,27 @@ _effective_route_context_var: ContextVar[Any | None] = ContextVar( _SCOPE_MISSING = object() +def _frontend_dependency_endpoint() -> None: + pass # pragma: no cover + + +def _build_dependant_with_parameterless_dependencies( + *, + path: str, + call: Callable[..., Any], + dependencies: Sequence[params.Depends], +) -> tuple[Dependant, Dependant, bool]: + dependant = get_dependant(path=path, call=call, scope="function") + for depends in dependencies[::-1]: + dependant.dependencies.insert( + 0, + get_parameterless_sub_dependant(depends=depends, path=path), + ) + flat_dependant = get_flat_dependant(dependant) + embed_body_fields = _should_embed_body_fields(flat_dependant.body_params) + return dependant, flat_dependant, embed_body_fields + + class _RouteWithPath(Protocol): path: str @@ -861,6 +880,15 @@ def _get_scope_included_router(scope: Scope) -> Any | None: return scope.get(_FASTAPI_SCOPE_KEY, {}).get(_FASTAPI_INCLUDED_ROUTER_KEY) +def _frontend_scope_specificity(scope: Scope) -> int | None: + specificity = scope.get(_FASTAPI_SCOPE_KEY, {}).get( + _FASTAPI_FRONTEND_SPECIFICITY_KEY + ) + if isinstance(specificity, int): + return specificity + return None + + def _restore_fastapi_scope_key(scope: Scope, key: str, previous: Any) -> None: fastapi_scope = scope.get(_FASTAPI_SCOPE_KEY) if not isinstance(fastapi_scope, dict): @@ -1053,17 +1081,14 @@ def _populate_api_route_state( route.response_fields = {} assert callable(endpoint), "An endpoint must be a callable" - route.dependant = get_dependant( - path=route.path_format, call=route.endpoint, scope="function" - ) - for depends in route.dependencies[::-1]: - route.dependant.dependencies.insert( - 0, - get_parameterless_sub_dependant(depends=depends, path=route.path_format), - ) - route._flat_dependant = get_flat_dependant(route.dependant) - route._embed_body_fields = _should_embed_body_fields( - route._flat_dependant.body_params + ( + route.dependant, + route._flat_dependant, + route._embed_body_fields, + ) = _build_dependant_with_parameterless_dependencies( + path=route.path_format, + call=route.endpoint, + dependencies=route.dependencies, ) route.body_field = get_body_field( flat_dependant=route._flat_dependant, @@ -1334,6 +1359,7 @@ class _RouterIncludeContext: class _EffectiveRouteContext: original_route: BaseRoute starlette_route: BaseRoute | None = None + frontend_prefix: str = "" path: str = "" endpoint: Callable[..., Any] | None = None stream_item_type: Any | None = None @@ -1436,7 +1462,34 @@ class _EffectiveRouteContext: ) return context + @classmethod + def from_frontend_route_group( + cls, + *, + original_route: "_FrontendRouteGroup", + include_context: _RouterIncludeContext, + ) -> "_EffectiveRouteContext": + dependencies = [*include_context.dependencies, *original_route.dependencies] + context = cls( + original_route=original_route, + frontend_prefix=include_context.prefix, + dependencies=dependencies, + dependency_overrides_provider=include_context.dependency_overrides_provider, + ) + ( + context.dependant, + context._flat_dependant, + context._embed_body_fields, + ) = _build_dependant_with_parameterless_dependencies( + path="", + call=_frontend_dependency_endpoint, + dependencies=dependencies, + ) + return context + def matches(self, scope: Scope) -> tuple[Match, Scope]: + if isinstance(self.original_route, _FrontendRouteGroup): + return self.original_route.matches_with_prefix(scope, self.frontend_prefix) if not isinstance(self.original_route, APIRoute): assert self.starlette_route is not None return self.starlette_route.matches(scope) @@ -1579,9 +1632,9 @@ class _IncludedRouter(BaseRoute): include_context=self.include_context, ) if isinstance(route, _FrontendRouteGroup): - return _EffectiveRouteContext( + return _EffectiveRouteContext.from_frontend_route_group( original_route=route, - starlette_route=route.with_prefix(self.include_context.prefix), + include_context=self.include_context, ) if isinstance(route, routing.Route): starlette_route: BaseRoute = routing.Route( @@ -1970,28 +2023,31 @@ class _FrontendRoute(BaseRoute): directory=directory, fallback=fallback, check_dir=check_dir ) - def with_path(self, path: str) -> "_FrontendRoute": - route = copy.copy(self) - route.path = _normalize_frontend_path(path) - return route - def matches(self, scope: Scope) -> tuple[Match, Scope]: + return self.matches_with_path(scope, self.path) + + def matches_with_path(self, scope: Scope, path: str) -> tuple[Match, Scope]: if scope["type"] != "http": return Match.NONE, {} - frontend_path = self._get_frontend_path(get_route_path(scope)) + frontend_path = self._get_frontend_path(path, get_route_path(scope)) if frontend_path is None: return Match.NONE, {} - child_scope = {_FASTAPI_SCOPE_KEY: {_FASTAPI_FRONTEND_PATH_KEY: frontend_path}} + child_scope = { + _FASTAPI_SCOPE_KEY: { + _FASTAPI_FRONTEND_PATH_KEY: frontend_path, + _FASTAPI_FRONTEND_SPECIFICITY_KEY: _frontend_path_specificity(path), + } + } if scope["method"] not in self.methods: return Match.PARTIAL, child_scope return Match.FULL, child_scope - def _get_frontend_path(self, route_path: str) -> str | None: - if self.path == "/": + def _get_frontend_path(self, path: str, route_path: str) -> str | None: + if path == "/": return route_path.lstrip("/") - if route_path == self.path: + if route_path == path: return "" - prefix = self.path + "/" + prefix = path + "/" if route_path.startswith(prefix): return route_path[len(prefix) :] return None @@ -2004,8 +2060,24 @@ class _FrontendRoute(BaseRoute): class _FrontendRouteGroup(BaseRoute): - def __init__(self) -> None: + def __init__( + self, + *, + dependencies: Sequence[params.Depends] | None = None, + dependency_overrides_provider: Any | None = None, + ) -> None: self.routes: list[_FrontendRoute] = [] + self.dependencies = list(dependencies or []) + self.dependency_overrides_provider = dependency_overrides_provider + ( + self.dependant, + self._flat_dependant, + self._embed_body_fields, + ) = _build_dependant_with_parameterless_dependencies( + path="", + call=_frontend_dependency_endpoint, + dependencies=self.dependencies, + ) def add_frontend_route( self, @@ -2024,51 +2096,116 @@ class _FrontendRouteGroup(BaseRoute): ) ) - def with_prefix(self, prefix: str) -> "_FrontendRouteGroup": - route_group = copy.copy(self) - route_group.routes = [ - route.with_path(_join_frontend_paths(prefix, route.path)) - for route in self.routes - ] - return route_group - def matches(self, scope: Scope) -> tuple[Match, Scope]: - match, child_scope, _ = self._match(scope) + match, child_scope, _ = self._match(scope, prefix="") return match, child_scope - def _match(self, scope: Scope) -> tuple[Match, Scope, _FrontendRoute | None]: - full: tuple[Scope, _FrontendRoute] | None = None - partial: tuple[Scope, _FrontendRoute] | None = None + def matches_with_prefix(self, scope: Scope, prefix: str) -> tuple[Match, Scope]: + match, child_scope, _ = self._match(scope, prefix=prefix) + return match, child_scope + + def _match( + self, scope: Scope, *, prefix: str + ) -> tuple[Match, Scope, _FrontendRoute | None]: + full: tuple[Scope, _FrontendRoute, int] | None = None + partial: tuple[Scope, _FrontendRoute, int] | None = None for route in self.routes: - match, child_scope = route.matches(scope) + path = _join_frontend_paths(prefix, route.path) + match, child_scope = route.matches_with_path(scope, path) + specificity = _frontend_path_specificity(path) if match == Match.FULL: - if full is None or _frontend_path_specificity( - route.path - ) > _frontend_path_specificity(full[1].path): - full = (child_scope, route) + if full is None or specificity > full[2]: + full = (child_scope, route, specificity) elif match == Match.PARTIAL: - if partial is None or _frontend_path_specificity( - route.path - ) > _frontend_path_specificity(partial[1].path): - partial = (child_scope, route) + if partial is None or specificity > partial[2]: + partial = (child_scope, route, specificity) if full is not None: - child_scope, route = full + child_scope, route, _ = full return Match.FULL, child_scope, route if partial is not None: - child_scope, route = partial + child_scope, route, _ = partial return Match.PARTIAL, child_scope, route return Match.NONE, {}, None async def handle(self, scope: Scope, receive: Receive, send: Send) -> None: - match, child_scope, route = self._match(scope) + effective_context = _get_scope_effective_route_context(scope) + if ( + isinstance(effective_context, _EffectiveRouteContext) + and effective_context.original_route is self + ): + prefix = effective_context.frontend_prefix + dependant = effective_context.dependant + dependency_overrides_provider = ( + effective_context.dependency_overrides_provider + ) + embed_body_fields = effective_context._embed_body_fields + else: + prefix = "" + dependant = self.dependant + dependency_overrides_provider = self.dependency_overrides_provider + embed_body_fields = self._embed_body_fields + match, child_scope, route = self._match(scope, prefix=prefix) if match == Match.NONE or route is None: raise HTTPException(status_code=404) _update_scope(scope, child_scope) + if match == Match.FULL and dependant and dependant.dependencies: + async with self._solve_dependencies( + scope, + receive, + send, + dependant=dependant, + dependency_overrides_provider=dependency_overrides_provider, + embed_body_fields=embed_body_fields, + ): + await route.handle(scope, receive, send) + return await route.handle(scope, receive, send) def url_path_for(self, name: str, /, **path_params: Any) -> URLPath: raise NoMatchFound(name, path_params) + # TODO: probably move this out of the Route / Route Group, same in APIRoute + # this should probably be top level FastAPI logic, not part of APIRoute and + # duplicated here + @asynccontextmanager + async def _solve_dependencies( + self, + scope: Scope, + receive: Receive, + send: Send, + *, + dependant: Dependant, + dependency_overrides_provider: Any | None, + embed_body_fields: bool, + ) -> AsyncIterator[None]: + request = Request(scope, receive, send) + previous_inner_astack = scope.get("fastapi_inner_astack", _SCOPE_MISSING) + previous_function_astack = scope.get("fastapi_function_astack", _SCOPE_MISSING) + try: + async with AsyncExitStack() as request_stack: + scope["fastapi_inner_astack"] = request_stack + async with AsyncExitStack() as function_stack: + scope["fastapi_function_astack"] = function_stack + solved_result = await solve_dependencies( + request=request, + dependant=dependant, + dependency_overrides_provider=dependency_overrides_provider, + async_exit_stack=request_stack, + embed_body_fields=embed_body_fields, + ) + if solved_result.errors: + raise RequestValidationError(solved_result.errors) + yield + finally: + if previous_inner_astack is _SCOPE_MISSING: + scope.pop("fastapi_inner_astack", None) + else: + scope["fastapi_inner_astack"] = previous_inner_astack + if previous_function_astack is _SCOPE_MISSING: + scope.pop("fastapi_function_astack", None) + else: + scope["fastapi_function_astack"] = previous_function_astack + class APIRouter(routing.Router): """ @@ -2515,7 +2652,10 @@ class APIRouter(routing.Router): """ normalized_path = _normalize_frontend_path(path) if self._frontend_routes is None: - self._frontend_routes = _FrontendRouteGroup() + self._frontend_routes = _FrontendRouteGroup( + dependencies=self.dependencies, + dependency_overrides_provider=self.dependency_overrides_provider, + ) self._low_priority_routes.append(self._frontend_routes) self._frontend_routes.add_frontend_route( _join_frontend_paths(self.prefix, normalized_path), @@ -2650,10 +2790,14 @@ class APIRouter(routing.Router): match, child_scope = candidate.matches(scope) route = candidate if match == Match.FULL: - if full is None: + if full is None or self._frontend_match_is_more_specific( + child_scope, full[0] + ): full = (child_scope, route, route_context) elif match == Match.PARTIAL: - if partial is None: + if partial is None or self._frontend_match_is_more_specific( + child_scope, partial[0] + ): partial = (child_scope, route, route_context) if full is not None: child_scope, route, route_context = full @@ -2663,6 +2807,15 @@ class APIRouter(routing.Router): return Match.PARTIAL, child_scope, route, route_context return Match.NONE, {}, None, None + def _frontend_match_is_more_specific( + self, child_scope: Scope, previous_child_scope: Scope + ) -> bool: + specificity = _frontend_scope_specificity(child_scope) + previous_specificity = _frontend_scope_specificity(previous_child_scope) + if specificity is None or previous_specificity is None: + return False + return specificity > previous_specificity + def route( self, path: str, diff --git a/tests/test_frontend.py b/tests/test_frontend.py index 81cffc228..b8dd62fb8 100644 --- a/tests/test_frontend.py +++ b/tests/test_frontend.py @@ -1,12 +1,13 @@ import errno import os import runpy +from contextlib import AsyncExitStack from pathlib import Path from typing import Literal import anyio import pytest -from fastapi import APIRouter, FastAPI, HTTPException, Request, WebSocket +from fastapi import APIRouter, Depends, FastAPI, HTTPException, Request, WebSocket from fastapi.testclient import TestClient from starlette.exceptions import HTTPException as StarletteHTTPException from starlette.responses import PlainTextResponse, Response @@ -18,11 +19,18 @@ def write_file(path: Path, content: str) -> None: path.write_text(content) +def record_dependency(calls: list[str], name: str): + def dependency() -> None: + calls.append(name) + + return dependency + + def test_frontend_exact_prefix_path_serves_index(tmp_path: Path): dist = tmp_path / "dist" write_file(dist / "index.html", "app") app = FastAPI() - app.frontend("/app", directory=dist) + app.frontend("/", directory=dist) response = TestClient(app).get("/app") @@ -109,7 +117,7 @@ def test_frontend_route_group_helpers(tmp_path: Path): dist = tmp_path / "dist" write_file(dist / "index.html", "app") app = FastAPI() - app.frontend("/", directory=dist) + app.frontend("/app", directory=dist) route_group = app.router._frontend_routes assert route_group is not None @@ -117,9 +125,22 @@ def test_frontend_route_group_helpers(tmp_path: Path): assert match == Match.NONE assert child_scope == {} + match, child_scope = route_group.matches_with_prefix( + {"type": "http", "path": "/prefix/app", "method": "GET"}, + "/prefix", + ) + assert match == Match.FULL + assert child_scope["fastapi"]["frontend_path"] == "" + + match, child_scope = route_group.routes[0].matches( + {"type": "http", "path": "/app", "method": "GET"} + ) + assert match == Match.FULL + assert child_scope["fastapi"]["frontend_path"] == "" + with pytest.raises(StarletteHTTPException) as exc_info: anyio.run( - route_group.with_prefix("/app").handle, + route_group.handle, {"type": "http", "path": "/missing", "method": "GET"}, None, None, @@ -246,6 +267,322 @@ def test_basic_file_serving(tmp_path: Path): assert "last-modified" in response.headers +def test_app_frontend_dependencies_protect_root_asset_and_fallback(tmp_path: Path): + calls: list[str] = [] + + def require_cookie(request: Request) -> None: + calls.append(request.url.path) + if request.cookies.get("session") != "ok": + raise HTTPException(status_code=401) + + dist = tmp_path / "dist" + write_file(dist / "index.html", "app") + write_file(dist / "assets" / "app.js", "console.log('ok')") + app = FastAPI(dependencies=[Depends(require_cookie)]) + app.frontend("/", directory=dist, fallback="index.html") + client = TestClient(app) + + response = client.get("/") + assert response.status_code == 401 + + response = client.get("/", headers={"cookie": "session=ok"}) + assert response.status_code == 200 + assert response.text == "app" + + response = client.get("/assets/app.js", headers={"cookie": "session=ok"}) + assert response.status_code == 200 + assert response.text == "console.log('ok')" + + response = client.get( + "/dashboard", + headers={"accept": "text/html", "cookie": "session=ok"}, + ) + assert response.status_code == 200 + assert response.text == "app" + assert calls == ["/", "/", "/assets/app.js", "/dashboard"] + + +def test_apirouter_frontend_dependencies_protect_prefixed_frontend(tmp_path: Path): + def require_cookie(request: Request) -> None: + if request.cookies.get("session") != "ok": + raise HTTPException(status_code=401) + + dist = tmp_path / "dist" + write_file(dist / "index.html", "app") + write_file(dist / "assets" / "app.js", "console.log('ok')") + router = APIRouter(dependencies=[Depends(require_cookie)]) + router.frontend("/", directory=dist, fallback="index.html") + app = FastAPI() + app.include_router(router, prefix="/app") + client = TestClient(app) + + response = client.get("/app/") + assert response.status_code == 401 + + response = client.get("/app/", headers={"cookie": "session=ok"}) + assert response.status_code == 200 + assert response.text == "app" + + response = client.get("/app/assets/app.js", headers={"cookie": "session=ok"}) + assert response.status_code == 200 + assert response.text == "console.log('ok')" + + response = client.get( + "/app/dashboard", + headers={"accept": "text/html", "cookie": "session=ok"}, + ) + assert response.status_code == 200 + assert response.text == "app" + + +def test_included_frontend_does_not_block_url_path_for(tmp_path: Path): + dist = tmp_path / "dist" + write_file(dist / "index.html", "app") + frontend_router = APIRouter() + frontend_router.frontend("/", directory=dist) + api_router = APIRouter() + + @api_router.get("/api", name="read_api") + def read_api(): + return {"ok": True} + + app = FastAPI() + app.include_router(frontend_router, prefix="/app") + app.include_router(api_router) + included_frontend = next( + route + for route in app.router.routes + if hasattr(route, "effective_low_priority_routes") + ) + + with pytest.raises(NoMatchFound): + included_frontend.url_path_for("missing") + assert app.url_path_for("read_api") == "/api" + response = TestClient(app).get("/api") + assert response.status_code == 200 + assert response.json() == {"ok": True} + + +def test_include_router_frontend_dependencies_apply_in_nested_order(tmp_path: Path): + calls: list[str] = [] + + dist = tmp_path / "dist" + write_file(dist / "index.html", "app") + child = APIRouter(dependencies=[Depends(record_dependency(calls, "child"))]) + child.frontend("/ui", directory=dist) + parent = APIRouter(dependencies=[Depends(record_dependency(calls, "parent"))]) + parent.include_router( + child, + prefix="/child", + dependencies=[Depends(record_dependency(calls, "parent-include"))], + ) + app = FastAPI(dependencies=[Depends(record_dependency(calls, "app"))]) + app.include_router( + parent, + prefix="/parent", + dependencies=[Depends(record_dependency(calls, "app-include"))], + ) + + response = TestClient(app).get("/parent/child/ui/") + + assert response.status_code == 200 + assert response.text == "app" + assert calls == ["app", "app-include", "parent", "parent-include", "child"] + + +def test_frontend_dependency_overrides_apply(tmp_path: Path): + calls: list[str] = [] + + def require_cookie() -> None: + raise HTTPException(status_code=401) # pragma: no cover + + def allow_cookie() -> None: + calls.append("override") + + dist = tmp_path / "dist" + write_file(dist / "index.html", "app") + app = FastAPI(dependencies=[Depends(require_cookie)]) + app.dependency_overrides[require_cookie] = allow_cookie + app.frontend("/", directory=dist) + + response = TestClient(app).get("/") + + assert response.status_code == 200 + assert response.text == "app" + assert calls == ["override"] + + +def test_frontend_dependencies_do_not_run_when_api_route_wins(tmp_path: Path): + calls: list[str] = [] + + def frontend_dependency() -> None: + calls.append("frontend") # pragma: no cover + + dist = tmp_path / "dist" + write_file(dist / "api", "frontend") + router = APIRouter(dependencies=[Depends(frontend_dependency)]) + router.frontend("/", directory=dist) + app = FastAPI() + + @app.get("/api") + def read_api(): + return {"source": "api"} + + app.include_router(router) + + response = TestClient(app).get("/api") + + assert response.status_code == 200 + assert response.json() == {"source": "api"} + assert calls == [] + + +def test_only_selected_frontend_mount_dependencies_run(tmp_path: Path): + calls: list[str] = [] + + site = tmp_path / "site" + admin = tmp_path / "admin" + write_file(site / "index.html", "site") + write_file(admin / "index.html", "admin") + site_router = APIRouter() + site_router.frontend("/", directory=site) + admin_router = APIRouter() + admin_router.frontend("/", directory=admin) + app = FastAPI() + app.include_router( + site_router, dependencies=[Depends(record_dependency(calls, "site"))] + ) + app.include_router( + admin_router, + prefix="/admin", + dependencies=[Depends(record_dependency(calls, "admin"))], + ) + + response = TestClient(app).get("/admin/") + + assert response.status_code == 200 + assert response.text == "admin" + assert calls == ["admin"] + + +def test_app_middleware_still_runs_for_frontend_dependencies(tmp_path: Path): + calls: list[str] = [] + + def frontend_dependency() -> None: + calls.append("dependency") + + dist = tmp_path / "dist" + write_file(dist / "index.html", "app") + app = FastAPI(dependencies=[Depends(frontend_dependency)]) + + @app.middleware("http") + async def record_middleware(request: Request, call_next): + calls.append("middleware-before") + response = await call_next(request) + calls.append("middleware-after") + return response + + app.frontend("/", directory=dist) + + response = TestClient(app).get("/") + + assert response.status_code == 200 + assert response.text == "app" + assert calls == ["middleware-before", "dependency", "middleware-after"] + + +def test_frontend_dependency_validation_errors_return_422(tmp_path: Path): + def require_token(token: str) -> None: + pass # pragma: no cover + + dist = tmp_path / "dist" + write_file(dist / "index.html", "app") + app = FastAPI(dependencies=[Depends(require_token)]) + app.frontend("/", directory=dist) + + response = TestClient(app).get("/") + + assert response.status_code == 422 + assert response.json() == { + "detail": [ + { + "type": "missing", + "loc": ["query", "token"], + "msg": "Field required", + "input": None, + } + ] + } + + +@pytest.mark.anyio +async def test_frontend_dependency_restores_existing_dependency_stacks( + tmp_path: Path, +): + def frontend_dependency() -> None: + pass + + dist = tmp_path / "dist" + write_file(dist / "index.html", "app") + app = FastAPI(dependencies=[Depends(frontend_dependency)]) + app.frontend("/", directory=dist) + assert app.router._frontend_routes is not None + inner_stack = AsyncExitStack() + function_stack = AsyncExitStack() + scope = { + "type": "http", + "http_version": "1.1", + "method": "GET", + "scheme": "http", + "path": "/", + "root_path": "", + "query_string": b"", + "headers": [], + "client": ("testclient", 50000), + "server": ("testserver", 80), + "fastapi_inner_astack": inner_stack, + "fastapi_function_astack": function_stack, + } + messages = [] + + async def receive(): + return { # pragma: no cover + "type": "http.request", + "body": b"", + "more_body": False, + } + + async def send(message): + messages.append(message) + + async with inner_stack, function_stack: + await app.router._frontend_routes.handle(scope, receive, send) + + assert scope["fastapi_inner_astack"] is inner_stack + assert scope["fastapi_function_astack"] is function_stack + assert messages[0]["type"] == "http.response.start" + assert messages[0]["status"] == 200 + + +def test_non_frontend_low_priority_route_keeps_order_before_frontend( + tmp_path: Path, +): + async def low_priority_endpoint(request: Request): + return PlainTextResponse("low") + + dist = tmp_path / "dist" + write_file(dist / "index.html", "frontend") + app = FastAPI() + app.router._low_priority_routes.append(Route("/admin", low_priority_endpoint)) + app.router._mark_routes_changed() + app.frontend("/", directory=dist) + + response = TestClient(app).get("/admin") + + assert response.status_code == 200 + assert response.text == "low" + + def test_existing_api_route_wins_over_frontend(tmp_path: Path): dist = tmp_path / "dist" write_file(dist / "api" / "users", "frontend") From aea660936b55fdbd84270d24f892839388922dd6 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Wed, 1 Jul 2026 16:13:00 +0000 Subject: [PATCH 387/462] =?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 f33f13c36..07a8307f2 100644 --- a/docs/en/docs/release-notes.md +++ b/docs/en/docs/release-notes.md @@ -7,6 +7,10 @@ hide: ## Latest Changes +### Features + +* ✨ Support dependencies in `app.frontend()`, e.g. for automatic cookie authentication for the frontend. PR [#15908](https://github.com/fastapi/fastapi/pull/15908) by [@tiangolo](https://github.com/tiangolo). + ### Translations * 🌐 Update translations for fr (update-outdated). PR [#15897](https://github.com/fastapi/fastapi/pull/15897) by [@tiangolo](https://github.com/tiangolo). From cecd96d9c6c318e0df1c40cedbc2e953381ddfd3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebasti=C3=A1n=20Ram=C3=ADrez?= Date: Wed, 1 Jul 2026 18:24:47 +0200 Subject: [PATCH 388/462] =?UTF-8?q?=F0=9F=94=96=20Release=20version=200.13?= =?UTF-8?q?9.0=20(#15910)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: github-actions[bot] --- docs/en/docs/release-notes.md | 2 ++ fastapi/__init__.py | 2 +- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/docs/en/docs/release-notes.md b/docs/en/docs/release-notes.md index 07a8307f2..2e42ba00f 100644 --- a/docs/en/docs/release-notes.md +++ b/docs/en/docs/release-notes.md @@ -7,6 +7,8 @@ hide: ## Latest Changes +## 0.139.0 (2026-07-01) + ### Features * ✨ Support dependencies in `app.frontend()`, e.g. for automatic cookie authentication for the frontend. PR [#15908](https://github.com/fastapi/fastapi/pull/15908) by [@tiangolo](https://github.com/tiangolo). diff --git a/fastapi/__init__.py b/fastapi/__init__.py index af5117aec..df55e7a6c 100644 --- a/fastapi/__init__.py +++ b/fastapi/__init__.py @@ -1,6 +1,6 @@ """FastAPI framework, high performance, easy to learn, fast to code, ready for production""" -__version__ = "0.138.2" +__version__ = "0.139.0" from starlette import status as status From b0708dcbb99ee0b63521b84c8cdc843055095124 Mon Sep 17 00:00:00 2001 From: Yurii Motov <109919500+YuriiMotov@users.noreply.github.com> Date: Fri, 3 Jul 2026 14:38:40 +0200 Subject: [PATCH 389/462] =?UTF-8?q?=F0=9F=8C=90=20Fix=20language-specific?= =?UTF-8?q?=20translation=20prompt=20for=20Russian=20language=20(#15924)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docs/ru/docs/deployment/concepts.md | 6 +++--- docs/ru/docs/deployment/docker.md | 10 +++++----- docs/ru/llm-prompt.md | 10 +++++----- 3 files changed, 13 insertions(+), 13 deletions(-) diff --git a/docs/ru/docs/deployment/concepts.md b/docs/ru/docs/deployment/concepts.md index 23c62b8d3..86dbdabe5 100644 --- a/docs/ru/docs/deployment/concepts.md +++ b/docs/ru/docs/deployment/concepts.md @@ -27,13 +27,13 @@ В [предыдущей главе про HTTPS](https.md) мы разобрались, как HTTPS обеспечивает шифрование для вашего API. -Также мы увидели, что HTTPS обычно обеспечивает компонент, **внешний** по отношению к серверу вашего приложения — **прокси-сервер TSL-терминации**. +Также мы увидели, что HTTPS обычно обеспечивает компонент, **внешний** по отношению к серверу вашего приложения — **прокси-сервер TLS-терминации**. И должен быть компонент, отвечающий за **обновление HTTPS‑сертификатов** — это может быть тот же самый компонент или отдельный. ### Примеры инструментов для HTTPS { #example-tools-for-https } -Некоторые инструменты, которые можно использовать как прокси-сервер TSL-терминации: +Некоторые инструменты, которые можно использовать как прокси-сервер TLS-терминации: * Traefik * Автоматически обновляет сертификаты ✨ @@ -47,7 +47,7 @@ * С внешним компонентом (например, cert-manager) для обновления сертификатов * Обрабатывается внутри облачного провайдера как часть его услуг (см. ниже 👇) -Другой вариант — использовать **облачный сервис**, который возьмёт на себя больше задач, включая настройку HTTPS. Там могут быть ограничения или дополнительная стоимость и т.п., но в таком случае вам не придётся самим настраивать прокси-сервер TSL-терминации. +Другой вариант — использовать **облачный сервис**, который возьмёт на себя больше задач, включая настройку HTTPS. Там могут быть ограничения или дополнительная стоимость и т.п., но в таком случае вам не придётся самим настраивать прокси-сервер TLS-терминации. В следующих главах я покажу конкретные примеры. diff --git a/docs/ru/docs/deployment/docker.md b/docs/ru/docs/deployment/docker.md index c3cf9a328..1a7586f53 100644 --- a/docs/ru/docs/deployment/docker.md +++ b/docs/ru/docs/deployment/docker.md @@ -273,9 +273,9 @@ CMD fastapi run app/main.py --port 80 └── requirements.txt ``` -#### За прокси-сервером TSL-терминации { #behind-a-tls-termination-proxy } +#### За прокси-сервером TLS-терминации { #behind-a-tls-termination-proxy } -Если вы запускаете контейнер за прокси-сервером TSL-терминации (балансировщиком нагрузки), таким как Nginx или Traefik, добавьте опцию `--proxy-headers`. Это сообщит Uvicorn (через FastAPI CLI), что можно доверять заголовкам, отправленным этим прокси и сообщающим, что приложение работает за HTTPS, и т.д. +Если вы запускаете контейнер за прокси-сервером TLS-терминации (балансировщиком нагрузки), таким как Nginx или Traefik, добавьте опцию `--proxy-headers`. Это сообщит Uvicorn (через FastAPI CLI), что можно доверять заголовкам, отправленным этим прокси и сообщающим, что приложение работает за HTTPS, и т.д. ```Dockerfile CMD ["fastapi", "run", "app/main.py", "--proxy-headers", "--port", "80"] @@ -462,17 +462,17 @@ CMD ["fastapi", "run", "main.py", "--port", "80"] ### Балансировщик нагрузки { #load-balancer } -При использовании контейнеров обычно есть компонент, **слушающий главный порт**. Это может быть другой контейнер — **прокси-сервер TSL-терминации** для обработки **HTTPS** или похожий инструмент. +При использовании контейнеров обычно есть компонент, **слушающий главный порт**. Это может быть другой контейнер — **прокси-сервер TLS-терминации** для обработки **HTTPS** или похожий инструмент. Поскольку этот компонент принимает **нагрузку** запросов и распределяет её между воркерами **сбалансированно**, его часто называют **балансировщиком нагрузки**. /// tip | Подсказка -Тот же компонент **прокси-сервер TSL-терминации**, который обрабатывает HTTPS, скорее всего также будет **балансировщиком нагрузки**. +Тот же компонент **прокси-сервер TLS-терминации**, который обрабатывает HTTPS, скорее всего также будет **балансировщиком нагрузки**. /// -При работе с контейнерами система, которую вы используете для запуска и управления ими, уже имеет внутренние средства для передачи **сетевого взаимодействия** (например, HTTP-запросов) от **балансировщика нагрузки** (который также может быть **прокси-сервером TSL-терминации**) к контейнеру(-ам) с вашим приложением. +При работе с контейнерами система, которую вы используете для запуска и управления ими, уже имеет внутренние средства для передачи **сетевого взаимодействия** (например, HTTP-запросов) от **балансировщика нагрузки** (который также может быть **прокси-сервером TLS-терминации**) к контейнеру(-ам) с вашим приложением. ### Один балансировщик — несколько контейнеров-воркеров { #one-load-balancer-multiple-worker-containers } diff --git a/docs/ru/llm-prompt.md b/docs/ru/llm-prompt.md index 9131a5d3b..6760609e2 100644 --- a/docs/ru/llm-prompt.md +++ b/docs/ru/llm-prompt.md @@ -21,7 +21,7 @@ For the following technical terms, use these specific translations to ensure con * path operation: операция пути (optionally clarify as `обработчик пути`) * path operation function: функция-обработчик пути (or `функция обработки пути`) * proprietary: проприетарный -* benchmark: бенчмарк (add (`тест производительности`) if clarification is needed or use just `тест производительности`) +* benchmark: бенчмарк (add `(тест производительности)` if clarification is needed or use just `тест производительности`) * ASGI server: ASGI-сервер * In a hurry? : Нет времени? * response status code: статус-код ответа @@ -42,7 +42,7 @@ For the following technical terms, use these specific translations to ensure con * include: включать (add `в себя` if it's appropriate, or use `содержать` as an alternative) * virtual environment: виртуальное окружение * framework: фреймворк -* path paremeter: path-параметр +* path parameter: path-параметр * path (as in URL path): путь * form (as in HTML form): форма * media type: тип содержимого (or `медиа-тип`) @@ -76,9 +76,9 @@ For the following technical terms, use these specific translations to ensure con * have the next best performance, after: быть на следующем месте по производительности после * timing attack: тайминговая атака (clarify `атака по времени` if needed) * OAuth2 scope: OAuth2 scope (clarify `область` if needed) -* TLS Termination Proxy: прокси-сервер TSL-терминации +* TLS Termination Proxy: прокси-сервер TLS-терминации * utilize (resources): использовать -* сontent: содержимое (or `контент`) +* content: содержимое (or `контент`) * raise exception: вызвать исключение (also possible to use `сгенерировать исключение` or `выбросить исключение`) * password flow: password flow (clarify as `аутентификация по паролю` if needed) * tutorial: руководство (or `учебник`) @@ -95,7 +95,7 @@ For the following technical terms, use these specific translations to ensure con * submodule: подмодуль * subpackage: подпакет * router: роутер -* building, deploying, accessing (when describing features of FastAPI Cloud): созданиe образа, развертывание и доступ +* building, deploying, accessing (when describing features of FastAPI Cloud): создание образа, развертывание и доступ * type checker tool: инструмент проверки типов Do not add whitespace in `т.д.`, `т.п.`. From ae59432d3ba389ba6e83101ffc6b2c5b10b43421 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Fri, 3 Jul 2026 12:39:09 +0000 Subject: [PATCH 390/462] =?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 2e42ba00f..eaba075d4 100644 --- a/docs/en/docs/release-notes.md +++ b/docs/en/docs/release-notes.md @@ -7,6 +7,10 @@ hide: ## Latest Changes +### Translations + +* 🌐 Fix language-specific translation prompt for Russian language. PR [#15924](https://github.com/fastapi/fastapi/pull/15924) by [@YuriiMotov](https://github.com/YuriiMotov). + ## 0.139.0 (2026-07-01) ### Features From 91df2c20bc83ba67aaf71cf461acd36c314ba326 Mon Sep 17 00:00:00 2001 From: Yurii Motov <109919500+YuriiMotov@users.noreply.github.com> Date: Fri, 3 Jul 2026 15:38:49 +0200 Subject: [PATCH 391/462] =?UTF-8?q?=F0=9F=8C=90=20Update=20`llm-prompt.md`?= =?UTF-8?q?=20for=20Hindi=20(#15810)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docs/hi/llm-prompt.md | 53 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 53 insertions(+) diff --git a/docs/hi/llm-prompt.md b/docs/hi/llm-prompt.md index 337ea3823..b626ea586 100644 --- a/docs/hi/llm-prompt.md +++ b/docs/hi/llm-prompt.md @@ -3,3 +3,56 @@ Translate to Hindi (हिन्दी). Language code: hi. + +For the following terms, use these specific choices: + +* path (URL path): path (do not transliterate as "पाथ") +* path parameter / path operation: keep in English +* query / query parameter: keep in English (do not transliterate as "क्वेरी") +* parameter: parameter (do not transliterate as "पैरामीटर") +* header / headers (HTTP): keep in English (do not translate as "हेडर" / "शीर्षक") +* cookie / cookies: keep in English (do not transliterate as "कुकी") +* form / form data: keep in English (do not transliterate as "फ़ॉर्म" / "फ़ॉर्म डेटा") +* field / fields: keep in English (do not transliterate as "फ़ील्ड्स") +* body / request body / response body: keep in English (do not transliterate as "बॉडी" / "रिक्वेस्ट बॉडी") +* request / response: keep in English (do not translate as "अनुरोध" / "प्रतिक्रिया") +* required: required (do not translate as "आवश्यक") +* route / router / endpoint: keep in English +* framework: framework +* middleware: middleware (do not transliterate as "मिडलवेयर") +* lifespan: lifespan (do not translate as "जीवनकाल") +* context manager: keep in English +* CORS: keep in English +* function: function (do not transliterate as "फ़ंक्शन") +* variable: variable (do not transliterate as "वेरिएबल") +* model / Pydantic model: keep in English (do not transliterate as "मॉडल") +* value: value (do not translate as "मान") +* spec / specification: keep in English (do not translate as "स्पेक" / "विनिर्देश") +* Enum / enumeration: keep in English +* data: data (do not transliterate as "डेटा") +* parsing: parsing (do not transliterate as "पार्सिंग") +* conversion: conversion (do not translate as "रूपांतरण") +* virtual environment: virtual environment (do not transliterate as "वर्चुअल एनवायरनमेंट") +* environment variable: environment variable (do not transliterate as "एनवायरनमेंट वेरिएबल") +* directory: directory (do not transliterate as "डायरेक्टरी") +* package: package (do not transliterate as "पैकेज") +* file / files: keep in English (do not transliterate as "फ़ाइल") +* install / installation: keep in English (do not transliterate as "इंस्टॉल") +* setup: setup (do not transliterate as "सेटअप") +* section: section (do not transliterate as "सेक्शन") +* editor / editor support: keep in English (do not transliterate as "एडिटर सपोर्ट") +* application discovery: keep in English +* event / events: event (do not transliterate as "इवेंट्स") +* startup / shutdown: keep in English (do not transliterate as "स्टार्टअप") +* worker / worker process: keep in English (do not translate as "वर्कर" / "श्रमिक") +* activate / deactivate: keep in English (do not translate as "सक्रिय करें" / "निष्क्रिय करें") +* development: development (do not transliterate as "डेवलपमेंट") +* production: production (do not transliterate as "प्रोडक्शन") +* feature: feature (do not transliterate as "फीचर") +* tool: tool (do not transliterate as "टूल") +* project: project (do not transliterate as "प्रोजेक्ट") +* developer / team: keep in English +* default: default (do not transliterate as "डिफ़ॉल्ट") +* standard: standard (do not translate as "मानक") +* asynchronous: asynchronous (do not transliterate as "असिंक्रोनस") +* Recap (section heading): keep in English (do not translate as "पुनरावलोकन") From d27fe5cf15106a93687951479272999d4d84ecce Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Fri, 3 Jul 2026 13:39:15 +0000 Subject: [PATCH 392/462] =?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 eaba075d4..1a75ca9f3 100644 --- a/docs/en/docs/release-notes.md +++ b/docs/en/docs/release-notes.md @@ -9,6 +9,7 @@ hide: ### Translations +* 🌐 Update `llm-prompt.md` for Hindi. PR [#15810](https://github.com/fastapi/fastapi/pull/15810) by [@YuriiMotov](https://github.com/YuriiMotov). * 🌐 Fix language-specific translation prompt for Russian language. PR [#15924](https://github.com/fastapi/fastapi/pull/15924) by [@YuriiMotov](https://github.com/YuriiMotov). ## 0.139.0 (2026-07-01) From 72726acc6b16d419c02db9da5859b5b0f859fb6f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebasti=C3=A1n=20Ram=C3=ADrez?= Date: Fri, 3 Jul 2026 15:41:36 +0200 Subject: [PATCH 393/462] =?UTF-8?q?=F0=9F=8C=90=20Update=20translations=20?= =?UTF-8?q?for=20hi=20(add-missing)=20(#15797)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: github-actions[bot] Co-authored-by: Yurii Motov Co-authored-by: Yurii Motov <109919500+YuriiMotov@users.noreply.github.com> --- docs/hi/docs/alternatives.md | 485 +++++++++++++++ docs/hi/docs/async.md | 444 +++++++++++++ docs/hi/docs/benchmarks.md | 34 + docs/hi/docs/editor-support.md | 23 + docs/hi/docs/fastapi-cli.md | 134 ++++ docs/hi/docs/features.md | 201 ++++++ docs/hi/docs/history-design-future.md | 79 +++ docs/hi/docs/project-generation.md | 28 + docs/hi/docs/python-types.md | 348 +++++++++++ docs/hi/docs/virtual-environments.md | 864 ++++++++++++++++++++++++++ 10 files changed, 2640 insertions(+) create mode 100644 docs/hi/docs/alternatives.md create mode 100644 docs/hi/docs/async.md create mode 100644 docs/hi/docs/benchmarks.md create mode 100644 docs/hi/docs/editor-support.md create mode 100644 docs/hi/docs/fastapi-cli.md create mode 100644 docs/hi/docs/features.md create mode 100644 docs/hi/docs/history-design-future.md create mode 100644 docs/hi/docs/project-generation.md create mode 100644 docs/hi/docs/python-types.md create mode 100644 docs/hi/docs/virtual-environments.md diff --git a/docs/hi/docs/alternatives.md b/docs/hi/docs/alternatives.md new file mode 100644 index 000000000..31ca9e107 --- /dev/null +++ b/docs/hi/docs/alternatives.md @@ -0,0 +1,485 @@ +# विकल्प, प्रेरणा और तुलनाएँ { #alternatives-inspiration-and-comparisons } + +**FastAPI** को किससे प्रेरणा मिली, यह विकल्पों की तुलना में कैसा है और उनसे इसने क्या सीखा। + +## परिचय { #intro } + +दूसरों के पिछले काम के बिना **FastAPI** अस्तित्व में नहीं होता। + +इससे पहले कई tools बनाए गए हैं जिन्होंने इसके निर्माण को प्रेरित करने में मदद की। + +मैं कई वर्षों तक एक नया framework बनाने से बचता रहा। पहले मैंने **FastAPI** द्वारा कवर किए गए सभी features को कई अलग-अलग frameworks, plug-ins और tools का उपयोग करके हल करने की कोशिश की। + +लेकिन एक समय ऐसा आया जब ऐसा कुछ बनाने के अलावा कोई विकल्प नहीं था जो ये सभी features प्रदान करे, पिछले tools से सर्वोत्तम विचारों को लेकर, और उन्हें सबसे अच्छे तरीके से मिलाकर, उन language features का उपयोग करते हुए जो पहले उपलब्ध भी नहीं थे (Python 3.6+ type hints)। + +## पिछले tools { #previous-tools } + +### [Django](https://www.djangoproject.com/) { #django } + +यह सबसे लोकप्रिय Python framework है और व्यापक रूप से भरोसेमंद है। इसका उपयोग Instagram जैसे systems बनाने के लिए किया जाता है। + +यह relational databases (जैसे MySQL या PostgreSQL) के साथ अपेक्षाकृत tightly coupled है, इसलिए मुख्य store engine के रूप में NoSQL database (जैसे Couchbase, MongoDB, Cassandra, आदि) रखना बहुत आसान नहीं है। + +इसे backend में HTML generate करने के लिए बनाया गया था, न कि किसी modern frontend (जैसे React, Vue.js और Angular) या इसके साथ संचार करने वाले अन्य systems (जैसे IoT devices) द्वारा उपयोग की जाने वाली APIs बनाने के लिए। + +### [Django REST Framework](https://www.django-rest-framework.org/) { #django-rest-framework } + +Django REST Framework को Django के ऊपर Web APIs बनाने के लिए एक flexible toolkit के रूप में बनाया गया था, ताकि इसकी API क्षमताओं में सुधार हो सके। + +इसका उपयोग Mozilla, Red Hat और Eventbrite सहित कई कंपनियाँ करती हैं। + +यह **automatic API documentation** के पहले उदाहरणों में से एक था, और यह विशेष रूप से उन पहले विचारों में से एक था जिसने **FastAPI** की "खोज" को प्रेरित किया। + +/// note | नोट + +Django REST Framework को Tom Christie ने बनाया था। वही Starlette और Uvicorn के creator हैं, जिन पर **FastAPI** आधारित है। + +/// + +/// tip | **FastAPI** को इससे प्रेरणा मिली कि + +एक automatic API documentation web user interface हो। + +/// + +### [Flask](https://flask.palletsprojects.com) { #flask } + +Flask एक "microframework" है, इसमें database integrations या Django में default रूप से आने वाली कई चीज़ें शामिल नहीं हैं। + +यह simplicity और flexibility मुख्य data storage system के रूप में NoSQL databases का उपयोग करने जैसी चीज़ें करने की अनुमति देती है। + +क्योंकि यह बहुत सरल है, इसे सीखना अपेक्षाकृत सहज है, हालांकि documentation कुछ बिंदुओं पर थोड़ा technical हो जाता है। + +इसका उपयोग आमतौर पर उन अन्य applications के लिए भी किया जाता है जिन्हें जरूरी नहीं कि database, user management, या Django में पहले से built-in आने वाले कई features की आवश्यकता हो। हालांकि इनमें से कई features plug-ins के साथ जोड़े जा सकते हैं। + +Parts का यह decoupling, और एक "microframework" होना जिसे ठीक वही कवर करने के लिए extend किया जा सके जिसकी आवश्यकता है, एक key feature था जिसे मैं बनाए रखना चाहता था। + +Flask की simplicity को देखते हुए, यह APIs बनाने के लिए अच्छा match लगा। अगली चीज़ जो खोजनी थी वह Flask के लिए एक "Django REST Framework" था। + +/// tip | **FastAPI** को इससे प्रेरणा मिली कि + +एक micro-framework हो। आवश्यक tools और parts को mix and match करना आसान बनाया जाए। + +एक simple और उपयोग में आसान routing system हो। + +/// + +### [Requests](https://requests.readthedocs.io) { #requests } + +**FastAPI** वास्तव में **Requests** का विकल्प नहीं है। उनका scope बहुत अलग है। + +वास्तव में FastAPI application के *अंदर* Requests का उपयोग करना सामान्य बात होगी। + +लेकिन फिर भी, FastAPI को Requests से काफी प्रेरणा मिली। + +**Requests** APIs के साथ *interact* करने के लिए (client के रूप में) एक library है, जबकि **FastAPI** APIs *बनाने* के लिए (server के रूप में) एक library है। + +वे कमोबेश विपरीत सिरों पर हैं, एक-दूसरे को पूरक करते हुए। + +Requests का design बहुत simple और intuitive है, sensible defaults के साथ इसका उपयोग करना बहुत आसान है। लेकिन साथ ही, यह बहुत powerful और customizable है। + +इसीलिए, जैसा कि official website में कहा गया है: + +> Requests अब तक के सबसे अधिक downloaded Python packages में से एक है + +आप इसे जिस तरह उपयोग करते हैं वह बहुत सरल है। उदाहरण के लिए, `GET` request करने के लिए, आप लिखेंगे: + +```Python +response = requests.get("http://example.com/some/url") +``` + +FastAPI में इसके समकक्ष API *path operation* इस तरह दिख सकता है: + +```Python hl_lines="1" +@app.get("/some/url") +def read_url(): + return {"message": "Hello World"} +``` + +`requests.get(...)` और `@app.get(...)` में समानताएँ देखें। + +/// tip | **FastAPI** को इससे प्रेरणा मिली कि + +* एक simple और intuitive API हो। +* HTTP method names (operations) को सीधे, straightforward और intuitive तरीके से उपयोग किया जाए। +* sensible defaults हों, लेकिन powerful customizations भी हों। + +/// + +### [Swagger](https://swagger.io/) / [OpenAPI](https://github.com/OAI/OpenAPI-Specification/) { #swagger-openapi } + +Django REST Framework से जो मुख्य feature मैं चाहता था वह automatic API documentation था। + +फिर मुझे पता चला कि APIs को document करने के लिए JSON (या YAML, JSON का एक extension) का उपयोग करने वाला एक standard था, जिसे Swagger कहा जाता था। + +और Swagger APIs के लिए एक web user interface पहले से बनाया जा चुका था। इसलिए, किसी API के लिए Swagger documentation generate कर पाना इस web user interface का automatically उपयोग करने की अनुमति देता। + +एक समय पर, Swagger को Linux Foundation को दे दिया गया, ताकि उसका नाम बदलकर OpenAPI रखा जा सके। + +इसीलिए version 2.0 के बारे में बात करते समय "Swagger" कहना आम है, और version 3+ के लिए "OpenAPI"। + +/// tip | **FastAPI** को इससे प्रेरणा मिली कि + +Custom schema के बजाय API specifications के लिए एक open standard अपनाया और उपयोग किया जाए। + +और standards-based user interface tools को integrate किया जाए: + +* [Swagger UI](https://github.com/swagger-api/swagger-ui) +* [ReDoc](https://github.com/Rebilly/ReDoc) + +इन दोनों को इसलिए चुना गया क्योंकि ये काफी popular और stable थे, लेकिन एक quick search करने पर, आप OpenAPI के लिए दर्जनों alternative user interfaces पा सकते हैं (जिन्हें आप **FastAPI** के साथ उपयोग कर सकते हैं)। + +/// + +### Flask REST frameworks { #flask-rest-frameworks } + +कई Flask REST frameworks हैं, लेकिन उनकी जाँच में समय और काम लगाने के बाद, मैंने पाया कि कई discontinue या abandon हो चुके हैं, और उनमें कई unresolved issues हैं जिन्होंने उन्हें अनुपयुक्त बना दिया। + +### [Marshmallow](https://marshmallow.readthedocs.io/en/stable/) { #marshmallow } + +API systems द्वारा आवश्यक मुख्य features में से एक data "serialization" है, जिसमें code (Python) से data लेकर उसे ऐसी चीज़ में बदला जाता है जिसे network के माध्यम से भेजा जा सके। उदाहरण के लिए, database से data रखने वाले object को JSON object में बदलना। `datetime` objects को strings में बदलना, आदि। + +APIs द्वारा आवश्यक एक और बड़ा feature data validation है, यह सुनिश्चित करना कि data निश्चित parameters के अनुसार valid है। उदाहरण के लिए, कोई field `int` है, कोई random string नहीं। यह incoming data के लिए विशेष रूप से उपयोगी है। + +Data validation system के बिना, आपको सभी checks हाथ से, code में करने पड़ते। + +ये features वही हैं जिन्हें प्रदान करने के लिए Marshmallow बनाया गया था। यह एक बेहतरीन library है, और मैंने पहले इसका बहुत उपयोग किया है। + +लेकिन इसे Python type hints के अस्तित्व में आने से पहले बनाया गया था। इसलिए, हर schema को define करने के लिए आपको Marshmallow द्वारा प्रदान किए गए specific utils और classes का उपयोग करना पड़ता है। + +/// tip | **FastAPI** को इससे प्रेरणा मिली कि + +"schemas" को define करने के लिए code का उपयोग किया जाए जो data types और validation, automatically प्रदान करे। + +/// + +### [Webargs](https://webargs.readthedocs.io/en/latest/) { #webargs } + +APIs द्वारा आवश्यक एक और बड़ा feature incoming requests से data parsing करना है। + +Webargs एक tool है जिसे Flask सहित कई frameworks के ऊपर यह प्रदान करने के लिए बनाया गया था। + +यह data validation करने के लिए नीचे Marshmallow का उपयोग करता है। और इसे उन्हीं developers ने बनाया था। + +यह एक बेहतरीन tool है और **FastAPI** से पहले मैंने इसका भी बहुत उपयोग किया था। + +/// note | नोट + +Webargs को उन्हीं Marshmallow developers ने बनाया था। + +/// + +/// tip | **FastAPI** को इससे प्रेरणा मिली कि + +Incoming request data का automatic validation हो। + +/// + +### [APISpec](https://apispec.readthedocs.io/en/stable/) { #apispec } + +Marshmallow और Webargs plug-ins के रूप में validation, parsing और serialization प्रदान करते हैं। + +लेकिन documentation अभी भी missing है। फिर APISpec बनाया गया। + +यह कई frameworks के लिए एक plug-in है (और Starlette के लिए भी एक plug-in है)। + +यह जिस तरह काम करता है वह यह है कि आप route handle करने वाली प्रत्येक function की docstring के अंदर YAML format का उपयोग करके schema की definition लिखते हैं। + +और यह OpenAPI schemas generate करता है। + +Flask, Starlette, Responder, आदि में यह इसी तरह काम करता है। + +लेकिन फिर, हमारे पास फिर से Python string (एक बड़ा YAML) के अंदर micro-syntax होने की समस्या है। + +Editor इसमें ज्यादा मदद नहीं कर सकता। और अगर हम parameters या Marshmallow schemas modify करते हैं और उस YAML docstring को भी modify करना भूल जाते हैं, तो generated schema obsolete हो जाएगा। + +/// note | नोट + +APISpec को उन्हीं Marshmallow developers ने बनाया था। + +/// + +/// tip | **FastAPI** को इससे प्रेरणा मिली कि + +APIs के लिए open standard, OpenAPI को support किया जाए। + +/// + +### [Flask-apispec](https://flask-apispec.readthedocs.io/en/latest/) { #flask-apispec } + +यह एक Flask plug-in है, जो Webargs, Marshmallow और APISpec को एक साथ जोड़ता है। + +यह APISpec का उपयोग करके OpenAPI schemas automatically generate करने के लिए Webargs और Marshmallow की जानकारी का उपयोग करता है। + +यह एक बेहतरीन tool है, बहुत underrated। इसे वहाँ मौजूद कई Flask plug-ins से कहीं अधिक popular होना चाहिए। यह शायद इसकी documentation के बहुत concise और abstract होने के कारण हो सकता है। + +इसने Python docstrings के अंदर YAML (एक और syntax) लिखने की आवश्यकता को हल कर दिया। + +Flask, Flask-apispec को Marshmallow और Webargs के साथ मिलाकर यह combination **FastAPI** बनाने तक मेरा पसंदीदा backend stack था। + +इसका उपयोग करने से कई Flask full-stack generators बने। ये वे main stacks हैं जिन्हें मैं (और कई external teams) अब तक उपयोग कर रहे हैं: + +* [https://github.com/tiangolo/full-stack](https://github.com/tiangolo/full-stack) +* [https://github.com/tiangolo/full-stack-flask-couchbase](https://github.com/tiangolo/full-stack-flask-couchbase) +* [https://github.com/tiangolo/full-stack-flask-couchdb](https://github.com/tiangolo/full-stack-flask-couchdb) + +और यही full-stack generators [**FastAPI** Project Generators](project-generation.md) का base थे। + +/// note | नोट + +Flask-apispec को उन्हीं Marshmallow developers ने बनाया था। + +/// + +/// tip | **FastAPI** को इससे प्रेरणा मिली कि + +OpenAPI schema को automatically generate किया जाए, उसी code से जो serialization और validation define करता है। + +/// + +### [NestJS](https://nestjs.com/) (और [Angular](https://angular.io/)) { #nestjs-and-angular } + +यह Python भी नहीं है, NestJS Angular से प्रेरित एक JavaScript (TypeScript) NodeJS framework है। + +यह कुछ ऐसा हासिल करता है जो Flask-apispec के साथ किए जा सकने वाले काम जैसा है। + +इसमें Angular 2 से प्रेरित एक integrated dependency injection system है। इसमें "injectables" को pre-register करना आवश्यक है (जैसे मुझे ज्ञात सभी अन्य dependency injection systems में), इसलिए, यह verbosity और code repetition बढ़ाता है। + +क्योंकि parameters को TypeScript types (Python type hints के समान) के साथ describe किया जाता है, editor support काफी अच्छा है। + +लेकिन क्योंकि TypeScript data compilation के बाद JavaScript में preserve नहीं रहता, यह validation, serialization और documentation को एक ही समय पर define करने के लिए types पर निर्भर नहीं हो सकता। इसके कारण और कुछ design decisions के कारण, validation, serialization और automatic schema generation पाने के लिए, कई जगह decorators जोड़ने की आवश्यकता होती है। इसलिए, यह काफी verbose हो जाता है। + +यह nested models को बहुत अच्छी तरह handle नहीं कर सकता। इसलिए, अगर request में JSON body एक JSON object है जिसमें inner fields हैं जो खुद nested JSON objects हैं, तो इसे ठीक से document और validate नहीं किया जा सकता। + +/// tip | **FastAPI** को इससे प्रेरणा मिली कि + +बेहतरीन editor support के लिए Python types का उपयोग किया जाए। + +एक powerful dependency injection system हो। Code repetition को minimize करने का तरीका खोजा जाए। + +/// + +### [Sanic](https://sanic.readthedocs.io/en/latest/) { #sanic } + +यह `asyncio` पर आधारित पहले बेहद तेज़ Python frameworks में से एक था। इसे Flask के बहुत समान बनाया गया था। + +/// note | तकनीकी विवरण + +इसने default Python `asyncio` loop के बजाय [`uvloop`](https://github.com/MagicStack/uvloop) का उपयोग किया। यही इसे इतना तेज़ बनाता था। + +इसने स्पष्ट रूप से Uvicorn और Starlette को प्रेरित किया, जो वर्तमान में open benchmarks में Sanic से तेज़ हैं। + +/// + +/// tip | **FastAPI** को इससे प्रेरणा मिली कि + +बेहद तेज़ performance हासिल करने का तरीका खोजा जाए। + +इसीलिए **FastAPI** Starlette पर आधारित है, क्योंकि यह उपलब्ध सबसे तेज़ framework है (third-party benchmarks द्वारा tested)। + +/// + +### [Falcon](https://falconframework.org/) { #falcon } + +Falcon एक और high performance Python framework है, इसे minimal होने और Hug जैसे अन्य frameworks की foundation के रूप में काम करने के लिए design किया गया है। + +इसे ऐसी functions रखने के लिए design किया गया है जो दो parameters receive करती हैं, एक "request" और एक "response"। फिर आप request से parts "read" करते हैं, और response में parts "write" करते हैं। इस design के कारण, standard Python type hints के साथ function parameters के रूप में request parameters और bodies declare करना संभव नहीं है। + +इसलिए, data validation, serialization, और documentation को code में करना पड़ता है, automatically नहीं। या उन्हें Falcon के ऊपर एक framework के रूप में implement करना पड़ता है, जैसे Hug। यही अंतर उन अन्य frameworks में भी होता है जो Falcon के design से प्रेरित हैं, जहाँ parameters के रूप में एक request object और एक response object होता है। + +/// tip | **FastAPI** को इससे प्रेरणा मिली कि + +बेहतरीन performance पाने के तरीके खोजे जाएँ। + +Hug के साथ (क्योंकि Hug Falcon पर आधारित है) इसने **FastAPI** को functions में `response` parameter declare करने के लिए प्रेरित किया। + +हालांकि FastAPI में यह optional है, और मुख्य रूप से headers, cookies, और alternative status codes set करने के लिए उपयोग किया जाता है। + +/// + +### [Molten](https://moltenframework.com/) { #molten } + +मैंने **FastAPI** बनाने के शुरुआती चरणों में Molten खोजा। और इसमें काफी समान विचार हैं: + +* Python type hints पर आधारित। +* इन types से validation और documentation। +* Dependency Injection system। + +यह Pydantic जैसी data validation, serialization और documentation third-party library का उपयोग नहीं करता, इसकी अपनी library है। इसलिए, ये data type definitions उतनी आसानी से reusable नहीं होंगी। + +इसे थोड़ी अधिक verbose configurations की आवश्यकता होती है। और क्योंकि यह WSGI (ASGI के बजाय) पर आधारित है, इसे Uvicorn, Starlette और Sanic जैसे tools द्वारा प्रदान किए गए high performance का लाभ उठाने के लिए design नहीं किया गया है। + +Dependency injection system को dependencies की pre-registration की आवश्यकता होती है और dependencies declared types के आधार पर solve की जाती हैं। इसलिए, किसी निश्चित type को provide करने वाले एक से अधिक "component" declare करना संभव नहीं है। + +Routes एक ही जगह declare किए जाते हैं, दूसरी जगहों पर declared functions का उपयोग करके (decorators का उपयोग करने के बजाय जिन्हें endpoint handle करने वाली function के ठीक ऊपर रखा जा सकता है)। यह Flask (और Starlette) के तरीके की तुलना में Django के तरीके के अधिक करीब है। यह code में उन चीज़ों को अलग करता है जो अपेक्षाकृत tightly coupled हैं। + +/// tip | **FastAPI** को इससे प्रेरणा मिली कि + +Model attributes के "default" value का उपयोग करके data types के लिए extra validations define किए जाएँ। यह editor support को बेहतर बनाता है, और यह पहले Pydantic में उपलब्ध नहीं था। + +इसने वास्तव में Pydantic के parts को update करने के लिए प्रेरित किया, ताकि वही validation declaration style support किया जा सके (यह सारी functionality अब Pydantic में पहले से उपलब्ध है)। + +/// + +### [Hug](https://github.com/hugapi/hug) { #hug } + +Hug उन पहले frameworks में से एक था जिसने Python type hints का उपयोग करके API parameter types की declaration implement की। यह एक बेहतरीन विचार था जिसने अन्य tools को भी ऐसा ही करने के लिए प्रेरित किया। + +इसने अपनी declarations में standard Python types के बजाय custom types का उपयोग किया, लेकिन फिर भी यह एक बहुत बड़ा कदम आगे था। + +यह पूरे API को JSON में declare करने वाला custom schema generate करने वाले पहले frameworks में से भी एक था। + +यह OpenAPI और JSON Schema जैसे standard पर आधारित नहीं था। इसलिए इसे Swagger UI जैसे अन्य tools के साथ integrate करना straightforward नहीं होता। लेकिन फिर भी, यह एक बहुत innovative idea था। + +इसमें एक दिलचस्प, uncommon feature है: उसी framework का उपयोग करके APIs और CLIs भी बनाना संभव है। + +क्योंकि यह synchronous Python web frameworks (WSGI) के पिछले standard पर आधारित है, यह Websockets और अन्य चीज़ों को handle नहीं कर सकता, हालांकि इसका performance भी high है। + +/// note | नोट + +Hug को Timothy Crosley ने बनाया था, वही [`isort`](https://github.com/timothycrosley/isort) के creator हैं, जो Python files में imports को automatically sort करने के लिए एक बेहतरीन tool है। + +/// + +/// tip | **FastAPI** को प्रेरित करने वाले विचार + +Hug ने APIStar के parts को प्रेरित किया, और APIStar के साथ-साथ यह उन tools में से एक था जो मुझे सबसे promising लगे। + +Hug ने **FastAPI** को parameters declare करने के लिए Python type hints का उपयोग करने, और API को automatically define करने वाला schema generate करने के लिए प्रेरित किया। + +Hug ने **FastAPI** को headers और cookies set करने के लिए functions में `response` parameter declare करने के लिए प्रेरित किया। + +/// + +### [APIStar](https://github.com/encode/apistar) (<= 0.5) { #apistar-0-5 } + +**FastAPI** बनाने का निर्णय लेने से ठीक पहले मुझे **APIStar** server मिला। इसमें लगभग वह सब कुछ था जिसकी मुझे तलाश थी और इसका design बेहतरीन था। + +यह उन पहले implementations में से एक था जो मैंने कभी देखे, जिसमें parameters और requests declare करने के लिए Python type hints का उपयोग करने वाला framework था (NestJS और Molten से पहले)। मुझे यह Hug के लगभग उसी समय मिला। लेकिन APIStar ने OpenAPI standard का उपयोग किया। + +इसमें कई जगहों पर उन्हीं type hints के आधार पर automatic data validation, data serialization और OpenAPI schema generation था। + +Body schema definitions Pydantic जैसे Python type hints का उपयोग नहीं करती थीं, यह Marshmallow के थोड़ा अधिक समान था, इसलिए editor support उतना अच्छा नहीं होता, लेकिन फिर भी, APIStar उपलब्ध सबसे अच्छा विकल्प था। + +उस समय इसके performance benchmarks सबसे अच्छे थे (सिर्फ Starlette ने surpass किया था)। + +शुरुआत में, इसमें automatic API documentation web UI नहीं था, लेकिन मुझे पता था कि मैं इसमें Swagger UI जोड़ सकता हूँ। + +इसमें dependency injection system था। ऊपर चर्चा किए गए अन्य tools की तरह, इसमें components की pre-registration आवश्यक थी। लेकिन फिर भी, यह एक बेहतरीन feature था। + +मैं कभी भी इसे full project में उपयोग नहीं कर पाया, क्योंकि इसमें security integration नहीं था, इसलिए मैं Flask-apispec पर आधारित full-stack generators के साथ मौजूद सभी features को replace नहीं कर सका। मेरे projects backlog में उस functionality को जोड़ने वाला pull request बनाने का विचार था। + +लेकिन फिर, project का focus shift हो गया। + +यह अब API web framework नहीं रहा, क्योंकि creator को Starlette पर focus करना था। + +अब APIStar OpenAPI specifications validate करने के लिए tools का एक set है, web framework नहीं। + +/// note | नोट + +APIStar को Tom Christie ने बनाया था। वही व्यक्ति जिन्होंने बनाया: + +* Django REST Framework +* Starlette (जिस पर **FastAPI** आधारित है) +* Uvicorn (Starlette और **FastAPI** द्वारा उपयोग किया जाता है) + +/// + +/// tip | **FastAPI** को इससे प्रेरणा मिली कि + +अस्तित्व में आए। + +एक ही Python types के साथ कई चीज़ें (data validation, serialization और documentation) declare करने का विचार, जो साथ ही बेहतरीन editor support भी देता था, मुझे एक शानदार विचार लगा। + +और लंबे समय तक समान framework की खोज करने और कई अलग-अलग alternatives को test करने के बाद, APIStar उपलब्ध सबसे अच्छा विकल्प था। + +फिर APIStar ने server के रूप में अस्तित्व में रहना बंद कर दिया और Starlette बनाया गया, और यह ऐसे system के लिए एक नई बेहतर foundation था। यही **FastAPI** बनाने की अंतिम प्रेरणा थी। + +मैं **FastAPI** को APIStar का "spiritual successor" मानता हूँ, जो इन सभी पिछले tools से मिली सीख के आधार पर features, typing system, और अन्य parts को improve और increase करता है। + +/// + +## **FastAPI** द्वारा उपयोग किया गया { #used-by-fastapi } + +### [Pydantic](https://docs.pydantic.dev/) { #pydantic } + +Pydantic Python type hints के आधार पर data validation, serialization और documentation (JSON Schema का उपयोग करके) define करने के लिए एक library है। + +यह इसे बेहद intuitive बनाता है। + +यह Marshmallow से comparable है। हालांकि benchmarks में यह Marshmallow से तेज़ है। और क्योंकि यह उन्हीं Python type hints पर आधारित है, editor support बेहतरीन है। + +/// tip | **FastAPI** इसे इन कामों के लिए उपयोग करता है + +सभी data validation, data serialization और automatic model documentation (JSON Schema पर आधारित) handle करना। + +फिर **FastAPI** उस JSON Schema data को लेता है और उसे OpenAPI में डालता है, उन सभी अन्य चीज़ों के अलावा जो यह करता है। + +/// + +### [Starlette](https://www.starlette.dev/) { #starlette } + +Starlette एक lightweight ASGI framework/toolkit है, जो high-performance asyncio services बनाने के लिए ideal है। + +यह बहुत simple और intuitive है। इसे आसानी से extensible होने और modular components रखने के लिए design किया गया है। + +इसमें है: + +* बहुत प्रभावशाली performance. +* WebSocket support. +* In-process background tasks. +* Startup और shutdown events. +* HTTPX पर built test client. +* CORS, GZip, Static Files, Streaming responses. +* Session और Cookie support. +* 100% test coverage. +* 100% type annotated codebase. +* कुछ hard dependencies. + +Starlette वर्तमान में tested सबसे तेज़ Python framework है। केवल Uvicorn ने इसे surpass किया है, जो framework नहीं, बल्कि server है। + +Starlette सभी basic web microframework functionality प्रदान करता है। + +लेकिन यह automatic data validation, serialization या documentation प्रदान नहीं करता। + +यह उन मुख्य चीज़ों में से एक है जो **FastAPI** ऊपर से जोड़ता है, सब Python type hints (Pydantic का उपयोग करके) पर आधारित। इसके साथ dependency injection system, security utilities, OpenAPI schema generation, आदि। + +/// note | तकनीकी विवरण + +ASGI एक नया "standard" है जिसे Django core team members द्वारा develop किया जा रहा है। यह अभी भी "Python standard" (एक PEP) नहीं है, हालांकि वे ऐसा करने की प्रक्रिया में हैं। + +फिर भी, इसे पहले से ही कई tools द्वारा "standard" के रूप में उपयोग किया जा रहा है। यह interoperability को बहुत बेहतर बनाता है, क्योंकि आप Uvicorn को किसी अन्य ASGI server (जैसे Daphne या Hypercorn) से switch कर सकते हैं, या आप ASGI compatible tools, जैसे `python-socketio`, जोड़ सकते हैं। + +/// + +/// tip | **FastAPI** इसे इन कामों के लिए उपयोग करता है + +सभी core web parts को handle करना। ऊपर से features जोड़ना। + +Class `FastAPI` खुद सीधे class `Starlette` से inherit करती है। + +इसलिए, जो कुछ भी आप Starlette के साथ कर सकते हैं, उसे आप सीधे **FastAPI** के साथ कर सकते हैं, क्योंकि यह मूल रूप से steroids पर Starlette है। + +/// + +### [Uvicorn](https://www.uvicorn.dev/) { #uvicorn } + +Uvicorn एक lightning-fast ASGI server है, जो uvloop और httptools पर बना है। + +यह web framework नहीं, बल्कि server है। उदाहरण के लिए, यह paths द्वारा routing के लिए tools प्रदान नहीं करता। यह ऐसी चीज़ है जो Starlette (या **FastAPI**) जैसा framework ऊपर से प्रदान करेगा। + +यह Starlette और **FastAPI** के लिए recommended server है। + +/// tip | **FastAPI** इसे इस रूप में अनुशंसित करता है + +**FastAPI** applications चलाने के लिए main web server। + +आप asynchronous multi-process server पाने के लिए `--workers` command line option का भी उपयोग कर सकते हैं। + +अधिक विवरण [Deployment](deployment/index.md) section में देखें। + +/// + +## Benchmarks और speed { #benchmarks-and-speed } + +Uvicorn, Starlette और FastAPI के बीच समझने, तुलना करने, और अंतर देखने के लिए, [Benchmarks](benchmarks.md) के बारे में section देखें। diff --git a/docs/hi/docs/async.md b/docs/hi/docs/async.md new file mode 100644 index 000000000..8841c92be --- /dev/null +++ b/docs/hi/docs/async.md @@ -0,0 +1,444 @@ +# Concurrency और async / await { #concurrency-and-async-await } + +*path operation functions* के लिए `async def` syntax के बारे में विवरण और asynchronous code, concurrency, और parallelism के बारे में कुछ पृष्ठभूमि। + +## जल्दी में हैं? { #in-a-hurry } + +TL;DR: + +अगर आप third party libraries का उपयोग कर रहे हैं जो आपको उन्हें `await` के साथ call करने को कहती हैं, जैसे: + +```Python +results = await some_library() +``` + +तो, अपने *path operation functions* को `async def` के साथ declare करें, जैसे: + +```Python hl_lines="2" +@app.get('/') +async def read_results(): + results = await some_library() + return results +``` + +/// note | नोट + +आप `await` का उपयोग केवल `async def` के साथ बनाए गए functions के अंदर ही कर सकते हैं। + +/// + +--- + +अगर आप ऐसी third party library का उपयोग कर रहे हैं जो किसी चीज़ (database, API, file system, आदि) से communicate करती है और `await` का उपयोग करने का support नहीं रखती, (वर्तमान में अधिकांश database libraries के साथ यही स्थिति है), तो अपने *path operation functions* को सामान्य रूप से, केवल `def` के साथ declare करें, जैसे: + +```Python hl_lines="2" +@app.get('/') +def results(): + results = some_library() + return results +``` + +--- + +अगर आपके application को (किसी तरह) किसी और चीज़ से communicate करने और उसके response का इंतज़ार करने की ज़रूरत नहीं है, तो `async def` का उपयोग करें, भले ही आपको अंदर `await` का उपयोग करने की ज़रूरत न हो। + +--- + +अगर आपको पता नहीं है, तो सामान्य `def` का उपयोग करें। + +--- + +**नोट**: आप अपनी ज़रूरत के अनुसार अपने *path operation functions* में `def` और `async def` को mix कर सकते हैं और हर एक को अपने लिए सबसे अच्छे option का उपयोग करके define कर सकते हैं। FastAPI उनके साथ सही काम करेगा। + +किसी भी स्थिति में, ऊपर दिए गए किसी भी case में, FastAPI फिर भी asynchronously काम करेगा और बेहद तेज़ होगा। + +लेकिन ऊपर दिए गए steps को follow करने से, यह कुछ performance optimizations कर पाएगा। + +## तकनीकी विवरण { #technical-details } + +Python के आधुनिक versions **"asynchronous code"** का support करते हैं, जो **"coroutines"** नाम की चीज़ का उपयोग करता है, **`async` और `await`** syntax के साथ। + +आइए नीचे के sections में इस phrase को हिस्सों में देखते हैं: + +* **Asynchronous Code** +* **`async` और `await`** +* **Coroutines** + +## Asynchronous Code { #asynchronous-code } + +Asynchronous code का मतलब बस यह है कि language 💬 के पास computer / program 🤖 को यह बताने का एक तरीका होता है कि code में किसी point पर, उसे 🤖 कहीं और *किसी और चीज़* के finish होने का इंतज़ार करना होगा। मान लें कि उस *किसी और चीज़* को "slow-file" 📝 कहा जाता है। + +तो, उस समय के दौरान, computer कोई और काम कर सकता है, जबकि "slow-file" 📝 finish हो रही होती है। + +फिर computer / program 🤖 हर बार वापस आएगा जब उसे मौका मिलेगा क्योंकि वह फिर से इंतज़ार कर रहा होगा, या जब भी वह 🤖 उस point पर अपना सारा काम finish कर लेगा। और वह 🤖 देखेगा कि जिन tasks का वह इंतज़ार कर रहा था, उनमें से कोई पहले ही finish हो चुका है या नहीं, फिर वह जो भी करना था करेगा। + +इसके बाद, वह 🤖 finish होने वाला पहला task लेता है (मान लें, हमारी "slow-file" 📝) और उसके साथ जो भी करना था उसे जारी रखता है। + +वह "किसी और चीज़ का इंतज़ार" आम तौर पर I/O operations को refer करता है जो अपेक्षाकृत "slow" होते हैं (processor और RAM memory की speed की तुलना में), जैसे इंतज़ार करना: + +* client से data network के माध्यम से भेजे जाने का +* आपके program द्वारा भेजा गया data client द्वारा network के माध्यम से receive किए जाने का +* disk पर किसी file की contents system द्वारा पढ़े जाने और आपके program को दिए जाने का +* आपके program द्वारा system को दी गई contents disk पर लिखे जाने का +* किसी remote API operation का +* किसी database operation के finish होने का +* किसी database query द्वारा results return किए जाने का +* आदि। + +क्योंकि execution time ज़्यादातर I/O operations का इंतज़ार करने में consume होता है, उन्हें "I/O bound" operations कहा जाता है। + +इसे "asynchronous" इसलिए कहा जाता है क्योंकि computer / program को slow task के साथ "synchronized" होने की ज़रूरत नहीं होती, task के finish होने के exact moment का इंतज़ार करते हुए, कुछ भी न करते हुए, ताकि वह task result ले सके और काम जारी रख सके। + +इसके बजाय, "asynchronous" system होने के कारण, task finish होने के बाद, computer / program के वापस आने तक थोड़ा सा line में wait कर सकता है (कुछ microseconds), ताकि computer / program जो काम करने गया था उसे finish करे, और फिर वापस आकर results ले और उनके साथ काम जारी रखे। + +"Synchronous" ("asynchronous" के विपरीत) के लिए वे आमतौर पर "sequential" term भी use करते हैं, क्योंकि computer / program किसी अलग task पर switch करने से पहले sequence में सभी steps follow करता है, भले ही उन steps में इंतज़ार शामिल हो। + +### Concurrency और Burgers { #concurrency-and-burgers } + +ऊपर describe किए गए **asynchronous** code के इस idea को कभी-कभी **"concurrency"** भी कहा जाता है। यह **"parallelism"** से अलग है। + +**Concurrency** और **parallelism** दोनों "अलग-अलग चीज़ें लगभग एक ही समय पर हो रही हैं" से related हैं। + +लेकिन *concurrency* और *parallelism* के बीच के details काफी अलग हैं। + +अंतर देखने के लिए, burgers के बारे में निम्न story imagine करें: + +### Concurrent Burgers { #concurrent-burgers } + +आप अपनी crush के साथ fast food लेने जाते हैं, आप line में खड़े होते हैं जबकि cashier आपके आगे के लोगों से orders ले रहा होता है। 😍 + + + +फिर आपकी बारी आती है, आप अपनी crush और अपने लिए 2 बहुत fancy burgers का order देते हैं। 🍔🍔 + + + +Cashier kitchen में cook से कुछ कहता है ताकि उन्हें पता हो कि उन्हें आपके burgers prepare करने हैं (भले ही वे currently previous clients के burgers prepare कर रहे हों)। + + + +आप pay करते हैं। 💸 + +Cashier आपको आपकी turn का number देता है। + + + +जब आप wait कर रहे होते हैं, आप अपनी crush के साथ एक table चुनते हैं, बैठते हैं और अपनी crush से लंबे समय तक बात करते हैं (क्योंकि आपके burgers बहुत fancy हैं और prepare होने में कुछ समय लेते हैं)। + +जब आप अपनी crush के साथ table पर बैठे होते हैं, burgers का इंतज़ार करते हुए, आप उस समय को यह admire करने में spend कर सकते हैं कि आपकी crush कितनी awesome, cute और smart है ✨😍✨। + + + +Wait करते हुए और अपनी crush से बात करते हुए, time to time, आप counter पर displayed number check करते हैं कि क्या आपकी turn आ गई है। + +फिर किसी point पर, आखिरकार आपकी turn आ जाती है। आप counter पर जाते हैं, अपने burgers लेते हैं और table पर वापस आते हैं। + + + +आप और आपकी crush burgers खाते हैं और अच्छा समय बिताते हैं। ✨ + + + +/// note | नोट + +सुंदर illustrations [Ketrina Thompson](https://www.instagram.com/ketrinadrawsalot) द्वारा। 🎨 + +/// + +--- + +कल्पना करें कि उस story में आप computer / program 🤖 हैं। + +जब आप line में होते हैं, आप बस idle 😴 होते हैं, अपनी turn का इंतज़ार करते हुए, कुछ बहुत "productive" नहीं कर रहे होते। लेकिन line fast है क्योंकि cashier केवल orders ले रहा है (उन्हें prepare नहीं कर रहा), इसलिए यह ठीक है। + +फिर, जब आपकी turn आती है, आप actual "productive" work करते हैं, menu process करते हैं, decide करते हैं कि आपको क्या चाहिए, अपनी crush की choice लेते हैं, pay करते हैं, check करते हैं कि आप correct bill या card दे रहे हैं, check करते हैं कि आपसे सही charge किया गया है, check करते हैं कि order में correct items हैं, आदि। + +लेकिन फिर, भले ही आपके पास अभी burgers नहीं हैं, cashier के साथ आपका work "on pause" ⏸ है, क्योंकि आपको अपने burgers ready होने का wait 🕙 करना है। + +लेकिन जब आप counter से दूर जाते हैं और अपनी turn के number के साथ table पर बैठते हैं, आप अपना attention अपनी crush पर switch 🔀 कर सकते हैं, और उस पर "work" ⏯ 🤓 कर सकते हैं। फिर आप दोबारा कुछ बहुत "productive" कर रहे होते हैं, जैसे अपनी crush 😍 के साथ flirting। + +फिर cashier 💁 counter के display पर आपका number डालकर कहता है "मैंने burgers बना लिए हैं", लेकिन displayed number आपकी turn number में बदलते ही आप तुरंत पागलों की तरह jump नहीं करते। आपको पता है कि कोई आपके burgers नहीं चुराएगा क्योंकि आपके पास आपकी turn का number है, और उनके पास उनका। + +तो आप अपनी crush के story finish करने का इंतज़ार करते हैं (current work ⏯ / process हो रहा task 🤓 finish होना), gentle smile करते हैं और कहते हैं कि आप burgers लेने जा रहे हैं ⏸। + +फिर आप counter 🔀 पर जाते हैं, उस initial task पर जो अब finish हो चुका है ⏯, burgers उठाते हैं, thanks कहते हैं और उन्हें table पर ले जाते हैं। इससे counter के साथ interaction का वह step / task finish हो जाता है ⏹। यह बदले में, "eating burgers" 🔀 ⏯ का एक नया task create करता है, लेकिन "getting burgers" वाला previous task finish हो चुका है ⏹। + +### Parallel Burgers { #parallel-burgers } + +अब imagine करें कि ये "Concurrent Burgers" नहीं, बल्कि "Parallel Burgers" हैं। + +आप अपनी crush के साथ parallel fast food लेने जाते हैं। + +आप line में खड़े होते हैं जबकि कई (मान लें 8) cashiers, जो उसी समय cooks भी हैं, आपके आगे के लोगों से orders ले रहे होते हैं। + +आपसे पहले हर कोई counter छोड़ने से पहले अपने burgers ready होने का wait कर रहा है क्योंकि 8 cashiers में से हर एक next order लेने से पहले तुरंत जाकर burger prepare करता है। + + + +फिर आखिरकार आपकी turn आती है, आप अपनी crush और अपने लिए 2 बहुत fancy burgers का order देते हैं। + +आप pay करते हैं 💸। + + + +Cashier kitchen में जाता है। + +आप counter 🕙 के सामने खड़े होकर wait करते हैं, ताकि आपसे पहले कोई और आपके burgers न ले जाए, क्योंकि turns के लिए कोई numbers नहीं हैं। + + + +क्योंकि आप और आपकी crush इस बात में busy हैं कि कोई आपके आगे न आ जाए और आपके burgers आते ही उन्हें न ले जाए, आप अपनी crush पर attention नहीं दे सकते। 😞 + +यह "synchronous" work है, आप cashier/cook 👨‍🍳 के साथ "synchronized" हैं। आपको wait 🕙 करना है और exact moment पर वहाँ होना है जब cashier/cook 👨‍🍳 burgers finish करता है और आपको देता है, नहीं तो कोई और उन्हें ले सकता है। + + + +फिर आपका cashier/cook 👨‍🍳 लंबे समय तक counter के सामने wait 🕙 कराने के बाद आखिरकार आपके burgers लेकर वापस आता है। + + + +आप अपने burgers लेते हैं और अपनी crush के साथ table पर जाते हैं। + +आप बस उन्हें खाते हैं, और आपका काम हो जाता है। ⏹ + + + +ज़्यादा बात या flirting नहीं हुई क्योंकि अधिकतर समय counter के सामने wait 🕙 करने में spend हुआ। 😞 + +/// note | नोट + +सुंदर illustrations [Ketrina Thompson](https://www.instagram.com/ketrinadrawsalot) द्वारा। 🎨 + +/// + +--- + +Parallel burgers के इस scenario में, आप एक computer / program 🤖 हैं जिसमें दो processors हैं (आप और आपकी crush), दोनों wait 🕙 कर रहे हैं और लंबे समय तक "counter पर waiting" 🕙 में अपना attention ⏯ dedicate कर रहे हैं। + +Fast food store में 8 processors (cashiers/cooks) हैं। जबकि concurrent burgers store में शायद केवल 2 (एक cashier और एक cook) रहे होंगे। + +लेकिन फिर भी, final experience सबसे अच्छा नहीं है। 😞 + +--- + +यह burgers के लिए parallel equivalent story होगी। 🍔 + +इसके एक और "real life" example के लिए, एक bank imagine करें। + +हाल तक, अधिकांश banks में multiple cashiers 👨‍💼👨‍💼👨‍💼👨‍💼 और एक बड़ी line 🕙🕙🕙🕙🕙🕙🕙🕙 होती थी। + +सभी cashiers एक client के बाद दूसरे client के साथ सारा काम कर रहे होते थे 👨‍💼⏯। + +और आपको line में लंबे समय तक wait 🕙 करना पड़ता है या आप अपनी turn खो देते हैं। + +आप शायद अपनी crush 😍 को bank 🏦 में errands करने के लिए अपने साथ नहीं ले जाना चाहेंगे। + +### Burger निष्कर्ष { #burger-conclusion } + +"अपनी crush के साथ fast food burgers" के इस scenario में, क्योंकि बहुत waiting 🕙 है, concurrent system ⏸🔀⏯ रखना कहीं अधिक sensible है। + +अधिकांश web applications के लिए यही case है। + +बहुत, बहुत सारे users, लेकिन आपका server उनकी not-so-good connection द्वारा उनकी requests भेजने का wait 🕙 कर रहा है। + +और फिर responses वापस आने का फिर से wait 🕙 कर रहा है। + +यह "waiting" 🕙 microseconds में measure की जाती है, लेकिन फिर भी, सबको जोड़ने पर, अंत में काफी waiting हो जाती है। + +इसीलिए web APIs के लिए asynchronous ⏸🔀⏯ code use करना बहुत sensible है। + +इसी तरह की asynchronicity ने NodeJS को popular बनाया (भले ही NodeJS parallel नहीं है) और यही Go की programming language के रूप में strength है। + +और यही same level की performance आपको **FastAPI** के साथ मिलती है। + +और क्योंकि आपके पास parallelism और asynchronicity एक ही समय पर हो सकते हैं, आपको tested NodeJS frameworks में से अधिकांश से higher performance मिलती है और Go के बराबर, जो C के करीब एक compiled language है [(यह सब Starlette के कारण)](https://www.techempower.com/benchmarks/#section=data-r17&hw=ph&test=query&l=zijmkf-1)। + +### क्या concurrency parallelism से बेहतर है? { #is-concurrency-better-than-parallelism } + +नहीं! यह story की moral नहीं है। + +Concurrency, parallelism से अलग है। और यह उन **specific** scenarios में बेहतर है जिनमें बहुत waiting शामिल होती है। इसी कारण, web application development के लिए यह आम तौर पर parallelism से बहुत बेहतर है। लेकिन हर चीज़ के लिए नहीं। + +तो, इसे balance करने के लिए, निम्न short story imagine करें: + +> आपको एक बड़ा, गंदा house clean करना है। + +*हाँ, यही पूरी story है*। + +--- + +कहीं भी कोई waiting 🕙 नहीं है, बस बहुत सारा काम करना है, house के multiple places में। + +आप burgers example की तरह turns रख सकते थे, पहले living room, फिर kitchen, लेकिन क्योंकि आप किसी चीज़ का wait 🕙 नहीं कर रहे, बस cleaning and cleaning कर रहे हैं, turns किसी चीज़ को affect नहीं करेंगे। + +Turns (concurrency) के साथ या बिना finish करने में उतना ही time लगेगा और आपने उतना ही काम किया होगा। + +लेकिन इस case में, अगर आप 8 ex-cashier/cooks/now-cleaners ला सकें, और उनमें से हर एक (plus आप) house का एक zone clean करने के लिए ले सके, तो आप extra help के साथ सारा काम **parallel** में कर सकते हैं, और बहुत जल्दी finish कर सकते हैं। + +इस scenario में, cleaners में से हर एक (आप सहित) एक processor होगा, job का अपना part कर रहा होगा। + +और क्योंकि execution time का अधिकतर हिस्सा actual work (waiting के बजाय) में लगता है, और computer में work CPU द्वारा किया जाता है, वे इन problems को "CPU bound" कहते हैं। + +--- + +CPU bound operations के common examples ऐसी चीज़ें हैं जिन्हें complex math processing की ज़रूरत होती है। + +उदाहरण के लिए: + +* **Audio** या **image processing**। +* **Computer vision**: एक image millions of pixels से composed होती है, हर pixel में 3 values / colors होते हैं, उसे process करने के लिए आम तौर पर उन pixels पर कुछ compute करना पड़ता है, सब एक ही समय पर। +* **Machine Learning**: इसमें आम तौर पर बहुत सारे "matrix" और "vector" multiplications की ज़रूरत होती है। Numbers वाली एक huge spreadsheet के बारे में सोचें और उन सभी को एक ही समय पर multiply करना। +* **Deep Learning**: यह Machine Learning का sub-field है, इसलिए, वही लागू होता है। बस इतना है कि multiply करने के लिए numbers की एक single spreadsheet नहीं होती, बल्कि उनका huge set होता है, और कई cases में, आप उन models को build और / या use करने के लिए एक special processor का उपयोग करते हैं। + +### Concurrency + Parallelism: Web + Machine Learning { #concurrency-parallelism-web-machine-learning } + +**FastAPI** के साथ आप concurrency का advantage ले सकते हैं जो web development के लिए बहुत common है (NodeJS का वही main attraction)। + +लेकिन आप Machine Learning systems जैसे **CPU bound** workloads के लिए parallelism और multiprocessing (multiple processes parallel में चलाना) के benefits का भी exploit कर सकते हैं। + +वह, साथ ही यह simple fact कि Python **Data Science**, Machine Learning और खासकर Deep Learning की main language है, FastAPI को Data Science / Machine Learning web APIs और applications (कई अन्य के बीच) के लिए बहुत अच्छा match बनाता है। + +Production में इस parallelism को कैसे achieve करें, यह देखने के लिए [Deployment](deployment/index.md) के बारे में section देखें। + +## `async` और `await` { #async-and-await } + +Python के आधुनिक versions में asynchronous code define करने का बहुत intuitive तरीका है। इससे यह सामान्य "sequential" code जैसा दिखता है और सही moments पर आपके लिए "awaiting" करता है। + +जब कोई operation results देने से पहले waiting require करेगा और इन नए Python features का support रखता है, तो आप उसे ऐसे code कर सकते हैं: + +```Python +burgers = await get_burgers(2) +``` + +यहाँ key `await` है। यह Python को बताता है कि `burgers` में results store करने से पहले उसे `get_burgers(2)` के अपना काम 🕙 finish करने का wait ⏸ करना है। इससे, Python जान जाएगा कि वह meanwhile कुछ और 🔀 ⏯ कर सकता है (जैसे कोई दूसरी request receive करना)। + +`await` के work करने के लिए, इसे ऐसे function के अंदर होना चाहिए जो इस asynchronicity को support करता हो। ऐसा करने के लिए, आप बस इसे `async def` के साथ declare करते हैं: + +```Python hl_lines="1" +async def get_burgers(number: int): + # Burgers बनाने के लिए कुछ asynchronous काम करें + return burgers +``` + +...`def` के बजाय: + +```Python hl_lines="2" +# यह asynchronous नहीं है +def get_sequential_burgers(number: int): + # Burgers बनाने के लिए कुछ sequential काम करें + return burgers +``` + +`async def` के साथ, Python जानता है कि उस function के अंदर उसे `await` expressions के बारे में aware रहना है, और वह उस function के execution को "pause" ⏸ कर सकता है और वापस आने से पहले कुछ और 🔀 कर सकता है। + +जब आप किसी `async def` function को call करना चाहते हैं, तो आपको उसे "await" करना होता है। इसलिए, यह काम नहीं करेगा: + +```Python +# यह काम नहीं करेगा, क्योंकि get_burgers को async def के साथ define किया गया था +burgers = get_burgers(2) +``` + +--- + +तो, अगर आप कोई library use कर रहे हैं जो आपको बताती है कि आप उसे `await` के साथ call कर सकते हैं, तो आपको उसका उपयोग करने वाले *path operation functions* को `async def` के साथ create करना होगा, जैसे: + +```Python hl_lines="2-3" +@app.get('/burgers') +async def read_burgers(): + burgers = await get_burgers(2) + return burgers +``` + +### अधिक तकनीकी विवरण { #more-technical-details } + +आपने notice किया होगा कि `await` केवल `async def` के साथ defined functions के अंदर ही use किया जा सकता है। + +लेकिन उसी समय, `async def` के साथ defined functions को "awaited" होना पड़ता है। इसलिए, `async def` वाले functions केवल `async def` के साथ defined functions के अंदर ही call किए जा सकते हैं। + +तो, egg और chicken के बारे में, आप first `async` function को कैसे call करते हैं? + +अगर आप **FastAPI** के साथ काम कर रहे हैं तो आपको इसकी चिंता करने की ज़रूरत नहीं है, क्योंकि वह "first" function आपका *path operation function* होगा, और FastAPI जानता होगा कि सही काम कैसे करना है। + +लेकिन अगर आप FastAPI के बिना `async` / `await` use करना चाहते हैं, तो आप ऐसा भी कर सकते हैं। + +### अपना async code लिखें { #write-your-own-async-code } + +Starlette (और **FastAPI**) [AnyIO](https://anyio.readthedocs.io/en/stable/) पर based हैं, जो इसे Python की standard library [asyncio](https://docs.python.org/3/library/asyncio-task.html) और [Trio](https://trio.readthedocs.io/en/stable/) दोनों के साथ compatible बनाता है। + +विशेष रूप से, आप अपने advanced concurrency use cases के लिए सीधे [AnyIO](https://anyio.readthedocs.io/en/stable/) use कर सकते हैं जिन्हें आपके अपने code में अधिक advanced patterns की ज़रूरत होती है। + +और भले ही आप FastAPI use नहीं कर रहे हों, आप high compatibility और इसके benefits (जैसे *structured concurrency*) पाने के लिए [AnyIO](https://anyio.readthedocs.io/en/stable/) के साथ अपने खुद के async applications भी लिख सकते हैं। + +मैंने AnyIO के ऊपर एक और library बनाई, ऊपर एक thin layer के रूप में, ताकि type annotations को थोड़ा improve किया जा सके और बेहतर **autocompletion**, **inline errors**, आदि मिल सकें। इसमें एक friendly introduction और tutorial भी है ताकि आपको **समझने** और **अपना async code** लिखने में मदद मिले: [Asyncer](https://asyncer.tiangolo.com/)। यह विशेष रूप से useful होगा अगर आपको **async code को regular** (blocking/synchronous) code के साथ **combine** करना हो। + +### Asynchronous code के अन्य forms { #other-forms-of-asynchronous-code } + +`async` और `await` use करने की यह style language में relatively new है। + +लेकिन यह asynchronous code के साथ काम करना बहुत आसान बनाती है। + +यही same syntax (या लगभग identical) हाल ही में JavaScript के modern versions (Browser और NodeJS में) में भी शामिल किया गया था। + +लेकिन उससे पहले, asynchronous code handle करना कहीं अधिक complex और difficult था। + +Python के previous versions में, आप threads या [Gevent](https://www.gevent.org/) use कर सकते थे। लेकिन code समझने, debug करने और उसके बारे में सोचने के लिए कहीं अधिक complex होता है। + +NodeJS / Browser JavaScript के previous versions में, आप "callbacks" use करते। जो "callback hell" तक ले जाता है। + +## Coroutines { #coroutines } + +**Coroutine** बस उस चीज़ के लिए बहुत fancy term है जो किसी `async def` function द्वारा return की जाती है। Python जानता है कि यह function जैसी कोई चीज़ है, जिसे वह start कर सकता है और जो किसी point पर end होगी, लेकिन यह internally pause ⏸ भी हो सकती है, जब भी इसके अंदर कोई `await` हो। + +लेकिन asynchronous code को `async` और `await` के साथ use करने की यह सारी functionality कई बार "coroutines" use करने के रूप में summarize की जाती है। यह Go की main key feature, "Goroutines" से comparable है। + +## निष्कर्ष { #conclusion } + +आइए ऊपर वाला वही phrase देखें: + +> Python के आधुनिक versions **"asynchronous code"** का support करते हैं, जो **"coroutines"** नाम की चीज़ का उपयोग करता है, **`async` और `await`** syntax के साथ। + +अब यह अधिक sense बनाना चाहिए। ✨ + +यह सब FastAPI (Starlette के माध्यम से) को power करता है और इसे इतनी impressive performance देता है। + +## बहुत तकनीकी विवरण { #very-technical-details } + +/// warning | चेतावनी + +आप शायद इसे skip कर सकते हैं। + +ये **FastAPI** अंदर से कैसे काम करता है, इसके बहुत technical details हैं। + +अगर आपके पास काफी technical knowledge (coroutines, threads, blocking, आदि) है और आप curious हैं कि FastAPI `async def` बनाम normal `def` को कैसे handle करता है, तो आगे बढ़ें। + +/// + +### Path operation functions { #path-operation-functions } + +जब आप किसी *path operation function* को `async def` के बजाय normal `def` के साथ declare करते हैं, तो इसे directly call करने के बजाय (क्योंकि यह server को block करेगा), एक external threadpool में run किया जाता है जिसे फिर awaited किया जाता है। + +अगर आप किसी दूसरे async framework से आ रहे हैं जो ऊपर described तरीके से काम नहीं करता और आप tiny performance gain (लगभग 100 nanoseconds) के लिए trivial compute-only *path operation functions* को plain `def` के साथ define करने के आदी हैं, तो कृपया ध्यान दें कि **FastAPI** में effect बिल्कुल उल्टा होगा। इन cases में, `async def` use करना बेहतर है, जब तक कि आपके *path operation functions* ऐसा code use न करें जो blocking I/O perform करता हो। + +फिर भी, दोनों situations में, संभावना है कि **FastAPI** आपके previous framework से [फिर भी तेज़ होगा](index.md#performance) (या कम से कम comparable होगा)। + +### Dependencies { #dependencies } + +[Dependencies](tutorial/dependencies/index.md) के लिए भी यही लागू होता है। अगर कोई dependency `async def` के बजाय standard `def` function है, तो उसे external threadpool में run किया जाता है। + +### Sub-dependencies { #sub-dependencies } + +आपके पास multiple dependencies और [sub-dependencies](tutorial/dependencies/sub-dependencies.md) हो सकती हैं जो एक-दूसरे को require करती हैं (function definitions के parameters के रूप में), उनमें से कुछ `async def` के साथ created हो सकती हैं और कुछ normal `def` के साथ। यह फिर भी work करेगा, और normal `def` के साथ created ones को "awaited" होने के बजाय external thread (threadpool से) पर call किया जाएगा। + +### अन्य utility functions { #other-utility-functions } + +कोई भी अन्य utility function जिसे आप directly call करते हैं, normal `def` या `async def` के साथ created हो सकता है और FastAPI आपके उसे call करने के तरीके को affect नहीं करेगा। + +यह उन functions के contrast में है जिन्हें FastAPI आपके लिए call करता है: *path operation functions* और dependencies। + +अगर आपका utility function `def` वाला normal function है, तो उसे directly call किया जाएगा (जैसा आप अपने code में लिखते हैं), threadpool में नहीं; अगर function `async def` के साथ created है तो आपको अपने code में उसे call करते समय उस function को `await` करना चाहिए। + +--- + +फिर से, ये बहुत technical details हैं जो शायद useful होंगे अगर आप इन्हें search करते हुए आए हैं। + +अन्यथा, आपको ऊपर के section की guidelines के साथ ठीक होना चाहिए: जल्दी में हैं?। diff --git a/docs/hi/docs/benchmarks.md b/docs/hi/docs/benchmarks.md new file mode 100644 index 000000000..11a22bcb8 --- /dev/null +++ b/docs/hi/docs/benchmarks.md @@ -0,0 +1,34 @@ +# Benchmarks { #benchmarks } + +स्वतंत्र TechEmpower benchmarks दिखाते हैं कि Uvicorn के अंतर्गत चलने वाले **FastAPI** applications [उपलब्ध सबसे तेज़ Python frameworks में से एक](https://www.techempower.com/benchmarks/#section=test&runid=7464e520-0dc2-473d-bd34-dbdfd7e85911&hw=ph&test=query&l=zijzen-7) हैं, केवल Starlette और Uvicorn स्वयं से नीचे (जिनका उपयोग FastAPI द्वारा internally किया जाता है)। + +लेकिन benchmarks और comparisons देखते समय आपको निम्न बातों को ध्यान में रखना चाहिए। + +## Benchmarks और speed { #benchmarks-and-speed } + +जब आप benchmarks देखते हैं, तो अलग-अलग प्रकार के कई tools को equivalent मानकर compare होते देखना आम बात है। + +विशेष रूप से, Uvicorn, Starlette और FastAPI को एक साथ compare होते देखना (कई अन्य tools के साथ)। + +Tool जितनी सरल समस्या हल करता है, उसे उतनी ही बेहतर performance मिलेगी। और अधिकांश benchmarks, tool द्वारा प्रदान की जाने वाली अतिरिक्त features को test नहीं करते। + +Hierarchy इस प्रकार है: + +* **Uvicorn**: एक ASGI server + * **Starlette**: (Uvicorn का उपयोग करता है) एक web microframework + * **FastAPI**: (Starlette का उपयोग करता है) APIs बनाने के लिए कई अतिरिक्त features वाला एक API microframework, जिसमें data validation आदि शामिल हैं। + +* **Uvicorn**: + * इसकी performance सबसे अच्छी होगी, क्योंकि इसमें server स्वयं के अलावा बहुत अधिक extra code नहीं होता। + * आप सीधे Uvicorn में application नहीं लिखेंगे। इसका मतलब होगा कि आपके code में कमोबेश, कम से कम, Starlette (या **FastAPI**) द्वारा प्रदान किया गया सारा code शामिल करना पड़ेगा। और यदि आपने ऐसा किया, तो आपके final application में framework का उपयोग करने और अपने app code तथा bugs को कम करने जितना ही overhead होगा। + * यदि आप Uvicorn की तुलना कर रहे हैं, तो इसकी तुलना Daphne, Hypercorn, uWSGI आदि से करें। Application servers से। +* **Starlette**: + * Uvicorn के बाद इसकी performance अगली सबसे अच्छी होगी। वास्तव में, Starlette चलने के लिए Uvicorn का उपयोग करता है। इसलिए, संभवतः यह केवल अधिक code execute करने के कारण Uvicorn से "धीमा" हो सकता है। + * लेकिन यह आपको simple web applications बनाने के लिए tools देता है, जैसे paths पर आधारित routing आदि। + * यदि आप Starlette की तुलना कर रहे हैं, तो इसकी तुलना Sanic, Flask, Django आदि से करें। Web frameworks (या microframeworks) से। +* **FastAPI**: + * जैसे Starlette, Uvicorn का उपयोग करता है और उससे तेज़ नहीं हो सकता, वैसे ही **FastAPI**, Starlette का उपयोग करता है, इसलिए यह उससे तेज़ नहीं हो सकता। + * FastAPI, Starlette के ऊपर और features प्रदान करता है। ऐसे features जिनकी आपको APIs बनाते समय लगभग हमेशा आवश्यकता होती है, जैसे data validation और serialization। और इसका उपयोग करके आपको automatic documentation मुफ्त में मिलती है (automatic documentation running applications में overhead भी नहीं जोड़ती, यह startup पर generate होती है)। + * यदि आपने FastAPI का उपयोग नहीं किया और सीधे Starlette (या कोई अन्य tool, जैसे Sanic, Flask, Responder आदि) का उपयोग किया, तो आपको सभी data validation और serialization स्वयं implement करने पड़ेंगे। इसलिए, आपके final application में फिर भी उतना ही overhead होगा जितना FastAPI का उपयोग करके बनाए जाने पर होता। और कई मामलों में, यह data validation और serialization applications में लिखे गए code का सबसे बड़ा हिस्सा होता है। + * इसलिए, FastAPI का उपयोग करके आप development time, bugs और lines of code बचाते हैं, और संभवतः आपको वही performance (या बेहतर) मिलेगी जो आपको इसे उपयोग न करने पर मिलती (क्योंकि तब आपको यह सब अपने code में implement करना पड़ता)। + * यदि आप FastAPI की तुलना कर रहे हैं, तो इसकी तुलना ऐसे web application framework (या tools के set) से करें जो data validation, serialization और documentation प्रदान करता हो, जैसे Flask-apispec, NestJS, Molten आदि। ऐसे frameworks जिनमें integrated automatic data validation, serialization और documentation हो। diff --git a/docs/hi/docs/editor-support.md b/docs/hi/docs/editor-support.md new file mode 100644 index 000000000..eee38f058 --- /dev/null +++ b/docs/hi/docs/editor-support.md @@ -0,0 +1,23 @@ +# Editor Support { #editor-support } + +आधिकारिक [FastAPI Extension](https://marketplace.visualstudio.com/items?itemName=FastAPILabs.fastapi-vscode) आपके FastAPI development workflow को *path operation* discovery, navigation, साथ ही FastAPI Cloud deployment और live log streaming के साथ बेहतर बनाता है। + +Extension के बारे में अधिक जानकारी के लिए, [GitHub repository](https://github.com/fastapi/fastapi-vscode) पर README देखें। + +## Setup और Installation { #setup-and-installation } + +**FastAPI Extension** [VS Code](https://code.visualstudio.com/) और [Cursor](https://www.cursor.com/) दोनों के लिए उपलब्ध है। इसे हर editor के Extensions panel से सीधे "FastAPI" खोजकर और **FastAPI Labs** द्वारा प्रकाशित extension चुनकर install किया जा सकता है। यह extension browser-based editors जैसे [vscode.dev](https://vscode.dev) और [github.dev](https://github.dev) में भी काम करता है। + +### Application Discovery { #application-discovery } + +Default रूप से, extension आपके workspace में `FastAPI()` instantiate करने वाली files को scan करके FastAPI applications को अपने-आप discover करेगा। यदि auto-detection आपके project structure के लिए काम नहीं करता, तो आप `pyproject.toml` में `[tool.fastapi]` के माध्यम से या module notation (जैसे `myapp.main:app`) का उपयोग करके `fastapi.entryPoint` VS Code setting में entrypoint specify कर सकते हैं। + +## Features { #features } + +- **Path Operation Explorer** - आपके application में सभी *path operations* का sidebar tree view। किसी भी route या router definition पर जाने के लिए click करें। +- **Route Search** - Ctrl + Shift + E (macOS पर: Cmd + Shift + E) के साथ path, method, या name के आधार पर search करें। +- **CodeLens Navigation** - test client calls (जैसे `client.get('/items')`) के ऊपर clickable links, जो tests और implementation के बीच quick navigation के लिए matching *path operation* पर ले जाते हैं। +- **Deploy to FastAPI Cloud** - आपकी app को [FastAPI Cloud](https://fastapicloud.com/) पर one-click deployment। +- **Stream Application Logs** - level filtering और text search के साथ आपके FastAPI Cloud-deployed application से real-time log streaming। + +यदि आप extension के features से परिचित होना चाहते हैं, तो Command Palette (Ctrl + Shift + P या macOS पर: Cmd + Shift + P) खोलकर और "Welcome: Open walkthrough..." चुनकर, फिर "Get started with FastAPI" walkthrough चुनकर extension walkthrough देख सकते हैं। diff --git a/docs/hi/docs/fastapi-cli.md b/docs/hi/docs/fastapi-cli.md new file mode 100644 index 000000000..87a1a983f --- /dev/null +++ b/docs/hi/docs/fastapi-cli.md @@ -0,0 +1,134 @@ +# FastAPI CLI { #fastapi-cli } + +**FastAPI CLI** एक command line प्रोग्राम है जिसका उपयोग आप अपने FastAPI ऐप को serve करने, अपने FastAPI project को manage करने, और भी बहुत कुछ करने के लिए कर सकते हैं। + +जब आप FastAPI install करते हैं (जैसे `pip install "fastapi[standard]"` के साथ), तो इसके साथ एक command line प्रोग्राम आता है जिसे आप terminal में चला सकते हैं। + +development के लिए अपना FastAPI ऐप चलाने के लिए, आप `fastapi dev` command का उपयोग कर सकते हैं: + +
+ +```console +$ fastapi dev + + FastAPI Starting development server 🚀 + + Searching for package file structure from directories with + __init__.py files + Importing from /home/user/code/awesomeapp + + module 🐍 main.py + + code Importing the FastAPI app object from the module with the + following code: + + from main import app + + app Using import string: main:app + + server Server started at http://127.0.0.1:8000 + server Documentation at http://127.0.0.1:8000/docs + + tip Running in development mode, for production use: + fastapi run + + Logs: + + INFO Will watch for changes in these directories: + ['/home/user/code/awesomeapp'] + INFO Uvicorn running on http://127.0.0.1:8000 (Press CTRL+C to + quit) + INFO Started reloader process [383138] using WatchFiles + INFO Started server process [383153] + INFO Waiting for application startup. + INFO Application startup complete. +``` + +
+ +/// tip | सुझाव + +production के लिए आप `fastapi dev` की जगह `fastapi run` का उपयोग करेंगे। 🚀 + +/// + +आंतरिक रूप से, **FastAPI CLI** [Uvicorn](https://www.uvicorn.dev) का उपयोग करता है, जो एक high-performance, production-ready, ASGI server है। 😎 + +`fastapi` CLI चलाने के लिए FastAPI ऐप को अपने-आप detect करने की कोशिश करेगा, यह मानते हुए कि यह `main.py` file में `app` नाम का object है (या कुछ अन्य variants में से कोई एक)। + +लेकिन आप उपयोग किए जाने वाले ऐप को स्पष्ट रूप से configure कर सकते हैं। + +## ऐप `entrypoint` को `pyproject.toml` में configure करें { #configure-the-app-entrypoint-in-pyproject-toml } + +आप `pyproject.toml` file में यह configure कर सकते हैं कि आपका ऐप कहाँ स्थित है, जैसे: + +```toml +[tool.fastapi] +entrypoint = "main:app" +``` + +वह `entrypoint` `fastapi` command को बताएगा कि उसे ऐप को इस तरह import करना चाहिए: + +```python +from main import app +``` + +अगर आपका code इस तरह structured था: + +``` +. +├── backend +│   ├── main.py +│   ├── __init__.py +``` + +तो आप `entrypoint` को इस तरह set करेंगे: + +```toml +[tool.fastapi] +entrypoint = "backend.main:app" +``` + +जो इसके बराबर होगा: + +```python +from backend.main import app +``` + +### path के साथ या `--entrypoint` CLI option के साथ `fastapi dev` { #fastapi-dev-with-path-or-with-entrypoint-cli-option } + +आप `fastapi dev` command को file path भी pass कर सकते हैं, और यह उपयोग किए जाने वाले FastAPI app object का अनुमान लगा लेगा: + +```console +$ fastapi dev main.py +``` + +या, आप `fastapi dev` command को `--entrypoint` option भी pass कर सकते हैं: + +```console +$ fastapi dev --entrypoint main:app +``` + +लेकिन आपको हर बार `fastapi` command call करते समय सही path\entrypoint pass करना याद रखना होगा। + +इसके अतिरिक्त, अन्य tools इसे ढूँढने में सक्षम नहीं हो सकते हैं, उदाहरण के लिए [VS Code एक्सटेंशन](editor-support.md) या [FastAPI Cloud](https://fastapicloud.com), इसलिए `pyproject.toml` में `entrypoint` का उपयोग करने की सिफारिश की जाती है। + +## `fastapi dev` { #fastapi-dev } + +`fastapi dev` चलाने से development mode शुरू होता है। + +Default रूप से, **auto-reload** enabled होता है, जो आपके code में changes करने पर server को अपने-आप reload कर देता है। यह resource-intensive है और disabled होने की तुलना में कम stable हो सकता है। आपको इसे केवल development के लिए ही उपयोग करना चाहिए। यह IP address `127.0.0.1` पर भी listen करता है, जो आपकी machine का खुद से ही communicate करने वाला IP है (`localhost`)। + +## `fastapi run` { #fastapi-run } + +`fastapi run` execute करने से FastAPI production mode में शुरू होता है। + +Default रूप से, **auto-reload** disabled होता है। यह IP address `0.0.0.0` पर भी listen करता है, जिसका मतलब सभी available IP addresses है, इस तरह यह उस machine से communicate कर सकने वाले किसी भी व्यक्ति के लिए publicly accessible होगा। आम तौर पर आप production में इसे इसी तरह चलाएँगे, उदाहरण के लिए, एक container में। + +अधिकतर मामलों में आपके पास ऊपर से HTTPS handle करने वाला "termination proxy" होगा (और होना चाहिए), यह इस पर निर्भर करेगा कि आप अपना application कैसे deploy करते हैं, आपका provider आपके लिए यह कर सकता है, या आपको इसे खुद set up करने की ज़रूरत हो सकती है। + +/// tip | सुझाव + +आप इसके बारे में [deployment documentation](deployment/index.md) में और जान सकते हैं। + +/// diff --git a/docs/hi/docs/features.md b/docs/hi/docs/features.md new file mode 100644 index 000000000..a3f52427d --- /dev/null +++ b/docs/hi/docs/features.md @@ -0,0 +1,201 @@ +# विशेषताएँ { #features } + +## FastAPI की विशेषताएँ { #fastapi-features } + +**FastAPI** आपको निम्नलिखित देता है: + +### खुले मानकों पर आधारित { #based-on-open-standards } + +* API बनाने के लिए [**OpenAPI**](https://github.com/OAI/OpenAPI-Specification), जिसमें path operations, parameters, request bodies, security, आदि की घोषणाएँ शामिल हैं। +* [**JSON Schema**](https://json-schema.org/) के साथ automatic data model documentation (क्योंकि OpenAPI स्वयं JSON Schema पर आधारित है)। +* इन मानकों के इर्द-गिर्द डिज़ाइन किया गया, एक बहुत सावधानीपूर्वक अध्ययन के बाद। ऊपर से बाद में जोड़ी गई परत की तरह नहीं। +* यह कई भाषाओं में automatic **client code generation** का उपयोग करने की भी अनुमति देता है। + +### Automatic docs { #automatic-docs } + +Interactive API documentation और exploration web user interfaces। क्योंकि framework OpenAPI पर आधारित है, कई विकल्प हैं, जिनमें 2 default रूप से शामिल हैं। + +* [**Swagger UI**](https://github.com/swagger-api/swagger-ui), interactive exploration के साथ, अपने API को सीधे browser से call और test करें। + +![Swagger UI इंटरैक्शन](https://fastapi.tiangolo.com/img/index/index-03-swagger-02.png) + +* [**ReDoc**](https://github.com/Rebilly/ReDoc) के साथ वैकल्पिक API documentation। + +![ReDoc](https://fastapi.tiangolo.com/img/index/index-06-redoc-02.png) + +### सिर्फ़ आधुनिक Python { #just-modern-python } + +यह सब standard **Python type** declarations पर आधारित है (Pydantic की बदौलत)। सीखने के लिए कोई नया syntax नहीं। सिर्फ़ standard modern Python। + +अगर आपको Python types का उपयोग कैसे करें, इसका 2 मिनट का छोटा refresher चाहिए (भले ही आप FastAPI का उपयोग न करते हों), तो छोटा tutorial देखें: [Python Types](python-types.md)। + +आप types के साथ standard Python लिखते हैं: + +```Python +from datetime import date + +from pydantic import BaseModel + +# किसी variable को str के रूप में घोषित करें +# और function के अंदर editor support पाएँ +def main(user_id: str): + return user_id + + +# एक Pydantic model +class User(BaseModel): + id: int + name: str + joined: date +``` + +फिर उसे इस तरह उपयोग किया जा सकता है: + +```Python +my_user: User = User(id=3, name="John Doe", joined="2018-07-19") + +second_user_data = { + "id": 4, + "name": "Mary", + "joined": "2018-11-30", +} + +my_second_user: User = User(**second_user_data) +``` + +/// note | नोट + +`**second_user_data` का मतलब है: + +`second_user_data` dict की keys और values को सीधे key-value arguments के रूप में पास करें, जो इसके बराबर है: `User(id=4, name="Mary", joined="2018-11-30")` + +/// + +### Editor support { #editor-support } + +पूरे framework को उपयोग में आसान और सहज बनाने के लिए डिज़ाइन किया गया था, development शुरू करने से पहले ही सभी निर्णयों को कई editors पर test किया गया, ताकि सबसे अच्छा development experience सुनिश्चित किया जा सके। + +Python developer surveys में, यह स्पष्ट है [कि सबसे अधिक उपयोग की जाने वाली सुविधाओं में से एक "autocompletion" है](https://www.jetbrains.com/research/python-developers-survey-2017/#tools-and-features)। + +पूरा **FastAPI** framework इसे पूरा करने के लिए डिज़ाइन किया गया है। Autocompletion हर जगह काम करता है। + +आपको शायद ही कभी docs पर वापस आने की आवश्यकता होगी। + +यहाँ बताया गया है कि आपका editor आपकी कैसे मदद कर सकता है: + +* [Visual Studio Code](https://code.visualstudio.com/) में: + +![editor support](https://fastapi.tiangolo.com/img/vscode-completion.png) + +* [PyCharm](https://www.jetbrains.com/pycharm/) में: + +![editor support](https://fastapi.tiangolo.com/img/pycharm-completion.png) + +आपको ऐसे code में completion मिलेगा जिसे आप पहले असंभव भी मान सकते थे। जैसे, किसी request से आने वाले JSON body (जो nested भी हो सकता था) के अंदर `price` key। + +अब गलत key names टाइप करने, docs के बीच आगे-पीछे जाने, या यह खोजने के लिए ऊपर-नीचे scroll करने की ज़रूरत नहीं कि आपने आखिर `username` उपयोग किया था या `user_name`। + +### संक्षिप्त { #short } + +हर चीज़ के लिए इसके समझदार **defaults** हैं, और हर जगह optional configurations हैं। सभी parameters को आपकी ज़रूरत के अनुसार और आपकी ज़रूरत की API define करने के लिए fine-tune किया जा सकता है। + +लेकिन default रूप से, सब कुछ **"बस काम करता है"**। + +### Validation { #validation } + +* अधिकांश (या सभी?) Python **data types** के लिए validation, जिनमें शामिल हैं: + * JSON objects (`dict`)। + * JSON array (`list`) जो item types define करता है। + * String (`str`) fields, जिनमें min और max lengths define होती हैं। + * Numbers (`int`, `float`) जिनमें min और max values, आदि। + +* अधिक असामान्य types के लिए validation, जैसे: + * URL। + * Email। + * UUID। + * ...और अन्य। + +सारी validation well-established और robust **Pydantic** द्वारा handle की जाती है। + +### Security और authentication { #security-and-authentication } + +Security और authentication integrated हैं। Databases या data models के साथ किसी भी compromise के बिना। + +OpenAPI में define की गई सभी security schemes, जिनमें शामिल हैं: + +* HTTP Basic। +* **OAuth2** (**JWT tokens** के साथ भी)। [OAuth2 with JWT](tutorial/security/oauth2-jwt.md) पर tutorial देखें। +* API keys: + * Headers में। + * Query parameters में। + * Cookies में, आदि। + +साथ ही Starlette की सभी security features (जिसमें **session cookies** भी शामिल हैं)। + +सब reusable tools और components के रूप में बनाए गए हैं, जिन्हें आपके systems, data stores, relational और NoSQL databases, आदि के साथ integrate करना आसान है। + +### Dependency Injection { #dependency-injection } + +FastAPI में एक बेहद आसान, लेकिन बेहद शक्तिशाली Dependency Injection system शामिल है। + +* Dependencies की भी dependencies हो सकती हैं, जिससे dependencies की hierarchy या **"graph"** बनता है। +* सब कुछ framework द्वारा **automatically handled** होता है। +* सभी dependencies requests से data मांग सकती हैं और **path operation** constraints तथा automatic documentation को बढ़ा सकती हैं। +* Dependencies में define किए गए *path operation* parameters के लिए भी **automatic validation**। +* जटिल user authentication systems, **database connections**, आदि के लिए support। +* Databases, frontends, आदि के साथ **कोई compromise नहीं**। लेकिन उन सभी के साथ आसान integration। + +### असीमित "plug-ins" { #unlimited-plug-ins } + +या दूसरे शब्दों में, उनकी आवश्यकता नहीं है, अपनी ज़रूरत का code import करें और उपयोग करें। + +किसी भी integration को (dependencies के साथ) उपयोग में इतना सरल बनाने के लिए डिज़ाइन किया गया है कि आप अपनी application के लिए उसी structure और syntax का उपयोग करके 2 lines of code में एक "plug-in" बना सकते हैं, जो आपके *path operations* के लिए उपयोग होता है। + +### Tested { #tested } + +* 100% test coverage। +* 100% type annotated code base। +* Production applications में उपयोग किया गया। + +## Starlette की विशेषताएँ { #starlette-features } + +**FastAPI** [**Starlette**](https://www.starlette.dev/) के साथ पूरी तरह compatible है (और उसी पर आधारित है)। इसलिए, आपके पास जो भी अतिरिक्त Starlette code है, वह भी काम करेगा। + +`FastAPI` वास्तव में `Starlette` का एक sub-class है। इसलिए, अगर आप पहले से Starlette जानते हैं या उपयोग करते हैं, तो अधिकांश functionality उसी तरह काम करेगी। + +**FastAPI** के साथ आपको **Starlette** की सभी features मिलती हैं (क्योंकि FastAPI मूलतः steroids पर Starlette है): + +* सचमुच प्रभावशाली performance। यह [उपलब्ध सबसे तेज़ Python frameworks में से एक है, **NodeJS** और **Go** के बराबर](https://github.com/encode/starlette#performance)। +* **WebSocket** support। +* In-process background tasks। +* Startup और shutdown events। +* HTTPX पर बना test client। +* **CORS**, GZip, Static Files, Streaming responses। +* **Session और Cookie** support। +* 100% test coverage। +* 100% type annotated codebase। + +## Pydantic की विशेषताएँ { #pydantic-features } + +**FastAPI** [**Pydantic**](https://docs.pydantic.dev/) के साथ पूरी तरह compatible है (और उसी पर आधारित है)। इसलिए, आपके पास जो भी अतिरिक्त Pydantic code है, वह भी काम करेगा। + +इसमें Pydantic पर आधारित external libraries भी शामिल हैं, जैसे databases के लिए ORMs और ODMs। + +इसका यह भी मतलब है कि कई मामलों में आप request से मिलने वाले उसी object को **सीधे database में** पास कर सकते हैं, क्योंकि सब कुछ automatically validated होता है। + +उसी तरह उल्टा भी लागू होता है, कई मामलों में आप database से मिलने वाले object को **सीधे client को** पास कर सकते हैं। + +**FastAPI** के साथ आपको **Pydantic** की सभी features मिलती हैं (क्योंकि FastAPI सभी data handling के लिए Pydantic पर आधारित है): + +* **कोई brainfuck नहीं**: + * सीखने के लिए कोई नई schema definition micro-language नहीं। + * अगर आप Python types जानते हैं, तो आप जानते हैं कि Pydantic का उपयोग कैसे करना है। +* आपके **IDE/linter/brain** के साथ अच्छी तरह काम करता है: + * क्योंकि pydantic data structures केवल उन classes के instances होते हैं जिन्हें आप define करते हैं; auto-completion, linting, mypy और आपकी intuition, सभी आपके validated data के साथ सही ढंग से काम करने चाहिए। +* **Complex structures** validate करें: + * Hierarchical Pydantic models, Python `typing` के `List` और `Dict`, आदि का उपयोग। + * और validators complex data schemas को JSON Schema के रूप में स्पष्ट और आसानी से define, check और document करने देते हैं। + * आपके पास deeply **nested JSON** objects हो सकते हैं और वे सभी validated और annotated हो सकते हैं। +* **Extensible**: + * Pydantic custom data types को define करने देता है या आप validator decorator से decorated model पर methods के साथ validation extend कर सकते हैं। +* 100% test coverage। diff --git a/docs/hi/docs/history-design-future.md b/docs/hi/docs/history-design-future.md new file mode 100644 index 000000000..a3b97d154 --- /dev/null +++ b/docs/hi/docs/history-design-future.md @@ -0,0 +1,79 @@ +# इतिहास, डिज़ाइन और भविष्य { #history-design-and-future } + +कुछ समय पहले, [एक **FastAPI** user ने पूछा](https://github.com/fastapi/fastapi/issues/3#issuecomment-454956920): + +> इस project का इतिहास क्या है? ऐसा लगता है कि यह कुछ ही हफ्तों में कहीं से भी सीधे शानदार बन गया [...] + +यहाँ उस इतिहास का एक छोटा सा हिस्सा है। + +## विकल्प { #alternatives } + +मैं कई वर्षों से जटिल requirements वाली APIs बना रहा हूँ (Machine Learning, distributed systems, asynchronous jobs, NoSQL databases, आदि), और developers की कई teams का नेतृत्व कर चुका हूँ। + +इसके हिस्से के रूप में, मुझे कई विकल्पों की जाँच, परीक्षण और उपयोग करना पड़ा। + +**FastAPI** का इतिहास काफी हद तक इसके पूर्ववर्तियों का इतिहास है। + +जैसा कि [विकल्प](alternatives.md) section में कहा गया है: + +
+ +दूसरों के पिछले काम के बिना **FastAPI** मौजूद नहीं होता। + +इससे पहले कई tools बनाए गए हैं जिन्होंने इसके निर्माण को प्रेरित करने में मदद की है। + +मैं कई वर्षों से एक नया framework बनाने से बचता रहा। पहले मैंने **FastAPI** द्वारा कवर किए गए सभी features को कई अलग-अलग frameworks, plug-ins और tools का उपयोग करके हल करने की कोशिश की। + +लेकिन किसी बिंदु पर, ऐसा कुछ बनाने के अलावा कोई विकल्प नहीं बचा था जो ये सभी features प्रदान करे, पिछले tools से सर्वोत्तम ideas ले और उन्हें सर्वोत्तम संभव तरीके से जोड़े, साथ ही ऐसी language features का उपयोग करे जो पहले उपलब्ध भी नहीं थीं (Python 3.6+ type hints)। + +
+ +## जाँच-पड़ताल { #investigation } + +सभी पिछले विकल्पों का उपयोग करके मुझे उन सभी से सीखने, ideas लेने, और उन्हें अपने तथा जिन developer teams के साथ मैंने काम किया है उनके लिए सबसे अच्छे तरीके से मिलाने का अवसर मिला। + +उदाहरण के लिए, यह स्पष्ट था कि आदर्श रूप से इसे standard Python type hints पर आधारित होना चाहिए। + +साथ ही, सबसे अच्छा तरीका पहले से मौजूद standards का उपयोग करना था। + +इसलिए, **FastAPI** की coding शुरू करने से पहले ही, मैंने OpenAPI, JSON Schema, OAuth2 आदि के specs का अध्ययन करने में कई महीने बिताए। उनके संबंध, overlap और differences को समझा। + +## डिज़ाइन { #design } + +फिर मैंने उस developer "API" को डिज़ाइन करने में कुछ समय लगाया जिसे मैं एक user के रूप में पाना चाहता था (FastAPI का उपयोग करने वाले developer के रूप में)। + +मैंने सबसे लोकप्रिय Python editors में कई ideas का परीक्षण किया: PyCharm, VS Code, Jedi आधारित editors। + +पिछले [Python Developer Survey](https://www.jetbrains.com/research/python-developers-survey-2018/#development-tools) के अनुसार, यह लगभग 80% users को कवर करता है। + +इसका मतलब है कि **FastAPI** को विशेष रूप से उन editors के साथ test किया गया था जिनका उपयोग 80% Python developers करते हैं। और चूँकि अधिकांश अन्य editors भी समान तरीके से काम करते हैं, इसके सभी लाभ लगभग सभी editors के लिए काम करने चाहिए। + +इस तरह मैं code duplication को जितना संभव हो उतना कम करने, हर जगह completion पाने, type और error checks आदि के सर्वोत्तम तरीके खोज सका। + +सब कुछ इस तरह से किया गया कि सभी developers को सर्वोत्तम development experience मिल सके। + +## Requirements { #requirements } + +कई विकल्पों का परीक्षण करने के बाद, मैंने तय किया कि मैं इसके लाभों के लिए [**Pydantic**](https://docs.pydantic.dev/) का उपयोग करूँगा। + +फिर मैंने इसमें योगदान दिया, ताकि इसे JSON Schema के साथ पूरी तरह compliant बनाया जा सके, constraint declarations को define करने के अलग-अलग तरीकों का समर्थन किया जा सके, और कई editors में tests के आधार पर editor support (type checks, autocompletion) को बेहतर बनाया जा सके। + +Development के दौरान, मैंने [**Starlette**](https://www.starlette.dev/) में भी योगदान दिया, जो दूसरी मुख्य requirement थी। + +## Development { #development } + +जब तक मैंने **FastAPI** खुद बनाना शुरू किया, तब तक अधिकांश हिस्से पहले से तैयार थे, design तय हो चुका था, requirements और tools तैयार थे, और standards तथा specifications के बारे में ज्ञान स्पष्ट और ताज़ा था। + +## भविष्य { #future } + +इस बिंदु तक, यह पहले से ही स्पष्ट है कि **FastAPI** अपने ideas के साथ कई लोगों के लिए उपयोगी साबित हो रहा है। + +इसे कई use cases के लिए बेहतर उपयुक्त होने के कारण पिछले विकल्पों पर चुना जा रहा है। + +कई developers और teams अपने projects के लिए पहले से ही **FastAPI** पर निर्भर हैं (मेरे और मेरी team सहित)। + +लेकिन फिर भी, अभी कई improvements और features आने बाकी हैं। + +**FastAPI** का भविष्य बहुत उज्ज्वल है। + +और [आपकी मदद](help-fastapi.md) की बहुत सराहना की जाती है। diff --git a/docs/hi/docs/project-generation.md b/docs/hi/docs/project-generation.md new file mode 100644 index 000000000..747e4da53 --- /dev/null +++ b/docs/hi/docs/project-generation.md @@ -0,0 +1,28 @@ +# Full Stack FastAPI Template { #full-stack-fastapi-template } + +Templates आम तौर पर एक विशिष्ट setup के साथ आते हैं, लेकिन उन्हें flexible और customizable होने के लिए डिज़ाइन किया जाता है। इससे आप उन्हें अपने project की आवश्यकताओं के अनुसार modify और adapt कर सकते हैं, जिससे वे एक बेहतरीन starting point बन जाते हैं। 🏁 + +आप शुरू करने के लिए इस template का उपयोग कर सकते हैं, क्योंकि इसमें आपके लिए बहुत सा initial setup, security, database और कुछ API endpoints पहले से तैयार हैं। + +GitHub Repository: [Full Stack FastAPI Template](https://github.com/tiangolo/full-stack-fastapi-template) + +## Full Stack FastAPI Template - Technology Stack और Features { #full-stack-fastapi-template-technology-stack-and-features } + +- ⚡ Python backend API के लिए [**FastAPI**](https://fastapi.tiangolo.com/hi)। + - 🧰 Python SQL database interactions (ORM) के लिए [SQLModel](https://sqlmodel.tiangolo.com)। + - 🔍 data validation और settings management के लिए [Pydantic](https://docs.pydantic.dev), जिसका उपयोग FastAPI करता है। + - 💾 SQL database के रूप में [PostgreSQL](https://www.postgresql.org)। +- 🚀 frontend के लिए [React](https://react.dev)। + - 💃 TypeScript, hooks, Vite, और modern frontend stack के अन्य parts का उपयोग। + - 🎨 frontend components के लिए [Tailwind CSS](https://tailwindcss.com) और [shadcn/ui](https://ui.shadcn.com)। + - 🤖 एक automatically generated frontend client। + - 🧪 End-to-End testing के लिए [Playwright](https://playwright.dev)। + - 🦇 Dark mode support। +- 🐋 development और production के लिए [Docker Compose](https://www.docker.com)। +- 🔒 default रूप से secure password hashing। +- 🔑 JWT (JSON Web Token) authentication। +- 📫 Email आधारित password recovery। +- ✅ [Pytest](https://pytest.org) के साथ tests। +- 📞 reverse proxy / load balancer के रूप में [Traefik](https://traefik.io)। +- 🚢 Docker Compose का उपयोग करके deployment instructions, जिसमें automatic HTTPS certificates handle करने के लिए frontend Traefik proxy setup करना शामिल है। +- 🏭 GitHub Actions पर आधारित CI (continuous integration) और CD (continuous deployment)। diff --git a/docs/hi/docs/python-types.md b/docs/hi/docs/python-types.md new file mode 100644 index 000000000..86522e18e --- /dev/null +++ b/docs/hi/docs/python-types.md @@ -0,0 +1,348 @@ +# Python Types परिचय { #python-types-intro } + +Python में वैकल्पिक "type hints" (जिन्हें "type annotations" भी कहा जाता है) का समर्थन है। + +ये **"type hints"** या annotations एक विशेष syntax हैं, जो किसी variable का type घोषित करने की अनुमति देते हैं। + +अपने variables के लिए types घोषित करके, editors और tools आपको बेहतर support दे सकते हैं। + +यह Python type hints के बारे में बस एक **त्वरित tutorial / refresher** है। इसमें केवल उतना ही शामिल है जितना उन्हें **FastAPI** के साथ उपयोग करने के लिए न्यूनतम रूप से आवश्यक है... जो वास्तव में बहुत कम है। + +**FastAPI** पूरी तरह से इन्हीं type hints पर आधारित है, ये इसे कई फायदे और लाभ देते हैं। + +लेकिन अगर आप कभी **FastAPI** का उपयोग नहीं भी करते, तब भी इनके बारे में थोड़ा सीखने से आपको लाभ होगा। + +/// note | नोट + +अगर आप Python expert हैं, और type hints के बारे में पहले से सब कुछ जानते हैं, तो अगले chapter पर जाएँ। + +/// + +## प्रेरणा { #motivation } + +आइए एक सरल उदाहरण से शुरू करें: + +{* ../../docs_src/python_types/tutorial001_py310.py *} + +इस program को call करने पर output आता है: + +``` +John Doe +``` + +Function निम्नलिखित करता है: + +* एक `first_name` और `last_name` लेता है। +* प्रत्येक के पहले अक्षर को `title()` के साथ upper case में बदलता है। +* उन्हें बीच में एक space के साथ Concatenate करता है। + +{* ../../docs_src/python_types/tutorial001_py310.py hl[2] *} + +### इसे edit करें { #edit-it } + +यह एक बहुत सरल program है। + +लेकिन अब कल्पना करें कि आप इसे scratch से लिख रहे थे। + +किसी point पर आप function define करना शुरू करते हैं, और आपके parameters तैयार हैं... + +लेकिन फिर आपको "वह method जो पहले अक्षर को upper case में बदलता है" call करना है। + +क्या वह `upper` था? क्या वह `uppercase` था? `first_uppercase`? `capitalize`? + +फिर, आप programmer के पुराने दोस्त, editor autocompletion के साथ कोशिश करते हैं। + +आप function का पहला parameter, `first_name`, फिर एक dot (`.`) type करते हैं और फिर completion trigger करने के लिए `Ctrl+Space` दबाते हैं। + +लेकिन, दुख की बात है, आपको कुछ भी उपयोगी नहीं मिलता: + + + +### Types जोड़ें { #add-types } + +आइए पिछले version की एक single line बदलते हैं। + +हम ठीक इस fragment को, function के parameters को, इससे बदलेंगे: + +```Python + first_name, last_name +``` + +इसमें: + +```Python + first_name: str, last_name: str +``` + +बस इतना ही। + +यही "type hints" हैं: + +{* ../../docs_src/python_types/tutorial002_py310.py hl[1] *} + +यह default values declare करने जैसा नहीं है, जैसा कि इसमें होता: + +```Python + first_name="john", last_name="doe" +``` + +यह एक अलग चीज़ है। + +हम colons (`:`) का उपयोग कर रहे हैं, equals (`=`) का नहीं। + +और type hints जोड़ने से सामान्यतः यह नहीं बदलता कि बिना उनके जो होता, वह कैसे होता। + +लेकिन अब, कल्पना करें कि आप फिर से उस function को बनाने के बीच में हैं, लेकिन type hints के साथ। + +उसी point पर, आप `Ctrl+Space` के साथ autocomplete trigger करने की कोशिश करते हैं और आप देखते हैं: + + + +इसके साथ, आप options देखते हुए scroll कर सकते हैं, जब तक आपको वह न मिल जाए जो "पहचाना हुआ लगे": + + + +## और प्रेरणा { #more-motivation } + +इस function को देखें, इसमें पहले से type hints हैं: + +{* ../../docs_src/python_types/tutorial003_py310.py hl[1] *} + +क्योंकि editor variables के types जानता है, आपको केवल completion ही नहीं मिलता, आपको error checks भी मिलते हैं: + + + +अब आप जानते हैं कि आपको इसे ठीक करना है, `age` को `str(age)` के साथ string में convert करना है: + +{* ../../docs_src/python_types/tutorial004_py310.py hl[2] *} + +## Types declare करना { #declaring-types } + +आपने अभी type hints declare करने की मुख्य जगह देखी। Function parameters के रूप में। + +यही वह मुख्य जगह भी है जहाँ आप उन्हें **FastAPI** के साथ उपयोग करेंगे। + +### Simple types { #simple-types } + +आप सभी standard Python types declare कर सकते हैं, केवल `str` ही नहीं। + +आप उदाहरण के लिए उपयोग कर सकते हैं: + +* `int` +* `float` +* `bool` +* `bytes` + +{* ../../docs_src/python_types/tutorial005_py310.py hl[1] *} + +### `typing` module { #typing-module } + +कुछ अतिरिक्त use cases के लिए, आपको standard library के `typing` module से कुछ चीज़ें import करने की आवश्यकता हो सकती है, उदाहरण के लिए जब आप declare करना चाहते हैं कि किसी चीज़ का "कोई भी type" है, तो आप `typing` से `Any` का उपयोग कर सकते हैं: + +```python +from typing import Any + + +def some_function(data: Any): + print(data) +``` + +### Generic types { #generic-types } + +कुछ types square brackets में "type parameters" ले सकते हैं, ताकि उनके internal types define किए जा सकें, उदाहरण के लिए "strings की list" को `list[str]` declare किया जाएगा। + +जो types type parameters ले सकते हैं उन्हें **Generic types** या **Generics** कहा जाता है। + +आप उन्हीं builtin types को generics के रूप में उपयोग कर सकते हैं (square brackets और अंदर types के साथ): + +* `list` +* `tuple` +* `set` +* `dict` + +#### List { #list } + +उदाहरण के लिए, आइए एक variable को `str` की `list` के रूप में define करते हैं। + +Variable को उसी colon (`:`) syntax के साथ declare करें। + +Type के रूप में, `list` रखें। + +क्योंकि list एक ऐसा type है जिसमें कुछ internal types होते हैं, आप उन्हें square brackets में रखते हैं: + +{* ../../docs_src/python_types/tutorial006_py310.py hl[1] *} + +/// note | नोट + +Square brackets में मौजूद उन internal types को "type parameters" कहा जाता है। + +इस case में, `str` वह type parameter है जो `list` को pass किया गया है। + +/// + +इसका मतलब है: "variable `items` एक `list` है, और इस list का प्रत्येक item एक `str` है"। + +ऐसा करने से, आपका editor list से items process करते समय भी support दे सकता है: + + + +Types के बिना, इसे हासिल करना लगभग असंभव है। + +ध्यान दें कि variable `item`, list `items` के elements में से एक है। + +और फिर भी, editor जानता है कि यह एक `str` है, और उसके लिए support देता है। + +#### Tuple और Set { #tuple-and-set } + +आप `tuple`s और `set`s declare करने के लिए भी ऐसा ही करेंगे: + +{* ../../docs_src/python_types/tutorial007_py310.py hl[1] *} + +इसका मतलब है: + +* Variable `items_t` 3 items वाला एक `tuple` है, एक `int`, दूसरा `int`, और एक `str`। +* Variable `items_s` एक `set` है, और इसके प्रत्येक item का type `bytes` है। + +#### Dict { #dict } + +`dict` define करने के लिए, आप 2 type parameters pass करते हैं, commas से separated। + +पहला type parameter `dict` की keys के लिए होता है। + +दूसरा type parameter `dict` की values के लिए होता है: + +{* ../../docs_src/python_types/tutorial008_py310.py hl[1] *} + +इसका मतलब है: + +* Variable `prices` एक `dict` है: + * इस `dict` की keys `str` type की हैं (मान लें, प्रत्येक item का नाम)। + * इस `dict` की values `float` type की हैं (मान लें, प्रत्येक item की price)। + +#### Union { #union } + +आप declare कर सकते हैं कि कोई variable **कई types** में से कोई भी हो सकता है, उदाहरण के लिए, एक `int` या एक `str`। + +इसे define करने के लिए आप दोनों types को separate करने के लिए vertical bar (`|`) का उपयोग करते हैं। + +इसे "union" कहा जाता है, क्योंकि variable उन दो type sets के union में कुछ भी हो सकता है। + +```Python hl_lines="1" +{!> ../../docs_src/python_types/tutorial008b_py310.py!} +``` + +इसका मतलब है कि `item` एक `int` या एक `str` हो सकता है। + +#### संभवतः `None` { #possibly-none } + +आप declare कर सकते हैं कि किसी value का type, जैसे `str`, हो सकता है, लेकिन वह `None` भी हो सकती है। + +//// tab | Python 3.10+ + +```Python hl_lines="1" +{!> ../../docs_src/python_types/tutorial009_py310.py!} +``` + +//// + +सिर्फ `str` के बजाय `str | None` का उपयोग करने से editor आपको उन errors को detect करने में मदद करेगा जहाँ आप यह मान रहे हो सकते हैं कि कोई value हमेशा `str` है, जबकि वास्तव में वह `None` भी हो सकती है। + +### Classes को types के रूप में { #classes-as-types } + +आप किसी class को भी variable के type के रूप में declare कर सकते हैं। + +मान लें आपके पास एक class `Person` है, जिसमें एक name है: + +{* ../../docs_src/python_types/tutorial010_py310.py hl[1:3] *} + +फिर आप किसी variable को `Person` type का declare कर सकते हैं: + +{* ../../docs_src/python_types/tutorial010_py310.py hl[6] *} + +और फिर, फिर से, आपको पूरा editor support मिलता है: + + + +ध्यान दें कि इसका मतलब है "`one_person`, class `Person` का एक **instance** है"। + +इसका मतलब यह नहीं है कि "`one_person`, `Person` नाम की **class** है"। + +## Pydantic models { #pydantic-models } + +[Pydantic](https://docs.pydantic.dev/) data validation करने के लिए एक Python library है। + +आप data की "shape" को attributes वाली classes के रूप में declare करते हैं। + +और प्रत्येक attribute का एक type होता है। + +फिर आप कुछ values के साथ उस class का एक instance create करते हैं और यह values को validate करेगा, उन्हें appropriate type में convert करेगा (अगर ऐसा case है) और आपको पूरे data वाला एक object देगा। + +और उस resulting object के साथ आपको पूरा editor support मिलता है। + +Official Pydantic docs से एक उदाहरण: + +{* ../../docs_src/python_types/tutorial011_py310.py *} + +/// note | नोट + +अधिक जानने के लिए [Pydantic, इसके docs देखें](https://docs.pydantic.dev/)। + +/// + +**FastAPI** पूरी तरह से Pydantic पर आधारित है। + +आप यह सब practice में [Tutorial - User Guide](tutorial/index.md) में बहुत अधिक देखेंगे। + +## Metadata Annotations के साथ Type Hints { #type-hints-with-metadata-annotations } + +Python में एक feature भी है जो `Annotated` का उपयोग करके इन type hints में **अतिरिक्त metadata** डालने की अनुमति देता है। + +आप `typing` से `Annotated` import कर सकते हैं। + +{* ../../docs_src/python_types/tutorial013_py310.py hl[1,4] *} + +Python खुद इस `Annotated` के साथ कुछ नहीं करता। और editors और अन्य tools के लिए, type अभी भी `str` है। + +लेकिन आप `Annotated` में इस जगह का उपयोग **FastAPI** को अतिरिक्त metadata देने के लिए कर सकते हैं कि आप अपनी application को कैसे behave कराना चाहते हैं। + +याद रखने वाली महत्वपूर्ण बात यह है कि `Annotated` को pass किया गया **पहला *type parameter*** ही **actual type** होता है। बाकी सब, अन्य tools के लिए केवल metadata है। + +अभी के लिए, आपको बस यह जानना है कि `Annotated` मौजूद है, और यह standard Python है। 😎 + +बाद में आप देखेंगे कि यह कितना **powerful** हो सकता है। + +/// tip | सुझाव + +यह तथ्य कि यह **standard Python** है, इसका मतलब है कि आपको अपने editor में, अपने code को analyze और refactor करने वाले tools के साथ, आदि, अभी भी **सबसे अच्छा possible developer experience** मिलेगा। ✨ + +और यह भी कि आपका code कई अन्य Python tools और libraries के साथ बहुत compatible होगा। 🚀 + +/// + +## **FastAPI** में Type hints { #type-hints-in-fastapi } + +**FastAPI** इन type hints का लाभ उठाकर कई चीज़ें करता है। + +**FastAPI** के साथ आप type hints के साथ parameters declare करते हैं और आपको मिलता है: + +* **Editor support**। +* **Type checks**। + +...और **FastAPI** उन्हीं declarations का उपयोग करता है: + +* **Requirements define** करने के लिए: request path parameters, query parameters, headers, bodies, dependencies, आदि से। +* **Data convert** करने के लिए: request से required type में। +* **Data validate** करने के लिए: प्रत्येक request से आने वाले data को: + * Data invalid होने पर client को लौटाए जाने वाले **automatic errors** generate करना। +* OpenAPI का उपयोग करके API को **document** करने के लिए: + * जिसका उपयोग फिर automatic interactive documentation user interfaces द्वारा किया जाता है। + +यह सब abstract लग सकता है। चिंता न करें। आप यह सब action में [Tutorial - User Guide](tutorial/index.md) में देखेंगे। + +महत्वपूर्ण बात यह है कि standard Python types का उपयोग करके, एक ही जगह पर (अधिक classes, decorators, आदि जोड़ने के बजाय), **FastAPI** आपके लिए बहुत सारा काम कर देगा। + +/// note | नोट + +अगर आप पहले ही पूरे tutorial से गुजर चुके हैं और types के बारे में और देखने के लिए वापस आए हैं, तो एक अच्छा resource [`mypy` की "cheat sheet"](https://mypy.readthedocs.io/en/latest/cheat_sheet_py3.html) है। + +/// diff --git a/docs/hi/docs/virtual-environments.md b/docs/hi/docs/virtual-environments.md new file mode 100644 index 000000000..cacadd0df --- /dev/null +++ b/docs/hi/docs/virtual-environments.md @@ -0,0 +1,864 @@ +# Virtual Environments { #virtual-environments } + +जब आप Python projects पर काम करते हैं, तो संभवतः आपको हर project के लिए install किए जाने वाले packages को अलग रखने के लिए एक **virtual environment** (या कोई समान तरीका) इस्तेमाल करना चाहिए। + +/// note | नोट + +अगर आप पहले से virtual environments के बारे में जानते हैं, उन्हें कैसे बनाना और इस्तेमाल करना है जानते हैं, तो आप इस section को छोड़ना चाह सकते हैं। 🤓 + +/// + +/// tip | सुझाव + +एक **virtual environment**, एक **environment variable** से अलग होता है। + +एक **environment variable** system में एक variable होता है जिसे programs इस्तेमाल कर सकते हैं। + +एक **virtual environment** एक directory होती है जिसमें कुछ files होती हैं। + +/// + +/// note | नोट + +यह पेज आपको **virtual environments** का उपयोग करना और वे कैसे काम करते हैं, सिखाएगा। + +अगर आप अपने लिए **सब कुछ manage करने वाला tool** अपनाने के लिए तैयार हैं (जिसमें Python install करना भी शामिल है), तो [uv](https://github.com/astral-sh/uv) आज़माएँ। + +/// + +## Project बनाएँ { #create-a-project } + +सबसे पहले, अपने project के लिए एक directory बनाएँ। + +मैं सामान्यतः अपनी home/user directory के अंदर `code` नाम की एक directory बनाता हूँ। + +और उसके अंदर हर project के लिए एक directory बनाता हूँ। + +
+ +```console +// home directory में जाएँ +$ cd +// अपने सभी code projects के लिए एक directory बनाएँ +$ mkdir code +// उस code directory में जाएँ +$ cd code +// इस project के लिए एक directory बनाएँ +$ mkdir awesome-project +// उस project directory में जाएँ +$ cd awesome-project +``` + +
+ +## Virtual Environment बनाएँ { #create-a-virtual-environment } + +जब आप किसी Python project पर **पहली बार** काम शुरू करते हैं, तो एक virtual environment **अपने project के अंदर** बनाएँ। + +/// tip | सुझाव + +आपको यह **हर project के लिए केवल एक बार** करना होता है, हर बार काम करते समय नहीं। + +/// + +//// tab | `venv` + +Virtual environment बनाने के लिए, आप Python के साथ आने वाले `venv` module का उपयोग कर सकते हैं। + +
+ +```console +$ python -m venv .venv +``` + +
+ +/// details | उस command का क्या अर्थ है + +* `python`: `python` नाम के program का उपयोग करें +* `-m`: किसी module को script की तरह call करें, अगला हम उसे बताएँगे कि कौन-सा module +* `venv`: `venv` नाम के module का उपयोग करें जो सामान्यतः Python के साथ install आता है +* `.venv`: नई directory `.venv` में virtual environment बनाएँ + +/// + +//// + +//// tab | `uv` + +अगर आपके पास [`uv`](https://github.com/astral-sh/uv) install है, तो आप इसका उपयोग virtual environment बनाने के लिए कर सकते हैं। + +
+ +```console +$ uv venv +``` + +
+ +/// tip | सुझाव + +Default रूप से, `uv` `.venv` नाम की directory में virtual environment बनाएगा। + +लेकिन आप directory नाम के साथ एक अतिरिक्त argument देकर इसे customize कर सकते हैं। + +/// + +//// + +वह command `.venv` नाम की directory में एक नया virtual environment बनाता है। + +/// details | `.venv` या कोई दूसरा नाम + +आप virtual environment को किसी दूसरी directory में बना सकते हैं, लेकिन इसे `.venv` कहने की एक convention है। + +/// + +## Virtual Environment activate करें { #activate-the-virtual-environment } + +नए virtual environment को activate करें ताकि आप जो भी Python command चलाएँ या जो package install करें, वह इसका उपयोग करे। + +/// tip | सुझाव + +Project पर काम करने के लिए **हर बार** जब आप एक **नया terminal session** शुरू करें, तो यह करें। + +/// + +//// tab | Linux, macOS + +
+ +```console +$ source .venv/bin/activate +``` + +
+ +//// + +//// tab | Windows PowerShell + +
+ +```console +$ .venv\Scripts\Activate.ps1 +``` + +
+ +//// + +//// tab | Windows Bash + +या अगर आप Windows के लिए Bash का उपयोग करते हैं (जैसे [Git Bash](https://gitforwindows.org/)): + +
+ +```console +$ source .venv/Scripts/activate +``` + +
+ +//// + +/// tip | सुझाव + +हर बार जब आप उस environment में कोई **नया package** install करें, तो environment को फिर से **activate** करें। + +यह सुनिश्चित करता है कि अगर आप उस package द्वारा install किया गया कोई **terminal (CLI) program** इस्तेमाल करते हैं, तो आप अपने virtual environment वाला ही उपयोग करें, कोई और नहीं जो global रूप से install हो सकता है, शायद आपकी ज़रूरत से अलग version के साथ। + +/// + +## जाँचें कि Virtual Environment Active है { #check-the-virtual-environment-is-active } + +जाँचें कि virtual environment active है (पिछली command ने काम किया)। + +/// tip | सुझाव + +यह **वैकल्पिक** है, लेकिन यह **जाँचने** का एक अच्छा तरीका है कि सब कुछ अपेक्षा के अनुसार काम कर रहा है और आप वही virtual environment इस्तेमाल कर रहे हैं जिसका आपने इरादा किया था। + +/// + +//// tab | Linux, macOS, Windows Bash + +
+ +```console +$ which python + +/home/user/code/awesome-project/.venv/bin/python +``` + +
+ +अगर यह `.venv/bin/python` पर `python` binary दिखाता है, आपके project के अंदर (इस मामले में `awesome-project`), तो यह काम कर गया। 🎉 + +//// + +//// tab | Windows PowerShell + +
+ +```console +$ Get-Command python + +C:\Users\user\code\awesome-project\.venv\Scripts\python +``` + +
+ +अगर यह `.venv\Scripts\python` पर `python` binary दिखाता है, आपके project के अंदर (इस मामले में `awesome-project`), तो यह काम कर गया। 🎉 + +//// + +## `pip` Upgrade करें { #upgrade-pip } + +/// tip | सुझाव + +अगर आप [`uv`](https://github.com/astral-sh/uv) का उपयोग करते हैं, तो आप चीजें install करने के लिए `pip` की बजाय उसी का उपयोग करेंगे, इसलिए आपको `pip` upgrade करने की ज़रूरत नहीं है। 😎 + +/// + +अगर आप packages install करने के लिए `pip` का उपयोग कर रहे हैं (यह Python के साथ default रूप से आता है), तो आपको इसे latest version में **upgrade** करना चाहिए। + +किसी package को install करते समय कई अजीब errors केवल पहले `pip` upgrade करने से हल हो जाते हैं। + +/// tip | सुझाव + +आप सामान्यतः यह **एक बार** करेंगे, virtual environment बनाने के ठीक बाद। + +/// + +सुनिश्चित करें कि virtual environment active है (ऊपर वाली command से) और फिर चलाएँ: + +
+ +```console +$ python -m pip install --upgrade pip + +---> 100% +``` + +
+ +/// tip | सुझाव + +कभी-कभी, pip upgrade करने की कोशिश करते समय आपको **`No module named pip`** error मिल सकता है। + +अगर ऐसा होता है, तो नीचे दी गई command का उपयोग करके pip install और upgrade करें: + +
+ +```console +$ python -m ensurepip --upgrade + +---> 100% +``` + +
+ +यह command pip को install करेगी अगर वह पहले से install नहीं है और यह भी सुनिश्चित करेगी कि install किया गया pip का version कम से कम `ensurepip` में उपलब्ध version जितना नया हो। + +/// + +## `.gitignore` जोड़ें { #add-gitignore } + +अगर आप **Git** का उपयोग कर रहे हैं (आपको करना चाहिए), तो अपनी `.venv` की हर चीज़ को Git से exclude करने के लिए एक `.gitignore` file जोड़ें। + +/// tip | सुझाव + +अगर आपने virtual environment बनाने के लिए [`uv`](https://github.com/astral-sh/uv) का उपयोग किया है, तो यह आपके लिए पहले ही कर चुका है, आप यह step छोड़ सकते हैं। 😎 + +/// + +/// tip | सुझाव + +यह **एक बार** करें, virtual environment बनाने के ठीक बाद। + +/// + +
+ +```console +$ echo "*" > .venv/.gitignore +``` + +
+ +/// details | उस command का क्या अर्थ है + +* `echo "*"`: terminal में text `*` को "print" करेगा (अगला हिस्सा इसे थोड़ा बदल देता है) +* `>`: `>` के बाईं ओर वाली command द्वारा terminal में print की गई कोई भी चीज़ print नहीं होनी चाहिए, बल्कि `>` के दाईं ओर वाली file में लिखी जानी चाहिए +* `.gitignore`: उस file का नाम जहाँ text लिखा जाना चाहिए + +और Git के लिए `*` का मतलब "सब कुछ" होता है। इसलिए, यह `.venv` directory में सब कुछ ignore करेगा। + +वह command `.gitignore` file बनाएगी, इस content के साथ: + +```gitignore +* +``` + +/// + +## Packages install करें { #install-packages } + +Environment activate करने के बाद, आप उसमें packages install कर सकते हैं। + +/// tip | सुझाव + +जब आप अपने project के लिए required packages install या upgrade कर रहे हों, तो यह **एक बार** करें। + +अगर आपको किसी version को upgrade करना हो या कोई नया package जोड़ना हो, तो आप **यह फिर से करेंगे**। + +/// + +### सीधे Packages install करें { #install-packages-directly } + +अगर आप जल्दी में हैं और अपने project की package requirements declare करने के लिए कोई file इस्तेमाल नहीं करना चाहते, तो आप उन्हें सीधे install कर सकते हैं। + +/// tip | सुझाव + +आपके program को जिन packages और versions की ज़रूरत है, उन्हें एक file में रखना (बहुत) अच्छा विचार है (उदाहरण के लिए `requirements.txt` या `pyproject.toml`)। + +/// + +//// tab | `pip` + +
+ +```console +$ pip install "fastapi[standard]" + +---> 100% +``` + +
+ +//// + +//// tab | `uv` + +अगर आपके पास [`uv`](https://github.com/astral-sh/uv) है: + +
+ +```console +$ uv pip install "fastapi[standard]" +---> 100% +``` + +
+ +//// + +### `requirements.txt` से install करें { #install-from-requirements-txt } + +अगर आपके पास `requirements.txt` है, तो अब आप इसके packages install करने के लिए इसका उपयोग कर सकते हैं। + +//// tab | `pip` + +
+ +```console +$ pip install -r requirements.txt +---> 100% +``` + +
+ +//// + +//// tab | `uv` + +अगर आपके पास [`uv`](https://github.com/astral-sh/uv) है: + +
+ +```console +$ uv pip install -r requirements.txt +---> 100% +``` + +
+ +//// + +/// details | `requirements.txt` + +कुछ packages वाला `requirements.txt` ऐसा दिख सकता है: + +```requirements.txt +fastapi[standard]==0.113.0 +pydantic==2.8.0 +``` + +/// + +## अपना Program चलाएँ { #run-your-program } + +Virtual environment activate करने के बाद, आप अपना program चला सकते हैं, और यह आपके virtual environment के अंदर मौजूद Python का उपयोग करेगा, उन packages के साथ जिन्हें आपने वहाँ install किया है। + +
+ +```console +$ python main.py + +Hello World +``` + +
+ +## अपना Editor Configure करें { #configure-your-editor } + +आप शायद एक editor का उपयोग करेंगे, सुनिश्चित करें कि आप इसे उसी virtual environment का उपयोग करने के लिए configure करें जिसे आपने बनाया है (यह शायद इसे autodetect कर लेगा), ताकि आपको autocompletion और inline errors मिल सकें। + +उदाहरण के लिए: + +* [VS Code](https://code.visualstudio.com/docs/python/environments#_select-and-activate-an-environment) +* [PyCharm](https://www.jetbrains.com/help/pycharm/creating-virtual-environment.html) + +/// tip | सुझाव + +आपको सामान्यतः यह केवल **एक बार** करना होता है, जब आप virtual environment बनाते हैं। + +/// + +## Virtual Environment deactivate करें { #deactivate-the-virtual-environment } + +जब आप अपने project पर काम कर लें, तो आप virtual environment को **deactivate** कर सकते हैं। + +
+ +```console +$ deactivate +``` + +
+ +इस तरह, जब आप `python` चलाएँगे, तो यह वहाँ install packages वाले उस virtual environment से इसे चलाने की कोशिश नहीं करेगा। + +## काम करने के लिए तैयार { #ready-to-work } + +अब आप अपने project पर काम शुरू करने के लिए तैयार हैं। + + + +/// tip | सुझाव + +क्या आप समझना चाहते हैं कि ऊपर की सारी चीज़ें क्या हैं? + +आगे पढ़ते रहें। 👇🤓 + +/// + +## Virtual Environments क्यों { #why-virtual-environments } + +FastAPI के साथ काम करने के लिए आपको [Python](https://www.python.org/) install करना होगा। + +उसके बाद, आपको FastAPI और कोई भी अन्य **packages** जिन्हें आप इस्तेमाल करना चाहते हैं, **install** करने होंगे। + +Packages install करने के लिए आप सामान्यतः Python के साथ आने वाली `pip` command (या समान alternatives) का उपयोग करेंगे। + +फिर भी, अगर आप सीधे `pip` का उपयोग करते हैं, तो packages आपके **global Python environment** (Python की global installation) में install हो जाएँगे। + +### समस्या { #the-problem } + +तो, global Python environment में packages install करने में समस्या क्या है? + +किसी समय, आप शायद कई अलग-अलग programs लिखेंगे जो **अलग-अलग packages** पर निर्भर करते हैं। और जिन projects पर आप काम करेंगे उनमें से कुछ उसी package के **अलग-अलग versions** पर निर्भर होंगे। 😱 + +उदाहरण के लिए, आप `philosophers-stone` नाम का एक project बना सकते हैं, यह program **`harry`, version `1`** नाम के किसी दूसरे package पर निर्भर करता है। इसलिए, आपको `harry` install करना होगा। + +```mermaid +flowchart LR + stone(philosophers-stone) -->|requires| harry-1[harry v1] +``` + +फिर, कुछ समय बाद, आप `prisoner-of-azkaban` नाम का दूसरा project बनाते हैं, और यह project भी `harry` पर निर्भर करता है, लेकिन इस project को **`harry` version `3`** चाहिए। + +```mermaid +flowchart LR + azkaban(prisoner-of-azkaban) --> |requires| harry-3[harry v3] +``` + +लेकिन अब समस्या यह है कि अगर आप packages को local **virtual environment** में install करने के बजाय globally (global environment में) install करते हैं, तो आपको चुनना होगा कि `harry` का कौन-सा version install करना है। + +अगर आप `philosophers-stone` चलाना चाहते हैं, तो आपको पहले `harry` version `1` install करना होगा, उदाहरण के लिए: + +
+ +```console +$ pip install "harry==1" +``` + +
+ +और फिर आपके global Python environment में `harry` version `1` install हो जाएगा। + +```mermaid +flowchart LR + subgraph global[global env] + harry-1[harry v1] + end + subgraph stone-project[philosophers-stone project] + stone(philosophers-stone) -->|requires| harry-1 + end +``` + +लेकिन फिर अगर आप `prisoner-of-azkaban` चलाना चाहते हैं, तो आपको `harry` version `1` uninstall करके `harry` version `3` install करना होगा (या सिर्फ version `3` install करने से version `1` automatically uninstall हो जाएगा)। + +
+ +```console +$ pip install "harry==3" +``` + +
+ +और फिर आपके global Python environment में `harry` version `3` install हो जाएगा। + +और अगर आप `philosophers-stone` फिर से चलाने की कोशिश करते हैं, तो संभावना है कि यह **काम न करे** क्योंकि इसे `harry` version `1` चाहिए। + +```mermaid +flowchart LR + subgraph global[global env] + harry-1[harry v1] + style harry-1 fill:#ccc,stroke-dasharray: 5 5 + harry-3[harry v3] + end + subgraph stone-project[philosophers-stone project] + stone(philosophers-stone) -.-x|⛔️| harry-1 + end + subgraph azkaban-project[prisoner-of-azkaban project] + azkaban(prisoner-of-azkaban) --> |requires| harry-3 + end +``` + +/// tip | सुझाव + +Python packages में **नए versions** में **breaking changes से बचने** की पूरी कोशिश करना बहुत आम है, लेकिन सुरक्षित रहना बेहतर है, और नए versions को जानबूझकर तथा तब install करना बेहतर है जब आप tests चलाकर जाँच सकें कि सब कुछ सही तरीके से काम कर रहा है। + +/// + +अब, यही चीज़ उन **कई** अन्य **packages** के साथ कल्पना करें जिन पर आपके सभी **projects निर्भर करते हैं**। इसे manage करना बहुत कठिन है। और संभवतः आप कुछ projects को packages के कुछ **incompatible versions** के साथ चला देंगे, और यह नहीं जान पाएँगे कि कुछ काम क्यों नहीं कर रहा। + +साथ ही, आपके operating system (जैसे Linux, Windows, macOS) के आधार पर, उसमें Python पहले से install आया हो सकता है। और उस मामले में संभवतः कुछ packages कुछ specific versions के साथ pre-installed होंगे जो **आपके system के लिए required** हैं। अगर आप global Python environment में packages install करते हैं, तो आप अपने operating system के साथ आए कुछ programs को **break** कर सकते हैं। + +## Packages कहाँ install होते हैं { #where-are-packages-installed } + +जब आप Python install करते हैं, तो यह आपके computer पर कुछ files वाली कुछ directories बनाता है। + +इनमें से कुछ directories वे होती हैं जो आपके द्वारा install किए गए सभी packages को रखने की जिम्मेदार होती हैं। + +जब आप चलाते हैं: + +
+ +```console +// इसे अभी न चलाएँ, यह केवल एक उदाहरण है 🤓 +$ pip install "fastapi[standard]" +---> 100% +``` + +
+ +तो यह FastAPI code वाली एक compressed file download करेगा, सामान्यतः [PyPI](https://pypi.org/project/fastapi/) से। + +यह उन अन्य packages की files भी **download** करेगा जिन पर FastAPI निर्भर करता है। + +फिर यह उन सभी files को **extract** करेगा और उन्हें आपके computer की एक directory में रखेगा। + +Default रूप से, यह उन downloaded और extracted files को उस directory में रखेगा जो आपकी Python installation के साथ आती है, वही **global environment** है। + +## Virtual Environments क्या हैं { #what-are-virtual-environments } + +सभी packages को global environment में रखने की समस्याओं का समाधान है कि आप जिस भी project पर काम करते हैं उसके लिए **एक virtual environment** उपयोग करें। + +एक virtual environment एक **directory** है, global वाली के बहुत समान, जहाँ आप किसी project के लिए packages install कर सकते हैं। + +इस तरह, हर project का अपना virtual environment (`.venv` directory) होगा, अपने packages के साथ। + +```mermaid +flowchart TB + subgraph stone-project[philosophers-stone project] + stone(philosophers-stone) --->|requires| harry-1 + subgraph venv1[.venv] + harry-1[harry v1] + end + end + subgraph azkaban-project[prisoner-of-azkaban project] + azkaban(prisoner-of-azkaban) --->|requires| harry-3 + subgraph venv2[.venv] + harry-3[harry v3] + end + end + stone-project ~~~ azkaban-project +``` + +## Virtual Environment activate करने का क्या मतलब है { #what-does-activating-a-virtual-environment-mean } + +जब आप किसी virtual environment को activate करते हैं, उदाहरण के लिए: + +//// tab | Linux, macOS + +
+ +```console +$ source .venv/bin/activate +``` + +
+ +//// + +//// tab | Windows PowerShell + +
+ +```console +$ .venv\Scripts\Activate.ps1 +``` + +
+ +//// + +//// tab | Windows Bash + +या अगर आप Windows के लिए Bash का उपयोग करते हैं (जैसे [Git Bash](https://gitforwindows.org/)): + +
+ +```console +$ source .venv/Scripts/activate +``` + +
+ +//// + +वह command कुछ [environment variables](environment-variables.md) बनाएगी या modify करेगी, जो अगली commands के लिए उपलब्ध होंगे। + +उन variables में से एक `PATH` variable है। + +/// tip | सुझाव + +आप [Environment Variables](environment-variables.md#path-environment-variable) section में `PATH` environment variable के बारे में और जान सकते हैं। + +/// + +Virtual environment activate करने से उसका path `.venv/bin` (Linux और macOS पर) या `.venv\Scripts` (Windows पर) `PATH` environment variable में जुड़ जाता है। + +मान लीजिए कि environment activate करने से पहले, `PATH` variable ऐसा दिखता था: + +//// tab | Linux, macOS + +```plaintext +/usr/bin:/bin:/usr/sbin:/sbin +``` + +इसका मतलब है कि system programs को इनमें खोजता: + +* `/usr/bin` +* `/bin` +* `/usr/sbin` +* `/sbin` + +//// + +//// tab | Windows + +```plaintext +C:\Windows\System32 +``` + +इसका मतलब है कि system programs को इसमें खोजता: + +* `C:\Windows\System32` + +//// + +Virtual environment activate करने के बाद, `PATH` variable कुछ ऐसा दिखेगा: + +//// tab | Linux, macOS + +```plaintext +/home/user/code/awesome-project/.venv/bin:/usr/bin:/bin:/usr/sbin:/sbin +``` + +इसका मतलब है कि system अब सबसे पहले programs को यहाँ खोजना शुरू करेगा: + +```plaintext +/home/user/code/awesome-project/.venv/bin +``` + +बाकी directories में देखने से पहले। + +तो, जब आप terminal में `python` type करते हैं, तो system Python program को यहाँ पाएगा + +```plaintext +/home/user/code/awesome-project/.venv/bin/python +``` + +और उसी का उपयोग करेगा। + +//// + +//// tab | Windows + +```plaintext +C:\Users\user\code\awesome-project\.venv\Scripts;C:\Windows\System32 +``` + +इसका मतलब है कि system अब सबसे पहले programs को यहाँ खोजना शुरू करेगा: + +```plaintext +C:\Users\user\code\awesome-project\.venv\Scripts +``` + +बाकी directories में देखने से पहले। + +तो, जब आप terminal में `python` type करते हैं, तो system Python program को यहाँ पाएगा + +```plaintext +C:\Users\user\code\awesome-project\.venv\Scripts\python +``` + +और उसी का उपयोग करेगा। + +//// + +एक महत्वपूर्ण detail यह है कि यह virtual environment path को `PATH` variable की **शुरुआत** में रखेगा। System इसे किसी भी अन्य उपलब्ध Python से **पहले** पाएगा। इस तरह, जब आप `python` चलाते हैं, तो यह किसी अन्य `python` (उदाहरण के लिए, global environment वाला `python`) के बजाय **virtual environment से** Python का उपयोग करेगा। + +Virtual environment activate करने से कुछ और चीजें भी बदलती हैं, लेकिन यह उसके द्वारा की जाने वाली सबसे महत्वपूर्ण चीज़ों में से एक है। + +## Virtual Environment की जाँच करना { #checking-a-virtual-environment } + +जब आप जाँचते हैं कि virtual environment active है या नहीं, उदाहरण के लिए: + +//// tab | Linux, macOS, Windows Bash + +
+ +```console +$ which python + +/home/user/code/awesome-project/.venv/bin/python +``` + +
+ +//// + +//// tab | Windows PowerShell + +
+ +```console +$ Get-Command python + +C:\Users\user\code\awesome-project\.venv\Scripts\python +``` + +
+ +//// + +इसका मतलब है कि जो `python` program उपयोग किया जाएगा, वह **virtual environment में** मौजूद है। + +आप Linux और macOS में `which` और Windows PowerShell में `Get-Command` का उपयोग करते हैं। + +वह command जिस तरह काम करती है, वह यह है कि यह `PATH` environment variable में जाकर **हर path को क्रम से** check करेगी, `python` नाम के program को खोजते हुए। एक बार जब यह उसे ढूँढ लेती है, तो यह आपको उस program का **path दिखाएगी**। + +सबसे महत्वपूर्ण हिस्सा यह है कि जब आप `python` call करते हैं, तो वही exact "`python`" execute होगा। + +तो, आप confirm कर सकते हैं कि आप सही virtual environment में हैं या नहीं। + +/// tip | सुझाव + +एक virtual environment activate करना, एक Python पाना, और फिर **दूसरे project में चले जाना** आसान है। + +और दूसरा project **काम नहीं करेगा** क्योंकि आप **गलत Python** का उपयोग कर रहे हैं, जो किसी दूसरे project के virtual environment से है। + +यह check कर पाना उपयोगी है कि कौन-सा `python` उपयोग हो रहा है। 🤓 + +/// + +## Virtual Environment deactivate क्यों करें { #why-deactivate-a-virtual-environment } + +उदाहरण के लिए, आप `philosophers-stone` project पर काम कर रहे हो सकते हैं, **उस virtual environment को activate** करके, packages install करके और उस environment के साथ काम करके। + +और फिर आप **किसी दूसरे project** `prisoner-of-azkaban` पर काम करना चाहते हैं। + +आप उस project में जाते हैं: + +
+ +```console +$ cd ~/code/prisoner-of-azkaban +``` + +
+ +अगर आप `philosophers-stone` के लिए virtual environment को deactivate नहीं करते, तो जब आप terminal में `python` चलाएँगे, यह `philosophers-stone` से Python का उपयोग करने की कोशिश करेगा। + +
+ +```console +$ cd ~/code/prisoner-of-azkaban + +$ python main.py + +// sirius import करने में error, यह install नहीं है 😱 +Traceback (most recent call last): + File "main.py", line 1, in + import sirius +``` + +
+ +लेकिन अगर आप virtual environment deactivate करके `prisoner-of-azkaban` के लिए नया वाला activate करते हैं, तो जब आप `python` चलाएँगे, यह `prisoner-of-azkaban` में मौजूद virtual environment से Python का उपयोग करेगा। + +
+ +```console +$ cd ~/code/prisoner-of-azkaban + +// deactivate करने के लिए आपको पुरानी directory में होने की ज़रूरत नहीं है, आप जहाँ भी हों वहाँ से कर सकते हैं, दूसरे project में जाने के बाद भी 😎 +$ deactivate + +// prisoner-of-azkaban/.venv में virtual environment activate करें 🚀 +$ source .venv/bin/activate + +// अब जब आप python चलाएँगे, तो यह इस virtual environment में install package sirius को पाएगा ✨ +$ python main.py + +I solemnly swear 🐺 +``` + +
+ +## Alternatives { #alternatives } + +यह आपको शुरू करने और यह सिखाने के लिए एक सरल guide है कि सब कुछ **अंदर से** कैसे काम करता है। + +Virtual environments, package dependencies (requirements), projects को manage करने के कई **alternatives** हैं। + +जब आप तैयार हों और **पूरे project को manage** करने के लिए कोई tool उपयोग करना चाहें, package dependencies, virtual environments आदि सहित, तो मैं सुझाव दूँगा कि आप [uv](https://github.com/astral-sh/uv) आज़माएँ। + +`uv` बहुत सारी चीज़ें कर सकता है, यह कर सकता है: + +* आपके लिए **Python install** करना, अलग-अलग versions सहित +* आपके projects के लिए **virtual environment** manage करना +* **Packages** install करना +* आपके project के लिए package **dependencies और versions** manage करना +* सुनिश्चित करना कि आपके पास install करने के लिए packages और versions का **exact** set हो, उनकी dependencies सहित, ताकि आप सुनिश्चित हो सकें कि आप अपने project को production में ठीक उसी तरह चला सकते हैं जैसे development के दौरान अपने computer पर चलाते हैं, इसे **locking** कहा जाता है +* और कई अन्य चीज़ें + +## निष्कर्ष { #conclusion } + +अगर आपने यह सब पढ़ा और समझा है, तो अब **आप virtual environments के बारे में** वहाँ मौजूद कई developers से कहीं ज़्यादा जानते हैं। 🤓 + +इन details को जानना भविष्य में उस समय बहुत संभवतः उपयोगी होगा जब आप किसी ऐसी चीज़ को debug कर रहे होंगे जो complex लगती है, लेकिन आपको पता होगा कि **यह सब अंदर से कैसे काम करता है**। 😎 From 33299e22d178aa6f731140f67f8dbf5dd07cfa25 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Fri, 3 Jul 2026 13:42:01 +0000 Subject: [PATCH 394/462] =?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 1a75ca9f3..583a78a37 100644 --- a/docs/en/docs/release-notes.md +++ b/docs/en/docs/release-notes.md @@ -9,6 +9,7 @@ hide: ### Translations +* 🌐 Update translations for hi (add-missing). PR [#15797](https://github.com/fastapi/fastapi/pull/15797) by [@tiangolo](https://github.com/tiangolo). * 🌐 Update `llm-prompt.md` for Hindi. PR [#15810](https://github.com/fastapi/fastapi/pull/15810) by [@YuriiMotov](https://github.com/YuriiMotov). * 🌐 Fix language-specific translation prompt for Russian language. PR [#15924](https://github.com/fastapi/fastapi/pull/15924) by [@YuriiMotov](https://github.com/YuriiMotov). From a52b4b9283ef42704ce1392f9ef2819205400855 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebasti=C3=A1n=20Ram=C3=ADrez?= Date: Fri, 3 Jul 2026 16:41:40 +0200 Subject: [PATCH 395/462] =?UTF-8?q?=E2=AC=86=EF=B8=8F=20Update=20latest-ch?= =?UTF-8?q?anges=20to=200.6.1=20(#15926)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .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 111b47424..6f206940d 100644 --- a/.github/workflows/latest-changes.yml +++ b/.github/workflows/latest-changes.yml @@ -39,7 +39,7 @@ jobs: if: ${{ github.event_name == 'workflow_dispatch' && github.event.inputs.debug_enabled == 'true' }} with: limit-access-to-actor: true - - uses: tiangolo/latest-changes@eb3f6e7ff0073896ecb561e774a121de9418fa06 # 0.5.0 + - uses: tiangolo/latest-changes@c9b73efbc8992ef1a401e4235ea307a8ca8a724b # 0.6.1 with: token: ${{ secrets.GITHUB_TOKEN }} latest_changes_file: docs/en/docs/release-notes.md From f9816e4aa3e4e6ae55abd3fe4a190a6fa9da2c43 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Fri, 3 Jul 2026 14:43:06 +0000 Subject: [PATCH 396/462] =?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 583a78a37..fff0bc193 100644 --- a/docs/en/docs/release-notes.md +++ b/docs/en/docs/release-notes.md @@ -13,6 +13,10 @@ hide: * 🌐 Update `llm-prompt.md` for Hindi. PR [#15810](https://github.com/fastapi/fastapi/pull/15810) by [@YuriiMotov](https://github.com/YuriiMotov). * 🌐 Fix language-specific translation prompt for Russian language. PR [#15924](https://github.com/fastapi/fastapi/pull/15924) by [@YuriiMotov](https://github.com/YuriiMotov). +### Internal + +* ⬆️ Update latest-changes to 0.6.1. PR [#15926](https://github.com/fastapi/fastapi/pull/15926) by [@tiangolo](https://github.com/tiangolo). + ## 0.139.0 (2026-07-01) ### Features From 9c913b7bf748db2f1b2ed7a02c45264abc208698 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebasti=C3=A1n=20Ram=C3=ADrez?= Date: Fri, 3 Jul 2026 21:08:33 +0200 Subject: [PATCH 397/462] =?UTF-8?q?=E2=AC=86=EF=B8=8F=20Update=20issue-man?= =?UTF-8?q?ager=20to=200.8.1=20(#15928)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .github/workflows/issue-manager.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/issue-manager.yml b/.github/workflows/issue-manager.yml index bba089c6f..e7f3a5f53 100644 --- a/.github/workflows/issue-manager.yml +++ b/.github/workflows/issue-manager.yml @@ -29,6 +29,6 @@ jobs: env: GITHUB_CONTEXT: ${{ toJson(github) }} run: echo "$GITHUB_CONTEXT" - - uses: tiangolo/issue-manager@75d60679db1ea348f6f6ea1d0e20de80a7c04645 # 0.7.1 + - uses: tiangolo/issue-manager@dc846170c36eb62fb434b3d943b36399fe240fb5 # 0.8.1 with: token: ${{ secrets.GITHUB_TOKEN }} From 0475b62ff7dff909db08dc9bba96607ec08e2b5d Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Fri, 3 Jul 2026 19:10:54 +0000 Subject: [PATCH 398/462] =?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 fff0bc193..7bf1c2778 100644 --- a/docs/en/docs/release-notes.md +++ b/docs/en/docs/release-notes.md @@ -15,6 +15,7 @@ hide: ### Internal +* ⬆️ Update issue-manager to 0.8.1. PR [#15928](https://github.com/fastapi/fastapi/pull/15928) by [@tiangolo](https://github.com/tiangolo). * ⬆️ Update latest-changes to 0.6.1. PR [#15926](https://github.com/fastapi/fastapi/pull/15926) by [@tiangolo](https://github.com/tiangolo). ## 0.139.0 (2026-07-01) From 28c6fa1132b62489aef98234a09a8a663495d67b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebasti=C3=A1n=20Ram=C3=ADrez?= Date: Sat, 4 Jul 2026 15:14:37 +0200 Subject: [PATCH 399/462] =?UTF-8?q?=F0=9F=94=A7=20Update=20sponsors:=20rem?= =?UTF-8?q?ove=20RapidProxy=20(#15929)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 1 - docs/en/data/sponsors.yml | 3 --- 2 files changed, 4 deletions(-) diff --git a/README.md b/README.md index 03cd90e77..42f26ecde 100644 --- a/README.md +++ b/README.md @@ -66,7 +66,6 @@ The key features are: - diff --git a/docs/en/data/sponsors.yml b/docs/en/data/sponsors.yml index ae2c0f6e2..12b812c2a 100644 --- a/docs/en/data/sponsors.yml +++ b/docs/en/data/sponsors.yml @@ -51,9 +51,6 @@ silver: - url: https://dribia.com/en/ title: Dribia - Data Science within your reach img: /img/sponsors/dribia.png - - url: https://www.rapidproxy.io/?ref=fastapi - title: Try RapidProxy for free - Residential Proxies with 90M+ Global IPs. Starting from $0.65/GB for web scraping, automation, and data collection. - img: /img/sponsors/rapidproxy.png - url: https://www.bairesdev.com/ title: "BairesDev | Nearshore Software Development & Staff Augmentation Company" img: /img/sponsors/bairesdev.svg From fdfd5091f149bd9c7281c2bcc4bb867bdaa1269c Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Sat, 4 Jul 2026 13:15:08 +0000 Subject: [PATCH 400/462] =?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 7bf1c2778..25ffd4d59 100644 --- a/docs/en/docs/release-notes.md +++ b/docs/en/docs/release-notes.md @@ -15,6 +15,7 @@ hide: ### Internal +* 🔧 Update sponsors: remove RapidProxy. PR [#15929](https://github.com/fastapi/fastapi/pull/15929) by [@tiangolo](https://github.com/tiangolo). * ⬆️ Update issue-manager to 0.8.1. PR [#15928](https://github.com/fastapi/fastapi/pull/15928) by [@tiangolo](https://github.com/tiangolo). * ⬆️ Update latest-changes to 0.6.1. PR [#15926](https://github.com/fastapi/fastapi/pull/15926) by [@tiangolo](https://github.com/tiangolo). From f500ef131e0c00bd42b26706ce75ece89eb39081 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebasti=C3=A1n=20Ram=C3=ADrez?= Date: Sat, 4 Jul 2026 22:03:22 +0200 Subject: [PATCH 401/462] =?UTF-8?q?=F0=9F=91=B7=20Fix=20latest-changes=20c?= =?UTF-8?q?heckout=20target=20(#15932)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .github/workflows/latest-changes.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/latest-changes.yml b/.github/workflows/latest-changes.yml index 6f206940d..be20c98ae 100644 --- a/.github/workflows/latest-changes.yml +++ b/.github/workflows/latest-changes.yml @@ -30,6 +30,7 @@ jobs: run: echo "$GITHUB_CONTEXT" - uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0 with: + ref: ${{ github.event.repository.default_branch }} # To allow latest-changes to commit to the main branch token: ${{ secrets.FASTAPI_LATEST_CHANGES }} # zizmor: ignore[secrets-outside-env] persist-credentials: true # required by tiangolo/latest-changes From 68c02766d4a537890a892d42c94fc4c4c4d16906 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Sat, 4 Jul 2026 20:04:00 +0000 Subject: [PATCH 402/462] =?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 25ffd4d59..888bdcc95 100644 --- a/docs/en/docs/release-notes.md +++ b/docs/en/docs/release-notes.md @@ -15,6 +15,7 @@ hide: ### Internal +* 👷 Fix latest-changes checkout target. PR [#15932](https://github.com/fastapi/fastapi/pull/15932) by [@tiangolo](https://github.com/tiangolo). * 🔧 Update sponsors: remove RapidProxy. PR [#15929](https://github.com/fastapi/fastapi/pull/15929) by [@tiangolo](https://github.com/tiangolo). * ⬆️ Update issue-manager to 0.8.1. PR [#15928](https://github.com/fastapi/fastapi/pull/15928) by [@tiangolo](https://github.com/tiangolo). * ⬆️ Update latest-changes to 0.6.1. PR [#15926](https://github.com/fastapi/fastapi/pull/15926) by [@tiangolo](https://github.com/tiangolo). From 787e11b4266581c7623afa1bd950aecfe64e8eea Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebasti=C3=A1n=20Ram=C3=ADrez?= Date: Sat, 4 Jul 2026 22:23:59 +0200 Subject: [PATCH 403/462] =?UTF-8?q?=F0=9F=91=B7=20Fix=20notify=20translati?= =?UTF-8?q?ons=20checkout=20target=20(#15933)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .github/workflows/notify-translations.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/notify-translations.yml b/.github/workflows/notify-translations.yml index aa006978c..261be1a98 100644 --- a/.github/workflows/notify-translations.yml +++ b/.github/workflows/notify-translations.yml @@ -32,6 +32,7 @@ jobs: run: echo "$GITHUB_CONTEXT" - uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0 with: + ref: ${{ github.event.repository.default_branch }} persist-credentials: false - name: Set up Python uses: actions/setup-python@ece7cb06caefa5fff74198d8649806c4678c61a1 # v6.3.0 From dd17e4f723a23854cfe4b9b6258e31efd86ea523 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Sat, 4 Jul 2026 20:24:30 +0000 Subject: [PATCH 404/462] =?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 888bdcc95..3af8a925b 100644 --- a/docs/en/docs/release-notes.md +++ b/docs/en/docs/release-notes.md @@ -15,6 +15,7 @@ hide: ### Internal +* 👷 Fix notify translations checkout target. PR [#15933](https://github.com/fastapi/fastapi/pull/15933) by [@tiangolo](https://github.com/tiangolo). * 👷 Fix latest-changes checkout target. PR [#15932](https://github.com/fastapi/fastapi/pull/15932) by [@tiangolo](https://github.com/tiangolo). * 🔧 Update sponsors: remove RapidProxy. PR [#15929](https://github.com/fastapi/fastapi/pull/15929) by [@tiangolo](https://github.com/tiangolo). * ⬆️ Update issue-manager to 0.8.1. PR [#15928](https://github.com/fastapi/fastapi/pull/15928) by [@tiangolo](https://github.com/tiangolo). From 4cafad584d5eb4cff0ace66f25b6b9a461d6fa6f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebasti=C3=A1n=20Ram=C3=ADrez?= Date: Tue, 7 Jul 2026 00:41:18 +0200 Subject: [PATCH 405/462] =?UTF-8?q?=F0=9F=94=A7=20Update=20sponsors:=20add?= =?UTF-8?q?=20TutorCruncher=20(#15947)?= 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/img/sponsors/tutorcruncher.png | Bin 0 -> 8061 bytes 4 files changed, 5 insertions(+) create mode 100644 docs/en/docs/img/sponsors/tutorcruncher.png diff --git a/README.md b/README.md index 42f26ecde..36d262983 100644 --- a/README.md +++ b/README.md @@ -67,6 +67,7 @@ The key features are: + diff --git a/docs/en/data/sponsors.yml b/docs/en/data/sponsors.yml index 12b812c2a..f2e5df571 100644 --- a/docs/en/data/sponsors.yml +++ b/docs/en/data/sponsors.yml @@ -54,6 +54,9 @@ silver: - url: https://www.bairesdev.com/ title: "BairesDev | Nearshore Software Development & Staff Augmentation Company" img: /img/sponsors/bairesdev.svg + - url: https://tutorcruncher.com/?utm_source=fastapi + title: TutorCruncher + img: /img/sponsors/tutorcruncher.png bronze: # - url: https://testdriven.io/courses/tdd-fastapi/ # title: Learn to build high-quality web apps with best practices diff --git a/docs/en/data/sponsors_badge.yml b/docs/en/data/sponsors_badge.yml index d35a4b19f..d2fd7029f 100644 --- a/docs/en/data/sponsors_badge.yml +++ b/docs/en/data/sponsors_badge.yml @@ -49,3 +49,4 @@ logins: - requestly - greptileai - talorelowen + - tutorcruncher diff --git a/docs/en/docs/img/sponsors/tutorcruncher.png b/docs/en/docs/img/sponsors/tutorcruncher.png new file mode 100644 index 0000000000000000000000000000000000000000..aae58b2f5e78d838dd0a19fe6125d430ca07ba22 GIT binary patch literal 8061 zcmeHMXH=8Rx&~1Q2#A36jua6SKzdVJrqHTAmzrr&pP|uANR*zcikU%t(~>Le3NrlLZR zdYJSw-4F&Gy2KmY>oaQF04MQe!s!K+G1|IP-92>oH=>!u-M zWoROF1A&AI$phtqGFNobaDO=wO$H%#q?5C%sgB;iC@8-)L|lD+y;MOU6bc1IT?HbL zE+API6%~+-97s;?3dQ1zPk^Vd1Nw@mkLYiTKRI+@K2Rjw%NLID6#C8S;E3?^)esS( z;6nc*|2;VWX7}{@mk1O&K)(@?EKmmYpXR=B=l{X{H}aSH@4~7ka5T)_N(b%%^Yo!K zK|@4NUgi(7ztFq?fy&DKiT-9%1$#KSz%1cTzOH{2`wM`;JY9Yx|E-8I5)Pwi@VmDZ zLK#c-$V0Tpa1*MKb8C~jsKDBAG!XP0)NZ+AMg4{uD_+g-!lHkyZ(R4 z#qd{f2lJ#vbSO&b_F=5mj}rFL_-KR80RX_*jPW!T6+05Fqh*dBUBkMd*<30gF7n0) zdOr)IaVNGbu7BYool>Me_2~M;9-2oPjZ7oYqcS?zCnhrLMph#)Ue{(d1@N1l8loS# zFZ87jDl;AFol@jpl-fHkcuMz$JM`n};mo~&pEz!~{8X*aLgtSUxux`uhtwY%&MGrf zQ)$ys0hp+S4^v{ny*2WxbWgYJs`jtH|6jd5yE-(ot*(5lA zY#|$a220y8*aho&#hZMt2*lnSW80zu7*;b(nbfjg;%SC{v1^c#VT1J93f9qVw*V%@ zC7@R#6q6#|EQ?~#-kO-O3qzf^7RPK%VRB3hWEn|Y)d>mAqN}U3EAKapnO;AVuj`u_ zC=ct_s>=#KeiA_X5|mCC^sIF6D3m+Tbbr2*Ut^+f<7B77(NR>;gR7ssw>q90aCjP= z3g!g$9Y7J5oEA*GSs<{8I9wZQHL)KQ4lk`}@sO zrNch8w)R%Q`{su4?sNy2%@<`TJ@DTcCo4?$_xJOg&d@C=rMEAU$tT++56<#1VepnG zmA~`*m*-f|Mn1X-CKz};%N-Ap=3#t5u*MC(MBXJB6q^>rSG}+(x>H~-l`^_LAsz09 zFfP^U>m9qykECO4@>Q*~&Ko3ee}RI7@`{T+Li#jG7T}4i81m zd%-$vlam#_Znc(fx5lD7%s54@C`(wxyW*o!7oPIrn+P?50qshrS_qrux_j@Bc}ZVe{xq>0+575&*f^1W55^r z?XVN0IlxTWtL8=DRIy#v4HZ?T1VV8GV%l5JHN}7sLLS;DK3QOk0G0qx%f8SDT>(z* zcY2-!?V+ZA(O`{~rpzsEPWE4v{tP}=%TOF09jPQ#o{%0V4oLYS5}#jeMO21WMK$N1 z|NK7X)-0Q&;YQyZg;bv{qvPOwv%Z3X<(G_+i^|<;<^7~tsB48*XPV$S!3MA6zU}RA zb8xf0byX8<^L%qDytqXD?w7y_liOO+ukB`+=Bn@as?$E!oJ&Rd`CzlM4km`wC~o

P`-(C72d;XreBWxA)iA1x!m_%B(c&HGLL38JO74rEy-GixEt8K1K@bi(^C?M@B~= zw{E5FyQ^k&R$A=)L;G`R^bz+;Z%eW($1ey~BxcLOcgNGz1%`sVMWYhzmBTJwg0;PM zaXI`xG1)gOmuIR1wKz!kyDXU4V+x`0v_ zSoe>PKY&7^jAgWswen0022dgudN>6WcCDV9TSEy3h*Dqj0?6Q2+j;F%ywusgT66P!Kn$r_CY`%hTv*$-fLvmX+??}Owe!AB59Y~*il|3+ zi?KACnzCUt`B=2`YjlB@@=63R;y9vyG%aLZ1k>sym!`ayP;+!d(`k5RUBL6k(>#+3 zd4(VQ!7*|#XKih6@kW~H?x$d<)_dW8!PME2BvZJ(L+I_!&QYbQ5f<(Xp2xzh;1&r% zkAixCnig+fUh3EuGb#2n0Z+tq^J4GWQk=ktkrw*>XVLM_41OM#Qdy~}E?^AAC`@@y z?yr@Q2b3t&=vlL4+BF$tr>xOBpKQ~D*{$keP2*CDjCAXju;J`fn|GVVLve5JoO|6@Pbhtx#U&6U6Ngg5TNWuyZ4BQrHJ5r9j~A3Xl6&Td^j;*8v=Yl?0xEy*&N^R{y-!y?Hshl6xvN~tgWw%G)Rcb zL)-)3x5BnSRcqD$J0Bk7yqZ_?W|QtKW{9nkuRRM`>1ch6i%K9?tKuOU4>-Kb#xsKz zV+j;VZZw8-L!42TsD(|o#V#k#3(wgXQXvYLqbQDp3TZIL^>(~WQG`0DW6E*&@C^Yt z=ZzAY9RgD}Vt=J6?C2auWy$jrsOX|=Me1NNV+L2FbNQ9ZV?FJ?-EGf(ry4>hS7e!$ zw7$d)i8WmhNB?BkH(W+f?a}q=X_=*V_Js@c3v)ky*2W_m1lTzJ@HYwPrES&iB`c;5 zmUqkXU1H*5r%xX+wb|~>@rI#2`sS=+7jO`9{CRn$D!SDNaQSr3R8ZjhzDws12C^_e z6J>E57?|%wDZU)!c@4QW>!p11t14`8NO8Onv3<6>|F9Mr5(<#xlG9eJ}xW=X`B+b8G z$PPKwg?o=A-9X4B89do)mBxURJL)n^2OfyxL>p=MOj)#}!Ss)`sHIY*lq9BRza1Xx z&YX7`9APeypy&DYzD-m=8e3;)`andJCJ6vucoQ=_37&F4NU@N?>tHk zYZV2{$*Kqo^-Kl3&_1re-&;#@z&uEXfx~0uO>ftCiC=@hcQN9^?fC6J)HJ&p8cq}+ z=qaJ9_RlU_IWZe`C0y#q$V6P=VCTK;&Za3MNG>}ve4-g5S5)!Zy*k$_&-BFi@O7DQ zNMBO>g&n^t7VX}$+k=UUs*eSfRA^f^$wQu2=9>v!35-QY=jC>s1>Tumes}&mx>i<2 zffh5fJnyh0f&opNvFDo?Ld3Mppln(!81a@~*J{5;#ju%i7iWCNVh_L}D@$Myg?)@; z5r*LUpP>xjNSF34`_3j^r>qaKCt(jkT0LW9qw@?;_7{iMhOb5%Ulj;w>mBw|BX0+g zhuv#M&88JTs)5|*^cvGqPwVMQk__UM>zzrN&wfy=g;MI3(R+YZ^hdcN~|IK=)?6`c#19ZOqqrR<&$W`jRXw^u}$;nz`zPZ zrF~JMk&$7AYf?tP@Nx(7c~t-R<>gDF-8q^MxENIvNEg9{8%DbEBci98;xv}$p6ihL z4u+}|`uX_y1j>6tLXLvMl)Vn-MrO90Ba*&$M+pHUSW?^PkwmDv6+o$yhmp3u2COM0 z3T~3T76qCf8y@~j>r}PEdqi{i7F9ja^QM0}Gm}r5ugi7i-SE$seaTzzleZ2&(8lt# zOLLekcHJ9pSbT*~ZHY_k*Sm8h6yfmlp0PFFKcp{oMR?F+cw}sIU%jAW!yk%?E&9Ro z=tb^3I-8#{Nq9V6q;MK!VRprU1=@f{yT>%{Dz@qix(j?-pxmZk>&2aIRoCR4d4sQM zkzaJ@IZB>IVnc^debWXoN3D?;Z`?NbzMW=J@E+)Lb}LpghJl&hF`)z!9TUx^G+9(- z8F;^2I1jl5`H)jG6KtWVEvYH&DZdvjD|w$w{F$%ScC0*)VE}x-32=o4AdXH{;$jR) zJ^S|TUOF!!`_PB1WWQFs*s+`R^u}Xu#xI>@1uQ>y(8k7QjCTbQFP<6{p`FT}TGy}) zvXm-`bHDny^*ixI!5i1o-~PCLrfojv@h|2KDH*H`3a{AVztfcsH<}7E7Zx5%6%}LFe=J@jj}8bkBy0m8*|ThUSc0D4Tf`PbOJ8{e^K^D zUW7uLpi$|NeZiZ9rHu@=i`Yp`Hs=ll-ueBQ!(cBygd1FKvmcJ}H^^J*d4wA(La0N= zU-d_St6&$$q@h$!`ku5eCrfh@$2CCA|4EoXb4-rYq@9_9N^4e7EJo1Mj z4b6MwW8!=#(?%%Kqs5gYJ}#s!X9%-c4h(J}(GhL6CNAfqgN#{*0Rq?_X6DAPOW$vC zBHwr0t*)-dM8|6@7fKerEv)6>=D%%f?p$^)qiJ_nU}|zOboJ{=D~v&3!odptCN}nJ zq=Tck$w9|*3$x4mK`26B-{o*l*+wm6GHdc}`G`s?l3rETWpeeG^)asicO`nck)mlT zN9w?kf=-Lh(_mdbV2$ypz2E%GK;eTt?cZ|QH9XjkKl7|KG3?>g&I&L0uf%TygHcbS z9>|Z*HYR_G{IXR2CVV_Rio0WJ_$e4e0y^7|mK}{PXpLMV$db2qp|F3kTB;DrP=4S-{hvvGQ9K7Tk2(kSZ+s^sxV1GQ7n{01Wvx5QgtRUtWITq}JA6aHM17cI_ zK03;tMV{@w;Y&5*zUy{EOz08{C3@}O{F10I7pkKyr)d?z+~`+YE8mMur-`>>U>@b+ zWBoapA5RIv{E7@vJ7pP}uVG(vDBXcN zih8WM-<7V!l$$w0J{Kyqlh|e@8A#s5Pr_RD$0DR~wwPQ=Mz;M}?WWJ}3C)>eeQ>{f zq`Jn&8+;w1NG+Eh(OhxbGju``GK^(+rO$y9E4T~X28-FFXfv?lePl2SHIyV%wzI7X z7aEbaNK%%R`8pN699vUk6Re$y!_a6eYd`H?j6Mv`N=vD9o{)+?bH*Aw`AJKXnJH^p z!&BZF=l1?tath_>U4=OMKrDb+2eyTCE~u!enX>y43J=N?tH7gb5b9z5xhu@{a{P&) zX?%BPs61)7x2Yxmm(1M`!?0jA%6$wiRbq0`9Mv&({l?M$ghzHrz!turvM6@h%SgyW z4)D%k5CStCK(q_JSD{I zub<#fYYCk^Sms<8Sm#eRViZ=@(rMOtd#}c^8dhIY(sf$Pm0-=-1PFI_aiM8qQV-3M zWrWJ5UA6@I`LeH%_`M<)oN@Tt+PwUv`3GfgCicV<%B!GdclC18Ao=lE08HxK+E6Y% zQCDz*8DiptoxRNld85W@ Date: Mon, 6 Jul 2026 22:41:52 +0000 Subject: [PATCH 406/462] =?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 3af8a925b..c2dac0c4c 100644 --- a/docs/en/docs/release-notes.md +++ b/docs/en/docs/release-notes.md @@ -15,6 +15,7 @@ hide: ### Internal +* 🔧 Update sponsors: add TutorCruncher. PR [#15947](https://github.com/fastapi/fastapi/pull/15947) by [@tiangolo](https://github.com/tiangolo). * 👷 Fix notify translations checkout target. PR [#15933](https://github.com/fastapi/fastapi/pull/15933) by [@tiangolo](https://github.com/tiangolo). * 👷 Fix latest-changes checkout target. PR [#15932](https://github.com/fastapi/fastapi/pull/15932) by [@tiangolo](https://github.com/tiangolo). * 🔧 Update sponsors: remove RapidProxy. PR [#15929](https://github.com/fastapi/fastapi/pull/15929) by [@tiangolo](https://github.com/tiangolo). From 74963395fc32638a2b698d9fc0b2a46961556b1b Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 7 Jul 2026 21:00:31 +0200 Subject: [PATCH 407/462] =?UTF-8?q?=E2=AC=86=20Bump=20the=20python-package?= =?UTF-8?q?s=20group=20with=208=20updates=20(#15952)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- uv.lock | 1429 ++++--------------------------------------------------- 1 file changed, 82 insertions(+), 1347 deletions(-) diff --git a/uv.lock b/uv.lock index 4fdc971ee..25cd6e8a8 100644 --- a/uv.lock +++ b/uv.lock @@ -19,18 +19,6 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/02/d5/349aba3dc421e73cbd4958c0ce0a4f1aa3a738bc0d7de75d2f40ed43a535/a2wsgi-1.10.10-py3-none-any.whl", hash = "sha256:d2b21379479718539dc15fce53b876251a0efe7615352dfe49f6ad1bc507848d", size = 17389, upload-time = "2025-06-18T09:00:09.676Z" }, ] -[[package]] -name = "ag-ui-protocol" -version = "0.1.10" -source = { registry = "https://pypi.org/simple" } -dependencies = [ - { name = "pydantic" }, -] -sdist = { url = "https://files.pythonhosted.org/packages/67/bb/5a5ec893eea5805fb9a3db76a9888c3429710dfb6f24bbb37568f2cf7320/ag_ui_protocol-0.1.10.tar.gz", hash = "sha256:3213991c6b2eb24bb1a8c362ee270c16705a07a4c5962267a083d0959ed894f4", size = 6945, upload-time = "2025-11-06T15:17:17.068Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/8f/78/eb55fabaab41abc53f52c0918a9a8c0f747807e5306273f51120fd695957/ag_ui_protocol-0.1.10-py3-none-any.whl", hash = "sha256:c81e6981f30aabdf97a7ee312bfd4df0cd38e718d9fc10019c7d438128b93ab5", size = 7889, upload-time = "2025-11-06T15:17:15.325Z" }, -] - [[package]] name = "aiofile" version = "3.9.0" @@ -43,165 +31,6 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/50/25/da1f0b4dd970e52bf5a36c204c107e11a0c6d3ed195eba0bfbc664c312b2/aiofile-3.9.0-py3-none-any.whl", hash = "sha256:ce2f6c1571538cbdfa0143b04e16b208ecb0e9cb4148e528af8a640ed51cc8aa", size = 19539, upload-time = "2024-10-08T10:39:32.955Z" }, ] -[[package]] -name = "aiohappyeyeballs" -version = "2.6.1" -source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/26/30/f84a107a9c4331c14b2b586036f40965c128aa4fee4dda5d3d51cb14ad54/aiohappyeyeballs-2.6.1.tar.gz", hash = "sha256:c3f9d0113123803ccadfdf3f0faa505bc78e6a72d1cc4806cbd719826e943558", size = 22760, upload-time = "2025-03-12T01:42:48.764Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/0f/15/5bf3b99495fb160b63f95972b81750f18f7f4e02ad051373b669d17d44f2/aiohappyeyeballs-2.6.1-py3-none-any.whl", hash = "sha256:f349ba8f4b75cb25c99c5c2d84e997e485204d2902a9597802b0371f09331fb8", size = 15265, upload-time = "2025-03-12T01:42:47.083Z" }, -] - -[[package]] -name = "aiohttp" -version = "3.14.1" -source = { registry = "https://pypi.org/simple" } -dependencies = [ - { name = "aiohappyeyeballs" }, - { name = "aiosignal" }, - { name = "async-timeout", marker = "python_full_version < '3.11'" }, - { name = "attrs" }, - { name = "frozenlist" }, - { name = "multidict" }, - { name = "propcache" }, - { name = "typing-extensions", marker = "python_full_version < '3.13'" }, - { name = "yarl" }, -] -sdist = { url = "https://files.pythonhosted.org/packages/82/78/8ea7308cac6934de8c74a14f3d5f65d1c89287426688be79538d0e5c013d/aiohttp-3.14.1.tar.gz", hash = "sha256:307f2cff90a764d329e77040603fa032db89c5c24fdad50c4c15334cba744035", size = 7955794, upload-time = "2026-06-07T21:09:35.529Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/6d/67/58ded4b3f2e10f94972d8928050c85330e249a31dd45a0e5f3c0e9c3fa05/aiohttp-3.14.1-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:8f6bb621e5863cfe8fe5ff5468002d200ec31f30f1280b259dc505b02595099e", size = 766140, upload-time = "2026-06-07T21:05:37.471Z" }, - { url = "https://files.pythonhosted.org/packages/18/68/4ae5b4e08943f316594bb68da89957d3baf5760588fa09509594bd777e4b/aiohttp-3.14.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:4f7215cb3933784f79ed20e5f050e15984f390424339b22375d5a53c933a0491", size = 519430, upload-time = "2026-06-07T21:05:40.751Z" }, - { url = "https://files.pythonhosted.org/packages/cb/c1/316c8f3549dbe5245f92bfd523ec6f32dd4d98cafe21df3f6a19b1184c75/aiohttp-3.14.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:d9d4e294455b23a68c9b8f042d0e8e377a265bcb15332753695f6e5b6819e0ce", size = 514406, upload-time = "2026-06-07T21:05:42.111Z" }, - { url = "https://files.pythonhosted.org/packages/5a/ee/fb0ac28684e8d753b83c8a4eebc19a5846912aa0a4daaabb6a9936363840/aiohttp-3.14.1-cp310-cp310-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:b238af795833d5731d049d82bc84b768ae6f8f97f0495963b3ed9935c5901cc3", size = 1703649, upload-time = "2026-06-07T21:05:43.427Z" }, - { url = "https://files.pythonhosted.org/packages/3b/57/aa2beab673331f111885db8a7b69dfe3ab0e53e446a0ace18ca694b4dc58/aiohttp-3.14.1-cp310-cp310-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:e4e5e0ae56914ecdbf446493addefc0159053dd53962cef37d7839f37f73d505", size = 1675126, upload-time = "2026-06-07T21:05:44.897Z" }, - { url = "https://files.pythonhosted.org/packages/47/ea/dad128abe365e79be03b16ed464198ac73e0d257e8260c6f7d6f31cbef26/aiohttp-3.14.1-cp310-cp310-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:092e4ce3619a7c6dee52a6bdabda973d9b34b66781f840ce93c7e0cec30cf521", size = 1771558, upload-time = "2026-06-07T21:05:46.405Z" }, - { url = "https://files.pythonhosted.org/packages/63/f3/b5b4e10327cb85d34d24232c6b71b64602f190b3ccb238a043ac6b187dac/aiohttp-3.14.1-cp310-cp310-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:bb33777ea21e8b7ecde0e6fc84f598be0a1192eab1a63bc746d75aa75d38e7bd", size = 1856631, upload-time = "2026-06-07T21:05:47.844Z" }, - { url = "https://files.pythonhosted.org/packages/2b/9d/93294c3045775c708ac8310eb3d3622a11d2951345ad590d532d62a1faa4/aiohttp-3.14.1-cp310-cp310-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:23119f8fd4f5d16902ed459b63b100bcd269628075162bddac56cc7b5273b3fb", size = 1714139, upload-time = "2026-06-07T21:05:49.982Z" }, - { url = "https://files.pythonhosted.org/packages/29/c4/93067c85a0373492ce8e577435203c5947c454af074ac48ed4f3a1b9dd4a/aiohttp-3.14.1-cp310-cp310-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:57fc6745a4b7d0f5a9eb4f40a69718be6c0bc1b8368cc9fe89e90118719f4f42", size = 1588321, upload-time = "2026-06-07T21:05:51.431Z" }, - { url = "https://files.pythonhosted.org/packages/c4/39/9ff91aaf02af8b7b8222a987466da539f154c3e01732c22b5f5a20a8ee66/aiohttp-3.14.1-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:6fd35beba67c4183b09375c5fff9accb47524191a244a99f95fd4472f5402c2b", size = 1670375, upload-time = "2026-06-07T21:05:53.109Z" }, - { url = "https://files.pythonhosted.org/packages/aa/e4/77452a3676b8d99ac1375f77691d6bf65ea6e9f4b201b82ef77c916dc767/aiohttp-3.14.1-cp310-cp310-musllinux_1_2_armv7l.whl", hash = "sha256:672b9d65f42eb877f5c3f234a4547e4e1a226ca8c2eed879bb34670a0ce51192", size = 1690933, upload-time = "2026-06-07T21:05:54.902Z" }, - { url = "https://files.pythonhosted.org/packages/7d/84/b0059a7c7fc05ea23f3bc1596ba91c12f79588b9450564a24cac37536d0a/aiohttp-3.14.1-cp310-cp310-musllinux_1_2_ppc64le.whl", hash = "sha256:24ba13339fed9251d9b1a1bec8c7ab84c0d1675d79d33501e11f94f8b9a84e05", size = 1740798, upload-time = "2026-06-07T21:05:56.458Z" }, - { url = "https://files.pythonhosted.org/packages/8f/3a/e2a513ecbfc362591caa51a7f7e011b3bfc8938b388ae44cd95560d36999/aiohttp-3.14.1-cp310-cp310-musllinux_1_2_riscv64.whl", hash = "sha256:94da27378da0610e341c4d30de29a191672683cc82b8f9556e8f7c7212a020fe", size = 1576412, upload-time = "2026-06-07T21:05:57.953Z" }, - { url = "https://files.pythonhosted.org/packages/a1/10/08f1654f538f93d36dcac66310a06eefce4641cdafca83f9f0a5317be254/aiohttp-3.14.1-cp310-cp310-musllinux_1_2_s390x.whl", hash = "sha256:52cdac9432d8b4a719f35094a818d95adcae0f0b4fe9b9b921909e0c87de9e7d", size = 1750199, upload-time = "2026-06-07T21:05:59.488Z" }, - { url = "https://files.pythonhosted.org/packages/99/e4/d91b70c57d8b8e9611e4a2e52238ca3698d3dc1c2efe25b7a9bf594ac584/aiohttp-3.14.1-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:672ac254412a24d0d0cf00a9e6c238877e4be5e5fa2d188832c1244f45f31966", size = 1699356, upload-time = "2026-06-07T21:06:01.131Z" }, - { url = "https://files.pythonhosted.org/packages/3d/f1/15340176f35ff61b95dbe34020bcf43f9e624a2d7bbac934715ff97d2033/aiohttp-3.14.1-cp310-cp310-win32.whl", hash = "sha256:2fe3607e71acc6ebb0ec8e492a247bf7a291226192dc0084236dfc12478916f6", size = 458939, upload-time = "2026-06-07T21:06:02.86Z" }, - { url = "https://files.pythonhosted.org/packages/c3/c2/a2f1ec5b37f903109e43ae2862268cfe4a67a60c1b2cf43169fcdff5995f/aiohttp-3.14.1-cp310-cp310-win_amd64.whl", hash = "sha256:30099eda75a53c32efb0920e9c33c195314d2cc1c680fbfd30894932ac5f27df", size = 482583, upload-time = "2026-06-07T21:06:04.666Z" }, - { url = "https://files.pythonhosted.org/packages/d0/7a/7b56f6732ef79530afaa72aa335d41b67c8d79b946995f0b11ad72985435/aiohttp-3.14.1-cp310-cp310-win_arm64.whl", hash = "sha256:5a837f49d901f9e368651b676912bff1104ed8c1a83b280bcd7b29adccef5c9c", size = 453470, upload-time = "2026-06-07T21:06:06.322Z" }, - { url = "https://files.pythonhosted.org/packages/26/dd/bf526e6f0a1120dd6f2df2e97bacfe4d358f13d17a0ff5847301a1375a51/aiohttp-3.14.1-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:aa00140699487bd435fde4342d85c94cb256b7cd3a5b9c3396c67f19922afda2", size = 765225, upload-time = "2026-06-07T21:06:07.957Z" }, - { url = "https://files.pythonhosted.org/packages/8f/e1/a2872aa55495a70f61310d411541c6ee23812d9a884e000c716e1bc3edbf/aiohttp-3.14.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:1c1af67559445498b502030c35c59db59966f47041ca9de5b4e707f86bd10b5f", size = 518743, upload-time = "2026-06-07T21:06:09.749Z" }, - { url = "https://files.pythonhosted.org/packages/5b/e7/c60c7b209e509cc787de3cea0550a518538cfc08003e1c1e14c1c63fff71/aiohttp-3.14.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:d44ec478e713ee7f29b439f7eb8dc2b9d4079e11ae114d2c2ac3d5daf30516c8", size = 514139, upload-time = "2026-06-07T21:06:11.26Z" }, - { url = "https://files.pythonhosted.org/packages/5b/8d/614ace2f579702c9840ab1e1447fd8509e35b0b904f7196418fa2f57b25d/aiohttp-3.14.1-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:d3b1a184a9a8f548a6b73f1e26b96b052193e4b3175ed7342aaf1151a1f00a04", size = 1784088, upload-time = "2026-06-07T21:06:12.887Z" }, - { url = "https://files.pythonhosted.org/packages/49/e0/726e90f99542bf292f81a96a12cc4847deb86f3ccf62c6f4014a201f4d33/aiohttp-3.14.1-cp311-cp311-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:5f2504bc0322437c9a1ff6d3333ca56c7477b727c995f036b976ae17b98372c8", size = 1737835, upload-time = "2026-06-07T21:06:14.564Z" }, - { url = "https://files.pythonhosted.org/packages/0b/4b/d176d5c4db9d33dacf0543102ea59503bc1d528af4cfd0b719949ca49389/aiohttp-3.14.1-cp311-cp311-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:73f05ea02013e02512c3bf42714f1208c57168c779cc6fe23516e4543089d0a6", size = 1842801, upload-time = "2026-06-07T21:06:16.228Z" }, - { url = "https://files.pythonhosted.org/packages/dc/d6/5a99b563690ea0cbed912ae94a2ce33993a5709a651a3a4fe761e7dd973a/aiohttp-3.14.1-cp311-cp311-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:797457503c2d426bee06eef808d07b31ede30b65e054444e7de64cad0061b7af", size = 1929992, upload-time = "2026-06-07T21:06:17.947Z" }, - { url = "https://files.pythonhosted.org/packages/76/7f/a987b14a3859094b3cea3f4825219c3e5536242564af6e3f9c2f6c994eb2/aiohttp-3.14.1-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:b821a1f7dedf7e37450654e620038ac3b2e81e8fa6ea269337e97101978ec730", size = 1786989, upload-time = "2026-06-07T21:06:19.677Z" }, - { url = "https://files.pythonhosted.org/packages/f1/1a/420e5c85a3e73349372ed22ce0b6af86bfa6ce16a4b20a64a2e94608c781/aiohttp-3.14.1-cp311-cp311-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:4cd96b5ba05d67ed0cf00b5b405c8cd99586d8e3481e8ee0a831057591af7621", size = 1640129, upload-time = "2026-06-07T21:06:22.558Z" }, - { url = "https://files.pythonhosted.org/packages/a7/80/18a592ed3be0a402cc03670bd72ee1f8563ddbe1d8d5542dbf868f274136/aiohttp-3.14.1-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:1d459b98a932296c6f0e94f87511a0b1b90a8a02c30a50e60a297619cd5a58ee", size = 1756576, upload-time = "2026-06-07T21:06:24.8Z" }, - { url = "https://files.pythonhosted.org/packages/ec/0b/8b3d5713373858ff71a617daf6e3b0e81ad63e79d09a3cf2f6b6b983939c/aiohttp-3.14.1-cp311-cp311-musllinux_1_2_armv7l.whl", hash = "sha256:764457a7be60825fb770a644852ff717bcbb5042f189f2bd16df61a81b3f6573", size = 1754668, upload-time = "2026-06-07T21:06:26.528Z" }, - { url = "https://files.pythonhosted.org/packages/9f/49/fd564575cf225821d7ba5a117cb8bc27213d8a7e1811162afb43ae077039/aiohttp-3.14.1-cp311-cp311-musllinux_1_2_ppc64le.whl", hash = "sha256:f7a16ef45b081454ef844502d87a848876c490c4cb5c650c230f6ec79ed2c1e7", size = 1817019, upload-time = "2026-06-07T21:06:28.297Z" }, - { url = "https://files.pythonhosted.org/packages/ed/1b/e850c9ae6fc91356552ae668bb6c51e93fa29c8aef13398a10b56678557f/aiohttp-3.14.1-cp311-cp311-musllinux_1_2_riscv64.whl", hash = "sha256:2fbc3ed048b3475b9f0cbcb9978e9d2d3511acd91ead203af26ed9f0056004cf", size = 1631638, upload-time = "2026-06-07T21:06:30.242Z" }, - { url = "https://files.pythonhosted.org/packages/eb/94/3c337ba72451a89806ace6f75bddc92bafc5b8d53d90115a512858024b63/aiohttp-3.14.1-cp311-cp311-musllinux_1_2_s390x.whl", hash = "sha256:bedb0cd073cc2dc035e30aeb99444389d3cd2113afe4ef9fcd23d439f5bade85", size = 1835660, upload-time = "2026-06-07T21:06:31.943Z" }, - { url = "https://files.pythonhosted.org/packages/2b/9c/9c18cf367a0498212d9ba7daf990b504a5e8ae064cda4b504e2647c89c03/aiohttp-3.14.1-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:b6feea921016eb3d4e04d65fc4e9ca402d1a3801f562aef94989f54694917af3", size = 1775698, upload-time = "2026-06-07T21:06:33.72Z" }, - { url = "https://files.pythonhosted.org/packages/b5/63/a251a9d2a6cb45065b2ddc0bde2b3dd10108740a9a42f632c66405a761a2/aiohttp-3.14.1-cp311-cp311-win32.whl", hash = "sha256:313701e488100074ce99850404ee36e741abf6330179fec908a1944ecf570126", size = 458386, upload-time = "2026-06-07T21:06:35.279Z" }, - { url = "https://files.pythonhosted.org/packages/17/ca/69274c51dcd6e8947d77b2806cf47a4a15f2c846e2cbeb1882547d3da283/aiohttp-3.14.1-cp311-cp311-win_amd64.whl", hash = "sha256:03ab4530fdcb3a543a122ba4b65ac9919da9fe9f78a03d328a6e38ff962f7aa5", size = 483406, upload-time = "2026-06-07T21:06:36.824Z" }, - { url = "https://files.pythonhosted.org/packages/2c/8a/c25904f77690c3688ec140f87591ef11a0cfe36bf3d5c0f1f38056fb62b3/aiohttp-3.14.1-cp311-cp311-win_arm64.whl", hash = "sha256:486f7d16ed54c39c2cbd7ca71fd8ba2b8bb7860df65bd7b6ed640bab96a38a8b", size = 452987, upload-time = "2026-06-07T21:06:38.371Z" }, - { url = "https://files.pythonhosted.org/packages/1d/21/151624b51cd92553d95424daf4bf19f19ce9be9002d19253e7e7ce67197b/aiohttp-3.14.1-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:d35143e27778b4bb0fb189562d7f275bff79c62ab8e98459717c0ea617ff2480", size = 757402, upload-time = "2026-06-07T21:06:40.311Z" }, - { url = "https://files.pythonhosted.org/packages/c2/82/280619e0bd7bf2454987e19282616e84762255dd9c8468f62382e8c191f1/aiohttp-3.14.1-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:bcfb80a2cc36fba2534e5e5b5264dc7ae6fcd9bf15256da3e53d2f499e6fa29d", size = 512310, upload-time = "2026-06-07T21:06:42.207Z" }, - { url = "https://files.pythonhosted.org/packages/55/b2/2aac325583aaa1353045f96dffa586d8a34e8322e14a7ba49cffeb103ab4/aiohttp-3.14.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:27fd7c91e51729b4f7e1577865fa6d34c9adccbc39aabe9000285b48af9f0ec2", size = 512448, upload-time = "2026-06-07T21:06:43.813Z" }, - { url = "https://files.pythonhosted.org/packages/8a/72/a60607cb849faa8af8a356c9329ea2eb6f395d49e82cc82ccba1fd8deb8f/aiohttp-3.14.1-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:64c567bf9eaf664280116a8688f63016e6b32db2505908e2bdaca1b6438142f2", size = 1766854, upload-time = "2026-06-07T21:06:45.391Z" }, - { url = "https://files.pythonhosted.org/packages/b5/d3/d9fe1c9ec7557ab4d0d82bebaa728c6418f0b93295ec2f4ab015f7710cc7/aiohttp-3.14.1-cp312-cp312-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:f5e6ff2bdbb8f4cd3fbe41f99e25bbcd58e3bf9f13d3dd31a11e7917251cc77a", size = 1740884, upload-time = "2026-06-07T21:06:47.413Z" }, - { url = "https://files.pythonhosted.org/packages/c1/dc/f2cecfaf9337ba3e63f181500814ff502aa3d00d9c7ec93a9d23d10a27b2/aiohttp-3.14.1-cp312-cp312-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:2f73e01dc37122325caf079982621262f96d74823c179038a82fddfc50359264", size = 1810034, upload-time = "2026-06-07T21:06:50.165Z" }, - { url = "https://files.pythonhosted.org/packages/66/d7/2ff65c5e65c0d7476daf7e15c032e0805e36811185b9623e3238ad6c763e/aiohttp-3.14.1-cp312-cp312-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:bb2c0c80d431c0d03f2c7dbf125150fedd4f0de17366a7ca33f7ccb822391842", size = 1904054, upload-time = "2026-06-07T21:06:52.035Z" }, - { url = "https://files.pythonhosted.org/packages/20/9c/d445818389df371f56d141d881153ba23183c4735a03f7356ffb43f7757d/aiohttp-3.14.1-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:3e6fc1a85fa7194a1a7d19f44e8609180f4a8eb5fa4c7ed8b4355f080fad235c", size = 1790278, upload-time = "2026-06-07T21:06:54.049Z" }, - { url = "https://files.pythonhosted.org/packages/4d/aa/bf04cb4d865fc6101c2229a294ad744973b72e513fdc5a6b791e6983d72a/aiohttp-3.14.1-cp312-cp312-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:686b6c0d3911ec387b444ddf5dc62fb7f7c0a7d5186a7861626496a5ab4aff95", size = 1591795, upload-time = "2026-06-07T21:06:55.911Z" }, - { url = "https://files.pythonhosted.org/packages/dc/b4/4dac0038960427ba832f6609dfb4ea5437d7fd80c72001b9e48f834f428b/aiohttp-3.14.1-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:c6fa4dc7ad6f8109c70bb1499e589f76b0b792baf39f9b017eb92c8a81d0a199", size = 1728397, upload-time = "2026-06-07T21:06:57.777Z" }, - { url = "https://files.pythonhosted.org/packages/2b/f9/7cd4e8ad7aa3b75f17d56bb5498dd604a93d4e6eece822ba0568c413fff0/aiohttp-3.14.1-cp312-cp312-musllinux_1_2_armv7l.whl", hash = "sha256:87a5eea1b2a5e21e1ebdbb33ad4165359189327e63fc4e4894693e7f821ac817", size = 1766504, upload-time = "2026-06-07T21:07:00.009Z" }, - { url = "https://files.pythonhosted.org/packages/f9/df/fc01d9fcad0f73fed3f3d361f1f94f975947b50dff82919f6dc2bf4316cc/aiohttp-3.14.1-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:1c1421eb01d4fd608d88cc8290211d177a58532b55ad94076fb349c5bf467f0a", size = 1777806, upload-time = "2026-06-07T21:07:02.064Z" }, - { url = "https://files.pythonhosted.org/packages/41/09/47e2d090bddcc8fb4ccb4c314aadc32d7c5d9bb55f50f6ad1c92fc15d501/aiohttp-3.14.1-cp312-cp312-musllinux_1_2_riscv64.whl", hash = "sha256:34b257ec41345c1e8f2df68fa908a7952f5de932723871eb633ecbbff396c9a4", size = 1580707, upload-time = "2026-06-07T21:07:03.942Z" }, - { url = "https://files.pythonhosted.org/packages/3d/36/f1a4ce904ae0b6930cfe9afc96d0896f7ec1a620c400405d63783bb95a9c/aiohttp-3.14.1-cp312-cp312-musllinux_1_2_s390x.whl", hash = "sha256:de538791a80e5d862addbc183f70f0158ac9b9bb872bb147f1fd2a683691e087", size = 1798121, upload-time = "2026-06-07T21:07:05.987Z" }, - { url = "https://files.pythonhosted.org/packages/70/0a/e0075ce9ca0279ee1d4f0c0b85f54fea02ebc83c3007651a72bece658fec/aiohttp-3.14.1-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:6f71173be42d3241d428f760122febb748de0623f44308a6f120d0dd9ec572e3", size = 1767580, upload-time = "2026-06-07T21:07:07.873Z" }, - { url = "https://files.pythonhosted.org/packages/3e/61/a0c0a8f327a9c52095cdd8e312391b00d3ed64ab6c72bb5c33d8ec251cf7/aiohttp-3.14.1-cp312-cp312-win32.whl", hash = "sha256:ec8dc383ee57ea3e883477dcca3f11b65d58199f1080acaf4cd6ad9a99698be4", size = 452771, upload-time = "2026-06-07T21:07:09.669Z" }, - { url = "https://files.pythonhosted.org/packages/df/d9/ea367c75f16ac9c6cdc8febb25e8318fa21a2b1bc8d6514d4b2d890bface/aiohttp-3.14.1-cp312-cp312-win_amd64.whl", hash = "sha256:2aa92c87868cd13674989f9ee83e5f9f7ea4237589b728048e1f0c8f6caa3271", size = 479873, upload-time = "2026-06-07T21:07:11.538Z" }, - { url = "https://files.pythonhosted.org/packages/03/64/8d96784a7851156db8a4c6c3f6f91042fdf39fb15a4cc38c8b3c14833c45/aiohttp-3.14.1-cp312-cp312-win_arm64.whl", hash = "sha256:2c840c90759922cb5e6dda94596e079a30fb5a5ba548e7e0dc00574703940847", size = 448073, upload-time = "2026-06-07T21:07:13.637Z" }, - { url = "https://files.pythonhosted.org/packages/bc/97/bd137012dd97e1649162b099135a80e1fd59aaa807b2430fc448d1029aff/aiohttp-3.14.1-cp313-cp313-android_21_arm64_v8a.whl", hash = "sha256:b3a03285a7f9c7b016324574a6d92a1c895da6b978cb8f1deee3ac72bc6da178", size = 506882, upload-time = "2026-06-07T21:07:15.501Z" }, - { url = "https://files.pythonhosted.org/packages/ef/79/e5cc690e9d922a66887ceeaca53a8ffd5a7b0be3816142b7abc433742d89/aiohttp-3.14.1-cp313-cp313-android_21_x86_64.whl", hash = "sha256:2a73f487ab8ef5abbb24b7aa9b73e98eaba9e9e031804ff2416f02eca315ccaf", size = 515270, upload-time = "2026-06-07T21:07:17.53Z" }, - { url = "https://files.pythonhosted.org/packages/fe/22/a73ccbf9dbd6e26dda0b24d5fd5db7da92ee3383a79f47677ffb834c5c5b/aiohttp-3.14.1-cp313-cp313-ios_13_0_arm64_iphoneos.whl", hash = "sha256:915fbb7b41b115192259f8c9ae58f3ddc444d2b5579917270211858e606a4afd", size = 485841, upload-time = "2026-06-07T21:07:19.555Z" }, - { url = "https://files.pythonhosted.org/packages/3b/b9/57ed8eaf596321c2ad747bd480fb1700dbd7177c60dfc9e4c187f629662e/aiohttp-3.14.1-cp313-cp313-ios_13_0_arm64_iphonesimulator.whl", hash = "sha256:7fb4bdf95b0561a79f259f9d28fbc109728c5ee7f27aff6391f0ca703a329abe", size = 492088, upload-time = "2026-06-07T21:07:21.581Z" }, - { url = "https://files.pythonhosted.org/packages/78/c0/5ebe5270a7c140d7c6f79dcb018640225f14d406c149e4eec04a7d82fe71/aiohttp-3.14.1-cp313-cp313-ios_13_0_x86_64_iphonesimulator.whl", hash = "sha256:1b9748363260121d2927704f5d4fc498150669ca3ae93625986ee89c8f80dcd4", size = 501564, upload-time = "2026-06-07T21:07:23.388Z" }, - { url = "https://files.pythonhosted.org/packages/75/7f/8cdaa24fc7983865e0915153b96a9ac5bcdd3548d64c5a27d17cecccad2d/aiohttp-3.14.1-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:86a6dab78b0e43e2897a3bbe15745aa60dc5423ca437b7b0b164c069bf91b876", size = 751998, upload-time = "2026-06-07T21:07:25.046Z" }, - { url = "https://files.pythonhosted.org/packages/b2/f4/c4227aacfacc5cb0cc2d119b65301d177912a6842cd64e120c47af76064f/aiohttp-3.14.1-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:4dfd6e47d3c44c2279907607f73a4240b88c69eb8b90da7e2441a8045dfd21da", size = 510918, upload-time = "2026-06-07T21:07:27.28Z" }, - { url = "https://files.pythonhosted.org/packages/ab/01/a2d5f96cd4e74424864d30bc0a7e44d0a12dacdcfa91b5b2d1bd3dca6bf3/aiohttp-3.14.1-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:317acd9f8602858dc7d59679812c376c7f0b97bcbbf16e0d6237f54141d8a8a6", size = 508657, upload-time = "2026-06-07T21:07:29.252Z" }, - { url = "https://files.pythonhosted.org/packages/e8/ed/3c0fb5c500fdd8e7ebc10d1889c04384fffa1a9163eac1356088ca9da1b1/aiohttp-3.14.1-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:bd869c427324e5cb15195793de951295710db28be7d818247f3097b4ab5d4b96", size = 1757907, upload-time = "2026-06-07T21:07:31.03Z" }, - { url = "https://files.pythonhosted.org/packages/0b/ab/d4c924d9bd5be3050c226612413ce68cb54c70d2c31b661bfc8d9a5b6a70/aiohttp-3.14.1-cp313-cp313-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:93b032b5ec3255473c143627d21a69ac74ae12f7f33974cb587c564d11b1066f", size = 1737565, upload-time = "2026-06-07T21:07:33.031Z" }, - { url = "https://files.pythonhosted.org/packages/19/2a/37326821ff779084020cdc33224d20b19f42f4183a500ff92022a739eda7/aiohttp-3.14.1-cp313-cp313-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:f234b4deb12f3ad59127e037bc57c40c21e45b45282df7d3a55a0f409f595296", size = 1799018, upload-time = "2026-06-07T21:07:35.003Z" }, - { url = "https://files.pythonhosted.org/packages/b3/4f/6e947ba73e4ce09070761c05ed3a8ceb7c21f5e46798671d8b2aac0e4626/aiohttp-3.14.1-cp313-cp313-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:9af6779bfb46abf124068327abcdf9ce95c9ef8287a3e8da76ccf2d0f16c28fa", size = 1894416, upload-time = "2026-06-07T21:07:36.956Z" }, - { url = "https://files.pythonhosted.org/packages/9d/6e/dbf1d0625dc711fb2851f4f3c3055c39ed58bae92082d8c627dbe6013736/aiohttp-3.14.1-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:faccab372e66bc76d5731525e7f1143c922271725b9d38c9f97edcc66266b451", size = 1783881, upload-time = "2026-06-07T21:07:39.063Z" }, - { url = "https://files.pythonhosted.org/packages/44/c2/5e25098a67268ed369483ae7d1a58bd0a13d03aab860d2a0e4a6eb25b046/aiohttp-3.14.1-cp313-cp313-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:f380468b09d2a81633ee863b0ec5648d364bd17bb8ecfb8c2f387f7ac1faf42c", size = 1587572, upload-time = "2026-06-07T21:07:41.058Z" }, - { url = "https://files.pythonhosted.org/packages/2a/bd/cf9cee17e140f942a3de73e658a543aa8fbf35a5fc67a9d2538d52d77f0b/aiohttp-3.14.1-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:97e704dcd26271f5bda3fa07c3ce0fb76d6d3f8659f4baa1a24442cc9ba177ca", size = 1722137, upload-time = "2026-06-07T21:07:43.014Z" }, - { url = "https://files.pythonhosted.org/packages/89/6d/5684f8c59045c96f81a18cefbc1fbbd79d25b88f1c622f2a5c5c08fcb632/aiohttp-3.14.1-cp313-cp313-musllinux_1_2_armv7l.whl", hash = "sha256:269b76ac5394092b95bc4a098f4fc6c191c083c3bd12775d1e30e663132f6a09", size = 1755953, upload-time = "2026-06-07T21:07:45.933Z" }, - { url = "https://files.pythonhosted.org/packages/a8/40/35caf3170f8359760740a7d9aa0fff2e344bef98e1d1186f5a0f6dec17e6/aiohttp-3.14.1-cp313-cp313-musllinux_1_2_ppc64le.whl", hash = "sha256:5c0b3e614340c889d575451696374c9d17affd54cd607ca0babed8f8c37b9397", size = 1766479, upload-time = "2026-06-07T21:07:48.047Z" }, - { url = "https://files.pythonhosted.org/packages/6d/a1/b0c61e7a137f0d81de49a82023a6df73c3c16d6fefb0f8e4a93d21639002/aiohttp-3.14.1-cp313-cp313-musllinux_1_2_riscv64.whl", hash = "sha256:5663ee9257cfa1add7253a7da3035a02f31b6600ec48261585e1800a81533080", size = 1580077, upload-time = "2026-06-07T21:07:50.069Z" }, - { url = "https://files.pythonhosted.org/packages/0b/41/194ea4623693009fcefebef7aef63c141754f153e9cd0d39d3b9e36c175c/aiohttp-3.14.1-cp313-cp313-musllinux_1_2_s390x.whl", hash = "sha256:603a2c834142172ffddc054067f5ec0ca65d57a0aa98a71bc81952573208e345", size = 1791688, upload-time = "2026-06-07T21:07:52.106Z" }, - { url = "https://files.pythonhosted.org/packages/ba/45/4de841f005cfe1fd63e2a2fe011262c515e2a62aa6994b15947e7d717ac9/aiohttp-3.14.1-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:cb21957bb8aca671c1765e32f58164cf0c50e6bf41c0bbbd16da20732ecaf588", size = 1761094, upload-time = "2026-06-07T21:07:54.113Z" }, - { url = "https://files.pythonhosted.org/packages/e4/ae/dbce10533d3896d544d5053939ed75b7dc31a1b0973d959b1b5ae21028d6/aiohttp-3.14.1-cp313-cp313-win32.whl", hash = "sha256:e509a55f681e6158c20f70f102f9cf61fb20fbc382272bc6d94b7343f2582780", size = 452662, upload-time = "2026-06-07T21:07:56.06Z" }, - { url = "https://files.pythonhosted.org/packages/7b/d9/0bf1a19362c32f06229da5e7ddfcec91f93474d6307f7a2d3135e9c674dc/aiohttp-3.14.1-cp313-cp313-win_amd64.whl", hash = "sha256:1ac8531b638959718e18c2207fbfe297819875da46a740b29dfa29beba64355a", size = 479748, upload-time = "2026-06-07T21:07:58.319Z" }, - { url = "https://files.pythonhosted.org/packages/22/0a/62e7232dc9484fbec112ceb32efb6a624cc7994ec6e2b019286f17c4e8f2/aiohttp-3.14.1-cp313-cp313-win_arm64.whl", hash = "sha256:250d14af67f6b6a1a4a811049b1afa69d61d617fca6bf33149b3ab1a6dbcf7b8", size = 447723, upload-time = "2026-06-07T21:08:00.154Z" }, - { url = "https://files.pythonhosted.org/packages/c4/a1/5fafa04e1ca91ddb47608699d60649c1c6db3cf41c99e78fc4056f9513db/aiohttp-3.14.1-cp314-cp314-android_24_arm64_v8a.whl", hash = "sha256:7c106c26852ca1c2047c6b80384f17100b4e439af276f21ef3d4e2f450ae7e15", size = 508531, upload-time = "2026-06-07T21:08:02.093Z" }, - { url = "https://files.pythonhosted.org/packages/fa/2e/bfa02f699d87ffc86d5959270b28f1cb410add3ccaced8ed2e0b8a5238fc/aiohttp-3.14.1-cp314-cp314-android_24_x86_64.whl", hash = "sha256:20205f7f5ade7aaec9f4b500549bbc071b046453aed72f9c06dcab87896a83e8", size = 514718, upload-time = "2026-06-07T21:08:04.476Z" }, - { url = "https://files.pythonhosted.org/packages/85/a5/9594ad6289eebbc97d167c44213d557807f90e59115caad24de21ad2c3b1/aiohttp-3.14.1-cp314-cp314-ios_13_0_arm64_iphoneos.whl", hash = "sha256:62a759436b29e677181a9e76bab8b8f689a29cb9c535f45f7c48c9c830d3f8c3", size = 487918, upload-time = "2026-06-07T21:08:06.377Z" }, - { url = "https://files.pythonhosted.org/packages/b4/61/16a32c36c3c49edec122a3dc811f2057df2f94d3b14aa107c8017d981618/aiohttp-3.14.1-cp314-cp314-ios_13_0_arm64_iphonesimulator.whl", hash = "sha256:2964cbf553df4d7a57348da44d961d871895fc1ee4e8c322b2a95612c7b17fba", size = 494014, upload-time = "2026-06-07T21:08:08.263Z" }, - { url = "https://files.pythonhosted.org/packages/9b/89/3ebcf96ed99c05bec9c434aaac6963fd3cbab4a786ae739908a144d9ce44/aiohttp-3.14.1-cp314-cp314-ios_13_0_x86_64_iphonesimulator.whl", hash = "sha256:237651caadc3a59badd39319c54642b5299e9cc98a3a194310e55d5bb9f5e397", size = 502398, upload-time = "2026-06-07T21:08:10.244Z" }, - { url = "https://files.pythonhosted.org/packages/fd/3d/b74870a0c2d40c355928cd5b96c7a11fa821b8a40fc41365e64479b151fb/aiohttp-3.14.1-cp314-cp314-macosx_10_15_universal2.whl", hash = "sha256:896e12dfdbbab9d8f7e16d2b28c6769a60126fa92095d1ebf9473d02593a2448", size = 758018, upload-time = "2026-06-07T21:08:12.447Z" }, - { url = "https://files.pythonhosted.org/packages/d3/66/f42f5c984d99e49c6cff5f26f590750f2e2f7ef1fcfb99966ab5be1b632e/aiohttp-3.14.1-cp314-cp314-macosx_10_15_x86_64.whl", hash = "sha256:d03f281ed22579314ba00821ce20115a7c0ac430660b4cc05704a3f818b3e004", size = 512462, upload-time = "2026-06-07T21:08:14.624Z" }, - { url = "https://files.pythonhosted.org/packages/e9/a7/248e1aebe0c7810b0271e021a0f2a5eb6e78a051885b3c9df49f42a5802d/aiohttp-3.14.1-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:07eabb979d236335fed927e137a928c9adfb7df3b9ec7aa31726f133a62be983", size = 512824, upload-time = "2026-06-07T21:08:16.572Z" }, - { url = "https://files.pythonhosted.org/packages/26/97/2aa0e5ba0727dc3bd5aaebb7ccbc510f7dfb7fb961ec87497cd496635ab1/aiohttp-3.14.1-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:4fe1f1087cbadb280b5e1bb054a4f00d1423c74d6626c5e48400d871d34ecefe", size = 1749898, upload-time = "2026-06-07T21:08:18.635Z" }, - { url = "https://files.pythonhosted.org/packages/00/8d/e97f6c96c891d457c8479d92a514ba194d0412f981d72c70341ee18488ed/aiohttp-3.14.1-cp314-cp314-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:367a9314fdc79dab0fac96e216cb41dd73c85bdca85306ce8999118ba7e0f333", size = 1710114, upload-time = "2026-06-07T21:08:20.892Z" }, - { url = "https://files.pythonhosted.org/packages/6f/e6/aa8d7e863048c8fceb5cd6ce74017311cec3ead07847387e12265fb4444e/aiohttp-3.14.1-cp314-cp314-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:a24f677ebe83749039e7bdf862ff0bbb16818ae4193d4ef96505e269375bcce0", size = 1802541, upload-time = "2026-06-07T21:08:23.044Z" }, - { url = "https://files.pythonhosted.org/packages/83/a8/72193137de57fda4ebfae4563182d082c8856e3b6e9871d0b46f028fb369/aiohttp-3.14.1-cp314-cp314-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:c83afe0ba876be7e943d2e0ba645809ad441575d2840c895c21ee5de93b9377a", size = 1875776, upload-time = "2026-06-07T21:08:25.288Z" }, - { url = "https://files.pythonhosted.org/packages/a0/18/938441025db6769a3464596b2410af3afde0b21eb2f204c6f766f68af4bd/aiohttp-3.14.1-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:634e385930fb6d2d479cf3aa66515955863b77a5e3c2b5894ca259a25b308602", size = 1760329, upload-time = "2026-06-07T21:08:27.363Z" }, - { url = "https://files.pythonhosted.org/packages/60/29/bf2496b4065e76e09fe48015aaffe5ce161d8f089b06ac6982070f653076/aiohttp-3.14.1-cp314-cp314-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:eeea07c4397bbc57719c4eed8f9c284874d4f175f9b6d57f7a1546b976d455ca", size = 1587293, upload-time = "2026-06-07T21:08:29.805Z" }, - { url = "https://files.pythonhosted.org/packages/49/a2/2136674d52123b1354bd05dd5753c318db47dc0c927cc70b27bab3755456/aiohttp-3.14.1-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:335c0cc3e3545ce98dcb9cfcb836f40c3411f43fa03dab757597d80c89af8a35", size = 1714756, upload-time = "2026-06-07T21:08:32.094Z" }, - { url = "https://files.pythonhosted.org/packages/a7/b9/e5fd2e6f915503081c0f9b1e8540947037929c70c191da2e4d54b31a21a1/aiohttp-3.14.1-cp314-cp314-musllinux_1_2_armv7l.whl", hash = "sha256:ae6be797afdef264e8a84864a85b196ca06045586481b3df8a967322fd2fa844", size = 1721052, upload-time = "2026-06-07T21:08:34.167Z" }, - { url = "https://files.pythonhosted.org/packages/63/5a/2833e324a2263e104e31e2e91bc5bbee81bc499afd32203faee048a883f0/aiohttp-3.14.1-cp314-cp314-musllinux_1_2_ppc64le.whl", hash = "sha256:8560b4d712474335d08907db7973f71912d3a9a8f1dee992ec06b5d2fe359496", size = 1766888, upload-time = "2026-06-07T21:08:36.95Z" }, - { url = "https://files.pythonhosted.org/packages/57/fa/dea6511870913162f3b2e8c42a7614eb203a4540b8c2da43e0bfb0548f3c/aiohttp-3.14.1-cp314-cp314-musllinux_1_2_riscv64.whl", hash = "sha256:2b7edd08e0a5deb1e8564a2fcd8f4561014a3f05252334671bbf55ddd47db0e5", size = 1581679, upload-time = "2026-06-07T21:08:39.292Z" }, - { url = "https://files.pythonhosted.org/packages/14/bd/3cf0d55e71784b33534e9710a67d382d900598b4787fbce6cc7317f8c42a/aiohttp-3.14.1-cp314-cp314-musllinux_1_2_s390x.whl", hash = "sha256:b6ff7fcee63287ae57b5df3e4f5957ce032122802509246dec1a5bcc55904c95", size = 1782021, upload-time = "2026-06-07T21:08:41.407Z" }, - { url = "https://files.pythonhosted.org/packages/c1/af/14bb5843eccbe234f4dfb78ab73e549d99727247e62ae5d62cbd22eaf5b0/aiohttp-3.14.1-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:6ffbb2f4ec1ceaff7e07d43922954da26b223d188bf30658e561b98e23089444", size = 1742574, upload-time = "2026-06-07T21:08:43.795Z" }, - { url = "https://files.pythonhosted.org/packages/f2/1e/fbeb7af9210a67ac0f9c9bec0f8f4568497924e33137a3d5b48e1cf85f3f/aiohttp-3.14.1-cp314-cp314-win32.whl", hash = "sha256:a9875b46d910cff3ea2f5962f9d266b465459fe634e22556ab9bd6fc1192eea0", size = 457773, upload-time = "2026-06-07T21:08:46.168Z" }, - { url = "https://files.pythonhosted.org/packages/f0/2b/13e8d741a9ec5db7d900c060554cf8352ab85e44e2a4469ebb9d377bda17/aiohttp-3.14.1-cp314-cp314-win_amd64.whl", hash = "sha256:af8b4b81a960eeaf1234971ac3cd0ba5901f3cd42eae42a46b4d089a8b492719", size = 485001, upload-time = "2026-06-07T21:08:48.401Z" }, - { url = "https://files.pythonhosted.org/packages/df/30/491acfa2c4d6c3ff59c49a14fc1b50be3241e25bbb0c84c09e2da4d11395/aiohttp-3.14.1-cp314-cp314-win_arm64.whl", hash = "sha256:cf4491381b1b57425c315a56a439251b1bdac07b2275f19a8c44bc57744532ec", size = 453809, upload-time = "2026-06-07T21:08:50.7Z" }, - { url = "https://files.pythonhosted.org/packages/34/e3/19dbe1a1f4cc6230eb9e314de7fe68053b0992f9302b27d12141a0b5db53/aiohttp-3.14.1-cp314-cp314t-macosx_10_15_universal2.whl", hash = "sha256:819c054312f1af92947e6a55883d1b66feefab11531a7fc45e0fb9b63880b5c2", size = 793320, upload-time = "2026-06-07T21:08:52.775Z" }, - { url = "https://files.pythonhosted.org/packages/7f/20/1b7182219ba1b108430d6e4dc53d25ae02dcfcf5a045b33af4e8c5167527/aiohttp-3.14.1-cp314-cp314t-macosx_10_15_x86_64.whl", hash = "sha256:10ee9c1753a8f706345b22496c79fbddb5be0599e0823f3738b1534058e25340", size = 529077, upload-time = "2026-06-07T21:08:55Z" }, - { url = "https://files.pythonhosted.org/packages/b9/c8/14ce60ec31a2e5f5274bb17d383a6f7a3aabca31ac04eee05585bbadab16/aiohttp-3.14.1-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:1601cc37baf5750ccacae618ec2daf020769581695550e3b654a911f859c563d", size = 532476, upload-time = "2026-06-07T21:08:57.176Z" }, - { url = "https://files.pythonhosted.org/packages/7e/02/9ac85e081e53da2e061b02fa7758fe0a12d17b8ce2d1f5e6c7cb76730328/aiohttp-3.14.1-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:4d6e0ac9da31c9c04c84e1c0182ad8d6df35965a85cae29cd71d089621b3ae94", size = 1922347, upload-time = "2026-06-07T21:08:59.563Z" }, - { url = "https://files.pythonhosted.org/packages/c0/3e/d3ba07a0ab38b5389e10bec4362d21e10a4f667cba2d79ba30837b3a5059/aiohttp-3.14.1-cp314-cp314t-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:9e8f2d660c350b3d0e259c7a7e3d9b7fc8b41210cbcc3d4a7076ff0a5e5c2fdc", size = 1786465, upload-time = "2026-06-07T21:09:01.909Z" }, - { url = "https://files.pythonhosted.org/packages/0b/cb/e2ee978a00cfb2df829704a69528b18154eba5939f45bc1efa8f33aee4c5/aiohttp-3.14.1-cp314-cp314t-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:4691802dda97be727f79d86818acaad7eb8e9252626a1d6b519fedbb92d5e251", size = 1909423, upload-time = "2026-06-07T21:09:04.357Z" }, - { url = "https://files.pythonhosted.org/packages/73/5d/1430334858b1022b58ae50399a918f0bd6fe8fa7fa183598d657ff61e040/aiohttp-3.14.1-cp314-cp314t-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:c389c482a7e9b9dc3ee2701ac46c4125297a3818875b9c305ddb603c04828fd1", size = 2001906, upload-time = "2026-06-07T21:09:06.722Z" }, - { url = "https://files.pythonhosted.org/packages/66/4e/560c7472d3d198a23aa5c8b19a5115bf6a9b77b7d3e4bb363da320430ad2/aiohttp-3.14.1-cp314-cp314t-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:fc0cacab7ba4e56f0f81c82a98c09bed2f39c940107b03a34b168bdf7597edd3", size = 1877095, upload-time = "2026-06-07T21:09:09.011Z" }, - { url = "https://files.pythonhosted.org/packages/0d/f1/4745806578d447db4a784a8591e2dae3afdfc2bcb96f8f81271b13df6543/aiohttp-3.14.1-cp314-cp314t-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:979ed4717f59b8bb12e3963378fa285d93d367e15bcd66c721311826d3c44a6c", size = 1676222, upload-time = "2026-06-07T21:09:11.461Z" }, - { url = "https://files.pythonhosted.org/packages/6a/c9/48255813cca749a229ef0ab476004ec623728ad79a9c0840616f6c076325/aiohttp-3.14.1-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:38e1e7daaea81df51c952e18483f323d878499a1e2bfe564790e0f9701d6f203", size = 1842922, upload-time = "2026-06-07T21:09:14.118Z" }, - { url = "https://files.pythonhosted.org/packages/3d/c0/bbd054e2bee909f529523a5af3891052606af5143c09f5f183ec3b234676/aiohttp-3.14.1-cp314-cp314t-musllinux_1_2_armv7l.whl", hash = "sha256:4132e72c608fe9fecb8f409113567605915b83e9bdd3ea56538d2f9cd35002f1", size = 1825035, upload-time = "2026-06-07T21:09:16.447Z" }, - { url = "https://files.pythonhosted.org/packages/a8/ae/90395d4376deceb74e09ec26b6adf7d2015a6f8802d6d84446af860fef04/aiohttp-3.14.1-cp314-cp314t-musllinux_1_2_ppc64le.whl", hash = "sha256:eefd9cc9b6d4a2db5f00a26bc3e4f9acf71926a6ec557cd56c9c6f27c290b665", size = 1849512, upload-time = "2026-06-07T21:09:18.742Z" }, - { url = "https://files.pythonhosted.org/packages/93/bd/fb25f3049957553d4ce0ba6ae480aa2f592a6985497fca590837d16c1be0/aiohttp-3.14.1-cp314-cp314t-musllinux_1_2_riscv64.whl", hash = "sha256:b165790117eea512d7f3fb22f1f6dad3d55a7189571993eb015591c1401276d1", size = 1668571, upload-time = "2026-06-07T21:09:21.458Z" }, - { url = "https://files.pythonhosted.org/packages/3f/22/7f73303d64dd567ff3addca90b556690ed1233a47b8f55d242fb90af3681/aiohttp-3.14.1-cp314-cp314t-musllinux_1_2_s390x.whl", hash = "sha256:ed09c7eb1c391271c2ed0314a51903e72a3acb653d5ccfc264cdf3ef11f8269d", size = 1881159, upload-time = "2026-06-07T21:09:23.813Z" }, - { url = "https://files.pythonhosted.org/packages/44/be/0474c5a8b5640e1e4aa1923430a91f4151be82e511373fe764189b89aef5/aiohttp-3.14.1-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:99abd37084b82f5830c635fddd0b4993b9742a66eb746dacf433c8590e8f9e3c", size = 1841409, upload-time = "2026-06-07T21:09:26.207Z" }, - { url = "https://files.pythonhosted.org/packages/7b/3c/bb4a7cba26956cb3da4553cc2056cf67be5b5ff6e6d8fa4fbdff73bfb7ae/aiohttp-3.14.1-cp314-cp314t-win32.whl", hash = "sha256:47ddf841cdecc810749921d25606dee45857d12d2ad5ddb7b5bd7eab12e4b365", size = 494166, upload-time = "2026-06-07T21:09:28.505Z" }, - { url = "https://files.pythonhosted.org/packages/8a/84/ec80c2c1f66a952555a9f86df6b33af65108a6febfa0471b69013a12f807/aiohttp-3.14.1-cp314-cp314t-win_amd64.whl", hash = "sha256:5e78b522b7a6e27e0b25d19b247b75039ac4c94f99823e3c9e53ae1603a9f7e9", size = 530255, upload-time = "2026-06-07T21:09:30.843Z" }, - { url = "https://files.pythonhosted.org/packages/2a/71/6e22be134a4061ada85a92951b842f2657f17d926b727f3f94c56ae963d6/aiohttp-3.14.1-cp314-cp314t-win_arm64.whl", hash = "sha256:90d53f1609c29ccc2193945ef732428382a28f78d0456ae4d3daf0d48b74f0f6", size = 469640, upload-time = "2026-06-07T21:09:33.028Z" }, -] - -[[package]] -name = "aiosignal" -version = "1.4.0" -source = { registry = "https://pypi.org/simple" } -dependencies = [ - { name = "frozenlist" }, - { name = "typing-extensions", marker = "python_full_version < '3.13'" }, -] -sdist = { url = "https://files.pythonhosted.org/packages/61/62/06741b579156360248d1ec624842ad0edf697050bbaf7c3e46394e106ad1/aiosignal-1.4.0.tar.gz", hash = "sha256:f47eecd9468083c2029cc99945502cb7708b082c232f9aca65da147157b251c7", size = 25007, upload-time = "2025-07-03T22:54:43.528Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/fb/76/641ae371508676492379f16e2fa48f4e2c11741bd63c48be4b12a6b09cba/aiosignal-1.4.0-py3-none-any.whl", hash = "sha256:053243f8b92b990551949e63930a839ff0cf0b0ebbe0597b0f3fb19e1a0fe82e", size = 7490, upload-time = "2025-07-03T22:54:42.156Z" }, -] - [[package]] name = "annotated-doc" version = "0.0.4" @@ -364,15 +193,6 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/d2/39/e7eaf1799466a4aef85b6a4fe7bd175ad2b1c6345066aa33f1f58d4b18d0/asttokens-3.0.1-py3-none-any.whl", hash = "sha256:15a3ebc0f43c2d0a50eeafea25e19046c68398e487b9f1f5b517f7c0f40f976a", size = 27047, upload-time = "2025-11-15T16:43:16.109Z" }, ] -[[package]] -name = "async-timeout" -version = "5.0.1" -source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/a5/ae/136395dfbfe00dfc94da3f3e136d0b13f394cba8f4841120e34226265780/async_timeout-5.0.1.tar.gz", hash = "sha256:d9321a7a3d5a6a5e187e824d2fa0793ce379a202935782d555d6e9d2735677d3", size = 9274, upload-time = "2024-11-06T16:41:39.6Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/fe/ba/e2081de779ca30d473f21f5b30e0e737c438205440784c7dfc81efc2b029/async_timeout-5.0.1-py3-none-any.whl", hash = "sha256:39e3809566ff85354557ec2398b55e096c8364bacac9405a7a1fa429e77fe76c", size = 6233, upload-time = "2024-11-06T16:41:37.9Z" }, -] - [[package]] name = "attrs" version = "25.4.0" @@ -466,34 +286,6 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/10/cb/f2ad4230dc2eb1a74edf38f1a38b9b52277f75bef262d8908e60d957e13c/blinker-1.9.0-py3-none-any.whl", hash = "sha256:ba0efaa9080b619ff2f3459d1d500c57bddea4a6b424b60a91141db6fd2f08bc", size = 8458, upload-time = "2024-11-08T17:25:46.184Z" }, ] -[[package]] -name = "boto3" -version = "1.42.94" -source = { registry = "https://pypi.org/simple" } -dependencies = [ - { name = "botocore" }, - { name = "jmespath" }, - { name = "s3transfer" }, -] -sdist = { url = "https://files.pythonhosted.org/packages/6a/6a/95302333208830de932ad1d0b69599ee13e936349a44981fb72632507861/boto3-1.42.94.tar.gz", hash = "sha256:5b6056a661c19e974aaea3cb97690ddbe30d10c31e4f887df3bff06574f34510", size = 113211, upload-time = "2026-04-22T20:36:19.167Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/c4/6f/4e175604f3168befcb413c95bf45eada67d12042f92f76a9305d6a817ea9/boto3-1.42.94-py3-none-any.whl", hash = "sha256:56d53bce75629cc7c78a32da8b62de74cee3e2a3d54a2b60ba1a65f9f1b129da", size = 140555, upload-time = "2026-04-22T20:36:16.182Z" }, -] - -[[package]] -name = "botocore" -version = "1.42.94" -source = { registry = "https://pypi.org/simple" } -dependencies = [ - { name = "jmespath" }, - { name = "python-dateutil" }, - { name = "urllib3" }, -] -sdist = { url = "https://files.pythonhosted.org/packages/b7/90/1a4d0e81b325d38e37f81d907ceacac3b8f509ad38b495bb95086ecb609d/botocore-1.42.94.tar.gz", hash = "sha256:41c6b3b11b073221a41f52b222ba387be34459fb77cdc506e8b74cdaf24bdcce", size = 15260901, upload-time = "2026-04-22T20:36:00.853Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/61/73/313af9ee02ac0155247bcf3f04fcf54fcae2e33250bb437528c18aeefd81/botocore-1.42.94-py3-none-any.whl", hash = "sha256:a2143742132ed0f6cdb90204d667b89d0301068b1045e8bc099efa267bf1b348", size = 14942938, upload-time = "2026-04-22T20:35:55.663Z" }, -] - [[package]] name = "cachetools" version = "7.0.0" @@ -752,25 +544,6 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/85/32/10bb5764d90a8eee674e9dc6f4db6a0ab47c8c4d0d83c27f7c39ac415a4d/click-8.2.1-py3-none-any.whl", hash = "sha256:61a3265b914e850b85317d0b3109c7f8cd35a670f963866005d6ef1d5175a12b", size = 102215, upload-time = "2025-05-20T23:19:47.796Z" }, ] -[[package]] -name = "cohere" -version = "5.20.7" -source = { registry = "https://pypi.org/simple" } -dependencies = [ - { name = "fastavro" }, - { name = "httpx" }, - { name = "pydantic" }, - { name = "pydantic-core" }, - { name = "requests" }, - { name = "tokenizers" }, - { name = "types-requests" }, - { name = "typing-extensions" }, -] -sdist = { url = "https://files.pythonhosted.org/packages/44/0b/96e2b55a0114ed9d69b3154565f54b764e7530735426290b000f467f4c0f/cohere-5.20.7.tar.gz", hash = "sha256:997ed85fabb3a1e4a4c036fdb520382e7bfa670db48eb59a026803b6f7061dbb", size = 184986, upload-time = "2026-02-25T01:22:18.673Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/9d/86/dc991a75e3b9c2007b90dbfaf7f36fdb2457c216f799e26ce0474faf0c1f/cohere-5.20.7-py3-none-any.whl", hash = "sha256:043fef2a12c30c07e9b2c1f0b869fd66ffd911f58d1492f87e901c4190a65914", size = 323389, upload-time = "2026-02-25T01:22:16.902Z" }, -] - [[package]] name = "colorama" version = "0.4.6" @@ -978,23 +751,6 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/c0/c0/9f59d2ebd9d585e1681c51767eb138bcd9d0ea770f6fc003cd875c7f5e62/cyclic-1.0.0-py3-none-any.whl", hash = "sha256:32d8181d7698f426bce6f14f4c3921ef95b6a84af9f96192b59beb05bc00c3ed", size = 2547, upload-time = "2018-09-26T16:47:05.609Z" }, ] -[[package]] -name = "cyclopts" -version = "4.5.1" -source = { registry = "https://pypi.org/simple" } -dependencies = [ - { name = "attrs" }, - { name = "docstring-parser" }, - { name = "rich" }, - { name = "rich-rst" }, - { name = "tomli", marker = "python_full_version < '3.11'" }, - { name = "typing-extensions", marker = "python_full_version < '3.11'" }, -] -sdist = { url = "https://files.pythonhosted.org/packages/d4/93/6085aa89c3fff78a5180987354538d72e43b0db27e66a959302d0c07821a/cyclopts-4.5.1.tar.gz", hash = "sha256:fadc45304763fd9f5d6033727f176898d17a1778e194436964661a005078a3dd", size = 162075, upload-time = "2026-01-25T15:23:54.07Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/1c/7c/996760c30f1302704af57c66ff2d723f7d656d0d0b93563b5528a51484bb/cyclopts-4.5.1-py3-none-any.whl", hash = "sha256:0642c93601e554ca6b7b9abd81093847ea4448b2616280f2a0952416574e8c7a", size = 199807, upload-time = "2026-01-25T15:23:55.219Z" }, -] - [[package]] name = "deepmerge" version = "2.0" @@ -1049,15 +805,6 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/55/e2/2537ebcff11c1ee1ff17d8d0b6f4db75873e3b0fb32c2d4a2ee31ecb310a/docstring_parser-0.17.0-py3-none-any.whl", hash = "sha256:cf2569abd23dce8099b300f9b4fa8191e9582dda731fd533daf54c4551658708", size = 36896, upload-time = "2025-07-21T07:35:00.684Z" }, ] -[[package]] -name = "docutils" -version = "0.22.4" -source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/ae/b6/03bb70946330e88ffec97aefd3ea75ba575cb2e762061e0e62a213befee8/docutils-0.22.4.tar.gz", hash = "sha256:4db53b1fde9abecbb74d91230d32ab626d94f6badfc575d6db9194a49df29968", size = 2291750, upload-time = "2025-12-18T19:00:26.443Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/02/10/5da547df7a391dcde17f59520a231527b8571e6f46fc8efb02ccb370ab12/docutils-0.22.4-py3-none-any.whl", hash = "sha256:d0013f540772d1420576855455d050a2180186c91c15779301ac2ccb3eeb68de", size = 633196, upload-time = "2025-12-18T19:00:18.077Z" }, -] - [[package]] name = "email-validator" version = "2.3.0" @@ -1071,15 +818,6 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/de/15/545e2b6cf2e3be84bc1ed85613edd75b8aea69807a71c26f4ca6a9258e82/email_validator-2.3.0-py3-none-any.whl", hash = "sha256:80f13f623413e6b197ae73bb10bf4eb0908faf509ad8362c5edeb0be7fd450b4", size = 35604, upload-time = "2025-08-26T13:09:05.858Z" }, ] -[[package]] -name = "eval-type-backport" -version = "0.3.1" -source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/fb/a3/cafafb4558fd638aadfe4121dc6cefb8d743368c085acb2f521df0f3d9d7/eval_type_backport-0.3.1.tar.gz", hash = "sha256:57e993f7b5b69d271e37482e62f74e76a0276c82490cf8e4f0dffeb6b332d5ed", size = 9445, upload-time = "2025-12-02T11:51:42.987Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/cf/22/fdc2e30d43ff853720042fa15baa3e6122722be1a7950a98233ebb55cd71/eval_type_backport-0.3.1-py3-none-any.whl", hash = "sha256:279ab641905e9f11129f56a8a78f493518515b83402b860f6f06dd7c011fdfa8", size = 6063, upload-time = "2025-12-02T11:51:41.665Z" }, -] - [[package]] name = "exceptiongroup" version = "1.3.1" @@ -1563,65 +1301,6 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/ec/6d/56ef943ea524784598c035ccbd42e564e937da0438ae3f55f0e76cb95571/fastar-0.11.0-pp311-pypy311_pp73-musllinux_1_2_x86_64.whl", hash = "sha256:6a1c56957ac82408be37a3f63594bc83e0919e8760492a4475e542f9f1828778", size = 1034886, upload-time = "2026-04-13T17:11:15.617Z" }, ] -[[package]] -name = "fastavro" -version = "1.12.1" -source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/65/8b/fa2d3287fd2267be6261d0177c6809a7fa12c5600ddb33490c8dc29e77b2/fastavro-1.12.1.tar.gz", hash = "sha256:2f285be49e45bc047ab2f6bed040bb349da85db3f3c87880e4b92595ea093b2b", size = 1025661, upload-time = "2025-10-10T15:40:55.41Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/40/a0/077fd7cbfc143152cb96780cb592ed6cb6696667d8bc1b977745eb2255a8/fastavro-1.12.1-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:00650ca533907361edda22e6ffe8cf87ab2091c5d8aee5c8000b0f2dcdda7ed3", size = 1000335, upload-time = "2025-10-10T15:40:59.834Z" }, - { url = "https://files.pythonhosted.org/packages/a0/ae/a115e027f3a75df237609701b03ecba0b7f0aa3d77fe0161df533fde1eb7/fastavro-1.12.1-cp310-cp310-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:ac76d6d95f909c72ee70d314b460b7e711d928845771531d823eb96a10952d26", size = 3221067, upload-time = "2025-10-10T15:41:04.399Z" }, - { url = "https://files.pythonhosted.org/packages/94/4e/c4991c3eec0175af9a8a0c161b88089cb7bf7fe353b3e3be1bc4cf9036b2/fastavro-1.12.1-cp310-cp310-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:1f55eef18c41d4476bd32a82ed5dd86aabc3f614e1b66bdb09ffa291612e1670", size = 3228979, upload-time = "2025-10-10T15:41:06.738Z" }, - { url = "https://files.pythonhosted.org/packages/21/0c/f2afb8eaea38799ccb1ed07d68bf2659f2e313f1902bbd36774cf6a1bef9/fastavro-1.12.1-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:81563e1f93570e6565487cdb01ba241a36a00e58cff9c5a0614af819d1155d8f", size = 3160740, upload-time = "2025-10-10T15:41:08.731Z" }, - { url = "https://files.pythonhosted.org/packages/0d/1a/f4d367924b40b86857862c1fa65f2afba94ddadf298b611e610a676a29e5/fastavro-1.12.1-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:bec207360f76f0b3de540758a297193c5390e8e081c43c3317f610b1414d8c8f", size = 3235787, upload-time = "2025-10-10T15:41:10.869Z" }, - { url = "https://files.pythonhosted.org/packages/90/ec/8db9331896e3dfe4f71b2b3c23f2e97fbbfd90129777467ca9f8bafccb74/fastavro-1.12.1-cp310-cp310-win_amd64.whl", hash = "sha256:c0390bfe4a9f8056a75ac6785fbbff8f5e317f5356481d2e29ec980877d2314b", size = 449350, upload-time = "2025-10-10T15:41:12.104Z" }, - { url = "https://files.pythonhosted.org/packages/a0/e9/31c64b47cefc0951099e7c0c8c8ea1c931edd1350f34d55c27cbfbb08df1/fastavro-1.12.1-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:6b632b713bc5d03928a87d811fa4a11d5f25cd43e79c161e291c7d3f7aa740fd", size = 1016585, upload-time = "2025-10-10T15:41:13.717Z" }, - { url = "https://files.pythonhosted.org/packages/10/76/111560775b548f5d8d828c1b5285ff90e2d2745643fb80ecbf115344eea4/fastavro-1.12.1-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:eaa7ab3769beadcebb60f0539054c7755f63bd9cf7666e2c15e615ab605f89a8", size = 3404629, upload-time = "2025-10-10T15:41:15.642Z" }, - { url = "https://files.pythonhosted.org/packages/b0/07/6bb93cb963932146c2b6c5c765903a0a547ad9f0f8b769a4a9aad8c06369/fastavro-1.12.1-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:123fb221df3164abd93f2d042c82f538a1d5a43ce41375f12c91ce1355a9141e", size = 3428594, upload-time = "2025-10-10T15:41:17.779Z" }, - { url = "https://files.pythonhosted.org/packages/d1/67/8115ec36b584197ea737ec79e3499e1f1b640b288d6c6ee295edd13b80f6/fastavro-1.12.1-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:632a4e3ff223f834ddb746baae0cc7cee1068eb12c32e4d982c2fee8a5b483d0", size = 3344145, upload-time = "2025-10-10T15:41:19.89Z" }, - { url = "https://files.pythonhosted.org/packages/9e/9e/a7cebb3af967e62539539897c10138fa0821668ec92525d1be88a9cd3ee6/fastavro-1.12.1-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:83e6caf4e7a8717d932a3b1ff31595ad169289bbe1128a216be070d3a8391671", size = 3431942, upload-time = "2025-10-10T15:41:22.076Z" }, - { url = "https://files.pythonhosted.org/packages/c0/d1/7774ddfb8781c5224294c01a593ebce2ad3289b948061c9701bd1903264d/fastavro-1.12.1-cp311-cp311-win_amd64.whl", hash = "sha256:b91a0fe5a173679a6c02d53ca22dcaad0a2c726b74507e0c1c2e71a7c3f79ef9", size = 450542, upload-time = "2025-10-10T15:41:23.333Z" }, - { url = "https://files.pythonhosted.org/packages/7c/f0/10bd1a3d08667fa0739e2b451fe90e06df575ec8b8ba5d3135c70555c9bd/fastavro-1.12.1-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:509818cb24b98a804fc80be9c5fed90f660310ae3d59382fc811bfa187122167", size = 1009057, upload-time = "2025-10-10T15:41:24.556Z" }, - { url = "https://files.pythonhosted.org/packages/78/ad/0d985bc99e1fa9e74c636658000ba38a5cd7f5ab2708e9c62eaf736ecf1a/fastavro-1.12.1-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:089e155c0c76e0d418d7e79144ce000524dd345eab3bc1e9c5ae69d500f71b14", size = 3391866, upload-time = "2025-10-10T15:41:26.882Z" }, - { url = "https://files.pythonhosted.org/packages/0d/9e/b4951dc84ebc34aac69afcbfbb22ea4a91080422ec2bfd2c06076ff1d419/fastavro-1.12.1-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:44cbff7518901c91a82aab476fcab13d102e4999499df219d481b9e15f61af34", size = 3458005, upload-time = "2025-10-10T15:41:29.017Z" }, - { url = "https://files.pythonhosted.org/packages/af/f8/5a8df450a9f55ca8441f22ea0351d8c77809fc121498b6970daaaf667a21/fastavro-1.12.1-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:a275e48df0b1701bb764b18a8a21900b24cf882263cb03d35ecdba636bbc830b", size = 3295258, upload-time = "2025-10-10T15:41:31.564Z" }, - { url = "https://files.pythonhosted.org/packages/99/b2/40f25299111d737e58b85696e91138a66c25b7334f5357e7ac2b0e8966f8/fastavro-1.12.1-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:2de72d786eb38be6b16d556b27232b1bf1b2797ea09599507938cdb7a9fe3e7c", size = 3430328, upload-time = "2025-10-10T15:41:33.689Z" }, - { url = "https://files.pythonhosted.org/packages/e0/07/85157a7c57c5f8b95507d7829b5946561e5ee656ff80e9dd9a757f53ddaf/fastavro-1.12.1-cp312-cp312-win_amd64.whl", hash = "sha256:9090f0dee63fe022ee9cc5147483366cc4171c821644c22da020d6b48f576b4f", size = 444140, upload-time = "2025-10-10T15:41:34.902Z" }, - { url = "https://files.pythonhosted.org/packages/bb/57/26d5efef9182392d5ac9f253953c856ccb66e4c549fd3176a1e94efb05c9/fastavro-1.12.1-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:78df838351e4dff9edd10a1c41d1324131ffecbadefb9c297d612ef5363c049a", size = 1000599, upload-time = "2025-10-10T15:41:36.554Z" }, - { url = "https://files.pythonhosted.org/packages/33/cb/8ab55b21d018178eb126007a56bde14fd01c0afc11d20b5f2624fe01e698/fastavro-1.12.1-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:780476c23175d2ae457c52f45b9ffa9d504593499a36cd3c1929662bf5b7b14b", size = 3335933, upload-time = "2025-10-10T15:41:39.07Z" }, - { url = "https://files.pythonhosted.org/packages/fe/03/9c94ec9bf873eb1ffb0aa694f4e71940154e6e9728ddfdc46046d7e8ced4/fastavro-1.12.1-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:0714b285160fcd515eb0455540f40dd6dac93bdeacdb03f24e8eac3d8aa51f8d", size = 3402066, upload-time = "2025-10-10T15:41:41.608Z" }, - { url = "https://files.pythonhosted.org/packages/75/c8/cb472347c5a584ccb8777a649ebb28278fccea39d005fc7df19996f41df8/fastavro-1.12.1-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:a8bc2dcec5843d499f2489bfe0747999108f78c5b29295d877379f1972a3d41a", size = 3240038, upload-time = "2025-10-10T15:41:43.743Z" }, - { url = "https://files.pythonhosted.org/packages/e1/77/569ce9474c40304b3a09e109494e020462b83e405545b78069ddba5f614e/fastavro-1.12.1-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:3b1921ac35f3d89090a5816b626cf46e67dbecf3f054131f84d56b4e70496f45", size = 3369398, upload-time = "2025-10-10T15:41:45.719Z" }, - { url = "https://files.pythonhosted.org/packages/4a/1f/9589e35e9ea68035385db7bdbf500d36b8891db474063fb1ccc8215ee37c/fastavro-1.12.1-cp313-cp313-win_amd64.whl", hash = "sha256:5aa777b8ee595b50aa084104cd70670bf25a7bbb9fd8bb5d07524b0785ee1699", size = 444220, upload-time = "2025-10-10T15:41:47.39Z" }, - { url = "https://files.pythonhosted.org/packages/6c/d2/78435fe737df94bd8db2234b2100f5453737cffd29adee2504a2b013de84/fastavro-1.12.1-cp313-cp313t-macosx_10_13_universal2.whl", hash = "sha256:c3d67c47f177e486640404a56f2f50b165fe892cc343ac3a34673b80cc7f1dd6", size = 1086611, upload-time = "2025-10-10T15:41:48.818Z" }, - { url = "https://files.pythonhosted.org/packages/b6/be/428f99b10157230ddac77ec8cc167005b29e2bd5cbe228345192bb645f30/fastavro-1.12.1-cp313-cp313t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:5217f773492bac43dae15ff2931432bce2d7a80be7039685a78d3fab7df910bd", size = 3541001, upload-time = "2025-10-10T15:41:50.871Z" }, - { url = "https://files.pythonhosted.org/packages/16/08/a2eea4f20b85897740efe44887e1ac08f30dfa4bfc3de8962bdcbb21a5a1/fastavro-1.12.1-cp313-cp313t-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:469fecb25cba07f2e1bfa4c8d008477cd6b5b34a59d48715e1b1a73f6160097d", size = 3432217, upload-time = "2025-10-10T15:41:53.149Z" }, - { url = "https://files.pythonhosted.org/packages/87/bb/b4c620b9eb6e9838c7f7e4b7be0762834443adf9daeb252a214e9ad3178c/fastavro-1.12.1-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:d71c8aa841ef65cfab709a22bb887955f42934bced3ddb571e98fdbdade4c609", size = 3366742, upload-time = "2025-10-10T15:41:55.237Z" }, - { url = "https://files.pythonhosted.org/packages/3d/d1/e69534ccdd5368350646fea7d93be39e5f77c614cca825c990bd9ca58f67/fastavro-1.12.1-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:b81fc04e85dfccf7c028e0580c606e33aa8472370b767ef058aae2c674a90746", size = 3383743, upload-time = "2025-10-10T15:41:57.68Z" }, - { url = "https://files.pythonhosted.org/packages/58/54/b7b4a0c3fb5fcba38128542da1b26c4e6d69933c923f493548bdfd63ab6a/fastavro-1.12.1-cp314-cp314-macosx_10_15_universal2.whl", hash = "sha256:9445da127751ba65975d8e4bdabf36bfcfdad70fc35b2d988e3950cce0ec0e7c", size = 1001377, upload-time = "2025-10-10T15:41:59.241Z" }, - { url = "https://files.pythonhosted.org/packages/1e/4f/0e589089c7df0d8f57d7e5293fdc34efec9a3b758a0d4d0c99a7937e2492/fastavro-1.12.1-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:ed924233272719b5d5a6a0b4d80ef3345fc7e84fc7a382b6232192a9112d38a6", size = 3320401, upload-time = "2025-10-10T15:42:01.682Z" }, - { url = "https://files.pythonhosted.org/packages/f9/19/260110d56194ae29d7e423a336fccea8bcd103196d00f0b364b732bdb84e/fastavro-1.12.1-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:3616e2f0e1c9265e92954fa099db79c6e7817356d3ff34f4bcc92699ae99697c", size = 3350894, upload-time = "2025-10-10T15:42:04.073Z" }, - { url = "https://files.pythonhosted.org/packages/d0/96/58b0411e8be9694d5972bee3167d6c1fd1fdfdf7ce253c1a19a327208f4f/fastavro-1.12.1-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:cb0337b42fd3c047fcf0e9b7597bd6ad25868de719f29da81eabb6343f08d399", size = 3229644, upload-time = "2025-10-10T15:42:06.221Z" }, - { url = "https://files.pythonhosted.org/packages/5b/db/38660660eac82c30471d9101f45b3acfdcbadfe42d8f7cdb129459a45050/fastavro-1.12.1-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:64961ab15b74b7c168717bbece5660e0f3d457837c3cc9d9145181d011199fa7", size = 3329704, upload-time = "2025-10-10T15:42:08.384Z" }, - { url = "https://files.pythonhosted.org/packages/9d/a9/1672910f458ecb30b596c9e59e41b7c00309b602a0494341451e92e62747/fastavro-1.12.1-cp314-cp314-win_amd64.whl", hash = "sha256:792356d320f6e757e89f7ac9c22f481e546c886454a6709247f43c0dd7058004", size = 452911, upload-time = "2025-10-10T15:42:09.795Z" }, - { url = "https://files.pythonhosted.org/packages/dc/8d/2e15d0938ded1891b33eff252e8500605508b799c2e57188a933f0bd744c/fastavro-1.12.1-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:120aaf82ac19d60a1016afe410935fe94728752d9c2d684e267e5b7f0e70f6d9", size = 3541999, upload-time = "2025-10-10T15:42:11.794Z" }, - { url = "https://files.pythonhosted.org/packages/a7/1c/6dfd082a205be4510543221b734b1191299e6a1810c452b6bc76dfa6968e/fastavro-1.12.1-cp314-cp314t-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:b6a3462934b20a74f9ece1daa49c2e4e749bd9a35fa2657b53bf62898fba80f5", size = 3433972, upload-time = "2025-10-10T15:42:14.485Z" }, - { url = "https://files.pythonhosted.org/packages/24/90/9de694625a1a4b727b1ad0958d220cab25a9b6cf7f16a5c7faa9ea7b2261/fastavro-1.12.1-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:1f81011d54dd47b12437b51dd93a70a9aa17b61307abf26542fc3c13efbc6c51", size = 3368752, upload-time = "2025-10-10T15:42:16.618Z" }, - { url = "https://files.pythonhosted.org/packages/fa/93/b44f67589e4d439913dab6720f7e3507b0fa8b8e56d06f6fc875ced26afb/fastavro-1.12.1-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:43ded16b3f4a9f1a42f5970c2aa618acb23ea59c4fcaa06680bdf470b255e5a8", size = 3386636, upload-time = "2025-10-10T15:42:18.974Z" }, -] - -[[package]] -name = "fastmcp" -version = "3.3.1" -source = { registry = "https://pypi.org/simple" } -dependencies = [ - { name = "fastmcp-slim", extra = ["client", "server"] }, -] -sdist = { url = "https://files.pythonhosted.org/packages/3b/a9/5c5a01b6abd5346bf60b97cfd29e4a86661940c27dd562bfcda07fd03519/fastmcp-3.3.1.tar.gz", hash = "sha256:979362ea557de42a5f40342563c7e4b236bcc8e7cd192715f50030695d1a71cd", size = 28681699, upload-time = "2026-05-15T15:50:39.673Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/9f/11/6b1bdada6ccfe647d615ae63f9106f8136aec17971e9361546af01c7d38e/fastmcp-3.3.1-py3-none-any.whl", hash = "sha256:862440c5c4d281363a5995eee59d77f0f7cac1f18869038729cecf03b02fc522", size = 7903, upload-time = "2026-05-15T15:50:36.424Z" }, -] - [[package]] name = "fastmcp-slim" version = "3.3.1" @@ -1648,36 +1327,6 @@ client = [ { name = "opentelemetry-api" }, { name = "py-key-value-aio", extra = ["filetree", "keyring", "memory"] }, ] -server = [ - { name = "authlib" }, - { name = "cyclopts" }, - { name = "exceptiongroup" }, - { name = "griffelib" }, - { name = "httpx" }, - { name = "jsonref" }, - { name = "jsonschema-path" }, - { name = "mcp" }, - { name = "openapi-pydantic" }, - { name = "opentelemetry-api" }, - { name = "packaging" }, - { name = "py-key-value-aio", extra = ["filetree", "keyring", "memory"] }, - { name = "pyperclip" }, - { name = "python-multipart" }, - { name = "pyyaml" }, - { name = "uncalled-for" }, - { name = "uvicorn" }, - { name = "watchfiles" }, - { name = "websockets" }, -] - -[[package]] -name = "filelock" -version = "3.20.3" -source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/1d/65/ce7f1b70157833bf3cb851b556a37d4547ceafc158aa9b34b36782f23696/filelock-3.20.3.tar.gz", hash = "sha256:18c57ee915c7ec61cff0ecf7f0f869936c7c30191bb0cf406f1341778d0834e1", size = 19485, upload-time = "2026-01-09T17:55:05.421Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/b5/36/7fb70f04bf00bc646cd5bb45aa9eddb15e19437a28b8fb2b4a5249fac770/filelock-3.20.3-py3-none-any.whl", hash = "sha256:4b0dda527ee31078689fc205ec4f1c1bf7d56cf88b6dc9426c4f230e46c2dce1", size = 16701, upload-time = "2026-01-09T17:55:04.334Z" }, -] [[package]] name = "flask" @@ -1696,136 +1345,6 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/7f/9c/34f6962f9b9e9c71f6e5ed806e0d0ff03c9d1b0b2340088a0cf4bce09b18/flask-3.1.3-py3-none-any.whl", hash = "sha256:f4bcbefc124291925f1a26446da31a5178f9483862233b23c0c96a20701f670c", size = 103424, upload-time = "2026-02-19T05:00:56.027Z" }, ] -[[package]] -name = "frozenlist" -version = "1.8.0" -source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/2d/f5/c831fac6cc817d26fd54c7eaccd04ef7e0288806943f7cc5bbf69f3ac1f0/frozenlist-1.8.0.tar.gz", hash = "sha256:3ede829ed8d842f6cd48fc7081d7a41001a56f1f38603f9d49bf3020d59a31ad", size = 45875, upload-time = "2025-10-06T05:38:17.865Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/83/4a/557715d5047da48d54e659203b9335be7bfaafda2c3f627b7c47e0b3aaf3/frozenlist-1.8.0-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:b37f6d31b3dcea7deb5e9696e529a6aa4a898adc33db82da12e4c60a7c4d2011", size = 86230, upload-time = "2025-10-06T05:35:23.699Z" }, - { url = "https://files.pythonhosted.org/packages/a2/fb/c85f9fed3ea8fe8740e5b46a59cc141c23b842eca617da8876cfce5f760e/frozenlist-1.8.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:ef2b7b394f208233e471abc541cc6991f907ffd47dc72584acee3147899d6565", size = 49621, upload-time = "2025-10-06T05:35:25.341Z" }, - { url = "https://files.pythonhosted.org/packages/63/70/26ca3f06aace16f2352796b08704338d74b6d1a24ca38f2771afbb7ed915/frozenlist-1.8.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:a88f062f072d1589b7b46e951698950e7da00442fc1cacbe17e19e025dc327ad", size = 49889, upload-time = "2025-10-06T05:35:26.797Z" }, - { url = "https://files.pythonhosted.org/packages/5d/ed/c7895fd2fde7f3ee70d248175f9b6cdf792fb741ab92dc59cd9ef3bd241b/frozenlist-1.8.0-cp310-cp310-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:f57fb59d9f385710aa7060e89410aeb5058b99e62f4d16b08b91986b9a2140c2", size = 219464, upload-time = "2025-10-06T05:35:28.254Z" }, - { url = "https://files.pythonhosted.org/packages/6b/83/4d587dccbfca74cb8b810472392ad62bfa100bf8108c7223eb4c4fa2f7b3/frozenlist-1.8.0-cp310-cp310-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:799345ab092bee59f01a915620b5d014698547afd011e691a208637312db9186", size = 221649, upload-time = "2025-10-06T05:35:29.454Z" }, - { url = "https://files.pythonhosted.org/packages/6a/c6/fd3b9cd046ec5fff9dab66831083bc2077006a874a2d3d9247dea93ddf7e/frozenlist-1.8.0-cp310-cp310-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:c23c3ff005322a6e16f71bf8692fcf4d5a304aaafe1e262c98c6d4adc7be863e", size = 219188, upload-time = "2025-10-06T05:35:30.951Z" }, - { url = "https://files.pythonhosted.org/packages/ce/80/6693f55eb2e085fc8afb28cf611448fb5b90e98e068fa1d1b8d8e66e5c7d/frozenlist-1.8.0-cp310-cp310-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:8a76ea0f0b9dfa06f254ee06053d93a600865b3274358ca48a352ce4f0798450", size = 231748, upload-time = "2025-10-06T05:35:32.101Z" }, - { url = "https://files.pythonhosted.org/packages/97/d6/e9459f7c5183854abd989ba384fe0cc1a0fb795a83c033f0571ec5933ca4/frozenlist-1.8.0-cp310-cp310-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:c7366fe1418a6133d5aa824ee53d406550110984de7637d65a178010f759c6ef", size = 236351, upload-time = "2025-10-06T05:35:33.834Z" }, - { url = "https://files.pythonhosted.org/packages/97/92/24e97474b65c0262e9ecd076e826bfd1d3074adcc165a256e42e7b8a7249/frozenlist-1.8.0-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:13d23a45c4cebade99340c4165bd90eeb4a56c6d8a9d8aa49568cac19a6d0dc4", size = 218767, upload-time = "2025-10-06T05:35:35.205Z" }, - { url = "https://files.pythonhosted.org/packages/ee/bf/dc394a097508f15abff383c5108cb8ad880d1f64a725ed3b90d5c2fbf0bb/frozenlist-1.8.0-cp310-cp310-musllinux_1_2_armv7l.whl", hash = "sha256:e4a3408834f65da56c83528fb52ce7911484f0d1eaf7b761fc66001db1646eff", size = 235887, upload-time = "2025-10-06T05:35:36.354Z" }, - { url = "https://files.pythonhosted.org/packages/40/90/25b201b9c015dbc999a5baf475a257010471a1fa8c200c843fd4abbee725/frozenlist-1.8.0-cp310-cp310-musllinux_1_2_ppc64le.whl", hash = "sha256:42145cd2748ca39f32801dad54aeea10039da6f86e303659db90db1c4b614c8c", size = 228785, upload-time = "2025-10-06T05:35:37.949Z" }, - { url = "https://files.pythonhosted.org/packages/84/f4/b5bc148df03082f05d2dd30c089e269acdbe251ac9a9cf4e727b2dbb8a3d/frozenlist-1.8.0-cp310-cp310-musllinux_1_2_s390x.whl", hash = "sha256:e2de870d16a7a53901e41b64ffdf26f2fbb8917b3e6ebf398098d72c5b20bd7f", size = 230312, upload-time = "2025-10-06T05:35:39.178Z" }, - { url = "https://files.pythonhosted.org/packages/db/4b/87e95b5d15097c302430e647136b7d7ab2398a702390cf4c8601975709e7/frozenlist-1.8.0-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:20e63c9493d33ee48536600d1a5c95eefc870cd71e7ab037763d1fbb89cc51e7", size = 217650, upload-time = "2025-10-06T05:35:40.377Z" }, - { url = "https://files.pythonhosted.org/packages/e5/70/78a0315d1fea97120591a83e0acd644da638c872f142fd72a6cebee825f3/frozenlist-1.8.0-cp310-cp310-win32.whl", hash = "sha256:adbeebaebae3526afc3c96fad434367cafbfd1b25d72369a9e5858453b1bb71a", size = 39659, upload-time = "2025-10-06T05:35:41.863Z" }, - { url = "https://files.pythonhosted.org/packages/66/aa/3f04523fb189a00e147e60c5b2205126118f216b0aa908035c45336e27e4/frozenlist-1.8.0-cp310-cp310-win_amd64.whl", hash = "sha256:667c3777ca571e5dbeb76f331562ff98b957431df140b54c85fd4d52eea8d8f6", size = 43837, upload-time = "2025-10-06T05:35:43.205Z" }, - { url = "https://files.pythonhosted.org/packages/39/75/1135feecdd7c336938bd55b4dc3b0dfc46d85b9be12ef2628574b28de776/frozenlist-1.8.0-cp310-cp310-win_arm64.whl", hash = "sha256:80f85f0a7cc86e7a54c46d99c9e1318ff01f4687c172ede30fd52d19d1da1c8e", size = 39989, upload-time = "2025-10-06T05:35:44.596Z" }, - { url = "https://files.pythonhosted.org/packages/bc/03/077f869d540370db12165c0aa51640a873fb661d8b315d1d4d67b284d7ac/frozenlist-1.8.0-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:09474e9831bc2b2199fad6da3c14c7b0fbdd377cce9d3d77131be28906cb7d84", size = 86912, upload-time = "2025-10-06T05:35:45.98Z" }, - { url = "https://files.pythonhosted.org/packages/df/b5/7610b6bd13e4ae77b96ba85abea1c8cb249683217ef09ac9e0ae93f25a91/frozenlist-1.8.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:17c883ab0ab67200b5f964d2b9ed6b00971917d5d8a92df149dc2c9779208ee9", size = 50046, upload-time = "2025-10-06T05:35:47.009Z" }, - { url = "https://files.pythonhosted.org/packages/6e/ef/0e8f1fe32f8a53dd26bdd1f9347efe0778b0fddf62789ea683f4cc7d787d/frozenlist-1.8.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:fa47e444b8ba08fffd1c18e8cdb9a75db1b6a27f17507522834ad13ed5922b93", size = 50119, upload-time = "2025-10-06T05:35:48.38Z" }, - { url = "https://files.pythonhosted.org/packages/11/b1/71a477adc7c36e5fb628245dfbdea2166feae310757dea848d02bd0689fd/frozenlist-1.8.0-cp311-cp311-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:2552f44204b744fba866e573be4c1f9048d6a324dfe14475103fd51613eb1d1f", size = 231067, upload-time = "2025-10-06T05:35:49.97Z" }, - { url = "https://files.pythonhosted.org/packages/45/7e/afe40eca3a2dc19b9904c0f5d7edfe82b5304cb831391edec0ac04af94c2/frozenlist-1.8.0-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:957e7c38f250991e48a9a73e6423db1bb9dd14e722a10f6b8bb8e16a0f55f695", size = 233160, upload-time = "2025-10-06T05:35:51.729Z" }, - { url = "https://files.pythonhosted.org/packages/a6/aa/7416eac95603ce428679d273255ffc7c998d4132cfae200103f164b108aa/frozenlist-1.8.0-cp311-cp311-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:8585e3bb2cdea02fc88ffa245069c36555557ad3609e83be0ec71f54fd4abb52", size = 228544, upload-time = "2025-10-06T05:35:53.246Z" }, - { url = "https://files.pythonhosted.org/packages/8b/3d/2a2d1f683d55ac7e3875e4263d28410063e738384d3adc294f5ff3d7105e/frozenlist-1.8.0-cp311-cp311-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:edee74874ce20a373d62dc28b0b18b93f645633c2943fd90ee9d898550770581", size = 243797, upload-time = "2025-10-06T05:35:54.497Z" }, - { url = "https://files.pythonhosted.org/packages/78/1e/2d5565b589e580c296d3bb54da08d206e797d941a83a6fdea42af23be79c/frozenlist-1.8.0-cp311-cp311-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:c9a63152fe95756b85f31186bddf42e4c02c6321207fd6601a1c89ebac4fe567", size = 247923, upload-time = "2025-10-06T05:35:55.861Z" }, - { url = "https://files.pythonhosted.org/packages/aa/c3/65872fcf1d326a7f101ad4d86285c403c87be7d832b7470b77f6d2ed5ddc/frozenlist-1.8.0-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:b6db2185db9be0a04fecf2f241c70b63b1a242e2805be291855078f2b404dd6b", size = 230886, upload-time = "2025-10-06T05:35:57.399Z" }, - { url = "https://files.pythonhosted.org/packages/a0/76/ac9ced601d62f6956f03cc794f9e04c81719509f85255abf96e2510f4265/frozenlist-1.8.0-cp311-cp311-musllinux_1_2_armv7l.whl", hash = "sha256:f4be2e3d8bc8aabd566f8d5b8ba7ecc09249d74ba3c9ed52e54dc23a293f0b92", size = 245731, upload-time = "2025-10-06T05:35:58.563Z" }, - { url = "https://files.pythonhosted.org/packages/b9/49/ecccb5f2598daf0b4a1415497eba4c33c1e8ce07495eb07d2860c731b8d5/frozenlist-1.8.0-cp311-cp311-musllinux_1_2_ppc64le.whl", hash = "sha256:c8d1634419f39ea6f5c427ea2f90ca85126b54b50837f31497f3bf38266e853d", size = 241544, upload-time = "2025-10-06T05:35:59.719Z" }, - { url = "https://files.pythonhosted.org/packages/53/4b/ddf24113323c0bbcc54cb38c8b8916f1da7165e07b8e24a717b4a12cbf10/frozenlist-1.8.0-cp311-cp311-musllinux_1_2_s390x.whl", hash = "sha256:1a7fa382a4a223773ed64242dbe1c9c326ec09457e6b8428efb4118c685c3dfd", size = 241806, upload-time = "2025-10-06T05:36:00.959Z" }, - { url = "https://files.pythonhosted.org/packages/a7/fb/9b9a084d73c67175484ba2789a59f8eebebd0827d186a8102005ce41e1ba/frozenlist-1.8.0-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:11847b53d722050808926e785df837353bd4d75f1d494377e59b23594d834967", size = 229382, upload-time = "2025-10-06T05:36:02.22Z" }, - { url = "https://files.pythonhosted.org/packages/95/a3/c8fb25aac55bf5e12dae5c5aa6a98f85d436c1dc658f21c3ac73f9fa95e5/frozenlist-1.8.0-cp311-cp311-win32.whl", hash = "sha256:27c6e8077956cf73eadd514be8fb04d77fc946a7fe9f7fe167648b0b9085cc25", size = 39647, upload-time = "2025-10-06T05:36:03.409Z" }, - { url = "https://files.pythonhosted.org/packages/0a/f5/603d0d6a02cfd4c8f2a095a54672b3cf967ad688a60fb9faf04fc4887f65/frozenlist-1.8.0-cp311-cp311-win_amd64.whl", hash = "sha256:ac913f8403b36a2c8610bbfd25b8013488533e71e62b4b4adce9c86c8cea905b", size = 44064, upload-time = "2025-10-06T05:36:04.368Z" }, - { url = "https://files.pythonhosted.org/packages/5d/16/c2c9ab44e181f043a86f9a8f84d5124b62dbcb3a02c0977ec72b9ac1d3e0/frozenlist-1.8.0-cp311-cp311-win_arm64.whl", hash = "sha256:d4d3214a0f8394edfa3e303136d0575eece0745ff2b47bd2cb2e66dd92d4351a", size = 39937, upload-time = "2025-10-06T05:36:05.669Z" }, - { url = "https://files.pythonhosted.org/packages/69/29/948b9aa87e75820a38650af445d2ef2b6b8a6fab1a23b6bb9e4ef0be2d59/frozenlist-1.8.0-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:78f7b9e5d6f2fdb88cdde9440dc147259b62b9d3b019924def9f6478be254ac1", size = 87782, upload-time = "2025-10-06T05:36:06.649Z" }, - { url = "https://files.pythonhosted.org/packages/64/80/4f6e318ee2a7c0750ed724fa33a4bdf1eacdc5a39a7a24e818a773cd91af/frozenlist-1.8.0-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:229bf37d2e4acdaf808fd3f06e854a4a7a3661e871b10dc1f8f1896a3b05f18b", size = 50594, upload-time = "2025-10-06T05:36:07.69Z" }, - { url = "https://files.pythonhosted.org/packages/2b/94/5c8a2b50a496b11dd519f4a24cb5496cf125681dd99e94c604ccdea9419a/frozenlist-1.8.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:f833670942247a14eafbb675458b4e61c82e002a148f49e68257b79296e865c4", size = 50448, upload-time = "2025-10-06T05:36:08.78Z" }, - { url = "https://files.pythonhosted.org/packages/6a/bd/d91c5e39f490a49df14320f4e8c80161cfcce09f1e2cde1edd16a551abb3/frozenlist-1.8.0-cp312-cp312-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:494a5952b1c597ba44e0e78113a7266e656b9794eec897b19ead706bd7074383", size = 242411, upload-time = "2025-10-06T05:36:09.801Z" }, - { url = "https://files.pythonhosted.org/packages/8f/83/f61505a05109ef3293dfb1ff594d13d64a2324ac3482be2cedc2be818256/frozenlist-1.8.0-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:96f423a119f4777a4a056b66ce11527366a8bb92f54e541ade21f2374433f6d4", size = 243014, upload-time = "2025-10-06T05:36:11.394Z" }, - { url = "https://files.pythonhosted.org/packages/d8/cb/cb6c7b0f7d4023ddda30cf56b8b17494eb3a79e3fda666bf735f63118b35/frozenlist-1.8.0-cp312-cp312-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:3462dd9475af2025c31cc61be6652dfa25cbfb56cbbf52f4ccfe029f38decaf8", size = 234909, upload-time = "2025-10-06T05:36:12.598Z" }, - { url = "https://files.pythonhosted.org/packages/31/c5/cd7a1f3b8b34af009fb17d4123c5a778b44ae2804e3ad6b86204255f9ec5/frozenlist-1.8.0-cp312-cp312-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:c4c800524c9cd9bac5166cd6f55285957fcfc907db323e193f2afcd4d9abd69b", size = 250049, upload-time = "2025-10-06T05:36:14.065Z" }, - { url = "https://files.pythonhosted.org/packages/c0/01/2f95d3b416c584a1e7f0e1d6d31998c4a795f7544069ee2e0962a4b60740/frozenlist-1.8.0-cp312-cp312-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:d6a5df73acd3399d893dafc71663ad22534b5aa4f94e8a2fabfe856c3c1b6a52", size = 256485, upload-time = "2025-10-06T05:36:15.39Z" }, - { url = "https://files.pythonhosted.org/packages/ce/03/024bf7720b3abaebcff6d0793d73c154237b85bdf67b7ed55e5e9596dc9a/frozenlist-1.8.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:405e8fe955c2280ce66428b3ca55e12b3c4e9c336fb2103a4937e891c69a4a29", size = 237619, upload-time = "2025-10-06T05:36:16.558Z" }, - { url = "https://files.pythonhosted.org/packages/69/fa/f8abdfe7d76b731f5d8bd217827cf6764d4f1d9763407e42717b4bed50a0/frozenlist-1.8.0-cp312-cp312-musllinux_1_2_armv7l.whl", hash = "sha256:908bd3f6439f2fef9e85031b59fd4f1297af54415fb60e4254a95f75b3cab3f3", size = 250320, upload-time = "2025-10-06T05:36:17.821Z" }, - { url = "https://files.pythonhosted.org/packages/f5/3c/b051329f718b463b22613e269ad72138cc256c540f78a6de89452803a47d/frozenlist-1.8.0-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:294e487f9ec720bd8ffcebc99d575f7eff3568a08a253d1ee1a0378754b74143", size = 246820, upload-time = "2025-10-06T05:36:19.046Z" }, - { url = "https://files.pythonhosted.org/packages/0f/ae/58282e8f98e444b3f4dd42448ff36fa38bef29e40d40f330b22e7108f565/frozenlist-1.8.0-cp312-cp312-musllinux_1_2_s390x.whl", hash = "sha256:74c51543498289c0c43656701be6b077f4b265868fa7f8a8859c197006efb608", size = 250518, upload-time = "2025-10-06T05:36:20.763Z" }, - { url = "https://files.pythonhosted.org/packages/8f/96/007e5944694d66123183845a106547a15944fbbb7154788cbf7272789536/frozenlist-1.8.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:776f352e8329135506a1d6bf16ac3f87bc25b28e765949282dcc627af36123aa", size = 239096, upload-time = "2025-10-06T05:36:22.129Z" }, - { url = "https://files.pythonhosted.org/packages/66/bb/852b9d6db2fa40be96f29c0d1205c306288f0684df8fd26ca1951d461a56/frozenlist-1.8.0-cp312-cp312-win32.whl", hash = "sha256:433403ae80709741ce34038da08511d4a77062aa924baf411ef73d1146e74faf", size = 39985, upload-time = "2025-10-06T05:36:23.661Z" }, - { url = "https://files.pythonhosted.org/packages/b8/af/38e51a553dd66eb064cdf193841f16f077585d4d28394c2fa6235cb41765/frozenlist-1.8.0-cp312-cp312-win_amd64.whl", hash = "sha256:34187385b08f866104f0c0617404c8eb08165ab1272e884abc89c112e9c00746", size = 44591, upload-time = "2025-10-06T05:36:24.958Z" }, - { url = "https://files.pythonhosted.org/packages/a7/06/1dc65480ab147339fecc70797e9c2f69d9cea9cf38934ce08df070fdb9cb/frozenlist-1.8.0-cp312-cp312-win_arm64.whl", hash = "sha256:fe3c58d2f5db5fbd18c2987cba06d51b0529f52bc3a6cdc33d3f4eab725104bd", size = 40102, upload-time = "2025-10-06T05:36:26.333Z" }, - { url = "https://files.pythonhosted.org/packages/2d/40/0832c31a37d60f60ed79e9dfb5a92e1e2af4f40a16a29abcc7992af9edff/frozenlist-1.8.0-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:8d92f1a84bb12d9e56f818b3a746f3efba93c1b63c8387a73dde655e1e42282a", size = 85717, upload-time = "2025-10-06T05:36:27.341Z" }, - { url = "https://files.pythonhosted.org/packages/30/ba/b0b3de23f40bc55a7057bd38434e25c34fa48e17f20ee273bbde5e0650f3/frozenlist-1.8.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:96153e77a591c8adc2ee805756c61f59fef4cf4073a9275ee86fe8cba41241f7", size = 49651, upload-time = "2025-10-06T05:36:28.855Z" }, - { url = "https://files.pythonhosted.org/packages/0c/ab/6e5080ee374f875296c4243c381bbdef97a9ac39c6e3ce1d5f7d42cb78d6/frozenlist-1.8.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:f21f00a91358803399890ab167098c131ec2ddd5f8f5fd5fe9c9f2c6fcd91e40", size = 49417, upload-time = "2025-10-06T05:36:29.877Z" }, - { url = "https://files.pythonhosted.org/packages/d5/4e/e4691508f9477ce67da2015d8c00acd751e6287739123113a9fca6f1604e/frozenlist-1.8.0-cp313-cp313-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:fb30f9626572a76dfe4293c7194a09fb1fe93ba94c7d4f720dfae3b646b45027", size = 234391, upload-time = "2025-10-06T05:36:31.301Z" }, - { url = "https://files.pythonhosted.org/packages/40/76/c202df58e3acdf12969a7895fd6f3bc016c642e6726aa63bd3025e0fc71c/frozenlist-1.8.0-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:eaa352d7047a31d87dafcacbabe89df0aa506abb5b1b85a2fb91bc3faa02d822", size = 233048, upload-time = "2025-10-06T05:36:32.531Z" }, - { url = "https://files.pythonhosted.org/packages/f9/c0/8746afb90f17b73ca5979c7a3958116e105ff796e718575175319b5bb4ce/frozenlist-1.8.0-cp313-cp313-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:03ae967b4e297f58f8c774c7eabcce57fe3c2434817d4385c50661845a058121", size = 226549, upload-time = "2025-10-06T05:36:33.706Z" }, - { url = "https://files.pythonhosted.org/packages/7e/eb/4c7eefc718ff72f9b6c4893291abaae5fbc0c82226a32dcd8ef4f7a5dbef/frozenlist-1.8.0-cp313-cp313-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:f6292f1de555ffcc675941d65fffffb0a5bcd992905015f85d0592201793e0e5", size = 239833, upload-time = "2025-10-06T05:36:34.947Z" }, - { url = "https://files.pythonhosted.org/packages/c2/4e/e5c02187cf704224f8b21bee886f3d713ca379535f16893233b9d672ea71/frozenlist-1.8.0-cp313-cp313-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:29548f9b5b5e3460ce7378144c3010363d8035cea44bc0bf02d57f5a685e084e", size = 245363, upload-time = "2025-10-06T05:36:36.534Z" }, - { url = "https://files.pythonhosted.org/packages/1f/96/cb85ec608464472e82ad37a17f844889c36100eed57bea094518bf270692/frozenlist-1.8.0-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:ec3cc8c5d4084591b4237c0a272cc4f50a5b03396a47d9caaf76f5d7b38a4f11", size = 229314, upload-time = "2025-10-06T05:36:38.582Z" }, - { url = "https://files.pythonhosted.org/packages/5d/6f/4ae69c550e4cee66b57887daeebe006fe985917c01d0fff9caab9883f6d0/frozenlist-1.8.0-cp313-cp313-musllinux_1_2_armv7l.whl", hash = "sha256:517279f58009d0b1f2e7c1b130b377a349405da3f7621ed6bfae50b10adf20c1", size = 243365, upload-time = "2025-10-06T05:36:40.152Z" }, - { url = "https://files.pythonhosted.org/packages/7a/58/afd56de246cf11780a40a2c28dc7cbabbf06337cc8ddb1c780a2d97e88d8/frozenlist-1.8.0-cp313-cp313-musllinux_1_2_ppc64le.whl", hash = "sha256:db1e72ede2d0d7ccb213f218df6a078a9c09a7de257c2fe8fcef16d5925230b1", size = 237763, upload-time = "2025-10-06T05:36:41.355Z" }, - { url = "https://files.pythonhosted.org/packages/cb/36/cdfaf6ed42e2644740d4a10452d8e97fa1c062e2a8006e4b09f1b5fd7d63/frozenlist-1.8.0-cp313-cp313-musllinux_1_2_s390x.whl", hash = "sha256:b4dec9482a65c54a5044486847b8a66bf10c9cb4926d42927ec4e8fd5db7fed8", size = 240110, upload-time = "2025-10-06T05:36:42.716Z" }, - { url = "https://files.pythonhosted.org/packages/03/a8/9ea226fbefad669f11b52e864c55f0bd57d3c8d7eb07e9f2e9a0b39502e1/frozenlist-1.8.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:21900c48ae04d13d416f0e1e0c4d81f7931f73a9dfa0b7a8746fb2fe7dd970ed", size = 233717, upload-time = "2025-10-06T05:36:44.251Z" }, - { url = "https://files.pythonhosted.org/packages/1e/0b/1b5531611e83ba7d13ccc9988967ea1b51186af64c42b7a7af465dcc9568/frozenlist-1.8.0-cp313-cp313-win32.whl", hash = "sha256:8b7b94a067d1c504ee0b16def57ad5738701e4ba10cec90529f13fa03c833496", size = 39628, upload-time = "2025-10-06T05:36:45.423Z" }, - { url = "https://files.pythonhosted.org/packages/d8/cf/174c91dbc9cc49bc7b7aab74d8b734e974d1faa8f191c74af9b7e80848e6/frozenlist-1.8.0-cp313-cp313-win_amd64.whl", hash = "sha256:878be833caa6a3821caf85eb39c5ba92d28e85df26d57afb06b35b2efd937231", size = 43882, upload-time = "2025-10-06T05:36:46.796Z" }, - { url = "https://files.pythonhosted.org/packages/c1/17/502cd212cbfa96eb1388614fe39a3fc9ab87dbbe042b66f97acb57474834/frozenlist-1.8.0-cp313-cp313-win_arm64.whl", hash = "sha256:44389d135b3ff43ba8cc89ff7f51f5a0bb6b63d829c8300f79a2fe4fe61bcc62", size = 39676, upload-time = "2025-10-06T05:36:47.8Z" }, - { url = "https://files.pythonhosted.org/packages/d2/5c/3bbfaa920dfab09e76946a5d2833a7cbdf7b9b4a91c714666ac4855b88b4/frozenlist-1.8.0-cp313-cp313t-macosx_10_13_universal2.whl", hash = "sha256:e25ac20a2ef37e91c1b39938b591457666a0fa835c7783c3a8f33ea42870db94", size = 89235, upload-time = "2025-10-06T05:36:48.78Z" }, - { url = "https://files.pythonhosted.org/packages/d2/d6/f03961ef72166cec1687e84e8925838442b615bd0b8854b54923ce5b7b8a/frozenlist-1.8.0-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:07cdca25a91a4386d2e76ad992916a85038a9b97561bf7a3fd12d5d9ce31870c", size = 50742, upload-time = "2025-10-06T05:36:49.837Z" }, - { url = "https://files.pythonhosted.org/packages/1e/bb/a6d12b7ba4c3337667d0e421f7181c82dda448ce4e7ad7ecd249a16fa806/frozenlist-1.8.0-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:4e0c11f2cc6717e0a741f84a527c52616140741cd812a50422f83dc31749fb52", size = 51725, upload-time = "2025-10-06T05:36:50.851Z" }, - { url = "https://files.pythonhosted.org/packages/bc/71/d1fed0ffe2c2ccd70b43714c6cab0f4188f09f8a67a7914a6b46ee30f274/frozenlist-1.8.0-cp313-cp313t-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:b3210649ee28062ea6099cfda39e147fa1bc039583c8ee4481cb7811e2448c51", size = 284533, upload-time = "2025-10-06T05:36:51.898Z" }, - { url = "https://files.pythonhosted.org/packages/c9/1f/fb1685a7b009d89f9bf78a42d94461bc06581f6e718c39344754a5d9bada/frozenlist-1.8.0-cp313-cp313t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:581ef5194c48035a7de2aefc72ac6539823bb71508189e5de01d60c9dcd5fa65", size = 292506, upload-time = "2025-10-06T05:36:53.101Z" }, - { url = "https://files.pythonhosted.org/packages/e6/3b/b991fe1612703f7e0d05c0cf734c1b77aaf7c7d321df4572e8d36e7048c8/frozenlist-1.8.0-cp313-cp313t-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:3ef2d026f16a2b1866e1d86fc4e1291e1ed8a387b2c333809419a2f8b3a77b82", size = 274161, upload-time = "2025-10-06T05:36:54.309Z" }, - { url = "https://files.pythonhosted.org/packages/ca/ec/c5c618767bcdf66e88945ec0157d7f6c4a1322f1473392319b7a2501ded7/frozenlist-1.8.0-cp313-cp313t-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:5500ef82073f599ac84d888e3a8c1f77ac831183244bfd7f11eaa0289fb30714", size = 294676, upload-time = "2025-10-06T05:36:55.566Z" }, - { url = "https://files.pythonhosted.org/packages/7c/ce/3934758637d8f8a88d11f0585d6495ef54b2044ed6ec84492a91fa3b27aa/frozenlist-1.8.0-cp313-cp313t-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:50066c3997d0091c411a66e710f4e11752251e6d2d73d70d8d5d4c76442a199d", size = 300638, upload-time = "2025-10-06T05:36:56.758Z" }, - { url = "https://files.pythonhosted.org/packages/fc/4f/a7e4d0d467298f42de4b41cbc7ddaf19d3cfeabaf9ff97c20c6c7ee409f9/frozenlist-1.8.0-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:5c1c8e78426e59b3f8005e9b19f6ff46e5845895adbde20ece9218319eca6506", size = 283067, upload-time = "2025-10-06T05:36:57.965Z" }, - { url = "https://files.pythonhosted.org/packages/dc/48/c7b163063d55a83772b268e6d1affb960771b0e203b632cfe09522d67ea5/frozenlist-1.8.0-cp313-cp313t-musllinux_1_2_armv7l.whl", hash = "sha256:eefdba20de0d938cec6a89bd4d70f346a03108a19b9df4248d3cf0d88f1b0f51", size = 292101, upload-time = "2025-10-06T05:36:59.237Z" }, - { url = "https://files.pythonhosted.org/packages/9f/d0/2366d3c4ecdc2fd391e0afa6e11500bfba0ea772764d631bbf82f0136c9d/frozenlist-1.8.0-cp313-cp313t-musllinux_1_2_ppc64le.whl", hash = "sha256:cf253e0e1c3ceb4aaff6df637ce033ff6535fb8c70a764a8f46aafd3d6ab798e", size = 289901, upload-time = "2025-10-06T05:37:00.811Z" }, - { url = "https://files.pythonhosted.org/packages/b8/94/daff920e82c1b70e3618a2ac39fbc01ae3e2ff6124e80739ce5d71c9b920/frozenlist-1.8.0-cp313-cp313t-musllinux_1_2_s390x.whl", hash = "sha256:032efa2674356903cd0261c4317a561a6850f3ac864a63fc1583147fb05a79b0", size = 289395, upload-time = "2025-10-06T05:37:02.115Z" }, - { url = "https://files.pythonhosted.org/packages/e3/20/bba307ab4235a09fdcd3cc5508dbabd17c4634a1af4b96e0f69bfe551ebd/frozenlist-1.8.0-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:6da155091429aeba16851ecb10a9104a108bcd32f6c1642867eadaee401c1c41", size = 283659, upload-time = "2025-10-06T05:37:03.711Z" }, - { url = "https://files.pythonhosted.org/packages/fd/00/04ca1c3a7a124b6de4f8a9a17cc2fcad138b4608e7a3fc5877804b8715d7/frozenlist-1.8.0-cp313-cp313t-win32.whl", hash = "sha256:0f96534f8bfebc1a394209427d0f8a63d343c9779cda6fc25e8e121b5fd8555b", size = 43492, upload-time = "2025-10-06T05:37:04.915Z" }, - { url = "https://files.pythonhosted.org/packages/59/5e/c69f733a86a94ab10f68e496dc6b7e8bc078ebb415281d5698313e3af3a1/frozenlist-1.8.0-cp313-cp313t-win_amd64.whl", hash = "sha256:5d63a068f978fc69421fb0e6eb91a9603187527c86b7cd3f534a5b77a592b888", size = 48034, upload-time = "2025-10-06T05:37:06.343Z" }, - { url = "https://files.pythonhosted.org/packages/16/6c/be9d79775d8abe79b05fa6d23da99ad6e7763a1d080fbae7290b286093fd/frozenlist-1.8.0-cp313-cp313t-win_arm64.whl", hash = "sha256:bf0a7e10b077bf5fb9380ad3ae8ce20ef919a6ad93b4552896419ac7e1d8e042", size = 41749, upload-time = "2025-10-06T05:37:07.431Z" }, - { url = "https://files.pythonhosted.org/packages/f1/c8/85da824b7e7b9b6e7f7705b2ecaf9591ba6f79c1177f324c2735e41d36a2/frozenlist-1.8.0-cp314-cp314-macosx_10_13_universal2.whl", hash = "sha256:cee686f1f4cadeb2136007ddedd0aaf928ab95216e7691c63e50a8ec066336d0", size = 86127, upload-time = "2025-10-06T05:37:08.438Z" }, - { url = "https://files.pythonhosted.org/packages/8e/e8/a1185e236ec66c20afd72399522f142c3724c785789255202d27ae992818/frozenlist-1.8.0-cp314-cp314-macosx_10_13_x86_64.whl", hash = "sha256:119fb2a1bd47307e899c2fac7f28e85b9a543864df47aa7ec9d3c1b4545f096f", size = 49698, upload-time = "2025-10-06T05:37:09.48Z" }, - { url = "https://files.pythonhosted.org/packages/a1/93/72b1736d68f03fda5fdf0f2180fb6caaae3894f1b854d006ac61ecc727ee/frozenlist-1.8.0-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:4970ece02dbc8c3a92fcc5228e36a3e933a01a999f7094ff7c23fbd2beeaa67c", size = 49749, upload-time = "2025-10-06T05:37:10.569Z" }, - { url = "https://files.pythonhosted.org/packages/a7/b2/fabede9fafd976b991e9f1b9c8c873ed86f202889b864756f240ce6dd855/frozenlist-1.8.0-cp314-cp314-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:cba69cb73723c3f329622e34bdbf5ce1f80c21c290ff04256cff1cd3c2036ed2", size = 231298, upload-time = "2025-10-06T05:37:11.993Z" }, - { url = "https://files.pythonhosted.org/packages/3a/3b/d9b1e0b0eed36e70477ffb8360c49c85c8ca8ef9700a4e6711f39a6e8b45/frozenlist-1.8.0-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:778a11b15673f6f1df23d9586f83c4846c471a8af693a22e066508b77d201ec8", size = 232015, upload-time = "2025-10-06T05:37:13.194Z" }, - { url = "https://files.pythonhosted.org/packages/dc/94/be719d2766c1138148564a3960fc2c06eb688da592bdc25adcf856101be7/frozenlist-1.8.0-cp314-cp314-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:0325024fe97f94c41c08872db482cf8ac4800d80e79222c6b0b7b162d5b13686", size = 225038, upload-time = "2025-10-06T05:37:14.577Z" }, - { url = "https://files.pythonhosted.org/packages/e4/09/6712b6c5465f083f52f50cf74167b92d4ea2f50e46a9eea0523d658454ae/frozenlist-1.8.0-cp314-cp314-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:97260ff46b207a82a7567b581ab4190bd4dfa09f4db8a8b49d1a958f6aa4940e", size = 240130, upload-time = "2025-10-06T05:37:15.781Z" }, - { url = "https://files.pythonhosted.org/packages/f8/d4/cd065cdcf21550b54f3ce6a22e143ac9e4836ca42a0de1022da8498eac89/frozenlist-1.8.0-cp314-cp314-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:54b2077180eb7f83dd52c40b2750d0a9f175e06a42e3213ce047219de902717a", size = 242845, upload-time = "2025-10-06T05:37:17.037Z" }, - { url = "https://files.pythonhosted.org/packages/62/c3/f57a5c8c70cd1ead3d5d5f776f89d33110b1addae0ab010ad774d9a44fb9/frozenlist-1.8.0-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:2f05983daecab868a31e1da44462873306d3cbfd76d1f0b5b69c473d21dbb128", size = 229131, upload-time = "2025-10-06T05:37:18.221Z" }, - { url = "https://files.pythonhosted.org/packages/6c/52/232476fe9cb64f0742f3fde2b7d26c1dac18b6d62071c74d4ded55e0ef94/frozenlist-1.8.0-cp314-cp314-musllinux_1_2_armv7l.whl", hash = "sha256:33f48f51a446114bc5d251fb2954ab0164d5be02ad3382abcbfe07e2531d650f", size = 240542, upload-time = "2025-10-06T05:37:19.771Z" }, - { url = "https://files.pythonhosted.org/packages/5f/85/07bf3f5d0fb5414aee5f47d33c6f5c77bfe49aac680bfece33d4fdf6a246/frozenlist-1.8.0-cp314-cp314-musllinux_1_2_ppc64le.whl", hash = "sha256:154e55ec0655291b5dd1b8731c637ecdb50975a2ae70c606d100750a540082f7", size = 237308, upload-time = "2025-10-06T05:37:20.969Z" }, - { url = "https://files.pythonhosted.org/packages/11/99/ae3a33d5befd41ac0ca2cc7fd3aa707c9c324de2e89db0e0f45db9a64c26/frozenlist-1.8.0-cp314-cp314-musllinux_1_2_s390x.whl", hash = "sha256:4314debad13beb564b708b4a496020e5306c7333fa9a3ab90374169a20ffab30", size = 238210, upload-time = "2025-10-06T05:37:22.252Z" }, - { url = "https://files.pythonhosted.org/packages/b2/60/b1d2da22f4970e7a155f0adde9b1435712ece01b3cd45ba63702aea33938/frozenlist-1.8.0-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:073f8bf8becba60aa931eb3bc420b217bb7d5b8f4750e6f8b3be7f3da85d38b7", size = 231972, upload-time = "2025-10-06T05:37:23.5Z" }, - { url = "https://files.pythonhosted.org/packages/3f/ab/945b2f32de889993b9c9133216c068b7fcf257d8595a0ac420ac8677cab0/frozenlist-1.8.0-cp314-cp314-win32.whl", hash = "sha256:bac9c42ba2ac65ddc115d930c78d24ab8d4f465fd3fc473cdedfccadb9429806", size = 40536, upload-time = "2025-10-06T05:37:25.581Z" }, - { url = "https://files.pythonhosted.org/packages/59/ad/9caa9b9c836d9ad6f067157a531ac48b7d36499f5036d4141ce78c230b1b/frozenlist-1.8.0-cp314-cp314-win_amd64.whl", hash = "sha256:3e0761f4d1a44f1d1a47996511752cf3dcec5bbdd9cc2b4fe595caf97754b7a0", size = 44330, upload-time = "2025-10-06T05:37:26.928Z" }, - { url = "https://files.pythonhosted.org/packages/82/13/e6950121764f2676f43534c555249f57030150260aee9dcf7d64efda11dd/frozenlist-1.8.0-cp314-cp314-win_arm64.whl", hash = "sha256:d1eaff1d00c7751b7c6662e9c5ba6eb2c17a2306ba5e2a37f24ddf3cc953402b", size = 40627, upload-time = "2025-10-06T05:37:28.075Z" }, - { url = "https://files.pythonhosted.org/packages/c0/c7/43200656ecc4e02d3f8bc248df68256cd9572b3f0017f0a0c4e93440ae23/frozenlist-1.8.0-cp314-cp314t-macosx_10_13_universal2.whl", hash = "sha256:d3bb933317c52d7ea5004a1c442eef86f426886fba134ef8cf4226ea6ee1821d", size = 89238, upload-time = "2025-10-06T05:37:29.373Z" }, - { url = "https://files.pythonhosted.org/packages/d1/29/55c5f0689b9c0fb765055629f472c0de484dcaf0acee2f7707266ae3583c/frozenlist-1.8.0-cp314-cp314t-macosx_10_13_x86_64.whl", hash = "sha256:8009897cdef112072f93a0efdce29cd819e717fd2f649ee3016efd3cd885a7ed", size = 50738, upload-time = "2025-10-06T05:37:30.792Z" }, - { url = "https://files.pythonhosted.org/packages/ba/7d/b7282a445956506fa11da8c2db7d276adcbf2b17d8bb8407a47685263f90/frozenlist-1.8.0-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:2c5dcbbc55383e5883246d11fd179782a9d07a986c40f49abe89ddf865913930", size = 51739, upload-time = "2025-10-06T05:37:32.127Z" }, - { url = "https://files.pythonhosted.org/packages/62/1c/3d8622e60d0b767a5510d1d3cf21065b9db874696a51ea6d7a43180a259c/frozenlist-1.8.0-cp314-cp314t-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:39ecbc32f1390387d2aa4f5a995e465e9e2f79ba3adcac92d68e3e0afae6657c", size = 284186, upload-time = "2025-10-06T05:37:33.21Z" }, - { url = "https://files.pythonhosted.org/packages/2d/14/aa36d5f85a89679a85a1d44cd7a6657e0b1c75f61e7cad987b203d2daca8/frozenlist-1.8.0-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:92db2bf818d5cc8d9c1f1fc56b897662e24ea5adb36ad1f1d82875bd64e03c24", size = 292196, upload-time = "2025-10-06T05:37:36.107Z" }, - { url = "https://files.pythonhosted.org/packages/05/23/6bde59eb55abd407d34f77d39a5126fb7b4f109a3f611d3929f14b700c66/frozenlist-1.8.0-cp314-cp314t-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:2dc43a022e555de94c3b68a4ef0b11c4f747d12c024a520c7101709a2144fb37", size = 273830, upload-time = "2025-10-06T05:37:37.663Z" }, - { url = "https://files.pythonhosted.org/packages/d2/3f/22cff331bfad7a8afa616289000ba793347fcd7bc275f3b28ecea2a27909/frozenlist-1.8.0-cp314-cp314t-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:cb89a7f2de3602cfed448095bab3f178399646ab7c61454315089787df07733a", size = 294289, upload-time = "2025-10-06T05:37:39.261Z" }, - { url = "https://files.pythonhosted.org/packages/a4/89/5b057c799de4838b6c69aa82b79705f2027615e01be996d2486a69ca99c4/frozenlist-1.8.0-cp314-cp314t-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:33139dc858c580ea50e7e60a1b0ea003efa1fd42e6ec7fdbad78fff65fad2fd2", size = 300318, upload-time = "2025-10-06T05:37:43.213Z" }, - { url = "https://files.pythonhosted.org/packages/30/de/2c22ab3eb2a8af6d69dc799e48455813bab3690c760de58e1bf43b36da3e/frozenlist-1.8.0-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:168c0969a329b416119507ba30b9ea13688fafffac1b7822802537569a1cb0ef", size = 282814, upload-time = "2025-10-06T05:37:45.337Z" }, - { url = "https://files.pythonhosted.org/packages/59/f7/970141a6a8dbd7f556d94977858cfb36fa9b66e0892c6dd780d2219d8cd8/frozenlist-1.8.0-cp314-cp314t-musllinux_1_2_armv7l.whl", hash = "sha256:28bd570e8e189d7f7b001966435f9dac6718324b5be2990ac496cf1ea9ddb7fe", size = 291762, upload-time = "2025-10-06T05:37:46.657Z" }, - { url = "https://files.pythonhosted.org/packages/c1/15/ca1adae83a719f82df9116d66f5bb28bb95557b3951903d39135620ef157/frozenlist-1.8.0-cp314-cp314t-musllinux_1_2_ppc64le.whl", hash = "sha256:b2a095d45c5d46e5e79ba1e5b9cb787f541a8dee0433836cea4b96a2c439dcd8", size = 289470, upload-time = "2025-10-06T05:37:47.946Z" }, - { url = "https://files.pythonhosted.org/packages/ac/83/dca6dc53bf657d371fbc88ddeb21b79891e747189c5de990b9dfff2ccba1/frozenlist-1.8.0-cp314-cp314t-musllinux_1_2_s390x.whl", hash = "sha256:eab8145831a0d56ec9c4139b6c3e594c7a83c2c8be25d5bcf2d86136a532287a", size = 289042, upload-time = "2025-10-06T05:37:49.499Z" }, - { url = "https://files.pythonhosted.org/packages/96/52/abddd34ca99be142f354398700536c5bd315880ed0a213812bc491cff5e4/frozenlist-1.8.0-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:974b28cf63cc99dfb2188d8d222bc6843656188164848c4f679e63dae4b0708e", size = 283148, upload-time = "2025-10-06T05:37:50.745Z" }, - { url = "https://files.pythonhosted.org/packages/af/d3/76bd4ed4317e7119c2b7f57c3f6934aba26d277acc6309f873341640e21f/frozenlist-1.8.0-cp314-cp314t-win32.whl", hash = "sha256:342c97bf697ac5480c0a7ec73cd700ecfa5a8a40ac923bd035484616efecc2df", size = 44676, upload-time = "2025-10-06T05:37:52.222Z" }, - { url = "https://files.pythonhosted.org/packages/89/76/c615883b7b521ead2944bb3480398cbb07e12b7b4e4d073d3752eb721558/frozenlist-1.8.0-cp314-cp314t-win_amd64.whl", hash = "sha256:06be8f67f39c8b1dc671f5d83aaefd3358ae5cdcf8314552c57e7ed3e6475bdd", size = 49451, upload-time = "2025-10-06T05:37:53.425Z" }, - { url = "https://files.pythonhosted.org/packages/e0/a3/5982da14e113d07b325230f95060e2169f5311b1017ea8af2a29b374c289/frozenlist-1.8.0-cp314-cp314t-win_arm64.whl", hash = "sha256:102e6314ca4da683dca92e3b1355490fed5f313b768500084fbe6371fddfdb79", size = 42507, upload-time = "2025-10-06T05:37:54.513Z" }, - { url = "https://files.pythonhosted.org/packages/9a/9a/e35b4a917281c0b8419d4207f4334c8e8c5dbf4f3f5f9ada73958d937dcc/frozenlist-1.8.0-py3-none-any.whl", hash = "sha256:0c18a16eab41e82c295618a77502e17b195883241c563b00f0aa5106fc4eaa0d", size = 13409, upload-time = "2025-10-06T05:38:16.721Z" }, -] - -[[package]] -name = "fsspec" -version = "2026.2.0" -source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/51/7c/f60c259dcbf4f0c47cc4ddb8f7720d2dcdc8888c8e5ad84c73ea4531cc5b/fsspec-2026.2.0.tar.gz", hash = "sha256:6544e34b16869f5aacd5b90bdf1a71acb37792ea3ddf6125ee69a22a53fb8bff", size = 313441, upload-time = "2026-02-05T21:50:53.743Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/e6/ab/fb21f4c939bb440104cc2b396d3be1d9b7a9fd3c6c2a53d98c45b3d7c954/fsspec-2026.2.0-py3-none-any.whl", hash = "sha256:98de475b5cb3bd66bedd5c4679e87b4fdfe1a3bf4d707b151b3c07e58c9a2437", size = 202505, upload-time = "2026-02-05T21:50:51.819Z" }, -] - [[package]] name = "genai-prices" version = "0.0.62" @@ -2029,84 +1548,6 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/4d/51/c936033e16d12b627ea334aaaaf42229c37620d0f15593456ab69ab48161/griffelib-2.0.0-py3-none-any.whl", hash = "sha256:01284878c966508b6d6f1dbff9b6fa607bc062d8261c5c7253cb285b06422a7f", size = 142004, upload-time = "2026-02-09T19:09:40.561Z" }, ] -[[package]] -name = "groq" -version = "1.0.0" -source = { registry = "https://pypi.org/simple" } -dependencies = [ - { name = "anyio" }, - { name = "distro" }, - { name = "httpx" }, - { name = "pydantic" }, - { name = "sniffio" }, - { name = "typing-extensions" }, -] -sdist = { url = "https://files.pythonhosted.org/packages/3f/12/f4099a141677fcd2ed79dcc1fcec431e60c52e0e90c9c5d935f0ffaf8c0e/groq-1.0.0.tar.gz", hash = "sha256:66cb7bb729e6eb644daac7ce8efe945e99e4eb33657f733ee6f13059ef0c25a9", size = 146068, upload-time = "2025-12-17T23:34:23.115Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/4a/88/3175759d2ef30406ea721f4d837bfa1ba4339fde3b81ba8c5640a96ed231/groq-1.0.0-py3-none-any.whl", hash = "sha256:6e22bf92ffad988f01d2d4df7729add66b8fd5dbfb2154b5bbf3af245b72c731", size = 138292, upload-time = "2025-12-17T23:34:21.957Z" }, -] - -[[package]] -name = "grpcio" -version = "1.78.0" -source = { registry = "https://pypi.org/simple" } -dependencies = [ - { name = "typing-extensions" }, -] -sdist = { url = "https://files.pythonhosted.org/packages/06/8a/3d098f35c143a89520e568e6539cc098fcd294495910e359889ce8741c84/grpcio-1.78.0.tar.gz", hash = "sha256:7382b95189546f375c174f53a5fa873cef91c4b8005faa05cc5b3beea9c4f1c5", size = 12852416, upload-time = "2026-02-06T09:57:18.093Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/5a/a8/690a085b4d1fe066130de97a87de32c45062cf2ecd218df9675add895550/grpcio-1.78.0-cp310-cp310-linux_armv7l.whl", hash = "sha256:7cc47943d524ee0096f973e1081cb8f4f17a4615f2116882a5f1416e4cfe92b5", size = 5946986, upload-time = "2026-02-06T09:54:34.043Z" }, - { url = "https://files.pythonhosted.org/packages/c7/1b/e5213c5c0ced9d2d92778d30529ad5bb2dcfb6c48c4e2d01b1f302d33d64/grpcio-1.78.0-cp310-cp310-macosx_11_0_universal2.whl", hash = "sha256:c3f293fdc675ccba4db5a561048cca627b5e7bd1c8a6973ffedabe7d116e22e2", size = 11816533, upload-time = "2026-02-06T09:54:37.04Z" }, - { url = "https://files.pythonhosted.org/packages/18/37/1ba32dccf0a324cc5ace744c44331e300b000a924bf14840f948c559ede7/grpcio-1.78.0-cp310-cp310-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:10a9a644b5dd5aec3b82b5b0b90d41c0fa94c85ef42cb42cf78a23291ddb5e7d", size = 6519964, upload-time = "2026-02-06T09:54:40.268Z" }, - { url = "https://files.pythonhosted.org/packages/ed/f5/c0e178721b818072f2e8b6fde13faaba942406c634009caf065121ce246b/grpcio-1.78.0-cp310-cp310-manylinux2014_i686.manylinux_2_17_i686.whl", hash = "sha256:4c5533d03a6cbd7f56acfc9cfb44ea64f63d29091e40e44010d34178d392d7eb", size = 7198058, upload-time = "2026-02-06T09:54:42.389Z" }, - { url = "https://files.pythonhosted.org/packages/5b/b2/40d43c91ae9cd667edc960135f9f08e58faa1576dc95af29f66ec912985f/grpcio-1.78.0-cp310-cp310-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:ff870aebe9a93a85283837801d35cd5f8814fe2ad01e606861a7fb47c762a2b7", size = 6727212, upload-time = "2026-02-06T09:54:44.91Z" }, - { url = "https://files.pythonhosted.org/packages/ed/88/9da42eed498f0efcfcd9156e48ae63c0cde3bea398a16c99fb5198c885b6/grpcio-1.78.0-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:391e93548644e6b2726f1bb84ed60048d4bcc424ce5e4af0843d28ca0b754fec", size = 7300845, upload-time = "2026-02-06T09:54:47.562Z" }, - { url = "https://files.pythonhosted.org/packages/23/3f/1c66b7b1b19a8828890e37868411a6e6925df5a9030bfa87ab318f34095d/grpcio-1.78.0-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:df2c8f3141f7cbd112a6ebbd760290b5849cda01884554f7c67acc14e7b1758a", size = 8284605, upload-time = "2026-02-06T09:54:50.475Z" }, - { url = "https://files.pythonhosted.org/packages/94/c4/ca1bd87394f7b033e88525384b4d1e269e8424ab441ea2fba1a0c5b50986/grpcio-1.78.0-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:bd8cb8026e5f5b50498a3c4f196f57f9db344dad829ffae16b82e4fdbaea2813", size = 7726672, upload-time = "2026-02-06T09:54:53.11Z" }, - { url = "https://files.pythonhosted.org/packages/41/09/f16e487d4cc65ccaf670f6ebdd1a17566b965c74fc3d93999d3b2821e052/grpcio-1.78.0-cp310-cp310-win32.whl", hash = "sha256:f8dff3d9777e5d2703a962ee5c286c239bf0ba173877cc68dc02c17d042e29de", size = 4076715, upload-time = "2026-02-06T09:54:55.549Z" }, - { url = "https://files.pythonhosted.org/packages/2a/32/4ce60d94e242725fd3bcc5673c04502c82a8e87b21ea411a63992dc39f8f/grpcio-1.78.0-cp310-cp310-win_amd64.whl", hash = "sha256:94f95cf5d532d0e717eed4fc1810e8e6eded04621342ec54c89a7c2f14b581bf", size = 4799157, upload-time = "2026-02-06T09:54:59.838Z" }, - { url = "https://files.pythonhosted.org/packages/86/c7/d0b780a29b0837bf4ca9580904dfb275c1fc321ded7897d620af7047ec57/grpcio-1.78.0-cp311-cp311-linux_armv7l.whl", hash = "sha256:2777b783f6c13b92bd7b716667452c329eefd646bfb3f2e9dabea2e05dbd34f6", size = 5951525, upload-time = "2026-02-06T09:55:01.989Z" }, - { url = "https://files.pythonhosted.org/packages/c5/b1/96920bf2ee61df85a9503cb6f733fe711c0ff321a5a697d791b075673281/grpcio-1.78.0-cp311-cp311-macosx_11_0_universal2.whl", hash = "sha256:9dca934f24c732750389ce49d638069c3892ad065df86cb465b3fa3012b70c9e", size = 11830418, upload-time = "2026-02-06T09:55:04.462Z" }, - { url = "https://files.pythonhosted.org/packages/83/0c/7c1528f098aeb75a97de2bae18c530f56959fb7ad6c882db45d9884d6edc/grpcio-1.78.0-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:459ab414b35f4496138d0ecd735fed26f1318af5e52cb1efbc82a09f0d5aa911", size = 6524477, upload-time = "2026-02-06T09:55:07.111Z" }, - { url = "https://files.pythonhosted.org/packages/8d/52/e7c1f3688f949058e19a011c4e0dec973da3d0ae5e033909677f967ae1f4/grpcio-1.78.0-cp311-cp311-manylinux2014_i686.manylinux_2_17_i686.whl", hash = "sha256:082653eecbdf290e6e3e2c276ab2c54b9e7c299e07f4221872380312d8cf395e", size = 7198266, upload-time = "2026-02-06T09:55:10.016Z" }, - { url = "https://files.pythonhosted.org/packages/e5/61/8ac32517c1e856677282c34f2e7812d6c328fa02b8f4067ab80e77fdc9c9/grpcio-1.78.0-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:85f93781028ec63f383f6bc90db785a016319c561cc11151fbb7b34e0d012303", size = 6730552, upload-time = "2026-02-06T09:55:12.207Z" }, - { url = "https://files.pythonhosted.org/packages/bd/98/b8ee0158199250220734f620b12e4a345955ac7329cfd908d0bf0fda77f0/grpcio-1.78.0-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:f12857d24d98441af6a1d5c87442d624411db486f7ba12550b07788f74b67b04", size = 7304296, upload-time = "2026-02-06T09:55:15.044Z" }, - { url = "https://files.pythonhosted.org/packages/bd/0f/7b72762e0d8840b58032a56fdbd02b78fc645b9fa993d71abf04edbc54f4/grpcio-1.78.0-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:5397fff416b79e4b284959642a4e95ac4b0f1ece82c9993658e0e477d40551ec", size = 8288298, upload-time = "2026-02-06T09:55:17.276Z" }, - { url = "https://files.pythonhosted.org/packages/24/ae/ae4ce56bc5bb5caa3a486d60f5f6083ac3469228faa734362487176c15c5/grpcio-1.78.0-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:fbe6e89c7ffb48518384068321621b2a69cab509f58e40e4399fdd378fa6d074", size = 7730953, upload-time = "2026-02-06T09:55:19.545Z" }, - { url = "https://files.pythonhosted.org/packages/b5/6e/8052e3a28eb6a820c372b2eb4b5e32d195c661e137d3eca94d534a4cfd8a/grpcio-1.78.0-cp311-cp311-win32.whl", hash = "sha256:6092beabe1966a3229f599d7088b38dfc8ffa1608b5b5cdda31e591e6500f856", size = 4076503, upload-time = "2026-02-06T09:55:21.521Z" }, - { url = "https://files.pythonhosted.org/packages/08/62/f22c98c5265dfad327251fa2f840b591b1df5f5e15d88b19c18c86965b27/grpcio-1.78.0-cp311-cp311-win_amd64.whl", hash = "sha256:1afa62af6e23f88629f2b29ec9e52ec7c65a7176c1e0a83292b93c76ca882558", size = 4799767, upload-time = "2026-02-06T09:55:24.107Z" }, - { url = "https://files.pythonhosted.org/packages/4e/f4/7384ed0178203d6074446b3c4f46c90a22ddf7ae0b3aee521627f54cfc2a/grpcio-1.78.0-cp312-cp312-linux_armv7l.whl", hash = "sha256:f9ab915a267fc47c7e88c387a3a28325b58c898e23d4995f765728f4e3dedb97", size = 5913985, upload-time = "2026-02-06T09:55:26.832Z" }, - { url = "https://files.pythonhosted.org/packages/81/ed/be1caa25f06594463f685b3790b320f18aea49b33166f4141bfdc2bfb236/grpcio-1.78.0-cp312-cp312-macosx_11_0_universal2.whl", hash = "sha256:3f8904a8165ab21e07e58bf3e30a73f4dffc7a1e0dbc32d51c61b5360d26f43e", size = 11811853, upload-time = "2026-02-06T09:55:29.224Z" }, - { url = "https://files.pythonhosted.org/packages/24/a7/f06d151afc4e64b7e3cc3e872d331d011c279aaab02831e40a81c691fb65/grpcio-1.78.0-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:859b13906ce098c0b493af92142ad051bf64c7870fa58a123911c88606714996", size = 6475766, upload-time = "2026-02-06T09:55:31.825Z" }, - { url = "https://files.pythonhosted.org/packages/8a/a8/4482922da832ec0082d0f2cc3a10976d84a7424707f25780b82814aafc0a/grpcio-1.78.0-cp312-cp312-manylinux2014_i686.manylinux_2_17_i686.whl", hash = "sha256:b2342d87af32790f934a79c3112641e7b27d63c261b8b4395350dad43eff1dc7", size = 7170027, upload-time = "2026-02-06T09:55:34.7Z" }, - { url = "https://files.pythonhosted.org/packages/54/bf/f4a3b9693e35d25b24b0b39fa46d7d8a3c439e0a3036c3451764678fec20/grpcio-1.78.0-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:12a771591ae40bc65ba67048fa52ef4f0e6db8279e595fd349f9dfddeef571f9", size = 6690766, upload-time = "2026-02-06T09:55:36.902Z" }, - { url = "https://files.pythonhosted.org/packages/c7/b9/521875265cc99fe5ad4c5a17010018085cae2810a928bf15ebe7d8bcd9cc/grpcio-1.78.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:185dea0d5260cbb2d224c507bf2a5444d5abbb1fa3594c1ed7e4c709d5eb8383", size = 7266161, upload-time = "2026-02-06T09:55:39.824Z" }, - { url = "https://files.pythonhosted.org/packages/05/86/296a82844fd40a4ad4a95f100b55044b4f817dece732bf686aea1a284147/grpcio-1.78.0-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:51b13f9aed9d59ee389ad666b8c2214cc87b5de258fa712f9ab05f922e3896c6", size = 8253303, upload-time = "2026-02-06T09:55:42.353Z" }, - { url = "https://files.pythonhosted.org/packages/f3/e4/ea3c0caf5468537f27ad5aab92b681ed7cc0ef5f8c9196d3fd42c8c2286b/grpcio-1.78.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:fd5f135b1bd58ab088930b3c613455796dfa0393626a6972663ccdda5b4ac6ce", size = 7698222, upload-time = "2026-02-06T09:55:44.629Z" }, - { url = "https://files.pythonhosted.org/packages/d7/47/7f05f81e4bb6b831e93271fb12fd52ba7b319b5402cbc101d588f435df00/grpcio-1.78.0-cp312-cp312-win32.whl", hash = "sha256:94309f498bcc07e5a7d16089ab984d42ad96af1d94b5a4eb966a266d9fcabf68", size = 4066123, upload-time = "2026-02-06T09:55:47.644Z" }, - { url = "https://files.pythonhosted.org/packages/ad/e7/d6914822c88aa2974dbbd10903d801a28a19ce9cd8bad7e694cbbcf61528/grpcio-1.78.0-cp312-cp312-win_amd64.whl", hash = "sha256:9566fe4ababbb2610c39190791e5b829869351d14369603702e890ef3ad2d06e", size = 4797657, upload-time = "2026-02-06T09:55:49.86Z" }, - { url = "https://files.pythonhosted.org/packages/05/a9/8f75894993895f361ed8636cd9237f4ab39ef87fd30db17467235ed1c045/grpcio-1.78.0-cp313-cp313-linux_armv7l.whl", hash = "sha256:ce3a90455492bf8bfa38e56fbbe1dbd4f872a3d8eeaf7337dc3b1c8aa28c271b", size = 5920143, upload-time = "2026-02-06T09:55:52.035Z" }, - { url = "https://files.pythonhosted.org/packages/55/06/0b78408e938ac424100100fd081189451b472236e8a3a1f6500390dc4954/grpcio-1.78.0-cp313-cp313-macosx_11_0_universal2.whl", hash = "sha256:2bf5e2e163b356978b23652c4818ce4759d40f4712ee9ec5a83c4be6f8c23a3a", size = 11803926, upload-time = "2026-02-06T09:55:55.494Z" }, - { url = "https://files.pythonhosted.org/packages/88/93/b59fe7832ff6ae3c78b813ea43dac60e295fa03606d14d89d2e0ec29f4f3/grpcio-1.78.0-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:8f2ac84905d12918e4e55a16da17939eb63e433dc11b677267c35568aa63fc84", size = 6478628, upload-time = "2026-02-06T09:55:58.533Z" }, - { url = "https://files.pythonhosted.org/packages/ed/df/e67e3734527f9926b7d9c0dde6cd998d1d26850c3ed8eeec81297967ac67/grpcio-1.78.0-cp313-cp313-manylinux2014_i686.manylinux_2_17_i686.whl", hash = "sha256:b58f37edab4a3881bc6c9bca52670610e0c9ca14e2ea3cf9debf185b870457fb", size = 7173574, upload-time = "2026-02-06T09:56:01.786Z" }, - { url = "https://files.pythonhosted.org/packages/a6/62/cc03fffb07bfba982a9ec097b164e8835546980aec25ecfa5f9c1a47e022/grpcio-1.78.0-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:735e38e176a88ce41840c21bb49098ab66177c64c82426e24e0082500cc68af5", size = 6692639, upload-time = "2026-02-06T09:56:04.529Z" }, - { url = "https://files.pythonhosted.org/packages/bf/9a/289c32e301b85bdb67d7ec68b752155e674ee3ba2173a1858f118e399ef3/grpcio-1.78.0-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:2045397e63a7a0ee7957c25f7dbb36ddc110e0cfb418403d110c0a7a68a844e9", size = 7268838, upload-time = "2026-02-06T09:56:08.397Z" }, - { url = "https://files.pythonhosted.org/packages/0e/79/1be93f32add280461fa4773880196572563e9c8510861ac2da0ea0f892b6/grpcio-1.78.0-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:a9f136fbafe7ccf4ac7e8e0c28b31066e810be52d6e344ef954a3a70234e1702", size = 8251878, upload-time = "2026-02-06T09:56:10.914Z" }, - { url = "https://files.pythonhosted.org/packages/65/65/793f8e95296ab92e4164593674ae6291b204bb5f67f9d4a711489cd30ffa/grpcio-1.78.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:748b6138585379c737adc08aeffd21222abbda1a86a0dca2a39682feb9196c20", size = 7695412, upload-time = "2026-02-06T09:56:13.593Z" }, - { url = "https://files.pythonhosted.org/packages/1c/9f/1e233fe697ecc82845942c2822ed06bb522e70d6771c28d5528e4c50f6a4/grpcio-1.78.0-cp313-cp313-win32.whl", hash = "sha256:271c73e6e5676afe4fc52907686670c7cea22ab2310b76a59b678403ed40d670", size = 4064899, upload-time = "2026-02-06T09:56:15.601Z" }, - { url = "https://files.pythonhosted.org/packages/4d/27/d86b89e36de8a951501fb06a0f38df19853210f341d0b28f83f4aa0ffa08/grpcio-1.78.0-cp313-cp313-win_amd64.whl", hash = "sha256:f2d4e43ee362adfc05994ed479334d5a451ab7bc3f3fee1b796b8ca66895acb4", size = 4797393, upload-time = "2026-02-06T09:56:17.882Z" }, - { url = "https://files.pythonhosted.org/packages/29/f2/b56e43e3c968bfe822fa6ce5bca10d5c723aa40875b48791ce1029bb78c7/grpcio-1.78.0-cp314-cp314-linux_armv7l.whl", hash = "sha256:e87cbc002b6f440482b3519e36e1313eb5443e9e9e73d6a52d43bd2004fcfd8e", size = 5920591, upload-time = "2026-02-06T09:56:20.758Z" }, - { url = "https://files.pythonhosted.org/packages/5d/81/1f3b65bd30c334167bfa8b0d23300a44e2725ce39bba5b76a2460d85f745/grpcio-1.78.0-cp314-cp314-macosx_11_0_universal2.whl", hash = "sha256:c41bc64626db62e72afec66b0c8a0da76491510015417c127bfc53b2fe6d7f7f", size = 11813685, upload-time = "2026-02-06T09:56:24.315Z" }, - { url = "https://files.pythonhosted.org/packages/0e/1c/bbe2f8216a5bd3036119c544d63c2e592bdf4a8ec6e4a1867592f4586b26/grpcio-1.78.0-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:8dfffba826efcf366b1e3ccc37e67afe676f290e13a3b48d31a46739f80a8724", size = 6487803, upload-time = "2026-02-06T09:56:27.367Z" }, - { url = "https://files.pythonhosted.org/packages/16/5c/a6b2419723ea7ddce6308259a55e8e7593d88464ce8db9f4aa857aba96fa/grpcio-1.78.0-cp314-cp314-manylinux2014_i686.manylinux_2_17_i686.whl", hash = "sha256:74be1268d1439eaaf552c698cdb11cd594f0c49295ae6bb72c34ee31abbe611b", size = 7173206, upload-time = "2026-02-06T09:56:29.876Z" }, - { url = "https://files.pythonhosted.org/packages/df/1e/b8801345629a415ea7e26c83d75eb5dbe91b07ffe5210cc517348a8d4218/grpcio-1.78.0-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:be63c88b32e6c0f1429f1398ca5c09bc64b0d80950c8bb7807d7d7fb36fb84c7", size = 6693826, upload-time = "2026-02-06T09:56:32.305Z" }, - { url = "https://files.pythonhosted.org/packages/34/84/0de28eac0377742679a510784f049738a80424b17287739fc47d63c2439e/grpcio-1.78.0-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:3c586ac70e855c721bda8f548d38c3ca66ac791dc49b66a8281a1f99db85e452", size = 7277897, upload-time = "2026-02-06T09:56:34.915Z" }, - { url = "https://files.pythonhosted.org/packages/ca/9c/ad8685cfe20559a9edb66f735afdcb2b7d3de69b13666fdfc542e1916ebd/grpcio-1.78.0-cp314-cp314-musllinux_1_2_i686.whl", hash = "sha256:35eb275bf1751d2ffbd8f57cdbc46058e857cf3971041521b78b7db94bdaf127", size = 8252404, upload-time = "2026-02-06T09:56:37.553Z" }, - { url = "https://files.pythonhosted.org/packages/3c/05/33a7a4985586f27e1de4803887c417ec7ced145ebd069bc38a9607059e2b/grpcio-1.78.0-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:207db540302c884b8848036b80db352a832b99dfdf41db1eb554c2c2c7800f65", size = 7696837, upload-time = "2026-02-06T09:56:40.173Z" }, - { url = "https://files.pythonhosted.org/packages/73/77/7382241caf88729b106e49e7d18e3116216c778e6a7e833826eb96de22f7/grpcio-1.78.0-cp314-cp314-win32.whl", hash = "sha256:57bab6deef2f4f1ca76cc04565df38dc5713ae6c17de690721bdf30cb1e0545c", size = 4142439, upload-time = "2026-02-06T09:56:43.258Z" }, - { url = "https://files.pythonhosted.org/packages/48/b2/b096ccce418882fbfda4f7496f9357aaa9a5af1896a9a7f60d9f2b275a06/grpcio-1.78.0-cp314-cp314-win_amd64.whl", hash = "sha256:dce09d6116df20a96acfdbf85e4866258c3758180e8c49845d6ba8248b6d0bbb", size = 4929852, upload-time = "2026-02-06T09:56:45.885Z" }, -] - [[package]] name = "h11" version = "0.16.0" @@ -2116,35 +1557,6 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/04/4b/29cac41a4d98d144bf5f6d33995617b185d14b22401f75ca86f384e87ff1/h11-0.16.0-py3-none-any.whl", hash = "sha256:63cf8bbe7522de3bf65932fda1d9c2772064ffb3dae62d55932da54b31cb6c86", size = 37515, upload-time = "2025-04-24T03:35:24.344Z" }, ] -[[package]] -name = "hf-xet" -version = "1.2.0" -source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/5e/6e/0f11bacf08a67f7fb5ee09740f2ca54163863b07b70d579356e9222ce5d8/hf_xet-1.2.0.tar.gz", hash = "sha256:a8c27070ca547293b6890c4bf389f713f80e8c478631432962bb7f4bc0bd7d7f", size = 506020, upload-time = "2025-10-24T19:04:32.129Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/9e/a5/85ef910a0aa034a2abcfadc360ab5ac6f6bc4e9112349bd40ca97551cff0/hf_xet-1.2.0-cp313-cp313t-macosx_10_12_x86_64.whl", hash = "sha256:ceeefcd1b7aed4956ae8499e2199607765fbd1c60510752003b6cc0b8413b649", size = 2861870, upload-time = "2025-10-24T19:04:11.422Z" }, - { url = "https://files.pythonhosted.org/packages/ea/40/e2e0a7eb9a51fe8828ba2d47fe22a7e74914ea8a0db68a18c3aa7449c767/hf_xet-1.2.0-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:b70218dd548e9840224df5638fdc94bd033552963cfa97f9170829381179c813", size = 2717584, upload-time = "2025-10-24T19:04:09.586Z" }, - { url = "https://files.pythonhosted.org/packages/a5/7d/daf7f8bc4594fdd59a8a596f9e3886133fdc68e675292218a5e4c1b7e834/hf_xet-1.2.0-cp313-cp313t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7d40b18769bb9a8bc82a9ede575ce1a44c75eb80e7375a01d76259089529b5dc", size = 3315004, upload-time = "2025-10-24T19:04:00.314Z" }, - { url = "https://files.pythonhosted.org/packages/b1/ba/45ea2f605fbf6d81c8b21e4d970b168b18a53515923010c312c06cd83164/hf_xet-1.2.0-cp313-cp313t-manylinux_2_28_aarch64.whl", hash = "sha256:cd3a6027d59cfb60177c12d6424e31f4b5ff13d8e3a1247b3a584bf8977e6df5", size = 3222636, upload-time = "2025-10-24T19:03:58.111Z" }, - { url = "https://files.pythonhosted.org/packages/4a/1d/04513e3cab8f29ab8c109d309ddd21a2705afab9d52f2ba1151e0c14f086/hf_xet-1.2.0-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:6de1fc44f58f6dd937956c8d304d8c2dea264c80680bcfa61ca4a15e7b76780f", size = 3408448, upload-time = "2025-10-24T19:04:20.951Z" }, - { url = "https://files.pythonhosted.org/packages/f0/7c/60a2756d7feec7387db3a1176c632357632fbe7849fce576c5559d4520c7/hf_xet-1.2.0-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:f182f264ed2acd566c514e45da9f2119110e48a87a327ca271027904c70c5832", size = 3503401, upload-time = "2025-10-24T19:04:22.549Z" }, - { url = "https://files.pythonhosted.org/packages/4e/64/48fffbd67fb418ab07451e4ce641a70de1c40c10a13e25325e24858ebe5a/hf_xet-1.2.0-cp313-cp313t-win_amd64.whl", hash = "sha256:293a7a3787e5c95d7be1857358a9130694a9c6021de3f27fa233f37267174382", size = 2900866, upload-time = "2025-10-24T19:04:33.461Z" }, - { url = "https://files.pythonhosted.org/packages/e2/51/f7e2caae42f80af886db414d4e9885fac959330509089f97cccb339c6b87/hf_xet-1.2.0-cp314-cp314t-macosx_10_12_x86_64.whl", hash = "sha256:10bfab528b968c70e062607f663e21e34e2bba349e8038db546646875495179e", size = 2861861, upload-time = "2025-10-24T19:04:19.01Z" }, - { url = "https://files.pythonhosted.org/packages/6e/1d/a641a88b69994f9371bd347f1dd35e5d1e2e2460a2e350c8d5165fc62005/hf_xet-1.2.0-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:2a212e842647b02eb6a911187dc878e79c4aa0aa397e88dd3b26761676e8c1f8", size = 2717699, upload-time = "2025-10-24T19:04:17.306Z" }, - { url = "https://files.pythonhosted.org/packages/df/e0/e5e9bba7d15f0318955f7ec3f4af13f92e773fbb368c0b8008a5acbcb12f/hf_xet-1.2.0-cp314-cp314t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:30e06daccb3a7d4c065f34fc26c14c74f4653069bb2b194e7f18f17cbe9939c0", size = 3314885, upload-time = "2025-10-24T19:04:07.642Z" }, - { url = "https://files.pythonhosted.org/packages/21/90/b7fe5ff6f2b7b8cbdf1bd56145f863c90a5807d9758a549bf3d916aa4dec/hf_xet-1.2.0-cp314-cp314t-manylinux_2_28_aarch64.whl", hash = "sha256:29c8fc913a529ec0a91867ce3d119ac1aac966e098cf49501800c870328cc090", size = 3221550, upload-time = "2025-10-24T19:04:05.55Z" }, - { url = "https://files.pythonhosted.org/packages/6f/cb/73f276f0a7ce46cc6a6ec7d6c7d61cbfe5f2e107123d9bbd0193c355f106/hf_xet-1.2.0-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:66e159cbfcfbb29f920db2c09ed8b660eb894640d284f102ada929b6e3dc410a", size = 3408010, upload-time = "2025-10-24T19:04:28.598Z" }, - { url = "https://files.pythonhosted.org/packages/b8/1e/d642a12caa78171f4be64f7cd9c40e3ca5279d055d0873188a58c0f5fbb9/hf_xet-1.2.0-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:9c91d5ae931510107f148874e9e2de8a16052b6f1b3ca3c1b12f15ccb491390f", size = 3503264, upload-time = "2025-10-24T19:04:30.397Z" }, - { url = "https://files.pythonhosted.org/packages/17/b5/33764714923fa1ff922770f7ed18c2daae034d21ae6e10dbf4347c854154/hf_xet-1.2.0-cp314-cp314t-win_amd64.whl", hash = "sha256:210d577732b519ac6ede149d2f2f34049d44e8622bf14eb3d63bbcd2d4b332dc", size = 2901071, upload-time = "2025-10-24T19:04:37.463Z" }, - { url = "https://files.pythonhosted.org/packages/96/2d/22338486473df5923a9ab7107d375dbef9173c338ebef5098ef593d2b560/hf_xet-1.2.0-cp37-abi3-macosx_10_12_x86_64.whl", hash = "sha256:46740d4ac024a7ca9b22bebf77460ff43332868b661186a8e46c227fdae01848", size = 2866099, upload-time = "2025-10-24T19:04:15.366Z" }, - { url = "https://files.pythonhosted.org/packages/7f/8c/c5becfa53234299bc2210ba314eaaae36c2875e0045809b82e40a9544f0c/hf_xet-1.2.0-cp37-abi3-macosx_11_0_arm64.whl", hash = "sha256:27df617a076420d8845bea087f59303da8be17ed7ec0cd7ee3b9b9f579dff0e4", size = 2722178, upload-time = "2025-10-24T19:04:13.695Z" }, - { url = "https://files.pythonhosted.org/packages/9a/92/cf3ab0b652b082e66876d08da57fcc6fa2f0e6c70dfbbafbd470bb73eb47/hf_xet-1.2.0-cp37-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3651fd5bfe0281951b988c0facbe726aa5e347b103a675f49a3fa8144c7968fd", size = 3320214, upload-time = "2025-10-24T19:04:03.596Z" }, - { url = "https://files.pythonhosted.org/packages/46/92/3f7ec4a1b6a65bf45b059b6d4a5d38988f63e193056de2f420137e3c3244/hf_xet-1.2.0-cp37-abi3-manylinux_2_28_aarch64.whl", hash = "sha256:d06fa97c8562fb3ee7a378dd9b51e343bc5bc8190254202c9771029152f5e08c", size = 3229054, upload-time = "2025-10-24T19:04:01.949Z" }, - { url = "https://files.pythonhosted.org/packages/0b/dd/7ac658d54b9fb7999a0ccb07ad863b413cbaf5cf172f48ebcd9497ec7263/hf_xet-1.2.0-cp37-abi3-musllinux_1_2_aarch64.whl", hash = "sha256:4c1428c9ae73ec0939410ec73023c4f842927f39db09b063b9482dac5a3bb737", size = 3413812, upload-time = "2025-10-24T19:04:24.585Z" }, - { url = "https://files.pythonhosted.org/packages/92/68/89ac4e5b12a9ff6286a12174c8538a5930e2ed662091dd2572bbe0a18c8a/hf_xet-1.2.0-cp37-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:a55558084c16b09b5ed32ab9ed38421e2d87cf3f1f89815764d1177081b99865", size = 3508920, upload-time = "2025-10-24T19:04:26.927Z" }, - { url = "https://files.pythonhosted.org/packages/cb/44/870d44b30e1dcfb6a65932e3e1506c103a8a5aea9103c337e7a53180322c/hf_xet-1.2.0-cp37-abi3-win_amd64.whl", hash = "sha256:e6584a52253f72c9f52f9e549d5895ca7a471608495c4ecaa6cc73dba2b24d69", size = 2905735, upload-time = "2025-10-24T19:04:35.928Z" }, -] - [[package]] name = "httpcore" version = "1.0.9" @@ -2160,15 +1572,15 @@ wheels = [ [[package]] name = "httpcore2" -version = "2.4.0" +version = "2.5.0" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "h11" }, { name = "truststore" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/7b/9b/2b1d1833a58236d1f6ee755e027a3917da0db59cc9708554cefc440ee8b6/httpcore2-2.4.0.tar.gz", hash = "sha256:3093a8ab8980d9f910b9cb4351df9186a0ad2350a6284a9107ac9a362a584422", size = 64618, upload-time = "2026-06-11T06:35:53.425Z" } +sdist = { url = "https://files.pythonhosted.org/packages/47/06/5c12df521b5322fb1114a83d46911b2fbcb8855ddb3a635f11c01a214af5/httpcore2-2.5.0.tar.gz", hash = "sha256:88aa170137c17328d5ac44234f9fd10706466d5fb347f3edac4d39b91137b09d", size = 64808, upload-time = "2026-06-25T14:16:56.472Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/7c/72/4fdf2306143a92a471fad9f3655aa542d43aa9188a7c9534e82c9aecf837/httpcore2-2.4.0-py3-none-any.whl", hash = "sha256:5218779da5d6e3c2013ac706121abfb3815d450e0613495c0de50264dce58242", size = 80151, upload-time = "2026-06-11T06:35:50.89Z" }, + { url = "https://files.pythonhosted.org/packages/c9/a1/7564199d1a8728fe737b0a72e5b3f8d92dfe085a74ddf7cdd83bce5f206d/httpcore2-2.5.0-py3-none-any.whl", hash = "sha256:5ce35188de461d31e8d000bfb8ef8bf22c6c16587a211e5571deaa5e9bdf842a", size = 80330, upload-time = "2026-06-25T14:16:53.634Z" }, ] [[package]] @@ -2240,7 +1652,7 @@ wheels = [ [[package]] name = "httpx2" -version = "2.4.0" +version = "2.5.0" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "anyio" }, @@ -2249,30 +1661,9 @@ dependencies = [ { name = "truststore" }, { name = "typing-extensions", marker = "python_full_version < '3.13'" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/fc/60/b43ced4ccf26e95b396dbf67051d3e5042b645917d4da0469dd82a3bdd4f/httpx2-2.4.0.tar.gz", hash = "sha256:32e0734b61eb0824b3f56a9e98d6d92d381a3ef12c0045aa917ee63df6c411ef", size = 81691, upload-time = "2026-06-11T06:35:54.538Z" } +sdist = { url = "https://files.pythonhosted.org/packages/d0/e2/b5dedc0cf35aa65de5f541ccd30d2bc1fd7f1d43c9ab09f8ed9a7342317b/httpx2-2.5.0.tar.gz", hash = "sha256:e2df9cb4611021527ff8a675b1c320b610a2ec397acc8d6fe6e91df2d9b33c29", size = 83121, upload-time = "2026-06-25T14:16:57.491Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/29/45/82bc57c3d9c3314f663b67cc057f1c017a6450685dde513f4f8db5cf431f/httpx2-2.4.0-py3-none-any.whl", hash = "sha256:425acd99297829599decf6701386dd84db3542597d36d3e2e4def930ecd57fd9", size = 74941, upload-time = "2026-06-11T06:35:52.235Z" }, -] - -[[package]] -name = "huggingface-hub" -version = "1.4.1" -source = { registry = "https://pypi.org/simple" } -dependencies = [ - { name = "filelock" }, - { name = "fsspec" }, - { name = "hf-xet", marker = "platform_machine == 'AMD64' or platform_machine == 'aarch64' or platform_machine == 'amd64' or platform_machine == 'arm64' or platform_machine == 'x86_64'" }, - { name = "httpx" }, - { name = "packaging" }, - { name = "pyyaml" }, - { name = "shellingham" }, - { name = "tqdm" }, - { name = "typer-slim" }, - { name = "typing-extensions" }, -] -sdist = { url = "https://files.pythonhosted.org/packages/c4/fc/eb9bc06130e8bbda6a616e1b80a7aa127681c448d6b49806f61db2670b61/huggingface_hub-1.4.1.tar.gz", hash = "sha256:b41131ec35e631e7383ab26d6146b8d8972abc8b6309b963b306fbcca87f5ed5", size = 642156, upload-time = "2026-02-06T09:20:03.013Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/d5/ae/2f6d96b4e6c5478d87d606a1934b5d436c4a2bce6bb7c6fdece891c128e3/huggingface_hub-1.4.1-py3-none-any.whl", hash = "sha256:9931d075fb7a79af5abc487106414ec5fba2c0ae86104c0c62fd6cae38873d18", size = 553326, upload-time = "2026-02-06T09:20:00.728Z" }, + { url = "https://files.pythonhosted.org/packages/31/22/859d8252dad9bc9adee34b52e62cde621ece07b042ccb2ab4da1be46695f/httpx2-2.5.0-py3-none-any.whl", hash = "sha256:3d2d4d9cf4b61f1a1f46a95947cfdb47e80cb56a2f91c6256ac8f58e4891df41", size = 76652, upload-time = "2026-06-25T14:16:55.23Z" }, ] [[package]] @@ -2491,15 +1882,6 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/67/8a/a342b2f0251f3dac4ca17618265d93bf244a2a4d089126e81e4c1056ac50/jiter-0.13.0-graalpy312-graalpy250_312_native-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7bb00b6d26db67a05fe3e12c76edc75f32077fb51deed13822dc648fa373bc19", size = 343768, upload-time = "2026-02-02T12:37:55.055Z" }, ] -[[package]] -name = "jmespath" -version = "1.1.0" -source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/d3/59/322338183ecda247fb5d1763a6cbe46eff7222eaeebafd9fa65d4bf5cb11/jmespath-1.1.0.tar.gz", hash = "sha256:472c87d80f36026ae83c6ddd0f1d05d4e510134ed462851fd5f754c8c3cbb88d", size = 27377, upload-time = "2026-01-22T16:35:26.279Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/14/2f/967ba146e6d58cf6a652da73885f52fc68001525b4197effc174321d70b4/jmespath-1.1.0-py3-none-any.whl", hash = "sha256:a5663118de4908c91729bea0acadca56526eb2698e83de10cd116ae0f4e97c64", size = 20419, upload-time = "2026-01-22T16:35:24.919Z" }, -] - [[package]] name = "joserfc" version = "1.6.8" @@ -2512,24 +1894,6 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/98/8c/5cdce2cf3ce8155849baf9a5e2ce77e89dc87ec3bdb38259e5d85fbc45bd/joserfc-1.6.8-py3-none-any.whl", hash = "sha256:22fb31a69094a5e6f44632002a9df2c30c941fc6c8ce1b037e92c03de954cf9f", size = 70927, upload-time = "2026-05-27T03:22:35.796Z" }, ] -[[package]] -name = "jsonpath-python" -version = "1.1.5" -source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/2d/db/2f4ecc24da35c6142b39c353d5b7c16eef955cc94b35a48d3fa47996d7c3/jsonpath_python-1.1.5.tar.gz", hash = "sha256:ceea2efd9e56add09330a2c9631ea3d55297b9619348c1055e5bfb9cb0b8c538", size = 87352, upload-time = "2026-03-17T06:16:40.597Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/28/50/1a313fb700526b134c71eb8a225d8b83be0385dbb0204337b4379c698cef/jsonpath_python-1.1.5-py3-none-any.whl", hash = "sha256:a60315404d70a65e76c9a782c84e50600480221d94a58af47b7b4d437351cb4b", size = 14090, upload-time = "2026-03-17T06:16:39.152Z" }, -] - -[[package]] -name = "jsonref" -version = "1.1.0" -source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/aa/0d/c1f3277e90ccdb50d33ed5ba1ec5b3f0a242ed8c1b1a85d3afeb68464dca/jsonref-1.1.0.tar.gz", hash = "sha256:32fe8e1d85af0fdefbebce950af85590b22b60f9e95443176adbde4e1ecea552", size = 8814, upload-time = "2023-01-16T16:10:04.455Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/0c/ec/e1db9922bceb168197a558a2b8c03a7963f1afe93517ddd3cf99f202f996/jsonref-1.1.0-py3-none-any.whl", hash = "sha256:590dc7773df6c21cbf948b5dac07a72a251db28b0238ceecce0a2abfa8ec30a9", size = 9425, upload-time = "2023-01-16T16:10:02.255Z" }, -] - [[package]] name = "jsonschema" version = "4.26.0" @@ -2545,21 +1909,6 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/69/90/f63fb5873511e014207a475e2bb4e8b2e570d655b00ac19a9a0ca0a385ee/jsonschema-4.26.0-py3-none-any.whl", hash = "sha256:d489f15263b8d200f8387e64b4c3a75f06629559fb73deb8fdfb525f2dab50ce", size = 90630, upload-time = "2026-01-07T13:41:05.306Z" }, ] -[[package]] -name = "jsonschema-path" -version = "0.3.4" -source = { registry = "https://pypi.org/simple" } -dependencies = [ - { name = "pathable" }, - { name = "pyyaml" }, - { name = "referencing" }, - { name = "requests" }, -] -sdist = { url = "https://files.pythonhosted.org/packages/6e/45/41ebc679c2a4fced6a722f624c18d658dee42612b83ea24c1caf7c0eb3a8/jsonschema_path-0.3.4.tar.gz", hash = "sha256:8365356039f16cc65fddffafda5f58766e34bebab7d6d105616ab52bc4297001", size = 11159, upload-time = "2025-01-24T14:33:16.547Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/cb/58/3485da8cb93d2f393bce453adeef16896751f14ba3e2024bc21dc9597646/jsonschema_path-0.3.4-py3-none-any.whl", hash = "sha256:f502191fdc2b22050f9a81c9237be9d27145b9001c55842bece5e94e382e52f8", size = 14810, upload-time = "2025-01-24T14:33:14.652Z" }, -] - [[package]] name = "jsonschema-specifications" version = "2025.9.1" @@ -2883,25 +2232,6 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/2c/19/04f9b178c2d8a15b076c8b5140708fa6ffc5601fb6f1e975537072df5b2a/mergedeep-1.3.4-py3-none-any.whl", hash = "sha256:70775750742b25c0d8f36c55aed03d24c3384d17c951b3175d898bd778ef0307", size = 6354, upload-time = "2021-02-05T18:55:29.583Z" }, ] -[[package]] -name = "mistralai" -version = "2.4.1" -source = { registry = "https://pypi.org/simple" } -dependencies = [ - { name = "eval-type-backport" }, - { name = "httpx" }, - { name = "jsonpath-python" }, - { name = "opentelemetry-api" }, - { name = "opentelemetry-semantic-conventions" }, - { name = "pydantic" }, - { name = "python-dateutil" }, - { name = "typing-inspection" }, -] -sdist = { url = "https://files.pythonhosted.org/packages/88/e2/fb226b81fdfba702a59ad50635fd9e72d6321cb92b2b4e76adfef7fe1903/mistralai-2.4.1.tar.gz", hash = "sha256:9aad8270b3085e84a1a88b07a7824aa6b97ee8470baee1a57f23a3f2b17b286c", size = 413448, upload-time = "2026-04-21T13:44:59.563Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/0c/03/1ab3de0cb123c0b5e4df612bacce65a5ad4c4f322dcdf95db2786092ea6d/mistralai-2.4.1-py3-none-any.whl", hash = "sha256:a535ac7fafec368ce66e7ecd22380489ce04d8b1466a35a20905c45e020f660e", size = 975691, upload-time = "2026-04-21T13:44:57.586Z" }, -] - [[package]] name = "mkdocs" version = "1.6.1" @@ -3000,144 +2330,6 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/a4/8e/469e5a4a2f5855992e425f3cb33804cc07bf18d48f2db061aec61ce50270/more_itertools-10.8.0-py3-none-any.whl", hash = "sha256:52d4362373dcf7c52546bc4af9a86ee7c4579df9a8dc268be0a2f949d376cc9b", size = 69667, upload-time = "2025-09-02T15:23:09.635Z" }, ] -[[package]] -name = "multidict" -version = "6.7.1" -source = { registry = "https://pypi.org/simple" } -dependencies = [ - { name = "typing-extensions", marker = "python_full_version < '3.11'" }, -] -sdist = { url = "https://files.pythonhosted.org/packages/1a/c2/c2d94cbe6ac1753f3fc980da97b3d930efe1da3af3c9f5125354436c073d/multidict-6.7.1.tar.gz", hash = "sha256:ec6652a1bee61c53a3e5776b6049172c53b6aaba34f18c9ad04f82712bac623d", size = 102010, upload-time = "2026-01-26T02:46:45.979Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/84/0b/19348d4c98980c4851d2f943f8ebafdece2ae7ef737adcfa5994ce8e5f10/multidict-6.7.1-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:c93c3db7ea657dd4637d57e74ab73de31bccefe144d3d4ce370052035bc85fb5", size = 77176, upload-time = "2026-01-26T02:42:59.784Z" }, - { url = "https://files.pythonhosted.org/packages/ef/04/9de3f8077852e3d438215c81e9b691244532d2e05b4270e89ce67b7d103c/multidict-6.7.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:974e72a2474600827abaeda71af0c53d9ebbc3c2eb7da37b37d7829ae31232d8", size = 44996, upload-time = "2026-01-26T02:43:01.674Z" }, - { url = "https://files.pythonhosted.org/packages/31/5c/08c7f7fe311f32e83f7621cd3f99d805f45519cd06fafb247628b861da7d/multidict-6.7.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:cdea2e7b2456cfb6694fb113066fd0ec7ea4d67e3a35e1f4cbeea0b448bf5872", size = 44631, upload-time = "2026-01-26T02:43:03.169Z" }, - { url = "https://files.pythonhosted.org/packages/b7/7f/0e3b1390ae772f27501199996b94b52ceeb64fe6f9120a32c6c3f6b781be/multidict-6.7.1-cp310-cp310-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:17207077e29342fdc2c9a82e4b306f1127bf1ea91f8b71e02d4798a70bb99991", size = 242561, upload-time = "2026-01-26T02:43:04.733Z" }, - { url = "https://files.pythonhosted.org/packages/dd/f4/8719f4f167586af317b69dd3e90f913416c91ca610cac79a45c53f590312/multidict-6.7.1-cp310-cp310-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:d4f49cb5661344764e4c7c7973e92a47a59b8fc19b6523649ec9dc4960e58a03", size = 242223, upload-time = "2026-01-26T02:43:06.695Z" }, - { url = "https://files.pythonhosted.org/packages/47/ab/7c36164cce64a6ad19c6d9a85377b7178ecf3b89f8fd589c73381a5eedfd/multidict-6.7.1-cp310-cp310-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:a9fc4caa29e2e6ae408d1c450ac8bf19892c5fca83ee634ecd88a53332c59981", size = 222322, upload-time = "2026-01-26T02:43:08.472Z" }, - { url = "https://files.pythonhosted.org/packages/f5/79/a25add6fb38035b5337bc5734f296d9afc99163403bbcf56d4170f97eb62/multidict-6.7.1-cp310-cp310-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:c5f0c21549ab432b57dcc82130f388d84ad8179824cc3f223d5e7cfbfd4143f6", size = 254005, upload-time = "2026-01-26T02:43:10.127Z" }, - { url = "https://files.pythonhosted.org/packages/4a/7b/64a87cf98e12f756fc8bd444b001232ffff2be37288f018ad0d3f0aae931/multidict-6.7.1-cp310-cp310-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:7dfb78d966b2c906ae1d28ccf6e6712a3cd04407ee5088cd276fe8cb42186190", size = 251173, upload-time = "2026-01-26T02:43:11.731Z" }, - { url = "https://files.pythonhosted.org/packages/4b/ac/b605473de2bb404e742f2cc3583d12aedb2352a70e49ae8fce455b50c5aa/multidict-6.7.1-cp310-cp310-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:9b0d9b91d1aa44db9c1f1ecd0d9d2ae610b2f4f856448664e01a3b35899f3f92", size = 243273, upload-time = "2026-01-26T02:43:13.063Z" }, - { url = "https://files.pythonhosted.org/packages/03/65/11492d6a0e259783720f3bc1d9ea55579a76f1407e31ed44045c99542004/multidict-6.7.1-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:dd96c01a9dcd4889dcfcf9eb5544ca0c77603f239e3ffab0524ec17aea9a93ee", size = 238956, upload-time = "2026-01-26T02:43:14.843Z" }, - { url = "https://files.pythonhosted.org/packages/5f/a7/7ee591302af64e7c196fb63fe856c788993c1372df765102bd0448e7e165/multidict-6.7.1-cp310-cp310-musllinux_1_2_armv7l.whl", hash = "sha256:067343c68cd6612d375710f895337b3a98a033c94f14b9a99eff902f205424e2", size = 233477, upload-time = "2026-01-26T02:43:16.025Z" }, - { url = "https://files.pythonhosted.org/packages/9c/99/c109962d58756c35fd9992fed7f2355303846ea2ff054bb5f5e9d6b888de/multidict-6.7.1-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:5884a04f4ff56c6120f6ccf703bdeb8b5079d808ba604d4d53aec0d55dc33568", size = 243615, upload-time = "2026-01-26T02:43:17.84Z" }, - { url = "https://files.pythonhosted.org/packages/d5/5f/1973e7c771c86e93dcfe1c9cc55a5481b610f6614acfc28c0d326fe6bfad/multidict-6.7.1-cp310-cp310-musllinux_1_2_ppc64le.whl", hash = "sha256:8affcf1c98b82bc901702eb73b6947a1bfa170823c153fe8a47b5f5f02e48e40", size = 249930, upload-time = "2026-01-26T02:43:19.06Z" }, - { url = "https://files.pythonhosted.org/packages/5d/a5/f170fc2268c3243853580203378cd522446b2df632061e0a5409817854c7/multidict-6.7.1-cp310-cp310-musllinux_1_2_s390x.whl", hash = "sha256:0d17522c37d03e85c8098ec8431636309b2682cf12e58f4dbc76121fb50e4962", size = 243807, upload-time = "2026-01-26T02:43:20.286Z" }, - { url = "https://files.pythonhosted.org/packages/de/01/73856fab6d125e5bc652c3986b90e8699a95e84b48d72f39ade6c0e74a8c/multidict-6.7.1-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:24c0cf81544ca5e17cfcb6e482e7a82cd475925242b308b890c9452a074d4505", size = 239103, upload-time = "2026-01-26T02:43:21.508Z" }, - { url = "https://files.pythonhosted.org/packages/e7/46/f1220bd9944d8aa40d8ccff100eeeee19b505b857b6f603d6078cb5315b0/multidict-6.7.1-cp310-cp310-win32.whl", hash = "sha256:d82dd730a95e6643802f4454b8fdecdf08667881a9c5670db85bc5a56693f122", size = 41416, upload-time = "2026-01-26T02:43:22.703Z" }, - { url = "https://files.pythonhosted.org/packages/68/00/9b38e272a770303692fc406c36e1a4c740f401522d5787691eb38a8925a8/multidict-6.7.1-cp310-cp310-win_amd64.whl", hash = "sha256:cf37cbe5ced48d417ba045aca1b21bafca67489452debcde94778a576666a1df", size = 46022, upload-time = "2026-01-26T02:43:23.77Z" }, - { url = "https://files.pythonhosted.org/packages/64/65/d8d42490c02ee07b6bbe00f7190d70bb4738b3cce7629aaf9f213ef730dd/multidict-6.7.1-cp310-cp310-win_arm64.whl", hash = "sha256:59bc83d3f66b41dac1e7460aac1d196edc70c9ba3094965c467715a70ecb46db", size = 43238, upload-time = "2026-01-26T02:43:24.882Z" }, - { url = "https://files.pythonhosted.org/packages/ce/f1/a90635c4f88fb913fbf4ce660b83b7445b7a02615bda034b2f8eb38fd597/multidict-6.7.1-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:7ff981b266af91d7b4b3793ca3382e53229088d193a85dfad6f5f4c27fc73e5d", size = 76626, upload-time = "2026-01-26T02:43:26.485Z" }, - { url = "https://files.pythonhosted.org/packages/a6/9b/267e64eaf6fc637a15b35f5de31a566634a2740f97d8d094a69d34f524a4/multidict-6.7.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:844c5bca0b5444adb44a623fb0a1310c2f4cd41f402126bb269cd44c9b3f3e1e", size = 44706, upload-time = "2026-01-26T02:43:27.607Z" }, - { url = "https://files.pythonhosted.org/packages/dd/a4/d45caf2b97b035c57267791ecfaafbd59c68212004b3842830954bb4b02e/multidict-6.7.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:f2a0a924d4c2e9afcd7ec64f9de35fcd96915149b2216e1cb2c10a56df483855", size = 44356, upload-time = "2026-01-26T02:43:28.661Z" }, - { url = "https://files.pythonhosted.org/packages/fd/d2/0a36c8473f0cbaeadd5db6c8b72d15bbceeec275807772bfcd059bef487d/multidict-6.7.1-cp311-cp311-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:8be1802715a8e892c784c0197c2ace276ea52702a0ede98b6310c8f255a5afb3", size = 244355, upload-time = "2026-01-26T02:43:31.165Z" }, - { url = "https://files.pythonhosted.org/packages/5d/16/8c65be997fd7dd311b7d39c7b6e71a0cb449bad093761481eccbbe4b42a2/multidict-6.7.1-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:2e2d2ed645ea29f31c4c7ea1552fcfd7cb7ba656e1eafd4134a6620c9f5fdd9e", size = 246433, upload-time = "2026-01-26T02:43:32.581Z" }, - { url = "https://files.pythonhosted.org/packages/01/fb/4dbd7e848d2799c6a026ec88ad39cf2b8416aa167fcc903baa55ecaa045c/multidict-6.7.1-cp311-cp311-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:95922cee9a778659e91db6497596435777bd25ed116701a4c034f8e46544955a", size = 225376, upload-time = "2026-01-26T02:43:34.417Z" }, - { url = "https://files.pythonhosted.org/packages/b6/8a/4a3a6341eac3830f6053062f8fbc9a9e54407c80755b3f05bc427295c2d0/multidict-6.7.1-cp311-cp311-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:6b83cabdc375ffaaa15edd97eb7c0c672ad788e2687004990074d7d6c9b140c8", size = 257365, upload-time = "2026-01-26T02:43:35.741Z" }, - { url = "https://files.pythonhosted.org/packages/f7/a2/dd575a69c1aa206e12d27d0770cdf9b92434b48a9ef0cd0d1afdecaa93c4/multidict-6.7.1-cp311-cp311-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:38fb49540705369bab8484db0689d86c0a33a0a9f2c1b197f506b71b4b6c19b0", size = 254747, upload-time = "2026-01-26T02:43:36.976Z" }, - { url = "https://files.pythonhosted.org/packages/5a/56/21b27c560c13822ed93133f08aa6372c53a8e067f11fbed37b4adcdac922/multidict-6.7.1-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:439cbebd499f92e9aa6793016a8acaa161dfa749ae86d20960189f5398a19144", size = 246293, upload-time = "2026-01-26T02:43:38.258Z" }, - { url = "https://files.pythonhosted.org/packages/5a/a4/23466059dc3854763423d0ad6c0f3683a379d97673b1b89ec33826e46728/multidict-6.7.1-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:6d3bc717b6fe763b8be3f2bee2701d3c8eb1b2a8ae9f60910f1b2860c82b6c49", size = 242962, upload-time = "2026-01-26T02:43:40.034Z" }, - { url = "https://files.pythonhosted.org/packages/1f/67/51dd754a3524d685958001e8fa20a0f5f90a6a856e0a9dcabff69be3dbb7/multidict-6.7.1-cp311-cp311-musllinux_1_2_armv7l.whl", hash = "sha256:619e5a1ac57986dbfec9f0b301d865dddf763696435e2962f6d9cf2fdff2bb71", size = 237360, upload-time = "2026-01-26T02:43:41.752Z" }, - { url = "https://files.pythonhosted.org/packages/64/3f/036dfc8c174934d4b55d86ff4f978e558b0e585cef70cfc1ad01adc6bf18/multidict-6.7.1-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:0b38ebffd9be37c1170d33bc0f36f4f262e0a09bc1aac1c34c7aa51a7293f0b3", size = 245940, upload-time = "2026-01-26T02:43:43.042Z" }, - { url = "https://files.pythonhosted.org/packages/3d/20/6214d3c105928ebc353a1c644a6ef1408bc5794fcb4f170bb524a3c16311/multidict-6.7.1-cp311-cp311-musllinux_1_2_ppc64le.whl", hash = "sha256:10ae39c9cfe6adedcdb764f5e8411d4a92b055e35573a2eaa88d3323289ef93c", size = 253502, upload-time = "2026-01-26T02:43:44.371Z" }, - { url = "https://files.pythonhosted.org/packages/b1/e2/c653bc4ae1be70a0f836b82172d643fcf1dade042ba2676ab08ec08bff0f/multidict-6.7.1-cp311-cp311-musllinux_1_2_s390x.whl", hash = "sha256:25167cc263257660290fba06b9318d2026e3c910be240a146e1f66dd114af2b0", size = 247065, upload-time = "2026-01-26T02:43:45.745Z" }, - { url = "https://files.pythonhosted.org/packages/c8/11/a854b4154cd3bd8b1fd375e8a8ca9d73be37610c361543d56f764109509b/multidict-6.7.1-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:128441d052254f42989ef98b7b6a6ecb1e6f708aa962c7984235316db59f50fa", size = 241870, upload-time = "2026-01-26T02:43:47.054Z" }, - { url = "https://files.pythonhosted.org/packages/13/bf/9676c0392309b5fdae322333d22a829715b570edb9baa8016a517b55b558/multidict-6.7.1-cp311-cp311-win32.whl", hash = "sha256:d62b7f64ffde3b99d06b707a280db04fb3855b55f5a06df387236051d0668f4a", size = 41302, upload-time = "2026-01-26T02:43:48.753Z" }, - { url = "https://files.pythonhosted.org/packages/c9/68/f16a3a8ba6f7b6dc92a1f19669c0810bd2c43fc5a02da13b1cbf8e253845/multidict-6.7.1-cp311-cp311-win_amd64.whl", hash = "sha256:bdbf9f3b332abd0cdb306e7c2113818ab1e922dc84b8f8fd06ec89ed2a19ab8b", size = 45981, upload-time = "2026-01-26T02:43:49.921Z" }, - { url = "https://files.pythonhosted.org/packages/ac/ad/9dd5305253fa00cd3c7555dbef69d5bf4133debc53b87ab8d6a44d411665/multidict-6.7.1-cp311-cp311-win_arm64.whl", hash = "sha256:b8c990b037d2fff2f4e33d3f21b9b531c5745b33a49a7d6dbe7a177266af44f6", size = 43159, upload-time = "2026-01-26T02:43:51.635Z" }, - { url = "https://files.pythonhosted.org/packages/8d/9c/f20e0e2cf80e4b2e4b1c365bf5fe104ee633c751a724246262db8f1a0b13/multidict-6.7.1-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:a90f75c956e32891a4eda3639ce6dd86e87105271f43d43442a3aedf3cddf172", size = 76893, upload-time = "2026-01-26T02:43:52.754Z" }, - { url = "https://files.pythonhosted.org/packages/fe/cf/18ef143a81610136d3da8193da9d80bfe1cb548a1e2d1c775f26b23d024a/multidict-6.7.1-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:3fccb473e87eaa1382689053e4a4618e7ba7b9b9b8d6adf2027ee474597128cd", size = 45456, upload-time = "2026-01-26T02:43:53.893Z" }, - { url = "https://files.pythonhosted.org/packages/a9/65/1caac9d4cd32e8433908683446eebc953e82d22b03d10d41a5f0fefe991b/multidict-6.7.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:b0fa96985700739c4c7853a43c0b3e169360d6855780021bfc6d0f1ce7c123e7", size = 43872, upload-time = "2026-01-26T02:43:55.041Z" }, - { url = "https://files.pythonhosted.org/packages/cf/3b/d6bd75dc4f3ff7c73766e04e705b00ed6dbbaccf670d9e05a12b006f5a21/multidict-6.7.1-cp312-cp312-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:cb2a55f408c3043e42b40cc8eecd575afa27b7e0b956dfb190de0f8499a57a53", size = 251018, upload-time = "2026-01-26T02:43:56.198Z" }, - { url = "https://files.pythonhosted.org/packages/fd/80/c959c5933adedb9ac15152e4067c702a808ea183a8b64cf8f31af8ad3155/multidict-6.7.1-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:eb0ce7b2a32d09892b3dd6cc44877a0d02a33241fafca5f25c8b6b62374f8b75", size = 258883, upload-time = "2026-01-26T02:43:57.499Z" }, - { url = "https://files.pythonhosted.org/packages/86/85/7ed40adafea3d4f1c8b916e3b5cc3a8e07dfcdcb9cd72800f4ed3ca1b387/multidict-6.7.1-cp312-cp312-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:c3a32d23520ee37bf327d1e1a656fec76a2edd5c038bf43eddfa0572ec49c60b", size = 242413, upload-time = "2026-01-26T02:43:58.755Z" }, - { url = "https://files.pythonhosted.org/packages/d2/57/b8565ff533e48595503c785f8361ff9a4fde4d67de25c207cd0ba3befd03/multidict-6.7.1-cp312-cp312-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:9c90fed18bffc0189ba814749fdcc102b536e83a9f738a9003e569acd540a733", size = 268404, upload-time = "2026-01-26T02:44:00.216Z" }, - { url = "https://files.pythonhosted.org/packages/e0/50/9810c5c29350f7258180dfdcb2e52783a0632862eb334c4896ac717cebcb/multidict-6.7.1-cp312-cp312-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:da62917e6076f512daccfbbde27f46fed1c98fee202f0559adec8ee0de67f71a", size = 269456, upload-time = "2026-01-26T02:44:02.202Z" }, - { url = "https://files.pythonhosted.org/packages/f3/8d/5e5be3ced1d12966fefb5c4ea3b2a5b480afcea36406559442c6e31d4a48/multidict-6.7.1-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:bfde23ef6ed9db7eaee6c37dcec08524cb43903c60b285b172b6c094711b3961", size = 256322, upload-time = "2026-01-26T02:44:03.56Z" }, - { url = "https://files.pythonhosted.org/packages/31/6e/d8a26d81ac166a5592782d208dd90dfdc0a7a218adaa52b45a672b46c122/multidict-6.7.1-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:3758692429e4e32f1ba0df23219cd0b4fc0a52f476726fff9337d1a57676a582", size = 253955, upload-time = "2026-01-26T02:44:04.845Z" }, - { url = "https://files.pythonhosted.org/packages/59/4c/7c672c8aad41534ba619bcd4ade7a0dc87ed6b8b5c06149b85d3dd03f0cd/multidict-6.7.1-cp312-cp312-musllinux_1_2_armv7l.whl", hash = "sha256:398c1478926eca669f2fd6a5856b6de9c0acf23a2cb59a14c0ba5844fa38077e", size = 251254, upload-time = "2026-01-26T02:44:06.133Z" }, - { url = "https://files.pythonhosted.org/packages/7b/bd/84c24de512cbafbdbc39439f74e967f19570ce7924e3007174a29c348916/multidict-6.7.1-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:c102791b1c4f3ab36ce4101154549105a53dc828f016356b3e3bcae2e3a039d3", size = 252059, upload-time = "2026-01-26T02:44:07.518Z" }, - { url = "https://files.pythonhosted.org/packages/fa/ba/f5449385510825b73d01c2d4087bf6d2fccc20a2d42ac34df93191d3dd03/multidict-6.7.1-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:a088b62bd733e2ad12c50dad01b7d0166c30287c166e137433d3b410add807a6", size = 263588, upload-time = "2026-01-26T02:44:09.382Z" }, - { url = "https://files.pythonhosted.org/packages/d7/11/afc7c677f68f75c84a69fe37184f0f82fce13ce4b92f49f3db280b7e92b3/multidict-6.7.1-cp312-cp312-musllinux_1_2_s390x.whl", hash = "sha256:3d51ff4785d58d3f6c91bdbffcb5e1f7ddfda557727043aa20d20ec4f65e324a", size = 259642, upload-time = "2026-01-26T02:44:10.73Z" }, - { url = "https://files.pythonhosted.org/packages/2b/17/ebb9644da78c4ab36403739e0e6e0e30ebb135b9caf3440825001a0bddcb/multidict-6.7.1-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:fc5907494fccf3e7d3f94f95c91d6336b092b5fc83811720fae5e2765890dfba", size = 251377, upload-time = "2026-01-26T02:44:12.042Z" }, - { url = "https://files.pythonhosted.org/packages/ca/a4/840f5b97339e27846c46307f2530a2805d9d537d8b8bd416af031cad7fa0/multidict-6.7.1-cp312-cp312-win32.whl", hash = "sha256:28ca5ce2fd9716631133d0e9a9b9a745ad7f60bac2bccafb56aa380fc0b6c511", size = 41887, upload-time = "2026-01-26T02:44:14.245Z" }, - { url = "https://files.pythonhosted.org/packages/80/31/0b2517913687895f5904325c2069d6a3b78f66cc641a86a2baf75a05dcbb/multidict-6.7.1-cp312-cp312-win_amd64.whl", hash = "sha256:fcee94dfbd638784645b066074b338bc9cc155d4b4bffa4adce1615c5a426c19", size = 46053, upload-time = "2026-01-26T02:44:15.371Z" }, - { url = "https://files.pythonhosted.org/packages/0c/5b/aba28e4ee4006ae4c7df8d327d31025d760ffa992ea23812a601d226e682/multidict-6.7.1-cp312-cp312-win_arm64.whl", hash = "sha256:ba0a9fb644d0c1a2194cf7ffb043bd852cea63a57f66fbd33959f7dae18517bf", size = 43307, upload-time = "2026-01-26T02:44:16.852Z" }, - { url = "https://files.pythonhosted.org/packages/f2/22/929c141d6c0dba87d3e1d38fbdf1ba8baba86b7776469f2bc2d3227a1e67/multidict-6.7.1-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:2b41f5fed0ed563624f1c17630cb9941cf2309d4df00e494b551b5f3e3d67a23", size = 76174, upload-time = "2026-01-26T02:44:18.509Z" }, - { url = "https://files.pythonhosted.org/packages/c7/75/bc704ae15fee974f8fccd871305e254754167dce5f9e42d88a2def741a1d/multidict-6.7.1-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:84e61e3af5463c19b67ced91f6c634effb89ef8bfc5ca0267f954451ed4bb6a2", size = 45116, upload-time = "2026-01-26T02:44:19.745Z" }, - { url = "https://files.pythonhosted.org/packages/79/76/55cd7186f498ed080a18440c9013011eb548f77ae1b297206d030eb1180a/multidict-6.7.1-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:935434b9853c7c112eee7ac891bc4cb86455aa631269ae35442cb316790c1445", size = 43524, upload-time = "2026-01-26T02:44:21.571Z" }, - { url = "https://files.pythonhosted.org/packages/e9/3c/414842ef8d5a1628d68edee29ba0e5bcf235dbfb3ccd3ea303a7fe8c72ff/multidict-6.7.1-cp313-cp313-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:432feb25a1cb67fe82a9680b4d65fb542e4635cb3166cd9c01560651ad60f177", size = 249368, upload-time = "2026-01-26T02:44:22.803Z" }, - { url = "https://files.pythonhosted.org/packages/f6/32/befed7f74c458b4a525e60519fe8d87eef72bb1e99924fa2b0f9d97a221e/multidict-6.7.1-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:e82d14e3c948952a1a85503817e038cba5905a3352de76b9a465075d072fba23", size = 256952, upload-time = "2026-01-26T02:44:24.306Z" }, - { url = "https://files.pythonhosted.org/packages/03/d6/c878a44ba877f366630c860fdf74bfb203c33778f12b6ac274936853c451/multidict-6.7.1-cp313-cp313-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:4cfb48c6ea66c83bcaaf7e4dfa7ec1b6bbcf751b7db85a328902796dfde4c060", size = 240317, upload-time = "2026-01-26T02:44:25.772Z" }, - { url = "https://files.pythonhosted.org/packages/68/49/57421b4d7ad2e9e60e25922b08ceb37e077b90444bde6ead629095327a6f/multidict-6.7.1-cp313-cp313-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:1d540e51b7e8e170174555edecddbd5538105443754539193e3e1061864d444d", size = 267132, upload-time = "2026-01-26T02:44:27.648Z" }, - { url = "https://files.pythonhosted.org/packages/b7/fe/ec0edd52ddbcea2a2e89e174f0206444a61440b40f39704e64dc807a70bd/multidict-6.7.1-cp313-cp313-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:273d23f4b40f3dce4d6c8a821c741a86dec62cded82e1175ba3d99be128147ed", size = 268140, upload-time = "2026-01-26T02:44:29.588Z" }, - { url = "https://files.pythonhosted.org/packages/b0/73/6e1b01cbeb458807aa0831742232dbdd1fa92bfa33f52a3f176b4ff3dc11/multidict-6.7.1-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:9d624335fd4fa1c08a53f8b4be7676ebde19cd092b3895c421045ca87895b429", size = 254277, upload-time = "2026-01-26T02:44:30.902Z" }, - { url = "https://files.pythonhosted.org/packages/6a/b2/5fb8c124d7561a4974c342bc8c778b471ebbeb3cc17df696f034a7e9afe7/multidict-6.7.1-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:12fad252f8b267cc75b66e8fc51b3079604e8d43a75428ffe193cd9e2195dfd6", size = 252291, upload-time = "2026-01-26T02:44:32.31Z" }, - { url = "https://files.pythonhosted.org/packages/5a/96/51d4e4e06bcce92577fcd488e22600bd38e4fd59c20cb49434d054903bd2/multidict-6.7.1-cp313-cp313-musllinux_1_2_armv7l.whl", hash = "sha256:03ede2a6ffbe8ef936b92cb4529f27f42be7f56afcdab5ab739cd5f27fb1cbf9", size = 250156, upload-time = "2026-01-26T02:44:33.734Z" }, - { url = "https://files.pythonhosted.org/packages/db/6b/420e173eec5fba721a50e2a9f89eda89d9c98fded1124f8d5c675f7a0c0f/multidict-6.7.1-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:90efbcf47dbe33dcf643a1e400d67d59abeac5db07dc3f27d6bdeae497a2198c", size = 249742, upload-time = "2026-01-26T02:44:35.222Z" }, - { url = "https://files.pythonhosted.org/packages/44/a3/ec5b5bd98f306bc2aa297b8c6f11a46714a56b1e6ef5ebda50a4f5d7c5fb/multidict-6.7.1-cp313-cp313-musllinux_1_2_ppc64le.whl", hash = "sha256:5c4b9bfc148f5a91be9244d6264c53035c8a0dcd2f51f1c3c6e30e30ebaa1c84", size = 262221, upload-time = "2026-01-26T02:44:36.604Z" }, - { url = "https://files.pythonhosted.org/packages/cd/f7/e8c0d0da0cd1e28d10e624604e1a36bcc3353aaebdfdc3a43c72bc683a12/multidict-6.7.1-cp313-cp313-musllinux_1_2_s390x.whl", hash = "sha256:401c5a650f3add2472d1d288c26deebc540f99e2fb83e9525007a74cd2116f1d", size = 258664, upload-time = "2026-01-26T02:44:38.008Z" }, - { url = "https://files.pythonhosted.org/packages/52/da/151a44e8016dd33feed44f730bd856a66257c1ee7aed4f44b649fb7edeb3/multidict-6.7.1-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:97891f3b1b3ffbded884e2916cacf3c6fc87b66bb0dde46f7357404750559f33", size = 249490, upload-time = "2026-01-26T02:44:39.386Z" }, - { url = "https://files.pythonhosted.org/packages/87/af/a3b86bf9630b732897f6fc3f4c4714b90aa4361983ccbdcd6c0339b21b0c/multidict-6.7.1-cp313-cp313-win32.whl", hash = "sha256:e1c5988359516095535c4301af38d8a8838534158f649c05dd1050222321bcb3", size = 41695, upload-time = "2026-01-26T02:44:41.318Z" }, - { url = "https://files.pythonhosted.org/packages/b2/35/e994121b0e90e46134673422dd564623f93304614f5d11886b1b3e06f503/multidict-6.7.1-cp313-cp313-win_amd64.whl", hash = "sha256:960c83bf01a95b12b08fd54324a4eb1d5b52c88932b5cba5d6e712bb3ed12eb5", size = 45884, upload-time = "2026-01-26T02:44:42.488Z" }, - { url = "https://files.pythonhosted.org/packages/ca/61/42d3e5dbf661242a69c97ea363f2d7b46c567da8eadef8890022be6e2ab0/multidict-6.7.1-cp313-cp313-win_arm64.whl", hash = "sha256:563fe25c678aaba333d5399408f5ec3c383ca5b663e7f774dd179a520b8144df", size = 43122, upload-time = "2026-01-26T02:44:43.664Z" }, - { url = "https://files.pythonhosted.org/packages/6d/b3/e6b21c6c4f314bb956016b0b3ef2162590a529b84cb831c257519e7fde44/multidict-6.7.1-cp313-cp313t-macosx_10_13_universal2.whl", hash = "sha256:c76c4bec1538375dad9d452d246ca5368ad6e1c9039dadcf007ae59c70619ea1", size = 83175, upload-time = "2026-01-26T02:44:44.894Z" }, - { url = "https://files.pythonhosted.org/packages/fb/76/23ecd2abfe0957b234f6c960f4ade497f55f2c16aeb684d4ecdbf1c95791/multidict-6.7.1-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:57b46b24b5d5ebcc978da4ec23a819a9402b4228b8a90d9c656422b4bdd8a963", size = 48460, upload-time = "2026-01-26T02:44:46.106Z" }, - { url = "https://files.pythonhosted.org/packages/c4/57/a0ed92b23f3a042c36bc4227b72b97eca803f5f1801c1ab77c8a212d455e/multidict-6.7.1-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:e954b24433c768ce78ab7929e84ccf3422e46deb45a4dc9f93438f8217fa2d34", size = 46930, upload-time = "2026-01-26T02:44:47.278Z" }, - { url = "https://files.pythonhosted.org/packages/b5/66/02ec7ace29162e447f6382c495dc95826bf931d3818799bbef11e8f7df1a/multidict-6.7.1-cp313-cp313t-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:3bd231490fa7217cc832528e1cd8752a96f0125ddd2b5749390f7c3ec8721b65", size = 242582, upload-time = "2026-01-26T02:44:48.604Z" }, - { url = "https://files.pythonhosted.org/packages/58/18/64f5a795e7677670e872673aca234162514696274597b3708b2c0d276cce/multidict-6.7.1-cp313-cp313t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:253282d70d67885a15c8a7716f3a73edf2d635793ceda8173b9ecc21f2fb8292", size = 250031, upload-time = "2026-01-26T02:44:50.544Z" }, - { url = "https://files.pythonhosted.org/packages/c8/ed/e192291dbbe51a8290c5686f482084d31bcd9d09af24f63358c3d42fd284/multidict-6.7.1-cp313-cp313t-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:0b4c48648d7649c9335cf1927a8b87fa692de3dcb15faa676c6a6f1f1aabda43", size = 228596, upload-time = "2026-01-26T02:44:51.951Z" }, - { url = "https://files.pythonhosted.org/packages/1e/7e/3562a15a60cf747397e7f2180b0a11dc0c38d9175a650e75fa1b4d325e15/multidict-6.7.1-cp313-cp313t-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:98bc624954ec4d2c7cb074b8eefc2b5d0ce7d482e410df446414355d158fe4ca", size = 257492, upload-time = "2026-01-26T02:44:53.902Z" }, - { url = "https://files.pythonhosted.org/packages/24/02/7d0f9eae92b5249bb50ac1595b295f10e263dd0078ebb55115c31e0eaccd/multidict-6.7.1-cp313-cp313t-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:1b99af4d9eec0b49927b4402bcbb58dea89d3e0db8806a4086117019939ad3dd", size = 255899, upload-time = "2026-01-26T02:44:55.316Z" }, - { url = "https://files.pythonhosted.org/packages/00/e3/9b60ed9e23e64c73a5cde95269ef1330678e9c6e34dd4eb6b431b85b5a10/multidict-6.7.1-cp313-cp313t-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:6aac4f16b472d5b7dc6f66a0d49dd57b0e0902090be16594dc9ebfd3d17c47e7", size = 247970, upload-time = "2026-01-26T02:44:56.783Z" }, - { url = "https://files.pythonhosted.org/packages/3e/06/538e58a63ed5cfb0bd4517e346b91da32fde409d839720f664e9a4ae4f9d/multidict-6.7.1-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:21f830fe223215dffd51f538e78c172ed7c7f60c9b96a2bf05c4848ad49921c3", size = 245060, upload-time = "2026-01-26T02:44:58.195Z" }, - { url = "https://files.pythonhosted.org/packages/b2/2f/d743a3045a97c895d401e9bd29aaa09b94f5cbdf1bd561609e5a6c431c70/multidict-6.7.1-cp313-cp313t-musllinux_1_2_armv7l.whl", hash = "sha256:f5dd81c45b05518b9aa4da4aa74e1c93d715efa234fd3e8a179df611cc85e5f4", size = 235888, upload-time = "2026-01-26T02:44:59.57Z" }, - { url = "https://files.pythonhosted.org/packages/38/83/5a325cac191ab28b63c52f14f1131f3b0a55ba3b9aa65a6d0bf2a9b921a0/multidict-6.7.1-cp313-cp313t-musllinux_1_2_i686.whl", hash = "sha256:eb304767bca2bb92fb9c5bd33cedc95baee5bb5f6c88e63706533a1c06ad08c8", size = 243554, upload-time = "2026-01-26T02:45:01.054Z" }, - { url = "https://files.pythonhosted.org/packages/20/1f/9d2327086bd15da2725ef6aae624208e2ef828ed99892b17f60c344e57ed/multidict-6.7.1-cp313-cp313t-musllinux_1_2_ppc64le.whl", hash = "sha256:c9035dde0f916702850ef66460bc4239d89d08df4d02023a5926e7446724212c", size = 252341, upload-time = "2026-01-26T02:45:02.484Z" }, - { url = "https://files.pythonhosted.org/packages/e8/2c/2a1aa0280cf579d0f6eed8ee5211c4f1730bd7e06c636ba2ee6aafda302e/multidict-6.7.1-cp313-cp313t-musllinux_1_2_s390x.whl", hash = "sha256:af959b9beeb66c822380f222f0e0a1889331597e81f1ded7f374f3ecb0fd6c52", size = 246391, upload-time = "2026-01-26T02:45:03.862Z" }, - { url = "https://files.pythonhosted.org/packages/e5/03/7ca022ffc36c5a3f6e03b179a5ceb829be9da5783e6fe395f347c0794680/multidict-6.7.1-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:41f2952231456154ee479651491e94118229844dd7226541788be783be2b5108", size = 243422, upload-time = "2026-01-26T02:45:05.296Z" }, - { url = "https://files.pythonhosted.org/packages/dc/1d/b31650eab6c5778aceed46ba735bd97f7c7d2f54b319fa916c0f96e7805b/multidict-6.7.1-cp313-cp313t-win32.whl", hash = "sha256:df9f19c28adcb40b6aae30bbaa1478c389efd50c28d541d76760199fc1037c32", size = 47770, upload-time = "2026-01-26T02:45:06.754Z" }, - { url = "https://files.pythonhosted.org/packages/ac/5b/2d2d1d522e51285bd61b1e20df8f47ae1a9d80839db0b24ea783b3832832/multidict-6.7.1-cp313-cp313t-win_amd64.whl", hash = "sha256:d54ecf9f301853f2c5e802da559604b3e95bb7a3b01a9c295c6ee591b9882de8", size = 53109, upload-time = "2026-01-26T02:45:08.044Z" }, - { url = "https://files.pythonhosted.org/packages/3d/a3/cc409ba012c83ca024a308516703cf339bdc4b696195644a7215a5164a24/multidict-6.7.1-cp313-cp313t-win_arm64.whl", hash = "sha256:5a37ca18e360377cfda1d62f5f382ff41f2b8c4ccb329ed974cc2e1643440118", size = 45573, upload-time = "2026-01-26T02:45:09.349Z" }, - { url = "https://files.pythonhosted.org/packages/91/cc/db74228a8be41884a567e88a62fd589a913708fcf180d029898c17a9a371/multidict-6.7.1-cp314-cp314-macosx_10_15_universal2.whl", hash = "sha256:8f333ec9c5eb1b7105e3b84b53141e66ca05a19a605368c55450b6ba208cb9ee", size = 75190, upload-time = "2026-01-26T02:45:10.651Z" }, - { url = "https://files.pythonhosted.org/packages/d5/22/492f2246bb5b534abd44804292e81eeaf835388901f0c574bac4eeec73c5/multidict-6.7.1-cp314-cp314-macosx_10_15_x86_64.whl", hash = "sha256:a407f13c188f804c759fc6a9f88286a565c242a76b27626594c133b82883b5c2", size = 44486, upload-time = "2026-01-26T02:45:11.938Z" }, - { url = "https://files.pythonhosted.org/packages/f1/4f/733c48f270565d78b4544f2baddc2fb2a245e5a8640254b12c36ac7ac68e/multidict-6.7.1-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:0e161ddf326db5577c3a4cc2d8648f81456e8a20d40415541587a71620d7a7d1", size = 43219, upload-time = "2026-01-26T02:45:14.346Z" }, - { url = "https://files.pythonhosted.org/packages/24/bb/2c0c2287963f4259c85e8bcbba9182ced8d7fca65c780c38e99e61629d11/multidict-6.7.1-cp314-cp314-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:1e3a8bb24342a8201d178c3b4984c26ba81a577c80d4d525727427460a50c22d", size = 245132, upload-time = "2026-01-26T02:45:15.712Z" }, - { url = "https://files.pythonhosted.org/packages/a7/f9/44d4b3064c65079d2467888794dea218d1601898ac50222ab8a9a8094460/multidict-6.7.1-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:97231140a50f5d447d3164f994b86a0bed7cd016e2682f8650d6a9158e14fd31", size = 252420, upload-time = "2026-01-26T02:45:17.293Z" }, - { url = "https://files.pythonhosted.org/packages/8b/13/78f7275e73fa17b24c9a51b0bd9d73ba64bb32d0ed51b02a746eb876abe7/multidict-6.7.1-cp314-cp314-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:6b10359683bd8806a200fd2909e7c8ca3a7b24ec1d8132e483d58e791d881048", size = 233510, upload-time = "2026-01-26T02:45:19.356Z" }, - { url = "https://files.pythonhosted.org/packages/4b/25/8167187f62ae3cbd52da7893f58cb036b47ea3fb67138787c76800158982/multidict-6.7.1-cp314-cp314-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:283ddac99f7ac25a4acadbf004cb5ae34480bbeb063520f70ce397b281859362", size = 264094, upload-time = "2026-01-26T02:45:20.834Z" }, - { url = "https://files.pythonhosted.org/packages/a1/e7/69a3a83b7b030cf283fb06ce074a05a02322359783424d7edf0f15fe5022/multidict-6.7.1-cp314-cp314-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:538cec1e18c067d0e6103aa9a74f9e832904c957adc260e61cd9d8cf0c3b3d37", size = 260786, upload-time = "2026-01-26T02:45:22.818Z" }, - { url = "https://files.pythonhosted.org/packages/fe/3b/8ec5074bcfc450fe84273713b4b0a0dd47c0249358f5d82eb8104ffe2520/multidict-6.7.1-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:7eee46ccb30ff48a1e35bb818cc90846c6be2b68240e42a78599166722cea709", size = 248483, upload-time = "2026-01-26T02:45:24.368Z" }, - { url = "https://files.pythonhosted.org/packages/48/5a/d5a99e3acbca0e29c5d9cba8f92ceb15dce78bab963b308ae692981e3a5d/multidict-6.7.1-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:fa263a02f4f2dd2d11a7b1bb4362aa7cb1049f84a9235d31adf63f30143469a0", size = 248403, upload-time = "2026-01-26T02:45:25.982Z" }, - { url = "https://files.pythonhosted.org/packages/35/48/e58cd31f6c7d5102f2a4bf89f96b9cf7e00b6c6f3d04ecc44417c00a5a3c/multidict-6.7.1-cp314-cp314-musllinux_1_2_armv7l.whl", hash = "sha256:2e1425e2f99ec5bd36c15a01b690a1a2456209c5deed58f95469ffb46039ccbb", size = 240315, upload-time = "2026-01-26T02:45:27.487Z" }, - { url = "https://files.pythonhosted.org/packages/94/33/1cd210229559cb90b6786c30676bb0c58249ff42f942765f88793b41fdce/multidict-6.7.1-cp314-cp314-musllinux_1_2_i686.whl", hash = "sha256:497394b3239fc6f0e13a78a3e1b61296e72bf1c5f94b4c4eb80b265c37a131cd", size = 245528, upload-time = "2026-01-26T02:45:28.991Z" }, - { url = "https://files.pythonhosted.org/packages/64/f2/6e1107d226278c876c783056b7db43d800bb64c6131cec9c8dfb6903698e/multidict-6.7.1-cp314-cp314-musllinux_1_2_ppc64le.whl", hash = "sha256:233b398c29d3f1b9676b4b6f75c518a06fcb2ea0b925119fb2c1bc35c05e1601", size = 258784, upload-time = "2026-01-26T02:45:30.503Z" }, - { url = "https://files.pythonhosted.org/packages/4d/c1/11f664f14d525e4a1b5327a82d4de61a1db604ab34c6603bb3c2cc63ad34/multidict-6.7.1-cp314-cp314-musllinux_1_2_s390x.whl", hash = "sha256:93b1818e4a6e0930454f0f2af7dfce69307ca03cdcfb3739bf4d91241967b6c1", size = 251980, upload-time = "2026-01-26T02:45:32.603Z" }, - { url = "https://files.pythonhosted.org/packages/e1/9f/75a9ac888121d0c5bbd4ecf4eead45668b1766f6baabfb3b7f66a410e231/multidict-6.7.1-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:f33dc2a3abe9249ea5d8360f969ec7f4142e7ac45ee7014d8f8d5acddf178b7b", size = 243602, upload-time = "2026-01-26T02:45:34.043Z" }, - { url = "https://files.pythonhosted.org/packages/9a/e7/50bf7b004cc8525d80dbbbedfdc7aed3e4c323810890be4413e589074032/multidict-6.7.1-cp314-cp314-win32.whl", hash = "sha256:3ab8b9d8b75aef9df299595d5388b14530839f6422333357af1339443cff777d", size = 40930, upload-time = "2026-01-26T02:45:36.278Z" }, - { url = "https://files.pythonhosted.org/packages/e0/bf/52f25716bbe93745595800f36fb17b73711f14da59ed0bb2eba141bc9f0f/multidict-6.7.1-cp314-cp314-win_amd64.whl", hash = "sha256:5e01429a929600e7dab7b166062d9bb54a5eed752384c7384c968c2afab8f50f", size = 45074, upload-time = "2026-01-26T02:45:37.546Z" }, - { url = "https://files.pythonhosted.org/packages/97/ab/22803b03285fa3a525f48217963da3a65ae40f6a1b6f6cf2768879e208f9/multidict-6.7.1-cp314-cp314-win_arm64.whl", hash = "sha256:4885cb0e817aef5d00a2e8451d4665c1808378dc27c2705f1bf4ef8505c0d2e5", size = 42471, upload-time = "2026-01-26T02:45:38.889Z" }, - { url = "https://files.pythonhosted.org/packages/e0/6d/f9293baa6146ba9507e360ea0292b6422b016907c393e2f63fc40ab7b7b5/multidict-6.7.1-cp314-cp314t-macosx_10_15_universal2.whl", hash = "sha256:0458c978acd8e6ea53c81eefaddbbee9c6c5e591f41b3f5e8e194780fe026581", size = 82401, upload-time = "2026-01-26T02:45:40.254Z" }, - { url = "https://files.pythonhosted.org/packages/7a/68/53b5494738d83558d87c3c71a486504d8373421c3e0dbb6d0db48ad42ee0/multidict-6.7.1-cp314-cp314t-macosx_10_15_x86_64.whl", hash = "sha256:c0abd12629b0af3cf590982c0b413b1e7395cd4ec026f30986818ab95bfaa94a", size = 48143, upload-time = "2026-01-26T02:45:41.635Z" }, - { url = "https://files.pythonhosted.org/packages/37/e8/5284c53310dcdc99ce5d66563f6e5773531a9b9fe9ec7a615e9bc306b05f/multidict-6.7.1-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:14525a5f61d7d0c94b368a42cff4c9a4e7ba2d52e2672a7b23d84dc86fb02b0c", size = 46507, upload-time = "2026-01-26T02:45:42.99Z" }, - { url = "https://files.pythonhosted.org/packages/e4/fc/6800d0e5b3875568b4083ecf5f310dcf91d86d52573160834fb4bfcf5e4f/multidict-6.7.1-cp314-cp314t-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:17307b22c217b4cf05033dabefe68255a534d637c6c9b0cc8382718f87be4262", size = 239358, upload-time = "2026-01-26T02:45:44.376Z" }, - { url = "https://files.pythonhosted.org/packages/41/75/4ad0973179361cdf3a113905e6e088173198349131be2b390f9fa4da5fc6/multidict-6.7.1-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:7a7e590ff876a3eaf1c02a4dfe0724b6e69a9e9de6d8f556816f29c496046e59", size = 246884, upload-time = "2026-01-26T02:45:47.167Z" }, - { url = "https://files.pythonhosted.org/packages/c3/9c/095bb28b5da139bd41fb9a5d5caff412584f377914bd8787c2aa98717130/multidict-6.7.1-cp314-cp314t-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:5fa6a95dfee63893d80a34758cd0e0c118a30b8dcb46372bf75106c591b77889", size = 225878, upload-time = "2026-01-26T02:45:48.698Z" }, - { url = "https://files.pythonhosted.org/packages/07/d0/c0a72000243756e8f5a277b6b514fa005f2c73d481b7d9e47cd4568aa2e4/multidict-6.7.1-cp314-cp314t-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:a0543217a6a017692aa6ae5cc39adb75e587af0f3a82288b1492eb73dd6cc2a4", size = 253542, upload-time = "2026-01-26T02:45:50.164Z" }, - { url = "https://files.pythonhosted.org/packages/c0/6b/f69da15289e384ecf2a68837ec8b5ad8c33e973aa18b266f50fe55f24b8c/multidict-6.7.1-cp314-cp314t-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:f99fe611c312b3c1c0ace793f92464d8cd263cc3b26b5721950d977b006b6c4d", size = 252403, upload-time = "2026-01-26T02:45:51.779Z" }, - { url = "https://files.pythonhosted.org/packages/a2/76/b9669547afa5a1a25cd93eaca91c0da1c095b06b6d2d8ec25b713588d3a1/multidict-6.7.1-cp314-cp314t-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:9004d8386d133b7e6135679424c91b0b854d2d164af6ea3f289f8f2761064609", size = 244889, upload-time = "2026-01-26T02:45:53.27Z" }, - { url = "https://files.pythonhosted.org/packages/7e/a9/a50d2669e506dad33cfc45b5d574a205587b7b8a5f426f2fbb2e90882588/multidict-6.7.1-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:e628ef0e6859ffd8273c69412a2465c4be4a9517d07261b33334b5ec6f3c7489", size = 241982, upload-time = "2026-01-26T02:45:54.919Z" }, - { url = "https://files.pythonhosted.org/packages/c5/bb/1609558ad8b456b4827d3c5a5b775c93b87878fd3117ed3db3423dfbce1b/multidict-6.7.1-cp314-cp314t-musllinux_1_2_armv7l.whl", hash = "sha256:841189848ba629c3552035a6a7f5bf3b02eb304e9fea7492ca220a8eda6b0e5c", size = 232415, upload-time = "2026-01-26T02:45:56.981Z" }, - { url = "https://files.pythonhosted.org/packages/d8/59/6f61039d2aa9261871e03ab9dc058a550d240f25859b05b67fd70f80d4b3/multidict-6.7.1-cp314-cp314t-musllinux_1_2_i686.whl", hash = "sha256:ce1bbd7d780bb5a0da032e095c951f7014d6b0a205f8318308140f1a6aba159e", size = 240337, upload-time = "2026-01-26T02:45:58.698Z" }, - { url = "https://files.pythonhosted.org/packages/a1/29/fdc6a43c203890dc2ae9249971ecd0c41deaedfe00d25cb6564b2edd99eb/multidict-6.7.1-cp314-cp314t-musllinux_1_2_ppc64le.whl", hash = "sha256:b26684587228afed0d50cf804cc71062cc9c1cdf55051c4c6345d372947b268c", size = 248788, upload-time = "2026-01-26T02:46:00.862Z" }, - { url = "https://files.pythonhosted.org/packages/a9/14/a153a06101323e4cf086ecee3faadba52ff71633d471f9685c42e3736163/multidict-6.7.1-cp314-cp314t-musllinux_1_2_s390x.whl", hash = "sha256:9f9af11306994335398293f9958071019e3ab95e9a707dc1383a35613f6abcb9", size = 242842, upload-time = "2026-01-26T02:46:02.824Z" }, - { url = "https://files.pythonhosted.org/packages/41/5f/604ae839e64a4a6efc80db94465348d3b328ee955e37acb24badbcd24d83/multidict-6.7.1-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:b4938326284c4f1224178a560987b6cf8b4d38458b113d9b8c1db1a836e640a2", size = 240237, upload-time = "2026-01-26T02:46:05.898Z" }, - { url = "https://files.pythonhosted.org/packages/5f/60/c3a5187bf66f6fb546ff4ab8fb5a077cbdd832d7b1908d4365c7f74a1917/multidict-6.7.1-cp314-cp314t-win32.whl", hash = "sha256:98655c737850c064a65e006a3df7c997cd3b220be4ec8fe26215760b9697d4d7", size = 48008, upload-time = "2026-01-26T02:46:07.468Z" }, - { url = "https://files.pythonhosted.org/packages/0c/f7/addf1087b860ac60e6f382240f64fb99f8bfb532bb06f7c542b83c29ca61/multidict-6.7.1-cp314-cp314t-win_amd64.whl", hash = "sha256:497bde6223c212ba11d462853cfa4f0ae6ef97465033e7dc9940cdb3ab5b48e5", size = 53542, upload-time = "2026-01-26T02:46:08.809Z" }, - { url = "https://files.pythonhosted.org/packages/4c/81/4629d0aa32302ef7b2ec65c75a728cc5ff4fa410c50096174c1632e70b3e/multidict-6.7.1-cp314-cp314t-win_arm64.whl", hash = "sha256:2bbd113e0d4af5db41d5ebfe9ccaff89de2120578164f86a5d17d5a576d1e5b2", size = 44719, upload-time = "2026-01-26T02:46:11.146Z" }, - { url = "https://files.pythonhosted.org/packages/81/08/7036c080d7117f28a4af526d794aab6a84463126db031b007717c1a6676e/multidict-6.7.1-py3-none-any.whl", hash = "sha256:55d97cc6dae627efa6a6e548885712d4864b81110ac76fa4e534c03819fa4a56", size = 12319, upload-time = "2026-01-26T02:46:44.004Z" }, -] - [[package]] name = "mypy" version = "2.1.0" @@ -3206,18 +2398,6 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/79/7b/2c79738432f5c924bef5071f933bcc9efd0473bac3b4aa584a6f7c1c8df8/mypy_extensions-1.1.0-py3-none-any.whl", hash = "sha256:1be4cccdb0f2482337c4743e60421de3a356cd97508abadd57d47403e94f5505", size = 4963, upload-time = "2025-04-22T14:54:22.983Z" }, ] -[[package]] -name = "nexus-rpc" -version = "1.4.0" -source = { registry = "https://pypi.org/simple" } -dependencies = [ - { name = "typing-extensions" }, -] -sdist = { url = "https://files.pythonhosted.org/packages/35/d5/cd1ffb202b76ebc1b33c1332a3416e55a39929006982adc2b1eb069aaa9b/nexus_rpc-1.4.0.tar.gz", hash = "sha256:3b8b373d4865671789cc43623e3dc0bcbf192562e40e13727e17f1c149050fba", size = 82367, upload-time = "2026-02-25T22:01:34.053Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/11/52/6327a5f4fda01207205038a106a99848a41c83e933cd23ea2cab3d2ebc6c/nexus_rpc-1.4.0-py3-none-any.whl", hash = "sha256:14c953d3519113f8ccec533a9efdb6b10c28afef75d11cdd6d422640c40b3a49", size = 29645, upload-time = "2026-02-25T22:01:33.122Z" }, -] - [[package]] name = "openai" version = "2.32.0" @@ -3237,18 +2417,6 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/1e/c1/d6e64ccd0536bf616556f0cad2b6d94a8125f508d25cfd814b1d2db4e2f1/openai-2.32.0-py3-none-any.whl", hash = "sha256:4dcc9badeb4bf54ad0d187453742f290226d30150890b7890711bda4f32f192f", size = 1162570, upload-time = "2026-04-15T22:28:17.714Z" }, ] -[[package]] -name = "openapi-pydantic" -version = "0.5.1" -source = { registry = "https://pypi.org/simple" } -dependencies = [ - { name = "pydantic" }, -] -sdist = { url = "https://files.pythonhosted.org/packages/02/2e/58d83848dd1a79cb92ed8e63f6ba901ca282c5f09d04af9423ec26c56fd7/openapi_pydantic-0.5.1.tar.gz", hash = "sha256:ff6835af6bde7a459fb93eb93bb92b8749b754fc6e51b2f1590a19dc3005ee0d", size = 60892, upload-time = "2025-01-08T19:29:27.083Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/12/cf/03675d8bd8ecbf4445504d8071adab19f5f993676795708e36402ab38263/openapi_pydantic-0.5.1-py3-none-any.whl", hash = "sha256:a3a09ef4586f5bd760a8df7f43028b60cafb6d9f61de2acba9574766255ab146", size = 96381, upload-time = "2025-01-08T19:29:25.275Z" }, -] - [[package]] name = "opentelemetry-api" version = "1.39.1" @@ -3392,15 +2560,6 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/20/12/38679034af332785aac8774540895e234f4d07f7545804097de4b666afd8/packaging-25.0-py3-none-any.whl", hash = "sha256:29572ef2b1f17581046b3a2227d5c611fb25ec70ca1ba8554b24b0e69331a484", size = 66469, upload-time = "2025-04-19T11:48:57.875Z" }, ] -[[package]] -name = "pathable" -version = "0.4.4" -source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/67/93/8f2c2075b180c12c1e9f6a09d1a985bc2036906b13dff1d8917e395f2048/pathable-0.4.4.tar.gz", hash = "sha256:6905a3cd17804edfac7875b5f6c9142a218c7caef78693c2dbbbfbac186d88b2", size = 8124, upload-time = "2025-01-10T18:43:13.247Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/7d/eb/b6260b31b1a96386c0a880edebe26f89669098acea8e0318bff6adb378fd/pathable-0.4.4-py3-none-any.whl", hash = "sha256:5ae9e94793b6ef5a4cbe0a7ce9dbbefc1eec38df253763fd0aeeacf2762dbbc2", size = 9592, upload-time = "2025-01-10T18:43:11.88Z" }, -] - [[package]] name = "pathspec" version = "1.0.4" @@ -3519,21 +2678,21 @@ wheels = [ [[package]] name = "playwright" -version = "1.60.0" +version = "1.61.0" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "greenlet" }, { name = "pyee" }, ] wheels = [ - { url = "https://files.pythonhosted.org/packages/21/f0/832bd9677194908da118064eef20082f2791e3d18215cc6d9391ee2c5a67/playwright-1.60.0-py3-none-macosx_10_13_x86_64.whl", hash = "sha256:6a8cd0fec171fb3089e95e898c8bc8a6f35dea0b78b399e12fcc19427e91b1d7", size = 43474635, upload-time = "2026-05-18T12:00:31.969Z" }, - { url = "https://files.pythonhosted.org/packages/59/7b/e1d32ae8a3ed937ec2be3721c5f728b13d731a0b7c6442e0b3bec5094ac0/playwright-1.60.0-py3-none-macosx_11_0_arm64.whl", hash = "sha256:39b5420ba6145045b69ced4c5c47d4d9fe5bddfc8ff816c518913afcb25ec7a5", size = 42261327, upload-time = "2026-05-18T12:00:35.638Z" }, - { url = "https://files.pythonhosted.org/packages/d7/bc/23de499ded6411c188a20c5a0dea6f0cd4ed5d2b3cc6042a5dbd3ed609aa/playwright-1.60.0-py3-none-macosx_11_0_universal2.whl", hash = "sha256:2581d0e6a3392c71f91b27460c7fd093356818dc430f48153896c8aeeaef7705", size = 43474636, upload-time = "2026-05-18T12:00:39.294Z" }, - { url = "https://files.pythonhosted.org/packages/22/7b/1d679f4fced4ea94efadd17103856d8c565384f68382a1681264e46f5925/playwright-1.60.0-py3-none-manylinux1_x86_64.whl", hash = "sha256:1c2bfae7884fb3fb05b853290eab8f343d524e5016f2f1def702acbbdf14c93e", size = 47467220, upload-time = "2026-05-18T12:00:43.179Z" }, - { url = "https://files.pythonhosted.org/packages/84/c2/1528d267d4442bd2c6b8eaeab819dd52c2030bf80e89293f0ba1f687473b/playwright-1.60.0-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:43e66564125ee31b07a58cefb21e256d62d67d8d1713e6858df7a3019d8ed353", size = 47154856, upload-time = "2026-05-18T12:00:46.715Z" }, - { url = "https://files.pythonhosted.org/packages/bb/4e/b008b6440a7a1624378041da94829956d4b8f7ab9ef5aad22d0dc3f2e26d/playwright-1.60.0-py3-none-win32.whl", hash = "sha256:ec94e416ea320711e0ad4bf185dcbf41833672961e90773e1885255d7db7b7e7", size = 37902157, upload-time = "2026-05-18T12:00:50.374Z" }, - { url = "https://files.pythonhosted.org/packages/55/f0/0541524133104f9cc20bf900870ff4a736b76a23483f3a55295ddfa58409/playwright-1.60.0-py3-none-win_amd64.whl", hash = "sha256:9566821ce6030a1f9e7146a24e19355ab0d98805fd0f9be50bb3d8fef1750c02", size = 37902159, upload-time = "2026-05-18T12:00:53.728Z" }, - { url = "https://files.pythonhosted.org/packages/80/c8/210f282d278e4709cdd71b12a31af45a30a22ab3207b387e29b37e478713/playwright-1.60.0-py3-none-win_arm64.whl", hash = "sha256:6e4f6700a4c2250efff8e690a81d66e3855754fb587b6b87cf5c784014f91537", size = 34037981, upload-time = "2026-05-18T12:00:57.584Z" }, + { url = "https://files.pythonhosted.org/packages/44/ee/31e4e0db36588b817a10b299a0285082545fde7d36543c2abe498bb3d61a/playwright-1.61.0-py3-none-macosx_10_13_x86_64.whl", hash = "sha256:ff138c3a604f69911e9d42fd036e55c2a171e5616edf04c1e7f60a2a285540b0", size = 43421877, upload-time = "2026-06-29T10:32:48.428Z" }, + { url = "https://files.pythonhosted.org/packages/42/35/71395dd3ecc798965be4a3ef8c443217d4abca168e7cb34536304f9489e6/playwright-1.61.0-py3-none-macosx_11_0_arm64.whl", hash = "sha256:009588c2a7e499bc5a8b425b61fa65490968bbda9cd69e0cf2cff10f8304659a", size = 42205016, upload-time = "2026-06-29T10:32:52.104Z" }, + { url = "https://files.pythonhosted.org/packages/f4/44/323164cf5cd1647bdefce76ffce27651aadb959d089b48f53ea40918276e/playwright-1.61.0-py3-none-macosx_11_0_universal2.whl", hash = "sha256:9f7de4536088d12037c13a52b7ea34b59270b78926bb56935070597ffac6b1af", size = 43421884, upload-time = "2026-06-29T10:32:55.773Z" }, + { url = "https://files.pythonhosted.org/packages/ab/f8/a35bf179e4ba2522c1893635094a64e407572547bd61528820fc0abc87fe/playwright-1.61.0-py3-none-manylinux1_x86_64.whl", hash = "sha256:54f3b39f6eab832e33458c1dd7da0b5682aedab3b09ae731b5c59fa12fd2024e", size = 47421381, upload-time = "2026-06-29T10:32:59.903Z" }, + { url = "https://files.pythonhosted.org/packages/b7/eb/e3f922348ec17c315f98c463f72faa1181a1c3de0bfe31a8d2edf6561723/playwright-1.61.0-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:93454322ade8c11d5d6c211bfd91bdfb9ffb4810e3e026371bcbc4bec1b7ee4c", size = 47120545, upload-time = "2026-06-29T10:33:03.574Z" }, + { url = "https://files.pythonhosted.org/packages/c2/a6/5be4e52b40a9c0c8a073e7c5b0785c05cf5a9ea8f8a7b5b260e32d970342/playwright-1.61.0-py3-none-win32.whl", hash = "sha256:372d55a6f1248fa1dd47599686980cb8fb5bbe6fcda59eab793eb657c11d8a9b", size = 37844841, upload-time = "2026-06-29T10:33:07.361Z" }, + { url = "https://files.pythonhosted.org/packages/6c/fd/2b78036e5fbe9d5f5645bbe08a1eac7160c51243c0093963edbcf67c35d9/playwright-1.61.0-py3-none-win_amd64.whl", hash = "sha256:35c6cc4589a5d00964a59d7b3e59641e0aac0c02f15479a7af77d20f6bc79597", size = 37844846, upload-time = "2026-06-29T10:33:10.637Z" }, + { url = "https://files.pythonhosted.org/packages/27/0d/1b0f3c4ee4eb0514bc805b5c2f9a223e5b6de4f11a926f5235d51d0fc81b/playwright-1.61.0-py3-none-win_arm64.whl", hash = "sha256:e9fcbffcf557a8620fdedd92491eb59a32d18e23d6f3b4f6214b952be324fe51", size = 33955127, upload-time = "2026-06-29T10:33:14.008Z" }, ] [[package]] @@ -3581,120 +2740,6 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/84/03/0d3ce49e2505ae70cf43bc5bb3033955d2fc9f932163e84dc0779cc47f48/prompt_toolkit-3.0.52-py3-none-any.whl", hash = "sha256:9aac639a3bbd33284347de5ad8d68ecc044b91a762dc39b7c21095fcd6a19955", size = 391431, upload-time = "2025-08-27T15:23:59.498Z" }, ] -[[package]] -name = "propcache" -version = "0.4.1" -source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/9e/da/e9fc233cf63743258bff22b3dfa7ea5baef7b5bc324af47a0ad89b8ffc6f/propcache-0.4.1.tar.gz", hash = "sha256:f48107a8c637e80362555f37ecf49abe20370e557cc4ab374f04ec4423c97c3d", size = 46442, upload-time = "2025-10-08T19:49:02.291Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/3c/0e/934b541323035566a9af292dba85a195f7b78179114f2c6ebb24551118a9/propcache-0.4.1-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:7c2d1fa3201efaf55d730400d945b5b3ab6e672e100ba0f9a409d950ab25d7db", size = 79534, upload-time = "2025-10-08T19:46:02.083Z" }, - { url = "https://files.pythonhosted.org/packages/a1/6b/db0d03d96726d995dc7171286c6ba9d8d14251f37433890f88368951a44e/propcache-0.4.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:1eb2994229cc8ce7fe9b3db88f5465f5fd8651672840b2e426b88cdb1a30aac8", size = 45526, upload-time = "2025-10-08T19:46:03.884Z" }, - { url = "https://files.pythonhosted.org/packages/e4/c3/82728404aea669e1600f304f2609cde9e665c18df5a11cdd57ed73c1dceb/propcache-0.4.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:66c1f011f45a3b33d7bcb22daed4b29c0c9e2224758b6be00686731e1b46f925", size = 47263, upload-time = "2025-10-08T19:46:05.405Z" }, - { url = "https://files.pythonhosted.org/packages/df/1b/39313ddad2bf9187a1432654c38249bab4562ef535ef07f5eb6eb04d0b1b/propcache-0.4.1-cp310-cp310-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:9a52009f2adffe195d0b605c25ec929d26b36ef986ba85244891dee3b294df21", size = 201012, upload-time = "2025-10-08T19:46:07.165Z" }, - { url = "https://files.pythonhosted.org/packages/5b/01/f1d0b57d136f294a142acf97f4ed58c8e5b974c21e543000968357115011/propcache-0.4.1-cp310-cp310-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:5d4e2366a9c7b837555cf02fb9be2e3167d333aff716332ef1b7c3a142ec40c5", size = 209491, upload-time = "2025-10-08T19:46:08.909Z" }, - { url = "https://files.pythonhosted.org/packages/a1/c8/038d909c61c5bb039070b3fb02ad5cccdb1dde0d714792e251cdb17c9c05/propcache-0.4.1-cp310-cp310-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:9d2b6caef873b4f09e26ea7e33d65f42b944837563a47a94719cc3544319a0db", size = 215319, upload-time = "2025-10-08T19:46:10.7Z" }, - { url = "https://files.pythonhosted.org/packages/08/57/8c87e93142b2c1fa2408e45695205a7ba05fb5db458c0bf5c06ba0e09ea6/propcache-0.4.1-cp310-cp310-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:2b16ec437a8c8a965ecf95739448dd938b5c7f56e67ea009f4300d8df05f32b7", size = 196856, upload-time = "2025-10-08T19:46:12.003Z" }, - { url = "https://files.pythonhosted.org/packages/42/df/5615fec76aa561987a534759b3686008a288e73107faa49a8ae5795a9f7a/propcache-0.4.1-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:296f4c8ed03ca7476813fe666c9ea97869a8d7aec972618671b33a38a5182ef4", size = 193241, upload-time = "2025-10-08T19:46:13.495Z" }, - { url = "https://files.pythonhosted.org/packages/d5/21/62949eb3a7a54afe8327011c90aca7e03547787a88fb8bd9726806482fea/propcache-0.4.1-cp310-cp310-musllinux_1_2_armv7l.whl", hash = "sha256:1f0978529a418ebd1f49dad413a2b68af33f85d5c5ca5c6ca2a3bed375a7ac60", size = 190552, upload-time = "2025-10-08T19:46:14.938Z" }, - { url = "https://files.pythonhosted.org/packages/30/ee/ab4d727dd70806e5b4de96a798ae7ac6e4d42516f030ee60522474b6b332/propcache-0.4.1-cp310-cp310-musllinux_1_2_ppc64le.whl", hash = "sha256:fd138803047fb4c062b1c1dd95462f5209456bfab55c734458f15d11da288f8f", size = 200113, upload-time = "2025-10-08T19:46:16.695Z" }, - { url = "https://files.pythonhosted.org/packages/8a/0b/38b46208e6711b016aa8966a3ac793eee0d05c7159d8342aa27fc0bc365e/propcache-0.4.1-cp310-cp310-musllinux_1_2_s390x.whl", hash = "sha256:8c9b3cbe4584636d72ff556d9036e0c9317fa27b3ac1f0f558e7e84d1c9c5900", size = 200778, upload-time = "2025-10-08T19:46:18.023Z" }, - { url = "https://files.pythonhosted.org/packages/cf/81/5abec54355ed344476bee711e9f04815d4b00a311ab0535599204eecc257/propcache-0.4.1-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:f93243fdc5657247533273ac4f86ae106cc6445a0efacb9a1bfe982fcfefd90c", size = 193047, upload-time = "2025-10-08T19:46:19.449Z" }, - { url = "https://files.pythonhosted.org/packages/ec/b6/1f237c04e32063cb034acd5f6ef34ef3a394f75502e72703545631ab1ef6/propcache-0.4.1-cp310-cp310-win32.whl", hash = "sha256:a0ee98db9c5f80785b266eb805016e36058ac72c51a064040f2bc43b61101cdb", size = 38093, upload-time = "2025-10-08T19:46:20.643Z" }, - { url = "https://files.pythonhosted.org/packages/a6/67/354aac4e0603a15f76439caf0427781bcd6797f370377f75a642133bc954/propcache-0.4.1-cp310-cp310-win_amd64.whl", hash = "sha256:1cdb7988c4e5ac7f6d175a28a9aa0c94cb6f2ebe52756a3c0cda98d2809a9e37", size = 41638, upload-time = "2025-10-08T19:46:21.935Z" }, - { url = "https://files.pythonhosted.org/packages/e0/e1/74e55b9fd1a4c209ff1a9a824bf6c8b3d1fc5a1ac3eabe23462637466785/propcache-0.4.1-cp310-cp310-win_arm64.whl", hash = "sha256:d82ad62b19645419fe79dd63b3f9253e15b30e955c0170e5cebc350c1844e581", size = 38229, upload-time = "2025-10-08T19:46:23.368Z" }, - { url = "https://files.pythonhosted.org/packages/8c/d4/4e2c9aaf7ac2242b9358f98dccd8f90f2605402f5afeff6c578682c2c491/propcache-0.4.1-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:60a8fda9644b7dfd5dece8c61d8a85e271cb958075bfc4e01083c148b61a7caf", size = 80208, upload-time = "2025-10-08T19:46:24.597Z" }, - { url = "https://files.pythonhosted.org/packages/c2/21/d7b68e911f9c8e18e4ae43bdbc1e1e9bbd971f8866eb81608947b6f585ff/propcache-0.4.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:c30b53e7e6bda1d547cabb47c825f3843a0a1a42b0496087bb58d8fedf9f41b5", size = 45777, upload-time = "2025-10-08T19:46:25.733Z" }, - { url = "https://files.pythonhosted.org/packages/d3/1d/11605e99ac8ea9435651ee71ab4cb4bf03f0949586246476a25aadfec54a/propcache-0.4.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:6918ecbd897443087a3b7cd978d56546a812517dcaaca51b49526720571fa93e", size = 47647, upload-time = "2025-10-08T19:46:27.304Z" }, - { url = "https://files.pythonhosted.org/packages/58/1a/3c62c127a8466c9c843bccb503d40a273e5cc69838805f322e2826509e0d/propcache-0.4.1-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:3d902a36df4e5989763425a8ab9e98cd8ad5c52c823b34ee7ef307fd50582566", size = 214929, upload-time = "2025-10-08T19:46:28.62Z" }, - { url = "https://files.pythonhosted.org/packages/56/b9/8fa98f850960b367c4b8fe0592e7fc341daa7a9462e925228f10a60cf74f/propcache-0.4.1-cp311-cp311-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:a9695397f85973bb40427dedddf70d8dc4a44b22f1650dd4af9eedf443d45165", size = 221778, upload-time = "2025-10-08T19:46:30.358Z" }, - { url = "https://files.pythonhosted.org/packages/46/a6/0ab4f660eb59649d14b3d3d65c439421cf2f87fe5dd68591cbe3c1e78a89/propcache-0.4.1-cp311-cp311-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:2bb07ffd7eaad486576430c89f9b215f9e4be68c4866a96e97db9e97fead85dc", size = 228144, upload-time = "2025-10-08T19:46:32.607Z" }, - { url = "https://files.pythonhosted.org/packages/52/6a/57f43e054fb3d3a56ac9fc532bc684fc6169a26c75c353e65425b3e56eef/propcache-0.4.1-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:fd6f30fdcf9ae2a70abd34da54f18da086160e4d7d9251f81f3da0ff84fc5a48", size = 210030, upload-time = "2025-10-08T19:46:33.969Z" }, - { url = "https://files.pythonhosted.org/packages/40/e2/27e6feebb5f6b8408fa29f5efbb765cd54c153ac77314d27e457a3e993b7/propcache-0.4.1-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:fc38cba02d1acba4e2869eef1a57a43dfbd3d49a59bf90dda7444ec2be6a5570", size = 208252, upload-time = "2025-10-08T19:46:35.309Z" }, - { url = "https://files.pythonhosted.org/packages/9e/f8/91c27b22ccda1dbc7967f921c42825564fa5336a01ecd72eb78a9f4f53c2/propcache-0.4.1-cp311-cp311-musllinux_1_2_armv7l.whl", hash = "sha256:67fad6162281e80e882fb3ec355398cf72864a54069d060321f6cd0ade95fe85", size = 202064, upload-time = "2025-10-08T19:46:36.993Z" }, - { url = "https://files.pythonhosted.org/packages/f2/26/7f00bd6bd1adba5aafe5f4a66390f243acab58eab24ff1a08bebb2ef9d40/propcache-0.4.1-cp311-cp311-musllinux_1_2_ppc64le.whl", hash = "sha256:f10207adf04d08bec185bae14d9606a1444715bc99180f9331c9c02093e1959e", size = 212429, upload-time = "2025-10-08T19:46:38.398Z" }, - { url = "https://files.pythonhosted.org/packages/84/89/fd108ba7815c1117ddca79c228f3f8a15fc82a73bca8b142eb5de13b2785/propcache-0.4.1-cp311-cp311-musllinux_1_2_s390x.whl", hash = "sha256:e9b0d8d0845bbc4cfcdcbcdbf5086886bc8157aa963c31c777ceff7846c77757", size = 216727, upload-time = "2025-10-08T19:46:39.732Z" }, - { url = "https://files.pythonhosted.org/packages/79/37/3ec3f7e3173e73f1d600495d8b545b53802cbf35506e5732dd8578db3724/propcache-0.4.1-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:981333cb2f4c1896a12f4ab92a9cc8f09ea664e9b7dbdc4eff74627af3a11c0f", size = 205097, upload-time = "2025-10-08T19:46:41.025Z" }, - { url = "https://files.pythonhosted.org/packages/61/b0/b2631c19793f869d35f47d5a3a56fb19e9160d3c119f15ac7344fc3ccae7/propcache-0.4.1-cp311-cp311-win32.whl", hash = "sha256:f1d2f90aeec838a52f1c1a32fe9a619fefd5e411721a9117fbf82aea638fe8a1", size = 38084, upload-time = "2025-10-08T19:46:42.693Z" }, - { url = "https://files.pythonhosted.org/packages/f4/78/6cce448e2098e9f3bfc91bb877f06aa24b6ccace872e39c53b2f707c4648/propcache-0.4.1-cp311-cp311-win_amd64.whl", hash = "sha256:364426a62660f3f699949ac8c621aad6977be7126c5807ce48c0aeb8e7333ea6", size = 41637, upload-time = "2025-10-08T19:46:43.778Z" }, - { url = "https://files.pythonhosted.org/packages/9c/e9/754f180cccd7f51a39913782c74717c581b9cc8177ad0e949f4d51812383/propcache-0.4.1-cp311-cp311-win_arm64.whl", hash = "sha256:e53f3a38d3510c11953f3e6a33f205c6d1b001129f972805ca9b42fc308bc239", size = 38064, upload-time = "2025-10-08T19:46:44.872Z" }, - { url = "https://files.pythonhosted.org/packages/a2/0f/f17b1b2b221d5ca28b4b876e8bb046ac40466513960646bda8e1853cdfa2/propcache-0.4.1-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:e153e9cd40cc8945138822807139367f256f89c6810c2634a4f6902b52d3b4e2", size = 80061, upload-time = "2025-10-08T19:46:46.075Z" }, - { url = "https://files.pythonhosted.org/packages/76/47/8ccf75935f51448ba9a16a71b783eb7ef6b9ee60f5d14c7f8a8a79fbeed7/propcache-0.4.1-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:cd547953428f7abb73c5ad82cbb32109566204260d98e41e5dfdc682eb7f8403", size = 46037, upload-time = "2025-10-08T19:46:47.23Z" }, - { url = "https://files.pythonhosted.org/packages/0a/b6/5c9a0e42df4d00bfb4a3cbbe5cf9f54260300c88a0e9af1f47ca5ce17ac0/propcache-0.4.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:f048da1b4f243fc44f205dfd320933a951b8d89e0afd4c7cacc762a8b9165207", size = 47324, upload-time = "2025-10-08T19:46:48.384Z" }, - { url = "https://files.pythonhosted.org/packages/9e/d3/6c7ee328b39a81ee877c962469f1e795f9db87f925251efeb0545e0020d0/propcache-0.4.1-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:ec17c65562a827bba85e3872ead335f95405ea1674860d96483a02f5c698fa72", size = 225505, upload-time = "2025-10-08T19:46:50.055Z" }, - { url = "https://files.pythonhosted.org/packages/01/5d/1c53f4563490b1d06a684742cc6076ef944bc6457df6051b7d1a877c057b/propcache-0.4.1-cp312-cp312-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:405aac25c6394ef275dee4c709be43745d36674b223ba4eb7144bf4d691b7367", size = 230242, upload-time = "2025-10-08T19:46:51.815Z" }, - { url = "https://files.pythonhosted.org/packages/20/e1/ce4620633b0e2422207c3cb774a0ee61cac13abc6217763a7b9e2e3f4a12/propcache-0.4.1-cp312-cp312-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:0013cb6f8dde4b2a2f66903b8ba740bdfe378c943c4377a200551ceb27f379e4", size = 238474, upload-time = "2025-10-08T19:46:53.208Z" }, - { url = "https://files.pythonhosted.org/packages/46/4b/3aae6835b8e5f44ea6a68348ad90f78134047b503765087be2f9912140ea/propcache-0.4.1-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:15932ab57837c3368b024473a525e25d316d8353016e7cc0e5ba9eb343fbb1cf", size = 221575, upload-time = "2025-10-08T19:46:54.511Z" }, - { url = "https://files.pythonhosted.org/packages/6e/a5/8a5e8678bcc9d3a1a15b9a29165640d64762d424a16af543f00629c87338/propcache-0.4.1-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:031dce78b9dc099f4c29785d9cf5577a3faf9ebf74ecbd3c856a7b92768c3df3", size = 216736, upload-time = "2025-10-08T19:46:56.212Z" }, - { url = "https://files.pythonhosted.org/packages/f1/63/b7b215eddeac83ca1c6b934f89d09a625aa9ee4ba158338854c87210cc36/propcache-0.4.1-cp312-cp312-musllinux_1_2_armv7l.whl", hash = "sha256:ab08df6c9a035bee56e31af99be621526bd237bea9f32def431c656b29e41778", size = 213019, upload-time = "2025-10-08T19:46:57.595Z" }, - { url = "https://files.pythonhosted.org/packages/57/74/f580099a58c8af587cac7ba19ee7cb418506342fbbe2d4a4401661cca886/propcache-0.4.1-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:4d7af63f9f93fe593afbf104c21b3b15868efb2c21d07d8732c0c4287e66b6a6", size = 220376, upload-time = "2025-10-08T19:46:59.067Z" }, - { url = "https://files.pythonhosted.org/packages/c4/ee/542f1313aff7eaf19c2bb758c5d0560d2683dac001a1c96d0774af799843/propcache-0.4.1-cp312-cp312-musllinux_1_2_s390x.whl", hash = "sha256:cfc27c945f422e8b5071b6e93169679e4eb5bf73bbcbf1ba3ae3a83d2f78ebd9", size = 226988, upload-time = "2025-10-08T19:47:00.544Z" }, - { url = "https://files.pythonhosted.org/packages/8f/18/9c6b015dd9c6930f6ce2229e1f02fb35298b847f2087ea2b436a5bfa7287/propcache-0.4.1-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:35c3277624a080cc6ec6f847cbbbb5b49affa3598c4535a0a4682a697aaa5c75", size = 215615, upload-time = "2025-10-08T19:47:01.968Z" }, - { url = "https://files.pythonhosted.org/packages/80/9e/e7b85720b98c45a45e1fca6a177024934dc9bc5f4d5dd04207f216fc33ed/propcache-0.4.1-cp312-cp312-win32.whl", hash = "sha256:671538c2262dadb5ba6395e26c1731e1d52534bfe9ae56d0b5573ce539266aa8", size = 38066, upload-time = "2025-10-08T19:47:03.503Z" }, - { url = "https://files.pythonhosted.org/packages/54/09/d19cff2a5aaac632ec8fc03737b223597b1e347416934c1b3a7df079784c/propcache-0.4.1-cp312-cp312-win_amd64.whl", hash = "sha256:cb2d222e72399fcf5890d1d5cc1060857b9b236adff2792ff48ca2dfd46c81db", size = 41655, upload-time = "2025-10-08T19:47:04.973Z" }, - { url = "https://files.pythonhosted.org/packages/68/ab/6b5c191bb5de08036a8c697b265d4ca76148efb10fa162f14af14fb5f076/propcache-0.4.1-cp312-cp312-win_arm64.whl", hash = "sha256:204483131fb222bdaaeeea9f9e6c6ed0cac32731f75dfc1d4a567fc1926477c1", size = 37789, upload-time = "2025-10-08T19:47:06.077Z" }, - { url = "https://files.pythonhosted.org/packages/bf/df/6d9c1b6ac12b003837dde8a10231a7344512186e87b36e855bef32241942/propcache-0.4.1-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:43eedf29202c08550aac1d14e0ee619b0430aaef78f85864c1a892294fbc28cf", size = 77750, upload-time = "2025-10-08T19:47:07.648Z" }, - { url = "https://files.pythonhosted.org/packages/8b/e8/677a0025e8a2acf07d3418a2e7ba529c9c33caf09d3c1f25513023c1db56/propcache-0.4.1-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:d62cdfcfd89ccb8de04e0eda998535c406bf5e060ffd56be6c586cbcc05b3311", size = 44780, upload-time = "2025-10-08T19:47:08.851Z" }, - { url = "https://files.pythonhosted.org/packages/89/a4/92380f7ca60f99ebae761936bc48a72a639e8a47b29050615eef757cb2a7/propcache-0.4.1-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:cae65ad55793da34db5f54e4029b89d3b9b9490d8abe1b4c7ab5d4b8ec7ebf74", size = 46308, upload-time = "2025-10-08T19:47:09.982Z" }, - { url = "https://files.pythonhosted.org/packages/2d/48/c5ac64dee5262044348d1d78a5f85dd1a57464a60d30daee946699963eb3/propcache-0.4.1-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:333ddb9031d2704a301ee3e506dc46b1fe5f294ec198ed6435ad5b6a085facfe", size = 208182, upload-time = "2025-10-08T19:47:11.319Z" }, - { url = "https://files.pythonhosted.org/packages/c6/0c/cd762dd011a9287389a6a3eb43aa30207bde253610cca06824aeabfe9653/propcache-0.4.1-cp313-cp313-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:fd0858c20f078a32cf55f7e81473d96dcf3b93fd2ccdb3d40fdf54b8573df3af", size = 211215, upload-time = "2025-10-08T19:47:13.146Z" }, - { url = "https://files.pythonhosted.org/packages/30/3e/49861e90233ba36890ae0ca4c660e95df565b2cd15d4a68556ab5865974e/propcache-0.4.1-cp313-cp313-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:678ae89ebc632c5c204c794f8dab2837c5f159aeb59e6ed0539500400577298c", size = 218112, upload-time = "2025-10-08T19:47:14.913Z" }, - { url = "https://files.pythonhosted.org/packages/f1/8b/544bc867e24e1bd48f3118cecd3b05c694e160a168478fa28770f22fd094/propcache-0.4.1-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:d472aeb4fbf9865e0c6d622d7f4d54a4e101a89715d8904282bb5f9a2f476c3f", size = 204442, upload-time = "2025-10-08T19:47:16.277Z" }, - { url = "https://files.pythonhosted.org/packages/50/a6/4282772fd016a76d3e5c0df58380a5ea64900afd836cec2c2f662d1b9bb3/propcache-0.4.1-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:4d3df5fa7e36b3225954fba85589da77a0fe6a53e3976de39caf04a0db4c36f1", size = 199398, upload-time = "2025-10-08T19:47:17.962Z" }, - { url = "https://files.pythonhosted.org/packages/3e/ec/d8a7cd406ee1ddb705db2139f8a10a8a427100347bd698e7014351c7af09/propcache-0.4.1-cp313-cp313-musllinux_1_2_armv7l.whl", hash = "sha256:ee17f18d2498f2673e432faaa71698032b0127ebf23ae5974eeaf806c279df24", size = 196920, upload-time = "2025-10-08T19:47:19.355Z" }, - { url = "https://files.pythonhosted.org/packages/f6/6c/f38ab64af3764f431e359f8baf9e0a21013e24329e8b85d2da32e8ed07ca/propcache-0.4.1-cp313-cp313-musllinux_1_2_ppc64le.whl", hash = "sha256:580e97762b950f993ae618e167e7be9256b8353c2dcd8b99ec100eb50f5286aa", size = 203748, upload-time = "2025-10-08T19:47:21.338Z" }, - { url = "https://files.pythonhosted.org/packages/d6/e3/fa846bd70f6534d647886621388f0a265254d30e3ce47e5c8e6e27dbf153/propcache-0.4.1-cp313-cp313-musllinux_1_2_s390x.whl", hash = "sha256:501d20b891688eb8e7aa903021f0b72d5a55db40ffaab27edefd1027caaafa61", size = 205877, upload-time = "2025-10-08T19:47:23.059Z" }, - { url = "https://files.pythonhosted.org/packages/e2/39/8163fc6f3133fea7b5f2827e8eba2029a0277ab2c5beee6c1db7b10fc23d/propcache-0.4.1-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:9a0bd56e5b100aef69bd8562b74b46254e7c8812918d3baa700c8a8009b0af66", size = 199437, upload-time = "2025-10-08T19:47:24.445Z" }, - { url = "https://files.pythonhosted.org/packages/93/89/caa9089970ca49c7c01662bd0eeedfe85494e863e8043565aeb6472ce8fe/propcache-0.4.1-cp313-cp313-win32.whl", hash = "sha256:bcc9aaa5d80322bc2fb24bb7accb4a30f81e90ab8d6ba187aec0744bc302ad81", size = 37586, upload-time = "2025-10-08T19:47:25.736Z" }, - { url = "https://files.pythonhosted.org/packages/f5/ab/f76ec3c3627c883215b5c8080debb4394ef5a7a29be811f786415fc1e6fd/propcache-0.4.1-cp313-cp313-win_amd64.whl", hash = "sha256:381914df18634f5494334d201e98245c0596067504b9372d8cf93f4bb23e025e", size = 40790, upload-time = "2025-10-08T19:47:26.847Z" }, - { url = "https://files.pythonhosted.org/packages/59/1b/e71ae98235f8e2ba5004d8cb19765a74877abf189bc53fc0c80d799e56c3/propcache-0.4.1-cp313-cp313-win_arm64.whl", hash = "sha256:8873eb4460fd55333ea49b7d189749ecf6e55bf85080f11b1c4530ed3034cba1", size = 37158, upload-time = "2025-10-08T19:47:27.961Z" }, - { url = "https://files.pythonhosted.org/packages/83/ce/a31bbdfc24ee0dcbba458c8175ed26089cf109a55bbe7b7640ed2470cfe9/propcache-0.4.1-cp313-cp313t-macosx_10_13_universal2.whl", hash = "sha256:92d1935ee1f8d7442da9c0c4fa7ac20d07e94064184811b685f5c4fada64553b", size = 81451, upload-time = "2025-10-08T19:47:29.445Z" }, - { url = "https://files.pythonhosted.org/packages/25/9c/442a45a470a68456e710d96cacd3573ef26a1d0a60067e6a7d5e655621ed/propcache-0.4.1-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:473c61b39e1460d386479b9b2f337da492042447c9b685f28be4f74d3529e566", size = 46374, upload-time = "2025-10-08T19:47:30.579Z" }, - { url = "https://files.pythonhosted.org/packages/f4/bf/b1d5e21dbc3b2e889ea4327044fb16312a736d97640fb8b6aa3f9c7b3b65/propcache-0.4.1-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:c0ef0aaafc66fbd87842a3fe3902fd889825646bc21149eafe47be6072725835", size = 48396, upload-time = "2025-10-08T19:47:31.79Z" }, - { url = "https://files.pythonhosted.org/packages/f4/04/5b4c54a103d480e978d3c8a76073502b18db0c4bc17ab91b3cb5092ad949/propcache-0.4.1-cp313-cp313t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:f95393b4d66bfae908c3ca8d169d5f79cd65636ae15b5e7a4f6e67af675adb0e", size = 275950, upload-time = "2025-10-08T19:47:33.481Z" }, - { url = "https://files.pythonhosted.org/packages/b4/c1/86f846827fb969c4b78b0af79bba1d1ea2156492e1b83dea8b8a6ae27395/propcache-0.4.1-cp313-cp313t-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:c07fda85708bc48578467e85099645167a955ba093be0a2dcba962195676e859", size = 273856, upload-time = "2025-10-08T19:47:34.906Z" }, - { url = "https://files.pythonhosted.org/packages/36/1d/fc272a63c8d3bbad6878c336c7a7dea15e8f2d23a544bda43205dfa83ada/propcache-0.4.1-cp313-cp313t-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:af223b406d6d000830c6f65f1e6431783fc3f713ba3e6cc8c024d5ee96170a4b", size = 280420, upload-time = "2025-10-08T19:47:36.338Z" }, - { url = "https://files.pythonhosted.org/packages/07/0c/01f2219d39f7e53d52e5173bcb09c976609ba30209912a0680adfb8c593a/propcache-0.4.1-cp313-cp313t-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:a78372c932c90ee474559c5ddfffd718238e8673c340dc21fe45c5b8b54559a0", size = 263254, upload-time = "2025-10-08T19:47:37.692Z" }, - { url = "https://files.pythonhosted.org/packages/2d/18/cd28081658ce597898f0c4d174d4d0f3c5b6d4dc27ffafeef835c95eb359/propcache-0.4.1-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:564d9f0d4d9509e1a870c920a89b2fec951b44bf5ba7d537a9e7c1ccec2c18af", size = 261205, upload-time = "2025-10-08T19:47:39.659Z" }, - { url = "https://files.pythonhosted.org/packages/7a/71/1f9e22eb8b8316701c2a19fa1f388c8a3185082607da8e406a803c9b954e/propcache-0.4.1-cp313-cp313t-musllinux_1_2_armv7l.whl", hash = "sha256:17612831fda0138059cc5546f4d12a2aacfb9e47068c06af35c400ba58ba7393", size = 247873, upload-time = "2025-10-08T19:47:41.084Z" }, - { url = "https://files.pythonhosted.org/packages/4a/65/3d4b61f36af2b4eddba9def857959f1016a51066b4f1ce348e0cf7881f58/propcache-0.4.1-cp313-cp313t-musllinux_1_2_ppc64le.whl", hash = "sha256:41a89040cb10bd345b3c1a873b2bf36413d48da1def52f268a055f7398514874", size = 262739, upload-time = "2025-10-08T19:47:42.51Z" }, - { url = "https://files.pythonhosted.org/packages/2a/42/26746ab087faa77c1c68079b228810436ccd9a5ce9ac85e2b7307195fd06/propcache-0.4.1-cp313-cp313t-musllinux_1_2_s390x.whl", hash = "sha256:e35b88984e7fa64aacecea39236cee32dd9bd8c55f57ba8a75cf2399553f9bd7", size = 263514, upload-time = "2025-10-08T19:47:43.927Z" }, - { url = "https://files.pythonhosted.org/packages/94/13/630690fe201f5502d2403dd3cfd451ed8858fe3c738ee88d095ad2ff407b/propcache-0.4.1-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:6f8b465489f927b0df505cbe26ffbeed4d6d8a2bbc61ce90eb074ff129ef0ab1", size = 257781, upload-time = "2025-10-08T19:47:45.448Z" }, - { url = "https://files.pythonhosted.org/packages/92/f7/1d4ec5841505f423469efbfc381d64b7b467438cd5a4bbcbb063f3b73d27/propcache-0.4.1-cp313-cp313t-win32.whl", hash = "sha256:2ad890caa1d928c7c2965b48f3a3815c853180831d0e5503d35cf00c472f4717", size = 41396, upload-time = "2025-10-08T19:47:47.202Z" }, - { url = "https://files.pythonhosted.org/packages/48/f0/615c30622316496d2cbbc29f5985f7777d3ada70f23370608c1d3e081c1f/propcache-0.4.1-cp313-cp313t-win_amd64.whl", hash = "sha256:f7ee0e597f495cf415bcbd3da3caa3bd7e816b74d0d52b8145954c5e6fd3ff37", size = 44897, upload-time = "2025-10-08T19:47:48.336Z" }, - { url = "https://files.pythonhosted.org/packages/fd/ca/6002e46eccbe0e33dcd4069ef32f7f1c9e243736e07adca37ae8c4830ec3/propcache-0.4.1-cp313-cp313t-win_arm64.whl", hash = "sha256:929d7cbe1f01bb7baffb33dc14eb5691c95831450a26354cd210a8155170c93a", size = 39789, upload-time = "2025-10-08T19:47:49.876Z" }, - { url = "https://files.pythonhosted.org/packages/8e/5c/bca52d654a896f831b8256683457ceddd490ec18d9ec50e97dfd8fc726a8/propcache-0.4.1-cp314-cp314-macosx_10_13_universal2.whl", hash = "sha256:3f7124c9d820ba5548d431afb4632301acf965db49e666aa21c305cbe8c6de12", size = 78152, upload-time = "2025-10-08T19:47:51.051Z" }, - { url = "https://files.pythonhosted.org/packages/65/9b/03b04e7d82a5f54fb16113d839f5ea1ede58a61e90edf515f6577c66fa8f/propcache-0.4.1-cp314-cp314-macosx_10_13_x86_64.whl", hash = "sha256:c0d4b719b7da33599dfe3b22d3db1ef789210a0597bc650b7cee9c77c2be8c5c", size = 44869, upload-time = "2025-10-08T19:47:52.594Z" }, - { url = "https://files.pythonhosted.org/packages/b2/fa/89a8ef0468d5833a23fff277b143d0573897cf75bd56670a6d28126c7d68/propcache-0.4.1-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:9f302f4783709a78240ebc311b793f123328716a60911d667e0c036bc5dcbded", size = 46596, upload-time = "2025-10-08T19:47:54.073Z" }, - { url = "https://files.pythonhosted.org/packages/86/bd/47816020d337f4a746edc42fe8d53669965138f39ee117414c7d7a340cfe/propcache-0.4.1-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:c80ee5802e3fb9ea37938e7eecc307fb984837091d5fd262bb37238b1ae97641", size = 206981, upload-time = "2025-10-08T19:47:55.715Z" }, - { url = "https://files.pythonhosted.org/packages/df/f6/c5fa1357cc9748510ee55f37173eb31bfde6d94e98ccd9e6f033f2fc06e1/propcache-0.4.1-cp314-cp314-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:ed5a841e8bb29a55fb8159ed526b26adc5bdd7e8bd7bf793ce647cb08656cdf4", size = 211490, upload-time = "2025-10-08T19:47:57.499Z" }, - { url = "https://files.pythonhosted.org/packages/80/1e/e5889652a7c4a3846683401a48f0f2e5083ce0ec1a8a5221d8058fbd1adf/propcache-0.4.1-cp314-cp314-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:55c72fd6ea2da4c318e74ffdf93c4fe4e926051133657459131a95c846d16d44", size = 215371, upload-time = "2025-10-08T19:47:59.317Z" }, - { url = "https://files.pythonhosted.org/packages/b2/f2/889ad4b2408f72fe1a4f6a19491177b30ea7bf1a0fd5f17050ca08cfc882/propcache-0.4.1-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:8326e144341460402713f91df60ade3c999d601e7eb5ff8f6f7862d54de0610d", size = 201424, upload-time = "2025-10-08T19:48:00.67Z" }, - { url = "https://files.pythonhosted.org/packages/27/73/033d63069b57b0812c8bd19f311faebeceb6ba31b8f32b73432d12a0b826/propcache-0.4.1-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:060b16ae65bc098da7f6d25bf359f1f31f688384858204fe5d652979e0015e5b", size = 197566, upload-time = "2025-10-08T19:48:02.604Z" }, - { url = "https://files.pythonhosted.org/packages/dc/89/ce24f3dc182630b4e07aa6d15f0ff4b14ed4b9955fae95a0b54c58d66c05/propcache-0.4.1-cp314-cp314-musllinux_1_2_armv7l.whl", hash = "sha256:89eb3fa9524f7bec9de6e83cf3faed9d79bffa560672c118a96a171a6f55831e", size = 193130, upload-time = "2025-10-08T19:48:04.499Z" }, - { url = "https://files.pythonhosted.org/packages/a9/24/ef0d5fd1a811fb5c609278d0209c9f10c35f20581fcc16f818da959fc5b4/propcache-0.4.1-cp314-cp314-musllinux_1_2_ppc64le.whl", hash = "sha256:dee69d7015dc235f526fe80a9c90d65eb0039103fe565776250881731f06349f", size = 202625, upload-time = "2025-10-08T19:48:06.213Z" }, - { url = "https://files.pythonhosted.org/packages/f5/02/98ec20ff5546f68d673df2f7a69e8c0d076b5abd05ca882dc7ee3a83653d/propcache-0.4.1-cp314-cp314-musllinux_1_2_s390x.whl", hash = "sha256:5558992a00dfd54ccbc64a32726a3357ec93825a418a401f5cc67df0ac5d9e49", size = 204209, upload-time = "2025-10-08T19:48:08.432Z" }, - { url = "https://files.pythonhosted.org/packages/a0/87/492694f76759b15f0467a2a93ab68d32859672b646aa8a04ce4864e7932d/propcache-0.4.1-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:c9b822a577f560fbd9554812526831712c1436d2c046cedee4c3796d3543b144", size = 197797, upload-time = "2025-10-08T19:48:09.968Z" }, - { url = "https://files.pythonhosted.org/packages/ee/36/66367de3575db1d2d3f3d177432bd14ee577a39d3f5d1b3d5df8afe3b6e2/propcache-0.4.1-cp314-cp314-win32.whl", hash = "sha256:ab4c29b49d560fe48b696cdcb127dd36e0bc2472548f3bf56cc5cb3da2b2984f", size = 38140, upload-time = "2025-10-08T19:48:11.232Z" }, - { url = "https://files.pythonhosted.org/packages/0c/2a/a758b47de253636e1b8aef181c0b4f4f204bf0dd964914fb2af90a95b49b/propcache-0.4.1-cp314-cp314-win_amd64.whl", hash = "sha256:5a103c3eb905fcea0ab98be99c3a9a5ab2de60228aa5aceedc614c0281cf6153", size = 41257, upload-time = "2025-10-08T19:48:12.707Z" }, - { url = "https://files.pythonhosted.org/packages/34/5e/63bd5896c3fec12edcbd6f12508d4890d23c265df28c74b175e1ef9f4f3b/propcache-0.4.1-cp314-cp314-win_arm64.whl", hash = "sha256:74c1fb26515153e482e00177a1ad654721bf9207da8a494a0c05e797ad27b992", size = 38097, upload-time = "2025-10-08T19:48:13.923Z" }, - { url = "https://files.pythonhosted.org/packages/99/85/9ff785d787ccf9bbb3f3106f79884a130951436f58392000231b4c737c80/propcache-0.4.1-cp314-cp314t-macosx_10_13_universal2.whl", hash = "sha256:824e908bce90fb2743bd6b59db36eb4f45cd350a39637c9f73b1c1ea66f5b75f", size = 81455, upload-time = "2025-10-08T19:48:15.16Z" }, - { url = "https://files.pythonhosted.org/packages/90/85/2431c10c8e7ddb1445c1f7c4b54d886e8ad20e3c6307e7218f05922cad67/propcache-0.4.1-cp314-cp314t-macosx_10_13_x86_64.whl", hash = "sha256:c2b5e7db5328427c57c8e8831abda175421b709672f6cfc3d630c3b7e2146393", size = 46372, upload-time = "2025-10-08T19:48:16.424Z" }, - { url = "https://files.pythonhosted.org/packages/01/20/b0972d902472da9bcb683fa595099911f4d2e86e5683bcc45de60dd05dc3/propcache-0.4.1-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:6f6ff873ed40292cd4969ef5310179afd5db59fdf055897e282485043fc80ad0", size = 48411, upload-time = "2025-10-08T19:48:17.577Z" }, - { url = "https://files.pythonhosted.org/packages/e2/e3/7dc89f4f21e8f99bad3d5ddb3a3389afcf9da4ac69e3deb2dcdc96e74169/propcache-0.4.1-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:49a2dc67c154db2c1463013594c458881a069fcf98940e61a0569016a583020a", size = 275712, upload-time = "2025-10-08T19:48:18.901Z" }, - { url = "https://files.pythonhosted.org/packages/20/67/89800c8352489b21a8047c773067644e3897f02ecbbd610f4d46b7f08612/propcache-0.4.1-cp314-cp314t-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:005f08e6a0529984491e37d8dbc3dd86f84bd78a8ceb5fa9a021f4c48d4984be", size = 273557, upload-time = "2025-10-08T19:48:20.762Z" }, - { url = "https://files.pythonhosted.org/packages/e2/a1/b52b055c766a54ce6d9c16d9aca0cad8059acd9637cdf8aa0222f4a026ef/propcache-0.4.1-cp314-cp314t-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:5c3310452e0d31390da9035c348633b43d7e7feb2e37be252be6da45abd1abcc", size = 280015, upload-time = "2025-10-08T19:48:22.592Z" }, - { url = "https://files.pythonhosted.org/packages/48/c8/33cee30bd890672c63743049f3c9e4be087e6780906bfc3ec58528be59c1/propcache-0.4.1-cp314-cp314t-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:4c3c70630930447f9ef1caac7728c8ad1c56bc5015338b20fed0d08ea2480b3a", size = 262880, upload-time = "2025-10-08T19:48:23.947Z" }, - { url = "https://files.pythonhosted.org/packages/0c/b1/8f08a143b204b418285c88b83d00edbd61afbc2c6415ffafc8905da7038b/propcache-0.4.1-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:8e57061305815dfc910a3634dcf584f08168a8836e6999983569f51a8544cd89", size = 260938, upload-time = "2025-10-08T19:48:25.656Z" }, - { url = "https://files.pythonhosted.org/packages/cf/12/96e4664c82ca2f31e1c8dff86afb867348979eb78d3cb8546a680287a1e9/propcache-0.4.1-cp314-cp314t-musllinux_1_2_armv7l.whl", hash = "sha256:521a463429ef54143092c11a77e04056dd00636f72e8c45b70aaa3140d639726", size = 247641, upload-time = "2025-10-08T19:48:27.207Z" }, - { url = "https://files.pythonhosted.org/packages/18/ed/e7a9cfca28133386ba52278136d42209d3125db08d0a6395f0cba0c0285c/propcache-0.4.1-cp314-cp314t-musllinux_1_2_ppc64le.whl", hash = "sha256:120c964da3fdc75e3731aa392527136d4ad35868cc556fd09bb6d09172d9a367", size = 262510, upload-time = "2025-10-08T19:48:28.65Z" }, - { url = "https://files.pythonhosted.org/packages/f5/76/16d8bf65e8845dd62b4e2b57444ab81f07f40caa5652b8969b87ddcf2ef6/propcache-0.4.1-cp314-cp314t-musllinux_1_2_s390x.whl", hash = "sha256:d8f353eb14ee3441ee844ade4277d560cdd68288838673273b978e3d6d2c8f36", size = 263161, upload-time = "2025-10-08T19:48:30.133Z" }, - { url = "https://files.pythonhosted.org/packages/e7/70/c99e9edb5d91d5ad8a49fa3c1e8285ba64f1476782fed10ab251ff413ba1/propcache-0.4.1-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:ab2943be7c652f09638800905ee1bab2c544e537edb57d527997a24c13dc1455", size = 257393, upload-time = "2025-10-08T19:48:31.567Z" }, - { url = "https://files.pythonhosted.org/packages/08/02/87b25304249a35c0915d236575bc3574a323f60b47939a2262b77632a3ee/propcache-0.4.1-cp314-cp314t-win32.whl", hash = "sha256:05674a162469f31358c30bcaa8883cb7829fa3110bf9c0991fe27d7896c42d85", size = 42546, upload-time = "2025-10-08T19:48:32.872Z" }, - { url = "https://files.pythonhosted.org/packages/cb/ef/3c6ecf8b317aa982f309835e8f96987466123c6e596646d4e6a1dfcd080f/propcache-0.4.1-cp314-cp314t-win_amd64.whl", hash = "sha256:990f6b3e2a27d683cb7602ed6c86f15ee6b43b1194736f9baaeb93d0016633b1", size = 46259, upload-time = "2025-10-08T19:48:34.226Z" }, - { url = "https://files.pythonhosted.org/packages/c4/2d/346e946d4951f37eca1e4f55be0f0174c52cd70720f84029b02f296f4a38/propcache-0.4.1-cp314-cp314t-win_arm64.whl", hash = "sha256:ecef2343af4cc68e05131e45024ba34f6095821988a9d0a02aa7c73fcc448aa9", size = 40428, upload-time = "2025-10-08T19:48:35.441Z" }, - { url = "https://files.pythonhosted.org/packages/5b/5a/bc7b4a4ef808fa59a816c17b20c4bef6884daebbdf627ff2a161da67da19/propcache-0.4.1-py3-none-any.whl", hash = "sha256:af2a6052aeb6cf17d3e46ee169099044fd8224cbaf75c76a2ef596e8163e2237", size = 13305, upload-time = "2025-10-08T19:49:00.792Z" }, -] - [[package]] name = "protobuf" version = "6.33.5" @@ -3829,19 +2874,19 @@ email = [ [[package]] name = "pydantic-ai" -version = "1.107.0" +version = "2.1.0" source = { registry = "https://pypi.org/simple" } dependencies = [ - { name = "pydantic-ai-slim", extra = ["ag-ui", "anthropic", "bedrock", "cli", "cohere", "evals", "fastmcp", "google", "groq", "huggingface", "logfire", "mcp", "mistral", "openai", "retries", "spec", "temporal", "ui", "vertexai", "xai"] }, + { name = "pydantic-ai-slim", extra = ["anthropic", "cli", "evals", "google", "logfire", "mcp", "openai", "retries", "web"] }, ] -sdist = { url = "https://files.pythonhosted.org/packages/17/71/7132293bc7ce791d8f3ee7f56b696b216a104bb30a08113f7b3db30a0c9a/pydantic_ai-1.107.0.tar.gz", hash = "sha256:254496d18451b2750a4dddc2591c6c42f25dd223d02ca4252812ab06e75f1044", size = 18414, upload-time = "2026-06-10T14:53:08.678Z" } +sdist = { url = "https://files.pythonhosted.org/packages/14/2e/e393160043ee999c501c95f27dcb6439eec3092eca7d75b94f06165905a8/pydantic_ai-2.1.0.tar.gz", hash = "sha256:6279657f7640df3765a9faab9d9fa25b33c58caf20d67c6189dd5469dbbbb782", size = 18451, upload-time = "2026-06-29T09:51:16.374Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/65/38/db37ab59fced191a75babbbbe99470e512c91fe730b27d113e3280fdbe44/pydantic_ai-1.107.0-py3-none-any.whl", hash = "sha256:e031880b44ad7ce3836b2f6aa8ce2a0bd733cdb0b89a34adba647e96ddcba788", size = 7588, upload-time = "2026-06-10T14:53:00.57Z" }, + { url = "https://files.pythonhosted.org/packages/c7/dc/7cfa843db74fefdba995a2e21fe602e725e2ba77b0d7bc402bc62c1bf2d7/pydantic_ai-2.1.0-py3-none-any.whl", hash = "sha256:001272126e78f982805b1a4ac7e7805da10c88c4f28f9e4b905e923cfc1192d5", size = 7700, upload-time = "2026-06-29T09:51:07.83Z" }, ] [[package]] name = "pydantic-ai-slim" -version = "1.107.0" +version = "2.1.0" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "exceptiongroup", marker = "python_full_version < '3.11'" }, @@ -3853,22 +2898,15 @@ dependencies = [ { name = "pydantic-graph" }, { name = "typing-inspection" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/4c/26/ced63dfaabbc77f3beb86d59689cdea748e7ccffb6b419dbaf4780f211e8/pydantic_ai_slim-1.107.0.tar.gz", hash = "sha256:4616f689a92fcfecfecf2a7af27aca22f139a873cf6d7a8929eaeee9c0eedbb4", size = 779902, upload-time = "2026-06-10T14:53:10.574Z" } +sdist = { url = "https://files.pythonhosted.org/packages/ca/d1/78fd15c9c68b95ac0bec2d2afe22feb3b2f46e4b8e3a6dd1cead61cde434/pydantic_ai_slim-2.1.0.tar.gz", hash = "sha256:f79dca2429dbb9d2e32a0e2c613cfb9b9d6f0dc81d42cff8a5c81ede8ca0a6c7", size = 738698, upload-time = "2026-06-29T09:51:18.634Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/15/57/71044e17f931b08cc3930bc0fe5a1e1fd37fa474ae826be004729ef1cb4a/pydantic_ai_slim-1.107.0-py3-none-any.whl", hash = "sha256:1af49bbae06a6c598f72c54d4734ba377100cac493c9a05fa8e089bebeae0da6", size = 964046, upload-time = "2026-06-10T14:53:03.333Z" }, + { url = "https://files.pythonhosted.org/packages/5e/c7/b531cf65a1f8b221ab39739a16fe08f7b6a56fd24db875b9c33010320c9c/pydantic_ai_slim-2.1.0-py3-none-any.whl", hash = "sha256:2afda56459606226113ab433ee659aac7ff29bb66feefa716c67144bd82e5ce2", size = 910109, upload-time = "2026-06-29T09:51:11.016Z" }, ] [package.optional-dependencies] -ag-ui = [ - { name = "ag-ui-protocol" }, - { name = "starlette" }, -] anthropic = [ { name = "anthropic" }, ] -bedrock = [ - { name = "boto3" }, -] cli = [ { name = "argcomplete" }, { name = "prompt-toolkit" }, @@ -3876,34 +2914,18 @@ cli = [ { name = "pyyaml" }, { name = "rich" }, ] -cohere = [ - { name = "cohere", marker = "sys_platform != 'emscripten'" }, -] evals = [ { name = "pydantic-evals" }, ] -fastmcp = [ - { name = "fastmcp" }, -] google = [ { name = "google-genai" }, ] -groq = [ - { name = "groq" }, -] -huggingface = [ - { name = "hf-xet", marker = "platform_machine == 'AMD64' or platform_machine == 'aarch64' or platform_machine == 'amd64' or platform_machine == 'arm64' or platform_machine == 'x86_64'" }, - { name = "huggingface-hub" }, -] logfire = [ { name = "logfire", extra = ["httpx"] }, ] mcp = [ { name = "fastmcp-slim", extra = ["client"] }, ] -mistral = [ - { name = "mistralai" }, -] openai = [ { name = "openai" }, { name = "tiktoken" }, @@ -3911,22 +2933,10 @@ openai = [ retries = [ { name = "tenacity" }, ] -spec = [ - { name = "pydantic-handlebars" }, - { name = "pyyaml" }, -] -temporal = [ - { name = "temporalio" }, -] -ui = [ +web = [ + { name = "httpx" }, { name = "starlette" }, -] -vertexai = [ - { name = "google-auth" }, - { name = "requests" }, -] -xai = [ - { name = "xai-sdk" }, + { name = "uvicorn" }, ] [[package]] @@ -4047,7 +3057,7 @@ wheels = [ [[package]] name = "pydantic-evals" -version = "1.107.0" +version = "2.1.0" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "anyio" }, @@ -4057,9 +3067,9 @@ dependencies = [ { name = "pyyaml" }, { name = "rich" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/26/ad/f33306cf668d33cabce8af5e82b58ae367cc8422a2078c2df13327c13532/pydantic_evals-1.107.0.tar.gz", hash = "sha256:153378eda4847d48ca5e6b995e6221e5f0e4f4641771a1eed244fa2065923b27", size = 78546, upload-time = "2026-06-10T14:53:12.01Z" } +sdist = { url = "https://files.pythonhosted.org/packages/7b/d6/d2a315322052fa849cb1008c18ac43688e06e1059573cd424cfd20d49be5/pydantic_evals-2.1.0.tar.gz", hash = "sha256:58e72ceba61ba673f074b58f057413dc8d3393720767c89969681d2e4f4067a4", size = 76016, upload-time = "2026-06-29T09:51:19.798Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/23/ea/ecdaab037479f3b26c0efd47598f7caaad506fc53837196c1cf7e4701263/pydantic_evals-1.107.0-py3-none-any.whl", hash = "sha256:2df2f6deb82226f0404137ebecf9389c2270e08e30c066e239ae9090173826ec", size = 93586, upload-time = "2026-06-10T14:53:05.362Z" }, + { url = "https://files.pythonhosted.org/packages/80/7b/59f9d4f865e2f518179a3a42986e4e8785b70c98ec180c8da10fd78c02a6/pydantic_evals-2.1.0-py3-none-any.whl", hash = "sha256:6c9fc370808d883c20477ce69a6d6bc0b9c5a8d3dab66be5dd85d960a3f88d23", size = 90590, upload-time = "2026-06-29T09:51:12.816Z" }, ] [[package]] @@ -4077,7 +3087,7 @@ wheels = [ [[package]] name = "pydantic-graph" -version = "1.107.0" +version = "2.1.0" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "httpx" }, @@ -4085,21 +3095,9 @@ dependencies = [ { name = "pydantic" }, { name = "typing-inspection" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/dd/c3/6e8c2d13b8701041f1b3eac5deb41f25d4dbfa479a190d5c6becc23f2a49/pydantic_graph-1.107.0.tar.gz", hash = "sha256:278dd89b3e33f3a2963ac949f27a53aef705c5d883a8ce5d06d23e6e3cfbd972", size = 62564, upload-time = "2026-06-10T14:53:13.366Z" } +sdist = { url = "https://files.pythonhosted.org/packages/39/20/018532c826aba3c29ffc37bda46c20f3db4584bb555a8c7dc2769866267d/pydantic_graph-2.1.0.tar.gz", hash = "sha256:36ed6af24543421fb628fee593ccf5553a286c1dd1677018f5064a4e44c4daba", size = 43052, upload-time = "2026-06-29T09:51:20.832Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/fc/72/621556e3f5068400d43a0375d38e5963de30256eaa5a702aba12e82ed0ff/pydantic_graph-1.107.0-py3-none-any.whl", hash = "sha256:71add94fe7e14c703977a895117c475aae6c0b02a774a036c4d00d9a63c78b00", size = 80106, upload-time = "2026-06-10T14:53:06.543Z" }, -] - -[[package]] -name = "pydantic-handlebars" -version = "0.1.0" -source = { registry = "https://pypi.org/simple" } -dependencies = [ - { name = "pydantic" }, -] -sdist = { url = "https://files.pythonhosted.org/packages/90/16/d41768bd3fd77e6250c20be11a3e68fee5fff07c3356455e6708f6a60f2a/pydantic_handlebars-0.1.0.tar.gz", hash = "sha256:1931c54946add1b5e3796c9bf6a005ed7662cef0109bb05c352f0b3d031a1260", size = 159826, upload-time = "2026-03-01T20:00:17.497Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/99/5f/86b1630be61bdebf253c2f953a6c3f073ec21bb0725565ea3896802e1ca3/pydantic_handlebars-0.1.0-py3-none-any.whl", hash = "sha256:8a436fe8bc607295eb04bec58bd6e2c9498c9e069c557ff0b505e3d568c783bc", size = 40890, upload-time = "2026-03-01T20:00:16.106Z" }, + { url = "https://files.pythonhosted.org/packages/42/a8/7f32bdeda6cff28652bba1c21ab2155c81d1733abd4b8bfef46a26e8d3fe/pydantic_graph-2.1.0-py3-none-any.whl", hash = "sha256:bae1e99829abf590a8693442ba5693ace38d2d93a80ae48be55c610a503e3709", size = 50772, upload-time = "2026-06-29T09:51:14.161Z" }, ] [[package]] @@ -4699,19 +3697,6 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/ef/45/615f5babd880b4bd7d405cc0dc348234c5ffb6ed1ea33e152ede08b2072d/rich-14.3.2-py3-none-any.whl", hash = "sha256:08e67c3e90884651da3239ea668222d19bea7b589149d8014a21c633420dbb69", size = 309963, upload-time = "2026-02-01T16:20:46.078Z" }, ] -[[package]] -name = "rich-rst" -version = "1.3.2" -source = { registry = "https://pypi.org/simple" } -dependencies = [ - { name = "docutils" }, - { name = "rich" }, -] -sdist = { url = "https://files.pythonhosted.org/packages/bc/6d/a506aaa4a9eaa945ed8ab2b7347859f53593864289853c5d6d62b77246e0/rich_rst-1.3.2.tar.gz", hash = "sha256:a1196fdddf1e364b02ec68a05e8ff8f6914fee10fbca2e6b6735f166bb0da8d4", size = 14936, upload-time = "2025-10-14T16:49:45.332Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/13/2f/b4530fbf948867702d0a3f27de4a6aab1d156f406d72852ab902c4d04de9/rich_rst-1.3.2-py3-none-any.whl", hash = "sha256:a99b4907cbe118cf9d18b0b44de272efa61f15117c61e39ebdc431baf5df722a", size = 12567, upload-time = "2025-10-14T16:49:42.953Z" }, -] - [[package]] name = "rich-toolkit" version = "0.18.1" @@ -4971,39 +3956,27 @@ wheels = [ [[package]] name = "ruff" -version = "0.15.18" -source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/74/98/1295ad5a5aa9bc85bdcdfa5d82fe7b49c61af5657df4f227637ff9de0da6/ruff-0.15.18.tar.gz", hash = "sha256:2698a964c70e8bf402dcb99c8810472d270d141e7aa8c4e13599fd52033a2f33", size = 4761437, upload-time = "2026-06-18T18:25:39.224Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/b9/d0/686e984941269621e2be72612d5c1e461f8f7b38415a2a7d7a81c8ae6715/ruff-0.15.18-py3-none-linux_armv6l.whl", hash = "sha256:8b6850172348c8381b8b3084c5915a4393c2373b9b54cd5b5e1ea15812bc10df", size = 10887308, upload-time = "2026-06-18T18:25:03.062Z" }, - { url = "https://files.pythonhosted.org/packages/ed/21/bc4123e3f5515ee99f8ce1eb93a14a0628fe4d1678663cd08f933ac16931/ruff-0.15.18-py3-none-macosx_10_12_x86_64.whl", hash = "sha256:3fccc153a85417dcd976883160cacce486997b0a0058dd18f54b8aaaac7d1ce2", size = 11281305, upload-time = "2026-06-18T18:25:30.026Z" }, - { url = "https://files.pythonhosted.org/packages/51/93/4769464c25cf7ab2acb3c7dda9cad3d867eb41c59565b3e2a9d17249c90c/ruff-0.15.18-py3-none-macosx_11_0_arm64.whl", hash = "sha256:08d4c86a68f2c3ec2c9d56380a71fb4a4f65373055cbb8caabd645e9102f38d4", size = 10641215, upload-time = "2026-06-18T18:25:15.802Z" }, - { url = "https://files.pythonhosted.org/packages/6c/42/56926d17120db2c208d76bf60a1a019644dd9e91dc27f0f95c9caddb1366/ruff-0.15.18-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:37e5108745c2c0705da916d7d4de533ddf547051ef45f62888c31bae73f66318", size = 10957224, upload-time = "2026-06-18T18:25:36.955Z" }, - { url = "https://files.pythonhosted.org/packages/22/4f/d43fab8d8189afde803103022d000a8ef9f230616d436d52a8b2b8d63b50/ruff-0.15.18-py3-none-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:56949a6ce8b3abde54c0bcb22cebfe57e8771cadc84b407ae8b8eaf67ebdcd43", size = 10699024, upload-time = "2026-06-18T18:25:05.707Z" }, - { url = "https://files.pythonhosted.org/packages/63/42/1e3e4c68bd408b9768cf3e439acbe2c78245225faef253f7028a0cdb63e0/ruff-0.15.18-py3-none-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:01a754cd6a1b630d3f97e33eb452cf7a98040482318e870f8bc52a5a30e62657", size = 11491458, upload-time = "2026-06-18T18:25:20.275Z" }, - { url = "https://files.pythonhosted.org/packages/20/77/47a3484bea8521e14a203d98c389c5c97846675e4f02734672da4a69b52a/ruff-0.15.18-py3-none-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:6ba7a07e03a44dbf10bb086ee06705b173625014ec99f73a7e6836a5e5590a0c", size = 12383752, upload-time = "2026-06-18T18:25:22.535Z" }, - { url = "https://files.pythonhosted.org/packages/0a/ca/054159590787023d83b658a1a1819c4c8910114e7015069340b71c0961cb/ruff-0.15.18-py3-none-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:5a2c40a41a4cadbcf5897b548ab29dfe248b20c540961c0247d98a3973c70403", size = 11577923, upload-time = "2026-06-18T18:25:10.702Z" }, - { url = "https://files.pythonhosted.org/packages/6d/ff/d353d6b7bbd73cc0ec37f4463d7540e45e894338abdd9964eee0de332708/ruff-0.15.18-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:5f0480ce690cbb6c4db6e5d08f19fce98e10ba131a8b60c1bcdac42771e3ae2d", size = 11583925, upload-time = "2026-06-18T18:25:32.391Z" }, - { url = "https://files.pythonhosted.org/packages/c1/4a/891f89b9c296ed3e5f3ece1a5629badc989d9a8fdaa30431aaf4774bc1c2/ruff-0.15.18-py3-none-manylinux_2_31_riscv64.whl", hash = "sha256:2330215f1f393fa8733f55edce04fcf94c36a2c460fcde31f78cc84e4951e9b1", size = 11582834, upload-time = "2026-06-18T18:25:27.309Z" }, - { url = "https://files.pythonhosted.org/packages/32/a3/ed9e370154bf85de360b93c03026157f02d4943b2d01ff4945f4429f8e8a/ruff-0.15.18-py3-none-musllinux_1_2_aarch64.whl", hash = "sha256:a6aa6a3d979e48ae617578183674bf264fbe7d0114a796a26bd678d67963c7ff", size = 10927328, upload-time = "2026-06-18T18:25:34.676Z" }, - { url = "https://files.pythonhosted.org/packages/f5/d1/5cf5909329fedb5d39d555ee818ba5cf4638e1a301b89785d34f2905bfcb/ruff-0.15.18-py3-none-musllinux_1_2_armv7l.whl", hash = "sha256:a81beadbbff2c9c245561ae3f77b16709d87f35eec650d0501679239d3449b22", size = 10693187, upload-time = "2026-06-18T18:25:08.245Z" }, - { url = "https://files.pythonhosted.org/packages/fd/44/ff6c635cf2c4f4e7b618b6640da057376baa36014695487d88aed4794268/ruff-0.15.18-py3-none-musllinux_1_2_i686.whl", hash = "sha256:2186d9e940ae332ab293623a75b5f4fe49565f449954d50a72a046683aa6b809", size = 11208721, upload-time = "2026-06-18T18:25:41.327Z" }, - { url = "https://files.pythonhosted.org/packages/88/d9/5baa2a30861adfb7022cf33c1e35b2fc18085b08c16f83eff4c7b99a5f48/ruff-0.15.18-py3-none-musllinux_1_2_x86_64.whl", hash = "sha256:5c2abf140438032bc77b2284a6c9944ecd8a19e5f1c7b52b1b8e4a0a80d19a7a", size = 11678599, upload-time = "2026-06-18T18:25:13.607Z" }, - { url = "https://files.pythonhosted.org/packages/c3/1a/0725a7cfdc32ff769efb96ee782bec882e16448c5d9e3be947ec4c04ce27/ruff-0.15.18-py3-none-win32.whl", hash = "sha256:02299e6e9fa5b297a3f6d5d10d7bcd655c925b028bb8b9d4588214549c6b9ec4", size = 10901903, upload-time = "2026-06-18T18:25:24.755Z" }, - { url = "https://files.pythonhosted.org/packages/f3/51/805d9f6fb7970505c3504794a5ec350f605361b807fef4dcf214ebd35e72/ruff-0.15.18-py3-none-win_amd64.whl", hash = "sha256:dac80dc8d26b2257dbefabed62f5d255c3937b4ccb122da1fc634794fa3578b3", size = 12041189, upload-time = "2026-06-18T18:25:17.915Z" }, - { url = "https://files.pythonhosted.org/packages/29/4c/67bb45e41609eb4726f1bfeb59e083cf91d14c696d4bd14c234a980be93d/ruff-0.15.18-py3-none-win_arm64.whl", hash = "sha256:b2c9257fcbd4a3e5b977a1904e6facca016bafe2edc17df24db67cfaee03b4e4", size = 11329958, upload-time = "2026-06-18T18:25:43.686Z" }, -] - -[[package]] -name = "s3transfer" -version = "0.16.0" -source = { registry = "https://pypi.org/simple" } -dependencies = [ - { name = "botocore" }, -] -sdist = { url = "https://files.pythonhosted.org/packages/05/04/74127fc843314818edfa81b5540e26dd537353b123a4edc563109d8f17dd/s3transfer-0.16.0.tar.gz", hash = "sha256:8e990f13268025792229cd52fa10cb7163744bf56e719e0b9cb925ab79abf920", size = 153827, upload-time = "2025-12-01T02:30:59.114Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/fc/51/727abb13f44c1fcf6d145979e1535a35794db0f6e450a0cb46aa24732fe2/s3transfer-0.16.0-py3-none-any.whl", hash = "sha256:18e25d66fed509e3868dc1572b3f427ff947dd2c56f844a5bf09481ad3f3b2fe", size = 86830, upload-time = "2025-12-01T02:30:57.729Z" }, +version = "0.15.20" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/43/dc/35b341fc554ba02f217fc10da57d1a75168cfbcf75b0ef2202176d4c4f2d/ruff-0.15.20.tar.gz", hash = "sha256:1416eb04349192646b54de98f146c4f59afe37d0decfc02c3cbbf396f3a28566", size = 4755489, upload-time = "2026-06-25T17:20:37.578Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/94/d9/2d5014f0253ba541d2061d9fa7193f48e941c8b21bb88a7ff9bbe0bd0596/ruff-0.15.20-py3-none-linux_armv6l.whl", hash = "sha256:00e188c53e499c3c1637f73c91dcf2fb56d576cab76ce1be50a27c4e80e37078", size = 10839665, upload-time = "2026-06-25T17:19:44.702Z" }, + { url = "https://files.pythonhosted.org/packages/c6/d3/ac1798ba64f670698867fcfc591d50e7e421bef137db564858f619a30fcf/ruff-0.15.20-py3-none-macosx_10_12_x86_64.whl", hash = "sha256:9ebd1fd9b9c95fc0bd7b2761aebec1f030013d2e193a2901b224af68fe47251b", size = 11208649, upload-time = "2026-06-25T17:19:48.787Z" }, + { url = "https://files.pythonhosted.org/packages/47/47/d3ac899991202095dfcf3d5176be4272642be3cf981a2f1a30f72a2afb95/ruff-0.15.20-py3-none-macosx_11_0_arm64.whl", hash = "sha256:c5b16cdd67ca108185cd36dce98c576350c03b1660a751de725fb049193a0632", size = 10622638, upload-time = "2026-06-25T17:19:51.354Z" }, + { url = "https://files.pythonhosted.org/packages/33/13/4e043fe30aa94d4ff5213a9881fc296d12960f5971b234a5263fdc225312/ruff-0.15.20-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3413bb3c3d2ca6a8208f1f4809cd2dca3c6de6d0b491c0e70847672bde6e6efd", size = 10984227, upload-time = "2026-06-25T17:19:54.044Z" }, + { url = "https://files.pythonhosted.org/packages/76/e6/92e7bf40388bc5800073b96564f56264f7e48bfd1a498f5ced6ae6d5a769/ruff-0.15.20-py3-none-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:bd7ec42b3bb3da066488db093308a69c4ac5ee6d2af333a86ba6e2eb2e7dd44b", size = 10622882, upload-time = "2026-06-25T17:19:57.037Z" }, + { url = "https://files.pythonhosted.org/packages/13/7a/43460be3f24495a3aa46d4b16873e2c4941b3b5f0b00cf88c03b7b94b339/ruff-0.15.20-py3-none-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:e1a36ad0eb77fba9aabfb69ede54de6f376d04ac18ebea022847046d340a8267", size = 11474808, upload-time = "2026-06-25T17:20:00.357Z" }, + { url = "https://files.pythonhosted.org/packages/27/a0/f37077884873221c6b33b4ab49eb18f9f88e54a16a25a5bca59bef46dd66/ruff-0.15.20-py3-none-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:b6df3b1e4610432f0386dba04d853b5f08cbbc903410c6fcc02f620f05aff53c", size = 12293094, upload-time = "2026-06-25T17:20:03.446Z" }, + { url = "https://files.pythonhosted.org/packages/a6/74/165545b60256a9704c21ac0ec4a0d07933b320812f9584836c9f4aca4292/ruff-0.15.20-py3-none-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:e89f198a1ea6ef0d727c1cf16088bc91a6cb0ab947dedc966715691647186eae", size = 11526176, upload-time = "2026-06-25T17:20:06.301Z" }, + { url = "https://files.pythonhosted.org/packages/86/b1/a976a136d40ade83ce743578399865f57001003a409acadc0ecbb3051082/ruff-0.15.20-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:309809086c2acb67624950a3c8133e80f32d0d3e27106c0cd60ff26657c9f24b", size = 11520767, upload-time = "2026-06-25T17:20:09.191Z" }, + { url = "https://files.pythonhosted.org/packages/19/0f/f032696cb01c9b54c0263fa393474d7758f1cdc021a01b04e3cbc2500999/ruff-0.15.20-py3-none-manylinux_2_31_riscv64.whl", hash = "sha256:2d2374caa2f2c2f9e2b7da0a50802cfb8b79f55a9b5e49379f564544fbf56487", size = 11500132, upload-time = "2026-06-25T17:20:13.602Z" }, + { url = "https://files.pythonhosted.org/packages/4b/f4/51b1a14bc69e8c224b15dab9cce8e99b425e0455d462caa2b3c9be2b6a8e/ruff-0.15.20-py3-none-musllinux_1_2_aarch64.whl", hash = "sha256:a1ed17b65293e0c2f22fc387bc13198a5de94bf4429589b0ff6946b0feaf21a3", size = 10943828, upload-time = "2026-06-25T17:20:16.635Z" }, + { url = "https://files.pythonhosted.org/packages/71/4b/fe267640783cd02bf6c5cc290b1df1051be2ec294c678b5c15fe19e52343/ruff-0.15.20-py3-none-musllinux_1_2_armv7l.whl", hash = "sha256:f701305e66b38ea6c91882490eb73459796808e4c6362a1b765255e0cdcd4053", size = 10645418, upload-time = "2026-06-25T17:20:19.4Z" }, + { url = "https://files.pythonhosted.org/packages/b0/c0/a65aa4ec2f5e87a1df32dc3ec1fede434fe3dfd5cbcf3b503cafc676ab54/ruff-0.15.20-py3-none-musllinux_1_2_i686.whl", hash = "sha256:5b9c0c367ad8e5d0d5b5b8537864c469a0a0e55417aadfbeca41fa61333be9f4", size = 11211770, upload-time = "2026-06-25T17:20:22.033Z" }, + { url = "https://files.pythonhosted.org/packages/5a/a4/0caa331d954ae2723d729d351c989cb4ca8b6077d5c6c2cb6de75e98c041/ruff-0.15.20-py3-none-musllinux_1_2_x86_64.whl", hash = "sha256:01cc00dd58f0df339d0e902219dd53990ea99996a0344e5d9cc8d45d5307e460", size = 11618698, upload-time = "2026-06-25T17:20:25.259Z" }, + { url = "https://files.pythonhosted.org/packages/10/9b/5f14927848d2fd4aa891fd88d883788c5a7baba561c7874732364045708c/ruff-0.15.20-py3-none-win32.whl", hash = "sha256:ed65ef510e43a137207e0f01cfcf998aeddb1aeeda5c9d35023e910284d7cf21", size = 10857322, upload-time = "2026-06-25T17:20:28.612Z" }, + { url = "https://files.pythonhosted.org/packages/fa/f0/fe47c501f9dea92a26d788ff98bb5d92ed4cb4c88792c5c88af6b697dc8e/ruff-0.15.20-py3-none-win_amd64.whl", hash = "sha256:a525c81c70fb0380344dd1d8745d8cc1c890b7fc94a58d5a07bd8eb9557b8415", size = 11993274, upload-time = "2026-06-25T17:20:31.871Z" }, + { url = "https://files.pythonhosted.org/packages/d7/2b/9555445e1201d92b3195f45cdb153a0b68f24e0a4273f6e3d5ab46e212bb/ruff-0.15.20-py3-none-win_arm64.whl", hash = "sha256:2f5b2a6d614e8700388806a14996c40fab2c47b819ef57d790a34878858ed9ca", size = 11343498, upload-time = "2026-06-25T17:20:35.03Z" }, ] [[package]] @@ -5148,16 +4121,16 @@ wheels = [ [[package]] name = "sqlmodel" -version = "0.0.38" +version = "0.0.39" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "pydantic" }, { name = "sqlalchemy" }, { name = "typing-extensions" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/64/0d/26ec1329960ea9430131fe63f63a95ea4cb8971d49c891ff7e1f3255421c/sqlmodel-0.0.38.tar.gz", hash = "sha256:d583ec237b14103809f74e8630032bc40ab68cd6b754a610f0813c56911a547b", size = 86710, upload-time = "2026-04-02T21:03:55.571Z" } +sdist = { url = "https://files.pythonhosted.org/packages/68/ee/22a0559283c3cf6048678e787ed5d4959dcd00dedd8ba4567eeae684eeb1/sqlmodel-0.0.39.tar.gz", hash = "sha256:23d8e50a8d8ee936032ed79c55023a5d618dd6bc3c510bbf4909d1a7a605a570", size = 91057, upload-time = "2026-06-25T13:01:38.475Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/72/c7/10c60af0607ab6fa136264f7f39d205932218516226d38585324ffda705d/sqlmodel-0.0.38-py3-none-any.whl", hash = "sha256:84e3fa990a77395461ded72a6c73173438ce8449d5c1c4d97fbff1b1df692649", size = 27294, upload-time = "2026-04-02T21:03:56.406Z" }, + { url = "https://files.pythonhosted.org/packages/cf/7d/b9813a582d4eb310be35e1fc7dfaae71207d7b62e9e53be314ebd251b53b/sqlmodel-0.0.39-py3-none-any.whl", hash = "sha256:90ebe92ce5cc11d7fff8dc7cb594790a102333c8fe7c14865254f6fc5c939795", size = 29680, upload-time = "2026-06-25T13:01:37.494Z" }, ] [[package]] @@ -5188,7 +4161,7 @@ wheels = [ [[package]] name = "strawberry-graphql" -version = "0.319.0" +version = "0.320.0" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "cross-web" }, @@ -5197,29 +4170,9 @@ dependencies = [ { name = "python-dateutil" }, { name = "typing-extensions" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/7f/c4/5d7cf2f2459d9a553993217212acc911bfc63f3957a45980230105e1c92e/strawberry_graphql-0.319.0.tar.gz", hash = "sha256:e9afdfe2ca745b5337d3c4909ffd612e405105af6ffc21b1766a2b9848fcfd4f", size = 227709, upload-time = "2026-06-21T14:57:38.324Z" } +sdist = { url = "https://files.pythonhosted.org/packages/44/38/95a72342ba94570a35b8cc7db6a6789378f10b69be1d77e0fb022f5079e0/strawberry_graphql-0.320.0.tar.gz", hash = "sha256:c5ee8abf7f4db00d3515e537578a5c094a4a9f3b732a959d9020c8788d3ac7c7", size = 229231, upload-time = "2026-06-27T23:11:43.262Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/d3/b4/5005afc8369dbb3f5c03dd681ac8a13a5c0b9a8c6ae13f1c0643bb815cfa/strawberry_graphql-0.319.0-py3-none-any.whl", hash = "sha256:fcd5cbe43a5d7274d91bda2261f272f57c84d39532ff58b95fadd0749d225835", size = 330534, upload-time = "2026-06-21T14:57:36.36Z" }, -] - -[[package]] -name = "temporalio" -version = "1.26.0" -source = { registry = "https://pypi.org/simple" } -dependencies = [ - { name = "nexus-rpc" }, - { name = "protobuf" }, - { name = "python-dateutil", marker = "python_full_version < '3.11'" }, - { name = "types-protobuf" }, - { name = "typing-extensions" }, -] -sdist = { url = "https://files.pythonhosted.org/packages/ae/d4/fa21150a225393f87732ed6fef3cc9735d9e751edc6be415fe6e375105c6/temporalio-1.26.0.tar.gz", hash = "sha256:f4bfb35125e6f5e8c7f7ed1277c7354d812c6fac7ed5f8dbd50536cf289aaaa7", size = 2388994, upload-time = "2026-04-15T23:43:00.911Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/1e/27/8c421c622d18cc8e034247d5d72b89e6456937344b5bec1de40abef3c085/temporalio-1.26.0-cp310-abi3-macosx_10_12_x86_64.whl", hash = "sha256:5489040c0cf621edeb36984199dd9e4fbd2b3a07d61a4f2a8da1f2cb9820ef26", size = 14221070, upload-time = "2026-04-15T23:42:26.21Z" }, - { url = "https://files.pythonhosted.org/packages/49/7c/d2b691d16ec5db87198c2e08dbfba58e286c096faee15753613a581abdce/temporalio-1.26.0-cp310-abi3-macosx_11_0_arm64.whl", hash = "sha256:b18dd85771509c19ef059a31908bcd4e6130d1f67037c4db519702f3f2ad6d4a", size = 13583991, upload-time = "2026-04-15T23:42:34.357Z" }, - { url = "https://files.pythonhosted.org/packages/05/ca/b8728451320ca9d8bb6e1680b9bd23767118f86d5b8644edf2304d533f1b/temporalio-1.26.0-cp310-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:46187d5f82ca2ae81f35ea5916a76db0e2f067210dc6b1852c3749475721946e", size = 13808036, upload-time = "2026-04-15T23:42:42.757Z" }, - { url = "https://files.pythonhosted.org/packages/cb/54/3113f5e0ac58655790abac64656373e06191b351d74bfb94692e81bd6784/temporalio-1.26.0-cp310-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:03300c3e5237443367ac61bb20bd726c656b3daa50310bdd436599d5bdc7cf97", size = 14336604, upload-time = "2026-04-15T23:42:49.851Z" }, - { url = "https://files.pythonhosted.org/packages/fd/9b/c50840a26af3587c0c8d9af04d9976743e22496996dc1a377efc75dcd316/temporalio-1.26.0-cp310-abi3-win_amd64.whl", hash = "sha256:1c4a0d82f0a3796cbf78864c799f8dca0b94cdaec68e7b8b224c859005686ec4", size = 14525849, upload-time = "2026-04-15T23:42:57.589Z" }, + { url = "https://files.pythonhosted.org/packages/db/99/f8e8919a73ae466f9740e63115f010a02fac3f2b69c02ea60c9c85d42c1a/strawberry_graphql-0.320.0-py3-none-any.whl", hash = "sha256:8ea27f43f73a1accbfd1599b37234086d26504cf60213ebb521528319ccf2309", size = 332321, upload-time = "2026-06-27T23:11:41.045Z" }, ] [[package]] @@ -5322,36 +4275,6 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/60/45/c7b5c3168458db837e8ceab06dc77824e18202679d0463f0e8f002143a97/tinycss2-1.5.1-py3-none-any.whl", hash = "sha256:3415ba0f5839c062696996998176c4a3751d18b7edaaeeb658c9ce21ec150661", size = 28404, upload-time = "2025-11-23T10:29:08.676Z" }, ] -[[package]] -name = "tokenizers" -version = "0.22.2" -source = { registry = "https://pypi.org/simple" } -dependencies = [ - { name = "huggingface-hub" }, -] -sdist = { url = "https://files.pythonhosted.org/packages/73/6f/f80cfef4a312e1fb34baf7d85c72d4411afde10978d4657f8cdd811d3ccc/tokenizers-0.22.2.tar.gz", hash = "sha256:473b83b915e547aa366d1eee11806deaf419e17be16310ac0a14077f1e28f917", size = 372115, upload-time = "2026-01-05T10:45:15.988Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/92/97/5dbfabf04c7e348e655e907ed27913e03db0923abb5dfdd120d7b25630e1/tokenizers-0.22.2-cp39-abi3-macosx_10_12_x86_64.whl", hash = "sha256:544dd704ae7238755d790de45ba8da072e9af3eea688f698b137915ae959281c", size = 3100275, upload-time = "2026-01-05T10:41:02.158Z" }, - { url = "https://files.pythonhosted.org/packages/2e/47/174dca0502ef88b28f1c9e06b73ce33500eedfac7a7692108aec220464e7/tokenizers-0.22.2-cp39-abi3-macosx_11_0_arm64.whl", hash = "sha256:1e418a55456beedca4621dbab65a318981467a2b188e982a23e117f115ce5001", size = 2981472, upload-time = "2026-01-05T10:41:00.276Z" }, - { url = "https://files.pythonhosted.org/packages/d6/84/7990e799f1309a8b87af6b948f31edaa12a3ed22d11b352eaf4f4b2e5753/tokenizers-0.22.2-cp39-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:2249487018adec45d6e3554c71d46eb39fa8ea67156c640f7513eb26f318cec7", size = 3290736, upload-time = "2026-01-05T10:40:32.165Z" }, - { url = "https://files.pythonhosted.org/packages/78/59/09d0d9ba94dcd5f4f1368d4858d24546b4bdc0231c2354aa31d6199f0399/tokenizers-0.22.2-cp39-abi3-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:25b85325d0815e86e0bac263506dd114578953b7b53d7de09a6485e4a160a7dd", size = 3168835, upload-time = "2026-01-05T10:40:38.847Z" }, - { url = "https://files.pythonhosted.org/packages/47/50/b3ebb4243e7160bda8d34b731e54dd8ab8b133e50775872e7a434e524c28/tokenizers-0.22.2-cp39-abi3-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:bfb88f22a209ff7b40a576d5324bf8286b519d7358663db21d6246fb17eea2d5", size = 3521673, upload-time = "2026-01-05T10:40:56.614Z" }, - { url = "https://files.pythonhosted.org/packages/e0/fa/89f4cb9e08df770b57adb96f8cbb7e22695a4cb6c2bd5f0c4f0ebcf33b66/tokenizers-0.22.2-cp39-abi3-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:1c774b1276f71e1ef716e5486f21e76333464f47bece56bbd554485982a9e03e", size = 3724818, upload-time = "2026-01-05T10:40:44.507Z" }, - { url = "https://files.pythonhosted.org/packages/64/04/ca2363f0bfbe3b3d36e95bf67e56a4c88c8e3362b658e616d1ac185d47f2/tokenizers-0.22.2-cp39-abi3-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:df6c4265b289083bf710dff49bc51ef252f9d5be33a45ee2bed151114a56207b", size = 3379195, upload-time = "2026-01-05T10:40:51.139Z" }, - { url = "https://files.pythonhosted.org/packages/2e/76/932be4b50ef6ccedf9d3c6639b056a967a86258c6d9200643f01269211ca/tokenizers-0.22.2-cp39-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:369cc9fc8cc10cb24143873a0d95438bb8ee257bb80c71989e3ee290e8d72c67", size = 3274982, upload-time = "2026-01-05T10:40:58.331Z" }, - { url = "https://files.pythonhosted.org/packages/1d/28/5f9f5a4cc211b69e89420980e483831bcc29dade307955cc9dc858a40f01/tokenizers-0.22.2-cp39-abi3-musllinux_1_2_aarch64.whl", hash = "sha256:29c30b83d8dcd061078b05ae0cb94d3c710555fbb44861139f9f83dcca3dc3e4", size = 9478245, upload-time = "2026-01-05T10:41:04.053Z" }, - { url = "https://files.pythonhosted.org/packages/6c/fb/66e2da4704d6aadebf8cb39f1d6d1957df667ab24cff2326b77cda0dcb85/tokenizers-0.22.2-cp39-abi3-musllinux_1_2_armv7l.whl", hash = "sha256:37ae80a28c1d3265bb1f22464c856bd23c02a05bb211e56d0c5301a435be6c1a", size = 9560069, upload-time = "2026-01-05T10:45:10.673Z" }, - { url = "https://files.pythonhosted.org/packages/16/04/fed398b05caa87ce9b1a1bb5166645e38196081b225059a6edaff6440fac/tokenizers-0.22.2-cp39-abi3-musllinux_1_2_i686.whl", hash = "sha256:791135ee325f2336f498590eb2f11dc5c295232f288e75c99a36c5dbce63088a", size = 9899263, upload-time = "2026-01-05T10:45:12.559Z" }, - { url = "https://files.pythonhosted.org/packages/05/a1/d62dfe7376beaaf1394917e0f8e93ee5f67fea8fcf4107501db35996586b/tokenizers-0.22.2-cp39-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:38337540fbbddff8e999d59970f3c6f35a82de10053206a7562f1ea02d046fa5", size = 10033429, upload-time = "2026-01-05T10:45:14.333Z" }, - { url = "https://files.pythonhosted.org/packages/fd/18/a545c4ea42af3df6effd7d13d250ba77a0a86fb20393143bbb9a92e434d4/tokenizers-0.22.2-cp39-abi3-win32.whl", hash = "sha256:a6bf3f88c554a2b653af81f3204491c818ae2ac6fbc09e76ef4773351292bc92", size = 2502363, upload-time = "2026-01-05T10:45:20.593Z" }, - { url = "https://files.pythonhosted.org/packages/65/71/0670843133a43d43070abeb1949abfdef12a86d490bea9cd9e18e37c5ff7/tokenizers-0.22.2-cp39-abi3-win_amd64.whl", hash = "sha256:c9ea31edff2968b44a88f97d784c2f16dc0729b8b143ed004699ebca91f05c48", size = 2747786, upload-time = "2026-01-05T10:45:18.411Z" }, - { url = "https://files.pythonhosted.org/packages/72/f4/0de46cfa12cdcbcd464cc59fde36912af405696f687e53a091fb432f694c/tokenizers-0.22.2-cp39-abi3-win_arm64.whl", hash = "sha256:9ce725d22864a1e965217204946f830c37876eee3b2ba6fc6255e8e903d5fcbc", size = 2612133, upload-time = "2026-01-05T10:45:17.232Z" }, - { url = "https://files.pythonhosted.org/packages/84/04/655b79dbcc9b3ac5f1479f18e931a344af67e5b7d3b251d2dcdcd7558592/tokenizers-0.22.2-pp310-pypy310_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:753d47ebd4542742ef9261d9da92cd545b2cacbb48349a1225466745bb866ec4", size = 3282301, upload-time = "2026-01-05T10:40:34.858Z" }, - { url = "https://files.pythonhosted.org/packages/46/cd/e4851401f3d8f6f45d8480262ab6a5c8cb9c4302a790a35aa14eeed6d2fd/tokenizers-0.22.2-pp310-pypy310_pp73-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:e10bf9113d209be7cd046d40fbabbaf3278ff6d18eb4da4c500443185dc1896c", size = 3161308, upload-time = "2026-01-05T10:40:40.737Z" }, - { url = "https://files.pythonhosted.org/packages/6f/6e/55553992a89982cd12d4a66dddb5e02126c58677ea3931efcbe601d419db/tokenizers-0.22.2-pp310-pypy310_pp73-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:64d94e84f6660764e64e7e0b22baa72f6cd942279fdbb21d46abd70d179f0195", size = 3718964, upload-time = "2026-01-05T10:40:46.56Z" }, - { url = "https://files.pythonhosted.org/packages/59/8c/b1c87148aa15e099243ec9f0cf9d0e970cc2234c3257d558c25a2c5304e6/tokenizers-0.22.2-pp310-pypy310_pp73-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:f01a9c019878532f98927d2bacb79bbb404b43d3437455522a00a30718cdedb5", size = 3373542, upload-time = "2026-01-05T10:40:52.803Z" }, -] - [[package]] name = "tomli" version = "2.4.0" @@ -5447,32 +4370,32 @@ wheels = [ [[package]] name = "ty" -version = "0.0.52" -source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/5d/84/4417eb08328dcc547bf407d20af5e45ec8c64a85470f388fc2d590c9200a/ty-0.0.52.tar.gz", hash = "sha256:f1191175429fea917f96f79a57773eb6e57b861ee97e9ad2d77cc7538f0f284b", size = 5973710, upload-time = "2026-06-23T01:43:31.906Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/22/8f/ba97090625c824bdb2ddac4e22e9f3568c6e5e20e75923daa49ff5254648/ty-0.0.52-py3-none-linux_armv6l.whl", hash = "sha256:5e9403d3b5c5067cef06e29f33e842b095a71479314e38e4aa5e0afe7940e4eb", size = 11956857, upload-time = "2026-06-23T01:42:43.935Z" }, - { url = "https://files.pythonhosted.org/packages/6e/d2/d8ed189611c658e567a2d267f088d5b1128ae6c80e4f40b29552679fd9e1/ty-0.0.52-py3-none-macosx_10_12_x86_64.whl", hash = "sha256:397971af92f63fd1ab244ded9f07e6a13834cf2299a53db19f20ff3076ec5998", size = 11745925, upload-time = "2026-06-23T01:42:47.85Z" }, - { url = "https://files.pythonhosted.org/packages/19/19/db06dd15512bf8e589f2bd92ddfe77a656185801e800cd73f99f12d86305/ty-0.0.52-py3-none-macosx_11_0_arm64.whl", hash = "sha256:3857ba38d5caa55be5a028c1dfda00a50fe9688a776455983f7e6f75783675e0", size = 11090262, upload-time = "2026-06-23T01:42:50.351Z" }, - { url = "https://files.pythonhosted.org/packages/c2/9a/15d3b77ad5e03b802266920bd406a321ac86be88ddbf7db058003559ccad/ty-0.0.52-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:bdb6b21947ab96cacf15384f245609439d117abfd67479d9dd9e193fc3c88332", size = 11634345, upload-time = "2026-06-23T01:42:53.164Z" }, - { url = "https://files.pythonhosted.org/packages/75/4e/a32b72b11f02e6aeda01ffa8459a6dfa3582cb1555212dc38485c36b44b0/ty-0.0.52-py3-none-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:c3acdcb7be88e2248c9ac3210fd21a7bf708ccf65365712ff860d6d2a5794295", size = 11741270, upload-time = "2026-06-23T01:42:55.996Z" }, - { url = "https://files.pythonhosted.org/packages/c6/e0/c2f4de96c2cb25ee74fc41b6bfb80f64b6f90d4e77580454860ee81dde19/ty-0.0.52-py3-none-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:186302513a72816f5253e32768a2c2f416fbc250079e1404ab6d758b963c402b", size = 12249540, upload-time = "2026-06-23T01:42:58.697Z" }, - { url = "https://files.pythonhosted.org/packages/c8/01/77d45372342983c98c1f3b26b4a8ea7139cb10b26820f0f6b37a298c9fa1/ty-0.0.52-py3-none-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:02ee1083e9fd1a8c221eaa1e7018d4bac40e7b8a9f06db724757491b2948857a", size = 12822873, upload-time = "2026-06-23T01:43:01.57Z" }, - { url = "https://files.pythonhosted.org/packages/1c/09/9bdb394da75cefd41498c86a1f357b7f319368122ac8943d457f28f02609/ty-0.0.52-py3-none-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:83cadaa3efdb3860d24eb45ee3103da0c9a4f7be73c089984e9df095545b9da5", size = 12441154, upload-time = "2026-06-23T01:43:04.129Z" }, - { url = "https://files.pythonhosted.org/packages/ea/07/969dce9b75fdfad9cad3aeae484761e57882b92a6e3d0fe8951b9427846b/ty-0.0.52-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:680738fdfdce72df8be1a213df9ed87add63e1e7705a7927bd360150cd4d749e", size = 12301402, upload-time = "2026-06-23T01:43:06.978Z" }, - { url = "https://files.pythonhosted.org/packages/0b/66/a6fc838efc21c5303d83fd1ccf2b8f0e551b8b3426c54513ea1b1499b1b9/ty-0.0.52-py3-none-manylinux_2_31_riscv64.whl", hash = "sha256:30bbe8390a4e58003f181d52c2b3e50facf6b83491c8638f9136a5b8a5a7d931", size = 12507384, upload-time = "2026-06-23T01:43:09.693Z" }, - { url = "https://files.pythonhosted.org/packages/c5/38/eb2c8c17ae3a022e5e1ca187afa5cc03fe0cc40d6dfb5404e6941c98f7af/ty-0.0.52-py3-none-musllinux_1_2_aarch64.whl", hash = "sha256:77c8699e796d37534243ea8ac54ac7f64690bf787e2894cb3be18c16ff6fc53c", size = 11600728, upload-time = "2026-06-23T01:43:12.236Z" }, - { url = "https://files.pythonhosted.org/packages/ce/3a/9f25321f6a173021bc728d158cd9e30c5ee28b62f4a20421fca3ebf3f6a5/ty-0.0.52-py3-none-musllinux_1_2_armv7l.whl", hash = "sha256:ef5c3f6e2cf649773382b9843227b62d689a0179ec1d0366159c349990ceaeb9", size = 11765676, upload-time = "2026-06-23T01:43:14.922Z" }, - { url = "https://files.pythonhosted.org/packages/fc/96/2790300be5bca3bedaa7eb143c26d02b9188685bbf9b9a6bae79e4566085/ty-0.0.52-py3-none-musllinux_1_2_i686.whl", hash = "sha256:dba4c4ee5e1b33c5ad6c965042101d09804b352a3b1482f3ad7b32ad78c22dd4", size = 11886884, upload-time = "2026-06-23T01:43:17.608Z" }, - { url = "https://files.pythonhosted.org/packages/74/06/c098d9422d297cccd27f6a8f5cf5e7eff857b62a89b4549bad9dd0759365/ty-0.0.52-py3-none-musllinux_1_2_x86_64.whl", hash = "sha256:3e2b06401af954515403f0b2bbe382ca74f09bf2993e7b64fc3c1ad96fde7948", size = 12401990, upload-time = "2026-06-23T01:43:20.267Z" }, - { url = "https://files.pythonhosted.org/packages/5c/c9/34b771d0581fbfd0dde89f869af597b3907c7e5c59439005f59f6671c7d5/ty-0.0.52-py3-none-win32.whl", hash = "sha256:6347248c640f0d71ba9c4fe5de941ec7e3df167008bdda5c2cf795055045f266", size = 11247464, upload-time = "2026-06-23T01:43:23.36Z" }, - { url = "https://files.pythonhosted.org/packages/33/b1/0c381ac39d85a885d4e2841173e9a88bf190b4f7cf7d15afd4a1d7e8c715/ty-0.0.52-py3-none-win_amd64.whl", hash = "sha256:57150a68abfea2ec4727647b26f136850695972a650587f44a4b98fc9d4a1096", size = 12385753, upload-time = "2026-06-23T01:43:26.479Z" }, - { url = "https://files.pythonhosted.org/packages/fb/1f/2744053d80ca1b350817dbf41286bac9c95491cfa437c0cc923feaf3522b/ty-0.0.52-py3-none-win_arm64.whl", hash = "sha256:c669df56e41c99ea53405191da0fd65cbcb9bb7162c676ef6f45e480c6a7da6e", size = 11695815, upload-time = "2026-06-23T01:43:29.465Z" }, +version = "0.0.55" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/08/48/f687c8d268e3581f2f104d1f2ac5944d5b5e841b3695c613b3f263e5bbf7/ty-0.0.55.tar.gz", hash = "sha256:88ca87073825a79a8327c550efcc86cec94344890244c5946f84c9e44a969f31", size = 6040230, upload-time = "2026-06-27T00:27:29.385Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/87/a3/1a90ba7e5a61c6d09adb92346ddba97668095fc257b577af433e5ac4f404/ty-0.0.55-py3-none-linux_armv6l.whl", hash = "sha256:31e83eef512d066542fe990fe1a3b814423abd1616376c54e48af7045b3e1749", size = 11677249, upload-time = "2026-06-27T00:26:52.18Z" }, + { url = "https://files.pythonhosted.org/packages/82/3a/669f9aa478c38243e213a2684db1502086026cfadc15bb1b29b7cbde030d/ty-0.0.55-py3-none-macosx_10_12_x86_64.whl", hash = "sha256:ab4bca857950608fea73e269e2da369d43e6467131de85160d68e2fa466fa248", size = 11444180, upload-time = "2026-06-27T00:26:54.576Z" }, + { url = "https://files.pythonhosted.org/packages/15/a4/6a4b2507a53ce6530c66c5b4fe0d58551eb1748ffa9e0696c32fdd55bbd4/ty-0.0.55-py3-none-macosx_11_0_arm64.whl", hash = "sha256:55032bfd31bf2c5355ee81bdc6407b144a1cc7ee41e5681dd1368e4cef2ba327", size = 10963134, upload-time = "2026-06-27T00:26:57.348Z" }, + { url = "https://files.pythonhosted.org/packages/ce/ae/a3b1a0f1cc83b7d258662cb98aa80a720c2e671d0e8fa0d17a4d5d057a7a/ty-0.0.55-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ef1e049f69ce65b3c269af67624607f435e1c32319786c1e453ef9611502f295", size = 11493517, upload-time = "2026-06-27T00:26:59.26Z" }, + { url = "https://files.pythonhosted.org/packages/0d/9f/311ce39065a979ef40a9b847f685c8e02464e53adf1671e081eea90640ca/ty-0.0.55-py3-none-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:631409975c681d5a280fc5a99b7b32e9e801f33be7567c6b42ec331362f59d7d", size = 11460590, upload-time = "2026-06-27T00:27:01.425Z" }, + { url = "https://files.pythonhosted.org/packages/cd/8f/3bf29aa77bd78aae48275153135a2052fa7d3ccdf1ecabeb99c8773abd66/ty-0.0.55-py3-none-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:e08cb0436e68b9351555ae8f2697138c9009b4d5b4ae4272232988b2a431a98f", size = 12098430, upload-time = "2026-06-27T00:27:03.596Z" }, + { url = "https://files.pythonhosted.org/packages/bc/6e/e88411a88240b94640bba06fb6d0d92b247fbeef47ee2bc71f39e58c2558/ty-0.0.55-py3-none-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:16c215ad9f823829409b94ee188cfaa4563f6e1384f6ce3fecb1db75f6c7cf7c", size = 12673086, upload-time = "2026-06-27T00:27:05.589Z" }, + { url = "https://files.pythonhosted.org/packages/6c/7e/8f1762fb7f9245a68ba5ae338d73c59403ce57554e5d311b8bb55027b0ec/ty-0.0.55-py3-none-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:b510eb8f4032baf11b7aee2f1d53babc3b4ca03939b9cdcf6a9d15761d575188", size = 12242559, upload-time = "2026-06-27T00:27:07.714Z" }, + { url = "https://files.pythonhosted.org/packages/72/1f/143657daf2670d977dac83435f1fe03d4843efb798d8e1e75950e541aadd/ty-0.0.55-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0ddc05e7959709c3b9b83aa627128a80446865e3c1a4882638dcff6d776dc34a", size = 12021409, upload-time = "2026-06-27T00:27:09.881Z" }, + { url = "https://files.pythonhosted.org/packages/6d/30/69487c439dd1fad3a4a3d96f0a472193de297eaba6fc4b8ea687ce434ac2/ty-0.0.55-py3-none-manylinux_2_31_riscv64.whl", hash = "sha256:636e8e5078787b8c6916c94e1406719f10189a4ca6b37b813a5922ce5857a8c7", size = 12303807, upload-time = "2026-06-27T00:27:11.986Z" }, + { url = "https://files.pythonhosted.org/packages/e8/ca/cd88b6493dafc7db077f5e17c0438eb3af6e2d6d08f616dbb52a8ddfd567/ty-0.0.55-py3-none-musllinux_1_2_aarch64.whl", hash = "sha256:ef7d6deaacb73fec603666b5471f1dc5a5699aa84e11a6d4d644dd07ca72121e", size = 11441263, upload-time = "2026-06-27T00:27:14.087Z" }, + { url = "https://files.pythonhosted.org/packages/aa/fe/66b6915671653ab739f71e4f1b0528e69da64429b7ebf3840c625b6e43f2/ty-0.0.55-py3-none-musllinux_1_2_armv7l.whl", hash = "sha256:9aeea0fe5875d3cf37faf0e44d0fdf9669335467749741b8fc0103916fb5cd32", size = 11484584, upload-time = "2026-06-27T00:27:16.311Z" }, + { url = "https://files.pythonhosted.org/packages/4a/4f/7a9c0bbac8b899e9f6c0ec110c6612f52e4db35f6bb17ddc0ef60384fa3e/ty-0.0.55-py3-none-musllinux_1_2_i686.whl", hash = "sha256:0b699c01310dbd2705a07c97c5f4aaeedef61bd9adeea2e7c46aed32401d3576", size = 11759309, upload-time = "2026-06-27T00:27:18.471Z" }, + { url = "https://files.pythonhosted.org/packages/ca/de/b6f8b1b69aa631b5716ef3f985c3b56de0e46c2499cc00d30c402b41f714/ty-0.0.55-py3-none-musllinux_1_2_x86_64.whl", hash = "sha256:32cbeba543e46de2a983ec6d525d8b56514f7422bd1e1b57c44ccf7bfa72c38a", size = 12128755, upload-time = "2026-06-27T00:27:20.55Z" }, + { url = "https://files.pythonhosted.org/packages/7d/90/a912531e51ee7e076b42972479290fa687c0f5e747b7e773f3033164acaa/ty-0.0.55-py3-none-win32.whl", hash = "sha256:52b968e24eb4f7a5c3bd251db1f99f60dd385890356d38fc619d84f1b423446a", size = 11117501, upload-time = "2026-06-27T00:27:22.714Z" }, + { url = "https://files.pythonhosted.org/packages/4c/7a/99d59843bf8908a7f9f4d13fda107dbad07b7faa28ecd7860eacf363fb1c/ty-0.0.55-py3-none-win_amd64.whl", hash = "sha256:bf39cbfdc0add44d94bd3fff1f53c351418d134b6a66b87efdb7876d7b7a2224", size = 12150106, upload-time = "2026-06-27T00:27:24.881Z" }, + { url = "https://files.pythonhosted.org/packages/b3/44/20987505cedf2a865b08482f0eabc181fd9599b062964057ec8a128a4296/ty-0.0.55-py3-none-win_arm64.whl", hash = "sha256:f7f3700a9a060e8f1af11e4fb63fafcaf272b041781f4ccdfda2b3b5c6c1e439", size = 11560157, upload-time = "2026-06-27T00:27:27.332Z" }, ] [[package]] name = "typer" -version = "0.26.7" +version = "0.26.8" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "annotated-doc" }, @@ -5480,43 +4403,9 @@ dependencies = [ { name = "rich" }, { name = "shellingham" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/5e/ed/ef06584ccdd5c410df0837951ecd7e15d9a6144ea1bd4c73cecab1a89891/typer-0.26.7.tar.gz", hash = "sha256:e314a34c617e419c091b2830dda3ea1f257134ff593061a8f5b9717ab8dddb3a", size = 201709, upload-time = "2026-06-03T07:18:06.843Z" } +sdist = { url = "https://files.pythonhosted.org/packages/7c/f7/68adc395201b20b872d68e975386832e8005ffeacedd43a1d837a32815be/typer-0.26.8.tar.gz", hash = "sha256:c244a6bd558886fe3f8780efb6bdd28bb9aff005a94eedebaa5cb32926fe2f7e", size = 202097, upload-time = "2026-06-26T09:22:45.705Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/24/25/2201973529af2c954de0bb725323c3aaed6d7f0ceee8f550dec9185df013/typer-0.26.7-py3-none-any.whl", hash = "sha256:5c87cfbc5d34491c5346ebf49c23e18d56ccb863268d3a8d592b26087c2f5e58", size = 122456, upload-time = "2026-06-03T07:18:05.732Z" }, -] - -[[package]] -name = "typer-slim" -version = "0.21.2" -source = { registry = "https://pypi.org/simple" } -dependencies = [ - { name = "annotated-doc" }, - { name = "click" }, -] -sdist = { url = "https://files.pythonhosted.org/packages/a5/ca/0d9d822fd8a4c7e830cba36a2557b070d4b4a9558a0460377a61f8fb315d/typer_slim-0.21.2.tar.gz", hash = "sha256:78f20d793036a62aaf9c3798306142b08261d4b2a941c6e463081239f062a2f9", size = 120497, upload-time = "2026-02-10T19:33:45.836Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/54/03/e09325cfc40a33a82b31ba1a3f1d97e85246736856a45a43b19fcb48b1c2/typer_slim-0.21.2-py3-none-any.whl", hash = "sha256:4705082bb6c66c090f60e47c8be09a93158c139ce0aa98df7c6c47e723395e5f", size = 56790, upload-time = "2026-02-10T19:33:47.221Z" }, -] - -[[package]] -name = "types-protobuf" -version = "6.32.1.20251210" -source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/c2/59/c743a842911887cd96d56aa8936522b0cd5f7a7f228c96e81b59fced45be/types_protobuf-6.32.1.20251210.tar.gz", hash = "sha256:c698bb3f020274b1a2798ae09dc773728ce3f75209a35187bd11916ebfde6763", size = 63900, upload-time = "2025-12-10T03:14:25.451Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/aa/43/58e75bac4219cbafee83179505ff44cae3153ec279be0e30583a73b8f108/types_protobuf-6.32.1.20251210-py3-none-any.whl", hash = "sha256:2641f78f3696822a048cfb8d0ff42ccd85c25f12f871fbebe86da63793692140", size = 77921, upload-time = "2025-12-10T03:14:24.477Z" }, -] - -[[package]] -name = "types-requests" -version = "2.32.4.20260107" -source = { registry = "https://pypi.org/simple" } -dependencies = [ - { name = "urllib3" }, -] -sdist = { url = "https://files.pythonhosted.org/packages/0f/f3/a0663907082280664d745929205a89d41dffb29e89a50f753af7d57d0a96/types_requests-2.32.4.20260107.tar.gz", hash = "sha256:018a11ac158f801bfa84857ddec1650750e393df8a004a8a9ae2a9bec6fcb24f", size = 23165, upload-time = "2026-01-07T03:20:54.091Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/1c/12/709ea261f2bf91ef0a26a9eed20f2623227a8ed85610c1e54c5805692ecb/types_requests-2.32.4.20260107-py3-none-any.whl", hash = "sha256:b703fe72f8ce5b31ef031264fe9395cac8f46a04661a79f7ed31a80fb308730d", size = 20676, upload-time = "2026-01-07T03:20:52.929Z" }, + { url = "https://files.pythonhosted.org/packages/80/87/b9fd69c92c6102a066e1b86a35243f53e70bd4c709f2a26d9f4fee4f4dc0/typer-0.26.8-py3-none-any.whl", hash = "sha256:3512ca79ac5c11113414b36e80281b872884477722440691c89d1112e321a49c", size = 122564, upload-time = "2026-06-26T09:22:44.72Z" }, ] [[package]] @@ -5540,15 +4429,6 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/dc/9b/47798a6c91d8bdb567fe2698fe81e0c6b7cb7ef4d13da4114b41d239f65d/typing_inspection-0.4.2-py3-none-any.whl", hash = "sha256:4ed1cacbdc298c220f1bd249ed5287caa16f34d44ef4e9c3d0cbad5b521545e7", size = 14611, upload-time = "2025-10-01T02:14:40.154Z" }, ] -[[package]] -name = "uncalled-for" -version = "0.2.0" -source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/02/7c/b5b7d8136f872e3f13b0584e576886de0489d7213a12de6bebf29ff6ebfc/uncalled_for-0.2.0.tar.gz", hash = "sha256:b4f8fdbcec328c5a113807d653e041c5094473dd4afa7c34599ace69ccb7e69f", size = 49488, upload-time = "2026-02-27T17:40:58.137Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/ff/7f/4320d9ce3be404e6310b915c3629fe27bf1e2f438a1a7a3cb0396e32e9a9/uncalled_for-0.2.0-py3-none-any.whl", hash = "sha256:2c0bd338faff5f930918f79e7eb9ff48290df2cb05fcc0b40a7f334e55d4d85f", size = 11351, upload-time = "2026-02-27T17:40:56.804Z" }, -] - [[package]] name = "urllib3" version = "2.7.0" @@ -5920,151 +4800,6 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/1f/f6/a933bd70f98e9cf3e08167fc5cd7aaaca49147e48411c0bd5ae701bb2194/wrapt-1.17.3-py3-none-any.whl", hash = "sha256:7171ae35d2c33d326ac19dd8facb1e82e5fd04ef8c6c0e394d7af55a55051c22", size = 23591, upload-time = "2025-08-12T05:53:20.674Z" }, ] -[[package]] -name = "xai-sdk" -version = "1.15.0" -source = { registry = "https://pypi.org/simple" } -dependencies = [ - { name = "aiohttp" }, - { name = "googleapis-common-protos" }, - { name = "grpcio" }, - { name = "opentelemetry-sdk" }, - { name = "packaging" }, - { name = "protobuf" }, - { name = "pydantic" }, - { name = "requests" }, -] -sdist = { url = "https://files.pythonhosted.org/packages/33/0a/74a835cff3c2c5135bcbdca152eed1bd0b7b2c9156e457dfc0d9af987df9/xai_sdk-1.15.0.tar.gz", hash = "sha256:6508b702d01da9c55c15cdcb329c4ad58eb9251340b2514d0974bcba11e764e3", size = 433102, upload-time = "2026-05-30T01:42:15.977Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/f5/39/7513677c0dafc5171ca4a78f9af3a2acfb9c8798aab62bc4464452ac277f/xai_sdk-1.15.0-py3-none-any.whl", hash = "sha256:de1dcb856941bcbc64c0e61b7202395593c1950e0e00e6aa0ca7657448c03aca", size = 260289, upload-time = "2026-05-30T01:42:14.431Z" }, -] - -[[package]] -name = "yarl" -version = "1.22.0" -source = { registry = "https://pypi.org/simple" } -dependencies = [ - { name = "idna" }, - { name = "multidict" }, - { name = "propcache" }, -] -sdist = { url = "https://files.pythonhosted.org/packages/57/63/0c6ebca57330cd313f6102b16dd57ffaf3ec4c83403dcb45dbd15c6f3ea1/yarl-1.22.0.tar.gz", hash = "sha256:bebf8557577d4401ba8bd9ff33906f1376c877aa78d1fe216ad01b4d6745af71", size = 187169, upload-time = "2025-10-06T14:12:55.963Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/d1/43/a2204825342f37c337f5edb6637040fa14e365b2fcc2346960201d457579/yarl-1.22.0-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:c7bd6683587567e5a49ee6e336e0612bec8329be1b7d4c8af5687dcdeb67ee1e", size = 140517, upload-time = "2025-10-06T14:08:42.494Z" }, - { url = "https://files.pythonhosted.org/packages/44/6f/674f3e6f02266428c56f704cd2501c22f78e8b2eeb23f153117cc86fb28a/yarl-1.22.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:5cdac20da754f3a723cceea5b3448e1a2074866406adeb4ef35b469d089adb8f", size = 93495, upload-time = "2025-10-06T14:08:46.2Z" }, - { url = "https://files.pythonhosted.org/packages/b8/12/5b274d8a0f30c07b91b2f02cba69152600b47830fcfb465c108880fcee9c/yarl-1.22.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:07a524d84df0c10f41e3ee918846e1974aba4ec017f990dc735aad487a0bdfdf", size = 94400, upload-time = "2025-10-06T14:08:47.855Z" }, - { url = "https://files.pythonhosted.org/packages/e2/7f/df1b6949b1fa1aa9ff6de6e2631876ad4b73c4437822026e85d8acb56bb1/yarl-1.22.0-cp310-cp310-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:e1b329cb8146d7b736677a2440e422eadd775d1806a81db2d4cded80a48efc1a", size = 347545, upload-time = "2025-10-06T14:08:49.683Z" }, - { url = "https://files.pythonhosted.org/packages/84/09/f92ed93bd6cd77872ab6c3462df45ca45cd058d8f1d0c9b4f54c1704429f/yarl-1.22.0-cp310-cp310-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:75976c6945d85dbb9ee6308cd7ff7b1fb9409380c82d6119bd778d8fcfe2931c", size = 319598, upload-time = "2025-10-06T14:08:51.215Z" }, - { url = "https://files.pythonhosted.org/packages/c3/97/ac3f3feae7d522cf7ccec3d340bb0b2b61c56cb9767923df62a135092c6b/yarl-1.22.0-cp310-cp310-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:80ddf7a5f8c86cb3eb4bc9028b07bbbf1f08a96c5c0bc1244be5e8fefcb94147", size = 363893, upload-time = "2025-10-06T14:08:53.144Z" }, - { url = "https://files.pythonhosted.org/packages/06/49/f3219097403b9c84a4d079b1d7bda62dd9b86d0d6e4428c02d46ab2c77fc/yarl-1.22.0-cp310-cp310-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:d332fc2e3c94dad927f2112395772a4e4fedbcf8f80efc21ed7cdfae4d574fdb", size = 371240, upload-time = "2025-10-06T14:08:55.036Z" }, - { url = "https://files.pythonhosted.org/packages/35/9f/06b765d45c0e44e8ecf0fe15c9eacbbde342bb5b7561c46944f107bfb6c3/yarl-1.22.0-cp310-cp310-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:0cf71bf877efeac18b38d3930594c0948c82b64547c1cf420ba48722fe5509f6", size = 346965, upload-time = "2025-10-06T14:08:56.722Z" }, - { url = "https://files.pythonhosted.org/packages/c5/69/599e7cea8d0fcb1694323b0db0dda317fa3162f7b90166faddecf532166f/yarl-1.22.0-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:663e1cadaddae26be034a6ab6072449a8426ddb03d500f43daf952b74553bba0", size = 342026, upload-time = "2025-10-06T14:08:58.563Z" }, - { url = "https://files.pythonhosted.org/packages/95/6f/9dfd12c8bc90fea9eab39832ee32ea48f8e53d1256252a77b710c065c89f/yarl-1.22.0-cp310-cp310-musllinux_1_2_armv7l.whl", hash = "sha256:6dcbb0829c671f305be48a7227918cfcd11276c2d637a8033a99a02b67bf9eda", size = 335637, upload-time = "2025-10-06T14:09:00.506Z" }, - { url = "https://files.pythonhosted.org/packages/57/2e/34c5b4eb9b07e16e873db5b182c71e5f06f9b5af388cdaa97736d79dd9a6/yarl-1.22.0-cp310-cp310-musllinux_1_2_ppc64le.whl", hash = "sha256:f0d97c18dfd9a9af4490631905a3f131a8e4c9e80a39353919e2cfed8f00aedc", size = 359082, upload-time = "2025-10-06T14:09:01.936Z" }, - { url = "https://files.pythonhosted.org/packages/31/71/fa7e10fb772d273aa1f096ecb8ab8594117822f683bab7d2c5a89914c92a/yarl-1.22.0-cp310-cp310-musllinux_1_2_s390x.whl", hash = "sha256:437840083abe022c978470b942ff832c3940b2ad3734d424b7eaffcd07f76737", size = 357811, upload-time = "2025-10-06T14:09:03.445Z" }, - { url = "https://files.pythonhosted.org/packages/26/da/11374c04e8e1184a6a03cf9c8f5688d3e5cec83ed6f31ad3481b3207f709/yarl-1.22.0-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:a899cbd98dce6f5d8de1aad31cb712ec0a530abc0a86bd6edaa47c1090138467", size = 351223, upload-time = "2025-10-06T14:09:05.401Z" }, - { url = "https://files.pythonhosted.org/packages/82/8f/e2d01f161b0c034a30410e375e191a5d27608c1f8693bab1a08b089ca096/yarl-1.22.0-cp310-cp310-win32.whl", hash = "sha256:595697f68bd1f0c1c159fcb97b661fc9c3f5db46498043555d04805430e79bea", size = 82118, upload-time = "2025-10-06T14:09:11.148Z" }, - { url = "https://files.pythonhosted.org/packages/62/46/94c76196642dbeae634c7a61ba3da88cd77bed875bf6e4a8bed037505aa6/yarl-1.22.0-cp310-cp310-win_amd64.whl", hash = "sha256:cb95a9b1adaa48e41815a55ae740cfda005758104049a640a398120bf02515ca", size = 86852, upload-time = "2025-10-06T14:09:12.958Z" }, - { url = "https://files.pythonhosted.org/packages/af/af/7df4f179d3b1a6dcb9a4bd2ffbc67642746fcafdb62580e66876ce83fff4/yarl-1.22.0-cp310-cp310-win_arm64.whl", hash = "sha256:b85b982afde6df99ecc996990d4ad7ccbdbb70e2a4ba4de0aecde5922ba98a0b", size = 82012, upload-time = "2025-10-06T14:09:14.664Z" }, - { url = "https://files.pythonhosted.org/packages/4d/27/5ab13fc84c76a0250afd3d26d5936349a35be56ce5785447d6c423b26d92/yarl-1.22.0-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:1ab72135b1f2db3fed3997d7e7dc1b80573c67138023852b6efb336a5eae6511", size = 141607, upload-time = "2025-10-06T14:09:16.298Z" }, - { url = "https://files.pythonhosted.org/packages/6a/a1/d065d51d02dc02ce81501d476b9ed2229d9a990818332242a882d5d60340/yarl-1.22.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:669930400e375570189492dc8d8341301578e8493aec04aebc20d4717f899dd6", size = 94027, upload-time = "2025-10-06T14:09:17.786Z" }, - { url = "https://files.pythonhosted.org/packages/c1/da/8da9f6a53f67b5106ffe902c6fa0164e10398d4e150d85838b82f424072a/yarl-1.22.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:792a2af6d58177ef7c19cbf0097aba92ca1b9cb3ffdd9c7470e156c8f9b5e028", size = 94963, upload-time = "2025-10-06T14:09:19.662Z" }, - { url = "https://files.pythonhosted.org/packages/68/fe/2c1f674960c376e29cb0bec1249b117d11738db92a6ccc4a530b972648db/yarl-1.22.0-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:3ea66b1c11c9150f1372f69afb6b8116f2dd7286f38e14ea71a44eee9ec51b9d", size = 368406, upload-time = "2025-10-06T14:09:21.402Z" }, - { url = "https://files.pythonhosted.org/packages/95/26/812a540e1c3c6418fec60e9bbd38e871eaba9545e94fa5eff8f4a8e28e1e/yarl-1.22.0-cp311-cp311-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:3e2daa88dc91870215961e96a039ec73e4937da13cf77ce17f9cad0c18df3503", size = 336581, upload-time = "2025-10-06T14:09:22.98Z" }, - { url = "https://files.pythonhosted.org/packages/0b/f5/5777b19e26fdf98563985e481f8be3d8a39f8734147a6ebf459d0dab5a6b/yarl-1.22.0-cp311-cp311-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:ba440ae430c00eee41509353628600212112cd5018d5def7e9b05ea7ac34eb65", size = 388924, upload-time = "2025-10-06T14:09:24.655Z" }, - { url = "https://files.pythonhosted.org/packages/86/08/24bd2477bd59c0bbd994fe1d93b126e0472e4e3df5a96a277b0a55309e89/yarl-1.22.0-cp311-cp311-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:e6438cc8f23a9c1478633d216b16104a586b9761db62bfacb6425bac0a36679e", size = 392890, upload-time = "2025-10-06T14:09:26.617Z" }, - { url = "https://files.pythonhosted.org/packages/46/00/71b90ed48e895667ecfb1eaab27c1523ee2fa217433ed77a73b13205ca4b/yarl-1.22.0-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:4c52a6e78aef5cf47a98ef8e934755abf53953379b7d53e68b15ff4420e6683d", size = 365819, upload-time = "2025-10-06T14:09:28.544Z" }, - { url = "https://files.pythonhosted.org/packages/30/2d/f715501cae832651d3282387c6a9236cd26bd00d0ff1e404b3dc52447884/yarl-1.22.0-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:3b06bcadaac49c70f4c88af4ffcfbe3dc155aab3163e75777818092478bcbbe7", size = 363601, upload-time = "2025-10-06T14:09:30.568Z" }, - { url = "https://files.pythonhosted.org/packages/f8/f9/a678c992d78e394e7126ee0b0e4e71bd2775e4334d00a9278c06a6cce96a/yarl-1.22.0-cp311-cp311-musllinux_1_2_armv7l.whl", hash = "sha256:6944b2dc72c4d7f7052683487e3677456050ff77fcf5e6204e98caf785ad1967", size = 358072, upload-time = "2025-10-06T14:09:32.528Z" }, - { url = "https://files.pythonhosted.org/packages/2c/d1/b49454411a60edb6fefdcad4f8e6dbba7d8019e3a508a1c5836cba6d0781/yarl-1.22.0-cp311-cp311-musllinux_1_2_ppc64le.whl", hash = "sha256:d5372ca1df0f91a86b047d1277c2aaf1edb32d78bbcefffc81b40ffd18f027ed", size = 385311, upload-time = "2025-10-06T14:09:34.634Z" }, - { url = "https://files.pythonhosted.org/packages/87/e5/40d7a94debb8448c7771a916d1861d6609dddf7958dc381117e7ba36d9e8/yarl-1.22.0-cp311-cp311-musllinux_1_2_s390x.whl", hash = "sha256:51af598701f5299012b8416486b40fceef8c26fc87dc6d7d1f6fc30609ea0aa6", size = 381094, upload-time = "2025-10-06T14:09:36.268Z" }, - { url = "https://files.pythonhosted.org/packages/35/d8/611cc282502381ad855448643e1ad0538957fc82ae83dfe7762c14069e14/yarl-1.22.0-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:b266bd01fedeffeeac01a79ae181719ff848a5a13ce10075adbefc8f1daee70e", size = 370944, upload-time = "2025-10-06T14:09:37.872Z" }, - { url = "https://files.pythonhosted.org/packages/2d/df/fadd00fb1c90e1a5a8bd731fa3d3de2e165e5a3666a095b04e31b04d9cb6/yarl-1.22.0-cp311-cp311-win32.whl", hash = "sha256:a9b1ba5610a4e20f655258d5a1fdc7ebe3d837bb0e45b581398b99eb98b1f5ca", size = 81804, upload-time = "2025-10-06T14:09:39.359Z" }, - { url = "https://files.pythonhosted.org/packages/b5/f7/149bb6f45f267cb5c074ac40c01c6b3ea6d8a620d34b337f6321928a1b4d/yarl-1.22.0-cp311-cp311-win_amd64.whl", hash = "sha256:078278b9b0b11568937d9509b589ee83ef98ed6d561dfe2020e24a9fd08eaa2b", size = 86858, upload-time = "2025-10-06T14:09:41.068Z" }, - { url = "https://files.pythonhosted.org/packages/2b/13/88b78b93ad3f2f0b78e13bfaaa24d11cbc746e93fe76d8c06bf139615646/yarl-1.22.0-cp311-cp311-win_arm64.whl", hash = "sha256:b6a6f620cfe13ccec221fa312139135166e47ae169f8253f72a0abc0dae94376", size = 81637, upload-time = "2025-10-06T14:09:42.712Z" }, - { url = "https://files.pythonhosted.org/packages/75/ff/46736024fee3429b80a165a732e38e5d5a238721e634ab41b040d49f8738/yarl-1.22.0-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:e340382d1afa5d32b892b3ff062436d592ec3d692aeea3bef3a5cfe11bbf8c6f", size = 142000, upload-time = "2025-10-06T14:09:44.631Z" }, - { url = "https://files.pythonhosted.org/packages/5a/9a/b312ed670df903145598914770eb12de1bac44599549b3360acc96878df8/yarl-1.22.0-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:f1e09112a2c31ffe8d80be1b0988fa6a18c5d5cad92a9ffbb1c04c91bfe52ad2", size = 94338, upload-time = "2025-10-06T14:09:46.372Z" }, - { url = "https://files.pythonhosted.org/packages/ba/f5/0601483296f09c3c65e303d60c070a5c19fcdbc72daa061e96170785bc7d/yarl-1.22.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:939fe60db294c786f6b7c2d2e121576628468f65453d86b0fe36cb52f987bd74", size = 94909, upload-time = "2025-10-06T14:09:48.648Z" }, - { url = "https://files.pythonhosted.org/packages/60/41/9a1fe0b73dbcefce72e46cf149b0e0a67612d60bfc90fb59c2b2efdfbd86/yarl-1.22.0-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:e1651bf8e0398574646744c1885a41198eba53dc8a9312b954073f845c90a8df", size = 372940, upload-time = "2025-10-06T14:09:50.089Z" }, - { url = "https://files.pythonhosted.org/packages/17/7a/795cb6dfee561961c30b800f0ed616b923a2ec6258b5def2a00bf8231334/yarl-1.22.0-cp312-cp312-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:b8a0588521a26bf92a57a1705b77b8b59044cdceccac7151bd8d229e66b8dedb", size = 345825, upload-time = "2025-10-06T14:09:52.142Z" }, - { url = "https://files.pythonhosted.org/packages/d7/93/a58f4d596d2be2ae7bab1a5846c4d270b894958845753b2c606d666744d3/yarl-1.22.0-cp312-cp312-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:42188e6a615c1a75bcaa6e150c3fe8f3e8680471a6b10150c5f7e83f47cc34d2", size = 386705, upload-time = "2025-10-06T14:09:54.128Z" }, - { url = "https://files.pythonhosted.org/packages/61/92/682279d0e099d0e14d7fd2e176bd04f48de1484f56546a3e1313cd6c8e7c/yarl-1.22.0-cp312-cp312-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:f6d2cb59377d99718913ad9a151030d6f83ef420a2b8f521d94609ecc106ee82", size = 396518, upload-time = "2025-10-06T14:09:55.762Z" }, - { url = "https://files.pythonhosted.org/packages/db/0f/0d52c98b8a885aeda831224b78f3be7ec2e1aa4a62091f9f9188c3c65b56/yarl-1.22.0-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:50678a3b71c751d58d7908edc96d332af328839eea883bb554a43f539101277a", size = 377267, upload-time = "2025-10-06T14:09:57.958Z" }, - { url = "https://files.pythonhosted.org/packages/22/42/d2685e35908cbeaa6532c1fc73e89e7f2efb5d8a7df3959ea8e37177c5a3/yarl-1.22.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:1e8fbaa7cec507aa24ea27a01456e8dd4b6fab829059b69844bd348f2d467124", size = 365797, upload-time = "2025-10-06T14:09:59.527Z" }, - { url = "https://files.pythonhosted.org/packages/a2/83/cf8c7bcc6355631762f7d8bdab920ad09b82efa6b722999dfb05afa6cfac/yarl-1.22.0-cp312-cp312-musllinux_1_2_armv7l.whl", hash = "sha256:433885ab5431bc3d3d4f2f9bd15bfa1614c522b0f1405d62c4f926ccd69d04fa", size = 365535, upload-time = "2025-10-06T14:10:01.139Z" }, - { url = "https://files.pythonhosted.org/packages/25/e1/5302ff9b28f0c59cac913b91fe3f16c59a033887e57ce9ca5d41a3a94737/yarl-1.22.0-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:b790b39c7e9a4192dc2e201a282109ed2985a1ddbd5ac08dc56d0e121400a8f7", size = 382324, upload-time = "2025-10-06T14:10:02.756Z" }, - { url = "https://files.pythonhosted.org/packages/bf/cd/4617eb60f032f19ae3a688dc990d8f0d89ee0ea378b61cac81ede3e52fae/yarl-1.22.0-cp312-cp312-musllinux_1_2_s390x.whl", hash = "sha256:31f0b53913220599446872d757257be5898019c85e7971599065bc55065dc99d", size = 383803, upload-time = "2025-10-06T14:10:04.552Z" }, - { url = "https://files.pythonhosted.org/packages/59/65/afc6e62bb506a319ea67b694551dab4a7e6fb7bf604e9bd9f3e11d575fec/yarl-1.22.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:a49370e8f711daec68d09b821a34e1167792ee2d24d405cbc2387be4f158b520", size = 374220, upload-time = "2025-10-06T14:10:06.489Z" }, - { url = "https://files.pythonhosted.org/packages/e7/3d/68bf18d50dc674b942daec86a9ba922d3113d8399b0e52b9897530442da2/yarl-1.22.0-cp312-cp312-win32.whl", hash = "sha256:70dfd4f241c04bd9239d53b17f11e6ab672b9f1420364af63e8531198e3f5fe8", size = 81589, upload-time = "2025-10-06T14:10:09.254Z" }, - { url = "https://files.pythonhosted.org/packages/c8/9a/6ad1a9b37c2f72874f93e691b2e7ecb6137fb2b899983125db4204e47575/yarl-1.22.0-cp312-cp312-win_amd64.whl", hash = "sha256:8884d8b332a5e9b88e23f60bb166890009429391864c685e17bd73a9eda9105c", size = 87213, upload-time = "2025-10-06T14:10:11.369Z" }, - { url = "https://files.pythonhosted.org/packages/44/c5/c21b562d1680a77634d748e30c653c3ca918beb35555cff24986fff54598/yarl-1.22.0-cp312-cp312-win_arm64.whl", hash = "sha256:ea70f61a47f3cc93bdf8b2f368ed359ef02a01ca6393916bc8ff877427181e74", size = 81330, upload-time = "2025-10-06T14:10:13.112Z" }, - { url = "https://files.pythonhosted.org/packages/ea/f3/d67de7260456ee105dc1d162d43a019ecad6b91e2f51809d6cddaa56690e/yarl-1.22.0-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:8dee9c25c74997f6a750cd317b8ca63545169c098faee42c84aa5e506c819b53", size = 139980, upload-time = "2025-10-06T14:10:14.601Z" }, - { url = "https://files.pythonhosted.org/packages/01/88/04d98af0b47e0ef42597b9b28863b9060bb515524da0a65d5f4db160b2d5/yarl-1.22.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:01e73b85a5434f89fc4fe27dcda2aff08ddf35e4d47bbbea3bdcd25321af538a", size = 93424, upload-time = "2025-10-06T14:10:16.115Z" }, - { url = "https://files.pythonhosted.org/packages/18/91/3274b215fd8442a03975ce6bee5fe6aa57a8326b29b9d3d56234a1dca244/yarl-1.22.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:22965c2af250d20c873cdbee8ff958fb809940aeb2e74ba5f20aaf6b7ac8c70c", size = 93821, upload-time = "2025-10-06T14:10:17.993Z" }, - { url = "https://files.pythonhosted.org/packages/61/3a/caf4e25036db0f2da4ca22a353dfeb3c9d3c95d2761ebe9b14df8fc16eb0/yarl-1.22.0-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:b4f15793aa49793ec8d1c708ab7f9eded1aa72edc5174cae703651555ed1b601", size = 373243, upload-time = "2025-10-06T14:10:19.44Z" }, - { url = "https://files.pythonhosted.org/packages/6e/9e/51a77ac7516e8e7803b06e01f74e78649c24ee1021eca3d6a739cb6ea49c/yarl-1.22.0-cp313-cp313-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:e5542339dcf2747135c5c85f68680353d5cb9ffd741c0f2e8d832d054d41f35a", size = 342361, upload-time = "2025-10-06T14:10:21.124Z" }, - { url = "https://files.pythonhosted.org/packages/d4/f8/33b92454789dde8407f156c00303e9a891f1f51a0330b0fad7c909f87692/yarl-1.22.0-cp313-cp313-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:5c401e05ad47a75869c3ab3e35137f8468b846770587e70d71e11de797d113df", size = 387036, upload-time = "2025-10-06T14:10:22.902Z" }, - { url = "https://files.pythonhosted.org/packages/d9/9a/c5db84ea024f76838220280f732970aa4ee154015d7f5c1bfb60a267af6f/yarl-1.22.0-cp313-cp313-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:243dda95d901c733f5b59214d28b0120893d91777cb8aa043e6ef059d3cddfe2", size = 397671, upload-time = "2025-10-06T14:10:24.523Z" }, - { url = "https://files.pythonhosted.org/packages/11/c9/cd8538dc2e7727095e0c1d867bad1e40c98f37763e6d995c1939f5fdc7b1/yarl-1.22.0-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:bec03d0d388060058f5d291a813f21c011041938a441c593374da6077fe21b1b", size = 377059, upload-time = "2025-10-06T14:10:26.406Z" }, - { url = "https://files.pythonhosted.org/packages/a1/b9/ab437b261702ced75122ed78a876a6dec0a1b0f5e17a4ac7a9a2482d8abe/yarl-1.22.0-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:b0748275abb8c1e1e09301ee3cf90c8a99678a4e92e4373705f2a2570d581273", size = 365356, upload-time = "2025-10-06T14:10:28.461Z" }, - { url = "https://files.pythonhosted.org/packages/b2/9d/8e1ae6d1d008a9567877b08f0ce4077a29974c04c062dabdb923ed98e6fe/yarl-1.22.0-cp313-cp313-musllinux_1_2_armv7l.whl", hash = "sha256:47fdb18187e2a4e18fda2c25c05d8251a9e4a521edaed757fef033e7d8498d9a", size = 361331, upload-time = "2025-10-06T14:10:30.541Z" }, - { url = "https://files.pythonhosted.org/packages/ca/5a/09b7be3905962f145b73beb468cdd53db8aa171cf18c80400a54c5b82846/yarl-1.22.0-cp313-cp313-musllinux_1_2_ppc64le.whl", hash = "sha256:c7044802eec4524fde550afc28edda0dd5784c4c45f0be151a2d3ba017daca7d", size = 382590, upload-time = "2025-10-06T14:10:33.352Z" }, - { url = "https://files.pythonhosted.org/packages/aa/7f/59ec509abf90eda5048b0bc3e2d7b5099dffdb3e6b127019895ab9d5ef44/yarl-1.22.0-cp313-cp313-musllinux_1_2_s390x.whl", hash = "sha256:139718f35149ff544caba20fce6e8a2f71f1e39b92c700d8438a0b1d2a631a02", size = 385316, upload-time = "2025-10-06T14:10:35.034Z" }, - { url = "https://files.pythonhosted.org/packages/e5/84/891158426bc8036bfdfd862fabd0e0fa25df4176ec793e447f4b85cf1be4/yarl-1.22.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:e1b51bebd221006d3d2f95fbe124b22b247136647ae5dcc8c7acafba66e5ee67", size = 374431, upload-time = "2025-10-06T14:10:37.76Z" }, - { url = "https://files.pythonhosted.org/packages/bb/49/03da1580665baa8bef5e8ed34c6df2c2aca0a2f28bf397ed238cc1bbc6f2/yarl-1.22.0-cp313-cp313-win32.whl", hash = "sha256:d3e32536234a95f513bd374e93d717cf6b2231a791758de6c509e3653f234c95", size = 81555, upload-time = "2025-10-06T14:10:39.649Z" }, - { url = "https://files.pythonhosted.org/packages/9a/ee/450914ae11b419eadd067c6183ae08381cfdfcb9798b90b2b713bbebddda/yarl-1.22.0-cp313-cp313-win_amd64.whl", hash = "sha256:47743b82b76d89a1d20b83e60d5c20314cbd5ba2befc9cda8f28300c4a08ed4d", size = 86965, upload-time = "2025-10-06T14:10:41.313Z" }, - { url = "https://files.pythonhosted.org/packages/98/4d/264a01eae03b6cf629ad69bae94e3b0e5344741e929073678e84bf7a3e3b/yarl-1.22.0-cp313-cp313-win_arm64.whl", hash = "sha256:5d0fcda9608875f7d052eff120c7a5da474a6796fe4d83e152e0e4d42f6d1a9b", size = 81205, upload-time = "2025-10-06T14:10:43.167Z" }, - { url = "https://files.pythonhosted.org/packages/88/fc/6908f062a2f77b5f9f6d69cecb1747260831ff206adcbc5b510aff88df91/yarl-1.22.0-cp313-cp313t-macosx_10_13_universal2.whl", hash = "sha256:719ae08b6972befcba4310e49edb1161a88cdd331e3a694b84466bd938a6ab10", size = 146209, upload-time = "2025-10-06T14:10:44.643Z" }, - { url = "https://files.pythonhosted.org/packages/65/47/76594ae8eab26210b4867be6f49129861ad33da1f1ebdf7051e98492bf62/yarl-1.22.0-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:47d8a5c446df1c4db9d21b49619ffdba90e77c89ec6e283f453856c74b50b9e3", size = 95966, upload-time = "2025-10-06T14:10:46.554Z" }, - { url = "https://files.pythonhosted.org/packages/ab/ce/05e9828a49271ba6b5b038b15b3934e996980dd78abdfeb52a04cfb9467e/yarl-1.22.0-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:cfebc0ac8333520d2d0423cbbe43ae43c8838862ddb898f5ca68565e395516e9", size = 97312, upload-time = "2025-10-06T14:10:48.007Z" }, - { url = "https://files.pythonhosted.org/packages/d1/c5/7dffad5e4f2265b29c9d7ec869c369e4223166e4f9206fc2243ee9eea727/yarl-1.22.0-cp313-cp313t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:4398557cbf484207df000309235979c79c4356518fd5c99158c7d38203c4da4f", size = 361967, upload-time = "2025-10-06T14:10:49.997Z" }, - { url = "https://files.pythonhosted.org/packages/50/b2/375b933c93a54bff7fc041e1a6ad2c0f6f733ffb0c6e642ce56ee3b39970/yarl-1.22.0-cp313-cp313t-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:2ca6fd72a8cd803be290d42f2dec5cdcd5299eeb93c2d929bf060ad9efaf5de0", size = 323949, upload-time = "2025-10-06T14:10:52.004Z" }, - { url = "https://files.pythonhosted.org/packages/66/50/bfc2a29a1d78644c5a7220ce2f304f38248dc94124a326794e677634b6cf/yarl-1.22.0-cp313-cp313t-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:ca1f59c4e1ab6e72f0a23c13fca5430f889634166be85dbf1013683e49e3278e", size = 361818, upload-time = "2025-10-06T14:10:54.078Z" }, - { url = "https://files.pythonhosted.org/packages/46/96/f3941a46af7d5d0f0498f86d71275696800ddcdd20426298e572b19b91ff/yarl-1.22.0-cp313-cp313t-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:6c5010a52015e7c70f86eb967db0f37f3c8bd503a695a49f8d45700144667708", size = 372626, upload-time = "2025-10-06T14:10:55.767Z" }, - { url = "https://files.pythonhosted.org/packages/c1/42/8b27c83bb875cd89448e42cd627e0fb971fa1675c9ec546393d18826cb50/yarl-1.22.0-cp313-cp313t-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:9d7672ecf7557476642c88497c2f8d8542f8e36596e928e9bcba0e42e1e7d71f", size = 341129, upload-time = "2025-10-06T14:10:57.985Z" }, - { url = "https://files.pythonhosted.org/packages/49/36/99ca3122201b382a3cf7cc937b95235b0ac944f7e9f2d5331d50821ed352/yarl-1.22.0-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:3b7c88eeef021579d600e50363e0b6ee4f7f6f728cd3486b9d0f3ee7b946398d", size = 346776, upload-time = "2025-10-06T14:10:59.633Z" }, - { url = "https://files.pythonhosted.org/packages/85/b4/47328bf996acd01a4c16ef9dcd2f59c969f495073616586f78cd5f2efb99/yarl-1.22.0-cp313-cp313t-musllinux_1_2_armv7l.whl", hash = "sha256:f4afb5c34f2c6fecdcc182dfcfc6af6cccf1aa923eed4d6a12e9d96904e1a0d8", size = 334879, upload-time = "2025-10-06T14:11:01.454Z" }, - { url = "https://files.pythonhosted.org/packages/c2/ad/b77d7b3f14a4283bffb8e92c6026496f6de49751c2f97d4352242bba3990/yarl-1.22.0-cp313-cp313t-musllinux_1_2_ppc64le.whl", hash = "sha256:59c189e3e99a59cf8d83cbb31d4db02d66cda5a1a4374e8a012b51255341abf5", size = 350996, upload-time = "2025-10-06T14:11:03.452Z" }, - { url = "https://files.pythonhosted.org/packages/81/c8/06e1d69295792ba54d556f06686cbd6a7ce39c22307100e3fb4a2c0b0a1d/yarl-1.22.0-cp313-cp313t-musllinux_1_2_s390x.whl", hash = "sha256:5a3bf7f62a289fa90f1990422dc8dff5a458469ea71d1624585ec3a4c8d6960f", size = 356047, upload-time = "2025-10-06T14:11:05.115Z" }, - { url = "https://files.pythonhosted.org/packages/4b/b8/4c0e9e9f597074b208d18cef227d83aac36184bfbc6eab204ea55783dbc5/yarl-1.22.0-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:de6b9a04c606978fdfe72666fa216ffcf2d1a9f6a381058d4378f8d7b1e5de62", size = 342947, upload-time = "2025-10-06T14:11:08.137Z" }, - { url = "https://files.pythonhosted.org/packages/e0/e5/11f140a58bf4c6ad7aca69a892bff0ee638c31bea4206748fc0df4ebcb3a/yarl-1.22.0-cp313-cp313t-win32.whl", hash = "sha256:1834bb90991cc2999f10f97f5f01317f99b143284766d197e43cd5b45eb18d03", size = 86943, upload-time = "2025-10-06T14:11:10.284Z" }, - { url = "https://files.pythonhosted.org/packages/31/74/8b74bae38ed7fe6793d0c15a0c8207bbb819cf287788459e5ed230996cdd/yarl-1.22.0-cp313-cp313t-win_amd64.whl", hash = "sha256:ff86011bd159a9d2dfc89c34cfd8aff12875980e3bd6a39ff097887520e60249", size = 93715, upload-time = "2025-10-06T14:11:11.739Z" }, - { url = "https://files.pythonhosted.org/packages/69/66/991858aa4b5892d57aef7ee1ba6b4d01ec3b7eb3060795d34090a3ca3278/yarl-1.22.0-cp313-cp313t-win_arm64.whl", hash = "sha256:7861058d0582b847bc4e3a4a4c46828a410bca738673f35a29ba3ca5db0b473b", size = 83857, upload-time = "2025-10-06T14:11:13.586Z" }, - { url = "https://files.pythonhosted.org/packages/46/b3/e20ef504049f1a1c54a814b4b9bed96d1ac0e0610c3b4da178f87209db05/yarl-1.22.0-cp314-cp314-macosx_10_13_universal2.whl", hash = "sha256:34b36c2c57124530884d89d50ed2c1478697ad7473efd59cfd479945c95650e4", size = 140520, upload-time = "2025-10-06T14:11:15.465Z" }, - { url = "https://files.pythonhosted.org/packages/e4/04/3532d990fdbab02e5ede063676b5c4260e7f3abea2151099c2aa745acc4c/yarl-1.22.0-cp314-cp314-macosx_10_13_x86_64.whl", hash = "sha256:0dd9a702591ca2e543631c2a017e4a547e38a5c0f29eece37d9097e04a7ac683", size = 93504, upload-time = "2025-10-06T14:11:17.106Z" }, - { url = "https://files.pythonhosted.org/packages/11/63/ff458113c5c2dac9a9719ac68ee7c947cb621432bcf28c9972b1c0e83938/yarl-1.22.0-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:594fcab1032e2d2cc3321bb2e51271e7cd2b516c7d9aee780ece81b07ff8244b", size = 94282, upload-time = "2025-10-06T14:11:19.064Z" }, - { url = "https://files.pythonhosted.org/packages/a7/bc/315a56aca762d44a6aaaf7ad253f04d996cb6b27bad34410f82d76ea8038/yarl-1.22.0-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:f3d7a87a78d46a2e3d5b72587ac14b4c16952dd0887dbb051451eceac774411e", size = 372080, upload-time = "2025-10-06T14:11:20.996Z" }, - { url = "https://files.pythonhosted.org/packages/3f/3f/08e9b826ec2e099ea6e7c69a61272f4f6da62cb5b1b63590bb80ca2e4a40/yarl-1.22.0-cp314-cp314-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:852863707010316c973162e703bddabec35e8757e67fcb8ad58829de1ebc8590", size = 338696, upload-time = "2025-10-06T14:11:22.847Z" }, - { url = "https://files.pythonhosted.org/packages/e3/9f/90360108e3b32bd76789088e99538febfea24a102380ae73827f62073543/yarl-1.22.0-cp314-cp314-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:131a085a53bfe839a477c0845acf21efc77457ba2bcf5899618136d64f3303a2", size = 387121, upload-time = "2025-10-06T14:11:24.889Z" }, - { url = "https://files.pythonhosted.org/packages/98/92/ab8d4657bd5b46a38094cfaea498f18bb70ce6b63508fd7e909bd1f93066/yarl-1.22.0-cp314-cp314-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:078a8aefd263f4d4f923a9677b942b445a2be970ca24548a8102689a3a8ab8da", size = 394080, upload-time = "2025-10-06T14:11:27.307Z" }, - { url = "https://files.pythonhosted.org/packages/f5/e7/d8c5a7752fef68205296201f8ec2bf718f5c805a7a7e9880576c67600658/yarl-1.22.0-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:bca03b91c323036913993ff5c738d0842fc9c60c4648e5c8d98331526df89784", size = 372661, upload-time = "2025-10-06T14:11:29.387Z" }, - { url = "https://files.pythonhosted.org/packages/b6/2e/f4d26183c8db0bb82d491b072f3127fb8c381a6206a3a56332714b79b751/yarl-1.22.0-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:68986a61557d37bb90d3051a45b91fa3d5c516d177dfc6dd6f2f436a07ff2b6b", size = 364645, upload-time = "2025-10-06T14:11:31.423Z" }, - { url = "https://files.pythonhosted.org/packages/80/7c/428e5812e6b87cd00ee8e898328a62c95825bf37c7fa87f0b6bb2ad31304/yarl-1.22.0-cp314-cp314-musllinux_1_2_armv7l.whl", hash = "sha256:4792b262d585ff0dff6bcb787f8492e40698443ec982a3568c2096433660c694", size = 355361, upload-time = "2025-10-06T14:11:33.055Z" }, - { url = "https://files.pythonhosted.org/packages/ec/2a/249405fd26776f8b13c067378ef4d7dd49c9098d1b6457cdd152a99e96a9/yarl-1.22.0-cp314-cp314-musllinux_1_2_ppc64le.whl", hash = "sha256:ebd4549b108d732dba1d4ace67614b9545b21ece30937a63a65dd34efa19732d", size = 381451, upload-time = "2025-10-06T14:11:35.136Z" }, - { url = "https://files.pythonhosted.org/packages/67/a8/fb6b1adbe98cf1e2dd9fad71003d3a63a1bc22459c6e15f5714eb9323b93/yarl-1.22.0-cp314-cp314-musllinux_1_2_s390x.whl", hash = "sha256:f87ac53513d22240c7d59203f25cc3beac1e574c6cd681bbfd321987b69f95fd", size = 383814, upload-time = "2025-10-06T14:11:37.094Z" }, - { url = "https://files.pythonhosted.org/packages/d9/f9/3aa2c0e480fb73e872ae2814c43bc1e734740bb0d54e8cb2a95925f98131/yarl-1.22.0-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:22b029f2881599e2f1b06f8f1db2ee63bd309e2293ba2d566e008ba12778b8da", size = 370799, upload-time = "2025-10-06T14:11:38.83Z" }, - { url = "https://files.pythonhosted.org/packages/50/3c/af9dba3b8b5eeb302f36f16f92791f3ea62e3f47763406abf6d5a4a3333b/yarl-1.22.0-cp314-cp314-win32.whl", hash = "sha256:6a635ea45ba4ea8238463b4f7d0e721bad669f80878b7bfd1f89266e2ae63da2", size = 82990, upload-time = "2025-10-06T14:11:40.624Z" }, - { url = "https://files.pythonhosted.org/packages/ac/30/ac3a0c5bdc1d6efd1b41fa24d4897a4329b3b1e98de9449679dd327af4f0/yarl-1.22.0-cp314-cp314-win_amd64.whl", hash = "sha256:0d6e6885777af0f110b0e5d7e5dda8b704efed3894da26220b7f3d887b839a79", size = 88292, upload-time = "2025-10-06T14:11:42.578Z" }, - { url = "https://files.pythonhosted.org/packages/df/0a/227ab4ff5b998a1b7410abc7b46c9b7a26b0ca9e86c34ba4b8d8bc7c63d5/yarl-1.22.0-cp314-cp314-win_arm64.whl", hash = "sha256:8218f4e98d3c10d683584cb40f0424f4b9fd6e95610232dd75e13743b070ee33", size = 82888, upload-time = "2025-10-06T14:11:44.863Z" }, - { url = "https://files.pythonhosted.org/packages/06/5e/a15eb13db90abd87dfbefb9760c0f3f257ac42a5cac7e75dbc23bed97a9f/yarl-1.22.0-cp314-cp314t-macosx_10_13_universal2.whl", hash = "sha256:45c2842ff0e0d1b35a6bf1cd6c690939dacb617a70827f715232b2e0494d55d1", size = 146223, upload-time = "2025-10-06T14:11:46.796Z" }, - { url = "https://files.pythonhosted.org/packages/18/82/9665c61910d4d84f41a5bf6837597c89e665fa88aa4941080704645932a9/yarl-1.22.0-cp314-cp314t-macosx_10_13_x86_64.whl", hash = "sha256:d947071e6ebcf2e2bee8fce76e10faca8f7a14808ca36a910263acaacef08eca", size = 95981, upload-time = "2025-10-06T14:11:48.845Z" }, - { url = "https://files.pythonhosted.org/packages/5d/9a/2f65743589809af4d0a6d3aa749343c4b5f4c380cc24a8e94a3c6625a808/yarl-1.22.0-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:334b8721303e61b00019474cc103bdac3d7b1f65e91f0bfedeec2d56dfe74b53", size = 97303, upload-time = "2025-10-06T14:11:50.897Z" }, - { url = "https://files.pythonhosted.org/packages/b0/ab/5b13d3e157505c43c3b43b5a776cbf7b24a02bc4cccc40314771197e3508/yarl-1.22.0-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:1e7ce67c34138a058fd092f67d07a72b8e31ff0c9236e751957465a24b28910c", size = 361820, upload-time = "2025-10-06T14:11:52.549Z" }, - { url = "https://files.pythonhosted.org/packages/fb/76/242a5ef4677615cf95330cfc1b4610e78184400699bdda0acb897ef5e49a/yarl-1.22.0-cp314-cp314t-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:d77e1b2c6d04711478cb1c4ab90db07f1609ccf06a287d5607fcd90dc9863acf", size = 323203, upload-time = "2025-10-06T14:11:54.225Z" }, - { url = "https://files.pythonhosted.org/packages/8c/96/475509110d3f0153b43d06164cf4195c64d16999e0c7e2d8a099adcd6907/yarl-1.22.0-cp314-cp314t-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:c4647674b6150d2cae088fc07de2738a84b8bcedebef29802cf0b0a82ab6face", size = 363173, upload-time = "2025-10-06T14:11:56.069Z" }, - { url = "https://files.pythonhosted.org/packages/c9/66/59db471aecfbd559a1fd48aedd954435558cd98c7d0da8b03cc6c140a32c/yarl-1.22.0-cp314-cp314t-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:efb07073be061c8f79d03d04139a80ba33cbd390ca8f0297aae9cce6411e4c6b", size = 373562, upload-time = "2025-10-06T14:11:58.783Z" }, - { url = "https://files.pythonhosted.org/packages/03/1f/c5d94abc91557384719da10ff166b916107c1b45e4d0423a88457071dd88/yarl-1.22.0-cp314-cp314t-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:e51ac5435758ba97ad69617e13233da53908beccc6cfcd6c34bbed8dcbede486", size = 339828, upload-time = "2025-10-06T14:12:00.686Z" }, - { url = "https://files.pythonhosted.org/packages/5f/97/aa6a143d3afba17b6465733681c70cf175af89f76ec8d9286e08437a7454/yarl-1.22.0-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:33e32a0dd0c8205efa8e83d04fc9f19313772b78522d1bdc7d9aed706bfd6138", size = 347551, upload-time = "2025-10-06T14:12:02.628Z" }, - { url = "https://files.pythonhosted.org/packages/43/3c/45a2b6d80195959239a7b2a8810506d4eea5487dce61c2a3393e7fc3c52e/yarl-1.22.0-cp314-cp314t-musllinux_1_2_armv7l.whl", hash = "sha256:bf4a21e58b9cde0e401e683ebd00f6ed30a06d14e93f7c8fd059f8b6e8f87b6a", size = 334512, upload-time = "2025-10-06T14:12:04.871Z" }, - { url = "https://files.pythonhosted.org/packages/86/a0/c2ab48d74599c7c84cb104ebd799c5813de252bea0f360ffc29d270c2caa/yarl-1.22.0-cp314-cp314t-musllinux_1_2_ppc64le.whl", hash = "sha256:e4b582bab49ac33c8deb97e058cd67c2c50dac0dd134874106d9c774fd272529", size = 352400, upload-time = "2025-10-06T14:12:06.624Z" }, - { url = "https://files.pythonhosted.org/packages/32/75/f8919b2eafc929567d3d8411f72bdb1a2109c01caaab4ebfa5f8ffadc15b/yarl-1.22.0-cp314-cp314t-musllinux_1_2_s390x.whl", hash = "sha256:0b5bcc1a9c4839e7e30b7b30dd47fe5e7e44fb7054ec29b5bb8d526aa1041093", size = 357140, upload-time = "2025-10-06T14:12:08.362Z" }, - { url = "https://files.pythonhosted.org/packages/cf/72/6a85bba382f22cf78add705d8c3731748397d986e197e53ecc7835e76de7/yarl-1.22.0-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:c0232bce2170103ec23c454e54a57008a9a72b5d1c3105dc2496750da8cfa47c", size = 341473, upload-time = "2025-10-06T14:12:10.994Z" }, - { url = "https://files.pythonhosted.org/packages/35/18/55e6011f7c044dc80b98893060773cefcfdbf60dfefb8cb2f58b9bacbd83/yarl-1.22.0-cp314-cp314t-win32.whl", hash = "sha256:8009b3173bcd637be650922ac455946197d858b3630b6d8787aa9e5c4564533e", size = 89056, upload-time = "2025-10-06T14:12:13.317Z" }, - { url = "https://files.pythonhosted.org/packages/f9/86/0f0dccb6e59a9e7f122c5afd43568b1d31b8ab7dda5f1b01fb5c7025c9a9/yarl-1.22.0-cp314-cp314t-win_amd64.whl", hash = "sha256:9fb17ea16e972c63d25d4a97f016d235c78dd2344820eb35bc034bc32012ee27", size = 96292, upload-time = "2025-10-06T14:12:15.398Z" }, - { url = "https://files.pythonhosted.org/packages/48/b7/503c98092fb3b344a179579f55814b613c1fbb1c23b3ec14a7b008a66a6e/yarl-1.22.0-cp314-cp314t-win_arm64.whl", hash = "sha256:9f6d73c1436b934e3f01df1e1b21ff765cd1d28c77dfb9ace207f746d4610ee1", size = 85171, upload-time = "2025-10-06T14:12:16.935Z" }, - { url = "https://files.pythonhosted.org/packages/73/ae/b48f95715333080afb75a4504487cbe142cae1268afc482d06692d605ae6/yarl-1.22.0-py3-none-any.whl", hash = "sha256:1380560bdba02b6b6c90de54133c81c9f2a453dee9912fe58c1dcced1edb7cff", size = 46814, upload-time = "2025-10-06T14:12:53.872Z" }, -] - [[package]] name = "zensical" version = "0.0.46" From fb53e1df99d05689d2c519bd30ae50442c3240cb Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Tue, 7 Jul 2026 19:01:05 +0000 Subject: [PATCH 408/462] =?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 c2dac0c4c..95d589862 100644 --- a/docs/en/docs/release-notes.md +++ b/docs/en/docs/release-notes.md @@ -15,6 +15,7 @@ hide: ### Internal +* ⬆ Bump the python-packages group with 8 updates. PR [#15952](https://github.com/fastapi/fastapi/pull/15952) by [@dependabot[bot]](https://github.com/apps/dependabot). * 🔧 Update sponsors: add TutorCruncher. PR [#15947](https://github.com/fastapi/fastapi/pull/15947) by [@tiangolo](https://github.com/tiangolo). * 👷 Fix notify translations checkout target. PR [#15933](https://github.com/fastapi/fastapi/pull/15933) by [@tiangolo](https://github.com/tiangolo). * 👷 Fix latest-changes checkout target. PR [#15932](https://github.com/fastapi/fastapi/pull/15932) by [@tiangolo](https://github.com/tiangolo). From 1e60e3299246c6b1515ab9ef1b1c5de11bf4454b Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 7 Jul 2026 21:02:48 +0200 Subject: [PATCH 409/462] =?UTF-8?q?=E2=AC=86=20Bump=20CodSpeedHQ/action=20?= =?UTF-8?q?from=204.17.6=20to=204.18.1=20in=20the=20github-actions=20group?= =?UTF-8?q?=20(#15950)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/test.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index e28e90e3e..42725b3df 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -191,7 +191,7 @@ jobs: - name: Install Dependencies run: uv sync --no-dev --group tests --extra all - name: CodSpeed benchmarks - uses: CodSpeedHQ/action@63f3e98b61959fe67f146a3ff022e4136fe9bb9c # v4.17.6 + uses: CodSpeedHQ/action@a4a36bb07c0638b0b4ca52bf1f3dad1b4289e52f # v4.18.1 with: mode: simulation run: uv run --no-sync pytest tests/benchmarks --codspeed From 7cb06f360dd44efac059848df1a9beee7643b018 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Tue, 7 Jul 2026 19:03:19 +0000 Subject: [PATCH 410/462] =?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 95d589862..3cc2548db 100644 --- a/docs/en/docs/release-notes.md +++ b/docs/en/docs/release-notes.md @@ -15,6 +15,7 @@ hide: ### Internal +* ⬆ Bump CodSpeedHQ/action from 4.17.6 to 4.18.1 in the github-actions group. PR [#15950](https://github.com/fastapi/fastapi/pull/15950) by [@dependabot[bot]](https://github.com/apps/dependabot). * ⬆ Bump the python-packages group with 8 updates. PR [#15952](https://github.com/fastapi/fastapi/pull/15952) by [@dependabot[bot]](https://github.com/apps/dependabot). * 🔧 Update sponsors: add TutorCruncher. PR [#15947](https://github.com/fastapi/fastapi/pull/15947) by [@tiangolo](https://github.com/tiangolo). * 👷 Fix notify translations checkout target. PR [#15933](https://github.com/fastapi/fastapi/pull/15933) by [@tiangolo](https://github.com/tiangolo). From 59e4a1c8a84dc6a19fdf054f74317504b68d7bc0 Mon Sep 17 00:00:00 2001 From: Yurii Motov <109919500+YuriiMotov@users.noreply.github.com> Date: Mon, 13 Jul 2026 10:02:51 +0200 Subject: [PATCH 411/462] =?UTF-8?q?=F0=9F=94=A7=20Set=20Dependabot=20sched?= =?UTF-8?q?ule=20interval=20to=20"monthly"=20(#15874)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .github/dependabot.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/dependabot.yml b/.github/dependabot.yml index 95c9f07cb..a9d2d73c7 100644 --- a/.github/dependabot.yml +++ b/.github/dependabot.yml @@ -4,7 +4,7 @@ updates: - package-ecosystem: "github-actions" directory: "/" schedule: - interval: "weekly" + interval: "monthly" cooldown: default-days: 7 commit-message: @@ -21,7 +21,7 @@ updates: - package-ecosystem: "uv" directory: "/" schedule: - interval: "weekly" + interval: "monthly" cooldown: default-days: 7 commit-message: From 424f6b3c9ac8df1e35ed421bfeb4ef147cfecdeb Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Mon, 13 Jul 2026 08:03:27 +0000 Subject: [PATCH 412/462] =?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 3cc2548db..587a5c278 100644 --- a/docs/en/docs/release-notes.md +++ b/docs/en/docs/release-notes.md @@ -15,6 +15,7 @@ hide: ### Internal +* 🔧 Set Dependabot schedule interval to "monthly". PR [#15874](https://github.com/fastapi/fastapi/pull/15874) by [@YuriiMotov](https://github.com/YuriiMotov). * ⬆ Bump CodSpeedHQ/action from 4.17.6 to 4.18.1 in the github-actions group. PR [#15950](https://github.com/fastapi/fastapi/pull/15950) by [@dependabot[bot]](https://github.com/apps/dependabot). * ⬆ Bump the python-packages group with 8 updates. PR [#15952](https://github.com/fastapi/fastapi/pull/15952) by [@dependabot[bot]](https://github.com/apps/dependabot). * 🔧 Update sponsors: add TutorCruncher. PR [#15947](https://github.com/fastapi/fastapi/pull/15947) by [@tiangolo](https://github.com/tiangolo). From 8bd152772e7f0aa50b88006ec574cf23f92ba571 Mon Sep 17 00:00:00 2001 From: Yurii Motov <109919500+YuriiMotov@users.noreply.github.com> Date: Mon, 13 Jul 2026 10:08:13 +0200 Subject: [PATCH 413/462] =?UTF-8?q?=F0=9F=91=B7=20Add=20GH=20workflow=20to?= =?UTF-8?q?=20bump=20pre-commit=20hook=20versions=20(#15873)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .github/dependabot.yml | 17 ------ .github/workflows/bump-pre-commit-hooks.yml | 67 +++++++++++++++++++++ 2 files changed, 67 insertions(+), 17 deletions(-) create mode 100644 .github/workflows/bump-pre-commit-hooks.yml diff --git a/.github/dependabot.yml b/.github/dependabot.yml index a9d2d73c7..2e0061f5e 100644 --- a/.github/dependabot.yml +++ b/.github/dependabot.yml @@ -31,20 +31,3 @@ updates: dependency-type: "development" patterns: - "*" - # pre-commit - - package-ecosystem: "pre-commit" - directory: "/" - schedule: - interval: "weekly" - cooldown: - default-days: 7 - commit-message: - prefix: ⬆ - labels: - - "internal" - - "dependencies" - - "pre-commit" - groups: - pre-commit: - patterns: - - "*" diff --git a/.github/workflows/bump-pre-commit-hooks.yml b/.github/workflows/bump-pre-commit-hooks.yml new file mode 100644 index 000000000..53c31e09c --- /dev/null +++ b/.github/workflows/bump-pre-commit-hooks.yml @@ -0,0 +1,67 @@ +name: Bump pre-commit hooks + +on: + schedule: + - cron: "0 12 1 * *" + workflow_dispatch: + +permissions: {} + +jobs: + bump-pre-commit-hooks: + if: github.repository_owner == 'fastapi' + runs-on: ubuntu-latest + timeout-minutes: 10 + steps: + - name: Dump GitHub context + env: + GITHUB_CONTEXT: ${{ toJson(github) }} + run: echo "$GITHUB_CONTEXT" + - uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0 + with: + token: ${{ secrets.FASTAPI_PR_TOKEN }} + persist-credentials: true + - name: Set up Python + uses: actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405 # v6.2.0 + with: + python-version-file: ".python-version" + - name: Setup uv + uses: astral-sh/setup-uv@fac544c07dec837d0ccb6301d7b5580bf5edae39 # v8.2.0 + with: + # Before upgrading uv version, make sure astral-sh/setup-uv knows its checksum. + # See: https://github.com/astral-sh/setup-uv/issues/851#issuecomment-4282017837 + version: "0.11.18" + cache-dependency-glob: | + pyproject.toml + uv.lock + - name: Bump pre-commit hooks + run: uv run prek auto-update --freeze --cooldown-days 7 + - name: Create pull request + env: + GH_TOKEN: ${{ secrets.FASTAPI_PR_TOKEN }} + BASE_BRANCH: ${{ github.event.repository.default_branch }} + run: | + set -euo pipefail + if git diff --quiet; then + echo "No pre-commit hook updates available" + exit 0 + fi + git config user.name "github-actions[bot]" + git config user.email "github-actions[bot]@users.noreply.github.com" + branch="bump-pre-commit-hooks" + git switch -C "$branch" + git add .pre-commit-config.yaml + git commit -m "⬆ Bump pre-commit hooks" + git push --force origin "$branch" + if [ -z "$(gh pr list --head "$branch" --state open --json number --jq '.[].number')" ]; then + gh pr create \ + --base "$BASE_BRANCH" \ + --head "$branch" \ + --title "⬆ Bump pre-commit hooks" \ + --body "Bump pre-commit hook versions via \`prek auto-update --freeze --cooldown-days 7\`." \ + --label internal \ + --label dependencies \ + --label pre-commit + else + echo "PR for \"$branch\" already open; branch updated in place." + fi From c87047938912ce46ac1855d45638333397c81714 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Mon, 13 Jul 2026 08:09:09 +0000 Subject: [PATCH 414/462] =?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 587a5c278..494aecb16 100644 --- a/docs/en/docs/release-notes.md +++ b/docs/en/docs/release-notes.md @@ -15,6 +15,7 @@ hide: ### Internal +* 👷 Add GH workflow to bump pre-commit hook versions. PR [#15873](https://github.com/fastapi/fastapi/pull/15873) by [@YuriiMotov](https://github.com/YuriiMotov). * 🔧 Set Dependabot schedule interval to "monthly". PR [#15874](https://github.com/fastapi/fastapi/pull/15874) by [@YuriiMotov](https://github.com/YuriiMotov). * ⬆ Bump CodSpeedHQ/action from 4.17.6 to 4.18.1 in the github-actions group. PR [#15950](https://github.com/fastapi/fastapi/pull/15950) by [@dependabot[bot]](https://github.com/apps/dependabot). * ⬆ Bump the python-packages group with 8 updates. PR [#15952](https://github.com/fastapi/fastapi/pull/15952) by [@dependabot[bot]](https://github.com/apps/dependabot). From b75bd318f30e57a93727b17b4ef246fc2af61863 Mon Sep 17 00:00:00 2001 From: Yurii Motov <109919500+YuriiMotov@users.noreply.github.com> Date: Mon, 13 Jul 2026 11:03:30 +0200 Subject: [PATCH 415/462] =?UTF-8?q?=F0=9F=91=B7=20Use=20`FASTAPI=5FLATEST?= =?UTF-8?q?=5FCHANGES`=20token=20in=20`bump-pre-commit-hooks`=20workflow?= =?UTF-8?q?=20(#15984)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .github/workflows/bump-pre-commit-hooks.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/bump-pre-commit-hooks.yml b/.github/workflows/bump-pre-commit-hooks.yml index 53c31e09c..e80168ae1 100644 --- a/.github/workflows/bump-pre-commit-hooks.yml +++ b/.github/workflows/bump-pre-commit-hooks.yml @@ -19,7 +19,7 @@ jobs: run: echo "$GITHUB_CONTEXT" - uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0 with: - token: ${{ secrets.FASTAPI_PR_TOKEN }} + token: ${{ secrets.FASTAPI_LATEST_CHANGES }} persist-credentials: true - name: Set up Python uses: actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405 # v6.2.0 @@ -38,7 +38,7 @@ jobs: run: uv run prek auto-update --freeze --cooldown-days 7 - name: Create pull request env: - GH_TOKEN: ${{ secrets.FASTAPI_PR_TOKEN }} + GH_TOKEN: ${{ secrets.FASTAPI_LATEST_CHANGES }} BASE_BRANCH: ${{ github.event.repository.default_branch }} run: | set -euo pipefail From cf93cc6258babf28a5c4b7a269517903b30ef609 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Mon, 13 Jul 2026 09:04:02 +0000 Subject: [PATCH 416/462] =?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 494aecb16..60afb0399 100644 --- a/docs/en/docs/release-notes.md +++ b/docs/en/docs/release-notes.md @@ -15,6 +15,7 @@ hide: ### Internal +* 👷 Use `FASTAPI_LATEST_CHANGES` token in `bump-pre-commit-hooks` workflow. PR [#15984](https://github.com/fastapi/fastapi/pull/15984) by [@YuriiMotov](https://github.com/YuriiMotov). * 👷 Add GH workflow to bump pre-commit hook versions. PR [#15873](https://github.com/fastapi/fastapi/pull/15873) by [@YuriiMotov](https://github.com/YuriiMotov). * 🔧 Set Dependabot schedule interval to "monthly". PR [#15874](https://github.com/fastapi/fastapi/pull/15874) by [@YuriiMotov](https://github.com/YuriiMotov). * ⬆ Bump CodSpeedHQ/action from 4.17.6 to 4.18.1 in the github-actions group. PR [#15950](https://github.com/fastapi/fastapi/pull/15950) by [@dependabot[bot]](https://github.com/apps/dependabot). From ef3f1ac9c1483666fb70ced80b089f08f7c8d5bf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebasti=C3=A1n=20Ram=C3=ADrez?= Date: Mon, 13 Jul 2026 11:53:48 +0200 Subject: [PATCH 417/462] =?UTF-8?q?=E2=AC=86=20Bump=20pre-commit=20hooks?= =?UTF-8?q?=20(#15985)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: github-actions[bot] --- .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 eb0762df5..967d5e6d3 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -15,7 +15,7 @@ repos: - id: trailing-whitespace - repo: https://github.com/crate-ci/typos - rev: 37bb98842b0d8c4ffebdb75301a13db0267cef89 # v1.47.2 + rev: bee27e3a4fd1ea2111cf90ab89cd076c870fce14 # frozen: v1.48.0 hooks: - id: typos args: [--force-exclude] From c9d88e33d8aecb96a4898a8f82d154ea1d40e318 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Mon, 13 Jul 2026 09:54:21 +0000 Subject: [PATCH 418/462] =?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 60afb0399..c34a60abf 100644 --- a/docs/en/docs/release-notes.md +++ b/docs/en/docs/release-notes.md @@ -15,6 +15,7 @@ hide: ### Internal +* ⬆ Bump pre-commit hooks. PR [#15985](https://github.com/fastapi/fastapi/pull/15985) by [@tiangolo](https://github.com/tiangolo). * 👷 Use `FASTAPI_LATEST_CHANGES` token in `bump-pre-commit-hooks` workflow. PR [#15984](https://github.com/fastapi/fastapi/pull/15984) by [@YuriiMotov](https://github.com/YuriiMotov). * 👷 Add GH workflow to bump pre-commit hook versions. PR [#15873](https://github.com/fastapi/fastapi/pull/15873) by [@YuriiMotov](https://github.com/YuriiMotov). * 🔧 Set Dependabot schedule interval to "monthly". PR [#15874](https://github.com/fastapi/fastapi/pull/15874) by [@YuriiMotov](https://github.com/YuriiMotov). From 2b0b417c0cc38e3197d1c8eab90d512c6d905e25 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 13 Jul 2026 12:15:37 +0200 Subject: [PATCH 419/462] =?UTF-8?q?=E2=AC=86=20Bump=20the=20github-actions?= =?UTF-8?q?=20group=20across=201=20directory=20with=204=20updates=20(#1598?= =?UTF-8?q?3)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 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/bump-pre-commit-hooks.yml | 4 ++-- .github/workflows/contributors.yml | 2 +- .github/workflows/create-draft-release.yml | 2 +- .github/workflows/deploy-docs.yml | 2 +- .github/workflows/label-approved.yml | 2 +- .github/workflows/labeler.yml | 2 +- .github/workflows/notify-translations.yml | 2 +- .github/workflows/people.yml | 2 +- .github/workflows/pre-commit.yml | 2 +- .github/workflows/prepare-release.yml | 2 +- .github/workflows/publish.yml | 2 +- .github/workflows/smokeshow.yml | 2 +- .github/workflows/sponsors.yml | 2 +- .github/workflows/test.yml | 8 ++++---- .github/workflows/topic-repos.yml | 2 +- .github/workflows/translate.yml | 4 ++-- 17 files changed, 24 insertions(+), 24 deletions(-) diff --git a/.github/workflows/build-docs.yml b/.github/workflows/build-docs.yml index fe2a39c45..030132a17 100644 --- a/.github/workflows/build-docs.yml +++ b/.github/workflows/build-docs.yml @@ -21,7 +21,7 @@ jobs: with: persist-credentials: false # For pull requests it's not necessary to checkout the code but for the main branch it is - - uses: dorny/paths-filter@fbd0ab8f3e69293af611ebaee6363fc25e6d187d # v4.0.1 + - uses: dorny/paths-filter@7b450fff21473bca461d4b92ce414b9d0420d706 # v4.0.2 id: filter with: filters: | @@ -51,7 +51,7 @@ jobs: with: python-version-file: ".python-version" - name: Setup uv - uses: astral-sh/setup-uv@fac544c07dec837d0ccb6301d7b5580bf5edae39 # v8.2.0 + uses: astral-sh/setup-uv@d31148d669074a8d0a63714ba94f3201e7020bc3 # v8.3.0 with: # Before upgrading uv version, make sure astral-sh/setup-uv knows its checksum. # See: https://github.com/astral-sh/setup-uv/issues/851#issuecomment-4282017837 @@ -90,7 +90,7 @@ jobs: with: python-version-file: ".python-version" - name: Setup uv - uses: astral-sh/setup-uv@fac544c07dec837d0ccb6301d7b5580bf5edae39 # v8.2.0 + uses: astral-sh/setup-uv@d31148d669074a8d0a63714ba94f3201e7020bc3 # v8.3.0 with: # Before upgrading uv version, make sure astral-sh/setup-uv knows its checksum. # See: https://github.com/astral-sh/setup-uv/issues/851#issuecomment-4282017837 diff --git a/.github/workflows/bump-pre-commit-hooks.yml b/.github/workflows/bump-pre-commit-hooks.yml index e80168ae1..b64341a45 100644 --- a/.github/workflows/bump-pre-commit-hooks.yml +++ b/.github/workflows/bump-pre-commit-hooks.yml @@ -22,11 +22,11 @@ jobs: token: ${{ secrets.FASTAPI_LATEST_CHANGES }} persist-credentials: true - name: Set up Python - uses: actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405 # v6.2.0 + uses: actions/setup-python@ece7cb06caefa5fff74198d8649806c4678c61a1 # v6.3.0 with: python-version-file: ".python-version" - name: Setup uv - uses: astral-sh/setup-uv@fac544c07dec837d0ccb6301d7b5580bf5edae39 # v8.2.0 + uses: astral-sh/setup-uv@d31148d669074a8d0a63714ba94f3201e7020bc3 # v8.3.0 with: # Before upgrading uv version, make sure astral-sh/setup-uv knows its checksum. # See: https://github.com/astral-sh/setup-uv/issues/851#issuecomment-4282017837 diff --git a/.github/workflows/contributors.yml b/.github/workflows/contributors.yml index 1d869e7b8..04d82c34a 100644 --- a/.github/workflows/contributors.yml +++ b/.github/workflows/contributors.yml @@ -31,7 +31,7 @@ jobs: with: python-version-file: ".python-version" - name: Setup uv - uses: astral-sh/setup-uv@fac544c07dec837d0ccb6301d7b5580bf5edae39 # v8.2.0 + uses: astral-sh/setup-uv@d31148d669074a8d0a63714ba94f3201e7020bc3 # v8.3.0 with: # Before upgrading uv version, make sure astral-sh/setup-uv knows its checksum. # See: https://github.com/astral-sh/setup-uv/issues/851#issuecomment-4282017837 diff --git a/.github/workflows/create-draft-release.yml b/.github/workflows/create-draft-release.yml index e0af097e2..8f9e6fc73 100644 --- a/.github/workflows/create-draft-release.yml +++ b/.github/workflows/create-draft-release.yml @@ -31,7 +31,7 @@ jobs: with: python-version-file: ".python-version" - name: Install uv - uses: astral-sh/setup-uv@fac544c07dec837d0ccb6301d7b5580bf5edae39 # v8.2.0 + uses: astral-sh/setup-uv@d31148d669074a8d0a63714ba94f3201e7020bc3 # v8.3.0 with: # Before upgrading uv version, make sure astral-sh/setup-uv knows its checksum. # See: https://github.com/astral-sh/setup-uv/issues/851#issuecomment-4282017837 diff --git a/.github/workflows/deploy-docs.yml b/.github/workflows/deploy-docs.yml index d8353ad55..6e40b5b83 100644 --- a/.github/workflows/deploy-docs.yml +++ b/.github/workflows/deploy-docs.yml @@ -30,7 +30,7 @@ jobs: with: python-version-file: ".python-version" - name: Setup uv - uses: astral-sh/setup-uv@fac544c07dec837d0ccb6301d7b5580bf5edae39 # v8.2.0 + uses: astral-sh/setup-uv@d31148d669074a8d0a63714ba94f3201e7020bc3 # v8.3.0 with: # Before upgrading uv version, make sure astral-sh/setup-uv knows its checksum. # See: https://github.com/astral-sh/setup-uv/issues/851#issuecomment-4282017837 diff --git a/.github/workflows/label-approved.yml b/.github/workflows/label-approved.yml index 6d4f2ef52..f5f036ec7 100644 --- a/.github/workflows/label-approved.yml +++ b/.github/workflows/label-approved.yml @@ -27,7 +27,7 @@ jobs: with: python-version-file: ".python-version" - name: Setup uv - uses: astral-sh/setup-uv@fac544c07dec837d0ccb6301d7b5580bf5edae39 # v8.2.0 + uses: astral-sh/setup-uv@d31148d669074a8d0a63714ba94f3201e7020bc3 # v8.3.0 with: # Before upgrading uv version, make sure astral-sh/setup-uv knows its checksum. # See: https://github.com/astral-sh/setup-uv/issues/851#issuecomment-4282017837 diff --git a/.github/workflows/labeler.yml b/.github/workflows/labeler.yml index 803160ef5..2cbfe8cca 100644 --- a/.github/workflows/labeler.yml +++ b/.github/workflows/labeler.yml @@ -19,7 +19,7 @@ jobs: runs-on: ubuntu-latest timeout-minutes: 5 steps: - - uses: actions/labeler@f27b608878404679385c85cfa523b85ccb86e213 # v6.1.0 + - uses: actions/labeler@b8dd2d9be0f68b860e7dae5dae7d772984eacd6d # v6.2.0 if: ${{ github.event.action != 'labeled' && github.event.action != 'unlabeled' }} - run: echo "Done adding labels" # Run this after labeler applied labels diff --git a/.github/workflows/notify-translations.yml b/.github/workflows/notify-translations.yml index 261be1a98..7e72488ef 100644 --- a/.github/workflows/notify-translations.yml +++ b/.github/workflows/notify-translations.yml @@ -39,7 +39,7 @@ jobs: with: python-version-file: ".python-version" - name: Setup uv - uses: astral-sh/setup-uv@fac544c07dec837d0ccb6301d7b5580bf5edae39 # v8.2.0 + uses: astral-sh/setup-uv@d31148d669074a8d0a63714ba94f3201e7020bc3 # v8.3.0 with: # Before upgrading uv version, make sure astral-sh/setup-uv knows its checksum. # See: https://github.com/astral-sh/setup-uv/issues/851#issuecomment-4282017837 diff --git a/.github/workflows/people.yml b/.github/workflows/people.yml index 2e48c9d70..a7dd8a4fb 100644 --- a/.github/workflows/people.yml +++ b/.github/workflows/people.yml @@ -31,7 +31,7 @@ jobs: with: python-version-file: ".python-version" - name: Setup uv - uses: astral-sh/setup-uv@fac544c07dec837d0ccb6301d7b5580bf5edae39 # v8.2.0 + uses: astral-sh/setup-uv@d31148d669074a8d0a63714ba94f3201e7020bc3 # v8.3.0 with: # Before upgrading uv version, make sure astral-sh/setup-uv knows its checksum. # See: https://github.com/astral-sh/setup-uv/issues/851#issuecomment-4282017837 diff --git a/.github/workflows/pre-commit.yml b/.github/workflows/pre-commit.yml index 963fd68ab..06a706928 100644 --- a/.github/workflows/pre-commit.yml +++ b/.github/workflows/pre-commit.yml @@ -43,7 +43,7 @@ jobs: with: python-version-file: ".python-version" - name: Setup uv - uses: astral-sh/setup-uv@fac544c07dec837d0ccb6301d7b5580bf5edae39 # v8.2.0 + uses: astral-sh/setup-uv@d31148d669074a8d0a63714ba94f3201e7020bc3 # v8.3.0 with: # Before upgrading uv version, make sure astral-sh/setup-uv knows its checksum. # See: https://github.com/astral-sh/setup-uv/issues/851#issuecomment-4282017837 diff --git a/.github/workflows/prepare-release.yml b/.github/workflows/prepare-release.yml index 5b241aa4f..6b84ade70 100644 --- a/.github/workflows/prepare-release.yml +++ b/.github/workflows/prepare-release.yml @@ -43,7 +43,7 @@ jobs: with: python-version-file: ".python-version" - name: Install uv - uses: astral-sh/setup-uv@fac544c07dec837d0ccb6301d7b5580bf5edae39 # v8.2.0 + uses: astral-sh/setup-uv@d31148d669074a8d0a63714ba94f3201e7020bc3 # v8.3.0 with: # Before upgrading uv version, make sure astral-sh/setup-uv knows its checksum. # See: https://github.com/astral-sh/setup-uv/issues/851#issuecomment-4282017837 diff --git a/.github/workflows/publish.yml b/.github/workflows/publish.yml index 447ce8c33..bb601611b 100644 --- a/.github/workflows/publish.yml +++ b/.github/workflows/publish.yml @@ -27,7 +27,7 @@ jobs: with: python-version-file: ".python-version" - name: Install uv - uses: astral-sh/setup-uv@fac544c07dec837d0ccb6301d7b5580bf5edae39 # v8.2.0 + uses: astral-sh/setup-uv@d31148d669074a8d0a63714ba94f3201e7020bc3 # v8.3.0 with: # Before upgrading uv version, make sure astral-sh/setup-uv knows its checksum. # See: https://github.com/astral-sh/setup-uv/issues/851#issuecomment-4282017837 diff --git a/.github/workflows/smokeshow.yml b/.github/workflows/smokeshow.yml index 41804cee9..f7e4323c3 100644 --- a/.github/workflows/smokeshow.yml +++ b/.github/workflows/smokeshow.yml @@ -26,7 +26,7 @@ jobs: with: python-version-file: ".python-version" - name: Setup uv - uses: astral-sh/setup-uv@fac544c07dec837d0ccb6301d7b5580bf5edae39 # v8.2.0 + uses: astral-sh/setup-uv@d31148d669074a8d0a63714ba94f3201e7020bc3 # v8.3.0 with: # Before upgrading uv version, make sure astral-sh/setup-uv knows its checksum. # See: https://github.com/astral-sh/setup-uv/issues/851#issuecomment-4282017837 diff --git a/.github/workflows/sponsors.yml b/.github/workflows/sponsors.yml index a20dcaf05..c880f578e 100644 --- a/.github/workflows/sponsors.yml +++ b/.github/workflows/sponsors.yml @@ -32,7 +32,7 @@ jobs: with: python-version-file: ".python-version" - name: Setup uv - uses: astral-sh/setup-uv@fac544c07dec837d0ccb6301d7b5580bf5edae39 # v8.2.0 + uses: astral-sh/setup-uv@d31148d669074a8d0a63714ba94f3201e7020bc3 # v8.3.0 with: # Before upgrading uv version, make sure astral-sh/setup-uv knows its checksum. # See: https://github.com/astral-sh/setup-uv/issues/851#issuecomment-4282017837 diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 42725b3df..6855f0d48 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -30,7 +30,7 @@ jobs: with: persist-credentials: false # For pull requests it's not necessary to checkout the code but for the main branch it is - - uses: dorny/paths-filter@fbd0ab8f3e69293af611ebaee6363fc25e6d187d # v4.0.1 + - uses: dorny/paths-filter@7b450fff21473bca461d4b92ce414b9d0420d706 # v4.0.2 id: filter with: filters: | @@ -115,7 +115,7 @@ jobs: with: python-version: ${{ matrix.python-version }} - name: Setup uv - uses: astral-sh/setup-uv@fac544c07dec837d0ccb6301d7b5580bf5edae39 # v8.2.0 + uses: astral-sh/setup-uv@d31148d669074a8d0a63714ba94f3201e7020bc3 # v8.3.0 with: # Before upgrading uv version, make sure astral-sh/setup-uv knows its checksum. # See: https://github.com/astral-sh/setup-uv/issues/851#issuecomment-4282017837 @@ -179,7 +179,7 @@ jobs: with: python-version: "3.13" - name: Setup uv - uses: astral-sh/setup-uv@fac544c07dec837d0ccb6301d7b5580bf5edae39 # v8.2.0 + uses: astral-sh/setup-uv@d31148d669074a8d0a63714ba94f3201e7020bc3 # v8.3.0 with: # Before upgrading uv version, make sure astral-sh/setup-uv knows its checksum. # See: https://github.com/astral-sh/setup-uv/issues/851#issuecomment-4282017837 @@ -213,7 +213,7 @@ jobs: with: python-version-file: ".python-version" - name: Setup uv - uses: astral-sh/setup-uv@fac544c07dec837d0ccb6301d7b5580bf5edae39 # v8.2.0 + uses: astral-sh/setup-uv@d31148d669074a8d0a63714ba94f3201e7020bc3 # v8.3.0 with: # Before upgrading uv version, make sure astral-sh/setup-uv knows its checksum. # See: https://github.com/astral-sh/setup-uv/issues/851#issuecomment-4282017837 diff --git a/.github/workflows/topic-repos.yml b/.github/workflows/topic-repos.yml index b0fb40398..762422813 100644 --- a/.github/workflows/topic-repos.yml +++ b/.github/workflows/topic-repos.yml @@ -27,7 +27,7 @@ jobs: with: python-version-file: ".python-version" - name: Setup uv - uses: astral-sh/setup-uv@fac544c07dec837d0ccb6301d7b5580bf5edae39 # v8.2.0 + uses: astral-sh/setup-uv@d31148d669074a8d0a63714ba94f3201e7020bc3 # v8.3.0 with: # Before upgrading uv version, make sure astral-sh/setup-uv knows its checksum. # See: https://github.com/astral-sh/setup-uv/issues/851#issuecomment-4282017837 diff --git a/.github/workflows/translate.yml b/.github/workflows/translate.yml index 7f96798da..abe77537b 100644 --- a/.github/workflows/translate.yml +++ b/.github/workflows/translate.yml @@ -58,7 +58,7 @@ jobs: with: python-version-file: ".python-version" - name: Setup uv - uses: astral-sh/setup-uv@fac544c07dec837d0ccb6301d7b5580bf5edae39 # v8.2.0 + uses: astral-sh/setup-uv@d31148d669074a8d0a63714ba94f3201e7020bc3 # v8.3.0 with: # Before upgrading uv version, make sure astral-sh/setup-uv knows its checksum. # See: https://github.com/astral-sh/setup-uv/issues/851#issuecomment-4282017837 @@ -101,7 +101,7 @@ jobs: with: python-version-file: ".python-version" - name: Setup uv - uses: astral-sh/setup-uv@fac544c07dec837d0ccb6301d7b5580bf5edae39 # v8.2.0 + uses: astral-sh/setup-uv@d31148d669074a8d0a63714ba94f3201e7020bc3 # v8.3.0 with: # Before upgrading uv version, make sure astral-sh/setup-uv knows its checksum. # See: https://github.com/astral-sh/setup-uv/issues/851#issuecomment-4282017837 From b335c906e1495c1b35100823b8b33639879d15f2 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Mon, 13 Jul 2026 10:16:09 +0000 Subject: [PATCH 420/462] =?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 c34a60abf..1eb4c57c7 100644 --- a/docs/en/docs/release-notes.md +++ b/docs/en/docs/release-notes.md @@ -15,6 +15,7 @@ hide: ### Internal +* ⬆ Bump the github-actions group across 1 directory with 4 updates. PR [#15983](https://github.com/fastapi/fastapi/pull/15983) by [@dependabot[bot]](https://github.com/apps/dependabot). * ⬆ Bump pre-commit hooks. PR [#15985](https://github.com/fastapi/fastapi/pull/15985) by [@tiangolo](https://github.com/tiangolo). * 👷 Use `FASTAPI_LATEST_CHANGES` token in `bump-pre-commit-hooks` workflow. PR [#15984](https://github.com/fastapi/fastapi/pull/15984) by [@YuriiMotov](https://github.com/YuriiMotov). * 👷 Add GH workflow to bump pre-commit hook versions. PR [#15873](https://github.com/fastapi/fastapi/pull/15873) by [@YuriiMotov](https://github.com/YuriiMotov). From 87bbab1b739e7f7018bb826bc929af5c0e8e5d40 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 13 Jul 2026 12:26:39 +0200 Subject: [PATCH 421/462] =?UTF-8?q?=E2=AC=86=20Bump=20typing-extensions=20?= =?UTF-8?q?from=204.15.0=20to=204.16.0=20(#15982)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- uv.lock | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/uv.lock b/uv.lock index 25cd6e8a8..aef17a4ef 100644 --- a/uv.lock +++ b/uv.lock @@ -4410,11 +4410,11 @@ wheels = [ [[package]] name = "typing-extensions" -version = "4.15.0" +version = "4.16.0" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/72/94/1a15dd82efb362ac84269196e94cf00f187f7ed21c242792a923cdb1c61f/typing_extensions-4.15.0.tar.gz", hash = "sha256:0cea48d173cc12fa28ecabc3b837ea3cf6f38c6d1136f85cbaaf598984861466", size = 109391, upload-time = "2025-08-25T13:49:26.313Z" } +sdist = { url = "https://files.pythonhosted.org/packages/f6/cc/6253133b5bb138fc3306cebfbda2c520f545d36b5be2c7255cc528bb45d6/typing_extensions-4.16.0.tar.gz", hash = "sha256:dc983d19a509c94dba722ee6abd33940f7c05a89e243c47e907eb4db6f1a43e5", size = 113555, upload-time = "2026-07-02T08:40:05.92Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/18/67/36e9267722cc04a6b9f15c7f3441c2363321a3ea07da7ae0c0707beb2a9c/typing_extensions-4.15.0-py3-none-any.whl", hash = "sha256:f0fa19c6845758ab08074a0cfa8b7aecb71c999ca73d62883bc25cc018c4e548", size = 44614, upload-time = "2025-08-25T13:49:24.86Z" }, + { url = "https://files.pythonhosted.org/packages/49/d3/b8441a820a491ddfc024b0b0cf0393375b75ea13866d9c66727e54c2fc80/typing_extensions-4.16.0-py3-none-any.whl", hash = "sha256:481caa481374e813c1b176ada14e97f1f67a4539ce9cfeb3f350d78d6370c2e8", size = 45571, upload-time = "2026-07-02T08:40:04.659Z" }, ] [[package]] From fd4c4cfc3e8d3ffc207ff9f510a27b459e79fa0f Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Mon, 13 Jul 2026 10:27:10 +0000 Subject: [PATCH 422/462] =?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 1eb4c57c7..1c22f832a 100644 --- a/docs/en/docs/release-notes.md +++ b/docs/en/docs/release-notes.md @@ -15,6 +15,7 @@ hide: ### Internal +* ⬆ Bump typing-extensions from 4.15.0 to 4.16.0. PR [#15982](https://github.com/fastapi/fastapi/pull/15982) by [@dependabot[bot]](https://github.com/apps/dependabot). * ⬆ Bump the github-actions group across 1 directory with 4 updates. PR [#15983](https://github.com/fastapi/fastapi/pull/15983) by [@dependabot[bot]](https://github.com/apps/dependabot). * ⬆ Bump pre-commit hooks. PR [#15985](https://github.com/fastapi/fastapi/pull/15985) by [@tiangolo](https://github.com/tiangolo). * 👷 Use `FASTAPI_LATEST_CHANGES` token in `bump-pre-commit-hooks` workflow. PR [#15984](https://github.com/fastapi/fastapi/pull/15984) by [@YuriiMotov](https://github.com/YuriiMotov). From 9405816f15ffa5e6c3558444a14791f3b62e0c99 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 13 Jul 2026 13:02:21 +0200 Subject: [PATCH 423/462] =?UTF-8?q?=E2=AC=86=20Bump=20the=20python-package?= =?UTF-8?q?s=20group=20across=201=20directory=20with=206=20updates=20(#159?= =?UTF-8?q?81)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- uv.lock | 328 ++++++++++++++++++++++++++++---------------------------- 1 file changed, 162 insertions(+), 166 deletions(-) diff --git a/uv.lock b/uv.lock index aef17a4ef..1918bdb67 100644 --- a/uv.lock +++ b/uv.lock @@ -1347,15 +1347,15 @@ wheels = [ [[package]] name = "genai-prices" -version = "0.0.62" +version = "0.0.71" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "httpx2" }, { name = "pydantic" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/0c/8e/ed322d1f22b57fd455749bdbe2f285d310e1c1ebe921cb3d5c0b920de648/genai_prices-0.0.62.tar.gz", hash = "sha256:baf1ffa64be0d15577878216464d6a2d04244db5fbdf78d56bde43809e7aef44", size = 67611, upload-time = "2026-05-25T18:47:16.306Z" } +sdist = { url = "https://files.pythonhosted.org/packages/1d/e4/5072862613fba039da2b7c981a8649c6c6bbcb2863bd8bc81617c09ce5ee/genai_prices-0.0.71.tar.gz", hash = "sha256:de4db34ec38404f9ef383cb1ab29e204d16ccf27071af0b16d5747ee7affe36b", size = 82105, upload-time = "2026-07-10T00:38:30.491Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/81/35/ce64112dcc6f406b3e290dcf57a97acfa2b7d3d0391979219cb9d4a9db6d/genai_prices-0.0.62-py3-none-any.whl", hash = "sha256:5d9ab0d9e5d81e035f88bf591fb6a8dde527922786acf1ee2737358f7bbe0167", size = 70333, upload-time = "2026-05-25T18:47:17.642Z" }, + { url = "https://files.pythonhosted.org/packages/0d/98/c06c1318f6834a26268a2d4280e4183f60c5ea92152aea841feff29826ff/genai_prices-0.0.71-py3-none-any.whl", hash = "sha256:1d13111563af2b1ce43ccfacf77b7ac3216ad704c644408a56e11b181fe0d128", size = 84586, upload-time = "2026-07-10T00:38:29.252Z" }, ] [[package]] @@ -2571,100 +2571,96 @@ wheels = [ [[package]] name = "pillow" -version = "12.2.0" -source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/8c/21/c2bcdd5906101a30244eaffc1b6e6ce71a31bd0742a01eb89e660ebfac2d/pillow-12.2.0.tar.gz", hash = "sha256:a830b1a40919539d07806aa58e1b114df53ddd43213d9c8b75847eee6c0182b5", size = 46987819, upload-time = "2026-04-01T14:46:17.687Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/3a/aa/d0b28e1c811cd4d5f5c2bfe2e022292bd255ae5744a3b9ac7d6c8f72dd75/pillow-12.2.0-cp310-cp310-macosx_10_10_x86_64.whl", hash = "sha256:a4e8f36e677d3336f35089648c8955c51c6d386a13cf6ee9c189c5f5bd713a9f", size = 5354355, upload-time = "2026-04-01T14:42:15.402Z" }, - { url = "https://files.pythonhosted.org/packages/27/8e/1d5b39b8ae2bd7650d0c7b6abb9602d16043ead9ebbfef4bc4047454da2a/pillow-12.2.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:2e589959f10d9824d39b350472b92f0ce3b443c0a3442ebf41c40cb8361c5b97", size = 4695871, upload-time = "2026-04-01T14:42:18.234Z" }, - { url = "https://files.pythonhosted.org/packages/f0/c5/dcb7a6ca6b7d3be41a76958e90018d56c8462166b3ef223150360850c8da/pillow-12.2.0-cp310-cp310-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:a52edc8bfff4429aaabdf4d9ee0daadbbf8562364f940937b941f87a4290f5ff", size = 6269734, upload-time = "2026-04-01T14:42:20.608Z" }, - { url = "https://files.pythonhosted.org/packages/ea/f1/aa1bb13b2f4eba914e9637893c73f2af8e48d7d4023b9d3750d4c5eb2d0c/pillow-12.2.0-cp310-cp310-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:975385f4776fafde056abb318f612ef6285b10a1f12b8570f3647ad0d74b48ec", size = 8076080, upload-time = "2026-04-01T14:42:23.095Z" }, - { url = "https://files.pythonhosted.org/packages/a1/2a/8c79d6a53169937784604a8ae8d77e45888c41537f7f6f65ed1f407fe66d/pillow-12.2.0-cp310-cp310-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:bd9c0c7a0c681a347b3194c500cb1e6ca9cab053ea4d82a5cf45b6b754560136", size = 6382236, upload-time = "2026-04-01T14:42:25.82Z" }, - { url = "https://files.pythonhosted.org/packages/b5/42/bbcb6051030e1e421d103ce7a8ecadf837aa2f39b8f82ef1a8d37c3d4ebc/pillow-12.2.0-cp310-cp310-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:88d387ff40b3ff7c274947ed3125dedf5262ec6919d83946753b5f3d7c67ea4c", size = 7070220, upload-time = "2026-04-01T14:42:28.68Z" }, - { url = "https://files.pythonhosted.org/packages/3f/e1/c2a7d6dd8cfa6b231227da096fd2d58754bab3603b9d73bf609d3c18b64f/pillow-12.2.0-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:51c4167c34b0d8ba05b547a3bb23578d0ba17b80a5593f93bd8ecb123dd336a3", size = 6493124, upload-time = "2026-04-01T14:42:31.579Z" }, - { url = "https://files.pythonhosted.org/packages/5f/41/7c8617da5d32e1d2f026e509484fdb6f3ad7efaef1749a0c1928adbb099e/pillow-12.2.0-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:34c0d99ecccea270c04882cb3b86e7b57296079c9a4aff88cb3b33563d95afaa", size = 7194324, upload-time = "2026-04-01T14:42:34.615Z" }, - { url = "https://files.pythonhosted.org/packages/2d/de/a777627e19fd6d62f84070ee1521adde5eeda4855b5cf60fe0b149118bca/pillow-12.2.0-cp310-cp310-win32.whl", hash = "sha256:b85f66ae9eb53e860a873b858b789217ba505e5e405a24b85c0464822fe88032", size = 6376363, upload-time = "2026-04-01T14:42:37.19Z" }, - { url = "https://files.pythonhosted.org/packages/e7/34/fc4cb5204896465842767b96d250c08410f01f2f28afc43b257de842eed5/pillow-12.2.0-cp310-cp310-win_amd64.whl", hash = "sha256:673aa32138f3e7531ccdbca7b3901dba9b70940a19ccecc6a37c77d5fdeb05b5", size = 7083523, upload-time = "2026-04-01T14:42:39.62Z" }, - { url = "https://files.pythonhosted.org/packages/2d/a0/32852d36bc7709f14dc3f64f929a275e958ad8c19a6deba9610d458e28b3/pillow-12.2.0-cp310-cp310-win_arm64.whl", hash = "sha256:3e080565d8d7c671db5802eedfb438e5565ffa40115216eabb8cd52d0ecce024", size = 2463318, upload-time = "2026-04-01T14:42:42.063Z" }, - { url = "https://files.pythonhosted.org/packages/68/e1/748f5663efe6edcfc4e74b2b93edfb9b8b99b67f21a854c3ae416500a2d9/pillow-12.2.0-cp311-cp311-macosx_10_10_x86_64.whl", hash = "sha256:8be29e59487a79f173507c30ddf57e733a357f67881430449bb32614075a40ab", size = 5354347, upload-time = "2026-04-01T14:42:44.255Z" }, - { url = "https://files.pythonhosted.org/packages/47/a1/d5ff69e747374c33a3b53b9f98cca7889fce1fd03d79cdc4e1bccc6c5a87/pillow-12.2.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:71cde9a1e1551df7d34a25462fc60325e8a11a82cc2e2f54578e5e9a1e153d65", size = 4695873, upload-time = "2026-04-01T14:42:46.452Z" }, - { url = "https://files.pythonhosted.org/packages/df/21/e3fbdf54408a973c7f7f89a23b2cb97a7ef30c61ab4142af31eee6aebc88/pillow-12.2.0-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:f490f9368b6fc026f021db16d7ec2fbf7d89e2edb42e8ec09d2c60505f5729c7", size = 6280168, upload-time = "2026-04-01T14:42:49.228Z" }, - { url = "https://files.pythonhosted.org/packages/d3/f1/00b7278c7dd52b17ad4329153748f87b6756ec195ff786c2bdf12518337d/pillow-12.2.0-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:8bd7903a5f2a4545f6fd5935c90058b89d30045568985a71c79f5fd6edf9b91e", size = 8088188, upload-time = "2026-04-01T14:42:51.735Z" }, - { url = "https://files.pythonhosted.org/packages/ad/cf/220a5994ef1b10e70e85748b75649d77d506499352be135a4989c957b701/pillow-12.2.0-cp311-cp311-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:3997232e10d2920a68d25191392e3a4487d8183039e1c74c2297f00ed1c50705", size = 6394401, upload-time = "2026-04-01T14:42:54.343Z" }, - { url = "https://files.pythonhosted.org/packages/e9/bd/e51a61b1054f09437acfbc2ff9106c30d1eb76bc1453d428399946781253/pillow-12.2.0-cp311-cp311-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:e74473c875d78b8e9d5da2a70f7099549f9eb37ded4e2f6a463e60125bccd176", size = 7079655, upload-time = "2026-04-01T14:42:56.954Z" }, - { url = "https://files.pythonhosted.org/packages/6b/3d/45132c57d5fb4b5744567c3817026480ac7fc3ce5d4c47902bc0e7f6f853/pillow-12.2.0-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:56a3f9c60a13133a98ecff6197af34d7824de9b7b38c3654861a725c970c197b", size = 6503105, upload-time = "2026-04-01T14:42:59.847Z" }, - { url = "https://files.pythonhosted.org/packages/7d/2e/9df2fc1e82097b1df3dce58dc43286aa01068e918c07574711fcc53e6fb4/pillow-12.2.0-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:90e6f81de50ad6b534cab6e5aef77ff6e37722b2f5d908686f4a5c9eba17a909", size = 7203402, upload-time = "2026-04-01T14:43:02.664Z" }, - { url = "https://files.pythonhosted.org/packages/bd/2e/2941e42858ebb67e50ae741473de81c2984e6eff7b397017623c676e2e8d/pillow-12.2.0-cp311-cp311-win32.whl", hash = "sha256:8c984051042858021a54926eb597d6ee3012393ce9c181814115df4c60b9a808", size = 6378149, upload-time = "2026-04-01T14:43:05.274Z" }, - { url = "https://files.pythonhosted.org/packages/69/42/836b6f3cd7f3e5fa10a1f1a5420447c17966044c8fbf589cc0452d5502db/pillow-12.2.0-cp311-cp311-win_amd64.whl", hash = "sha256:6e6b2a0c538fc200b38ff9eb6628228b77908c319a005815f2dde585a0664b60", size = 7082626, upload-time = "2026-04-01T14:43:08.557Z" }, - { url = "https://files.pythonhosted.org/packages/c2/88/549194b5d6f1f494b485e493edc6693c0a16f4ada488e5bd974ed1f42fad/pillow-12.2.0-cp311-cp311-win_arm64.whl", hash = "sha256:9a8a34cc89c67a65ea7437ce257cea81a9dad65b29805f3ecee8c8fe8ff25ffe", size = 2463531, upload-time = "2026-04-01T14:43:10.743Z" }, - { url = "https://files.pythonhosted.org/packages/58/be/7482c8a5ebebbc6470b3eb791812fff7d5e0216c2be3827b30b8bb6603ed/pillow-12.2.0-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:2d192a155bbcec180f8564f693e6fd9bccff5a7af9b32e2e4bf8c9c69dbad6b5", size = 5308279, upload-time = "2026-04-01T14:43:13.246Z" }, - { url = "https://files.pythonhosted.org/packages/d8/95/0a351b9289c2b5cbde0bacd4a83ebc44023e835490a727b2a3bd60ddc0f4/pillow-12.2.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:f3f40b3c5a968281fd507d519e444c35f0ff171237f4fdde090dd60699458421", size = 4695490, upload-time = "2026-04-01T14:43:15.584Z" }, - { url = "https://files.pythonhosted.org/packages/de/af/4e8e6869cbed569d43c416fad3dc4ecb944cb5d9492defaed89ddd6fe871/pillow-12.2.0-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:03e7e372d5240cc23e9f07deca4d775c0817bffc641b01e9c3af208dbd300987", size = 6284462, upload-time = "2026-04-01T14:43:18.268Z" }, - { url = "https://files.pythonhosted.org/packages/e9/9e/c05e19657fd57841e476be1ab46c4d501bffbadbafdc31a6d665f8b737b6/pillow-12.2.0-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:b86024e52a1b269467a802258c25521e6d742349d760728092e1bc2d135b4d76", size = 8094744, upload-time = "2026-04-01T14:43:20.716Z" }, - { url = "https://files.pythonhosted.org/packages/2b/54/1789c455ed10176066b6e7e6da1b01e50e36f94ba584dc68d9eebfe9156d/pillow-12.2.0-cp312-cp312-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:7371b48c4fa448d20d2714c9a1f775a81155050d383333e0a6c15b1123dda005", size = 6398371, upload-time = "2026-04-01T14:43:23.443Z" }, - { url = "https://files.pythonhosted.org/packages/43/e3/fdc657359e919462369869f1c9f0e973f353f9a9ee295a39b1fea8ee1a77/pillow-12.2.0-cp312-cp312-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:62f5409336adb0663b7caa0da5c7d9e7bdbaae9ce761d34669420c2a801b2780", size = 7087215, upload-time = "2026-04-01T14:43:26.758Z" }, - { url = "https://files.pythonhosted.org/packages/8b/f8/2f6825e441d5b1959d2ca5adec984210f1ec086435b0ed5f52c19b3b8a6e/pillow-12.2.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:01afa7cf67f74f09523699b4e88c73fb55c13346d212a59a2db1f86b0a63e8c5", size = 6509783, upload-time = "2026-04-01T14:43:29.56Z" }, - { url = "https://files.pythonhosted.org/packages/67/f9/029a27095ad20f854f9dba026b3ea6428548316e057e6fc3545409e86651/pillow-12.2.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:fc3d34d4a8fbec3e88a79b92e5465e0f9b842b628675850d860b8bd300b159f5", size = 7212112, upload-time = "2026-04-01T14:43:32.091Z" }, - { url = "https://files.pythonhosted.org/packages/be/42/025cfe05d1be22dbfdb4f264fe9de1ccda83f66e4fc3aac94748e784af04/pillow-12.2.0-cp312-cp312-win32.whl", hash = "sha256:58f62cc0f00fd29e64b29f4fd923ffdb3859c9f9e6105bfc37ba1d08994e8940", size = 6378489, upload-time = "2026-04-01T14:43:34.601Z" }, - { url = "https://files.pythonhosted.org/packages/5d/7b/25a221d2c761c6a8ae21bfa3874988ff2583e19cf8a27bf2fee358df7942/pillow-12.2.0-cp312-cp312-win_amd64.whl", hash = "sha256:7f84204dee22a783350679a0333981df803dac21a0190d706a50475e361c93f5", size = 7084129, upload-time = "2026-04-01T14:43:37.213Z" }, - { url = "https://files.pythonhosted.org/packages/10/e1/542a474affab20fd4a0f1836cb234e8493519da6b76899e30bcc5d990b8b/pillow-12.2.0-cp312-cp312-win_arm64.whl", hash = "sha256:af73337013e0b3b46f175e79492d96845b16126ddf79c438d7ea7ff27783a414", size = 2463612, upload-time = "2026-04-01T14:43:39.421Z" }, - { url = "https://files.pythonhosted.org/packages/4a/01/53d10cf0dbad820a8db274d259a37ba50b88b24768ddccec07355382d5ad/pillow-12.2.0-cp313-cp313-ios_13_0_arm64_iphoneos.whl", hash = "sha256:8297651f5b5679c19968abefd6bb84d95fe30ef712eb1b2d9b2d31ca61267f4c", size = 4100837, upload-time = "2026-04-01T14:43:41.506Z" }, - { url = "https://files.pythonhosted.org/packages/0f/98/f3a6657ecb698c937f6c76ee564882945f29b79bad496abcba0e84659ec5/pillow-12.2.0-cp313-cp313-ios_13_0_arm64_iphonesimulator.whl", hash = "sha256:50d8520da2a6ce0af445fa6d648c4273c3eeefbc32d7ce049f22e8b5c3daecc2", size = 4176528, upload-time = "2026-04-01T14:43:43.773Z" }, - { url = "https://files.pythonhosted.org/packages/69/bc/8986948f05e3ea490b8442ea1c1d4d990b24a7e43d8a51b2c7d8b1dced36/pillow-12.2.0-cp313-cp313-ios_13_0_x86_64_iphonesimulator.whl", hash = "sha256:766cef22385fa1091258ad7e6216792b156dc16d8d3fa607e7545b2b72061f1c", size = 3640401, upload-time = "2026-04-01T14:43:45.87Z" }, - { url = "https://files.pythonhosted.org/packages/34/46/6c717baadcd62bc8ed51d238d521ab651eaa74838291bda1f86fe1f864c9/pillow-12.2.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:5d2fd0fa6b5d9d1de415060363433f28da8b1526c1c129020435e186794b3795", size = 5308094, upload-time = "2026-04-01T14:43:48.438Z" }, - { url = "https://files.pythonhosted.org/packages/71/43/905a14a8b17fdb1ccb58d282454490662d2cb89a6bfec26af6d3520da5ec/pillow-12.2.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:56b25336f502b6ed02e889f4ece894a72612fe885889a6e8c4c80239ff6e5f5f", size = 4695402, upload-time = "2026-04-01T14:43:51.292Z" }, - { url = "https://files.pythonhosted.org/packages/73/dd/42107efcb777b16fa0393317eac58f5b5cf30e8392e266e76e51cff28c3d/pillow-12.2.0-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:f1c943e96e85df3d3478f7b691f229887e143f81fedab9b20205349ab04d73ed", size = 6280005, upload-time = "2026-04-01T14:43:54.242Z" }, - { url = "https://files.pythonhosted.org/packages/a8/68/b93e09e5e8549019e61acf49f65b1a8530765a7f812c77a7461bca7e4494/pillow-12.2.0-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:03f6fab9219220f041c74aeaa2939ff0062bd5c364ba9ce037197f4c6d498cd9", size = 8090669, upload-time = "2026-04-01T14:43:57.335Z" }, - { url = "https://files.pythonhosted.org/packages/4b/6e/3ccb54ce8ec4ddd1accd2d89004308b7b0b21c4ac3d20fa70af4760a4330/pillow-12.2.0-cp313-cp313-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:5cdfebd752ec52bf5bb4e35d9c64b40826bc5b40a13df7c3cda20a2c03a0f5ed", size = 6395194, upload-time = "2026-04-01T14:43:59.864Z" }, - { url = "https://files.pythonhosted.org/packages/67/ee/21d4e8536afd1a328f01b359b4d3997b291ffd35a237c877b331c1c3b71c/pillow-12.2.0-cp313-cp313-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:eedf4b74eda2b5a4b2b2fb4c006d6295df3bf29e459e198c90ea48e130dc75c3", size = 7082423, upload-time = "2026-04-01T14:44:02.74Z" }, - { url = "https://files.pythonhosted.org/packages/78/5f/e9f86ab0146464e8c133fe85df987ed9e77e08b29d8d35f9f9f4d6f917ba/pillow-12.2.0-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:00a2865911330191c0b818c59103b58a5e697cae67042366970a6b6f1b20b7f9", size = 6505667, upload-time = "2026-04-01T14:44:05.381Z" }, - { url = "https://files.pythonhosted.org/packages/ed/1e/409007f56a2fdce61584fd3acbc2bbc259857d555196cedcadc68c015c82/pillow-12.2.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:1e1757442ed87f4912397c6d35a0db6a7b52592156014706f17658ff58bbf795", size = 7208580, upload-time = "2026-04-01T14:44:08.39Z" }, - { url = "https://files.pythonhosted.org/packages/23/c4/7349421080b12fb35414607b8871e9534546c128a11965fd4a7002ccfbee/pillow-12.2.0-cp313-cp313-win32.whl", hash = "sha256:144748b3af2d1b358d41286056d0003f47cb339b8c43a9ea42f5fea4d8c66b6e", size = 6375896, upload-time = "2026-04-01T14:44:11.197Z" }, - { url = "https://files.pythonhosted.org/packages/3f/82/8a3739a5e470b3c6cbb1d21d315800d8e16bff503d1f16b03a4ec3212786/pillow-12.2.0-cp313-cp313-win_amd64.whl", hash = "sha256:390ede346628ccc626e5730107cde16c42d3836b89662a115a921f28440e6a3b", size = 7081266, upload-time = "2026-04-01T14:44:13.947Z" }, - { url = "https://files.pythonhosted.org/packages/c3/25/f968f618a062574294592f668218f8af564830ccebdd1fa6200f598e65c5/pillow-12.2.0-cp313-cp313-win_arm64.whl", hash = "sha256:8023abc91fba39036dbce14a7d6535632f99c0b857807cbbbf21ecc9f4717f06", size = 2463508, upload-time = "2026-04-01T14:44:16.312Z" }, - { url = "https://files.pythonhosted.org/packages/4d/a4/b342930964e3cb4dce5038ae34b0eab4653334995336cd486c5a8c25a00c/pillow-12.2.0-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:042db20a421b9bafecc4b84a8b6e444686bd9d836c7fd24542db3e7df7baad9b", size = 5309927, upload-time = "2026-04-01T14:44:18.89Z" }, - { url = "https://files.pythonhosted.org/packages/9f/de/23198e0a65a9cf06123f5435a5d95cea62a635697f8f03d134d3f3a96151/pillow-12.2.0-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:dd025009355c926a84a612fecf58bb315a3f6814b17ead51a8e48d3823d9087f", size = 4698624, upload-time = "2026-04-01T14:44:21.115Z" }, - { url = "https://files.pythonhosted.org/packages/01/a6/1265e977f17d93ea37aa28aa81bad4fa597933879fac2520d24e021c8da3/pillow-12.2.0-cp313-cp313t-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:88ddbc66737e277852913bd1e07c150cc7bb124539f94c4e2df5344494e0a612", size = 6321252, upload-time = "2026-04-01T14:44:23.663Z" }, - { url = "https://files.pythonhosted.org/packages/3c/83/5982eb4a285967baa70340320be9f88e57665a387e3a53a7f0db8231a0cd/pillow-12.2.0-cp313-cp313t-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:d362d1878f00c142b7e1a16e6e5e780f02be8195123f164edf7eddd911eefe7c", size = 8126550, upload-time = "2026-04-01T14:44:26.772Z" }, - { url = "https://files.pythonhosted.org/packages/4e/48/6ffc514adce69f6050d0753b1a18fd920fce8cac87620d5a31231b04bfc5/pillow-12.2.0-cp313-cp313t-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:2c727a6d53cb0018aadd8018c2b938376af27914a68a492f59dfcaca650d5eea", size = 6433114, upload-time = "2026-04-01T14:44:29.615Z" }, - { url = "https://files.pythonhosted.org/packages/36/a3/f9a77144231fb8d40ee27107b4463e205fa4677e2ca2548e14da5cf18dce/pillow-12.2.0-cp313-cp313t-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:efd8c21c98c5cc60653bcb311bef2ce0401642b7ce9d09e03a7da87c878289d4", size = 7115667, upload-time = "2026-04-01T14:44:32.773Z" }, - { url = "https://files.pythonhosted.org/packages/c1/fc/ac4ee3041e7d5a565e1c4fd72a113f03b6394cc72ab7089d27608f8aaccb/pillow-12.2.0-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:9f08483a632889536b8139663db60f6724bfcb443c96f1b18855860d7d5c0fd4", size = 6538966, upload-time = "2026-04-01T14:44:35.252Z" }, - { url = "https://files.pythonhosted.org/packages/c0/a8/27fb307055087f3668f6d0a8ccb636e7431d56ed0750e07a60547b1e083e/pillow-12.2.0-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:dac8d77255a37e81a2efcbd1fc05f1c15ee82200e6c240d7e127e25e365c39ea", size = 7238241, upload-time = "2026-04-01T14:44:37.875Z" }, - { url = "https://files.pythonhosted.org/packages/ad/4b/926ab182c07fccae9fcb120043464e1ff1564775ec8864f21a0ebce6ac25/pillow-12.2.0-cp313-cp313t-win32.whl", hash = "sha256:ee3120ae9dff32f121610bb08e4313be87e03efeadfc6c0d18f89127e24d0c24", size = 6379592, upload-time = "2026-04-01T14:44:40.336Z" }, - { url = "https://files.pythonhosted.org/packages/c2/c4/f9e476451a098181b30050cc4c9a3556b64c02cf6497ea421ac047e89e4b/pillow-12.2.0-cp313-cp313t-win_amd64.whl", hash = "sha256:325ca0528c6788d2a6c3d40e3568639398137346c3d6e66bb61db96b96511c98", size = 7085542, upload-time = "2026-04-01T14:44:43.251Z" }, - { url = "https://files.pythonhosted.org/packages/00/a4/285f12aeacbe2d6dc36c407dfbbe9e96d4a80b0fb710a337f6d2ad978c75/pillow-12.2.0-cp313-cp313t-win_arm64.whl", hash = "sha256:2e5a76d03a6c6dcef67edabda7a52494afa4035021a79c8558e14af25313d453", size = 2465765, upload-time = "2026-04-01T14:44:45.996Z" }, - { url = "https://files.pythonhosted.org/packages/bf/98/4595daa2365416a86cb0d495248a393dfc84e96d62ad080c8546256cb9c0/pillow-12.2.0-cp314-cp314-ios_13_0_arm64_iphoneos.whl", hash = "sha256:3adc9215e8be0448ed6e814966ecf3d9952f0ea40eb14e89a102b87f450660d8", size = 4100848, upload-time = "2026-04-01T14:44:48.48Z" }, - { url = "https://files.pythonhosted.org/packages/0b/79/40184d464cf89f6663e18dfcf7ca21aae2491fff1a16127681bf1fa9b8cf/pillow-12.2.0-cp314-cp314-ios_13_0_arm64_iphonesimulator.whl", hash = "sha256:6a9adfc6d24b10f89588096364cc726174118c62130c817c2837c60cf08a392b", size = 4176515, upload-time = "2026-04-01T14:44:51.353Z" }, - { url = "https://files.pythonhosted.org/packages/b0/63/703f86fd4c422a9cf722833670f4f71418fb116b2853ff7da722ea43f184/pillow-12.2.0-cp314-cp314-ios_13_0_x86_64_iphonesimulator.whl", hash = "sha256:6a6e67ea2e6feda684ed370f9a1c52e7a243631c025ba42149a2cc5934dec295", size = 3640159, upload-time = "2026-04-01T14:44:53.588Z" }, - { url = "https://files.pythonhosted.org/packages/71/e0/fb22f797187d0be2270f83500aab851536101b254bfa1eae10795709d283/pillow-12.2.0-cp314-cp314-macosx_10_15_x86_64.whl", hash = "sha256:2bb4a8d594eacdfc59d9e5ad972aa8afdd48d584ffd5f13a937a664c3e7db0ed", size = 5312185, upload-time = "2026-04-01T14:44:56.039Z" }, - { url = "https://files.pythonhosted.org/packages/ba/8c/1a9e46228571de18f8e28f16fabdfc20212a5d019f3e3303452b3f0a580d/pillow-12.2.0-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:80b2da48193b2f33ed0c32c38140f9d3186583ce7d516526d462645fd98660ae", size = 4695386, upload-time = "2026-04-01T14:44:58.663Z" }, - { url = "https://files.pythonhosted.org/packages/70/62/98f6b7f0c88b9addd0e87c217ded307b36be024d4ff8869a812b241d1345/pillow-12.2.0-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:22db17c68434de69d8ecfc2fe821569195c0c373b25cccb9cbdacf2c6e53c601", size = 6280384, upload-time = "2026-04-01T14:45:01.5Z" }, - { url = "https://files.pythonhosted.org/packages/5e/03/688747d2e91cfbe0e64f316cd2e8005698f76ada3130d0194664174fa5de/pillow-12.2.0-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:7b14cc0106cd9aecda615dd6903840a058b4700fcb817687d0ee4fc8b6e389be", size = 8091599, upload-time = "2026-04-01T14:45:04.5Z" }, - { url = "https://files.pythonhosted.org/packages/f6/35/577e22b936fcdd66537329b33af0b4ccfefaeabd8aec04b266528cddb33c/pillow-12.2.0-cp314-cp314-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:8cbeb542b2ebc6fcdacabf8aca8c1a97c9b3ad3927d46b8723f9d4f033288a0f", size = 6396021, upload-time = "2026-04-01T14:45:07.117Z" }, - { url = "https://files.pythonhosted.org/packages/11/8d/d2532ad2a603ca2b93ad9f5135732124e57811d0168155852f37fbce2458/pillow-12.2.0-cp314-cp314-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:4bfd07bc812fbd20395212969e41931001fd59eb55a60658b0e5710872e95286", size = 7083360, upload-time = "2026-04-01T14:45:09.763Z" }, - { url = "https://files.pythonhosted.org/packages/5e/26/d325f9f56c7e039034897e7380e9cc202b1e368bfd04d4cbe6a441f02885/pillow-12.2.0-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:9aba9a17b623ef750a4d11b742cbafffeb48a869821252b30ee21b5e91392c50", size = 6507628, upload-time = "2026-04-01T14:45:12.378Z" }, - { url = "https://files.pythonhosted.org/packages/5f/f7/769d5632ffb0988f1c5e7660b3e731e30f7f8ec4318e94d0a5d674eb65a4/pillow-12.2.0-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:deede7c263feb25dba4e82ea23058a235dcc2fe1f6021025dc71f2b618e26104", size = 7209321, upload-time = "2026-04-01T14:45:15.122Z" }, - { url = "https://files.pythonhosted.org/packages/6a/7a/c253e3c645cd47f1aceea6a8bacdba9991bf45bb7dfe927f7c893e89c93c/pillow-12.2.0-cp314-cp314-win32.whl", hash = "sha256:632ff19b2778e43162304d50da0181ce24ac5bb8180122cbe1bf4673428328c7", size = 6479723, upload-time = "2026-04-01T14:45:17.797Z" }, - { url = "https://files.pythonhosted.org/packages/cd/8b/601e6566b957ca50e28725cb6c355c59c2c8609751efbecd980db44e0349/pillow-12.2.0-cp314-cp314-win_amd64.whl", hash = "sha256:4e6c62e9d237e9b65fac06857d511e90d8461a32adcc1b9065ea0c0fa3a28150", size = 7217400, upload-time = "2026-04-01T14:45:20.529Z" }, - { url = "https://files.pythonhosted.org/packages/d6/94/220e46c73065c3e2951bb91c11a1fb636c8c9ad427ac3ce7d7f3359b9b2f/pillow-12.2.0-cp314-cp314-win_arm64.whl", hash = "sha256:b1c1fbd8a5a1af3412a0810d060a78b5136ec0836c8a4ef9aa11807f2a22f4e1", size = 2554835, upload-time = "2026-04-01T14:45:23.162Z" }, - { url = "https://files.pythonhosted.org/packages/b6/ab/1b426a3974cb0e7da5c29ccff4807871d48110933a57207b5a676cccc155/pillow-12.2.0-cp314-cp314t-macosx_10_15_x86_64.whl", hash = "sha256:57850958fe9c751670e49b2cecf6294acc99e562531f4bd317fa5ddee2068463", size = 5314225, upload-time = "2026-04-01T14:45:25.637Z" }, - { url = "https://files.pythonhosted.org/packages/19/1e/dce46f371be2438eecfee2a1960ee2a243bbe5e961890146d2dee1ff0f12/pillow-12.2.0-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:d5d38f1411c0ed9f97bcb49b7bd59b6b7c314e0e27420e34d99d844b9ce3b6f3", size = 4698541, upload-time = "2026-04-01T14:45:28.355Z" }, - { url = "https://files.pythonhosted.org/packages/55/c3/7fbecf70adb3a0c33b77a300dc52e424dc22ad8cdc06557a2e49523b703d/pillow-12.2.0-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:5c0a9f29ca8e79f09de89293f82fc9b0270bb4af1d58bc98f540cc4aedf03166", size = 6322251, upload-time = "2026-04-01T14:45:30.924Z" }, - { url = "https://files.pythonhosted.org/packages/1c/3c/7fbc17cfb7e4fe0ef1642e0abc17fc6c94c9f7a16be41498e12e2ba60408/pillow-12.2.0-cp314-cp314t-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:1610dd6c61621ae1cf811bef44d77e149ce3f7b95afe66a4512f8c59f25d9ebe", size = 8127807, upload-time = "2026-04-01T14:45:33.908Z" }, - { url = "https://files.pythonhosted.org/packages/ff/c3/a8ae14d6defd2e448493ff512fae903b1e9bd40b72efb6ec55ce0048c8ce/pillow-12.2.0-cp314-cp314t-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:0a34329707af4f73cf1782a36cd2289c0368880654a2c11f027bcee9052d35dd", size = 6433935, upload-time = "2026-04-01T14:45:36.623Z" }, - { url = "https://files.pythonhosted.org/packages/6e/32/2880fb3a074847ac159d8f902cb43278a61e85f681661e7419e6596803ed/pillow-12.2.0-cp314-cp314t-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:8e9c4f5b3c546fa3458a29ab22646c1c6c787ea8f5ef51300e5a60300736905e", size = 7116720, upload-time = "2026-04-01T14:45:39.258Z" }, - { url = "https://files.pythonhosted.org/packages/46/87/495cc9c30e0129501643f24d320076f4cc54f718341df18cc70ec94c44e1/pillow-12.2.0-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:fb043ee2f06b41473269765c2feae53fc2e2fbf96e5e22ca94fb5ad677856f06", size = 6540498, upload-time = "2026-04-01T14:45:41.879Z" }, - { url = "https://files.pythonhosted.org/packages/18/53/773f5edca692009d883a72211b60fdaf8871cbef075eaa9d577f0a2f989e/pillow-12.2.0-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:f278f034eb75b4e8a13a54a876cc4a5ab39173d2cdd93a638e1b467fc545ac43", size = 7239413, upload-time = "2026-04-01T14:45:44.705Z" }, - { url = "https://files.pythonhosted.org/packages/c9/e4/4b64a97d71b2a83158134abbb2f5bd3f8a2ea691361282f010998f339ec7/pillow-12.2.0-cp314-cp314t-win32.whl", hash = "sha256:6bb77b2dcb06b20f9f4b4a8454caa581cd4dd0643a08bacf821216a16d9c8354", size = 6482084, upload-time = "2026-04-01T14:45:47.568Z" }, - { url = "https://files.pythonhosted.org/packages/ba/13/306d275efd3a3453f72114b7431c877d10b1154014c1ebbedd067770d629/pillow-12.2.0-cp314-cp314t-win_amd64.whl", hash = "sha256:6562ace0d3fb5f20ed7290f1f929cae41b25ae29528f2af1722966a0a02e2aa1", size = 7225152, upload-time = "2026-04-01T14:45:50.032Z" }, - { url = "https://files.pythonhosted.org/packages/ff/6e/cf826fae916b8658848d7b9f38d88da6396895c676e8086fc0988073aaf8/pillow-12.2.0-cp314-cp314t-win_arm64.whl", hash = "sha256:aa88ccfe4e32d362816319ed727a004423aab09c5cea43c01a4b435643fa34eb", size = 2556579, upload-time = "2026-04-01T14:45:52.529Z" }, - { url = "https://files.pythonhosted.org/packages/4e/b7/2437044fb910f499610356d1352e3423753c98e34f915252aafecc64889f/pillow-12.2.0-pp311-pypy311_pp73-macosx_10_15_x86_64.whl", hash = "sha256:0538bd5e05efec03ae613fd89c4ce0368ecd2ba239cc25b9f9be7ed426b0af1f", size = 5273969, upload-time = "2026-04-01T14:45:55.538Z" }, - { url = "https://files.pythonhosted.org/packages/f6/f4/8316e31de11b780f4ac08ef3654a75555e624a98db1056ecb2122d008d5a/pillow-12.2.0-pp311-pypy311_pp73-macosx_11_0_arm64.whl", hash = "sha256:394167b21da716608eac917c60aa9b969421b5dcbbe02ae7f013e7b85811c69d", size = 4659674, upload-time = "2026-04-01T14:45:58.093Z" }, - { url = "https://files.pythonhosted.org/packages/d4/37/664fca7201f8bb2aa1d20e2c3d5564a62e6ae5111741966c8319ca802361/pillow-12.2.0-pp311-pypy311_pp73-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:5d04bfa02cc2d23b497d1e90a0f927070043f6cbf303e738300532379a4b4e0f", size = 5288479, upload-time = "2026-04-01T14:46:01.141Z" }, - { url = "https://files.pythonhosted.org/packages/49/62/5b0ed78fce87346be7a5cfcfaaad91f6a1f98c26f86bdbafa2066c647ef6/pillow-12.2.0-pp311-pypy311_pp73-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:0c838a5125cee37e68edec915651521191cef1e6aa336b855f495766e77a366e", size = 7032230, upload-time = "2026-04-01T14:46:03.874Z" }, - { url = "https://files.pythonhosted.org/packages/c3/28/ec0fc38107fc32536908034e990c47914c57cd7c5a3ece4d8d8f7ffd7e27/pillow-12.2.0-pp311-pypy311_pp73-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:4a6c9fa44005fa37a91ebfc95d081e8079757d2e904b27103f4f5fa6f0bf78c0", size = 5355404, upload-time = "2026-04-01T14:46:06.33Z" }, - { url = "https://files.pythonhosted.org/packages/5e/8b/51b0eddcfa2180d60e41f06bd6d0a62202b20b59c68f5a132e615b75aecf/pillow-12.2.0-pp311-pypy311_pp73-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:25373b66e0dd5905ed63fa3cae13c82fbddf3079f2c8bf15c6fb6a35586324c1", size = 6002215, upload-time = "2026-04-01T14:46:08.83Z" }, - { url = "https://files.pythonhosted.org/packages/bc/60/5382c03e1970de634027cee8e1b7d39776b778b81812aaf45b694dfe9e28/pillow-12.2.0-pp311-pypy311_pp73-win_amd64.whl", hash = "sha256:bfa9c230d2fe991bed5318a5f119bd6780cda2915cca595393649fc118ab895e", size = 7080946, upload-time = "2026-04-01T14:46:11.734Z" }, +version = "12.3.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/1c/3d/bb7fca845737cf9d7dbde16ed1843984665ff2e0a518f5db43e77ec540b9/pillow-12.3.0.tar.gz", hash = "sha256:3b8182a766685eaa002637e28b4ec8d6b18819a0c71f579bf0dbaa5830297cce", size = 47025035, upload-time = "2026-07-01T11:56:38.965Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/25/c2/669d88644cddb1485bd9534e63e8cf476c8e51cb3c3a1297677023505c0e/pillow-12.3.0-cp310-cp310-macosx_10_10_x86_64.whl", hash = "sha256:6c0016e7b354317c4e9e525b937ac8596c38d2d232b419529b9cd7a1cd46e39a", size = 5392418, upload-time = "2026-07-01T11:53:27.808Z" }, + { url = "https://files.pythonhosted.org/packages/6b/ba/3762f376a2948e3036488d773a146e0ae6ecc2ca03ac20e2615bd0b2ba02/pillow-12.3.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:bcc33feacfaefce60c12fd500a277533bdc02b10a19f7f6d348763d8140bbba7", size = 4785287, upload-time = "2026-07-01T11:53:29.761Z" }, + { url = "https://files.pythonhosted.org/packages/07/50/b5d688cc9c52d4482f3d5bcab6ce20bc2a74a85d2343841c907444a3be2c/pillow-12.3.0-cp310-cp310-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:5594fc43d548a7ed94949d139aa1341b270f1863f11cfd37f5a6c8b778a6b67f", size = 6253754, upload-time = "2026-07-01T11:53:32.298Z" }, + { url = "https://files.pythonhosted.org/packages/4e/89/36f4cd76cf4baf05c50ababb976249153f18c959171c7f6ba09a6f217260/pillow-12.3.0-cp310-cp310-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:f0606c8bf2cdefea14a43530f7657cbbb7ecf1c4222512492ef4a4434a9501ec", size = 6925605, upload-time = "2026-07-01T11:53:34.487Z" }, + { url = "https://files.pythonhosted.org/packages/eb/c0/4de58cf6633b9e3a6061ef4be6fb91fc3c90b812ece886f531e3c523d777/pillow-12.3.0-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:85f998ea1848bc6757289e739cfbdda3a04adfd58b02fc018ce54d754a5ce468", size = 6327788, upload-time = "2026-07-01T11:53:36.433Z" }, + { url = "https://files.pythonhosted.org/packages/87/3c/14d53682a19550dbbaf3b598f807d5457646c510805a44c7d7891cd1cd1a/pillow-12.3.0-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:25b9b82bb22e6e2b3cd07b39c68b7b862001226cb3dff7130d1cb914121b39ed", size = 7036288, upload-time = "2026-07-01T11:53:38.712Z" }, + { url = "https://files.pythonhosted.org/packages/38/1d/36279e3c77efe034e4cc2b0393ee74ffdb5a62391dacbf9b916154f5f0b8/pillow-12.3.0-cp310-cp310-win32.whl", hash = "sha256:37dc8f7bbb66efe481bb60defacef820c950c24713fb44962ed6aa2a50966de1", size = 6472396, upload-time = "2026-07-01T11:53:40.781Z" }, + { url = "https://files.pythonhosted.org/packages/48/7c/8fa0039574c476d7c6fa57dd7c32a130436877c6ec1e5ce1cc8ec44878c1/pillow-12.3.0-cp310-cp310-win_amd64.whl", hash = "sha256:300557495eb45ebb8aec96c2da9c4be642fbf7cd937278b4013ba894ea8eb0eb", size = 7226887, upload-time = "2026-07-01T11:53:42.764Z" }, + { url = "https://files.pythonhosted.org/packages/fa/17/e324be141d173c1c919428066c3259f21c1b8982e564e01a4a81e96dbdcf/pillow-12.3.0-cp310-cp310-win_arm64.whl", hash = "sha256:514435a37670e3e5e08f3945b68718b6ed329bb84367777e16f9f4dfe1e61a0f", size = 2568039, upload-time = "2026-07-01T11:53:45.372Z" }, + { url = "https://files.pythonhosted.org/packages/fb/c8/0a78b0e02d7ac54bc03e5321c9220da52f0c2ea83b21f7c40e7f3169c502/pillow-12.3.0-cp311-cp311-macosx_10_10_x86_64.whl", hash = "sha256:00808c5e14ef63ac5161091d242999076604ff74b883423a11e5d7bbb38bf756", size = 5392415, upload-time = "2026-07-01T11:53:47.162Z" }, + { url = "https://files.pythonhosted.org/packages/b2/5b/a02d30018abd97ced9f5a6c63d28597694a00d066516b9c1c6de45859fc9/pillow-12.3.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:37d6d0a00072fd2948eb22bce7e1475f34569d90c87c59f7a2ec59541b77f7a6", size = 4785266, upload-time = "2026-07-01T11:53:49.079Z" }, + { url = "https://files.pythonhosted.org/packages/c8/98/766667a4be768150a202836acd9fad19c06824ca86c4286d3cf6b274964e/pillow-12.3.0-cp311-cp311-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:bcb46e2f9feff8d06323983bd83ed00c201fdcab3d74973e7072a889b3979fcd", size = 6263814, upload-time = "2026-07-01T11:53:51.32Z" }, + { url = "https://files.pythonhosted.org/packages/3b/2d/ede717bc1144f63886c21fd349bb95860b0d1a21149ff16f2bb362b612b6/pillow-12.3.0-cp311-cp311-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:23d27a3e0307ec2244cc51e7287b919aa68d097504ebe19df4e76a98a3eea5bd", size = 6934408, upload-time = "2026-07-01T11:53:53.487Z" }, + { url = "https://files.pythonhosted.org/packages/a3/48/9c58b685e69d49c31af6c8eb9012055fab7e665785165c84796e2c73ce72/pillow-12.3.0-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:4f883547d4b7f0495ebe7056b0cc2aea76094e7a4abc8e933540f3271df27d9c", size = 6337160, upload-time = "2026-07-01T11:53:55.457Z" }, + { url = "https://files.pythonhosted.org/packages/ff/fa/dc2a5c0ba6df93f67c31d34b808b7ce440b40cdbf96f0b81cde1d1e6fa93/pillow-12.3.0-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:236ff70b9312fb68943c703aa842ca6a758abfa45ac187a5e7c1452e96ef72b5", size = 7045172, upload-time = "2026-07-01T11:53:57.736Z" }, + { url = "https://files.pythonhosted.org/packages/86/a5/444817a4d4c4c2417df00513086ca196f388d8f9ef40c2e4ccd1ad1af54b/pillow-12.3.0-cp311-cp311-win32.whl", hash = "sha256:10e41f0fbf1eec8cfd234b8fe17a4caac7c9d0db4c204d3c173a8f9f6ef3232b", size = 6472232, upload-time = "2026-07-01T11:53:59.767Z" }, + { url = "https://files.pythonhosted.org/packages/63/c6/4bad1b18d132a50b27e1365e1ab163616f7a5bb56d330f66f9d1d9d4f9d4/pillow-12.3.0-cp311-cp311-win_amd64.whl", hash = "sha256:8e95e1385e4998ae9694eeaa4730ba5457ff61185b3a55e2e7bea0880aef452a", size = 7233653, upload-time = "2026-07-01T11:54:02.066Z" }, + { url = "https://files.pythonhosted.org/packages/fd/16/00f91ab7760dc842f5aad55217e80fc4a7067a0604535249bc8a2d6d9870/pillow-12.3.0-cp311-cp311-win_arm64.whl", hash = "sha256:ebaea975e03d3141d9d3a507df75c9b3ec90fa9d2ffd07567b3a978d9d790b26", size = 2568195, upload-time = "2026-07-01T11:54:04.622Z" }, + { url = "https://files.pythonhosted.org/packages/37/bf/fb3ebff8ddcb76aac5a01389251bbbb9519922a9b520d8247c1ca864a25d/pillow-12.3.0-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:ba09209fbe443b4acccebe845d8a138b89a8f4fbaeedd44953490b5315d5e965", size = 5345969, upload-time = "2026-07-01T11:54:06.397Z" }, + { url = "https://files.pythonhosted.org/packages/d8/66/9a386a92561f402389a4fc70c18838bf6d35eb5eb5c6850b4b2dc64f5048/pillow-12.3.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:ffd0c5368496f41b0944be820fcb7a838aa6e623d250b01acf2643939c3f99d7", size = 4780323, upload-time = "2026-07-01T11:54:09.351Z" }, + { url = "https://files.pythonhosted.org/packages/25/27/ac8f99618ffd3dde21db0f4d4b1d2ab00c0880595bfd17df103f7f39fd0c/pillow-12.3.0-cp312-cp312-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:d9c7f76c0673154f044e9d78c8655fb4213f6ca31a836df48b40fe5d187717b9", size = 6266838, upload-time = "2026-07-01T11:54:11.71Z" }, + { url = "https://files.pythonhosted.org/packages/84/21/a35af28dcc61f37ed850a2d64c65c701321dfbf25085e469d5559360cbbf/pillow-12.3.0-cp312-cp312-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:78cb2c6865a35ab8ff8b75fd122f6033b92a62c82801110e48ddd6c936a45d91", size = 6940830, upload-time = "2026-07-01T11:54:13.732Z" }, + { url = "https://files.pythonhosted.org/packages/eb/51/8b08617af3ad95e33ce6d7dd2c99ed6c8298f7fb131636303956be022e25/pillow-12.3.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:e491916b378fba47242221bb9ead245211b70d504f495d105d17b14a24b4907c", size = 6344383, upload-time = "2026-07-01T11:54:15.756Z" }, + { url = "https://files.pythonhosted.org/packages/1d/72/cf78ac9780bb93c28328f408973845a309d4d145041665f734572ced1b52/pillow-12.3.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:0dd2064cbc55aaec028ef5fbb60fa47bb6c3e7918e07ff17935284b227a9d2df", size = 7052934, upload-time = "2026-07-01T11:54:17.721Z" }, + { url = "https://files.pythonhosted.org/packages/20/20/25e0f4dc178a6bc0696793720055519a0de89e7661dae886992decbd2f81/pillow-12.3.0-cp312-cp312-win32.whl", hash = "sha256:dbce0b29841537a2fa4a214c2bbf14de3587c9680caa9b4e217568472490b28f", size = 6472684, upload-time = "2026-07-01T11:54:19.839Z" }, + { url = "https://files.pythonhosted.org/packages/45/89/da2f7971a317f83d807fdd4065c0af40208e59e692cc43d315a71a0e96d1/pillow-12.3.0-cp312-cp312-win_amd64.whl", hash = "sha256:a2b55dd6b2a4c4b7d87ffa56bdb33fdc5fdb9a462173861a7bc097f17d91cb09", size = 7227137, upload-time = "2026-07-01T11:54:22.025Z" }, + { url = "https://files.pythonhosted.org/packages/de/47/4845a0a6c0dbf1db8456bd9fc791f13c5ced7ced20606d08a0aacfd25b49/pillow-12.3.0-cp312-cp312-win_arm64.whl", hash = "sha256:331b624368d4f1d069149002f25f44bc61c8919ce8ddb3c45bdad8f6e2d89510", size = 2568267, upload-time = "2026-07-01T11:54:24.051Z" }, + { url = "https://files.pythonhosted.org/packages/9d/ac/31fb64e1e7efb5a4b50cd3d92049ba89ac6e4d8d3bb6a74e15048ca3353e/pillow-12.3.0-cp313-cp313-ios_13_0_arm64_iphoneos.whl", hash = "sha256:21900ce7ba264168cd50defae43cd75d25c833ad4ad6e73ffc5596d12e25ac89", size = 4161684, upload-time = "2026-07-01T11:54:25.934Z" }, + { url = "https://files.pythonhosted.org/packages/87/b4/9805e23d2b4d77842b468513841fda254ee42f0289d25088340e4ff46e2d/pillow-12.3.0-cp313-cp313-ios_13_0_arm64_iphonesimulator.whl", hash = "sha256:4e8c2a84d977f50b9daed6eeaf3baef67d00d5d74d932288f02cb94518ee3ace", size = 4255487, upload-time = "2026-07-01T11:54:27.935Z" }, + { url = "https://files.pythonhosted.org/packages/df/39/ecf519435a200c693fe053a6ee4d835b41cf963a4dfc2551c4e637cb2a71/pillow-12.3.0-cp313-cp313-ios_13_0_x86_64_iphonesimulator.whl", hash = "sha256:ae26d61dfa7a47befdc7572b521024e8745f3d809bd95ca9505a7bba9ef849ec", size = 3696433, upload-time = "2026-07-01T11:54:29.813Z" }, + { url = "https://files.pythonhosted.org/packages/42/92/2fc3ffad878ae8dd5469ec1bc8eb83b71f48e13efdf68f02709003982a32/pillow-12.3.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:7a743ff716f746fc19a9557f60dab1600d4613255f8a7aeb3cdde4db7eb15a66", size = 5345889, upload-time = "2026-07-01T11:54:31.97Z" }, + { url = "https://files.pythonhosted.org/packages/10/76/8803c13605b763d33d156c4678fc77f8443389c0c51c8aef707bb02015f4/pillow-12.3.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:d69141514cc30b774ceea5e3ed3a6635c8d8a96edf664689b890f4089111fb35", size = 4780109, upload-time = "2026-07-01T11:54:34.026Z" }, + { url = "https://files.pythonhosted.org/packages/1f/01/e18aff37cb0b4aac47ac90f016d347a49aca667ef97f190b06ac2aabc928/pillow-12.3.0-cp313-cp313-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:f7401aebd7f581d7f83a439d87d474999317ee099218e5ad25d125290990ba65", size = 6263736, upload-time = "2026-07-01T11:54:36.131Z" }, + { url = "https://files.pythonhosted.org/packages/f7/62/de5bdd77d935331f4f802edc11e4d82950f642caad6cb2f949837b8560e2/pillow-12.3.0-cp313-cp313-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:0847a763afefb695bc912d7c131e7e0632d4edc1d8698f58ddabec8e46b8b6d3", size = 6937129, upload-time = "2026-07-01T11:54:38.216Z" }, + { url = "https://files.pythonhosted.org/packages/70/4d/105627a13300c5e0df1d174230b32fd1273062c96f7745fd552b945d1e1d/pillow-12.3.0-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:571b9fcb07b97ef3a492028fb3d2dc0993ca23a06138b0315286566d29ef718a", size = 6339562, upload-time = "2026-07-01T11:54:40.354Z" }, + { url = "https://files.pythonhosted.org/packages/6b/1d/f13de01a553988ab895ba1c722e06cf3144d4f57656fd5b81b6d881f1179/pillow-12.3.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:756c768d0c9c2955feb7a56c37ea24aea2e369f8d36a88da270b6a9f19e62b5e", size = 7049439, upload-time = "2026-07-01T11:54:42.489Z" }, + { url = "https://files.pythonhosted.org/packages/c9/f9/066794cca041b969964f779ee5fa66a9498bbf34248ac39c5d7954e4198f/pillow-12.3.0-cp313-cp313-win32.whl", hash = "sha256:a876864214e136f0eb367788dbd7df045f4806801518e2cfe9e13229cfe06d8f", size = 6473287, upload-time = "2026-07-01T11:54:44.9Z" }, + { url = "https://files.pythonhosted.org/packages/a6/9b/7a58e61d62be561da3a356fe2384d4059a6345fc130e23ef1c36a5b81d24/pillow-12.3.0-cp313-cp313-win_amd64.whl", hash = "sha256:1cca606cd25738df4ed873d5ad46bbdb3d83b5cbca291f6b4ff13a4df6b0bbe8", size = 7239691, upload-time = "2026-07-01T11:54:47.141Z" }, + { url = "https://files.pythonhosted.org/packages/aa/b0/c4ed4f0ef8f8fa5ee8351537db6650bb8189f7e118842978dd6589065692/pillow-12.3.0-cp313-cp313-win_arm64.whl", hash = "sha256:b629de27fda84b42cde7edef0d85f13b958b47f6e9bbcbba9b673c562a89bd8b", size = 2568185, upload-time = "2026-07-01T11:54:49.137Z" }, + { url = "https://files.pythonhosted.org/packages/dc/01/001f65b68192f0228cc1dbbc8d2530ab5d58b61037ba0587f946fea607cd/pillow-12.3.0-cp314-cp314-ios_13_0_arm64_iphoneos.whl", hash = "sha256:9cf95fe4d0f84c82d282745d9bb08ad9f926efa00be4697e767b814ce40d4330", size = 4161736, upload-time = "2026-07-01T11:54:51.156Z" }, + { url = "https://files.pythonhosted.org/packages/1a/d2/0219746d0fd16fc8a84498e79452375be3797d3ce4044596ce565164b84f/pillow-12.3.0-cp314-cp314-ios_13_0_arm64_iphonesimulator.whl", hash = "sha256:8728f216dcdb6e6d555cf971cb34076139ad74b31fc2c14da4fafc741c5f6217", size = 4255435, upload-time = "2026-07-01T11:54:53.414Z" }, + { url = "https://files.pythonhosted.org/packages/c8/02/8d0bc62ef0302318c46ff2a512822d2610e81c7aa46c9b3abe6cbaca5ad0/pillow-12.3.0-cp314-cp314-ios_13_0_x86_64_iphonesimulator.whl", hash = "sha256:a45650e8ce7fafffd731db8550230db6b0d306d181a90b67d3e6bca2f1990930", size = 3696262, upload-time = "2026-07-01T11:54:55.739Z" }, + { url = "https://files.pythonhosted.org/packages/85/e2/73c77d218410b14f5f2d565e8a998d5317b7b9c75368d29985139f7a46f0/pillow-12.3.0-cp314-cp314-macosx_10_15_x86_64.whl", hash = "sha256:ba54cfebe86920a559a7c4d6b9050791c20513650a1952ebe3368c7dc70306f8", size = 5350344, upload-time = "2026-07-01T11:54:57.657Z" }, + { url = "https://files.pythonhosted.org/packages/c7/da/32c752228ae345f489e3a42499d817b6c3996da7e8a3bc7a04fc806b243b/pillow-12.3.0-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:e158cb00350dc278f3b91551101aa7d12415a66ebf2c91d8d5ac14e56ddd3ad0", size = 4780131, upload-time = "2026-07-01T11:54:59.713Z" }, + { url = "https://files.pythonhosted.org/packages/b1/9d/8b2c807dbef61a5197c047afe99823787eb66f63daf9fb2432f91d6f0462/pillow-12.3.0-cp314-cp314-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:e9aeb04d6aef139de265b29683e119b638208f88cf73cdd1658aa07221165321", size = 6263757, upload-time = "2026-07-01T11:55:01.778Z" }, + { url = "https://files.pythonhosted.org/packages/5c/44/c85361f65dbe00eea8576ee467c768d25129989efb76e94f205e9ca9bb46/pillow-12.3.0-cp314-cp314-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:251bf95b67017e27b13d82f5b326234ca62d70f9cf4c2b9032de2358a3b12c7b", size = 6936962, upload-time = "2026-07-01T11:55:03.93Z" }, + { url = "https://files.pythonhosted.org/packages/18/7e/e483414b35800b86b6f08dbbc7803fb5cd52c4d6f897f47d53ea2c7e6f65/pillow-12.3.0-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:fe3cca2e4e8a592be0f269a1ca4835c25199d9f3ce815c8491048f785b0a0198", size = 6339171, upload-time = "2026-07-01T11:55:05.989Z" }, + { url = "https://files.pythonhosted.org/packages/f0/f4/68c491844841ede6bed70189546b3ee9731cf9f2cbad396faff5e1ccba45/pillow-12.3.0-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:23aceaa007d6172b02c277f0cd359c79492bbb14f7072b4ede9fbcaf20648130", size = 7048116, upload-time = "2026-07-01T11:55:08.131Z" }, + { url = "https://files.pythonhosted.org/packages/a3/34/77f3f793fed8efc7d243f21b33c5a3f0d1c97ee70346d3db855587e155ff/pillow-12.3.0-cp314-cp314-win32.whl", hash = "sha256:af8d94b0db561cf68b88a267c5c44b49e134f525d0dc2cb7ed413a66bc23559a", size = 6467209, upload-time = "2026-07-01T11:55:10.408Z" }, + { url = "https://files.pythonhosted.org/packages/f1/e0/492879f69d94f91f60fc8cd05ba03650e9520afebb2fb7aa12777d7c7f38/pillow-12.3.0-cp314-cp314-win_amd64.whl", hash = "sha256:fdafc9cce40277e0f7a0feabce0ee50dd2fa1800f3b38015e51296b5e814048d", size = 7237707, upload-time = "2026-07-01T11:55:12.745Z" }, + { url = "https://files.pythonhosted.org/packages/c9/ac/6b11f2875f1c2ac040d84e1bbf9cf22a88038f901ca1037898b280b38365/pillow-12.3.0-cp314-cp314-win_arm64.whl", hash = "sha256:e91206ee562682b51b98ef4b26a6ef48fd84e15fd4c4bc5ec768eb641d206838", size = 2565995, upload-time = "2026-07-01T11:55:14.736Z" }, + { url = "https://files.pythonhosted.org/packages/52/69/c2208e56af9bfc1913afb24020297a691eb1d4ef688474c8a04913f65e04/pillow-12.3.0-cp314-cp314t-macosx_10_15_x86_64.whl", hash = "sha256:164b31cd1a0490ab6efae01aa5df49da7061be0af1b30e035b6e9a1bfe34ee6e", size = 5352503, upload-time = "2026-07-01T11:55:17.076Z" }, + { url = "https://files.pythonhosted.org/packages/07/70/e5686d753e898a45d778ff1718dba8516ead6ab6b95d85fc8c4b70650cf2/pillow-12.3.0-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:5afb51d599ea772b8365ae807ae557f18bccfe46ab261fd1c2a9ed700fc6eb17", size = 4782956, upload-time = "2026-07-01T11:55:19.448Z" }, + { url = "https://files.pythonhosted.org/packages/d5/37/25c6692f06927ee973ff18c8d9ee98ad0b4d84ee67a09610c2dd1447958e/pillow-12.3.0-cp314-cp314t-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:3edce1d53195db527e0191f84b71d02022de0540bf43a16ed734ed7537b07385", size = 6322855, upload-time = "2026-07-01T11:55:21.613Z" }, + { url = "https://files.pythonhosted.org/packages/cc/91/420637fcb8f1bc11029e403b4538e6694744428d8246118e45719f944556/pillow-12.3.0-cp314-cp314t-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:bf16ba1b4d0b6b7c8e534936632270cf70eb00dbe09005bc345b2677b726855c", size = 6989642, upload-time = "2026-07-01T11:55:24.006Z" }, + { url = "https://files.pythonhosted.org/packages/10/08/b94d7811281ccf0d143a1cf768d1c49e1e54af63e7b708ab2ee3eb87face/pillow-12.3.0-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:24870b09b224f7ae3c39ed07d10e819d06f8720bc551847b1d623832b5b0e28d", size = 6391281, upload-time = "2026-07-01T11:55:26.252Z" }, + { url = "https://files.pythonhosted.org/packages/d2/87/24233f785f55474dc02ce3e739c5528a77e3a862e9333d1dd7a25cc31f70/pillow-12.3.0-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:30f2aa603c41533cc25c05acd0da21636e84a315768feb631c937177db558931", size = 7096716, upload-time = "2026-07-01T11:55:28.318Z" }, + { url = "https://files.pythonhosted.org/packages/23/26/fcb2f6e37175b04f53570b59937867e2b80ee1685e744023153028fc14f9/pillow-12.3.0-cp314-cp314t-win32.whl", hash = "sha256:4b0a7fe987b14c31ebda6083f74f22b561fd3739bc0ac51e019622e3d72668c7", size = 6474125, upload-time = "2026-07-01T11:55:30.956Z" }, + { url = "https://files.pythonhosted.org/packages/90/de/3634abee5f1c9e13c56787b7d5517b0ba8d6de51700b95578cf338349c9f/pillow-12.3.0-cp314-cp314t-win_amd64.whl", hash = "sha256:962864dc93511324d51ddbb5b9f8731bf71675b93ca612a07441896f4688fb8c", size = 7242939, upload-time = "2026-07-01T11:55:34.044Z" }, + { url = "https://files.pythonhosted.org/packages/ce/2a/fd13f8eb24de5714a6eb444a3d67e2842c6c576e159a43793adf23051351/pillow-12.3.0-cp314-cp314t-win_arm64.whl", hash = "sha256:0740a512dc522224c77d9aa5a8d70d8b7d73fb91f2c21125d8d025d3b8990e45", size = 2567506, upload-time = "2026-07-01T11:55:35.988Z" }, + { url = "https://files.pythonhosted.org/packages/5d/dc/8fdce34ec725a33c81c6ba122b904d6b9024e50ea9ac7bede62fab54506c/pillow-12.3.0-cp315-cp315-ios_13_0_arm64_iphoneos.whl", hash = "sha256:0feb2e9d6ad6c9e3c06effe9d00f3f1e618a6643273576b016f591e9315a7139", size = 4162063, upload-time = "2026-07-01T11:55:37.941Z" }, + { url = "https://files.pythonhosted.org/packages/76/66/2044b9a63d3b84ff048228dfcb7cd9bf0df983e8470971bf7d4c57b693de/pillow-12.3.0-cp315-cp315-ios_13_0_arm64_iphonesimulator.whl", hash = "sha256:9e881fca225083806662a5c43d627d215f258ff43c890f831966c7d7ba9c7402", size = 4255549, upload-time = "2026-07-01T11:55:40.022Z" }, + { url = "https://files.pythonhosted.org/packages/52/7e/1f67e6f4ece6b582ee4b539decbcc9f848dc245a93ed8cd7338bafef72f1/pillow-12.3.0-cp315-cp315-ios_13_0_x86_64_iphonesimulator.whl", hash = "sha256:4998562bf62a445225f22e07c896bb04b35b1b1f2eb6d760584c9c51d7a5f78c", size = 3696331, upload-time = "2026-07-01T11:55:41.98Z" }, + { url = "https://files.pythonhosted.org/packages/12/40/d306fc2c8e4d45d7f175c77edca7063be7b86fe7fe6e68f4353bf71d808c/pillow-12.3.0-cp315-cp315-macosx_10_15_x86_64.whl", hash = "sha256:dc624f6bc473dacdf7ef7eb8678d0d08edf15cd94fad6ae5c7d6cc67a4e4902f", size = 5350370, upload-time = "2026-07-01T11:55:44.028Z" }, + { url = "https://files.pythonhosted.org/packages/dd/44/668fb1437e8ce420f62d6106eb66e44a5971602a4d794615bdf79315d82d/pillow-12.3.0-cp315-cp315-macosx_11_0_arm64.whl", hash = "sha256:71d6097b330eea8fd15097780c8e89cb1a8ce7838669f48c5bacd6f663dd4701", size = 4780147, upload-time = "2026-07-01T11:55:46.073Z" }, + { url = "https://files.pythonhosted.org/packages/0c/08/93fa2e70e30a2d81547e481b6ee2bb9522117221fb1e0ce4b5df70967677/pillow-12.3.0-cp315-cp315-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:28ce87c5ab450a9dd970b52e5aca5fe63ed432d18a2eaddd1979a00a1ba24ace", size = 6273659, upload-time = "2026-07-01T11:55:48.264Z" }, + { url = "https://files.pythonhosted.org/packages/f8/6d/043e96ff814fc31a33077e4cba86082167db520c93632afdf2042febbb0c/pillow-12.3.0-cp315-cp315-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:6b02afb9b97f65fbca5f31db6a2a3ba21aa93030225f150fa3f249717e938fb4", size = 6947439, upload-time = "2026-07-01T11:55:50.503Z" }, + { url = "https://files.pythonhosted.org/packages/af/92/ba71d2ee2ac0edf3fa33bd9d5ee9ee080da70b1766f3ca3934f9938ddac9/pillow-12.3.0-cp315-cp315-musllinux_1_2_aarch64.whl", hash = "sha256:1182d52bc2d5e5d7d0949503aa7e36d12f42205dc287e4883f407b1988820d39", size = 6353577, upload-time = "2026-07-01T11:55:52.697Z" }, + { url = "https://files.pythonhosted.org/packages/0f/ce/e63064e2122923ff687c8ad792d0d736a7b3920a56a46982e81a7fdd25d6/pillow-12.3.0-cp315-cp315-musllinux_1_2_x86_64.whl", hash = "sha256:e795b7eb908249c4e43c7c99fac7c2c75dab0c43566e37db472a355f63693d71", size = 7060394, upload-time = "2026-07-01T11:55:55.149Z" }, + { url = "https://files.pythonhosted.org/packages/54/76/a09cc3ccc8d773a7283d34c38bec1708f9e3cc932093cbc4c5e71ac4060b/pillow-12.3.0-cp315-cp315-win32.whl", hash = "sha256:57b3d78c95ba9059768b10e28b813002261d3f3dfc55cc48b0c988f625175827", size = 6467375, upload-time = "2026-07-01T11:55:57.769Z" }, + { url = "https://files.pythonhosted.org/packages/3e/03/1846c49ba3b1d5550392a4bbd06d6fb4578e1cd91a803198b5c90f5f7d53/pillow-12.3.0-cp315-cp315-win_amd64.whl", hash = "sha256:fa4ecea169a355be7a3ade2c783e2ed12f0e40d2c5621cda8b3297faf7fbb9f5", size = 7237048, upload-time = "2026-07-01T11:55:59.975Z" }, + { url = "https://files.pythonhosted.org/packages/fb/bb/89f35dcc79610423f9f195504d7def7f0d1416a711541b42867e25fe3412/pillow-12.3.0-cp315-cp315-win_arm64.whl", hash = "sha256:877c3f311ff35410f690861c4409e7ccbf0cd2f878e50628a28e5a0bb689e658", size = 2566006, upload-time = "2026-07-01T11:56:02.143Z" }, + { url = "https://files.pythonhosted.org/packages/30/88/707027ba09942dfa2c28759b5c222d769290a41c6d20ea60ec250801941f/pillow-12.3.0-cp315-cp315t-macosx_10_15_x86_64.whl", hash = "sha256:e9871b1ffbfa9656b60aeee92ed5136a5742696006fa322b29ea3d8da0ecc9cf", size = 5352509, upload-time = "2026-07-01T11:56:04.2Z" }, + { url = "https://files.pythonhosted.org/packages/b0/6d/00352fa25332c2569cd387851f568cc5a4b75a9adbfb37ac4fbce4c02eec/pillow-12.3.0-cp315-cp315t-macosx_11_0_arm64.whl", hash = "sha256:53aa02d20d10c3d814d536aa4e5ac9b84ca0ff5a88377963b085ad6822f93e64", size = 4783167, upload-time = "2026-07-01T11:56:06.631Z" }, + { url = "https://files.pythonhosted.org/packages/13/4f/9e049dfa21af7c22427275720e2490267ba8138120add5c4c574deb69782/pillow-12.3.0-cp315-cp315t-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:446c34dcc4324b084a53b705127dc15717b22c5e140ae0a3c38349d4efec071e", size = 6329237, upload-time = "2026-07-01T11:56:08.868Z" }, + { url = "https://files.pythonhosted.org/packages/36/16/cf6eeaae8d0fce8dd390a33437cf68c5d5bd73834a2bc6e2f14efda0ab45/pillow-12.3.0-cp315-cp315t-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:cf1845d02ad822a369a49f2bb9345b1614744267682e7a03527dc3bf6eea1777", size = 6997047, upload-time = "2026-07-01T11:56:11.379Z" }, + { url = "https://files.pythonhosted.org/packages/1e/69/dbf769bdd55f48bf5733cac28edc6364ffaa072ec9ba336266e4fe66be55/pillow-12.3.0-cp315-cp315t-musllinux_1_2_aarch64.whl", hash = "sha256:186941b6aef820ad110fb01fb06eb925374dc3a21b17e37ec9a53b250c6fe2d1", size = 6400440, upload-time = "2026-07-01T11:56:13.908Z" }, + { url = "https://files.pythonhosted.org/packages/a0/e1/ffc9cfc2eea0d178da8018e18e959301ad9d6bc9f3edb7181e748a474b97/pillow-12.3.0-cp315-cp315t-musllinux_1_2_x86_64.whl", hash = "sha256:f13c32a3abd6079a66d9526e18dad9b6d280384d49d7c54040cd57b6424041d9", size = 7105895, upload-time = "2026-07-01T11:56:16.575Z" }, + { url = "https://files.pythonhosted.org/packages/18/f0/a5595c1e8c3ae44b9828cb2f0fa8155e5095ef04d6327b8f61cf44a3df85/pillow-12.3.0-cp315-cp315t-win32.whl", hash = "sha256:1657923d2d45afb66526e5b933e5b3052e6bdea196c90d3abb2424e18c77dae8", size = 6474384, upload-time = "2026-07-01T11:56:18.855Z" }, + { url = "https://files.pythonhosted.org/packages/e4/04/62bcd9f844984c5938d3b05264a61d797a29d3e0812341a8204af70bbdee/pillow-12.3.0-cp315-cp315t-win_amd64.whl", hash = "sha256:8cd2f7bdda092d99c9fc2fb7391354f306d01443d22785d0cbfafa2e2c8bb418", size = 7243537, upload-time = "2026-07-01T11:56:21.214Z" }, + { url = "https://files.pythonhosted.org/packages/3d/68/1f3066acedf37673694a7141381d8f811ae97f30d34413d236abe7d489f1/pillow-12.3.0-cp315-cp315t-win_arm64.whl", hash = "sha256:06ff022112bc9cbf83b60f8e028d94ad87b60621706487e65f673de61610ab59", size = 2567491, upload-time = "2026-07-01T11:56:23.506Z" }, + { url = "https://files.pythonhosted.org/packages/75/18/2e8b40223153ccbc60df07f9e8928dc0c76202aa4e55ae9f53962b6510d6/pillow-12.3.0-pp311-pypy311_pp73-macosx_10_15_x86_64.whl", hash = "sha256:b3c777e849237620b022f7f297dd67705f9f5cf1685f09f02e46f93e92725468", size = 5302510, upload-time = "2026-07-01T11:56:25.736Z" }, + { url = "https://files.pythonhosted.org/packages/46/3e/51fabf59d5ab801ceab709453d3ab6b180083496579549de4c45ced6528a/pillow-12.3.0-pp311-pypy311_pp73-macosx_11_0_arm64.whl", hash = "sha256:b343699e8308bdc51978310e1c959c584e7869cc8c40780058c87da7781a1e94", size = 4736058, upload-time = "2026-07-01T11:56:28.041Z" }, + { url = "https://files.pythonhosted.org/packages/bf/20/22fe9384b7949e25fb1293bcfc84fb82590ff4ea6b37c95b24d26d793d86/pillow-12.3.0-pp311-pypy311_pp73-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:fbd139c8447d25dd750ab79ee274cc5e1fe80fc56340ab10b18a195e1b6eca3e", size = 5237776, upload-time = "2026-07-01T11:56:30.263Z" }, + { url = "https://files.pythonhosted.org/packages/08/14/f6ba68107680ffa74b39985f3f30884e41318fbc4250caa423c79b4788bb/pillow-12.3.0-pp311-pypy311_pp73-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:e7e480451b9fa137494bccd3a7d69adbe8ac65a87d97be61e11f1b1050a5bac3", size = 5860358, upload-time = "2026-07-01T11:56:32.68Z" }, + { url = "https://files.pythonhosted.org/packages/36/54/0169bc772ec491108b62f644f8ecf1fe5d8ae5ebafde2ee2142210166903/pillow-12.3.0-pp311-pypy311_pp73-win_amd64.whl", hash = "sha256:04f01d28a6aaff387bf842a13be313df23ba0597a44f1a976c9feb3c6ff4711a", size = 7231786, upload-time = "2026-07-01T11:56:35.046Z" }, ] [[package]] @@ -2706,26 +2702,26 @@ wheels = [ [[package]] name = "prek" -version = "0.4.5" +version = "0.4.8" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/2f/65/23866f43521d31173879aa74bb3a2df50ab7f3f74cdb4eaa31b8f446c7ca/prek-0.4.5.tar.gz", hash = "sha256:2be7bcf839de19a0144ed5a5aadf73bc5899cf6823bb1c58cf1d45ae389c201a", size = 482566, upload-time = "2026-06-15T11:36:48.299Z" } +sdist = { url = "https://files.pythonhosted.org/packages/8e/46/e436a6eb9fdb4d3fd08d0ab7fdba19fe03a9e994ec810de57869b853bd8e/prek-0.4.8.tar.gz", hash = "sha256:d15d8bef72ab7b02c7dc01458ac9e05b3131534492b5ce9bb11c4f6f636fa868", size = 494570, upload-time = "2026-07-04T12:05:10.941Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/f4/cb/a9eedf9a35ca6ec72f12af2b4392d7f757bb24863b7b7af4523f939cf3fa/prek-0.4.5-py3-none-linux_armv6l.whl", hash = "sha256:f7517774c72b001573520dc7111156779fd3e5b4452c11f09ff53c71a067e835", size = 5618105, upload-time = "2026-06-15T11:36:21.998Z" }, - { url = "https://files.pythonhosted.org/packages/30/a7/c96c06f17db7da0a57be2be4c229aa00b525bca8001c9c765663b339cbb7/prek-0.4.5-py3-none-macosx_10_12_x86_64.whl", hash = "sha256:aca9fa995536036a0171bcf7a4db96dc0a14f480054eda1d7d1c2e7739650993", size = 5972998, upload-time = "2026-06-15T11:36:41.12Z" }, - { url = "https://files.pythonhosted.org/packages/28/f1/721695355cdaa44be6f091e3a77fb9c72ed60289520f78b2f8c9a7197bdd/prek-0.4.5-py3-none-macosx_11_0_arm64.whl", hash = "sha256:66877ff21ae9d548f0f7e56fab8e65f1500a74a810e7749188c3f35a4a1b911b", size = 5525098, upload-time = "2026-06-15T11:36:30.127Z" }, - { url = "https://files.pythonhosted.org/packages/9b/1b/a334e1bb5361b49adf52b5ac7b6532018940f9f0f253437e8f43c3c1f7f3/prek-0.4.5-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.musllinux_1_1_aarch64.whl", hash = "sha256:50697089a86a78d16f087c1912a2f3bc2bea82319a220fac52cc8e3ec9fc0426", size = 5793732, upload-time = "2026-06-15T11:36:35.745Z" }, - { url = "https://files.pythonhosted.org/packages/28/8c/aff94d276e91207a87cedff7cfefdd4aca20444137cca77bf53fffebe77a/prek-0.4.5-py3-none-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:590427a42a3c1e5064487a0dc91167ae0c8a52168e77f574758ef9b138fcfd61", size = 5521719, upload-time = "2026-06-15T11:36:39.383Z" }, - { url = "https://files.pythonhosted.org/packages/4f/73/cfb0c5c909442050a8357e26233f7e511ba8e0d2f4b0bdc460065d62beb6/prek-0.4.5-py3-none-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:1fd98b986767dafdb6b4305b563ee5a3a8f13bd3c78b98d708626815ea9f147f", size = 5922623, upload-time = "2026-06-15T11:36:18.063Z" }, - { url = "https://files.pythonhosted.org/packages/0a/ad/ff9d26551ba80d190bd08c6341176a5d56d4e6de9c2ebf077793d4adbb78/prek-0.4.5-py3-none-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:fccd11613ae92619d1ecda0ab3359ceebeb38898909ec84a8d383733d12158cc", size = 6722071, upload-time = "2026-06-15T11:36:43.086Z" }, - { url = "https://files.pythonhosted.org/packages/d3/43/11d1dfd66c919953fe89ae2fdedd4f413ee923883043816d35982177bb75/prek-0.4.5-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:14109d37b33e5529db41a3539d4f8f72d295f6eeddede3964994d898b8cec05c", size = 6176454, upload-time = "2026-06-15T11:36:33.803Z" }, - { url = "https://files.pythonhosted.org/packages/d7/d4/9749f25c2e0ee5225f812457b888acef301e0ccce64bebcda2ac1d04abee/prek-0.4.5-py3-none-manylinux_2_28_aarch64.whl", hash = "sha256:40d262418105b2ede9836593a1927fc927cc8093c432e998640964102196996e", size = 5791133, upload-time = "2026-06-15T11:36:23.891Z" }, - { url = "https://files.pythonhosted.org/packages/c7/72/5e0344bab1eacf813a5b1b082cb4c6253930096166dad51c1cccee0a4f83/prek-0.4.5-py3-none-manylinux_2_31_riscv64.whl", hash = "sha256:a586d14c3b852fdee1c3dcd0b9cb0915db9f9d054334b854fd9470bf68edf129", size = 5658098, upload-time = "2026-06-15T11:36:44.862Z" }, - { url = "https://files.pythonhosted.org/packages/be/a5/1f406e0362dd0f18ba09a562d50d7c04a70ac05d350b1ab6fba36ca3e9f0/prek-0.4.5-py3-none-musllinux_1_1_armv7l.whl", hash = "sha256:a8ed0d28f3e7790e4402a9324c386509066df6e67cc587f7406f9a245b97b7e8", size = 5498634, upload-time = "2026-06-15T11:36:31.828Z" }, - { url = "https://files.pythonhosted.org/packages/c7/df/b0cbf0fa527330188390b7b6c8d279cd5e509923262d0a6c5cc44bbdf103/prek-0.4.5-py3-none-musllinux_1_1_i686.whl", hash = "sha256:86f76bd3d2ecf6fd9034d75c62ff4c786eb11d0dd0a1f79bbb4343b023e12769", size = 5784840, upload-time = "2026-06-15T11:36:37.481Z" }, - { url = "https://files.pythonhosted.org/packages/9d/d7/977ee3c622c906677dd94187a00392ce2dd76035486b3a3b1b5a5267dd34/prek-0.4.5-py3-none-musllinux_1_1_x86_64.whl", hash = "sha256:e491a1a4641d91d8b03dcce5588397e76d2a5b432c9b0a6c70475972b4512ab4", size = 6300384, upload-time = "2026-06-15T11:36:27.602Z" }, - { url = "https://files.pythonhosted.org/packages/79/fa/43b1d761381dc1c7eeb8f2235c66e902970d4b2bff2dec0f02836c085769/prek-0.4.5-py3-none-win32.whl", hash = "sha256:7546989b2403c96137bd79d19ebfe21facb87266cefe819db2458c3b9b23f350", size = 5287935, upload-time = "2026-06-15T11:36:20.293Z" }, - { url = "https://files.pythonhosted.org/packages/f5/fe/59b5eb3124f5a4cc255a93857b9ab42402635b273f157e91de23bfa40e8f/prek-0.4.5-py3-none-win_amd64.whl", hash = "sha256:8b2ac9227504371d97338215b344184cb0b31ca94113515a3a90c509c6c5a707", size = 5682560, upload-time = "2026-06-15T11:36:25.865Z" }, - { url = "https://files.pythonhosted.org/packages/97/0e/589ff0eab9034909b1ec8654ee03483797305fb743b3554ce6140d82da9d/prek-0.4.5-py3-none-win_arm64.whl", hash = "sha256:646a86a1a082dbd99fed96314b1064f5644bb34c1f4037a63547a18e2160fb86", size = 5509019, upload-time = "2026-06-15T11:36:46.595Z" }, + { url = "https://files.pythonhosted.org/packages/5c/78/b4149c8913ced2e42debb49e261c4788a1ce431e84226921c2e1a7ea8545/prek-0.4.8-py3-none-linux_armv6l.whl", hash = "sha256:1f8f8cdc65836b571824c965daebb81b449f7e4a43894c58621f5708d5a185ed", size = 5668955, upload-time = "2026-07-04T12:04:41.588Z" }, + { url = "https://files.pythonhosted.org/packages/76/5f/7f54a0087b6b2f1751aeb41266d9c15e66fd0055492814798ab818cd0414/prek-0.4.8-py3-none-macosx_10_12_x86_64.whl", hash = "sha256:bce1798e96d9e3a6e6abf435da7107e81452f69edb3ca7c6f90a457355ea46e2", size = 6030947, upload-time = "2026-07-04T12:04:43.8Z" }, + { url = "https://files.pythonhosted.org/packages/6c/d6/f2829fc3902920c36b764a386fa303e71a8219dac25cb3827c575e84199a/prek-0.4.8-py3-none-macosx_11_0_arm64.whl", hash = "sha256:ab3a52db17254d701c3cebb7eea58c8230aa7c1959aacfd5b5f25de18edb15d1", size = 5572593, upload-time = "2026-07-04T12:04:45.763Z" }, + { url = "https://files.pythonhosted.org/packages/74/8c/c5589955bcd5e3e33b67d8bc3110818cecac82a38fd6bc8b5dfdc5de421c/prek-0.4.8-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.musllinux_1_1_aarch64.whl", hash = "sha256:b3fcfd620523bbc3f51a21d7cd63449f659b9e2cf3582de12dd5949e23227b8f", size = 5847150, upload-time = "2026-07-04T12:04:47.419Z" }, + { url = "https://files.pythonhosted.org/packages/2d/9d/1f2dc91bdb79d2c4714b27eac9477a51490fba5b4731330dbbebc76bd345/prek-0.4.8-py3-none-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:42e65bc8425e9d7f1691a13ca1da2e07807d1ba76c35740833354b945131689e", size = 5573738, upload-time = "2026-07-04T12:04:49.125Z" }, + { url = "https://files.pythonhosted.org/packages/81/29/69a7b58e16ecbc5f3989bf4b028018d11a82dcdd320b93d6588d72f32aa7/prek-0.4.8-py3-none-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:f578492a8e0c9bc6b4bf6dfbba8716f647d4cd0769bf10ad6cf336e3096fd392", size = 5981054, upload-time = "2026-07-04T12:04:50.842Z" }, + { url = "https://files.pythonhosted.org/packages/63/cc/9b9850a60c22ed18c7755ebd2d72c6eefb37fac58149d09f6adc4691c2cf/prek-0.4.8-py3-none-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:d4335f9d5beb123a3884a7fe34f57c9f0828f4fbb7666beab4298833459b104f", size = 6751350, upload-time = "2026-07-04T12:04:52.529Z" }, + { url = "https://files.pythonhosted.org/packages/01/e5/c425aa7272b430630119e6757def3a2007555ba8cbeb2630e0448e7a8b7f/prek-0.4.8-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:18a8747df9c602e052881d3efb14dd7f7d62a59bd7277ae5171c9e7661d59d84", size = 6243881, upload-time = "2026-07-04T12:04:54.703Z" }, + { url = "https://files.pythonhosted.org/packages/1c/da/accd3ad07fd2891d3c2777eb42435439fdf11982c51d60f087c0b6b6e102/prek-0.4.8-py3-none-manylinux_2_28_aarch64.whl", hash = "sha256:4db639db481d5f854eff9b3d2108889e613b8c15868bcf6bdd777c7cee577436", size = 5848846, upload-time = "2026-07-04T12:04:56.402Z" }, + { url = "https://files.pythonhosted.org/packages/15/00/3477704635249f21f5f98ce444cd7690c2aa9dc8d146a045db88ef2cd8c5/prek-0.4.8-py3-none-manylinux_2_31_riscv64.whl", hash = "sha256:c3890a6f92316d2cf44eb50584e8d2b23a596dd70487022e61186a71a2ac0900", size = 5713942, upload-time = "2026-07-04T12:04:58.311Z" }, + { url = "https://files.pythonhosted.org/packages/fb/e6/3ca4fabaebeadc976d9a92d1d9130674265355ea3b728418bad61583b097/prek-0.4.8-py3-none-musllinux_1_1_armv7l.whl", hash = "sha256:fc7e15c24c591a37c6ffce5b25a021b16c299ac2649f183d812b67d665cd6551", size = 5554725, upload-time = "2026-07-04T12:04:59.96Z" }, + { url = "https://files.pythonhosted.org/packages/a5/46/2ab6aaaeff0cedb8955b2e4032071c8712382bdd423bb849718c3720180d/prek-0.4.8-py3-none-musllinux_1_1_i686.whl", hash = "sha256:36fe721704ff0c7624c1167639e23a5fe658bfd38c314f487219c9afd1eeb733", size = 5838595, upload-time = "2026-07-04T12:05:01.861Z" }, + { url = "https://files.pythonhosted.org/packages/ae/8b/91398f2b6cd1629d5d8ca8c85b08eca500814a374313b0193f4aaf6ab6c4/prek-0.4.8-py3-none-musllinux_1_1_x86_64.whl", hash = "sha256:162e544abc394a8124f3a4ad68efee116bad09440e679dbd1675177335c2a432", size = 6357222, upload-time = "2026-07-04T12:05:03.845Z" }, + { url = "https://files.pythonhosted.org/packages/b2/2a/ce5cbfaad36866134a21754640a05ecdba641fcd7ad15aa74cf3443f34f6/prek-0.4.8-py3-none-win32.whl", hash = "sha256:2602e46c8c5da7dfa69f60fcf88c2b57132ac623f49fb08bfb3094298c5f07e3", size = 5354388, upload-time = "2026-07-04T12:05:05.587Z" }, + { url = "https://files.pythonhosted.org/packages/df/03/3bc908bc5f7e430315553e47dfa055f19923a3888f9afe4da19f244b5cbf/prek-0.4.8-py3-none-win_amd64.whl", hash = "sha256:7cb22da60bee41b89c4978c0bea7126a3c0ccc003dae6748cf29b53947815edc", size = 5748221, upload-time = "2026-07-04T12:05:07.559Z" }, + { url = "https://files.pythonhosted.org/packages/dd/a7/4295e6d5f5028171dfeb115ad38ab76bf3fe0c8df91b70d73c79aa760a94/prek-0.4.8-py3-none-win_arm64.whl", hash = "sha256:da70057f577b15d4bd121bf9dd29ee205fd4b4d75a0cafba062e84d7e8b4378b", size = 5574425, upload-time = "2026-07-04T12:05:09.595Z" }, ] [[package]] @@ -2874,19 +2870,19 @@ email = [ [[package]] name = "pydantic-ai" -version = "2.1.0" +version = "2.5.0" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "pydantic-ai-slim", extra = ["anthropic", "cli", "evals", "google", "logfire", "mcp", "openai", "retries", "web"] }, ] -sdist = { url = "https://files.pythonhosted.org/packages/14/2e/e393160043ee999c501c95f27dcb6439eec3092eca7d75b94f06165905a8/pydantic_ai-2.1.0.tar.gz", hash = "sha256:6279657f7640df3765a9faab9d9fa25b33c58caf20d67c6189dd5469dbbbb782", size = 18451, upload-time = "2026-06-29T09:51:16.374Z" } +sdist = { url = "https://files.pythonhosted.org/packages/57/6b/6fa7e71ad5c0ccd37ec8987a1a9d42e3ce6d8d3212ef7f3e0d6326647bd4/pydantic_ai-2.5.0.tar.gz", hash = "sha256:06d48d9b432a71096851910a29b98fcc88a746d3d0241c7db283737037998661", size = 18532, upload-time = "2026-07-04T00:47:38.869Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/c7/dc/7cfa843db74fefdba995a2e21fe602e725e2ba77b0d7bc402bc62c1bf2d7/pydantic_ai-2.1.0-py3-none-any.whl", hash = "sha256:001272126e78f982805b1a4ac7e7805da10c88c4f28f9e4b905e923cfc1192d5", size = 7700, upload-time = "2026-06-29T09:51:07.83Z" }, + { url = "https://files.pythonhosted.org/packages/cd/aa/c1f0d8cd78c0653936ef842210ca96e6849085d58c3e93520f4e68563ef8/pydantic_ai-2.5.0-py3-none-any.whl", hash = "sha256:309f85896b80ff58f9baffd4f28a2fb6485e07c9e20a6c1f31cf81a18910c153", size = 7717, upload-time = "2026-07-04T00:47:29.504Z" }, ] [[package]] name = "pydantic-ai-slim" -version = "2.1.0" +version = "2.5.0" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "exceptiongroup", marker = "python_full_version < '3.11'" }, @@ -2898,9 +2894,9 @@ dependencies = [ { name = "pydantic-graph" }, { name = "typing-inspection" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/ca/d1/78fd15c9c68b95ac0bec2d2afe22feb3b2f46e4b8e3a6dd1cead61cde434/pydantic_ai_slim-2.1.0.tar.gz", hash = "sha256:f79dca2429dbb9d2e32a0e2c613cfb9b9d6f0dc81d42cff8a5c81ede8ca0a6c7", size = 738698, upload-time = "2026-06-29T09:51:18.634Z" } +sdist = { url = "https://files.pythonhosted.org/packages/22/8b/360c7dc4d28eb267fd8a872f269400f3ad4521dee2f2ce771a9479bc0260/pydantic_ai_slim-2.5.0.tar.gz", hash = "sha256:cec48e93ac45a3e5c20e3f7f27469fc7267b9f99b5b0433331465dc25a0d01e3", size = 769832, upload-time = "2026-07-04T00:47:40.759Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/5e/c7/b531cf65a1f8b221ab39739a16fe08f7b6a56fd24db875b9c33010320c9c/pydantic_ai_slim-2.1.0-py3-none-any.whl", hash = "sha256:2afda56459606226113ab433ee659aac7ff29bb66feefa716c67144bd82e5ce2", size = 910109, upload-time = "2026-06-29T09:51:11.016Z" }, + { url = "https://files.pythonhosted.org/packages/21/11/2d5f17149ebb9b02718ed041a522ae907981ccca4949024598f5db0dd0d6/pydantic_ai_slim-2.5.0-py3-none-any.whl", hash = "sha256:8ad3a3c8cb0faee7b4017da7e5fff40017225f54fc700b52682ce19867d23e09", size = 946225, upload-time = "2026-07-04T00:47:32.528Z" }, ] [package.optional-dependencies] @@ -3057,7 +3053,7 @@ wheels = [ [[package]] name = "pydantic-evals" -version = "2.1.0" +version = "2.5.0" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "anyio" }, @@ -3067,9 +3063,9 @@ dependencies = [ { name = "pyyaml" }, { name = "rich" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/7b/d6/d2a315322052fa849cb1008c18ac43688e06e1059573cd424cfd20d49be5/pydantic_evals-2.1.0.tar.gz", hash = "sha256:58e72ceba61ba673f074b58f057413dc8d3393720767c89969681d2e4f4067a4", size = 76016, upload-time = "2026-06-29T09:51:19.798Z" } +sdist = { url = "https://files.pythonhosted.org/packages/48/6a/62cc359ea7d92d31b630c94e6934a751ef8c3ecaa2044dac6437cd184b15/pydantic_evals-2.5.0.tar.gz", hash = "sha256:e49345856a30ce95a1683d7984cf5268a057cba938194eacc476559dd6241dcc", size = 84832, upload-time = "2026-07-04T00:47:42.163Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/80/7b/59f9d4f865e2f518179a3a42986e4e8785b70c98ec180c8da10fd78c02a6/pydantic_evals-2.1.0-py3-none-any.whl", hash = "sha256:6c9fc370808d883c20477ce69a6d6bc0b9c5a8d3dab66be5dd85d960a3f88d23", size = 90590, upload-time = "2026-06-29T09:51:12.816Z" }, + { url = "https://files.pythonhosted.org/packages/2a/86/8e6bf22e671079bcb537b4dd674c85b2612648f0c84c42300a1e53d6f629/pydantic_evals-2.5.0-py3-none-any.whl", hash = "sha256:4e06b54c2f4afd3cf9d6de8893624dd79bb544330148366fe8205768dc53e09a", size = 100158, upload-time = "2026-07-04T00:47:34.979Z" }, ] [[package]] @@ -3087,7 +3083,7 @@ wheels = [ [[package]] name = "pydantic-graph" -version = "2.1.0" +version = "2.5.0" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "httpx" }, @@ -3095,9 +3091,9 @@ dependencies = [ { name = "pydantic" }, { name = "typing-inspection" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/39/20/018532c826aba3c29ffc37bda46c20f3db4584bb555a8c7dc2769866267d/pydantic_graph-2.1.0.tar.gz", hash = "sha256:36ed6af24543421fb628fee593ccf5553a286c1dd1677018f5064a4e44c4daba", size = 43052, upload-time = "2026-06-29T09:51:20.832Z" } +sdist = { url = "https://files.pythonhosted.org/packages/bc/51/dcd78a4ccfb7c0e68a3c1c57100797f8674dcd24b33665670307d4912f61/pydantic_graph-2.5.0.tar.gz", hash = "sha256:b41ca881108a0584366966001badcd4792d4b19330a1f2c527512c3f1739aab5", size = 43905, upload-time = "2026-07-04T00:47:43.249Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/42/a8/7f32bdeda6cff28652bba1c21ab2155c81d1733abd4b8bfef46a26e8d3fe/pydantic_graph-2.1.0-py3-none-any.whl", hash = "sha256:bae1e99829abf590a8693442ba5693ace38d2d93a80ae48be55c610a503e3709", size = 50772, upload-time = "2026-06-29T09:51:14.161Z" }, + { url = "https://files.pythonhosted.org/packages/dd/9a/823b4b617acc392326d56c62ca736fc494f1ec9c4e7b748817a14fcc63e0/pydantic_graph-2.5.0-py3-none-any.whl", hash = "sha256:bee68a560cb946ddc1f9d5d11c2d1bebe21b1b1ab352ac1c5d80e16cde5a6b67", size = 51646, upload-time = "2026-07-04T00:47:36.549Z" }, ] [[package]] @@ -4161,7 +4157,7 @@ wheels = [ [[package]] name = "strawberry-graphql" -version = "0.320.0" +version = "0.320.1" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "cross-web" }, @@ -4170,9 +4166,9 @@ dependencies = [ { name = "python-dateutil" }, { name = "typing-extensions" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/44/38/95a72342ba94570a35b8cc7db6a6789378f10b69be1d77e0fb022f5079e0/strawberry_graphql-0.320.0.tar.gz", hash = "sha256:c5ee8abf7f4db00d3515e537578a5c094a4a9f3b732a959d9020c8788d3ac7c7", size = 229231, upload-time = "2026-06-27T23:11:43.262Z" } +sdist = { url = "https://files.pythonhosted.org/packages/01/87/ac45b0ed6aedf32c13322810ce131d542f1b26c2360e7bf2830078e4d3cd/strawberry_graphql-0.320.1.tar.gz", hash = "sha256:ef244499dd23d964b27cb096609d182dcc9eba3f4d000c95b3505f119cf9e9d3", size = 229165, upload-time = "2026-07-02T10:58:12.904Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/db/99/f8e8919a73ae466f9740e63115f010a02fac3f2b69c02ea60c9c85d42c1a/strawberry_graphql-0.320.0-py3-none-any.whl", hash = "sha256:8ea27f43f73a1accbfd1599b37234086d26504cf60213ebb521528319ccf2309", size = 332321, upload-time = "2026-06-27T23:11:41.045Z" }, + { url = "https://files.pythonhosted.org/packages/6b/b0/f84325fc10ac26b51b0e827035ee63faddd337ab0641469046faf8e2823e/strawberry_graphql-0.320.1-py3-none-any.whl", hash = "sha256:782deb6378412f943feac573274068073b4f9e25ec7caf323136db9277cec20e", size = 332207, upload-time = "2026-07-02T10:58:11.319Z" }, ] [[package]] @@ -4370,27 +4366,27 @@ wheels = [ [[package]] name = "ty" -version = "0.0.55" -source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/08/48/f687c8d268e3581f2f104d1f2ac5944d5b5e841b3695c613b3f263e5bbf7/ty-0.0.55.tar.gz", hash = "sha256:88ca87073825a79a8327c550efcc86cec94344890244c5946f84c9e44a969f31", size = 6040230, upload-time = "2026-06-27T00:27:29.385Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/87/a3/1a90ba7e5a61c6d09adb92346ddba97668095fc257b577af433e5ac4f404/ty-0.0.55-py3-none-linux_armv6l.whl", hash = "sha256:31e83eef512d066542fe990fe1a3b814423abd1616376c54e48af7045b3e1749", size = 11677249, upload-time = "2026-06-27T00:26:52.18Z" }, - { url = "https://files.pythonhosted.org/packages/82/3a/669f9aa478c38243e213a2684db1502086026cfadc15bb1b29b7cbde030d/ty-0.0.55-py3-none-macosx_10_12_x86_64.whl", hash = "sha256:ab4bca857950608fea73e269e2da369d43e6467131de85160d68e2fa466fa248", size = 11444180, upload-time = "2026-06-27T00:26:54.576Z" }, - { url = "https://files.pythonhosted.org/packages/15/a4/6a4b2507a53ce6530c66c5b4fe0d58551eb1748ffa9e0696c32fdd55bbd4/ty-0.0.55-py3-none-macosx_11_0_arm64.whl", hash = "sha256:55032bfd31bf2c5355ee81bdc6407b144a1cc7ee41e5681dd1368e4cef2ba327", size = 10963134, upload-time = "2026-06-27T00:26:57.348Z" }, - { url = "https://files.pythonhosted.org/packages/ce/ae/a3b1a0f1cc83b7d258662cb98aa80a720c2e671d0e8fa0d17a4d5d057a7a/ty-0.0.55-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ef1e049f69ce65b3c269af67624607f435e1c32319786c1e453ef9611502f295", size = 11493517, upload-time = "2026-06-27T00:26:59.26Z" }, - { url = "https://files.pythonhosted.org/packages/0d/9f/311ce39065a979ef40a9b847f685c8e02464e53adf1671e081eea90640ca/ty-0.0.55-py3-none-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:631409975c681d5a280fc5a99b7b32e9e801f33be7567c6b42ec331362f59d7d", size = 11460590, upload-time = "2026-06-27T00:27:01.425Z" }, - { url = "https://files.pythonhosted.org/packages/cd/8f/3bf29aa77bd78aae48275153135a2052fa7d3ccdf1ecabeb99c8773abd66/ty-0.0.55-py3-none-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:e08cb0436e68b9351555ae8f2697138c9009b4d5b4ae4272232988b2a431a98f", size = 12098430, upload-time = "2026-06-27T00:27:03.596Z" }, - { url = "https://files.pythonhosted.org/packages/bc/6e/e88411a88240b94640bba06fb6d0d92b247fbeef47ee2bc71f39e58c2558/ty-0.0.55-py3-none-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:16c215ad9f823829409b94ee188cfaa4563f6e1384f6ce3fecb1db75f6c7cf7c", size = 12673086, upload-time = "2026-06-27T00:27:05.589Z" }, - { url = "https://files.pythonhosted.org/packages/6c/7e/8f1762fb7f9245a68ba5ae338d73c59403ce57554e5d311b8bb55027b0ec/ty-0.0.55-py3-none-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:b510eb8f4032baf11b7aee2f1d53babc3b4ca03939b9cdcf6a9d15761d575188", size = 12242559, upload-time = "2026-06-27T00:27:07.714Z" }, - { url = "https://files.pythonhosted.org/packages/72/1f/143657daf2670d977dac83435f1fe03d4843efb798d8e1e75950e541aadd/ty-0.0.55-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0ddc05e7959709c3b9b83aa627128a80446865e3c1a4882638dcff6d776dc34a", size = 12021409, upload-time = "2026-06-27T00:27:09.881Z" }, - { url = "https://files.pythonhosted.org/packages/6d/30/69487c439dd1fad3a4a3d96f0a472193de297eaba6fc4b8ea687ce434ac2/ty-0.0.55-py3-none-manylinux_2_31_riscv64.whl", hash = "sha256:636e8e5078787b8c6916c94e1406719f10189a4ca6b37b813a5922ce5857a8c7", size = 12303807, upload-time = "2026-06-27T00:27:11.986Z" }, - { url = "https://files.pythonhosted.org/packages/e8/ca/cd88b6493dafc7db077f5e17c0438eb3af6e2d6d08f616dbb52a8ddfd567/ty-0.0.55-py3-none-musllinux_1_2_aarch64.whl", hash = "sha256:ef7d6deaacb73fec603666b5471f1dc5a5699aa84e11a6d4d644dd07ca72121e", size = 11441263, upload-time = "2026-06-27T00:27:14.087Z" }, - { url = "https://files.pythonhosted.org/packages/aa/fe/66b6915671653ab739f71e4f1b0528e69da64429b7ebf3840c625b6e43f2/ty-0.0.55-py3-none-musllinux_1_2_armv7l.whl", hash = "sha256:9aeea0fe5875d3cf37faf0e44d0fdf9669335467749741b8fc0103916fb5cd32", size = 11484584, upload-time = "2026-06-27T00:27:16.311Z" }, - { url = "https://files.pythonhosted.org/packages/4a/4f/7a9c0bbac8b899e9f6c0ec110c6612f52e4db35f6bb17ddc0ef60384fa3e/ty-0.0.55-py3-none-musllinux_1_2_i686.whl", hash = "sha256:0b699c01310dbd2705a07c97c5f4aaeedef61bd9adeea2e7c46aed32401d3576", size = 11759309, upload-time = "2026-06-27T00:27:18.471Z" }, - { url = "https://files.pythonhosted.org/packages/ca/de/b6f8b1b69aa631b5716ef3f985c3b56de0e46c2499cc00d30c402b41f714/ty-0.0.55-py3-none-musllinux_1_2_x86_64.whl", hash = "sha256:32cbeba543e46de2a983ec6d525d8b56514f7422bd1e1b57c44ccf7bfa72c38a", size = 12128755, upload-time = "2026-06-27T00:27:20.55Z" }, - { url = "https://files.pythonhosted.org/packages/7d/90/a912531e51ee7e076b42972479290fa687c0f5e747b7e773f3033164acaa/ty-0.0.55-py3-none-win32.whl", hash = "sha256:52b968e24eb4f7a5c3bd251db1f99f60dd385890356d38fc619d84f1b423446a", size = 11117501, upload-time = "2026-06-27T00:27:22.714Z" }, - { url = "https://files.pythonhosted.org/packages/4c/7a/99d59843bf8908a7f9f4d13fda107dbad07b7faa28ecd7860eacf363fb1c/ty-0.0.55-py3-none-win_amd64.whl", hash = "sha256:bf39cbfdc0add44d94bd3fff1f53c351418d134b6a66b87efdb7876d7b7a2224", size = 12150106, upload-time = "2026-06-27T00:27:24.881Z" }, - { url = "https://files.pythonhosted.org/packages/b3/44/20987505cedf2a865b08482f0eabc181fd9599b062964057ec8a128a4296/ty-0.0.55-py3-none-win_arm64.whl", hash = "sha256:f7f3700a9a060e8f1af11e4fb63fafcaf272b041781f4ccdfda2b3b5c6c1e439", size = 11560157, upload-time = "2026-06-27T00:27:27.332Z" }, +version = "0.0.56" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/55/07/fb29aea5235b0aa8ecfc4d1cc6ddf9fba8b863d67d96c6d345694d644c43/ty-0.0.56.tar.gz", hash = "sha256:84d114dc3796361c0fc72945016eabd74d46b9ee64f198cb0e485719704681e5", size = 6050123, upload-time = "2026-07-01T16:44:56.036Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/dc/48/bce79e7ca5c1cc529d3e0d37ddd1121aea4b68a4f749974ad1cc77161871/ty-0.0.56-py3-none-linux_armv6l.whl", hash = "sha256:186d4a53e15747c947e1ec3d7eec8e345d8e40a1ca10e634c585db52497e87dd", size = 11643066, upload-time = "2026-07-01T16:44:18.374Z" }, + { url = "https://files.pythonhosted.org/packages/80/d1/22555d8a1d719661f10050f3865d877bbf497da908961c75fe22217dd18a/ty-0.0.56-py3-none-macosx_10_12_x86_64.whl", hash = "sha256:aae1a980fd9535da0469b7ba2b2e1b54a907743a5e0f442dd57eee9f5bfd034c", size = 11407487, upload-time = "2026-07-01T16:44:20.956Z" }, + { url = "https://files.pythonhosted.org/packages/cf/2d/b3b7a74ce8bc59ef48843ad80179bb0d9598bbd6cfc0d11d519bdf6b1352/ty-0.0.56-py3-none-macosx_11_0_arm64.whl", hash = "sha256:afd3058c0a6c5f241e814734f133008c93ee805f61c9cf4ce7412b8822b5d9ad", size = 10962270, upload-time = "2026-07-01T16:44:22.959Z" }, + { url = "https://files.pythonhosted.org/packages/64/ac/6c2fd7de0304a8a7218a756af74f7e62a5e8540fdb175e0a869e51042345/ty-0.0.56-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:058b52f7a823ac13aae3cae30809dd6b5145794b64d8478f9ef38c75d79b4483", size = 11471406, upload-time = "2026-07-01T16:44:25.327Z" }, + { url = "https://files.pythonhosted.org/packages/50/b6/11d861156861c03c7726b74558f9a0e0092661aff83a4fda1279df28c425/ty-0.0.56-py3-none-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:2c66e00c1522add1f2bbdd2e45828c953b35c306b7bef03ec9169c75a63699a0", size = 11445612, upload-time = "2026-07-01T16:44:27.531Z" }, + { url = "https://files.pythonhosted.org/packages/fb/ba/09df108582090f3c0770ec4bc8675affed60248f6793a78d909be16211d9/ty-0.0.56-py3-none-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:40903d71c669a30691b5a5d5728056c7877a1bd6be4f233a38883a8b28cf34d7", size = 12093889, upload-time = "2026-07-01T16:44:29.548Z" }, + { url = "https://files.pythonhosted.org/packages/d7/f7/dbb4b4ccb69cd64c209ae55b1ab788ace8222c2bc1f6845be9e7cbedbf25/ty-0.0.56-py3-none-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:63fe3947fe0c46c69a7d950e6832ee70a9ec17321fefbff3d2e3c20baf9e5bd0", size = 12666337, upload-time = "2026-07-01T16:44:31.586Z" }, + { url = "https://files.pythonhosted.org/packages/86/e9/73f903fe4a3d9ea02f26f57c1eb07e3b1029ec92b0e8c2364718893440e3/ty-0.0.56-py3-none-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:71a0c1a72f9854532e710e119b6871ffe4542c8a65146f1f65dcd78fecd885b4", size = 12280247, upload-time = "2026-07-01T16:44:33.637Z" }, + { url = "https://files.pythonhosted.org/packages/d6/90/cebd222495832f1a00dcd321ba25f3cab804221a4991b992c2178bec68ee/ty-0.0.56-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:70d1665596494e24d8ebd198438872b5a56ec3cae5f2bcf6c673be797acc4e3c", size = 11991107, upload-time = "2026-07-01T16:44:36.122Z" }, + { url = "https://files.pythonhosted.org/packages/b7/07/8f7337a07250f42d975cdb6decf47fc5b421e6c7da5e3e7be1e85f63a7e5/ty-0.0.56-py3-none-manylinux_2_31_riscv64.whl", hash = "sha256:778f99e51558afc1dbbe48ee38ab6aae7b31390ed8c1a1ef1499b295e9f1e82f", size = 12298970, upload-time = "2026-07-01T16:44:38.243Z" }, + { url = "https://files.pythonhosted.org/packages/3c/b9/a52cd59034a48f5f18c6b155cc2cc36861d874b6d0af204b12c898024c3d/ty-0.0.56-py3-none-musllinux_1_2_aarch64.whl", hash = "sha256:867bc5708e0066bb4ff6c7db524bd5deea2676c62bfe71d3303138b3be850af0", size = 11425683, upload-time = "2026-07-01T16:44:40.473Z" }, + { url = "https://files.pythonhosted.org/packages/1d/2e/48e42d33357d52eefb695c0c3fcfc96879b73668a7447d1d1e0ad774fedc/ty-0.0.56-py3-none-musllinux_1_2_armv7l.whl", hash = "sha256:a6012f4189c928edb330a37deb9930f982380bd4aa7c4b8e0428eec9651c7551", size = 11469258, upload-time = "2026-07-01T16:44:42.513Z" }, + { url = "https://files.pythonhosted.org/packages/d5/01/ad1b4138be1e3fa97863af3925aa2134f17a593240c35dc38c3429fb5ad1/ty-0.0.56-py3-none-musllinux_1_2_i686.whl", hash = "sha256:8ee83de1a7ff4cc32837ec06134ce391d441bc5b35ecd8d3cfe053f120f3e4c1", size = 11758736, upload-time = "2026-07-01T16:44:44.567Z" }, + { url = "https://files.pythonhosted.org/packages/09/34/9d81967ff240eaa57e9249728ef7b7790747cf6d3c9a98ec86b2cfdcc8ee/ty-0.0.56-py3-none-musllinux_1_2_x86_64.whl", hash = "sha256:62619b3b0e2c6248ef30d3f0e2f2217ae9893040585be07f32324242f197cd6f", size = 12100242, upload-time = "2026-07-01T16:44:46.584Z" }, + { url = "https://files.pythonhosted.org/packages/c3/36/f51d4666d2de6cf33c1f3a1fcc4bb6b70b197dd6ceaa491eef71d78fe8e8/ty-0.0.56-py3-none-win32.whl", hash = "sha256:b30687bb5cd9729d34c889a289edf32770388d9bb05243e534e723fb45e0381b", size = 11093759, upload-time = "2026-07-01T16:44:49.171Z" }, + { url = "https://files.pythonhosted.org/packages/5e/b4/8fb5d4acfa4afb152245b20fa263069a7547bd1f8e4bfca4eda280c897d7/ty-0.0.56-py3-none-win_amd64.whl", hash = "sha256:ad4c8c47b6f4e3f9ed3fc0b1a5d650088d229e17dd8f63c1826d6bbe94cc3235", size = 12100327, upload-time = "2026-07-01T16:44:51.26Z" }, + { url = "https://files.pythonhosted.org/packages/b8/fc/6a183e71edde90d0c35c2303f23f7a45b6891d1a2c45daf7b8f869831e19/ty-0.0.56-py3-none-win_arm64.whl", hash = "sha256:57538f273d444a5f1293fa7860e967178afe3917611fc5eff16b64e1204fe0d6", size = 11538780, upload-time = "2026-07-01T16:44:53.8Z" }, ] [[package]] @@ -4802,7 +4798,7 @@ wheels = [ [[package]] name = "zensical" -version = "0.0.46" +version = "0.0.47" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "click" }, @@ -4814,20 +4810,20 @@ dependencies = [ { name = "pyyaml" }, { name = "tomli" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/aa/57/c7bbb71f943e1e0ba5ce460f4930ec836ead7286969e7fd742f7a6c049ab/zensical-0.0.46.tar.gz", hash = "sha256:3ec21f4fb1e78cd7c0d6b07ae336b04770e27ba020dabc457b2790e5d34f1978", size = 3973968, upload-time = "2026-06-21T18:52:40.368Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/4c/bd/bbc499ee35ac9ec5459dbfec7bb7231556689e97eaa13a5eddbe1f0443b5/zensical-0.0.46-cp310-abi3-macosx_10_12_x86_64.whl", hash = "sha256:d91af81ab058c8693dfd75f2f77b4c73bcba4125681d1d276f38624291820bd2", size = 12796482, upload-time = "2026-06-21T18:52:07.369Z" }, - { url = "https://files.pythonhosted.org/packages/88/1b/7acc273184d59b8e894d15ebe3cf1c5e81b3a822fde1792ea3e33be37a2e/zensical-0.0.46-cp310-abi3-macosx_11_0_arm64.whl", hash = "sha256:d9221264a9a87409900a47e29985607b0c9245dacb89077e87c8e16e31edc167", size = 12660030, upload-time = "2026-06-21T18:52:10.186Z" }, - { url = "https://files.pythonhosted.org/packages/80/df/bd0a68de98a19fc6050c58be11f36d05ea72a213b6a7ff7395d33c793747/zensical-0.0.46-cp310-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ec43018d5343ca2e1d71aa352eeddd560fef504effd03025840a5a783abefa4f", size = 13057130, upload-time = "2026-06-21T18:52:12.911Z" }, - { url = "https://files.pythonhosted.org/packages/f4/db/e27635f5787a42245f900e658340698a6654e165d466f9a3b640efced2cd/zensical-0.0.46-cp310-abi3-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:26e98fb8ab7ab50cdd20a73e2c7d4d9aae0b46cf2d8691e6bb22f9c261b8a60a", size = 13022345, upload-time = "2026-06-21T18:52:15.84Z" }, - { url = "https://files.pythonhosted.org/packages/e7/9d/6ce2ba11c97154870b458a8dae4637ade93b7097912f0102f5ea7fe8cf5b/zensical-0.0.46-cp310-abi3-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:46fe578f26963f8ee89567983e62737b6fadc9197d4742e1020b522e092d7baa", size = 13377445, upload-time = "2026-06-21T18:52:18.538Z" }, - { url = "https://files.pythonhosted.org/packages/68/06/9930d43cd9d2f899b648d63491007c1b4f9716cf118b0c98e867b933069c/zensical-0.0.46-cp310-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:aef03fa186a5589148e10b62610500989c6b075a2c08e1554233adbf91b2a3dc", size = 13086749, upload-time = "2026-06-21T18:52:21.452Z" }, - { url = "https://files.pythonhosted.org/packages/c4/ed/2342cf860fbb02314938b0d1f1b02344935801b04d185ff3151ef1812898/zensical-0.0.46-cp310-abi3-musllinux_1_2_aarch64.whl", hash = "sha256:bc7446cdf97a8dea390f20ed2bd6b030cddc1bd36a8ce113ea3efef6fa61c573", size = 13231120, upload-time = "2026-06-21T18:52:24.171Z" }, - { url = "https://files.pythonhosted.org/packages/de/b0/d2ece02f63cd767fcf10fd7608dc8e0a995f87dc5261209b1dbc296fd57b/zensical-0.0.46-cp310-abi3-musllinux_1_2_armv7l.whl", hash = "sha256:bbee37801f1ed500f158dc0992c569282950f780ae353c37fe6969f99983d701", size = 13295035, upload-time = "2026-06-21T18:52:26.942Z" }, - { url = "https://files.pythonhosted.org/packages/4b/b2/cb0048a612e63e615399fc507472a557d1c5b7c2f74065c5bf11998fd597/zensical-0.0.46-cp310-abi3-musllinux_1_2_i686.whl", hash = "sha256:9487c147c9cceb50c04d0ad70b024821a6eab1629dafd70ab6d1e86ec841e623", size = 13437191, upload-time = "2026-06-21T18:52:29.69Z" }, - { url = "https://files.pythonhosted.org/packages/91/16/515f81db8055b109a510063be481e60a657c4fad1a883680b2ee4aa9a424/zensical-0.0.46-cp310-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:f42a4683c762f026878d19ede4bcf7bfbb84dbecb5ad923949abb77806ed88a5", size = 13369382, upload-time = "2026-06-21T18:52:32.521Z" }, - { url = "https://files.pythonhosted.org/packages/b9/5c/da54ee65b642eb7d88dd4a3db35845d0765915638e05d5d434a10b42f1c3/zensical-0.0.46-cp310-abi3-win32.whl", hash = "sha256:85f018f2a7ee76a83915c87ddb12b58cf343fd6154081d33ac95b6751b011dd7", size = 12354298, upload-time = "2026-06-21T18:52:34.976Z" }, - { url = "https://files.pythonhosted.org/packages/73/26/fc7ef081acbdada8436825221cb728ee84a81d4d78a7bb79aa58bd150d31/zensical-0.0.46-cp310-abi3-win_amd64.whl", hash = "sha256:1543a693a160de60e86ca589592401b584670e7e12c5ae30e3c2ba76786f7ec3", size = 12599687, upload-time = "2026-06-21T18:52:37.913Z" }, +sdist = { url = "https://files.pythonhosted.org/packages/d7/99/53171a5211359a95b0d6caad9a1c960b002a4bf82eacdd3cdbde225db25f/zensical-0.0.47.tar.gz", hash = "sha256:324f783b22cd0deed0d0f3b69e28d5380b47238a1ef0f25913b88014af2bade2", size = 3976587, upload-time = "2026-07-05T15:51:25.488Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/07/7c/5848aad6a5b566f5a3cebc77ab787793daec622b79295de243da7b8efae6/zensical-0.0.47-cp310-abi3-macosx_10_12_x86_64.whl", hash = "sha256:4162fb8b62f38e6d9b75688c1fb87e18a1cffef5eee51d2c18b79334b548e973", size = 12789282, upload-time = "2026-07-05T15:50:45.118Z" }, + { url = "https://files.pythonhosted.org/packages/ce/08/c2a056ae22eba7063985cc89554ab8e54efb11af8e26f6d606e5bd300ae8/zensical-0.0.47-cp310-abi3-macosx_11_0_arm64.whl", hash = "sha256:cdc2d84f38da809a28402eda5f2b6dbb150e14427f296c5b521e0dfc6a2e8a39", size = 12661193, upload-time = "2026-07-05T15:50:49.138Z" }, + { url = "https://files.pythonhosted.org/packages/dc/2b/30dc3262e99bc72e9a6529487fbfca58cf4f81cebfac59ef8e8d757d90eb/zensical-0.0.47-cp310-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:97ed2b21aba5f788fc39d1597d00938d602b4d2724ed599a1dab7548fe4f0025", size = 13044347, upload-time = "2026-07-05T15:50:52.429Z" }, + { url = "https://files.pythonhosted.org/packages/4d/80/296ff21b686cda47c4a3f94c35bf62472291501c34e4f06dfd107cb237da/zensical-0.0.47-cp310-abi3-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:6f6b2de477c45284201e92301f997415f45f78493bd20f479ea9a1c86bbbbcca", size = 13006494, upload-time = "2026-07-05T15:50:55.376Z" }, + { url = "https://files.pythonhosted.org/packages/2d/4e/5aeba02363db89c625cd41c76d2a6e40b07d6a75d869d970ace7accd2bfa/zensical-0.0.47-cp310-abi3-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:2ee29ff819372eaab02ca0f14ac82e804332d898c57c56ffd4d89674f3e5ff71", size = 13379253, upload-time = "2026-07-05T15:50:58.743Z" }, + { url = "https://files.pythonhosted.org/packages/fd/dc/e72a1449544aeffa3dbe878c6340bcec98ba4eebabe7a592414064b0ae8d/zensical-0.0.47-cp310-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:1bd94937c48a2e42b5b65b32c5075849937f23cebccaf250d249efa27266e0be", size = 13103356, upload-time = "2026-07-05T15:51:02.247Z" }, + { url = "https://files.pythonhosted.org/packages/48/eb/7fb956915cc59ee9f2ddf36ec5b16e8e858823217611e1d766816a661651/zensical-0.0.47-cp310-abi3-musllinux_1_2_aarch64.whl", hash = "sha256:4702605b991bece11494a9bb318d5ba7229f00e5adcc9e6010acd58e9719686b", size = 13220897, upload-time = "2026-07-05T15:51:05.919Z" }, + { url = "https://files.pythonhosted.org/packages/57/6b/944954d60bf1d61de2a7fa2732d0fb2d5deee64567db6088cdd2b5f76973/zensical-0.0.47-cp310-abi3-musllinux_1_2_armv7l.whl", hash = "sha256:77f08ffcc3da9ca2f972330e501927aa7e8e445bfa7b758107edc645acda266e", size = 13280476, upload-time = "2026-07-05T15:51:09.352Z" }, + { url = "https://files.pythonhosted.org/packages/ce/80/4aece9b99eb5809b04fc6577fc50e877c998917293dfd58b5b229616b92b/zensical-0.0.47-cp310-abi3-musllinux_1_2_i686.whl", hash = "sha256:319cf370ecc6d87da69c935c5acd6e1959dd48954766e9f954319bdb0bec5d36", size = 13439392, upload-time = "2026-07-05T15:51:12.564Z" }, + { url = "https://files.pythonhosted.org/packages/41/10/5cbffe680605b4fa7c0d6326f07a6adc86854f8b9d61bb1b29bb482d40eb/zensical-0.0.47-cp310-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:59656bf604a8b03eede4ce1a847640bab1129ab86dec2e39e5bd4b808b1802d2", size = 13386534, upload-time = "2026-07-05T15:51:15.892Z" }, + { url = "https://files.pythonhosted.org/packages/d5/06/79c7726b0388da40a96cc01113d872d639da1d8a5f96b5265e46e8472ceb/zensical-0.0.47-cp310-abi3-win32.whl", hash = "sha256:81a13a8bacadedada4847eed4aaa4a3f4ef0e5b78dbb2a2022bc6fb7e7dc9464", size = 12356060, upload-time = "2026-07-05T15:51:19.167Z" }, + { url = "https://files.pythonhosted.org/packages/f9/7a/7daaeadfdf7dc2941c8b931f9c6c83396d1da45634cec1a28f8d85a57708/zensical-0.0.47-cp310-abi3-win_amd64.whl", hash = "sha256:944a309be69b11daa8bba46c61fb74f32a98b637f3e7c11135e7cc2a5eccbe32", size = 12601932, upload-time = "2026-07-05T15:51:22.485Z" }, ] [[package]] From b1346bb142c8154950953255eea535e5a83d62eb Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Mon, 13 Jul 2026 11:02:55 +0000 Subject: [PATCH 424/462] =?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 1c22f832a..d4f84a739 100644 --- a/docs/en/docs/release-notes.md +++ b/docs/en/docs/release-notes.md @@ -15,6 +15,7 @@ hide: ### Internal +* ⬆ Bump the python-packages group across 1 directory with 6 updates. PR [#15981](https://github.com/fastapi/fastapi/pull/15981) by [@dependabot[bot]](https://github.com/apps/dependabot). * ⬆ Bump typing-extensions from 4.15.0 to 4.16.0. PR [#15982](https://github.com/fastapi/fastapi/pull/15982) by [@dependabot[bot]](https://github.com/apps/dependabot). * ⬆ Bump the github-actions group across 1 directory with 4 updates. PR [#15983](https://github.com/fastapi/fastapi/pull/15983) by [@dependabot[bot]](https://github.com/apps/dependabot). * ⬆ Bump pre-commit hooks. PR [#15985](https://github.com/fastapi/fastapi/pull/15985) by [@tiangolo](https://github.com/tiangolo). From e5d61c34a35f65676115ceec75acb26e1502f2c3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebasti=C3=A1n=20Ram=C3=ADrez?= Date: Tue, 14 Jul 2026 14:17:35 +0200 Subject: [PATCH 425/462] =?UTF-8?q?=F0=9F=8C=90=20Update=20translations=20?= =?UTF-8?q?for=20hi=20(add-missing)=20(#15925)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: github-actions[bot] Co-authored-by: Yurii Motov --- docs/hi/docs/environment-variables.md | 298 ++++++++++ docs/hi/docs/help-fastapi.md | 87 +++ docs/hi/docs/learn/index.md | 5 + docs/hi/docs/tutorial/background-tasks.md | 86 +++ docs/hi/docs/tutorial/bigger-applications.md | 547 ++++++++++++++++++ docs/hi/docs/tutorial/body-fields.md | 61 ++ docs/hi/docs/tutorial/body-multiple-params.md | 169 ++++++ docs/hi/docs/tutorial/body-nested-models.md | 221 +++++++ docs/hi/docs/tutorial/body-updates.md | 100 ++++ docs/hi/docs/tutorial/body.md | 166 ++++++ docs/hi/docs/tutorial/cookie-param-models.md | 76 +++ docs/hi/docs/tutorial/cookie-params.md | 45 ++ docs/hi/docs/tutorial/cors.md | 89 +++ docs/hi/docs/tutorial/debugging.md | 113 ++++ .../dependencies/classes-as-dependencies.md | 288 +++++++++ ...pendencies-in-path-operation-decorators.md | 69 +++ .../dependencies/dependencies-with-yield.md | 289 +++++++++ .../dependencies/global-dependencies.md | 16 + docs/hi/docs/tutorial/dependencies/index.md | 250 ++++++++ .../tutorial/dependencies/sub-dependencies.md | 105 ++++ docs/hi/docs/tutorial/encoder.md | 35 ++ docs/hi/docs/tutorial/extra-data-types.md | 62 ++ docs/hi/docs/tutorial/extra-models.md | 211 +++++++ docs/hi/docs/tutorial/first-steps.md | 421 ++++++++++++++ docs/hi/docs/tutorial/frontend.md | 139 +++++ docs/hi/docs/tutorial/handling-errors.md | 244 ++++++++ docs/hi/docs/tutorial/header-param-models.md | 72 +++ docs/hi/docs/tutorial/header-params.md | 91 +++ docs/hi/docs/tutorial/index.md | 101 ++++ docs/hi/docs/tutorial/metadata.md | 120 ++++ docs/hi/docs/tutorial/middleware.md | 95 +++ .../tutorial/path-operation-configuration.md | 107 ++++ .../path-params-numeric-validations.md | 154 +++++ docs/hi/docs/tutorial/path-params.md | 251 ++++++++ docs/hi/docs/tutorial/query-param-models.md | 68 +++ .../tutorial/query-params-str-validations.md | 450 ++++++++++++++ docs/hi/docs/tutorial/query-params.md | 188 ++++++ docs/hi/docs/tutorial/request-files.md | 176 ++++++ docs/hi/docs/tutorial/request-form-models.md | 78 +++ .../docs/tutorial/request-forms-and-files.md | 41 ++ docs/hi/docs/tutorial/request-forms.md | 73 +++ docs/hi/docs/tutorial/response-model.md | 344 +++++++++++ docs/hi/docs/tutorial/response-status-code.md | 101 ++++ docs/hi/docs/tutorial/schema-extra-example.md | 202 +++++++ .../docs/tutorial/security/simple-oauth2.md | 289 +++++++++ docs/hi/docs/tutorial/server-sent-events.md | 120 ++++ docs/hi/docs/tutorial/sql-databases.md | 357 ++++++++++++ docs/hi/docs/tutorial/static-files.md | 48 ++ docs/hi/docs/tutorial/stream-json-lines.md | 111 ++++ docs/hi/docs/tutorial/testing.md | 193 ++++++ 50 files changed, 8022 insertions(+) create mode 100644 docs/hi/docs/environment-variables.md create mode 100644 docs/hi/docs/help-fastapi.md create mode 100644 docs/hi/docs/learn/index.md create mode 100644 docs/hi/docs/tutorial/background-tasks.md create mode 100644 docs/hi/docs/tutorial/bigger-applications.md create mode 100644 docs/hi/docs/tutorial/body-fields.md create mode 100644 docs/hi/docs/tutorial/body-multiple-params.md create mode 100644 docs/hi/docs/tutorial/body-nested-models.md create mode 100644 docs/hi/docs/tutorial/body-updates.md create mode 100644 docs/hi/docs/tutorial/body.md create mode 100644 docs/hi/docs/tutorial/cookie-param-models.md create mode 100644 docs/hi/docs/tutorial/cookie-params.md create mode 100644 docs/hi/docs/tutorial/cors.md create mode 100644 docs/hi/docs/tutorial/debugging.md create mode 100644 docs/hi/docs/tutorial/dependencies/classes-as-dependencies.md create mode 100644 docs/hi/docs/tutorial/dependencies/dependencies-in-path-operation-decorators.md create mode 100644 docs/hi/docs/tutorial/dependencies/dependencies-with-yield.md create mode 100644 docs/hi/docs/tutorial/dependencies/global-dependencies.md create mode 100644 docs/hi/docs/tutorial/dependencies/index.md create mode 100644 docs/hi/docs/tutorial/dependencies/sub-dependencies.md create mode 100644 docs/hi/docs/tutorial/encoder.md create mode 100644 docs/hi/docs/tutorial/extra-data-types.md create mode 100644 docs/hi/docs/tutorial/extra-models.md create mode 100644 docs/hi/docs/tutorial/first-steps.md create mode 100644 docs/hi/docs/tutorial/frontend.md create mode 100644 docs/hi/docs/tutorial/handling-errors.md create mode 100644 docs/hi/docs/tutorial/header-param-models.md create mode 100644 docs/hi/docs/tutorial/header-params.md create mode 100644 docs/hi/docs/tutorial/index.md create mode 100644 docs/hi/docs/tutorial/metadata.md create mode 100644 docs/hi/docs/tutorial/middleware.md create mode 100644 docs/hi/docs/tutorial/path-operation-configuration.md create mode 100644 docs/hi/docs/tutorial/path-params-numeric-validations.md create mode 100644 docs/hi/docs/tutorial/path-params.md create mode 100644 docs/hi/docs/tutorial/query-param-models.md create mode 100644 docs/hi/docs/tutorial/query-params-str-validations.md create mode 100644 docs/hi/docs/tutorial/query-params.md create mode 100644 docs/hi/docs/tutorial/request-files.md create mode 100644 docs/hi/docs/tutorial/request-form-models.md create mode 100644 docs/hi/docs/tutorial/request-forms-and-files.md create mode 100644 docs/hi/docs/tutorial/request-forms.md create mode 100644 docs/hi/docs/tutorial/response-model.md create mode 100644 docs/hi/docs/tutorial/response-status-code.md create mode 100644 docs/hi/docs/tutorial/schema-extra-example.md create mode 100644 docs/hi/docs/tutorial/security/simple-oauth2.md create mode 100644 docs/hi/docs/tutorial/server-sent-events.md create mode 100644 docs/hi/docs/tutorial/sql-databases.md create mode 100644 docs/hi/docs/tutorial/static-files.md create mode 100644 docs/hi/docs/tutorial/stream-json-lines.md create mode 100644 docs/hi/docs/tutorial/testing.md diff --git a/docs/hi/docs/environment-variables.md b/docs/hi/docs/environment-variables.md new file mode 100644 index 000000000..0545d03b7 --- /dev/null +++ b/docs/hi/docs/environment-variables.md @@ -0,0 +1,298 @@ +# Environment Variables { #environment-variables } + +/// tip | टिप + +अगर आप पहले से जानते हैं कि "environment variables" क्या होते हैं और उनका उपयोग कैसे करना है, तो आप इसे छोड़ सकते हैं। + +/// + +एक environment variable (जिसे "**env var**" भी कहा जाता है) एक variable है जो Python code के **बाहर**, **ऑपरेटिंग सिस्टम** में रहता है, और जिसे आपका Python code (या दूसरे programs भी) पढ़ सकते हैं। + +Environment variables application **settings** संभालने, Python की **installation** के हिस्से के रूप में, आदि में उपयोगी हो सकते हैं। + +## Env Vars बनाएं और उपयोग करें { #create-and-use-env-vars } + +आप Python की ज़रूरत के बिना, **shell (terminal)** में environment variables **बना** और उपयोग कर सकते हैं: + +//// tab | Linux, macOS, Windows Bash + +

+ +```console +// आप MY_NAME नाम का env var ऐसे बना सकते हैं +$ export MY_NAME="Wade Wilson" + +// फिर आप इसे दूसरे programs के साथ उपयोग कर सकते हैं, जैसे +$ echo "Hello $MY_NAME" + +Hello Wade Wilson +``` + +
+ +//// + +//// tab | Windows PowerShell + +
+ +```console +// MY_NAME नाम का env var बनाएं +$ $Env:MY_NAME = "Wade Wilson" + +// इसे दूसरे programs के साथ उपयोग करें, जैसे +$ echo "Hello $Env:MY_NAME" + +Hello Wade Wilson +``` + +
+ +//// + +## Python में env vars पढ़ें { #read-env-vars-in-python } + +आप Python के **बाहर**, terminal में (या किसी भी दूसरे तरीके से) environment variables बना सकते हैं, और फिर **उन्हें Python में पढ़** सकते हैं। + +उदाहरण के लिए, आपके पास `main.py` नाम की file हो सकती है जिसमें: + +```Python hl_lines="3" +import os + +name = os.getenv("MY_NAME", "World") +print(f"Hello {name} from Python") +``` + +/// tip | टिप + +[`os.getenv()`](https://docs.python.org/3.8/library/os.html#os.getenv) का दूसरा argument लौटाने के लिए default value है। + +अगर यह दिया नहीं गया है, तो default रूप से यह `None` होता है, यहाँ हम उपयोग करने के लिए default value के रूप में `"World"` देते हैं। + +/// + +फिर आप उस Python program को call कर सकते हैं: + +//// tab | Linux, macOS, Windows Bash + +
+ +```console +// यहाँ हमने अभी env var set नहीं किया है +$ python main.py + +// क्योंकि हमने env var set नहीं किया, हमें default value मिलती है + +Hello World from Python + +// लेकिन अगर हम पहले एक environment variable बनाते हैं +$ export MY_NAME="Wade Wilson" + +// और फिर program को फिर से call करते हैं +$ python main.py + +// अब यह environment variable पढ़ सकता है + +Hello Wade Wilson from Python +``` + +
+ +//// + +//// tab | Windows PowerShell + +
+ +```console +// यहाँ हमने अभी env var set नहीं किया है +$ python main.py + +// क्योंकि हमने env var set नहीं किया, हमें default value मिलती है + +Hello World from Python + +// लेकिन अगर हम पहले एक environment variable बनाते हैं +$ $Env:MY_NAME = "Wade Wilson" + +// और फिर program को फिर से call करते हैं +$ python main.py + +// अब यह environment variable पढ़ सकता है + +Hello Wade Wilson from Python +``` + +
+ +//// + +क्योंकि environment variables code के बाहर set किए जा सकते हैं, लेकिन code द्वारा पढ़े जा सकते हैं, और उन्हें बाकी files के साथ store (`git` में commit) करने की ज़रूरत नहीं होती, इसलिए configurations या **settings** के लिए उनका उपयोग करना आम है। + +आप किसी **specific program invocation** के लिए भी एक environment variable बना सकते हैं, जो केवल उसी program के लिए उपलब्ध होता है, और केवल उसकी अवधि तक। + +ऐसा करने के लिए, program से ठीक पहले, उसी line पर इसे बनाएं: + +
+ +```console +// इस program call के लिए line में MY_NAME नाम का env var बनाएं +$ MY_NAME="Wade Wilson" python main.py + +// अब यह environment variable पढ़ सकता है + +Hello Wade Wilson from Python + +// इसके बाद env var मौजूद नहीं रहता +$ python main.py + +Hello World from Python +``` + +
+ +/// tip | टिप + +आप इसके बारे में [The Twelve-Factor App: Config](https://12factor.net/config) पर और पढ़ सकते हैं। + +/// + +## Types और Validation { #types-and-validation } + +ये environment variables केवल **text strings** को ही संभाल सकते हैं, क्योंकि ये Python से बाहरी होते हैं और इन्हें दूसरे programs तथा बाकी system (और अलग-अलग ऑपरेटिंग सिस्टम, जैसे Linux, Windows, और macOS) के साथ compatible होना होता है। + +इसका मतलब है कि Python में environment variable से पढ़ा गया **कोई भी value** **`str` होगा**, और किसी अलग type में कोई भी conversion या कोई भी validation code में करना होगा। + +आप [Advanced User Guide - Settings and Environment Variables](./advanced/settings.md) में **application settings** संभालने के लिए environment variables के उपयोग के बारे में और सीखेंगे। + +## `PATH` Environment Variable { #path-environment-variable } + +**`PATH`** नाम का एक **special** environment variable होता है जिसका उपयोग ऑपरेटिंग सिस्टम (Linux, macOS, Windows) चलाने के लिए programs खोजने में करते हैं। + +`PATH` variable का value एक लंबी string होती है जो Linux और macOS पर colon `:` से, और Windows पर semicolon `;` से अलग की गई directories से बनी होती है। + +उदाहरण के लिए, `PATH` environment variable ऐसा दिख सकता है: + +//// tab | Linux, macOS + +```plaintext +/usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbin +``` + +इसका मतलब है कि system को इन directories में programs ढूंढने चाहिए: + +* `/usr/local/bin` +* `/usr/bin` +* `/bin` +* `/usr/sbin` +* `/sbin` + +//// + +//// tab | Windows + +```plaintext +C:\Program Files\Python312\Scripts;C:\Program Files\Python312;C:\Windows\System32 +``` + +इसका मतलब है कि system को इन directories में programs ढूंढने चाहिए: + +* `C:\Program Files\Python312\Scripts` +* `C:\Program Files\Python312` +* `C:\Windows\System32` + +//// + +जब आप terminal में कोई **command** type करते हैं, तो ऑपरेटिंग सिस्टम `PATH` environment variable में listed **उनमें से प्रत्येक directory** में program को **ढूंढता है**। + +उदाहरण के लिए, जब आप terminal में `python` type करते हैं, तो ऑपरेटिंग सिस्टम उस list की **पहली directory** में `python` नाम का program ढूंढता है। + +अगर उसे यह मिल जाता है, तो वह **इसे उपयोग** करेगा। नहीं तो वह **दूसरी directories** में ढूंढना जारी रखता है। + +### Python install करना और `PATH` update करना { #installing-python-and-updating-the-path } + +जब आप Python install करते हैं, तो आपसे पूछा जा सकता है कि क्या आप `PATH` environment variable को update करना चाहते हैं। + +//// tab | Linux, macOS + +मान लें कि आप Python install करते हैं और वह `/opt/custompython/bin` directory में जाता है। + +अगर आप `PATH` environment variable को update करने के लिए yes कहते हैं, तो installer `/opt/custompython/bin` को `PATH` environment variable में जोड़ देगा। + +यह ऐसा दिख सकता है: + +```plaintext +/usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbin:/opt/custompython/bin +``` + +इस तरह, जब आप terminal में `python` type करते हैं, तो system Python program को `/opt/custompython/bin` (आखिरी directory) में ढूंढेगा और उसी का उपयोग करेगा। + +//// + +//// tab | Windows + +मान लें कि आप Python install करते हैं और वह `C:\opt\custompython\bin` directory में जाता है। + +अगर आप `PATH` environment variable को update करने के लिए yes कहते हैं, तो installer `C:\opt\custompython\bin` को `PATH` environment variable में जोड़ देगा। + +```plaintext +C:\Program Files\Python312\Scripts;C:\Program Files\Python312;C:\Windows\System32;C:\opt\custompython\bin +``` + +इस तरह, जब आप terminal में `python` type करते हैं, तो system Python program को `C:\opt\custompython\bin` (आखिरी directory) में ढूंढेगा और उसी का उपयोग करेगा। + +//// + +तो, अगर आप type करते हैं: + +
+ +```console +$ python +``` + +
+ +//// tab | Linux, macOS + +System `/opt/custompython/bin` में `python` program को **ढूंढेगा** और उसे चलाएगा। + +यह लगभग ऐसा type करने के बराबर होगा: + +
+ +```console +$ /opt/custompython/bin/python +``` + +
+ +//// + +//// tab | Windows + +System `C:\opt\custompython\bin\python` में `python` program को **ढूंढेगा** और उसे चलाएगा। + +यह लगभग ऐसा type करने के बराबर होगा: + +
+ +```console +$ C:\opt\custompython\bin\python +``` + +
+ +//// + +यह जानकारी [Virtual Environments](virtual-environments.md) के बारे में सीखते समय उपयोगी होगी। + +## निष्कर्ष { #conclusion } + +इससे आपको यह basic समझ मिल जानी चाहिए कि **environment variables** क्या होते हैं और Python में उनका उपयोग कैसे करना है। + +आप इनके बारे में [Wikipedia for Environment Variable](https://en.wikipedia.org/wiki/Environment_variable) में भी और पढ़ सकते हैं। + +कई मामलों में तुरंत यह बहुत स्पष्ट नहीं होता कि environment variables कैसे उपयोगी और applicable होंगे। लेकिन जब आप developing कर रहे होते हैं, तो ये कई अलग-अलग scenarios में बार-बार सामने आते हैं, इसलिए इनके बारे में जानना अच्छा है। + +उदाहरण के लिए, अगले section में, [Virtual Environments](virtual-environments.md) के बारे में, आपको इस जानकारी की ज़रूरत होगी। diff --git a/docs/hi/docs/help-fastapi.md b/docs/hi/docs/help-fastapi.md new file mode 100644 index 000000000..bbeb2f16d --- /dev/null +++ b/docs/hi/docs/help-fastapi.md @@ -0,0 +1,87 @@ +# मदद { #help } + +क्या आप FastAPI की मदद करना चाहते हैं या FastAPI के बारे में मदद पाना चाहते हैं? + +मदद करने और मदद पाने के बहुत सरल तरीके हैं। + +## newsletter की सदस्यता लें { #subscribe-to-the-newsletter } + +आप (कभी-कभार आने वाले) [**FastAPI and friends** newsletter](newsletter.md) की सदस्यता ले सकते हैं ताकि आप इन चीज़ों से अपडेट रहें: + +* FastAPI और friends के बारे में खबरें 🚀 +* गाइड्स 📝 +* Features ✨ +* Breaking changes 🚨 +* टिप्स और ट्रिक्स ✅ + +## FastAPI को ऑनलाइन फ़ॉलो करें { #follow-fastapi-online } + +आप **FastAPI** को कई जगहों पर ऑनलाइन फ़ॉलो कर सकते हैं: + +* [**X / Twitter** पर @fastapi](https://x.com/fastapi) +* [**Bluesky** पर @fastapi.tiangolo.com](https://bsky.app/profile/fastapi.tiangolo.com) +* [**LinkedIn** पर FastAPI](https://www.linkedin.com/company/fastapi/) + +## GitHub में **FastAPI** को Star करें { #star-fastapi-in-github } + +आप GitHub में FastAPI को "star" कर सकते हैं (ऊपर दाईं ओर star बटन पर क्लिक करके): [https://github.com/fastapi/fastapi](https://github.com/fastapi/fastapi). ⭐️ + +Star जोड़ने से, अन्य users इसे अधिक आसानी से ढूंढ पाएंगे और देख पाएंगे कि यह दूसरों के लिए पहले से उपयोगी रहा है। + +## Releases के लिए GitHub repository को Watch करें { #watch-the-github-repository-for-releases } + +आप GitHub में FastAPI को "watch" कर सकते हैं (ऊपर दाईं ओर "watch" बटन पर क्लिक करके): [https://github.com/fastapi/fastapi](https://github.com/fastapi/fastapi). 👀 + +वहाँ आप "Releases only" चुन सकते हैं। + +ऐसा करने पर, जब भी bug fixes और नए features के साथ **FastAPI** की कोई नई release (एक नया version) आएगी, आपको notifications (आपके email में) मिलेंगे। + +## लेखक को फ़ॉलो करें { #follow-the-author } + +आप [मुझे (Sebastián Ramírez / `tiangolo`)](https://tiangolo.com), लेखक को कुछ जगहों पर फ़ॉलो कर सकते हैं, ताकि जब मेरे पास FastAPI और friends के बारे में साझा करने के लिए खबरें हों तो आपको पता चले: + +* [**GitHub** पर @tiangolo](https://github.com/tiangolo). +* [**X (Twitter)** पर @tiangolo](https://x.com/tiangolo) +* [**Bluesky** पर @tiangolo.com](https://bsky.app/profile/tiangolo.com) +* [**LinkedIn** पर @tiangolo](https://www.linkedin.com/in/tiangolo/). + +## GitHub में प्रश्नों के साथ दूसरों की मदद करें { #help-others-with-questions-in-github } + +आप [GitHub Discussions](https://github.com/fastapi/fastapi/discussions/categories/questions?discussions_q=category%3AQuestions+is%3Aunanswered) में दूसरों के प्रश्नों में मदद करने की कोशिश कर सकते हैं। + +कई मामलों में आपको उन प्रश्नों का उत्तर पहले से पता हो सकता है। 🤓 + +यदि आप बहुत से लोगों के प्रश्नों में उनकी मदद कर रहे हैं, तो आप आधिकारिक [FastAPI Expert](fastapi-people.md#fastapi-experts) बन जाएंगे। 🎉 + +बस याद रखें, सबसे महत्वपूर्ण बात है: विनम्र रहने की कोशिश करें। 🤗 + +### मदद कैसे करें { #how-to-help } + +यहाँ [मदद कैसे करें वाली गाइड](https://tiangolo.com/open-source/help/#help-others-with-questions-in-github) का पालन करें। + +## प्रश्न पूछें { #ask-questions } + +आप GitHub repository में [एक नया प्रश्न बना सकते हैं](https://github.com/fastapi/fastapi/discussions/new?category=questions), उदाहरण के लिए: + +* कोई **प्रश्न** पूछें या किसी **समस्या** के बारे में पूछें। +* कोई नया **feature** सुझाएँ। + +## Chat से जुड़ें { #join-the-chat } + +👥 [Discord chat server](https://discord.gg/VQjSZaeJmf) 👥 से जुड़ें और FastAPI community में दूसरों के साथ बातचीत करें। + +/// tip | सुझाव + +प्रश्नों के लिए, उन्हें GitHub Discussions में पूछें, वहाँ आपको मदद मिलने की संभावना कहीं बेहतर है। + +Chat का उपयोग केवल अन्य सामान्य बातचीत के लिए करें। + +/// + +### प्रश्नों के लिए Chat का उपयोग न करें { #dont-use-the-chat-for-questions } + +ध्यान रखें कि chats अधिक "मुक्त बातचीत" की अनुमति देते हैं, इसलिए बहुत सामान्य और उत्तर देने में अधिक कठिन प्रश्न पूछना आसान हो जाता है, इसलिए हो सकता है आपको उत्तर न मिलें। + +GitHub में, template आपको सही प्रश्न लिखने में मार्गदर्शन करेगा ताकि आप अधिक आसानी से अच्छा उत्तर पा सकें, या पूछने से पहले ही समस्या को स्वयं भी हल कर सकें। + +Chat systems में बातचीत GitHub जितनी आसानी से searchable भी नहीं होती, वे खो जाती हैं। diff --git a/docs/hi/docs/learn/index.md b/docs/hi/docs/learn/index.md new file mode 100644 index 000000000..20f63c173 --- /dev/null +++ b/docs/hi/docs/learn/index.md @@ -0,0 +1,5 @@ +# सीखें { #learn } + +यहाँ **FastAPI** सीखने के लिए परिचयात्मक section और ट्यूटोरियल हैं। + +आप इसे FastAPI सीखने का एक **book**, एक **course**, **आधिकारिक** और अनुशंसित तरीका मान सकते हैं। 😎 diff --git a/docs/hi/docs/tutorial/background-tasks.md b/docs/hi/docs/tutorial/background-tasks.md new file mode 100644 index 000000000..f1c685644 --- /dev/null +++ b/docs/hi/docs/tutorial/background-tasks.md @@ -0,0 +1,86 @@ +# Background Tasks { #background-tasks } + +आप background tasks define कर सकते हैं जिन्हें response लौटाने के *बाद* चलाया जाए। + +यह उन operations के लिए उपयोगी है जिन्हें request के बाद होना होता है, लेकिन client को response पाने से पहले operation के पूरा होने का इंतज़ार करने की वास्तव में ज़रूरत नहीं होती। + +इसमें, उदाहरण के लिए, ये शामिल हैं: + +* कोई action करने के बाद भेजे गए email notifications: + * क्योंकि email server से connect करना और email भेजना आम तौर पर "slow" (कई seconds) होता है, आप response तुरंत लौटा सकते हैं और email notification को background में भेज सकते हैं। +* data process करना: + * उदाहरण के लिए, मान लीजिए आपको एक file मिलती है जिसे किसी slow process से गुजरना है, आप "Accepted" (HTTP 202) का response लौटा सकते हैं और file को background में process कर सकते हैं। + +## `BackgroundTasks` का उपयोग करना { #using-backgroundtasks } + +सबसे पहले, `BackgroundTasks` import करें और अपनी *path operation function* में `BackgroundTasks` की type declaration के साथ एक parameter define करें: + +{* ../../docs_src/background_tasks/tutorial001_py310.py hl[1,13] *} + +**FastAPI** आपके लिए `BackgroundTasks` type का object बनाएगा और उसे उस parameter के रूप में pass करेगा। + +## task function बनाएँ { #create-a-task-function } + +background task के रूप में चलाने के लिए एक function बनाएँ। + +यह बस एक standard function है जो parameters receive कर सकता है। + +यह `async def` या normal `def` function हो सकता है, **FastAPI** जानता होगा कि इसे सही तरीके से कैसे handle करना है। + +इस case में, task function एक file में लिखेगा (email भेजने का simulation करते हुए)। + +और क्योंकि write operation `async` और `await` का उपयोग नहीं करता, हम function को normal `def` के साथ define करते हैं: + +{* ../../docs_src/background_tasks/tutorial001_py310.py hl[6:9] *} + +## background task जोड़ें { #add-the-background-task } + +अपनी *path operation function* के अंदर, अपनी task function को *background tasks* object में method `.add_task()` के साथ pass करें: + +{* ../../docs_src/background_tasks/tutorial001_py310.py hl[14] *} + +`.add_task()` arguments के रूप में receive करता है: + +* background में चलाने के लिए एक task function (`write_notification`)। +* arguments की कोई भी sequence जो order में task function को pass की जानी चाहिए (`email`)। +* कोई भी keyword arguments जो task function को pass किए जाने चाहिए (`message="some notification"`)। + +## Dependency Injection { #dependency-injection } + +`BackgroundTasks` का उपयोग dependency injection system के साथ भी काम करता है, आप कई levels पर `BackgroundTasks` type का parameter declare कर सकते हैं: किसी *path operation function* में, dependency (dependable) में, sub-dependency में, आदि। + +**FastAPI** जानता है कि हर case में क्या करना है और same object को कैसे reuse करना है, ताकि सभी background tasks merge हो जाएँ और बाद में background में run हों: + + +{* ../../docs_src/background_tasks/tutorial002_an_py310.py hl[13,15,22,25] *} + + +इस example में, response भेजे जाने के *बाद* messages `log.txt` file में लिखे जाएँगे। + +अगर request में कोई query थी, तो उसे एक background task में log में लिखा जाएगा। + +और फिर *path operation function* पर generate हुआ एक और background task `email` path parameter का उपयोग करके एक message लिखेगा। + +## Technical Details { #technical-details } + +class `BackgroundTasks` सीधे [`starlette.background`](https://www.starlette.dev/background/) से आती है। + +इसे सीधे FastAPI में import/include किया गया है ताकि आप इसे `fastapi` से import कर सकें और गलती से `starlette.background` से alternative `BackgroundTask` (अंत में `s` के बिना) import करने से बच सकें। + +सिर्फ `BackgroundTasks` (और `BackgroundTask` नहीं) का उपयोग करने से, इसे *path operation function* parameter के रूप में use करना संभव होता है और **FastAPI** आपके लिए बाकी चीज़ें handle करता है, ठीक वैसे ही जैसे `Request` object को सीधे use करते समय होता है। + +FastAPI में अकेले `BackgroundTask` का उपयोग करना अभी भी संभव है, लेकिन आपको अपने code में object बनाना होगा और उसे शामिल करते हुए Starlette `Response` return करना होगा। + +आप [Background Tasks के लिए Starlette के official docs](https://www.starlette.dev/background/) में अधिक details देख सकते हैं। + +## सावधानी { #caveat } + +अगर आपको heavy background computation perform करनी है और यह ज़रूरी नहीं है कि वह same process द्वारा run हो (उदाहरण के लिए, आपको memory, variables, आदि share करने की ज़रूरत नहीं है), तो आपको [Celery](https://docs.celeryq.dev) जैसे दूसरे बड़े tools का उपयोग करने से लाभ हो सकता है। + +उन्हें आम तौर पर अधिक complex configurations, RabbitMQ या Redis जैसे message/job queue manager की ज़रूरत होती है, लेकिन वे आपको multiple processes में, और खासकर multiple servers में, background tasks run करने देते हैं। + +लेकिन अगर आपको उसी **FastAPI** app से variables और objects access करने हैं, या आपको छोटे background tasks perform करने हैं (जैसे email notification भेजना), तो आप आसानी से `BackgroundTasks` का उपयोग कर सकते हैं। + +## Recap { #recap } + +background tasks जोड़ने के लिए *path operation functions* और dependencies में parameters के साथ `BackgroundTasks` import और use करें। diff --git a/docs/hi/docs/tutorial/bigger-applications.md b/docs/hi/docs/tutorial/bigger-applications.md new file mode 100644 index 000000000..263a59397 --- /dev/null +++ b/docs/hi/docs/tutorial/bigger-applications.md @@ -0,0 +1,547 @@ +# बड़े Applications - Multiple Files { #bigger-applications-multiple-files } + +अगर आप कोई application या web API बना रहे हैं, तो ऐसा कम ही होता है कि आप सब कुछ एक ही file में रख सकें। + +**FastAPI** आपके application को structure करने के लिए एक सुविधाजनक tool देता है, और साथ ही पूरी flexibility भी बनाए रखता है। + +/// note | नोट + +अगर आप Flask से आए हैं, तो यह Flask के Blueprints के बराबर होगा। + +/// + +## एक उदाहरण file structure { #an-example-file-structure } + +मान लीजिए आपके पास ऐसा file structure है: + +``` +. +├── app +│ ├── __init__.py +│ ├── main.py +│ ├── dependencies.py +│ └── routers +│ │ ├── __init__.py +│ │ ├── items.py +│ │ └── users.py +│ └── internal +│ ├── __init__.py +│ └── admin.py +``` + +/// tip | टिप + +कई `__init__.py` files हैं: हर directory या subdirectory में एक। + +यही एक file से दूसरी file में code import करने की अनुमति देता है। + +उदाहरण के लिए, `app/main.py` में आपके पास ऐसी line हो सकती है: + +``` +from app.routers import items +``` + +/// + +* `app` directory में सब कुछ है। और इसमें एक खाली file `app/__init__.py` है, इसलिए यह एक "Python package" है ("Python modules" का संग्रह): `app`. +* इसमें एक `app/main.py` file है। क्योंकि यह एक Python package (एक ऐसी directory जिसमें `__init__.py` file है) के अंदर है, यह उस package का एक "module" है: `app.main`. +* एक `app/dependencies.py` file भी है, `app/main.py` की तरह, यह एक "module" है: `app.dependencies`. +* एक subdirectory `app/routers/` है जिसमें एक और file `__init__.py` है, इसलिए यह एक "Python subpackage" है: `app.routers`. +* file `app/routers/items.py` एक package, `app/routers/`, के अंदर है, इसलिए यह एक submodule है: `app.routers.items`. +* `app/routers/users.py` के साथ भी वही है, यह एक और submodule है: `app.routers.users`. +* एक subdirectory `app/internal/` भी है जिसमें एक और file `__init__.py` है, इसलिए यह एक और "Python subpackage" है: `app.internal`. +* और file `app/internal/admin.py` एक और submodule है: `app.internal.admin`. + + + +वही file structure comments के साथ: + +```bash +. +├── app # "app" एक Python package है +│   ├── __init__.py # यह file "app" को "Python package" बनाती है +│   ├── main.py # "main" module, जैसे import app.main +│   ├── dependencies.py # "dependencies" module, जैसे import app.dependencies +│   └── routers # "routers" एक "Python subpackage" है +│   │ ├── __init__.py # "routers" को "Python subpackage" बनाता है +│   │ ├── items.py # "items" submodule, जैसे import app.routers.items +│   │ └── users.py # "users" submodule, जैसे import app.routers.users +│   └── internal # "internal" एक "Python subpackage" है +│   ├── __init__.py # "internal" को "Python subpackage" बनाता है +│   └── admin.py # "admin" submodule, जैसे import app.internal.admin +``` + +## `APIRouter` { #apirouter } + +मान लीजिए सिर्फ users को handle करने के लिए dedicated file `/app/routers/users.py` पर submodule है। + +आप अपने users से संबंधित *path operations* को बाकी code से अलग रखना चाहते हैं, ताकि यह व्यवस्थित रहे। + +लेकिन यह अभी भी उसी **FastAPI** application/web API का हिस्सा है (यह उसी "Python Package" का हिस्सा है)। + +आप उस module के लिए *path operations* `APIRouter` का उपयोग करके बना सकते हैं। + +### `APIRouter` import करें { #import-apirouter } + +आप इसे import करते हैं और उसी तरह एक "instance" बनाते हैं जैसे आप `FastAPI` class के साथ करते: + +{* ../../docs_src/bigger_applications/app_an_py310/routers/users.py hl[1,3] title["app/routers/users.py"] *} + +### `APIRouter` के साथ *Path operations* { #path-operations-with-apirouter } + +और फिर आप इसका उपयोग अपने *path operations* declare करने के लिए करते हैं। + +इसे उसी तरह उपयोग करें जैसे आप `FastAPI` class का उपयोग करते: + +{* ../../docs_src/bigger_applications/app_an_py310/routers/users.py hl[6,11,16] title["app/routers/users.py"] *} + +आप `APIRouter` को एक "mini `FastAPI`" class की तरह सोच सकते हैं। + +सभी वही options समर्थित हैं। + +सभी वही `parameters`, `responses`, `dependencies`, `tags`, आदि। + +/// tip | टिप + +इस उदाहरण में, variable को `router` कहा गया है, लेकिन आप इसे अपनी इच्छा अनुसार कोई भी नाम दे सकते हैं। + +/// + +हम इस `APIRouter` को main `FastAPI` app में शामिल करने जा रहे हैं, लेकिन पहले, dependencies और एक और `APIRouter` देखें। + +## Dependencies { #dependencies } + +हम देखते हैं कि हमें application के कई स्थानों पर उपयोग होने वाली कुछ dependencies की ज़रूरत होगी। + +इसलिए हम उन्हें उनके अपने `dependencies` module (`app/dependencies.py`) में रखते हैं। + +अब हम एक custom `X-Token` header पढ़ने के लिए एक सरल dependency का उपयोग करेंगे: + +{* ../../docs_src/bigger_applications/app_an_py310/dependencies.py hl[3,6:8] title["app/dependencies.py"] *} + +/// tip | टिप + +हम इस उदाहरण को सरल बनाने के लिए एक काल्पनिक header का उपयोग कर रहे हैं। + +लेकिन वास्तविक मामलों में आपको integrated [Security utilities](security/index.md) का उपयोग करके बेहतर परिणाम मिलेंगे। + +/// + +## `APIRouter` के साथ एक और module { #another-module-with-apirouter } + +मान लीजिए आपके application से "items" को handle करने के लिए dedicated endpoints भी `app/routers/items.py` module में हैं। + +आपके पास इनके लिए *path operations* हैं: + +* `/items/` +* `/items/{item_id}` + +यह सब `app/routers/users.py` जैसी ही structure है। + +लेकिन हम थोड़े अधिक smart होना चाहते हैं और code को थोड़ा simplify करना चाहते हैं। + +हम जानते हैं कि इस module के सभी *path operations* में वही हैं: + +* Path `prefix`: `/items`. +* `tags`: (सिर्फ एक tag: `items`). +* अतिरिक्त `responses`. +* `dependencies`: उन सभी को वह `X-Token` dependency चाहिए जो हमने बनाई है। + +इसलिए, यह सब प्रत्येक *path operation* में जोड़ने के बजाय, हम इसे `APIRouter` में जोड़ सकते हैं। + +{* ../../docs_src/bigger_applications/app_an_py310/routers/items.py hl[5:10,16,21] title["app/routers/items.py"] *} + +क्योंकि प्रत्येक *path operation* का path `/` से शुरू होना चाहिए, जैसे: + +```Python hl_lines="1" +@router.get("/{item_id}") +async def read_item(item_id: str): + ... +``` + +...prefix में अंत में `/` शामिल नहीं होना चाहिए। + +इसलिए, इस मामले में prefix `/items` है। + +हम `tags` की list और अतिरिक्त `responses` भी जोड़ सकते हैं जो इस router में शामिल सभी *path operations* पर लागू होंगे। + +और हम `dependencies` की list जोड़ सकते हैं जो router के सभी *path operations* में जोड़ी जाएगी और उन पर किए गए हर request के लिए execute/solve की जाएगी। + +/// tip | टिप + +ध्यान दें कि, [*path operation decorators* में dependencies](dependencies/dependencies-in-path-operation-decorators.md) की तरह ही, आपके *path operation function* को कोई value pass नहीं की जाएगी। + +/// + +अंतिम परिणाम यह है कि item paths अब ये हैं: + +* `/items/` +* `/items/{item_id}` + +...जैसा हमने चाहा था। + +* उन्हें tags की list से mark किया जाएगा जिसमें एक ही string `"items"` होगी। + * ये "tags" automatic interactive documentation systems (OpenAPI का उपयोग करते हुए) के लिए विशेष रूप से उपयोगी हैं। +* उन सभी में predefined `responses` शामिल होंगे। +* इन सभी *path operations* से पहले `dependencies` की list evaluate/execute की जाएगी। + * अगर आप किसी specific *path operation* में भी dependencies declare करते हैं, **तो वे भी execute होंगी**। + * router dependencies पहले execute होती हैं, फिर decorator में [`dependencies`](dependencies/dependencies-in-path-operation-decorators.md), और फिर normal parameter dependencies। + * आप [`Security` dependencies with `scopes`](../advanced/security/oauth2-scopes.md) भी जोड़ सकते हैं। + +/// tip | टिप + +`APIRouter` में `dependencies` होने का उपयोग, उदाहरण के लिए, *path operations* के पूरे group के लिए authentication require करने के लिए किया जा सकता है। भले ही dependencies उनमें से हर एक में individually न जोड़ी गई हों। + +/// + +/// tip | टिप + +`prefix`, `tags`, `responses`, और `dependencies` parameters (कई अन्य मामलों की तरह) **FastAPI** की एक feature हैं जो आपको code duplication से बचने में मदद करती है। + +/// + +### dependencies import करें { #import-the-dependencies } + +यह code `app.routers.items` module, file `app/routers/items.py` में रहता है। + +और हमें dependency function `app.dependencies` module, file `app/dependencies.py` से लेनी है। + +इसलिए हम dependencies के लिए `..` के साथ relative import का उपयोग करते हैं: + +{* ../../docs_src/bigger_applications/app_an_py310/routers/items.py hl[3] title["app/routers/items.py"] *} + +#### Relative imports कैसे काम करते हैं { #how-relative-imports-work } + +/// tip | टिप + +अगर आप पूरी तरह जानते हैं कि imports कैसे काम करते हैं, तो नीचे वाले अगले section पर जाएँ। + +/// + +एक single dot `.`, जैसे: + +```Python +from .dependencies import get_token_header +``` + +का मतलब होगा: + +* उसी package से शुरू करना जिसमें यह module (file `app/routers/items.py`) रहता है (directory `app/routers/`)... +* module `dependencies` ढूँढना (`app/routers/dependencies.py` पर एक काल्पनिक file)... +* और उससे, function `get_token_header` import करना। + +लेकिन वह file मौजूद नहीं है, हमारी dependencies `app/dependencies.py` पर एक file में हैं। + +याद रखें कि हमारी app/file structure कैसी दिखती है: + + + +--- + +दो dots `..`, जैसे: + +```Python +from ..dependencies import get_token_header +``` + +का मतलब है: + +* उसी package से शुरू करना जिसमें यह module (file `app/routers/items.py`) रहता है (directory `app/routers/`)... +* parent package (directory `app/`) पर जाना... +* और वहाँ, module `dependencies` ढूँढना (file `app/dependencies.py` पर)... +* और उससे, function `get_token_header` import करना। + +यह सही तरीके से काम करता है! 🎉 + +--- + +उसी तरह, अगर हमने तीन dots `...` का उपयोग किया होता, जैसे: + +```Python +from ...dependencies import get_token_header +``` + +तो उसका मतलब होगा: + +* उसी package से शुरू करना जिसमें यह module (file `app/routers/items.py`) रहता है (directory `app/routers/`)... +* parent package (directory `app/`) पर जाना... +* फिर उस package के parent पर जाना (कोई parent package नहीं है, `app` top level है 😱)... +* और वहाँ, module `dependencies` ढूँढना (file `app/dependencies.py` पर)... +* और उससे, function `get_token_header` import करना। + +यह `app/` के ऊपर किसी package को refer करेगा, जिसकी अपनी file `__init__.py` आदि होगी। लेकिन हमारे पास वह नहीं है। इसलिए, हमारे उदाहरण में इससे error आएगा। 🚨 + +लेकिन अब आप जानते हैं कि यह कैसे काम करता है, इसलिए आप अपने apps में relative imports का उपयोग कर सकते हैं, चाहे वे कितने भी complex हों। 🤓 + +### कुछ custom `tags`, `responses`, और `dependencies` जोड़ें { #add-some-custom-tags-responses-and-dependencies } + +हम प्रत्येक *path operation* में prefix `/items` या `tags=["items"]` नहीं जोड़ रहे हैं क्योंकि हमने उन्हें `APIRouter` में जोड़ दिया है। + +लेकिन हम अभी भी _अधिक_ `tags` जोड़ सकते हैं जो किसी specific *path operation* पर लागू होंगे, और उस *path operation* के लिए specific कुछ अतिरिक्त `responses` भी: + +{* ../../docs_src/bigger_applications/app_an_py310/routers/items.py hl[30:31] title["app/routers/items.py"] *} + +/// tip | टिप + +इस आखिरी path operation में tags का combination होगा: `["items", "custom"]`। + +और documentation में इसके दोनों responses भी होंगे, एक `404` के लिए और एक `403` के लिए। + +/// + +## मुख्य `FastAPI` { #the-main-fastapi } + +अब, `app/main.py` पर module देखें। + +यहीं आप `FastAPI` class import और use करते हैं। + +यह आपके application की main file होगी जो सब कुछ एक साथ जोड़ती है। + +और क्योंकि आपका अधिकतर logic अब अपने-अपने specific module में रहेगा, main file काफी सरल होगी। + +### `FastAPI` import करें { #import-fastapi } + +आप सामान्य रूप से `FastAPI` class import और create करते हैं। + +और हम [global dependencies](dependencies/global-dependencies.md) भी declare कर सकते हैं जिन्हें प्रत्येक `APIRouter` के लिए dependencies के साथ combine किया जाएगा: + +{* ../../docs_src/bigger_applications/app_an_py310/main.py hl[1,3,7] title["app/main.py"] *} + +### `APIRouter` import करें { #import-the-apirouter } + +अब हम उन अन्य submodules को import करते हैं जिनके पास `APIRouter`s हैं: + +{* ../../docs_src/bigger_applications/app_an_py310/main.py hl[4:5] title["app/main.py"] *} + +क्योंकि files `app/routers/users.py` और `app/routers/items.py` ऐसे submodules हैं जो उसी Python package `app` का हिस्सा हैं, हम "relative imports" का उपयोग करके उन्हें import करने के लिए single dot `.` का उपयोग कर सकते हैं। + +### importing कैसे काम करता है { #how-the-importing-works } + +section: + +```Python +from .routers import items, users +``` + +का मतलब है: + +* उसी package से शुरू करना जिसमें यह module (file `app/main.py`) रहता है (directory `app/`)... +* subpackage `routers` ढूँढना (directory `app/routers/` पर)... +* और उससे, submodule `items` (file `app/routers/items.py` पर) और `users` (file `app/routers/users.py` पर) import करना... + +module `items` में एक variable `router` (`items.router`) होगा। यह वही है जो हमने file `app/routers/items.py` में बनाया था, यह एक `APIRouter` object है। + +और फिर हम module `users` के लिए भी वही करते हैं। + +हम उन्हें इस तरह भी import कर सकते थे: + +```Python +from app.routers import items, users +``` + +/// note | नोट + +पहला version एक "relative import" है: + +```Python +from .routers import items, users +``` + +दूसरा version एक "absolute import" है: + +```Python +from app.routers import items, users +``` + +Python Packages और Modules के बारे में अधिक जानने के लिए, [Modules के बारे में official Python documentation](https://docs.python.org/3/tutorial/modules.html) पढ़ें। + +/// + +### नामों के collisions से बचें { #avoid-name-collisions } + +हम submodule `items` को directly import कर रहे हैं, केवल उसके variable `router` को import करने के बजाय। + +ऐसा इसलिए है क्योंकि हमारे पास submodule `users` में भी `router` नाम का एक और variable है। + +अगर हमने एक के बाद एक import किया होता, जैसे: + +```Python +from .routers.items import router +from .routers.users import router +``` + +तो `users` का `router`, `items` वाले को overwrite कर देता और हम उन्हें एक ही समय में use नहीं कर पाते। + +इसलिए, उन्हें एक ही file में दोनों को use करने में सक्षम होने के लिए, हम submodules को directly import करते हैं: + +{* ../../docs_src/bigger_applications/app_an_py310/main.py hl[5] title["app/main.py"] *} + +### `users` और `items` के लिए `APIRouter`s include करें { #include-the-apirouters-for-users-and-items } + +अब, submodules `users` और `items` से `router`s include करें: + +{* ../../docs_src/bigger_applications/app_an_py310/main.py hl[10:11] title["app/main.py"] *} + +/// note | नोट + +`users.router` file `app/routers/users.py` के अंदर मौजूद `APIRouter` को contain करता है। + +और `items.router` file `app/routers/items.py` के अंदर मौजूद `APIRouter` को contain करता है। + +/// + +`app.include_router()` के साथ हम प्रत्येक `APIRouter` को main `FastAPI` application में जोड़ सकते हैं। + +यह उस router के सभी routes को उसका हिस्सा बनाकर include करेगा। + +/// note | तकनीकी विवरण + +FastAPI मूल `APIRouter` और उसके `APIRoute`s को active रखता है जब router main application में include किया जाता है। + +इसका मतलब है कि custom `APIRouter` और `APIRoute` subclasses router include होने के बाद भी participate कर सकते हैं। + +/// + +/// tip | टिप + +routers include करते समय आपको performance के बारे में चिंता करने की ज़रूरत नहीं है। + +इसे lightweight होने और हर request में overhead जोड़ने से बचने के लिए design किया गया है। + +इसलिए यह performance को affect नहीं करेगा। ⚡ + +/// + +### custom `prefix`, `tags`, `responses`, और `dependencies` के साथ `APIRouter` include करें { #include-an-apirouter-with-a-custom-prefix-tags-responses-and-dependencies } + +अब, कल्पना करें कि आपकी organization ने आपको `app/internal/admin.py` file दी है। + +इसमें कुछ admin *path operations* वाला `APIRouter` है जिसे आपकी organization कई projects के बीच share करती है। + +इस उदाहरण के लिए यह बहुत सरल होगा। लेकिन मान लीजिए कि क्योंकि यह organization में अन्य projects के साथ shared है, हम इसे modify नहीं कर सकते और `prefix`, `dependencies`, `tags`, आदि directly `APIRouter` में नहीं जोड़ सकते: + +{* ../../docs_src/bigger_applications/app_an_py310/internal/admin.py hl[3] title["app/internal/admin.py"] *} + +लेकिन हम फिर भी `APIRouter` include करते समय एक custom `prefix` set करना चाहते हैं ताकि इसके सभी *path operations* `/admin` से शुरू हों, हम इसे इस project के लिए पहले से मौजूद `dependencies` के साथ secure करना चाहते हैं, और हम `tags` और `responses` include करना चाहते हैं। + +हम original `APIRouter` को modify किए बिना यह सब declare कर सकते हैं, उन parameters को `app.include_router()` में pass करके: + +{* ../../docs_src/bigger_applications/app_an_py310/main.py hl[14:17] title["app/main.py"] *} + +इस तरह, original `APIRouter` unmodified रहेगा, इसलिए हम वही `app/internal/admin.py` file organization में अन्य projects के साथ अब भी share कर सकते हैं। + +परिणाम यह है कि हमारी app में, `admin` module से प्रत्येक *path operation* में होगा: + +* prefix `/admin`. +* tag `admin`. +* dependency `get_token_header`. +* response `418`. 🍵 + +लेकिन यह केवल हमारी app में उस `APIRouter` को affect करेगा, उसे use करने वाले किसी अन्य code को नहीं। + +इसलिए, उदाहरण के लिए, अन्य projects उसी `APIRouter` को किसी अलग authentication method के साथ use कर सकते हैं। + +### एक *path operation* include करें { #include-a-path-operation } + +हम सीधे `FastAPI` app में भी *path operations* जोड़ सकते हैं। + +यहाँ हम ऐसा करते हैं... बस यह दिखाने के लिए कि हम कर सकते हैं 🤷: + +{* ../../docs_src/bigger_applications/app_an_py310/main.py hl[21:23] title["app/main.py"] *} + +और यह `app.include_router()` के साथ जोड़े गए सभी अन्य *path operations* के साथ सही तरीके से काम करेगा। + +/// note | बहुत तकनीकी विवरण + +**नोट**: यह बहुत technical detail है जिसे आप शायद **बस skip** कर सकते हैं। + +--- + +`APIRouter`s "mounted" नहीं होते, वे बाकी application से isolated नहीं होते। + +ऐसा इसलिए है क्योंकि हम उनके *path operations* को OpenAPI schema और user interfaces में include करना चाहते हैं। + +FastAPI original routers और path operations को active रखता है, और requests handle करते समय और OpenAPI generate करते समय router prefixes, dependencies, tags, responses, और अन्य metadata को combine करता है। + +/// + +## `pyproject.toml` में `entrypoint` configure करें { #configure-the-entrypoint-in-pyproject-toml } + +क्योंकि आपका FastAPI `app` object `app/main.py` में रहता है, आप अपने `pyproject.toml` file में `entrypoint` को इस तरह configure कर सकते हैं: + +```toml +[tool.fastapi] +entrypoint = "app.main:app" +``` + +यह इस तरह import करने के बराबर है: + +```python +from app.main import app +``` + +इस तरह `fastapi` command जान जाएगा कि आपकी app कहाँ मिलेगी। + +/// Note | नोट + +आप command को path भी pass कर सकते हैं, जैसे: + +```console +$ fastapi dev app/main.py +``` + +लेकिन हर बार `fastapi` command call करते समय आपको सही path pass करना याद रखना होगा। + +इसके अलावा, अन्य tools शायद इसे ढूँढ न पाएँ, उदाहरण के लिए [VS Code Extension](../editor-support.md) या [FastAPI Cloud](https://fastapicloud.com), इसलिए `pyproject.toml` में `entrypoint` का उपयोग करने की सलाह दी जाती है। + +/// + +## automatic API docs जाँचें { #check-the-automatic-api-docs } + +अब, अपनी app चलाएँ: + +
+ +```console +$ fastapi dev + +INFO: Uvicorn running on http://127.0.0.1:8000 (Press CTRL+C to quit) +``` + +
+ +और docs को [http://127.0.0.1:8000/docs](http://127.0.0.1:8000/docs) पर खोलें। + +आप automatic API docs देखेंगे, जिसमें सभी submodules से paths शामिल होंगे, सही paths (और prefixes) और सही tags का उपयोग करते हुए: + + + +## अलग-अलग `prefix` के साथ उसी router को multiple times include करें { #include-the-same-router-multiple-times-with-different-prefix } + +आप अलग-अलग prefixes का उपयोग करके *same* router के साथ `.include_router()` को multiple times भी use कर सकते हैं। + +यह उपयोगी हो सकता है, उदाहरण के लिए, उसी API को अलग-अलग prefixes के तहत expose करने के लिए, जैसे `/api/v1` और `/api/latest`। + +यह एक advanced usage है जिसकी आपको शायद सच में ज़रूरत न हो, लेकिन अगर हो तो यह मौजूद है। + +## एक `APIRouter` को दूसरे में include करें { #include-an-apirouter-in-another } + +जिस तरह आप `FastAPI` application में `APIRouter` include कर सकते हैं, उसी तरह आप एक `APIRouter` को दूसरे `APIRouter` में include कर सकते हैं: + +```Python +router.include_router(other_router) +``` + +आप यह `FastAPI` app में `router` include करने से पहले या बाद में कर सकते हैं। FastAPI फिर भी `other_router` से *path operations* को routing और OpenAPI में include करेगा। + +बाद में routers में जोड़े गए *path operations* पर भी यही लागू होता है। वे पहले वाली inclusion के माध्यम से भी visible होंगे। + +/// warning | तकनीकी विवरण + +router include करने के बाद `router.routes` को directly mutate करने से बचें। FastAPI router inclusion को live मानता है, इसलिए original router और उसके routes routing और OpenAPI generation का हिस्सा बने रहते हैं। + +routes और routers जोड़ने के लिए documented APIs जैसे path operation decorators और `.include_router()` का उपयोग करें। + +`router.routes` को एक lower-level route tree की तरह treat करें जिसमें route definitions और included routers हो सकते हैं, और इस पर final path operations की flat list की तरह rely करने से बचें। + +/// diff --git a/docs/hi/docs/tutorial/body-fields.md b/docs/hi/docs/tutorial/body-fields.md new file mode 100644 index 000000000..22f5d38fd --- /dev/null +++ b/docs/hi/docs/tutorial/body-fields.md @@ -0,0 +1,61 @@ +# Body - Fields { #body-fields } + +जिस तरह आप *path operation function* के parameters में `Query`, `Path` और `Body` के साथ अतिरिक्त validation और metadata घोषित कर सकते हैं, उसी तरह आप Pydantic के `Field` का उपयोग करके Pydantic models के अंदर validation और metadata घोषित कर सकते हैं। + +## `Field` import करें { #import-field } + +सबसे पहले, आपको इसे import करना होगा: + +{* ../../docs_src/body_fields/tutorial001_an_py310.py hl[4] *} + + +/// warning | चेतावनी + +ध्यान दें कि `Field` को सीधे `pydantic` से import किया जाता है, `fastapi` से नहीं, जैसे बाकी सभी (`Query`, `Path`, `Body`, आदि) किए जाते हैं। + +/// + +## model attributes घोषित करें { #declare-model-attributes } + +फिर आप model attributes के साथ `Field` का उपयोग कर सकते हैं: + +{* ../../docs_src/body_fields/tutorial001_an_py310.py hl[11:14] *} + +`Field` उसी तरह काम करता है जैसे `Query`, `Path` और `Body`, इसमें वही सभी parameters आदि होते हैं। + +/// note | तकनीकी विवरण + +वास्तव में, `Query`, `Path` और अन्य जिन्हें आप आगे देखेंगे, एक सामान्य `Param` class के subclasses के objects बनाते हैं, जो स्वयं Pydantic की `FieldInfo` class का subclass है। + +और Pydantic का `Field` भी `FieldInfo` का एक instance लौटाता है। + +`Body` भी सीधे `FieldInfo` के subclass के objects लौटाता है। और कुछ अन्य भी हैं जिन्हें आप बाद में देखेंगे, जो `Body` class के subclasses हैं। + +याद रखें कि जब आप `fastapi` से `Query`, `Path` और अन्य import करते हैं, तो वे वास्तव में functions होते हैं जो विशेष classes लौटाते हैं। + +/// + +/// tip | सुझाव + +ध्यान दें कि type, default value और `Field` वाले हर model के attribute की संरचना *path operation function* के parameter जैसी ही होती है, बस `Path`, `Query` और `Body` की जगह `Field` होता है। + +/// + +## अतिरिक्त जानकारी जोड़ें { #add-extra-information } + +आप `Field`, `Query`, `Body` आदि में अतिरिक्त जानकारी घोषित कर सकते हैं। और यह जनरेट किए गए JSON Schema में शामिल होगी। + +आप docs में आगे examples घोषित करना सीखते समय अतिरिक्त जानकारी जोड़ने के बारे में और जानेंगे। + +/// warning | चेतावनी + +`Field` को दिए गए अतिरिक्त keys आपके application के परिणामी OpenAPI schema में भी मौजूद होंगे। +क्योंकि ये keys जरूरी नहीं कि OpenAPI specification का हिस्सा हों, इसलिए कुछ OpenAPI tools, उदाहरण के लिए [OpenAPI validator](https://validator.swagger.io/), आपके जनरेट किए गए schema के साथ काम नहीं कर सकते। + +/// + +## Recap { #recap } + +आप model attributes के लिए अतिरिक्त validations और metadata घोषित करने के लिए Pydantic के `Field` का उपयोग कर सकते हैं। + +आप अतिरिक्त JSON Schema metadata पास करने के लिए extra keyword arguments का भी उपयोग कर सकते हैं। diff --git a/docs/hi/docs/tutorial/body-multiple-params.md b/docs/hi/docs/tutorial/body-multiple-params.md new file mode 100644 index 000000000..0d095ddf3 --- /dev/null +++ b/docs/hi/docs/tutorial/body-multiple-params.md @@ -0,0 +1,169 @@ +# Body - कई Parameters { #body-multiple-parameters } + +अब जबकि हमने देख लिया है कि `Path` और `Query` का उपयोग कैसे करना है, आइए request body declarations के और उन्नत उपयोग देखें। + +## `Path`, `Query` और body parameters को मिलाएँ { #mix-path-query-and-body-parameters } + +सबसे पहले, बेशक, आप `Path`, `Query` और request body parameter declarations को स्वतंत्र रूप से मिला सकते हैं और **FastAPI** जान जाएगा कि क्या करना है। + +और आप body parameters को optional भी declare कर सकते हैं, default को `None` पर सेट करके: + +{* ../../docs_src/body_multiple_params/tutorial001_an_py310.py hl[18:20] *} + +/// note | नोट + +ध्यान दें कि, इस मामले में, body से लिया जाने वाला `item` optional है। क्योंकि इसका default value `None` है। + +/// + +## कई body parameters { #multiple-body-parameters } + +पिछले उदाहरण में, *path operations* एक JSON body की अपेक्षा करेंगे जिसमें `Item` के attributes हों, जैसे: + +```JSON +{ + "name": "Foo", + "description": "The pretender", + "price": 42.0, + "tax": 3.2 +} +``` + +लेकिन आप कई body parameters भी declare कर सकते हैं, उदाहरण के लिए `item` और `user`: + +{* ../../docs_src/body_multiple_params/tutorial002_py310.py hl[20] *} + + +इस मामले में, **FastAPI** ध्यान देगा कि function में एक से अधिक body parameter हैं (दो parameters हैं जो Pydantic models हैं)। + +तो, फिर यह parameter names को body में keys (field names) के रूप में उपयोग करेगा, और ऐसी body की अपेक्षा करेगा: + +```JSON +{ + "item": { + "name": "Foo", + "description": "The pretender", + "price": 42.0, + "tax": 3.2 + }, + "user": { + "username": "dave", + "full_name": "Dave Grohl" + } +} +``` + +/// note | नोट + +ध्यान दें कि भले ही `item` को पहले की तरह ही declare किया गया था, अब उससे अपेक्षा की जाती है कि वह body के अंदर key `item` के साथ हो। + +/// + +**FastAPI** request से automatic conversion करेगा, ताकि parameter `item` को उसकी विशिष्ट content मिले और `user` के लिए भी यही हो। + +यह compound data का validation करेगा, और इसे OpenAPI schema और automatic docs के लिए उसी तरह document करेगा। + +## body में एकल values { #singular-values-in-body } + +जिस तरह query और path parameters के लिए extra data define करने हेतु `Query` और `Path` हैं, **FastAPI** एक समान `Body` प्रदान करता है। + +उदाहरण के लिए, पिछले model को extend करते हुए, आप तय कर सकते हैं कि आप उसी body में `item` और `user` के अलावा एक और key `importance` रखना चाहते हैं। + +यदि आप इसे जैसे है वैसे declare करते हैं, क्योंकि यह एक single value है, **FastAPI** मान लेगा कि यह एक query parameter है। + +लेकिन आप **FastAPI** को `Body` का उपयोग करके इसे एक और body key के रूप में treat करने का निर्देश दे सकते हैं: + +{* ../../docs_src/body_multiple_params/tutorial003_an_py310.py hl[23] *} + + +इस मामले में, **FastAPI** ऐसी body की अपेक्षा करेगा: + +```JSON +{ + "item": { + "name": "Foo", + "description": "The pretender", + "price": 42.0, + "tax": 3.2 + }, + "user": { + "username": "dave", + "full_name": "Dave Grohl" + }, + "importance": 5 +} +``` + +फिर से, यह data types को convert करेगा, validate करेगा, document करेगा, आदि। + +## कई body params और query { #multiple-body-params-and-query } + +बेशक, आप जब भी ज़रूरत हो, किसी भी body parameters के अतिरिक्त, extra query parameters भी declare कर सकते हैं। + +क्योंकि default रूप से, single values को query parameters के रूप में interpret किया जाता है, आपको स्पष्ट रूप से `Query` जोड़ने की ज़रूरत नहीं है, आप बस ऐसा कर सकते हैं: + +```Python +q: str | None = None +``` + +उदाहरण के लिए: + +{* ../../docs_src/body_multiple_params/tutorial004_an_py310.py hl[28] *} + + +/// note | नोट + +`Body` में भी वही सभी extra validation और metadata parameters हैं जो `Query`, `Path` और अन्य में हैं जिन्हें आप बाद में देखेंगे। + +/// + +## एक single body parameter को embed करें { #embed-a-single-body-parameter } + +मान लीजिए आपके पास Pydantic model `Item` से केवल एक single `item` body parameter है। + +default रूप से, **FastAPI** फिर सीधे उसकी body की अपेक्षा करेगा। + +लेकिन यदि आप चाहते हैं कि यह key `item` के साथ JSON की अपेक्षा करे और उसके अंदर model contents हों, जैसा कि यह तब करता है जब आप extra body parameters declare करते हैं, तो आप special `Body` parameter `embed` का उपयोग कर सकते हैं: + +```Python +item: Annotated[Item, Body(embed=True)] +``` + +जैसे कि: + +{* ../../docs_src/body_multiple_params/tutorial005_an_py310.py hl[17] *} + + +इस मामले में **FastAPI** ऐसी body की अपेक्षा करेगा: + +```JSON hl_lines="2" +{ + "item": { + "name": "Foo", + "description": "The pretender", + "price": 42.0, + "tax": 3.2 + } +} +``` + +इसके बजाय: + +```JSON +{ + "name": "Foo", + "description": "The pretender", + "price": 42.0, + "tax": 3.2 +} +``` + +## Recap { #recap } + +आप अपनी *path operation function* में कई body parameters जोड़ सकते हैं, भले ही एक request में केवल एक ही body हो सकती है। + +लेकिन **FastAPI** इसे handle करेगा, आपको आपके function में सही data देगा, और *path operation* में सही schema को validate और document करेगा। + +आप single values को body के हिस्से के रूप में receive करने के लिए भी declare कर सकते हैं। + +और आप **FastAPI** को body को एक key में embed करने का निर्देश दे सकते हैं, भले ही केवल एक single parameter declare किया गया हो। diff --git a/docs/hi/docs/tutorial/body-nested-models.md b/docs/hi/docs/tutorial/body-nested-models.md new file mode 100644 index 000000000..04ac55bfd --- /dev/null +++ b/docs/hi/docs/tutorial/body-nested-models.md @@ -0,0 +1,221 @@ +# Body - Nested Models { #body-nested-models } + +**FastAPI** के साथ, आप arbitrarily deeply nested models को define, validate, document, और use कर सकते हैं (Pydantic की बदौलत)। + +## List fields { #list-fields } + +आप किसी attribute को subtype के रूप में define कर सकते हैं। उदाहरण के लिए, एक Python `list`: + +{* ../../docs_src/body_nested_models/tutorial001_py310.py hl[12] *} + +यह `tags` को एक list बना देगा, हालांकि यह list के elements का type declare नहीं करता। + +## Type parameter के साथ List fields { #list-fields-with-type-parameter } + +लेकिन Python में internal types, या "type parameters" के साथ lists declare करने का एक खास तरीका है: + +### Type parameter के साथ `list` declare करें { #declare-a-list-with-a-type-parameter } + +ऐसे types declare करने के लिए जिनमें type parameters (internal types) होते हैं, जैसे `list`, `dict`, `tuple`, +internal type(s) को square brackets: `[` और `]` का उपयोग करके "type parameters" के रूप में pass करें + +```Python +my_list: list[str] +``` + +Type declarations के लिए यह सब standard Python syntax है। + +Internal types वाले model attributes के लिए भी वही standard syntax उपयोग करें। + +तो, हमारे उदाहरण में, हम `tags` को खास तौर पर "strings की list" बना सकते हैं: + +{* ../../docs_src/body_nested_models/tutorial002_py310.py hl[12] *} + +## Set types { #set-types } + +लेकिन फिर हम इस पर सोचते हैं, और समझते हैं कि tags repeat नहीं होने चाहिए, वे शायद unique strings होंगे। + +और Python में unique items के sets के लिए एक खास data type है, `set`। + +फिर हम `tags` को strings के set के रूप में declare कर सकते हैं: + +{* ../../docs_src/body_nested_models/tutorial003_py310.py hl[12] *} + +इसके साथ, भले ही आपको duplicate data वाला request मिले, वह unique items के set में convert हो जाएगा। + +और जब भी आप उस data को output करेंगे, भले ही source में duplicates हों, वह unique items के set के रूप में output होगा। + +और इसे उसी अनुसार annotate / document भी किया जाएगा। + +## Nested Models { #nested-models } + +Pydantic model के हर attribute का एक type होता है। + +लेकिन वह type खुद भी कोई दूसरा Pydantic model हो सकता है। + +इसलिए, आप खास attribute names, types और validations के साथ deeply nested JSON "objects" declare कर सकते हैं। + +यह सब, मनचाही गहराई तक nested हो सकता है। + +### Submodel define करें { #define-a-submodel } + +उदाहरण के लिए, हम एक `Image` model define कर सकते हैं: + +{* ../../docs_src/body_nested_models/tutorial004_py310.py hl[7:9] *} + +### Submodel को type के रूप में उपयोग करें { #use-the-submodel-as-a-type } + +और फिर हम इसे किसी attribute के type के रूप में उपयोग कर सकते हैं: + +{* ../../docs_src/body_nested_models/tutorial004_py310.py hl[18] *} + +इसका मतलब होगा कि **FastAPI** कुछ इस तरह के body की अपेक्षा करेगा: + +```JSON +{ + "name": "Foo", + "description": "The pretender", + "price": 42.0, + "tax": 3.2, + "tags": ["rock", "metal", "bar"], + "image": { + "url": "http://example.com/baz.jpg", + "name": "The Foo live" + } +} +``` + +फिर से, सिर्फ वह declaration करने से, **FastAPI** के साथ आपको मिलता है: + +* Editor support (completion, आदि), nested models के लिए भी +* Data conversion +* Data validation +* Automatic documentation + +## Special types और validation { #special-types-and-validation } + +`str`, `int`, `float`, आदि जैसे सामान्य singular types के अलावा, आप अधिक complex singular types उपयोग कर सकते हैं जो `str` से inherit करते हैं। + +आपके पास मौजूद सभी options देखने के लिए, [Pydantic का Type Overview](https://docs.pydantic.dev/latest/concepts/types/) देखें। अगले chapter में आपको कुछ उदाहरण दिखेंगे। + +उदाहरण के लिए, जैसा कि `Image` model में हमारे पास एक `url` field है, हम इसे `str` के बजाय Pydantic के `HttpUrl` का instance declare कर सकते हैं: + +{* ../../docs_src/body_nested_models/tutorial005_py310.py hl[2,8] *} + +String को valid URL होने के लिए check किया जाएगा, और JSON Schema / OpenAPI में उसी तरह document किया जाएगा। + +## Submodels की lists वाले attributes { #attributes-with-lists-of-submodels } + +आप Pydantic models को `list`, `set`, आदि के subtypes के रूप में भी उपयोग कर सकते हैं: + +{* ../../docs_src/body_nested_models/tutorial006_py310.py hl[18] *} + +यह इस तरह के JSON body की अपेक्षा करेगा (convert, validate, document, आदि): + +```JSON hl_lines="11" +{ + "name": "Foo", + "description": "The pretender", + "price": 42.0, + "tax": 3.2, + "tags": [ + "rock", + "metal", + "bar" + ], + "images": [ + { + "url": "http://example.com/baz.jpg", + "name": "The Foo live" + }, + { + "url": "http://example.com/dave.jpg", + "name": "The Baz" + } + ] +} +``` + +/// note | नोट + +ध्यान दें कि `images` key में अब image objects की एक list है। + +/// + +## Deeply nested models { #deeply-nested-models } + +आप arbitrarily deeply nested models define कर सकते हैं: + +{* ../../docs_src/body_nested_models/tutorial007_py310.py hl[7,12,18,21,25] *} + +/// note | नोट + +ध्यान दें कि `Offer` में `Item`s की एक list है, जिनमें आगे `Image`s की एक optional list है + +/// + +## Pure lists के bodies { #bodies-of-pure-lists } + +अगर जिस JSON body की आप अपेक्षा करते हैं उसका top level value एक JSON `array` (एक Python `list`) है, तो आप function के parameter में type declare कर सकते हैं, बिल्कुल Pydantic models की तरह: + +```Python +images: list[Image] +``` + +जैसे कि: + +{* ../../docs_src/body_nested_models/tutorial008_py310.py hl[13] *} + +## हर जगह editor support { #editor-support-everywhere } + +और आपको हर जगह editor support मिलता है। + +Lists के अंदर के items के लिए भी: + + + +अगर आप Pydantic models के बजाय सीधे `dict` के साथ काम कर रहे होते, तो आपको इस तरह का editor support नहीं मिल सकता था। + +लेकिन आपको उनकी चिंता भी करने की ज़रूरत नहीं है, आने वाले dicts अपने आप convert हो जाते हैं और आपका output भी अपने आप JSON में convert हो जाता है। + +## Arbitrary `dict`s के bodies { #bodies-of-arbitrary-dicts } + +आप body को एक `dict` के रूप में भी declare कर सकते हैं, जिसकी keys किसी type की हों और values किसी दूसरे type की। + +इस तरह, आपको पहले से यह जानने की ज़रूरत नहीं होती कि valid field/attribute names क्या हैं (जैसा कि Pydantic models के साथ होता)। + +यह तब उपयोगी होगा जब आप ऐसी keys receive करना चाहते हैं जिन्हें आप पहले से नहीं जानते। + +--- + +एक और उपयोगी case वह है जब आप किसी दूसरे type (जैसे, `int`) की keys रखना चाहते हैं। + +यही हम यहाँ देखने जा रहे हैं। + +इस case में, आप कोई भी `dict` accept करेंगे, जब तक कि उसमें `float` values वाली `int` keys हों: + +{* ../../docs_src/body_nested_models/tutorial009_py310.py hl[7] *} + +/// tip | टिप + +ध्यान रखें कि JSON केवल `str` को keys के रूप में support करता है। + +लेकिन Pydantic में automatic data conversion है। + +इसका मतलब है कि, भले ही आपके API clients केवल strings को keys के रूप में भेज सकते हैं, जब तक उन strings में pure integers हैं, Pydantic उन्हें convert और validate कर देगा। + +और `weights` के रूप में आपको जो `dict` receive होगा, उसमें वास्तव में `int` keys और `float` values होंगी। + +/// + +## Recap { #recap } + +**FastAPI** के साथ आपके पास Pydantic models द्वारा दी गई अधिकतम flexibility होती है, जबकि आपका code simple, short और elegant बना रहता है। + +लेकिन सभी benefits के साथ: + +* Editor support (हर जगह completion!) +* Data conversion (a.k.a. parsing / serialization) +* Data validation +* Schema documentation +* Automatic docs diff --git a/docs/hi/docs/tutorial/body-updates.md b/docs/hi/docs/tutorial/body-updates.md new file mode 100644 index 000000000..cab762e47 --- /dev/null +++ b/docs/hi/docs/tutorial/body-updates.md @@ -0,0 +1,100 @@ +# Body - अपडेट्स { #body-updates } + +## `PUT` के साथ बदलकर अपडेट करना { #update-replacing-with-put } + +किसी item को अपडेट करने के लिए आप [HTTP `PUT`](https://developer.mozilla.org/en-US/docs/Web/HTTP/Methods/PUT) operation का उपयोग कर सकते हैं। + +आप input data को ऐसे data में बदलने के लिए `jsonable_encoder` का उपयोग कर सकते हैं जिसे JSON के रूप में संग्रहीत किया जा सके (जैसे NoSQL database के साथ)। उदाहरण के लिए, `datetime` को `str` में बदलना। + +{* ../../docs_src/body_updates/tutorial001_py310.py hl[28:33] *} + +`PUT` का उपयोग ऐसा data प्राप्त करने के लिए किया जाता है जो मौजूदा data को बदल दे। + +### बदलने के बारे में चेतावनी { #warning-about-replacing } + +इसका मतलब है कि अगर आप item `bar` को `PUT` का उपयोग करके ऐसे body के साथ अपडेट करना चाहते हैं जिसमें यह हो: + +```Python +{ + "name": "Barz", + "price": 3, + "description": None, +} +``` + +क्योंकि इसमें पहले से संग्रहीत attribute `"tax": 20.2` शामिल नहीं है, input model `"tax": 10.5` की default value लेगा। + +और data उस "नए" `tax` `10.5` के साथ सहेजा जाएगा। + +## `PATCH` के साथ आंशिक अपडेट्स { #partial-updates-with-patch } + +आप data को *आंशिक रूप से* अपडेट करने के लिए [HTTP `PATCH`](https://developer.mozilla.org/en-US/docs/Web/HTTP/Methods/PATCH) operation का भी उपयोग कर सकते हैं। + +इसका मतलब है कि आप केवल वही data भेज सकते हैं जिसे आप अपडेट करना चाहते हैं, बाकी को वैसा ही छोड़ते हुए। + +/// note | नोट + +`PATCH`, `PUT` की तुलना में कम सामान्य रूप से उपयोग और जाना जाता है। + +और कई teams आंशिक अपडेट्स के लिए भी केवल `PUT` का उपयोग करती हैं। + +आप इन्हें जैसे चाहें वैसे उपयोग करने के लिए **स्वतंत्र** हैं, **FastAPI** कोई प्रतिबंध नहीं लगाता। + +लेकिन यह गाइड आपको मोटे तौर पर दिखाती है कि इन्हें कैसे उपयोग करने का इरादा है। + +/// + +### Pydantic के `exclude_unset` parameter का उपयोग करना { #using-pydantics-exclude-unset-parameter } + +अगर आप आंशिक अपडेट्स प्राप्त करना चाहते हैं, तो Pydantic के model के `.model_dump()` में parameter `exclude_unset` का उपयोग करना बहुत उपयोगी है। + +जैसे `item.model_dump(exclude_unset=True)`। + +इससे केवल उस data के साथ एक `dict` बनेगा जो `item` model बनाते समय सेट किया गया था, default values को छोड़कर। + +फिर आप इसका उपयोग केवल उस data के साथ एक `dict` बनाने के लिए कर सकते हैं जो सेट किया गया था (request में भेजा गया), default values को छोड़ते हुए: + +{* ../../docs_src/body_updates/tutorial002_py310.py hl[32] *} + +### Pydantic के `update` parameter का उपयोग करना { #using-pydantics-update-parameter } + +अब, आप `.model_copy()` का उपयोग करके मौजूदा model की एक copy बना सकते हैं, और अपडेट करने के लिए data वाले `dict` के साथ `update` parameter पास कर सकते हैं। + +जैसे `stored_item_model.model_copy(update=update_data)`: + +{* ../../docs_src/body_updates/tutorial002_py310.py hl[33] *} + +### आंशिक अपडेट्स Recap { #partial-updates-recap } + +संक्षेप में, आंशिक अपडेट्स लागू करने के लिए आप: + +* (वैकल्पिक रूप से) `PUT` के बजाय `PATCH` का उपयोग करें। +* संग्रहीत data प्राप्त करें। +* उस data को Pydantic model में रखें। +* input model से default values के बिना एक `dict` बनाएँ (`exclude_unset` का उपयोग करके)। + * इस तरह आप केवल उन values को अपडेट कर सकते हैं जिन्हें वास्तव में user ने सेट किया है, बजाय इसके कि आपके model में पहले से संग्रहीत values को default values से override कर दें। +* संग्रहीत model की एक copy बनाएँ, और प्राप्त आंशिक अपडेट्स के साथ उसके attributes को अपडेट करें (`update` parameter का उपयोग करके)। +* copied model को ऐसी चीज़ में बदलें जिसे आपकी DB में संग्रहीत किया जा सके (उदाहरण के लिए, `jsonable_encoder` का उपयोग करके)। + * यह model की `.model_dump()` method को फिर से उपयोग करने जैसा है, लेकिन यह सुनिश्चित करता है (और बदलता है) कि values ऐसे data types में हों जिन्हें JSON में बदला जा सके, उदाहरण के लिए, `datetime` को `str` में। +* data को अपनी DB में सहेजें। +* अपडेट किया गया model लौटाएँ। + +{* ../../docs_src/body_updates/tutorial002_py310.py hl[28:35] *} + +/// tip | टिप + +आप वास्तव में इसी तकनीक का उपयोग HTTP `PUT` operation के साथ भी कर सकते हैं। + +लेकिन यहाँ का उदाहरण `PATCH` का उपयोग करता है क्योंकि इसे इन्हीं use cases के लिए बनाया गया था। + +/// + +/// note | नोट + +ध्यान दें कि input model अभी भी validate किया जाता है। + +इसलिए, अगर आप ऐसे आंशिक अपडेट्स प्राप्त करना चाहते हैं जो सभी attributes को छोड़ सकते हैं, तो आपको ऐसा model चाहिए जिसमें सभी attributes optional के रूप में चिह्नित हों (default values या `None` के साथ)। + +**अपडेट्स** के लिए सभी optional values वाले models और **creation** के लिए required values वाले models में अंतर करने के लिए, आप [Extra Models](extra-models.md) में बताए गए विचारों का उपयोग कर सकते हैं। + +/// diff --git a/docs/hi/docs/tutorial/body.md b/docs/hi/docs/tutorial/body.md new file mode 100644 index 000000000..dfccf3726 --- /dev/null +++ b/docs/hi/docs/tutorial/body.md @@ -0,0 +1,166 @@ +# Request Body { #request-body } + +जब आपको किसी client (मान लें, एक browser) से अपनी API को data भेजना होता है, तो आप उसे **request body** के रूप में भेजते हैं। + +**request** body वह data है जो client आपकी API को भेजता है। **response** body वह data है जो आपकी API client को भेजती है। + +आपकी API को लगभग हमेशा **response** body भेजनी होती है। लेकिन clients को हर समय **request bodies** भेजने की ज़रूरत नहीं होती, कभी-कभी वे केवल एक path request करते हैं, शायद कुछ query parameters के साथ, लेकिन body नहीं भेजते। + +**request** body घोषित करने के लिए, आप [Pydantic](https://docs.pydantic.dev/) models का उनकी पूरी शक्ति और लाभों के साथ उपयोग करते हैं। + +/// note | नोट + +Data भेजने के लिए, आपको इनमें से किसी एक का उपयोग करना चाहिए: `POST` (सबसे आम), `PUT`, `DELETE` या `PATCH`. + +`GET` request के साथ body भेजने का व्यवहार specifications में undefined है, फिर भी, FastAPI इसे support करता है, केवल बहुत जटिल/चरम use cases के लिए। + +क्योंकि इसे discouraged किया जाता है, Swagger UI वाले interactive docs `GET` का उपयोग करते समय body के लिए documentation नहीं दिखाएँगे, और बीच में मौजूद proxies इसे support नहीं कर सकते। + +/// + +## Pydantic के `BaseModel` को import करें { #import-pydantics-basemodel } + +सबसे पहले, आपको `pydantic` से `BaseModel` import करना होगा: + +{* ../../docs_src/body/tutorial001_py310.py hl[2] *} + +## अपना data model बनाएँ { #create-your-data-model } + +फिर आप अपने data model को एक class के रूप में घोषित करते हैं जो `BaseModel` से inherit करती है। + +सभी attributes के लिए standard Python types का उपयोग करें: + +{* ../../docs_src/body/tutorial001_py310.py hl[5:9] *} + + +Query parameters घोषित करते समय की तरह, जब किसी model attribute का default value होता है, तो वह required नहीं होता। अन्यथा, वह required होता है। उसे केवल optional बनाने के लिए `None` का उपयोग करें। + +उदाहरण के लिए, ऊपर दिया गया यह model इस तरह का JSON "`object`" (या Python `dict`) घोषित करता है: + +```JSON +{ + "name": "Foo", + "description": "An optional description", + "price": 45.2, + "tax": 3.5 +} +``` + +...क्योंकि `description` और `tax` optional हैं (`None` के default value के साथ), यह JSON "`object`" भी valid होगा: + +```JSON +{ + "name": "Foo", + "price": 45.2 +} +``` + +## इसे एक parameter के रूप में घोषित करें { #declare-it-as-a-parameter } + +इसे अपनी *path operation* में जोड़ने के लिए, इसे उसी तरह घोषित करें जैसे आपने path और query parameters घोषित किए थे: + +{* ../../docs_src/body/tutorial001_py310.py hl[16] *} + +...और इसके type को आपके बनाए हुए model, `Item`, के रूप में घोषित करें। + +## परिणाम { #results } + +सिर्फ उस Python type declaration के साथ, **FastAPI** यह करेगा: + +* request के body को JSON के रूप में पढ़ेगा। +* संबंधित types को convert करेगा (यदि ज़रूरत हो)। +* data को validate करेगा। + * यदि data invalid है, तो यह एक अच्छा और स्पष्ट error return करेगा, जो ठीक-ठीक बताएगा कि गलत data कहाँ और क्या था। +* आपको प्राप्त data parameter `item` में देगा। + * क्योंकि आपने इसे function में `Item` type का घोषित किया है, आपको इसके सभी attributes और उनके types के लिए पूरा editor support (completion, आदि) भी मिलेगा। +* आपके model के लिए [JSON Schema](https://json-schema.org) definitions generate करेगा, यदि आपके project के लिए उचित हो तो आप उन्हें कहीं और भी उपयोग कर सकते हैं। +* वे schemas generated OpenAPI schema का हिस्सा होंगे, और automatic documentation UIs द्वारा उपयोग किए जाएँगे। + +## स्वचालित docs { #automatic-docs } + +आपके models के JSON Schemas आपके OpenAPI generated schema का हिस्सा होंगे, और interactive API docs में दिखाए जाएँगे: + + + +और वे API docs में हर उस *path operation* के अंदर भी उपयोग किए जाएँगे जिसे उनकी ज़रूरत है: + + + +## Editor support { #editor-support } + +अपने editor में, अपने function के अंदर आपको हर जगह type hints और completion मिलेंगे (यदि आपको Pydantic model के बजाय `dict` मिला होता, तो ऐसा नहीं होता): + + + +आपको incorrect type operations के लिए error checks भी मिलते हैं: + + + +यह संयोग से नहीं है, पूरा framework इसी design के इर्द-गिर्द बनाया गया था। + +और किसी भी implementation से पहले, design phase में इसे पूरी तरह test किया गया था, ताकि सुनिश्चित किया जा सके कि यह सभी editors के साथ काम करेगा। + +इसे support करने के लिए Pydantic में भी कुछ बदलाव किए गए थे। + +पिछले screenshots [Visual Studio Code](https://code.visualstudio.com) के साथ लिए गए थे। + +लेकिन आपको [PyCharm](https://www.jetbrains.com/pycharm/) और अधिकांश अन्य Python editors के साथ भी वही editor support मिलेगा: + + + +/// tip | सुझाव + +यदि आप [PyCharm](https://www.jetbrains.com/pycharm/) को अपने editor के रूप में उपयोग करते हैं, तो आप [Pydantic PyCharm Plugin](https://github.com/koxudaxi/pydantic-pycharm-plugin/) का उपयोग कर सकते हैं। + +यह Pydantic models के लिए editor support को बेहतर बनाता है, इन चीज़ों के साथ: + +* auto-completion +* type checks +* refactoring +* searching +* inspections + +/// + +## model का उपयोग करें { #use-the-model } + +Function के अंदर, आप model object के सभी attributes को सीधे access कर सकते हैं: + +{* ../../docs_src/body/tutorial002_py310.py *} + +## Request body + path parameters { #request-body-path-parameters } + +आप path parameters और request body को एक ही समय में घोषित कर सकते हैं। + +**FastAPI** पहचानेगा कि वे function parameters जो path parameters से match करते हैं, उन्हें **path से लिया जाना चाहिए**, और वे function parameters जो Pydantic models के रूप में घोषित हैं, उन्हें **request body से लिया जाना चाहिए**। + +{* ../../docs_src/body/tutorial003_py310.py hl[15:16] *} + + +## Request body + path + query parameters { #request-body-path-query-parameters } + +आप **body**, **path** और **query** parameters को भी एक ही समय में घोषित कर सकते हैं। + +**FastAPI** उनमें से प्रत्येक को पहचानेगा और data को सही जगह से लेगा। + +{* ../../docs_src/body/tutorial004_py310.py hl[16] *} + +Function parameters को इस प्रकार पहचाना जाएगा: + +* यदि parameter **path** में भी घोषित है, तो उसे path parameter के रूप में उपयोग किया जाएगा। +* यदि parameter **singular type** का है (जैसे `int`, `float`, `str`, `bool`, आदि), तो उसे **query** parameter के रूप में interpret किया जाएगा। +* यदि parameter को **Pydantic model** के type का घोषित किया गया है, तो उसे request **body** के रूप में interpret किया जाएगा। + +/// note | नोट + +FastAPI जान जाएगा कि `q` का value required नहीं है क्योंकि उसका default value `= None` है। + +`str | None` का उपयोग FastAPI यह निर्धारित करने के लिए नहीं करता कि value required नहीं है, वह जान जाएगा कि यह required नहीं है क्योंकि इसका default value `= None` है। + +लेकिन type annotations जोड़ने से आपका editor आपको बेहतर support दे सकेगा और errors detect कर सकेगा। + +/// + +## Pydantic के बिना { #without-pydantic } + +यदि आप Pydantic models का उपयोग नहीं करना चाहते, तो आप **Body** parameters का भी उपयोग कर सकते हैं। [Body - Multiple Parameters: Singular values in body](body-multiple-params.md#singular-values-in-body) के docs देखें। diff --git a/docs/hi/docs/tutorial/cookie-param-models.md b/docs/hi/docs/tutorial/cookie-param-models.md new file mode 100644 index 000000000..38ea681b2 --- /dev/null +++ b/docs/hi/docs/tutorial/cookie-param-models.md @@ -0,0 +1,76 @@ +# Cookie Parameter Models { #cookie-parameter-models } + +अगर आपके पास संबंधित **cookies** का एक समूह है, तो आप उन्हें declare करने के लिए एक **Pydantic model** बना सकते हैं। 🍪 + +यह आपको **model को फिर से उपयोग** करने की अनुमति देगा, **कई जगहों** पर, और साथ ही सभी parameters के लिए validations और metadata एक साथ declare करने की भी। 😎 + +/// note | नोट + +यह FastAPI version `0.115.0` से supported है। 🤓 + +/// + +/// tip | सुझाव + +यही तकनीक `Query`, `Cookie`, और `Header` पर लागू होती है। 😎 + +/// + +## Pydantic Model के साथ Cookies { #cookies-with-a-pydantic-model } + +जिन **cookie** parameters की आपको ज़रूरत है, उन्हें एक **Pydantic model** में declare करें, और फिर parameter को `Cookie` के रूप में declare करें: + +{* ../../docs_src/cookie_param_models/tutorial001_an_py310.py hl[9:12,16] *} + +**FastAPI** request में प्राप्त **cookies** से **हर field** के लिए data **extract** करेगा और आपको वह Pydantic model देगा जिसे आपने define किया है। + +## Docs देखें { #check-the-docs } + +आप `/docs` पर docs UI में defined cookies देख सकते हैं: + +
+ +
+ +/// note | नोट + +ध्यान रखें कि, क्योंकि **browsers cookies को** विशेष तरीकों से और पर्दे के पीछे handle करते हैं, वे **JavaScript** को आसानी से उन्हें छूने की अनुमति **नहीं** देते। + +अगर आप `/docs` पर **API docs UI** पर जाते हैं, तो आप अपने *path operations* के लिए cookies की **documentation** देख पाएँगे। + +लेकिन भले ही आप **data भरें** और "Execute" पर क्लिक करें, क्योंकि docs UI **JavaScript** के साथ काम करता है, cookies नहीं भेजे जाएँगे, और आपको एक **error** message दिखाई देगा जैसे कि आपने कोई values लिखी ही न हों। + +/// + +## Extra Cookies को forbid करें { #forbid-extra-cookies } + +कुछ विशेष use cases में (शायद बहुत आम नहीं), आप उन cookies को **restrict** करना चाह सकते हैं जिन्हें आप प्राप्त करना चाहते हैं। + +आपकी API के पास अब अपनी खुद की cookie सहमति को control करने की शक्ति है। 🤪🍪 + +आप Pydantic के model configuration का उपयोग करके किसी भी `extra` fields को `forbid` कर सकते हैं: + +{* ../../docs_src/cookie_param_models/tutorial002_an_py310.py hl[10] *} + +अगर कोई client कुछ **extra cookies** भेजने की कोशिश करता है, तो उन्हें एक **error** response मिलेगा। + +बेचारे cookie banners, जो API द्वारा उसे reject किए जाने के लिए आपकी सहमति पाने में इतनी मेहनत करते हैं। 🍪 + +उदाहरण के लिए, अगर client `good-list-please` value के साथ एक `santa_tracker` cookie भेजने की कोशिश करता है, तो client को एक **error** response मिलेगा जो बताएगा कि `santa_tracker` cookie की अनुमति नहीं है: + +```json +{ + "detail": [ + { + "type": "extra_forbidden", + "loc": ["cookie", "santa_tracker"], + "msg": "Extra inputs are not permitted", + "input": "good-list-please", + } + ] +} +``` + +## सारांश { #summary } + +आप **FastAPI** में **cookies** declare करने के लिए **Pydantic models** का उपयोग कर सकते हैं। 😎 diff --git a/docs/hi/docs/tutorial/cookie-params.md b/docs/hi/docs/tutorial/cookie-params.md new file mode 100644 index 000000000..9f6265dd6 --- /dev/null +++ b/docs/hi/docs/tutorial/cookie-params.md @@ -0,0 +1,45 @@ +# Cookie Parameters { #cookie-parameters } + +आप `Cookie` parameters को उसी तरह define कर सकते हैं जैसे आप `Query` और `Path` parameters define करते हैं। + +## `Cookie` import करें { #import-cookie } + +पहले `Cookie` import करें: + +{* ../../docs_src/cookie_params/tutorial001_an_py310.py hl[3] *} + +## `Cookie` parameters declare करें { #declare-cookie-parameters } + +फिर cookie parameters को `Path` और `Query` जैसी ही structure का उपयोग करके declare करें। + +आप default value के साथ-साथ सभी extra validation या annotation parameters भी define कर सकते हैं: + +{* ../../docs_src/cookie_params/tutorial001_an_py310.py hl[9] *} + +/// note | तकनीकी विवरण + +`Cookie`, `Path` और `Query` की एक "sister" class है। यह भी उसी common `Param` class से inherit करती है। + +लेकिन याद रखें कि जब आप `fastapi` से `Query`, `Path`, `Cookie` और अन्य चीज़ें import करते हैं, तो वे वास्तव में ऐसे functions होते हैं जो special classes return करते हैं। + +/// + +/// note | नोट + +Cookies declare करने के लिए, आपको `Cookie` का उपयोग करना होगा, क्योंकि अन्यथा parameters को query parameters के रूप में interpret किया जाएगा। + +/// + +/// note | नोट + +ध्यान रखें कि, क्योंकि **browsers cookies को** विशेष तरीकों से और पर्दे के पीछे handle करते हैं, वे **JavaScript** को उन्हें आसानी से access करने की अनुमति **नहीं** देते। + +यदि आप `/docs` पर **API docs UI** में जाते हैं, तो आप अपनी *path operations* के लिए cookies की **documentation** देख पाएँगे। + +लेकिन भले ही आप **data भरें** और "Execute" पर click करें, क्योंकि docs UI **JavaScript** के साथ काम करता है, cookies भेजी नहीं जाएँगी, और आपको ऐसा **error** message दिखेगा जैसे आपने कोई values लिखी ही नहीं हों। + +/// + +## Recap { #recap } + +`Query` और `Path` जैसे ही common pattern का उपयोग करके, `Cookie` के साथ cookies declare करें। diff --git a/docs/hi/docs/tutorial/cors.md b/docs/hi/docs/tutorial/cors.md new file mode 100644 index 000000000..cd707990c --- /dev/null +++ b/docs/hi/docs/tutorial/cors.md @@ -0,0 +1,89 @@ +# CORS (Cross-Origin Resource Sharing) { #cors-cross-origin-resource-sharing } + +[CORS या "Cross-Origin Resource Sharing"](https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS) उन स्थितियों को संदर्भित करता है जब browser में चल रहे frontend में JavaScript code होता है जो backend से communicate करता है, और backend frontend से अलग "origin" में होता है। + +## Origin { #origin } + +एक origin protocol (`http`, `https`), domain (`myapp.com`, `localhost`, `localhost.tiangolo.com`), और port (`80`, `443`, `8080`) का combination होता है। + +तो, ये सभी अलग-अलग origins हैं: + +* `http://localhost` +* `https://localhost` +* `http://localhost:8080` + +भले ही वे सभी `localhost` में हों, वे अलग-अलग protocols या ports का उपयोग करते हैं, इसलिए वे अलग-अलग "origins" हैं। + +## Steps { #steps } + +तो, मान लें कि आपके browser में `http://localhost:8080` पर एक frontend चल रहा है, और उसका JavaScript `http://localhost` पर चल रहे backend से communicate करने की कोशिश कर रहा है (क्योंकि हम port specify नहीं करते, browser default port `80` मान लेगा)। + +फिर, browser `:80`-backend को एक HTTP `OPTIONS` request भेजेगा, और अगर backend इस अलग origin (`http://localhost:8080`) से communication को authorize करने वाले उचित headers भेजता है, तो `:8080`-browser frontend में JavaScript को अपना request `:80`-backend को भेजने देगा। + +इसे हासिल करने के लिए, `:80`-backend के पास "allowed origins" की एक list होनी चाहिए। + +इस मामले में, `:8080`-frontend के सही ढंग से काम करने के लिए list में `http://localhost:8080` शामिल होना चाहिए। + +## Wildcards { #wildcards } + +यह भी possible है कि list को `"*"` (एक "wildcard") के रूप में declare किया जाए, यह बताने के लिए कि सभी allowed हैं। + +लेकिन यह केवल कुछ प्रकार के communication को allow करेगा, उन सभी चीज़ों को छोड़कर जिनमें credentials शामिल हैं: Cookies, Authorization headers जैसे कि Bearer Tokens के साथ उपयोग किए जाने वाले, आदि। + +इसलिए, सब कुछ सही ढंग से काम करे, इसके लिए allowed origins को स्पष्ट रूप से specify करना बेहतर है। + +## `CORSMiddleware` का उपयोग करें { #use-corsmiddleware } + +आप `CORSMiddleware` का उपयोग करके इसे अपनी **FastAPI** application में configure कर सकते हैं। + +* `CORSMiddleware` import करें। +* allowed origins की एक list बनाएँ (strings के रूप में)। +* इसे अपनी **FastAPI** application में "middleware" के रूप में जोड़ें। + +आप यह भी specify कर सकते हैं कि आपका backend allow करता है या नहीं: + +* Credentials (Authorization headers, Cookies, आदि)। +* Specific HTTP methods (`POST`, `PUT`) या wildcard `"*"` के साथ सभी methods। +* Specific HTTP headers या wildcard `"*"` के साथ सभी headers। + +{* ../../docs_src/cors/tutorial001_py310.py hl[2,6:11,13:19] *} + + +`CORSMiddleware` implementation द्वारा उपयोग किए जाने वाले default parameters default रूप से restrictive होते हैं, इसलिए browsers को Cross-Domain context में उनका उपयोग करने की permission देने के लिए आपको particular origins, methods, या headers को स्पष्ट रूप से enable करना होगा। + +निम्नलिखित arguments supported हैं: + +* `allow_origins` - origins की एक list जिन्हें cross-origin requests करने की permission होनी चाहिए। जैसे `['https://example.org', 'https://www.example.org']`। आप किसी भी origin को allow करने के लिए `['*']` का उपयोग कर सकते हैं। +* `allow_origin_regex` - origins के against match करने के लिए एक regex string जिन्हें cross-origin requests करने की permission होनी चाहिए। जैसे `'https://.*\.example\.org'`। +* `allow_methods` - HTTP methods की एक list जिन्हें cross-origin requests के लिए allowed होना चाहिए। Defaults to `['GET']`। आप सभी standard methods को allow करने के लिए `['*']` का उपयोग कर सकते हैं। +* `allow_headers` - HTTP request headers की एक list जिन्हें cross-origin requests के लिए supported होना चाहिए। Defaults to `[]`। आप सभी headers को allow करने के लिए `['*']` का उपयोग कर सकते हैं। `Accept`, `Accept-Language`, `Content-Language` और `Content-Type` headers हमेशा [simple CORS requests](https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS#simple_requests) के लिए allowed होते हैं। +* `allow_credentials` - indicate करता है कि cookies cross-origin requests के लिए supported होनी चाहिए। Defaults to `False`. + + अगर `allow_credentials` को `True` पर set किया गया है, तो `allow_origins`, `allow_methods` और `allow_headers` में से किसी को भी `['*']` पर set नहीं किया जा सकता। उन सभी को [explicitly specified](https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS#credentialed_requests_and_wildcards) होना चाहिए। + +* `expose_headers` - indicate करता है कि कौन से response headers browser के लिए accessible बनाए जाने चाहिए। Defaults to `[]`। +* `max_age` - browsers के लिए CORS responses को cache करने का maximum समय seconds में set करता है। Defaults to `600`। + +middleware दो particular प्रकार के HTTP request का response देता है... + +### CORS preflight requests { #cors-preflight-requests } + +ये `Origin` और `Access-Control-Request-Method` headers वाले कोई भी `OPTIONS` request होते हैं। + +इस मामले में middleware incoming request को intercept करेगा और appropriate CORS headers के साथ respond करेगा, और informational purposes के लिए या तो `200` या `400` response देगा। + +### Simple requests { #simple-requests } + +`Origin` header वाला कोई भी request। इस मामले में middleware request को सामान्य रूप से pass through करेगा, लेकिन response पर appropriate CORS headers शामिल करेगा। + +## अधिक जानकारी { #more-info } + +CORS के बारे में अधिक जानकारी के लिए, [Mozilla CORS documentation](https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS) देखें। + +/// note | तकनीकी विवरण + +आप `from starlette.middleware.cors import CORSMiddleware` का भी उपयोग कर सकते हैं। + +**FastAPI** आपकी सुविधा के लिए, developer के रूप में, `fastapi.middleware` में कई middlewares provide करता है। लेकिन available middlewares में से अधिकांश सीधे Starlette से आते हैं। + +/// diff --git a/docs/hi/docs/tutorial/debugging.md b/docs/hi/docs/tutorial/debugging.md new file mode 100644 index 000000000..0c214bb9a --- /dev/null +++ b/docs/hi/docs/tutorial/debugging.md @@ -0,0 +1,113 @@ +# Debugging { #debugging } + +आप अपने editor में debugger connect कर सकते हैं, उदाहरण के लिए Visual Studio Code या PyCharm के साथ। + +## `uvicorn` को call करें { #call-uvicorn } + +अपने FastAPI application में, `uvicorn` को सीधे import करके run करें: + +{* ../../docs_src/debugging/tutorial001_py310.py hl[1,15] *} + +### `__name__ == "__main__"` के बारे में { #about-name-main } + +`__name__ == "__main__"` का मुख्य उद्देश्य ऐसा कुछ code रखना है जो तब execute होता है जब आपकी file को इसके साथ call किया जाता है: + +
+ +```console +$ python myapp.py +``` + +
+ +लेकिन तब call नहीं होता जब कोई दूसरी file इसे import करती है, जैसे कि: + +```Python +from myapp import app +``` + +#### अधिक विवरण { #more-details } + +मान लीजिए आपकी file का नाम `myapp.py` है। + +अगर आप इसे इसके साथ run करते हैं: + +
+ +```console +$ python myapp.py +``` + +
+ +तो आपकी file में Python द्वारा अपने आप बनाई गई internal variable `__name__` का value string `"__main__"` होगा। + +तो, यह section: + +```Python + uvicorn.run(app, host="0.0.0.0", port=8000) +``` + +run होगा। + +--- + +अगर आप उस module (file) को import करते हैं तो ऐसा नहीं होगा। + +तो, अगर आपके पास `importer.py` नाम की कोई दूसरी file है जिसमें यह है: + +```Python +from myapp import app + +# कुछ और code +``` + +उस स्थिति में, `myapp.py` के अंदर अपने आप बनाई गई variable `__name__` का value `"__main__"` नहीं होगा। + +तो, यह line: + +```Python + uvicorn.run(app, host="0.0.0.0", port=8000) +``` + +execute नहीं होगी। + +/// note | नोट + +अधिक जानकारी के लिए, [आधिकारिक Python docs](https://docs.python.org/3/library/__main__.html) देखें। + +/// + +## अपने debugger के साथ अपना code run करें { #run-your-code-with-your-debugger } + +क्योंकि आप Uvicorn server को सीधे अपने code से run कर रहे हैं, आप अपने Python program (अपने FastAPI application) को सीधे debugger से call कर सकते हैं। + +--- + +उदाहरण के लिए, Visual Studio Code में, आप यह कर सकते हैं: + +* "Debug" panel पर जाएँ। +* "Add configuration..."। +* "Python" चुनें। +* "`Python: Current File (Integrated Terminal)`" option के साथ debugger run करें। + +फिर यह आपके **FastAPI** code के साथ server start करेगा, आपके breakpoints पर रुकेगा, आदि। + +यह कुछ ऐसा दिख सकता है: + + + +--- + +अगर आप PyCharm का उपयोग करते हैं, तो आप यह कर सकते हैं: + +* "Run" menu खोलें। +* "Debug..." option चुनें। +* फिर एक context menu दिखाई देता है। +* debug करने के लिए file चुनें (इस मामले में, `main.py`)। + +फिर यह आपके **FastAPI** code के साथ server start करेगा, आपके breakpoints पर रुकेगा, आदि। + +यह कुछ ऐसा दिख सकता है: + + diff --git a/docs/hi/docs/tutorial/dependencies/classes-as-dependencies.md b/docs/hi/docs/tutorial/dependencies/classes-as-dependencies.md new file mode 100644 index 000000000..0d166e7ea --- /dev/null +++ b/docs/hi/docs/tutorial/dependencies/classes-as-dependencies.md @@ -0,0 +1,288 @@ +# Dependencies के रूप में Classes { #classes-as-dependencies } + +**Dependency Injection** system में और गहराई में जाने से पहले, पिछले उदाहरण को बेहतर बनाते हैं। + +## पिछले उदाहरण से एक `dict` { #a-dict-from-the-previous-example } + +पिछले उदाहरण में, हम अपनी dependency ("dependable") से एक `dict` return कर रहे थे: + +{* ../../docs_src/dependencies/tutorial001_an_py310.py hl[9] *} + +लेकिन फिर हमें *path operation function* के parameter `commons` में एक `dict` मिलता है। + +और हम जानते हैं कि editors `dict`s के लिए ज़्यादा support (जैसे completion) नहीं दे सकते, क्योंकि वे उनकी keys और value types नहीं जान सकते। + +हम इससे बेहतर कर सकते हैं... + +## Dependency किससे बनती है { #what-makes-a-dependency } + +अब तक आपने dependencies को functions के रूप में declare होते देखा है। + +लेकिन dependencies declare करने का यही एकमात्र तरीका नहीं है (हालाँकि शायद यह अधिक common होगा)। + +मुख्य बात यह है कि dependency एक "callable" होनी चाहिए। + +Python में "**callable**" वह कोई भी चीज़ है जिसे Python एक function की तरह "call" कर सकता है। + +तो, अगर आपके पास कोई object `something` है (जो शायद function _न_ हो) और आप उसे इस तरह "call" (execute) कर सकते हैं: + +```Python +something() +``` + +या + +```Python +something(some_argument, some_keyword_argument="foo") +``` + +तो वह एक "callable" है। + +## Dependencies के रूप में Classes { #classes-as-dependencies_1 } + +आप ध्यान दे सकते हैं कि Python class का instance बनाने के लिए भी आप वही syntax उपयोग करते हैं। + +उदाहरण के लिए: + +```Python +class Cat: + def __init__(self, name: str): + self.name = name + + +fluffy = Cat(name="Mr Fluffy") +``` + +इस case में, `fluffy` class `Cat` का एक instance है। + +और `fluffy` बनाने के लिए, आप `Cat` को "call" कर रहे हैं। + +इसलिए, Python class भी एक **callable** है। + +फिर, **FastAPI** में, आप Python class को dependency के रूप में उपयोग कर सकते हैं। + +FastAPI वास्तव में यह check करता है कि वह एक "callable" (function, class या कुछ और) है और उसमें parameters defined हैं। + +अगर आप **FastAPI** में dependency के रूप में कोई "callable" pass करते हैं, तो यह उस "callable" के parameters को analyze करेगा, और उन्हें *path operation function* के parameters की तरह ही process करेगा। इसमें sub-dependencies भी शामिल हैं। + +यह उन callables पर भी लागू होता है जिनमें कोई parameters नहीं होते। ठीक वैसे ही जैसे बिना parameters वाले *path operation functions* के लिए होता। + +फिर, हम ऊपर वाली dependency "dependable" `common_parameters` को class `CommonQueryParams` में बदल सकते हैं: + +{* ../../docs_src/dependencies/tutorial002_an_py310.py hl[11:15] *} + +Class का instance बनाने के लिए उपयोग की गई `__init__` method पर ध्यान दें: + +{* ../../docs_src/dependencies/tutorial002_an_py310.py hl[12] *} + +...इसमें वही parameters हैं जो हमारे पिछले `common_parameters` में थे: + +{* ../../docs_src/dependencies/tutorial001_an_py310.py hl[8] *} + +यही parameters **FastAPI** dependency को "solve" करने के लिए उपयोग करेगा। + +दोनों cases में, इसमें होगा: + +* एक optional `q` query parameter जो `str` है। +* एक `skip` query parameter जो `int` है, जिसका default `0` है। +* एक `limit` query parameter जो `int` है, जिसका default `100` है। + +दोनों cases में data converted, validated, OpenAPI schema पर documented, आदि किया जाएगा। + +## इसका उपयोग करें { #use-it } + +अब आप इस class का उपयोग करके अपनी dependency declare कर सकते हैं। + +{* ../../docs_src/dependencies/tutorial002_an_py310.py hl[19] *} + +**FastAPI** `CommonQueryParams` class को call करता है। यह उस class का एक "instance" बनाता है और वह instance आपके function को parameter `commons` के रूप में pass किया जाएगा। + +## Type annotation बनाम `Depends` { #type-annotation-vs-depends } + +ध्यान दें कि ऊपर के code में हम `CommonQueryParams` को दो बार कैसे लिखते हैं: + +//// tab | Python 3.10+ + +```Python +commons: Annotated[CommonQueryParams, Depends(CommonQueryParams)] +``` + +//// + +//// tab | Python 3.10+ non-Annotated + +/// tip | सुझाव + +संभव हो तो `Annotated` version का उपयोग करना बेहतर है। + +/// + +```Python +commons: CommonQueryParams = Depends(CommonQueryParams) +``` + +//// + +आखिरी `CommonQueryParams`, इसमें: + +```Python +... Depends(CommonQueryParams) +``` + +...वही है जिसे **FastAPI** वास्तव में यह जानने के लिए उपयोग करेगा कि dependency क्या है। + +FastAPI इसी से declared parameters extract करेगा और वास्तव में इसी को call करेगा। + +--- + +इस case में, पहला `CommonQueryParams`, इसमें: + +//// tab | Python 3.10+ + +```Python +commons: Annotated[CommonQueryParams, ... +``` + +//// + +//// tab | Python 3.10+ non-Annotated + +/// tip | सुझाव + +संभव हो तो `Annotated` version का उपयोग करना बेहतर है। + +/// + +```Python +commons: CommonQueryParams ... +``` + +//// + +...का **FastAPI** के लिए कोई विशेष अर्थ नहीं है। FastAPI इसे data conversion, validation, आदि के लिए उपयोग नहीं करेगा। (क्योंकि वह इसके लिए `Depends(CommonQueryParams)` का उपयोग कर रहा है)। + +आप वास्तव में सिर्फ यह लिख सकते हैं: + +//// tab | Python 3.10+ + +```Python +commons: Annotated[Any, Depends(CommonQueryParams)] +``` + +//// + +//// tab | Python 3.10+ non-Annotated + +/// tip | सुझाव + +संभव हो तो `Annotated` version का उपयोग करना बेहतर है। + +/// + +```Python +commons = Depends(CommonQueryParams) +``` + +//// + +...जैसे: + +{* ../../docs_src/dependencies/tutorial003_an_py310.py hl[19] *} + +लेकिन type declare करने को प्रोत्साहित किया जाता है क्योंकि इस तरह आपका editor जान पाएगा कि parameter `commons` के रूप में क्या pass होगा, और फिर यह code completion, type checks, आदि में आपकी मदद कर सकता है: + + + +## Shortcut { #shortcut } + +लेकिन आप देखते हैं कि यहाँ कुछ code repetition हो रहा है, `CommonQueryParams` को दो बार लिखते हुए: + +//// tab | Python 3.10+ + +```Python +commons: Annotated[CommonQueryParams, Depends(CommonQueryParams)] +``` + +//// + +//// tab | Python 3.10+ non-Annotated + +/// tip | सुझाव + +संभव हो तो `Annotated` version का उपयोग करना बेहतर है। + +/// + +```Python +commons: CommonQueryParams = Depends(CommonQueryParams) +``` + +//// + +**FastAPI** ऐसे cases के लिए एक shortcut प्रदान करता है, जहाँ dependency *specifically* एक class है जिसे **FastAPI** class का instance बनाने के लिए "call" करेगा। + +उन specific cases के लिए, आप यह कर सकते हैं: + +यह लिखने के बजाय: + +//// tab | Python 3.10+ + +```Python +commons: Annotated[CommonQueryParams, Depends(CommonQueryParams)] +``` + +//// + +//// tab | Python 3.10+ non-Annotated + +/// tip | सुझाव + +संभव हो तो `Annotated` version का उपयोग करना बेहतर है। + +/// + +```Python +commons: CommonQueryParams = Depends(CommonQueryParams) +``` + +//// + +...आप लिखते हैं: + +//// tab | Python 3.10+ + +```Python +commons: Annotated[CommonQueryParams, Depends()] +``` + +//// + +//// tab | Python 3.10+ non-Annotated + +/// tip | सुझाव + +संभव हो तो `Annotated` version का उपयोग करना बेहतर है। + +/// + +```Python +commons: CommonQueryParams = Depends() +``` + +//// + +आप dependency को parameter के type के रूप में declare करते हैं, और `Depends(CommonQueryParams)` के अंदर पूरी class को *फिर से* लिखने के बजाय, आप बिना किसी parameter के `Depends()` का उपयोग करते हैं। + +फिर वही उदाहरण इस तरह दिखेगा: + +{* ../../docs_src/dependencies/tutorial004_an_py310.py hl[19] *} + +...और **FastAPI** जान जाएगा कि क्या करना है। + +/// tip | सुझाव + +अगर यह मददगार से ज़्यादा confusing लगता है, तो इसे अनदेखा करें, आपको इसकी *ज़रूरत* नहीं है। + +यह सिर्फ एक shortcut है। क्योंकि **FastAPI** आपको code repetition कम करने में मदद करने की परवाह करता है। + +/// diff --git a/docs/hi/docs/tutorial/dependencies/dependencies-in-path-operation-decorators.md b/docs/hi/docs/tutorial/dependencies/dependencies-in-path-operation-decorators.md new file mode 100644 index 000000000..6e051ef5d --- /dev/null +++ b/docs/hi/docs/tutorial/dependencies/dependencies-in-path-operation-decorators.md @@ -0,0 +1,69 @@ +# path operation decorators में Dependencies { #dependencies-in-path-operation-decorators } + +कुछ मामलों में आपको अपनी *path operation function* के अंदर किसी dependency की return value की वास्तव में ज़रूरत नहीं होती। + +या dependency कोई value return नहीं करती। + +लेकिन फिर भी आपको उसका execute/solve होना चाहिए। + +ऐसे मामलों के लिए, `Depends` के साथ *path operation function* parameter declare करने के बजाय, आप *path operation decorator* में `dependencies` की एक `list` जोड़ सकते हैं। + +## *path operation decorator* में `dependencies` जोड़ें { #add-dependencies-to-the-path-operation-decorator } + +*path operation decorator* एक optional argument `dependencies` प्राप्त करता है। + +यह `Depends()` की एक `list` होनी चाहिए: + +{* ../../docs_src/dependencies/tutorial006_an_py310.py hl[19] *} + +ये dependencies normal dependencies की तरह ही execute/solve होंगी। लेकिन उनकी value (यदि वे कोई return करती हैं) आपकी *path operation function* को pass नहीं की जाएगी। + +/// tip | सुझाव + +कुछ editors unused function parameters की जाँच करते हैं, और उन्हें errors के रूप में दिखाते हैं। + +*path operation decorator* में इन `dependencies` का उपयोग करके आप सुनिश्चित कर सकते हैं कि वे execute हों, साथ ही editor/tooling errors से बच सकें। + +यह नए developers के लिए भ्रम से बचने में भी मदद कर सकता है, जो आपके code में unused parameter देखकर सोच सकते हैं कि यह अनावश्यक है। + +/// + +/// note | नोट + +इस example में हम बनाए गए custom headers `X-Key` और `X-Token` का उपयोग करते हैं। + +लेकिन वास्तविक मामलों में, security implement करते समय, आपको integrated [Security utilities (अगला अध्याय)](../security/index.md) का उपयोग करने से अधिक लाभ मिलेंगे। + +/// + +## Dependencies errors और return values { #dependencies-errors-and-return-values } + +आप वही dependency *functions* उपयोग कर सकते हैं जिन्हें आप सामान्य रूप से उपयोग करते हैं। + +### Dependency requirements { #dependency-requirements } + +वे request requirements (जैसे headers) या अन्य sub-dependencies declare कर सकती हैं: + +{* ../../docs_src/dependencies/tutorial006_an_py310.py hl[8,13] *} + +### Exceptions raise करें { #raise-exceptions } + +ये dependencies normal dependencies की तरह ही exceptions `raise` कर सकती हैं: + +{* ../../docs_src/dependencies/tutorial006_an_py310.py hl[10,15] *} + +### Return values { #return-values } + +और वे values return कर सकती हैं या नहीं भी कर सकतीं, values का उपयोग नहीं किया जाएगा। + +इसलिए, आप एक normal dependency (जो value return करती है) को फिर से उपयोग कर सकते हैं जिसे आप पहले से कहीं और उपयोग करते हैं, और भले ही value का उपयोग न हो, dependency execute होगी: + +{* ../../docs_src/dependencies/tutorial006_an_py310.py hl[11,16] *} + +## *path operations* के समूह के लिए Dependencies { #dependencies-for-a-group-of-path-operations } + +बाद में, जब आप बड़े applications को structure करने के बारे में पढ़ेंगे ([बड़े Applications - कई Files](../../tutorial/bigger-applications.md)), संभवतः कई files के साथ, तो आप सीखेंगे कि *path operations* के समूह के लिए एक ही `dependencies` parameter कैसे declare किया जाए। + +## Global Dependencies { #global-dependencies } + +आगे हम देखेंगे कि पूरे `FastAPI` application में dependencies कैसे जोड़ी जाएँ, ताकि वे हर *path operation* पर लागू हों। diff --git a/docs/hi/docs/tutorial/dependencies/dependencies-with-yield.md b/docs/hi/docs/tutorial/dependencies/dependencies-with-yield.md new file mode 100644 index 000000000..e85d7401a --- /dev/null +++ b/docs/hi/docs/tutorial/dependencies/dependencies-with-yield.md @@ -0,0 +1,289 @@ +# `yield` वाली Dependencies { #dependencies-with-yield } + +FastAPI ऐसी dependencies को support करता है जो पूरा होने के बाद अतिरिक्त steps करती हैं। + +ऐसा करने के लिए, `return` की जगह `yield` का उपयोग करें, और अतिरिक्त steps (code) उसके बाद लिखें। + +/// tip | सुझाव + +हर dependency में `yield` का उपयोग केवल एक बार करना सुनिश्चित करें। + +/// + +/// note | तकनीकी विवरण + +कोई भी function जो इनके साथ उपयोग करने के लिए valid है: + +* [`@contextlib.contextmanager`](https://docs.python.org/3/library/contextlib.html#contextlib.contextmanager) या +* [`@contextlib.asynccontextmanager`](https://docs.python.org/3/library/contextlib.html#contextlib.asynccontextmanager) + +वह **FastAPI** dependency के रूप में उपयोग करने के लिए valid होगी। + +वास्तव में, FastAPI internally इन दोनों decorators का उपयोग करता है। + +/// + +## `yield` वाली database dependency { #a-database-dependency-with-yield } + +उदाहरण के लिए, आप इसका उपयोग database session बनाने और पूरा होने के बाद उसे close करने के लिए कर सकते हैं। + +`yield` statement से पहले और उसे शामिल करते हुए केवल वही code response बनाने से पहले execute होता है: + +{* ../../docs_src/dependencies/tutorial007_py310.py hl[2:4] *} + +yield किया गया value वही होता है जिसे *path operations* और अन्य dependencies में inject किया जाता है: + +{* ../../docs_src/dependencies/tutorial007_py310.py hl[4] *} + +`yield` statement के बाद वाला code response के बाद execute होता है: + +{* ../../docs_src/dependencies/tutorial007_py310.py hl[5:6] *} + +/// tip | सुझाव + +आप `async` या regular functions का उपयोग कर सकते हैं। + +**FastAPI** हर एक के साथ सही काम करेगा, ठीक normal dependencies की तरह। + +/// + +## `yield` और `try` वाली dependency { #a-dependency-with-yield-and-try } + +अगर आप `yield` वाली dependency में `try` block का उपयोग करते हैं, तो dependency का उपयोग करते समय throw की गई कोई भी exception आपको मिलेगी। + +उदाहरण के लिए, अगर बीच में किसी point पर, किसी दूसरी dependency में या किसी *path operation* में, कुछ code ने database transaction को "rollback" किया या कोई अन्य exception बनाई, तो आपको अपनी dependency में वह exception मिलेगी। + +इसलिए, आप `except SomeException` के साथ dependency के अंदर उस specific exception को देख सकते हैं। + +इसी तरह, आप `finally` का उपयोग यह सुनिश्चित करने के लिए कर सकते हैं कि exit steps execute हों, चाहे exception आई हो या नहीं। + +{* ../../docs_src/dependencies/tutorial007_py310.py hl[3,5] *} + +## `yield` वाली Sub-dependencies { #sub-dependencies-with-yield } + +आपके पास किसी भी size और shape की sub-dependencies और sub-dependencies के "trees" हो सकते हैं, और उनमें से कोई भी या सभी `yield` का उपयोग कर सकती हैं। + +**FastAPI** यह सुनिश्चित करेगा कि `yield` वाली हर dependency में "exit code" सही क्रम में run हो। + +उदाहरण के लिए, `dependency_c` की dependency `dependency_b` पर हो सकती है, और `dependency_b` की `dependency_a` पर: + +{* ../../docs_src/dependencies/tutorial008_an_py310.py hl[6,14,22] *} + +और वे सभी `yield` का उपयोग कर सकती हैं। + +इस case में `dependency_c` को अपना exit code execute करने के लिए `dependency_b` से मिला value (यहाँ `dep_b` नाम दिया गया है) अभी भी उपलब्ध चाहिए। + +और, बदले में, `dependency_b` को अपने exit code के लिए `dependency_a` से मिला value (यहाँ `dep_a` नाम दिया गया है) उपलब्ध चाहिए। + +{* ../../docs_src/dependencies/tutorial008_an_py310.py hl[18:19,26:27] *} + +इसी तरह, आपके पास कुछ dependencies `yield` वाली और कुछ अन्य dependencies `return` वाली हो सकती हैं, और उनमें से कुछ बाकी कुछ पर depend कर सकती हैं। + +और आपके पास एक single dependency हो सकती है जिसे `yield` वाली कई अन्य dependencies required हों, आदि। + +आप dependencies के कोई भी combinations रख सकते हैं। + +**FastAPI** यह सुनिश्चित करेगा कि सब कुछ सही क्रम में run हो। + +/// note | तकनीकी विवरण + +यह Python के [Context Managers](https://docs.python.org/3/library/contextlib.html) की वजह से काम करता है। + +**FastAPI** इसे हासिल करने के लिए internally उनका उपयोग करता है। + +/// + +## `yield` और `HTTPException` वाली Dependencies { #dependencies-with-yield-and-httpexception } + +आपने देखा कि आप `yield` वाली dependencies का उपयोग कर सकते हैं और ऐसे `try` blocks रख सकते हैं जो कुछ code execute करने की कोशिश करते हैं और फिर `finally` के बाद कुछ exit code run करते हैं। + +आप raise की गई exception को catch करने और उसके साथ कुछ करने के लिए `except` का भी उपयोग कर सकते हैं। + +उदाहरण के लिए, आप कोई अलग exception raise कर सकते हैं, जैसे `HTTPException`। + +/// tip | सुझाव + +यह थोड़ी advanced technique है, और ज्यादातर cases में आपको वास्तव में इसकी ज़रूरत नहीं होगी, क्योंकि आप अपने application code के बाकी हिस्से के अंदर से exceptions (जिसमें `HTTPException` भी शामिल है) raise कर सकते हैं, उदाहरण के लिए, *path operation function* में। + +लेकिन अगर आपको इसकी ज़रूरत हो तो यह उपलब्ध है। 🤓 + +/// + +{* ../../docs_src/dependencies/tutorial008b_an_py310.py hl[18:22,31] *} + +अगर आप exceptions को catch करके उसके आधार पर custom response बनाना चाहते हैं, तो [Custom Exception Handler](../handling-errors.md#install-custom-exception-handlers) बनाएँ। + +## `yield` और `except` वाली Dependencies { #dependencies-with-yield-and-except } + +अगर आप `yield` वाली dependency में `except` का उपयोग करके exception catch करते हैं और उसे फिर से raise नहीं करते (या कोई नई exception raise नहीं करते), तो FastAPI यह notice नहीं कर पाएगा कि कोई exception हुई थी, ठीक वैसे ही जैसे regular Python में होता: + +{* ../../docs_src/dependencies/tutorial008c_an_py310.py hl[15:16] *} + +इस case में, client को *HTTP 500 Internal Server Error* response दिखेगा, जैसा कि होना चाहिए, क्योंकि हम `HTTPException` या उसके जैसी कोई चीज़ raise नहीं कर रहे हैं, लेकिन server के पास **कोई logs नहीं होंगे** या error क्या था इसका कोई अन्य संकेत नहीं होगा। 😱 + +### `yield` और `except` वाली Dependencies में हमेशा `raise` करें { #always-raise-in-dependencies-with-yield-and-except } + +अगर आप `yield` वाली dependency में exception catch करते हैं, तो जब तक आप कोई दूसरी `HTTPException` या similar चीज़ raise नहीं कर रहे हैं, **आपको original exception को फिर से raise करना चाहिए**। + +आप `raise` का उपयोग करके उसी exception को फिर से raise कर सकते हैं: + +{* ../../docs_src/dependencies/tutorial008d_an_py310.py hl[17] *} + +अब client को वही *HTTP 500 Internal Server Error* response मिलेगा, लेकिन server के logs में हमारा custom `InternalError` होगा। 😎 + +## `yield` वाली dependencies का Execution { #execution-of-dependencies-with-yield } + +Execution का sequence कमोबेश इस diagram जैसा है। Time ऊपर से नीचे की ओर चलता है। और हर column code के साथ interact करने या execute करने वाले parts में से एक है। + +```mermaid +sequenceDiagram + +participant client as Client +participant handler as Exception handler +participant dep as Dep with yield +participant operation as Path Operation +participant tasks as Background tasks + + Note over client,operation: Can raise exceptions, including HTTPException + client ->> dep: Start request + Note over dep: Run code up to yield + opt raise Exception + dep -->> handler: Raise Exception + handler -->> client: HTTP error response + end + dep ->> operation: Run dependency, e.g. DB session + opt raise + operation -->> dep: Raise Exception (e.g. HTTPException) + opt handle + dep -->> dep: Can catch exception, raise a new HTTPException, raise other exception + end + handler -->> client: HTTP error response + end + + operation ->> client: Return response to client + Note over client,operation: Response is already sent, can't change it anymore + opt Tasks + operation -->> tasks: Send background tasks + end + opt Raise other exception + tasks -->> tasks: Handle exceptions in the background task code + end +``` + +/// note | नोट + +Client को केवल **एक response** भेजा जाएगा। यह error responses में से एक हो सकता है या *path operation* से आया response होगा। + +उन responses में से एक भेजे जाने के बाद, कोई अन्य response नहीं भेजा जा सकता। + +/// + +/// tip | सुझाव + +अगर आप *path operation function* के code में कोई भी exception raise करते हैं, तो उसे yield वाली dependencies को pass किया जाएगा, जिसमें `HTTPException` भी शामिल है। ज्यादातर cases में आप चाहेंगे कि `yield` वाली dependency से वही exception या कोई नई exception फिर से raise करें ताकि यह सुनिश्चित हो सके कि उसे सही तरीके से handle किया गया है। + +/// + +## Early exit और `scope` { #early-exit-and-scope } + +आम तौर पर `yield` वाली dependencies का exit code client को **response** भेजे जाने के बाद execute होता है। + +लेकिन अगर आपको पता है कि *path operation function* से return करने के बाद आपको dependency का उपयोग करने की ज़रूरत नहीं होगी, तो आप `Depends(scope="function")` का उपयोग करके FastAPI को बता सकते हैं कि उसे dependency को *path operation function* के return करने के बाद, लेकिन **response भेजे जाने से पहले** close करना चाहिए। + +{* ../../docs_src/dependencies/tutorial008e_an_py310.py hl[12,16] *} + +`Depends()` एक `scope` parameter receive करता है जो यह हो सकता है: + +* `"function"`: request handle करने वाले *path operation function* से पहले dependency शुरू करें, *path operation function* खत्म होने के बाद dependency खत्म करें, लेकिन client को response वापस भेजे जाने से **पहले**। यानी, dependency function *path operation **function*** के **around** execute होगा। +* `"request"`: request handle करने वाले *path operation function* से पहले dependency शुरू करें (`"function"` उपयोग करने जैसा), लेकिन client को response वापस भेजे जाने के **बाद** खत्म करें। यानी, dependency function **request** और response cycle के **around** execute होगा। + +अगर specify नहीं किया गया है और dependency में `yield` है, तो उसका `scope` default रूप से `"request"` होगा। + +### Sub-dependencies के लिए `scope` { #scope-for-sub-dependencies } + +जब आप `scope="request"` (default) वाली dependency declare करते हैं, तो किसी भी sub-dependency का `scope` भी `"request"` होना चाहिए। + +लेकिन `"function"` के `scope` वाली dependency के पास `"function"` और `"request"` scope वाली dependencies हो सकती हैं। + +ऐसा इसलिए है क्योंकि किसी भी dependency को sub-dependencies से पहले अपना exit code run करने में सक्षम होना चाहिए, क्योंकि उसे अपने exit code के दौरान अभी भी उनका उपयोग करने की ज़रूरत हो सकती है। + +```mermaid +sequenceDiagram + +participant client as Client +participant dep_req as Dep scope="request" +participant dep_func as Dep scope="function" +participant operation as Path Operation + + client ->> dep_req: Start request + Note over dep_req: Run code up to yield + dep_req ->> dep_func: Pass dependency + Note over dep_func: Run code up to yield + dep_func ->> operation: Run path operation with dependency + operation ->> dep_func: Return from path operation + Note over dep_func: Run code after yield + Note over dep_func: ✅ Dependency closed + dep_func ->> client: Send response to client + Note over client: Response sent + Note over dep_req: Run code after yield + Note over dep_req: ✅ Dependency closed +``` + +## `yield`, `HTTPException`, `except` और Background Tasks वाली Dependencies { #dependencies-with-yield-httpexception-except-and-background-tasks } + +`yield` वाली Dependencies समय के साथ अलग-अलग use cases cover करने और कुछ issues fix करने के लिए evolve हुई हैं। + +अगर आप देखना चाहते हैं कि FastAPI के अलग-अलग versions में क्या बदला है, तो आप इसके बारे में advanced guide में, [Advanced Dependencies - `yield`, `HTTPException`, `except` और Background Tasks वाली Dependencies](../../advanced/advanced-dependencies.md#dependencies-with-yield-httpexception-except-and-background-tasks) में और पढ़ सकते हैं। + +## Context Managers { #context-managers } + +### "Context Managers" क्या हैं { #what-are-context-managers } + +"Context Managers" उन Python objects में से कोई भी हैं जिनका उपयोग आप `with` statement में कर सकते हैं। + +उदाहरण के लिए, [आप file पढ़ने के लिए `with` का उपयोग कर सकते हैं](https://docs.python.org/3/tutorial/inputoutput.html#reading-and-writing-files): + +```Python +with open("./somefile.txt") as f: + contents = f.read() + print(contents) +``` + +अंदर से, `open("./somefile.txt")` एक object बनाता है जिसे "Context Manager" कहा जाता है। + +जब `with` block खत्म होता है, तो यह file को close करना सुनिश्चित करता है, भले ही exceptions आई हों। + +जब आप `yield` वाली dependency बनाते हैं, तो **FastAPI** internally उसके लिए एक context manager बनाएगा, और उसे कुछ अन्य related tools के साथ combine करेगा। + +### `yield` वाली dependencies में context managers का उपयोग करना { #using-context-managers-in-dependencies-with-yield } + +/// warning | चेतावनी + +यह कमोबेश एक "advanced" idea है। + +अगर आप अभी **FastAPI** शुरू ही कर रहे हैं, तो शायद आप इसे अभी skip करना चाहेंगे। + +/// + +Python में, आप [दो methods वाली class बनाकर: `__enter__()` और `__exit__()`](https://docs.python.org/3/reference/datamodel.html#context-managers) Context Managers बना सकते हैं। + +आप dependency function के अंदर `with` या `async with` statements का उपयोग करके इन्हें `yield` वाली **FastAPI** dependencies के अंदर भी उपयोग कर सकते हैं: + +{* ../../docs_src/dependencies/tutorial010_py310.py hl[1:9,13] *} + +/// tip | सुझाव + +Context manager बनाने का एक और तरीका है: + +* [`@contextlib.contextmanager`](https://docs.python.org/3/library/contextlib.html#contextlib.contextmanager) या +* [`@contextlib.asynccontextmanager`](https://docs.python.org/3/library/contextlib.html#contextlib.asynccontextmanager) + +इनका उपयोग single `yield` वाले function को decorate करने के लिए करना। + +**FastAPI** internally `yield` वाली dependencies के लिए यही उपयोग करता है। + +लेकिन आपको FastAPI dependencies के लिए decorators का उपयोग करने की ज़रूरत नहीं है (और आपको नहीं करना चाहिए)। + +FastAPI internally आपके लिए यह कर देगा। + +/// diff --git a/docs/hi/docs/tutorial/dependencies/global-dependencies.md b/docs/hi/docs/tutorial/dependencies/global-dependencies.md new file mode 100644 index 000000000..e313b40f0 --- /dev/null +++ b/docs/hi/docs/tutorial/dependencies/global-dependencies.md @@ -0,0 +1,16 @@ +# वैश्विक Dependencies { #global-dependencies } + +कुछ प्रकार के applications के लिए आप पूरे application में dependencies जोड़ना चाह सकते हैं। + +जिस तरह आप [*path operation decorators* में `dependencies` जोड़ सकते हैं](dependencies-in-path-operation-decorators.md), उसी तरह आप उन्हें `FastAPI` application में भी जोड़ सकते हैं। + +उस स्थिति में, वे application की सभी *path operations* पर लागू होंगी: + +{* ../../docs_src/dependencies/tutorial012_an_py310.py hl[17] *} + + +और [*path operation decorators* में `dependencies` जोड़ने](dependencies-in-path-operation-decorators.md) वाले section की सभी बातें अभी भी लागू होती हैं, लेकिन इस मामले में, app की सभी *path operations* पर। + +## *path operations* के समूहों के लिए Dependencies { #dependencies-for-groups-of-path-operations } + +बाद में, जब आप बड़े applications को संरचित करने के तरीके के बारे में पढ़ेंगे ([बड़े Applications - कई Files](../../tutorial/bigger-applications.md)), संभवतः कई files के साथ, तो आप सीखेंगे कि *path operations* के एक समूह के लिए एक ही `dependencies` parameter कैसे declare किया जाए। diff --git a/docs/hi/docs/tutorial/dependencies/index.md b/docs/hi/docs/tutorial/dependencies/index.md new file mode 100644 index 000000000..903e43391 --- /dev/null +++ b/docs/hi/docs/tutorial/dependencies/index.md @@ -0,0 +1,250 @@ +# Dependencies { #dependencies } + +**FastAPI** में एक बहुत शक्तिशाली लेकिन सहज **Dependency Injection** system है। + +इसे उपयोग में बहुत सरल होने के लिए, और किसी भी developer के लिए दूसरे components को **FastAPI** के साथ integrate करना बहुत आसान बनाने के लिए design किया गया है। + +## "Dependency Injection" क्या है { #what-is-dependency-injection } + +**"Dependency Injection"** का मतलब programming में यह है कि आपके code (इस मामले में, आपके *path operation functions*) के पास यह declare करने का एक तरीका होता है कि उसे काम करने और उपयोग करने के लिए किन चीज़ों की ज़रूरत है: "dependencies"। + +और फिर, वह system (इस मामले में **FastAPI**) आपके code को वे ज़रूरी dependencies उपलब्ध कराने के लिए जो भी required है, उसका ध्यान रखेगा (dependencies को "inject" करेगा)। + +यह तब बहुत उपयोगी होता है जब आपको: + +* shared logic चाहिए (वही code logic बार-बार)। +* database connections share करने हों। +* security, authentication, role requirements, आदि enforce करने हों। +* और भी कई चीज़ें... + +ये सब, code repetition को कम से कम रखते हुए। + +## पहले कदम { #first-steps } + +आइए एक बहुत सरल उदाहरण देखते हैं। यह इतना सरल होगा कि अभी के लिए बहुत उपयोगी नहीं है। + +लेकिन इस तरह हम इस बात पर focus कर सकते हैं कि **Dependency Injection** system कैसे काम करता है। + +### एक dependency, या "dependable" बनाएँ { #create-a-dependency-or-dependable } + +पहले dependency पर focus करते हैं। + +यह बस एक function है जो वे सभी समान parameters ले सकता है जो एक *path operation function* ले सकता है: + +{* ../../docs_src/dependencies/tutorial001_an_py310.py hl[8:9] *} + +बस इतना ही। + +**2 lines**। + +और इसका shape और structure वही है जो आपके सभी *path operation functions* का होता है। + +आप इसे "decorator" के बिना एक *path operation function* के रूप में सोच सकते हैं (`@app.get("/some-path")` के बिना)। + +और यह आपकी इच्छा के अनुसार कुछ भी return कर सकता है। + +इस मामले में, यह dependency अपेक्षा करती है: + +* एक optional query parameter `q` जो `str` है। +* एक optional query parameter `skip` जो `int` है, और default रूप से `0` है। +* एक optional query parameter `limit` जो `int` है, और default रूप से `100` है। + +और फिर यह बस उन values वाला एक `dict` return करता है। + +/// note | नोट + +FastAPI ने version 0.95.0 में `Annotated` के लिए support जोड़ा (और इसे recommend करना शुरू किया)। + +अगर आपके पास पुराना version है, तो `Annotated` का उपयोग करने की कोशिश करते समय आपको errors मिलेंगे। + +`Annotated` का उपयोग करने से पहले सुनिश्चित करें कि आप [FastAPI version को Upgrade](../../deployment/versions.md#upgrading-the-fastapi-versions) करके कम से कम 0.95.1 कर लें। + +/// + +### `Depends` import करें { #import-depends } + +{* ../../docs_src/dependencies/tutorial001_an_py310.py hl[3] *} + +### "dependant" में dependency declare करें { #declare-the-dependency-in-the-dependant } + +जिस तरह आप अपने *path operation function* parameters के साथ `Body`, `Query`, आदि का उपयोग करते हैं, उसी तरह एक नए parameter के साथ `Depends` का उपयोग करें: + +{* ../../docs_src/dependencies/tutorial001_an_py310.py hl[13,18] *} + +हालाँकि आप अपने function के parameters में `Depends` का उपयोग उसी तरह करते हैं जैसे आप `Body`, `Query`, आदि का उपयोग करते हैं, `Depends` थोड़ा अलग तरीके से काम करता है। + +आप `Depends` को केवल एक parameter देते हैं। + +यह parameter किसी function जैसा होना चाहिए। + +आप इसे सीधे **call नहीं करते** (अंत में parentheses नहीं जोड़ते), आप बस इसे `Depends()` को एक parameter के रूप में pass करते हैं। + +और वह function उसी तरह parameters लेता है जैसे *path operation functions* लेते हैं। + +/// tip | सुझाव + +अगले chapter में आप देखेंगे कि functions के अलावा कौन सी दूसरी "चीज़ें" dependencies के रूप में उपयोग की जा सकती हैं। + +/// + +जब भी कोई नया request आता है, **FastAPI** इन बातों का ध्यान रखेगा: + +* आपकी dependency ("dependable") function को सही parameters के साथ call करना। +* आपके function से result लेना। +* उस result को आपके *path operation function* के parameter को assign करना। + +```mermaid +graph TB + +common_parameters(["common_parameters"]) +read_items["/items/"] +read_users["/users/"] + +common_parameters --> read_items +common_parameters --> read_users +``` + +इस तरह आप shared code एक बार लिखते हैं और **FastAPI** आपके *path operations* के लिए उसे call करने का ध्यान रखता है। + +/// tip | सुझाव + +ध्यान दें कि आपको कोई special class बनाकर उसे **FastAPI** को "register" करने के लिए कहीं pass करने या ऐसा कुछ करने की ज़रूरत नहीं है। + +आप बस इसे `Depends` को pass करते हैं और **FastAPI** जानता है कि बाकी कैसे करना है। + +/// + +## `Annotated` dependencies share करें { #share-annotated-dependencies } + +ऊपर के उदाहरणों में, आप देखते हैं कि **code duplication** का थोड़ा सा हिस्सा है। + +जब आपको `common_parameters()` dependency का उपयोग करना हो, तो आपको type annotation और `Depends()` के साथ पूरा parameter लिखना पड़ता है: + +```Python +commons: Annotated[dict, Depends(common_parameters)] +``` + +लेकिन क्योंकि हम `Annotated` का उपयोग कर रहे हैं, हम उस `Annotated` value को एक variable में store कर सकते हैं और कई जगहों पर उपयोग कर सकते हैं: + +{* ../../docs_src/dependencies/tutorial001_02_an_py310.py hl[12,16,21] *} + +/// tip | सुझाव + +यह बस standard Python है, इसे "type alias" कहा जाता है, यह वास्तव में **FastAPI** के लिए specific नहीं है। + +लेकिन क्योंकि **FastAPI** Python standards पर आधारित है, जिसमें `Annotated` भी शामिल है, आप अपने code में इस trick का उपयोग कर सकते हैं। 😎 + +/// + +dependencies अपेक्षित रूप से काम करती रहेंगी, और **सबसे अच्छी बात** यह है कि **type information preserve रहेगी**, जिसका मतलब है कि आपका editor आपको **autocompletion**, **inline errors**, आदि प्रदान करना जारी रख सकेगा। यही बात `mypy` जैसे दूसरे tools के लिए भी लागू होती है। + +यह खास तौर पर तब उपयोगी होगा जब आप इसे एक **large code base** में उपयोग करते हैं जहाँ आप **वही dependencies** बार-बार **कई *path operations*** में उपयोग करते हैं। + +## `async` करें या `async` न करें { #to-async-or-not-to-async } + +क्योंकि dependencies को भी **FastAPI** द्वारा call किया जाएगा (आपके *path operation functions* की तरह), functions define करते समय वही rules लागू होते हैं। + +आप `async def` या सामान्य `def` का उपयोग कर सकते हैं। + +और आप normal `def` *path operation functions* के अंदर `async def` dependencies declare कर सकते हैं, या `async def` *path operation functions* के अंदर `def` dependencies, आदि। + +इससे फर्क नहीं पड़ता। **FastAPI** जानता होगा कि क्या करना है। + +/// note | नोट + +अगर आपको नहीं पता, तो docs में `async` और `await` के बारे में [Async: *"In a hurry?"*](../../async.md#in-a-hurry) section देखें। + +/// + +## OpenAPI के साथ integrated { #integrated-with-openapi } + +आपकी dependencies (और sub-dependencies) की सभी request declarations, validations और requirements उसी OpenAPI schema में integrate की जाएँगी। + +इसलिए, interactive docs में इन dependencies की सारी जानकारी भी होगी: + + + +## सरल उपयोग { #simple-usage } + +अगर आप इसे देखें, तो *path operation functions* इस तरह declare किए जाते हैं कि जब भी कोई *path* और *operation* match करता है, उनका उपयोग किया जाए, और फिर **FastAPI** सही parameters के साथ function को call करने और request से data extract करने का ध्यान रखता है। + +असल में, सभी (या अधिकांश) web frameworks इसी तरह काम करते हैं। + +आप उन functions को कभी सीधे call नहीं करते। वे आपके framework द्वारा call किए जाते हैं (इस मामले में, **FastAPI**)। + +Dependency Injection system के साथ, आप **FastAPI** को यह भी बता सकते हैं कि आपका *path operation function* किसी और चीज़ पर भी "depend" करता है जिसे आपके *path operation function* से पहले execute किया जाना चाहिए, और **FastAPI** उसे execute करने और results को "inject" करने का ध्यान रखेगा। + +"dependency injection" के इसी idea के लिए अन्य common terms हैं: + +* resources +* providers +* services +* injectables +* components + +## **FastAPI** plug-ins { #fastapi-plug-ins } + +Integrations और "plug-ins" **Dependency Injection** system का उपयोग करके बनाए जा सकते हैं। लेकिन वास्तव में, **"plug-ins" बनाने की कोई ज़रूरत नहीं है**, क्योंकि dependencies का उपयोग करके अनगिनत integrations और interactions declare किए जा सकते हैं जो आपके *path operation functions* के लिए उपलब्ध हो जाते हैं। + +और dependencies को बहुत सरल और सहज तरीके से बनाया जा सकता है, जिससे आप बस अपने required Python packages import कर सकते हैं, और उन्हें अपने API functions के साथ कुछ lines of code में integrate कर सकते हैं, *literally*। + +आप अगले chapters में relational और NoSQL databases, security, आदि के बारे में इसके examples देखेंगे। + +## **FastAPI** compatibility { #fastapi-compatibility } + +Dependency injection system की सरलता **FastAPI** को इनके साथ compatible बनाती है: + +* सभी relational databases +* NoSQL databases +* external packages +* external APIs +* authentication और authorization systems +* API usage monitoring systems +* response data injection systems +* आदि। + +## सरल और शक्तिशाली { #simple-and-powerful } + +हालाँकि hierarchical dependency injection system को define और use करना बहुत सरल है, फिर भी यह बहुत शक्तिशाली है। + +आप ऐसी dependencies define कर सकते हैं जो बदले में खुद dependencies define कर सकती हैं। + +अंत में, dependencies का एक hierarchical tree बनता है, और **Dependency Injection** system आपके लिए इन सभी dependencies (और उनकी sub-dependencies) को solve करने और हर step पर results प्रदान करने (inject करने) का ध्यान रखता है। + +उदाहरण के लिए, मान लें कि आपके पास 4 API endpoints (*path operations*) हैं: + +* `/items/public/` +* `/items/private/` +* `/users/{user_id}/activate` +* `/items/pro/` + +तो आप उनमें से हर एक के लिए अलग-अलग permission requirements केवल dependencies और sub-dependencies के साथ जोड़ सकते हैं: + +```mermaid +graph TB + +current_user(["current_user"]) +active_user(["active_user"]) +admin_user(["admin_user"]) +paying_user(["paying_user"]) + +public["/items/public/"] +private["/items/private/"] +activate_user["/users/{user_id}/activate"] +pro_items["/items/pro/"] + +current_user --> active_user +active_user --> admin_user +active_user --> paying_user + +current_user --> public +active_user --> private +admin_user --> activate_user +paying_user --> pro_items +``` + +## **OpenAPI** के साथ integrated { #integrated-with-openapi_1 } + +ये सभी dependencies, अपनी requirements declare करते समय, आपके *path operations* में parameters, validations, आदि भी जोड़ती हैं। + +**FastAPI** यह सब OpenAPI schema में जोड़ने का ध्यान रखेगा, ताकि यह interactive documentation systems में दिखाया जा सके। diff --git a/docs/hi/docs/tutorial/dependencies/sub-dependencies.md b/docs/hi/docs/tutorial/dependencies/sub-dependencies.md new file mode 100644 index 000000000..7fb4bbdb7 --- /dev/null +++ b/docs/hi/docs/tutorial/dependencies/sub-dependencies.md @@ -0,0 +1,105 @@ +# Sub-dependencies { #sub-dependencies } + +आप ऐसी dependencies बना सकते हैं जिनकी अपनी **sub-dependencies** हों। + +वे उतनी **deep** हो सकती हैं जितनी आपको चाहिए। + +**FastAPI** उन्हें solve करने का ध्यान रखेगा। + +## पहली dependency "dependable" { #first-dependency-dependable } + +आप पहली dependency ("dependable") इस तरह बना सकते हैं: + +{* ../../docs_src/dependencies/tutorial005_an_py310.py hl[8:9] *} + +यह एक optional query parameter `q` को `str` के रूप में declare करता है, और फिर बस उसे return करता है। + +यह काफी सरल है (बहुत उपयोगी नहीं), लेकिन इससे हमें यह समझने पर ध्यान देने में मदद मिलेगी कि sub-dependencies कैसे काम करती हैं। + +## दूसरी dependency, "dependable" और "dependant" { #second-dependency-dependable-and-dependant } + +फिर आप एक और dependency function (एक "dependable") बना सकते हैं जो उसी समय अपनी खुद की dependency declare करता है (इसलिए यह एक "dependant" भी है): + +{* ../../docs_src/dependencies/tutorial005_an_py310.py hl[13] *} + +आइए declared parameters पर ध्यान दें: + +* भले ही यह function खुद एक dependency ("dependable") है, यह एक और dependency भी declare करता है (यह किसी और चीज़ पर "depends" करता है)। + * यह `query_extractor` पर depends करता है, और उसके द्वारा return किए गए value को parameter `q` में assign करता है। +* यह एक optional `last_query` cookie को भी `str` के रूप में declare करता है। + * अगर user ने कोई query `q` provide नहीं की, तो हम पिछली इस्तेमाल की गई query का उपयोग करते हैं, जिसे हमने पहले एक cookie में save किया था। + +## dependency का उपयोग करें { #use-the-dependency } + +फिर हम dependency का उपयोग इस तरह कर सकते हैं: + +{* ../../docs_src/dependencies/tutorial005_an_py310.py hl[23] *} + +/// note | नोट + +ध्यान दें कि हम *path operation function* में केवल एक dependency declare कर रहे हैं, `query_or_cookie_extractor`। + +लेकिन **FastAPI** को पता होगा कि `query_or_cookie_extractor` को call करते समय उसके results pass करने के लिए पहले `query_extractor` को solve करना है। + +/// + +```mermaid +graph TB + +query_extractor(["query_extractor"]) +query_or_cookie_extractor(["query_or_cookie_extractor"]) + +read_query["/items/"] + +query_extractor --> query_or_cookie_extractor --> read_query +``` + +## उसी dependency को कई बार उपयोग करना { #using-the-same-dependency-multiple-times } + +अगर आपकी किसी dependency को उसी *path operation* के लिए कई बार declare किया गया है, उदाहरण के लिए, कई dependencies की कोई common sub-dependency है, तो **FastAPI** जानता होगा कि उस sub-dependency को प्रति request केवल एक बार call करना है। + +और यह return किए गए value को एक "cache" में save करेगा और उसे उन सभी "dependants" को pass करेगा जिन्हें उस specific request में इसकी ज़रूरत है, बजाय उसी request के लिए dependency को कई बार call करने के। + +एक advanced scenario में, जहाँ आप जानते हैं कि आपको उसी request में "cached" value का उपयोग करने के बजाय हर step पर dependency को call करवाना है (संभवतः कई बार), आप `Depends` का उपयोग करते समय parameter `use_cache=False` set कर सकते हैं: + +//// tab | Python 3.10+ + +```Python hl_lines="1" +async def needy_dependency(fresh_value: Annotated[str, Depends(get_value, use_cache=False)]): + return {"fresh_value": fresh_value} +``` + +//// + +//// tab | Python 3.10+ non-Annotated + +/// tip | सुझाव + +अगर संभव हो तो `Annotated` version का उपयोग करना पसंद करें। + +/// + +```Python hl_lines="1" +async def needy_dependency(fresh_value: str = Depends(get_value, use_cache=False)): + return {"fresh_value": fresh_value} +``` + +//// + +## Recap { #recap } + +यहाँ इस्तेमाल किए गए सभी fancy words को छोड़ दें, तो **Dependency Injection** system काफी सरल है। + +बस ऐसे functions जो *path operation functions* जैसे ही दिखते हैं। + +लेकिन फिर भी, यह बहुत powerful है, और आपको arbitrarily deeply nested dependency "graphs" (trees) declare करने देता है। + +/// tip | सुझाव + +इन सरल examples के साथ यह सब इतना उपयोगी नहीं लग सकता। + +लेकिन **security** के बारे में chapters में आप देखेंगे कि यह कितना उपयोगी है। + +और आप यह भी देखेंगे कि यह आपका कितना code बचाएगा। + +/// diff --git a/docs/hi/docs/tutorial/encoder.md b/docs/hi/docs/tutorial/encoder.md new file mode 100644 index 000000000..66dbbca2b --- /dev/null +++ b/docs/hi/docs/tutorial/encoder.md @@ -0,0 +1,35 @@ +# JSON संगत Encoder { #json-compatible-encoder } + +कुछ मामलों में आपको किसी data type (जैसे Pydantic model) को JSON के साथ संगत किसी चीज़ (जैसे `dict`, `list`, आदि) में convert करने की ज़रूरत पड़ सकती है। + +उदाहरण के लिए, अगर आपको इसे database में store करना हो। + +इसके लिए, **FastAPI** एक `jsonable_encoder()` function प्रदान करता है। + +## `jsonable_encoder` का उपयोग करना { #using-the-jsonable-encoder } + +कल्पना करें कि आपके पास एक database `fake_db` है जो केवल JSON संगत data ही स्वीकार करता है। + +उदाहरण के लिए, यह `datetime` objects स्वीकार नहीं करता, क्योंकि वे JSON के साथ संगत नहीं होते। + +इसलिए, एक `datetime` object को [ISO format](https://en.wikipedia.org/wiki/ISO_8601) में data रखने वाले `str` में convert करना होगा। + +इसी तरह, यह database Pydantic model (attributes वाला एक object) स्वीकार नहीं करेगा, केवल एक `dict`। + +इसके लिए आप `jsonable_encoder` का उपयोग कर सकते हैं। + +यह एक object, जैसे Pydantic model, प्राप्त करता है और JSON संगत version लौटाता है: + +{* ../../docs_src/encoder/tutorial001_py310.py hl[4,21] *} + +इस उदाहरण में, यह Pydantic model को `dict` में और `datetime` को `str` में convert करेगा। + +इसे call करने का परिणाम कुछ ऐसा होता है जिसे Python standard [`json.dumps()`](https://docs.python.org/3/library/json.html#json.dumps) के साथ encode किया जा सकता है। + +यह JSON format में data रखने वाला कोई बड़ा `str` (string के रूप में) return नहीं करता। यह एक Python standard data structure (जैसे `dict`) return करता है, जिसमें values और sub-values होती हैं जो सभी JSON के साथ संगत होती हैं। + +/// note | नोट + +`jsonable_encoder` वास्तव में **FastAPI** द्वारा internally data convert करने के लिए उपयोग किया जाता है। लेकिन यह कई अन्य scenarios में भी उपयोगी है। + +/// diff --git a/docs/hi/docs/tutorial/extra-data-types.md b/docs/hi/docs/tutorial/extra-data-types.md new file mode 100644 index 000000000..a157ea017 --- /dev/null +++ b/docs/hi/docs/tutorial/extra-data-types.md @@ -0,0 +1,62 @@ +# अतिरिक्त Data Types { #extra-data-types } + +अब तक, आप सामान्य data types का उपयोग करते रहे हैं, जैसे: + +* `int` +* `float` +* `str` +* `bool` + +लेकिन आप अधिक जटिल data types भी उपयोग कर सकते हैं। + +और आपको अब तक देखी गई वही features मिलती रहेंगी: + +* शानदार editor support. +* आने वाली requests से data conversion. +* response data के लिए data conversion. +* Data validation. +* Automatic annotation और documentation. + +## अन्य data types { #other-data-types } + +यहाँ कुछ अतिरिक्त data types हैं जिनका आप उपयोग कर सकते हैं: + +* `UUID`: + * एक standard "Universally Unique Identifier", जो कई databases और systems में ID के रूप में आम है। + * requests और responses में इसे `str` के रूप में दर्शाया जाएगा। +* `datetime.datetime`: + * एक Python `datetime.datetime`. + * requests और responses में इसे ISO 8601 format में `str` के रूप में दर्शाया जाएगा, जैसे: `2008-09-15T15:53:00+05:00`. +* `datetime.date`: + * Python `datetime.date`. + * requests और responses में इसे ISO 8601 format में `str` के रूप में दर्शाया जाएगा, जैसे: `2008-09-15`. +* `datetime.time`: + * एक Python `datetime.time`. + * requests और responses में इसे ISO 8601 format में `str` के रूप में दर्शाया जाएगा, जैसे: `14:23:55.003`. +* `datetime.timedelta`: + * एक Python `datetime.timedelta`. + * requests और responses में इसे कुल seconds के `float` के रूप में दर्शाया जाएगा। + * Pydantic इसे "ISO 8601 time diff encoding" के रूप में दर्शाने की अनुमति भी देता है, [अधिक जानकारी के लिए docs देखें](https://docs.pydantic.dev/latest/concepts/serialization/#custom-serializers). +* `frozenset`: + * requests और responses में, इसे `set` जैसा ही माना जाता है: + * requests में, एक list पढ़ी जाएगी, duplicates हटाए जाएँगे और उसे `set` में convert किया जाएगा। + * responses में, `set` को `list` में convert किया जाएगा। + * generate किया गया schema बताएगा कि `set` values unique हैं (JSON Schema के `uniqueItems` का उपयोग करते हुए)। +* `bytes`: + * Standard Python `bytes`. + * requests और responses में इसे `str` की तरह माना जाएगा। + * generate किया गया schema बताएगा कि यह `binary` "format" वाला `str` है। +* `Decimal`: + * Standard Python `Decimal`. + * requests और responses में, इसे `float` जैसा ही handle किया जाएगा। +* आप सभी valid Pydantic data types यहाँ देख सकते हैं: [Pydantic data types](https://docs.pydantic.dev/latest/usage/types/types/). + +## उदाहरण { #example } + +यहाँ ऊपर दिए गए कुछ types का उपयोग करते हुए parameters वाला एक उदाहरण *path operation* है। + +{* ../../docs_src/extra_data_types/tutorial001_an_py310.py hl[1,3,12:16] *} + +ध्यान दें कि function के अंदर parameters के अपने natural data type होते हैं, और उदाहरण के लिए, आप सामान्य date manipulations कर सकते हैं, जैसे: + +{* ../../docs_src/extra_data_types/tutorial001_an_py310.py hl[18:19] *} diff --git a/docs/hi/docs/tutorial/extra-models.md b/docs/hi/docs/tutorial/extra-models.md new file mode 100644 index 000000000..93a4e91dc --- /dev/null +++ b/docs/hi/docs/tutorial/extra-models.md @@ -0,0 +1,211 @@ +# Extra Models { #extra-models } + +पिछले उदाहरण को आगे बढ़ाते हुए, एक से अधिक संबंधित model होना आम बात होगी। + +यह खासकर user models के मामले में होता है, क्योंकि: + +* **input model** में password हो सकने की क्षमता चाहिए। +* **output model** में password नहीं होना चाहिए। +* **database model** में शायद hashed password होना चाहिए। + +/// danger | खतरा + +user के plaintext passwords कभी store न करें। हमेशा एक "secure hash" store करें जिसे आप बाद में verify कर सकें। + +अगर आप नहीं जानते, तो आप [security chapters](security/simple-oauth2.md#password-hashing) में सीखेंगे कि "password hash" क्या होता है। + +/// + +## कई models { #multiple-models } + +यह एक सामान्य idea है कि models अपने password fields और जहाँ वे इस्तेमाल होते हैं, वहाँ कैसे दिख सकते हैं: + +{* ../../docs_src/extra_models/tutorial001_py310.py hl[7,9,14,20,22,27:28,31:33,38:39] *} + +### `**user_in.model_dump()` के बारे में { #about-user-in-model-dump } + +#### Pydantic का `.model_dump()` { #pydantics-model-dump } + +`user_in`, class `UserIn` का एक Pydantic model है। + +Pydantic models में एक `.model_dump()` method होता है जो model के data के साथ एक `dict` return करता है। + +तो, अगर हम इस तरह एक Pydantic object `user_in` बनाते हैं: + +```Python +user_in = UserIn(username="john", password="secret", email="john.doe@example.com") +``` + +और फिर हम call करते हैं: + +```Python +user_dict = user_in.model_dump() +``` + +तो अब हमारे पास variable `user_dict` में data के साथ एक `dict` है (यह Pydantic model object के बजाय एक `dict` है)। + +और अगर हम call करते हैं: + +```Python +print(user_dict) +``` + +तो हमें यह Python `dict` मिलेगा: + +```Python +{ + 'username': 'john', + 'password': 'secret', + 'email': 'john.doe@example.com', + 'full_name': None, +} +``` + +#### एक `dict` को unpack करना { #unpacking-a-dict } + +अगर हम `user_dict` जैसा एक `dict` लेते हैं और उसे किसी function (या class) को `**user_dict` के साथ pass करते हैं, तो Python उसे "unpack" करेगा। यह `user_dict` की keys और values को सीधे key-value arguments के रूप में pass करेगा। + +तो, ऊपर वाले `user_dict` को जारी रखते हुए, यह लिखना: + +```Python +UserInDB(**user_dict) +``` + +कुछ इस equivalent result देगा: + +```Python +UserInDB( + username="john", + password="secret", + email="john.doe@example.com", + full_name=None, +) +``` + +या अधिक सही रूप में, `user_dict` को सीधे इस्तेमाल करते हुए, उसमें भविष्य में जो भी contents हों: + +```Python +UserInDB( + username = user_dict["username"], + password = user_dict["password"], + email = user_dict["email"], + full_name = user_dict["full_name"], +) +``` + +#### दूसरे model के contents से एक Pydantic model { #a-pydantic-model-from-the-contents-of-another } + +जैसा कि ऊपर के उदाहरण में हमें `user_in.model_dump()` से `user_dict` मिला, यह code: + +```Python +user_dict = user_in.model_dump() +UserInDB(**user_dict) +``` + +इसके equivalent होगा: + +```Python +UserInDB(**user_in.model_dump()) +``` + +...क्योंकि `user_in.model_dump()` एक `dict` है, और फिर हम उसे `**` prefix के साथ `UserInDB` को pass करके Python से उसे "unpack" करवाते हैं। + +तो, हमें एक Pydantic model के data से दूसरा Pydantic model मिलता है। + +#### एक `dict` को unpack करना और extra keywords { #unpacking-a-dict-and-extra-keywords } + +और फिर extra keyword argument `hashed_password=hashed_password` जोड़ना, जैसे: + +```Python +UserInDB(**user_in.model_dump(), hashed_password=hashed_password) +``` + +...अंत में ऐसा बन जाता है: + +```Python +UserInDB( + username = user_dict["username"], + password = user_dict["password"], + email = user_dict["email"], + full_name = user_dict["full_name"], + hashed_password = hashed_password, +) +``` + +/// warning | चेतावनी + +supporting additional functions `fake_password_hasher` और `fake_save_user` सिर्फ data के एक possible flow को demo करने के लिए हैं, लेकिन वे निश्चित रूप से कोई real security नहीं दे रहे हैं। + +/// + +## Duplication कम करें { #reduce-duplication } + +Code duplication कम करना **FastAPI** के core ideas में से एक है। + +क्योंकि code duplication बढ़ने से bugs, security issues, code desynchronization issues (जब आप एक जगह update करते हैं लेकिन बाकी जगह नहीं), आदि की संभावना बढ़ जाती है। + +और ये models बहुत सारा data share कर रहे हैं और attribute names और types को duplicate कर रहे हैं। + +हम इससे बेहतर कर सकते हैं। + +हम एक `UserBase` model declare कर सकते हैं जो हमारे दूसरे models के लिए base की तरह काम करता है। और फिर हम उस model की subclasses बना सकते हैं जो उसके attributes (type declarations, validation, आदि) inherit करती हैं। + +सारा data conversion, validation, documentation, आदि सामान्य रूप से काम करता रहेगा। + +इस तरह, हम केवल models के बीच के अंतर declare कर सकते हैं (plaintext `password` के साथ, `hashed_password` के साथ और password के बिना): + +{* ../../docs_src/extra_models/tutorial002_py310.py hl[7,13:14,17:18,21:22] *} + +## `Union` या `anyOf` { #union-or-anyof } + +आप response को दो या अधिक types के `Union` के रूप में declare कर सकते हैं, जिसका मतलब है कि response उनमें से कोई भी हो सकता है। + +इसे OpenAPI में `anyOf` के साथ define किया जाएगा। + +ऐसा करने के लिए, standard Python type hint [`typing.Union`](https://docs.python.org/3/library/typing.html#typing.Union) का इस्तेमाल करें: + +/// note | नोट + +[`Union`](https://docs.pydantic.dev/latest/concepts/types/#unions) define करते समय, सबसे specific type को पहले include करें, उसके बाद कम specific type को। नीचे दिए गए उदाहरण में, अधिक specific `PlaneItem`, `Union[PlaneItem, CarItem]` में `CarItem` से पहले आता है। + +/// + +{* ../../docs_src/extra_models/tutorial003_py310.py hl[1,14:15,18:20,33] *} + +### Python 3.10 में `Union` { #union-in-python-3-10 } + +इस उदाहरण में हम argument `response_model` की value के रूप में `Union[PlaneItem, CarItem]` pass करते हैं। + +क्योंकि हम इसे **type annotation** में रखने के बजाय **argument को value** के रूप में pass कर रहे हैं, इसलिए हमें Python 3.10 में भी `Union` इस्तेमाल करना होगा। + +अगर यह type annotation में होता तो हम vertical bar इस्तेमाल कर सकते थे, जैसे: + +```Python +some_variable: PlaneItem | CarItem +``` + +लेकिन अगर हम इसे assignment `response_model=PlaneItem | CarItem` में डालते, तो हमें error मिलता, क्योंकि Python इसे type annotation के रूप में interpret करने के बजाय `PlaneItem` और `CarItem` के बीच एक **invalid operation** perform करने की कोशिश करता। + +## Models की list { #list-of-models } + +इसी तरह, आप objects की lists के responses declare कर सकते हैं। + +इसके लिए, standard Python `list` इस्तेमाल करें: + +{* ../../docs_src/extra_models/tutorial004_py310.py hl[18] *} + +## Arbitrary `dict` के साथ response { #response-with-arbitrary-dict } + +आप plain arbitrary `dict` का इस्तेमाल करके भी response declare कर सकते हैं, जिसमें Pydantic model का इस्तेमाल किए बिना केवल keys और values का type declare किया जाता है। + +यह तब उपयोगी है जब आपको valid field/attribute names (जो Pydantic model के लिए चाहिए होंगे) पहले से नहीं पता हों। + +इस मामले में, आप `dict` इस्तेमाल कर सकते हैं: + +{* ../../docs_src/extra_models/tutorial005_py310.py hl[6] *} + +## Recap { #recap } + +हर case के लिए कई Pydantic models इस्तेमाल करें और freely inherit करें। + +अगर किसी entity में अलग-अलग "states" हो सकने चाहिए, तो आपको प्रति entity एक ही data model रखने की जरूरत नहीं है। **user** "entity" एक उदाहरण है, जिसमें states में `password`, `password_hash`, या कोई password नहीं होना शामिल है। diff --git a/docs/hi/docs/tutorial/first-steps.md b/docs/hi/docs/tutorial/first-steps.md new file mode 100644 index 000000000..aa6fd4e37 --- /dev/null +++ b/docs/hi/docs/tutorial/first-steps.md @@ -0,0 +1,421 @@ +# पहले कदम { #first-steps } + +सबसे सरल FastAPI file ऐसी दिख सकती है: + +{* ../../docs_src/first_steps/tutorial001_py310.py *} + +इसे `main.py` नाम की file में copy करें। + +live server चलाएँ: + +
+ +```console +$ fastapi dev + + FastAPI Starting development server 🚀 + + Searching for package file structure from directories + with __init__.py files + Importing from /home/user/code/awesomeapp + + module 🐍 main.py + + code Importing the FastAPI app object from the module with + the following code: + + from main import app + + app Using import string: main:app + + server Server started at http://127.0.0.1:8000 + server Documentation at http://127.0.0.1:8000/docs + + tip Running in development mode, for production use: + fastapi run + + Logs: + + INFO Will watch for changes in these directories: + ['/home/user/code/awesomeapp'] + INFO Uvicorn running on http://127.0.0.1:8000 (Press CTRL+C + to quit) + INFO Started reloader process [383138] using WatchFiles + INFO Started server process [383153] + INFO Waiting for application startup. + INFO Application startup complete. +``` + +
+ +output में, कुछ ऐसी एक line होती है: + +```hl_lines="4" +INFO: Uvicorn running on http://127.0.0.1:8000 (Press CTRL+C to quit) +``` + +यह line वह URL दिखाती है जहाँ आपकी app आपकी local machine पर serve की जा रही है। + +### इसे जाँचें { #check-it } + +अपने browser में [http://127.0.0.1:8000](http://127.0.0.1:8000) खोलें। + +आपको JSON response इस तरह दिखेगा: + +```JSON +{"message": "Hello World"} +``` + +### Interactive API docs { #interactive-api-docs } + +अब [http://127.0.0.1:8000/docs](http://127.0.0.1:8000/docs) पर जाएँ। + +आपको automatic interactive API documentation दिखेगी ([Swagger UI](https://github.com/swagger-api/swagger-ui) द्वारा प्रदान की गई): + +![Swagger UI](https://fastapi.tiangolo.com/img/index/index-01-swagger-ui-simple.png) + +### वैकल्पिक API docs { #alternative-api-docs } + +और अब, [http://127.0.0.1:8000/redoc](http://127.0.0.1:8000/redoc) पर जाएँ। + +आपको वैकल्पिक automatic documentation दिखेगी ([ReDoc](https://github.com/Rebilly/ReDoc) द्वारा प्रदान की गई): + +![ReDoc](https://fastapi.tiangolo.com/img/index/index-02-redoc-simple.png) + +### OpenAPI { #openapi } + +**FastAPI** APIs को define करने के लिए **OpenAPI** standard का उपयोग करके आपकी पूरी API के साथ एक "schema" generate करता है। + +#### "Schema" { #schema } + +"schema" किसी चीज़ की definition या description है। वह code नहीं जो इसे implement करता है, बल्कि सिर्फ़ एक abstract description है। + +#### API "schema" { #api-schema } + +इस मामले में, [OpenAPI](https://github.com/OAI/OpenAPI-Specification) एक specification है जो बताती है कि आपकी API का schema कैसे define करना है। + +इस schema definition में आपकी API paths, उनके द्वारा लिए जा सकने वाले संभावित parameters आदि शामिल होते हैं। + +#### Data "schema" { #data-schema } + +"schema" शब्द कुछ data के आकार को भी refer कर सकता है, जैसे JSON content। + +उस मामले में, इसका मतलब JSON attributes, और उनके data types आदि होगा। + +#### OpenAPI और JSON Schema { #openapi-and-json-schema } + +OpenAPI आपकी API के लिए API schema define करता है। और उस schema में **JSON Schema**, जो JSON data schemas के लिए standard है, का उपयोग करके आपकी API द्वारा भेजे और प्राप्त किए गए data की definitions (या "schemas") शामिल होती हैं। + +#### `openapi.json` जाँचें { #check-the-openapi-json } + +अगर आप यह जानने को उत्सुक हैं कि raw OpenAPI schema कैसा दिखता है, FastAPI आपकी पूरी API के descriptions के साथ अपने आप एक JSON (schema) generate करता है। + +आप इसे सीधे यहाँ देख सकते हैं: [http://127.0.0.1:8000/openapi.json](http://127.0.0.1:8000/openapi.json)। + +यह कुछ ऐसे शुरू होने वाला JSON दिखाएगा: + +```JSON +{ + "openapi": "3.1.0", + "info": { + "title": "FastAPI", + "version": "0.1.0" + }, + "paths": { + "/items/": { + "get": { + "responses": { + "200": { + "description": "Successful Response", + "content": { + "application/json": { + + + +... +``` + +#### OpenAPI किसलिए है { #what-is-openapi-for } + +OpenAPI schema ही शामिल किए गए दो interactive documentation systems को power देता है। + +और दर्जनों विकल्प हैं, सभी OpenAPI पर आधारित। आप **FastAPI** से बनी अपनी application में इनमें से कोई भी विकल्प आसानी से जोड़ सकते हैं। + +आप इसका उपयोग उन clients के लिए अपने आप code generate करने के लिए भी कर सकते हैं जो आपकी API से communicate करते हैं। उदाहरण के लिए, frontend, mobile या IoT applications। + +### `pyproject.toml` में app `entrypoint` configure करें { #configure-the-app-entrypoint-in-pyproject-toml } + +आप `pyproject.toml` file में अपनी app कहाँ स्थित है, इसे इस तरह configure कर सकते हैं: + +```toml +[tool.fastapi] +entrypoint = "main:app" +``` + +वह `entrypoint` `fastapi` command को बताएगा कि उसे app को इस तरह import करना चाहिए: + +```python +from main import app +``` + +अगर आपका code इस तरह structured था: + +``` +. +├── backend +│   ├── main.py +│   ├── __init__.py +``` + +तो आप `entrypoint` को इस तरह set करेंगे: + +```toml +[tool.fastapi] +entrypoint = "backend.main:app" +``` + +जो इसके equivalent होगा: + +```python +from backend.main import app +``` + +### `fastapi dev` path के साथ या `--entrypoint` CLI option के साथ { #fastapi-dev-with-path-or-with-entrypoint-cli-option } + +आप `fastapi dev` command को file path भी pass कर सकते हैं, और यह उपयोग करने के लिए FastAPI app object का अनुमान लगा लेगा: + +```console +$ fastapi dev main.py +``` + +या, आप `fastapi dev` command को `--entrypoint` option भी pass कर सकते हैं: + +```console +$ fastapi dev --entrypoint main:app +``` + +लेकिन हर बार `fastapi` command call करते समय आपको सही path\entrypoint pass करना याद रखना होगा। + +इसके अलावा, दूसरे tools इसे ढूँढ नहीं पाएँगे, उदाहरण के लिए [VS Code Extension](../editor-support.md) या [FastAPI Cloud](https://fastapicloud.com), इसलिए `pyproject.toml` में `entrypoint` का उपयोग करने की सलाह दी जाती है। + +### अपनी app deploy करें (वैकल्पिक) { #deploy-your-app-optional } + +आप वैकल्पिक रूप से अपनी FastAPI app को एक single command से [FastAPI Cloud](https://fastapicloud.com) पर deploy कर सकते हैं। 🚀 + +
+ +```console +$ fastapi deploy + +Deploying to FastAPI Cloud... + +✅ Deployment successful! + +🐔 Ready the chicken! Your app is ready at https://myapp.fastapicloud.dev +``` + +
+ +CLI आपकी FastAPI application को अपने आप detect करेगा और उसे cloud पर deploy करेगा। अगर आप logged in नहीं हैं, तो authentication process पूरा करने के लिए आपका browser खुलेगा। + +बस इतना ही! अब आप उस URL पर अपनी app access कर सकते हैं। ✨ + +## Recap, चरण दर चरण { #recap-step-by-step } + +### चरण 1: `FastAPI` import करें { #step-1-import-fastapi } + +{* ../../docs_src/first_steps/tutorial001_py310.py hl[1] *} + +`FastAPI` एक Python class है जो आपकी API के लिए सारी functionality प्रदान करती है। + +/// note | तकनीकी विवरण + +`FastAPI` एक class है जो सीधे `Starlette` से inherit करती है। + +आप `FastAPI` के साथ सारी [Starlette](https://www.starlette.dev/) functionality भी उपयोग कर सकते हैं। + +/// + +### चरण 2: एक `FastAPI` "instance" बनाएँ { #step-2-create-a-fastapi-instance } + +{* ../../docs_src/first_steps/tutorial001_py310.py hl[3] *} + +यहाँ `app` variable class `FastAPI` का एक "instance" होगा। + +यह आपकी पूरी API बनाने के लिए interaction का मुख्य point होगा। + +### चरण 3: एक *path operation* बनाएँ { #step-3-create-a-path-operation } + +#### Path { #path } + +यहाँ "Path" URL के पहले `/` से शुरू होने वाले आख़िरी हिस्से को refer करता है। + +तो, ऐसे URL में: + +``` +https://example.com/items/foo +``` + +...path होगा: + +``` +/items/foo +``` + +/// note | नोट + +एक "path" को आमतौर पर "endpoint" या "route" भी कहा जाता है। + +/// + +API बनाते समय, "path" "concerns" और "resources" को अलग करने का मुख्य तरीका है। + +#### Operation { #operation } + +यहाँ "Operation" HTTP "methods" में से किसी एक को refer करता है। + +इनमें से एक: + +* `POST` +* `GET` +* `PUT` +* `DELETE` + +...और कुछ अधिक असामान्य वाले: + +* `OPTIONS` +* `HEAD` +* `PATCH` +* `TRACE` + +HTTP protocol में, आप इन "methods" में से एक (या अधिक) का उपयोग करके हर path से communicate कर सकते हैं। + +--- + +APIs बनाते समय, आप आमतौर पर कोई specific action करने के लिए इन specific HTTP methods का उपयोग करते हैं। + +आम तौर पर आप उपयोग करते हैं: + +* `POST`: data बनाने के लिए। +* `GET`: data पढ़ने के लिए। +* `PUT`: data update करने के लिए। +* `DELETE`: data delete करने के लिए। + +इसलिए, OpenAPI में, हर HTTP method को एक "operation" कहा जाता है। + +हम उन्हें भी "**operations**" कहेंगे। + +#### एक *path operation decorator* define करें { #define-a-path-operation-decorator } + +{* ../../docs_src/first_steps/tutorial001_py310.py hl[6] *} + +`@app.get("/")` **FastAPI** को बताता है कि ठीक नीचे वाला function उन requests को handle करने का प्रभारी है जो यहाँ जाती हैं: + +* path `/` +* get operation का उपयोग करते हुए + +/// note | `@decorator` जानकारी + +Python में उस `@something` syntax को "decorator" कहा जाता है। + +आप इसे किसी function के ऊपर लगाते हैं। जैसे एक सुंदर सजावटी टोपी (मुझे लगता है term वहीं से आया है)। + +एक "decorator" नीचे वाले function को लेता है और उसके साथ कुछ करता है। + +हमारे मामले में, यह decorator **FastAPI** को बताता है कि नीचे वाला function **path** `/` के साथ **operation** `get` से संबंधित है। + +यह "**path operation decorator**" है। + +/// + +आप दूसरे operations भी उपयोग कर सकते हैं: + +* `@app.post()` +* `@app.put()` +* `@app.delete()` + +और कुछ अधिक असामान्य वाले: + +* `@app.options()` +* `@app.head()` +* `@app.patch()` +* `@app.trace()` + +/// tip | सुझाव + +आप हर operation (HTTP method) को अपनी इच्छा के अनुसार उपयोग करने के लिए स्वतंत्र हैं। + +**FastAPI** कोई specific अर्थ enforce नहीं करता। + +यहाँ दी गई जानकारी guideline के रूप में प्रस्तुत की गई है, requirement के रूप में नहीं। + +उदाहरण के लिए, GraphQL का उपयोग करते समय आप आम तौर पर सभी actions केवल `POST` operations का उपयोग करके करते हैं। + +/// + +### चरण 4: **path operation function** define करें { #step-4-define-the-path-operation-function } + +यह हमारा "**path operation function**" है: + +* **path**: `/` है। +* **operation**: `get` है। +* **function**: "decorator" के नीचे वाला function है (`@app.get("/")` के नीचे)। + +{* ../../docs_src/first_steps/tutorial001_py310.py hl[7] *} + +यह एक Python function है। + +जब भी **FastAPI** को `GET` operation का उपयोग करके URL "`/`" पर कोई request मिलती है, तो यह इसे call करेगा। + +इस मामले में, यह एक `async` function है। + +--- + +आप इसे `async def` के बजाय normal function के रूप में भी define कर सकते हैं: + +{* ../../docs_src/first_steps/tutorial003_py310.py hl[7] *} + +/// note | नोट + +अगर आपको अंतर नहीं पता है, तो [Async: *"In a hurry?"*](../async.md#in-a-hurry) देखें। + +/// + +### चरण 5: content return करें { #step-5-return-the-content } + +{* ../../docs_src/first_steps/tutorial001_py310.py hl[8] *} + +आप `dict`, `list`, `str`, `int` आदि जैसे singular values return कर सकते हैं। + +आप Pydantic models भी return कर सकते हैं (इसके बारे में आप आगे और देखेंगे)। + +कई अन्य objects और models हैं जिन्हें अपने आप JSON में convert किया जाएगा (ORMs आदि सहित)। अपने पसंदीदा ones उपयोग करके देखें, बहुत संभावना है कि वे पहले से supported हों। + +### चरण 6: इसे Deploy करें { #step-6-deploy-it } + +अपनी app को **[FastAPI Cloud](https://fastapicloud.com)** पर एक command से deploy करें: `fastapi deploy`। 🎉 + +#### FastAPI Cloud के बारे में { #about-fastapi-cloud } + +**[FastAPI Cloud](https://fastapicloud.com)** को **FastAPI** के पीछे मौजूद उसी author और team ने बनाया है। + +यह कम से कम प्रयास के साथ API को **बनाने**, **deploy करने**, और **access करने** की process को streamlined करता है। + +यह FastAPI के साथ apps बनाने जैसा ही **developer experience**, उन्हें cloud पर **deploy** करने में लाता है। 🎉 + +FastAPI Cloud *FastAPI and friends* open source projects का प्राथमिक sponsor और funding provider है। ✨ + +#### दूसरे cloud providers पर deploy करें { #deploy-to-other-cloud-providers } + +FastAPI open source है और standards पर आधारित है। आप FastAPI apps को अपनी पसंद के किसी भी cloud provider पर deploy कर सकते हैं। + +FastAPI apps को उनके साथ deploy करने के लिए अपने cloud provider की guides follow करें। 🤓 + +## Recap { #recap } + +* `FastAPI` import करें। +* एक `app` instance बनाएँ। +* `@app.get("/")` जैसे decorators का उपयोग करके एक **path operation decorator** लिखें। +* एक **path operation function** define करें; उदाहरण के लिए, `def root(): ...`। +* `fastapi dev` command का उपयोग करके development server चलाएँ। +* वैकल्पिक रूप से अपनी app को `fastapi deploy` के साथ deploy करें। diff --git a/docs/hi/docs/tutorial/frontend.md b/docs/hi/docs/tutorial/frontend.md new file mode 100644 index 000000000..bc8e188fc --- /dev/null +++ b/docs/hi/docs/tutorial/frontend.md @@ -0,0 +1,139 @@ +# Frontend { #frontend } + +आप `app.frontend()` (या `router.frontend()`) के साथ static frontend apps serve कर सकते हैं। + +यह उन frontend tools के लिए उपयोगी है जो static files generate करते हैं, जैसे React with Vite, TanStack Router, Astro, Vue, Svelte, Angular, Solid, और अन्य। + +इन tools के साथ, आपके पास आमतौर पर एक step होता है जो frontend को build करता है, जैसे इस command के साथ: + +```bash +npm run build +``` + +यह आपके frontend files के साथ `./dist/` जैसी एक directory generate करेगा। + +आप उस directory को इन frontend frameworks के लिए required conventions के अनुसार serve करने के लिए `app.frontend()` का उपयोग कर सकते हैं। + +**FastAPI** पहले *path operations* की जाँच करता है। frontend files की जाँच केवल तब की जाती है जब कोई सामान्य route match नहीं हुआ हो, इसलिए आपकी API प्रभावित नहीं होगी। + +## Frontend Serve करें { #serve-a-frontend } + +अपना frontend build करने के बाद, उदाहरण के लिए `npm run build` के साथ, generate की गई files को किसी directory में रखें, उदाहरण के लिए, `dist`। + +आपकी project संरचना ऐसी दिख सकती है: + +```text +. +├── pyproject.toml +├── app +│ ├── __init__.py +│ └── main.py +└── dist + ├── index.html + └── assets + └── app.js +``` + +फिर इसे `app.frontend()` के साथ serve करें: + +{* ../../docs_src/frontend/tutorial001_py310.py hl[5] *} + +इसके साथ, `/assets/app.js` के लिए एक request `dist/assets/app.js` serve कर सकती है। + +अगर आपके पास एक **FastAPI** *path operation* भी है, तो *path operation* को प्राथमिकता मिलती है। + +## Client-Side Routing { #client-side-routing } + +कई frontend apps, जिनमें **single-page apps** (SPAs) शामिल हैं, client-side routing का उपयोग करते हैं। `/dashboard/settings` जैसा path असली file नहीं हो सकता है, लेकिन framework इसे handle करने का ध्यान रखेगा। + +इसलिए, अगर उस URL को सीधे access किया जा रहा है (app के अंदर navigate करने के बजाय), तो backend को frontend app को `index.html` से serve करना चाहिए, ताकि frontend framework फिर client-side routing को handle कर सके। + +इसके लिए, `fallback="index.html"` का उपयोग करें: + +{* ../../docs_src/frontend/tutorial002_py310.py hl[5] *} + +**FastAPI** इस fallback का उपयोग केवल उन `GET` और `HEAD` requests के लिए करता है जो browser navigation जैसी दिखती हैं। JavaScript, CSS, और images जैसी missing files अभी भी `404` लौटाती हैं। + +अन्य methods वाली requests, जैसे `POST` या `PUT`, उन paths पर जो केवल frontend fallback से match करते हैं, वे भी `404` लौटाती हैं। नियमित **FastAPI** *path operations* की priority अभी भी frontend routes से अधिक होती है। + +/// tip | सुझाव + +Default रूप से, `fallback` की value `fallback="auto"` होती है। अधिकतर मामलों में आपको `fallback` specify करने की ज़रूरत नहीं होगी। विवरण के लिए नीचे पढ़ें। + +/// + +यह वही है जो आप कई frontend apps के साथ चाहेंगे जो client-side routing का उपयोग करते हैं, उदाहरण के लिए, React with TanStack Router, Vue, Angular, SvelteKit, या Solid। + +## Custom 404 Page { #custom-404-page } + +आप missing frontend paths के लिए static `404.html` page भी serve कर सकते हैं: + +{* ../../docs_src/frontend/tutorial003_py310.py hl[5] *} + +वह response `404` का status code बनाए रखती है। + +इस मामले में, **FastAPI** missing frontend paths के लिए `index.html` serve नहीं करेगा। इसके बजाय यह `404.html` file लौटाएगा। + +/// tip | सुझाव + +Default रूप से, `fallback` की value `fallback="auto"` होती है। इसके साथ, अगर `404.html` file मिलती है, तो उसे अपने-आप fallback के रूप में उपयोग किया जाएगा। + +इसलिए, आप सामान्यतः `fallback` argument छोड़ सकते हैं। + +/// + +यह उन frontend tools के साथ उपयोगी है जो हर page के लिए static HTML files generate करते हैं, जैसे Astro। + +## Fallback Auto { #fallback-auto } + +Default रूप से, `app.frontend()` `fallback="auto"` का उपयोग करता है। + +अगर frontend directory में `404.html` file है, तो missing frontend paths उस file को status code `404` के साथ serve करते हैं। + +अन्यथा, अगर `index.html` file है, तो missing browser navigation paths `index.html` serve करते हैं, जो client-side routing वाले कई frontend apps अपेक्षा करते हैं। + +इसलिए, अधिकतर मामलों में आप `fallback` argument specify किए बिना `app.frontend("/", directory="dist")` का उपयोग कर सकते हैं। + +{* ../../docs_src/frontend/tutorial001_py310.py hl[5] *} + +## Fallback बंद करें { #disable-fallback } + +अगर आप missing frontend paths के लिए fallback file serve नहीं करना चाहते, तो `fallback=None` का उपयोग करें: + +{* ../../docs_src/frontend/tutorial005_py310.py hl[5] *} + +फिर missing frontend paths सामान्य `404` लौटाते हैं। + +## Directory जाँचें { #check-directory } + +Default रूप से, `app.frontend()` app बनाते समय जाँचता है कि directory मौजूद है। + +यह configuration errors को जल्दी पकड़ने में मदद करता है। उदाहरण के लिए, अगर frontend build output directory missing है, तो **FastAPI** startup पर error raise करेगा। + +अगर आपकी frontend files बाद में बनाई जाती हैं, उदाहरण के लिए app object बनने के बाद किसी अलग build step द्वारा, तो `check_dir=False` set करें: + +{* ../../docs_src/frontend/tutorial006_py310.py hl[5] *} + +`check_dir=False` के साथ, **FastAPI** app बनाते समय directory की जाँच नहीं करेगा। अगर configured directory किसी request को handle करते समय अभी भी missing है, तो **FastAPI** तब error raise करेगा। + +## इसे `APIRouter` के साथ उपयोग करें { #use-it-with-apirouter } + +आप frontend files को `APIRouter` में भी जोड़ सकते हैं और उसे prefix के साथ include कर सकते हैं: + +{* ../../docs_src/frontend/tutorial004_py310.py hl[6,7] *} + +इस उदाहरण में, frontend paths `/app` के अंतर्गत serve किए जाते हैं। + +App में कोई भी नियमित *path operations* अभी भी precedence लेंगे, अन्य routers में शामिल ones भी। + +## Dependencies और Middleware { #dependencies-and-middleware } + +Frontend responses सामान्य **FastAPI** application के अंदर run करती हैं, इसलिए HTTP middleware उन पर लागू होता है। + +App से, `APIRouter` से, और `include_router()` से dependencies भी frontend responses पर लागू होती हैं। यह cookie authentication या इसी तरह से frontend को protect करने के लिए उपयोगी हो सकता है। + +## केवल Static Build Output { #static-build-output-only } + +`app.frontend()` आपके frontend build द्वारा पहले से generate की गई files serve करता है। + +यह server-side rendering run नहीं करता। यह उन frontend frameworks के लिए है जो static files generate करते हैं, न कि उन frameworks के लिए जिन्हें हर request के लिए server पर dynamic rendering की ज़रूरत होती है। diff --git a/docs/hi/docs/tutorial/handling-errors.md b/docs/hi/docs/tutorial/handling-errors.md new file mode 100644 index 000000000..ee4570761 --- /dev/null +++ b/docs/hi/docs/tutorial/handling-errors.md @@ -0,0 +1,244 @@ +# Errors को हैंडल करना { #handling-errors } + +ऐसी कई स्थितियाँ होती हैं जिनमें आपको अपनी API का उपयोग कर रहे client को error report करना पड़ता है। + +यह client frontend वाला कोई browser, किसी और का code, कोई IoT device आदि हो सकता है। + +आपको client को यह बताने की ज़रूरत पड़ सकती है कि: + +* client के पास उस operation के लिए पर्याप्त privileges नहीं हैं। +* client के पास उस resource का access नहीं है। +* जिस item को client access करने की कोशिश कर रहा था, वह मौजूद नहीं है। +* आदि। + +इन मामलों में, आप सामान्यतः **400** की range (400 से 499 तक) में एक **HTTP status code** return करेंगे। + +यह 200 HTTP status codes (200 से 299 तक) जैसा ही है। वे "200" status codes का मतलब है कि request में किसी तरह "success" हुआ था। + +400 range के status codes का मतलब है कि client की तरफ़ से कोई error था। + +वे सभी **"404 Not Found"** errors (और jokes) याद हैं? + +## `HTTPException` का उपयोग करें { #use-httpexception } + +Client को errors वाली HTTP responses return करने के लिए आप `HTTPException` का उपयोग करते हैं। + +### `HTTPException` import करें { #import-httpexception } + +{* ../../docs_src/handling_errors/tutorial001_py310.py hl[1] *} + +### अपने code में `HTTPException` raise करें { #raise-an-httpexception-in-your-code } + +`HTTPException` APIs के लिए प्रासंगिक अतिरिक्त data के साथ एक सामान्य Python exception है। + +क्योंकि यह एक Python exception है, आप इसे `return` नहीं करते, आप इसे `raise` करते हैं। + +इसका यह भी मतलब है कि अगर आप किसी utility function के अंदर हैं जिसे आप अपनी *path operation function* के अंदर call कर रहे हैं, और आप उस utility function के अंदर से `HTTPException` raise करते हैं, तो यह *path operation function* में बाकी code नहीं चलाएगा, यह उस request को तुरंत समाप्त कर देगा और `HTTPException` से HTTP error client को भेज देगा। + +किसी value को return करने के बजाय exception raise करने का लाभ Dependencies और Security वाले section में अधिक स्पष्ट होगा। + +इस example में, जब client किसी ऐसे ID से item request करता है जो मौजूद नहीं है, तो `404` के status code के साथ exception raise करें: + +{* ../../docs_src/handling_errors/tutorial001_py310.py hl[11] *} + +### परिणामी response { #the-resulting-response } + +अगर client `http://example.com/items/foo` (एक `item_id` `"foo"`) request करता है, तो उस client को 200 का HTTP status code और यह JSON response मिलेगा: + +```JSON +{ + "item": "The Foo Wrestlers" +} +``` + +लेकिन अगर client `http://example.com/items/bar` (एक non-existent `item_id` `"bar"`) request करता है, तो उस client को 404 का HTTP status code ("not found" error) और यह JSON response मिलेगा: + +```JSON +{ + "detail": "Item not found" +} +``` + +/// tip | सुझाव + +`HTTPException` raise करते समय, आप `detail` parameter के रूप में ऐसी कोई भी value pass कर सकते हैं जिसे JSON में convert किया जा सकता हो, केवल `str` ही नहीं। + +आप `dict`, `list` आदि pass कर सकते हैं। + +इन्हें **FastAPI** अपने आप handle करता है और JSON में convert करता है। + +/// + +## custom headers जोड़ें { #add-custom-headers } + +कुछ स्थितियाँ ऐसी होती हैं जहाँ HTTP error में custom headers जोड़ पाना उपयोगी होता है। उदाहरण के लिए, कुछ प्रकार की security के लिए। + +आपको शायद अपने code में सीधे इसका उपयोग करने की ज़रूरत नहीं होगी। + +लेकिन अगर किसी advanced scenario में आपको इसकी ज़रूरत पड़े, तो आप custom headers जोड़ सकते हैं: + +{* ../../docs_src/handling_errors/tutorial002_py310.py hl[14] *} + +## custom exception handlers install करें { #install-custom-exception-handlers } + +आप [Starlette से वही exception utilities](https://www.starlette.dev/exceptions/) के साथ custom exception handlers जोड़ सकते हैं। + +मान लीजिए आपके पास एक custom exception `UnicornException` है जिसे आप (या कोई library जिसका आप उपयोग करते हैं) `raise` कर सकते हैं। + +और आप इस exception को FastAPI के साथ globally handle करना चाहते हैं। + +आप `@app.exception_handler()` के साथ custom exception handler जोड़ सकते हैं: + +{* ../../docs_src/handling_errors/tutorial003_py310.py hl[5:7,13:18,24] *} + +यहाँ, अगर आप `/unicorns/yolo` request करते हैं, तो *path operation* एक `UnicornException` `raise` करेगा। + +लेकिन इसे `unicorn_exception_handler` द्वारा handle किया जाएगा। + +इसलिए, आपको `418` के HTTP status code और इस JSON content के साथ एक साफ़ error मिलेगा: + +```JSON +{"message": "Oops! yolo did something. There goes a rainbow..."} +``` + +/// note | Technical Details + +आप `from starlette.requests import Request` और `from starlette.responses import JSONResponse` का भी उपयोग कर सकते हैं। + +**FastAPI** आपकी, developer की, सुविधा के लिए `starlette.responses` को `fastapi.responses` के रूप में उपलब्ध कराता है। लेकिन उपलब्ध अधिकांश responses सीधे Starlette से आते हैं। `Request` के साथ भी यही है। + +/// + +## default exception handlers को override करें { #override-the-default-exception-handlers } + +**FastAPI** में कुछ default exception handlers होते हैं। + +ये handlers default JSON responses return करने के लिए ज़िम्मेदार होते हैं, जब आप `HTTPException` `raise` करते हैं और जब request में invalid data होता है। + +आप इन exception handlers को अपने खुद के handlers से override कर सकते हैं। + +### request validation exceptions को override करें { #override-request-validation-exceptions } + +जब किसी request में invalid data होता है, तो **FastAPI** internally एक `RequestValidationError` raise करता है। + +और इसमें इसके लिए एक default exception handler भी शामिल होता है। + +इसे override करने के लिए, `RequestValidationError` import करें और exception handler को decorate करने के लिए इसे `@app.exception_handler(RequestValidationError)` के साथ उपयोग करें। + +Exception handler को एक `Request` और exception मिलेगा। + +{* ../../docs_src/handling_errors/tutorial004_py310.py hl[2,14:19] *} + +अब, अगर आप `/items/foo` पर जाते हैं, तो default JSON error पाने के बजाय: + +```JSON +{ + "detail": [ + { + "loc": [ + "path", + "item_id" + ], + "msg": "value is not a valid integer", + "type": "type_error.integer" + } + ] +} +``` + +आपको text version मिलेगा, जिसमें होगा: + +``` +Validation errors: +Field: ('path', 'item_id'), Error: Input should be a valid integer, unable to parse string as an integer +``` + +### `HTTPException` error handler को override करें { #override-the-httpexception-error-handler } + +उसी तरह, आप `HTTPException` handler को override कर सकते हैं। + +उदाहरण के लिए, आप इन errors के लिए JSON के बजाय plain text response return करना चाह सकते हैं: + +{* ../../docs_src/handling_errors/tutorial004_py310.py hl[3:4,9:11,25] *} + +/// note | Technical Details + +आप `from starlette.responses import PlainTextResponse` का भी उपयोग कर सकते हैं। + +**FastAPI** आपकी, developer की, सुविधा के लिए `starlette.responses` को `fastapi.responses` के रूप में उपलब्ध कराता है। लेकिन उपलब्ध अधिकांश responses सीधे Starlette से आते हैं। + +/// + +/// warning | चेतावनी + +ध्यान रखें कि `RequestValidationError` में file name और उस line की जानकारी होती है जहाँ validation error होता है, ताकि अगर आप चाहें तो relevant जानकारी के साथ उसे अपने logs में दिखा सकें। + +लेकिन इसका मतलब है कि अगर आप इसे केवल string में convert करके वह जानकारी सीधे return कर देते हैं, तो आप अपने system के बारे में थोड़ी जानकारी leak कर सकते हैं, इसलिए यहाँ code हर error को अलग-अलग extract करके दिखाता है। + +/// + +### `RequestValidationError` body का उपयोग करें { #use-the-requestvalidationerror-body } + +`RequestValidationError` में वह `body` होता है जो इसे invalid data के साथ मिला था। + +आप अपनी app develop करते समय body को log और debug करने, user को return करने आदि के लिए इसका उपयोग कर सकते हैं। + +{* ../../docs_src/handling_errors/tutorial005_py310.py hl[14] *} + +अब ऐसा invalid item भेजकर देखें: + +```JSON +{ + "title": "towel", + "size": "XL" +} +``` + +आपको एक response मिलेगा जो बताता है कि data invalid है और जिसमें received body शामिल होगा: + +```JSON hl_lines="12-15" +{ + "detail": [ + { + "loc": [ + "body", + "size" + ], + "msg": "value is not a valid integer", + "type": "type_error.integer" + } + ], + "body": { + "title": "towel", + "size": "XL" + } +} +``` + +#### FastAPI का `HTTPException` बनाम Starlette का `HTTPException` { #fastapis-httpexception-vs-starlettes-httpexception } + +**FastAPI** का अपना `HTTPException` है। + +और **FastAPI** की `HTTPException` error class, Starlette की `HTTPException` error class से inherit करती है। + +केवल अंतर यह है कि **FastAPI** का `HTTPException`, `detail` field के लिए कोई भी JSON-able data accept करता है, जबकि Starlette का `HTTPException` इसके लिए केवल strings accept करता है। + +इसलिए, आप अपने code में सामान्य रूप से **FastAPI** का `HTTPException` raise करते रह सकते हैं। + +लेकिन जब आप exception handler register करते हैं, तो आपको उसे Starlette के `HTTPException` के लिए register करना चाहिए। + +इस तरह, अगर Starlette के internal code का कोई हिस्सा, या कोई Starlette extension या plug-in, Starlette `HTTPException` raise करता है, तो आपका handler उसे catch और handle कर पाएगा। + +इस example में, एक ही code में दोनों `HTTPException`s रखने के लिए, Starlette के exceptions को `StarletteHTTPException` नाम दिया गया है: + +```Python +from starlette.exceptions import HTTPException as StarletteHTTPException +``` + +### **FastAPI** के exception handlers का फिर से उपयोग करें { #reuse-fastapis-exception-handlers } + +अगर आप **FastAPI** के उन्हीं default exception handlers के साथ exception का उपयोग करना चाहते हैं, तो आप `fastapi.exception_handlers` से default exception handlers import करके उनका फिर से उपयोग कर सकते हैं: + +{* ../../docs_src/handling_errors/tutorial006_py310.py hl[2:5,15,21] *} + +इस example में आप केवल error को बहुत expressive message के साथ print कर रहे हैं, लेकिन आप बात समझ गए। आप exception का उपयोग कर सकते हैं और फिर बस default exception handlers का फिर से उपयोग कर सकते हैं। diff --git a/docs/hi/docs/tutorial/header-param-models.md b/docs/hi/docs/tutorial/header-param-models.md new file mode 100644 index 000000000..4c15aa579 --- /dev/null +++ b/docs/hi/docs/tutorial/header-param-models.md @@ -0,0 +1,72 @@ +# Header Parameter Models { #header-parameter-models } + +अगर आपके पास संबंधित **header parameters** का एक समूह है, तो आप उन्हें declare करने के लिए एक **Pydantic model** बना सकते हैं। + +इससे आप **model को फिर से उपयोग** कर पाएंगे, **कई जगहों** पर, और साथ ही सभी parameters के लिए validations और metadata एक साथ declare कर पाएंगे। 😎 + +/// note | नोट + +यह FastAPI version `0.115.0` से समर्थित है। 🤓 + +/// + +## Pydantic Model के साथ Header Parameters { #header-parameters-with-a-pydantic-model } + +जिन **header parameters** की आपको ज़रूरत है, उन्हें एक **Pydantic model** में declare करें, और फिर parameter को `Header` के रूप में declare करें: + +{* ../../docs_src/header_param_models/tutorial001_an_py310.py hl[9:14,18] *} + +**FastAPI** request में **headers** से **हर field** का data **extract** करेगा और आपको वह Pydantic model देगा जिसे आपने define किया है। + +## Docs देखें { #check-the-docs } + +आप `/docs` पर docs UI में required headers देख सकते हैं: + +
+ +
+ +## Extra Headers को मना करें { #forbid-extra-headers } + +कुछ विशेष use cases में (शायद बहुत आम नहीं), आप उन headers को **restrict** करना चाह सकते हैं जिन्हें आप receive करना चाहते हैं। + +आप Pydantic की model configuration का उपयोग करके किसी भी `extra` fields को `forbid` कर सकते हैं: + +{* ../../docs_src/header_param_models/tutorial002_an_py310.py hl[10] *} + +अगर कोई client कुछ **extra headers** भेजने की कोशिश करता है, तो उन्हें एक **error** response मिलेगा। + +उदाहरण के लिए, अगर client `plumbus` के value के साथ एक `tool` header भेजने की कोशिश करता है, तो उन्हें एक **error** response मिलेगा जो बताएगा कि header parameter `tool` की अनुमति नहीं है: + +```json +{ + "detail": [ + { + "type": "extra_forbidden", + "loc": ["header", "tool"], + "msg": "Extra inputs are not permitted", + "input": "plumbus", + } + ] +} +``` + +## Convert Underscores को Disable करें { #disable-convert-underscores } + +नियमित header parameters की तरह ही, जब parameter names में underscore characters होते हैं, तो वे **स्वचालित रूप से hyphens में convert** हो जाते हैं। + +उदाहरण के लिए, अगर आपके code में header parameter `save_data` है, तो अपेक्षित HTTP header `save-data` होगा, और docs में भी वह इसी तरह दिखाई देगा। + +अगर किसी कारण से आपको इस automatic conversion को disable करना है, तो आप header parameters के लिए Pydantic models में भी ऐसा कर सकते हैं। + +{* ../../docs_src/header_param_models/tutorial003_an_py310.py hl[19] *} + +/// warning | चेतावनी + +`convert_underscores` को `False` पर set करने से पहले, ध्यान रखें कि कुछ HTTP proxies और servers underscores वाले headers के उपयोग की अनुमति नहीं देते। + +/// + +## सारांश { #summary } + +आप **FastAPI** में **headers** declare करने के लिए **Pydantic models** का उपयोग कर सकते हैं। 😎 diff --git a/docs/hi/docs/tutorial/header-params.md b/docs/hi/docs/tutorial/header-params.md new file mode 100644 index 000000000..1b683248c --- /dev/null +++ b/docs/hi/docs/tutorial/header-params.md @@ -0,0 +1,91 @@ +# Header Parameters { #header-parameters } + +आप Header parameters को उसी तरह define कर सकते हैं जैसे आप `Query`, `Path` और `Cookie` parameters को define करते हैं। + +## `Header` import करें { #import-header } + +पहले `Header` import करें: + +{* ../../docs_src/header_params/tutorial001_an_py310.py hl[3] *} + +## `Header` parameters घोषित करें { #declare-header-parameters } + +फिर `Path`, `Query` और `Cookie` जैसी ही structure का उपयोग करके header parameters घोषित करें। + +आप default value के साथ-साथ सभी अतिरिक्त validation या annotation parameters भी define कर सकते हैं: + +{* ../../docs_src/header_params/tutorial001_an_py310.py hl[9] *} + +/// note | तकनीकी विवरण + +`Header` `Path`, `Query` और `Cookie` की एक "sister" class है। यह भी उसी common `Param` class से inherit करता है। + +लेकिन याद रखें कि जब आप `fastapi` से `Query`, `Path`, `Header`, और अन्य import करते हैं, तो वे वास्तव में functions होते हैं जो special classes return करते हैं। + +/// + +/// note | नोट + +headers घोषित करने के लिए, आपको `Header` का उपयोग करना होगा, क्योंकि अन्यथा parameters को query parameters के रूप में interpret किया जाएगा। + +/// + +## स्वचालित conversion { #automatic-conversion } + +`Header` में `Path`, `Query` और `Cookie` द्वारा दी जाने वाली functionality के ऊपर थोड़ी अतिरिक्त functionality होती है। + +अधिकांश standard headers एक "hyphen" character से अलग किए जाते हैं, जिसे "minus symbol" (`-`) भी कहा जाता है। + +लेकिन Python में `user-agent` जैसा variable invalid है। + +इसलिए, default रूप से, `Header` headers को extract और document करने के लिए parameter names के characters को underscore (`_`) से hyphen (`-`) में convert करेगा। + +साथ ही, HTTP headers case-insensitive होते हैं, इसलिए, आप उन्हें standard Python style (जिसे "snake_case" भी कहा जाता है) में declare कर सकते हैं। + +इसलिए, Python code में सामान्य रूप से जैसे आप `user_agent` का उपयोग करते हैं, वैसा ही कर सकते हैं, बजाय इसके कि आपको पहले अक्षरों को `User_Agent` की तरह capitalize करना पड़े या कुछ समान करना पड़े। + +अगर किसी कारण से आपको underscores से hyphens में automatic conversion disable करना हो, तो `Header` के parameter `convert_underscores` को `False` पर set करें: + +{* ../../docs_src/header_params/tutorial002_an_py310.py hl[10] *} + +/// warning | चेतावनी + +`convert_underscores` को `False` पर set करने से पहले, ध्यान रखें कि कुछ HTTP proxies और servers underscores वाले headers के उपयोग की अनुमति नहीं देते। + +/// + +## Duplicate headers { #duplicate-headers } + +duplicate headers receive करना संभव है। इसका मतलब है, कई values वाला वही header। + +आप type declaration में list का उपयोग करके ऐसे cases define कर सकते हैं। + +आप duplicate header से सभी values Python `list` के रूप में receive करेंगे। + +उदाहरण के लिए, `X-Token` का header declare करने के लिए जो एक से अधिक बार आ सकता है, आप लिख सकते हैं: + +{* ../../docs_src/header_params/tutorial003_an_py310.py hl[9] *} + +यदि आप उस *path operation* के साथ दो HTTP headers भेजते हुए communicate करते हैं, जैसे: + +``` +X-Token: foo +X-Token: bar +``` + +response ऐसा होगा: + +```JSON +{ + "X-Token values": [ + "bar", + "foo" + ] +} +``` + +## Recap { #recap } + +`Query`, `Path` और `Cookie` जैसे ही common pattern का उपयोग करते हुए, `Header` के साथ headers declare करें। + +और अपनी variables में underscores के बारे में चिंता न करें, **FastAPI** उन्हें convert करने का ध्यान रखेगा। diff --git a/docs/hi/docs/tutorial/index.md b/docs/hi/docs/tutorial/index.md new file mode 100644 index 000000000..f5aff090f --- /dev/null +++ b/docs/hi/docs/tutorial/index.md @@ -0,0 +1,101 @@ +# Tutorial - उपयोगकर्ता गाइड { #tutorial-user-guide } + +यह tutorial आपको step by step दिखाता है कि **FastAPI** को इसकी अधिकतर features के साथ कैसे उपयोग करें। + +हर section धीरे-धीरे पिछले section पर आधारित होता है, लेकिन इसे topics को अलग रखने के लिए संरचित किया गया है, ताकि आप अपनी खास API ज़रूरतों को हल करने के लिए सीधे किसी भी specific topic पर जा सकें। + +इसे भविष्य के reference के रूप में काम करने के लिए भी बनाया गया है, ताकि आप वापस आकर ठीक वही देख सकें जिसकी आपको ज़रूरत है। + +## code चलाएँ { #run-the-code } + +सभी code blocks को copy करके सीधे उपयोग किया जा सकता है (वे वास्तव में tested Python files हैं)। + +किसी भी example को चलाने के लिए, code को `main.py` file में copy करें, और `fastapi dev` शुरू करें: + +
+ +```console +$ fastapi dev + + FastAPI Starting development server 🚀 + + Searching for package file structure from directories + with __init__.py files + Importing from /home/user/code/awesomeapp + + module 🐍 main.py + + code Importing the FastAPI app object from the module with + the following code: + + from main import app + + app Using import string: main:app + + server Server started at http://127.0.0.1:8000 + server Documentation at http://127.0.0.1:8000/docs + + tip Running in development mode, for production use: + fastapi run + + Logs: + + INFO Will watch for changes in these directories: + ['/home/user/code/awesomeapp'] + INFO Uvicorn running on http://127.0.0.1:8000 (Press CTRL+C + to quit) + INFO Started reloader process [383138] using WatchFiles + INFO Started server process [383153] + INFO Waiting for application startup. + INFO Application startup complete. +``` + +
+ +यह **बहुत ज़्यादा प्रोत्साहित** किया जाता है कि आप code लिखें या copy करें, उसे edit करें और locally चलाएँ। + +इसे अपने editor में उपयोग करना ही वास्तव में आपको FastAPI के लाभ दिखाता है, जैसे आपको कितना कम code लिखना पड़ता है, सभी type checks, autocompletion, आदि। + +--- + +## FastAPI install करें { #install-fastapi } + +पहला step FastAPI install करना है। + +सुनिश्चित करें कि आप एक [virtual environment](../virtual-environments.md) बनाएँ, उसे activate करें, और फिर **FastAPI install करें**: + +
+ +```console +$ pip install "fastapi[standard]" + +---> 100% +``` + +
+ +/// note | नोट + +जब आप `pip install "fastapi[standard]"` के साथ install करते हैं, तो यह कुछ default optional standard dependencies के साथ आता है, जिनमें `fastapi-cloud-cli` शामिल है, जो आपको [FastAPI Cloud](https://fastapicloud.com) पर deploy करने देता है। + +अगर आप वे optional dependencies नहीं चाहते, तो इसके बजाय आप `pip install fastapi` install कर सकते हैं। + +अगर आप standard dependencies install करना चाहते हैं लेकिन `fastapi-cloud-cli` के बिना, तो आप `pip install "fastapi[standard-no-fastapi-cloud-cli]"` के साथ install कर सकते हैं। + +/// + +/// tip | सुझाव + +FastAPI के पास [VS Code के लिए official extension](https://marketplace.visualstudio.com/items?itemName=FastAPILabs.fastapi-vscode) (और Cursor) है, जो बहुत सारी features देता है, जिनमें path operation explorer, path operation search, tests में CodeLens navigation (tests से definition पर jump करना), और FastAPI Cloud deployment और logs शामिल हैं — सब कुछ आपके editor से। + +/// + +## उन्नत उपयोगकर्ता गाइड { #advanced-user-guide } + +एक **उन्नत उपयोगकर्ता गाइड** भी है जिसे आप इस **Tutorial - उपयोगकर्ता गाइड** के बाद पढ़ सकते हैं। + +**उन्नत उपयोगकर्ता गाइड** इसी पर आधारित है, वही concepts उपयोग करता है, और आपको कुछ अतिरिक्त features सिखाता है। + +लेकिन आपको पहले **Tutorial - उपयोगकर्ता गाइड** पढ़ना चाहिए (जो आप अभी पढ़ रहे हैं)। + +इसे इस तरह design किया गया है कि आप सिर्फ **Tutorial - उपयोगकर्ता गाइड** के साथ एक complete application बना सकें, और फिर अपनी ज़रूरतों के अनुसार **उन्नत उपयोगकर्ता गाइड** के कुछ अतिरिक्त ideas का उपयोग करके उसे अलग-अलग तरीकों से extend कर सकें। diff --git a/docs/hi/docs/tutorial/metadata.md b/docs/hi/docs/tutorial/metadata.md new file mode 100644 index 000000000..ef3f817a2 --- /dev/null +++ b/docs/hi/docs/tutorial/metadata.md @@ -0,0 +1,120 @@ +# Metadata और Docs URLs { #metadata-and-docs-urls } + +आप अपनी **FastAPI** application में कई metadata configurations को customize कर सकते हैं। + +## API के लिए Metadata { #metadata-for-api } + +आप निम्नलिखित fields set कर सकते हैं, जिनका उपयोग OpenAPI specification और automatic API docs UIs में किया जाता है: + +| Parameter | Type | विवरण | +|------------|------|-------------| +| `title` | `str` | API का title। | +| `summary` | `str` | API का एक छोटा summary। OpenAPI 3.1.0, FastAPI 0.99.0 से उपलब्ध। | +| `description` | `str` | API का एक छोटा description। यह Markdown का उपयोग कर सकता है। | +| `version` | `str` | API का version। यह आपकी अपनी application का version है, OpenAPI का नहीं। उदाहरण के लिए `2.5.0`। | +| `terms_of_service` | `str` | API के Terms of Service के लिए एक URL। यदि दिया गया हो, तो यह URL होना चाहिए। | +| `contact` | `dict` | exposed API के लिए contact information। इसमें कई fields हो सकते हैं।
contact fields
ParameterTypeविवरण
namestrcontact person/organization का identifying name।
urlstrcontact information की ओर point करने वाला URL। URL के format में होना चाहिए।
emailstrcontact person/organization का email address। email address के format में होना चाहिए।
| +| `license_info` | `dict` | exposed API के लिए license information। इसमें कई fields हो सकते हैं।
license_info fields
ParameterTypeविवरण
namestrREQUIRED (यदि license_info set किया गया हो)। API के लिए उपयोग किया गया license name।
identifierstrAPI के लिए एक [SPDX](https://spdx.org/licenses/) license expression। identifier field, url field के साथ mutually exclusive है। OpenAPI 3.1.0, FastAPI 0.99.0 से उपलब्ध।
urlstrAPI के लिए उपयोग किए गए license का URL। URL के format में होना चाहिए।
| + +आप इन्हें इस तरह set कर सकते हैं: + +{* ../../docs_src/metadata/tutorial001_py310.py hl[3:16, 19:32] *} + +/// tip | सुझाव + +आप `description` field में Markdown लिख सकते हैं और यह output में render होगा। + +/// + +इस configuration के साथ, automatic API docs इस तरह दिखेंगे: + + + +## License identifier { #license-identifier } + +OpenAPI 3.1.0 और FastAPI 0.99.0 से, आप `license_info` को `url` के बजाय `identifier` के साथ भी set कर सकते हैं। + +उदाहरण के लिए: + +{* ../../docs_src/metadata/tutorial001_1_py310.py hl[31] *} + +## Tags के लिए Metadata { #metadata-for-tags } + +आप अपने path operations को group करने के लिए उपयोग किए गए अलग-अलग tags के लिए `openapi_tags` parameter के साथ अतिरिक्त metadata भी जोड़ सकते हैं। + +यह प्रत्येक tag के लिए एक dictionary वाली list लेता है। + +प्रत्येक dictionary में हो सकता है: + +* `name` (**required**): वही tag name वाला `str`, जिसे आप अपने *path operations* और `APIRouter`s में `tags` parameter में उपयोग करते हैं। +* `description`: tag के लिए short description वाला `str`। इसमें Markdown हो सकता है और यह docs UI में दिखाया जाएगा। +* `externalDocs`: external documentation का वर्णन करने वाला `dict`, जिसमें: + * `description`: external docs के लिए short description वाला `str`। + * `url` (**required**): external documentation के लिए URL वाला `str`। + +### Tags के लिए metadata बनाएँ { #create-metadata-for-tags } + +आइए इसे `users` और `items` के tags वाले एक उदाहरण में आज़माते हैं। + +अपने tags के लिए metadata बनाएँ और उसे `openapi_tags` parameter में pass करें: + +{* ../../docs_src/metadata/tutorial004_py310.py hl[3:16,18] *} + +ध्यान दें कि आप descriptions के अंदर Markdown का उपयोग कर सकते हैं, उदाहरण के लिए "login" bold (**login**) में दिखेगा और "fancy" italics (_fancy_) में दिखेगा। + +/// tip | सुझाव + +आपको अपने उपयोग किए गए सभी tags के लिए metadata जोड़ना ज़रूरी नहीं है। + +/// + +### अपने tags का उपयोग करें { #use-your-tags } + +अपने *path operations* (और `APIRouter`s) के साथ `tags` parameter का उपयोग करें, ताकि उन्हें अलग-अलग tags में assign किया जा सके: + +{* ../../docs_src/metadata/tutorial004_py310.py hl[21,26] *} + +/// note | नोट + +Tags के बारे में और पढ़ें [Path Operation Configuration](path-operation-configuration.md#tags) में। + +/// + +### Docs जाँचें { #check-the-docs } + +अब, अगर आप docs जाँचते हैं, तो वे सभी अतिरिक्त metadata दिखाएँगे: + + + +### Tags का क्रम { #order-of-tags } + +हर tag metadata dictionary का क्रम भी docs UI में दिखाए जाने वाले क्रम को define करता है। + +उदाहरण के लिए, भले ही `users` alphabetical order में `items` के बाद आता, यह उनसे पहले दिखाया जाता है, क्योंकि हमने उनकी metadata को list में पहली dictionary के रूप में जोड़ा था। + +## OpenAPI URL { #openapi-url } + +Default रूप से, OpenAPI schema `/openapi.json` पर serve किया जाता है। + +लेकिन आप इसे `openapi_url` parameter के साथ configure कर सकते हैं। + +उदाहरण के लिए, इसे `/api/v1/openapi.json` पर serve करने के लिए set करने हेतु: + +{* ../../docs_src/metadata/tutorial002_py310.py hl[3] *} + +यदि आप OpenAPI schema को पूरी तरह disable करना चाहते हैं, तो आप `openapi_url=None` set कर सकते हैं, इससे इसका उपयोग करने वाले documentation user interfaces भी disable हो जाएँगे। + +## Docs URLs { #docs-urls } + +आप शामिल किए गए दो documentation user interfaces configure कर सकते हैं: + +* **Swagger UI**: `/docs` पर serve किया जाता है। + * आप इसका URL `docs_url` parameter के साथ set कर सकते हैं। + * आप `docs_url=None` set करके इसे disable कर सकते हैं। +* **ReDoc**: `/redoc` पर serve किया जाता है। + * आप इसका URL `redoc_url` parameter के साथ set कर सकते हैं। + * आप `redoc_url=None` set करके इसे disable कर सकते हैं। + +उदाहरण के लिए, Swagger UI को `/documentation` पर serve करने के लिए set करना और ReDoc को disable करना: + +{* ../../docs_src/metadata/tutorial003_py310.py hl[3] *} diff --git a/docs/hi/docs/tutorial/middleware.md b/docs/hi/docs/tutorial/middleware.md new file mode 100644 index 000000000..0fd2be7a9 --- /dev/null +++ b/docs/hi/docs/tutorial/middleware.md @@ -0,0 +1,95 @@ +# Middleware { #middleware } + +आप **FastAPI** applications में middleware जोड़ सकते हैं। + +"middleware" एक function है जो हर **request** के साथ काम करता है, इससे पहले कि उसे किसी विशेष *path operation* द्वारा process किया जाए। और हर **response** के साथ भी, उसे लौटाने से पहले। + +* यह आपके application में आने वाली हर **request** लेता है। +* फिर यह उस **request** के साथ कुछ कर सकता है या कोई required code चला सकता है। +* फिर यह **request** को application के बाकी हिस्से द्वारा process होने के लिए आगे भेजता है (किसी *path operation* द्वारा)। +* फिर यह application द्वारा generate किया गया **response** लेता है (किसी *path operation* द्वारा)। +* यह उस **response** के साथ कुछ कर सकता है या कोई required code चला सकता है। +* फिर यह **response** लौटाता है। + +/// note | तकनीकी विवरण + +अगर आपके पास `yield` वाली dependencies हैं, तो exit code middleware के *बाद* चलेगा। + +अगर कोई background tasks थे ([Background Tasks](background-tasks.md) section में कवर किया गया है, आप इसे बाद में देखेंगे), तो वे सभी middleware के *बाद* चलेंगे। + +/// + +## Middleware बनाएं { #create-a-middleware } + +middleware बनाने के लिए आप किसी function के ऊपर decorator `@app.middleware("http")` का उपयोग करते हैं। + +middleware function को मिलता है: + +* `request`। +* एक function `call_next` जो `request` को parameter के रूप में प्राप्त करेगा। + * यह function `request` को संबंधित *path operation* तक पास करेगा। + * फिर यह संबंधित *path operation* द्वारा generate किया गया `response` लौटाता है। +* फिर आप `response` लौटाने से पहले उसे और modify कर सकते हैं। + +{* ../../docs_src/middleware/tutorial001_py310.py hl[8:9,11,14] *} + +/// tip | सुझाव + +ध्यान रखें कि custom proprietary headers को [`X-` prefix का उपयोग करके](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers) जोड़ा जा सकता है। + +लेकिन अगर आपके पास custom headers हैं जिन्हें आप browser में client को दिखाना चाहते हैं, तो आपको उन्हें अपने CORS configurations ([CORS (Cross-Origin Resource Sharing)](cors.md)) में `expose_headers` parameter का उपयोग करके जोड़ना होगा, जैसा कि [Starlette के CORS docs](https://www.starlette.dev/middleware/#corsmiddleware) में documented है। + +/// + +/// note | तकनीकी विवरण + +आप `from starlette.requests import Request` भी उपयोग कर सकते हैं। + +**FastAPI** इसे आपके लिए, developer की सुविधा के रूप में provide करता है। लेकिन यह सीधे Starlette से आता है। + +/// + +### `response` से पहले और बाद में { #before-and-after-the-response } + +आप `request` के साथ चलाने के लिए code जोड़ सकते हैं, इससे पहले कि कोई *path operation* उसे प्राप्त करे। + +और `response` generate होने के बाद भी, उसे लौटाने से पहले। + +उदाहरण के लिए, आप एक custom header `X-Process-Time` जोड़ सकते हैं जिसमें seconds में वह time हो जो request को process करने और response generate करने में लगा: + +{* ../../docs_src/middleware/tutorial001_py310.py hl[10,12:13] *} + +/// tip | सुझाव + +यहाँ हम `time.time()` के बजाय [`time.perf_counter()`](https://docs.python.org/3/library/time.html#time.perf_counter) का उपयोग करते हैं क्योंकि यह इन use cases के लिए अधिक precise हो सकता है। 🤓 + +/// + +## कई middleware का execution order { #multiple-middleware-execution-order } + +जब आप `@app.middleware()` decorator या `app.add_middleware()` method का उपयोग करके कई middleware जोड़ते हैं, तो हर नया middleware application को wrap करता है, जिससे एक stack बनता है। जो middleware अंत में जोड़ा जाता है वह *outermost* होता है, और पहला *innermost* होता है। + +request path पर, *outermost* middleware पहले चलता है। + +response path पर, यह अंत में चलता है। + +उदाहरण के लिए: + +```Python +app.add_middleware(MiddlewareA) +app.add_middleware(MiddlewareB) +``` + +इससे execution order यह होता है: + +* **Request**: MiddlewareB → MiddlewareA → route + +* **Response**: route → MiddlewareA → MiddlewareB + +यह stacking behavior सुनिश्चित करता है कि middleware एक predictable और controllable order में execute हों। + +## अन्य middleware { #other-middlewares } + +आप बाद में [Advanced User Guide: Advanced Middleware](../advanced/middleware.md) में अन्य middleware के बारे में और पढ़ सकते हैं। + +आप अगले section में middleware के साथ CORS को handle करने के बारे में पढ़ेंगे। diff --git a/docs/hi/docs/tutorial/path-operation-configuration.md b/docs/hi/docs/tutorial/path-operation-configuration.md new file mode 100644 index 000000000..99c63aec9 --- /dev/null +++ b/docs/hi/docs/tutorial/path-operation-configuration.md @@ -0,0 +1,107 @@ +# Path Operation Configuration { #path-operation-configuration } + +कई parameters हैं जिन्हें आप अपने *path operation decorator* को configure करने के लिए pass कर सकते हैं। + +/// warning | चेतावनी + +ध्यान दें कि ये parameters सीधे *path operation decorator* को pass किए जाते हैं, आपके *path operation function* को नहीं। + +/// + +## Response Status Code { #response-status-code } + +आप अपनी *path operation* की response में उपयोग किए जाने वाला (HTTP) `status_code` define कर सकते हैं। + +आप सीधे `int` code pass कर सकते हैं, जैसे `404`। + +लेकिन अगर आपको याद नहीं है कि हर number code किसके लिए है, तो आप `status` में shortcut constants का उपयोग कर सकते हैं: + +{* ../../docs_src/path_operation_configuration/tutorial001_py310.py hl[1,15] *} + +वह status code response में उपयोग किया जाएगा और OpenAPI schema में जोड़ा जाएगा। + +/// note | तकनीकी विवरण + +आप `from starlette import status` भी उपयोग कर सकते हैं। + +**FastAPI** आपकी सुविधा के लिए, developer के रूप में, वही `starlette.status` `fastapi.status` के रूप में प्रदान करता है। लेकिन यह सीधे Starlette से आता है। + +/// + +## Tags { #tags } + +आप अपनी *path operation* में tags जोड़ सकते हैं, parameter `tags` को `str` की `list` के साथ pass करें (आम तौर पर सिर्फ एक `str`): + +{* ../../docs_src/path_operation_configuration/tutorial002_py310.py hl[15,20,25] *} + +वे OpenAPI schema में जोड़े जाएंगे और automatic documentation interfaces द्वारा उपयोग किए जाएंगे: + + + +### Enums के साथ Tags { #tags-with-enums } + +अगर आपके पास एक बड़ी application है, तो आप अंत में **कई tags** जमा कर सकते हैं, और आप यह सुनिश्चित करना चाहेंगे कि related *path operations* के लिए आप हमेशा **एक ही tag** का उपयोग करें। + +इन मामलों में, tags को एक `Enum` में store करना समझदारी हो सकती है। + +**FastAPI** इसे plain strings की तरह ही support करता है: + +{* ../../docs_src/path_operation_configuration/tutorial002b_py310.py hl[1,8:10,13,18] *} + +## Summary और description { #summary-and-description } + +आप `summary` और `description` जोड़ सकते हैं: + +{* ../../docs_src/path_operation_configuration/tutorial003_py310.py hl[17:18] *} + +## Docstring से description { #description-from-docstring } + +क्योंकि descriptions आम तौर पर लंबी होती हैं और कई lines में फैलती हैं, आप *path operation* की description को function docstring में declare कर सकते हैं और **FastAPI** उसे वहीं से पढ़ेगा। + +आप docstring में [Markdown](https://en.wikipedia.org/wiki/Markdown) लिख सकते हैं, इसे सही तरीके से interpret और display किया जाएगा (docstring indentation को ध्यान में रखते हुए)। + +{* ../../docs_src/path_operation_configuration/tutorial004_py310.py hl[17:25] *} + +इसे interactive docs में उपयोग किया जाएगा: + + + +## Response description { #response-description } + +आप parameter `response_description` के साथ response description specify कर सकते हैं: + +{* ../../docs_src/path_operation_configuration/tutorial005_py310.py hl[18] *} + +/// note | नोट + +ध्यान दें कि `response_description` विशेष रूप से response को refer करता है, जबकि `description` सामान्य रूप से *path operation* को refer करता है। + +/// + +/// tip | सुझाव + +OpenAPI specify करता है कि प्रत्येक *path operation* को response description required होती है। + +इसलिए, अगर आप कोई provide नहीं करते, तो **FastAPI** अपने आप "Successful response" generate कर देगा। + +/// + + + +## एक *path operation* को Deprecated करें { #deprecate-a-path-operation } + +अगर आपको किसी *path operation* को deprecated के रूप में mark करना है, लेकिन उसे हटाना नहीं है, तो parameter `deprecated` pass करें: + +{* ../../docs_src/path_operation_configuration/tutorial006_py310.py hl[16] *} + +इसे interactive docs में स्पष्ट रूप से deprecated के रूप में mark किया जाएगा: + + + +देखें कि deprecated और non-deprecated *path operations* कैसे दिखते हैं: + + + +## Recap { #recap } + +आप *path operation decorators* को parameters pass करके अपनी *path operations* के लिए metadata आसानी से configure और add कर सकते हैं। diff --git a/docs/hi/docs/tutorial/path-params-numeric-validations.md b/docs/hi/docs/tutorial/path-params-numeric-validations.md new file mode 100644 index 000000000..59ecd7c4e --- /dev/null +++ b/docs/hi/docs/tutorial/path-params-numeric-validations.md @@ -0,0 +1,154 @@ +# Path Parameters और संख्यात्मक Validations { #path-parameters-and-numeric-validations } + +जिस तरह आप `Query` के साथ query parameters के लिए अधिक validations और metadata घोषित कर सकते हैं, उसी तरह आप `Path` के साथ path parameters के लिए उसी प्रकार की validations और metadata घोषित कर सकते हैं। + +## `Path` import करें { #import-path } + +सबसे पहले, `fastapi` से `Path` import करें, और `Annotated` import करें: + +{* ../../docs_src/path_params_numeric_validations/tutorial001_an_py310.py hl[1,3] *} + +/// note | नोट + +FastAPI ने version 0.95.0 में `Annotated` के लिए support जोड़ा था (और इसकी सिफारिश करना शुरू किया था)। + +अगर आपके पास पुराना version है, तो `Annotated` का उपयोग करने की कोशिश करते समय आपको errors मिलेंगे। + +`Annotated` का उपयोग करने से पहले सुनिश्चित करें कि आप [FastAPI version को Upgrade करें](../deployment/versions.md#upgrading-the-fastapi-versions) कम से कम 0.95.1 तक। + +/// + +## Metadata घोषित करें { #declare-metadata } + +आप `Query` के लिए जैसे सभी parameters घोषित करते हैं, वैसे ही यहाँ भी कर सकते हैं। + +उदाहरण के लिए, path parameter `item_id` के लिए `title` metadata value घोषित करने के लिए आप लिख सकते हैं: + +{* ../../docs_src/path_params_numeric_validations/tutorial001_an_py310.py hl[10] *} + +/// note | नोट + +एक path parameter हमेशा required होता है क्योंकि उसे path का हिस्सा होना होता है। भले ही आपने इसे `None` के साथ घोषित किया हो या कोई default value सेट की हो, इससे कुछ भी प्रभावित नहीं होगा, यह फिर भी हमेशा required रहेगा। + +/// + +## Parameters को अपनी ज़रूरत के अनुसार क्रम दें { #order-the-parameters-as-you-need } + +/// tip | सुझाव + +यदि आप `Annotated` का उपयोग करते हैं, तो यह शायद उतना महत्वपूर्ण या ज़रूरी नहीं है। + +/// + +मान लें कि आप query parameter `q` को required `str` के रूप में घोषित करना चाहते हैं। + +और आपको उस parameter के लिए कुछ और घोषित करने की ज़रूरत नहीं है, इसलिए वास्तव में आपको `Query` का उपयोग करने की ज़रूरत नहीं है। + +लेकिन आपको फिर भी `item_id` path parameter के लिए `Path` का उपयोग करना होगा। और किसी कारण से आप `Annotated` का उपयोग नहीं करना चाहते। + +यदि आप किसी ऐसे value को, जिसके पास "default" है, ऐसे value से पहले रखते हैं जिसके पास "default" नहीं है, तो Python शिकायत करेगा। + +लेकिन आप उनका क्रम बदल सकते हैं, और बिना default वाले value (query parameter `q`) को पहले रख सकते हैं। + +**FastAPI** के लिए इससे फर्क नहीं पड़ता। यह parameters को उनके नामों, types और default declarations (`Query`, `Path`, आदि) से पहचान लेगा, इसे क्रम से कोई फर्क नहीं पड़ता। + +तो, आप अपनी function इस तरह घोषित कर सकते हैं: + +{* ../../docs_src/path_params_numeric_validations/tutorial002_py310.py hl[7] *} + +लेकिन ध्यान रखें कि यदि आप `Annotated` का उपयोग करते हैं, तो आपको यह समस्या नहीं होगी, क्योंकि आप `Query()` या `Path()` के लिए function parameter default values का उपयोग नहीं कर रहे हैं। + +{* ../../docs_src/path_params_numeric_validations/tutorial002_an_py310.py *} + +## Parameters को अपनी ज़रूरत के अनुसार क्रम दें, tricks { #order-the-parameters-as-you-need-tricks } + +/// tip | सुझाव + +यदि आप `Annotated` का उपयोग करते हैं, तो यह शायद उतना महत्वपूर्ण या ज़रूरी नहीं है। + +/// + +यहाँ एक **छोटी trick** है जो काम आ सकती है, लेकिन आपको इसकी अक्सर ज़रूरत नहीं पड़ेगी। + +यदि आप चाहते हैं कि: + +* `q` query parameter को बिना `Query` और बिना किसी default value के घोषित करें +* path parameter `item_id` को `Path` का उपयोग करके घोषित करें +* उन्हें अलग क्रम में रखें +* `Annotated` का उपयोग न करें + +...तो Python में इसके लिए एक छोटी विशेष syntax है। + +function के पहले parameter के रूप में `*` पास करें। + +Python उस `*` के साथ कुछ नहीं करेगा, लेकिन उसे पता चल जाएगा कि उसके बाद आने वाले सभी parameters को keyword arguments (key-value pairs) के रूप में call किया जाना चाहिए, जिन्हें kwargs भी कहा जाता है। भले ही उनके पास default value न हो। + +{* ../../docs_src/path_params_numeric_validations/tutorial003_py310.py hl[7] *} + +### `Annotated` के साथ बेहतर { #better-with-annotated } + +ध्यान रखें कि यदि आप `Annotated` का उपयोग करते हैं, तो चूँकि आप function parameter default values का उपयोग नहीं कर रहे हैं, आपको यह समस्या नहीं होगी, और शायद आपको `*` का उपयोग करने की ज़रूरत नहीं पड़ेगी। + +{* ../../docs_src/path_params_numeric_validations/tutorial003_an_py310.py hl[10] *} + +## Number validations: greater than or equal { #number-validations-greater-than-or-equal } + +`Query` और `Path` (और अन्य जिन्हें आप बाद में देखेंगे) के साथ आप number constraints घोषित कर सकते हैं। + +यहाँ, `ge=1` के साथ, `item_id` को `1` से "`g`reater than or `e`qual" integer number होना होगा। + +{* ../../docs_src/path_params_numeric_validations/tutorial004_an_py310.py hl[10] *} + +## Number validations: greater than और less than or equal { #number-validations-greater-than-and-less-than-or-equal } + +यही बात इन पर भी लागू होती है: + +* `gt`: `g`reater `t`han +* `le`: `l`ess than or `e`qual + +{* ../../docs_src/path_params_numeric_validations/tutorial005_an_py310.py hl[10] *} + +## Number validations: floats, greater than और less than { #number-validations-floats-greater-than-and-less-than } + +Number validations `float` values के लिए भी काम करती हैं। + +यहीं पर gt घोषित कर पाना महत्वपूर्ण हो जाता है, सिर्फ ge नहीं। क्योंकि इसके साथ आप, उदाहरण के लिए, यह require कर सकते हैं कि कोई value `0` से अधिक होनी चाहिए, भले ही वह `1` से कम हो। + +तो, `0.5` एक valid value होगा। लेकिन `0.0` या `0` नहीं होंगे। + +और यही बात lt के लिए भी है। + +{* ../../docs_src/path_params_numeric_validations/tutorial006_an_py310.py hl[13] *} + +## Recap { #recap } + +`Query`, `Path` (और अन्य जिन्हें आपने अभी तक नहीं देखा है) के साथ आप metadata और string validations उसी तरह घोषित कर सकते हैं जैसे [Query Parameters और String Validations](query-params-str-validations.md) के साथ। + +और आप numeric validations भी घोषित कर सकते हैं: + +* `gt`: `g`reater `t`han +* `ge`: `g`reater than or `e`qual +* `lt`: `l`ess `t`han +* `le`: `l`ess than or `e`qual + +/// note | नोट + +`Query`, `Path`, और अन्य classes जिन्हें आप बाद में देखेंगे, एक common `Param` class की subclasses हैं। + +वे सभी अतिरिक्त validation और metadata के लिए वही parameters साझा करती हैं जिन्हें आपने देखा है। + +/// + +/// note | तकनीकी विवरण + +जब आप `fastapi` से `Query`, `Path` और अन्य import करते हैं, तो वे वास्तव में functions होते हैं। + +जब उन्हें call किया जाता है, तो वे उसी नाम की classes के instances return करते हैं। + +तो, आप `Query` import करते हैं, जो एक function है। और जब आप इसे call करते हैं, तो यह `Query` नाम की class का एक instance return करता है। + +ये functions इसलिए हैं (classes को सीधे उपयोग करने के बजाय) ताकि आपका editor उनके types के बारे में errors mark न करे। + +इस तरह आप उन errors को ignore करने के लिए custom configurations जोड़े बिना अपने सामान्य editor और coding tools का उपयोग कर सकते हैं। + +/// diff --git a/docs/hi/docs/tutorial/path-params.md b/docs/hi/docs/tutorial/path-params.md new file mode 100644 index 000000000..602ff1212 --- /dev/null +++ b/docs/hi/docs/tutorial/path-params.md @@ -0,0 +1,251 @@ +# Path Parameters { #path-parameters } + +आप Python format strings द्वारा इस्तेमाल किए जाने वाले समान syntax के साथ path "parameters" या "variables" declare कर सकते हैं: + +{* ../../docs_src/path_params/tutorial001_py310.py hl[6:7] *} + +path parameter `item_id` की value आपके function को argument `item_id` के रूप में pass की जाएगी। + +इसलिए, अगर आप यह example run करते हैं और [http://127.0.0.1:8000/items/foo](http://127.0.0.1:8000/items/foo) पर जाते हैं, तो आपको ऐसा response दिखाई देगा: + +```JSON +{"item_id":"foo"} +``` + +## Types के साथ Path parameters { #path-parameters-with-types } + +आप standard Python type annotations का उपयोग करके function में किसी path parameter का type declare कर सकते हैं: + +{* ../../docs_src/path_params/tutorial002_py310.py hl[7] *} + +इस मामले में, `item_id` को `int` declare किया गया है। + +/// tip | सुझाव + +इससे आपको अपने function के अंदर editor support मिलेगा, जिसमें error checks, completion आदि शामिल हैं। + +/// + +## Data conversion { #data-conversion } + +अगर आप यह example run करते हैं और अपने browser में [http://127.0.0.1:8000/items/3](http://127.0.0.1:8000/items/3) खोलते हैं, तो आपको ऐसा response दिखाई देगा: + +```JSON +{"item_id":3} +``` + +/// tip | सुझाव + +ध्यान दें कि आपके function ने जो value प्राप्त की (और return की) वह `3` है, Python `int` के रूप में, न कि string `"3"`। + +तो, उस type declaration के साथ, **FastAPI** आपको automatic request "parsing" देता है। + +/// + +## Data validation { #data-validation } + +लेकिन अगर आप browser में [http://127.0.0.1:8000/items/foo](http://127.0.0.1:8000/items/foo) पर जाते हैं, तो आपको ऐसा अच्छा HTTP error दिखाई देगा: + +```JSON +{ + "detail": [ + { + "type": "int_parsing", + "loc": [ + "path", + "item_id" + ], + "msg": "Input should be a valid integer, unable to parse string as an integer", + "input": "foo" + } + ] +} +``` + +क्योंकि path parameter `item_id` की value `"foo"` थी, जो कि `int` नहीं है। + +अगर आपने `int` के बजाय `float` दिया, तो भी वही error दिखाई देगा, जैसे: [http://127.0.0.1:8000/items/4.2](http://127.0.0.1:8000/items/4.2) + +/// tip | सुझाव + +तो, उसी Python type declaration के साथ, **FastAPI** आपको data validation देता है। + +ध्यान दें कि error यह भी स्पष्ट रूप से बताता है कि validation किस जगह pass नहीं हुआ। + +यह आपके API के साथ interact करने वाले code को develop और debug करते समय बेहद मददगार होता है। + +/// + +## Documentation { #documentation } + +और जब आप अपने browser में [http://127.0.0.1:8000/docs](http://127.0.0.1:8000/docs) खोलते हैं, तो आपको ऐसा automatic, interactive, API documentation दिखाई देगा: + + + +/// tip | सुझाव + +फिर से, बस उसी Python type declaration के साथ, **FastAPI** आपको automatic, interactive documentation देता है (Swagger UI को integrate करते हुए)। + +ध्यान दें कि path parameter को integer के रूप में declare किया गया है। + +/// + +## Standard-आधारित लाभ, वैकल्पिक documentation { #standards-based-benefits-alternative-documentation } + +और क्योंकि generate किया गया schema [OpenAPI](https://github.com/OAI/OpenAPI-Specification/blob/master/versions/3.1.0.md) standard से है, इसलिए कई compatible tools हैं। + +इसी वजह से, **FastAPI** स्वयं एक वैकल्पिक API documentation प्रदान करता है (ReDoc का उपयोग करते हुए), जिसे आप [http://127.0.0.1:8000/redoc](http://127.0.0.1:8000/redoc) पर access कर सकते हैं: + + + +इसी तरह, कई compatible tools हैं। इनमें कई भाषाओं के लिए code generation tools भी शामिल हैं। + +## Pydantic { #pydantic } + +सारा data validation अंदरूनी तौर पर [Pydantic](https://docs.pydantic.dev/) द्वारा किया जाता है, इसलिए आपको इसके सभी लाभ मिलते हैं। और आप जानते हैं कि आप अच्छे हाथों में हैं। + +आप `str`, `float`, `bool` और कई अन्य जटिल data types के साथ वही type declarations इस्तेमाल कर सकते हैं। + +इनमें से कई को tutorial के अगले chapters में explore किया गया है। + +## क्रम मायने रखता है { #order-matters } + +*path operations* बनाते समय, आपको ऐसी स्थितियाँ मिल सकती हैं जहाँ आपके पास एक fixed path हो। + +जैसे `/users/me`, मान लें कि यह current user के बारे में data प्राप्त करने के लिए है। + +और फिर आपके पास `/users/{user_id}` path भी हो सकता है, किसी specific user के बारे में किसी user ID से data प्राप्त करने के लिए। + +क्योंकि *path operations* का evaluation क्रम में किया जाता है, आपको यह सुनिश्चित करना होगा कि `/users/me` के लिए path, `/users/{user_id}` वाले path से पहले declare किया गया हो: + +{* ../../docs_src/path_params/tutorial003_py310.py hl[6,11] *} + +अन्यथा, `/users/{user_id}` के लिए path `/users/me` से भी match करेगा, यह "सोचते हुए" कि उसे `user_id` parameter मिल रहा है जिसकी value `"me"` है। + +इसी तरह, आप किसी path operation को फिर से define नहीं कर सकते: + +{* ../../docs_src/path_params/tutorial003b_py310.py hl[6,11] *} + +पहला वाला हमेशा इस्तेमाल किया जाएगा क्योंकि path पहले match करता है। + +## पहले से तय values { #predefined-values } + +अगर आपके पास ऐसा *path operation* है जो एक *path parameter* प्राप्त करता है, लेकिन आप चाहते हैं कि संभव valid *path parameter* values पहले से तय हों, तो आप standard Python `Enum` का उपयोग कर सकते हैं। + +### एक `Enum` class बनाएं { #create-an-enum-class } + +`Enum` import करें और एक sub-class बनाएं जो `str` और `Enum` से inherit करती हो। + +`str` से inherit करने पर API docs यह जान पाएंगे कि values का type `string` होना चाहिए और उन्हें सही तरह से render कर पाएंगे। + +फिर fixed values के साथ class attributes बनाएं, जो उपलब्ध valid values होंगी: + +{* ../../docs_src/path_params/tutorial005_py310.py hl[1,6:9] *} + +/// tip | सुझाव + +अगर आप सोच रहे हैं, "AlexNet", "ResNet", और "LeNet" बस Machine Learning models के नाम हैं। + +/// + +### एक *path parameter* declare करें { #declare-a-path-parameter } + +फिर आपके द्वारा बनाई गई enum class (`ModelName`) का उपयोग करके type annotation के साथ एक *path parameter* बनाएं: + +{* ../../docs_src/path_params/tutorial005_py310.py hl[16] *} + +### Docs देखें { #check-the-docs } + +क्योंकि *path parameter* के लिए उपलब्ध values पहले से तय हैं, interactive docs उन्हें अच्छे से दिखा सकते हैं: + + + +### Python *enumerations* के साथ काम करना { #working-with-python-enumerations } + +*path parameter* की value एक *enumeration member* होगी। + +#### *Enumeration members* की तुलना करें { #compare-enumeration-members } + +आप इसकी तुलना अपने बनाए हुए enum `ModelName` में मौजूद *enumeration member* से कर सकते हैं: + +{* ../../docs_src/path_params/tutorial005_py310.py hl[17] *} + +#### *Enumeration value* प्राप्त करें { #get-the-enumeration-value } + +आप `model_name.value` का उपयोग करके actual value (इस मामले में एक `str`) प्राप्त कर सकते हैं, या सामान्य रूप से, `your_enum_member.value`: + +{* ../../docs_src/path_params/tutorial005_py310.py hl[20] *} + +/// tip | सुझाव + +आप `ModelName.lenet.value` के साथ value `"lenet"` भी access कर सकते हैं। + +/// + +#### *Enumeration members* return करें { #return-enumeration-members } + +आप अपने *path operation* से *enum members* return कर सकते हैं, यहाँ तक कि JSON body में nested भी (जैसे एक `dict`)। + +Client को return करने से पहले उन्हें उनकी संबंधित values (इस मामले में strings) में convert कर दिया जाएगा: + +{* ../../docs_src/path_params/tutorial005_py310.py hl[18,21,23] *} + +अपने client में आपको ऐसा JSON response मिलेगा: + +```JSON +{ + "model_name": "alexnet", + "message": "Deep Learning FTW!" +} +``` + +## Paths रखने वाले Path parameters { #path-parameters-containing-paths } + +मान लें आपके पास path `/files/{file_path}` के साथ एक *path operation* है। + +लेकिन आपको `file_path` में स्वयं एक *path* रखना है, जैसे `home/johndoe/myfile.txt`। + +तो, उस file के लिए URL कुछ ऐसा होगा: `/files/home/johndoe/myfile.txt`। + +### OpenAPI support { #openapi-support } + +OpenAPI किसी *path parameter* को उसके अंदर एक *path* रखने के लिए declare करने का तरीका support नहीं करता, क्योंकि इससे ऐसे scenarios बन सकते हैं जिन्हें test और define करना कठिन हो। + +फिर भी, आप **FastAPI** में Starlette के internal tools में से एक का उपयोग करके यह कर सकते हैं। + +और docs फिर भी काम करेंगे, हालांकि ऐसा कोई documentation नहीं जोड़ेंगे जो बताए कि parameter में path होना चाहिए। + +### Path convertor { #path-convertor } + +Starlette से सीधे एक option का उपयोग करके, आप इस तरह के URL का उपयोग करते हुए एक *path* रखने वाला *path parameter* declare कर सकते हैं: + +``` +/files/{file_path:path} +``` + +इस मामले में, parameter का नाम `file_path` है, और आखिरी हिस्सा, `:path`, इसे बताता है कि parameter किसी भी *path* से match करना चाहिए। + +तो, आप इसे इसके साथ इस्तेमाल कर सकते हैं: + +{* ../../docs_src/path_params/tutorial004_py310.py hl[6] *} + +/// tip | सुझाव + +आपको parameter में `/home/johndoe/myfile.txt` रखना पड़ सकता है, leading slash (`/`) के साथ। + +उस मामले में, URL होगा: `/files//home/johndoe/myfile.txt`, `files` और `home` के बीच double slash (`//`) के साथ। + +/// + +## Recap { #recap } + +**FastAPI** के साथ, छोटे, सहज और standard Python type declarations का उपयोग करके, आपको मिलता है: + +* Editor support: error checks, autocompletion आदि। +* Data "parsing" +* Data validation +* API annotation और automatic documentation + +और आपको इन्हें केवल एक बार declare करना होता है। + +वैकल्पिक frameworks की तुलना में **FastAPI** का शायद यही मुख्य दिखने वाला लाभ है (raw performance के अलावा)। diff --git a/docs/hi/docs/tutorial/query-param-models.md b/docs/hi/docs/tutorial/query-param-models.md new file mode 100644 index 000000000..1727b7654 --- /dev/null +++ b/docs/hi/docs/tutorial/query-param-models.md @@ -0,0 +1,68 @@ +# Query Parameter Models { #query-parameter-models } + +अगर आपके पास संबंधित **query parameters** का एक समूह है, तो आप उन्हें declare करने के लिए एक **Pydantic model** बना सकते हैं। + +इससे आप **model को फिर से उपयोग** कर पाएँगे, **कई जगहों** पर, और साथ ही सभी parameters के लिए validations और metadata एक साथ declare कर पाएँगे। 😎 + +/// note | नोट + +यह FastAPI version `0.115.0` से supported है। 🤓 + +/// + +## Pydantic Model के साथ Query Parameters { #query-parameters-with-a-pydantic-model } + +जिन **query parameters** की आपको ज़रूरत है उन्हें एक **Pydantic model** में declare करें, और फिर parameter को `Query` के रूप में declare करें: + +{* ../../docs_src/query_param_models/tutorial001_an_py310.py hl[9:13,17] *} + +**FastAPI** request में मौजूद **query parameters** से **हर field** के लिए data **extract** करेगा और आपको वह Pydantic model देगा जिसे आपने define किया है। + +## Docs देखें { #check-the-docs } + +आप `/docs` पर docs UI में query parameters देख सकते हैं: + +
+ +
+ +## Extra Query Parameters को Forbid करें { #forbid-extra-query-parameters } + +कुछ विशेष use cases में (शायद बहुत आम नहीं), आप उन query parameters को **restrict** करना चाह सकते हैं जिन्हें आप receive करना चाहते हैं। + +आप किसी भी `extra` fields को `forbid` करने के लिए Pydantic की model configuration का उपयोग कर सकते हैं: + +{* ../../docs_src/query_param_models/tutorial002_an_py310.py hl[10] *} + +अगर कोई client **query parameters** में कुछ **extra** data भेजने की कोशिश करता है, तो उसे एक **error** response मिलेगा। + +उदाहरण के लिए, अगर client `plumbus` value के साथ `tool` query parameter भेजने की कोशिश करता है, जैसे: + +```http +https://example.com/items/?limit=10&tool=plumbus +``` + +उसे एक **error** response मिलेगा जो बताएगा कि query parameter `tool` allowed नहीं है: + +```json +{ + "detail": [ + { + "type": "extra_forbidden", + "loc": ["query", "tool"], + "msg": "Extra inputs are not permitted", + "input": "plumbus" + } + ] +} +``` + +## सारांश { #summary } + +आप **FastAPI** में **query parameters** declare करने के लिए **Pydantic models** का उपयोग कर सकते हैं। 😎 + +/// tip | सुझाव + +Spoiler alert: आप cookies और headers declare करने के लिए भी Pydantic models का उपयोग कर सकते हैं, लेकिन आप इसके बारे में tutorial में बाद में पढ़ेंगे। 🤫 + +/// diff --git a/docs/hi/docs/tutorial/query-params-str-validations.md b/docs/hi/docs/tutorial/query-params-str-validations.md new file mode 100644 index 000000000..05f2634a7 --- /dev/null +++ b/docs/hi/docs/tutorial/query-params-str-validations.md @@ -0,0 +1,450 @@ +# Query Parameters और String Validations { #query-parameters-and-string-validations } + +**FastAPI** आपको अपने parameters के लिए अतिरिक्त जानकारी और validation declare करने देता है। + +इस application को example के रूप में लेते हैं: + +{* ../../docs_src/query_params_str_validations/tutorial001_py310.py hl[7] *} + +query parameter `q` का type `str | None` है, इसका मतलब है कि यह type `str` का है लेकिन `None` भी हो सकता है, और वास्तव में, default value `None` है, इसलिए FastAPI जान जाएगा कि यह required नहीं है। + +/// note | नोट + +FastAPI जान जाएगा कि `q` की value required नहीं है क्योंकि default value `= None` है। + +`str | None` होने से आपका editor आपको बेहतर support दे पाएगा और errors detect कर पाएगा। + +/// + +## अतिरिक्त validation { #additional-validation } + +हम यह enforce करने जा रहे हैं कि भले ही `q` optional हो, जब भी यह provide किया जाए, **इसकी length 50 characters से अधिक न हो**। + +### `Query` और `Annotated` import करें { #import-query-and-annotated } + +इसे हासिल करने के लिए, पहले import करें: + +* `fastapi` से `Query` +* `typing` से `Annotated` + +{* ../../docs_src/query_params_str_validations/tutorial002_an_py310.py hl[1,3] *} + +/// note | नोट + +FastAPI ने version 0.95.0 में `Annotated` के लिए support जोड़ा (और इसकी recommendation शुरू की)। + +अगर आपके पास पुराना version है, तो `Annotated` use करने की कोशिश करने पर आपको errors मिलेंगे। + +`Annotated` use करने से पहले सुनिश्चित करें कि आप [FastAPI version Upgrade करें](../deployment/versions.md#upgrading-the-fastapi-versions) कम से कम 0.95.1 तक। + +/// + +## `q` parameter के type में `Annotated` use करें { #use-annotated-in-the-type-for-the-q-parameter } + +याद है मैंने आपको पहले बताया था कि [Python Types Intro](../python-types.md#type-hints-with-metadata-annotations) में `Annotated` का उपयोग आपके parameters में metadata जोड़ने के लिए किया जा सकता है? + +अब इसे FastAPI के साथ use करने का समय है। 🚀 + +हमारे पास यह type annotation था: + +```Python +q: str | None = None +``` + +हम इसे `Annotated` के साथ wrap करेंगे, तो यह बन जाता है: + +```Python +q: Annotated[str | None] = None +``` + +इन दोनों versions का मतलब एक ही है, `q` एक parameter है जो `str` या `None` हो सकता है, और default रूप से, यह `None` है। + +अब मज़ेदार चीज़ों पर चलते हैं। 🎉 + +## `q` parameter में `Annotated` में `Query` जोड़ें { #add-query-to-annotated-in-the-q-parameter } + +अब जब हमारे पास यह `Annotated` है जहाँ हम अधिक जानकारी रख सकते हैं (इस case में कुछ अतिरिक्त validation), `Annotated` के अंदर `Query` जोड़ें, और parameter `max_length` को `50` पर set करें: + +{* ../../docs_src/query_params_str_validations/tutorial002_an_py310.py hl[9] *} + +ध्यान दें कि default value अभी भी `None` है, इसलिए parameter अभी भी optional है। + +लेकिन अब, `Annotated` के अंदर `Query(max_length=50)` होने से, हम FastAPI को बता रहे हैं कि हम चाहते हैं कि इस value के लिए **अतिरिक्त validation** हो, हम चाहते हैं कि इसमें अधिकतम 50 characters हों। 😎 + +/// tip | टिप + +यहाँ हम `Query()` use कर रहे हैं क्योंकि यह एक **query parameter** है। बाद में हम `Path()`, `Body()`, `Header()`, और `Cookie()` जैसे अन्य देखेंगे, जो `Query()` जैसे ही arguments accept करते हैं। + +/// + +FastAPI अब: + +* data को **Validate** करेगा यह सुनिश्चित करते हुए कि max length 50 characters है +* जब data valid नहीं होगा तो client के लिए **clear error** दिखाएगा +* OpenAPI schema *path operation* में parameter को **Document** करेगा (ताकि यह **automatic docs UI** में दिखाई दे) + +## Alternative (पुराना): default value के रूप में `Query` { #alternative-old-query-as-the-default-value } + +FastAPI के पिछले versions (0.95.0 से पहले) में आपको अपने parameter की default value के रूप में `Query` use करना required था, बजाय इसे `Annotated` में रखने के, इसकी अच्छी संभावना है कि आपको आसपास ऐसा code दिखेगा, इसलिए मैं आपको इसे समझाऊंगा। + +/// tip | टिप + +नए code के लिए और जब भी संभव हो, ऊपर समझाए अनुसार `Annotated` use करें। इसके कई फायदे हैं (नीचे समझाए गए हैं) और कोई नुकसान नहीं। 🍰 + +/// + +इस तरह आप अपने function parameter की default value के रूप में `Query()` use करेंगे, parameter `max_length` को 50 पर set करते हुए: + +{* ../../docs_src/query_params_str_validations/tutorial002_py310.py hl[7] *} + +चूँकि इस case में (`Annotated` use किए बिना) हमें function में default value `None` को `Query()` से replace करना होता है, अब हमें parameter `Query(default=None)` के साथ default value set करनी होगी, यह उस default value को define करने का वही उद्देश्य पूरा करता है (कम से कम FastAPI के लिए)। + +तो: + +```Python +q: str | None = Query(default=None) +``` + +...parameter को optional बनाता है, `None` की default value के साथ, बिल्कुल इसके समान: + + +```Python +q: str | None = None +``` + +लेकिन `Query` version इसे स्पष्ट रूप से query parameter के रूप में declare करता है। + +फिर, हम `Query` को और parameters pass कर सकते हैं। इस case में, `max_length` parameter जो strings पर apply होता है: + +```Python +q: str | None = Query(default=None, max_length=50) +``` + +यह data को validate करेगा, data valid न होने पर clear error दिखाएगा, और OpenAPI schema *path operation* में parameter को document करेगा। + +### default value के रूप में या `Annotated` में `Query` { #query-as-the-default-value-or-in-annotated } + +ध्यान रखें कि `Annotated` के अंदर `Query` use करते समय आप `Query` के लिए `default` parameter use नहीं कर सकते। + +इसके बजाय, function parameter की वास्तविक default value use करें। अन्यथा, यह inconsistent होगा। + +उदाहरण के लिए, इसकी अनुमति नहीं है: + +```Python +q: Annotated[str, Query(default="rick")] = "morty" +``` + +...क्योंकि यह clear नहीं है कि default value `"rick"` होनी चाहिए या `"morty"`। + +तो, आप use करेंगे (preferably): + +```Python +q: Annotated[str, Query()] = "rick" +``` + +...या पुराने code bases में आपको मिलेगा: + +```Python +q: str = Query(default="rick") +``` + +### `Annotated` के फायदे { #advantages-of-annotated } + +function parameters में default value के बजाय **`Annotated` use करने की recommendation है**, यह कई कारणों से **बेहतर** है। 🤓 + +**function parameter** की **default** value ही **वास्तविक default** value है, यह सामान्य रूप से Python के साथ अधिक intuitive है। 😌 + +आप उसी function को FastAPI के बिना **अन्य जगहों** पर **call** कर सकते हैं, और यह **उम्मीद के अनुसार काम** करेगा। अगर कोई **required** parameter है (बिना default value के), तो आपका **editor** आपको error के साथ बता देगा, **Python** भी required parameter pass किए बिना इसे run करने पर complain करेगा। + +जब आप `Annotated` use नहीं करते और इसके बजाय **(पुराना) default value style** use करते हैं, अगर आप उस function को FastAPI के बिना **अन्य जगहों** पर call करते हैं, तो आपको function को सही से काम कराने के लिए arguments pass करना **याद रखना** होगा, अन्यथा values आपकी अपेक्षा से अलग होंगी (जैसे `str` के बजाय `QueryInfo` या कुछ similar)। और आपका editor complain नहीं करेगा, और Python भी उस function को run करते समय complain नहीं करेगा, केवल तब जब अंदर के operations error दें। + +क्योंकि `Annotated` में एक से अधिक metadata annotation हो सकते हैं, अब आप उसी function को अन्य tools के साथ भी use कर सकते हैं, जैसे [Typer](https://typer.tiangolo.com/)। 🚀 + +## और validations जोड़ें { #add-more-validations } + +आप parameter `min_length` भी जोड़ सकते हैं: + +{* ../../docs_src/query_params_str_validations/tutorial003_an_py310.py hl[10] *} + +## regular expressions जोड़ें { #add-regular-expressions } + +आप एक regular expression `pattern` define कर सकते हैं जिससे parameter match करना चाहिए: + +{* ../../docs_src/query_params_str_validations/tutorial004_an_py310.py hl[11] *} + +यह specific regular expression pattern check करता है कि received parameter value: + +* `^`: निम्न characters से शुरू होती है, पहले कोई characters नहीं हैं। +* `fixedquery`: exact value `fixedquery` रखती है। +* `$`: वहीं समाप्त होती है, `fixedquery` के बाद कोई और characters नहीं हैं। + +अगर आप इन सभी **"regular expression"** ideas से खोया हुआ महसूस करते हैं, तो चिंता न करें। यह कई लोगों के लिए कठिन topic है। आप अभी regular expressions की जरूरत के बिना भी बहुत कुछ कर सकते हैं। + +अब आप जानते हैं कि जब भी आपको इनकी जरूरत हो, आप इन्हें **FastAPI** में use कर सकते हैं। + +## Default values { #default-values } + +बेशक, आप `None` के अलावा default values use कर सकते हैं। + +मान लीजिए कि आप `q` query parameter को `3` की `min_length` और `"fixedquery"` की default value के साथ declare करना चाहते हैं: + +{* ../../docs_src/query_params_str_validations/tutorial005_an_py310.py hl[9] *} + +/// note | नोट + +`None` सहित किसी भी type की default value होना parameter को optional (not required) बनाता है। + +/// + +## Required parameters { #required-parameters } + +जब हमें अधिक validations या metadata declare करने की जरूरत नहीं होती, तो हम default value declare न करके ही `q` query parameter को required बना सकते हैं, जैसे: + +```Python +q: str +``` + +इसके बजाय: + +```Python +q: str | None = None +``` + +लेकिन अब हम इसे `Query` के साथ declare कर रहे हैं, उदाहरण के लिए ऐसे: + +```Python +q: Annotated[str | None, Query(min_length=3)] = None +``` + +तो, जब आपको `Query` use करते हुए किसी value को required के रूप में declare करना हो, तो आप बस default value declare न करें: + +{* ../../docs_src/query_params_str_validations/tutorial006_an_py310.py hl[9] *} + +### Required, `None` हो सकता है { #required-can-be-none } + +आप declare कर सकते हैं कि parameter `None` accept कर सकता है, लेकिन फिर भी यह required है। यह clients को value भेजने के लिए मजबूर करेगा, भले ही value `None` हो। + +ऐसा करने के लिए, आप declare कर सकते हैं कि `None` एक valid type है लेकिन बस default value declare न करें: + +{* ../../docs_src/query_params_str_validations/tutorial006c_an_py310.py hl[9] *} + +## Query parameter list / multiple values { #query-parameter-list-multiple-values } + +जब आप query parameter को स्पष्ट रूप से `Query` के साथ define करते हैं तो आप इसे values की list receive करने के लिए भी declare कर सकते हैं, या दूसरे शब्दों में, multiple values receive करने के लिए। + +उदाहरण के लिए, query parameter `q` declare करने के लिए जो URL में कई बार आ सकता है, आप लिख सकते हैं: + +{* ../../docs_src/query_params_str_validations/tutorial011_an_py310.py hl[9] *} + +फिर, ऐसे URL के साथ: + +``` +http://localhost:8000/items/?q=foo&q=bar +``` + +आप multiple `q` *query parameters* की values (`foo` और `bar`) को अपने *path operation function* के अंदर Python `list` में, *function parameter* `q` में receive करेंगे। + +तो, उस URL का response होगा: + +```JSON +{ + "q": [ + "foo", + "bar" + ] +} +``` + +/// tip | टिप + +ऊपर के example की तरह, `list` type वाला query parameter declare करने के लिए, आपको स्पष्ट रूप से `Query` use करना होगा, अन्यथा इसे request body के रूप में interpret किया जाएगा। + +/// + +interactive API docs accordingly update होंगे, ताकि multiple values allow हो सकें: + + + +### Defaults के साथ Query parameter list / multiple values { #query-parameter-list-multiple-values-with-defaults } + +अगर कोई values provide नहीं की गई हैं, तो आप values की default `list` भी define कर सकते हैं: + +{* ../../docs_src/query_params_str_validations/tutorial012_an_py310.py hl[9] *} + +अगर आप यहाँ जाते हैं: + +``` +http://localhost:8000/items/ +``` + +`q` का default होगा: `["foo", "bar"]` और आपका response होगा: + +```JSON +{ + "q": [ + "foo", + "bar" + ] +} +``` + +#### केवल `list` use करना { #using-just-list } + +आप `list[str]` के बजाय सीधे `list` भी use कर सकते हैं: + +{* ../../docs_src/query_params_str_validations/tutorial013_an_py310.py hl[9] *} + +/// note | नोट + +ध्यान रखें कि इस case में, FastAPI list की contents check नहीं करेगा। + +उदाहरण के लिए, `list[int]` check (और document) करेगा कि list की contents integers हैं। लेकिन केवल `list` ऐसा नहीं करेगा। + +/// + +## अधिक metadata declare करें { #declare-more-metadata } + +आप parameter के बारे में अधिक जानकारी जोड़ सकते हैं। + +वह जानकारी generated OpenAPI में शामिल होगी और documentation user interfaces और external tools द्वारा use की जाएगी। + +/// note | नोट + +ध्यान रखें कि अलग-अलग tools में OpenAPI support के अलग-अलग levels हो सकते हैं। + +उनमें से कुछ अभी declare की गई सारी extra information नहीं दिखा सकते, हालांकि अधिकतर cases में, missing feature पहले से ही development के लिए planned है। + +/// + +आप एक `title` जोड़ सकते हैं: + +{* ../../docs_src/query_params_str_validations/tutorial007_an_py310.py hl[10] *} + +और एक `description`: + +{* ../../docs_src/query_params_str_validations/tutorial008_an_py310.py hl[14] *} + +## Alias parameters { #alias-parameters } + +कल्पना करें कि आप parameter को `item-query` बनाना चाहते हैं। + +जैसे: + +``` +http://127.0.0.1:8000/items/?item-query=foobaritems +``` + +लेकिन `item-query` valid Python variable name नहीं है। + +सबसे निकटतम `item_query` होगा। + +लेकिन आपको अभी भी यह exactly `item-query` ही चाहिए... + +तब आप एक `alias` declare कर सकते हैं, और वही alias parameter value खोजने के लिए use किया जाएगा: + +{* ../../docs_src/query_params_str_validations/tutorial009_an_py310.py hl[9] *} + +## Parameters को deprecate करना { #deprecating-parameters } + +अब मान लीजिए कि आपको यह parameter अब पसंद नहीं है। + +आपको इसे कुछ समय के लिए वहीं छोड़ना होगा क्योंकि clients इसे use कर रहे हैं, लेकिन आप चाहते हैं कि docs इसे स्पष्ट रूप से deprecated के रूप में दिखाएँ। + +फिर parameter `deprecated=True` को `Query` में pass करें: + +{* ../../docs_src/query_params_str_validations/tutorial010_an_py310.py hl[19] *} + +docs इसे इस तरह दिखाएँगे: + + + +## OpenAPI से parameters exclude करें { #exclude-parameters-from-openapi } + +generated OpenAPI schema से query parameter exclude करने के लिए (और इस प्रकार, automatic documentation systems से), `Query` के parameter `include_in_schema` को `False` पर set करें: + +{* ../../docs_src/query_params_str_validations/tutorial014_an_py310.py hl[10] *} + +## Custom Validation { #custom-validation } + +ऐसे cases हो सकते हैं जहाँ आपको कुछ **custom validation** करना पड़े जो ऊपर दिखाए गए parameters से नहीं किया जा सकता। + +ऐसे cases में, आप एक **custom validator function** use कर सकते हैं जो normal validation के बाद apply होता है (जैसे value के `str` होने की validation के बाद)। + +आप इसे `Annotated` के अंदर [Pydantic के `AfterValidator`](https://docs.pydantic.dev/latest/concepts/validators/#field-after-validator) का उपयोग करके हासिल कर सकते हैं। + +/// tip | टिप + +Pydantic में [`BeforeValidator`](https://docs.pydantic.dev/latest/concepts/validators/#field-before-validator) और अन्य भी हैं। 🤓 + +/// + +उदाहरण के लिए, यह custom validator check करता है कि item ID किसी ISBN book number के लिए `isbn-` से शुरू होती है या किसी IMDB movie URL ID के लिए `imdb-` से: + +{* ../../docs_src/query_params_str_validations/tutorial015_an_py310.py hl[5,16:19,24] *} + +/// note | नोट + +यह Pydantic version 2 या उससे ऊपर के साथ available है। 😎 + +/// + +/// tip | टिप + +अगर आपको किसी भी प्रकार की validation करनी है जिसके लिए किसी **external component** से communicate करना required है, जैसे database या कोई अन्य API, तो आपको इसके बजाय **FastAPI Dependencies** use करनी चाहिए, आप इनके बारे में बाद में सीखेंगे। + +ये custom validators उन चीज़ों के लिए हैं जिन्हें request में provide किए गए **सिर्फ** **उसी data** से check किया जा सकता है। + +/// + +### उस Code को समझें { #understand-that-code } + +महत्वपूर्ण बात बस **`Annotated` के अंदर एक function के साथ `AfterValidator` use करना** है। आप चाहें तो इस part को skip कर सकते हैं। 🤸 + +--- + +लेकिन अगर आप इस specific code example के बारे में curious हैं और अभी भी entertained हैं, तो यहाँ कुछ extra details हैं। + +#### `value.startswith()` के साथ String { #string-with-value-startswith } + +क्या आपने ध्यान दिया? `value.startswith()` use करने वाली string tuple ले सकती है, और यह tuple की हर value check करेगी: + +{* ../../docs_src/query_params_str_validations/tutorial015_an_py310.py ln[16:19] hl[17] *} + +#### एक Random Item { #a-random-item } + +`data.items()` के साथ हमें tuples वाला एक iterable object मिलता है जिसमें हर dictionary item के लिए key और value होती है। + +हम इस iterable object को `list(data.items())` के साथ proper `list` में convert करते हैं। + +फिर `random.choice()` के साथ हम list से एक **random value** प्राप्त कर सकते हैं, तो हमें `(id, name)` वाला tuple मिलता है। यह कुछ ऐसा होगा `("imdb-tt0371724", "The Hitchhiker's Guide to the Galaxy")`। + +फिर हम tuple की **उन दो values को assign** करते हैं variables `id` और `name` को। + +तो, अगर user ने item ID provide नहीं की, तब भी उन्हें एक random suggestion receive होगा। + +...हम यह सब **एक single simple line** में करते हैं। 🤯 क्या आपको Python पसंद नहीं है? 🐍 + +{* ../../docs_src/query_params_str_validations/tutorial015_an_py310.py ln[22:30] hl[29] *} + +## Recap { #recap } + +आप अपने parameters के लिए अतिरिक्त validations और metadata declare कर सकते हैं। + +Generic validations और metadata: + +* `alias` +* `title` +* `description` +* `deprecated` + +Strings के लिए specific validations: + +* `min_length` +* `max_length` +* `pattern` + +`AfterValidator` का उपयोग करके custom validations। + +इन examples में आपने देखा कि `str` values के लिए validations कैसे declare करें। + +अगले chapters देखें ताकि आप सीख सकें कि numbers जैसे अन्य types के लिए validations कैसे declare करें। diff --git a/docs/hi/docs/tutorial/query-params.md b/docs/hi/docs/tutorial/query-params.md new file mode 100644 index 000000000..bc8573179 --- /dev/null +++ b/docs/hi/docs/tutorial/query-params.md @@ -0,0 +1,188 @@ +# Query Parameters { #query-parameters } + +जब आप ऐसे दूसरे function parameters declare करते हैं जो path parameters का हिस्सा नहीं हैं, तो उन्हें अपने-आप "query" parameters के रूप में समझा जाता है। + +{* ../../docs_src/query_params/tutorial001_py310.py hl[9] *} + +query उन key-value pairs का सेट है जो URL में `?` के बाद आते हैं, और `&` characters से अलग किए जाते हैं। + +उदाहरण के लिए, इस URL में: + +``` +http://127.0.0.1:8000/items/?skip=0&limit=10 +``` + +...query parameters हैं: + +* `skip`: `0` value के साथ +* `limit`: `10` value के साथ + +क्योंकि वे URL का हिस्सा हैं, वे "स्वाभाविक रूप से" strings होते हैं। + +लेकिन जब आप उन्हें Python types के साथ declare करते हैं (ऊपर दिए गए उदाहरण में, `int` के रूप में), तो उन्हें उस type में convert किया जाता है और उसके अनुसार validate किया जाता है। + +path parameters पर लागू होने वाली सभी वही प्रक्रियाएँ query parameters पर भी लागू होती हैं: + +* Editor support (स्पष्ट रूप से) +* Data "parsing" +* Data validation +* Automatic documentation + +## Defaults { #defaults } + +क्योंकि query parameters किसी path का fixed हिस्सा नहीं होते, वे optional हो सकते हैं और उनके default values हो सकते हैं। + +ऊपर दिए गए उदाहरण में उनके default values `skip=0` और `limit=10` हैं। + +तो, इस URL पर जाना: + +``` +http://127.0.0.1:8000/items/ +``` + +इस पर जाने जैसा ही होगा: + +``` +http://127.0.0.1:8000/items/?skip=0&limit=10 +``` + +लेकिन अगर आप, उदाहरण के लिए, इस पर जाते हैं: + +``` +http://127.0.0.1:8000/items/?skip=20 +``` + +तो आपके function में parameter values होंगी: + +* `skip=20`: क्योंकि आपने इसे URL में सेट किया है +* `limit=10`: क्योंकि वह default value था + +## Optional parameters { #optional-parameters } + +उसी तरह, आप optional query parameters declare कर सकते हैं, उनका default `None` सेट करके: + +{* ../../docs_src/query_params/tutorial002_py310.py hl[7] *} + +इस मामले में, function parameter `q` optional होगा, और default रूप से `None` होगा। + +/// tip | सुझाव + +यह भी ध्यान दें कि **FastAPI** इतना smart है कि यह पहचान लेता है कि path parameter `item_id` एक path parameter है और `q` नहीं है, इसलिए, यह एक query parameter है। + +/// + +## Query parameter type conversion { #query-parameter-type-conversion } + +आप `bool` types भी declare कर सकते हैं, और वे convert हो जाएँगे: + +{* ../../docs_src/query_params/tutorial003_py310.py hl[7] *} + +इस मामले में, अगर आप इस पर जाते हैं: + +``` +http://127.0.0.1:8000/items/foo?short=1 +``` + +या + +``` +http://127.0.0.1:8000/items/foo?short=True +``` + +या + +``` +http://127.0.0.1:8000/items/foo?short=true +``` + +या + +``` +http://127.0.0.1:8000/items/foo?short=on +``` + +या + +``` +http://127.0.0.1:8000/items/foo?short=yes +``` + +या कोई भी दूसरी case variation (uppercase, पहले अक्षर को uppercase, आदि), आपका function parameter `short` को `True` के `bool` value के साथ देखेगा। अन्यथा `False` के रूप में। + + +## कई path और query parameters { #multiple-path-and-query-parameters } + +आप एक ही समय में कई path parameters और query parameters declare कर सकते हैं, **FastAPI** जानता है कि कौन सा कौन है। + +और आपको उन्हें किसी विशेष order में declare करने की ज़रूरत नहीं है। + +उन्हें नाम से detect किया जाएगा: + +{* ../../docs_src/query_params/tutorial004_py310.py hl[6,8] *} + +## Required query parameters { #required-query-parameters } + +जब आप non-path parameters के लिए default value declare करते हैं (अभी तक, हमने केवल query parameters देखे हैं), तो वह required नहीं होता। + +अगर आप कोई specific value नहीं जोड़ना चाहते लेकिन बस उसे optional बनाना चाहते हैं, तो default को `None` के रूप में सेट करें। + +लेकिन जब आप किसी query parameter को required बनाना चाहते हैं, तो आप बस कोई default value declare न करें: + +{* ../../docs_src/query_params/tutorial005_py310.py hl[6:7] *} + +यहाँ query parameter `needy` type `str` का एक required query parameter है। + +अगर आप अपने browser में इस तरह का URL खोलते हैं: + +``` +http://127.0.0.1:8000/items/foo-item +``` + +...required parameter `needy` जोड़े बिना, तो आपको इस तरह की error दिखाई देगी: + +```JSON +{ + "detail": [ + { + "type": "missing", + "loc": [ + "query", + "needy" + ], + "msg": "Field required", + "input": null + } + ] +} +``` + +क्योंकि `needy` एक required parameter है, आपको इसे URL में सेट करना होगा: + +``` +http://127.0.0.1:8000/items/foo-item?needy=sooooneedy +``` + +...यह काम करेगा: + +```JSON +{ + "item_id": "foo-item", + "needy": "sooooneedy" +} +``` + +और निश्चित रूप से, आप कुछ parameters को required, कुछ को default value वाला, और कुछ को पूरी तरह optional define कर सकते हैं: + +{* ../../docs_src/query_params/tutorial006_py310.py hl[8] *} + +इस मामले में, 3 query parameters हैं: + +* `needy`, एक required `str`. +* `skip`, default value `0` के साथ एक `int`. +* `limit`, एक optional `int`. + +/// tip | सुझाव + +आप `Enum`s को भी उसी तरह use कर सकते हैं जैसे [Path Parameters](path-params.md#predefined-values) के साथ। + +/// diff --git a/docs/hi/docs/tutorial/request-files.md b/docs/hi/docs/tutorial/request-files.md new file mode 100644 index 000000000..4a79ca2b9 --- /dev/null +++ b/docs/hi/docs/tutorial/request-files.md @@ -0,0 +1,176 @@ +# Request Files { #request-files } + +आप client द्वारा अपलोड की जाने वाली files को `File` का उपयोग करके परिभाषित कर सकते हैं। + +/// note | नोट + +अपलोड की गई files प्राप्त करने के लिए, पहले [`python-multipart`](https://github.com/Kludex/python-multipart) install करें। + +सुनिश्चित करें कि आप एक [virtual environment](../virtual-environments.md) बनाते हैं, उसे activate करते हैं, और फिर इसे install करते हैं, उदाहरण के लिए: + +```console +$ pip install python-multipart +``` + +ऐसा इसलिए है क्योंकि अपलोड की गई files "form data" के रूप में भेजी जाती हैं। + +/// + +## `File` Import करें { #import-file } + +`fastapi` से `File` और `UploadFile` import करें: + +{* ../../docs_src/request_files/tutorial001_an_py310.py hl[3] *} + +## `File` Parameters परिभाषित करें { #define-file-parameters } + +file parameters उसी तरह बनाएं जैसे आप `Body` या `Form` के लिए बनाते हैं: + +{* ../../docs_src/request_files/tutorial001_an_py310.py hl[9] *} + +/// note | नोट + +`File` एक class है जो सीधे `Form` से inherit करती है। + +लेकिन याद रखें कि जब आप `fastapi` से `Query`, `Path`, `File` और अन्य import करते हैं, तो वे वास्तव में functions होते हैं जो विशेष classes return करते हैं। + +/// + +/// tip | सुझाव + +File bodies घोषित करने के लिए, आपको `File` का उपयोग करना होगा, क्योंकि अन्यथा parameters को query parameters या body (JSON) parameters के रूप में समझा जाएगा। + +/// + +files "form data" के रूप में अपलोड की जाएंगी। + +यदि आप अपने *path operation function* parameter का type `bytes` के रूप में घोषित करते हैं, तो **FastAPI** आपके लिए file पढ़ेगा और आपको सामग्री `bytes` के रूप में प्राप्त होगी। + +ध्यान रखें कि इसका मतलब है कि पूरी सामग्री memory में संग्रहीत होगी। यह छोटी files के लिए अच्छी तरह काम करेगा। + +लेकिन कई मामलों में आपको `UploadFile` का उपयोग करने से लाभ हो सकता है। + +## `UploadFile` के साथ File Parameters { #file-parameters-with-uploadfile } + +`UploadFile` type के साथ file parameter परिभाषित करें: + +{* ../../docs_src/request_files/tutorial001_an_py310.py hl[14] *} + +`bytes` की तुलना में `UploadFile` का उपयोग करने के कई फायदे हैं: + +* आपको parameter के default value में `File()` का उपयोग नहीं करना पड़ता। +* यह एक "spooled" file का उपयोग करता है: + * एक file जो अधिकतम size limit तक memory में संग्रहीत होती है, और इस limit को पार करने के बाद disk पर संग्रहीत होती है। +* इसका मतलब है कि यह images, videos, बड़े binaries आदि जैसी बड़ी files के लिए सारी memory का उपयोग किए बिना अच्छी तरह काम करेगा। +* आप अपलोड की गई file से metadata प्राप्त कर सकते हैं। +* इसमें [file-like](https://docs.python.org/3/glossary.html#term-file-like-object) `async` interface है। +* यह एक वास्तविक Python [`SpooledTemporaryFile`](https://docs.python.org/3/library/tempfile.html#tempfile.SpooledTemporaryFile) object expose करता है जिसे आप सीधे अन्य libraries को पास कर सकते हैं जो file-like object की अपेक्षा करती हैं। + +### `UploadFile` { #uploadfile } + +`UploadFile` में निम्नलिखित attributes होते हैं: + +* `filename`: मूल file name के साथ एक `str` जो अपलोड किया गया था (जैसे `myimage.jpg`)। +* `content_type`: content type (MIME type / media type) के साथ एक `str` (जैसे `image/jpeg`)। +* `file`: एक [`SpooledTemporaryFile`](https://docs.python.org/3/library/tempfile.html#tempfile.SpooledTemporaryFile) (एक [file-like](https://docs.python.org/3/glossary.html#term-file-like-object) object)। यह वास्तविक Python file object है जिसे आप सीधे अन्य functions या libraries को पास कर सकते हैं जो "file-like" object की अपेक्षा करती हैं। + +`UploadFile` में निम्नलिखित `async` methods होते हैं। ये सभी अंदर से संबंधित file methods को call करते हैं (internal `SpooledTemporaryFile` का उपयोग करके)। + +* `write(data)`: `data` (`str` या `bytes`) को file में लिखता है। +* `read(size)`: file के `size` (`int`) bytes/characters पढ़ता है। +* `seek(offset)`: file में byte position `offset` (`int`) पर जाता है। + * उदाहरण के लिए, `await myfile.seek(0)` file की शुरुआत पर जाएगा। + * यह विशेष रूप से तब उपयोगी है जब आप एक बार `await myfile.read()` चलाते हैं और फिर सामग्री को दोबारा पढ़ने की आवश्यकता होती है। +* `close()`: file को बंद करता है। + +क्योंकि ये सभी methods `async` methods हैं, आपको उन्हें "await" करना होगा। + +उदाहरण के लिए, एक `async` *path operation function* के अंदर आप सामग्री इस तरह प्राप्त कर सकते हैं: + +```Python +contents = await myfile.read() +``` + +यदि आप एक सामान्य `def` *path operation function* के अंदर हैं, तो आप सीधे `UploadFile.file` access कर सकते हैं, उदाहरण के लिए: + +```Python +contents = myfile.file.read() +``` + +/// note | `async` तकनीकी विवरण + +जब आप `async` methods का उपयोग करते हैं, तो **FastAPI** file methods को threadpool में चलाता है और उनके लिए await करता है। + +/// + +/// note | Starlette तकनीकी विवरण + +**FastAPI** का `UploadFile` सीधे **Starlette** के `UploadFile` से inherit करता है, लेकिन **Pydantic** और FastAPI के अन्य भागों के साथ इसे compatible बनाने के लिए कुछ आवश्यक हिस्से जोड़ता है। + +/// + +## "Form Data" क्या है { #what-is-form-data } + +HTML forms (`
`) सामान्यतः data को server पर भेजने के लिए उस data के लिए एक "special" encoding का उपयोग करते हैं, यह JSON से अलग होता है। + +**FastAPI** यह सुनिश्चित करेगा कि उस data को JSON के बजाय सही जगह से पढ़ा जाए। + +/// note | तकनीकी विवरण + +forms से data सामान्यतः "media type" `application/x-www-form-urlencoded` का उपयोग करके encoded होता है जब इसमें files शामिल नहीं होतीं। + +लेकिन जब form में files शामिल होती हैं, तो यह `multipart/form-data` के रूप में encoded होता है। यदि आप `File` का उपयोग करते हैं, तो **FastAPI** जान जाएगा कि उसे body के सही भाग से files प्राप्त करनी हैं। + +यदि आप इन encodings और form fields के बारे में अधिक पढ़ना चाहते हैं, तो [`POST` के लिए MDN web docs](https://developer.mozilla.org/en-US/docs/Web/HTTP/Methods/POST) पर जाएं। + +/// + +/// warning | चेतावनी + +आप एक *path operation* में कई `File` और `Form` parameters घोषित कर सकते हैं, लेकिन आप ऐसे `Body` fields भी घोषित नहीं कर सकते जिन्हें आप JSON के रूप में प्राप्त करने की अपेक्षा करते हैं, क्योंकि request में body `application/json` के बजाय `multipart/form-data` का उपयोग करके encoded होगी। + +यह **FastAPI** की limitation नहीं है, यह HTTP protocol का हिस्सा है। + +/// + +## Optional File Upload { #optional-file-upload } + +आप standard type annotations का उपयोग करके और default value `None` set करके file को optional बना सकते हैं: + +{* ../../docs_src/request_files/tutorial001_02_an_py310.py hl[9,17] *} + +## अतिरिक्त Metadata के साथ `UploadFile` { #uploadfile-with-additional-metadata } + +आप `UploadFile` के साथ `File()` का भी उपयोग कर सकते हैं, उदाहरण के लिए, अतिरिक्त metadata set करने के लिए: + +{* ../../docs_src/request_files/tutorial001_03_an_py310.py hl[9,15] *} + +## Multiple File Uploads { #multiple-file-uploads } + +एक ही समय में कई files अपलोड करना संभव है। + +वे "form data" का उपयोग करके भेजे गए उसी "form field" से संबंधित होंगी। + +इसका उपयोग करने के लिए, `bytes` या `UploadFile` की list घोषित करें: + +{* ../../docs_src/request_files/tutorial002_an_py310.py hl[10,15] *} + +आपको, जैसा घोषित किया गया है, `bytes` या `UploadFile`s की एक `list` प्राप्त होगी। + +/// note | तकनीकी विवरण + +आप `from starlette.responses import HTMLResponse` का भी उपयोग कर सकते हैं। + +**FastAPI** आपकी सुविधा के लिए, developer के रूप में, वही `starlette.responses` को `fastapi.responses` के रूप में प्रदान करता है। लेकिन उपलब्ध अधिकांश responses सीधे Starlette से आते हैं। + +/// + +### अतिरिक्त Metadata के साथ Multiple File Uploads { #multiple-file-uploads-with-additional-metadata } + +और पहले की तरह ही, आप अतिरिक्त parameters set करने के लिए `File()` का उपयोग कर सकते हैं, यहां तक कि `UploadFile` के लिए भी: + +{* ../../docs_src/request_files/tutorial003_an_py310.py hl[11,18:20] *} + +## Recap { #recap } + +request में अपलोड की जाने वाली files घोषित करने के लिए `File`, `bytes`, और `UploadFile` का उपयोग करें, जिन्हें form data के रूप में भेजा जाता है। diff --git a/docs/hi/docs/tutorial/request-form-models.md b/docs/hi/docs/tutorial/request-form-models.md new file mode 100644 index 000000000..98fc91ac8 --- /dev/null +++ b/docs/hi/docs/tutorial/request-form-models.md @@ -0,0 +1,78 @@ +# Form Models { #form-models } + +आप FastAPI में **form fields** declare करने के लिए **Pydantic models** का उपयोग कर सकते हैं। + +/// note | नोट + +forms का उपयोग करने के लिए, पहले [`python-multipart`](https://github.com/Kludex/python-multipart) install करें। + +सुनिश्चित करें कि आप एक [virtual environment](../virtual-environments.md) बनाते हैं, उसे activate करते हैं, और फिर इसे install करते हैं, उदाहरण के लिए: + +```console +$ pip install python-multipart +``` + +/// + +/// note | नोट + +यह FastAPI version `0.113.0` से supported है। 🤓 + +/// + +## Forms के लिए Pydantic Models { #pydantic-models-for-forms } + +आपको बस उन fields के साथ एक **Pydantic model** declare करना है जिन्हें आप **form fields** के रूप में receive करना चाहते हैं, और फिर parameter को `Form` के रूप में declare करना है: + +{* ../../docs_src/request_form_models/tutorial001_an_py310.py hl[9:11,15] *} + +**FastAPI** request में मौजूद **form data** से **हर field** के लिए data **extract** करेगा और आपको वह Pydantic model देगा जिसे आपने define किया है। + +## Docs जाँचें { #check-the-docs } + +आप इसे `/docs` पर docs UI में verify कर सकते हैं: + +
+ +
+ +## Extra Form Fields को मना करें { #forbid-extra-form-fields } + +कुछ खास use cases में (शायद बहुत आम नहीं), आप form fields को केवल उन तक **restrict** करना चाह सकते हैं जो Pydantic model में declare किए गए हैं। और किसी भी **extra** fields को **forbid** करना चाह सकते हैं। + +/// note | नोट + +यह FastAPI version `0.114.0` से supported है। 🤓 + +/// + +आप किसी भी `extra` fields को `forbid` करने के लिए Pydantic की model configuration का उपयोग कर सकते हैं: + +{* ../../docs_src/request_form_models/tutorial002_an_py310.py hl[12] *} + +अगर कोई client कुछ extra data भेजने की कोशिश करता है, तो उन्हें एक **error** response मिलेगा। + +उदाहरण के लिए, अगर client ये form fields भेजने की कोशिश करता है: + +* `username`: `Rick` +* `password`: `Portal Gun` +* `extra`: `Mr. Poopybutthole` + +तो उन्हें एक error response मिलेगा जो बताएगा कि field `extra` allowed नहीं है: + +```json +{ + "detail": [ + { + "type": "extra_forbidden", + "loc": ["body", "extra"], + "msg": "Extra inputs are not permitted", + "input": "Mr. Poopybutthole" + } + ] +} +``` + +## सारांश { #summary } + +आप FastAPI में form fields declare करने के लिए Pydantic models का उपयोग कर सकते हैं। 😎 diff --git a/docs/hi/docs/tutorial/request-forms-and-files.md b/docs/hi/docs/tutorial/request-forms-and-files.md new file mode 100644 index 000000000..c43edae0e --- /dev/null +++ b/docs/hi/docs/tutorial/request-forms-and-files.md @@ -0,0 +1,41 @@ +# Request Forms और Files { #request-forms-and-files } + +आप `File` और `Form` का उपयोग करके files और form fields को एक ही समय में define कर सकते हैं। + +/// note | नोट + +अपलोड की गई files और/या form data प्राप्त करने के लिए, पहले [`python-multipart`](https://github.com/Kludex/python-multipart) install करें। + +सुनिश्चित करें कि आप एक [virtual environment](../virtual-environments.md) बनाएँ, उसे activate करें, और फिर इसे install करें, उदाहरण के लिए: + +```console +$ pip install python-multipart +``` + +/// + +## `File` और `Form` Import करें { #import-file-and-form } + +{* ../../docs_src/request_forms_and_files/tutorial001_an_py310.py hl[3] *} + +## `File` और `Form` parameters define करें { #define-file-and-form-parameters } + +file और form parameters उसी तरह बनाएँ जैसे आप `Body` या `Query` के लिए बनाते हैं: + +{* ../../docs_src/request_forms_and_files/tutorial001_an_py310.py hl[10:12] *} + +files और form fields, form data के रूप में अपलोड किए जाएँगे और आपको files और form fields प्राप्त होंगे। + +और आप कुछ files को `bytes` के रूप में और कुछ को `UploadFile` के रूप में declare कर सकते हैं। + +/// warning | चेतावनी + +आप एक *path operation* में कई `File` और `Form` parameters declare कर सकते हैं, लेकिन आप साथ ही ऐसे `Body` fields declare नहीं कर सकते जिन्हें आप JSON के रूप में प्राप्त करने की अपेक्षा करते हैं, क्योंकि request में body `application/json` के बजाय `multipart/form-data` का उपयोग करके encoded होगी। + +यह **FastAPI** की कोई सीमा नहीं है, यह HTTP protocol का हिस्सा है। + +/// + +## Recap { #recap } + +जब आपको एक ही request में data और files प्राप्त करने की आवश्यकता हो, तो `File` और `Form` को साथ में उपयोग करें। diff --git a/docs/hi/docs/tutorial/request-forms.md b/docs/hi/docs/tutorial/request-forms.md new file mode 100644 index 000000000..32488ec1e --- /dev/null +++ b/docs/hi/docs/tutorial/request-forms.md @@ -0,0 +1,73 @@ +# Form Data { #form-data } + +जब आपको JSON के बजाय form fields प्राप्त करने हों, तो आप `Form` का उपयोग कर सकते हैं। + +/// note | नोट + +forms का उपयोग करने के लिए, पहले [`python-multipart`](https://github.com/Kludex/python-multipart) install करें। + +सुनिश्चित करें कि आप एक [virtual environment](../virtual-environments.md) बनाते हैं, उसे activate करते हैं, और फिर इसे install करते हैं, उदाहरण के लिए: + +```console +$ pip install python-multipart +``` + +/// + +## `Form` Import करें { #import-form } + +`fastapi` से `Form` import करें: + +{* ../../docs_src/request_forms/tutorial001_an_py310.py hl[3] *} + +## `Form` parameters परिभाषित करें { #define-form-parameters } + +form parameters उसी तरह बनाएं जैसे आप `Body` या `Query` के लिए बनाते: + +{* ../../docs_src/request_forms/tutorial001_an_py310.py hl[9] *} + +उदाहरण के लिए, OAuth2 specification का उपयोग जिन तरीकों से किया जा सकता है उनमें से एक में (जिसे "password flow" कहा जाता है) `username` और `password` को form fields के रूप में भेजना required है। + +spec के अनुसार fields के नाम बिल्कुल `username` और `password` होने चाहिए, और उन्हें JSON नहीं, बल्कि form fields के रूप में भेजा जाना चाहिए। + +`Form` के साथ आप वही configurations declare कर सकते हैं जो `Body` (और `Query`, `Path`, `Cookie`) के साथ करते हैं, जिसमें validation, examples, alias (जैसे `username` के बजाय `user-name`), आदि शामिल हैं। + +/// note | नोट + +`Form` एक class है जो सीधे `Body` से inherit करती है। + +/// + +/// tip | टिप + +form bodies declare करने के लिए, आपको स्पष्ट रूप से `Form` का उपयोग करना होगा, क्योंकि इसके बिना parameters को query parameters या body (JSON) parameters के रूप में समझा जाएगा। + +/// + +## "Form Fields" के बारे में { #about-form-fields } + +HTML forms (`
`) आमतौर पर data को server पर भेजने के लिए उस data के लिए एक "special" encoding का उपयोग करते हैं, यह JSON से अलग होता है। + +**FastAPI** यह सुनिश्चित करेगा कि उस data को JSON के बजाय सही जगह से पढ़ा जाए। + +/// note | तकनीकी विवरण + +forms से आने वाला data आमतौर पर "media type" `application/x-www-form-urlencoded` का उपयोग करके encoded होता है। + +लेकिन जब form में files शामिल होती हैं, तो इसे `multipart/form-data` के रूप में encoded किया जाता है। files को handle करने के बारे में आप अगले chapter में पढ़ेंगे। + +अगर आप इन encodings और form fields के बारे में अधिक पढ़ना चाहते हैं, तो [`POST` के लिए MDN web docs](https://developer.mozilla.org/en-US/docs/Web/HTTP/Methods/POST) देखें। + +/// + +/// warning | चेतावनी + +आप एक *path operation* में कई `Form` parameters declare कर सकते हैं, लेकिन आप साथ में ऐसे `Body` fields declare नहीं कर सकते जिन्हें आप JSON के रूप में प्राप्त करने की उम्मीद करते हैं, क्योंकि request में body `application/json` के बजाय `application/x-www-form-urlencoded` का उपयोग करके encoded होगी। + +यह **FastAPI** की limitation नहीं है, यह HTTP protocol का हिस्सा है। + +/// + +## Recap { #recap } + +form data input parameters declare करने के लिए `Form` का उपयोग करें। diff --git a/docs/hi/docs/tutorial/response-model.md b/docs/hi/docs/tutorial/response-model.md new file mode 100644 index 000000000..76f7ba4fc --- /dev/null +++ b/docs/hi/docs/tutorial/response-model.md @@ -0,0 +1,344 @@ +# Response Model - Return Type { #response-model-return-type } + +आप response के लिए उपयोग किए जाने वाले type को *path operation function* के **return type** को annotate करके declare कर सकते हैं। + +आप **type annotations** का उपयोग उसी तरह कर सकते हैं जैसे आप function **parameters** में input data के लिए करते हैं, आप Pydantic models, lists, dictionaries, scalar values जैसे integers, booleans, आदि का उपयोग कर सकते हैं। + +{* ../../docs_src/response_model/tutorial001_01_py310.py hl[16,21] *} + +FastAPI इस return type का उपयोग इनके लिए करेगा: + +* लौटाए गए data को **Validate** करना। + * अगर data invalid है (जैसे कि कोई field missing है), तो इसका मतलब है कि *आपके* app code में गड़बड़ी है, वह वह data return नहीं कर रहा जो उसे करना चाहिए, और यह incorrect data return करने के बजाय server error return करेगा। इस तरह आप और आपके clients सुनिश्चित हो सकते हैं कि उन्हें expected data और data shape मिलेगा। +* OpenAPI *path operation* में response के लिए एक **JSON Schema** जोड़ना। + * इसका उपयोग **automatic docs** द्वारा किया जाएगा। + * इसका उपयोग automatic client code generation tools द्वारा भी किया जाएगा। +* Pydantic का उपयोग करके लौटाए गए data को JSON में **Serialize** करना, जो **Rust** में लिखा गया है, इसलिए यह **बहुत तेज़** होगा। + +लेकिन सबसे महत्वपूर्ण: + +* यह output data को return type में defined data तक **limit और filter** करेगा। + * यह **security** के लिए विशेष रूप से महत्वपूर्ण है, हम नीचे इसका और अधिक देखेंगे। + +## `response_model` Parameter { #response-model-parameter } + +कुछ cases ऐसे होते हैं जहाँ आपको ऐसा data return करना होता है या आप ऐसा करना चाहते हैं जो type द्वारा declare किए गए data से बिल्कुल मेल नहीं खाता। + +उदाहरण के लिए, आप **dictionary return** करना या database object return करना चाह सकते हैं, लेकिन **उसे Pydantic model के रूप में declare** करना चाह सकते हैं। इस तरह Pydantic model आपके द्वारा लौटाए गए object (जैसे dictionary या database object) के लिए सभी data documentation, validation, आदि करेगा। + +अगर आपने return type annotation जोड़ा, तो tools और editors एक (सही) error के साथ शिकायत करेंगे कि आपका function ऐसा type (जैसे dict) return कर रहा है जो आपके द्वारा declare किए गए type (जैसे Pydantic model) से अलग है। + +ऐसे cases में, आप return type के बजाय *path operation decorator* parameter `response_model` का उपयोग कर सकते हैं। + +आप किसी भी *path operations* में `response_model` parameter का उपयोग कर सकते हैं: + +* `@app.get()` +* `@app.post()` +* `@app.put()` +* `@app.delete()` +* आदि। + +{* ../../docs_src/response_model/tutorial001_py310.py hl[17,22,24:27] *} + +/// note | नोट + +ध्यान दें कि `response_model` "decorator" method (`get`, `post`, आदि) का parameter है। यह आपके *path operation function* का parameter नहीं है, जैसे सभी parameters और body होते हैं। + +/// + +`response_model` वही type receive करता है जिसे आप Pydantic model field के लिए declare करेंगे, इसलिए यह Pydantic model हो सकता है, लेकिन यह, जैसे कि `List[Item]` की तरह Pydantic models की `list` भी हो सकता है। + +FastAPI इस `response_model` का उपयोग सभी data documentation, validation, आदि के लिए करेगा और output data को इसके type declaration में **convert और filter** भी करेगा। + +/// tip | सुझाव + +अगर आपके editor, mypy, आदि में strict type checks हैं, तो आप function return type को `Any` के रूप में declare कर सकते हैं। + +इस तरह आप editor को बताते हैं कि आप जानबूझकर कुछ भी return कर रहे हैं। लेकिन FastAPI फिर भी `response_model` के साथ data documentation, validation, filtering, आदि करेगा। + +/// + +### `response_model` Priority { #response-model-priority } + +अगर आप return type और `response_model` दोनों declare करते हैं, तो `response_model` को priority मिलेगी और FastAPI द्वारा इसका उपयोग किया जाएगा। + +इस तरह आप अपने functions में सही type annotations जोड़ सकते हैं, भले ही आप response model से अलग type return कर रहे हों, ताकि editor और mypy जैसे tools उनका उपयोग कर सकें। और फिर भी FastAPI `response_model` का उपयोग करके data validation, documentation, आदि कर सकता है। + +आप उस *path operation* के लिए response model बनाना disable करने के लिए `response_model=None` का भी उपयोग कर सकते हैं, आपको ऐसा तब करना पड़ सकता है जब आप उन चीज़ों के लिए type annotations जोड़ रहे हों जो valid Pydantic fields नहीं हैं, आप नीचे के sections में से एक में इसका उदाहरण देखेंगे। + +## वही input data return करें { #return-the-same-input-data } + +यहाँ हम एक `UserIn` model declare कर रहे हैं, इसमें plaintext password होगा: + +{* ../../docs_src/response_model/tutorial002_py310.py hl[7,9] *} + +/// note | नोट + +`EmailStr` का उपयोग करने के लिए, पहले [`email-validator`](https://github.com/JoshData/python-email-validator) install करें। + +सुनिश्चित करें कि आप एक [virtual environment](../virtual-environments.md) बनाते हैं, उसे activate करते हैं, और फिर इसे install करते हैं, उदाहरण के लिए: + +```console +$ pip install email-validator +``` + +या इसके साथ: + +```console +$ pip install "pydantic[email]" +``` + +/// + +और हम इस model का उपयोग अपने input को declare करने और उसी model का उपयोग अपने output को declare करने के लिए कर रहे हैं: + +{* ../../docs_src/response_model/tutorial002_py310.py hl[16] *} + +अब, जब भी कोई browser password के साथ user बना रहा होगा, API response में वही password return करेगी। + +इस case में, यह problem नहीं हो सकती, क्योंकि password भेजने वाला वही user है। + +लेकिन अगर हम उसी model का उपयोग किसी और *path operation* के लिए करते हैं, तो हम अपने user के passwords हर client को भेज सकते हैं। + +/// danger | खतरा + +कभी भी किसी user का plain password store न करें या उसे इस तरह response में न भेजें, जब तक कि आप सभी caveats नहीं जानते और यह नहीं जानते कि आप क्या कर रहे हैं। + +/// + +## Output model जोड़ें { #add-an-output-model } + +इसके बजाय हम plaintext password के साथ एक input model और उसके बिना एक output model बना सकते हैं: + +{* ../../docs_src/response_model/tutorial003_py310.py hl[9,11,16] *} + +यहाँ, भले ही हमारा *path operation function* वही input user return कर रहा है जिसमें password शामिल है: + +{* ../../docs_src/response_model/tutorial003_py310.py hl[24] *} + +...हमने `response_model` को अपना model `UserOut` declare किया है, जिसमें password शामिल नहीं है: + +{* ../../docs_src/response_model/tutorial003_py310.py hl[22] *} + +इसलिए, **FastAPI** output model में declare न किए गए सभी data को filter out करने का ध्यान रखेगा (Pydantic का उपयोग करके)। + +### `response_model` या Return Type { #response-model-or-return-type } + +इस case में, क्योंकि दोनों models अलग हैं, अगर हमने function return type को `UserOut` के रूप में annotate किया, तो editor और tools शिकायत करेंगे कि हम invalid type return कर रहे हैं, क्योंकि वे अलग classes हैं। + +इसीलिए इस उदाहरण में हमें इसे `response_model` parameter में declare करना पड़ता है। + +...लेकिन इसे कैसे overcome किया जाए, यह देखने के लिए नीचे पढ़ना जारी रखें। + +## Return Type और Data Filtering { #return-type-and-data-filtering } + +आइए पिछले उदाहरण से आगे बढ़ते हैं। हम **function को एक type के साथ annotate** करना चाहते थे, लेकिन हम function से ऐसा कुछ return कर पाना चाहते थे जिसमें वास्तव में **अधिक data** शामिल हो। + +हम चाहते हैं कि FastAPI response model का उपयोग करके data को **filter** करता रहे। ताकि भले ही function अधिक data return करे, response में केवल वही fields शामिल हों जो response model में declare किए गए हैं। + +पिछले उदाहरण में, क्योंकि classes अलग थीं, हमें `response_model` parameter का उपयोग करना पड़ा। लेकिन इसका मतलब यह भी है कि हमें function return type check करने वाले editor और tools से support नहीं मिलता। + +लेकिन अधिकतर cases में जहाँ हमें ऐसा कुछ करना होता है, हम चाहते हैं कि model बस इस उदाहरण की तरह कुछ data को **filter/remove** करे। + +और उन cases में, हम classes और inheritance का उपयोग करके function **type annotations** का लाभ उठा सकते हैं ताकि editor और tools में बेहतर support मिले, और फिर भी FastAPI **data filtering** मिल सके। + +{* ../../docs_src/response_model/tutorial003_01_py310.py hl[7:10,13:14,18] *} + +इसके साथ, हमें editors और mypy से tooling support मिलता है क्योंकि यह code types के संदर्भ में सही है, लेकिन हमें FastAPI से data filtering भी मिलती है। + +यह कैसे काम करता है? आइए इसे देखें। 🤓 + +### Type Annotations और Tooling { #type-annotations-and-tooling } + +पहले देखते हैं कि editors, mypy और अन्य tools इसे कैसे देखेंगे। + +`BaseUser` में base fields हैं। फिर `UserIn`, `BaseUser` से inherit करता है और `password` field जोड़ता है, इसलिए इसमें दोनों models के सभी fields शामिल होंगे। + +हम function return type को `BaseUser` के रूप में annotate करते हैं, लेकिन वास्तव में हम `UserIn` instance return कर रहे हैं। + +Editor, mypy, और अन्य tools इस पर शिकायत नहीं करेंगे क्योंकि typing terms में, `UserIn`, `BaseUser` का subclass है, जिसका मतलब है कि जब expected कुछ भी `BaseUser` हो, तो यह एक *valid* type है। + +### FastAPI Data Filtering { #fastapi-data-filtering } + +अब, FastAPI के लिए, यह return type देखेगा और सुनिश्चित करेगा कि आप जो return करते हैं उसमें **केवल** वही fields शामिल हों जो type में declare किए गए हैं। + +FastAPI internally Pydantic के साथ कई चीज़ें करता है ताकि यह सुनिश्चित हो सके कि class inheritance के वही rules returned data filtering के लिए उपयोग न किए जाएँ, नहीं तो आप expected से कहीं अधिक data return कर सकते हैं। + +इस तरह, आप दोनों दुनिया का best पा सकते हैं: **tooling support** के साथ type annotations और **data filtering**। + +## इसे docs में देखें { #see-it-in-the-docs } + +जब आप automatic docs देखते हैं, तो आप check कर सकते हैं कि input model और output model दोनों का अपना JSON Schema होगा: + + + +और दोनों models interactive API documentation के लिए उपयोग किए जाएँगे: + + + +## अन्य Return Type Annotations { #other-return-type-annotations } + +ऐसे cases हो सकते हैं जहाँ आप कुछ ऐसा return करते हैं जो valid Pydantic field नहीं है और आप उसे function में annotate करते हैं, केवल tooling (editor, mypy, आदि) द्वारा दिए गए support को पाने के लिए। + +### सीधे Response Return करें { #return-a-response-directly } + +सबसे common case होगा [advanced docs में बाद में समझाए अनुसार सीधे Response return करना](../advanced/response-directly.md)। + +{* ../../docs_src/response_model/tutorial003_02_py310.py hl[8,10:11] *} + +यह simple case FastAPI द्वारा automatically handle किया जाता है क्योंकि return type annotation `Response` class (या उसका subclass) है। + +और tools भी खुश होंगे क्योंकि `RedirectResponse` और `JSONResponse` दोनों `Response` के subclasses हैं, इसलिए type annotation सही है। + +### Response Subclass Annotate करें { #annotate-a-response-subclass } + +आप type annotation में `Response` के subclass का भी उपयोग कर सकते हैं: + +{* ../../docs_src/response_model/tutorial003_03_py310.py hl[8:9] *} + +यह भी काम करेगा क्योंकि `RedirectResponse`, `Response` का subclass है, और FastAPI इस simple case को automatically handle करेगा। + +### Invalid Return Type Annotations { #invalid-return-type-annotations } + +लेकिन जब आप कोई अन्य arbitrary object return करते हैं जो valid Pydantic type नहीं है (जैसे database object) और आप उसे function में उसी तरह annotate करते हैं, तो FastAPI उस type annotation से Pydantic response model बनाने की कोशिश करेगा, और fail हो जाएगा। + +ऐसा ही होगा अगर आपके पास अलग-अलग types के बीच union जैसा कुछ हो जहाँ उनमें से एक या अधिक valid Pydantic types नहीं हैं, उदाहरण के लिए यह fail होगा 💥: + +{* ../../docs_src/response_model/tutorial003_04_py310.py hl[8] *} + +...यह fail होता है क्योंकि type annotation Pydantic type नहीं है और केवल एक single `Response` class या subclass भी नहीं है, यह `Response` और `dict` के बीच union (दोनों में से कोई भी) है। + +### Response Model Disable करें { #disable-response-model } + +ऊपर दिए गए उदाहरण से आगे बढ़ते हुए, आप शायद default data validation, documentation, filtering, आदि नहीं चाहते हों जो FastAPI द्वारा किया जाता है। + +लेकिन आप शायद function में return type annotation फिर भी रखना चाहते हों ताकि editors और type checkers (जैसे mypy) जैसे tools से support मिल सके। + +इस case में, आप `response_model=None` set करके response model generation disable कर सकते हैं: + +{* ../../docs_src/response_model/tutorial003_05_py310.py hl[7] *} + +इससे FastAPI response model generation skip कर देगा और इस तरह आप अपनी जरूरत के किसी भी return type annotations का उपयोग कर सकते हैं, बिना इसके कि वह आपकी FastAPI application को प्रभावित करे। 🤓 + +## Response Model encoding parameters { #response-model-encoding-parameters } + +आपके response model में default values हो सकते हैं, जैसे: + +{* ../../docs_src/response_model/tutorial004_py310.py hl[9,11:12] *} + +* `description: Union[str, None] = None` (या Python 3.10 में `str | None = None`) का default `None` है। +* `tax: float = 10.5` का default `10.5` है। +* `tags: List[str] = []` का default खाली list है: `[]`। + +लेकिन अगर वे वास्तव में store नहीं किए गए थे तो आप उन्हें result से omit करना चाह सकते हैं। + +उदाहरण के लिए, अगर आपके पास NoSQL database में कई optional attributes वाले models हैं, लेकिन आप default values से भरे बहुत लंबे JSON responses नहीं भेजना चाहते। + +### `response_model_exclude_unset` parameter का उपयोग करें { #use-the-response-model-exclude-unset-parameter } + +आप *path operation decorator* parameter `response_model_exclude_unset=True` set कर सकते हैं: + +{* ../../docs_src/response_model/tutorial004_py310.py hl[22] *} + +और वे default values response में शामिल नहीं होंगे, केवल वास्तव में set किए गए values ही शामिल होंगे। + +तो, अगर आप ID `foo` वाले item के लिए उस *path operation* को request भेजते हैं, तो response (default values शामिल किए बिना) होगा: + +```JSON +{ + "name": "Foo", + "price": 50.2 +} +``` + +/// note | नोट + +आप इसका भी उपयोग कर सकते हैं: + +* `response_model_exclude_defaults=True` +* `response_model_exclude_none=True` + +जैसा कि `exclude_defaults` और `exclude_none` के लिए [Pydantic docs](https://docs.pydantic.dev/1.10/usage/exporting_models/#modeldict) में बताया गया है। + +/// + +#### Defaults वाले fields के लिए values वाला data { #data-with-values-for-fields-with-defaults } + +लेकिन अगर आपके data में model के default values वाले fields के लिए values हैं, जैसे ID `bar` वाला item: + +```Python hl_lines="3 5" +{ + "name": "Bar", + "description": "The bartenders", + "price": 62, + "tax": 20.2 +} +``` + +तो वे response में शामिल होंगे। + +#### Defaults जैसे ही values वाला data { #data-with-the-same-values-as-the-defaults } + +अगर data में default values जैसे ही values हैं, जैसे ID `baz` वाला item: + +```Python hl_lines="3 5-6" +{ + "name": "Baz", + "description": None, + "price": 50.2, + "tax": 10.5, + "tags": [] +} +``` + +FastAPI इतना smart है (दरअसल, Pydantic इतना smart है) कि यह समझ सके कि, भले ही `description`, `tax`, और `tags` के values defaults जैसे ही हैं, उन्हें explicitly set किया गया था (defaults से लिए जाने के बजाय)। + +इसलिए, वे JSON response में शामिल होंगे। + +/// tip | सुझाव + +ध्यान दें कि default values कुछ भी हो सकते हैं, केवल `None` नहीं। + +वे list (`[]`), `10.5` का `float`, आदि हो सकते हैं। + +/// + +### `response_model_include` और `response_model_exclude` { #response-model-include-and-response-model-exclude } + +आप *path operation decorator* parameters `response_model_include` और `response_model_exclude` का भी उपयोग कर सकते हैं। + +वे include करने के लिए attributes के नामों वाला `str` का `set` लेते हैं (बाकी को omit करते हुए) या exclude करने के लिए (बाकी को include करते हुए)। + +अगर आपके पास केवल एक Pydantic model है और आप output से कुछ data remove करना चाहते हैं, तो इसे quick shortcut के रूप में उपयोग किया जा सकता है। + +/// tip | सुझाव + +लेकिन फिर भी इन parameters के बजाय, multiple classes का उपयोग करते हुए, ऊपर दिए गए ideas का उपयोग करने की recommendation है। + +ऐसा इसलिए है क्योंकि आपके app के OpenAPI (और docs) में generated JSON Schema फिर भी complete model के लिए ही होगा, भले ही आप कुछ attributes omit करने के लिए `response_model_include` या `response_model_exclude` का उपयोग करें। + +यह `response_model_by_alias` पर भी लागू होता है जो इसी तरह काम करता है। + +/// + +{* ../../docs_src/response_model/tutorial005_py310.py hl[29,35] *} + +/// tip | सुझाव + +Syntax `{"name", "description"}` उन दो values के साथ एक `set` बनाता है। + +यह `set(["name", "description"])` के equivalent है। + +/// + +#### `set`s के बजाय `list`s का उपयोग करना { #using-lists-instead-of-sets } + +अगर आप `set` का उपयोग करना भूल जाते हैं और इसके बजाय `list` या `tuple` का उपयोग करते हैं, तो FastAPI फिर भी उसे `set` में convert कर देगा और यह सही तरह काम करेगा: + +{* ../../docs_src/response_model/tutorial006_py310.py hl[29,35] *} + +## Recap { #recap } + +Response models define करने और खासकर private data को filter out करना सुनिश्चित करने के लिए *path operation decorator* के parameter `response_model` का उपयोग करें। + +केवल explicitly set किए गए values return करने के लिए `response_model_exclude_unset` का उपयोग करें। diff --git a/docs/hi/docs/tutorial/response-status-code.md b/docs/hi/docs/tutorial/response-status-code.md new file mode 100644 index 000000000..b11bdb0ec --- /dev/null +++ b/docs/hi/docs/tutorial/response-status-code.md @@ -0,0 +1,101 @@ +# Response Status Code { #response-status-code } + +जिस तरह आप response model specify कर सकते हैं, उसी तरह आप किसी भी *path operations* में parameter `status_code` के साथ response के लिए इस्तेमाल किया जाने वाला HTTP status code भी declare कर सकते हैं: + +* `@app.get()` +* `@app.post()` +* `@app.put()` +* `@app.delete()` +* आदि। + +{* ../../docs_src/response_status_code/tutorial001_py310.py hl[6] *} + +/// note | नोट + +ध्यान दें कि `status_code`, "decorator" method (`get`, `post`, आदि) का parameter है। यह आपके *path operation function* का parameter नहीं है, जैसे बाकी सभी parameters और body होते हैं। + +/// + +`status_code` parameter HTTP status code वाला एक number receive करता है। + +/// note | नोट + +`status_code` वैकल्पिक रूप से एक `IntEnum` भी receive कर सकता है, जैसे Python का [`http.HTTPStatus`](https://docs.python.org/3/library/http.html#http.HTTPStatus). + +/// + +यह: + +* response में वह status code return करेगा। +* उसे OpenAPI schema में उसी तरह document करेगा (और इसलिए, user interfaces में भी): + + + +/// note | नोट + +कुछ response codes (अगला section देखें) यह indicate करते हैं कि response में body नहीं होती। + +FastAPI यह जानता है, और ऐसे OpenAPI docs बनाएगा जो बताते हैं कि कोई response body नहीं है। + +/// + +## HTTP status codes के बारे में { #about-http-status-codes } + +/// note | नोट + +अगर आप पहले से जानते हैं कि HTTP status codes क्या होते हैं, तो अगले section पर जाएँ। + +/// + +HTTP में, आप response के हिस्से के रूप में 3 digits का एक numeric status code भेजते हैं। + +इन status codes के साथ एक associated name होता है जिससे उन्हें पहचानने में मदद मिलती है, लेकिन महत्वपूर्ण हिस्सा number होता है। + +संक्षेप में: + +* `100 - 199` "Information" के लिए होते हैं। आप इन्हें सीधे बहुत कम इस्तेमाल करते हैं। इन status codes वाले responses में body नहीं हो सकती। +* **`200 - 299`** "Successful" responses के लिए होते हैं। ये वे हैं जिन्हें आप सबसे ज़्यादा इस्तेमाल करेंगे। + * `200` default status code है, जिसका मतलब है कि सब कुछ "OK" था। + * एक और उदाहरण `201`, "Created" होगा। इसे आमतौर पर database में नया record बनाने के बाद इस्तेमाल किया जाता है। + * एक विशेष case `204`, "No Content" है। यह response तब इस्तेमाल होता है जब client को return करने के लिए कोई content नहीं होता, और इसलिए response में body नहीं होनी चाहिए। +* **`300 - 399`** "Redirection" के लिए होते हैं। इन status codes वाले responses में body हो भी सकती है और नहीं भी, सिवाय `304`, "Not Modified" के, जिसमें body नहीं होनी चाहिए। +* **`400 - 499`** "Client error" responses के लिए होते हैं। ये दूसरा type है जिसे आप शायद सबसे ज़्यादा इस्तेमाल करेंगे। + * एक उदाहरण `404` है, "Not Found" response के लिए। + * client से आने वाली generic errors के लिए, आप सिर्फ़ `400` इस्तेमाल कर सकते हैं। +* `500 - 599` server errors के लिए होते हैं। आप इन्हें लगभग कभी सीधे इस्तेमाल नहीं करते। जब आपके application code या server के किसी हिस्से में कुछ गड़बड़ होती है, तो यह अपने-आप इन status codes में से एक return करेगा। + +/// tip | सुझाव + +हर status code के बारे में और कौन-सा code किसके लिए है, यह जानने के लिए [HTTP status codes के बारे में MDN documentation](https://developer.mozilla.org/en-US/docs/Web/HTTP/Status) देखें। + +/// + +## नाम याद रखने का shortcut { #shortcut-to-remember-the-names } + +आइए पिछले example को फिर से देखें: + +{* ../../docs_src/response_status_code/tutorial001_py310.py hl[6] *} + +`201` "Created" के लिए status code है। + +लेकिन आपको यह याद रखने की ज़रूरत नहीं है कि इनमें से हर code का क्या मतलब है। + +आप `fastapi.status` से convenience variables इस्तेमाल कर सकते हैं। + +{* ../../docs_src/response_status_code/tutorial002_py310.py hl[1,6] *} + +वे सिर्फ़ एक सुविधा हैं, उनमें वही number होता है, लेकिन इस तरह आप उन्हें खोजने के लिए editor के autocomplete का इस्तेमाल कर सकते हैं: + + + +/// note | तकनीकी विवरण + +आप `from starlette import status` भी इस्तेमाल कर सकते हैं। + +**FastAPI** आपकी सुविधा के लिए, developer के रूप में, वही `starlette.status` `fastapi.status` के रूप में provide करता है। लेकिन यह सीधे Starlette से आता है। + +/// + +## default बदलना { #changing-the-default } + +बाद में, [Advanced User Guide](../advanced/response-change-status-code.md) में, आप देखेंगे कि यहाँ declare किए जा रहे default से अलग status code कैसे return किया जाता है। diff --git a/docs/hi/docs/tutorial/schema-extra-example.md b/docs/hi/docs/tutorial/schema-extra-example.md new file mode 100644 index 000000000..dc8b29f58 --- /dev/null +++ b/docs/hi/docs/tutorial/schema-extra-example.md @@ -0,0 +1,202 @@ +# Request Example Data घोषित करें { #declare-request-example-data } + +आप उस data के examples घोषित कर सकते हैं जिसे आपका app receive कर सकता है। + +इसे करने के कई तरीके यहाँ दिए गए हैं। + +## Pydantic models में अतिरिक्त JSON Schema data { #extra-json-schema-data-in-pydantic-models } + +आप किसी Pydantic model के लिए `examples` घोषित कर सकते हैं, जिन्हें generated JSON Schema में जोड़ा जाएगा। + +{* ../../docs_src/schema_extra_example/tutorial001_py310.py hl[13:24] *} + +वह अतिरिक्त जानकारी उस model के output **JSON Schema** में जैसी है वैसी ही जोड़ी जाएगी, और API docs में उपयोग की जाएगी। + +आप `model_config` attribute का उपयोग कर सकते हैं, जो एक `dict` लेता है, जैसा कि [Pydantic के docs: Configuration](https://docs.pydantic.dev/latest/api/config/) में बताया गया है। + +आप `"json_schema_extra"` को एक `dict` के साथ set कर सकते हैं जिसमें कोई भी अतिरिक्त data हो जिसे आप generated JSON Schema में दिखाना चाहते हैं, जिसमें `examples` भी शामिल हैं। + +/// tip | सुझाव + +आप इसी technique का उपयोग JSON Schema को extend करने और अपनी custom अतिरिक्त जानकारी जोड़ने के लिए कर सकते हैं। + +उदाहरण के लिए, आप इसका उपयोग frontend user interface आदि के लिए metadata जोड़ने में कर सकते हैं। + +/// + +/// note | नोट + +OpenAPI 3.1.0 (FastAPI 0.99.0 से उपयोग किया गया) ने `examples` के लिए support जोड़ा, जो **JSON Schema** standard का हिस्सा है। + +उससे पहले, यह केवल keyword `example` को एक single example के साथ support करता था। यह अभी भी OpenAPI 3.1.0 द्वारा supported है, लेकिन deprecated है और JSON Schema standard का हिस्सा नहीं है। इसलिए आपको `example` से `examples` पर migrate करने के लिए प्रोत्साहित किया जाता है। 🤓 + +आप इस page के अंत में और पढ़ सकते हैं। + +/// + +## `Field` के अतिरिक्त arguments { #field-additional-arguments } + +Pydantic models के साथ `Field()` का उपयोग करते समय, आप अतिरिक्त `examples` भी घोषित कर सकते हैं: + +{* ../../docs_src/schema_extra_example/tutorial002_py310.py hl[2,8:11] *} + +## JSON Schema - OpenAPI में `examples` { #examples-in-json-schema-openapi } + +इनमें से किसी का भी उपयोग करते समय: + +* `Path()` +* `Query()` +* `Header()` +* `Cookie()` +* `Body()` +* `Form()` +* `File()` + +आप अतिरिक्त जानकारी के साथ `examples` का एक group भी घोषित कर सकते हैं, जिसे **OpenAPI** के अंदर उनके **JSON Schemas** में जोड़ा जाएगा। + +### `examples` के साथ `Body` { #body-with-examples } + +यहाँ हम `Body()` में अपेक्षित data के एक example वाला `examples` pass करते हैं: + +{* ../../docs_src/schema_extra_example/tutorial003_an_py310.py hl[22:29] *} + +### docs UI में Example { #example-in-the-docs-ui } + +ऊपर दिए गए किसी भी method के साथ यह `/docs` में इस तरह दिखेगा: + + + +### कई `examples` के साथ `Body` { #body-with-multiple-examples } + +बेशक आप कई `examples` भी pass कर सकते हैं: + +{* ../../docs_src/schema_extra_example/tutorial004_an_py310.py hl[23:38] *} + +जब आप ऐसा करते हैं, तो examples उस body data के internal **JSON Schema** का हिस्सा होंगे। + +फिर भी, यह लिखते समय, Swagger UI, वह tool जो docs UI दिखाने के लिए जिम्मेदार है, **JSON Schema** में data के लिए कई examples दिखाने को support नहीं करता। लेकिन workaround के लिए नीचे पढ़ें। + +### OpenAPI-specific `examples` { #openapi-specific-examples } + +**JSON Schema** द्वारा `examples` support किए जाने से पहले से ही, OpenAPI में एक अलग field के लिए support था जिसे `examples` भी कहा जाता था। + +यह **OpenAPI-specific** `examples` OpenAPI specification में किसी अन्य section में जाता है। यह प्रत्येक JSON Schema के अंदर नहीं, बल्कि **प्रत्येक *path operation* के details** में जाता है। + +और Swagger UI ने इस विशेष `examples` field को कुछ समय से support किया है। इसलिए, आप इसका उपयोग docs UI में अलग-अलग **examples दिखाने** के लिए कर सकते हैं। + +इस OpenAPI-specific field `examples` का आकार एक `dict` है जिसमें **कई examples** होते हैं (`list` के बजाय), और प्रत्येक में अतिरिक्त जानकारी होती है जो **OpenAPI** में भी जोड़ी जाएगी। + +यह OpenAPI में मौजूद प्रत्येक JSON Schema के अंदर नहीं जाता, यह बाहर, सीधे *path operation* में जाता है। + +### `openapi_examples` Parameter का उपयोग { #using-the-openapi-examples-parameter } + +आप FastAPI में OpenAPI-specific `examples` को parameter `openapi_examples` के साथ इनके लिए घोषित कर सकते हैं: + +* `Path()` +* `Query()` +* `Header()` +* `Cookie()` +* `Body()` +* `Form()` +* `File()` + +`dict` की keys प्रत्येक example की पहचान करती हैं, और प्रत्येक value एक और `dict` होती है। + +`examples` में प्रत्येक specific example `dict` में ये हो सकते हैं: + +* `summary`: example के लिए छोटा description। +* `description`: एक लंबा description जिसमें Markdown text हो सकता है। +* `value`: यह दिखाया गया वास्तविक example है, जैसे एक `dict`। +* `externalValue`: `value` का alternative, example की ओर point करने वाला URL। हालांकि यह शायद `value` जितने tools द्वारा supported न हो। + +आप इसे इस तरह use कर सकते हैं: + +{* ../../docs_src/schema_extra_example/tutorial005_an_py310.py hl[23:49] *} + +### Docs UI में OpenAPI Examples { #openapi-examples-in-the-docs-ui } + +`Body()` में `openapi_examples` जोड़ने के साथ `/docs` इस तरह दिखेगा: + + + +## तकनीकी विवरण { #technical-details } + +/// tip | सुझाव + +यदि आप पहले से ही **FastAPI** version **0.99.0 या उससे ऊपर** का उपयोग कर रहे हैं, तो आप शायद ये details **skip** कर सकते हैं। + +ये पुराने versions के लिए अधिक relevant हैं, OpenAPI 3.1.0 उपलब्ध होने से पहले। + +आप इसे एक संक्षिप्त OpenAPI और JSON Schema **history lesson** मान सकते हैं। 🤓 + +/// + +/// warning | चेतावनी + +ये standards **JSON Schema** और **OpenAPI** के बारे में बहुत technical details हैं। + +यदि ऊपर दिए गए ideas आपके लिए पहले से ही काम कर रहे हैं, तो वह पर्याप्त हो सकता है, और शायद आपको इन details की जरूरत नहीं है, इन्हें skip करने के लिए स्वतंत्र महसूस करें। + +/// + +OpenAPI 3.1.0 से पहले, OpenAPI ने **JSON Schema** के एक पुराने और modified version का उपयोग किया। + +JSON Schema में `examples` नहीं था, इसलिए OpenAPI ने अपने स्वयं के modified version में अपना `example` field जोड़ा। + +OpenAPI ने specification के अन्य हिस्सों में भी `example` और `examples` fields जोड़े: + +* [`Parameter Object` (specification में)](https://github.com/OAI/OpenAPI-Specification/blob/main/versions/3.1.0.md#parameter-object) जिसका उपयोग FastAPI के इनसे किया गया: + * `Path()` + * `Query()` + * `Header()` + * `Cookie()` +* [`Request Body Object`, field `content` में, `Media Type Object` पर (specification में)](https://github.com/OAI/OpenAPI-Specification/blob/main/versions/3.1.0.md#media-type-object) जिसका उपयोग FastAPI के इनसे किया गया: + * `Body()` + * `File()` + * `Form()` + +/// note | नोट + +यह पुराना OpenAPI-specific `examples` parameter अब FastAPI `0.103.0` से `openapi_examples` है। + +/// + +### JSON Schema का `examples` field { #json-schemas-examples-field } + +लेकिन फिर JSON Schema ने specification के एक नए version में एक [`examples`](https://json-schema.org/draft/2019-09/json-schema-validation.html#rfc.section.9.5) field जोड़ा। + +और फिर नया OpenAPI 3.1.0 latest version (JSON Schema 2020-12) पर आधारित था, जिसमें यह नया field `examples` शामिल था। + +और अब यह नया `examples` field पुराने single (और custom) `example` field पर precedence लेता है, जो अब deprecated है। + +JSON Schema में यह नया `examples` field OpenAPI में अन्य जगहों (ऊपर वर्णित) की तरह अतिरिक्त metadata वाला dict नहीं है, यह **सिर्फ एक `list`** है। + +/// note | नोट + +OpenAPI 3.1.0 के JSON Schema के साथ इस नए सरल integration के साथ release होने के बाद भी, कुछ समय तक, Swagger UI, वह tool जो automatic docs प्रदान करता है, OpenAPI 3.1.0 को support नहीं करता था (यह version 5.0.0 से करता है 🎉)। + +इसी वजह से, 0.99.0 से पहले के FastAPI versions अभी भी OpenAPI के 3.1.0 से कम versions का उपयोग करते थे। + +/// + +### Pydantic और FastAPI `examples` { #pydantic-and-fastapi-examples } + +जब आप Pydantic model के अंदर `examples` जोड़ते हैं, `schema_extra` या `Field(examples=["something"])` का उपयोग करके, तो वह example उस Pydantic model के **JSON Schema** में जोड़ा जाता है। + +और उस Pydantic model का **JSON Schema** आपकी API के **OpenAPI** में शामिल होता है, और फिर docs UI में उपयोग किया जाता है। + +FastAPI के 0.99.0 से पहले के versions में (0.99.0 और ऊपर वाले नए OpenAPI 3.1.0 का उपयोग करते हैं), जब आप किसी भी अन्य utilities (`Query()`, `Body()`, आदि) के साथ `example` या `examples` का उपयोग करते थे, तो वे examples उस data का वर्णन करने वाले JSON Schema में नहीं जोड़े जाते थे (OpenAPI के JSON Schema के अपने version में भी नहीं), वे सीधे OpenAPI में *path operation* declaration में जोड़े जाते थे (OpenAPI के उन parts के बाहर जो JSON Schema का उपयोग करते हैं)। + +लेकिन अब जबकि FastAPI 0.99.0 और ऊपर OpenAPI 3.1.0 का उपयोग करता है, जो JSON Schema 2020-12 का उपयोग करता है, और Swagger UI 5.0.0 और ऊपर, सब कुछ अधिक consistent है और examples JSON Schema में शामिल होते हैं। + +### Swagger UI और OpenAPI-specific `examples` { #swagger-ui-and-openapi-specific-examples } + +अब, क्योंकि Swagger UI कई JSON Schema examples को support नहीं करता था (2023-08-26 तक), users के पास docs में कई examples दिखाने का कोई तरीका नहीं था। + +इसे solve करने के लिए, FastAPI `0.103.0` ने नए parameter `openapi_examples` के साथ उसी पुराने **OpenAPI-specific** `examples` field को घोषित करने के लिए **support जोड़ा**। 🤓 + +### Summary { #summary } + +मैं कहा करता था कि मुझे history उतनी पसंद नहीं है... और अब मुझे देखिए, "tech history" lessons दे रहा हूँ। 😅 + +संक्षेप में, **FastAPI 0.99.0 या उससे ऊपर upgrade करें**, और चीजें बहुत अधिक **सरल, consistent, और intuitive** हैं, और आपको ये सारे historical details जानने की जरूरत नहीं है। 😎 diff --git a/docs/hi/docs/tutorial/security/simple-oauth2.md b/docs/hi/docs/tutorial/security/simple-oauth2.md new file mode 100644 index 000000000..87c9a4a28 --- /dev/null +++ b/docs/hi/docs/tutorial/security/simple-oauth2.md @@ -0,0 +1,289 @@ +# Password और Bearer के साथ सरल OAuth2 { #simple-oauth2-with-password-and-bearer } + +अब पिछले अध्याय से आगे बढ़ते हैं और एक पूरा security flow बनाने के लिए छूटे हुए हिस्से जोड़ते हैं। + +## `username` और `password` प्राप्त करें { #get-the-username-and-password } + +हम `username` और `password` प्राप्त करने के लिए **FastAPI** security utilities का उपयोग करने वाले हैं। + +OAuth2 निर्दिष्ट करता है कि "password flow" (जिसका हम उपयोग कर रहे हैं) का उपयोग करते समय client/user को `username` और `password` fields को form data के रूप में भेजना होगा। + +और spec कहता है कि fields के नाम ऐसे ही होने चाहिए। इसलिए `user-name` या `email` काम नहीं करेगा। + +लेकिन चिंता न करें, frontend में आप इसे अपने अंतिम users को जैसे चाहें दिखा सकते हैं। + +और आपके database models कोई भी दूसरे नाम उपयोग कर सकते हैं जो आप चाहें। + +लेकिन login *path operation* के लिए, हमें spec के साथ compatible होने के लिए इन नामों का उपयोग करना होगा (और उदाहरण के लिए, integrated API documentation system का उपयोग कर पाने के लिए)। + +Spec यह भी बताता है कि `username` और `password` को form data के रूप में भेजा जाना चाहिए (इसलिए, यहाँ कोई JSON नहीं)। + +### `scope` { #scope } + +Spec यह भी कहता है कि client एक और form field "`scope`" भेज सकता है। + +form field का नाम `scope` है (singular में), लेकिन यह वास्तव में spaces से अलग किए गए "scopes" वाली एक लंबी string होती है। + +हर "scope" बस एक string है (बिना spaces के)। + +इनका सामान्यतः विशिष्ट security permissions घोषित करने के लिए उपयोग किया जाता है, उदाहरण के लिए: + +* `users:read` या `users:write` आम उदाहरण हैं। +* `instagram_basic` Facebook / Instagram द्वारा उपयोग किया जाता है। +* `https://www.googleapis.com/auth/drive` Google द्वारा उपयोग किया जाता है। + +/// note | नोट + +OAuth2 में "scope" बस एक string है जो किसी विशिष्ट required permission को घोषित करती है। + +इससे फर्क नहीं पड़ता कि उसमें `:` जैसे अन्य characters हैं या वह URL है। + +वे details implementation specific हैं। + +OAuth2 के लिए वे बस strings हैं। + +/// + +## `username` और `password` प्राप्त करने का Code { #code-to-get-the-username-and-password } + +अब इसे संभालने के लिए **FastAPI** द्वारा प्रदान की गई utilities का उपयोग करते हैं। + +### `OAuth2PasswordRequestForm` { #oauth2passwordrequestform } + +पहले, `OAuth2PasswordRequestForm` import करें, और `/token` के *path operation* में `Depends` के साथ इसे dependency के रूप में उपयोग करें: + +{* ../../docs_src/security/tutorial003_an_py310.py hl[4,78] *} + +`OAuth2PasswordRequestForm` एक class dependency है जो एक form body घोषित करती है जिसमें: + +* `username`। +* `password`। +* एक वैकल्पिक `scope` field, एक बड़ी string के रूप में, जो spaces से अलग की गई strings से बनी होती है। +* एक वैकल्पिक `grant_type`। + +/// tip | टिप + +OAuth2 spec वास्तव में fixed value `password` के साथ एक field `grant_type` *required* करता है, लेकिन `OAuth2PasswordRequestForm` इसे enforce नहीं करता। + +अगर आपको इसे enforce करना है, तो `OAuth2PasswordRequestForm` की जगह `OAuth2PasswordRequestFormStrict` का उपयोग करें। + +/// + +* एक वैकल्पिक `client_id` (हमारे उदाहरण के लिए हमें इसकी आवश्यकता नहीं है)। +* एक वैकल्पिक `client_secret` (हमारे उदाहरण के लिए हमें इसकी आवश्यकता नहीं है)। + +/// note | नोट + +`OAuth2PasswordRequestForm`, **FastAPI** के लिए कोई विशेष class नहीं है जैसे `OAuth2PasswordBearer` है। + +`OAuth2PasswordBearer` **FastAPI** को बताता है कि यह एक security scheme है। इसलिए इसे OpenAPI में इस तरह जोड़ा जाता है। + +लेकिन `OAuth2PasswordRequestForm` बस एक class dependency है जिसे आप खुद भी लिख सकते थे, या आप सीधे `Form` parameters घोषित कर सकते थे। + +लेकिन क्योंकि यह एक सामान्य use case है, इसे आसान बनाने के लिए **FastAPI** द्वारा सीधे प्रदान किया गया है। + +/// + +### form data का उपयोग करें { #use-the-form-data } + +/// tip | टिप + +dependency class `OAuth2PasswordRequestForm` के instance में spaces से अलग की गई लंबी string वाला attribute `scope` नहीं होगा, इसके बजाय, इसमें भेजे गए प्रत्येक scope के लिए actual strings की list वाला `scopes` attribute होगा। + +हम इस उदाहरण में `scopes` का उपयोग नहीं कर रहे हैं, लेकिन यदि आपको इसकी आवश्यकता हो तो functionality उपलब्ध है। + +/// + +अब, form field से `username` का उपयोग करके (fake) database से user data प्राप्त करें। + +यदि ऐसा कोई user नहीं है, तो हम "Incorrect username or password" कहते हुए error लौटाते हैं। + +Error के लिए, हम exception `HTTPException` का उपयोग करते हैं: + +{* ../../docs_src/security/tutorial003_an_py310.py hl[3,79:81] *} + +### password जाँचें { #check-the-password } + +इस समय हमारे पास database से user data है, लेकिन हमने password नहीं जाँचा है। + +पहले उस data को Pydantic `UserInDB` model में डालते हैं। + +आपको कभी भी plaintext passwords save नहीं करने चाहिए, इसलिए, हम (fake) password hashing system का उपयोग करेंगे। + +यदि passwords match नहीं करते, तो हम वही error लौटाते हैं। + +#### Password hashing { #password-hashing } + +"Hashing" का मतलब है: कुछ content (इस मामले में password) को bytes की sequence (बस एक string) में convert करना जो बेतरतीब दिखती है। + +जब भी आप बिल्कुल वही content (बिल्कुल वही password) पास करते हैं, तो आपको बिल्कुल वही बेतरतीब string मिलती है। + +लेकिन आप उस बेतरतीब string से वापस password में convert नहीं कर सकते। + +##### Password hashing का उपयोग क्यों करें { #why-use-password-hashing } + +अगर आपका database चोरी हो जाता है, तो चोर के पास आपके users के plaintext passwords नहीं होंगे, केवल hashes होंगे। + +इसलिए, चोर उन same passwords को किसी दूसरे system में उपयोग करने की कोशिश नहीं कर पाएगा (क्योंकि कई users हर जगह वही password उपयोग करते हैं, यह खतरनाक होगा)। + +{* ../../docs_src/security/tutorial003_an_py310.py hl[82:85] *} + +#### `**user_dict` के बारे में { #about-user-dict } + +`UserInDB(**user_dict)` का मतलब है: + +*`user_dict` की keys और values को सीधे key-value arguments के रूप में पास करें, इसके बराबर:* + +```Python +UserInDB( + username = user_dict["username"], + email = user_dict["email"], + full_name = user_dict["full_name"], + disabled = user_dict["disabled"], + hashed_password = user_dict["hashed_password"], +) +``` + +/// note | नोट + +`**user_dict` की अधिक पूरी explanation के लिए [**Extra Models** के documentation](../extra-models.md#about-user-in-model-dump) में वापस देखें। + +/// + +## token लौटाएँ { #return-the-token } + +`token` endpoint का response एक JSON object होना चाहिए। + +इसमें `token_type` होना चाहिए। हमारे मामले में, क्योंकि हम "Bearer" tokens का उपयोग कर रहे हैं, token type "`bearer`" होना चाहिए। + +और इसमें `access_token` होना चाहिए, जिसमें हमारे access token वाली एक string हो। + +इस सरल उदाहरण के लिए, हम बस पूरी तरह insecure रहेंगे और token के रूप में वही `username` लौटाएँगे। + +/// tip | टिप + +अगले अध्याय में, आप password hashing और JWT tokens के साथ एक वास्तविक secure implementation देखेंगे। + +लेकिन अभी के लिए, आइए उन specific details पर ध्यान दें जिनकी हमें आवश्यकता है। + +/// + +{* ../../docs_src/security/tutorial003_an_py310.py hl[87] *} + +/// tip | टिप + +Spec के अनुसार, आपको `access_token` और `token_type` के साथ एक JSON लौटाना चाहिए, बिल्कुल इस उदाहरण की तरह। + +यह कुछ ऐसा है जो आपको अपने code में स्वयं करना होगा, और सुनिश्चित करना होगा कि आप उन JSON keys का उपयोग करें। + +Specifications के compliant होने के लिए, यह लगभग एकमात्र चीज है जिसे आपको सही तरीके से खुद करना याद रखना होगा। + +बाकी सब **FastAPI** आपके लिए संभालता है। + +/// + +## dependencies अपडेट करें { #update-the-dependencies } + +अब हम अपनी dependencies अपडेट करने वाले हैं। + +हम `current_user` को *केवल* तब प्राप्त करना चाहते हैं जब यह user active हो। + +इसलिए, हम एक अतिरिक्त dependency `get_current_active_user` बनाते हैं जो बदले में `get_current_user` को dependency के रूप में उपयोग करती है। + +ये दोनों dependencies बस एक HTTP error लौटाएँगी यदि user मौजूद नहीं है, या inactive है। + +इसलिए, हमारे endpoint में, हमें user केवल तभी मिलेगा जब user मौजूद हो, सही तरीके से authenticated हो, और active हो: + +{* ../../docs_src/security/tutorial003_an_py310.py hl[58:66,69:74,94] *} + +/// note | नोट + +Value `Bearer` के साथ अतिरिक्त header `WWW-Authenticate`, जिसे हम यहाँ लौटा रहे हैं, spec का भी हिस्सा है। + +किसी भी HTTP (error) status code 401 "UNAUTHORIZED" को `WWW-Authenticate` header भी लौटाना चाहिए। + +Bearer tokens (हमारे मामले) में, उस header की value `Bearer` होनी चाहिए। + +आप वास्तव में उस अतिरिक्त header को छोड़ सकते हैं और फिर भी यह काम करेगा। + +लेकिन specifications के compliant होने के लिए इसे यहाँ प्रदान किया गया है। + +साथ ही, ऐसे tools हो सकते हैं जो इसकी अपेक्षा करते हैं और इसका उपयोग करते हैं (अभी या भविष्य में) और यह आपके या आपके users के लिए उपयोगी हो सकता है, अभी या भविष्य में। + +यही standards का लाभ है... + +/// + +## इसे काम करते देखें { #see-it-in-action } + +Interactive docs खोलें: [http://127.0.0.1:8000/docs](http://127.0.0.1:8000/docs)। + +### Authenticate करें { #authenticate } + +"Authorize" button पर click करें। + +Credentials का उपयोग करें: + +User: `johndoe` + +Password: `secret` + + + +System में authenticate होने के बाद, आप इसे ऐसे देखेंगे: + + + +### अपना user data प्राप्त करें { #get-your-own-user-data } + +अब path `/users/me` के साथ operation `GET` का उपयोग करें। + +आपको अपने user का data मिलेगा, जैसे: + +```JSON +{ + "username": "johndoe", + "email": "johndoe@example.com", + "full_name": "John Doe", + "disabled": false, + "hashed_password": "fakehashedsecret" +} +``` + + + +यदि आप lock icon पर click करके logout करते हैं, और फिर वही operation दोबारा आज़माते हैं, तो आपको HTTP 401 error मिलेगा: + +```JSON +{ + "detail": "Not authenticated" +} +``` + +### Inactive user { #inactive-user } + +अब एक inactive user के साथ प्रयास करें, इनके साथ authenticate करें: + +User: `alice` + +Password: `secret2` + +और path `/users/me` के साथ operation `GET` का उपयोग करने का प्रयास करें। + +आपको "Inactive user" error मिलेगा, जैसे: + +```JSON +{ + "detail": "Inactive user" +} +``` + +## Recap { #recap } + +अब आपके पास अपनी API के लिए `username` और `password` पर आधारित एक पूरा security system implement करने के tools हैं। + +इन tools का उपयोग करके, आप security system को किसी भी database और किसी भी user या data model के साथ compatible बना सकते हैं। + +एकमात्र detail जो missing है वह यह है कि यह अभी वास्तव में "secure" नहीं है। + +अगले अध्याय में आप देखेंगे कि secure password hashing library और JWT tokens का उपयोग कैसे करें। diff --git a/docs/hi/docs/tutorial/server-sent-events.md b/docs/hi/docs/tutorial/server-sent-events.md new file mode 100644 index 000000000..cb23938df --- /dev/null +++ b/docs/hi/docs/tutorial/server-sent-events.md @@ -0,0 +1,120 @@ +# Server-Sent Events (SSE) { #server-sent-events-sse } + +आप **Server-Sent Events** (SSE) का उपयोग करके client को data stream कर सकते हैं। + +यह [Stream JSON Lines](stream-json-lines.md) जैसा है, लेकिन `text/event-stream` format का उपयोग करता है, जिसे browsers [`EventSource` API](https://developer.mozilla.org/en-US/docs/Web/API/EventSource) के साथ natively support करते हैं। + +/// note | नोट + +FastAPI 0.135.0 में जोड़ा गया। + +/// + +## Server-Sent Events क्या हैं? { #what-are-server-sent-events } + +SSE, HTTP के माध्यम से server से client तक data stream करने के लिए एक standard है। + +हर event एक छोटा text block होता है जिसमें `data`, `event`, `id`, और `retry` जैसे "fields" होते हैं, जिन्हें खाली lines से अलग किया जाता है। + +यह ऐसा दिखता है: + +``` +data: {"name": "Portal Gun", "price": 999.99} + +data: {"name": "Plumbus", "price": 32.99} + +``` + +SSE का उपयोग आमतौर पर AI chat streaming, live notifications, logs और observability, और अन्य मामलों में किया जाता है जहाँ server client को updates push करता है। + +/// tip | सुझाव + +अगर आप binary data stream करना चाहते हैं, जैसे video या audio, तो advanced guide देखें: [Data Stream करें](../advanced/stream-data.md). + +/// + +## FastAPI के साथ SSE Stream करें { #stream-sse-with-fastapi } + +FastAPI के साथ SSE stream करने के लिए, अपनी *path operation function* में `yield` का उपयोग करें और `response_class=EventSourceResponse` set करें। + +`EventSourceResponse` को `fastapi.sse` से import करें: + +{* ../../docs_src/server_sent_events/tutorial001_py310.py ln[1:25] hl[4,22] *} + +हर yielded item को JSON के रूप में encode किया जाता है और SSE event के `data:` field में भेजा जाता है। + +अगर आप return type को `AsyncIterable[Item]` के रूप में declare करते हैं, तो FastAPI इसका उपयोग Pydantic के साथ data को **validate**, **document**, और **serialize** करने के लिए करेगा। + +{* ../../docs_src/server_sent_events/tutorial001_py310.py ln[1:25] hl[10:12,23] *} + +/// tip | सुझाव + +क्योंकि Pydantic इसे **Rust** side में serialize करेगा, आपको return type declare न करने की तुलना में कहीं बेहतर **performance** मिलेगी। + +/// + +### Non-async *path operation functions* { #non-async-path-operation-functions } + +आप नियमित `def` functions (बिना `async`) का भी उपयोग कर सकते हैं, और उसी तरह `yield` का उपयोग कर सकते हैं। + +FastAPI सुनिश्चित करेगा कि यह सही तरीके से run हो ताकि यह event loop को block न करे। + +क्योंकि इस मामले में function async नहीं है, सही return type `Iterable[Item]` होगा: + +{* ../../docs_src/server_sent_events/tutorial001_py310.py ln[28:31] hl[29] *} + +### कोई Return Type नहीं { #no-return-type } + +आप return type को छोड़ भी सकते हैं। FastAPI data को convert करने और भेजने के लिए [`jsonable_encoder`](./encoder.md) का उपयोग करेगा। + +{* ../../docs_src/server_sent_events/tutorial001_py310.py ln[34:37] hl[35] *} + +## `ServerSentEvent` { #serversentevent } + +अगर आपको `event`, `id`, `retry`, या `comment` जैसे SSE fields set करने की ज़रूरत है, तो आप plain data के बजाय `ServerSentEvent` objects yield कर सकते हैं। + +`ServerSentEvent` को `fastapi.sse` से import करें: + +{* ../../docs_src/server_sent_events/tutorial002_py310.py hl[4,26] *} + +`data` field हमेशा JSON के रूप में encode किया जाता है। आप कोई भी value pass कर सकते हैं जिसे JSON के रूप में serialize किया जा सकता हो, जिसमें Pydantic models भी शामिल हैं। + +## Raw Data { #raw-data } + +अगर आपको JSON encoding के **बिना** data भेजना है, तो `data` के बजाय `raw_data` का उपयोग करें। + +यह pre-formatted text, log lines, या `[DONE]` जैसे विशेष "sentinel" values भेजने के लिए उपयोगी है। + +{* ../../docs_src/server_sent_events/tutorial003_py310.py hl[17] *} + +/// note | नोट + +`data` और `raw_data` mutually exclusive हैं। आप हर `ServerSentEvent` पर उनमें से केवल एक ही set कर सकते हैं। + +/// + +## `Last-Event-ID` के साथ फिर से शुरू करना { #resuming-with-last-event-id } + +जब कोई browser connection drop होने के बाद reconnect करता है, तो वह अंतिम प्राप्त `id` को `Last-Event-ID` header में भेजता है। + +आप इसे header parameter के रूप में read कर सकते हैं और stream को वहाँ से resume करने के लिए उपयोग कर सकते हैं जहाँ client ने छोड़ा था: + +{* ../../docs_src/server_sent_events/tutorial004_py310.py hl[25,27,31] *} + +## POST के साथ SSE { #sse-with-post } + +SSE **किसी भी HTTP method** के साथ काम करता है, केवल `GET` के साथ नहीं। + +यह [MCP](https://modelcontextprotocol.io) जैसे protocols के लिए उपयोगी है, जो `POST` पर SSE stream करते हैं: + +{* ../../docs_src/server_sent_events/tutorial005_py310.py hl[14] *} + +## तकनीकी विवरण { #technical-details } + +FastAPI कुछ SSE best practices को out of the box implement करता है। + +* जब कोई message नहीं आया हो, तो हर 15 सेकंड में **"keep alive" `ping` comment** भेजें, ताकि कुछ proxies connection को close न कर दें, जैसा कि [HTML specification: Server-Sent Events](https://html.spec.whatwg.org/multipage/server-sent-events.html#authoring-notes) में सुझाया गया है। +* stream की **caching रोकने** के लिए `Cache-Control: no-cache` header set करें। +* Nginx जैसे कुछ proxies में **buffering रोकने** के लिए एक special header `X-Accel-Buffering: no` set करें। + +आपको इसके लिए कुछ भी करने की ज़रूरत नहीं है, यह out of the box काम करता है। 🤓 diff --git a/docs/hi/docs/tutorial/sql-databases.md b/docs/hi/docs/tutorial/sql-databases.md new file mode 100644 index 000000000..041da16e9 --- /dev/null +++ b/docs/hi/docs/tutorial/sql-databases.md @@ -0,0 +1,357 @@ +# SQL (Relational) डेटाबेस { #sql-relational-databases } + +**FastAPI** के लिए SQL (relational) डेटाबेस इस्तेमाल करना required नहीं है। लेकिन आप **कोई भी डेटाबेस** इस्तेमाल कर सकते हैं जो आप चाहें। + +यहाँ हम [SQLModel](https://sqlmodel.tiangolo.com/) का उपयोग करके एक उदाहरण देखेंगे। + +**SQLModel**, [SQLAlchemy](https://www.sqlalchemy.org/) और Pydantic के ऊपर बना है। इसे **FastAPI** के उसी लेखक ने बनाया है ताकि यह उन FastAPI applications के लिए perfect match हो जिन्हें **SQL databases** इस्तेमाल करने की जरूरत होती है। + +/// tip | टिप + +आप अपनी पसंद की कोई भी दूसरी SQL या NoSQL डेटाबेस लाइब्रेरी इस्तेमाल कर सकते हैं (कुछ मामलों में इन्हें "ORMs" कहा जाता है), FastAPI आपको कुछ भी इस्तेमाल करने के लिए मजबूर नहीं करता। 😎 + +/// + +क्योंकि SQLModel, SQLAlchemy पर आधारित है, आप SQLAlchemy द्वारा **supported कोई भी डेटाबेस** आसानी से इस्तेमाल कर सकते हैं (जिससे वे SQLModel द्वारा भी supported हो जाते हैं), जैसे: + +* PostgreSQL +* MySQL +* SQLite +* Oracle +* Microsoft SQL Server, आदि। + +इस उदाहरण में, हम **SQLite** इस्तेमाल करेंगे, क्योंकि यह एक single file का उपयोग करता है और Python में इसके लिए integrated support है। इसलिए, आप इस उदाहरण को copy कर सकते हैं और जैसा है वैसा ही run कर सकते हैं। + +बाद में, अपनी production application के लिए, आप **PostgreSQL** जैसा database server इस्तेमाल करना चाह सकते हैं। + +/// tip | टिप + +**FastAPI** और **PostgreSQL** के साथ एक official project generator है जिसमें frontend और अधिक tools शामिल हैं: [https://github.com/fastapi/full-stack-fastapi-template](https://github.com/fastapi/full-stack-fastapi-template) + +/// + +यह एक बहुत ही सरल और छोटा tutorial है, अगर आप सामान्य रूप से databases, SQL, या अधिक advanced features के बारे में सीखना चाहते हैं, तो [SQLModel docs](https://sqlmodel.tiangolo.com/) पर जाएँ। + +## `SQLModel` install करें { #install-sqlmodel } + +सबसे पहले, सुनिश्चित करें कि आप अपना [virtual environment](../virtual-environments.md) बनाएँ, उसे activate करें, और फिर `sqlmodel` install करें: + +
+ +```console +$ pip install sqlmodel +---> 100% +``` + +
+ +## Single Model के साथ App बनाएँ { #create-the-app-with-a-single-model } + +हम पहले एक single **SQLModel** model के साथ app का सबसे सरल पहला version बनाएँगे। + +बाद में हम नीचे **multiple models** के साथ security और versatility बढ़ाते हुए इसे बेहतर बनाएँगे। 🤓 + +### Models बनाएँ { #create-models } + +`SQLModel` import करें और एक डेटाबेस model बनाएँ: + +{* ../../docs_src/sql_databases/tutorial001_an_py310.py ln[1:11] hl[7:11] *} + +`Hero` class एक Pydantic model से बहुत मिलती-जुलती है (वास्तव में, अंदर से, यह सच में *एक Pydantic model ही है*)। + +कुछ अंतर हैं: + +* `table=True` SQLModel को बताता है कि यह एक *table model* है, इसे SQL डेटाबेस में एक **table** को represent करना चाहिए, यह सिर्फ एक *data model* नहीं है (जैसा कि कोई भी दूसरी regular Pydantic class होती)। + +* `Field(primary_key=True)` SQLModel को बताता है कि `id` SQL डेटाबेस में **primary key** है (आप SQL primary keys के बारे में SQLModel docs में अधिक जान सकते हैं)। + + **ध्यान दें:** हम primary key field के लिए `int | None` का उपयोग करते हैं ताकि Python code में हम *बिना `id` के object बना सकें* (`id=None`), यह मानते हुए कि डेटाबेस *save करते समय इसे generate करेगा*। SQLModel समझता है कि डेटाबेस `id` provide करेगा और डेटाबेस schema में *column को non-null `INTEGER` के रूप में define करता है*। विवरण के लिए [primary keys पर SQLModel docs](https://sqlmodel.tiangolo.com/tutorial/create-db-and-table/#primary-key-id) देखें। + +* `Field(index=True)` SQLModel को बताता है कि उसे इस column के लिए एक **SQL index** बनाना चाहिए, जिससे इस column द्वारा filtered data पढ़ते समय डेटाबेस में तेज़ lookups हो सकें। + + SQLModel जान जाएगा कि `str` के रूप में declared कोई चीज़ `TEXT` type का SQL column होगी (या डेटाबेस के आधार पर `VARCHAR`)। + +### Engine बनाएँ { #create-an-engine } + +SQLModel `engine` (अंदर से यह वास्तव में SQLAlchemy `engine` है) वह है जो डेटाबेस से **connections को hold** करता है। + +आपके सभी code के लिए उसी डेटाबेस से connect करने हेतु **एक single `engine` object** होगा। + +{* ../../docs_src/sql_databases/tutorial001_an_py310.py ln[14:18] hl[14:15,17:18] *} + +`check_same_thread=False` का उपयोग FastAPI को अलग-अलग threads में वही SQLite डेटाबेस इस्तेमाल करने देता है। यह necessary है क्योंकि **एक single request** **एक से अधिक thread** का उपयोग कर सकती है (उदाहरण के लिए dependencies में)। + +चिंता न करें, code जिस तरह structured है, उससे हम सुनिश्चित करेंगे कि बाद में हम **प्रति request एक single SQLModel *session*** इस्तेमाल करें, वास्तव में `check_same_thread` यही हासिल करने की कोशिश कर रहा है। + +### Tables बनाएँ { #create-the-tables } + +फिर हम एक function जोड़ते हैं जो सभी *table models* के लिए **tables बनाने** हेतु `SQLModel.metadata.create_all(engine)` का उपयोग करता है। + +{* ../../docs_src/sql_databases/tutorial001_an_py310.py ln[21:22] hl[21:22] *} + +### Session Dependency बनाएँ { #create-a-session-dependency } + +**`Session`** वह है जो **objects को memory में store** करता है और data में required किसी भी बदलाव का track रखता है, फिर यह डेटाबेस से communicate करने के लिए **`engine` का उपयोग करता है**। + +हम `yield` के साथ एक FastAPI **dependency** बनाएँगे जो हर request के लिए एक नया `Session` provide करेगी। यही सुनिश्चित करता है कि हम प्रति request एक single session इस्तेमाल करें। 🤓 + +फिर हम इस dependency का उपयोग करने वाले बाकी code को आसान बनाने के लिए एक `Annotated` dependency `SessionDep` बनाते हैं। + +{* ../../docs_src/sql_databases/tutorial001_an_py310.py ln[25:30] hl[25:27,30] *} + +### Startup पर Database Tables बनाएँ { #create-database-tables-on-startup } + +हम application शुरू होने पर database tables बनाएँगे। + +{* ../../docs_src/sql_databases/tutorial001_an_py310.py ln[32:37] hl[35:37] *} + +यहाँ हम application startup event पर tables बनाते हैं। + +production के लिए आप शायद एक migration script इस्तेमाल करेंगे जो आपका app शुरू करने से पहले run होती है। 🤓 + +/// tip | टिप + +SQLModel में Alembic को wrap करने वाली migration utilities होंगी, लेकिन अभी के लिए, आप सीधे [Alembic](https://alembic.sqlalchemy.org/en/latest/) इस्तेमाल कर सकते हैं। + +/// + +### Hero बनाएँ { #create-a-hero } + +क्योंकि हर SQLModel model एक Pydantic model भी है, आप इसे उसी **type annotations** में इस्तेमाल कर सकते हैं जिनमें आप Pydantic models इस्तेमाल करते। + +उदाहरण के लिए, अगर आप `Hero` type का parameter declare करते हैं, तो यह **JSON body** से read किया जाएगा। + +उसी तरह, आप इसे function के **return type** के रूप में declare कर सकते हैं, और फिर data का shape automatic API docs UI में दिखाई देगा। + +{* ../../docs_src/sql_databases/tutorial001_an_py310.py ln[40:45] hl[40:45] *} + +यहाँ हम `SessionDep` dependency (एक `Session`) का उपयोग करके नए `Hero` को `Session` instance में add करते हैं, changes को डेटाबेस में commit करते हैं, `hero` में data refresh करते हैं, और फिर उसे return करते हैं। + +### Heroes पढ़ें { #read-heroes } + +हम `select()` का उपयोग करके डेटाबेस से `Hero`s **read** कर सकते हैं। results को paginate करने के लिए हम `limit` और `offset` include कर सकते हैं। + +{* ../../docs_src/sql_databases/tutorial001_an_py310.py ln[48:55] hl[51:52,54] *} + +### एक Hero पढ़ें { #read-one-hero } + +हम एक single `Hero` **read** कर सकते हैं। + +{* ../../docs_src/sql_databases/tutorial001_an_py310.py ln[58:63] hl[60] *} + +### Hero Delete करें { #delete-a-hero } + +हम एक `Hero` को **delete** भी कर सकते हैं। + +{* ../../docs_src/sql_databases/tutorial001_an_py310.py ln[66:73] hl[71] *} + +### App Run करें { #run-the-app } + +आप app run कर सकते हैं: + +
+ +```console +$ fastapi dev + +INFO: Uvicorn running on http://127.0.0.1:8000 (Press CTRL+C to quit) +``` + +
+ +फिर `/docs` UI पर जाएँ, आप देखेंगे कि **FastAPI** API को **document** करने के लिए इन **models** का उपयोग कर रहा है, और यह data को **serialize** और **validate** करने के लिए भी इनका उपयोग करेगा। + +
+ +
+ +## Multiple Models के साथ App Update करें { #update-the-app-with-multiple-models } + +अब आइए **security** और **versatility** बढ़ाने के लिए इस app को थोड़ा **refactor** करें। + +अगर आप previous app देखें, तो UI में आप देख सकते हैं कि अभी तक यह client को बनने वाले `Hero` का `id` तय करने देता है। 😱 + +हमें ऐसा नहीं होने देना चाहिए, वे DB में पहले से assigned किसी `id` को overwrite कर सकते हैं। `id` तय करना **backend** या **database** द्वारा किया जाना चाहिए, **client द्वारा नहीं**। + +इसके अलावा, हम hero के लिए `secret_name` बनाते हैं, लेकिन अब तक, हम इसे हर जगह return कर रहे हैं, यह बहुत **secret** नहीं है... 😅 + +हम कुछ **extra models** जोड़कर इन चीज़ों को ठीक करेंगे। यहीं SQLModel चमकेगा। ✨ + +### Multiple Models बनाएँ { #create-multiple-models } + +**SQLModel** में, कोई भी model class जिसमें `table=True` है, एक **table model** है। + +और कोई भी model class जिसमें `table=True` नहीं है, एक **data model** है, ये वास्तव में सिर्फ Pydantic models हैं (कुछ छोटे extra features के साथ)। 🤓 + +SQLModel के साथ, हम सभी मामलों में सभी fields को **duplicate करने से बचने** के लिए **inheritance** का उपयोग कर सकते हैं। + +#### `HeroBase` - base class { #herobase-the-base-class } + +आइए एक `HeroBase` model से शुरू करें जिसमें सभी models द्वारा **shared fields** हों: + +* `name` +* `age` + +{* ../../docs_src/sql_databases/tutorial002_an_py310.py ln[7:9] hl[7:9] *} + +#### `Hero` - *table model* { #hero-the-table-model } + +फिर आइए `Hero` बनाएँ, वास्तविक *table model*, जिसमें वे **extra fields** हों जो हमेशा दूसरे models में नहीं होते: + +* `id` +* `secret_name` + +क्योंकि `Hero`, `HeroBase` से inherit करता है, इसमें `HeroBase` में declared **fields** भी हैं, इसलिए `Hero` के लिए सभी fields हैं: + +* `id` +* `name` +* `age` +* `secret_name` + +{* ../../docs_src/sql_databases/tutorial002_an_py310.py ln[7:14] hl[12:14] *} + +#### `HeroPublic` - public *data model* { #heropublic-the-public-data-model } + +इसके बाद, हम एक `HeroPublic` model बनाते हैं, यही वह है जो API के clients को **return** किया जाएगा। + +इसमें `HeroBase` जैसे ही fields हैं, इसलिए इसमें `secret_name` शामिल नहीं होगा। + +आख़िरकार, हमारे heroes की identity protected है! 🥷 + +यह `id: int` को फिर से declare भी करता है। ऐसा करके, हम API clients के साथ एक **contract** बना रहे हैं, ताकि वे हमेशा expect कर सकें कि `id` मौजूद होगा और `int` होगा (यह कभी `None` नहीं होगा)। + +/// tip | टिप + +return model से यह सुनिश्चित करवाना कि कोई value हमेशा available है और हमेशा `int` है (`None` नहीं), API clients के लिए बहुत उपयोगी है, वे इस certainty के साथ बहुत सरल code लिख सकते हैं। + +साथ ही, **automatically generated clients** में सरल interfaces होंगे, ताकि आपकी API से communicate करने वाले developers आपकी API के साथ काम करते समय बहुत बेहतर अनुभव पा सकें। 😎 + +/// + +`HeroPublic` में सभी fields `HeroBase` जैसे ही हैं, जिसमें `id` को `int` (`None` नहीं) के रूप में declared किया गया है: + +* `id` +* `name` +* `age` + +{* ../../docs_src/sql_databases/tutorial002_an_py310.py ln[7:18] hl[17:18] *} + +#### `HeroCreate` - hero बनाने के लिए *data model* { #herocreate-the-data-model-to-create-a-hero } + +अब हम एक `HeroCreate` model बनाते हैं, यही वह है जो clients से आने वाले data को **validate** करेगा। + +इसमें `HeroBase` जैसे ही fields हैं, और इसमें `secret_name` भी है। + +अब, जब clients **एक नया hero create** करेंगे, वे `secret_name` भेजेंगे, यह डेटाबेस में store होगा, लेकिन वे secret names API में clients को return नहीं किए जाएँगे। + +/// tip | टिप + +आप **passwords** को ऐसे handle करेंगे। उन्हें receive करें, लेकिन API में return न करें। + +आप passwords की values को store करने से पहले **hash** भी करेंगे, **उन्हें plain text में कभी store न करें**। + +/// + +`HeroCreate` के fields हैं: + +* `name` +* `age` +* `secret_name` + +{* ../../docs_src/sql_databases/tutorial002_an_py310.py ln[7:22] hl[21:22] *} + +#### `HeroUpdate` - hero update करने के लिए *data model* { #heroupdate-the-data-model-to-update-a-hero } + +app के previous version में हमारे पास **hero update करने** का तरीका नहीं था, लेकिन अब **multiple models** के साथ, हम ऐसा कर सकते हैं। 🎉 + +`HeroUpdate` *data model* थोड़ा special है, इसमें **वे सभी same fields** हैं जिनकी एक नया hero create करने के लिए जरूरत होगी, लेकिन सभी fields **optional** हैं (उन सभी की default value है)। इस तरह, जब आप hero update करते हैं, तो आप सिर्फ वे fields भेज सकते हैं जिन्हें आप update करना चाहते हैं। + +क्योंकि सभी **fields वास्तव में change होते हैं** (type में अब `None` शामिल है और अब उनकी default value `None` है), हमें उन्हें **re-declare** करना होगा। + +हमें वास्तव में `HeroBase` से inherit करने की जरूरत नहीं है क्योंकि हम सभी fields को re-declare कर रहे हैं। मैं consistency के लिए इसे inherit करता हुआ छोड़ूँगा, लेकिन यह necessary नहीं है। यह personal taste का मामला अधिक है। 🤷 + +`HeroUpdate` के fields हैं: + +* `name` +* `age` +* `secret_name` + +{* ../../docs_src/sql_databases/tutorial002_an_py310.py ln[7:28] hl[25:28] *} + +### `HeroCreate` के साथ create करें और `HeroPublic` return करें { #create-with-herocreate-and-return-a-heropublic } + +अब जब हमारे पास **multiple models** हैं, हम app के उन parts को update कर सकते हैं जो उनका उपयोग करते हैं। + +हम request में एक `HeroCreate` *data model* receive करते हैं, और उससे, हम एक `Hero` *table model* बनाते हैं। + +इस नए *table model* `Hero` में client द्वारा भेजे गए fields होंगे, और इसमें डेटाबेस द्वारा generated एक `id` भी होगा। + +फिर हम उसी *table model* `Hero` को function से जैसा है वैसा ही return करते हैं। लेकिन क्योंकि हम `response_model` को `HeroPublic` *data model* के साथ declare करते हैं, **FastAPI** data को validate और serialize करने के लिए `HeroPublic` का उपयोग करेगा। + +{* ../../docs_src/sql_databases/tutorial002_an_py310.py ln[56:62] hl[56:58] *} + +/// tip | टिप + +अब हम **return type annotation** `-> HeroPublic` के बजाय `response_model=HeroPublic` इस्तेमाल करते हैं क्योंकि जो value हम return कर रहे हैं वह वास्तव में `HeroPublic` *नहीं* है। + +अगर हमने `-> HeroPublic` declare किया होता, तो आपका editor और linter complain करते (और सही करते) कि आप `HeroPublic` के बजाय `Hero` return कर रहे हैं। + +इसे `response_model` में declare करके हम **FastAPI** को अपना काम करने के लिए कह रहे हैं, बिना type annotations और आपके editor व अन्य tools से मिलने वाली help में interfere किए। + +/// + +### `HeroPublic` के साथ Heroes पढ़ें { #read-heroes-with-heropublic } + +हम `Hero`s को **read** करने के लिए पहले जैसा ही कर सकते हैं, फिर से, हम यह सुनिश्चित करने के लिए `response_model=list[HeroPublic]` का उपयोग करते हैं कि data सही तरीके से validate और serialize हो। + +{* ../../docs_src/sql_databases/tutorial002_an_py310.py ln[65:72] hl[65] *} + +### `HeroPublic` के साथ एक Hero पढ़ें { #read-one-hero-with-heropublic } + +हम एक single hero **read** कर सकते हैं: + +{* ../../docs_src/sql_databases/tutorial002_an_py310.py ln[75:80] hl[77] *} + +### `HeroUpdate` के साथ Hero Update करें { #update-a-hero-with-heroupdate } + +हम **hero update** कर सकते हैं। इसके लिए हम HTTP `PATCH` operation इस्तेमाल करते हैं। + +और code में, हमें client द्वारा भेजे गए सभी data के साथ एक `dict` मिलता है, **सिर्फ client द्वारा भेजा गया data**, उन किसी भी values को exclude करते हुए जो सिर्फ default values होने के कारण वहाँ होतीं। ऐसा करने के लिए हम `exclude_unset=True` इस्तेमाल करते हैं। यही main trick है। 🪄 + +फिर हम `hero_data` के data के साथ `hero_db` को update करने के लिए `hero_db.sqlmodel_update(hero_data)` इस्तेमाल करते हैं। + +{* ../../docs_src/sql_databases/tutorial002_an_py310.py ln[83:93] hl[83:84,88:89] *} + +### फिर से Hero Delete करें { #delete-a-hero-again } + +hero को **delete करना** लगभग पहले जैसा ही रहता है। + +हम इसमें सब कुछ refactor करने की इच्छा पूरी नहीं करेंगे। 😅 + +{* ../../docs_src/sql_databases/tutorial002_an_py310.py ln[96:103] hl[101] *} + +### App फिर से Run करें { #run-the-app-again } + +आप app फिर से run कर सकते हैं: + +
+ +```console +$ fastapi dev + +INFO: Uvicorn running on http://127.0.0.1:8000 (Press CTRL+C to quit) +``` + +
+ +अगर आप `/docs` API UI पर जाते हैं, तो आप देखेंगे कि यह अब updated है, और hero create करते समय यह client से `id` receive करने की expect नहीं करेगा, आदि। + +
+ +
+ +## Recap { #recap } + +आप SQL डेटाबेस के साथ interact करने और code को *data models* और *table models* के साथ सरल बनाने के लिए [**SQLModel**](https://sqlmodel.tiangolo.com/) का उपयोग कर सकते हैं। + +आप **SQLModel** docs में बहुत कुछ और सीख सकते हैं, वहाँ **FastAPI** के साथ SQLModel इस्तेमाल करने पर एक लंबा mini [tutorial](https://sqlmodel.tiangolo.com/tutorial/fastapi/) है। 🚀 diff --git a/docs/hi/docs/tutorial/static-files.md b/docs/hi/docs/tutorial/static-files.md new file mode 100644 index 000000000..6a41c900a --- /dev/null +++ b/docs/hi/docs/tutorial/static-files.md @@ -0,0 +1,48 @@ +# Static Files { #static-files } + +आप `StaticFiles` का उपयोग करके किसी directory से static files को अपने-आप serve कर सकते हैं। + +/// tip | सुझाव + +अगर आपको frontend host करना है, तो इसके बजाय `app.frontend()` का उपयोग करें, इसके बारे में [Frontend](frontend.md) में पढ़ें। + +`app.frontend()` अंदरूनी तौर पर `StaticFiles` का उपयोग करता है, जिसमें frontends के लिए कई अतिरिक्त फायदे होते हैं, जैसे client-side routing को handle करना। + +/// + +## `StaticFiles` का उपयोग करें { #use-staticfiles } + +* `StaticFiles` import करें। +* किसी विशिष्ट path में `StaticFiles()` instance को "Mount" करें। + +{* ../../docs_src/static_files/tutorial001_py310.py hl[2,6] *} + +/// note | तकनीकी विवरण + +आप `from starlette.staticfiles import StaticFiles` भी उपयोग कर सकते हैं। + +**FastAPI** आपकी, developer की, सुविधा के लिए वही `starlette.staticfiles` `fastapi.staticfiles` के रूप में प्रदान करता है। लेकिन यह वास्तव में सीधे Starlette से आता है। + +/// + +### "Mounting" क्या है { #what-is-mounting } + +"Mounting" का मतलब है किसी विशिष्ट path में एक पूरी "independent" application जोड़ना, जो फिर सभी sub-paths को handle करने का काम करती है। + +यह `APIRouter` का उपयोग करने से अलग है, क्योंकि mounted application पूरी तरह independent होती है। आपकी main application की OpenAPI और docs में mounted application से कुछ भी शामिल नहीं होगा, आदि। + +आप इसके बारे में [Advanced User Guide](../advanced/index.md) में और पढ़ सकते हैं। + +## विवरण { #details } + +पहला `"/static"` उस sub-path को संदर्भित करता है जिस पर यह "sub-application" "mount" की जाएगी। इसलिए, `"/static"` से शुरू होने वाला कोई भी path इसके द्वारा handle किया जाएगा। + +`directory="static"` उस directory के नाम को संदर्भित करता है जिसमें आपकी static files होती हैं। + +`name="static"` इसे एक नाम देता है, जिसे **FastAPI** द्वारा internally उपयोग किया जा सकता है। + +ये सभी parameters "`static`" से अलग हो सकते हैं, इन्हें अपनी application की जरूरतों और विशिष्ट विवरणों के अनुसार adjust करें। + +## अधिक जानकारी { #more-info } + +अधिक विवरण और options के लिए [Static Files के बारे में Starlette की docs](https://www.starlette.dev/staticfiles/) देखें। diff --git a/docs/hi/docs/tutorial/stream-json-lines.md b/docs/hi/docs/tutorial/stream-json-lines.md new file mode 100644 index 000000000..9d0645fc5 --- /dev/null +++ b/docs/hi/docs/tutorial/stream-json-lines.md @@ -0,0 +1,111 @@ +# JSON Lines को Stream करें { #stream-json-lines } + +आपके पास data की एक sequence हो सकती है जिसे आप "**stream**" में भेजना चाहें, आप इसे **JSON Lines** के साथ कर सकते हैं। + +/// note | टिप्पणी + +FastAPI 0.134.0 में जोड़ा गया। + +/// + +## Stream क्या है? { #what-is-a-stream } + +"**Streaming**" data का मतलब है कि आपका app items की पूरी sequence के तैयार होने का इंतज़ार किए बिना client को data items भेजना शुरू कर देगा। + +तो, यह पहला item भेजेगा, client उसे receive करके process करना शुरू कर देगा, और आप अभी भी अगला item produce कर रहे हो सकते हैं। + +```mermaid +sequenceDiagram + participant App + participant Client + + App->>App: Produce Item 1 + App->>Client: Send Item 1 + App->>App: Produce Item 2 + Client->>Client: Process Item 1 + App->>Client: Send Item 2 + App->>App: Produce Item 3 + Client->>Client: Process Item 2 + App->>Client: Send Item 3 + Client->>Client: Process Item 3 + Note over App: Keeps producing... + Note over Client: Keeps consuming... +``` + +यह एक infinite stream भी हो सकती है, जहाँ आप लगातार data भेजते रहते हैं। + +## JSON Lines { #json-lines } + +इन मामलों में, "**JSON Lines**" भेजना आम है, जो एक ऐसा format है जहाँ आप हर line में एक JSON object भेजते हैं। + +एक response का content type `application/jsonl` होगा (`application/json` के बजाय) और body कुछ इस तरह होगी: + +```json +{"name": "Plumbus", "description": "A multi-purpose household device."} +{"name": "Portal Gun", "description": "A portal opening device."} +{"name": "Meeseeks Box", "description": "A box that summons a Meeseeks."} +``` + +यह JSON array (Python list के equivalent) से बहुत मिलता-जुलता है, लेकिन `[]` में wrap होने और items के बीच `,` होने के बजाय, इसमें **हर line में एक JSON object** होता है, वे एक new line character से अलग होते हैं। + +/// note | टिप्पणी + +महत्वपूर्ण बात यह है कि आपका app हर line को बारी-बारी से produce कर पाएगा, जबकि client पिछली lines को consume करता रहेगा। + +/// + +/// note | तकनीकी विवरण + +क्योंकि हर JSON object एक new line से अलग होगा, उनके content में literal new line characters नहीं हो सकते, लेकिन उनमें escaped new lines (`\n`) हो सकती हैं, जो JSON standard का हिस्सा है। + +लेकिन आमतौर पर आपको इसके बारे में चिंता करने की ज़रूरत नहीं होगी, यह अपने आप हो जाता है, आगे पढ़ते रहें। 🤓 + +/// + +## उपयोग के मामले { #use-cases } + +आप इसका उपयोग **AI LLM** service से, **logs** या **telemetry** से, या अन्य प्रकार के data से data stream करने के लिए कर सकते हैं जिन्हें **JSON** items में structure किया जा सकता है। + +/// tip | सुझाव + +अगर आप binary data stream करना चाहते हैं, उदाहरण के लिए video या audio, तो advanced guide देखें: [Data Stream करें](../advanced/stream-data.md)। + +/// + +## FastAPI के साथ JSON Lines Stream करें { #stream-json-lines-with-fastapi } + +FastAPI के साथ JSON Lines stream करने के लिए, आप अपनी *path operation function* में `return` का उपयोग करने के बजाय, हर item को बारी-बारी से produce करने के लिए `yield` का उपयोग कर सकते हैं। + +{* ../../docs_src/stream_json_lines/tutorial001_py310.py ln[1:24] hl[24] *} + +अगर हर JSON item जिसे आप वापस भेजना चाहते हैं, type `Item` (एक Pydantic model) का है और यह एक async function है, तो आप return type को `AsyncIterable[Item]` के रूप में declare कर सकते हैं: + +{* ../../docs_src/stream_json_lines/tutorial001_py310.py ln[1:24] hl[9:11,22] *} + +अगर आप return type declare करते हैं, तो FastAPI इसका उपयोग data को **validate** करने, OpenAPI में इसे **document** करने, इसे **filter** करने, और Pydantic का उपयोग करके इसे **serialize** करने के लिए करेगा। + +/// tip | सुझाव + +क्योंकि Pydantic इसे **Rust** side में serialize करेगा, आपको return type declare न करने की तुलना में बहुत अधिक **performance** मिलेगी। + +/// + +### Non-async *path operation functions* { #non-async-path-operation-functions } + +आप regular `def` functions (बिना `async` के) भी उपयोग कर सकते हैं, और उसी तरह `yield` का उपयोग कर सकते हैं। + +FastAPI यह सुनिश्चित करेगा कि यह सही तरीके से चले ताकि यह event loop को block न करे। + +क्योंकि इस मामले में function async नहीं है, सही return type `Iterable[Item]` होगा: + +{* ../../docs_src/stream_json_lines/tutorial001_py310.py ln[27:30] hl[28] *} + +### कोई Return Type नहीं { #no-return-type } + +आप return type को omit भी कर सकते हैं। FastAPI फिर data को ऐसी चीज़ में convert करने के लिए [`jsonable_encoder`](./encoder.md) का उपयोग करेगा जिसे JSON में serialize किया जा सके और फिर उसे JSON Lines के रूप में भेजेगा। + +{* ../../docs_src/stream_json_lines/tutorial001_py310.py ln[33:36] hl[34] *} + +## Server-Sent Events (SSE) { #server-sent-events-sse } + +FastAPI में Server-Sent Events (SSE) के लिए भी first-class support है, जो काफी समान हैं लेकिन कुछ extra details के साथ। आप इनके बारे में अगले chapter में जान सकते हैं: [Server-Sent Events (SSE)](server-sent-events.md)। 🤓 diff --git a/docs/hi/docs/tutorial/testing.md b/docs/hi/docs/tutorial/testing.md new file mode 100644 index 000000000..3a05e7917 --- /dev/null +++ b/docs/hi/docs/tutorial/testing.md @@ -0,0 +1,193 @@ +# Testing { #testing } + +[Starlette](https://www.starlette.dev/testclient/) की बदौलत, **FastAPI** applications की testing आसान और आनंददायक है। + +यह [HTTPX](https://www.python-httpx.org) पर आधारित है, जो बदले में Requests के आधार पर design किया गया है, इसलिए यह बहुत परिचित और intuitive है। + +इसके साथ, आप **FastAPI** के साथ सीधे [pytest](https://docs.pytest.org/) का उपयोग कर सकते हैं। + +## `TestClient` का उपयोग करना { #using-testclient } + +/// note | नोट + +`TestClient` का उपयोग करने के लिए, पहले [`httpx`](https://www.python-httpx.org) install करें। + +सुनिश्चित करें कि आप एक [virtual environment](../virtual-environments.md) बनाते हैं, उसे activate करते हैं, और फिर इसे install करते हैं, उदाहरण के लिए: + +```console +$ pip install httpx +``` + +/// + +`TestClient` import करें। + +अपनी **FastAPI** application को इसमें pass करके एक `TestClient` बनाएँ। + +ऐसी functions बनाएँ जिनका नाम `test_` से शुरू होता हो (यह एक standard `pytest` convention है)। + +`TestClient` object का उपयोग उसी तरह करें जैसे आप `httpx` के साथ करते हैं। + +जिन चीज़ों की आपको जाँच करनी है उनके लिए standard Python expressions के साथ सरल `assert` statements लिखें (फिर से, standard `pytest`)। + +{* ../../docs_src/app_testing/tutorial001_py310.py hl[2,12,15:18] *} + +/// tip | टिप + +ध्यान दें कि testing functions सामान्य `def` हैं, `async def` नहीं। + +और client को की जाने वाली calls भी सामान्य calls हैं, `await` का उपयोग नहीं करतीं। + +यह आपको बिना जटिलताओं के सीधे `pytest` का उपयोग करने देता है। + +/// + +/// note | तकनीकी विवरण + +आप `from starlette.testclient import TestClient` का भी उपयोग कर सकते हैं। + +**FastAPI** आपकी सुविधा के लिए, developer के रूप में, उसी `starlette.testclient` को `fastapi.testclient` के रूप में प्रदान करता है। लेकिन यह सीधे Starlette से आता है। + +/// + +/// tip | टिप + +अगर आप अपनी FastAPI application को requests भेजने के अलावा अपने tests में `async` functions call करना चाहते हैं (जैसे asynchronous database functions), तो advanced tutorial में [Async Tests](../advanced/async-tests.md) देखें। + +/// + +## Tests को अलग करना { #separating-tests } + +एक वास्तविक application में, आपके tests शायद किसी अलग file में होंगे। + +और आपकी **FastAPI** application भी कई files/modules आदि से मिलकर बनी हो सकती है। + +### **FastAPI** app file { #fastapi-app-file } + +मान लीजिए आपके पास [Bigger Applications](bigger-applications.md) में बताए गए अनुसार एक file structure है: + +``` +. +├── app +│   ├── __init__.py +│   └── main.py +``` + +`main.py` file में आपकी **FastAPI** app है: + + +{* ../../docs_src/app_testing/app_a_py310/main.py *} + +### Testing file { #testing-file } + +फिर आपके पास अपने tests के साथ एक file `test_main.py` हो सकती है। यह उसी Python package में हो सकती है (वही directory जिसमें `__init__.py` file है): + +``` hl_lines="5" +. +├── app +│   ├── __init__.py +│   ├── main.py +│   └── test_main.py +``` + +क्योंकि यह file उसी package में है, आप `main` module (`main.py`) से object `app` को import करने के लिए relative imports का उपयोग कर सकते हैं: + +{* ../../docs_src/app_testing/app_a_py310/test_main.py hl[3] *} + + +...और tests के लिए code पहले जैसा ही रख सकते हैं। + +## Testing: विस्तृत उदाहरण { #testing-extended-example } + +अब इस उदाहरण को आगे बढ़ाते हैं और अलग-अलग हिस्सों की testing कैसे करनी है यह देखने के लिए और विवरण जोड़ते हैं। + +### विस्तारित **FastAPI** app file { #extended-fastapi-app-file } + +आइए पहले जैसी ही file structure के साथ जारी रखें: + +``` +. +├── app +│   ├── __init__.py +│   ├── main.py +│   └── test_main.py +``` + +मान लीजिए अब आपकी **FastAPI** app वाली file `main.py` में कुछ अन्य **path operations** हैं। + +इसमें एक `GET` operation है जो error return कर सकता है। + +इसमें एक `POST` operation है जो कई errors return कर सकता है। + +दोनों *path operations* को `X-Token` header required है। + +{* ../../docs_src/app_testing/app_b_an_py310/main.py *} + +### विस्तारित testing file { #extended-testing-file } + +फिर आप विस्तारित tests के साथ `test_main.py` को update कर सकते हैं: + +{* ../../docs_src/app_testing/app_b_an_py310/test_main.py *} + + +जब भी आपको client से request में जानकारी pass करवानी हो और आपको पता न हो कि कैसे, तो आप खोज (Google) सकते हैं कि इसे `httpx` में कैसे करें, या यहाँ तक कि `requests` के साथ कैसे करें, क्योंकि HTTPX का design Requests के design पर आधारित है। + +फिर आप अपने tests में वही करते हैं। + +उदाहरण के लिए: + +* *path* या *query* parameter pass करने के लिए, इसे URL में ही जोड़ें। +* JSON body pass करने के लिए, `json` parameter में एक Python object (जैसे `dict`) pass करें। +* अगर आपको JSON के बजाय *Form Data* भेजना है, तो इसके बजाय `data` parameter का उपयोग करें। +* *headers* pass करने के लिए, `headers` parameter में एक `dict` का उपयोग करें। +* *cookies* के लिए, `cookies` parameter में एक `dict`। + +backend को data कैसे pass करें (`httpx` या `TestClient` का उपयोग करके) इसके बारे में अधिक जानकारी के लिए [HTTPX documentation](https://www.python-httpx.org) देखें। + +/// note | नोट + +ध्यान दें कि `TestClient` ऐसा data receive करता है जिसे JSON में convert किया जा सकता है, Pydantic models नहीं। + +अगर आपके test में एक Pydantic model है और आप testing के दौरान उसका data application को भेजना चाहते हैं, तो आप [JSON Compatible Encoder](encoder.md) में बताए गए `jsonable_encoder` का उपयोग कर सकते हैं। + +/// + +## इसे चलाएँ { #run-it } + +उसके बाद, आपको बस `pytest` install करना है। + +सुनिश्चित करें कि आप एक [virtual environment](../virtual-environments.md) बनाते हैं, उसे activate करते हैं, और फिर इसे install करते हैं, उदाहरण के लिए: + +
+ +```console +$ pip install pytest + +---> 100% +``` + +
+ +यह files और tests को automatically detect करेगा, उन्हें execute करेगा, और results आपको वापस report करेगा। + +Tests चलाएँ: + +
+ +```console +$ pytest + +================ test session starts ================ +platform linux -- Python 3.6.9, pytest-5.3.5, py-1.8.1, pluggy-0.13.1 +rootdir: /home/user/code/superawesome-cli/app +plugins: forked-1.1.3, xdist-1.31.0, cov-2.8.1 +collected 6 items + +---> 100% + +test_main.py ...... [100%] + +================= 1 passed in 0.03s ================= +``` + +
From 64fc8a4521d924e15cfecf6bf37d775ce688267a Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Tue, 14 Jul 2026 12:18:15 +0000 Subject: [PATCH 426/462] =?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 d4f84a739..42338c8d0 100644 --- a/docs/en/docs/release-notes.md +++ b/docs/en/docs/release-notes.md @@ -9,6 +9,7 @@ hide: ### Translations +* 🌐 Update translations for hi (add-missing). PR [#15925](https://github.com/fastapi/fastapi/pull/15925) by [@tiangolo](https://github.com/tiangolo). * 🌐 Update translations for hi (add-missing). PR [#15797](https://github.com/fastapi/fastapi/pull/15797) by [@tiangolo](https://github.com/tiangolo). * 🌐 Update `llm-prompt.md` for Hindi. PR [#15810](https://github.com/fastapi/fastapi/pull/15810) by [@YuriiMotov](https://github.com/YuriiMotov). * 🌐 Fix language-specific translation prompt for Russian language. PR [#15924](https://github.com/fastapi/fastapi/pull/15924) by [@YuriiMotov](https://github.com/YuriiMotov). From 37ccca3e95e287822602e275e92301399ba8917b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebasti=C3=A1n=20Ram=C3=ADrez?= Date: Tue, 14 Jul 2026 17:40:20 +0200 Subject: [PATCH 427/462] =?UTF-8?q?=F0=9F=8C=90=20Update=20translations=20?= =?UTF-8?q?for=20hi=20(add-missing)=20(#15990)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: github-actions[bot] --- docs/hi/docs/about/index.md | 3 + docs/hi/docs/advanced/additional-responses.md | 247 +++++++ .../docs/advanced/additional-status-codes.md | 41 ++ .../hi/docs/advanced/advanced-dependencies.md | 163 +++++ .../hi/docs/advanced/advanced-python-types.md | 61 ++ docs/hi/docs/advanced/async-tests.md | 99 +++ docs/hi/docs/advanced/behind-a-proxy.md | 466 +++++++++++++ docs/hi/docs/advanced/custom-response.md | 273 ++++++++ docs/hi/docs/advanced/dataclasses.md | 95 +++ docs/hi/docs/advanced/events.md | 165 +++++ docs/hi/docs/advanced/generate-clients.md | 192 ++++++ docs/hi/docs/advanced/index.md | 21 + docs/hi/docs/advanced/json-base64-bytes.md | 63 ++ docs/hi/docs/advanced/middleware.md | 97 +++ docs/hi/docs/advanced/openapi-callbacks.md | 186 ++++++ docs/hi/docs/advanced/openapi-webhooks.md | 55 ++ .../path-operation-advanced-configuration.md | 166 +++++ .../advanced/response-change-status-code.md | 31 + docs/hi/docs/advanced/response-cookies.md | 51 ++ docs/hi/docs/advanced/response-directly.md | 83 +++ docs/hi/docs/advanced/response-headers.md | 41 ++ .../docs/advanced/security/http-basic-auth.md | 107 +++ docs/hi/docs/advanced/security/index.md | 19 + .../docs/advanced/security/oauth2-scopes.md | 274 ++++++++ docs/hi/docs/advanced/settings.md | 302 +++++++++ docs/hi/docs/advanced/stream-data.md | 117 ++++ docs/hi/docs/advanced/strict-content-type.md | 88 +++ docs/hi/docs/advanced/sub-applications.md | 67 ++ docs/hi/docs/advanced/templates.md | 126 ++++ docs/hi/docs/advanced/testing-dependencies.md | 53 ++ docs/hi/docs/advanced/testing-events.md | 12 + docs/hi/docs/advanced/testing-websockets.md | 13 + .../docs/advanced/using-request-directly.md | 56 ++ docs/hi/docs/advanced/websockets.md | 186 ++++++ docs/hi/docs/advanced/wsgi.md | 51 ++ docs/hi/docs/deployment/cloud.md | 24 + docs/hi/docs/deployment/concepts.md | 321 +++++++++ docs/hi/docs/deployment/docker.md | 618 ++++++++++++++++++ docs/hi/docs/deployment/fastapicloud.md | 47 ++ docs/hi/docs/deployment/https.md | 231 +++++++ docs/hi/docs/deployment/index.md | 23 + docs/hi/docs/deployment/manually.md | 156 +++++ docs/hi/docs/deployment/server-workers.md | 139 ++++ docs/hi/docs/deployment/versions.md | 93 +++ .../authentication-error-status-code.md | 17 + docs/hi/docs/how-to/conditional-openapi.md | 56 ++ docs/hi/docs/how-to/configure-swagger-ui.md | 70 ++ docs/hi/docs/how-to/custom-docs-ui-assets.md | 185 ++++++ .../docs/how-to/custom-request-and-route.md | 109 +++ docs/hi/docs/how-to/extending-openapi.md | 88 +++ docs/hi/docs/how-to/general.md | 43 ++ docs/hi/docs/how-to/graphql.md | 60 ++ docs/hi/docs/how-to/index.md | 13 + ...migrate-from-pydantic-v1-to-pydantic-v2.md | 153 +++++ .../docs/how-to/separate-openapi-schemas.md | 102 +++ docs/hi/docs/how-to/testing-database.md | 7 + docs/hi/docs/resources/index.md | 3 + docs/hi/docs/tutorial/security/first-steps.md | 203 ++++++ .../tutorial/security/get-current-user.md | 105 +++ docs/hi/docs/tutorial/security/index.md | 105 +++ docs/hi/docs/tutorial/security/oauth2-jwt.md | 277 ++++++++ 61 files changed, 7318 insertions(+) create mode 100644 docs/hi/docs/about/index.md create mode 100644 docs/hi/docs/advanced/additional-responses.md create mode 100644 docs/hi/docs/advanced/additional-status-codes.md create mode 100644 docs/hi/docs/advanced/advanced-dependencies.md create mode 100644 docs/hi/docs/advanced/advanced-python-types.md create mode 100644 docs/hi/docs/advanced/async-tests.md create mode 100644 docs/hi/docs/advanced/behind-a-proxy.md create mode 100644 docs/hi/docs/advanced/custom-response.md create mode 100644 docs/hi/docs/advanced/dataclasses.md create mode 100644 docs/hi/docs/advanced/events.md create mode 100644 docs/hi/docs/advanced/generate-clients.md create mode 100644 docs/hi/docs/advanced/index.md create mode 100644 docs/hi/docs/advanced/json-base64-bytes.md create mode 100644 docs/hi/docs/advanced/middleware.md create mode 100644 docs/hi/docs/advanced/openapi-callbacks.md create mode 100644 docs/hi/docs/advanced/openapi-webhooks.md create mode 100644 docs/hi/docs/advanced/path-operation-advanced-configuration.md create mode 100644 docs/hi/docs/advanced/response-change-status-code.md create mode 100644 docs/hi/docs/advanced/response-cookies.md create mode 100644 docs/hi/docs/advanced/response-directly.md create mode 100644 docs/hi/docs/advanced/response-headers.md create mode 100644 docs/hi/docs/advanced/security/http-basic-auth.md create mode 100644 docs/hi/docs/advanced/security/index.md create mode 100644 docs/hi/docs/advanced/security/oauth2-scopes.md create mode 100644 docs/hi/docs/advanced/settings.md create mode 100644 docs/hi/docs/advanced/stream-data.md create mode 100644 docs/hi/docs/advanced/strict-content-type.md create mode 100644 docs/hi/docs/advanced/sub-applications.md create mode 100644 docs/hi/docs/advanced/templates.md create mode 100644 docs/hi/docs/advanced/testing-dependencies.md create mode 100644 docs/hi/docs/advanced/testing-events.md create mode 100644 docs/hi/docs/advanced/testing-websockets.md create mode 100644 docs/hi/docs/advanced/using-request-directly.md create mode 100644 docs/hi/docs/advanced/websockets.md create mode 100644 docs/hi/docs/advanced/wsgi.md create mode 100644 docs/hi/docs/deployment/cloud.md create mode 100644 docs/hi/docs/deployment/concepts.md create mode 100644 docs/hi/docs/deployment/docker.md create mode 100644 docs/hi/docs/deployment/fastapicloud.md create mode 100644 docs/hi/docs/deployment/https.md create mode 100644 docs/hi/docs/deployment/index.md create mode 100644 docs/hi/docs/deployment/manually.md create mode 100644 docs/hi/docs/deployment/server-workers.md create mode 100644 docs/hi/docs/deployment/versions.md create mode 100644 docs/hi/docs/how-to/authentication-error-status-code.md create mode 100644 docs/hi/docs/how-to/conditional-openapi.md create mode 100644 docs/hi/docs/how-to/configure-swagger-ui.md create mode 100644 docs/hi/docs/how-to/custom-docs-ui-assets.md create mode 100644 docs/hi/docs/how-to/custom-request-and-route.md create mode 100644 docs/hi/docs/how-to/extending-openapi.md create mode 100644 docs/hi/docs/how-to/general.md create mode 100644 docs/hi/docs/how-to/graphql.md create mode 100644 docs/hi/docs/how-to/index.md create mode 100644 docs/hi/docs/how-to/migrate-from-pydantic-v1-to-pydantic-v2.md create mode 100644 docs/hi/docs/how-to/separate-openapi-schemas.md create mode 100644 docs/hi/docs/how-to/testing-database.md create mode 100644 docs/hi/docs/resources/index.md create mode 100644 docs/hi/docs/tutorial/security/first-steps.md create mode 100644 docs/hi/docs/tutorial/security/get-current-user.md create mode 100644 docs/hi/docs/tutorial/security/index.md create mode 100644 docs/hi/docs/tutorial/security/oauth2-jwt.md diff --git a/docs/hi/docs/about/index.md b/docs/hi/docs/about/index.md new file mode 100644 index 000000000..c155450a3 --- /dev/null +++ b/docs/hi/docs/about/index.md @@ -0,0 +1,3 @@ +# परिचय { #about } + +FastAPI, इसके design, प्रेरणा और और भी बहुत कुछ के बारे में। 🤓 diff --git a/docs/hi/docs/advanced/additional-responses.md b/docs/hi/docs/advanced/additional-responses.md new file mode 100644 index 000000000..410157c7a --- /dev/null +++ b/docs/hi/docs/advanced/additional-responses.md @@ -0,0 +1,247 @@ +# OpenAPI में अतिरिक्त Responses { #additional-responses-in-openapi } + +/// warning | चेतावनी + +यह एक काफ़ी advanced विषय है। + +अगर आप **FastAPI** के साथ शुरुआत कर रहे हैं, तो शायद आपको इसकी ज़रूरत न पड़े। + +/// + +आप अतिरिक्त status codes, media types, descriptions आदि के साथ अतिरिक्त responses घोषित कर सकते हैं। + +ये अतिरिक्त responses OpenAPI schema में शामिल किए जाएँगे, इसलिए वे API docs में भी दिखाई देंगे। + +लेकिन उन अतिरिक्त responses के लिए आपको यह सुनिश्चित करना होगा कि आप अपने status code और content के साथ सीधे `JSONResponse` जैसा कोई `Response` return करें। + +## `model` के साथ अतिरिक्त Response { #additional-response-with-model } + +आप अपने *path operation decorators* को `responses` parameter दे सकते हैं। + +यह एक `dict` प्राप्त करता है: keys प्रत्येक response के status codes होते हैं (जैसे `200`), और values अन्य `dict`s होते हैं जिनमें उनमें से प्रत्येक की जानकारी होती है। + +इनमें से प्रत्येक response `dict` में `model` key हो सकती है, जिसमें `response_model` की तरह एक Pydantic model होता है। + +**FastAPI** उस model को लेगा, उसका JSON Schema generate करेगा और उसे OpenAPI में सही जगह शामिल करेगा। + +उदाहरण के लिए, status code `404` और Pydantic model `Message` के साथ एक और response घोषित करने के लिए, आप लिख सकते हैं: + +{* ../../docs_src/additional_responses/tutorial001_py310.py hl[18,22] *} + +/// note | नोट + +ध्यान रखें कि आपको सीधे `JSONResponse` return करना होगा। + +/// + +/// note | नोट + +`model` key OpenAPI का हिस्सा नहीं है। + +**FastAPI** वहाँ से Pydantic model लेगा, JSON Schema generate करेगा, और उसे सही जगह रखेगा। + +सही जगह है: + +* `content` key में, जिसकी value एक और JSON object (`dict`) होती है जिसमें शामिल है: + * media type वाली एक key, जैसे `application/json`, जिसकी value एक और JSON object होती है, जिसमें शामिल है: + * एक key `schema`, जिसकी value model से JSON Schema होती है, यही सही जगह है। + * **FastAPI** इसे सीधे शामिल करने के बजाय आपके OpenAPI में किसी अन्य जगह मौजूद global JSON Schemas का reference यहाँ जोड़ता है। इस तरह, अन्य applications और clients उन JSON Schemas को सीधे उपयोग कर सकते हैं, बेहतर code generation tools प्रदान कर सकते हैं, आदि। + +/// + +इस *path operation* के लिए OpenAPI में generate किए गए responses होंगे: + +```JSON hl_lines="3-12" +{ + "responses": { + "404": { + "description": "Additional Response", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Message" + } + } + } + }, + "200": { + "description": "Successful Response", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Item" + } + } + } + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + } + } + } +} +``` + +Schemas को OpenAPI schema के अंदर किसी दूसरी जगह reference किया गया है: + +```JSON hl_lines="4-16" +{ + "components": { + "schemas": { + "Message": { + "title": "Message", + "required": [ + "message" + ], + "type": "object", + "properties": { + "message": { + "title": "Message", + "type": "string" + } + } + }, + "Item": { + "title": "Item", + "required": [ + "id", + "value" + ], + "type": "object", + "properties": { + "id": { + "title": "Id", + "type": "string" + }, + "value": { + "title": "Value", + "type": "string" + } + } + }, + "ValidationError": { + "title": "ValidationError", + "required": [ + "loc", + "msg", + "type" + ], + "type": "object", + "properties": { + "loc": { + "title": "Location", + "type": "array", + "items": { + "type": "string" + } + }, + "msg": { + "title": "Message", + "type": "string" + }, + "type": { + "title": "Error Type", + "type": "string" + } + } + }, + "HTTPValidationError": { + "title": "HTTPValidationError", + "type": "object", + "properties": { + "detail": { + "title": "Detail", + "type": "array", + "items": { + "$ref": "#/components/schemas/ValidationError" + } + } + } + } + } + } +} +``` + +## मुख्य response के लिए अतिरिक्त media types { #additional-media-types-for-the-main-response } + +आप इसी `responses` parameter का उपयोग करके उसी मुख्य response के लिए अलग-अलग media types जोड़ सकते हैं। + +उदाहरण के लिए, आप `image/png` का एक अतिरिक्त media type जोड़ सकते हैं, यह घोषित करते हुए कि आपका *path operation* एक JSON object (media type `application/json` के साथ) या एक PNG image return कर सकता है: + +{* ../../docs_src/additional_responses/tutorial002_py310.py hl[17:22,26] *} + +/// note | नोट + +ध्यान दें कि आपको image को सीधे `FileResponse` का उपयोग करके return करना होगा। + +/// + +/// note | नोट + +जब तक आप अपने `responses` parameter में स्पष्ट रूप से कोई अलग media type specify नहीं करते, FastAPI मान लेगा कि response का media type मुख्य response class (default `application/json`) जैसा ही है। + +लेकिन अगर आपने custom response class specify की है जिसका media type `None` है, तो FastAPI किसी भी ऐसे अतिरिक्त response के लिए `application/json` का उपयोग करेगा जिसके साथ कोई associated model है। + +/// + +## जानकारी को मिलाना { #combining-information } + +आप कई जगहों से response जानकारी को भी मिला सकते हैं, जिसमें `response_model`, `status_code`, और `responses` parameters शामिल हैं। + +आप default status code `200` (या ज़रूरत पड़ने पर custom code) का उपयोग करके `response_model` घोषित कर सकते हैं, और फिर उसी response के लिए अतिरिक्त जानकारी सीधे OpenAPI schema में `responses` के अंदर घोषित कर सकते हैं। + +**FastAPI** `responses` से अतिरिक्त जानकारी बनाए रखेगा, और उसे आपके model से JSON Schema के साथ मिला देगा। + +उदाहरण के लिए, आप status code `404` वाला एक response घोषित कर सकते हैं जो Pydantic model का उपयोग करता है और जिसमें custom `description` है। + +और status code `200` वाला एक response, जो आपके `response_model` का उपयोग करता है, लेकिन जिसमें custom `example` शामिल है: + +{* ../../docs_src/additional_responses/tutorial003_py310.py hl[20:31] *} + +यह सब मिलाकर आपके OpenAPI में शामिल किया जाएगा, और API docs में दिखाया जाएगा: + + + +## पहले से परिभाषित responses और custom responses को मिलाएँ { #combine-predefined-responses-and-custom-ones } + +आप कुछ पहले से परिभाषित responses रखना चाह सकते हैं जो कई *path operations* पर लागू होते हैं, लेकिन आप उन्हें प्रत्येक *path operation* के लिए ज़रूरी custom responses के साथ मिलाना चाहते हैं। + +ऐसे मामलों के लिए, आप `**dict_to_unpack` के साथ `dict` को "unpacking" करने की Python technique का उपयोग कर सकते हैं: + +```Python +old_dict = { + "old key": "old value", + "second old key": "second old value", +} +new_dict = {**old_dict, "new key": "new value"} +``` + +यहाँ, `new_dict` में `old_dict` के सभी key-value pairs के साथ नया key-value pair भी होगा: + +```Python +{ + "old key": "old value", + "second old key": "second old value", + "new key": "new value", +} +``` + +आप इस technique का उपयोग अपने *path operations* में कुछ पहले से परिभाषित responses को reuse करने और उन्हें अतिरिक्त custom responses के साथ मिलाने के लिए कर सकते हैं। + +उदाहरण के लिए: + +{* ../../docs_src/additional_responses/tutorial004_py310.py hl[11:15,24] *} + +## OpenAPI responses के बारे में अधिक जानकारी { #more-information-about-openapi-responses } + +Responses में आप ठीक-ठीक क्या शामिल कर सकते हैं, यह देखने के लिए आप OpenAPI specification में ये sections देख सकते हैं: + +* [OpenAPI Responses Object](https://github.com/OAI/OpenAPI-Specification/blob/master/versions/3.1.0.md#responses-object), इसमें `Response Object` शामिल है। +* [OpenAPI Response Object](https://github.com/OAI/OpenAPI-Specification/blob/master/versions/3.1.0.md#response-object), आप इसमें से कुछ भी सीधे अपने `responses` parameter के अंदर प्रत्येक response में शामिल कर सकते हैं। जिसमें `description`, `headers`, `content` (इसी के अंदर आप अलग-अलग media types और JSON Schemas घोषित करते हैं), और `links` शामिल हैं। diff --git a/docs/hi/docs/advanced/additional-status-codes.md b/docs/hi/docs/advanced/additional-status-codes.md new file mode 100644 index 000000000..bec6e4eae --- /dev/null +++ b/docs/hi/docs/advanced/additional-status-codes.md @@ -0,0 +1,41 @@ +# अतिरिक्त Status Codes { #additional-status-codes } + +default रूप से, **FastAPI** responses को `JSONResponse` का उपयोग करके return करेगा, जिसमें आपके *path operation* से return किया गया content उस `JSONResponse` के अंदर रखा जाएगा। + +यह default status code या वह status code उपयोग करेगा जो आपने अपने *path operation* में set किया है। + +## अतिरिक्त status codes { #additional-status-codes_1 } + +अगर आप मुख्य status code के अलावा अतिरिक्त status codes return करना चाहते हैं, तो आप सीधे `Response`, जैसे `JSONResponse`, return करके और अतिरिक्त status code को सीधे set करके ऐसा कर सकते हैं। + +उदाहरण के लिए, मान लीजिए कि आप एक ऐसा *path operation* रखना चाहते हैं जो items को update करने की अनुमति देता है, और सफल होने पर HTTP status code 200 "OK" return करता है। + +लेकिन आप यह भी चाहते हैं कि यह नए items को स्वीकार करे। और जब items पहले मौजूद नहीं थे, तो यह उन्हें बनाता है, और HTTP status code 201 "Created" return करता है। + +ऐसा करने के लिए, `JSONResponse` import करें, और अपना content वहीं सीधे return करें, साथ में अपनी पसंद का `status_code` set करें: + +{* ../../docs_src/additional_status_codes/tutorial001_an_py310.py hl[4,25] *} + +/// warning | चेतावनी + +जब आप सीधे `Response` return करते हैं, जैसे ऊपर के उदाहरण में, तो वह सीधे return किया जाएगा। + +इसे किसी model आदि के साथ serialize नहीं किया जाएगा। + +सुनिश्चित करें कि इसमें वही data है जो आप चाहते हैं, और values valid JSON हैं (अगर आप `JSONResponse` उपयोग कर रहे हैं)। + +/// + +/// note | तकनीकी विवरण + +आप `from starlette.responses import JSONResponse` भी उपयोग कर सकते हैं। + +**FastAPI** आपकी सुविधा के लिए, developer के रूप में, वही `starlette.responses` `fastapi.responses` के रूप में प्रदान करता है। लेकिन उपलब्ध अधिकांश responses सीधे Starlette से आते हैं। `status` के साथ भी यही है। + +/// + +## OpenAPI और API docs { #openapi-and-api-docs } + +अगर आप अतिरिक्त status codes और responses सीधे return करते हैं, तो वे OpenAPI schema (API docs) में शामिल नहीं होंगे, क्योंकि FastAPI के पास पहले से यह जानने का तरीका नहीं है कि आप क्या return करने वाले हैं। + +लेकिन आप इसे अपने code में document कर सकते हैं, उपयोग करके: [अतिरिक्त Responses](additional-responses.md)। diff --git a/docs/hi/docs/advanced/advanced-dependencies.md b/docs/hi/docs/advanced/advanced-dependencies.md new file mode 100644 index 000000000..4c6648b95 --- /dev/null +++ b/docs/hi/docs/advanced/advanced-dependencies.md @@ -0,0 +1,163 @@ +# Advanced Dependencies { #advanced-dependencies } + +## Parameterized dependencies { #parameterized-dependencies } + +अब तक हमने जो भी dependencies देखी हैं, वे एक निश्चित function या class हैं। + +लेकिन ऐसे मामले हो सकते हैं जहाँ आप dependency पर parameters सेट कर पाना चाहें, बिना कई अलग-अलग functions या classes declare किए। + +कल्पना करें कि हम एक ऐसी dependency रखना चाहते हैं जो जाँचती है कि query parameter `q` में कुछ निश्चित content है या नहीं। + +लेकिन हम उस निश्चित content को parameterize कर पाना चाहते हैं। + +## एक "callable" instance { #a-callable-instance } + +Python में किसी class के instance को "callable" बनाने का एक तरीका है। + +खुद class को नहीं (जो पहले से ही callable होती है), बल्कि उस class के एक instance को। + +ऐसा करने के लिए, हम एक method `__call__` declare करते हैं: + +{* ../../docs_src/dependencies/tutorial011_an_py310.py hl[12] *} + +इस मामले में, यही `__call__` है जिसे **FastAPI** अतिरिक्त parameters और sub-dependencies की जाँच के लिए उपयोग करेगा, और बाद में आपकी *path operation function* में parameter को value पास करने के लिए यही call किया जाएगा। + +## Instance को parameterize करें { #parameterize-the-instance } + +और अब, हम `__init__` का उपयोग करके instance के parameters declare कर सकते हैं जिन्हें हम dependency को "parameterize" करने के लिए उपयोग कर सकते हैं: + +{* ../../docs_src/dependencies/tutorial011_an_py310.py hl[9] *} + +इस मामले में, **FastAPI** कभी भी `__init__` को छुएगा या उसकी परवाह नहीं करेगा, हम इसे सीधे अपने code में उपयोग करेंगे। + +## एक instance बनाएँ { #create-an-instance } + +हम इस class का एक instance इस तरह बना सकते हैं: + +{* ../../docs_src/dependencies/tutorial011_an_py310.py hl[18] *} + +और इस तरह हम अपनी dependency को "parameterize" कर पाते हैं, जिसमें अब `"bar"` उसके अंदर है, attribute `checker.fixed_content` के रूप में। + +## Instance को dependency के रूप में उपयोग करें { #use-the-instance-as-a-dependency } + +फिर, हम `Depends(FixedContentQueryChecker)` के बजाय इस `checker` को `Depends(checker)` में उपयोग कर सकते हैं, क्योंकि dependency class खुद नहीं, बल्कि instance `checker` है। + +और dependency को solve करते समय, **FastAPI** इस `checker` को इस तरह call करेगा: + +```Python +checker(q="somequery") +``` + +...और जो भी यह return करेगा उसे हमारी *path operation function* में dependency की value के रूप में parameter `fixed_content_included` में पास करेगा: + +{* ../../docs_src/dependencies/tutorial011_an_py310.py hl[22] *} + +/// tip | सुझाव + +यह सब थोड़ा बनावटी लग सकता है। और अभी यह बहुत स्पष्ट नहीं हो सकता कि यह कैसे उपयोगी है। + +ये उदाहरण जानबूझकर सरल रखे गए हैं, लेकिन दिखाते हैं कि यह सब कैसे काम करता है। + +Security वाले chapters में utility functions हैं जिन्हें इसी तरीके से implement किया गया है। + +अगर आपने यह सब समझ लिया है, तो आप पहले से जानते हैं कि security के लिए वे utility tools अंदर से कैसे काम करते हैं। + +/// + +## `yield`, `HTTPException`, `except` और Background Tasks वाली Dependencies { #dependencies-with-yield-httpexception-except-and-background-tasks } + +/// warning | चेतावनी + +सबसे अधिक संभावना है कि आपको इन तकनीकी विवरणों की आवश्यकता नहीं है। + +ये विवरण मुख्य रूप से तब उपयोगी हैं जब आपके पास 0.121.0 से पुरानी FastAPI application थी और आपको `yield` वाली dependencies के साथ समस्याएँ आ रही हैं। + +/// + +`yield` वाली dependencies समय के साथ अलग-अलग use cases को संभालने और कुछ समस्याएँ ठीक करने के लिए विकसित हुई हैं, यहाँ बदले हुए व्यवहार का सारांश है। + +### `yield` और `scope` वाली Dependencies { #dependencies-with-yield-and-scope } + +Version 0.121.0 में, FastAPI ने `yield` वाली dependencies के लिए `Depends(scope="function")` का support जोड़ा। + +`Depends(scope="function")` का उपयोग करने पर, `yield` के बाद का exit code *path operation function* के समाप्त होते ही, response client को वापस भेजे जाने से पहले execute होता है। + +और `Depends(scope="request")` (default) का उपयोग करने पर, `yield` के बाद का exit code response भेजे जाने के बाद execute होता है। + +आप इसके बारे में docs में [Dependencies with `yield` - Early exit and `scope`](../tutorial/dependencies/dependencies-with-yield.md#early-exit-and-scope) में अधिक पढ़ सकते हैं। + +### `yield` और `StreamingResponse` वाली Dependencies, तकनीकी विवरण { #dependencies-with-yield-and-streamingresponse-technical-details } + +FastAPI 0.118.0 से पहले, यदि आप `yield` वाली dependency उपयोग करते थे, तो यह *path operation function* के return करने के बाद लेकिन response भेजने से ठीक पहले exit code run करती थी। + +इरादा यह था कि आवश्यक से अधिक समय तक resources को पकड़े रखने से बचा जाए, response के network से गुजरने की प्रतीक्षा करते हुए। + +इस बदलाव का अर्थ यह भी था कि यदि आपने `StreamingResponse` return किया, तो `yield` वाली dependency का exit code पहले ही run हो चुका होता। + +उदाहरण के लिए, यदि आपके पास `yield` वाली dependency में database session था, तो `StreamingResponse` data stream करते समय उस session का उपयोग नहीं कर पाता क्योंकि `yield` के बाद वाले exit code में session पहले ही बंद हो चुका होता। + +यह व्यवहार 0.118.0 में revert कर दिया गया, ताकि `yield` के बाद का exit code response भेजे जाने के बाद execute हो। + +/// note | ध्यान दें + +जैसा कि आप नीचे देखेंगे, यह version 0.106.0 से पहले के व्यवहार से बहुत मिलता-जुलता है, लेकिन कई सुधारों और corner cases के लिए bug fixes के साथ। + +/// + +#### Early Exit Code वाले Use Cases { #use-cases-with-early-exit-code } + +कुछ specific conditions वाले use cases हैं जिन्हें response भेजने से पहले `yield` वाली dependencies का exit code run करने के पुराने व्यवहार से लाभ हो सकता है। + +उदाहरण के लिए, कल्पना करें कि आपके पास ऐसा code है जो `yield` वाली dependency में database session का उपयोग केवल user verify करने के लिए करता है, लेकिन database session फिर *path operation function* में कभी उपयोग नहीं होता, केवल dependency में उपयोग होता है, **और** response भेजे जाने में लंबा समय लेता है, जैसे `StreamingResponse` जो data धीरे-धीरे भेजता है, लेकिन किसी कारण से database का उपयोग नहीं करता। + +इस मामले में, database session तब तक पकड़ा रहेगा जब तक response भेजना समाप्त नहीं हो जाता, लेकिन यदि आप इसका उपयोग नहीं करते हैं, तो इसे पकड़े रखना आवश्यक नहीं होगा। + +यह इस तरह दिख सकता है: + +{* ../../docs_src/dependencies/tutorial013_an_py310.py *} + +Exit code, यानी `Session` का automatic closing, यहाँ: + +{* ../../docs_src/dependencies/tutorial013_an_py310.py ln[19:21] *} + +...response द्वारा slow data भेजना समाप्त करने के बाद run होगा: + +{* ../../docs_src/dependencies/tutorial013_an_py310.py ln[30:38] hl[31:33] *} + +लेकिन क्योंकि `generate_stream()` database session का उपयोग नहीं करता, response भेजते समय session को खुला रखना वास्तव में आवश्यक नहीं है। + +यदि आपके पास SQLModel (या SQLAlchemy) का उपयोग करते हुए यह specific use case है, तो आप session को तब explicit रूप से बंद कर सकते हैं जब आपको इसकी आगे आवश्यकता न हो: + +{* ../../docs_src/dependencies/tutorial014_an_py310.py ln[24:28] hl[28] *} + +इस तरह session database connection release कर देगा, ताकि अन्य requests उसका उपयोग कर सकें। + +यदि आपके पास कोई अलग use case है जिसे `yield` वाली dependency से early exit करने की आवश्यकता है, तो कृपया अपने specific use case और dependencies with `yield` के लिए early closing से आपको क्यों लाभ होगा, इसके साथ एक [GitHub Discussion Question](https://github.com/fastapi/fastapi/discussions/new?category=questions) बनाएँ। + +यदि dependencies with `yield` में early closing के लिए compelling use cases होते हैं, तो मैं early closing में opt in करने का नया तरीका जोड़ने पर विचार करूँगा। + +### `yield` और `except` वाली Dependencies, तकनीकी विवरण { #dependencies-with-yield-and-except-technical-details } + +FastAPI 0.110.0 से पहले, यदि आप `yield` वाली dependency उपयोग करते थे, और फिर उस dependency में `except` के साथ exception capture करते थे, और exception को फिर से raise नहीं करते थे, तो exception automatic रूप से किसी भी exception handlers या internal server error handler को raise/forward कर दिया जाता था। + +यह version 0.110.0 में बदला गया ताकि handler के बिना forwarded exceptions (internal server errors) से होने वाली unhandled memory consumption ठीक की जा सके, और इसे regular Python code के व्यवहार के साथ consistent बनाया जा सके। + +### Background Tasks और `yield` वाली Dependencies, तकनीकी विवरण { #background-tasks-and-dependencies-with-yield-technical-details } + +FastAPI 0.106.0 से पहले, `yield` के बाद exceptions raise करना संभव नहीं था, `yield` वाली dependencies में exit code response भेजे जाने के *बाद* execute होता था, इसलिए [Exception Handlers](../tutorial/handling-errors.md#install-custom-exception-handlers) पहले ही run हो चुके होते। + +इसे मुख्य रूप से इस तरह design किया गया था ताकि dependencies द्वारा "yielded" किए गए उन्हीं objects को background tasks के अंदर उपयोग किया जा सके, क्योंकि exit code background tasks के समाप्त होने के बाद execute होता था। + +यह FastAPI 0.106.0 में बदला गया, इस इरादे से कि response के network से गुजरने की प्रतीक्षा करते समय resources को पकड़े न रखा जाए। + +/// tip | सुझाव + +इसके अतिरिक्त, background task सामान्यतः logic का एक independent set होता है जिसे अलग से संभाला जाना चाहिए, अपने स्वयं के resources के साथ (जैसे उसका अपना database connection)। + +इसलिए, इस तरह आपके पास शायद अधिक साफ़ code होगा। + +/// + +यदि आप इस व्यवहार पर निर्भर थे, तो अब आपको background tasks के लिए resources background task के अंदर ही बनाने चाहिए, और internally केवल ऐसा data उपयोग करना चाहिए जो `yield` वाली dependencies के resources पर निर्भर न हो। + +उदाहरण के लिए, उसी database session का उपयोग करने के बजाय, आप background task के अंदर एक नया database session बनाएँगे, और इस नए session का उपयोग करके database से objects प्राप्त करेंगे। और फिर database से object को background task function में parameter के रूप में पास करने के बजाय, आप उस object की ID पास करेंगे और फिर background task function के अंदर object को फिर से प्राप्त करेंगे। diff --git a/docs/hi/docs/advanced/advanced-python-types.md b/docs/hi/docs/advanced/advanced-python-types.md new file mode 100644 index 000000000..d73a95fd8 --- /dev/null +++ b/docs/hi/docs/advanced/advanced-python-types.md @@ -0,0 +1,61 @@ +# उन्नत Python Types { #advanced-python-types } + +Python types के साथ काम करते समय यहाँ कुछ अतिरिक्त विचार हैं जो उपयोगी हो सकते हैं। + +## `Union` या `Optional` का उपयोग { #using-union-or-optional } + +अगर आपका code किसी कारण से `|` का उपयोग नहीं कर सकता, उदाहरण के लिए अगर यह type annotation में नहीं बल्कि `response_model=` जैसी किसी चीज़ में है, तो vertical bar (`|`) का उपयोग करने के बजाय आप `typing` से `Union` का उपयोग कर सकते हैं। + +उदाहरण के लिए, आप declare कर सकते हैं कि कोई चीज़ `str` या `None` हो सकती है: + +```python +from typing import Union + + +def say_hi(name: Union[str, None]): + print(f"Hi {name}!") +``` + +`typing` में `Optional` के साथ यह declare करने का एक shortcut भी है कि कोई चीज़ `None` हो सकती है। + +मेरे बहुत **subjective** दृष्टिकोण से एक tip यहाँ है: + +* 🚨 `Optional[SomeType]` का उपयोग करने से बचें +* इसके बजाय ✨ **`Union[SomeType, None]` का उपयोग करें** ✨। + +दोनों equivalent हैं और अंदर से वे समान हैं, लेकिन मैं `Optional` के बजाय `Union` की सलाह दूँगा क्योंकि "**optional**" शब्द से ऐसा लग सकता है कि value optional है, जबकि इसका वास्तविक अर्थ है "यह `None` हो सकता है", भले ही यह optional न हो और अभी भी required हो। + +मुझे लगता है कि `Union[SomeType, None]` अपने अर्थ के बारे में अधिक explicit है। + +यह बस शब्दों और नामों की बात है। लेकिन ये शब्द इस बात को प्रभावित कर सकते हैं कि आप और आपके teammates code के बारे में कैसे सोचते हैं। + +एक उदाहरण के रूप में, इस function को लेते हैं: + +```python +from typing import Optional + + +def say_hi(name: Optional[str]): + print(f"Hey {name}!") +``` + +parameter `name` को `Optional[str]` के रूप में define किया गया है, लेकिन यह **optional नहीं है**, आप function को parameter के बिना call नहीं कर सकते: + +```Python +say_hi() # अरे नहीं, यह error throw करता है! 😱 +``` + +`name` parameter **अभी भी required** है (*optional* नहीं) क्योंकि इसमें default value नहीं है। फिर भी, `name` value के रूप में `None` स्वीकार करता है: + +```Python +say_hi(name=None) # यह काम करता है, None valid है 🎉 +``` + +अच्छी खबर यह है कि अधिकतर मामलों में, आप types के unions को define करने के लिए बस `|` का उपयोग कर पाएँगे: + +```python +def say_hi(name: str | None): + print(f"Hey {name}!") +``` + +इसलिए, सामान्यतः आपको `Optional` और `Union` जैसे नामों के बारे में चिंता करने की ज़रूरत नहीं होती। 😎 diff --git a/docs/hi/docs/advanced/async-tests.md b/docs/hi/docs/advanced/async-tests.md new file mode 100644 index 000000000..8981d552b --- /dev/null +++ b/docs/hi/docs/advanced/async-tests.md @@ -0,0 +1,99 @@ +# Async Tests { #async-tests } + +आपने पहले ही देखा है कि दिए गए `TestClient` का उपयोग करके अपनी **FastAPI** applications को कैसे test किया जाता है। अब तक, आपने केवल synchronous tests लिखना देखा है, `async` functions का उपयोग किए बिना। + +अपने tests में asynchronous functions का उपयोग कर पाना उपयोगी हो सकता है, उदाहरण के लिए, जब आप अपने database को asynchronously query कर रहे हों। कल्पना करें कि आप अपनी FastAPI application को requests भेजना test करना चाहते हैं और फिर verify करना चाहते हैं कि आपके backend ने async database library का उपयोग करते हुए database में सही data सफलतापूर्वक लिखा है। + +आइए देखें कि हम इसे कैसे काम करवा सकते हैं। + +## pytest.mark.anyio { #pytest-mark-anyio } + +अगर हम अपने tests में asynchronous functions call करना चाहते हैं, तो हमारे test functions asynchronous होने चाहिए। AnyIO इसके लिए एक अच्छा plugin प्रदान करता है, जो हमें specify करने देता है कि कुछ test functions को asynchronously call किया जाना है। + +## HTTPX { #httpx } + +भले ही आपकी **FastAPI** application `async def` के बजाय सामान्य `def` functions का उपयोग करती हो, यह अंदर से फिर भी एक `async` application होती है। + +`TestClient` अंदर कुछ magic करता है ताकि standard pytest का उपयोग करते हुए आपकी सामान्य `def` test functions में asynchronous FastAPI application को call किया जा सके। लेकिन जब हम इसे asynchronous functions के अंदर उपयोग करते हैं, तो वह magic अब काम नहीं करता। अपने tests को asynchronously चलाने पर, हम अपने test functions के अंदर `TestClient` का उपयोग नहीं कर सकते। + +`TestClient` [HTTPX](https://www.python-httpx.org) पर आधारित है, और सौभाग्य से, हम API को test करने के लिए इसे सीधे उपयोग कर सकते हैं। + +## उदाहरण { #example } + +एक सरल उदाहरण के लिए, आइए [बड़ी Applications](../tutorial/bigger-applications.md) और [Testing](../tutorial/testing.md) में वर्णित file structure जैसी एक structure पर विचार करें: + +``` +. +├── app +│   ├── __init__.py +│   ├── main.py +│   └── test_main.py +``` + +file `main.py` में यह होगा: + +{* ../../docs_src/async_tests/app_a_py310/main.py *} + +file `test_main.py` में `main.py` के लिए tests होंगे, यह अब कुछ ऐसा दिख सकता है: + +{* ../../docs_src/async_tests/app_a_py310/test_main.py *} + +## इसे चलाएँ { #run-it } + +आप अपने tests को हमेशा की तरह इस तरह चला सकते हैं: + +
+ +```console +$ pytest + +---> 100% +``` + +
+ +## विस्तार से { #in-detail } + +marker `@pytest.mark.anyio` pytest को बताता है कि इस test function को asynchronously call किया जाना चाहिए: + +{* ../../docs_src/async_tests/app_a_py310/test_main.py hl[7] *} + +/// tip | सुझाव + +ध्यान दें कि test function अब पहले की तरह `TestClient` का उपयोग करते समय केवल `def` नहीं, बल्कि `async def` है। + +/// + +फिर हम app के साथ एक `AsyncClient` बना सकते हैं, और `await` का उपयोग करते हुए इसमें async requests भेज सकते हैं। + +{* ../../docs_src/async_tests/app_a_py310/test_main.py hl[9:12] *} + +यह इसके बराबर है: + +```Python +response = client.get('/') +``` + +...जिसका उपयोग हम `TestClient` के साथ अपनी requests बनाने के लिए करते थे। + +/// tip | सुझाव + +ध्यान दें कि हम नए `AsyncClient` के साथ async/await का उपयोग कर रहे हैं - request asynchronous है। + +/// + +/// warning | चेतावनी + +अगर आपकी application lifespan events पर निर्भर करती है, तो `AsyncClient` इन events को trigger नहीं करेगा। यह सुनिश्चित करने के लिए कि वे trigger हों, [florimondmanca/asgi-lifespan](https://github.com/florimondmanca/asgi-lifespan#usage) से `LifespanManager` का उपयोग करें। + +/// + +## अन्य asynchronous function calls { #other-asynchronous-function-calls } + +क्योंकि testing function अब asynchronous है, आप अब अपने tests में अपनी FastAPI application को requests भेजने के अलावा अन्य `async` functions को भी call (और `await`) कर सकते हैं, ठीक वैसे ही जैसे आप उन्हें अपने code में कहीं और call करते हैं। + +/// tip | सुझाव + +अगर अपने tests में asynchronous function calls integrate करते समय आपको `RuntimeError: Task attached to a different loop` मिलता है (जैसे [MongoDB's MotorClient](https://stackoverflow.com/questions/41584243/runtimeerror-task-attached-to-a-different-loop) का उपयोग करते समय), तो याद रखें कि जिन objects को event loop की जरूरत होती है, उन्हें केवल async functions के भीतर ही instantiate करें, जैसे कि `@app.on_event("startup")` callback। + +/// diff --git a/docs/hi/docs/advanced/behind-a-proxy.md b/docs/hi/docs/advanced/behind-a-proxy.md new file mode 100644 index 000000000..11bd984a2 --- /dev/null +++ b/docs/hi/docs/advanced/behind-a-proxy.md @@ -0,0 +1,466 @@ +# Proxy के पीछे { #behind-a-proxy } + +कई स्थितियों में, आप अपने FastAPI app के सामने Traefik या Nginx जैसा **proxy** उपयोग करेंगे। + +ये proxies HTTPS certificates और दूसरी चीज़ें संभाल सकते हैं। + +## Proxy Forwarded Headers { #proxy-forwarded-headers } + +आपकी application के सामने मौजूद **proxy** आम तौर पर requests को आपके **server** तक भेजने से पहले तुरंत कुछ headers सेट करेगा, ताकि server को पता चल सके कि request proxy द्वारा **forwarded** की गई थी, उसे मूल (public) URL पता चल सके, जिसमें domain शामिल हो, कि वह HTTPS उपयोग कर रहा है, आदि। + +**server** program (उदाहरण के लिए **FastAPI CLI** के जरिए **Uvicorn**) इन headers को समझने में सक्षम है, और फिर वह जानकारी आपकी application को पास कर सकता है। + +लेकिन security के लिए, क्योंकि server को यह नहीं पता कि वह किसी trusted proxy के पीछे है, वह उन headers को interpret नहीं करेगा। + +/// note | तकनीकी विवरण + +Proxy headers हैं: + +* [X-Forwarded-For](https://developer.mozilla.org/en-US/docs/Web/HTTP/Reference/Headers/X-Forwarded-For) +* [X-Forwarded-Proto](https://developer.mozilla.org/en-US/docs/Web/HTTP/Reference/Headers/X-Forwarded-Proto) +* [X-Forwarded-Host](https://developer.mozilla.org/en-US/docs/Web/HTTP/Reference/Headers/X-Forwarded-Host) + +/// + +### Proxy Forwarded Headers सक्षम करें { #enable-proxy-forwarded-headers } + +आप FastAPI CLI को *CLI Option* `--forwarded-allow-ips` के साथ शुरू कर सकते हैं और वे IP addresses पास कर सकते हैं जिन पर उन forwarded headers को पढ़ने के लिए भरोसा किया जाना चाहिए। + +अगर आप इसे `--forwarded-allow-ips="*"` पर सेट करते हैं, तो यह सभी incoming IPs पर भरोसा करेगा। + +अगर आपका **server** किसी trusted **proxy** के पीछे है और केवल proxy ही उससे बात करता है, तो इससे वह उस **proxy** का जो भी IP है, उसे accept करेगा। + +
+ +```console +$ fastapi run --forwarded-allow-ips="*" + +INFO: Uvicorn running on http://127.0.0.1:8000 (Press CTRL+C to quit) +``` + +
+ +### HTTPS के साथ Redirects { #redirects-with-https } + +उदाहरण के लिए, मान लें कि आप एक *path operation* `/items/` define करते हैं: + +{* ../../docs_src/behind_a_proxy/tutorial001_01_py310.py hl[6] *} + +अगर client `/items` पर जाने की कोशिश करता है, तो default रूप से, उसे `/items/` पर redirect किया जाएगा। + +लेकिन *CLI Option* `--forwarded-allow-ips` सेट करने से पहले यह `http://localhost:8000/items/` पर redirect कर सकता है। + +लेकिन शायद आपकी application `https://mysuperapp.com` पर hosted है, और redirection `https://mysuperapp.com/items/` पर होना चाहिए। + +अब `--proxy-headers` सेट करने से FastAPI सही location पर redirect कर पाएगा। 😎 + +``` +https://mysuperapp.com/items/ +``` + +/// tip | सुझाव + +अगर आप HTTPS के बारे में और जानना चाहते हैं, तो guide [HTTPS के बारे में](../deployment/https.md) देखें। + +/// + +### Proxy Forwarded Headers कैसे काम करते हैं { #how-proxy-forwarded-headers-work } + +यहाँ client और **application server** के बीच **proxy** द्वारा forwarded headers जोड़ने का एक visual representation है: + +```mermaid +sequenceDiagram + participant Client + participant Proxy as Proxy/Load Balancer + participant Server as FastAPI Server + + Client->>Proxy: HTTPS Request
Host: mysuperapp.com
Path: /items + + Note over Proxy: Proxy adds forwarded headers + + Proxy->>Server: HTTP Request
X-Forwarded-For: [client IP]
X-Forwarded-Proto: https
X-Forwarded-Host: mysuperapp.com
Path: /items + + Note over Server: Server interprets headers
(if --forwarded-allow-ips is set) + + Server->>Proxy: HTTP Response
with correct HTTPS URLs + + Proxy->>Client: HTTPS Response +``` + +**proxy** मूल client request को intercept करता है और request को **application server** तक पास करने से पहले खास *forwarded* headers (`X-Forwarded-*`) जोड़ता है। + +ये headers मूल request के बारे में वह जानकारी सुरक्षित रखते हैं जो अन्यथा खो जाती: + +* **X-Forwarded-For**: मूल client का IP address +* **X-Forwarded-Proto**: मूल protocol (`https`) +* **X-Forwarded-Host**: मूल host (`mysuperapp.com`) + +जब **FastAPI CLI** को `--forwarded-allow-ips` के साथ configured किया जाता है, तो यह इन headers पर भरोसा करता है और उनका उपयोग करता है, उदाहरण के लिए redirects में सही URLs generate करने के लिए। + +## Stripped path prefix वाला Proxy { #proxy-with-a-stripped-path-prefix } + +आपके पास ऐसा proxy हो सकता है जो आपकी application में एक path prefix जोड़ता हो। + +इन मामलों में आप अपनी application configure करने के लिए `root_path` का उपयोग कर सकते हैं। + +`root_path` ASGI specification द्वारा प्रदान किया गया एक mechanism है (जिस पर FastAPI, Starlette के जरिए, बना है)। + +`root_path` का उपयोग इन specific cases को handle करने के लिए किया जाता है। + +और इसका उपयोग sub-applications mount करते समय internally भी किया जाता है। + +इस case में, stripped path prefix वाला proxy होने का मतलब है कि आप अपने code में `/app` पर एक path declare कर सकते हैं, लेकिन फिर आप ऊपर एक layer (proxy) जोड़ते हैं जो आपकी **FastAPI** application को `/api/v1` जैसे path के नीचे रखेगी। + +इस case में, मूल path `/app` वास्तव में `/api/v1/app` पर serve किया जाएगा। + +हालाँकि आपका सारा code यह मानकर लिखा गया है कि सिर्फ `/app` है। + +{* ../../docs_src/behind_a_proxy/tutorial001_py310.py hl[6] *} + +और proxy app server (शायद FastAPI CLI के जरिए Uvicorn) तक request भेजने से पहले तुरंत **path prefix** को **"strip"** कर देगा, आपकी application को यह भरोसा दिलाते हुए कि वह `/app` पर serve हो रही है, ताकि आपको prefix `/api/v1` शामिल करने के लिए अपना सारा code update न करना पड़े। + +यहाँ तक, सब कुछ सामान्य रूप से काम करेगा। + +लेकिन फिर, जब आप integrated docs UI (frontend) खोलेंगे, तो वह OpenAPI schema को `/api/v1/openapi.json` के बजाय `/openapi.json` पर पाने की अपेक्षा करेगा। + +इसलिए, frontend (जो browser में चलता है) `/openapi.json` तक पहुँचने की कोशिश करेगा और OpenAPI schema प्राप्त नहीं कर पाएगा। + +क्योंकि हमारे app के लिए `/api/v1` का path prefix वाला proxy है, frontend को OpenAPI schema `/api/v1/openapi.json` पर fetch करना होगा। + +```mermaid +graph LR + +browser("Browser") +proxy["Proxy on http://0.0.0.0:9999/api/v1/app"] +server["Server on http://127.0.0.1:8000/app"] + +browser --> proxy +proxy --> server +``` + +/// tip | सुझाव + +IP `0.0.0.0` आम तौर पर यह बताने के लिए उपयोग किया जाता है कि program उस machine/server में उपलब्ध सभी IPs पर listen करता है। + +/// + +Docs UI को OpenAPI schema में यह declare करने की भी ज़रूरत होगी कि यह API `server` `/api/v1` (proxy के पीछे) पर स्थित है। उदाहरण के लिए: + +```JSON hl_lines="4-8" +{ + "openapi": "3.1.0", + // यहाँ और चीज़ें + "servers": [ + { + "url": "/api/v1" + } + ], + "paths": { + // यहाँ और चीज़ें + } +} +``` + +इस उदाहरण में, "Proxy" कुछ **Traefik** जैसा हो सकता है। और server **Uvicorn** के साथ FastAPI CLI जैसा हो सकता है, जो आपकी FastAPI application चला रहा है। + +### `root_path` प्रदान करना { #providing-the-root-path } + +इसे हासिल करने के लिए, आप command line option `--root-path` इस तरह उपयोग कर सकते हैं: + +
+ +```console +$ fastapi run main.py --forwarded-allow-ips="*" --root-path /api/v1 + +INFO: Uvicorn running on http://127.0.0.1:8000 (Press CTRL+C to quit) +``` + +
+ +अगर आप Hypercorn उपयोग करते हैं, तो उसमें भी option `--root-path` है। + +/// note | तकनीकी विवरण + +ASGI specification इस use case के लिए `root_path` define करती है। + +और `--root-path` command line option वही `root_path` प्रदान करता है। + +/// + +### वर्तमान `root_path` जाँचना { #checking-the-current-root-path } + +आप प्रत्येक request के लिए आपकी application द्वारा उपयोग किया गया वर्तमान `root_path` प्राप्त कर सकते हैं, यह `scope` dictionary का हिस्सा है (जो ASGI spec का हिस्सा है)। + +यहाँ हम इसे केवल demonstration purposes के लिए message में शामिल कर रहे हैं। + +{* ../../docs_src/behind_a_proxy/tutorial001_py310.py hl[8] *} + +फिर, अगर आप Uvicorn को इस तरह शुरू करते हैं: + +
+ +```console +$ fastapi run main.py --forwarded-allow-ips="*" --root-path /api/v1 + +INFO: Uvicorn running on http://127.0.0.1:8000 (Press CTRL+C to quit) +``` + +
+ +Response कुछ ऐसा होगा: + +```JSON +{ + "message": "Hello World", + "root_path": "/api/v1" +} +``` + +### FastAPI app में `root_path` सेट करना { #setting-the-root-path-in-the-fastapi-app } + +वैकल्पिक रूप से, अगर आपके पास `--root-path` या equivalent जैसा command line option देने का तरीका नहीं है, तो आप अपनी FastAPI app बनाते समय `root_path` parameter सेट कर सकते हैं: + +{* ../../docs_src/behind_a_proxy/tutorial002_py310.py hl[3] *} + +`root_path` को `FastAPI` में पास करना, Uvicorn या Hypercorn को `--root-path` command line option पास करने के equivalent होगा। + +### `root_path` के बारे में { #about-root-path } + +ध्यान रखें कि server (Uvicorn) उस `root_path` का उपयोग app को पास करने के अलावा किसी और चीज़ के लिए नहीं करेगा। + +लेकिन अगर आप अपने browser में [http://127.0.0.1:8000/app](http://127.0.0.1:8000/app) पर जाते हैं, तो आपको normal response दिखाई देगा: + +```JSON +{ + "message": "Hello World", + "root_path": "/api/v1" +} +``` + +इसलिए, यह `http://127.0.0.1:8000/api/v1/app` पर access किए जाने की अपेक्षा नहीं करेगा। + +Uvicorn अपेक्षा करेगा कि proxy Uvicorn को `http://127.0.0.1:8000/app` पर access करे, और फिर ऊपर extra `/api/v1` prefix जोड़ना proxy की जिम्मेदारी होगी। + +## Stripped path prefix वाले proxies के बारे में { #about-proxies-with-a-stripped-path-prefix } + +ध्यान रखें कि stripped path prefix वाला proxy इसे configure करने के तरीकों में से केवल एक है। + +शायद कई cases में default यह होगा कि proxy के पास stripped path prefix नहीं होगा। + +ऐसे case में (बिना stripped path prefix के), proxy कुछ `https://myawesomeapp.com` जैसा listen करेगा, और फिर अगर browser `https://myawesomeapp.com/api/v1/app` पर जाता है और आपका server (जैसे Uvicorn) `http://127.0.0.1:8000` पर listen करता है, तो proxy (बिना stripped path prefix के) Uvicorn को उसी path पर access करेगा: `http://127.0.0.1:8000/api/v1/app`। + +## Traefik के साथ local testing { #testing-locally-with-traefik } + +आप [Traefik](https://docs.traefik.io/) का उपयोग करके stripped path prefix के साथ experiment आसानी से locally चला सकते हैं। + +[Traefik download करें](https://github.com/containous/traefik/releases), यह एक single binary है, आप compressed file extract कर सकते हैं और इसे सीधे terminal से चला सकते हैं। + +फिर `traefik.toml` नाम की file बनाएँ जिसमें यह हो: + +```TOML hl_lines="3" +[entryPoints] + [entryPoints.http] + address = ":9999" + +[providers] + [providers.file] + filename = "routes.toml" +``` + +यह Traefik को port 9999 पर listen करने और दूसरी file `routes.toml` उपयोग करने के लिए कहता है। + +/// tip | सुझाव + +हम standard HTTP port 80 के बजाय port 9999 उपयोग कर रहे हैं ताकि आपको इसे admin (`sudo`) privileges के साथ न चलाना पड़े। + +/// + +अब वह दूसरी file `routes.toml` बनाएँ: + +```TOML hl_lines="5 12 20" +[http] + [http.middlewares] + + [http.middlewares.api-stripprefix.stripPrefix] + prefixes = ["/api/v1"] + + [http.routers] + + [http.routers.app-http] + entryPoints = ["http"] + service = "app" + rule = "PathPrefix(`/api/v1`)" + middlewares = ["api-stripprefix"] + + [http.services] + + [http.services.app] + [http.services.app.loadBalancer] + [[http.services.app.loadBalancer.servers]] + url = "http://127.0.0.1:8000" +``` + +यह file Traefik को path prefix `/api/v1` उपयोग करने के लिए configure करती है। + +और फिर Traefik अपनी requests को `http://127.0.0.1:8000` पर चल रहे आपके Uvicorn पर redirect करेगा। + +अब Traefik शुरू करें: + +
+ +```console +$ ./traefik --configFile=traefik.toml + +INFO[0000] Configuration loaded from file: /home/user/awesomeapi/traefik.toml +``` + +
+ +और अब `--root-path` option का उपयोग करके अपना app शुरू करें: + +
+ +```console +$ fastapi run main.py --forwarded-allow-ips="*" --root-path /api/v1 + +INFO: Uvicorn running on http://127.0.0.1:8000 (Press CTRL+C to quit) +``` + +
+ +### Responses जाँचें { #check-the-responses } + +अब, अगर आप Uvicorn के port वाले URL पर जाते हैं: [http://127.0.0.1:8000/app](http://127.0.0.1:8000/app), तो आपको normal response दिखाई देगा: + +```JSON +{ + "message": "Hello World", + "root_path": "/api/v1" +} +``` + +/// tip | सुझाव + +ध्यान दें कि भले ही आप इसे `http://127.0.0.1:8000/app` पर access कर रहे हैं, यह option `--root-path` से लिया गया `/api/v1` का `root_path` दिखाता है। + +/// + +और अब Traefik के port वाले URL को खोलें, जिसमें path prefix शामिल है: [http://127.0.0.1:9999/api/v1/app](http://127.0.0.1:9999/api/v1/app)। + +हमें वही response मिलता है: + +```JSON +{ + "message": "Hello World", + "root_path": "/api/v1" +} +``` + +लेकिन इस बार proxy द्वारा प्रदान किए गए prefix path वाले URL पर: `/api/v1`। + +बेशक, यहाँ विचार यह है कि हर कोई app को proxy के जरिए access करेगा, इसलिए path prefix `/api/v1` वाला version "correct" है। + +और बिना path prefix वाला version (`http://127.0.0.1:8000/app`), जो सीधे Uvicorn द्वारा प्रदान किया गया है, केवल _proxy_ (Traefik) के access के लिए होगा। + +यह दिखाता है कि Proxy (Traefik) path prefix का उपयोग कैसे करता है और server (Uvicorn) option `--root-path` से `root_path` का उपयोग कैसे करता है। + +### Docs UI जाँचें { #check-the-docs-ui } + +लेकिन यहाँ मज़ेदार हिस्सा है। ✨ + +App को access करने का "official" तरीका उस path prefix वाले proxy के जरिए होगा जिसे हमने define किया है। इसलिए, जैसा कि हम अपेक्षा करेंगे, अगर आप Uvicorn द्वारा सीधे serve किया गया docs UI try करते हैं, URL में path prefix के बिना, तो यह काम नहीं करेगा, क्योंकि यह proxy के जरिए access किए जाने की अपेक्षा करता है। + +आप इसे [http://127.0.0.1:8000/docs](http://127.0.0.1:8000/docs) पर देख सकते हैं: + + + +लेकिन अगर हम port `9999` वाले proxy का उपयोग करके "official" URL पर, `/api/v1/docs` पर docs UI access करते हैं, तो यह सही तरीके से काम करता है! 🎉 + +आप इसे [http://127.0.0.1:9999/api/v1/docs](http://127.0.0.1:9999/api/v1/docs) पर देख सकते हैं: + + + +बिल्कुल जैसा हम चाहते थे। ✔️ + +ऐसा इसलिए है क्योंकि FastAPI इस `root_path` का उपयोग OpenAPI में default `server` बनाने के लिए करता है, जिसमें `root_path` द्वारा दिया गया URL होता है। + +## अतिरिक्त servers { #additional-servers } + +/// warning | चेतावनी + +यह एक अधिक advanced use case है। चाहें तो इसे skip कर सकते हैं। + +/// + +Default रूप से, **FastAPI** OpenAPI schema में `root_path` के URL वाला एक `server` बनाएगा। + +लेकिन आप अन्य alternative `servers` भी प्रदान कर सकते हैं, उदाहरण के लिए अगर आप चाहते हैं कि *वही* docs UI staging और production environment दोनों के साथ interact करे। + +अगर आप `servers` की custom list पास करते हैं और कोई `root_path` है (क्योंकि आपकी API proxy के पीछे रहती है), तो **FastAPI** list की शुरुआत में इस `root_path` के साथ एक "server" insert करेगा। + +उदाहरण के लिए: + +{* ../../docs_src/behind_a_proxy/tutorial003_py310.py hl[4:7] *} + +यह इस तरह का OpenAPI schema generate करेगा: + +```JSON hl_lines="5-7" +{ + "openapi": "3.1.0", + // यहाँ और चीज़ें + "servers": [ + { + "url": "/api/v1" + }, + { + "url": "https://stag.example.com", + "description": "Staging environment" + }, + { + "url": "https://prod.example.com", + "description": "Production environment" + } + ], + "paths": { + // यहाँ और चीज़ें + } +} +``` + +/// tip | सुझाव + +ध्यान दें कि `/api/v1` के `url` value वाला auto-generated server `root_path` से लिया गया है। + +/// + +[http://127.0.0.1:9999/api/v1/docs](http://127.0.0.1:9999/api/v1/docs) पर docs UI में यह ऐसा दिखेगा: + + + +/// tip | सुझाव + +Docs UI आपके द्वारा चुने गए server के साथ interact करेगा। + +/// + +/// note | तकनीकी विवरण + +OpenAPI specification में `servers` property optional है। + +अगर आप `servers` parameter specify नहीं करते और `root_path` `/` के बराबर है, तो generated OpenAPI schema में `servers` property default रूप से पूरी तरह omit कर दी जाएगी, जो `/` के `url` value वाले single server के equivalent है। + +/// + +### `root_path` से automatic server disable करें { #disable-automatic-server-from-root-path } + +अगर आप नहीं चाहते कि **FastAPI** `root_path` का उपयोग करके automatic server शामिल करे, तो आप parameter `root_path_in_servers=False` उपयोग कर सकते हैं: + +{* ../../docs_src/behind_a_proxy/tutorial004_py310.py hl[9] *} + +और फिर यह उसे OpenAPI schema में शामिल नहीं करेगा। + +## Sub-application mount करना { #mounting-a-sub-application } + +अगर आपको `root_path` वाले proxy का उपयोग करते हुए भी sub-application mount करनी है (जैसा कि [Sub Applications - Mounts](sub-applications.md) में बताया गया है), तो आप इसे सामान्य रूप से कर सकते हैं, जैसा कि आप अपेक्षा करेंगे। + +FastAPI internally `root_path` का smart तरीके से उपयोग करेगा, इसलिए यह बस काम करेगा। ✨ diff --git a/docs/hi/docs/advanced/custom-response.md b/docs/hi/docs/advanced/custom-response.md new file mode 100644 index 000000000..8655618f2 --- /dev/null +++ b/docs/hi/docs/advanced/custom-response.md @@ -0,0 +1,273 @@ +# कस्टम Response - HTML, Stream, File, अन्य { #custom-response-html-stream-file-others } + +Default रूप से, **FastAPI** JSON responses लौटाएगा। + +आप [सीधे Response लौटाएँ](response-directly.md) में दिखाए गए अनुसार सीधे `Response` लौटाकर इसे override कर सकते हैं। + +लेकिन अगर आप सीधे `Response` लौटाते हैं (या कोई subclass, जैसे `JSONResponse`), तो data अपने आप convert नहीं होगा (भले ही आप `response_model` declare करें), और documentation अपने आप generate नहीं होगी (उदाहरण के लिए, generated OpenAPI के हिस्से के रूप में HTTP header `Content-Type` में specific "media type" शामिल करना)। + +लेकिन आप *path operation decorator* में `response_class` parameter का उपयोग करके वह `Response` भी declare कर सकते हैं जिसे आप उपयोग करना चाहते हैं (जैसे कोई भी `Response` subclass)। + +आप अपनी *path operation function* से जो contents लौटाते हैं, उन्हें उस `Response` के अंदर रख दिया जाएगा। + +/// note | नोट + +यदि आप बिना media type वाली response class का उपयोग करते हैं, तो FastAPI अपेक्षा करेगा कि आपके response में कोई content न हो, इसलिए यह अपने generated OpenAPI docs में response format को document नहीं करेगा। + +/// + +## JSON Responses { #json-responses } + +Default रूप से FastAPI JSON responses लौटाता है। + +यदि आप [Response Model](../tutorial/response-model.md) declare करते हैं तो FastAPI Pydantic का उपयोग करके data को JSON में serialize करने के लिए उसका उपयोग करेगा। + +यदि आप response model declare नहीं करते हैं, तो FastAPI [JSON Compatible Encoder](../tutorial/encoder.md) में समझाए गए `jsonable_encoder` का उपयोग करेगा और उसे `JSONResponse` में रखेगा। + +यदि आप JSON media type (`application/json`) के साथ `response_class` declare करते हैं, जैसा कि `JSONResponse` के साथ होता है, तो आपके द्वारा लौटाया गया data आपकी *path operation decorator* में declare किए गए किसी भी Pydantic `response_model` के साथ अपने आप convert (और filter) हो जाएगा। लेकिन data Pydantic के साथ JSON bytes में serialize नहीं होगा, इसके बजाय इसे `jsonable_encoder` के साथ convert किया जाएगा और फिर `JSONResponse` class को pass किया जाएगा, जो Python की standard JSON library का उपयोग करके इसे bytes में serialize करेगी। + +### JSON Performance { #json-performance } + +संक्षेप में, यदि आप maximum performance चाहते हैं, तो [Response Model](../tutorial/response-model.md) का उपयोग करें और *path operation decorator* में `response_class` declare न करें। + +{* ../../docs_src/response_model/tutorial001_01_py310.py ln[15:17] hl[16] *} + +## HTML Response { #html-response } + +**FastAPI** से सीधे HTML के साथ response लौटाने के लिए, `HTMLResponse` का उपयोग करें। + +* `HTMLResponse` import करें। +* अपने *path operation decorator* के parameter `response_class` के रूप में `HTMLResponse` pass करें। + +{* ../../docs_src/custom_response/tutorial002_py310.py hl[2,7] *} + +/// note | नोट + +Parameter `response_class` का उपयोग response के "media type" को define करने के लिए भी किया जाएगा। + +इस मामले में, HTTP header `Content-Type` को `text/html` पर set किया जाएगा। + +और इसे OpenAPI में इसी तरह document किया जाएगा। + +/// + +### `Response` लौटाएँ { #return-a-response } + +जैसा कि [सीधे Response लौटाएँ](response-directly.md) में देखा गया है, आप अपनी *path operation* में response को सीधे लौटाकर भी override कर सकते हैं। + +ऊपर वाला वही उदाहरण, जो `HTMLResponse` लौटाता है, इस तरह दिख सकता है: + +{* ../../docs_src/custom_response/tutorial003_py310.py hl[2,7,19] *} + +/// warning | चेतावनी + +आपकी *path operation function* द्वारा सीधे लौटाया गया `Response` OpenAPI में document नहीं होगा (उदाहरण के लिए, `Content-Type` document नहीं होगा) और automatic interactive docs में visible नहीं होगा। + +/// + +/// note | नोट + +बेशक, वास्तविक `Content-Type` header, status code, आदि, आपके द्वारा लौटाए गए `Response` object से आएँगे। + +/// + +### OpenAPI में document करें और `Response` override करें { #document-in-openapi-and-override-response } + +यदि आप function के अंदर से response को override करना चाहते हैं लेकिन साथ ही OpenAPI में "media type" document करना चाहते हैं, तो आप `response_class` parameter का उपयोग कर सकते हैं और `Response` object भी लौटा सकते हैं। + +तब `response_class` का उपयोग केवल OpenAPI *path operation* को document करने के लिए किया जाएगा, लेकिन आपका `Response` जैसा है वैसा ही उपयोग किया जाएगा। + +#### सीधे `HTMLResponse` लौटाएँ { #return-an-htmlresponse-directly } + +उदाहरण के लिए, यह कुछ ऐसा हो सकता है: + +{* ../../docs_src/custom_response/tutorial004_py310.py hl[7,21,23] *} + +इस उदाहरण में, function `generate_html_response()` पहले से ही HTML को `str` में लौटाने के बजाय `Response` generate करके लौटाता है। + +`generate_html_response()` को call करने का result लौटाकर, आप पहले से ही एक `Response` लौटा रहे हैं जो default **FastAPI** behavior को override करेगा। + +लेकिन क्योंकि आपने `response_class` में भी `HTMLResponse` pass किया है, **FastAPI** को पता होगा कि इसे OpenAPI और interactive docs में `text/html` के साथ HTML के रूप में कैसे document करना है: + + + +## उपलब्ध responses { #available-responses } + +यहाँ कुछ उपलब्ध responses दिए गए हैं। + +ध्यान रखें कि आप कुछ और लौटाने के लिए `Response` का उपयोग कर सकते हैं, या custom sub-class भी बना सकते हैं। + +/// note | तकनीकी विवरण + +आप `from starlette.responses import HTMLResponse` भी उपयोग कर सकते हैं। + +**FastAPI** आपकी सुविधा के लिए, developer के रूप में, वही `starlette.responses` `fastapi.responses` के रूप में प्रदान करता है। लेकिन अधिकांश उपलब्ध responses सीधे Starlette से आते हैं। + +/// + +### `Response` { #response } + +मुख्य `Response` class, बाकी सभी responses इससे inherit करते हैं। + +आप इसे सीधे लौटा सकते हैं। + +यह निम्नलिखित parameters accept करता है: + +* `content` - एक `str` या `bytes`। +* `status_code` - एक `int` HTTP status code। +* `headers` - strings का एक `dict`। +* `media_type` - media type बताने वाला एक `str`। उदाहरण के लिए `"text/html"`। + +FastAPI (असल में Starlette) अपने आप एक Content-Length header शामिल करेगा। यह `media_type` के आधार पर Content-Type header भी शामिल करेगा और text types के लिए charset append करेगा। + +{* ../../docs_src/response_directly/tutorial002_py310.py hl[1,18] *} + +### `HTMLResponse` { #htmlresponse } + +कुछ text या bytes लेता है और HTML response लौटाता है, जैसा आपने ऊपर पढ़ा। + +### `PlainTextResponse` { #plaintextresponse } + +कुछ text या bytes लेता है और plain text response लौटाता है। + +{* ../../docs_src/custom_response/tutorial005_py310.py hl[2,7,9] *} + +### `JSONResponse` { #jsonresponse } + +कुछ data लेता है और `application/json` encoded response लौटाता है। + +जैसा आपने ऊपर पढ़ा, यह **FastAPI** में उपयोग किया जाने वाला default response है। + +/// note | तकनीकी विवरण + +लेकिन यदि आप response model या return type declare करते हैं, तो उसका उपयोग सीधे data को JSON में serialize करने के लिए किया जाएगा, और JSON के लिए सही media type वाला response सीधे लौटाया जाएगा, `JSONResponse` class का उपयोग किए बिना। + +यह best performance पाने का ideal तरीका है। + +/// + +### `RedirectResponse` { #redirectresponse } + +HTTP redirect लौटाता है। Default रूप से 307 status code (Temporary Redirect) का उपयोग करता है। + +आप सीधे `RedirectResponse` लौटा सकते हैं: + +{* ../../docs_src/custom_response/tutorial006_py310.py hl[2,9] *} + +--- + +या आप इसे `response_class` parameter में उपयोग कर सकते हैं: + + +{* ../../docs_src/custom_response/tutorial006b_py310.py hl[2,7,9] *} + +यदि आप ऐसा करते हैं, तो आप अपनी *path operation* function से URL सीधे लौटा सकते हैं। + +इस मामले में, उपयोग किया गया `status_code` `RedirectResponse` के लिए default वाला होगा, जो `307` है। + +--- + +आप `status_code` parameter को `response_class` parameter के साथ combine करके भी उपयोग कर सकते हैं: + +{* ../../docs_src/custom_response/tutorial006c_py310.py hl[2,7,9] *} + +### `StreamingResponse` { #streamingresponse } + +एक async generator या सामान्य generator/iterator (`yield` वाली function) लेता है और response body को stream करता है। + +{* ../../docs_src/custom_response/tutorial007_py310.py hl[3,16] *} + +/// note | तकनीकी विवरण + +एक `async` task केवल तब cancel किया जा सकता है जब वह किसी `await` तक पहुँचता है। यदि कोई `await` नहीं है, तो generator (`yield` वाली function) ठीक से cancel नहीं हो सकता और cancellation request किए जाने के बाद भी चलना जारी रख सकता है। + +चूँकि इस छोटे उदाहरण को किसी `await` statement की आवश्यकता नहीं है, हम event loop को cancellation handle करने का अवसर देने के लिए `await anyio.sleep(0)` जोड़ते हैं। + +यह बड़े या infinite streams के साथ और भी अधिक महत्वपूर्ण होगा। + +/// + +/// tip | टिप + +सीधे `StreamingResponse` लौटाने के बजाय, आपको शायद [Stream Data](./stream-data.md) में दिए गए style का पालन करना चाहिए, यह कहीं अधिक सुविधाजनक है और आपके लिए पर्दे के पीछे cancellation handle करता है। + +यदि आप JSON Lines stream कर रहे हैं, तो [Stream JSON Lines](../tutorial/stream-json-lines.md) tutorial का पालन करें। + +/// + +### `FileResponse` { #fileresponse } + +एक file को response के रूप में asynchronously stream करता है। + +Instantiate करने के लिए अन्य response types की तुलना में अलग set of arguments लेता है: + +* `path` - stream की जाने वाली file का file path। +* `headers` - dictionary के रूप में शामिल किए जाने वाले कोई भी custom headers। +* `media_type` - media type बताने वाली string। यदि unset है, तो media type infer करने के लिए filename या path का उपयोग किया जाएगा। +* `filename` - यदि set है, तो इसे response `Content-Disposition` में शामिल किया जाएगा। + +File responses में उपयुक्त `Content-Length`, `Last-Modified` और `ETag` headers शामिल होंगे। + +{* ../../docs_src/custom_response/tutorial009_py310.py hl[2,10] *} + +आप `response_class` parameter का उपयोग भी कर सकते हैं: + +{* ../../docs_src/custom_response/tutorial009b_py310.py hl[2,8,10] *} + +इस मामले में, आप अपनी *path operation* function से file path सीधे लौटा सकते हैं। + +## Custom response class { #custom-response-class } + +आप `Response` से inherit करके और उसका उपयोग करके अपनी खुद की custom response class बना सकते हैं। + +उदाहरण के लिए, मान लें कि आप कुछ settings के साथ [`orjson`](https://github.com/ijl/orjson) का उपयोग करना चाहते हैं। + +मान लें आप चाहते हैं कि यह indented और formatted JSON लौटाए, इसलिए आप orjson option `orjson.OPT_INDENT_2` का उपयोग करना चाहते हैं। + +आप `CustomORJSONResponse` बना सकते हैं। आपको मुख्य रूप से `Response.render(content)` method बनाना है जो content को `bytes` के रूप में लौटाता है: + +{* ../../docs_src/custom_response/tutorial009c_py310.py hl[9:14,17] *} + +अब यह लौटाने के बजाय: + +```json +{"message": "Hello World"} +``` + +...यह response लौटाएगा: + +```json +{ + "message": "Hello World" +} +``` + +बेशक, JSON formatting की तुलना में इसका लाभ उठाने के लिए आपको शायद कहीं बेहतर तरीके मिलेंगे। 😉 + +### `orjson` या Response Model { #orjson-or-response-model } + +यदि आप performance खोज रहे हैं, तो शायद `orjson` response की तुलना में [Response Model](../tutorial/response-model.md) का उपयोग करना आपके लिए बेहतर होगा। + +Response model के साथ, FastAPI data को JSON में serialize करने के लिए Pydantic का उपयोग करेगा, intermediate steps के बिना, जैसे `jsonable_encoder` के साथ convert करना, जो किसी भी अन्य मामले में होता। + +और अंदर से, Pydantic JSON में serialize करने के लिए `orjson` जैसे ही underlying Rust mechanisms का उपयोग करता है, इसलिए response model के साथ आपको पहले से ही best performance मिल जाएगी। + +## Default response class { #default-response-class } + +**FastAPI** class instance या `APIRouter` बनाते समय आप specify कर सकते हैं कि default रूप से कौन-सी response class उपयोग करनी है। + +इसे define करने वाला parameter `default_response_class` है। + +नीचे दिए गए उदाहरण में, **FastAPI** सभी *path operations* में JSON के बजाय default रूप से `HTMLResponse` का उपयोग करेगा। + +{* ../../docs_src/custom_response/tutorial010_py310.py hl[2,4] *} + +/// tip | टिप + +आप पहले की तरह *path operations* में अब भी `response_class` override कर सकते हैं। + +/// + +## अतिरिक्त documentation { #additional-documentation } + +आप `responses` का उपयोग करके OpenAPI में media type और कई अन्य details भी declare कर सकते हैं: [OpenAPI में अतिरिक्त Responses](additional-responses.md)। diff --git a/docs/hi/docs/advanced/dataclasses.md b/docs/hi/docs/advanced/dataclasses.md new file mode 100644 index 000000000..55e487691 --- /dev/null +++ b/docs/hi/docs/advanced/dataclasses.md @@ -0,0 +1,95 @@ +# Dataclasses का उपयोग { #using-dataclasses } + +FastAPI **Pydantic** के ऊपर बनाया गया है, और मैंने आपको दिखाया है कि requests और responses घोषित करने के लिए Pydantic models का उपयोग कैसे करें। + +लेकिन FastAPI उसी तरह [`dataclasses`](https://docs.python.org/3/library/dataclasses.html) का उपयोग भी support करता है: + +{* ../../docs_src/dataclasses_/tutorial001_py310.py hl[1,6:11,18:19] *} + +यह अभी भी **Pydantic** की वजह से support किया जाता है, क्योंकि इसमें [`dataclasses` के लिए internal support](https://docs.pydantic.dev/latest/concepts/dataclasses/#use-of-stdlib-dataclasses-with-basemodel) है। + +इसलिए, ऊपर दिए गए code में भी, जो Pydantic का स्पष्ट रूप से उपयोग नहीं करता, FastAPI उन standard dataclasses को Pydantic की अपनी तरह की dataclasses में बदलने के लिए Pydantic का उपयोग कर रहा है। + +और निश्चित रूप से, यह इन्हें भी support करता है: + +* data validation +* data serialization +* data documentation, आदि। + +यह Pydantic models की तरह ही काम करता है। और अंदर से यह वास्तव में उसी तरह, Pydantic का उपयोग करके हासिल किया जाता है। + +/// note | नोट + +ध्यान रखें कि dataclasses वह सब कुछ नहीं कर सकतीं जो Pydantic models कर सकते हैं। + +इसलिए, आपको अभी भी Pydantic models का उपयोग करना पड़ सकता है। + +लेकिन अगर आपके पास बहुत सारी dataclasses पहले से मौजूद हैं, तो FastAPI का उपयोग करके web API को power देने के लिए उनका उपयोग करने की यह एक अच्छी तरकीब है। 🤓 + +/// + +## `response_model` में Dataclasses { #dataclasses-in-response-model } + +आप `response_model` parameter में भी `dataclasses` का उपयोग कर सकते हैं: + +{* ../../docs_src/dataclasses_/tutorial002_py310.py hl[1,6:12,18] *} + +dataclass अपने आप Pydantic dataclass में बदल जाएगी। + +इस तरह, उसका schema API docs के user interface में दिखाई देगा: + + + +## Nested Data Structures में Dataclasses { #dataclasses-in-nested-data-structures } + +आप nested data structures बनाने के लिए `dataclasses` को अन्य type annotations के साथ भी जोड़ सकते हैं। + +कुछ मामलों में, आपको अभी भी Pydantic के `dataclasses` वाले version का उपयोग करना पड़ सकता है। उदाहरण के लिए, अगर automatically generated API documentation में errors हों। + +उस स्थिति में, आप standard `dataclasses` को बस `pydantic.dataclasses` से बदल सकते हैं, जो एक drop-in replacement है: + +{* ../../docs_src/dataclasses_/tutorial003_py310.py hl[1,4,7:10,13:16,22:24,27] *} + +1. हम अभी भी standard `dataclasses` से `field` import करते हैं। + +2. `pydantic.dataclasses`, `dataclasses` के लिए एक drop-in replacement है। + +3. `Author` dataclass में `Item` dataclasses की एक list शामिल है। + +4. `Author` dataclass को `response_model` parameter के रूप में उपयोग किया गया है। + +5. आप request body के रूप में dataclasses के साथ अन्य standard type annotations का उपयोग कर सकते हैं। + + इस मामले में, यह `Item` dataclasses की एक list है। + +6. यहाँ हम एक dictionary return कर रहे हैं जिसमें `items` है, जो dataclasses की एक list है। + + FastAPI अभी भी data को JSON में serialize करने में सक्षम है। + +7. यहाँ `response_model`, `Author` dataclasses की list के type annotation का उपयोग कर रहा है। + + फिर से, आप `dataclasses` को standard type annotations के साथ जोड़ सकते हैं। + +8. ध्यान दें कि यह *path operation function* `async def` की बजाय सामान्य `def` का उपयोग करता है। + + हमेशा की तरह, FastAPI में आप आवश्यकता के अनुसार `def` और `async def` को जोड़ सकते हैं। + + अगर आपको यह याद दिलाने की आवश्यकता है कि किसे कब उपयोग करना है, तो [`async` और `await`](../async.md#in-a-hurry) के docs में _"जल्दी में हैं?"_ section देखें। + +9. यह *path operation function* dataclasses return नहीं कर रहा है (हालाँकि कर सकता था), बल्कि internal data वाली dictionaries की list return कर रहा है। + + FastAPI response को बदलने के लिए `response_model` parameter (जिसमें dataclasses शामिल हैं) का उपयोग करेगा। + +आप जटिल data structures बनाने के लिए `dataclasses` को कई अलग-अलग combinations में अन्य type annotations के साथ जोड़ सकते हैं। + +अधिक विशिष्ट विवरण देखने के लिए ऊपर दिए गए in-code annotation tips देखें। + +## और जानें { #learn-more } + +आप `dataclasses` को अन्य Pydantic models के साथ भी जोड़ सकते हैं, उनसे inherit कर सकते हैं, उन्हें अपने models में शामिल कर सकते हैं, आदि। + +अधिक जानने के लिए, [dataclasses के बारे में Pydantic docs](https://docs.pydantic.dev/latest/concepts/dataclasses/) देखें। + +## Version { #version } + +यह FastAPI version `0.67.0` से उपलब्ध है। 🔖 diff --git a/docs/hi/docs/advanced/events.md b/docs/hi/docs/advanced/events.md new file mode 100644 index 000000000..05afd4e1c --- /dev/null +++ b/docs/hi/docs/advanced/events.md @@ -0,0 +1,165 @@ +# Lifespan Events { #lifespan-events } + +आप ऐसी logic (code) define कर सकते हैं जिसे application के **starts up** होने से पहले execute किया जाना चाहिए। इसका मतलब है कि यह code application के **requests receive करना शुरू करने से पहले**, **एक बार** execute होगा। + +उसी तरह, आप ऐसी logic (code) define कर सकते हैं जिसे application के **shutting down** होने पर execute किया जाना चाहिए। इस मामले में, यह code संभवतः **कई requests** handle करने के **बाद**, **एक बार** execute होगा। + +क्योंकि यह code application के requests लेना **शुरू** करने से पहले, और requests handle करना **पूरा** करने के तुरंत बाद execute होता है, यह पूरी application **lifespan** को cover करता है (शब्द "lifespan" थोड़ी देर में महत्वपूर्ण होगा 😉)। + +यह उन **resources** को setup करने के लिए बहुत उपयोगी हो सकता है जिनकी आपको पूरी app में जरूरत होती है, और जो requests के बीच **shared** होते हैं, और/या जिन्हें आपको बाद में **clean up** करना होता है। उदाहरण के लिए, database connection pool, या कोई shared machine learning model load करना। + +## Use Case { #use-case } + +आइए एक उदाहरण **use case** से शुरू करते हैं और फिर देखते हैं कि इसे इससे कैसे solve किया जाए। + +मान लीजिए कि आपके पास कुछ **machine learning models** हैं जिन्हें आप requests handle करने के लिए use करना चाहते हैं। 🤖 + +वही models requests के बीच shared हैं, इसलिए, यह हर request के लिए एक model, या हर user के लिए एक model या ऐसा कुछ नहीं है। + +मान लीजिए कि model load करने में **काफी समय लग सकता है**, क्योंकि उसे disk से बहुत सारा **data** read करना होता है। इसलिए आप इसे हर request के लिए नहीं करना चाहते। + +आप इसे module/file के top level पर load कर सकते हैं, लेकिन इसका मतलब यह भी होगा कि अगर आप सिर्फ एक simple automated test run कर रहे हैं, तब भी यह **model load** करेगा, और फिर वह test **slow** होगा क्योंकि code के किसी independent part को run कर पाने से पहले उसे model load होने का इंतजार करना पड़ेगा। + +यही हम solve करेंगे, चलिए model को requests handle होने से पहले load करते हैं, लेकिन केवल application के requests receive करना शुरू करने से ठीक पहले, code load होते समय नहीं। + +## Lifespan { #lifespan } + +आप `FastAPI` app के `lifespan` parameter और एक "context manager" (मैं अभी दिखाऊंगा कि यह क्या है) का use करके यह *startup* और *shutdown* logic define कर सकते हैं। + +आइए एक उदाहरण से शुरू करते हैं और फिर इसे detail में देखते हैं। + +हम `yield` के साथ एक async function `lifespan()` इस तरह create करते हैं: + +{* ../../docs_src/events/tutorial003_py310.py hl[16,19] *} + +यहां हम `yield` से पहले machine learning models वाली dictionary में (fake) model function रखकर model load करने वाली महंगी *startup* operation को simulate कर रहे हैं। यह code application के **requests लेना शुरू करने से पहले**, *startup* के दौरान execute होगा। + +और फिर, `yield` के तुरंत बाद, हम model unload करते हैं। यह code application के **requests handle करना पूरा करने के बाद**, *shutdown* से ठीक पहले execute होगा। उदाहरण के लिए, यह memory या GPU जैसे resources release कर सकता है। + +/// tip | सुझाव + +`shutdown` तब होगा जब आप application को **stop** कर रहे होंगे। + +शायद आपको कोई नया version start करना हो, या आप इसे चलाते-चलाते बस थक गए हों। 🤷 + +/// + +### Lifespan function { #lifespan-function } + +ध्यान देने वाली पहली चीज यह है कि हम `yield` के साथ एक async function define कर रहे हैं। यह `yield` वाली Dependencies से बहुत मिलता-जुलता है। + +{* ../../docs_src/events/tutorial003_py310.py hl[14:19] *} + +function का पहला हिस्सा, `yield` से पहले वाला, application start होने से **पहले** execute होगा। + +और `yield` के बाद वाला हिस्सा application के finish हो जाने के **बाद** execute होगा। + +### Async Context Manager { #async-context-manager } + +अगर आप check करें, तो function को `@asynccontextmanager` से decorate किया गया है। + +यह function को "**async context manager**" नाम की चीज में convert करता है। + +{* ../../docs_src/events/tutorial003_py310.py hl[1,13] *} + +Python में एक **context manager** ऐसी चीज है जिसे आप `with` statement में use कर सकते हैं, उदाहरण के लिए, `open()` को context manager की तरह use किया जा सकता है: + +```Python +with open("file.txt") as file: + file.read() +``` + +Python के नए versions में, एक **async context manager** भी है। आप इसे `async with` के साथ use करेंगे: + +```Python +async with lifespan(app): + await do_stuff() +``` + +जब आप ऊपर की तरह कोई context manager या async context manager create करते हैं, तो यह क्या करता है कि `with` block में enter करने से पहले, यह `yield` से पहले वाला code execute करेगा, और `with` block से exit करने के बाद, यह `yield` के बाद वाला code execute करेगा। + +ऊपर हमारे code example में, हम इसे सीधे use नहीं करते, बल्कि FastAPI को pass करते हैं ताकि वह इसे use कर सके। + +`FastAPI` app का `lifespan` parameter एक **async context manager** लेता है, इसलिए हम अपना नया `lifespan` async context manager उसे pass कर सकते हैं। + +{* ../../docs_src/events/tutorial003_py310.py hl[22] *} + +## Alternative Events (deprecated) { #alternative-events-deprecated } + +/// warning | चेतावनी + +*startup* और *shutdown* को handle करने का recommended तरीका ऊपर बताए गए अनुसार `FastAPI` app के `lifespan` parameter का use करना है। अगर आप `lifespan` parameter provide करते हैं, तो `startup` और `shutdown` event handlers अब call नहीं किए जाएंगे। यह पूरा `lifespan` होगा या पूरे events, दोनों नहीं। + +आप शायद यह हिस्सा skip कर सकते हैं। + +/// + +इस logic को *startup* के दौरान और *shutdown* के दौरान execute करने के लिए define करने का एक alternative तरीका है। + +आप event handlers (functions) define कर सकते हैं जिन्हें application के starts up होने से पहले, या application के shutting down होने पर execute किया जाना चाहिए। + +इन functions को `async def` या normal `def` के साथ declare किया जा सकता है। + +### `startup` event { #startup-event } + +application start होने से पहले run होने वाला function add करने के लिए, इसे event `"startup"` के साथ declare करें: + +{* ../../docs_src/events/tutorial001_py310.py hl[8] *} + +इस मामले में, `startup` event handler function items "database" (बस एक `dict`) को कुछ values के साथ initialize करेगा। + +आप एक से अधिक event handler function add कर सकते हैं। + +और आपकी application requests receive करना तब तक शुरू नहीं करेगी जब तक सभी `startup` event handlers complete नहीं हो जाते। + +### `shutdown` event { #shutdown-event } + +application के shutting down होने पर run होने वाला function add करने के लिए, इसे event `"shutdown"` के साथ declare करें: + +{* ../../docs_src/events/tutorial002_py310.py hl[6] *} + +यहां, `shutdown` event handler function एक text line `"Application shutdown"` को `log.txt` file में write करेगा। + +/// note | नोट + +`open()` function में, `mode="a"` का मतलब "append" होता है, इसलिए, line उस file में जो भी है उसके बाद add की जाएगी, पिछले contents को overwrite किए बिना। + +/// + +/// tip | सुझाव + +ध्यान दें कि इस मामले में हम एक standard Python `open()` function use कर रहे हैं जो एक file के साथ interact करता है। + +इसलिए, इसमें I/O (input/output) शामिल है, जिसके लिए चीजों के disk पर write होने का "waiting" करना पड़ता है। + +लेकिन `open()` `async` और `await` use नहीं करता। + +इसलिए, हम event handler function को `async def` के बजाय standard `def` के साथ declare करते हैं। + +/// + +### `startup` और `shutdown` साथ में { #startup-and-shutdown-together } + +इस बात की काफी संभावना है कि आपके *startup* और *shutdown* की logic connected हो, आप शायद कुछ start करना और फिर उसे finish करना, कोई resource acquire करना और फिर उसे release करना, आदि चाहें। + +इसे अलग-अलग functions में करना, जो logic या variables को साथ में share नहीं करते, अधिक कठिन है क्योंकि आपको values को global variables या इसी तरह की tricks में store करना पड़ेगा। + +इसी वजह से, अब इसके बजाय ऊपर explain किए गए `lifespan` को use करने की recommendation है। + +## Technical Details { #technical-details } + +जिज्ञासु nerds के लिए बस एक technical detail। 🤓 + +अंदर से, ASGI technical specification में, यह [Lifespan Protocol](https://asgi.readthedocs.io/en/latest/specs/lifespan.html) का हिस्सा है, और यह `startup` और `shutdown` नाम के events define करता है। + +/// note | नोट + +आप Starlette `lifespan` handlers के बारे में [Starlette की Lifespan docs](https://www.starlette.dev/lifespan/) में और पढ़ सकते हैं। + +इसमें यह भी शामिल है कि lifespan state को कैसे handle किया जाए जिसे आपके code के अन्य areas में use किया जा सकता है। + +/// + +## Sub Applications { #sub-applications } + +🚨 ध्यान रखें कि ये lifespan events (startup और shutdown) केवल main application के लिए execute होंगे, [Sub Applications - Mounts](sub-applications.md) के लिए नहीं। diff --git a/docs/hi/docs/advanced/generate-clients.md b/docs/hi/docs/advanced/generate-clients.md new file mode 100644 index 000000000..fa4b8f496 --- /dev/null +++ b/docs/hi/docs/advanced/generate-clients.md @@ -0,0 +1,192 @@ +# SDKs जेनरेट करना { #generating-sdks } + +क्योंकि **FastAPI** **OpenAPI** specification पर आधारित है, इसकी APIs को एक standard format में वर्णित किया जा सकता है जिसे कई tools समझते हैं। + +इससे up-to-date **documentation**, कई भाषाओं में client libraries (**SDKs**), और **testing** या **automation workflows** जेनरेट करना आसान हो जाता है, जो आपके code के साथ sync में रहते हैं। + +इस guide में, आप सीखेंगे कि अपने FastAPI backend के लिए **TypeScript SDK** कैसे जेनरेट करें। + +## Open Source SDK Generators { #open-source-sdk-generators } + +एक versatile विकल्प [OpenAPI Generator](https://openapi-generator.tech/) है, जो **कई programming languages** को support करता है और आपकी OpenAPI specification से SDKs जेनरेट कर सकता है। + +**TypeScript clients** के लिए, [Hey API](https://heyapi.dev/) एक purpose-built solution है, जो TypeScript ecosystem के लिए optimized experience प्रदान करता है। + +आप [OpenAPI.Tools](https://openapi.tools/#sdk) पर और SDK generators खोज सकते हैं। + +/// tip | सुझाव + +FastAPI अपने-आप **OpenAPI 3.1** specifications जेनरेट करता है, इसलिए आपके द्वारा उपयोग किया जाने वाला कोई भी tool इस version को support करना चाहिए। + +/// + +## TypeScript SDK बनाएँ { #create-a-typescript-sdk } + +आइए एक सरल FastAPI application से शुरू करें: + +{* ../../docs_src/generate_clients/tutorial001_py310.py hl[7:9,12:13,16:17,21] *} + +ध्यान दें कि *path operations* उन models को define करते हैं जिनका उपयोग वे request payload और response payload के लिए करते हैं, `Item` और `ResponseMessage` models का उपयोग करके। + +### API Docs { #api-docs } + +यदि आप `/docs` पर जाते हैं, तो आप देखेंगे कि इसमें requests में भेजे जाने और responses में प्राप्त होने वाले data के लिए **schemas** हैं: + + + +आप वे schemas देख सकते हैं क्योंकि उन्हें app में models के साथ declare किया गया था। + +वह जानकारी app के **OpenAPI schema** में उपलब्ध होती है, और फिर API docs में दिखाई जाती है। + +Models से वही जानकारी जो OpenAPI में शामिल होती है, **client code जेनरेट करने** के लिए उपयोग की जा सकती है। + +### Hey API { #hey-api } + +जब हमारे पास models के साथ एक FastAPI app हो, तो हम Hey API का उपयोग करके TypeScript client जेनरेट कर सकते हैं। ऐसा करने का सबसे तेज़ तरीका npx के माध्यम से है। + +```sh +npx @hey-api/openapi-ts -i http://localhost:8000/openapi.json -o src/client +``` + +यह `./src/client` में TypeScript SDK जेनरेट करेगा। + +आप उनकी website पर [`@hey-api/openapi-ts` install करना](https://heyapi.dev/openapi-ts/get-started) सीख सकते हैं और [generated output](https://heyapi.dev/openapi-ts/output) के बारे में पढ़ सकते हैं। + +### SDK का उपयोग करना { #using-the-sdk } + +अब आप client code को import करके उपयोग कर सकते हैं। यह कुछ ऐसा दिख सकता है, ध्यान दें कि आपको methods के लिए autocompletion मिलता है: + + + +आपको भेजने के लिए payload के लिए भी autocompletion मिलेगा: + + + +/// tip | सुझाव + +`name` और `price` के लिए autocompletion पर ध्यान दें, जिसे FastAPI application में, `Item` model में define किया गया था। + +/// + +आपके द्वारा भेजे जाने वाले data के लिए inline errors होंगे: + + + +Response object में भी autocompletion होगा: + + + +## Tags के साथ FastAPI App { #fastapi-app-with-tags } + +कई मामलों में, आपका FastAPI app बड़ा होगा, और आप शायद *path operations* के अलग-अलग groups को separate करने के लिए tags का उपयोग करेंगे। + +उदाहरण के लिए, आपके पास **items** के लिए एक section और **users** के लिए दूसरा section हो सकता है, और उन्हें tags द्वारा separate किया जा सकता है: + +{* ../../docs_src/generate_clients/tutorial002_py310.py hl[21,26,34] *} + +### Tags के साथ TypeScript Client जेनरेट करें { #generate-a-typescript-client-with-tags } + +यदि आप tags का उपयोग करने वाले FastAPI app के लिए client जेनरेट करते हैं, तो यह सामान्यतः client code को भी tags के आधार पर separate करेगा। + +इस तरह, आप client code के लिए चीज़ों को सही तरह से ordered और grouped रख पाएँगे: + + + +इस मामले में, आपके पास हैं: + +* `ItemsService` +* `UsersService` + +### Client Method Names { #client-method-names } + +अभी, जेनरेट किए गए method names जैसे `createItemItemsPost` बहुत साफ़ नहीं दिखते: + +```TypeScript +ItemsService.createItemItemsPost({name: "Plumbus", price: 5}) +``` + +...ऐसा इसलिए है क्योंकि client generator प्रत्येक *path operation* के लिए OpenAPI internal **operation ID** का उपयोग करता है। + +OpenAPI required करता है कि प्रत्येक operation ID सभी *path operations* में unique हो, इसलिए FastAPI उस operation ID को जेनरेट करने के लिए **function name**, **path**, और **HTTP method/operation** का उपयोग करता है, क्योंकि इस तरह यह सुनिश्चित कर सकता है कि operation IDs unique हैं। + +लेकिन मैं आगे आपको दिखाऊँगा कि इसे कैसे बेहतर बनाया जाए। 🤓 + +## Custom Operation IDs और बेहतर Method Names { #custom-operation-ids-and-better-method-names } + +आप इन operation IDs को **जेनरेट** करने के तरीके को **modify** कर सकते हैं ताकि वे clients में सरल हों और **सरल method names** हों। + +इस मामले में, आपको किसी दूसरे तरीके से सुनिश्चित करना होगा कि प्रत्येक operation ID **unique** हो। + +उदाहरण के लिए, आप सुनिश्चित कर सकते हैं कि प्रत्येक *path operation* में एक tag हो, और फिर **tag** और *path operation* **name** (function name) के आधार पर operation ID जेनरेट करें। + +### Custom Generate Unique ID Function { #custom-generate-unique-id-function } + +FastAPI प्रत्येक *path operation* के लिए एक **unique ID** का उपयोग करता है, जिसका उपयोग **operation ID** के लिए और requests या responses के लिए आवश्यक किसी भी custom models के names के लिए भी किया जाता है। + +आप उस function को customize कर सकते हैं। यह एक `APIRoute` लेता है और एक string output करता है। + +उदाहरण के लिए, यहाँ यह पहले tag (आपके पास शायद केवल एक tag होगा) और *path operation* name (function name) का उपयोग कर रहा है। + +फिर आप उस custom function को `generate_unique_id_function` parameter के रूप में **FastAPI** को pass कर सकते हैं: + +{* ../../docs_src/generate_clients/tutorial003_py310.py hl[6:7,10] *} + +### Custom Operation IDs के साथ TypeScript Client जेनरेट करें { #generate-a-typescript-client-with-custom-operation-ids } + +अब, यदि आप client को फिर से जेनरेट करते हैं, तो आप देखेंगे कि इसमें बेहतर method names हैं: + + + +जैसा कि आप देखते हैं, method names में अब tag और फिर function name है, अब वे URL path और HTTP operation की जानकारी शामिल नहीं करते। + +### Client Generator के लिए OpenAPI Specification को Preprocess करें { #preprocess-the-openapi-specification-for-the-client-generator } + +जेनरेट किए गए code में अभी भी कुछ **duplicated information** है। + +हम पहले से जानते हैं कि यह method **items** से संबंधित है क्योंकि वह शब्द `ItemsService` (tag से लिया गया) में है, लेकिन method name में भी tag name prefixed है। 😕 + +हम शायद इसे सामान्य रूप से OpenAPI के लिए रखना चाहेंगे, क्योंकि यह सुनिश्चित करेगा कि operation IDs **unique** हैं। + +लेकिन generated client के लिए, हम clients जेनरेट करने से ठीक पहले OpenAPI operation IDs को **modify** कर सकते हैं, ताकि उन method names को अधिक अच्छे और **cleaner** बनाया जा सके। + +हम OpenAPI JSON को `openapi.json` file में download कर सकते हैं और फिर इस तरह के script से **उस prefixed tag को remove** कर सकते हैं: + +{* ../../docs_src/generate_clients/tutorial004_py310.py *} + +//// tab | Node.js + +```Javascript +{!> ../../docs_src/generate_clients/tutorial004.js!} +``` + +//// + +इसके साथ, operation IDs को `items-get_items` जैसी चीज़ों से बदलकर सिर्फ़ `get_items` कर दिया जाएगा, इस तरह client generator सरल method names जेनरेट कर सकता है। + +### Preprocessed OpenAPI के साथ TypeScript Client जेनरेट करें { #generate-a-typescript-client-with-the-preprocessed-openapi } + +क्योंकि अंतिम परिणाम अब `openapi.json` file में है, आपको अपनी input location update करनी होगी: + +```sh +npx @hey-api/openapi-ts -i ./openapi.json -o src/client +``` + +नया client जेनरेट करने के बाद, अब आपके पास **clean method names** होंगे, सभी **autocompletion**, **inline errors**, आदि के साथ: + + + +## लाभ { #benefits } + +Automatically generated clients का उपयोग करते समय, आपको इन चीज़ों के लिए **autocompletion** मिलेगा: + +* Methods. +* body में request payloads, query parameters, आदि। +* Response payloads. + +आपके पास हर चीज़ के लिए **inline errors** भी होंगे। + +और जब भी आप backend code update करते हैं, और frontend को **regenerate** करते हैं, तो इसमें methods के रूप में कोई भी नए *path operations* उपलब्ध होंगे, पुराने remove हो जाएँगे, और कोई भी अन्य change generated code में reflect होगा। 🤓 + +इसका मतलब यह भी है कि यदि कुछ बदलता है, तो वह client code में अपने-आप **reflect** होगा। और यदि आप client को **build** करते हैं, तो यदि उपयोग किए गए data में कोई **mismatch** है, तो यह error देगा। + +इसलिए, आप development cycle में बहुत जल्दी **कई errors detect** कर लेंगे, बजाय इसके कि errors के production में आपके अंतिम users को दिखने का इंतज़ार करना पड़े और फिर यह debug करने की कोशिश करनी पड़े कि समस्या कहाँ है। ✨ diff --git a/docs/hi/docs/advanced/index.md b/docs/hi/docs/advanced/index.md new file mode 100644 index 000000000..d2ecb69dc --- /dev/null +++ b/docs/hi/docs/advanced/index.md @@ -0,0 +1,21 @@ +# उन्नत उपयोगकर्ता गाइड { #advanced-user-guide } + +## अतिरिक्त feature { #additional-features } + +मुख्य [ट्यूटोरियल - उपयोगकर्ता गाइड](../tutorial/index.md) आपको **FastAPI** के सभी मुख्य feature का अवलोकन देने के लिए पर्याप्त होना चाहिए। + +अगले sections में आप अन्य विकल्प, configurations, और अतिरिक्त feature देखेंगे। + +/// tip | सुझाव + +अगले sections **ज़रूरी नहीं कि "उन्नत"** हों। + +और संभव है कि आपके उपयोग के मामले के लिए समाधान उनमें से किसी एक में हो। + +/// + +## पहले ट्यूटोरियल पढ़ें { #read-the-tutorial-first } + +आप मुख्य [ट्यूटोरियल - उपयोगकर्ता गाइड](../tutorial/index.md) से मिली जानकारी के साथ भी **FastAPI** के ज़्यादातर feature का उपयोग कर सकते हैं। + +और अगले sections मानते हैं कि आपने इसे पहले ही पढ़ लिया है, और यह भी मानते हैं कि आप उन मुख्य विचारों को जानते हैं। diff --git a/docs/hi/docs/advanced/json-base64-bytes.md b/docs/hi/docs/advanced/json-base64-bytes.md new file mode 100644 index 000000000..c99ffbc7f --- /dev/null +++ b/docs/hi/docs/advanced/json-base64-bytes.md @@ -0,0 +1,63 @@ +# Base64 के रूप में Bytes वाला JSON { #json-with-bytes-as-base64 } + +अगर आपके app को JSON data receive और send करना है, लेकिन आपको उसमें binary data शामिल करना है, तो आप उसे base64 के रूप में encode कर सकते हैं। + +## Base64 बनाम Files { #base64-vs-files } + +पहले यह विचार करें कि क्या आप binary data upload करने के लिए [Request Files](../tutorial/request-files.md) और binary data भेजने के लिए [कस्टम Response - FileResponse](./custom-response.md#fileresponse) का उपयोग कर सकते हैं, बजाय इसके कि उसे JSON में encode किया जाए। + +JSON में केवल UTF-8 encoded strings हो सकती हैं, इसलिए उसमें raw bytes नहीं हो सकते। + +Base64 binary data को strings में encode कर सकता है, लेकिन ऐसा करने के लिए उसे मूल binary data की तुलना में अधिक characters का उपयोग करना पड़ता है, इसलिए यह सामान्य files की तुलना में आमतौर पर कम efficient होगा। + +Base64 का उपयोग केवल तभी करें जब आपको निश्चित रूप से JSON में binary data शामिल करना हो, और आप उसके लिए files का उपयोग नहीं कर सकते। + +## Pydantic `bytes` { #pydantic-bytes } + +आप `bytes` fields वाला एक Pydantic model declare कर सकते हैं, और फिर model config में `val_json_bytes` का उपयोग करके उसे बता सकते हैं कि input JSON data को *validate* करने के लिए base64 का उपयोग करे; उस validation के हिस्से के रूप में यह base64 string को bytes में decode करेगा। + +{* ../../docs_src/json_base64_bytes/tutorial001_py310.py ln[1:9,29:35] hl[9] *} + +अगर आप `/docs` देखें, तो वे दिखाएँगे कि field `data` base64 encoded bytes की अपेक्षा करता है: + +
+ +
+ +आप इस तरह का request भेज सकते हैं: + +```json +{ + "description": "Some data", + "data": "aGVsbG8=" +} +``` + +/// tip | सुझाव + +`aGVsbG8=` `hello` की base64 encoding है। + +/// + +और फिर Pydantic base64 string को decode करेगा और आपको model के `data` field में मूल bytes देगा। + +आपको इस तरह का response मिलेगा: + +```json +{ + "description": "Some data", + "content": "hello" +} +``` + +## Output Data के लिए Pydantic `bytes` { #pydantic-bytes-for-output-data } + +आप output data के लिए model config में `ser_json_bytes` के साथ `bytes` fields का भी उपयोग कर सकते हैं, और JSON response generate करते समय Pydantic bytes को base64 के रूप में *serialize* करेगा। + +{* ../../docs_src/json_base64_bytes/tutorial001_py310.py ln[1:2,12:16,29,38:41] hl[16] *} + +## Input और Output Data के लिए Pydantic `bytes` { #pydantic-bytes-for-input-and-output-data } + +और बेशक, JSON data receive और send करते समय आप उसी model को base64 उपयोग करने के लिए configure कर सकते हैं, ताकि input (*validate*) को `val_json_bytes` के साथ और output (*serialize*) को `ser_json_bytes` के साथ handle किया जा सके। + +{* ../../docs_src/json_base64_bytes/tutorial001_py310.py ln[1:2,19:26,29,44:46] hl[23:26] *} diff --git a/docs/hi/docs/advanced/middleware.md b/docs/hi/docs/advanced/middleware.md new file mode 100644 index 000000000..a920ba224 --- /dev/null +++ b/docs/hi/docs/advanced/middleware.md @@ -0,0 +1,97 @@ +# उन्नत Middleware { #advanced-middleware } + +मुख्य tutorial में आपने पढ़ा कि अपनी application में [Custom Middleware](../tutorial/middleware.md) कैसे जोड़ें। + +और फिर आपने यह भी पढ़ा कि [`CORSMiddleware` के साथ CORS](../tutorial/cors.md) को कैसे handle करें। + +इस section में हम देखेंगे कि अन्य middleware का उपयोग कैसे करें। + +## ASGI middleware जोड़ना { #adding-asgi-middlewares } + +क्योंकि **FastAPI** Starlette पर आधारित है और ASGI specification को implement करता है, आप कोई भी ASGI middleware उपयोग कर सकते हैं। + +किसी middleware को काम करने के लिए FastAPI या Starlette के लिए बना होना required नहीं है, जब तक वह ASGI spec का पालन करता है। + +सामान्यतः, ASGI middleware ऐसी classes होती हैं जो पहले argument के रूप में एक ASGI app प्राप्त करने की अपेक्षा करती हैं। + +इसलिए, third-party ASGI middleware के documentation में वे शायद आपको कुछ ऐसा करने के लिए कहेंगे: + +```Python +from unicorn import UnicornMiddleware + +app = SomeASGIApp() + +new_app = UnicornMiddleware(app, some_config="rainbow") +``` + +लेकिन FastAPI (वास्तव में Starlette) इसे करने का एक सरल तरीका प्रदान करता है, जो सुनिश्चित करता है कि internal middleware server errors को handle करें और custom exception handlers सही तरीके से काम करें। + +इसके लिए, आप `app.add_middleware()` का उपयोग करते हैं (जैसे CORS के उदाहरण में)। + +```Python +from fastapi import FastAPI +from unicorn import UnicornMiddleware + +app = FastAPI() + +app.add_middleware(UnicornMiddleware, some_config="rainbow") +``` + +`app.add_middleware()` पहले argument के रूप में एक middleware class प्राप्त करता है और middleware को pass किए जाने वाले कोई भी अतिरिक्त arguments भी प्राप्त करता है। + +## एकीकृत middleware { #integrated-middlewares } + +**FastAPI** common use cases के लिए कई middleware शामिल करता है, आगे हम देखेंगे कि उनका उपयोग कैसे करें। + +/// note | तकनीकी विवरण + +अगले उदाहरणों के लिए, आप `from starlette.middleware.something import SomethingMiddleware` भी उपयोग कर सकते हैं। + +**FastAPI** `fastapi.middleware` में कई middleware सिर्फ आपकी, developer की, सुविधा के लिए प्रदान करता है। लेकिन उपलब्ध अधिकांश middleware सीधे Starlette से आते हैं। + +/// + +## `HTTPSRedirectMiddleware` { #httpsredirectmiddleware } + +यह enforce करता है कि सभी incoming requests या तो `https` या `wss` हों। + +`http` या `ws` पर आने वाली कोई भी incoming request इसके बजाय secure scheme पर redirect कर दी जाएगी। + +{* ../../docs_src/advanced_middleware/tutorial001_py310.py hl[2,6] *} + +## `TrustedHostMiddleware` { #trustedhostmiddleware } + +यह enforce करता है कि सभी incoming requests में `Host` header सही तरीके से set हो, ताकि HTTP Host Header attacks से बचाव हो सके। + +{* ../../docs_src/advanced_middleware/tutorial002_py310.py hl[2,6:8] *} + +निम्नलिखित arguments supported हैं: + +* `allowed_hosts` - domain names की एक सूची जिन्हें hostnames के रूप में allow किया जाना चाहिए। `*.example.com` जैसे Wildcard domains subdomains को match करने के लिए supported हैं। किसी भी hostname को allow करने के लिए या तो `allowed_hosts=["*"]` उपयोग करें या middleware को omit करें। +* `www_redirect` - यदि True पर set किया गया है, तो allowed hosts के non-www versions पर आने वाली requests उनके www counterparts पर redirect कर दी जाएँगी। Default `True` है। + +यदि कोई incoming request सही तरीके से validate नहीं होती है तो `400` response भेजा जाएगा। + +## `GZipMiddleware` { #gzipmiddleware } + +ऐसी किसी भी request के लिए GZip responses handle करता है जिसमें `Accept-Encoding` header में `"gzip"` शामिल हो। + +middleware standard और streaming दोनों responses को handle करेगा। + +{* ../../docs_src/advanced_middleware/tutorial003_py310.py hl[2,6] *} + +निम्नलिखित arguments supported हैं: + +* `minimum_size` - इस minimum size से छोटे responses को GZip न करें, size bytes में है। Default `500` है। +* `compresslevel` - GZip compression के दौरान उपयोग किया जाता है। यह 1 से 9 तक की range में एक integer है। Default `9` है। कम value से compression तेज़ होता है लेकिन file sizes बड़ी होती हैं, जबकि अधिक value से compression धीमा होता है लेकिन file sizes छोटी होती हैं। + +## अन्य middleware { #other-middlewares } + +कई अन्य ASGI middleware हैं। + +उदाहरण के लिए: + +* [Uvicorn का `ProxyHeadersMiddleware`](https://github.com/encode/uvicorn/blob/master/uvicorn/middleware/proxy_headers.py) +* [MessagePack](https://github.com/florimondmanca/msgpack-asgi) + +अन्य उपलब्ध middleware देखने के लिए [Starlette के Middleware docs](https://www.starlette.dev/middleware/) और [ASGI Awesome List](https://github.com/florimondmanca/awesome-asgi) देखें। diff --git a/docs/hi/docs/advanced/openapi-callbacks.md b/docs/hi/docs/advanced/openapi-callbacks.md new file mode 100644 index 000000000..1cdbc823b --- /dev/null +++ b/docs/hi/docs/advanced/openapi-callbacks.md @@ -0,0 +1,186 @@ +# OpenAPI Callbacks { #openapi-callbacks } + +आप एक ऐसी API बना सकते हैं जिसमें एक *path operation* हो जो किसी और के द्वारा बनाई गई *external API* को request trigger कर सके (शायद वही developer जो आपकी API का *उपयोग* करेगा)। + +जब आपकी API app *external API* को call करती है, उस प्रक्रिया को "callback" कहा जाता है। क्योंकि external developer द्वारा लिखा गया software आपकी API को request भेजता है और फिर आपकी API *call back* करती है, यानी किसी *external API* को request भेजती है (जो शायद उसी developer द्वारा बनाई गई थी)। + +इस स्थिति में, आप यह document करना चाह सकते हैं कि वह external API कैसी *होनी चाहिए*। उसमें कौन-सा *path operation* होना चाहिए, उसे कौन-सा body expect करना चाहिए, उसे कौन-सा response लौटाना चाहिए, आदि। + +## Callbacks वाली एक app { #an-app-with-callbacks } + +आइए इसे एक उदाहरण के साथ देखते हैं। + +कल्पना करें कि आप एक ऐसी app develop करते हैं जो invoices बनाने देती है। + +इन invoices में एक `id`, `title` (optional), `customer`, और `total` होगा। + +आपकी API का user (एक external developer) आपकी API में POST request के साथ एक invoice बनाएगा। + +फिर आपकी API (कल्पना करें): + +* invoice को external developer के किसी customer को भेजेगी। +* पैसे collect करेगी। +* API user (external developer) को वापस एक notification भेजेगी। + * यह (*आपकी API* से) उस external developer द्वारा दी गई किसी *external API* को POST request भेजकर किया जाएगा (यही "callback" है)। + +## सामान्य **FastAPI** app { #the-normal-fastapi-app } + +Callback जोड़ने से पहले, पहले देखते हैं कि सामान्य API app कैसी दिखेगी। + +इसमें एक *path operation* होगा जो एक `Invoice` body receive करेगा, और एक query parameter `callback_url` होगा जिसमें callback के लिए URL होगा। + +यह हिस्सा काफ़ी सामान्य है, अधिकतर code शायद आपको पहले से परिचित होगा: + +{* ../../docs_src/openapi_callbacks/tutorial001_py310.py hl[7:11,34:51] *} + +/// tip | सुझाव + +`callback_url` query parameter एक Pydantic [Url](https://docs.pydantic.dev/latest/api/networks/) type का उपयोग करता है। + +/// + +केवल नई चीज़ है *path operation decorator* के argument के रूप में `callbacks=invoices_callback_router.routes`। आगे हम देखेंगे कि यह क्या है। + +## Callback को document करना { #documenting-the-callback } + +वास्तविक callback code आपकी अपनी API app पर बहुत अधिक निर्भर करेगा। + +और यह एक app से दूसरी app में काफ़ी अलग हो सकता है। + +यह code की सिर्फ़ एक या दो lines भी हो सकती हैं, जैसे: + +```Python +callback_url = "https://example.com/api/v1/invoices/events/" +httpx.post(callback_url, json={"description": "Invoice paid", "paid": True}) +``` + +लेकिन संभवतः callback का सबसे महत्वपूर्ण हिस्सा यह सुनिश्चित करना है कि आपका API user (external developer) *external API* को सही तरह से implement करे, उस data के अनुसार जिसे *आपकी API* callback के request body में भेजने वाली है, आदि। + +तो, अब हम वह code जोड़ेंगे जो document करेगा कि *आपकी API* से callback receive करने के लिए वह *external API* कैसी दिखनी चाहिए। + +यह documentation आपकी API में `/docs` पर Swagger UI में दिखाई देगी, और यह external developers को बताएगी कि *external API* कैसे बनानी है। + +यह उदाहरण callback को स्वयं implement नहीं करता (वह केवल code की एक line हो सकती है), केवल documentation वाला हिस्सा करता है। + +/// tip | सुझाव + +वास्तविक callback सिर्फ़ एक HTTP request है। + +Callback को स्वयं implement करते समय, आप [HTTPX](https://www.python-httpx.org) या [Requests](https://requests.readthedocs.io/) जैसी किसी चीज़ का उपयोग कर सकते हैं। + +/// + +## Callback documentation code लिखें { #write-the-callback-documentation-code } + +यह code आपकी app में execute नहीं होगा, हमें इसकी आवश्यकता केवल यह *document* करने के लिए है कि वह *external API* कैसी दिखनी चाहिए। + +लेकिन, आप पहले से जानते हैं कि **FastAPI** के साथ किसी API के लिए automatic documentation आसानी से कैसे बनाई जाती है। + +इसलिए हम उसी ज्ञान का उपयोग करके document करेंगे कि *external API* कैसी दिखनी चाहिए... उन *path operation(s)* को बनाकर जिन्हें external API को implement करना चाहिए (जिन्हें आपकी API call करेगी)। + +/// tip | सुझाव + +Callback को document करने के लिए code लिखते समय, यह कल्पना करना उपयोगी हो सकता है कि आप वही *external developer* हैं। और इस समय आप *external API* implement कर रहे हैं, *अपनी API* नहीं। + +इस दृष्टिकोण को अस्थायी रूप से अपनाना (*external developer* का) आपको यह अधिक स्पष्ट महसूस कराने में मदद कर सकता है कि उस *external API* के लिए parameters, body के लिए Pydantic model, response के लिए model, आदि कहाँ रखने हैं। + +/// + +### Callback `APIRouter` बनाएँ { #create-a-callback-apirouter } + +पहले एक नया `APIRouter` बनाएँ जिसमें एक या अधिक callbacks होंगे। + +{* ../../docs_src/openapi_callbacks/tutorial001_py310.py hl[1,23] *} + +### Callback *path operation* बनाएँ { #create-the-callback-path-operation } + +Callback *path operation* बनाने के लिए वही `APIRouter` उपयोग करें जो आपने ऊपर बनाया था। + +यह बिल्कुल सामान्य FastAPI *path operation* जैसा दिखना चाहिए: + +* इसमें शायद उस body की declaration होनी चाहिए जिसे इसे receive करना है, जैसे `body: InvoiceEvent`। +* और इसमें उस response की declaration भी हो सकती है जिसे इसे लौटाना चाहिए, जैसे `response_model=InvoiceEventReceived`। + +{* ../../docs_src/openapi_callbacks/tutorial001_py310.py hl[14:16,19:20,26:30] *} + +सामान्य *path operation* से 2 मुख्य अंतर हैं: + +* इसमें कोई वास्तविक code होना required नहीं है, क्योंकि आपकी app इस code को कभी call नहीं करेगी। इसका उपयोग केवल *external API* को document करने के लिए किया जाता है। इसलिए, function में केवल `pass` हो सकता है। +* *path* में एक [OpenAPI 3 expression](https://github.com/OAI/OpenAPI-Specification/blob/master/versions/3.1.0.md#key-expression) (नीचे और देखें) हो सकता है, जहाँ यह *आपकी API* को भेजी गई original request के parameters और parts के साथ variables का उपयोग कर सकता है। + +### Callback path expression { #the-callback-path-expression } + +Callback *path* में एक [OpenAPI 3 expression](https://github.com/OAI/OpenAPI-Specification/blob/master/versions/3.1.0.md#key-expression) हो सकता है जो *आपकी API* को भेजी गई original request के parts शामिल कर सकता है। + +इस case में, यह `str` है: + +```Python +"{$callback_url}/invoices/{$request.body.id}" +``` + +तो, यदि आपका API user (external developer) *आपकी API* को request भेजता है: + +``` +https://yourapi.com/invoices/?callback_url=https://www.external.org/events +``` + +इस JSON body के साथ: + +```JSON +{ + "id": "2expen51ve", + "customer": "Mr. Richie Rich", + "total": "9999" +} +``` + +तो *आपकी API* invoice को process करेगी, और बाद में किसी समय, `callback_url` (*external API*) को callback request भेजेगी: + +``` +https://www.external.org/events/invoices/2expen51ve +``` + +ऐसे JSON body के साथ जिसमें कुछ इस तरह होगा: + +```JSON +{ + "description": "Payment celebration", + "paid": true +} +``` + +और यह उस *external API* से इस तरह के JSON body वाले response की अपेक्षा करेगी: + +```JSON +{ + "ok": true +} +``` + +/// tip | सुझाव + +ध्यान दें कि उपयोग किए गए callback URL में `callback_url` (`https://www.external.org/events`) में query parameter के रूप में प्राप्त URL और JSON body के अंदर से invoice `id` (`2expen51ve`) दोनों शामिल हैं। + +/// + +### Callback router जोड़ें { #add-the-callback-router } + +इस समय आपके पास ऊपर बनाए गए callback router में required *callback path operation(s)* हैं (वे operation जिन्हें *external developer* को *external API* में implement करना चाहिए)। + +अब *आपकी API के path operation decorator* में parameter `callbacks` का उपयोग करके उस callback router से attribute `.routes` pass करें: + +{* ../../docs_src/openapi_callbacks/tutorial001_py310.py hl[33] *} + +/// tip | सुझाव + +ध्यान दें कि आप router स्वयं (`invoices_callback_router`) को `callbacks=` में pass नहीं कर रहे हैं, बल्कि उसकी `.routes` को pass कर रहे हैं, जैसे `invoices_callback_router.routes`। FastAPI उन routes का उपयोग callback OpenAPI documentation generate करने के लिए करेगा। + +/// + +### Docs देखें { #check-the-docs } + +अब आप अपनी app start कर सकते हैं और [http://127.0.0.1:8000/docs](http://127.0.0.1:8000/docs) पर जा सकते हैं। + +आपको अपनी docs में अपने *path operation* के लिए एक "Callbacks" section दिखेगा, जो दिखाता है कि *external API* कैसी दिखनी चाहिए: + + diff --git a/docs/hi/docs/advanced/openapi-webhooks.md b/docs/hi/docs/advanced/openapi-webhooks.md new file mode 100644 index 000000000..65cafd0d6 --- /dev/null +++ b/docs/hi/docs/advanced/openapi-webhooks.md @@ -0,0 +1,55 @@ +# OpenAPI Webhooks { #openapi-webhooks } + +ऐसे मामले होते हैं जहाँ आप अपने API **users** को बताना चाहते हैं कि आपकी app कुछ data के साथ (एक request भेजते हुए) *उनकी* app को कॉल कर सकती है, सामान्यतः किसी प्रकार के **event** की **सूचना** देने के लिए। + +इसका मतलब है कि आपके users द्वारा आपकी API को requests भेजने की सामान्य प्रक्रिया के बजाय, **आपकी API** (या आपकी app) **उनके system को requests भेज** सकती है (उनकी API, उनकी app को)। + +इसे सामान्यतः **webhook** कहा जाता है। + +## Webhooks के चरण { #webhooks-steps } + +सामान्यतः प्रक्रिया यह होती है कि **आप अपने code में define करते हैं** कि आप कौन-सा message भेजेंगे, यानी **request का body**। + +आप यह भी किसी तरीके से define करते हैं कि आपकी app किन **क्षणों** पर वे requests या events भेजेगी। + +और **आपके users** किसी तरीके से (उदाहरण के लिए कहीं किसी web dashboard में) वह **URL** define करते हैं जहाँ आपकी app को वे requests भेजनी चाहिए। + +Webhooks के लिए URLs को register करने की सारी **logic** और वास्तव में उन requests को भेजने का code आपके ऊपर है। आप इसे **अपने खुद के code** में जैसे चाहें वैसे लिखते हैं। + +## **FastAPI** और OpenAPI के साथ webhooks का दस्तावेज़ीकरण { #documenting-webhooks-with-fastapi-and-openapi } + +**FastAPI** के साथ, OpenAPI का उपयोग करते हुए, आप इन webhooks के नाम, आपकी app द्वारा भेजे जा सकने वाले HTTP operations के प्रकार (जैसे `POST`, `PUT`, आदि) और आपकी app द्वारा भेजे जाने वाले request **bodies** define कर सकते हैं। + +इससे आपके users के लिए आपकी **webhook** requests प्राप्त करने के लिए **अपनी APIs implement करना** बहुत आसान हो सकता है, वे शायद अपने कुछ API code को autogenerate भी कर सकें। + +/// note | नोट + +Webhooks OpenAPI 3.1.0 और उससे ऊपर में उपलब्ध हैं, और FastAPI `0.99.0` और उससे ऊपर द्वारा समर्थित हैं। + +/// + +## Webhooks वाली app { #an-app-with-webhooks } + +जब आप एक **FastAPI** application बनाते हैं, तो एक `webhooks` attribute होता है जिसका उपयोग आप *webhooks* define करने के लिए कर सकते हैं, उसी तरह जैसे आप *path operations* define करते हैं, उदाहरण के लिए `@app.webhooks.post()` के साथ। + +{* ../../docs_src/openapi_webhooks/tutorial001_py310.py hl[9:12,15:20] *} + +आप जिन webhooks को define करते हैं वे **OpenAPI** schema और automatic **docs UI** में आ जाएँगे। + +/// note | नोट + +`app.webhooks` object वास्तव में सिर्फ़ एक `APIRouter` है, वही type जिसका उपयोग आप अपनी app को multiple files के साथ structure करते समय करेंगे। + +/// + +ध्यान दें कि webhooks के साथ आप वास्तव में कोई *path* declare नहीं कर रहे हैं (जैसे `/items/`), वहाँ आप जो text pass करते हैं वह केवल webhook का एक **identifier** है (event का नाम), उदाहरण के लिए `@app.webhooks.post("new-subscription")` में, webhook का नाम `new-subscription` है। + +ऐसा इसलिए है क्योंकि उम्मीद की जाती है कि **आपके users** उस वास्तविक **URL path** को किसी और तरीके से define करेंगे जहाँ वे webhook request प्राप्त करना चाहते हैं (जैसे कोई web dashboard)। + +### Docs देखें { #check-the-docs } + +अब आप अपनी app start कर सकते हैं और [http://127.0.0.1:8000/docs](http://127.0.0.1:8000/docs) पर जा सकते हैं। + +आप देखेंगे कि आपके docs में सामान्य *path operations* हैं और अब कुछ **webhooks** भी हैं: + + diff --git a/docs/hi/docs/advanced/path-operation-advanced-configuration.md b/docs/hi/docs/advanced/path-operation-advanced-configuration.md new file mode 100644 index 000000000..1636b4f0e --- /dev/null +++ b/docs/hi/docs/advanced/path-operation-advanced-configuration.md @@ -0,0 +1,166 @@ +# Path Operation की उन्नत Configuration { #path-operation-advanced-configuration } + +## OpenAPI operationId { #openapi-operationid } + +/// warning | चेतावनी + +अगर आप OpenAPI में "expert" नहीं हैं, तो शायद आपको इसकी ज़रूरत नहीं है। + +/// + +आप अपने *path operation* में उपयोग किए जाने वाले OpenAPI `operationId` को parameter `operation_id` के साथ सेट कर सकते हैं। + +आपको यह सुनिश्चित करना होगा कि यह प्रत्येक operation के लिए unique हो। + +{* ../../docs_src/path_operation_advanced_configuration/tutorial001_py310.py hl[6] *} + +### *path operation function* के नाम को operationId के रूप में उपयोग करना { #using-the-path-operation-function-name-as-the-operationid } + +अगर आप अपने APIs के function नामों को `operationId`s के रूप में उपयोग करना चाहते हैं, तो आप `FastAPI` को एक custom `generate_unique_id_function` पास कर सकते हैं। + +यह function प्रत्येक `APIRoute` प्राप्त करता है और उस path operation के लिए उपयोग करने वाला `operationId` return करता है। + +{* ../../docs_src/path_operation_advanced_configuration/tutorial002_py310.py hl[2,5:6,9] *} + +/// warning | चेतावनी + +अगर आप ऐसा करते हैं, तो आपको यह सुनिश्चित करना होगा कि आपके प्रत्येक *path operation functions* का नाम unique हो। + +भले ही वे अलग-अलग modules (Python files) में हों। + +/// + +## OpenAPI से बाहर रखना { #exclude-from-openapi } + +किसी *path operation* को generated OpenAPI schema से बाहर रखने के लिए (और इस प्रकार, automatic documentation systems से भी), parameter `include_in_schema` का उपयोग करें और इसे `False` पर सेट करें: + +{* ../../docs_src/path_operation_advanced_configuration/tutorial003_py310.py hl[6] *} + +## Docstring से उन्नत description { #advanced-description-from-docstring } + +आप OpenAPI के लिए किसी *path operation function* की docstring से उपयोग की जाने वाली lines को सीमित कर सकते हैं। + +एक `\f` (एक escaped "form feed" character) जोड़ने से **FastAPI** इस बिंदु पर OpenAPI के लिए उपयोग किए जाने वाले output को truncate कर देता है। + +यह documentation में नहीं दिखेगा, लेकिन अन्य tools (जैसे Sphinx) बाकी हिस्से का उपयोग कर सकेंगे। + +{* ../../docs_src/path_operation_advanced_configuration/tutorial004_py310.py hl[17:27] *} + +## अतिरिक्त Responses { #additional-responses } + +आपने शायद देखा होगा कि किसी *path operation* के लिए `response_model` और `status_code` कैसे declare किए जाते हैं। + +यह किसी *path operation* के मुख्य response के बारे में metadata define करता है। + +आप उनके models, status codes आदि के साथ अतिरिक्त responses भी declare कर सकते हैं। + +इसके बारे में documentation में यहाँ एक पूरा chapter है, आप इसे [OpenAPI में अतिरिक्त Responses](additional-responses.md) पर पढ़ सकते हैं। + +## OpenAPI Extra { #openapi-extra } + +जब आप अपने application में कोई *path operation* declare करते हैं, तो **FastAPI** उस *path operation* के बारे में relevant metadata को automatically generate करता है, जिसे OpenAPI schema में शामिल किया जाता है। + +/// note | तकनीकी विवरण + +OpenAPI specification में इसे [Operation Object](https://github.com/OAI/OpenAPI-Specification/blob/main/versions/3.0.3.md#operation-object) कहा जाता है। + +/// + +इसमें *path operation* के बारे में सारी जानकारी होती है और इसका उपयोग automatic documentation generate करने के लिए किया जाता है। + +इसमें `tags`, `parameters`, `requestBody`, `responses` आदि शामिल होते हैं। + +यह *path operation*-specific OpenAPI schema सामान्यतः **FastAPI** द्वारा automatically generate किया जाता है, लेकिन आप इसे extend भी कर सकते हैं। + +/// tip | सुझाव + +यह एक low level extension point है। + +अगर आपको केवल अतिरिक्त responses declare करने की ज़रूरत है, तो ऐसा करने का एक अधिक सुविधाजनक तरीका [OpenAPI में अतिरिक्त Responses](additional-responses.md) के साथ है। + +/// + +आप parameter `openapi_extra` का उपयोग करके किसी *path operation* के लिए OpenAPI schema को extend कर सकते हैं। + +### OpenAPI Extensions { #openapi-extensions } + +यह `openapi_extra` उपयोगी हो सकता है, उदाहरण के लिए, [OpenAPI Extensions](https://github.com/OAI/OpenAPI-Specification/blob/main/versions/3.0.3.md#specificationExtensions) declare करने के लिए: + +{* ../../docs_src/path_operation_advanced_configuration/tutorial005_py310.py hl[6] *} + +अगर आप automatic API docs खोलते हैं, तो आपका extension specific *path operation* के नीचे दिखाई देगा। + + + +और अगर आप resulting OpenAPI (आपकी API में `/openapi.json` पर) देखते हैं, तो आपको अपना extension specific *path operation* के हिस्से के रूप में भी दिखाई देगा: + +```JSON hl_lines="22" +{ + "openapi": "3.1.0", + "info": { + "title": "FastAPI", + "version": "0.1.0" + }, + "paths": { + "/items/": { + "get": { + "summary": "Read Items", + "operationId": "read_items_items__get", + "responses": { + "200": { + "description": "Successful Response", + "content": { + "application/json": { + "schema": {} + } + } + } + }, + "x-aperture-labs-portal": "blue" + } + } + } +} +``` + +### Custom OpenAPI *path operation* schema { #custom-openapi-path-operation-schema } + +`openapi_extra` में मौजूद dictionary को *path operation* के लिए automatically generated OpenAPI schema के साथ deeply merge किया जाएगा। + +तो, आप automatically generated schema में अतिरिक्त data जोड़ सकते हैं। + +उदाहरण के लिए, आप FastAPI की Pydantic के साथ automatic features का उपयोग किए बिना, अपने code से request को read और validate करने का निर्णय ले सकते हैं, लेकिन फिर भी आप OpenAPI schema में request को define करना चाह सकते हैं। + +आप यह `openapi_extra` के साथ कर सकते हैं: + +{* ../../docs_src/path_operation_advanced_configuration/tutorial006_py310.py hl[19:36, 39:40] *} + +इस उदाहरण में, हमने कोई Pydantic model declare नहीं किया। वास्तव में, request body को JSON के रूप में parsed भी नहीं किया गया है, इसे सीधे `bytes` के रूप में read किया गया है, और function `magic_data_reader()` किसी तरीके से इसे parse करने का ज़िम्मेदार होगा। + +फिर भी, हम request body के लिए expected schema declare कर सकते हैं। + +### Custom OpenAPI content type { #custom-openapi-content-type } + +इसी trick का उपयोग करके, आप JSON Schema define करने के लिए Pydantic model का उपयोग कर सकते हैं, जिसे फिर *path operation* के लिए custom OpenAPI schema section में शामिल किया जाता है। + +और आप ऐसा तब भी कर सकते हैं जब request में data type JSON न हो। + +उदाहरण के लिए, इस application में हम Pydantic models से JSON Schema निकालने के लिए FastAPI की integrated functionality या JSON के लिए automatic validation का उपयोग नहीं करते हैं। वास्तव में, हम request content type को JSON नहीं, बल्कि YAML के रूप में declare कर रहे हैं: + +{* ../../docs_src/path_operation_advanced_configuration/tutorial007_py310.py hl[15:20, 22] *} + +फिर भी, हालांकि हम default integrated functionality का उपयोग नहीं कर रहे हैं, हम अभी भी उस data के लिए JSON Schema manually generate करने के लिए Pydantic model का उपयोग कर रहे हैं जिसे हम YAML में receive करना चाहते हैं। + +फिर हम request को सीधे उपयोग करते हैं, और body को `bytes` के रूप में extract करते हैं। इसका मतलब है कि FastAPI request payload को JSON के रूप में parse करने की कोशिश भी नहीं करेगा। + +और फिर अपने code में, हम उस YAML content को सीधे parse करते हैं, और फिर हम YAML content को validate करने के लिए फिर से उसी Pydantic model का उपयोग कर रहे हैं: + +{* ../../docs_src/path_operation_advanced_configuration/tutorial007_py310.py hl[24:31] *} + +/// tip | सुझाव + +यहाँ हम उसी Pydantic model को reuse करते हैं। + +लेकिन इसी तरह, हम इसे किसी और तरीके से भी validate कर सकते थे। + +/// diff --git a/docs/hi/docs/advanced/response-change-status-code.md b/docs/hi/docs/advanced/response-change-status-code.md new file mode 100644 index 000000000..3ef2f1b3f --- /dev/null +++ b/docs/hi/docs/advanced/response-change-status-code.md @@ -0,0 +1,31 @@ +# Response - Status Code बदलें { #response-change-status-code } + +आपने शायद पहले पढ़ा होगा कि आप एक default [Response Status Code](../tutorial/response-status-code.md) सेट कर सकते हैं। + +लेकिन कुछ मामलों में आपको default से अलग status code लौटाना पड़ता है। + +## उपयोग का मामला { #use-case } + +उदाहरण के लिए, कल्पना करें कि आप default रूप से "OK" `200` का HTTP status code लौटाना चाहते हैं। + +लेकिन अगर data मौजूद नहीं था, तो आप उसे बनाना चाहते हैं, और "CREATED" `201` का HTTP status code लौटाना चाहते हैं। + +लेकिन फिर भी आप `response_model` के साथ लौटाए गए data को filter और convert कर पाने में सक्षम रहना चाहते हैं। + +ऐसे मामलों के लिए, आप `Response` parameter का उपयोग कर सकते हैं। + +## `Response` parameter का उपयोग करें { #use-a-response-parameter } + +आप अपनी *path operation function* में `Response` type का parameter घोषित कर सकते हैं (जैसा कि आप cookies और headers के लिए कर सकते हैं)। + +और फिर आप उस *temporary* response object में `status_code` सेट कर सकते हैं। + +{* ../../docs_src/response_change_status_code/tutorial001_py310.py hl[1,9,12] *} + +और फिर आप अपनी ज़रूरत का कोई भी object लौटा सकते हैं, जैसा कि आप सामान्य रूप से करते हैं (एक `dict`, एक database model, आदि)। + +और अगर आपने `response_model` घोषित किया है, तो यह आपके लौटाए गए object को filter और convert करने के लिए अभी भी उपयोग किया जाएगा। + +**FastAPI** उस *temporary* response का उपयोग status code (साथ ही cookies और headers) निकालने के लिए करेगा, और उन्हें अंतिम response में डाल देगा जिसमें आपके द्वारा लौटाया गया value होगा, जिसे किसी भी `response_model` द्वारा filter किया गया होगा। + +आप dependencies में भी `Response` parameter घोषित कर सकते हैं, और उनमें status code सेट कर सकते हैं। लेकिन ध्यान रखें कि आख़िरी बार जो सेट किया जाएगा, वही प्रभावी होगा। diff --git a/docs/hi/docs/advanced/response-cookies.md b/docs/hi/docs/advanced/response-cookies.md new file mode 100644 index 000000000..ccd65dc0f --- /dev/null +++ b/docs/hi/docs/advanced/response-cookies.md @@ -0,0 +1,51 @@ +# Response Cookies { #response-cookies } + +## `Response` parameter का उपयोग करें { #use-a-response-parameter } + +आप अपने *path operation function* में `Response` प्रकार का parameter घोषित कर सकते हैं। + +और फिर आप उस *temporary* response object में cookies set कर सकते हैं। + +{* ../../docs_src/response_cookies/tutorial002_py310.py hl[1, 8:9] *} + +और फिर आप अपनी ज़रूरत का कोई भी object return कर सकते हैं, जैसा कि आप सामान्य रूप से करते हैं (एक `dict`, database model, आदि)। + +और अगर आपने `response_model` घोषित किया है, तो आपके द्वारा return किए गए object को filter और convert करने के लिए उसका अभी भी उपयोग किया जाएगा। + +**FastAPI** उस *temporary* response का उपयोग cookies (साथ ही headers और status code) निकालने के लिए करेगा, और उन्हें final response में डाल देगा जिसमें आपके द्वारा return किया गया value होगा, किसी भी `response_model` द्वारा filter किया हुआ। + +आप dependencies में भी `Response` parameter घोषित कर सकते हैं, और उनमें cookies (और headers) set कर सकते हैं। + +## सीधे `Response` return करें { #return-a-response-directly } + +आप अपने code में सीधे `Response` return करते समय भी cookies बना सकते हैं। + +ऐसा करने के लिए, आप [सीधे Response Return करें](response-directly.md) में बताए अनुसार एक response बना सकते हैं। + +फिर उसमें Cookies set करें, और फिर उसे return करें: + +{* ../../docs_src/response_cookies/tutorial001_py310.py hl[10:12] *} + +/// tip | सुझाव + +ध्यान रखें कि अगर आप `Response` parameter का उपयोग करने के बजाय सीधे response return करते हैं, तो FastAPI उसे सीधे return करेगा। + +इसलिए, आपको यह सुनिश्चित करना होगा कि आपका data सही प्रकार का है। उदाहरण के लिए, अगर आप `JSONResponse` return कर रहे हैं, तो वह JSON के साथ compatible हो। + +और यह भी कि आप कोई ऐसा data नहीं भेज रहे हैं जिसे `response_model` द्वारा filter किया जाना चाहिए था। + +/// + +### अधिक जानकारी { #more-info } + +/// note | तकनीकी विवरण + +आप `from starlette.responses import Response` या `from starlette.responses import JSONResponse` का भी उपयोग कर सकते हैं। + +**FastAPI** आपकी सुविधा के लिए, developer के रूप में, वही `starlette.responses` `fastapi.responses` के रूप में प्रदान करता है। लेकिन उपलब्ध अधिकांश responses सीधे Starlette से आते हैं। + +और क्योंकि `Response` का उपयोग अक्सर headers और cookies set करने के लिए किया जा सकता है, **FastAPI** इसे `fastapi.Response` पर भी प्रदान करता है। + +/// + +सभी उपलब्ध parameters और options देखने के लिए, [Starlette में documentation](https://www.starlette.dev/responses/#set-cookie) देखें। diff --git a/docs/hi/docs/advanced/response-directly.md b/docs/hi/docs/advanced/response-directly.md new file mode 100644 index 000000000..1f91a875e --- /dev/null +++ b/docs/hi/docs/advanced/response-directly.md @@ -0,0 +1,83 @@ +# सीधे एक Response लौटाएँ { #return-a-response-directly } + +जब आप **FastAPI** *path operation* बनाते हैं, तो सामान्यतः आप उससे कोई भी data लौटा सकते हैं: एक `dict`, एक `list`, एक Pydantic model, एक database model, आदि। + +अगर आप [Response Model](../tutorial/response-model.md) declare करते हैं, तो FastAPI Pydantic का उपयोग करके data को JSON में serialize करने के लिए उसका उपयोग करेगा। + +अगर आप response model declare नहीं करते, तो FastAPI [JSON Compatible Encoder](../tutorial/encoder.md) में समझाए गए `jsonable_encoder` का उपयोग करेगा और उसे एक `JSONResponse` में रखेगा। + +आप सीधे एक `JSONResponse` भी बना सकते हैं और उसे लौटा सकते हैं। + +/// tip | सुझाव + +आम तौर पर सीधे `JSONResponse` लौटाने की तुलना में [Response Model](../tutorial/response-model.md) का उपयोग करने पर performance काफी बेहतर होगी, क्योंकि उस तरीके से यह Rust में Pydantic का उपयोग करके data serialize करता है। + +/// + +## एक `Response` लौटाएँ { #return-a-response } + +आप एक `Response` या उसकी कोई भी sub-class लौटा सकते हैं। + +/// note | नोट + +`JSONResponse` खुद `Response` की एक sub-class है। + +/// + +और जब आप एक `Response` लौटाते हैं, तो **FastAPI** उसे सीधे pass कर देगा। + +यह Pydantic models के साथ कोई data conversion नहीं करेगा, contents को किसी भी type में convert नहीं करेगा, आदि। + +यह आपको बहुत अधिक **flexibility** देता है। आप कोई भी data type लौटा सकते हैं, किसी भी data declaration या validation को override कर सकते हैं, आदि। + +यह आपको बहुत अधिक **responsibility** भी देता है। आपको यह सुनिश्चित करना होगा कि आप जो data लौटा रहे हैं वह सही है, सही format में है, वह serialize किया जा सकता है, आदि। + +## `Response` में `jsonable_encoder` का उपयोग करना { #using-the-jsonable-encoder-in-a-response } + +क्योंकि **FastAPI** आपके लौटाए गए `Response` में कोई बदलाव नहीं करता, आपको सुनिश्चित करना होगा कि उसके contents इसके लिए तैयार हैं। + +उदाहरण के लिए, आप किसी Pydantic model को पहले `dict` में convert किए बिना `JSONResponse` में नहीं रख सकते, जिसमें सभी data types (जैसे `datetime`, `UUID`, आदि) JSON-compatible types में convert किए गए हों। + +ऐसे मामलों के लिए, response को pass करने से पहले आप अपने data को convert करने के लिए `jsonable_encoder` का उपयोग कर सकते हैं: + +{* ../../docs_src/response_directly/tutorial001_py310.py hl[5:6,20:21] *} + +/// note | तकनीकी विवरण + +आप `from starlette.responses import JSONResponse` का भी उपयोग कर सकते हैं। + +**FastAPI** आपकी सुविधा के लिए, developer के रूप में, वही `starlette.responses` `fastapi.responses` के रूप में उपलब्ध कराता है। लेकिन उपलब्ध अधिकांश responses सीधे Starlette से आते हैं। + +/// + +## custom `Response` लौटाना { #returning-a-custom-response } + +ऊपर दिया गया उदाहरण वे सभी हिस्से दिखाता है जिनकी आपको जरूरत है, लेकिन यह अभी बहुत उपयोगी नहीं है, क्योंकि आप सीधे `item` लौटा सकते थे, और **FastAPI** उसे आपके लिए `JSONResponse` में रख देता, उसे `dict` में convert करता, आदि। यह सब default रूप से होता है। + +अब, देखते हैं कि आप इसका उपयोग custom response लौटाने के लिए कैसे कर सकते हैं। + +मान लें कि आप एक [XML](https://en.wikipedia.org/wiki/XML) response लौटाना चाहते हैं। + +आप अपना XML content एक string में रख सकते हैं, उसे `Response` में रख सकते हैं, और उसे लौटा सकते हैं: + +{* ../../docs_src/response_directly/tutorial002_py310.py hl[1,18] *} + +## Response Model कैसे काम करता है { #how-a-response-model-works } + +जब आप किसी path operation में [Response Model - Return Type](../tutorial/response-model.md) declare करते हैं, तो **FastAPI** Pydantic का उपयोग करके data को JSON में serialize करने के लिए उसका उपयोग करेगा। + +{* ../../docs_src/response_model/tutorial001_01_py310.py hl[16,21] *} + +क्योंकि यह Rust side पर होगा, performance regular Python और `JSONResponse` class के साथ किए जाने की तुलना में काफी बेहतर होगी। + +`response_model` या return type का उपयोग करते समय, FastAPI data को convert करने के लिए `jsonable_encoder` का उपयोग नहीं करेगा (जो धीमा होता), और न ही `JSONResponse` class का उपयोग करेगा। + +इसके बजाय यह response model (या return type) का उपयोग करके Pydantic के साथ generate किए गए JSON bytes लेता है और JSON के लिए सही media type (`application/json`) के साथ सीधे एक `Response` लौटाता है। + +## नोट्स { #notes } + +जब आप सीधे एक `Response` लौटाते हैं, तो उसका data अपने-आप validate, convert (serialize), या document नहीं किया जाता। + +लेकिन आप फिर भी उसे [OpenAPI में अतिरिक्त Responses](additional-responses.md) में बताए अनुसार document कर सकते हैं। + +बाद के sections में आप देख सकते हैं कि automatic data conversion, documentation, आदि रखते हुए इन custom `Response`s का उपयोग/declare कैसे करें। diff --git a/docs/hi/docs/advanced/response-headers.md b/docs/hi/docs/advanced/response-headers.md new file mode 100644 index 000000000..9d62e2f47 --- /dev/null +++ b/docs/hi/docs/advanced/response-headers.md @@ -0,0 +1,41 @@ +# Response Headers { #response-headers } + +## `Response` parameter का उपयोग करें { #use-a-response-parameter } + +आप अपने *path operation function* में `Response` प्रकार का parameter घोषित कर सकते हैं (जैसा कि आप cookies के लिए कर सकते हैं)। + +और फिर आप उस *अस्थायी* response object में headers सेट कर सकते हैं। + +{* ../../docs_src/response_headers/tutorial002_py310.py hl[1, 7:8] *} + +और फिर आप अपनी ज़रूरत का कोई भी object return कर सकते हैं, जैसा कि आप सामान्य रूप से करते हैं (एक `dict`, database model, आदि)। + +और अगर आपने `response_model` घोषित किया है, तो वह अब भी आपके return किए गए object को filter और convert करने के लिए उपयोग किया जाएगा। + +**FastAPI** headers (साथ ही cookies और status code) निकालने के लिए उस *अस्थायी* response का उपयोग करेगा, और उन्हें अंतिम response में डाल देगा जिसमें आपके द्वारा return किया गया value होता है, जिसे किसी भी `response_model` द्वारा filter किया गया होता है। + +आप dependencies में भी `Response` parameter घोषित कर सकते हैं, और उनमें headers (और cookies) सेट कर सकते हैं। + +## सीधे `Response` return करें { #return-a-response-directly } + +जब आप सीधे `Response` return करते हैं, तब भी आप headers जोड़ सकते हैं। + +[सीधे Response Return करें](response-directly.md) में वर्णित तरीके से response बनाएँ और headers को एक अतिरिक्त parameter के रूप में पास करें: + +{* ../../docs_src/response_headers/tutorial001_py310.py hl[10:12] *} + +/// note | तकनीकी विवरण + +आप `from starlette.responses import Response` या `from starlette.responses import JSONResponse` का भी उपयोग कर सकते हैं। + +**FastAPI** आपकी, developer की, सुविधा के लिए वही `starlette.responses` `fastapi.responses` के रूप में प्रदान करता है। लेकिन उपलब्ध अधिकांश responses सीधे Starlette से आते हैं। + +और क्योंकि `Response` का उपयोग अक्सर headers और cookies सेट करने के लिए किया जा सकता है, **FastAPI** इसे `fastapi.Response` पर भी प्रदान करता है। + +/// + +## Custom Headers { #custom-headers } + +ध्यान रखें कि custom proprietary headers को [`X-` prefix का उपयोग करके](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers) जोड़ा जा सकता है। + +लेकिन अगर आपके पास custom headers हैं जिन्हें आप चाहते हैं कि browser में कोई client देख सके, तो आपको उन्हें अपनी CORS configurations में जोड़ना होगा ([CORS (Cross-Origin Resource Sharing)](../tutorial/cors.md) में और पढ़ें), इसके लिए [Starlette के CORS docs](https://www.starlette.dev/middleware/#corsmiddleware) में documented parameter `expose_headers` का उपयोग करें। diff --git a/docs/hi/docs/advanced/security/http-basic-auth.md b/docs/hi/docs/advanced/security/http-basic-auth.md new file mode 100644 index 000000000..172694ef9 --- /dev/null +++ b/docs/hi/docs/advanced/security/http-basic-auth.md @@ -0,0 +1,107 @@ +# HTTP Basic Auth { #http-basic-auth } + +सबसे सरल मामलों के लिए, आप HTTP Basic Auth का उपयोग कर सकते हैं। + +HTTP Basic Auth में, application एक header की अपेक्षा करता है जिसमें username और password होता है। + +अगर उसे यह नहीं मिलता, तो यह HTTP 401 "Unauthorized" error लौटाता है। + +और `WWW-Authenticate` header लौटाता है जिसका value `Basic` होता है, और एक optional `realm` parameter होता है। + +यह browser को username और password के लिए integrated prompt दिखाने को कहता है। + +फिर, जब आप वह username और password टाइप करते हैं, तो browser उन्हें header में अपने-आप भेज देता है। + +## Simple HTTP Basic Auth { #simple-http-basic-auth } + +* `HTTPBasic` और `HTTPBasicCredentials` import करें। +* `HTTPBasic` का उपयोग करके एक "`security` scheme" बनाएँ। +* अपने *path operation* में dependency के साथ उस `security` का उपयोग करें। +* यह `HTTPBasicCredentials` type का एक object लौटाता है: + * इसमें भेजे गए `username` और `password` होते हैं। + +{* ../../docs_src/security/tutorial006_an_py310.py hl[4,8,12] *} + +जब आप पहली बार URL खोलने की कोशिश करते हैं (या docs में "Execute" button पर क्लिक करते हैं), तो browser आपसे आपका username और password पूछेगा: + + + +## Username जाँचें { #check-the-username } + +यहाँ एक अधिक complete example है। + +यह जाँचने के लिए dependency का उपयोग करें कि username और password सही हैं या नहीं। + +इसके लिए, username और password जाँचने के लिए Python standard module [`secrets`](https://docs.python.org/3/library/secrets.html) का उपयोग करें। + +`secrets.compare_digest()` को `bytes` या ऐसा `str` लेना होता है जिसमें केवल ASCII characters (English वाले) हों, इसका मतलब है कि यह `á` जैसे characters के साथ काम नहीं करेगा, जैसे `Sebastián` में। + +इसे handle करने के लिए, हम पहले `username` और `password` को UTF-8 से encode करके `bytes` में convert करते हैं। + +फिर हम `secrets.compare_digest()` का उपयोग करके यह सुनिश्चित कर सकते हैं कि `credentials.username` `"stanleyjobson"` है, और `credentials.password` `"swordfish"` है। + +{* ../../docs_src/security/tutorial007_an_py310.py hl[1,12:24] *} + +यह इसके समान होगा: + +```Python +if not (credentials.username == "stanleyjobson") or not (credentials.password == "swordfish"): + # कोई error लौटाएँ + ... +``` + +लेकिन `secrets.compare_digest()` का उपयोग करने से यह "timing attacks" नाम के attacks के एक type के विरुद्ध सुरक्षित रहेगा। + +### Timing Attacks { #timing-attacks } + +लेकिन "timing attack" क्या होता है? + +मान लीजिए कुछ attackers username और password का अनुमान लगाने की कोशिश कर रहे हैं। + +और वे username `johndoe` और password `love123` के साथ एक request भेजते हैं। + +तब आपकी application में Python code कुछ इस तरह के बराबर होगा: + +```Python +if "johndoe" == "stanleyjobson" and "love123" == "swordfish": + ... +``` + +लेकिन जैसे ही Python `johndoe` में पहले `j` की तुलना `stanleyjobson` में पहले `s` से करता है, यह `False` लौटा देगा, क्योंकि उसे पहले से पता है कि ये दोनों strings समान नहीं हैं, यह सोचते हुए कि "बाकी अक्षरों की तुलना करके और computation खर्च करने की जरूरत नहीं है"। और आपकी application कहेगी "Incorrect username or password"। + +लेकिन फिर attackers username `stanleyjobsox` और password `love123` के साथ कोशिश करते हैं। + +और आपका application code कुछ ऐसा करता है: + +```Python +if "stanleyjobsox" == "stanleyjobson" and "love123" == "swordfish": + ... +``` + +Python को यह समझने से पहले कि दोनों strings समान नहीं हैं, `stanleyjobsox` और `stanleyjobson` दोनों में पूरे `stanleyjobso` की तुलना करनी पड़ेगी। इसलिए "Incorrect username or password" का reply वापस देने में कुछ extra microseconds लगेंगे। + +#### जवाब देने में लगा समय attackers की मदद करता है { #the-time-to-answer-helps-the-attackers } + +उस समय, यह देखकर कि server ने "Incorrect username or password" response भेजने में कुछ microseconds ज्यादा लिए, attackers जान जाएँगे कि उन्होंने _कुछ_ सही पाया है, शुरुआती अक्षरों में से कुछ सही थे। + +और फिर वे यह जानते हुए फिर कोशिश कर सकते हैं कि यह शायद `johndoe` की तुलना में `stanleyjobsox` से ज्यादा मिलता-जुलता है। + +#### एक "professional" attack { #a-professional-attack } + +बेशक, attackers यह सब हाथ से नहीं करेंगे, वे इसे करने के लिए एक program लिखेंगे, संभवतः प्रति सेकंड हजारों या लाखों tests के साथ। और उन्हें एक समय में बस एक extra सही अक्षर मिलेगा। + +लेकिन ऐसा करते हुए, कुछ minutes या hours में attackers ने हमारी application की "help" से सही username और password का अनुमान लगा लिया होगा, सिर्फ जवाब देने में लगे समय का उपयोग करके। + +#### इसे `secrets.compare_digest()` से ठीक करें { #fix-it-with-secrets-compare-digest } + +लेकिन हमारे code में हम वास्तव में `secrets.compare_digest()` का उपयोग कर रहे हैं। + +संक्षेप में, `stanleyjobsox` की तुलना `stanleyjobson` से करने में उतना ही समय लगेगा जितना `johndoe` की तुलना `stanleyjobson` से करने में लगता है। और password के लिए भी वही। + +इस तरह, अपने application code में `secrets.compare_digest()` का उपयोग करके, यह security attacks की इस पूरी range के विरुद्ध सुरक्षित रहेगा। + +### Error लौटाएँ { #return-the-error } + +यह detect करने के बाद कि credentials incorrect हैं, status code 401 (वही जो तब लौटाया जाता है जब कोई credentials provide नहीं किए जाते) के साथ एक `HTTPException` लौटाएँ और browser को login prompt फिर से दिखाने के लिए `WWW-Authenticate` header जोड़ें: + +{* ../../docs_src/security/tutorial007_an_py310.py hl[26:30] *} diff --git a/docs/hi/docs/advanced/security/index.md b/docs/hi/docs/advanced/security/index.md new file mode 100644 index 000000000..cd5d222c6 --- /dev/null +++ b/docs/hi/docs/advanced/security/index.md @@ -0,0 +1,19 @@ +# उन्नत सुरक्षा { #advanced-security } + +## अतिरिक्त Features { #additional-features } + +[Tutorial - User Guide: Security](../../tutorial/security/index.md) में शामिल चीज़ों के अलावा सुरक्षा संभालने के लिए कुछ अतिरिक्त features हैं। + +/// tip | सुझाव + +अगले sections **ज़रूरी नहीं कि "उन्नत" ही हों**। + +और यह संभव है कि आपके use case के लिए समाधान उनमें से किसी एक में हो। + +/// + +## पहले Tutorial पढ़ें { #read-the-tutorial-first } + +अगले sections मानकर चलते हैं कि आपने मुख्य [Tutorial - User Guide: Security](../../tutorial/security/index.md) पहले ही पढ़ लिया है। + +वे सभी समान concepts पर आधारित हैं, लेकिन कुछ अतिरिक्त functionalities की अनुमति देते हैं। diff --git a/docs/hi/docs/advanced/security/oauth2-scopes.md b/docs/hi/docs/advanced/security/oauth2-scopes.md new file mode 100644 index 000000000..1bf01f366 --- /dev/null +++ b/docs/hi/docs/advanced/security/oauth2-scopes.md @@ -0,0 +1,274 @@ +# OAuth2 scopes { #oauth2-scopes } + +आप **FastAPI** के साथ OAuth2 scopes सीधे उपयोग कर सकते हैं, वे निर्बाध रूप से काम करने के लिए एकीकृत हैं। + +यह आपको OAuth2 standard का पालन करते हुए, आपकी OpenAPI application (और API docs) में एक अधिक fine-grained permission system रखने की अनुमति देगा। + +Scopes के साथ OAuth2 वह mechanism है जिसे कई बड़े authentication providers, जैसे Facebook, Google, GitHub, Microsoft, X (Twitter), आदि उपयोग करते हैं। वे इसका उपयोग users और applications को विशिष्ट permissions देने के लिए करते हैं। + +हर बार जब आप Facebook, Google, GitHub, Microsoft, X (Twitter) के साथ "log in with" करते हैं, वह application scopes के साथ OAuth2 का उपयोग कर रही होती है। + +इस section में आप देखेंगे कि अपनी **FastAPI** application में उसी scopes वाले OAuth2 के साथ authentication और authorization को कैसे manage करें। + +/// warning | चेतावनी + +यह थोड़ा-बहुत advanced section है। यदि आप अभी शुरू कर रहे हैं, तो आप इसे छोड़ सकते हैं। + +आपको अनिवार्य रूप से OAuth2 scopes की आवश्यकता नहीं है, और आप authentication और authorization को जैसे चाहें handle कर सकते हैं। + +लेकिन scopes के साथ OAuth2 को आपकी API (OpenAPI के साथ) और आपकी API docs में अच्छी तरह integrate किया जा सकता है। + +फिर भी, आप उन scopes, या किसी भी अन्य security/authorization requirement को अपने code में अपनी आवश्यकता के अनुसार enforce करते हैं। + +कई मामलों में, scopes के साथ OAuth2 overkill हो सकता है। + +लेकिन यदि आप जानते हैं कि आपको इसकी आवश्यकता है, या आप curious हैं, तो पढ़ते रहें। + +/// + +## OAuth2 scopes और OpenAPI { #oauth2-scopes-and-openapi } + +OAuth2 specification "scopes" को spaces से अलग की गई strings की list के रूप में define करती है। + +इनमें से प्रत्येक string का content किसी भी format में हो सकता है, लेकिन उसमें spaces नहीं होने चाहिए। + +ये scopes "permissions" को दर्शाते हैं। + +OpenAPI में (जैसे API docs), आप "security schemes" define कर सकते हैं। + +जब इनमें से कोई security scheme OAuth2 का उपयोग करती है, तो आप scopes declare और उपयोग भी कर सकते हैं। + +प्रत्येक "scope" बस एक string है (spaces के बिना)। + +वे सामान्यतः विशिष्ट security permissions declare करने के लिए उपयोग किए जाते हैं, उदाहरण के लिए: + +* `users:read` या `users:write` आम examples हैं। +* `instagram_basic` Facebook / Instagram द्वारा उपयोग किया जाता है। +* `https://www.googleapis.com/auth/drive` Google द्वारा उपयोग किया जाता है। + +/// note | नोट + +OAuth2 में "scope" बस एक string है जो required विशिष्ट permission declare करती है। + +इससे फर्क नहीं पड़ता कि इसमें `:` जैसे अन्य characters हैं या यह एक URL है। + +वे details implementation specific हैं। + +OAuth2 के लिए वे बस strings हैं। + +/// + +## Global view { #global-view } + +पहले, आइए जल्दी से देखें कि मुख्य **Tutorial - User Guide** में [Password के साथ OAuth2 (और hashing), JWT tokens के साथ Bearer](../../tutorial/security/oauth2-jwt.md) के examples से कौन से parts बदलते हैं। अब OAuth2 scopes का उपयोग करते हुए: + +{* ../../docs_src/security/tutorial005_an_py310.py hl[5,9,13,47,65,106,108:116,122:126,130:136,141,157] *} + +अब आइए उन बदलावों को step by step review करें। + +## OAuth2 Security scheme { #oauth2-security-scheme } + +पहला बदलाव यह है कि अब हम OAuth2 security scheme को दो उपलब्ध scopes, `me` और `items`, के साथ declare कर रहे हैं। + +`scopes` parameter एक `dict` receive करता है जिसमें प्रत्येक scope key के रूप में और description value के रूप में होती है: + +{* ../../docs_src/security/tutorial005_an_py310.py hl[63:66] *} + +क्योंकि अब हम उन scopes को declare कर रहे हैं, वे API docs में तब दिखाई देंगे जब आप log-in/authorize करेंगे। + +और आप select कर सकेंगे कि आप किन scopes को access देना चाहते हैं: `me` और `items`। + +यह वही mechanism है जिसका उपयोग तब होता है जब आप Facebook, Google, GitHub, आदि के साथ log in करते समय permissions देते हैं: + + + +## Scopes के साथ JWT token { #jwt-token-with-scopes } + +अब, token *path operation* को modify करें ताकि requested scopes return हों। + +हम अभी भी वही `OAuth2PasswordRequestForm` उपयोग कर रहे हैं। इसमें `scopes` property शामिल है जिसमें `str` की `list` होती है, और request में received प्रत्येक scope होता है। + +और हम scopes को JWT token के part के रूप में return करते हैं। + +/// danger | खतरा + +सरलता के लिए, यहाँ हम received scopes को सीधे token में जोड़ रहे हैं। + +लेकिन आपकी application में, security के लिए, आपको सुनिश्चित करना चाहिए कि आप केवल वे scopes जोड़ें जिन्हें user वास्तव में रख सकता है, या जिन्हें आपने predefine किया है। + +/// + +{* ../../docs_src/security/tutorial005_an_py310.py hl[157] *} + +## *path operations* और dependencies में scopes declare करें { #declare-scopes-in-path-operations-and-dependencies } + +अब हम declare करते हैं कि `/users/me/items/` के लिए *path operation* को scope `items` required है। + +इसके लिए, हम `fastapi` से `Security` import और उपयोग करते हैं। + +आप dependencies declare करने के लिए `Security` का उपयोग कर सकते हैं (बिल्कुल `Depends` की तरह), लेकिन `Security` एक parameter `scopes` भी receive करता है जिसमें scopes (strings) की list होती है। + +इस case में, हम dependency function `get_current_active_user` को `Security` में pass करते हैं (उसी तरह जैसे हम `Depends` के साथ करते)। + +लेकिन हम scopes की एक `list` भी pass करते हैं, इस case में केवल एक scope के साथ: `items` (इसमें और भी हो सकते थे)। + +और dependency function `get_current_active_user` sub-dependencies भी declare कर सकता है, न केवल `Depends` के साथ बल्कि `Security` के साथ भी। अपना sub-dependency function (`get_current_user`) और अधिक scope requirements declare करते हुए। + +इस case में, इसे scope `me` required है (इसे एक से अधिक scope required हो सकते थे)। + +/// note | नोट + +आपको अलग-अलग जगहों पर अलग-अलग scopes जोड़ना अनिवार्य नहीं है। + +हम यहाँ यह demonstrate करने के लिए कर रहे हैं कि **FastAPI** अलग-अलग levels पर declared scopes को कैसे handle करता है। + +/// + +{* ../../docs_src/security/tutorial005_an_py310.py hl[5,141,172] *} + +/// note | तकनीकी विवरण + +`Security` वास्तव में `Depends` का subclass है, और इसमें केवल एक extra parameter है जिसे हम बाद में देखेंगे। + +लेकिन `Depends` के बजाय `Security` का उपयोग करके, **FastAPI** जान जाएगा कि यह security scopes declare कर सकता है, उन्हें internally उपयोग कर सकता है, और API को OpenAPI के साथ document कर सकता है। + +लेकिन जब आप `fastapi` से `Query`, `Path`, `Depends`, `Security` और अन्य import करते हैं, तो वे वास्तव में functions हैं जो special classes return करते हैं। + +/// + +## `SecurityScopes` का उपयोग करें { #use-securityscopes } + +अब dependency `get_current_user` को update करें। + +यह वही है जिसका उपयोग ऊपर की dependencies द्वारा किया जाता है। + +यहीं हम पहले बनाई गई उसी OAuth2 scheme का उपयोग कर रहे हैं, इसे dependency के रूप में declare करते हुए: `oauth2_scheme`। + +क्योंकि इस dependency function की अपनी कोई scope requirements नहीं हैं, हम `oauth2_scheme` के साथ `Depends` उपयोग कर सकते हैं, जब हमें security scopes specify करने की आवश्यकता नहीं है तो हमें `Security` उपयोग करने की आवश्यकता नहीं है। + +हम `SecurityScopes` type का एक special parameter भी declare करते हैं, जिसे `fastapi.security` से import किया गया है। + +यह `SecurityScopes` class `Request` के समान है (`Request` का उपयोग request object को सीधे प्राप्त करने के लिए किया गया था)। + +{* ../../docs_src/security/tutorial005_an_py310.py hl[9,106] *} + +## `scopes` का उपयोग करें { #use-the-scopes } + +Parameter `security_scopes` का type `SecurityScopes` होगा। + +इसमें property `scopes` होगी जिसमें एक list होगी, जिसमें स्वयं और इसे sub-dependency के रूप में उपयोग करने वाली सभी dependencies द्वारा required सभी scopes शामिल होंगे। इसका मतलब है, सभी "dependants"... यह confusing लग सकता है, इसे नीचे फिर से समझाया गया है। + +`security_scopes` object (`SecurityScopes` class का) एक `scope_str` attribute भी provide करता है जिसमें एक single string होती है, जिसमें वे scopes spaces से अलग होते हैं (हम इसका उपयोग करेंगे)। + +हम एक `HTTPException` बनाते हैं जिसे हम बाद में कई points पर reuse (`raise`) कर सकते हैं। + +इस exception में, हम required scopes (यदि कोई हों) को spaces से अलग की गई string के रूप में शामिल करते हैं (`scope_str` का उपयोग करके)। हम scopes वाली उस string को `WWW-Authenticate` header में रखते हैं (यह spec का part है)। + +{* ../../docs_src/security/tutorial005_an_py310.py hl[106,108:116] *} + +## `username` और data shape verify करें { #verify-the-username-and-data-shape } + +हम verify करते हैं कि हमें `username` मिलता है, और scopes extract करते हैं। + +और फिर हम उस data को Pydantic model के साथ validate करते हैं (`ValidationError` exception को catch करते हुए), और यदि JWT token पढ़ने या Pydantic के साथ data validate करने में error मिलता है, तो हम पहले बनाया हुआ `HTTPException` raise करते हैं। + +इसके लिए, हम Pydantic model `TokenData` को नई property `scopes` के साथ update करते हैं। + +Pydantic के साथ data validate करके हम यह सुनिश्चित कर सकते हैं कि हमारे पास, उदाहरण के लिए, scopes के साथ बिल्कुल `str` की `list` और `username` के साथ `str` है। + +उदाहरण के लिए, `dict`, या कुछ और नहीं, क्योंकि यह बाद में किसी point पर application को break कर सकता है, जिससे यह security risk बन सकता है। + +हम यह भी verify करते हैं कि हमारे पास उस username वाला user है, और यदि नहीं, तो हम वही exception raise करते हैं जो हमने पहले बनाया था। + +{* ../../docs_src/security/tutorial005_an_py310.py hl[47,117:129] *} + +## `scopes` verify करें { #verify-the-scopes } + +अब हम verify करते हैं कि इस dependency और सभी dependants (जिसमें *path operations* शामिल हैं) द्वारा required सभी scopes, received token में provided scopes में शामिल हैं, अन्यथा `HTTPException` raise करते हैं। + +इसके लिए, हम `security_scopes.scopes` का उपयोग करते हैं, जिसमें इन सभी scopes की `list` `str` के रूप में होती है। + +{* ../../docs_src/security/tutorial005_an_py310.py hl[130:136] *} + +## Dependency tree और scopes { #dependency-tree-and-scopes } + +आइए इस dependency tree और scopes को फिर से review करें। + +क्योंकि `get_current_active_user` dependency में `get_current_user` sub-dependency के रूप में है, `get_current_active_user` पर declared scope `"me"` required scopes की उस list में शामिल होगा जो `get_current_user` को pass किए गए `security_scopes.scopes` में होती है। + +*path operation* स्वयं भी एक scope, `"items"`, declare करता है, इसलिए यह भी `get_current_user` को pass किए गए `security_scopes.scopes` की list में होगा। + +Dependencies और scopes की hierarchy इस तरह दिखती है: + +* *path operation* `read_own_items` में है: + * Dependency के साथ required scopes `["items"]`: + * `get_current_active_user`: + * Dependency function `get_current_active_user` में है: + * Dependency के साथ required scopes `["me"]`: + * `get_current_user`: + * Dependency function `get_current_user` में है: + * स्वयं द्वारा required कोई scopes नहीं। + * `oauth2_scheme` का उपयोग करने वाली dependency। + * `SecurityScopes` type का एक `security_scopes` parameter: + * इस `security_scopes` parameter में property `scopes` है जिसमें ऊपर declared इन सभी scopes वाली `list` है, इसलिए: + * *path operation* `read_own_items` के लिए `security_scopes.scopes` में `["me", "items"]` होगा। + * *path operation* `read_users_me` के लिए `security_scopes.scopes` में `["me"]` होगा, क्योंकि यह dependency `get_current_active_user` में declared है। + * *path operation* `read_system_status` के लिए `security_scopes.scopes` में `[]` (कुछ नहीं) होगा, क्योंकि उसने `scopes` के साथ कोई `Security` declare नहीं किया, और उसकी dependency, `get_current_user`, भी कोई `scopes` declare नहीं करती। + +/// tip | सुझाव + +यहाँ महत्वपूर्ण और "magic" बात यह है कि प्रत्येक *path operation* के लिए `get_current_user` के पास check करने हेतु `scopes` की अलग list होगी। + +यह सब उस specific *path operation* के dependency tree में प्रत्येक *path operation* और प्रत्येक dependency में declared `scopes` पर निर्भर करता है। + +/// + +## `SecurityScopes` के बारे में अधिक details { #more-details-about-securityscopes } + +आप `SecurityScopes` का उपयोग किसी भी point पर, और multiple जगहों पर कर सकते हैं, इसका "root" dependency पर होना ज़रूरी नहीं है। + +इसमें हमेशा current `Security` dependencies और **उस specific** *path operation* तथा **उस specific** dependency tree के सभी dependants में declared security scopes होंगे। + +क्योंकि `SecurityScopes` में dependants द्वारा declared सभी scopes होंगे, आप इसका उपयोग यह verify करने के लिए कर सकते हैं कि token में required scopes हैं, एक central dependency function में, और फिर अलग-अलग *path operations* में अलग-अलग scope requirements declare कर सकते हैं। + +उन्हें प्रत्येक *path operation* के लिए independently check किया जाएगा। + +## इसे check करें { #check-it } + +यदि आप API docs खोलते हैं, तो आप authenticate कर सकते हैं और specify कर सकते हैं कि आप किन scopes को authorize करना चाहते हैं। + + + +यदि आप कोई scope select नहीं करते हैं, तो आप "authenticated" होंगे, लेकिन जब आप `/users/me/` या `/users/me/items/` access करने की कोशिश करेंगे तो आपको error मिलेगा कि आपके पास पर्याप्त permissions नहीं हैं। आप फिर भी `/status/` access कर पाएंगे। + +और यदि आप scope `me` select करते हैं लेकिन scope `items` नहीं, तो आप `/users/me/` access कर पाएंगे लेकिन `/users/me/items/` नहीं। + +ऐसा ही किसी third party application के साथ होगा जो user द्वारा provided token के साथ इन *path operations* में से किसी एक को access करने की कोशिश करती, यह इस पर निर्भर करता है कि user ने application को कितनी permissions दीं। + +## Third party integrations के बारे में { #about-third-party-integrations } + +इस example में हम OAuth2 "password" flow का उपयोग कर रहे हैं। + +यह तब appropriate है जब हम अपनी ही application में log in कर रहे हों, शायद अपने ही frontend के साथ। + +क्योंकि हम इस पर भरोसा कर सकते हैं कि यह `username` और `password` receive करे, क्योंकि हम इसे control करते हैं। + +लेकिन यदि आप ऐसी OAuth2 application बना रहे हैं जिससे दूसरे connect करेंगे (अर्थात, यदि आप Facebook, Google, GitHub, आदि के बराबर authentication provider बना रहे हैं) तो आपको अन्य flows में से किसी एक का उपयोग करना चाहिए। + +सबसे common implicit flow है। + +सबसे secure code flow है, लेकिन इसे implement करना अधिक complex है क्योंकि इसमें अधिक steps required हैं। क्योंकि यह अधिक complex है, कई providers अंततः implicit flow suggest करते हैं। + +/// note | नोट + +यह common है कि प्रत्येक authentication provider अपने flows को अलग तरीके से name करता है, ताकि इसे अपने brand का part बना सके। + +लेकिन अंततः, वे वही OAuth2 standard implement कर रहे होते हैं। + +/// + +**FastAPI** में इन सभी OAuth2 authentication flows के लिए utilities `fastapi.security.oauth2` में शामिल हैं। + +## Decorator `dependencies` में `Security` { #security-in-decorator-dependencies } + +जिस तरह आप decorator के `dependencies` parameter में `Depends` की `list` define कर सकते हैं (जैसा कि [path operation decorators में Dependencies](../../tutorial/dependencies/dependencies-in-path-operation-decorators.md) में समझाया गया है), आप वहाँ `scopes` के साथ `Security` भी उपयोग कर सकते हैं। diff --git a/docs/hi/docs/advanced/settings.md b/docs/hi/docs/advanced/settings.md new file mode 100644 index 000000000..0c4d3c061 --- /dev/null +++ b/docs/hi/docs/advanced/settings.md @@ -0,0 +1,302 @@ +# Settings और Environment Variables { #settings-and-environment-variables } + +कई मामलों में आपकी application को कुछ बाहरी settings या configurations की ज़रूरत हो सकती है, उदाहरण के लिए secret keys, database credentials, email services के लिए credentials, आदि। + +इनमें से ज़्यादातर settings variable होती हैं (बदल सकती हैं), जैसे database URLs। और कई sensitive हो सकती हैं, जैसे secrets। + +इसी कारण उन्हें आम तौर पर environment variables में दिया जाता है जिन्हें application पढ़ती है। + +/// tip | सुझाव + +Environment variables को समझने के लिए आप [Environment Variables](../environment-variables.md) पढ़ सकते हैं। + +/// + +## Types और validation { #types-and-validation } + +ये environment variables केवल text strings को handle कर सकते हैं, क्योंकि ये Python के बाहर होते हैं और इन्हें दूसरे programs और system के बाकी हिस्सों के साथ compatible होना होता है (और अलग-अलग operating systems, जैसे Linux, Windows, और macOS के साथ भी)। + +इसका मतलब है कि Python में किसी environment variable से पढ़ी गई कोई भी value एक `str` होगी, और किसी अलग type में कोई भी conversion या कोई भी validation code में करनी होगी। + +## Pydantic `Settings` { #pydantic-settings } + +सौभाग्य से, Pydantic environment variables से आने वाली इन settings को handle करने के लिए एक बेहतरीन utility देता है: [Pydantic: Settings management](https://docs.pydantic.dev/latest/concepts/pydantic_settings/)। + +### `pydantic-settings` install करें { #install-pydantic-settings } + +सबसे पहले, सुनिश्चित करें कि आप अपना [virtual environment](../virtual-environments.md) बनाते हैं, उसे activate करते हैं, और फिर `pydantic-settings` package install करते हैं: + +
+ +```console +$ pip install pydantic-settings +---> 100% +``` + +
+ +जब आप `all` extras को install करते हैं, तो यह भी शामिल आता है: + +
+ +```console +$ pip install "fastapi[all]" +---> 100% +``` + +
+ +### `Settings` object बनाएँ { #create-the-settings-object } + +Pydantic से `BaseSettings` import करें और एक sub-class बनाएँ, बिल्कुल Pydantic model की तरह। + +Pydantic models की तरह ही, आप type annotations के साथ class attributes घोषित करते हैं, और संभवतः default values भी। + +आप वे सभी validation features और tools इस्तेमाल कर सकते हैं जिन्हें आप Pydantic models के लिए इस्तेमाल करते हैं, जैसे अलग-अलग data types और `Field()` के साथ अतिरिक्त validations। + +{* ../../docs_src/settings/tutorial001_py310.py hl[2,5:8,11] *} + +/// tip | सुझाव + +अगर आप जल्दी copy और paste करने के लिए कुछ चाहते हैं, तो यह example इस्तेमाल न करें, नीचे वाला आखिरी example इस्तेमाल करें। + +/// + +फिर, जब आप उस `Settings` class का instance बनाते हैं (इस case में, `settings` object में), Pydantic environment variables को case-insensitive तरीके से पढ़ेगा, इसलिए upper-case variable `APP_NAME` भी attribute `app_name` के लिए पढ़ा जाएगा। + +इसके बाद यह data को convert और validate करेगा। इसलिए, जब आप उस `settings` object का उपयोग करेंगे, तो आपके पास उन types का data होगा जिन्हें आपने घोषित किया था (जैसे `items_per_user` एक `int` होगा)। + +### `settings` का उपयोग करें { #use-the-settings } + +फिर आप अपनी application में नए `settings` object का उपयोग कर सकते हैं: + +{* ../../docs_src/settings/tutorial001_py310.py hl[18:20] *} + +### Server चलाएँ { #run-the-server } + +इसके बाद, आप configurations को environment variables के रूप में pass करते हुए server चलाएँगे, उदाहरण के लिए आप `ADMIN_EMAIL` और `APP_NAME` set कर सकते हैं: + +
+ +```console +$ ADMIN_EMAIL="deadpool@example.com" APP_NAME="ChimichangApp" fastapi run main.py + +INFO: Uvicorn running on http://127.0.0.1:8000 (Press CTRL+C to quit) +``` + +
+ +/// tip | सुझाव + +एक ही command के लिए कई env vars set करने के लिए बस उन्हें space से अलग करें, और उन सभी को command से पहले रखें। + +/// + +और फिर `admin_email` setting `"deadpool@example.com"` पर set हो जाएगी। + +`app_name` `"ChimichangApp"` होगा। + +और `items_per_user` अपनी default value `50` बनाए रखेगा। + +## किसी दूसरे module में Settings { #settings-in-another-module } + +आप उन settings को किसी दूसरे module file में रख सकते हैं, जैसा आपने [Bigger Applications - Multiple Files](../tutorial/bigger-applications.md) में देखा था। + +उदाहरण के लिए, आपके पास `config.py` file हो सकती है: + +{* ../../docs_src/settings/app01_py310/config.py *} + +और फिर उसे `main.py` file में उपयोग करें: + +{* ../../docs_src/settings/app01_py310/main.py hl[3,11:13] *} + +/// tip | सुझाव + +आपको एक `__init__.py` file की भी ज़रूरत होगी, जैसा आपने [Bigger Applications - Multiple Files](../tutorial/bigger-applications.md) में देखा था। + +/// + +## Dependency में Settings { #settings-in-a-dependency } + +कुछ मौकों पर settings को dependency से देना उपयोगी हो सकता है, बजाय इसके कि `settings` के साथ एक global object हो जिसे हर जगह इस्तेमाल किया जाए। + +यह testing के दौरान विशेष रूप से उपयोगी हो सकता है, क्योंकि dependency को अपनी custom settings से override करना बहुत आसान है। + +### Config file { #the-config-file } + +पिछले example से आगे बढ़ते हुए, आपकी `config.py` file इस तरह दिख सकती है: + +{* ../../docs_src/settings/app02_an_py310/config.py hl[10] *} + +ध्यान दें कि अब हम default instance `settings = Settings()` नहीं बनाते। + +### Main app file { #the-main-app-file } + +अब हम एक dependency बनाते हैं जो नया `config.Settings()` return करती है। + +{* ../../docs_src/settings/app02_an_py310/main.py hl[6,12:13] *} + +/// tip | सुझाव + +हम थोड़ी देर में `@lru_cache` पर चर्चा करेंगे। + +अभी के लिए आप मान सकते हैं कि `get_settings()` एक normal function है। + +/// + +और फिर हम इसे *path operation function* से dependency के रूप में require कर सकते हैं और जहाँ भी ज़रूरत हो वहाँ इस्तेमाल कर सकते हैं। + +{* ../../docs_src/settings/app02_an_py310/main.py hl[17,19:21] *} + +### Settings और testing { #settings-and-testing } + +फिर testing के दौरान `get_settings` के लिए dependency override बनाकर अलग settings object देना बहुत आसान होगा: + +{* ../../docs_src/settings/app02_an_py310/test_main.py hl[9:10,13,21] *} + +Dependency override में हम नया `Settings` object बनाते समय `admin_email` के लिए नई value set करते हैं, और फिर उस नए object को return करते हैं। + +फिर हम test कर सकते हैं कि इसका उपयोग हुआ है। + +## `.env` file पढ़ना { #reading-a-env-file } + +अगर आपके पास कई settings हैं जो संभवतः बहुत बदलती हैं, शायद अलग-अलग environments में, तो उन्हें एक file में रखना और फिर वहाँ से ऐसे पढ़ना उपयोगी हो सकता है जैसे वे environment variables हों। + +यह practice इतनी आम है कि इसका एक नाम है, ये environment variables आम तौर पर `.env` file में रखे जाते हैं, और file को "dotenv" कहा जाता है। + +/// tip | सुझाव + +dot (`.`) से शुरू होने वाली file Unix-like systems, जैसे Linux और macOS में hidden file होती है। + +लेकिन dotenv file का वास्तव में वही exact filename होना ज़रूरी नहीं है। + +/// + +Pydantic के पास external library का उपयोग करके इस प्रकार की files से पढ़ने के लिए support है। आप [Pydantic Settings: Dotenv (.env) support](https://docs.pydantic.dev/latest/concepts/pydantic_settings/#dotenv-env-support) पर और पढ़ सकते हैं। + +/// tip | सुझाव + +इसे काम करने के लिए, आपको `pip install python-dotenv` करना होगा। + +/// + +### `.env` file { #the-env-file } + +आपके पास इस तरह की `.env` file हो सकती है: + +```bash +ADMIN_EMAIL="deadpool@example.com" +APP_NAME="ChimichangApp" +``` + +### `.env` से settings पढ़ें { #read-settings-from-env } + +और फिर अपनी `config.py` को update करें: + +{* ../../docs_src/settings/app03_an_py310/config.py hl[9] *} + +/// tip | सुझाव + +`model_config` attribute केवल Pydantic configuration के लिए उपयोग किया जाता है। आप [Pydantic: Concepts: Configuration](https://docs.pydantic.dev/latest/concepts/config/) पर और पढ़ सकते हैं। + +/// + +यहाँ हम आपकी Pydantic `Settings` class के अंदर config `env_file` define करते हैं, और value को उस dotenv file के filename पर set करते हैं जिसे हम उपयोग करना चाहते हैं। + +### `lru_cache` के साथ `Settings` को केवल एक बार बनाना { #creating-the-settings-only-once-with-lru-cache } + +Disk से file पढ़ना सामान्यतः costly (slow) operation होता है, इसलिए आप शायद इसे केवल एक बार करना चाहेंगे और फिर हर request के लिए पढ़ने के बजाय उसी settings object को reuse करना चाहेंगे। + +लेकिन हर बार जब हम करते हैं: + +```Python +Settings() +``` + +तो एक नया `Settings` object बनेगा, और बनते समय यह `.env` file को फिर से पढ़ेगा। + +अगर dependency function बस ऐसी होती: + +```Python +def get_settings(): + return Settings() +``` + +तो हम हर request के लिए वह object बनाते, और हर request के लिए `.env` file पढ़ते। ⚠️ + +लेकिन क्योंकि हम ऊपर `@lru_cache` decorator इस्तेमाल कर रहे हैं, `Settings` object केवल एक बार बनाया जाएगा, पहली बार जब इसे call किया जाएगा। ✔️ + +{* ../../docs_src/settings/app03_an_py310/main.py hl[1,11] *} + +फिर अगले requests के लिए dependencies में `get_settings()` की किसी भी बाद की call पर, `get_settings()` के internal code को execute करने और नया `Settings` object बनाने के बजाय, यह वही object return करेगा जो पहली call पर return किया गया था, बार-बार। + +#### `lru_cache` Technical Details { #lru-cache-technical-details } + +`@lru_cache` जिस function को decorate करता है उसे modify करता है ताकि वह हर बार function का code execute करके फिर से compute करने के बजाय वही value return करे जो पहली बार return की गई थी। + +इसलिए, उसके नीचे वाला function arguments के प्रत्येक combination के लिए एक बार execute होगा। और फिर उन arguments के प्रत्येक combination द्वारा return की गई values बार-बार उपयोग की जाएँगी, जब भी function को ठीक उसी arguments combination के साथ call किया जाएगा। + +उदाहरण के लिए, अगर आपके पास एक function है: + +```Python +@lru_cache +def say_hi(name: str, salutation: str = "Ms."): + return f"Hello {salutation} {name}" +``` + +आपका program इस तरह execute हो सकता है: + +```mermaid +sequenceDiagram + +participant code as Code +participant function as say_hi() +participant execute as Execute function + + rect rgba(0, 255, 0, .1) + code ->> function: say_hi(name="Camila") + function ->> execute: execute function code + execute ->> code: return the result + end + + rect rgba(0, 255, 255, .1) + code ->> function: say_hi(name="Camila") + function ->> code: return stored result + end + + rect rgba(0, 255, 0, .1) + code ->> function: say_hi(name="Rick") + function ->> execute: execute function code + execute ->> code: return the result + end + + rect rgba(0, 255, 0, .1) + code ->> function: say_hi(name="Rick", salutation="Mr.") + function ->> execute: execute function code + execute ->> code: return the result + end + + rect rgba(0, 255, 255, .1) + code ->> function: say_hi(name="Rick") + function ->> code: return stored result + end + + rect rgba(0, 255, 255, .1) + code ->> function: say_hi(name="Camila") + function ->> code: return stored result + end +``` + +हमारी dependency `get_settings()` के case में, function कोई arguments भी नहीं लेती, इसलिए यह हमेशा वही value return करती है। + +इस तरह, यह लगभग ऐसे behave करती है जैसे यह बस एक global variable हो। लेकिन क्योंकि यह dependency function का उपयोग करती है, इसलिए हम testing के लिए इसे आसानी से override कर सकते हैं। + +`@lru_cache` `functools` का हिस्सा है, जो Python की standard library का हिस्सा है। आप इसके बारे में [Python docs for `@lru_cache`](https://docs.python.org/3/library/functools.html#functools.lru_cache) में और पढ़ सकते हैं। + +## Recap { #recap } + +आप अपनी application की settings या configurations को handle करने के लिए Pydantic Settings का उपयोग कर सकते हैं, Pydantic models की पूरी power के साथ। + +* Dependency का उपयोग करके आप testing को सरल बना सकते हैं। +* आप इसके साथ `.env` files का उपयोग कर सकते हैं। +* `@lru_cache` का उपयोग करने से आप हर request के लिए dotenv file को बार-बार पढ़ने से बच सकते हैं, साथ ही testing के दौरान इसे override करने की अनुमति भी मिलती है। diff --git a/docs/hi/docs/advanced/stream-data.md b/docs/hi/docs/advanced/stream-data.md new file mode 100644 index 000000000..f1dd15de5 --- /dev/null +++ b/docs/hi/docs/advanced/stream-data.md @@ -0,0 +1,117 @@ +# Data Stream करें { #stream-data } + +अगर आप ऐसा data stream करना चाहते हैं जिसे JSON के रूप में संरचित किया जा सके, तो आपको [JSON Lines Stream करें](../tutorial/stream-json-lines.md)। + +लेकिन अगर आप **शुद्ध binary data** या strings stream करना चाहते हैं, तो यह आप ऐसे कर सकते हैं। + +/// note | नोट + +FastAPI 0.134.0 में जोड़ा गया। + +/// + +## उपयोग के मामले { #use-cases } + +आप इसका उपयोग तब कर सकते हैं जब आप शुद्ध strings stream करना चाहते हों, उदाहरण के लिए सीधे किसी **AI LLM** service के output से। + +आप इसका उपयोग **बड़ी binary files** stream करने के लिए भी कर सकते हैं, जहाँ आप data के प्रत्येक chunk को पढ़ते समय stream करते हैं, बिना पूरे data को एक साथ memory में पढ़े। + +आप इसी तरह **video** या **audio** भी stream कर सकते हैं, यह process और send करते समय generate भी किया जा सकता है। + +## `yield` के साथ एक `StreamingResponse` { #a-streamingresponse-with-yield } + +अगर आप अपने *path operation function* में `response_class=StreamingResponse` declare करते हैं, तो आप data के प्रत्येक chunk को क्रम से भेजने के लिए `yield` का उपयोग कर सकते हैं। + +{* ../../docs_src/stream_data/tutorial001_py310.py ln[1:23] hl[20,23] *} + +FastAPI data के प्रत्येक chunk को `StreamingResponse` को जैसा है वैसा ही देगा, यह उसे JSON या किसी समान चीज़ में convert करने की कोशिश नहीं करेगा। + +### Non-async *path operation functions* { #non-async-path-operation-functions } + +आप regular `def` functions (`async` के बिना) का भी उपयोग कर सकते हैं, और उसी तरह `yield` का उपयोग कर सकते हैं। + +{* ../../docs_src/stream_data/tutorial001_py310.py ln[26:29] hl[27] *} + +### Annotation नहीं { #no-annotation } + +Streaming binary data के लिए आपको return type annotation declare करने की वास्तव में आवश्यकता नहीं है। + +क्योंकि FastAPI data को Pydantic के साथ JSON में convert करने या किसी भी तरह serialize करने की कोशिश नहीं करेगा, इस मामले में type annotation केवल आपके editor और tools के उपयोग के लिए है, FastAPI इसका उपयोग नहीं करेगा। + +{* ../../docs_src/stream_data/tutorial001_py310.py ln[32:35] hl[33] *} + +इसका मतलब यह भी है कि `StreamingResponse` के साथ आपके पास type annotations से स्वतंत्र होकर data bytes को ठीक वैसे produce और encode करने की **स्वतंत्रता** और **ज़िम्मेदारी** है, जैसे उन्हें भेजा जाना चाहिए। 🤓 + +### Bytes Stream करें { #stream-bytes } + +मुख्य उपयोग मामलों में से एक strings के बजाय `bytes` stream करना होगा, और आप निश्चित रूप से ऐसा कर सकते हैं। + +{* ../../docs_src/stream_data/tutorial001_py310.py ln[44:47] hl[47] *} + +## एक Custom `PNGStreamingResponse` { #a-custom-pngstreamingresponse } + +ऊपर के उदाहरणों में, data bytes stream किए गए थे, लेकिन response में `Content-Type` header नहीं था, इसलिए client को पता नहीं था कि उसे किस प्रकार का data मिल रहा है। + +आप `StreamingResponse` की एक custom sub-class बना सकते हैं जो `Content-Type` header को उस प्रकार के data पर set करती है जिसे आप stream कर रहे हैं। + +उदाहरण के लिए, आप एक `PNGStreamingResponse` बना सकते हैं जो `media_type` attribute का उपयोग करके `Content-Type` header को `image/png` पर set करता है: + +{* ../../docs_src/stream_data/tutorial002_py310.py ln[6,19:20] hl[20] *} + +फिर आप अपने *path operation function* में `response_class=PNGStreamingResponse` में इस नई class का उपयोग कर सकते हैं: + +{* ../../docs_src/stream_data/tutorial002_py310.py ln[23:27] hl[23] *} + +### एक File का Simulation करें { #simulate-a-file } + +इस उदाहरण में, हम `io.BytesIO` के साथ एक file simulate कर रहे हैं, जो एक file-like object है जो केवल memory में रहता है, लेकिन हमें वही interface उपयोग करने देता है। + +उदाहरण के लिए, हम इसके contents consume करने के लिए इस पर iterate कर सकते हैं, जैसे हम किसी file के साथ कर सकते हैं। + +{* ../../docs_src/stream_data/tutorial002_py310.py ln[1:27] hl[3,12:13,25] *} + +/// note | तकनीकी विवरण + +अन्य दो variables, `image_base64` और `binary_image`, Base64 में encoded एक image हैं, और फिर bytes में convert किए गए हैं, ताकि फिर उन्हें `io.BytesIO` को pass किया जा सके। + +सिर्फ इसलिए ताकि इस उदाहरण के लिए यह उसी file में रह सके और आप इसे copy करके जैसा है वैसा ही run कर सकें। 🥚 + +/// + +`with` block का उपयोग करके, हम यह सुनिश्चित करते हैं कि generator function (`yield` वाला function) पूरा होने के बाद file-like object बंद हो जाए। यानी, response भेजना पूरा होने के बाद। + +इस विशिष्ट उदाहरण में यह उतना महत्वपूर्ण नहीं होगा क्योंकि यह एक fake in-memory file है (`io.BytesIO` के साथ), लेकिन एक वास्तविक file के साथ, यह सुनिश्चित करना महत्वपूर्ण होगा कि इसके साथ काम पूरा होने के बाद file बंद हो जाए। + +### Files और Async { #files-and-async } + +अधिकांश मामलों में, file-like objects default रूप से async और await के साथ compatible नहीं होते। + +उदाहरण के लिए, उनके पास `await file.read()` या `async for chunk in file` नहीं होता। + +और कई मामलों में, उन्हें पढ़ना एक blocking operation होगा (जो event loop को block कर सकता है), क्योंकि उन्हें disk या network से पढ़ा जाता है। + +/// note | नोट + +ऊपर दिया गया उदाहरण वास्तव में एक exception है, क्योंकि `io.BytesIO` object पहले से memory में है, इसलिए उसे पढ़ना किसी चीज़ को block नहीं करेगा। + +लेकिन कई मामलों में किसी file या file-like object को पढ़ना block करेगा। + +/// + +event loop को block करने से बचने के लिए, आप बस *path operation function* को `async def` के बजाय regular `def` के साथ declare कर सकते हैं, इस तरह FastAPI इसे main loop को block करने से बचाने के लिए threadpool worker पर run करेगा। + +{* ../../docs_src/stream_data/tutorial002_py310.py ln[30:34] hl[31] *} + +/// tip | सुझाव + +अगर आपको किसी async function के अंदर से blocking code call करना हो, या किसी blocking function के अंदर से async function call करना हो, तो आप [Asyncer](https://asyncer.tiangolo.com) का उपयोग कर सकते हैं, जो FastAPI की एक sibling library है। + +/// + +### `yield from` { #yield-from } + +जब आप किसी चीज़ पर iterate कर रहे हों, जैसे किसी file-like object पर, और फिर प्रत्येक item के लिए `yield` कर रहे हों, तो आप प्रत्येक item को सीधे yield करने और `for` loop को skip करने के लिए `yield from` का भी उपयोग कर सकते हैं। + +यह FastAPI के लिए विशेष नहीं है, यह सिर्फ Python है, लेकिन यह जानने लायक एक अच्छा trick है। 😎 + +{* ../../docs_src/stream_data/tutorial002_py310.py ln[37:40] hl[40] *} diff --git a/docs/hi/docs/advanced/strict-content-type.md b/docs/hi/docs/advanced/strict-content-type.md new file mode 100644 index 000000000..a63081024 --- /dev/null +++ b/docs/hi/docs/advanced/strict-content-type.md @@ -0,0 +1,88 @@ +# सख्त Content-Type जाँच { #strict-content-type-checking } + +default रूप से, **FastAPI** JSON request bodies के लिए सख्त `Content-Type` header जाँच का उपयोग करता है, इसका मतलब है कि body को JSON के रूप में parse करने के लिए JSON requests में वैध `Content-Type` header (जैसे `application/json`) **होना ही चाहिए**। + +## CSRF जोखिम { #csrf-risk } + +यह default व्यवहार एक बहुत विशिष्ट परिस्थिति में **Cross-Site Request Forgery (CSRF)** हमलों के एक वर्ग से सुरक्षा प्रदान करता है। + +ये हमले इस बात का फायदा उठाते हैं कि browsers scripts को बिना कोई CORS preflight check किए requests भेजने देते हैं, जब वे: + +* `Content-Type` header नहीं रखते (जैसे `Blob` body के साथ `fetch()` का उपयोग करना) +* और कोई authentication credentials नहीं भेजते। + +इस प्रकार का हमला मुख्य रूप से तब relevant होता है जब: + +* application स्थानीय रूप से चल रही हो (जैसे `localhost` पर) या किसी internal network में +* और application में कोई authentication न हो, वह यह मानती हो कि उसी network से आने वाली कोई भी request भरोसेमंद हो सकती है। + +## उदाहरण हमला { #example-attack } + +कल्पना करें कि आप एक local AI agent चलाने का तरीका बनाते हैं। + +यह यहाँ एक API प्रदान करता है + +``` +http://localhost:8000/v1/agents/multivac +``` + +यहाँ एक frontend भी है + +``` +http://localhost:8000 +``` + +/// tip | सुझाव + +ध्यान दें कि दोनों का host समान है। + +/// + +फिर frontend का उपयोग करके आप AI agent से अपनी ओर से काम करवा सकते हैं। + +क्योंकि यह **स्थानीय रूप से** चल रहा है, और खुले internet पर नहीं है, आप **कोई authentication setup न करने** का निर्णय लेते हैं, बस local network तक access पर भरोसा करते हुए। + +फिर आपके users में से कोई इसे install करके locally चला सकता है। + +फिर वे कोई malicious website खोल सकते हैं, जैसे कुछ इस तरह + +``` +https://evilhackers.example.com +``` + +और वह malicious website `Blob` body के साथ `fetch()` का उपयोग करके local API पर requests भेजती है + +``` +http://localhost:8000/v1/agents/multivac +``` + +भले ही malicious website और local app का host अलग हो, browser CORS preflight request trigger नहीं करेगा क्योंकि: + +* यह बिना किसी authentication के चल रहा है, इसे कोई credentials भेजने की जरूरत नहीं है। +* browser को लगता है कि यह JSON नहीं भेज रहा है (`Content-Type` header गायब होने के कारण)। + +फिर malicious website local AI agent से user के ex-boss को गुस्से भरे messages भेजवा सकती है... या उससे भी बुरा। 😅 + +## खुला Internet { #open-internet } + +अगर आपकी app खुले internet पर है, तो आप "network पर भरोसा" नहीं करेंगे और किसी को भी बिना authentication के privileged requests भेजने नहीं देंगे। + +Attackers सीधे आपकी API पर requests भेजने के लिए script चला सकते हैं, browser interaction की कोई जरूरत नहीं, इसलिए आप शायद पहले से ही किसी भी privileged endpoints को secure कर रहे होंगे। + +उस स्थिति में **यह हमला / जोखिम आप पर लागू नहीं होता**। + +यह जोखिम और हमला मुख्य रूप से तब relevant होता है जब app **local network** पर चलती है और वही **एकमात्र मानी गई सुरक्षा** होती है। + +## Content-Type के बिना Requests की अनुमति देना { #allowing-requests-without-content-type } + +अगर आपको ऐसे clients को support करना है जो `Content-Type` header नहीं भेजते, तो आप `strict_content_type=False` set करके strict checking disable कर सकते हैं: + +{* ../../docs_src/strict_content_type/tutorial001_py310.py hl[4] *} + +इस setting के साथ, जिन requests में `Content-Type` header नहीं होगा, उनकी body JSON के रूप में parse की जाएगी, जो FastAPI के पुराने versions जैसा ही व्यवहार है। + +/// note | नोट + +यह व्यवहार और configuration FastAPI 0.132.0 में जोड़ा गया था। + +/// diff --git a/docs/hi/docs/advanced/sub-applications.md b/docs/hi/docs/advanced/sub-applications.md new file mode 100644 index 000000000..3f4ea6da7 --- /dev/null +++ b/docs/hi/docs/advanced/sub-applications.md @@ -0,0 +1,67 @@ +# Sub Applications - Mounts { #sub-applications-mounts } + +अगर आपको दो स्वतंत्र FastAPI applications चाहिए, जिनका अपना स्वतंत्र OpenAPI और अपनी docs UIs हों, तो आप एक मुख्य app रख सकते हैं और एक (या अधिक) sub-application(s) को "mount" कर सकते हैं। + +## **FastAPI** application को Mount करना { #mounting-a-fastapi-application } + +"Mounting" का मतलब है किसी विशिष्ट path में पूरी तरह "स्वतंत्र" application जोड़ना, जो फिर उस path के अंतर्गत सब कुछ handle करने का ध्यान रखता है, उस sub-application में घोषित _path operations_ के साथ। + +### Top-level application { #top-level-application } + +सबसे पहले, मुख्य, top-level **FastAPI** application और उसके *path operations* बनाएँ: + +{* ../../docs_src/sub_applications/tutorial001_py310.py hl[3, 6:8] *} + +### Sub-application { #sub-application } + +फिर, अपनी sub-application और उसके *path operations* बनाएँ। + +यह sub-application बस एक और standard FastAPI application है, लेकिन यही वह है जिसे "mounted" किया जाएगा: + +{* ../../docs_src/sub_applications/tutorial001_py310.py hl[11, 14:16] *} + +### Sub-application को mount करें { #mount-the-sub-application } + +अपने top-level application, `app`, में sub-application, `subapi`, को mount करें। + +इस मामले में, इसे path `/subapi` पर mount किया जाएगा: + +{* ../../docs_src/sub_applications/tutorial001_py310.py hl[11, 19] *} + +### Automatic API docs देखें { #check-the-automatic-api-docs } + +अब, `fastapi` command चलाएँ: + +
+ +```console +$ fastapi dev + +INFO: Uvicorn running on http://127.0.0.1:8000 (Press CTRL+C to quit) +``` + +
+ +और docs को [http://127.0.0.1:8000/docs](http://127.0.0.1:8000/docs) पर खोलें। + +आप मुख्य app के लिए automatic API docs देखेंगे, जिसमें केवल उसके अपने _path operations_ शामिल होंगे: + + + +और फिर, sub-application के लिए docs को [http://127.0.0.1:8000/subapi/docs](http://127.0.0.1:8000/subapi/docs) पर खोलें। + +आप sub-application के लिए automatic API docs देखेंगे, जिसमें केवल उसके अपने _path operations_ शामिल होंगे, सभी सही sub-path prefix `/subapi` के अंतर्गत: + + + +अगर आप दोनों user interfaces में से किसी के साथ interact करने की कोशिश करते हैं, तो वे सही तरह काम करेंगे, क्योंकि browser हर specific app या sub-app से बात कर पाएगा। + +### तकनीकी विवरण: `root_path` { #technical-details-root-path } + +जब आप ऊपर बताए गए तरीके से कोई sub-application mount करते हैं, तो FastAPI sub-application के लिए mount path communicate करने का ध्यान रखेगा, ASGI specification के एक mechanism का उपयोग करके जिसे `root_path` कहा जाता है। + +इस तरह, sub-application को पता होगा कि docs UI के लिए उस path prefix का उपयोग करना है। + +और sub-application की अपनी mounted sub-applications भी हो सकती हैं और सब कुछ सही तरह काम करेगा, क्योंकि FastAPI इन सभी `root_path`s को अपने आप handle करता है। + +आप `root_path` के बारे में और इसे स्पष्ट रूप से कैसे उपयोग करें, यह [Behind a Proxy](behind-a-proxy.md) वाले section में और सीखेंगे। diff --git a/docs/hi/docs/advanced/templates.md b/docs/hi/docs/advanced/templates.md new file mode 100644 index 000000000..b16ef4a6e --- /dev/null +++ b/docs/hi/docs/advanced/templates.md @@ -0,0 +1,126 @@ +# Templates { #templates } + +आप **FastAPI** के साथ अपनी पसंद का कोई भी template engine उपयोग कर सकते हैं। + +एक आम विकल्प Jinja2 है, वही जिसे Flask और अन्य tools उपयोग करते हैं। + +इसे आसानी से configure करने के लिए utilities उपलब्ध हैं जिन्हें आप सीधे अपने **FastAPI** application में उपयोग कर सकते हैं (Starlette द्वारा प्रदान की गई)। + +## Dependencies install करें { #install-dependencies } + +सुनिश्चित करें कि आप एक [virtual environment](../virtual-environments.md) बनाएँ, उसे activate करें, और `jinja2` install करें: + +
+ +```console +$ pip install jinja2 + +---> 100% +``` + +
+ +## `Jinja2Templates` का उपयोग करना { #using-jinja2templates } + +* `Jinja2Templates` import करें। +* एक `templates` object बनाएँ जिसे आप बाद में फिर से उपयोग कर सकें। +* उस *path operation* में एक `Request` parameter declare करें जो एक template return करेगा। +* आपने जो `templates` बनाया है, उसका उपयोग करके एक `TemplateResponse` render और return करें; template का नाम, request object, और key-value pairs वाली एक "context" dictionary pass करें, जिनका उपयोग Jinja2 template के अंदर किया जाएगा। + +{* ../../docs_src/templates/tutorial001_py310.py hl[4,11,15:18] *} + +/// note | नोट + +FastAPI 0.108.0, Starlette 0.29.0 से पहले, `name` पहला parameter था। + +साथ ही, उससे पहले के versions में, `request` object को Jinja2 के context में key-value pairs के हिस्से के रूप में pass किया जाता था। + +/// + +/// tip | सुझाव + +`response_class=HTMLResponse` declare करने से docs UI यह जान पाएगा कि response HTML होगा। + +/// + +/// note | तकनीकी विवरण + +आप `from starlette.templating import Jinja2Templates` भी उपयोग कर सकते हैं। + +**FastAPI** आपकी सुविधा के लिए, developer के रूप में, वही `starlette.templating` `fastapi.templating` के रूप में प्रदान करता है। लेकिन उपलब्ध अधिकांश responses सीधे Starlette से आते हैं। `Request` और `StaticFiles` के साथ भी यही है। + +/// + +## Templates लिखना { #writing-templates } + +फिर आप `templates/item.html` पर एक template लिख सकते हैं, उदाहरण के लिए: + +```jinja hl_lines="7" +{!../../docs_src/templates/templates/item.html!} +``` + +### Template Context Values { #template-context-values } + +उस HTML में जिसमें यह शामिल है: + +{% raw %} + +```jinja +Item ID: {{ id }} +``` + +{% endraw %} + +...यह आपके द्वारा pass किए गए "context" `dict` से लिया गया `id` दिखाएगा: + +```Python +{"id": id} +``` + +उदाहरण के लिए, `42` की ID के साथ, यह render होगा: + +```html +Item ID: 42 +``` + +### Template `url_for` Arguments { #template-url-for-arguments } + +आप template के अंदर `url_for()` का भी उपयोग कर सकते हैं, यह arguments के रूप में वही arguments लेता है जो आपके *path operation function* द्वारा उपयोग किए जाते। + +इसलिए, इस section के साथ: + +{% raw %} + +```jinja + +``` + +{% endraw %} + +...यह उसी URL का link generate करेगा जिसे *path operation function* `read_item(id=id)` handle करेगा। + +उदाहरण के लिए, `42` की ID के साथ, यह render होगा: + +```html + +``` + +## Templates और static files { #templates-and-static-files } + +आप template के अंदर `url_for()` का भी उपयोग कर सकते हैं, और इसे, उदाहरण के लिए, उन `StaticFiles` के साथ उपयोग कर सकते हैं जिन्हें आपने `name="static"` के साथ mount किया है। + +```jinja hl_lines="4" +{!../../docs_src/templates/templates/item.html!} +``` + +इस उदाहरण में, यह `static/styles.css` पर मौजूद CSS file से link करेगा: + +```CSS hl_lines="4" +{!../../docs_src/templates/static/styles.css!} +``` + +और क्योंकि आप `StaticFiles` उपयोग कर रहे हैं, वह CSS file आपके **FastAPI** application द्वारा URL `/static/styles.css` पर automatic रूप से serve की जाएगी। + +## अधिक विवरण { #more-details } + +अधिक विवरण के लिए, जिसमें templates को test करना भी शामिल है, [templates पर Starlette के docs](https://www.starlette.dev/templates/) देखें। diff --git a/docs/hi/docs/advanced/testing-dependencies.md b/docs/hi/docs/advanced/testing-dependencies.md new file mode 100644 index 000000000..f8eb0f312 --- /dev/null +++ b/docs/hi/docs/advanced/testing-dependencies.md @@ -0,0 +1,53 @@ +# Overrides के साथ Dependencies की Testing { #testing-dependencies-with-overrides } + +## Testing के दौरान dependencies को override करना { #overriding-dependencies-during-testing } + +कुछ scenarios होते हैं जहाँ आप testing के दौरान किसी dependency को override करना चाह सकते हैं। + +आप नहीं चाहते कि original dependency चले (और न ही उसकी कोई sub-dependencies चलें)। + +इसके बजाय, आप एक अलग dependency देना चाहते हैं जो केवल tests के दौरान इस्तेमाल होगी (संभवतः केवल कुछ खास tests में), और वह एक ऐसा value देगी जिसे वहाँ इस्तेमाल किया जा सके जहाँ original dependency का value इस्तेमाल किया जाता था। + +### Use cases: external service { #use-cases-external-service } + +एक उदाहरण यह हो सकता है कि आपके पास एक external authentication provider हो जिसे आपको call करना हो। + +आप उसे एक token भेजते हैं और वह एक authenticated user लौटाता है। + +यह provider आपसे प्रति request शुल्क ले सकता है, और इसे call करने में tests के लिए एक fixed mock user रखने की तुलना में कुछ अतिरिक्त समय लग सकता है। + +आप शायद external provider को एक बार test करना चाहेंगे, लेकिन हर चलने वाले test के लिए उसे call करना जरूरी नहीं होगा। + +इस मामले में, आप उस dependency को override कर सकते हैं जो उस provider को call करती है, और अपनी tests के लिए एक custom dependency इस्तेमाल कर सकते हैं जो एक mock user लौटाती है। + +### `app.dependency_overrides` attribute का उपयोग करें { #use-the-app-dependency-overrides-attribute } + +इन मामलों के लिए, आपकी **FastAPI** application में एक attribute `app.dependency_overrides` होता है, यह एक simple `dict` है। + +Testing के लिए किसी dependency को override करने के लिए, आप key के रूप में original dependency (एक function) रखते हैं, और value के रूप में अपना dependency override (दूसरा function) रखते हैं। + +और फिर **FastAPI** original dependency की बजाय उस override को call करेगा। + +{* ../../docs_src/dependency_testing/tutorial001_an_py310.py hl[26:27,30] *} + +/// tip | सुझाव + +आप अपनी **FastAPI** application में कहीं भी इस्तेमाल की गई dependency के लिए dependency override set कर सकते हैं। + +Original dependency किसी *path operation function*, किसी *path operation decorator* (जब आप return value का उपयोग नहीं करते), किसी `.include_router()` call आदि में इस्तेमाल हो सकती है। + +FastAPI फिर भी उसे override कर पाएगा। + +/// + +फिर आप `app.dependency_overrides` को एक खाली `dict` पर set करके अपने overrides reset कर सकते हैं (उन्हें हटा सकते हैं): + +```Python +app.dependency_overrides = {} +``` + +/// tip | सुझाव + +यदि आप किसी dependency को केवल कुछ tests के दौरान override करना चाहते हैं, तो आप test की शुरुआत में (test function के अंदर) override set कर सकते हैं और अंत में (test function के अंत में) उसे reset कर सकते हैं। + +/// diff --git a/docs/hi/docs/advanced/testing-events.md b/docs/hi/docs/advanced/testing-events.md new file mode 100644 index 000000000..3f09fe193 --- /dev/null +++ b/docs/hi/docs/advanced/testing-events.md @@ -0,0 +1,12 @@ +# Testing Events: lifespan और startup - shutdown { #testing-events-lifespan-and-startup-shutdown } + +जब आपको अपने tests में `lifespan` चलाने की ज़रूरत हो, तो आप `with` statement के साथ `TestClient` का उपयोग कर सकते हैं: + +{* ../../docs_src/app_testing/tutorial004_py310.py hl[9:15,18,27:28,30:32,41:43] *} + + +आप इसके बारे में अधिक विवरण ["आधिकारिक Starlette documentation site में tests में lifespan चलाना।"](https://www.starlette.dev/lifespan/#running-lifespan-in-tests) में पढ़ सकते हैं। + +deprecated `startup` और `shutdown` event के लिए, आप `TestClient` का उपयोग इस प्रकार कर सकते हैं: + +{* ../../docs_src/app_testing/tutorial003_py310.py hl[9:12,20:24] *} diff --git a/docs/hi/docs/advanced/testing-websockets.md b/docs/hi/docs/advanced/testing-websockets.md new file mode 100644 index 000000000..470b079a8 --- /dev/null +++ b/docs/hi/docs/advanced/testing-websockets.md @@ -0,0 +1,13 @@ +# WebSockets की Testing { #testing-websockets } + +आप WebSockets को test करने के लिए उसी `TestClient` का उपयोग कर सकते हैं। + +इसके लिए, आप `TestClient` को एक `with` statement में उपयोग करते हैं, WebSocket से connect करते हुए: + +{* ../../docs_src/app_testing/tutorial002_py310.py hl[27:31] *} + +/// note | नोट + +अधिक जानकारी के लिए, Starlette की documentation में [WebSockets की testing](https://www.starlette.dev/testclient/#testing-websocket-sessions) देखें। + +/// diff --git a/docs/hi/docs/advanced/using-request-directly.md b/docs/hi/docs/advanced/using-request-directly.md new file mode 100644 index 000000000..8110e550f --- /dev/null +++ b/docs/hi/docs/advanced/using-request-directly.md @@ -0,0 +1,56 @@ +# Request को सीधे इस्तेमाल करना { #using-the-request-directly } + +अब तक, आप request के जिन हिस्सों की ज़रूरत है, उन्हें उनके types के साथ declare करते रहे हैं। + +Data लेना: + +* path से parameters के रूप में। +* Headers। +* Cookies। +* आदि। + +और ऐसा करके, **FastAPI** उस data को validate कर रहा है, उसे convert कर रहा है और आपकी API के लिए documentation अपने-आप generate कर रहा है। + +लेकिन ऐसी स्थितियाँ होती हैं जहाँ आपको `Request` object को सीधे access करने की ज़रूरत हो सकती है। + +## `Request` object के बारे में विवरण { #details-about-the-request-object } + +क्योंकि **FastAPI** असल में नीचे से **Starlette** है, जिसके ऊपर कई tools की एक layer है, इसलिए जब ज़रूरत हो, आप Starlette के [`Request`](https://www.starlette.dev/requests/) object को सीधे इस्तेमाल कर सकते हैं। + +इसका मतलब यह भी होगा कि अगर आप `Request` object से सीधे data लेते हैं (उदाहरण के लिए, body पढ़ते हैं), तो FastAPI उसे validate, convert या document नहीं करेगा (OpenAPI के साथ, automatic API user interface के लिए)। + +हालाँकि कोई भी अन्य parameter जो सामान्य रूप से declare किया गया हो (उदाहरण के लिए, Pydantic model के साथ body), वह फिर भी validate, convert, annotate आदि होगा। + +लेकिन कुछ विशिष्ट मामले हैं जहाँ `Request` object लेना उपयोगी होता है। + +## `Request` object को सीधे इस्तेमाल करें { #use-the-request-object-directly } + +मान लीजिए कि आप अपनी *path operation function* के अंदर client का IP address/host लेना चाहते हैं। + +इसके लिए आपको request को सीधे access करना होगा। + +{* ../../docs_src/using_request_directly/tutorial001_py310.py hl[1,7:8] *} + +`Request` type वाले *path operation function* parameter को declare करके, **FastAPI** जान जाएगा कि उस parameter में `Request` pass करना है। + +/// tip | सुझाव + +ध्यान दें कि इस मामले में, हम request parameter के साथ एक path parameter declare कर रहे हैं। + +इसलिए, path parameter extract किया जाएगा, validate किया जाएगा, specified type में convert किया जाएगा और OpenAPI के साथ annotate किया जाएगा। + +इसी तरह, आप किसी भी अन्य parameter को सामान्य रूप से declare कर सकते हैं, और साथ ही `Request` भी प्राप्त कर सकते हैं। + +/// + +## `Request` documentation { #request-documentation } + +आप [`Request` object के बारे में official Starlette documentation site](https://www.starlette.dev/requests/) पर और विवरण पढ़ सकते हैं। + +/// note | तकनीकी विवरण + +आप `from starlette.requests import Request` भी इस्तेमाल कर सकते हैं। + +**FastAPI** इसे सीधे सिर्फ आपकी, developer की, सुविधा के लिए प्रदान करता है। लेकिन यह सीधे Starlette से आता है। + +/// diff --git a/docs/hi/docs/advanced/websockets.md b/docs/hi/docs/advanced/websockets.md new file mode 100644 index 000000000..9e761a900 --- /dev/null +++ b/docs/hi/docs/advanced/websockets.md @@ -0,0 +1,186 @@ +# WebSockets { #websockets } + +आप **FastAPI** के साथ [WebSockets](https://developer.mozilla.org/en-US/docs/Web/API/WebSockets_API) का उपयोग कर सकते हैं। + +## `websockets` install करें { #install-websockets } + +सुनिश्चित करें कि आप एक [virtual environment](../virtual-environments.md) बनाएँ, उसे activate करें, और `websockets` install करें (एक Python library जो "WebSocket" protocol का उपयोग आसान बनाती है): + +
+ +```console +$ pip install websockets + +---> 100% +``` + +
+ +## WebSockets client { #websockets-client } + +### production में { #in-production } + +आपके production system में, संभवतः आपके पास React, Vue.js या Angular जैसे आधुनिक framework से बना frontend होगा। + +और अपने backend के साथ WebSockets का उपयोग करके संवाद करने के लिए आप संभवतः अपने frontend की utilities का उपयोग करेंगे। + +या आपके पास एक native mobile application हो सकती है जो सीधे native code में आपके WebSocket backend से संवाद करती हो। + +या आपके पास WebSocket endpoint से संवाद करने का कोई और तरीका हो सकता है। + +--- + +लेकिन इस उदाहरण के लिए, हम कुछ JavaScript के साथ एक बहुत सरल HTML document का उपयोग करेंगे, सब कुछ एक लंबी string के अंदर। + +बेशक, यह optimal नहीं है और आप इसे production के लिए उपयोग नहीं करेंगे। + +production में आपके पास ऊपर दिए गए विकल्पों में से एक होगा। + +लेकिन WebSockets के server-side पर ध्यान केंद्रित करने और एक working उदाहरण पाने का यह सबसे सरल तरीका है: + +{* ../../docs_src/websockets_/tutorial001_py310.py hl[2,6:38,41:43] *} + +## एक `websocket` बनाएँ { #create-a-websocket } + +अपने **FastAPI** application में, एक `websocket` बनाएँ: + +{* ../../docs_src/websockets_/tutorial001_py310.py hl[1,46:47] *} + +/// note | तकनीकी विवरण + +आप `from starlette.websockets import WebSocket` का भी उपयोग कर सकते हैं। + +**FastAPI** वही `WebSocket` सीधे उपलब्ध कराता है, सिर्फ़ आपकी सुविधा के लिए, developer के रूप में। लेकिन यह सीधे Starlette से आता है। + +/// + +## messages का await करें और messages भेजें { #await-for-messages-and-send-messages } + +अपने WebSocket route में आप messages के लिए `await` कर सकते हैं और messages भेज सकते हैं। + +{* ../../docs_src/websockets_/tutorial001_py310.py hl[48:52] *} + +आप binary, text, और JSON data receive और send कर सकते हैं। + +## इसे आज़माएँ { #try-it } + +अपना code `main.py` file में रखें और फिर अपना application चलाएँ: + +
+ +```console +$ fastapi dev + +INFO: Uvicorn running on http://127.0.0.1:8000 (Press CTRL+C to quit) +``` + +
+ +अपने browser में [http://127.0.0.1:8000](http://127.0.0.1:8000) खोलें। + +आपको ऐसा एक सरल page दिखेगा: + + + +आप input box में messages टाइप कर सकते हैं, और उन्हें भेज सकते हैं: + + + +और WebSockets के साथ आपका **FastAPI** application जवाब देगा: + + + +आप कई messages भेज (और receive कर) सकते हैं: + + + +और वे सभी उसी WebSocket connection का उपयोग करेंगे। + +## `Depends` और अन्य का उपयोग { #using-depends-and-others } + +WebSocket endpoints में आप `fastapi` से import कर सकते हैं और उपयोग कर सकते हैं: + +* `Depends` +* `Security` +* `Cookie` +* `Header` +* `Path` +* `Query` + +वे अन्य FastAPI endpoints/*path operations* की तरह ही काम करते हैं: + +{* ../../docs_src/websockets_/tutorial002_an_py310.py hl[68:69,82] *} + +/// note | नोट + +क्योंकि यह एक WebSocket है, इसलिए `HTTPException` raise करना वास्तव में उचित नहीं है, इसके बजाय हम `WebSocketException` raise करते हैं। + +आप [specification में परिभाषित valid codes](https://tools.ietf.org/html/rfc6455#section-7.4.1) में से एक closing code का उपयोग कर सकते हैं। + +/// + +### dependencies के साथ WebSockets आज़माएँ { #try-the-websockets-with-dependencies } + +अपना application चलाएँ: + +
+ +```console +$ fastapi dev + +INFO: Uvicorn running on http://127.0.0.1:8000 (Press CTRL+C to quit) +``` + +
+ +अपने browser में [http://127.0.0.1:8000](http://127.0.0.1:8000) खोलें। + +वहाँ आप सेट कर सकते हैं: + +* path में उपयोग किया गया "Item ID"। +* query parameter के रूप में उपयोग किया गया "Token"। + +/// tip | सुझाव + +ध्यान दें कि query `token` को एक dependency द्वारा handle किया जाएगा। + +/// + +इसके साथ आप WebSocket connect कर सकते हैं और फिर messages भेज और receive कर सकते हैं: + + + +## disconnections और कई clients को handle करना { #handling-disconnections-and-multiple-clients } + +जब WebSocket connection बंद होता है, तो `await websocket.receive_text()` एक `WebSocketDisconnect` exception raise करेगा, जिसे आप इस उदाहरण की तरह catch और handle कर सकते हैं। + +{* ../../docs_src/websockets_/tutorial003_py310.py hl[79:81] *} + +इसे आज़माने के लिए: + +* app को कई browser tabs में खोलें। +* उनसे messages लिखें। +* फिर tabs में से एक को बंद करें। + +इससे `WebSocketDisconnect` exception raise होगा, और बाकी सभी clients को ऐसा message मिलेगा: + +``` +Client #1596980209979 left the chat +``` + +/// tip | सुझाव + +ऊपर दिया गया app एक minimal और सरल उदाहरण है, जो दिखाता है कि कई WebSocket connections को messages कैसे handle और broadcast किए जाएँ। + +लेकिन ध्यान रखें कि, चूँकि सब कुछ memory में, एक ही list में handle किया जाता है, यह केवल तब तक काम करेगा जब तक process चल रहा है, और केवल एक single process के साथ काम करेगा। + +अगर आपको कुछ ऐसा चाहिए जिसे FastAPI के साथ integrate करना आसान हो लेकिन जो अधिक robust हो, Redis, PostgreSQL या अन्य द्वारा supported हो, तो [encode/broadcaster](https://github.com/encode/broadcaster) देखें। + +/// + +## अधिक जानकारी { #more-info } + +विकल्पों के बारे में अधिक जानने के लिए, इनके लिए Starlette का documentation देखें: + +* [`WebSocket` class](https://www.starlette.dev/websockets/)। +* [Class-based WebSocket handling](https://www.starlette.dev/endpoints/#websocketendpoint)। diff --git a/docs/hi/docs/advanced/wsgi.md b/docs/hi/docs/advanced/wsgi.md new file mode 100644 index 000000000..1ea60d4e9 --- /dev/null +++ b/docs/hi/docs/advanced/wsgi.md @@ -0,0 +1,51 @@ +# WSGI शामिल करना - Flask, Django, अन्य { #including-wsgi-flask-django-others } + +आप WSGI applications को mount कर सकते हैं, जैसा आपने [Sub Applications - Mounts](sub-applications.md), [Proxy के पीछे](behind-a-proxy.md) में देखा। + +इसके लिए, आप `WSGIMiddleware` का उपयोग कर सकते हैं और इसे अपनी WSGI application को wrap करने के लिए इस्तेमाल कर सकते हैं, उदाहरण के लिए, Flask, Django, आदि। + +## `WSGIMiddleware` का उपयोग करना { #using-wsgimiddleware } + +/// note | नोट + +इसके लिए `a2wsgi` install करना required है, उदाहरण के लिए `pip install a2wsgi` के साथ। + +/// + +आपको `a2wsgi` से `WSGIMiddleware` import करना होगा। + +फिर WSGI (जैसे Flask) app को middleware के साथ wrap करें। + +और फिर उसे किसी path के अंतर्गत mount करें। + +{* ../../docs_src/wsgi/tutorial001_py310.py hl[1,3,23] *} + +/// note | नोट + +पहले, `fastapi.middleware.wsgi` से `WSGIMiddleware` का उपयोग करने की सलाह दी जाती थी, लेकिन अब यह deprecated है। + +इसके बजाय `a2wsgi` package का उपयोग करने की सलाह दी जाती है। उपयोग वही रहता है। + +बस यह सुनिश्चित करें कि आपके पास `a2wsgi` package install है और आप `a2wsgi` से `WSGIMiddleware` को सही ढंग से import करते हैं। + +/// + +## इसे जाँचें { #check-it } + +अब, path `/v1/` के अंतर्गत हर request को Flask application द्वारा handle किया जाएगा। + +और बाकी को **FastAPI** द्वारा handle किया जाएगा। + +यदि आप इसे run करते हैं और [http://localhost:8000/v1/](http://localhost:8000/v1/) पर जाते हैं, तो आपको Flask से response दिखाई देगा: + +```txt +Hello, World from Flask! +``` + +और यदि आप [http://localhost:8000/v2](http://localhost:8000/v2) पर जाते हैं, तो आपको FastAPI से response दिखाई देगा: + +```JSON +{ + "message": "Hello World" +} +``` diff --git a/docs/hi/docs/deployment/cloud.md b/docs/hi/docs/deployment/cloud.md new file mode 100644 index 000000000..f4c6087d3 --- /dev/null +++ b/docs/hi/docs/deployment/cloud.md @@ -0,0 +1,24 @@ +# Cloud Providers पर FastAPI Deploy करें { #deploy-fastapi-on-cloud-providers } + +आप अपनी FastAPI application deploy करने के लिए वस्तुतः **किसी भी cloud provider** का उपयोग कर सकते हैं। + +अधिकांश मामलों में, मुख्य cloud providers के पास उनके साथ FastAPI deploy करने के लिए guides होती हैं। + +## FastAPI Cloud { #fastapi-cloud } + +**[FastAPI Cloud](https://fastapicloud.com)** को **FastAPI** के पीछे मौजूद उसी author और team ने बनाया है। + +यह न्यूनतम प्रयास के साथ API को **build**, **deploy**, और **access** करने की प्रक्रिया को सरल बनाता है। + +यह FastAPI के साथ apps बनाने वाले उसी **developer experience** को उन्हें cloud पर **deploy** करने में भी लाता है। 🎉 + +FastAPI Cloud, *FastAPI and friends* open source projects का प्राथमिक sponsor और funding provider है। ✨ + +## Cloud Providers - Sponsors { #cloud-providers-sponsors } + +कुछ अन्य cloud providers भी ✨ [**FastAPI को sponsor करते हैं**](https://github.com/sponsors/tiangolo) ✨। 🙇 + +आप उनकी guides का पालन करने और उनकी services आज़माने के लिए उन पर भी विचार कर सकते हैं: + +* [Render](https://docs.render.com/deploy-fastapi?utm_source=deploydoc&utm_medium=referral&utm_campaign=fastapi) +* [Railway](https://docs.railway.com/guides/fastapi?utm_medium=integration&utm_source=docs&utm_campaign=fastapi) diff --git a/docs/hi/docs/deployment/concepts.md b/docs/hi/docs/deployment/concepts.md new file mode 100644 index 000000000..de085e34b --- /dev/null +++ b/docs/hi/docs/deployment/concepts.md @@ -0,0 +1,321 @@ +# Deployments की अवधारणाएँ { #deployments-concepts } + +जब आप एक **FastAPI** application, या वास्तव में किसी भी प्रकार की web API, deploy करते हैं, तो कई अवधारणाएँ होती हैं जिनकी आपको शायद परवाह होगी, और उनका उपयोग करके आप अपनी application को **deploy करने** का **सबसे उपयुक्त** तरीका ढूँढ सकते हैं। + +कुछ महत्वपूर्ण अवधारणाएँ हैं: + +* सुरक्षा - HTTPS +* startup पर चलना +* Restarts +* Replication (चल रहे processes की संख्या) +* Memory +* शुरू करने से पहले के पिछले steps + +हम देखेंगे कि ये **deployments** को कैसे प्रभावित करेंगे। + +अंत में, अंतिम उद्देश्य यह है कि आप अपने **API clients को serve** कर सकें, वह भी ऐसे तरीके से जो **सुरक्षित** हो, **disruptions से बचाए**, और **compute resources** (जैसे remote servers/virtual machines) का यथासंभव कुशलता से उपयोग करे। 🚀 + +मैं यहाँ इन **अवधारणाओं** के बारे में थोड़ा और बताऊँगा, और उम्मीद है कि इससे आपको वह **intuition** मिलेगी जिसकी आपको अपनी API को बहुत अलग-अलग environments में deploy करने का निर्णय लेने के लिए आवश्यकता होगी, संभवतः ऐसे **future** environments में भी जो अभी मौजूद नहीं हैं। + +इन अवधारणाओं पर विचार करके, आप **अपनी खुद की APIs** को deploy करने का सबसे अच्छा तरीका **evaluate और design** कर पाएँगे। + +अगले chapters में, मैं आपको FastAPI applications deploy करने के लिए अधिक **ठोस recipes** दूँगा। + +लेकिन अभी के लिए, आइए इन महत्वपूर्ण **conceptual ideas** को देखें। ये अवधारणाएँ किसी भी अन्य प्रकार की web API पर भी लागू होती हैं। 💡 + +## सुरक्षा - HTTPS { #security-https } + +[HTTPS के बारे में पिछले chapter](https.md) में हमने सीखा कि HTTPS आपकी API के लिए encryption कैसे प्रदान करता है। + +हमने यह भी देखा कि HTTPS सामान्यतः आपके application server से **external** एक component, एक **TLS Termination Proxy**, द्वारा प्रदान किया जाता है। + +और **HTTPS certificates renew** करने का प्रभारी कुछ होना चाहिए, यह वही component हो सकता है या कुछ अलग भी हो सकता है। + +### HTTPS के लिए उदाहरण Tools { #example-tools-for-https } + +TLS Termination Proxy के रूप में आप जिन tools का उपयोग कर सकते हैं, उनमें से कुछ हैं: + +* Traefik + * Certificate renewals को अपने-आप संभालता है ✨ +* Caddy + * Certificate renewals को अपने-आप संभालता है ✨ +* Nginx + * Certificate renewals के लिए Certbot जैसे external component के साथ +* HAProxy + * Certificate renewals के लिए Certbot जैसे external component के साथ +* Nginx जैसे Ingress Controller के साथ Kubernetes + * Certificate renewals के लिए cert-manager जैसे external component के साथ +* Cloud provider द्वारा उनकी services के हिस्से के रूप में internally संभाला गया (नीचे पढ़ें 👇) + +एक और विकल्प यह है कि आप एक **cloud service** का उपयोग कर सकते हैं जो HTTPS setup करने सहित अधिक काम करती है। इसमें कुछ restrictions हो सकती हैं या आपसे अधिक charge लिया जा सकता है, आदि। लेकिन उस स्थिति में, आपको स्वयं TLS Termination Proxy setup नहीं करना पड़ेगा। + +अगले chapters में मैं आपको कुछ ठोस उदाहरण दिखाऊँगा। + +--- + +फिर विचार करने के लिए अगले concepts उस program के बारे में हैं जो आपकी वास्तविक API चला रहा है (जैसे Uvicorn)। + +## Program और Process { #program-and-process } + +हम चल रहे "**process**" के बारे में बहुत बात करेंगे, इसलिए यह स्पष्ट होना उपयोगी है कि इसका क्या अर्थ है, और "**program**" शब्द से इसका क्या अंतर है। + +### Program क्या है { #what-is-a-program } + +**Program** शब्द का उपयोग आम तौर पर कई चीजों का वर्णन करने के लिए किया जाता है: + +* वह **code** जो आप लिखते हैं, **Python files**। +* वह **file** जिसे operating system द्वारा **execute** किया जा सकता है, उदाहरण के लिए: `python`, `python.exe` या `uvicorn`। +* कोई विशेष program जब वह operating system पर **चल रहा** हो, CPU का उपयोग कर रहा हो, और memory में चीजें store कर रहा हो। इसे **process** भी कहा जाता है। + +### Process क्या है { #what-is-a-process } + +**Process** शब्द सामान्यतः अधिक विशिष्ट तरीके से उपयोग किया जाता है, केवल उस चीज़ के लिए जो operating system में चल रही होती है (जैसे ऊपर के अंतिम point में): + +* कोई विशेष program जब वह operating system पर **चल रहा** हो। + * यह न तो file को refer करता है, न code को, यह **विशेष रूप से** उस चीज़ को refer करता है जिसे operating system द्वारा **execute** और manage किया जा रहा है। +* कोई भी program, कोई भी code, **केवल तभी कुछ कर सकता है** जब उसे **execute** किया जा रहा हो। यानी, जब कोई **process चल रहा** हो। +* Process को आपके द्वारा, या operating system द्वारा **terminate** (या "kill") किया जा सकता है। उस point पर, वह चलना/execute होना बंद कर देता है, और वह **अब कुछ नहीं कर सकता**। +* आपके computer पर चल रही प्रत्येक application के पीछे कोई process होता है, प्रत्येक running program, प्रत्येक window, आदि। और computer चालू होने पर सामान्यतः कई processes **एक ही समय में** चल रहे होते हैं। +* **एक ही program** के **multiple processes** एक ही समय में चल सकते हैं। + +यदि आप अपने operating system में "task manager" या "system monitor" (या समान tools) देखते हैं, तो आप उनमें से कई processes चलते हुए देख पाएँगे। + +और, उदाहरण के लिए, आप शायद देखेंगे कि एक ही browser program (Firefox, Chrome, Edge, आदि) को चलाने वाले multiple processes हैं। वे सामान्यतः प्रति tab एक process चलाते हैं, साथ में कुछ अन्य extra processes भी। + + + +--- + +अब जब हम **process** और **program** शब्दों के बीच अंतर जानते हैं, तो deployments के बारे में बात जारी रखते हैं। + +## startup पर चलना { #running-on-startup } + +अधिकांश मामलों में, जब आप एक web API बनाते हैं, तो आप चाहते हैं कि वह **हमेशा चलती रहे**, बिना interruption के, ताकि आपके clients हमेशा उसे access कर सकें। यह निश्चित रूप से तब तक है जब तक आपके पास कोई विशेष कारण न हो कि आप उसे केवल कुछ स्थितियों में ही चलाना चाहते हैं, लेकिन अधिकांश समय आप चाहते हैं कि वह लगातार चलती रहे और **available** रहे। + +### Remote Server में { #in-a-remote-server } + +जब आप एक remote server (एक cloud server, एक virtual machine, आदि) setup करते हैं, तो सबसे सरल चीज़ जो आप कर सकते हैं वह है `fastapi run` (जो Uvicorn का उपयोग करता है) या कुछ समान, manually, ठीक उसी तरह जैसे आप local development करते समय करते हैं। + +और यह काम करेगा और **development के दौरान** उपयोगी होगा। + +लेकिन यदि server से आपका connection खो जाता है, तो **running process** शायद मर जाएगा। + +और यदि server restart होता है (उदाहरण के लिए updates के बाद, या cloud provider से migrations के बाद) तो आप शायद **इसे notice नहीं करेंगे**। और इसके कारण, आपको यह भी पता नहीं चलेगा कि आपको process को manually restart करना है। इसलिए, आपकी API बस dead ही रहेगी। 😱 + +### Startup पर Automatically चलाना { #run-automatically-on-startup } + +सामान्यतः, आप शायद चाहेंगे कि server program (जैसे Uvicorn) server startup पर automatically start हो, और किसी **human intervention** की आवश्यकता के बिना, ताकि आपकी API के साथ हमेशा एक process चल रहा हो (जैसे Uvicorn आपकी FastAPI app चला रहा हो)। + +### अलग Program { #separate-program } + +इसे हासिल करने के लिए, आपके पास सामान्यतः एक **अलग program** होगा जो सुनिश्चित करेगा कि आपकी application startup पर चले। और कई मामलों में, यह यह भी सुनिश्चित करेगा कि अन्य components या applications भी चलें, उदाहरण के लिए, एक database। + +### Startup पर चलाने के लिए उदाहरण Tools { #example-tools-to-run-at-startup } + +इस काम को करने वाले tools के कुछ उदाहरण हैं: + +* Docker +* Kubernetes +* Docker Compose +* Docker in Swarm Mode +* Systemd +* Supervisor +* Cloud provider द्वारा उनकी services के हिस्से के रूप में internally संभाला गया +* अन्य... + +अगले chapters में मैं आपको अधिक ठोस उदाहरण दूँगा। + +## Restarts { #restarts } + +यह सुनिश्चित करने जैसा कि आपकी application startup पर चले, आप शायद यह भी सुनिश्चित करना चाहेंगे कि failures के बाद उसे **restart** किया जाए। + +### हम गलतियाँ करते हैं { #we-make-mistakes } + +हम, मनुष्य के रूप में, हर समय **गलतियाँ** करते हैं। Software में लगभग *हमेशा* अलग-अलग जगहों पर **bugs** छिपे होते हैं। 🐛 + +और हम developers उन bugs को खोजते हुए और नई features implement करते हुए code को बेहतर बनाते रहते हैं (संभवतः नए bugs भी जोड़ते हुए 😅)। + +### छोटे Errors Automatically संभाले जाते हैं { #small-errors-automatically-handled } + +FastAPI के साथ web APIs बनाते समय, यदि हमारे code में कोई error है, तो FastAPI सामान्यतः उसे उस single request तक सीमित रखेगा जिसने error trigger किया। 🛡 + +Client को उस request के लिए **500 Internal Server Error** मिलेगा, लेकिन application पूरी तरह crash होने के बजाय अगली requests के लिए काम करती रहेगी। + +### बड़े Errors - Crashes { #bigger-errors-crashes } + +फिर भी, ऐसे मामले हो सकते हैं जहाँ हम कुछ code लिखते हैं जो **पूरी application को crash** कर देता है, जिससे Uvicorn और Python crash हो जाते हैं। 💥 + +और फिर भी, आप शायद नहीं चाहेंगे कि application केवल इसलिए dead रहे क्योंकि एक जगह error था, आप शायद चाहेंगे कि वह कम से कम उन *path operations* के लिए **चलती रहे** जो broken नहीं हैं। + +### Crash के बाद Restart { #restart-after-crash } + +लेकिन उन मामलों में जहाँ वास्तव में खराब errors running **process** को crash कर देते हैं, आप चाहेंगे कि एक external component process को **restart** करने का प्रभारी हो, कम से कम कुछ बार... + +/// tip | सुझाव + +...हालाँकि यदि पूरी application बस **तुरंत crash** हो रही है तो शायद उसे हमेशा restart करते रहने का कोई अर्थ नहीं है। लेकिन ऐसे मामलों में, आप शायद इसे development के दौरान, या कम से कम deployment के ठीक बाद notice करेंगे। + +तो आइए मुख्य मामलों पर focus करें, जहाँ यह **future** में कुछ विशेष मामलों में पूरी तरह crash हो सकती है, और फिर भी उसे restart करना समझ में आता है। + +/// + +आप शायद चाहेंगे कि आपकी application को restart करने का प्रभारी एक **external component** हो, क्योंकि उस point तक, Uvicorn और Python वाली वही application पहले ही crash हो चुकी होती है, इसलिए उसी app के उसी code में ऐसा कुछ नहीं होता जो इसके बारे में कुछ कर सके। + +### Automatically Restart करने के लिए उदाहरण Tools { #example-tools-to-restart-automatically } + +अधिकांश मामलों में, वही tool जो **startup पर program चलाने** के लिए उपयोग होता है, automatic **restarts** संभालने के लिए भी उपयोग होता है। + +उदाहरण के लिए, इसे ये संभाल सकते हैं: + +* Docker +* Kubernetes +* Docker Compose +* Docker in Swarm Mode +* Systemd +* Supervisor +* Cloud provider द्वारा उनकी services के हिस्से के रूप में internally संभाला गया +* अन्य... + +## Replication - Processes और Memory { #replication-processes-and-memory } + +FastAPI application के साथ, Uvicorn चलाने वाले `fastapi` command जैसे server program का उपयोग करते हुए, उसे **एक process** में एक बार चलाना multiple clients को concurrently serve कर सकता है। + +लेकिन कई मामलों में, आप एक ही समय में कई worker processes चलाना चाहेंगे। + +### Multiple Processes - Workers { #multiple-processes-workers } + +यदि आपके पास single process द्वारा handle किए जा सकने से अधिक clients हैं (उदाहरण के लिए यदि virtual machine बहुत बड़ी नहीं है) और server के CPU में **multiple cores** हैं, तो आप एक ही application के साथ **multiple processes** एक ही समय में चला सकते हैं, और सभी requests को उनके बीच distribute कर सकते हैं। + +जब आप उसी API program के **multiple processes** चलाते हैं, तो उन्हें आम तौर पर **workers** कहा जाता है। + +### Worker Processes और Ports { #worker-processes-and-ports } + +Docs [About HTTPS](https.md) से याद करें कि server में port और IP address के एक combination पर केवल एक process listen कर सकता है? + +यह अभी भी सही है। + +इसलिए, एक ही समय में **multiple processes** रखने में सक्षम होने के लिए, एक **single process port पर listening** होना चाहिए जो फिर communication को किसी तरीके से प्रत्येक worker process तक transmit करे। + +### प्रति Process Memory { #memory-per-process } + +अब, जब program memory में चीजें load करता है, उदाहरण के लिए, किसी variable में machine learning model, या किसी बड़े file की contents किसी variable में, तो वह सब server की **memory (RAM) का थोड़ा हिस्सा consume** करता है। + +और multiple processes सामान्यतः **कोई memory share नहीं करते**। इसका मतलब है कि प्रत्येक running process की अपनी चीजें, variables, और memory होती है। और यदि आप अपने code में बड़ी मात्रा में memory consume कर रहे हैं, तो **प्रत्येक process** उतनी ही memory consume करेगा। + +### Server Memory { #server-memory } + +उदाहरण के लिए, यदि आपका code **1 GB size** वाला Machine Learning model load करता है, तो जब आप अपनी API के साथ एक process चलाते हैं, तो वह कम से कम 1 GB RAM consume करेगा। और यदि आप **4 processes** (4 workers) start करते हैं, तो प्रत्येक 1 GB RAM consume करेगा। इसलिए कुल मिलाकर, आपकी API **4 GB RAM** consume करेगी। + +और यदि आपके remote server या virtual machine में केवल 3 GB RAM है, तो 4 GB से अधिक RAM load करने की कोशिश problems पैदा करेगी। 🚨 + +### Multiple Processes - एक उदाहरण { #multiple-processes-an-example } + +इस उदाहरण में, एक **Manager Process** है जो दो **Worker Processes** start और control करता है। + +यह Manager Process शायद IP में **port** पर listen करने वाला होगा। और यह सभी communication को worker processes तक transmit करेगा। + +वे worker processes वे होंगे जो आपकी application चला रहे होंगे, वे **request** प्राप्त करने और **response** return करने के लिए मुख्य computations करेंगे, और वे RAM में variables में डाली गई कोई भी चीज़ load करेंगे। + + + +और निश्चित रूप से, उसी machine पर आपकी application के अलावा शायद **अन्य processes** भी चल रहे होंगे। + +एक दिलचस्प detail यह है कि प्रत्येक process द्वारा **उपयोग किए गए CPU** का percentage समय के साथ बहुत **बदल** सकता है, लेकिन **memory (RAM)** सामान्यतः कम या ज्यादा **stable** रहती है। + +यदि आपके पास एक API है जो हर बार comparable amount की computations करती है और आपके पास बहुत सारे clients हैं, तो **CPU utilization** शायद *stable भी रहेगा* (लगातार तेजी से ऊपर-नीचे जाने के बजाय)। + +### Replication Tools और Strategies के उदाहरण { #examples-of-replication-tools-and-strategies } + +इसे हासिल करने के कई approaches हो सकते हैं, और मैं अगले chapters में specific strategies के बारे में अधिक बताऊँगा, उदाहरण के लिए Docker और containers के बारे में बात करते समय। + +विचार करने की मुख्य constraint यह है कि **public IP** में **port** को handle करने वाला एक **single** component होना चाहिए। और फिर उसके पास replicated **processes/workers** तक communication **transmit** करने का कोई तरीका होना चाहिए। + +यहाँ कुछ संभावित combinations और strategies हैं: + +* **Uvicorn** `--workers` के साथ + * एक Uvicorn **process manager** **IP** और **port** पर listen करेगा, और यह **multiple Uvicorn worker processes** start करेगा। +* **Kubernetes** और अन्य distributed **container systems** + * **Kubernetes** layer में कुछ **IP** और **port** पर listen करेगा। Replication **multiple containers** रखने से होगी, प्रत्येक में **एक Uvicorn process** चल रहा होगा। +* **Cloud services** जो यह आपके लिए संभालती हैं + * Cloud service शायद **आपके लिए replication handle** करेगी। यह संभवतः आपको **चलाने के लिए process**, या उपयोग करने के लिए **container image** define करने देगी, किसी भी स्थिति में, यह बहुत संभवतः **एक single Uvicorn process** होगा, और cloud service उसे replicate करने की प्रभारी होगी। + +/// tip | सुझाव + +यदि **containers**, Docker, या Kubernetes के बारे में इनमें से कुछ items अभी अधिक समझ में नहीं आते हैं तो चिंता न करें। + +मैं future chapter में container images, Docker, Kubernetes, आदि के बारे में अधिक बताऊँगा: [Containers में FastAPI - Docker](docker.md)। + +/// + +## शुरू करने से पहले के पिछले Steps { #previous-steps-before-starting } + +कई मामले ऐसे होते हैं जहाँ आप अपनी application **start करने से पहले** कुछ steps perform करना चाहते हैं। + +उदाहरण के लिए, आप **database migrations** चलाना चाह सकते हैं। + +लेकिन अधिकांश मामलों में, आप इन steps को केवल **एक बार** perform करना चाहेंगे। + +इसलिए, आप application start करने से पहले उन **previous steps** को perform करने के लिए एक **single process** रखना चाहेंगे। + +और आपको यह सुनिश्चित करना होगा कि उन previous steps को चलाने वाला एक ही process हो, *भले ही* बाद में आप application के लिए **multiple processes** (multiple workers) start करें। यदि वे steps **multiple processes** द्वारा चलाए गए, तो वे उन्हें **parallel** में चलाकर काम को **duplicate** कर देंगे, और यदि steps database migration जैसी delicate चीज़ हैं, तो वे एक-दूसरे के साथ conflicts पैदा कर सकते हैं। + +बेशक, कुछ मामले ऐसे होते हैं जहाँ previous steps को multiple times चलाने में कोई समस्या नहीं होती, उस स्थिति में इसे handle करना बहुत आसान होता है। + +/// tip | सुझाव + +साथ ही, ध्यान रखें कि आपके setup पर निर्भर करते हुए, कुछ मामलों में आपकी application start करने से पहले आपको **शायद किसी previous steps की आवश्यकता भी न हो**। + +उस स्थिति में, आपको इनमें से किसी भी चीज़ की चिंता नहीं करनी होगी। 🤷 + +/// + +### Previous Steps Strategies के उदाहरण { #examples-of-previous-steps-strategies } + +यह इस बात पर **बहुत अधिक निर्भर** करेगा कि आप **अपना system कैसे deploy** करते हैं, और यह शायद programs start करने, restarts handle करने, आदि के तरीके से जुड़ा होगा। + +यहाँ कुछ संभावित ideas हैं: + +* Kubernetes में एक "Init Container" जो आपके app container से पहले चलता है +* एक bash script जो previous steps चलाती है और फिर आपकी application start करती है + * आपको फिर भी *उस* bash script को start/restart करने, errors detect करने, आदि का तरीका चाहिए होगा। + +/// tip | सुझाव + +Containers के साथ ऐसा करने के लिए मैं future chapter में अधिक ठोस उदाहरण दूँगा: [Containers में FastAPI - Docker](docker.md)। + +/// + +## Resource Utilization { #resource-utilization } + +आपके server(s) एक **resource** हैं, जिन्हें आप अपने programs के साथ consume या **utilize** कर सकते हैं, CPUs पर computation time और उपलब्ध RAM memory का उपयोग करके। + +आप system resources का कितना हिस्सा consume/utilize करना चाहते हैं? "बहुत ज्यादा नहीं" सोचना आसान हो सकता है, लेकिन वास्तव में, आप शायद **crash किए बिना जितना संभव हो उतना** consume करना चाहेंगे। + +यदि आप 3 servers के लिए भुगतान कर रहे हैं लेकिन उनकी RAM और CPU का केवल थोड़ा सा उपयोग कर रहे हैं, तो आप शायद **पैसा बर्बाद कर रहे हैं** 💸, और शायद **server की electric power बर्बाद कर रहे हैं** 🌎, आदि। + +उस स्थिति में, केवल 2 servers रखना और उनके resources (CPU, memory, disk, network bandwidth, आदि) का उच्च percentage उपयोग करना बेहतर हो सकता है। + +दूसरी ओर, यदि आपके पास 2 servers हैं और आप उनके **CPU और RAM का 100%** उपयोग कर रहे हैं, तो किसी point पर एक process अधिक memory माँगेगा, और server को disk को "memory" के रूप में उपयोग करना पड़ेगा (जो हजारों गुना धीमा हो सकता है), या वह **crash** भी हो सकता है। या किसी process को कुछ computation करनी हो सकती है और उसे CPU के फिर से free होने तक wait करना पड़ेगा। + +इस मामले में, **एक extra server** लेना और उस पर कुछ processes चलाना बेहतर होगा ताकि उन सभी के पास **पर्याप्त RAM और CPU time** हो। + +यह भी संभावना है कि किसी कारण से आपकी API के usage में **spike** हो। शायद यह viral हो गई, या शायद कुछ अन्य services या bots इसका उपयोग शुरू कर दें। और आप उन मामलों में safe रहने के लिए extra resources रखना चाह सकते हैं। + +आप target करने के लिए एक **arbitrary number** रख सकते हैं, उदाहरण के लिए, resource utilization का **50% से 90% के बीच** कुछ। बात यह है कि ये शायद वे मुख्य चीजें हैं जिन्हें आप measure करना और अपने deployments tweak करने के लिए उपयोग करना चाहेंगे। + +आप अपने server में उपयोग किए गए CPU और RAM या प्रत्येक process द्वारा उपयोग की गई मात्रा देखने के लिए `htop` जैसे simple tools का उपयोग कर सकते हैं। या आप अधिक complex monitoring tools का उपयोग कर सकते हैं, जो servers में distributed हो सकते हैं, आदि। + +## Recap { #recap } + +आपने यहाँ कुछ मुख्य अवधारणाएँ पढ़ी हैं जिन्हें अपनी application को कैसे deploy करना है, यह तय करते समय आपको शायद ध्यान में रखना होगा: + +* सुरक्षा - HTTPS +* startup पर चलना +* Restarts +* Replication (चल रहे processes की संख्या) +* Memory +* शुरू करने से पहले के पिछले steps + +इन ideas को समझना और उन्हें apply करना आपको अपने deployments configure और tweak करते समय कोई भी decisions लेने के लिए आवश्यक intuition देना चाहिए। 🤓 + +अगले sections में, मैं आपको उन संभावित strategies के अधिक ठोस उदाहरण दूँगा जिनका आप पालन कर सकते हैं। 🚀 diff --git a/docs/hi/docs/deployment/docker.md b/docs/hi/docs/deployment/docker.md new file mode 100644 index 000000000..6e8bea03a --- /dev/null +++ b/docs/hi/docs/deployment/docker.md @@ -0,0 +1,618 @@ +# Containers में FastAPI - Docker { #fastapi-in-containers-docker } + +FastAPI applications deploy करते समय एक आम तरीका **Linux container image** बनाना है। यह सामान्यतः [**Docker**](https://www.docker.com/) का उपयोग करके किया जाता है। फिर आप उस container image को कुछ संभावित तरीकों में से किसी एक में deploy कर सकते हैं। + +Linux containers का उपयोग करने के कई लाभ हैं, जिनमें **security**, **replicability**, **simplicity**, और अन्य शामिल हैं। + +/// tip | टिप + +जल्दी में हैं और यह सब पहले से जानते हैं? नीचे दिए गए [`Dockerfile` पर जाएँ 👇](#build-a-docker-image-for-fastapi). + +/// + +
+Dockerfile Preview 👀 + +```Dockerfile +FROM python:3.14 + +WORKDIR /code + +COPY ./requirements.txt /code/requirements.txt + +RUN pip install --no-cache-dir --upgrade -r /code/requirements.txt + +COPY ./app /code/app + +CMD ["fastapi", "run", "app/main.py", "--port", "80"] + +# यदि Nginx या Traefik जैसे proxy के पीछे चला रहे हैं तो --proxy-headers जोड़ें +# CMD ["fastapi", "run", "app/main.py", "--port", "80", "--proxy-headers"] +``` + +
+ +## Container क्या है { #what-is-a-container } + +Containers (मुख्य रूप से Linux containers) applications को उनकी सभी dependencies और आवश्यक files सहित package करने का एक बहुत **lightweight** तरीका हैं, जबकि उन्हें उसी system में दूसरे containers (दूसरी applications या components) से isolated रखा जाता है। + +Linux containers host (machine, virtual machine, cloud server, आदि) के उसी Linux kernel का उपयोग करके चलते हैं। इसका मतलब बस इतना है कि वे बहुत lightweight होते हैं (पूरे operating system को emulate करने वाली full virtual machines की तुलना में)। + +इस तरह, containers **कम resources** consume करते हैं, लगभग उतने ही जितने processes को सीधे चलाने में लगते हैं (virtual machine बहुत अधिक consume करेगी)। + +Containers के अपने **isolated** running processes (आमतौर पर सिर्फ एक process), file system, और network भी होते हैं, जिससे deployment, security, development, आदि सरल हो जाते हैं। + +## Container Image क्या है { #what-is-a-container-image } + +एक **container** एक **container image** से चलाया जाता है। + +Container image उन सभी files, environment variables, और default command/program का **static** version होता है जो container में मौजूद होना चाहिए। यहाँ **Static** का मतलब है कि container **image** चल नहीं रही है, execute नहीं हो रही है, यह सिर्फ packaged files और metadata है। + +"**container image**" जो stored static contents है, उसके विपरीत, "**container**" सामान्यतः running instance को संदर्भित करता है, वह चीज़ जो **execute** हो रही है। + +जब **container** start होकर running होता है (**container image** से start किया गया), तो यह files, environment variables, आदि बना या बदल सकता है। वे बदलाव केवल उस container में मौजूद होंगे, लेकिन underlying container image में persist नहीं होंगे (disk पर save नहीं होंगे)। + +Container image की तुलना **program** file और contents से की जा सकती है, जैसे `python` और कोई file `main.py`। + +और **container** स्वयं (**container image** के विपरीत) image का वास्तविक running instance है, जिसकी तुलना **process** से की जा सकती है। वास्तव में, container केवल तब running होता है जब उसमें **process running** हो (और आमतौर पर यह केवल एक single process होता है)। जब उसमें कोई process running नहीं रहता, तो container stop हो जाता है। + +## Container Images { #container-images } + +Docker **container images** और **containers** बनाने और manage करने के मुख्य tools में से एक रहा है। + +और एक public [Docker Hub](https://hub.docker.com/) है जिसमें कई tools, environments, databases, और applications के लिए पहले से बनी **official container images** हैं। + +उदाहरण के लिए, एक official [Python Image](https://hub.docker.com/_/python) है। + +और databases जैसी अलग-अलग चीज़ों के लिए कई अन्य images हैं, उदाहरण के लिए: + +* [PostgreSQL](https://hub.docker.com/_/postgres) +* [MySQL](https://hub.docker.com/_/mysql) +* [MongoDB](https://hub.docker.com/_/mongo) +* [Redis](https://hub.docker.com/_/redis), आदि। + +पहले से बनी container image का उपयोग करके अलग-अलग tools को **combine** और use करना बहुत आसान है। उदाहरण के लिए, नया database try करने के लिए। अधिकतर मामलों में, आप **official images** का उपयोग कर सकते हैं, और उन्हें सिर्फ environment variables से configure कर सकते हैं। + +इस तरह, कई मामलों में आप containers और Docker के बारे में सीख सकते हैं और उस knowledge को कई अलग-अलग tools और components के साथ reuse कर सकते हैं। + +तो, आप अलग-अलग चीज़ों के साथ **multiple containers** चलाएँगे, जैसे database, Python application, React frontend application वाला web server, और उन्हें उनके internal network के माध्यम से connect करेंगे। + +सभी container management systems (जैसे Docker या Kubernetes) में ये networking features integrated होते हैं। + +## Containers और Processes { #containers-and-processes } + +एक **container image** सामान्यतः अपने metadata में default program या command शामिल करती है जिसे **container** start होने पर run किया जाना चाहिए, और उस program को pass किए जाने वाले parameters। यह बहुत हद तक वैसा ही है जैसा command line में होता। + +जब कोई **container** start होता है, तो वह उस command/program को run करेगा (हालाँकि आप इसे override करके कोई अलग command/program run करवा सकते हैं)। + +Container तब तक running रहता है जब तक **main process** (command या program) running रहता है। + +Container में सामान्यतः **single process** होता है, लेकिन main process से subprocesses start करना भी संभव है, और इस तरह उसी container में **multiple processes** हो सकते हैं। + +लेकिन **कम से कम एक running process** के बिना running container होना संभव नहीं है। यदि main process stop हो जाता है, तो container stop हो जाता है। + +## FastAPI के लिए Docker Image बनाएँ { #build-a-docker-image-for-fastapi } + +ठीक है, अब कुछ बनाते हैं! 🚀 + +मैं आपको दिखाऊँगा कि **official Python** image पर आधारित FastAPI के लिए **scratch से** **Docker image** कैसे बनाएँ। + +यह वही है जो आप **अधिकतर मामलों** में करना चाहेंगे, उदाहरण के लिए: + +* **Kubernetes** या समान tools का उपयोग करते समय +* **Raspberry Pi** पर चलाते समय +* ऐसा cloud service उपयोग करते समय जो आपके लिए container image run करेगा, आदि। + +### Package Requirements { #package-requirements } + +आपकी application के लिए **package requirements** सामान्यतः किसी file में होंगे। + +यह मुख्य रूप से उस tool पर निर्भर करेगा जिसका उपयोग आप उन requirements को **install** करने के लिए करते हैं। + +इसे करने का सबसे आम तरीका है `requirements.txt` file रखना, जिसमें package names और उनके versions हों, प्रति line एक। + +आप versions की ranges set करने के लिए निश्चित रूप से वही ideas उपयोग करेंगे जो आपने [FastAPI versions के बारे में](versions.md) में पढ़े हैं। + +उदाहरण के लिए, आपका `requirements.txt` ऐसा दिख सकता है: + +``` +fastapi[standard]>=0.113.0,<0.114.0 +pydantic>=2.7.0,<3.0.0 +``` + +और आप सामान्यतः उन package dependencies को `pip` से install करेंगे, उदाहरण के लिए: + +
+ +```console +$ pip install -r requirements.txt +---> 100% +Successfully installed fastapi pydantic +``` + +
+ +/// note | नोट + +Package dependencies define और install करने के लिए अन्य formats और tools भी हैं। + +/// + +### **FastAPI** Code बनाएँ { #create-the-fastapi-code } + +* एक `app` directory बनाएँ और उसमें enter करें। +* एक खाली file `__init__.py` बनाएँ। +* एक `main.py` file बनाएँ जिसमें हो: + +```Python +from fastapi import FastAPI + +app = FastAPI() + + +@app.get("/") +def read_root(): + return {"Hello": "World"} + + +@app.get("/items/{item_id}") +def read_item(item_id: int, q: str | None = None): + return {"item_id": item_id, "q": q} +``` + +### Dockerfile { #dockerfile } + +अब उसी project directory में एक file `Dockerfile` बनाएँ जिसमें हो: + +```{ .dockerfile .annotate } +# (1)! +FROM python:3.14 + +# (2)! +WORKDIR /code + +# (3)! +COPY ./requirements.txt /code/requirements.txt + +# (4)! +RUN pip install --no-cache-dir --upgrade -r /code/requirements.txt + +# (5)! +COPY ./app /code/app + +# (6)! +CMD ["fastapi", "run", "app/main.py", "--port", "80"] +``` + +1. Official Python base image से start करें। + +2. Current working directory को `/code` पर set करें। + + यही वह जगह है जहाँ हम `requirements.txt` file और `app` directory रखेंगे। + +3. Requirements वाली file को `/code` directory में copy करें। + + पहले **केवल** requirements वाली file copy करें, बाकी code नहीं। + + क्योंकि यह file **अक्सर change नहीं होती**, Docker इसे detect करेगा और इस step के लिए **cache** का उपयोग करेगा, जिससे अगले step के लिए भी cache enable हो जाएगा। + +4. Requirements file में package dependencies install करें। + + `--no-cache-dir` option `pip` को बताता है कि downloaded packages को locally save न करे, क्योंकि यह केवल तब उपयोगी होता जब `pip` को उन्हीं packages को install करने के लिए फिर से run किया जाना हो, लेकिन containers के साथ काम करते समय ऐसा मामला नहीं है। + + /// note | नोट + + `--no-cache-dir` केवल `pip` से संबंधित है, इसका Docker या containers से कोई संबंध नहीं है। + + /// + + `--upgrade` option `pip` को बताता है कि यदि packages पहले से installed हैं तो उन्हें upgrade करे। + + क्योंकि पिछला step जिसमें file copy की गई थी **Docker cache** द्वारा detect किया जा सकता है, इसलिए यह step भी available होने पर **Docker cache का उपयोग** करेगा। + + इस step में cache का उपयोग development के दौरान image बार-बार build करते समय आपका बहुत **समय** **बचाएगा**, हर बार सभी dependencies को **download और install** करने के बजाय। + +5. `./app` directory को `/code` directory के अंदर copy करें। + + क्योंकि इसमें सारा code है, और यही वह चीज़ है जो **सबसे अधिक बार change होती** है, Docker **cache** इस या किसी भी **आगे के steps** के लिए आसानी से उपयोग नहीं होगा। + + इसलिए, container image build times optimize करने के लिए इसे `Dockerfile` के **end के पास** रखना महत्वपूर्ण है। + +6. **command** set करें ताकि `fastapi run` उपयोग हो, जो अंदर से Uvicorn का उपयोग करता है। + + `CMD` strings की list लेता है, इन strings में से प्रत्येक वही है जिसे आप command line में spaces से अलग करके type करेंगे। + + यह command **current working directory** से run होगा, वही `/code` directory जिसे आपने ऊपर `WORKDIR /code` से set किया है। + +/// tip | टिप + +Code में प्रत्येक number bubble पर click करके review करें कि हर line क्या करती है। 👆 + +/// + +/// warning | चेतावनी + +नीचे समझाए अनुसार, `CMD` instruction का **exec form** **हमेशा** use करना सुनिश्चित करें। + +/// + +#### `CMD` उपयोग करें - Exec Form { #use-cmd-exec-form } + +[`CMD`](https://docs.docker.com/reference/dockerfile/#cmd) Docker instruction दो forms में लिखा जा सकता है: + +✅ **Exec** form: + +```Dockerfile +# ✅ यह करें +CMD ["fastapi", "run", "app/main.py", "--port", "80"] +``` + +⛔️ **Shell** form: + +```Dockerfile +# ⛔️ यह न करें +CMD fastapi run app/main.py --port 80 +``` + +यह सुनिश्चित करने के लिए कि FastAPI gracefully shutdown कर सके और [lifespan events](../advanced/events.md) trigger हों, हमेशा **exec** form use करें। + +आप इसके बारे में [shell और exec form के लिए Docker docs](https://docs.docker.com/reference/dockerfile/#shell-and-exec-form) में और पढ़ सकते हैं। + +`docker compose` का उपयोग करते समय यह काफी noticeable हो सकता है। अधिक technical details के लिए यह Docker Compose FAQ section देखें: [मेरी services को recreate या stop होने में 10 seconds क्यों लगते हैं?](https://docs.docker.com/compose/faq/#why-do-my-services-take-10-seconds-to-recreate-or-stop). + +#### Directory Structure { #directory-structure } + +अब आपके पास ऐसी directory structure होनी चाहिए: + +``` +. +├── app +│   ├── __init__.py +│ └── main.py +├── Dockerfile +└── requirements.txt +``` + +#### TLS Termination Proxy के पीछे { #behind-a-tls-termination-proxy } + +यदि आप अपना container Nginx या Traefik जैसे TLS Termination Proxy (load balancer) के पीछे चला रहे हैं, तो option `--proxy-headers` जोड़ें, यह Uvicorn (FastAPI CLI के माध्यम से) को बताएगा कि उस proxy द्वारा भेजे गए headers पर trust करे, जो उसे बताता है कि application HTTPS के पीछे चल रही है, आदि। + +```Dockerfile +CMD ["fastapi", "run", "app/main.py", "--proxy-headers", "--port", "80"] +``` + +#### Docker Cache { #docker-cache } + +इस `Dockerfile` में एक महत्वपूर्ण trick है, हम पहले **केवल dependencies वाली file** copy करते हैं, बाकी code नहीं। मैं आपको बताता हूँ क्यों। + +```Dockerfile +COPY ./requirements.txt /code/requirements.txt +``` + +Docker और अन्य tools इन container images को **incrementally build** करते हैं, **एक layer के ऊपर दूसरी layer** जोड़ते हुए, `Dockerfile` के top से शुरू करके और `Dockerfile` के प्रत्येक instruction द्वारा बनाई गई कोई भी files जोड़ते हुए। + +Docker और समान tools image build करते समय **internal cache** भी use करते हैं, यदि कोई file पिछली बार container image build करने के बाद से change नहीं हुई है, तो वह file को फिर से copy करने और scratch से नई layer बनाने के बजाय पिछली बार बनाई गई **उसी layer को reuse** करेगा। + +सिर्फ files copy करने से बचना जरूरी नहीं कि चीज़ों को बहुत बेहतर कर दे, लेकिन क्योंकि उसने उस step के लिए cache use किया, वह **अगले step के लिए cache use** कर सकता है। उदाहरण के लिए, वह उस instruction के लिए cache use कर सकता है जो dependencies install करता है: + +```Dockerfile +RUN pip install --no-cache-dir --upgrade -r /code/requirements.txt +``` + +Package requirements वाली file **अक्सर change नहीं होगी**। इसलिए, केवल उस file को copy करके, Docker उस step के लिए **cache use** कर पाएगा। + +और फिर, Docker उन dependencies को download और install करने वाले **अगले step के लिए cache use** कर पाएगा। और यहीं हम **बहुत समय बचाते हैं**। ✨ ...और इंतज़ार की बोरियत से बचते हैं। 😪😆 + +Package dependencies को download और install करने में **minutes लग सकते हैं**, लेकिन **cache** का उपयोग करने में अधिकतम **seconds** लगेंगे। + +और क्योंकि development के दौरान आप अपने code changes काम कर रहे हैं या नहीं यह check करने के लिए container image बार-बार build करेंगे, इससे बहुत सारा जमा हुआ समय बचेगा। + +फिर, `Dockerfile` के end के पास, हम सारा code copy करते हैं। क्योंकि यही वह चीज़ है जो **सबसे अधिक बार change होती** है, हम इसे end के पास रखते हैं, क्योंकि लगभग हमेशा इस step के बाद कुछ भी cache use नहीं कर पाएगा। + +```Dockerfile +COPY ./app /code/app +``` + +### Docker Image Build करें { #build-the-docker-image } + +अब जब सभी files अपनी जगह पर हैं, चलिए container image build करते हैं। + +* Project directory में जाएँ (जहाँ आपका `Dockerfile` है, जिसमें आपकी `app` directory है)। +* अपनी FastAPI image build करें: + +
+ +```console +$ docker build -t myimage . + +---> 100% +``` + +
+ +/// tip | टिप + +अंत में `.` पर ध्यान दें, यह `./` के equivalent है, यह Docker को container image build करने के लिए use की जाने वाली directory बताता है। + +इस मामले में, यह वही current directory (`.`) है। + +/// + +### Docker Container Start करें { #start-the-docker-container } + +* अपनी image पर आधारित container run करें: + +
+ +```console +$ docker run -d --name mycontainer -p 80:80 myimage +``` + +
+ +## इसे Check करें { #check-it } + +आप इसे अपने Docker container के URL में check कर पाएँगे, उदाहरण के लिए: [http://192.168.99.100/items/5?q=somequery](http://192.168.99.100/items/5?q=somequery) या [http://127.0.0.1/items/5?q=somequery](http://127.0.0.1/items/5?q=somequery) (या equivalent, अपने Docker host का उपयोग करके)। + +आपको कुछ ऐसा दिखेगा: + +```JSON +{"item_id": 5, "q": "somequery"} +``` + +## Interactive API docs { #interactive-api-docs } + +अब आप [http://192.168.99.100/docs](http://192.168.99.100/docs) या [http://127.0.0.1/docs](http://127.0.0.1/docs) (या equivalent, अपने Docker host का उपयोग करके) पर जा सकते हैं। + +आप automatic interactive API documentation देखेंगे ([Swagger UI](https://github.com/swagger-api/swagger-ui) द्वारा provided): + +![Swagger UI](https://fastapi.tiangolo.com/img/index/index-01-swagger-ui-simple.png) + +## Alternative API docs { #alternative-api-docs } + +और आप [http://192.168.99.100/redoc](http://192.168.99.100/redoc) या [http://127.0.0.1/redoc](http://127.0.0.1/redoc) (या equivalent, अपने Docker host का उपयोग करके) पर भी जा सकते हैं। + +आप alternative automatic documentation देखेंगे ([ReDoc](https://github.com/Rebilly/ReDoc) द्वारा provided): + +![ReDoc](https://fastapi.tiangolo.com/img/index/index-02-redoc-simple.png) + +## Single-File FastAPI के साथ Docker Image बनाएँ { #build-a-docker-image-with-a-single-file-fastapi } + +यदि आपकी FastAPI एक single file है, उदाहरण के लिए, `./app` directory के बिना `main.py`, तो आपकी file structure ऐसी दिख सकती है: + +``` +. +├── Dockerfile +├── main.py +└── requirements.txt +``` + +फिर आपको बस `Dockerfile` के अंदर file copy करने के लिए संबंधित paths बदलने होंगे: + +```{ .dockerfile .annotate hl_lines="10 13" } +FROM python:3.14 + +WORKDIR /code + +COPY ./requirements.txt /code/requirements.txt + +RUN pip install --no-cache-dir --upgrade -r /code/requirements.txt + +# (1)! +COPY ./main.py /code/ + +# (2)! +CMD ["fastapi", "run", "main.py", "--port", "80"] +``` + +1. `main.py` file को सीधे `/code` directory में copy करें (बिना किसी `./app` directory के)। + +2. Single file `main.py` में अपनी application serve करने के लिए `fastapi run` use करें। + +जब आप file को `fastapi run` में pass करते हैं, तो यह automatically detect करेगा कि यह single file है और किसी package का हिस्सा नहीं है, और यह जान जाएगा कि इसे कैसे import करना है और आपकी FastAPI app को serve करना है। 😎 + +## Deployment Concepts { #deployment-concepts } + +आइए containers के संदर्भ में फिर से उन्हीं कुछ [Deployment Concepts](concepts.md) के बारे में बात करें। + +Containers मुख्य रूप से application को **build और deploy** करने की process को सरल बनाने का tool हैं, लेकिन वे इन **deployment concepts** को handle करने के लिए कोई particular approach enforce नहीं करते, और कई संभावित strategies हैं। + +**अच्छी खबर** यह है कि हर अलग strategy के साथ सभी deployment concepts को cover करने का एक तरीका है। 🎉 + +आइए इन **deployment concepts** को containers के संदर्भ में review करें: + +* HTTPS +* startup पर Running +* Restarts +* Replication (running processes की संख्या) +* Memory +* Start करने से पहले previous steps + +## HTTPS { #https } + +यदि हम FastAPI application के लिए सिर्फ **container image** (और बाद में running **container**) पर focus करें, तो HTTPS सामान्यतः किसी अन्य tool द्वारा **externally** handle किया जाएगा। + +यह कोई दूसरा container हो सकता है, उदाहरण के लिए [Traefik](https://traefik.io/) के साथ, जो **HTTPS** और **certificates** की **automatic** acquisition handle करता है। + +/// tip | टिप + +Traefik के Docker, Kubernetes, और अन्य के साथ integrations हैं, इसलिए इसके साथ अपने containers के लिए HTTPS set up और configure करना बहुत आसान है। + +/// + +वैकल्पिक रूप से, HTTPS को किसी cloud provider द्वारा उनकी services में से एक के रूप में handle किया जा सकता है (application अभी भी container में चल रही हो)। + +## Startup पर Running और Restarts { #running-on-startup-and-restarts } + +सामान्यतः कोई दूसरा tool आपके container को **start और run** करने के लिए charge में होता है। + +यह सीधे **Docker**, **Docker Compose**, **Kubernetes**, कोई **cloud service**, आदि हो सकता है। + +अधिकतर (या सभी) मामलों में, startup पर container run करने और failures पर restarts enable करने के लिए एक simple option होता है। उदाहरण के लिए, Docker में यह command line option `--restart` है। + +Containers का उपयोग किए बिना, applications को startup पर और restarts के साथ run कराना cumbersome और difficult हो सकता है। लेकिन **containers के साथ काम करते समय** अधिकतर मामलों में यह functionality default रूप से शामिल होती है। ✨ + +## Replication - Processes की संख्या { #replication-number-of-processes } + +यदि आपके पास machines का cluster है जिसमें **Kubernetes**, Docker Swarm Mode, Nomad, या multiple machines पर distributed containers manage करने के लिए कोई अन्य similar complex system है, तो आप शायद प्रत्येक container में **process manager** (जैसे workers के साथ Uvicorn) उपयोग करने के बजाय **cluster level** पर **replication handle** करना चाहेंगे। + +Kubernetes जैसे distributed container management systems में incoming requests के लिए **load balancing** support करते हुए **containers की replication** handle करने का कोई integrated तरीका सामान्यतः होता है। सब **cluster level** पर। + +उन मामलों में, आप शायद ऊपर [समझाए अनुसार](#dockerfile) **scratch से Docker image** build करना चाहेंगे, अपनी dependencies install करके, और multiple Uvicorn workers उपयोग करने के बजाय **single Uvicorn process** run करना चाहेंगे। + +### Load Balancer { #load-balancer } + +Containers का उपयोग करते समय, आपके पास सामान्यतः कोई component होगा जो **main port पर listening** कर रहा होगा। संभवतः यह कोई दूसरा container हो सकता है जो **HTTPS** handle करने के लिए **TLS Termination Proxy** भी हो, या कोई similar tool। + +क्योंकि यह component requests का **load** लेगा और उसे workers में (उम्मीद है) **balanced** तरीके से distribute करेगा, इसे सामान्यतः **Load Balancer** भी कहा जाता है। + +/// tip | टिप + +HTTPS के लिए उपयोग किया गया वही **TLS Termination Proxy** component शायद **Load Balancer** भी होगा। + +/// + +और containers के साथ काम करते समय, उन्हें start और manage करने के लिए आप जो system use करते हैं, उसमें उस **load balancer** (जो **TLS Termination Proxy** भी हो सकता है) से आपकी app वाले container(s) तक **network communication** (जैसे HTTP requests) transmit करने के internal tools पहले से होंगे। + +### One Load Balancer - Multiple Worker Containers { #one-load-balancer-multiple-worker-containers } + +**Kubernetes** या similar distributed container management systems के साथ काम करते समय, उनके internal networking mechanisms का उपयोग main **port** पर listening करने वाले single **load balancer** को communication (requests) आपकी app चला रहे संभवतः **multiple containers** तक transmit करने देगा। + +आपकी app चला रहे इन containers में से प्रत्येक में सामान्यतः **सिर्फ एक process** होगा (जैसे आपकी FastAPI application चलाने वाला Uvicorn process)। वे सभी **identical containers** होंगे, वही चीज़ चला रहे होंगे, लेकिन प्रत्येक का अपना process, memory, आदि होगा। इस तरह आप CPU के **different cores** में, या यहाँ तक कि **different machines** में **parallelization** का लाभ उठाएँगे। + +और **load balancer** वाला distributed container system requests को आपकी app वाले प्रत्येक container तक **बारी-बारी से distribute** करेगा। इसलिए, प्रत्येक request आपकी app चला रहे multiple **replicated containers** में से किसी एक द्वारा handle की जा सकती है। + +और सामान्यतः यह **load balancer** आपके cluster में *other* apps पर जाने वाली requests handle कर पाएगा (जैसे अलग domain पर, या अलग URL path prefix के तहत), और उस communication को आपके cluster में चल रही *उस other* application के सही containers तक transmit करेगा। + +### प्रति Container एक Process { #one-process-per-container } + +इस तरह के scenario में, आप शायद **प्रति container एक single (Uvicorn) process** रखना चाहेंगे, क्योंकि आप पहले से ही cluster level पर replication handle कर रहे होंगे। + +तो, इस मामले में, आप container में multiple workers **नहीं** रखना चाहेंगे, उदाहरण के लिए `--workers` command line option के साथ। आप प्रति container बस **single Uvicorn process** रखना चाहेंगे (लेकिन शायद multiple containers)। + +Container के अंदर एक और process manager रखना (जैसा multiple workers के साथ होगा) केवल **unnecessary complexity** जोड़ेगा, जिसे आप बहुत संभव है कि अपने cluster system के साथ पहले से संभाल रहे हैं। + +### Multiple Processes वाले Containers और Special Cases { #containers-with-multiple-processes-and-special-cases } + +बेशक, ऐसे **special cases** हैं जहाँ आप अंदर कई **Uvicorn worker processes** वाला **container** रखना चाह सकते हैं। + +उन मामलों में, आप run किए जाने वाले workers की संख्या set करने के लिए `--workers` command line option उपयोग कर सकते हैं: + +```{ .dockerfile .annotate } +FROM python:3.14 + +WORKDIR /code + +COPY ./requirements.txt /code/requirements.txt + +RUN pip install --no-cache-dir --upgrade -r /code/requirements.txt + +COPY ./app /code/app + +# (1)! +CMD ["fastapi", "run", "app/main.py", "--port", "80", "--workers", "4"] +``` + +1. यहाँ हम workers की संख्या 4 पर set करने के लिए `--workers` command line option उपयोग करते हैं। + +यहाँ कुछ examples हैं कि यह कब meaningful हो सकता है: + +#### एक Simple App { #a-simple-app } + +यदि आपकी application **इतनी simple** है कि आप इसे **single server** पर run कर सकते हैं, cluster पर नहीं, तो आप container में process manager चाह सकते हैं। + +#### Docker Compose { #docker-compose } + +आप **Docker Compose** के साथ **single server** (cluster नहीं) पर deploy कर रहे हो सकते हैं, इसलिए shared network और **load balancing** preserve करते हुए containers की replication (Docker Compose के साथ) manage करने का आसान तरीका आपके पास नहीं होगा। + +फिर आप **single container** रखना चाह सकते हैं जिसमें **process manager** अंदर **कई worker processes** start करे। + +--- + +मुख्य बात यह है कि इनमें से **कोई भी** ऐसी **पत्थर पर लिखी rules** नहीं हैं जिन्हें आपको आँख बंद करके follow करना हो। आप इन ideas का उपयोग **अपने use case का evaluate** करने और अपने system के लिए best approach तय करने के लिए कर सकते हैं, यह check करते हुए कि इन concepts को कैसे manage करना है: + +* Security - HTTPS +* startup पर Running +* Restarts +* Replication (running processes की संख्या) +* Memory +* Start करने से पहले previous steps + +## Memory { #memory } + +यदि आप **प्रति container single process** run करते हैं, तो उन containers में से प्रत्येक (यदि replicated हैं तो एक से अधिक) द्वारा consumed memory की quantity कमोबेश well-defined, stable, और limited होगी। + +और फिर आप अपने container management system (उदाहरण के लिए **Kubernetes** में) की configurations में वही memory limits और requirements set कर सकते हैं। इस तरह वह उन containers द्वारा आवश्यक memory की मात्रा, और cluster में machines में available मात्रा को ध्यान में रखते हुए **available machines** में **containers replicate** कर पाएगा। + +यदि आपकी application **simple** है, तो यह शायद **problem नहीं होगी**, और आपको hard memory limits specify करने की आवश्यकता नहीं हो सकती। लेकिन यदि आप **बहुत memory use** कर रहे हैं (उदाहरण के लिए **machine learning** models के साथ), तो आपको check करना चाहिए कि आप कितनी memory consume कर रहे हैं और **प्रत्येक machine** पर run होने वाले **containers की संख्या** adjust करनी चाहिए (और शायद अपने cluster में और machines add करनी चाहिए)। + +यदि आप **प्रति container multiple processes** run करते हैं, तो आपको सुनिश्चित करना होगा कि start किए गए processes की संख्या available memory से **अधिक memory consume** न करे। + +## Start करने से पहले Previous Steps और Containers { #previous-steps-before-starting-and-containers } + +यदि आप containers (जैसे Docker, Kubernetes) उपयोग कर रहे हैं, तो दो मुख्य approaches हैं जिनका आप उपयोग कर सकते हैं। + +### Multiple Containers { #multiple-containers } + +यदि आपके पास **multiple containers** हैं, शायद प्रत्येक **single process** run कर रहा है (उदाहरण के लिए, **Kubernetes** cluster में), तो आप replicated worker containers run करने से **पहले**, single container में, single process चलाते हुए, **previous steps** का काम करने वाला **separate container** रखना चाहेंगे। + +/// note | नोट + +यदि आप Kubernetes उपयोग कर रहे हैं, तो यह शायद [Init Container](https://kubernetes.io/docs/concepts/workloads/pods/init-containers/) होगा। + +/// + +यदि आपके use case में उन previous steps को **parallel में multiple times** run करने में कोई problem नहीं है (उदाहरण के लिए यदि आप database migrations नहीं चला रहे, बल्कि बस check कर रहे हैं कि database अभी ready है या नहीं), तो आप उन्हें हर container में main process start करने से ठीक पहले भी रख सकते हैं। + +### Single Container { #single-container } + +यदि आपका setup simple है, जिसमें **single container** है जो फिर multiple **worker processes** start करता है (या सिर्फ एक process), तो आप app के साथ process start करने से ठीक पहले, उन previous steps को उसी container में run कर सकते हैं। + +### Base Docker Image { #base-docker-image } + +एक official FastAPI Docker image हुआ करती थी: [tiangolo/uvicorn-gunicorn-fastapi](https://github.com/tiangolo/uvicorn-gunicorn-fastapi-docker)। लेकिन अब यह deprecated है। ⛔️ + +आपको शायद इस base Docker image (या किसी अन्य similar one) का उपयोग **नहीं** करना चाहिए। + +यदि आप **Kubernetes** (या अन्य) उपयोग कर रहे हैं और पहले से ही cluster level पर, multiple **containers** के साथ **replication** set कर रहे हैं। उन मामलों में, ऊपर बताए अनुसार **scratch से image build** करना बेहतर है: [FastAPI के लिए Docker Image बनाएँ](#build-a-docker-image-for-fastapi). + +और यदि आपको multiple workers की आवश्यकता है, तो आप बस `--workers` command line option उपयोग कर सकते हैं। + +/// note | Technical Details + +Docker image तब बनाई गई थी जब Uvicorn dead workers को manage और restart करने का support नहीं करता था, इसलिए Uvicorn के साथ Gunicorn का उपयोग करना required था, जिससे काफी complexity जुड़ती थी, सिर्फ इसलिए कि Gunicorn Uvicorn worker processes को manage और restart कर सके। + +लेकिन अब जब Uvicorn (और `fastapi` command) `--workers` use करने का support करते हैं, तो अपनी खुद की build करने के बजाय base Docker image उपयोग करने का कोई कारण नहीं है (यह लगभग उतनी ही code की मात्रा है 😅). + +/// + +## Container Image Deploy करें { #deploy-the-container-image } + +Container (Docker) Image होने के बाद इसे deploy करने के कई तरीके हैं। + +उदाहरण के लिए: + +* Single server में **Docker Compose** के साथ +* **Kubernetes** cluster के साथ +* Docker Swarm Mode cluster के साथ +* Nomad जैसे किसी अन्य tool के साथ +* किसी cloud service के साथ जो आपकी container image लेता है और उसे deploy करता है + +## `uv` के साथ Docker Image { #docker-image-with-uv } + +यदि आप अपने project को install और manage करने के लिए [uv](https://github.com/astral-sh/uv) उपयोग कर रहे हैं, तो आप उनकी [uv Docker guide](https://docs.astral.sh/uv/guides/integration/docker/) follow कर सकते हैं। + +## Recap { #recap } + +Container systems (जैसे **Docker** और **Kubernetes** के साथ) का उपयोग करने पर सभी **deployment concepts** handle करना काफी straightforward हो जाता है: + +* HTTPS +* startup पर Running +* Restarts +* Replication (running processes की संख्या) +* Memory +* Start करने से पहले previous steps + +अधिकतर मामलों में, आप शायद कोई base image use नहीं करना चाहेंगे, और इसके बजाय official Python Docker image पर आधारित **scratch से container image build** करेंगे। + +`Dockerfile` में instructions के **order** और **Docker cache** का ध्यान रखकर आप **build times minimize** कर सकते हैं, ताकि आपकी productivity maximize हो (और बोरियत से बचें)। 😎 diff --git a/docs/hi/docs/deployment/fastapicloud.md b/docs/hi/docs/deployment/fastapicloud.md new file mode 100644 index 000000000..06a2a2d3c --- /dev/null +++ b/docs/hi/docs/deployment/fastapicloud.md @@ -0,0 +1,47 @@ +# FastAPI Cloud { #fastapi-cloud } + +आप अपनी FastAPI app को सिर्फ **एक command** से [FastAPI Cloud](https://fastapicloud.com) पर deploy कर सकते हैं। 🚀 + +
+ +```console +$ fastapi deploy + +Deploying to FastAPI Cloud... + +✅ Deployment successful! + +🐔 Ready the chicken! Your app is ready at https://myapp.fastapicloud.dev +``` + +
+ +CLI अपने-आप आपकी FastAPI application का पता लगा लेगा और उसे cloud पर deploy कर देगा। अगर आप logged in नहीं हैं, तो authentication प्रक्रिया पूरी करने के लिए आपका browser खुलेगा। + +बस इतना ही! अब आप उस URL पर अपनी app access कर सकते हैं। ✨ + +## FastAPI Cloud के बारे में { #about-fastapi-cloud } + +**[FastAPI Cloud](https://fastapicloud.com)** उसी author और team द्वारा बनाया गया है जो **FastAPI** के पीछे हैं। + +यह कम से कम प्रयास में API को **build** करने, **deploy** करने, और **access** करने की प्रक्रिया को सरल बनाता है। + +यह FastAPI के साथ apps बनाने वाले उसी **developer experience** को उन्हें cloud पर **deploy** करने में भी लाता है। 🎉 + +यह app deploy करते समय ज़रूरी अधिकांश चीज़ों का भी ध्यान रखेगा, जैसे: + +* HTTPS +* Replication, requests के आधार पर autoscaling के साथ +* आदि। + +FastAPI Cloud, *FastAPI and friends* open source projects का मुख्य sponsor और funding provider है। ✨ + +## दूसरे cloud providers पर deploy करें { #deploy-to-other-cloud-providers } + +FastAPI open source है और standards पर आधारित है। आप FastAPI apps को अपने चुने हुए किसी भी cloud provider पर deploy कर सकते हैं। + +उनके साथ FastAPI apps deploy करने के लिए अपने cloud provider की guides follow करें। 🤓 + +## अपने खुद के server पर deploy करें { #deploy-your-own-server } + +मैं आपको इस **Deployment** guide में आगे सभी details भी सिखाऊँगा, ताकि आप समझ सकें कि क्या हो रहा है, क्या होना चाहिए, या FastAPI apps को अपने-आप, अपने खुद के servers के साथ भी कैसे deploy करना है। 🤓 diff --git a/docs/hi/docs/deployment/https.md b/docs/hi/docs/deployment/https.md new file mode 100644 index 000000000..834712835 --- /dev/null +++ b/docs/hi/docs/deployment/https.md @@ -0,0 +1,231 @@ +# HTTPS के बारे में { #about-https } + +यह मान लेना आसान है कि HTTPS कोई ऐसी चीज़ है जिसे बस "enabled" किया जाता है या नहीं। + +लेकिन यह उससे कहीं ज़्यादा जटिल है। + +/// tip | सुझाव + +अगर आप जल्दी में हैं या आपको परवाह नहीं है, तो अलग-अलग तकनीकों के साथ सब कुछ setup करने के लिए step by step निर्देशों हेतु अगले sections पर जाएँ। + +/// + +**HTTPS की मूल बातें सीखने** के लिए, एक उपभोक्ता के दृष्टिकोण से, देखें [https://howhttps.works/](https://howhttps.works/)। + +अब, एक **developer के दृष्टिकोण** से, HTTPS के बारे में सोचते समय ध्यान रखने योग्य कई बातें यहाँ हैं: + +* HTTPS के लिए, **server** के पास **तीसरे पक्ष** द्वारा बनाए गए "certificates" होने चाहिए। + * वे certificates वास्तव में तीसरे पक्ष से **प्राप्त** किए जाते हैं, "generated" नहीं। +* Certificates की एक **lifespan** होती है। + * वे **expire** हो जाते हैं। + * और फिर उन्हें **renew** करना पड़ता है, तीसरे पक्ष से **फिर से प्राप्त** करना पड़ता है। +* connection का encryption **TCP level** पर होता है। + * यह **HTTP से एक layer नीचे** है। + * इसलिए, **certificate और encryption** handling **HTTP से पहले** की जाती है। +* **TCP को "domains" के बारे में पता नहीं होता**। केवल IP addresses के बारे में। + * जिस **विशिष्ट domain** का request किया गया है, उसकी जानकारी **HTTP data** में जाती है। +* **HTTPS certificates** किसी **विशिष्ट domain** को "certify" करते हैं, लेकिन protocol और encryption TCP level पर होते हैं, इस domain को जानने से **पहले** कि किस domain से निपटा जा रहा है। +* **By default**, इसका मतलब होगा कि आपके पास **प्रति IP address केवल एक HTTPS certificate** हो सकता है। + * इससे कोई फर्क नहीं पड़ता कि आपका server कितना बड़ा है या उस पर मौजूद हर application कितनी छोटी हो सकती है। + * हालांकि, इसका एक **समाधान** है। +* **TLS** protocol (जो HTTP से पहले, TCP level पर encryption संभालता है) के लिए एक **extension** है जिसे **[SNI](https://en.wikipedia.org/wiki/Server_Name_Indication)** कहा जाता है। + * यह SNI extension एक ही server (एक **single IP address** के साथ) को **कई HTTPS certificates** रखने और **कई HTTPS domains/applications** serve करने की अनुमति देता है। + * इसे काम करने के लिए, server पर चल रहे, **public IP address** पर listen कर रहे, एक **single** component (program) के पास server में **सभी HTTPS certificates** होने चाहिए। +* सुरक्षित connection प्राप्त करने के **बाद**, communication protocol **अभी भी HTTP** रहता है। + * contents **encrypted** होते हैं, भले ही उन्हें **HTTP protocol** के साथ भेजा जा रहा हो। + +Server (machine, host, आदि) पर **एक program/HTTP server** चलाना और **HTTPS के सभी हिस्सों को manage** करना एक सामान्य practice है: **encrypted HTTPS requests** प्राप्त करना, उसी server में चल रही वास्तविक HTTP application (इस मामले में **FastAPI** application) को **decrypted HTTP requests** भेजना, application से **HTTP response** लेना, उपयुक्त **HTTPS certificate** का उपयोग करके उसे **encrypt** करना और **HTTPS** का उपयोग करके client को वापस भेजना। इस server को अक्सर **[TLS Termination Proxy](https://en.wikipedia.org/wiki/TLS_termination_proxy)** कहा जाता है। + +TLS Termination Proxy के रूप में आप जिन options का उपयोग कर सकते हैं, उनमें से कुछ हैं: + +* Traefik (जो certificate renewals भी handle कर सकता है) +* Caddy (जो certificate renewals भी handle कर सकता है) +* Nginx +* HAProxy + +## Let's Encrypt { #lets-encrypt } + +Let's Encrypt से पहले, ये **HTTPS certificates** trusted तीसरे पक्षों द्वारा बेचे जाते थे। + +इनमें से किसी certificate को प्राप्त करने की प्रक्रिया कठिन होती थी, काफी paperwork की जरूरत होती थी और certificates काफी महंगे होते थे। + +लेकिन फिर **[Let's Encrypt](https://letsencrypt.org/)** बनाया गया। + +यह Linux Foundation का एक project है। यह automated तरीके से **मुफ्त में HTTPS certificates** प्रदान करता है। ये certificates सभी standard cryptographic security का उपयोग करते हैं, और short-lived होते हैं (लगभग 3 महीने), इसलिए उनकी कम lifespan के कारण **security वास्तव में बेहतर** होती है। + +Domains को सुरक्षित रूप से verify किया जाता है और certificates automatically generate किए जाते हैं। इससे इन certificates के renewal को automate करना भी संभव होता है। + +विचार यह है कि इन certificates की acquisition और renewal को automate किया जाए ताकि आपके पास **secure HTTPS, मुफ्त में, हमेशा के लिए** हो सके। + +## Developers के लिए HTTPS { #https-for-developers } + +यहाँ step by step एक उदाहरण है कि HTTPS API कैसी दिख सकती है, मुख्य रूप से developers के लिए महत्वपूर्ण विचारों पर ध्यान देते हुए। + +### Domain Name { #domain-name } + +सब कुछ शायद आपके द्वारा कोई **domain name** **प्राप्त** करने से शुरू होगा। फिर, आप इसे DNS server में configure करेंगे (संभवतः आपके उसी cloud provider में)। + +आप शायद एक cloud server (एक virtual machine) या कुछ समान प्राप्त करेंगे, और उसके पास एक स्थिर **public IP address** होगा। + +DNS server(s) में आप एक record (एक "`A record`") configure करेंगे ताकि **आपका domain** आपके server के public **IP address** की ओर point करे। + +आप शायद यह सिर्फ एक बार करेंगे, पहली बार, जब सब कुछ setup कर रहे होंगे। + +/// tip | सुझाव + +यह Domain Name वाला हिस्सा HTTPS से बहुत पहले का है, लेकिन चूँकि सब कुछ domain और IP address पर निर्भर करता है, इसलिए इसे यहाँ mention करना उचित है। + +/// + +### DNS { #dns } + +अब आइए वास्तविक HTTPS parts पर focus करें। + +सबसे पहले, browser **DNS servers** से check करेगा कि **domain के लिए IP** क्या है, इस मामले में, `someapp.example.com`। + +DNS servers browser को किसी विशिष्ट **IP address** का उपयोग करने के लिए कहेंगे। यह आपके server द्वारा उपयोग किया जाने वाला public IP address होगा, जिसे आपने DNS servers में configure किया है। + + + +### TLS Handshake Start { #tls-handshake-start } + +Browser फिर उस IP address से **port 443** (HTTPS port) पर communicate करेगा। + +Communication का पहला हिस्सा केवल client और server के बीच connection establish करना और वे कौन-सी cryptographic keys उपयोग करेंगे आदि तय करना है। + + + +TLS connection establish करने के लिए client और server के बीच इस interaction को **TLS handshake** कहा जाता है। + +### SNI Extension के साथ TLS { #tls-with-sni-extension } + +Server में **केवल एक process** किसी विशिष्ट **IP address** में किसी विशिष्ट **port** पर listen कर सकता है। उसी IP address में दूसरे ports पर अन्य processes listen कर सकते हैं, लेकिन IP address और port के हर combination के लिए केवल एक। + +TLS (HTTPS) by default विशिष्ट port `443` का उपयोग करता है। इसलिए हमें इसी port की जरूरत होगी। + +क्योंकि इस port पर केवल एक process listen कर सकता है, जो process यह करेगा वह **TLS Termination Proxy** होगा। + +TLS Termination Proxy के पास एक या अधिक **TLS certificates** (HTTPS certificates) तक access होगा। + +ऊपर चर्चा किए गए **SNI extension** का उपयोग करके, TLS Termination Proxy check करेगा कि इस connection के लिए उपलब्ध TLS (HTTPS) certificates में से किसका उपयोग करना चाहिए, client द्वारा expected domain से match करने वाले certificate का उपयोग करते हुए। + +इस मामले में, यह `someapp.example.com` के लिए certificate का उपयोग करेगा। + + + +Client पहले से ही उस entity पर **trust** करता है जिसने वह TLS certificate generate किया है (इस मामले में Let's Encrypt, लेकिन हम इसके बारे में बाद में देखेंगे), इसलिए यह **verify** कर सकता है कि certificate valid है। + +फिर, certificate का उपयोग करके, client और TLS Termination Proxy **तय करते हैं कि बाकी TCP communication को कैसे encrypt करना है**। इससे **TLS Handshake** वाला हिस्सा पूरा होता है। + +इसके बाद, client और server के पास एक **encrypted TCP connection** होता है, यही TLS प्रदान करता है। और फिर वे उस connection का उपयोग वास्तविक **HTTP communication** शुरू करने के लिए कर सकते हैं। + +और **HTTPS** यही है, यह pure (unencrypted) TCP connection के बजाय एक **secure TLS connection** के अंदर साधारण **HTTP** ही है। + +/// tip | सुझाव + +ध्यान दें कि communication का encryption **TCP level** पर होता है, HTTP level पर नहीं। + +/// + +### HTTPS Request { #https-request } + +अब जबकि client और server (विशेष रूप से browser और TLS Termination Proxy) के पास एक **encrypted TCP connection** है, वे **HTTP communication** शुरू कर सकते हैं। + +तो, client एक **HTTPS request** भेजता है। यह encrypted TLS connection के माध्यम से बस एक HTTP request है। + + + +### Request को Decrypt करें { #decrypt-the-request } + +TLS Termination Proxy सहमत किए गए encryption का उपयोग **request को decrypt** करने के लिए करेगा, और **साधारण (decrypted) HTTP request** को application चलाने वाले process तक transmit करेगा (उदाहरण के लिए FastAPI application चलाने वाले Uvicorn के साथ एक process)। + + + +### HTTP Response { #http-response } + +Application request को process करेगी और TLS Termination Proxy को एक **साधारण (unencrypted) HTTP response** भेजेगी। + + + +### HTTPS Response { #https-response } + +TLS Termination Proxy फिर पहले सहमत cryptography (जो `someapp.example.com` के लिए certificate से शुरू हुई थी) का उपयोग करके **response को encrypt** करेगा, और इसे browser को वापस भेजेगा। + +इसके बाद, browser verify करेगा कि response valid है और सही cryptographic key आदि से encrypted है। फिर वह **response को decrypt** करेगा और process करेगा। + + + +Client (browser) को पता होगा कि response सही server से आया है क्योंकि यह उस cryptography का उपयोग कर रहा है जिस पर उन्होंने पहले **HTTPS certificate** का उपयोग करके सहमति की थी। + +### Multiple Applications { #multiple-applications } + +उसी server (या servers) में, **multiple applications** हो सकती हैं, उदाहरण के लिए, अन्य API programs या database। + +केवल एक process विशिष्ट IP और port handle कर सकता है (हमारे उदाहरण में TLS Termination Proxy) लेकिन अन्य applications/processes भी server(s) पर चल सकते हैं, जब तक वे **public IP और port के उसी combination** का उपयोग करने की कोशिश नहीं करते। + + + +इस तरह, TLS Termination Proxy **multiple domains** के लिए, multiple applications के लिए HTTPS और certificates handle कर सकता है, और फिर हर मामले में requests को सही application तक transmit कर सकता है। + +### Certificate Renewal { #certificate-renewal } + +भविष्य में किसी समय, प्रत्येक certificate **expire** हो जाएगा (इसे प्राप्त करने के लगभग 3 महीने बाद)। + +और फिर, कोई दूसरा program होगा (कुछ मामलों में यह दूसरा program होता है, कुछ मामलों में यह वही TLS Termination Proxy हो सकता है) जो Let's Encrypt से बात करेगा, और certificate(s) को renew करेगा। + + + +**TLS certificates** किसी **domain name** से **associated** होते हैं, IP address से नहीं। + +इसलिए, certificates renew करने के लिए, renewal program को authority (Let's Encrypt) को **prove** करना होगा कि वह वास्तव में उस domain को **"own" और control** करता है। + +ऐसा करने के लिए, और अलग-अलग application needs को accommodate करने के लिए, इसे करने के कई तरीके हैं। कुछ लोकप्रिय तरीके हैं: + +* **कुछ DNS records modify करें**। + * इसके लिए, renewal program को DNS provider की APIs support करनी होंगी, इसलिए, आप जिस DNS provider का उपयोग कर रहे हैं, उसके आधार पर यह option हो भी सकता है या नहीं भी। +* Domain से associated public IP address पर (कम से कम certificate acquisition process के दौरान) **server के रूप में चलें**। + * जैसा कि हमने ऊपर कहा, केवल एक process किसी विशिष्ट IP और port पर listen कर सकता है। + * यह उन कारणों में से एक है कि जब वही TLS Termination Proxy certificate renewal process का भी ध्यान रखता है तो यह बहुत उपयोगी होता है। + * अन्यथा, आपको TLS Termination Proxy को momentarily stop करना पड़ सकता है, certificates प्राप्त करने के लिए renewal program start करना पड़ सकता है, फिर उन्हें TLS Termination Proxy के साथ configure करना पड़ सकता है, और फिर TLS Termination Proxy को restart करना पड़ सकता है। यह ideal नहीं है, क्योंकि जिस समय TLS Termination Proxy off होगा, उस दौरान आपकी app(s) available नहीं होंगी। + +App को serve करते हुए भी यह पूरा renewal process, उन मुख्य कारणों में से एक है कि आप application server के साथ सीधे TLS certificates (जैसे Uvicorn) का उपयोग करने के बजाय TLS Termination Proxy के साथ **HTTPS handle करने के लिए एक अलग system** रखना चाहेंगे। + +## Proxy Forwarded Headers { #proxy-forwarded-headers } + +HTTPS handle करने के लिए proxy का उपयोग करते समय, आपका **application server** (उदाहरण के लिए FastAPI CLI के माध्यम से Uvicorn) HTTPS process के बारे में कुछ नहीं जानता, यह **TLS Termination Proxy** के साथ plain HTTP में communicate करता है। + +यह **proxy** सामान्यतः request को **application server** तक transmit करने से पहले कुछ HTTP headers on the fly set करेगा, ताकि application server को पता चल सके कि request proxy द्वारा **forwarded** की जा रही है। + +/// note | तकनीकी विवरण + +Proxy headers हैं: + +* [X-Forwarded-For](https://developer.mozilla.org/en-US/docs/Web/HTTP/Reference/Headers/X-Forwarded-For) +* [X-Forwarded-Proto](https://developer.mozilla.org/en-US/docs/Web/HTTP/Reference/Headers/X-Forwarded-Proto) +* [X-Forwarded-Host](https://developer.mozilla.org/en-US/docs/Web/HTTP/Reference/Headers/X-Forwarded-Host) + +/// + +फिर भी, क्योंकि **application server** नहीं जानता कि वह trusted **proxy** के पीछे है, by default, वह उन headers पर trust नहीं करेगा। + +लेकिन आप **application server** को **proxy** द्वारा भेजे गए *forwarded* headers पर trust करने के लिए configure कर सकते हैं। अगर आप FastAPI CLI का उपयोग कर रहे हैं, तो आप *CLI Option* `--forwarded-allow-ips` का उपयोग करके उसे बता सकते हैं कि उसे किन IPs से आने वाले उन *forwarded* headers पर trust करना चाहिए। + +उदाहरण के लिए, अगर **application server** केवल trusted **proxy** से communication receive कर रहा है, तो आप इसे `--forwarded-allow-ips="*"` पर set कर सकते हैं ताकि यह सभी incoming IPs पर trust करे, क्योंकि यह केवल उसी IP से requests receive करेगा जिसका उपयोग **proxy** कर रहा है। + +इस तरह application यह जान पाएगी कि उसका अपना public URL क्या है, क्या वह HTTPS का उपयोग कर रही है, domain, आदि। + +यह उदाहरण के लिए redirects को ठीक से handle करने में उपयोगी होगा। + +/// tip | सुझाव + +आप इसके बारे में documentation में और सीख सकते हैं: [Proxy के पीछे - Proxy Forwarded Headers सक्षम करें](../advanced/behind-a-proxy.md#enable-proxy-forwarded-headers) + +/// + +## Recap { #recap } + +**HTTPS** होना बहुत महत्वपूर्ण है, और अधिकांश मामलों में काफी **critical** है। HTTPS के आसपास एक developer के रूप में आपको जो ज़्यादातर effort लगाना होता है, वह बस **इन concepts को समझने** और वे कैसे काम करते हैं, इसे समझने के बारे में है। + +लेकिन एक बार जब आप **developers के लिए HTTPS** की मूल जानकारी जान लेते हैं, तो आप सब कुछ सरल तरीके से manage करने में मदद के लिए अलग-अलग tools को आसानी से combine और configure कर सकते हैं। + +अगले कुछ chapters में, मैं आपको **FastAPI** applications के लिए **HTTPS** setup करने के कई ठोस उदाहरण दिखाऊँगा। 🔒 diff --git a/docs/hi/docs/deployment/index.md b/docs/hi/docs/deployment/index.md new file mode 100644 index 000000000..7b0c5b2d5 --- /dev/null +++ b/docs/hi/docs/deployment/index.md @@ -0,0 +1,23 @@ +# Deployment { #deployment } + +**FastAPI** application को deploy करना अपेक्षाकृत आसान है। + +## Deployment का क्या अर्थ है { #what-does-deployment-mean } + +किसी application को **deploy** करने का अर्थ है उसे **users के लिए उपलब्ध** कराने के लिए आवश्यक चरण पूरे करना। + +किसी **web API** के लिए, इसमें सामान्यतः उसे एक **remote machine** में रखना शामिल होता है, एक **server program** के साथ जो अच्छा performance, stability आदि प्रदान करता है, ताकि आपके **users** application को कुशलता से और बिना रुकावटों या समस्याओं के **access** कर सकें। + +यह **development** चरणों के विपरीत है, जहाँ आप लगातार code बदल रहे होते हैं, उसे तोड़ते और ठीक करते हैं, development server को रोकते और फिर से शुरू करते हैं, आदि। + +## Deployment Strategies { #deployment-strategies } + +इसे करने के कई तरीके हैं, जो आपके विशिष्ट use case और आपके द्वारा उपयोग किए जाने वाले tools पर निर्भर करते हैं। + +आप tools के संयोजन का उपयोग करके स्वयं **server deploy** कर सकते हैं, आप कोई **cloud service** उपयोग कर सकते हैं जो आपके लिए काम का कुछ हिस्सा करती है, या अन्य संभावित विकल्प चुन सकते हैं। + +उदाहरण के लिए, हमने, FastAPI के पीछे की team ने, [**FastAPI Cloud**](https://fastapicloud.com) बनाया, ताकि FastAPI apps को cloud पर deploy करना जितना संभव हो उतना streamlined हो, FastAPI के साथ काम करने के समान developer experience के साथ। + +मैं आपको कुछ मुख्य concepts दिखाऊँगा जिन्हें **FastAPI** application deploy करते समय शायद ध्यान में रखना चाहिए (हालाँकि इनमें से अधिकतर किसी भी अन्य प्रकार की web application पर लागू होता है)। + +अगले sections में आपको ध्यान में रखने के लिए अधिक details और इसे करने की कुछ techniques दिखेंगी। ✨ diff --git a/docs/hi/docs/deployment/manually.md b/docs/hi/docs/deployment/manually.md new file mode 100644 index 000000000..840421513 --- /dev/null +++ b/docs/hi/docs/deployment/manually.md @@ -0,0 +1,156 @@ +# Server को मैन्युअली चलाएँ { #run-a-server-manually } + +## `fastapi run` Command का उपयोग करें { #use-the-fastapi-run-command } + +संक्षेप में, अपनी FastAPI application serve करने के लिए `fastapi run` का उपयोग करें: + +
+ +```console +$ fastapi run main.py + + FastAPI Starting production server 🚀 + + Searching for package file structure from directories + with __init__.py files + Importing from /home/user/code/awesomeapp + + module 🐍 main.py + + code Importing the FastAPI app object from the module with + the following code: + + from main import app + + app Using import string: main:app + + server Server started at http://0.0.0.0:8000 + server Documentation at http://0.0.0.0:8000/docs + + Logs: + + INFO Started server process [2306215] + INFO Waiting for application startup. + INFO Application startup complete. + INFO Uvicorn running on http://0.0.0.0:8000 (Press CTRL+C + to quit) +``` + +
+ +यह ज़्यादातर मामलों में काम करेगा। 😎 + +आप उस command का उपयोग, उदाहरण के लिए, अपनी **FastAPI** app को किसी container में, किसी server में, आदि शुरू करने के लिए कर सकते हैं। + +## ASGI Servers { #asgi-servers } + +आइए details में थोड़ा और गहराई से देखें। + +FastAPI Python web frameworks और servers बनाने के लिए एक standard का उपयोग करता है जिसे ASGI कहा जाता है। FastAPI एक ASGI web framework है। + +किसी remote server machine में **FastAPI** application (या कोई भी दूसरी ASGI application) चलाने के लिए आपको मुख्य रूप से एक ASGI server program चाहिए, जैसे **Uvicorn**; यही `fastapi` command में default रूप से आता है। + +कई विकल्प हैं, जिनमें शामिल हैं: + +* [Uvicorn](https://www.uvicorn.dev/): एक high performance ASGI server। +* [Hypercorn](https://hypercorn.readthedocs.io/): एक ASGI server जो अन्य features के साथ HTTP/2 और Trio के साथ compatible है। +* [Daphne](https://github.com/django/daphne): Django Channels के लिए बनाया गया ASGI server। +* [Granian](https://github.com/emmett-framework/granian): Python applications के लिए एक Rust HTTP server। + +## Server Machine और Server Program { #server-machine-and-server-program } + +नामों के बारे में ध्यान रखने योग्य एक छोटा-सा detail है। 💡 + +शब्द "**server**" आमतौर पर remote/cloud computer (physical या virtual machine) और उस machine पर चल रहे program (जैसे Uvicorn), दोनों के लिए उपयोग किया जाता है। + +बस ध्यान रखें कि जब आप सामान्य रूप से "server" पढ़ते हैं, तो यह उन दो चीज़ों में से किसी एक को संदर्भित कर सकता है। + +Remote machine का संदर्भ देते समय, इसे **server** कहना आम है, लेकिन **machine**, **VM** (virtual machine), **node** भी कहा जाता है। ये सभी किसी प्रकार की remote machine को संदर्भित करते हैं, जो सामान्यतः Linux चला रही होती है, जहाँ आप programs चलाते हैं। + +## Server Program Install करें { #install-the-server-program } + +जब आप FastAPI install करते हैं, तो यह एक production server, Uvicorn, के साथ आता है, और आप इसे `fastapi run` command से शुरू कर सकते हैं। + +लेकिन आप एक ASGI server को मैन्युअली भी install कर सकते हैं। + +सुनिश्चित करें कि आप एक [virtual environment](../virtual-environments.md) बनाएँ, उसे activate करें, और फिर आप server application install कर सकते हैं। + +उदाहरण के लिए, Uvicorn install करने के लिए: + +
+ +```console +$ pip install "uvicorn[standard]" + +---> 100% +``` + +
+ +किसी भी अन्य ASGI server program के लिए भी इसी तरह की प्रक्रिया लागू होगी। + +/// tip | टिप + +`standard` जोड़ने पर, Uvicorn कुछ recommended extra dependencies install और use करेगा। + +इसमें `uvloop` शामिल है, जो `asyncio` के लिए high-performance drop-in replacement है, और बड़ा concurrency performance boost देता है। + +जब आप `pip install "fastapi[standard]"` जैसी किसी command से FastAPI install करते हैं, तो आपको `uvicorn[standard]` भी मिल जाता है। + +/// + +## Server Program चलाएँ { #run-the-server-program } + +यदि आपने ASGI server मैन्युअली install किया है, तो आमतौर पर आपको अपनी FastAPI application import कराने के लिए एक खास format में import string पास करनी होगी: + +
+ +```console +$ uvicorn main:app --host 0.0.0.0 --port 80 + +INFO: Uvicorn running on http://0.0.0.0:80 (Press CTRL+C to quit) +``` + +
+ +/// note | नोट + +Command `uvicorn main:app` इनका संदर्भ देती है: + +* `main`: file `main.py` (Python "module")। +* `app`: `main.py` के अंदर `app = FastAPI()` line से बनाया गया object। + +यह इसके equivalent है: + +```Python +from main import app +``` + +/// + +हर alternative ASGI server program की command मिलती-जुलती होगी, आप उनके संबंधित documentation में और पढ़ सकते हैं। + +/// warning | चेतावनी + +Uvicorn और अन्य servers एक `--reload` option support करते हैं जो development के दौरान उपयोगी होता है। + +`--reload` option बहुत अधिक resources consume करता है, अधिक unstable होता है, आदि। + +यह **development** के दौरान बहुत मदद करता है, लेकिन आपको इसे **production** में use **नहीं** करना चाहिए। + +/// + +## Deployment Concepts { #deployment-concepts } + +ये examples server program (जैसे Uvicorn) चलाते हैं, **एक single process** शुरू करते हैं, जो predefined port (जैसे `80`) पर सभी IPs (`0.0.0.0`) को listen करता है। + +यह basic idea है। लेकिन आप शायद कुछ अतिरिक्त चीज़ों का ध्यान रखना चाहेंगे, जैसे: + +* Security - HTTPS +* startup पर चलना +* Restarts +* Replication (चल रहे processes की संख्या) +* Memory +* शुरू करने से पहले के previous steps + +अगले chapters में मैं आपको इन concepts में से हर एक के बारे में, उनके बारे में कैसे सोचें, और उन्हें handle करने की strategies के साथ कुछ concrete examples के बारे में और बताऊँगा। 🚀 diff --git a/docs/hi/docs/deployment/server-workers.md b/docs/hi/docs/deployment/server-workers.md new file mode 100644 index 000000000..540c2da5e --- /dev/null +++ b/docs/hi/docs/deployment/server-workers.md @@ -0,0 +1,139 @@ +# Server Workers - Workers के साथ Uvicorn { #server-workers-uvicorn-with-workers } + +आइए पहले वाले deployment concepts को फिर से देखें: + +* Security - HTTPS +* startup पर चलना +* Restarts +* **Replication (चल रहे processes की संख्या)** +* Memory +* शुरू करने से पहले के पिछले steps + +इस बिंदु तक, docs के सभी tutorials में, आपने शायद एक **server program** चलाया होगा, उदाहरण के लिए, `fastapi` command का उपयोग करके, जो Uvicorn चलाता है, और एक **single process** चलाता है। + +Applications deploy करते समय आप शायद **processes की कुछ replication** रखना चाहेंगे ताकि **multiple cores** का लाभ लिया जा सके और अधिक requests handle की जा सकें। + +जैसा कि आपने पिछले chapter में [Deployment Concepts](concepts.md) के बारे में देखा, कई strategies हैं जिनका आप उपयोग कर सकते हैं। + +यहाँ मैं आपको दिखाऊँगा कि `fastapi` command या सीधे `uvicorn` command का उपयोग करके **worker processes** के साथ **Uvicorn** कैसे उपयोग करें। + +/// note | नोट + +यदि आप containers का उपयोग कर रहे हैं, उदाहरण के लिए Docker या Kubernetes के साथ, तो मैं आपको इसके बारे में अगले chapter में और बताऊँगा: [Containers में FastAPI - Docker](docker.md)। + +विशेष रूप से, **Kubernetes** पर चलते समय आप शायद workers का उपयोग **नहीं** करना चाहेंगे और इसके बजाय **प्रति container एक single Uvicorn process** चलाना चाहेंगे, लेकिन मैं आपको इसके बारे में उस chapter में बाद में बताऊँगा। + +/// + +## Multiple Workers { #multiple-workers } + +आप `--workers` command line option के साथ multiple workers शुरू कर सकते हैं: + +//// tab | `fastapi` + +यदि आप `fastapi` command का उपयोग करते हैं: + +
+ +```console +$ fastapi run --workers 4 main.py + + FastAPI Starting production server 🚀 + + Searching for package file structure from directories with + __init__.py files + Importing from /home/user/code/awesomeapp + + module 🐍 main.py + + code Importing the FastAPI app object from the module with the + following code: + + from main import app + + app Using import string: main:app + + server Server started at http://0.0.0.0:8000 + server Documentation at http://0.0.0.0:8000/docs + + Logs: + + INFO Uvicorn running on http://0.0.0.0:8000 (Press CTRL+C to + quit) + INFO Started parent process [27365] + INFO Started server process [27368] + INFO Started server process [27369] + INFO Started server process [27370] + INFO Started server process [27367] + INFO Waiting for application startup. + INFO Waiting for application startup. + INFO Waiting for application startup. + INFO Waiting for application startup. + INFO Application startup complete. + INFO Application startup complete. + INFO Application startup complete. + INFO Application startup complete. +``` + +
+ +//// + +//// tab | `uvicorn` + +यदि आप सीधे `uvicorn` command का उपयोग करना पसंद करते हैं: + +
+ +```console +$ uvicorn main:app --host 0.0.0.0 --port 8080 --workers 4 +INFO: Uvicorn running on http://0.0.0.0:8080 (Press CTRL+C to quit) +INFO: Started parent process [27365] +INFO: Started server process [27368] +INFO: Waiting for application startup. +INFO: Application startup complete. +INFO: Started server process [27369] +INFO: Waiting for application startup. +INFO: Application startup complete. +INFO: Started server process [27370] +INFO: Waiting for application startup. +INFO: Application startup complete. +INFO: Started server process [27367] +INFO: Waiting for application startup. +INFO: Application startup complete. +``` + +
+ +//// + +यहाँ एकमात्र नया option `--workers` है, जो Uvicorn को 4 worker processes शुरू करने के लिए कहता है। + +आप यह भी देख सकते हैं कि यह प्रत्येक process का **PID** दिखाता है, parent process के लिए `27365` (यह **process manager** है) और प्रत्येक worker process के लिए एक: `27368`, `27369`, `27370`, और `27367`। + +## Deployment Concepts { #deployment-concepts } + +यहाँ आपने देखा कि application के execution को **parallelize** करने, CPU में **multiple cores** का लाभ लेने, और **अधिक requests** serve करने में सक्षम होने के लिए multiple **workers** का उपयोग कैसे किया जाता है। + +ऊपर दी गई deployment concepts की सूची से, workers का उपयोग मुख्य रूप से **replication** वाले हिस्से में मदद करेगा, और थोड़ा बहुत **restarts** में भी, लेकिन आपको अभी भी बाकी चीज़ों का ध्यान रखना होगा: + +* **Security - HTTPS** +* **startup पर चलना** +* ***Restarts*** +* Replication (चल रहे processes की संख्या) +* **Memory** +* **शुरू करने से पहले के पिछले steps** + +## Containers और Docker { #containers-and-docker } + +अगले chapter में [Containers में FastAPI - Docker](docker.md) के बारे में मैं कुछ strategies समझाऊँगा जिनका उपयोग आप बाकी **deployment concepts** को handle करने के लिए कर सकते हैं। + +मैं आपको दिखाऊँगा कि single Uvicorn process चलाने के लिए **शुरू से अपनी खुद की image कैसे build करें**। यह एक सरल process है और शायद यही आप तब करना चाहेंगे जब आप **Kubernetes** जैसे distributed container management system का उपयोग कर रहे हों। + +## Recap { #recap } + +आप `fastapi` या `uvicorn` commands के साथ `--workers` CLI option का उपयोग करके multiple worker processes का उपयोग कर सकते हैं, ताकि **multi-core CPUs** का लाभ लिया जा सके और **multiple processes parallel में** चलाए जा सकें। + +यदि आप बाकी deployment concepts का खुद ध्यान रखते हुए **अपना खुद का deployment system** setup कर रहे हैं, तो आप इन tools और ideas का उपयोग कर सकते हैं। + +Containers (जैसे Docker और Kubernetes) के साथ **FastAPI** के बारे में जानने के लिए अगला chapter देखें। आप देखेंगे कि उन tools में बाकी **deployment concepts** को भी हल करने के सरल तरीके हैं। ✨ diff --git a/docs/hi/docs/deployment/versions.md b/docs/hi/docs/deployment/versions.md new file mode 100644 index 000000000..cabf4bc31 --- /dev/null +++ b/docs/hi/docs/deployment/versions.md @@ -0,0 +1,93 @@ +# FastAPI संस्करणों के बारे में { #about-fastapi-versions } + +**FastAPI** पहले से ही कई applications और प्रणालियों में production में उपयोग किया जा रहा है। और test coverage 100% पर रखा जाता है। लेकिन इसका development अभी भी तेजी से आगे बढ़ रहा है। + +नई features अक्सर जोड़ी जाती हैं, bugs नियमित रूप से ठीक किए जाते हैं, और code अभी भी लगातार बेहतर हो रहा है। + +इसीलिए वर्तमान संस्करण अभी भी `0.x.x` हैं, यह दर्शाता है कि हर संस्करण में संभावित रूप से breaking changes हो सकते हैं। यह [Semantic Versioning](https://semver.org/) conventions का पालन करता है। + +आप अभी **FastAPI** के साथ production applications बना सकते हैं (और संभव है कि आप कुछ समय से ऐसा कर भी रहे हों), आपको बस यह सुनिश्चित करना होगा कि आप ऐसा संस्करण उपयोग करें जो आपके बाकी code के साथ सही ढंग से काम करता हो। + +## अपने `fastapi` संस्करण को pin करें { #pin-your-fastapi-version } + +सबसे पहले आपको **FastAPI** के जिस संस्करण का उपयोग आप कर रहे हैं उसे उस विशिष्ट नवीनतम संस्करण पर "pin" करना चाहिए जिसके बारे में आपको पता है कि वह आपके application के लिए सही ढंग से काम करता है। + +उदाहरण के लिए, मान लें कि आप अपने app में संस्करण `0.112.0` उपयोग कर रहे हैं। + +यदि आप `requirements.txt` file उपयोग करते हैं, तो आप संस्करण को इस तरह निर्दिष्ट कर सकते हैं: + +```txt +fastapi[standard]==0.112.0 +``` + +इसका मतलब होगा कि आप ठीक संस्करण `0.112.0` का उपयोग करेंगे। + +या आप इसे इस तरह भी pin कर सकते हैं: + +```txt +fastapi[standard]>=0.112.0,<0.113.0 +``` + +इसका मतलब होगा कि आप संस्करण `0.112.0` या उससे ऊपर, लेकिन `0.113.0` से कम उपयोग करेंगे, उदाहरण के लिए, संस्करण `0.112.2` अभी भी स्वीकार किया जाएगा। + +यदि आप अपनी installations प्रबंधित करने के लिए कोई अन्य tool उपयोग करते हैं, जैसे `uv`, Poetry, Pipenv, या अन्य, तो उन सभी में ऐसा तरीका होता है जिसका उपयोग करके आप अपने packages के लिए विशिष्ट संस्करण परिभाषित कर सकते हैं। + +## उपलब्ध संस्करण { #available-versions } + +आप उपलब्ध संस्करणों को (जैसे वर्तमान नवीनतम क्या है यह जांचने के लिए) [Release Notes](../release-notes.md) में देख सकते हैं। + +## संस्करणों के बारे में { #about-versions } + +Semantic Versioning conventions के अनुसार, `1.0.0` से नीचे का कोई भी संस्करण संभावित रूप से breaking changes जोड़ सकता है। + +FastAPI इस convention का भी पालन करता है कि कोई भी "PATCH" संस्करण परिवर्तन bug fixes और non-breaking changes के लिए होता है। + +/// tip | सुझाव + +"PATCH" आखिरी संख्या होती है, उदाहरण के लिए, `0.2.3` में, PATCH संस्करण `3` है। + +/// + +तो, आपको इस तरह के संस्करण पर pin करने में सक्षम होना चाहिए: + +```txt +fastapi>=0.45.0,<0.46.0 +``` + +Breaking changes और नई features "MINOR" संस्करणों में जोड़ी जाती हैं। + +/// tip | सुझाव + +"MINOR" बीच की संख्या होती है, उदाहरण के लिए, `0.2.3` में, MINOR संस्करण `2` है। + +/// + +## FastAPI संस्करणों को upgrade करना { #upgrading-the-fastapi-versions } + +आपको अपने app के लिए tests जोड़ने चाहिए। + +**FastAPI** के साथ यह बहुत आसान है (Starlette के लिए धन्यवाद), docs देखें: [Testing](../tutorial/testing.md) + +Tests होने के बाद, आप **FastAPI** संस्करण को अधिक हाल के संस्करण में upgrade कर सकते हैं, और अपने tests चलाकर सुनिश्चित कर सकते हैं कि आपका पूरा code सही ढंग से काम कर रहा है। + +यदि सब कुछ काम कर रहा है, या आवश्यक बदलाव करने के बाद, और आपके सभी tests pass हो रहे हैं, तो आप अपने `fastapi` को उस नए हालिया संस्करण पर pin कर सकते हैं। + +## Starlette के बारे में { #about-starlette } + +आपको `starlette` के संस्करण को pin नहीं करना चाहिए। + +**FastAPI** के अलग-अलग संस्करण Starlette के किसी विशिष्ट नए संस्करण का उपयोग करेंगे। + +इसलिए, आप बस **FastAPI** को सही Starlette संस्करण उपयोग करने दे सकते हैं। + +## Pydantic के बारे में { #about-pydantic } + +Pydantic अपने tests में **FastAPI** के tests शामिल करता है, इसलिए Pydantic के नए संस्करण (`1.0.0` से ऊपर) हमेशा FastAPI के साथ compatible होते हैं। + +आप Pydantic को `1.0.0` से ऊपर किसी भी ऐसे संस्करण पर pin कर सकते हैं जो आपके लिए काम करता हो। + +उदाहरण के लिए: + +```txt +pydantic>=2.7.0,<3.0.0 +``` diff --git a/docs/hi/docs/how-to/authentication-error-status-code.md b/docs/hi/docs/how-to/authentication-error-status-code.md new file mode 100644 index 000000000..267743d44 --- /dev/null +++ b/docs/hi/docs/how-to/authentication-error-status-code.md @@ -0,0 +1,17 @@ +# पुराने 403 Authentication Error Status Codes का उपयोग करें { #use-old-403-authentication-error-status-codes } + +FastAPI version `0.122.0` से पहले, जब integrated security utilities failed authentication के बाद client को error लौटाती थीं, तो वे HTTP status code `403 Forbidden` का उपयोग करती थीं। + +FastAPI version `0.122.0` से शुरू होकर, वे अधिक उपयुक्त HTTP status code `401 Unauthorized` का उपयोग करती हैं, और HTTP specifications, [RFC 7235](https://datatracker.ietf.org/doc/html/rfc7235#section-3.1), [RFC 9110](https://datatracker.ietf.org/doc/html/rfc9110#name-401-unauthorized) का पालन करते हुए response में एक उचित `WWW-Authenticate` header लौटाती हैं। + +लेकिन अगर किसी कारण से आपके clients पुराने behavior पर निर्भर हैं, तो आप अपनी security classes में method `make_not_authenticated_error` को override करके उस पर वापस जा सकते हैं। + +उदाहरण के लिए, आप `HTTPBearer` का एक subclass बना सकते हैं जो default `401 Unauthorized` error के बजाय `403 Forbidden` error लौटाता है: + +{* ../../docs_src/authentication_error_status_code/tutorial001_an_py310.py hl[9:13] *} + +/// tip | टिप + +ध्यान दें कि function exception instance लौटाता है, उसे raise नहीं करता। raising बाकी internal code में किया जाता है। + +/// diff --git a/docs/hi/docs/how-to/conditional-openapi.md b/docs/hi/docs/how-to/conditional-openapi.md new file mode 100644 index 000000000..3a39cd326 --- /dev/null +++ b/docs/hi/docs/how-to/conditional-openapi.md @@ -0,0 +1,56 @@ +# सशर्त OpenAPI { #conditional-openapi } + +अगर आपको ज़रूरत हो, तो आप environment के आधार पर OpenAPI को सशर्त रूप से configure करने के लिए settings और environment variables का उपयोग कर सकते हैं, और इसे पूरी तरह disable भी कर सकते हैं। + +## security, APIs, और docs के बारे में { #about-security-apis-and-docs } + +production में अपनी documentation user interfaces को छिपाना आपकी API को सुरक्षित करने का तरीका *नहीं होना चाहिए*। + +इससे आपकी API में कोई अतिरिक्त security नहीं जुड़ती, *path operations* अभी भी वहीं उपलब्ध रहेंगी जहाँ वे हैं। + +अगर आपके code में कोई security flaw है, तो वह अभी भी मौजूद रहेगा। + +documentation को छिपाना बस यह समझना अधिक कठिन बना देता है कि आपकी API के साथ कैसे interact किया जाए, और production में इसे debug करना आपके लिए अधिक कठिन बना सकता है। इसे बस [Security through obscurity](https://en.wikipedia.org/wiki/Security_through_obscurity) का एक रूप माना जा सकता है। + +अगर आप अपनी API को secure करना चाहते हैं, तो कई बेहतर चीज़ें हैं जो आप कर सकते हैं, उदाहरण के लिए: + +* सुनिश्चित करें कि आपके request bodies और responses के लिए अच्छी तरह defined Pydantic models हैं। +* dependencies का उपयोग करके कोई भी required permissions और roles configure करें। +* plaintext passwords कभी store न करें, केवल password hashes store करें। +* pwdlib और JWT tokens आदि जैसे जाने-माने cryptographic tools implement और use करें। +* जहाँ ज़रूरत हो, OAuth2 scopes के साथ अधिक granular permission controls जोड़ें। +* ...आदि। + +फिर भी, आपके पास कोई बहुत विशिष्ट use case हो सकता है जहाँ आपको सच में किसी environment (जैसे production) के लिए या environment variables से मिली configurations के आधार पर API docs को disable करने की ज़रूरत हो। + +## settings और env vars से सशर्त OpenAPI { #conditional-openapi-from-settings-and-env-vars } + +आप अपनी generated OpenAPI और docs UIs को configure करने के लिए आसानी से वही Pydantic settings use कर सकते हैं। + +उदाहरण के लिए: + +{* ../../docs_src/conditional_openapi/tutorial001_py310.py hl[6,11] *} + +यहाँ हम setting `openapi_url` को उसी default `"/openapi.json"` के साथ declare करते हैं। + +और फिर `FastAPI` app बनाते समय हम इसका उपयोग करते हैं। + +फिर आप environment variable `OPENAPI_URL` को empty string पर set करके OpenAPI (UI docs सहित) को disable कर सकते हैं, जैसे: + +
+ +```console +$ OPENAPI_URL= uvicorn main:app + +INFO: Uvicorn running on http://127.0.0.1:8000 (Press CTRL+C to quit) +``` + +
+ +फिर अगर आप `/openapi.json`, `/docs`, या `/redoc` URLs पर जाते हैं, तो आपको बस इस तरह का `404 Not Found` error मिलेगा: + +```JSON +{ + "detail": "Not Found" +} +``` diff --git a/docs/hi/docs/how-to/configure-swagger-ui.md b/docs/hi/docs/how-to/configure-swagger-ui.md new file mode 100644 index 000000000..9df59d68f --- /dev/null +++ b/docs/hi/docs/how-to/configure-swagger-ui.md @@ -0,0 +1,70 @@ +# Swagger UI configure करें { #configure-swagger-ui } + +आप कुछ अतिरिक्त [Swagger UI parameters](https://swagger.io/docs/open-source-tools/swagger-ui/usage/configuration/) configure कर सकते हैं। + +इन्हें configure करने के लिए, `FastAPI()` app object बनाते समय या `get_swagger_ui_html()` function में `swagger_ui_parameters` argument pass करें। + +`swagger_ui_parameters` एक dictionary प्राप्त करता है जिसमें configurations सीधे Swagger UI को pass की जाती हैं। + +FastAPI configurations को **JSON** में बदलता है ताकि वे JavaScript के साथ compatible हों, क्योंकि Swagger UI को यही चाहिए। + +## Syntax Highlighting disable करें { #disable-syntax-highlighting } + +उदाहरण के लिए, आप Swagger UI में syntax highlighting disable कर सकते हैं। + +Settings बदले बिना, syntax highlighting default रूप से enabled रहती है: + + + +लेकिन आप `syntaxHighlight` को `False` पर set करके इसे disable कर सकते हैं: + +{* ../../docs_src/configure_swagger_ui/tutorial001_py310.py hl[3] *} + +...और फिर Swagger UI अब syntax highlighting नहीं दिखाएगा: + + + +## Theme बदलें { #change-the-theme } + +इसी तरह आप key `"syntaxHighlight.theme"` के साथ syntax highlighting theme set कर सकते हैं (ध्यान दें कि इसके बीच में एक dot है): + +{* ../../docs_src/configure_swagger_ui/tutorial002_py310.py hl[3] *} + +वह configuration syntax highlighting color theme बदल देगी: + + + +## Default Swagger UI Parameters बदलें { #change-default-swagger-ui-parameters } + +FastAPI में ज़्यादातर use cases के लिए उपयुक्त कुछ default configuration parameters शामिल हैं। + +इसमें ये default configurations शामिल हैं: + +{* ../../fastapi/openapi/docs.py ln[9:24] hl[18:24] *} + +आप `swagger_ui_parameters` argument में अलग value set करके इनमें से किसी को भी override कर सकते हैं। + +उदाहरण के लिए, `deepLinking` disable करने के लिए आप ये settings `swagger_ui_parameters` में pass कर सकते हैं: + +{* ../../docs_src/configure_swagger_ui/tutorial003_py310.py hl[3] *} + +## अन्य Swagger UI Parameters { #other-swagger-ui-parameters } + +आप जिन अन्य सभी संभावित configurations का उपयोग कर सकते हैं, उन्हें देखने के लिए आधिकारिक [Swagger UI parameters के docs](https://swagger.io/docs/open-source-tools/swagger-ui/usage/configuration/) पढ़ें। + +## केवल JavaScript settings { #javascript-only-settings } + +Swagger UI अन्य configurations को **केवल JavaScript** objects (उदाहरण के लिए, JavaScript functions) होने की भी अनुमति देता है। + +FastAPI में ये केवल JavaScript `presets` settings भी शामिल हैं: + +```JavaScript +presets: [ + SwaggerUIBundle.presets.apis, + SwaggerUIBundle.SwaggerUIStandalonePreset +] +``` + +ये **JavaScript** objects हैं, strings नहीं, इसलिए आप इन्हें सीधे Python code से pass नहीं कर सकते। + +अगर आपको ऐसी केवल JavaScript configurations का उपयोग करना है, तो आप ऊपर दिए गए methods में से किसी एक का उपयोग कर सकते हैं। पूरी Swagger UI *path operation* को override करें और आपको जो भी JavaScript चाहिए उसे manually लिखें। diff --git a/docs/hi/docs/how-to/custom-docs-ui-assets.md b/docs/hi/docs/how-to/custom-docs-ui-assets.md new file mode 100644 index 000000000..5f22186df --- /dev/null +++ b/docs/hi/docs/how-to/custom-docs-ui-assets.md @@ -0,0 +1,185 @@ +# कस्टम Docs UI Static Assets (Self-Hosting) { #custom-docs-ui-static-assets-self-hosting } + +API docs **Swagger UI** और **ReDoc** का उपयोग करते हैं, और उनमें से प्रत्येक को कुछ JavaScript और CSS files की जरूरत होती है। + +Default रूप से, वे files एक CDN से serve की जाती हैं। + +लेकिन इसे customize करना संभव है, आप कोई विशिष्ट CDN set कर सकते हैं, या files को स्वयं serve कर सकते हैं। + +## JavaScript और CSS के लिए कस्टम CDN { #custom-cdn-for-javascript-and-css } + +मान लें कि आप कोई अलग CDN उपयोग करना चाहते हैं, उदाहरण के लिए आप `https://unpkg.com/` उपयोग करना चाहते हैं। + +यह उपयोगी हो सकता है अगर, उदाहरण के लिए, आप ऐसे देश में रहते हैं जो कुछ URLs को restrict करता है। + +### Automatic docs को disable करें { #disable-the-automatic-docs } + +पहला step automatic docs को disable करना है, क्योंकि default रूप से, वे default CDN का उपयोग करते हैं। + +उन्हें disable करने के लिए, अपना `FastAPI` app बनाते समय उनके URLs को `None` पर set करें: + +{* ../../docs_src/custom_docs_ui/tutorial001_py310.py hl[8] *} + +### कस्टम docs शामिल करें { #include-the-custom-docs } + +अब आप कस्टम docs के लिए *path operations* बना सकते हैं। + +आप docs के लिए HTML pages बनाने हेतु FastAPI के internal functions को reuse कर सकते हैं, और उन्हें जरूरी arguments pass कर सकते हैं: + +* `openapi_url`: वह URL जहां docs के लिए HTML page आपके API के लिए OpenAPI schema प्राप्त कर सकता है। आप यहां attribute `app.openapi_url` का उपयोग कर सकते हैं। +* `title`: आपके API का title। +* `oauth2_redirect_url`: default उपयोग करने के लिए आप यहां `app.swagger_ui_oauth2_redirect_url` का उपयोग कर सकते हैं। +* `swagger_js_url`: वह URL जहां आपके Swagger UI docs के लिए HTML **JavaScript** file प्राप्त कर सकता है। यह कस्टम CDN URL है। +* `swagger_css_url`: वह URL जहां आपके Swagger UI docs के लिए HTML **CSS** file प्राप्त कर सकता है। यह कस्टम CDN URL है। + +और ReDoc के लिए भी इसी तरह... + +{* ../../docs_src/custom_docs_ui/tutorial001_py310.py hl[2:6,11:19,22:24,27:33] *} + +/// tip | सुझाव + +`swagger_ui_redirect` के लिए *path operation* तब एक helper है जब आप OAuth2 का उपयोग करते हैं। + +यदि आप अपने API को किसी OAuth2 provider के साथ integrate करते हैं, तो आप authenticate कर पाएंगे और प्राप्त credentials के साथ API docs पर वापस आ पाएंगे। और वास्तविक OAuth2 authentication का उपयोग करके उससे interact कर पाएंगे। + +Swagger UI आपके लिए इसे behind the scenes handle करेगा, लेकिन इसके लिए इस "redirect" helper की जरूरत होती है। + +/// + +### इसे test करने के लिए एक *path operation* बनाएं { #create-a-path-operation-to-test-it } + +अब, यह test करने के लिए कि सब कुछ काम करता है, एक *path operation* बनाएं: + +{* ../../docs_src/custom_docs_ui/tutorial001_py310.py hl[36:38] *} + +### इसे test करें { #test-it } + +अब, आप अपने docs पर [http://127.0.0.1:8000/docs](http://127.0.0.1:8000/docs) जा सकेंगे, और page reload करने पर, यह उन assets को नए CDN से load करेगा। + +## Docs के लिए JavaScript और CSS की Self-hosting { #self-hosting-javascript-and-css-for-docs } + +JavaScript और CSS की self-hosting उपयोगी हो सकती है अगर, उदाहरण के लिए, आपको चाहिए कि आपका app offline रहने पर भी, खुले Internet access के बिना, या local network में काम करता रहे। + +यहां आप देखेंगे कि उन files को स्वयं, उसी FastAPI app में कैसे serve किया जाए, और docs को उनका उपयोग करने के लिए कैसे configure किया जाए। + +### Project file structure { #project-file-structure } + +मान लें आपके project की file structure ऐसी दिखती है: + +``` +. +├── app +│ ├── __init__.py +│ ├── main.py +``` + +अब उन static files को store करने के लिए एक directory बनाएं। + +आपकी नई file structure ऐसी दिख सकती है: + +``` +. +├── app +│   ├── __init__.py +│   ├── main.py +└── static/ +``` + +### Files download करें { #download-the-files } + +Docs के लिए जरूरी static files download करें और उन्हें उस `static/` directory में रखें। + +आप शायद प्रत्येक link पर right-click करके "Save link as..." जैसा कोई option select कर सकते हैं। + +**Swagger UI** files का उपयोग करता है: + +* [`swagger-ui-bundle.js`](https://cdn.jsdelivr.net/npm/swagger-ui-dist@5/swagger-ui-bundle.js) +* [`swagger-ui.css`](https://cdn.jsdelivr.net/npm/swagger-ui-dist@5/swagger-ui.css) + +और **ReDoc** file का उपयोग करता है: + +* [`redoc.standalone.js`](https://cdn.jsdelivr.net/npm/redoc@2/bundles/redoc.standalone.js) + +उसके बाद, आपकी file structure ऐसी दिख सकती है: + +``` +. +├── app +│   ├── __init__.py +│   ├── main.py +└── static + ├── redoc.standalone.js + ├── swagger-ui-bundle.js + └── swagger-ui.css +``` + +### Static files serve करें { #serve-the-static-files } + +* `StaticFiles` import करें। +* किसी विशिष्ट path में `StaticFiles()` instance को "Mount" करें। + +{* ../../docs_src/custom_docs_ui/tutorial002_py310.py hl[7,11] *} + +### Static files को test करें { #test-the-static-files } + +अपना application start करें और [http://127.0.0.1:8000/static/redoc.standalone.js](http://127.0.0.1:8000/static/redoc.standalone.js) पर जाएं। + +आपको **ReDoc** के लिए एक बहुत लंबी JavaScript file दिखनी चाहिए। + +यह कुछ इस तरह से शुरू हो सकती है: + +```JavaScript +/*! For license information please see redoc.standalone.js.LICENSE.txt */ +!function(e,t){"object"==typeof exports&&"object"==typeof module?module.exports=t(require("null")): +... +``` + +यह confirm करता है कि आप अपने app से static files serve कर पा रहे हैं, और आपने docs के लिए static files को सही जगह पर रखा है। + +अब हम app को docs के लिए उन static files का उपयोग करने के लिए configure कर सकते हैं। + +### Static files के लिए automatic docs को disable करें { #disable-the-automatic-docs-for-static-files } + +कस्टम CDN का उपयोग करने जैसा ही, पहला step automatic docs को disable करना है, क्योंकि वे default रूप से CDN का उपयोग करते हैं। + +उन्हें disable करने के लिए, अपना `FastAPI` app बनाते समय उनके URLs को `None` पर set करें: + +{* ../../docs_src/custom_docs_ui/tutorial002_py310.py hl[9] *} + +### Static files के लिए कस्टम docs शामिल करें { #include-the-custom-docs-for-static-files } + +और कस्टम CDN की तरह ही, अब आप कस्टम docs के लिए *path operations* बना सकते हैं। + +फिर से, आप docs के लिए HTML pages बनाने हेतु FastAPI के internal functions को reuse कर सकते हैं, और उन्हें जरूरी arguments pass कर सकते हैं: + +* `openapi_url`: वह URL जहां docs के लिए HTML page आपके API के लिए OpenAPI schema प्राप्त कर सकता है। आप यहां attribute `app.openapi_url` का उपयोग कर सकते हैं। +* `title`: आपके API का title। +* `oauth2_redirect_url`: default उपयोग करने के लिए आप यहां `app.swagger_ui_oauth2_redirect_url` का उपयोग कर सकते हैं। +* `swagger_js_url`: वह URL जहां आपके Swagger UI docs के लिए HTML **JavaScript** file प्राप्त कर सकता है। **यह वही है जिसे अब आपका अपना app serve कर रहा है**। +* `swagger_css_url`: वह URL जहां आपके Swagger UI docs के लिए HTML **CSS** file प्राप्त कर सकता है। **यह वही है जिसे अब आपका अपना app serve कर रहा है**। + +और ReDoc के लिए भी इसी तरह... + +{* ../../docs_src/custom_docs_ui/tutorial002_py310.py hl[2:6,14:22,25:27,30:36] *} + +/// tip | सुझाव + +`swagger_ui_redirect` के लिए *path operation* तब एक helper है जब आप OAuth2 का उपयोग करते हैं। + +यदि आप अपने API को किसी OAuth2 provider के साथ integrate करते हैं, तो आप authenticate कर पाएंगे और प्राप्त credentials के साथ API docs पर वापस आ पाएंगे। और वास्तविक OAuth2 authentication का उपयोग करके उससे interact कर पाएंगे। + +Swagger UI आपके लिए इसे behind the scenes handle करेगा, लेकिन इसके लिए इस "redirect" helper की जरूरत होती है। + +/// + +### Static files को test करने के लिए एक *path operation* बनाएं { #create-a-path-operation-to-test-static-files } + +अब, यह test करने के लिए कि सब कुछ काम करता है, एक *path operation* बनाएं: + +{* ../../docs_src/custom_docs_ui/tutorial002_py310.py hl[39:41] *} + +### Static Files UI को test करें { #test-static-files-ui } + +अब, आप अपना WiFi disconnect कर सकेंगे, अपने docs पर [http://127.0.0.1:8000/docs](http://127.0.0.1:8000/docs) जा सकेंगे, और page reload कर सकेंगे। + +और Internet के बिना भी, आप अपने API के docs देख पाएंगे और उससे interact कर पाएंगे। diff --git a/docs/hi/docs/how-to/custom-request-and-route.md b/docs/hi/docs/how-to/custom-request-and-route.md new file mode 100644 index 000000000..97743d169 --- /dev/null +++ b/docs/hi/docs/how-to/custom-request-and-route.md @@ -0,0 +1,109 @@ +# Custom Request और APIRoute class { #custom-request-and-apiroute-class } + +कुछ मामलों में, आप `Request` और `APIRoute` classes द्वारा उपयोग किए जाने वाले logic को override करना चाह सकते हैं। + +विशेष रूप से, यह middleware में logic का एक अच्छा विकल्प हो सकता है। + +उदाहरण के लिए, अगर आप request body को आपके application द्वारा process किए जाने से पहले पढ़ना या manipulate करना चाहते हैं। + +/// danger | खतरा + +यह एक "advanced" feature है। + +अगर आप अभी-अभी **FastAPI** के साथ शुरुआत कर रहे हैं, तो शायद आप इस section को छोड़ना चाहेंगे। + +/// + +## Use cases { #use-cases } + +कुछ use cases में शामिल हैं: + +* non-JSON request bodies को JSON में convert करना (जैसे [`msgpack`](https://msgpack.org/index.html)). +* gzip-compressed request bodies को decompress करना। +* सभी request bodies को automatically log करना। + +## Custom request body encodings को संभालना { #handling-custom-request-body-encodings } + +आइए देखें कि gzip requests को decompress करने के लिए custom `Request` subclass का उपयोग कैसे करें। + +और उस custom request class का उपयोग करने के लिए एक `APIRoute` subclass। + +### Custom `GzipRequest` class बनाएँ { #create-a-custom-gziprequest-class } + +/// tip | सुझाव + +यह दिखाने के लिए एक सरल उदाहरण है कि यह कैसे काम करता है, अगर आपको Gzip support चाहिए, तो आप दिए गए [`GzipMiddleware`](../advanced/middleware.md#gzipmiddleware) का उपयोग कर सकते हैं। + +/// + +सबसे पहले, हम एक `GzipRequest` class बनाते हैं, जो उपयुक्त header की मौजूदगी में body को decompress करने के लिए `Request.body()` method को overwrite करेगी। + +अगर header में `gzip` नहीं है, तो यह body को decompress करने की कोशिश नहीं करेगी। + +इस तरह, वही route class gzip compressed या uncompressed requests को संभाल सकती है। + +{* ../../docs_src/custom_request_and_route/tutorial001_an_py310.py hl[9:16] *} + +### Custom `GzipRoute` class बनाएँ { #create-a-custom-gziproute-class } + +इसके बाद, हम `fastapi.routing.APIRoute` की एक custom subclass बनाते हैं जो `GzipRequest` का उपयोग करेगी। + +इस बार, यह `APIRoute.get_route_handler()` method को overwrite करेगी। + +यह method एक function return करता है। और वही function एक request प्राप्त करेगा और response return करेगा। + +यहाँ हम इसका उपयोग original request से `GzipRequest` बनाने के लिए करते हैं। + +{* ../../docs_src/custom_request_and_route/tutorial001_an_py310.py hl[19:27] *} + +/// note | तकनीकी विवरण + +एक `Request` में `request.scope` attribute होता है, जो बस एक Python `dict` है जिसमें request से संबंधित metadata होता है। + +एक `Request` में `request.receive` भी होता है, जो request की body को "receive" करने के लिए एक function है। + +`scope` `dict` और `receive` function दोनों ASGI specification का हिस्सा हैं। + +और ये दो चीजें, `scope` और `receive`, नई `Request` instance बनाने के लिए आवश्यक हैं। + +`Request` के बारे में अधिक जानने के लिए [Requests के बारे में Starlette के docs](https://www.starlette.dev/requests/) देखें। + +/// + +`GzipRequest.get_route_handler` द्वारा return किए गए function का केवल एक अलग काम है: `Request` को `GzipRequest` में convert करना। + +ऐसा करने से, हमारा `GzipRequest` data को हमारे *path operations* तक पास करने से पहले decompress करने का ध्यान रखेगा (अगर आवश्यक हो)। + +उसके बाद, processing logic सब वही रहता है। + +लेकिन `GzipRequest.body` में हमारे बदलावों की वजह से, request body जरूरत पड़ने पर **FastAPI** द्वारा load किए जाने पर automatically decompress हो जाएगी। + +## Exception handler में request body तक पहुँचना { #accessing-the-request-body-in-an-exception-handler } + +/// tip | सुझाव + +इसी समस्या को हल करने के लिए, `RequestValidationError` के custom handler में `body` का उपयोग करना शायद बहुत आसान है ([Errors संभालना](../tutorial/handling-errors.md#use-the-requestvalidationerror-body))। + +लेकिन यह उदाहरण अभी भी valid है और यह दिखाता है कि internal components के साथ कैसे interact करें। + +/// + +हम इसी approach का उपयोग exception handler में request body तक पहुँचने के लिए भी कर सकते हैं। + +हमें बस request को `try`/`except` block के अंदर संभालना है: + +{* ../../docs_src/custom_request_and_route/tutorial002_an_py310.py hl[14,16] *} + +अगर कोई exception होता है, तो `Request` instance अभी भी scope में होगी, इसलिए error संभालते समय हम request body को पढ़ सकते हैं और उसका उपयोग कर सकते हैं: + +{* ../../docs_src/custom_request_and_route/tutorial002_an_py310.py hl[17:19] *} + +## Router में custom `APIRoute` class { #custom-apiroute-class-in-a-router } + +आप `APIRouter` का `route_class` parameter भी set कर सकते हैं: + +{* ../../docs_src/custom_request_and_route/tutorial003_py310.py hl[26] *} + +इस उदाहरण में, `router` के अंतर्गत *path operations* custom `TimedRoute` class का उपयोग करेंगे, और response में एक अतिरिक्त `X-Response-Time` header होगा जिसमें response generate करने में लगा समय होगा: + +{* ../../docs_src/custom_request_and_route/tutorial003_py310.py hl[13:20] *} diff --git a/docs/hi/docs/how-to/extending-openapi.md b/docs/hi/docs/how-to/extending-openapi.md new file mode 100644 index 000000000..f3bebfa66 --- /dev/null +++ b/docs/hi/docs/how-to/extending-openapi.md @@ -0,0 +1,88 @@ +# OpenAPI को विस्तारित करना { #extending-openapi } + +कुछ मामलों में आपको generated OpenAPI schema को संशोधित करने की ज़रूरत हो सकती है। + +इस section में आप देखेंगे कि कैसे। + +## सामान्य process { #the-normal-process } + +सामान्य (default) process इस प्रकार है। + +एक `FastAPI` application (instance) में एक `.openapi()` method होता है, जिससे OpenAPI schema return करने की अपेक्षा की जाती है। + +application object बनाने के हिस्से के रूप में, `/openapi.json` के लिए (या आपने अपने `openapi_url` में जो भी set किया है उसके लिए) एक *path operation* registered होता है। + +यह बस application के `.openapi()` method के result के साथ एक JSON response return करता है। + +Default रूप से, method `.openapi()` जो करता है वह यह है कि property `.openapi_schema` को check करता है कि उसमें contents हैं या नहीं, और उन्हें return करता है। + +अगर नहीं हैं, तो यह उन्हें `fastapi.openapi.utils.get_openapi` में utility function का उपयोग करके generate करता है। + +और वह function `get_openapi()` parameters के रूप में ये प्राप्त करता है: + +* `title`: OpenAPI title, जो docs में दिखाया जाता है। +* `version`: आपके API का version, जैसे `2.5.0`। +* `openapi_version`: उपयोग की गई OpenAPI specification का version। Default रूप से, latest: `3.1.0`। +* `summary`: API का एक छोटा summary। +* `description`: आपके API का description, इसमें markdown शामिल हो सकता है और यह docs में दिखाया जाएगा। +* `routes`: application से routes, जो `app.routes` से लिए जाते हैं। FastAPI इन्हें registered *path operations* collect करने के लिए उपयोग करता है, जिनमें included routers से आने वाले भी शामिल हैं। + +/// tip | तकनीकी विवरण + +`app.routes` एक lower-level route tree है। इसमें route candidates शामिल हो सकते हैं जिन्हें FastAPI internally included routers के लिए उपयोग करता है, केवल final `APIRoute` objects ही नहीं। + +आप फिर भी `app.routes` को `get_openapi()` में pass कर सकते हैं। FastAPI effective path operations collect करने के लिए उस route tree को traverse करेगा। + +/// + +/// note | नोट + +parameter `summary` OpenAPI 3.1.0 और उससे ऊपर में उपलब्ध है, जिसे FastAPI 0.99.0 और उससे ऊपर support करता है। + +/// + +## Defaults को override करना { #overriding-the-defaults } + +ऊपर दी गई जानकारी का उपयोग करके, आप OpenAPI schema generate करने और अपनी ज़रूरत के अनुसार प्रत्येक हिस्से को override करने के लिए उसी utility function का उपयोग कर सकते हैं। + +उदाहरण के लिए, आइए [custom logo शामिल करने के लिए ReDoc का OpenAPI extension](https://github.com/Rebilly/ReDoc/blob/master/docs/redoc-vendor-extensions.md#x-logo) जोड़ें। + +### सामान्य **FastAPI** { #normal-fastapi } + +सबसे पहले, अपनी पूरी **FastAPI** application सामान्य रूप से लिखें: + +{* ../../docs_src/extending_openapi/tutorial001_py310.py hl[1,4,7:9] *} + +### OpenAPI schema generate करें { #generate-the-openapi-schema } + +फिर, `custom_openapi()` function के अंदर, OpenAPI schema generate करने के लिए उसी utility function का उपयोग करें: + +{* ../../docs_src/extending_openapi/tutorial001_py310.py hl[2,15:21] *} + +### OpenAPI schema को संशोधित करें { #modify-the-openapi-schema } + +अब आप OpenAPI schema में `info` "object" में custom `x-logo` जोड़कर ReDoc extension जोड़ सकते हैं: + +{* ../../docs_src/extending_openapi/tutorial001_py310.py hl[22:24] *} + +### OpenAPI schema को cache करें { #cache-the-openapi-schema } + +आप अपनी generated schema store करने के लिए property `.openapi_schema` को "cache" के रूप में उपयोग कर सकते हैं। + +इस तरह, जब भी कोई user आपके API docs खोलेगा, आपकी application को हर बार schema generate नहीं करना पड़ेगा। + +यह केवल एक बार generate होगा, और फिर अगली requests के लिए वही cached schema उपयोग किया जाएगा। + +{* ../../docs_src/extending_openapi/tutorial001_py310.py hl[13:14,25:26] *} + +### Method को override करें { #override-the-method } + +अब आप `.openapi()` method को अपने नए function से replace कर सकते हैं। + +{* ../../docs_src/extending_openapi/tutorial001_py310.py hl[29] *} + +### इसे check करें { #check-it } + +जब आप [http://127.0.0.1:8000/redoc](http://127.0.0.1:8000/redoc) पर जाएंगे, तो आप देखेंगे कि आप अपना custom logo उपयोग कर रहे हैं (इस उदाहरण में, **FastAPI** का logo): + + diff --git a/docs/hi/docs/how-to/general.md b/docs/hi/docs/how-to/general.md new file mode 100644 index 000000000..95c8bb653 --- /dev/null +++ b/docs/hi/docs/how-to/general.md @@ -0,0 +1,43 @@ +# सामान्य - How To - Recipes { #general-how-to-recipes } + +सामान्य या अक्सर पूछे जाने वाले प्रश्नों के लिए, docs में अन्य जगहों के कई pointers यहाँ दिए गए हैं। + +## Data फ़िल्टर करें - सुरक्षा { #filter-data-security } + +यह सुनिश्चित करने के लिए कि आप जितना data लौटाना चाहिए उससे अधिक न लौटाएँ, [Tutorial - Response Model - Return Type](../tutorial/response-model.md) के docs पढ़ें। + +## Response Performance को optimize करें - Response Model - Return Type { #optimize-response-performance-response-model-return-type } + +JSON data लौटाते समय performance को optimize करने के लिए, return type या response model का उपयोग करें, इस तरह Pydantic JSON में serialization को Rust side पर संभालेगा, Python से गुज़रे बिना। अधिक पढ़ें [Tutorial - Response Model - Return Type](../tutorial/response-model.md) के docs में। + +## Documentation Tags - OpenAPI { #documentation-tags-openapi } + +अपने *path operations* में tags जोड़ने और उन्हें docs UI में group करने के लिए, [Tutorial - Path Operation Configurations - Tags](../tutorial/path-operation-configuration.md#tags) के docs पढ़ें। + +## Documentation Summary और Description - OpenAPI { #documentation-summary-and-description-openapi } + +अपने *path operations* में summary और description जोड़ने, और उन्हें docs UI में दिखाने के लिए, [Tutorial - Path Operation Configurations - Summary and Description](../tutorial/path-operation-configuration.md#summary-and-description) के docs पढ़ें। + +## Documentation Response description - OpenAPI { #documentation-response-description-openapi } + +response का description define करने के लिए, जो docs UI में दिखाया जाता है, [Tutorial - Path Operation Configurations - Response description](../tutorial/path-operation-configuration.md#response-description) के docs पढ़ें। + +## Documentation में *Path Operation* को Deprecate करें - OpenAPI { #documentation-deprecate-a-path-operation-openapi } + +किसी *path operation* को deprecate करने और उसे docs UI में दिखाने के लिए, [Tutorial - Path Operation Configurations - Deprecation](../tutorial/path-operation-configuration.md#deprecate-a-path-operation) के docs पढ़ें। + +## किसी भी Data को JSON-compatible में convert करें { #convert-any-data-to-json-compatible } + +किसी भी data को JSON-compatible में convert करने के लिए, [Tutorial - JSON Compatible Encoder](../tutorial/encoder.md) के docs पढ़ें। + +## OpenAPI Metadata - Docs { #openapi-metadata-docs } + +अपने OpenAPI schema में metadata जोड़ने के लिए, जिसमें license, version, contact, आदि शामिल हैं, [Tutorial - Metadata and Docs URLs](../tutorial/metadata.md) के docs पढ़ें। + +## OpenAPI Custom URL { #openapi-custom-url } + +OpenAPI URL को customize करने (या हटाने) के लिए, [Tutorial - Metadata and Docs URLs](../tutorial/metadata.md#openapi-url) के docs पढ़ें। + +## OpenAPI Docs URLs { #openapi-docs-urls } + +अपने-आप generate किए गए docs user interfaces के लिए उपयोग किए जाने वाले URLs को update करने के लिए, [Tutorial - Metadata and Docs URLs](../tutorial/metadata.md#docs-urls) के docs पढ़ें। diff --git a/docs/hi/docs/how-to/graphql.md b/docs/hi/docs/how-to/graphql.md new file mode 100644 index 000000000..7a8fbdb3d --- /dev/null +++ b/docs/hi/docs/how-to/graphql.md @@ -0,0 +1,60 @@ +# GraphQL { #graphql } + +क्योंकि **FastAPI** **ASGI** standard पर आधारित है, इसलिए ASGI के साथ compatible किसी भी **GraphQL** library को integrate करना बहुत आसान है। + +आप उसी application में सामान्य FastAPI *path operations* को GraphQL के साथ combine कर सकते हैं। + +/// tip | सुझाव + +**GraphQL** कुछ बहुत specific use cases को solve करता है। + +Common **web APIs** की तुलना में इसके **advantages** और **disadvantages** हैं। + +सुनिश्चित करें कि आप evaluate करें कि आपके use case के लिए **benefits**, **drawbacks** की भरपाई करते हैं या नहीं। 🤓 + +/// + +## GraphQL Libraries { #graphql-libraries } + +यहाँ कुछ **GraphQL** libraries हैं जिनमें **ASGI** support है। आप उन्हें **FastAPI** के साथ उपयोग कर सकते हैं: + +* [Strawberry](https://strawberry.rocks/) 🍓 + * [FastAPI के लिए docs](https://strawberry.rocks/docs/integrations/fastapi) के साथ +* [Ariadne](https://ariadnegraphql.org/) + * [FastAPI के लिए docs](https://ariadnegraphql.org/docs/fastapi-integration) के साथ +* [Tartiflette](https://tartiflette.io/) + * ASGI integration प्रदान करने के लिए [Tartiflette ASGI](https://tartiflette.github.io/tartiflette-asgi/) के साथ +* [Graphene](https://graphene-python.org/) + * [starlette-graphene3](https://github.com/ciscorn/starlette-graphene3) के साथ + +## Strawberry के साथ GraphQL { #graphql-with-strawberry } + +यदि आपको **GraphQL** के साथ काम करने की ज़रूरत है या आप करना चाहते हैं, तो [**Strawberry**](https://strawberry.rocks/) **recommended** library है क्योंकि इसका design **FastAPI** के design के सबसे करीब है, यह पूरी तरह **type annotations** पर आधारित है। + +आपके use case के आधार पर, आप कोई अलग library उपयोग करना पसंद कर सकते हैं, लेकिन अगर आप मुझसे पूछें, तो मैं शायद सुझाव दूँगा कि आप **Strawberry** आज़माएँ। + +यहाँ एक छोटा preview है कि आप Strawberry को FastAPI के साथ कैसे integrate कर सकते हैं: + +{* ../../docs_src/graphql_/tutorial001_py310.py hl[3,22,25] *} + +आप [Strawberry documentation](https://strawberry.rocks/) में Strawberry के बारे में और जान सकते हैं। + +और [FastAPI के साथ Strawberry](https://strawberry.rocks/docs/integrations/fastapi) के बारे में docs भी। + +## Starlette से पुराना `GraphQLApp` { #older-graphqlapp-from-starlette } + +Starlette के पिछले versions में [Graphene](https://graphene-python.org/) के साथ integrate करने के लिए एक `GraphQLApp` class शामिल थी। + +इसे Starlette से deprecated कर दिया गया था, लेकिन यदि आपके पास ऐसा code है जो इसका उपयोग करता था, तो आप आसानी से [starlette-graphene3](https://github.com/ciscorn/starlette-graphene3) पर **migrate** कर सकते हैं, जो वही use case cover करता है और जिसका **लगभग identical interface** है। + +/// tip | सुझाव + +यदि आपको GraphQL की ज़रूरत है, तो मैं फिर भी recommend करूँगा कि आप [Strawberry](https://strawberry.rocks/) देखें, क्योंकि यह custom classes और types की बजाय type annotations पर आधारित है। + +/// + +## और जानें { #learn-more } + +आप [official GraphQL documentation](https://graphql.org/) में **GraphQL** के बारे में और जान सकते हैं। + +आप ऊपर वर्णित उन libraries में से प्रत्येक के बारे में उनके links में और भी पढ़ सकते हैं। diff --git a/docs/hi/docs/how-to/index.md b/docs/hi/docs/how-to/index.md new file mode 100644 index 000000000..c42c2dd0c --- /dev/null +++ b/docs/hi/docs/how-to/index.md @@ -0,0 +1,13 @@ +# कैसे करें - रेसिपी { #how-to-recipes } + +यहाँ आप **कई topics** के लिए अलग-अलग recipes या "how to" guides देखेंगे। + +इनमें से ज़्यादातर ideas कमोबेश **स्वतंत्र** होंगे, और ज़्यादातर मामलों में आपको इन्हें केवल तभी पढ़ने की ज़रूरत होगी जब वे सीधे **आपके project** पर लागू होते हों। + +अगर कुछ आपके project के लिए रोचक और उपयोगी लगता है, तो आगे बढ़कर उसे देखें, लेकिन नहीं तो आप शायद उन्हें छोड़ सकते हैं। + +/// tip | सुझाव + +अगर आप **FastAPI सीखना** structured तरीके से चाहते हैं (recommended), तो इसके बजाय [ट्यूटोरियल - यूज़र गाइड](../tutorial/index.md) को अध्याय-दर-अध्याय पढ़ें। + +/// diff --git a/docs/hi/docs/how-to/migrate-from-pydantic-v1-to-pydantic-v2.md b/docs/hi/docs/how-to/migrate-from-pydantic-v1-to-pydantic-v2.md new file mode 100644 index 000000000..68bc07e30 --- /dev/null +++ b/docs/hi/docs/how-to/migrate-from-pydantic-v1-to-pydantic-v2.md @@ -0,0 +1,153 @@ +# Pydantic v1 से Pydantic v2 में माइग्रेट करें { #migrate-from-pydantic-v1-to-pydantic-v2 } + +अगर आपके पास कोई पुराना FastAPI app है, तो हो सकता है कि आप Pydantic version 1 का उपयोग कर रहे हों। + +FastAPI version 0.100.0 में Pydantic v1 या v2, दोनों में से किसी के लिए support था। यह वही उपयोग करता था जो आपने install किया हुआ था। + +FastAPI version 0.119.0 ने Pydantic v2 के अंदर से Pydantic v1 के लिए आंशिक support पेश किया (`pydantic.v1` के रूप में), ताकि v2 में migration आसान हो सके। + +FastAPI 0.126.0 ने Pydantic v1 के लिए support हटा दिया, लेकिन थोड़े समय के लिए `pydantic.v1` को support करना जारी रखा। + +FastAPI 0.128.0 ने `pydantic.v1` के लिए support भी हटा दिया, इसलिए FastAPI के नवीनतम versions के लिए Pydantic v2 required है। + +/// warning | चेतावनी + +Pydantic team ने **Python 3.14** से शुरू करते हुए, Python के नवीनतम versions के लिए Pydantic v1 का support बंद कर दिया। + +इसमें `pydantic.v1` भी शामिल है, जो अब Python 3.14 और उससे ऊपर में supported नहीं है। + +अगर आप Python की नवीनतम features का उपयोग करना चाहते हैं, तो आपको यह सुनिश्चित करना होगा कि आप Pydantic v2 का उपयोग करें। + +/// + +अगर आपके पास Pydantic v1 वाला कोई पुराना FastAPI app है, तो यहाँ मैं आपको दिखाऊँगा कि उसे Pydantic v2 में कैसे migrate करें, और gradual migration में मदद के लिए **FastAPI 0.119.0 की features** भी दिखाऊँगा। + +## आधिकारिक गाइड { #official-guide } + +Pydantic के पास v1 से v2 के लिए एक आधिकारिक [Migration Guide](https://docs.pydantic.dev/latest/migration/) है। + +इसमें यह भी शामिल है कि क्या बदला है, validations अब कैसे अधिक सही और strict हैं, संभावित caveats आदि। + +क्या बदला है इसे बेहतर समझने के लिए आप इसे पढ़ सकते हैं। + +## Tests { #tests } + +सुनिश्चित करें कि आपके app के लिए [tests](../tutorial/testing.md) हैं और आप उन्हें continuous integration (CI) पर चलाते हैं। + +इस तरह, आप upgrade कर सकते हैं और सुनिश्चित कर सकते हैं कि सब कुछ अभी भी अपेक्षा के अनुसार काम कर रहा है। + +## `bump-pydantic` { #bump-pydantic } + +कई मामलों में, जब आप customizations के बिना regular Pydantic models का उपयोग करते हैं, तो आप Pydantic v1 से Pydantic v2 में migration की अधिकांश प्रक्रिया automate कर पाएँगे। + +आप उसी Pydantic team का [`bump-pydantic`](https://github.com/pydantic/bump-pydantic) उपयोग कर सकते हैं। + +यह tool आपको उस अधिकांश code को अपने आप बदलने में मदद करेगा जिसे बदलने की ज़रूरत है। + +इसके बाद, आप tests चला सकते हैं और जाँच सकते हैं कि सब कुछ काम करता है या नहीं। अगर करता है, तो आपका काम हो गया। 😎 + +## v2 में Pydantic v1 { #pydantic-v1-in-v2 } + +Pydantic v2 में Pydantic v1 की सभी चीज़ें `pydantic.v1` submodule के रूप में शामिल हैं। लेकिन यह Python 3.13 से ऊपर के versions में अब supported नहीं है। + +इसका मतलब है कि आप Pydantic v2 का नवीनतम version install कर सकते हैं और इस submodule से पुराने Pydantic v1 components को import और उपयोग कर सकते हैं, जैसे कि आपके पास पुराना Pydantic v1 install हो। + +{* ../../docs_src/pydantic_v1_in_v2/tutorial001_an_py310.py hl[1,4] *} + +### v2 में Pydantic v1 के लिए FastAPI support { #fastapi-support-for-pydantic-v1-in-v2 } + +/// warning | चेतावनी + +`pydantic.v1` models के लिए यह FastAPI support **FastAPI 0.119.0** में जोड़ा गया था और **FastAPI 0.128.0** में हटा दिया गया। इसका उद्देश्य Pydantic v2 में migration के लिए अस्थायी सहायता होना था। + +FastAPI के वर्तमान versions में, अपने app में `pydantic.v1` model का उपयोग करने पर error आएगा। + +इस section का बाकी हिस्सा केवल उन पुराने versions में उपलब्ध अस्थायी support का वर्णन करता है। + +/// + +FastAPI 0.119.0 से, Pydantic v2 के अंदर से Pydantic v1 के लिए आंशिक support भी है, ताकि v2 में migration आसान हो सके। + +इसलिए, आप Pydantic को नवीनतम version 2 में upgrade कर सकते थे, और imports को `pydantic.v1` submodule का उपयोग करने के लिए बदल सकते थे, और कई मामलों में यह बस काम कर जाता। + +{* ../../docs_src/pydantic_v1_in_v2/tutorial002_an_py310.py hl[2,5,15] *} + +/// warning | चेतावनी + +ध्यान रखें कि Pydantic team अब Python के हाल के versions में Pydantic v1 को support नहीं करती, Python 3.14 से शुरू करते हुए, इसलिए `pydantic.v1` का उपयोग भी Python 3.14 और उससे ऊपर में supported नहीं है। + +/// + +### एक ही app में Pydantic v1 और v2 { #pydantic-v1-and-v2-on-the-same-app } + +Pydantic द्वारा यह **supported नहीं है** कि Pydantic v2 का कोई model हो जिसके अपने fields Pydantic v1 models के रूप में defined हों, या इसका उल्टा। + +```mermaid +graph TB + subgraph "❌ Not Supported" + direction TB + subgraph V2["Pydantic v2 Model"] + V1Field["Pydantic v1 Model"] + end + subgraph V1["Pydantic v1 Model"] + V2Field["Pydantic v2 Model"] + end + end + + style V2 fill:#f9fff3 + style V1 fill:#fff6f0 + style V1Field fill:#fff6f0 + style V2Field fill:#f9fff3 +``` + +...लेकिन आपके पास एक ही app में अलग-अलग models हो सकते हैं, कुछ Pydantic v1 का उपयोग करते हुए और कुछ Pydantic v2 का उपयोग करते हुए। + +```mermaid +graph TB + subgraph "✅ Supported" + direction TB + subgraph V2["Pydantic v2 Model"] + V2Field["Pydantic v2 Model"] + end + subgraph V1["Pydantic v1 Model"] + V1Field["Pydantic v1 Model"] + end + end + + style V2 fill:#f9fff3 + style V1 fill:#fff6f0 + style V1Field fill:#fff6f0 + style V2Field fill:#f9fff3 +``` + +कुछ मामलों में, आपके FastAPI app में एक ही **path operation** में Pydantic v1 और v2 दोनों models होना भी संभव है: + +{* ../../docs_src/pydantic_v1_in_v2/tutorial003_an_py310.py hl[2:3,6,12,21:22] *} + +ऊपर दिए गए इस उदाहरण में, input model एक Pydantic v1 model है, और output model (`response_model=ItemV2` में defined) एक Pydantic v2 model है। + +### Pydantic v1 parameters { #pydantic-v1-parameters } + +अगर आपको Pydantic v1 models के साथ parameters के लिए FastAPI-specific tools जैसे `Body`, `Query`, `Form` आदि का उपयोग करना है, तो Pydantic v2 में migration पूरा करते समय आप उन्हें `fastapi.temp_pydantic_v1_params` से import कर सकते हैं: + +{* ../../docs_src/pydantic_v1_in_v2/tutorial004_an_py310.py hl[4,18] *} + +### चरणों में माइग्रेट करें { #migrate-in-steps } + +/// warning | चेतावनी + +नीचे वर्णित, एक ही app में Pydantic v1 और v2 दोनों models का उपयोग करके gradual migration केवल **FastAPI 0.119.0 से 0.127.x** में काम करता है। इसे **FastAPI 0.128.0** में हटा दिया गया, नवीनतम versions के लिए **Pydantic v2** models required हैं। + +/// + +/// tip | सुझाव + +पहले `bump-pydantic` के साथ कोशिश करें, अगर आपके tests pass हो जाते हैं और वह काम करता है, तो आपका काम एक command में हो गया। ✨ + +/// + +अगर `bump-pydantic` आपके use case के लिए काम नहीं करता, तो आप Pydantic v2 में gradual migration करने के लिए एक ही app में Pydantic v1 और v2 दोनों models के support का उपयोग कर सकते हैं। + +आप पहले Pydantic को नवीनतम version 2 का उपयोग करने के लिए upgrade कर सकते हैं, और अपने सभी models के लिए `pydantic.v1` का उपयोग करने के लिए imports बदल सकते हैं। + +फिर, आप gradual steps में, groups के रूप में अपने models को Pydantic v1 से v2 में migrate करना शुरू कर सकते हैं। 🚶 diff --git a/docs/hi/docs/how-to/separate-openapi-schemas.md b/docs/hi/docs/how-to/separate-openapi-schemas.md new file mode 100644 index 000000000..c5d2b17a0 --- /dev/null +++ b/docs/hi/docs/how-to/separate-openapi-schemas.md @@ -0,0 +1,102 @@ +# Input और Output के लिए अलग OpenAPI Schemas या नहीं { #separate-openapi-schemas-for-input-and-output-or-not } + +जबसे **Pydantic v2** रिलीज़ हुआ है, generated OpenAPI पहले की तुलना में थोड़ा अधिक सटीक और **सही** है। 😎 + +वास्तव में, कुछ मामलों में, एक ही Pydantic model के लिए OpenAPI में **दो JSON Schemas** भी होंगे, input और output के लिए, इस पर निर्भर करते हुए कि उनमें **default values** हैं या नहीं। + +आइए देखते हैं कि यह कैसे काम करता है और अगर आपको ज़रूरत हो तो इसे कैसे बदलना है। + +## Input और Output के लिए Pydantic Models { #pydantic-models-for-input-and-output } + +मान लीजिए आपके पास default values वाला एक Pydantic model है, जैसे यह: + +{* ../../docs_src/separate_openapi_schemas/tutorial001_py310.py ln[1:7] hl[7] *} + +### Input के लिए Model { #model-for-input } + +अगर आप इस model को यहाँ की तरह input के रूप में उपयोग करते हैं: + +{* ../../docs_src/separate_openapi_schemas/tutorial001_py310.py ln[1:15] hl[14] *} + +...तो `description` field **required नहीं होगा**। क्योंकि इसका default value `None` है। + +### Docs में Input Model { #input-model-in-docs } + +आप docs में इसकी पुष्टि कर सकते हैं, `description` field के पास **लाल asterisk** नहीं है, इसे required के रूप में mark नहीं किया गया है: + +
+ +
+ +### Output के लिए Model { #model-for-output } + +लेकिन अगर आप उसी model को output के रूप में उपयोग करते हैं, जैसे यहाँ: + +{* ../../docs_src/separate_openapi_schemas/tutorial001_py310.py hl[19] *} + +...तो क्योंकि `description` का default value है, अगर आप उस field के लिए **कुछ भी return नहीं करते**, तब भी इसका वही **default value** रहेगा। + +### Output Response Data के लिए Model { #model-for-output-response-data } + +अगर आप docs के साथ interact करते हैं और response जाँचते हैं, तो भले ही code ने `description` fields में से किसी एक में कुछ भी add नहीं किया, JSON response में default value (`null`) शामिल होता है: + +
+ +
+ +इसका मतलब है कि इसमें **हमेशा एक value होगा**, बस कभी-कभी value `None` हो सकता है (या JSON में `null`)। + +इसका मतलब है कि आपकी API का उपयोग करने वाले clients को यह जाँचने की ज़रूरत नहीं है कि value मौजूद है या नहीं, वे **मान सकते हैं कि field हमेशा मौजूद रहेगा**, बस कुछ मामलों में इसका default value `None` होगा। + +OpenAPI में इसे describe करने का तरीका है कि उस field को **required** के रूप में mark किया जाए, क्योंकि वह हमेशा मौजूद रहेगा। + +इस वजह से, किसी model के लिए JSON Schema अलग हो सकता है, यह इस पर निर्भर करता है कि उसे **input या output** के लिए उपयोग किया गया है: + +* **input** के लिए `description` **required नहीं होगा** +* **output** के लिए यह **required** होगा (और संभवतः `None`, या JSON terms में, `null`) + +### Docs में Output के लिए Model { #model-for-output-in-docs } + +आप docs में output model भी देख सकते हैं, **दोनों** `name` और `description` को **लाल asterisk** के साथ **required** के रूप में mark किया गया है: + +
+ +
+ +### Docs में Input और Output के लिए Model { #model-for-input-and-output-in-docs } + +और अगर आप OpenAPI में उपलब्ध सभी Schemas (JSON Schemas) जाँचते हैं, तो आप देखेंगे कि दो हैं, एक `Item-Input` और एक `Item-Output`। + +`Item-Input` के लिए, `description` **required नहीं है**, इसमें लाल asterisk नहीं है। + +लेकिन `Item-Output` के लिए, `description` **required** है, इसमें लाल asterisk है। + +
+ +
+ +**Pydantic v2** की इस feature के साथ, आपकी API documentation अधिक **precise** होती है, और अगर आपके पास autogenerated clients और SDKs हैं, तो वे भी अधिक precise होंगे, बेहतर **developer experience** और consistency के साथ। 🎉 + +## Schemas को अलग न करें { #do-not-separate-schemas } + +अब, कुछ मामले ऐसे हैं जहाँ आप **input और output के लिए same schema** रखना चाह सकते हैं। + +शायद इसका मुख्य use case यह है कि अगर आपके पास पहले से कुछ autogenerated client code/SDKs हैं और आप अभी सभी autogenerated client code/SDKs को update नहीं करना चाहते, तो शायद आप इसे किसी समय करना चाहेंगे, लेकिन शायद अभी नहीं। + +उस स्थिति में, आप **FastAPI** में इस feature को parameter `separate_input_output_schemas=False` के साथ disable कर सकते हैं। + +/// note | नोट + +`separate_input_output_schemas` के लिए support FastAPI `0.102.0` में add किया गया था। 🤓 + +/// + +{* ../../docs_src/separate_openapi_schemas/tutorial002_py310.py hl[10] *} + +### Docs में Input और Output Models के लिए Same Schema { #same-schema-for-input-and-output-models-in-docs } + +और अब model के लिए input और output के लिए केवल एक single schema होगा, सिर्फ `Item`, और इसमें `description` **required नहीं** होगा: + +
+ +
diff --git a/docs/hi/docs/how-to/testing-database.md b/docs/hi/docs/how-to/testing-database.md new file mode 100644 index 000000000..c5189ca21 --- /dev/null +++ b/docs/hi/docs/how-to/testing-database.md @@ -0,0 +1,7 @@ +# Database की Testing { #testing-a-database } + +आप databases, SQL, और SQLModel के बारे में [SQLModel docs](https://sqlmodel.tiangolo.com/) में पढ़ सकते हैं। 🤓 + +[FastAPI के साथ SQLModel इस्तेमाल करने पर एक छोटा tutorial](https://sqlmodel.tiangolo.com/tutorial/fastapi/) है। ✨ + +उस tutorial में [SQL databases की testing](https://sqlmodel.tiangolo.com/tutorial/fastapi/tests/) के बारे में एक section शामिल है। 😎 diff --git a/docs/hi/docs/resources/index.md b/docs/hi/docs/resources/index.md new file mode 100644 index 000000000..d60effdc7 --- /dev/null +++ b/docs/hi/docs/resources/index.md @@ -0,0 +1,3 @@ +# संसाधन { #resources } + +अतिरिक्त संसाधन, external links, और भी बहुत कुछ। ✈️ diff --git a/docs/hi/docs/tutorial/security/first-steps.md b/docs/hi/docs/tutorial/security/first-steps.md new file mode 100644 index 000000000..a7bf2e700 --- /dev/null +++ b/docs/hi/docs/tutorial/security/first-steps.md @@ -0,0 +1,203 @@ +# सुरक्षा - पहले कदम { #security-first-steps } + +मान लें कि आपका **backend** API किसी domain में है। + +और आपका **frontend** किसी दूसरे domain में है या उसी domain के किसी अलग path में है (या किसी mobile application में)। + +और आप चाहते हैं कि frontend, **username** और **password** का उपयोग करके backend के साथ authenticate कर सके। + +हम इसे **FastAPI** के साथ बनाने के लिए **OAuth2** का उपयोग कर सकते हैं। + +लेकिन आपको केवल वे छोटी-छोटी जानकारियाँ खोजने के लिए पूरी लंबी specification पढ़ने में समय न लगाना पड़े। + +आइए सुरक्षा संभालने के लिए **FastAPI** द्वारा दिए गए tools का उपयोग करें। + +## यह कैसा दिखता है { #how-it-looks } + +आइए पहले बस code का उपयोग करें और देखें कि यह कैसे काम करता है, और फिर हम वापस आकर समझेंगे कि क्या हो रहा है। + +## `main.py` बनाएँ { #create-main-py } + +उदाहरण को एक file `main.py` में copy करें: + +{* ../../docs_src/security/tutorial001_an_py310.py *} + +## इसे चलाएँ { #run-it } + +/// note | नोट + +[`python-multipart`](https://github.com/Kludex/python-multipart) package **FastAPI** के साथ अपने-आप install हो जाता है जब आप `pip install "fastapi[standard]"` command चलाते हैं। + +हालाँकि, अगर आप `pip install fastapi` command का उपयोग करते हैं, तो `python-multipart` package default रूप से शामिल नहीं होता। + +इसे manually install करने के लिए, सुनिश्चित करें कि आप एक [virtual environment](../../virtual-environments.md) बनाएँ, उसे activate करें, और फिर इसे इस तरह install करें: + +```console +$ pip install python-multipart +``` + +ऐसा इसलिए है क्योंकि **OAuth2**, `username` और `password` भेजने के लिए "form data" का उपयोग करता है। + +/// + +उदाहरण को इस तरह चलाएँ: + +
+ +```console +$ fastapi dev + +INFO: Uvicorn running on http://127.0.0.1:8000 (Press CTRL+C to quit) +``` + +
+ +## इसे जाँचें { #check-it } + +Interactive docs पर जाएँ: [http://127.0.0.1:8000/docs](http://127.0.0.1:8000/docs). + +आपको कुछ ऐसा दिखाई देगा: + + + +/// tip | Authorize बटन! + +आपके पास पहले से ही एक चमकदार नया "Authorize" बटन है। + +और आपकी *path operation* के ऊपर-दाएँ कोने में एक छोटा-सा lock है जिस पर आप click कर सकते हैं। + +/// + +और अगर आप उस पर click करते हैं, तो आपके पास `username` और `password` (और अन्य optional fields) type करने के लिए एक छोटा authorization form होगा: + + + +/// note | नोट + +आप form में क्या type करते हैं, इससे कोई फर्क नहीं पड़ता, यह अभी काम नहीं करेगा। लेकिन हम वहाँ तक पहुँचेंगे। + +/// + +यह निश्चित रूप से final users के लिए frontend नहीं है, लेकिन यह आपके पूरे API को interactively document करने के लिए एक शानदार automatic tool है। + +इसे frontend team द्वारा उपयोग किया जा सकता है (जो आप खुद भी हो सकते हैं)। + +इसे third party applications और systems द्वारा उपयोग किया जा सकता है। + +और इसे आप खुद भी उसी application को debug, check और test करने के लिए उपयोग कर सकते हैं। + +## `password` flow { #the-password-flow } + +अब थोड़ा पीछे चलते हैं और समझते हैं कि यह सब क्या है। + +`password` "flow", OAuth2 में परिभाषित उन तरीकों ("flows") में से एक है, जिनका उपयोग security और authentication संभालने के लिए किया जाता है। + +OAuth2 को इस तरह design किया गया था कि backend या API उस server से independent हो सके जो user को authenticate करता है। + +लेकिन इस case में, वही **FastAPI** application API और authentication दोनों संभालेगा। + +तो, आइए इसे उस simplified दृष्टिकोण से review करें: + +* User frontend में `username` और `password` type करता है, और `Enter` दबाता है। +* Frontend (जो user के browser में चल रहा है) उस `username` और `password` को हमारे API के एक specific URL पर भेजता है (`tokenUrl="token"` के साथ declare किया गया)। +* API उस `username` और `password` को check करता है, और एक "token" के साथ respond करता है (हमने अभी तक इनमें से कुछ भी implement नहीं किया है)। + * एक "token" बस कुछ content वाली string है जिसका उपयोग हम बाद में इस user को verify करने के लिए कर सकते हैं। + * सामान्यतः, token को कुछ समय बाद expire होने के लिए set किया जाता है। + * इसलिए, user को बाद में किसी समय फिर से log in करना होगा। + * और अगर token चोरी हो जाता है, तो risk कम होता है। यह किसी permanent key जैसा नहीं है जो हमेशा काम करेगी (अधिकांश cases में)। +* Frontend उस token को अस्थायी रूप से कहीं store करता है। +* User frontend web app के किसी दूसरे section में जाने के लिए frontend में click करता है। +* Frontend को API से कुछ और data fetch करने की आवश्यकता होती है। + * लेकिन उस specific endpoint के लिए इसे authentication चाहिए। + * इसलिए, हमारे API के साथ authenticate करने के लिए, यह `Authorization` header भेजता है जिसकी value `Bearer ` plus token होती है। + * अगर token में `foobar` है, तो `Authorization` header का content होगा: `Bearer foobar`. + +## **FastAPI** का `OAuth2PasswordBearer` { #fastapis-oauth2passwordbearer } + +**FastAPI** इन security features को implement करने के लिए abstraction के अलग-अलग levels पर कई tools देता है। + +इस उदाहरण में हम **OAuth2** का उपयोग करने जा रहे हैं, **Password** flow के साथ, **Bearer** token का उपयोग करते हुए। हम यह `OAuth2PasswordBearer` class का उपयोग करके करते हैं। + +/// note | नोट + +"bearer" token एकमात्र विकल्प नहीं है। + +लेकिन हमारे use case के लिए यह सबसे अच्छा है। + +और यह अधिकांश use cases के लिए सबसे अच्छा हो सकता है, जब तक कि आप OAuth2 expert न हों और ठीक-ठीक न जानते हों कि कोई दूसरा विकल्प आपकी आवश्यकताओं के लिए बेहतर क्यों है। + +उस case में, **FastAPI** आपको इसे बनाने के लिए tools भी देता है। + +/// + +जब हम `OAuth2PasswordBearer` class का instance बनाते हैं तो हम `tokenUrl` parameter pass करते हैं। इस parameter में वह URL होता है जिसका उपयोग client (user के browser में चल रहा frontend) token पाने के लिए `username` और `password` भेजने में करेगा। + +{* ../../docs_src/security/tutorial001_an_py310.py hl[8] *} + +/// tip | सुझाव + +यहाँ `tokenUrl="token"` एक relative URL `token` को refer करता है जिसे हमने अभी तक बनाया नहीं है। क्योंकि यह relative URL है, यह `./token` के equivalent है। + +क्योंकि हम relative URL का उपयोग कर रहे हैं, अगर आपका API `https://example.com/` पर स्थित था, तो यह `https://example.com/token` को refer करेगा। लेकिन अगर आपका API `https://example.com/api/v1/` पर स्थित था, तो यह `https://example.com/api/v1/token` को refer करेगा। + +Relative URL का उपयोग करना महत्वपूर्ण है ताकि यह सुनिश्चित हो सके कि आपका application [Proxy के पीछे](../../advanced/behind-a-proxy.md) जैसे advanced use case में भी काम करता रहे। + +/// + +यह parameter उस endpoint / *path operation* को create नहीं करता, बल्कि declare करता है कि URL `/token` वही होगा जिसका उपयोग client को token पाने के लिए करना चाहिए। उस जानकारी का उपयोग OpenAPI में किया जाता है, और फिर interactive API documentation systems में। + +हम जल्द ही वास्तविक path operation भी बनाएँगे। + +/// note | नोट + +अगर आप बहुत strict "Pythonista" हैं, तो आपको parameter name `tokenUrl` की style `token_url` के बजाय पसंद न आए। + +ऐसा इसलिए है क्योंकि यह OpenAPI spec जैसा ही name उपयोग कर रहा है। ताकि अगर आपको इनमें से किसी भी security scheme के बारे में और अधिक जाँच करनी हो, तो आप बस इसे copy और paste करके इसके बारे में और जानकारी खोज सकें। + +/// + +`oauth2_scheme` variable `OAuth2PasswordBearer` का instance है, लेकिन यह एक "callable" भी है। + +इसे इस तरह call किया जा सकता है: + +```Python +oauth2_scheme(some, parameters) +``` + +तो, इसे `Depends` के साथ उपयोग किया जा सकता है। + +### इसका उपयोग करें { #use-it } + +अब आप उस `oauth2_scheme` को `Depends` के साथ dependency में pass कर सकते हैं। + +{* ../../docs_src/security/tutorial001_an_py310.py hl[12] *} + +यह dependency एक `str` प्रदान करेगी जिसे *path operation function* के parameter `token` को assign किया जाता है। + +**FastAPI** जान जाएगा कि यह OpenAPI schema (और automatic API docs) में "security scheme" define करने के लिए इस dependency का उपयोग कर सकता है। + +/// note | तकनीकी विवरण + +**FastAPI** जान जाएगा कि यह OpenAPI में security scheme define करने के लिए `OAuth2PasswordBearer` class (जो dependency में declare की गई है) का उपयोग कर सकता है क्योंकि यह `fastapi.security.oauth2.OAuth2` से inherit करती है, जो बदले में `fastapi.security.base.SecurityBase` से inherit करती है। + +OpenAPI (और automatic API docs) के साथ integrate होने वाली सभी security utilities `SecurityBase` से inherit करती हैं, इसी तरह **FastAPI** जान सकता है कि उन्हें OpenAPI में कैसे integrate करना है। + +/// + +## यह क्या करता है { #what-it-does } + +यह request में उस `Authorization` header को खोजेगा, check करेगा कि value `Bearer ` plus कोई token है या नहीं, और token को `str` के रूप में return करेगा। + +अगर इसे `Authorization` header नहीं दिखता, या value में `Bearer ` token नहीं है, तो यह सीधे 401 status code error (`UNAUTHORIZED`) के साथ respond करेगा। + +Error return करने के लिए आपको यह भी check करने की आवश्यकता नहीं है कि token मौजूद है या नहीं। आप निश्चिंत हो सकते हैं कि अगर आपकी function execute होती है, तो उस token में एक `str` होगा। + +आप इसे अभी interactive docs में आज़मा सकते हैं: + + + +हम अभी token की validity verify नहीं कर रहे हैं, लेकिन यह पहले से ही एक शुरुआत है। + +## Recap { #recap } + +तो, केवल 3 या 4 अतिरिक्त lines में, आपके पास पहले से ही security का कुछ primitive form है। diff --git a/docs/hi/docs/tutorial/security/get-current-user.md b/docs/hi/docs/tutorial/security/get-current-user.md new file mode 100644 index 000000000..403d6e7d5 --- /dev/null +++ b/docs/hi/docs/tutorial/security/get-current-user.md @@ -0,0 +1,105 @@ +# Current User प्राप्त करें { #get-current-user } + +पिछले अध्याय में security system (जो dependency injection system पर आधारित है) *path operation function* को `str` के रूप में एक `token` दे रहा था: + +{* ../../docs_src/security/tutorial001_an_py310.py hl[12] *} + +लेकिन वह अभी भी इतना उपयोगी नहीं है। + +आइए इसे हमें current user देने वाला बनाते हैं। + +## एक user model बनाएँ { #create-a-user-model } + +पहले, एक Pydantic user model बनाते हैं। + +जिस तरह हम bodies declare करने के लिए Pydantic का उपयोग करते हैं, उसी तरह हम इसे कहीं और भी उपयोग कर सकते हैं: + +{* ../../docs_src/security/tutorial002_an_py310.py hl[5,12:16] *} + +## एक `get_current_user` dependency बनाएँ { #create-a-get-current-user-dependency } + +आइए एक dependency `get_current_user` बनाएँ। + +याद है कि dependencies की sub-dependencies हो सकती हैं? + +`get_current_user` के पास उसी `oauth2_scheme` के साथ एक dependency होगी जिसे हमने पहले बनाया था। + +ठीक वैसे ही जैसे हम पहले सीधे *path operation* में कर रहे थे, हमारी नई dependency `get_current_user` sub-dependency `oauth2_scheme` से `str` के रूप में एक `token` प्राप्त करेगी: + +{* ../../docs_src/security/tutorial002_an_py310.py hl[25] *} + +## user प्राप्त करें { #get-the-user } + +`get_current_user` हमारे द्वारा बनाई गई एक (fake) utility function का उपयोग करेगी, जो token को `str` के रूप में लेती है और हमारा Pydantic `User` model लौटाती है: + +{* ../../docs_src/security/tutorial002_an_py310.py hl[19:22,26:27] *} + +## current user inject करें { #inject-the-current-user } + +तो अब हम *path operation* में अपने `get_current_user` के साथ वही `Depends` उपयोग कर सकते हैं: + +{* ../../docs_src/security/tutorial002_an_py310.py hl[31] *} + +ध्यान दें कि हम `current_user` का type Pydantic model `User` के रूप में declare करते हैं। + +यह function के अंदर completion और type checks में हमारी मदद करेगा। + +/// tip | टिप + +आपको याद होगा कि request bodies भी Pydantic models के साथ declare की जाती हैं। + +यहाँ **FastAPI** confuse नहीं होगा क्योंकि आप `Depends` का उपयोग कर रहे हैं। + +/// + +/// tip | टिप + +जिस तरह यह dependency system design किया गया है, वह हमें अलग-अलग dependencies (अलग-अलग "dependables") रखने देता है जो सभी एक `User` model लौटाती हैं। + +हम केवल एक dependency तक सीमित नहीं हैं जो उस type का data लौटा सकती है। + +/// + +## अन्य models { #other-models } + +अब आप *path operation functions* में सीधे current user प्राप्त कर सकते हैं और `Depends` का उपयोग करके **Dependency Injection** स्तर पर security mechanisms संभाल सकते हैं। + +और आप security requirements के लिए कोई भी model या data उपयोग कर सकते हैं (इस मामले में, Pydantic model `User`)। + +लेकिन आप किसी विशेष data model, class या type का उपयोग करने तक सीमित नहीं हैं। + +क्या आप अपने model में `id` और `email` रखना चाहते हैं और कोई `username` नहीं रखना चाहते? बिल्कुल। आप इन्हीं tools का उपयोग कर सकते हैं। + +क्या आप केवल एक `str` रखना चाहते हैं? या केवल एक `dict`? या सीधे database class model instance? सब कुछ उसी तरह काम करता है। + +असल में आपके application में login करने वाले users नहीं हैं, बल्कि robots, bots, या अन्य systems हैं, जिनके पास बस एक access token है? फिर भी, सब कुछ उसी तरह काम करता है। + +बस अपने application के लिए जिस भी प्रकार का model, जिस भी प्रकार की class, जिस भी प्रकार का database चाहिए, उसका उपयोग करें। **FastAPI** dependency injection system के साथ आपकी ज़रूरतें पूरी करता है। + +## Code size { #code-size } + +यह example verbose लग सकता है। ध्यान रखें कि हम security, data models, utility functions और *path operations* को उसी file में मिला रहे हैं। + +लेकिन यहाँ मुख्य बात है। + +security और dependency injection से जुड़ी चीज़ें एक बार लिखी जाती हैं। + +और आप इसे जितना चाहें उतना complex बना सकते हैं। फिर भी, यह केवल एक बार, एक ही जगह पर, पूरी flexibility के साथ लिखा जाता है। + +लेकिन आपके पास उसी security system का उपयोग करने वाले हजारों endpoints (*path operations*) हो सकते हैं। + +और वे सभी (या उनका कोई भी हिस्सा जिसे आप चाहें) इन dependencies या आपके द्वारा बनाई गई किसी भी अन्य dependencies को फिर से उपयोग करने का लाभ उठा सकते हैं। + +और ये सभी हजारों *path operations* सिर्फ 3 lines जितने छोटे हो सकते हैं: + +{* ../../docs_src/security/tutorial002_an_py310.py hl[30:32] *} + +## Recap { #recap } + +अब आप अपने *path operation function* में सीधे current user प्राप्त कर सकते हैं। + +हम पहले ही आधे रास्ते तक पहुँच चुके हैं। + +हमें बस user/client के लिए एक *path operation* जोड़ना है ताकि वह वास्तव में `username` और `password` भेज सके। + +वह आगे आता है। diff --git a/docs/hi/docs/tutorial/security/index.md b/docs/hi/docs/tutorial/security/index.md new file mode 100644 index 000000000..43fbd0a9b --- /dev/null +++ b/docs/hi/docs/tutorial/security/index.md @@ -0,0 +1,105 @@ +# Security { #security } + +security, authentication और authorization को handle करने के कई तरीके हैं। + +और यह सामान्यतः एक जटिल और "कठिन" विषय होता है। + +कई frameworks और systems में केवल security और authentication को handle करने में ही बहुत अधिक effort और code लग जाता है (कई मामलों में यह लिखे गए पूरे code का 50% या उससे अधिक हो सकता है)। + +**FastAPI** आपको **Security** से आसानी से, तेज़ी से, standard तरीके से निपटने में मदद करने के लिए कई tools प्रदान करता है, बिना सभी security specifications को पढ़ने और सीखने की ज़रूरत के। + +लेकिन पहले, आइए कुछ छोटे concepts देखते हैं। + +## जल्दी में हैं? { #in-a-hurry } + +अगर आपको इन terms की परवाह नहीं है और आपको बस username और password पर आधारित authentication के साथ security *अभी* जोड़नी है, तो अगले chapters पर जाएँ। + +## OAuth2 { #oauth2 } + +OAuth2 एक specification है जो authentication और authorization को handle करने के कई तरीके define करती है। + +यह काफ़ी विस्तृत specification है और कई जटिल use cases को cover करती है। + +इसमें "third party" का उपयोग करके authenticate करने के तरीके शामिल हैं। + +यही चीज़ अंदर से उन सभी systems में इस्तेमाल होती है जिनमें "login with Facebook, Google, X (Twitter), GitHub" होता है। + +### OAuth 1 { #oauth-1 } + +OAuth 1 भी था, जो OAuth2 से बहुत अलग और अधिक जटिल था, क्योंकि इसमें communication को encrypt करने के तरीके पर direct specifications शामिल थीं। + +आजकल यह बहुत लोकप्रिय या इस्तेमाल में नहीं है। + +OAuth2 यह specify नहीं करता कि communication को कैसे encrypt करना है, यह अपेक्षा करता है कि आपकी application HTTPS के साथ serve की जा रही हो। + +/// tip | सुझाव + +**deployment** वाले section में आप देखेंगे कि Traefik और Let's Encrypt का उपयोग करके HTTPS को मुफ्त में कैसे setup किया जाता है। + +/// + +## OpenID Connect { #openid-connect } + +OpenID Connect एक और specification है, जो **OAuth2** पर आधारित है। + +यह OAuth2 को बस extend करता है और कुछ ऐसी चीज़ें specify करता है जो OAuth2 में तुलनात्मक रूप से ambiguous हैं, ताकि इसे अधिक interoperable बनाया जा सके। + +उदाहरण के लिए, Google login OpenID Connect का उपयोग करता है (जो अंदर से OAuth2 का उपयोग करता है)। + +लेकिन Facebook login OpenID Connect को support नहीं करता। उसका अपना OAuth2 flavor है। + +### OpenID ("OpenID Connect" नहीं) { #openid-not-openid-connect } + +एक "OpenID" specification भी थी। उसने वही समस्या हल करने की कोशिश की जो **OpenID Connect** करता है, लेकिन वह OAuth2 पर आधारित नहीं थी। + +इसलिए, वह एक पूरा अतिरिक्त system था। + +आजकल यह बहुत लोकप्रिय या इस्तेमाल में नहीं है। + +## OpenAPI { #openapi } + +OpenAPI (पहले Swagger के नाम से जाना जाता था) APIs बनाने के लिए open specification है (अब Linux Foundation का हिस्सा)। + +**FastAPI** **OpenAPI** पर आधारित है। + +इसी वजह से कई automatic interactive documentation interfaces, code generation, आदि होना संभव होता है। + +OpenAPI कई security "schemes" define करने का तरीका देता है। + +इनका उपयोग करके, आप इन सभी standard-based tools का लाभ उठा सकते हैं, जिनमें ये interactive documentation systems भी शामिल हैं। + +OpenAPI निम्नलिखित security schemes define करता है: + +* `apiKey`: एक application-specific key जो यहाँ से आ सकती है: + * एक query parameter. + * एक header. + * एक cookie. +* `http`: standard HTTP authentication systems, जिनमें शामिल हैं: + * `bearer`: एक header `Authorization` जिसमें `Bearer ` plus एक token का value होता है। यह OAuth2 से inherited है। + * HTTP Basic authentication. + * HTTP Digest, आदि। +* `oauth2`: security handle करने के सभी OAuth2 तरीके (जिन्हें "flows" कहा जाता है)। + * इनमें से कई flows OAuth 2.0 authentication provider बनाने के लिए उपयुक्त हैं (जैसे Google, Facebook, X (Twitter), GitHub, आदि): + * `implicit` + * `clientCredentials` + * `authorizationCode` + * लेकिन एक specific "flow" है जिसे उसी application में सीधे authentication handle करने के लिए पूरी तरह इस्तेमाल किया जा सकता है: + * `password`: कुछ अगले chapters इसके examples cover करेंगे। +* `openIdConnect`: इसमें OAuth2 authentication data को automatically discover करने का तरीका होता है। + * यह automatic discovery वही है जो OpenID Connect specification में define की गई है। + +/// tip | सुझाव + +Google, Facebook, X (Twitter), GitHub, आदि जैसे अन्य authentication/authorization providers को integrate करना भी संभव और तुलनात्मक रूप से आसान है। + +सबसे जटिल समस्या उन जैसे authentication/authorization provider बनाना है, लेकिन **FastAPI** आपको इसे आसानी से करने के लिए tools देता है, और आपके लिए heavy lifting करता है। + +/// + +## **FastAPI** utilities { #fastapi-utilities } + +FastAPI इन security schemes में से प्रत्येक के लिए `fastapi.security` module में कई tools प्रदान करता है, जो इन security mechanisms का उपयोग आसान बनाते हैं। + +अगले chapters में आप देखेंगे कि **FastAPI** द्वारा प्रदान किए गए उन tools का उपयोग करके अपनी API में security कैसे जोड़ें। + +और आप यह भी देखेंगे कि यह interactive documentation system में automatically कैसे integrate हो जाता है। diff --git a/docs/hi/docs/tutorial/security/oauth2-jwt.md b/docs/hi/docs/tutorial/security/oauth2-jwt.md new file mode 100644 index 000000000..2066d8f5a --- /dev/null +++ b/docs/hi/docs/tutorial/security/oauth2-jwt.md @@ -0,0 +1,277 @@ +# Password के साथ OAuth2 (और hashing), JWT tokens के साथ Bearer { #oauth2-with-password-and-hashing-bearer-with-jwt-tokens } + +अब जब हमारे पास पूरा security flow है, तो आइए JWT tokens और secure password hashing का उपयोग करके application को वास्तव में secure बनाते हैं। + +यह code ऐसा है जिसे आप अपनी application में सच में उपयोग कर सकते हैं, password hashes को अपने database में save कर सकते हैं, आदि। + +हम पिछले chapter में जहाँ छोड़ा था, वहीं से शुरू करेंगे और उसे आगे बढ़ाएँगे। + +## JWT के बारे में { #about-jwt } + +JWT का मतलब है "JSON Web Tokens"। + +यह एक JSON object को बिना spaces वाली लंबी dense string में codify करने का standard है। यह ऐसा दिखता है: + +``` +eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c +``` + +यह encrypted नहीं है, इसलिए कोई भी contents से जानकारी वापस प्राप्त कर सकता है। + +लेकिन यह signed है। इसलिए, जब आपको कोई token मिलता है जिसे आपने issue किया था, तो आप verify कर सकते हैं कि उसे आपने ही issue किया था। + +इस तरह, आप एक token बना सकते हैं जिसकी expiration, मान लीजिए, 1 week हो। और फिर जब user अगले दिन token के साथ वापस आता है, तो आपको पता होता है कि वह user अभी भी आपके system में logged in है। + +एक week के बाद, token expired हो जाएगा और user authorized नहीं होगा और नया token पाने के लिए उसे फिर से sign in करना होगा। और अगर user (या कोई third party) expiration बदलने के लिए token को modify करने की कोशिश करे, तो आप इसे पता लगा पाएँगे, क्योंकि signatures match नहीं होंगे। + +अगर आप JWT tokens के साथ प्रयोग करना चाहते हैं और देखना चाहते हैं कि वे कैसे काम करते हैं, तो [https://jwt.io](https://jwt.io/) देखें। + +## `PyJWT` install करें { #install-pyjwt } + +Python में JWT tokens generate और verify करने के लिए हमें `PyJWT` install करना होगा। + +सुनिश्चित करें कि आप एक [virtual environment](../../virtual-environments.md) बनाएँ, उसे activate करें, और फिर `pyjwt` install करें: + +
+ +```console +$ pip install pyjwt + +---> 100% +``` + +
+ +/// note | नोट + +अगर आप RSA या ECDSA जैसे digital signature algorithms का उपयोग करने की योजना बना रहे हैं, तो आपको cryptography library dependency `pyjwt[crypto]` install करनी चाहिए। + +आप इसके बारे में [PyJWT Installation docs](https://pyjwt.readthedocs.io/en/latest/installation.html) में और पढ़ सकते हैं। + +/// + +## Password hashing { #password-hashing } + +"Hashing" का मतलब है किसी content (इस मामले में password) को bytes के sequence (बस एक string) में बदलना, जो बेकार/असमझ text जैसा दिखता है। + +जब भी आप बिल्कुल वही content (बिल्कुल वही password) pass करते हैं, आपको बिल्कुल वही gibberish मिलता है। + +लेकिन आप उस gibberish से वापस password में convert नहीं कर सकते। + +### Password hashing क्यों उपयोग करें { #why-use-password-hashing } + +अगर आपका database चोरी हो जाता है, तो चोर के पास आपके users के plaintext passwords नहीं होंगे, केवल hashes होंगे। + +इसलिए, चोर उस password को किसी दूसरे system में उपयोग करने की कोशिश नहीं कर पाएगा (क्योंकि कई users हर जगह वही password उपयोग करते हैं, यह खतरनाक होगा)। + +## `pwdlib` install करें { #install-pwdlib } + +pwdlib password hashes संभालने के लिए एक शानदार Python package है। + +यह कई secure hashing algorithms और उनके साथ काम करने के लिए utilities support करता है। + +Recommended algorithm "Argon2" है। + +सुनिश्चित करें कि आप एक [virtual environment](../../virtual-environments.md) बनाएँ, उसे activate करें, और फिर Argon2 के साथ pwdlib install करें: + +
+ +```console +$ pip install "pwdlib[argon2]" + +---> 100% +``` + +
+ +/// tip | सुझाव + +`pwdlib` के साथ, आप इसे इस तरह configure भी कर सकते हैं कि यह **Django**, **Flask** security plug-in या कई अन्य द्वारा बनाए गए passwords read कर सके। + +तो, उदाहरण के लिए, आप एक database में Django application का वही data FastAPI application के साथ share कर पाएँगे। या उसी database का उपयोग करते हुए धीरे-धीरे Django application को migrate कर पाएँगे। + +और आपके users एक ही समय में आपकी Django app या आपकी **FastAPI** app से login कर पाएँगे। + +/// + +## Passwords को hash और verify करें { #hash-and-verify-the-passwords } + +`pwdlib` से वे tools import करें जिनकी हमें ज़रूरत है। + +Recommended settings के साथ एक PasswordHash instance बनाएँ - इसका उपयोग passwords को hash और verify करने के लिए किया जाएगा। + +/// tip | सुझाव + +pwdlib bcrypt hashing algorithm को भी support करता है लेकिन legacy algorithms शामिल नहीं करता - outdated hashes के साथ काम करने के लिए passlib library का उपयोग करना recommended है। + +उदाहरण के लिए, आप इसका उपयोग किसी दूसरे system (जैसे Django) द्वारा generate किए गए passwords read और verify करने के लिए कर सकते हैं, लेकिन किसी भी नए passwords को Argon2 या Bcrypt जैसे अलग algorithm से hash कर सकते हैं। + +और एक ही समय में उन सभी के साथ compatible रह सकते हैं। + +/// + +User से आने वाले password को hash करने के लिए एक utility function बनाएँ। + +और एक और utility बनाएँ जो verify करे कि received password stored hash से match करता है या नहीं। + +और एक और utility बनाएँ जो authenticate करे और user return करे। + +{* ../../docs_src/security/tutorial004_an_py310.py hl[8,49,51,58:59,62:63,72:79] *} + +जब `authenticate_user` को ऐसे username के साथ call किया जाता है जो database में मौजूद नहीं है, तब भी हम dummy hash के against `verify_password` चलाते हैं। + +यह सुनिश्चित करता है कि username valid हो या न हो, endpoint response देने में लगभग समान समय ले, जिससे **timing attacks** रोके जा सकें जिनका उपयोग मौजूदा usernames enumerate करने के लिए किया जा सकता है। + +/// note | नोट + +अगर आप नए (fake) database `fake_users_db` को check करेंगे, तो आप देखेंगे कि hashed password अब कैसा दिखता है: `"$argon2id$v=19$m=65536,t=3,p=4$wagCPXjifgvUFBzq4hqe3w$CYaIb8sB+wtD+Vu/P4uod1+Qof8h+1g7bbDlBID48Rc"`। + +/// + +## JWT tokens संभालें { #handle-jwt-tokens } + +Installed modules import करें। + +एक random secret key बनाएँ जिसका उपयोग JWT tokens sign करने के लिए किया जाएगा। + +Secure random secret key generate करने के लिए command उपयोग करें: + +
+ +```console +$ openssl rand -hex 32 + +09d25e094faa6ca2556c818166b7a9563b93f7099f6f0f4caa6cf63b88e8d3e7 +``` + +
+ +और output को variable `SECRET_KEY` में copy करें (example वाला उपयोग न करें)। + +JWT token sign करने के लिए उपयोग किए गए algorithm के साथ एक variable `ALGORITHM` बनाएँ और इसे `"HS256"` पर set करें। + +Token की expiration के लिए एक variable बनाएँ। + +एक Pydantic Model define करें जिसका उपयोग response के लिए token endpoint में किया जाएगा। + +नया access token generate करने के लिए एक utility function बनाएँ। + +{* ../../docs_src/security/tutorial004_an_py310.py hl[4,7,13:15,29:31,82:90] *} + +## Dependencies update करें { #update-the-dependencies } + +`get_current_user` को update करें ताकि वह पहले जैसा ही token receive करे, लेकिन इस बार JWT tokens का उपयोग करते हुए। + +Received token को decode करें, verify करें, और current user return करें। + +अगर token invalid है, तो तुरंत HTTP error return करें। + +{* ../../docs_src/security/tutorial004_an_py310.py hl[93:110] *} + +## `/token` *path operation* update करें { #update-the-token-path-operation } + +Token की expiration time के साथ एक `timedelta` बनाएँ। + +एक वास्तविक JWT access token बनाएँ और उसे return करें। + +{* ../../docs_src/security/tutorial004_an_py310.py hl[121:136] *} + +### JWT "subject" `sub` के बारे में technical details { #technical-details-about-the-jwt-subject-sub } + +JWT specification कहता है कि token के subject के साथ एक key `sub` होती है। + +इसका उपयोग करना optional है, लेकिन यही वह जगह है जहाँ आप user की identification रखेंगे, इसलिए हम इसे यहाँ उपयोग कर रहे हैं। + +JWT का उपयोग user की पहचान करने और उन्हें आपकी API पर सीधे operations perform करने की अनुमति देने के अलावा अन्य चीज़ों के लिए भी किया जा सकता है। + +उदाहरण के लिए, आप एक "car" या एक "blog post" की पहचान कर सकते हैं। + +फिर आप उस entity के बारे में permissions जोड़ सकते हैं, जैसे "drive" (car के लिए) या "edit" (blog के लिए)। + +और फिर, आप वह JWT token किसी user (या bot) को दे सकते हैं, और वे उन actions को perform करने के लिए इसका उपयोग कर सकते हैं (car drive करना, या blog post edit करना), बिना account की ज़रूरत के, केवल उस JWT token के साथ जिसे आपकी API ने इसके लिए generate किया है। + +इन ideas का उपयोग करके, JWT का उपयोग कहीं अधिक sophisticated scenarios के लिए किया जा सकता है। + +इन cases में, उन entities में से कई की same ID हो सकती है, मान लीजिए `foo` (एक user `foo`, एक car `foo`, और एक blog post `foo`)। + +इसलिए, ID collisions से बचने के लिए, user के लिए JWT token बनाते समय, आप `sub` key के value के आगे prefix जोड़ सकते हैं, जैसे `username:`। इसलिए, इस example में, `sub` का value हो सकता था: `username:johndoe`। + +ध्यान रखने वाली महत्वपूर्ण बात यह है कि `sub` key के पास पूरी application में unique identifier होना चाहिए, और यह एक string होना चाहिए। + +## इसे check करें { #check-it } + +Server run करें और docs पर जाएँ: [http://127.0.0.1:8000/docs](http://127.0.0.1:8000/docs)। + +आप user interface ऐसा देखेंगे: + + + +Application को पहले की तरह ही authorize करें। + +Credentials का उपयोग करते हुए: + +Username: `johndoe` +Password: `secret` + +/// tip | सुझाव + +ध्यान दें कि code में कहीं भी plaintext password "`secret`" नहीं है, हमारे पास केवल hashed version है। + +/// + + + +Endpoint `/users/me/` call करें, आपको response इस तरह मिलेगा: + +```JSON +{ + "username": "johndoe", + "email": "johndoe@example.com", + "full_name": "John Doe", + "disabled": false +} +``` + + + +अगर आप developer tools खोलते हैं, तो आप देख सकते हैं कि भेजे गए data में केवल token शामिल है, password केवल पहले request में user को authenticate करने और वह access token पाने के लिए भेजा जाता है, लेकिन उसके बाद नहीं: + + + +/// note | नोट + +`Authorization` header पर ध्यान दें, जिसका value `Bearer ` से शुरू होता है। + +/// + +## `scopes` के साथ advanced उपयोग { #advanced-usage-with-scopes } + +OAuth2 में "scopes" की धारणा है। + +आप उनका उपयोग JWT token में permissions का specific set जोड़ने के लिए कर सकते हैं। + +फिर आप यह token सीधे किसी user या third party को दे सकते हैं, ताकि वे restrictions के set के साथ आपकी API से interact कर सकें। + +आप बाद में **Advanced User Guide** में सीख सकते हैं कि उनका उपयोग कैसे करें और वे **FastAPI** में कैसे integrated हैं। + +## Recap { #recap } + +अब तक आपने जो देखा है, उससे आप OAuth2 और JWT जैसे standards का उपयोग करके एक secure **FastAPI** application setup कर सकते हैं। + +लगभग किसी भी framework में security संभालना काफ़ी जल्दी एक जटिल विषय बन जाता है। + +कई packages जो इसे बहुत सरल बनाते हैं, उन्हें data model, database, और available features के साथ कई compromises करने पड़ते हैं। और इनमें से कुछ packages जो चीज़ों को बहुत अधिक सरल बना देते हैं, उनके अंदर वास्तव में security flaws होते हैं। + +--- + +**FastAPI** किसी भी database, data model या tool के साथ कोई compromise नहीं करता। + +यह आपको उन चीज़ों को चुनने की पूरी flexibility देता है जो आपके project के लिए सबसे अच्छी हों। + +और आप सीधे कई well maintained और widely used packages जैसे `pwdlib` और `PyJWT` का उपयोग कर सकते हैं, क्योंकि **FastAPI** external packages integrate करने के लिए किसी complex mechanism की मांग नहीं करता। + +लेकिन यह आपको process को जितना संभव हो उतना सरल बनाने के लिए tools देता है, बिना flexibility, robustness, या security से compromise किए। + +और आप OAuth2 जैसे secure, standard protocols को अपेक्षाकृत simple तरीके से उपयोग और implement कर सकते हैं। + +आप **Advanced User Guide** में और सीख सकते हैं कि अधिक fine-grained permission system के लिए OAuth2 "scopes" का उपयोग कैसे करें, इन्हीं standards का पालन करते हुए। Scopes के साथ OAuth2 वह mechanism है जिसका उपयोग कई बड़े authentication providers, जैसे Facebook, Google, GitHub, Microsoft, X (Twitter), आदि करते हैं, ताकि third party applications को अपने users की ओर से उनकी APIs के साथ interact करने के लिए authorize किया जा सके। From 027f27220c3ba66be6c42c95a227389b19383645 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Tue, 14 Jul 2026 15:40:57 +0000 Subject: [PATCH 428/462] =?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 42338c8d0..cb512f6d5 100644 --- a/docs/en/docs/release-notes.md +++ b/docs/en/docs/release-notes.md @@ -9,6 +9,7 @@ hide: ### Translations +* 🌐 Update translations for hi (add-missing). PR [#15990](https://github.com/fastapi/fastapi/pull/15990) by [@tiangolo](https://github.com/tiangolo). * 🌐 Update translations for hi (add-missing). PR [#15925](https://github.com/fastapi/fastapi/pull/15925) by [@tiangolo](https://github.com/tiangolo). * 🌐 Update translations for hi (add-missing). PR [#15797](https://github.com/fastapi/fastapi/pull/15797) by [@tiangolo](https://github.com/tiangolo). * 🌐 Update `llm-prompt.md` for Hindi. PR [#15810](https://github.com/fastapi/fastapi/pull/15810) by [@YuriiMotov](https://github.com/YuriiMotov). From 2ebfb7a7bc68b5346502676e7a234cd78cf01c26 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebasti=C3=A1n=20Ram=C3=ADrez?= Date: Wed, 15 Jul 2026 10:08:55 +0200 Subject: [PATCH 429/462] =?UTF-8?q?=F0=9F=8C=90=20Update=20translations=20?= =?UTF-8?q?for=20ru=20(update-outdated)=20(#16002)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: github-actions[bot] --- docs/ru/docs/tutorial/frontend.md | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/docs/ru/docs/tutorial/frontend.md b/docs/ru/docs/tutorial/frontend.md index 3b3e43809..b7f4dc0cb 100644 --- a/docs/ru/docs/tutorial/frontend.md +++ b/docs/ru/docs/tutorial/frontend.md @@ -126,6 +126,12 @@ npm run build Любые обычные *операции пути* в приложении всё равно будут иметь приоритет, включая операции в других роутерах. +## Зависимости и middleware { #dependencies-and-middleware } + +HTTP-ответы фронтенда выполняются внутри обычного приложения **FastAPI**, поэтому к ним применяется HTTP middleware. + +Зависимости из приложения, из `APIRouter` и из `include_router()` также применяются к HTTP-ответам фронтенда. Это может быть полезно для защиты фронтенда с помощью аутентификации на основе cookie или похожего механизма. + ## Только статический результат сборки { #static-build-output-only } `app.frontend()` отдаёт файлы, уже сгенерированные сборкой вашего фронтенда. From 24a957b5b01a25718b477897976bff7f032606f3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebasti=C3=A1n=20Ram=C3=ADrez?= Date: Wed, 15 Jul 2026 10:09:15 +0200 Subject: [PATCH 430/462] =?UTF-8?q?=F0=9F=8C=90=20Update=20translations=20?= =?UTF-8?q?for=20es=20(update-outdated)=20(#15997)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: github-actions[bot] --- docs/es/docs/tutorial/frontend.md | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/docs/es/docs/tutorial/frontend.md b/docs/es/docs/tutorial/frontend.md index 707772467..3365ae7f1 100644 --- a/docs/es/docs/tutorial/frontend.md +++ b/docs/es/docs/tutorial/frontend.md @@ -126,6 +126,12 @@ En este ejemplo, los paths frontend se sirven bajo `/app`. Cualquier *path operation* regular en la app seguirá teniendo prioridad, incluso en otros routers. +## Dependencias y Middleware { #dependencies-and-middleware } + +Las responses frontend se ejecutan dentro de la aplicación **FastAPI** normal, así que el middleware HTTP se aplica a ellas. + +Las dependencias de la app, de un `APIRouter` y de `include_router()` también se aplican a las responses frontend. Esto puede ser útil para proteger un frontend con autenticación por cookie o similar. + ## Solo salida estática del build { #static-build-output-only } `app.frontend()` sirve archivos ya generados por tu build del frontend. From 1d02512ce3c5d2ab0cb59ccda44725e7fc3076c7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebasti=C3=A1n=20Ram=C3=ADrez?= Date: Wed, 15 Jul 2026 10:09:33 +0200 Subject: [PATCH 431/462] =?UTF-8?q?=F0=9F=8C=90=20Update=20translations=20?= =?UTF-8?q?for=20pt=20(update-outdated)=20(#16000)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: github-actions[bot] --- docs/pt/docs/tutorial/frontend.md | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/docs/pt/docs/tutorial/frontend.md b/docs/pt/docs/tutorial/frontend.md index 872c32e9e..f0d08ce98 100644 --- a/docs/pt/docs/tutorial/frontend.md +++ b/docs/pt/docs/tutorial/frontend.md @@ -1,6 +1,6 @@ # Frontend { #frontend } -Você pode servir aplicações frontend estáticas com `app.frontend()` ou `router.frontend()`. +Você pode servir aplicações frontend estáticas com `app.frontend()` (ou `router.frontend()`). Isso é útil para ferramentas de frontend que geram arquivos estáticos, como React com Vite, TanStack Router, Astro, Vue, Svelte, Angular, Solid e outras. @@ -126,6 +126,12 @@ Neste exemplo, os paths de frontend são servidos em `/app`. Quaisquer *operações de rota* regulares na aplicação ainda terão precedência, inclusive em outros routers. +## Dependências e Middleware { #dependencies-and-middleware } + +Responses de frontend são executadas dentro da aplicação **FastAPI** normal, então middlewares HTTP se aplicam a elas. + +Dependências da aplicação, de um `APIRouter` e de `include_router()` também se aplicam a responses de frontend. Isso pode ser útil para proteger um frontend com autenticação por cookie ou similar. + ## Apenas Saída de Build Estático { #static-build-output-only } `app.frontend()` serve arquivos já gerados pelo build do seu frontend. From b10d3dac4ce2e17ecd04f65fd92b050ce33ca899 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Wed, 15 Jul 2026 08:09:35 +0000 Subject: [PATCH 432/462] =?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 cb512f6d5..5cbeec3a6 100644 --- a/docs/en/docs/release-notes.md +++ b/docs/en/docs/release-notes.md @@ -9,6 +9,7 @@ hide: ### Translations +* 🌐 Update translations for ru (update-outdated). PR [#16002](https://github.com/fastapi/fastapi/pull/16002) by [@tiangolo](https://github.com/tiangolo). * 🌐 Update translations for hi (add-missing). PR [#15990](https://github.com/fastapi/fastapi/pull/15990) by [@tiangolo](https://github.com/tiangolo). * 🌐 Update translations for hi (add-missing). PR [#15925](https://github.com/fastapi/fastapi/pull/15925) by [@tiangolo](https://github.com/tiangolo). * 🌐 Update translations for hi (add-missing). PR [#15797](https://github.com/fastapi/fastapi/pull/15797) by [@tiangolo](https://github.com/tiangolo). From 3a8ab1f76bc6af6d84101cf21d8180c20f3e6538 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebasti=C3=A1n=20Ram=C3=ADrez?= Date: Wed, 15 Jul 2026 10:09:44 +0200 Subject: [PATCH 433/462] =?UTF-8?q?=F0=9F=8C=90=20Update=20translations=20?= =?UTF-8?q?for=20ja=20(update-outdated)=20(#15998)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: github-actions[bot] --- docs/ja/docs/tutorial/frontend.md | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/docs/ja/docs/tutorial/frontend.md b/docs/ja/docs/tutorial/frontend.md index facbbc1d1..eb23d1e9b 100644 --- a/docs/ja/docs/tutorial/frontend.md +++ b/docs/ja/docs/tutorial/frontend.md @@ -126,6 +126,12 @@ npm run build 他の router 内のものを含め、アプリ内の通常の *path operations* は引き続き優先されます。 +## 依存関係とミドルウェア { #dependencies-and-middleware } + +フロントエンドのレスポンスは通常の **FastAPI** アプリケーション内で実行されるため、HTTP ミドルウェアが適用されます。 + +アプリ、`APIRouter`、および `include_router()` からの依存関係もフロントエンドのレスポンスに適用されます。これは、cookie 認証などでフロントエンドを保護する場合に役立ちます。 + ## 静的ビルド出力のみ { #static-build-output-only } `app.frontend()` は、フロントエンドのビルドで既に生成されたファイルを配信します。 From c29b4a17afe51299200fad8e5bc9f5c8822efe4d Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Wed, 15 Jul 2026 08:10:06 +0000 Subject: [PATCH 434/462] =?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 5cbeec3a6..4f49e40b8 100644 --- a/docs/en/docs/release-notes.md +++ b/docs/en/docs/release-notes.md @@ -9,6 +9,7 @@ hide: ### Translations +* 🌐 Update translations for es (update-outdated). PR [#15997](https://github.com/fastapi/fastapi/pull/15997) by [@tiangolo](https://github.com/tiangolo). * 🌐 Update translations for ru (update-outdated). PR [#16002](https://github.com/fastapi/fastapi/pull/16002) by [@tiangolo](https://github.com/tiangolo). * 🌐 Update translations for hi (add-missing). PR [#15990](https://github.com/fastapi/fastapi/pull/15990) by [@tiangolo](https://github.com/tiangolo). * 🌐 Update translations for hi (add-missing). PR [#15925](https://github.com/fastapi/fastapi/pull/15925) by [@tiangolo](https://github.com/tiangolo). From 75bdc46293f35d8ca806e4690d6e294d9444492b Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Wed, 15 Jul 2026 08:10:14 +0000 Subject: [PATCH 435/462] =?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 4f49e40b8..12be15844 100644 --- a/docs/en/docs/release-notes.md +++ b/docs/en/docs/release-notes.md @@ -9,6 +9,7 @@ hide: ### Translations +* 🌐 Update translations for pt (update-outdated). PR [#16000](https://github.com/fastapi/fastapi/pull/16000) by [@tiangolo](https://github.com/tiangolo). * 🌐 Update translations for es (update-outdated). PR [#15997](https://github.com/fastapi/fastapi/pull/15997) by [@tiangolo](https://github.com/tiangolo). * 🌐 Update translations for ru (update-outdated). PR [#16002](https://github.com/fastapi/fastapi/pull/16002) by [@tiangolo](https://github.com/tiangolo). * 🌐 Update translations for hi (add-missing). PR [#15990](https://github.com/fastapi/fastapi/pull/15990) by [@tiangolo](https://github.com/tiangolo). From 8458d35c96647a92801b9a243f3bd42a24fc7350 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Wed, 15 Jul 2026 08:10:29 +0000 Subject: [PATCH 436/462] =?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 12be15844..c31e9c809 100644 --- a/docs/en/docs/release-notes.md +++ b/docs/en/docs/release-notes.md @@ -9,6 +9,7 @@ hide: ### Translations +* 🌐 Update translations for ja (update-outdated). PR [#15998](https://github.com/fastapi/fastapi/pull/15998) by [@tiangolo](https://github.com/tiangolo). * 🌐 Update translations for pt (update-outdated). PR [#16000](https://github.com/fastapi/fastapi/pull/16000) by [@tiangolo](https://github.com/tiangolo). * 🌐 Update translations for es (update-outdated). PR [#15997](https://github.com/fastapi/fastapi/pull/15997) by [@tiangolo](https://github.com/tiangolo). * 🌐 Update translations for ru (update-outdated). PR [#16002](https://github.com/fastapi/fastapi/pull/16002) by [@tiangolo](https://github.com/tiangolo). From 745d3d222f52ea61c4e9d1cc19c7196992594085 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebasti=C3=A1n=20Ram=C3=ADrez?= Date: Wed, 15 Jul 2026 10:10:36 +0200 Subject: [PATCH 437/462] =?UTF-8?q?=F0=9F=8C=90=20Update=20translations=20?= =?UTF-8?q?for=20uk=20(update-outdated)=20(#16003)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: github-actions[bot] --- docs/uk/docs/tutorial/frontend.md | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/docs/uk/docs/tutorial/frontend.md b/docs/uk/docs/tutorial/frontend.md index c85e6693e..36703764f 100644 --- a/docs/uk/docs/tutorial/frontend.md +++ b/docs/uk/docs/tutorial/frontend.md @@ -126,6 +126,12 @@ npm run build Будь-які звичайні *операції шляху* в застосунку все ще матимуть перевагу, включно з операціями в інших роутерах. +## Залежності та проміжне програмне забезпечення { #dependencies-and-middleware } + +Фронтенд-відповіді виконуються всередині звичайного застосунку **FastAPI**, тому HTTP-проміжне програмне забезпечення застосовується до них. + +Залежності із застосунку, з `APIRouter` і з `include_router()` також застосовуються до фронтенд-відповідей. Це може бути корисно для захисту фронтенду за допомогою автентифікації на основі кукі або подібного. + ## Лише статичний результат збірки { #static-build-output-only } `app.frontend()` обслуговує файли, вже згенеровані вашою фронтенд-збіркою. From 4cb38a48098f0bce73cd6c7242cb6a4f81a5b4c2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebasti=C3=A1n=20Ram=C3=ADrez?= Date: Wed, 15 Jul 2026 10:10:45 +0200 Subject: [PATCH 438/462] =?UTF-8?q?=F0=9F=8C=90=20Update=20translations=20?= =?UTF-8?q?for=20zh=20(update-outdated)=20(#16001)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: github-actions[bot] --- docs/zh/docs/tutorial/frontend.md | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/docs/zh/docs/tutorial/frontend.md b/docs/zh/docs/tutorial/frontend.md index 8b57bbe60..32169076e 100644 --- a/docs/zh/docs/tutorial/frontend.md +++ b/docs/zh/docs/tutorial/frontend.md @@ -126,6 +126,12 @@ npm run build 应用中的任何常规*路径操作*仍会优先,包括其他 router 中的路径操作。 +## 依赖项和中间件 { #dependencies-and-middleware } + +前端响应在普通 **FastAPI** 应用内部运行,因此 HTTP 中间件会应用于它们。 + +来自 app、`APIRouter` 和 `include_router()` 的依赖项也会应用于前端响应。这可用于通过 cookie 身份验证或类似方式保护前端。 + ## 仅限静态构建输出 { #static-build-output-only } `app.frontend()` 提供的是你的前端构建已经生成的文件。 From 10f30b844b370aa56974c59ec8bb13439de75b96 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebasti=C3=A1n=20Ram=C3=ADrez?= Date: Wed, 15 Jul 2026 10:10:56 +0200 Subject: [PATCH 439/462] =?UTF-8?q?=F0=9F=8C=90=20Update=20translations=20?= =?UTF-8?q?for=20ko=20(update-outdated)=20(#16004)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: github-actions[bot] --- docs/ko/docs/tutorial/frontend.md | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/docs/ko/docs/tutorial/frontend.md b/docs/ko/docs/tutorial/frontend.md index 50149432c..452aed034 100644 --- a/docs/ko/docs/tutorial/frontend.md +++ b/docs/ko/docs/tutorial/frontend.md @@ -126,6 +126,12 @@ npm run build 다른 라우터에 있는 것을 포함하여, 애플리케이션의 모든 일반 *경로 처리*가 여전히 우선합니다. +## 의존성과 미들웨어 { #dependencies-and-middleware } + +프론트엔드 응답은 일반 **FastAPI** 애플리케이션 안에서 실행되므로 HTTP 미들웨어가 적용됩니다. + +애플리케이션, `APIRouter`, `include_router()`의 의존성도 프론트엔드 응답에 적용됩니다. 이는 쿠키 인증 등으로 프론트엔드를 보호하는 데 유용할 수 있습니다. + ## 정적 빌드 출력만 사용하기 { #static-build-output-only } `app.frontend()`는 프론트엔드 빌드에서 이미 생성된 파일을 제공합니다. From 362c6f1d3f11b1426cf18315568947e9e64894f3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebasti=C3=A1n=20Ram=C3=ADrez?= Date: Wed, 15 Jul 2026 10:11:05 +0200 Subject: [PATCH 440/462] =?UTF-8?q?=F0=9F=8C=90=20Update=20translations=20?= =?UTF-8?q?for=20de=20(update-outdated)=20(#15999)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: github-actions[bot] --- docs/de/docs/tutorial/frontend.md | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/docs/de/docs/tutorial/frontend.md b/docs/de/docs/tutorial/frontend.md index 9cd4644d9..55213e550 100644 --- a/docs/de/docs/tutorial/frontend.md +++ b/docs/de/docs/tutorial/frontend.md @@ -126,6 +126,12 @@ In diesem Beispiel werden Frontend-Pfade unter `/app` bereitgestellt. Alle regulären *Pfadoperationen* in der App haben weiterhin Vorrang, auch in anderen Routern. +## Abhängigkeiten und Middleware { #dependencies-and-middleware } + +Frontend-Responses laufen innerhalb der normalen **FastAPI**-Anwendung, daher gilt HTTP-Middleware für sie. + +Abhängigkeiten aus der App, aus einem `APIRouter` und aus `include_router()` gelten ebenfalls für Frontend-Responses. Das kann nützlich sein, um ein Frontend mit Cookie-Authentifizierung oder Ähnlichem zu schützen. + ## Nur statischer Build-Output { #static-build-output-only } `app.frontend()` liefert Dateien aus, die bereits von Ihrem Frontend-Build generiert wurden. From 569630f6463ff03bd711ad8dd07af6f074410124 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Wed, 15 Jul 2026 08:11:16 +0000 Subject: [PATCH 441/462] =?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 c31e9c809..d2b772a1c 100644 --- a/docs/en/docs/release-notes.md +++ b/docs/en/docs/release-notes.md @@ -9,6 +9,7 @@ hide: ### Translations +* 🌐 Update translations for uk (update-outdated). PR [#16003](https://github.com/fastapi/fastapi/pull/16003) by [@tiangolo](https://github.com/tiangolo). * 🌐 Update translations for ja (update-outdated). PR [#15998](https://github.com/fastapi/fastapi/pull/15998) by [@tiangolo](https://github.com/tiangolo). * 🌐 Update translations for pt (update-outdated). PR [#16000](https://github.com/fastapi/fastapi/pull/16000) by [@tiangolo](https://github.com/tiangolo). * 🌐 Update translations for es (update-outdated). PR [#15997](https://github.com/fastapi/fastapi/pull/15997) by [@tiangolo](https://github.com/tiangolo). From 3330e247ce1984f2e9bedeb20c6dbdedf3662cfa Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Wed, 15 Jul 2026 08:11:45 +0000 Subject: [PATCH 442/462] =?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 d2b772a1c..6636a123f 100644 --- a/docs/en/docs/release-notes.md +++ b/docs/en/docs/release-notes.md @@ -9,6 +9,7 @@ hide: ### Translations +* 🌐 Update translations for zh (update-outdated). PR [#16001](https://github.com/fastapi/fastapi/pull/16001) by [@tiangolo](https://github.com/tiangolo). * 🌐 Update translations for uk (update-outdated). PR [#16003](https://github.com/fastapi/fastapi/pull/16003) by [@tiangolo](https://github.com/tiangolo). * 🌐 Update translations for ja (update-outdated). PR [#15998](https://github.com/fastapi/fastapi/pull/15998) by [@tiangolo](https://github.com/tiangolo). * 🌐 Update translations for pt (update-outdated). PR [#16000](https://github.com/fastapi/fastapi/pull/16000) by [@tiangolo](https://github.com/tiangolo). From 1bea40556e933861fe5b66e91b04a84c766d6af6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebasti=C3=A1n=20Ram=C3=ADrez?= Date: Wed, 15 Jul 2026 10:12:13 +0200 Subject: [PATCH 443/462] =?UTF-8?q?=F0=9F=8C=90=20Update=20translations=20?= =?UTF-8?q?for=20fr=20(update-outdated)=20(#16006)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: github-actions[bot] --- docs/fr/docs/tutorial/frontend.md | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/docs/fr/docs/tutorial/frontend.md b/docs/fr/docs/tutorial/frontend.md index 6adb8a241..43a136608 100644 --- a/docs/fr/docs/tutorial/frontend.md +++ b/docs/fr/docs/tutorial/frontend.md @@ -126,6 +126,12 @@ Dans cet exemple, les chemins frontend sont servis sous `/app`. Tous les *chemins d'accès* réguliers dans l'application seront toujours prioritaires, y compris dans d'autres routers. +## Dépendances et middleware { #dependencies-and-middleware } + +Les réponses frontend s'exécutent au sein de l'application **FastAPI** normale, donc le middleware HTTP s'applique à elles. + +Les dépendances de l'application, d'un `APIRouter` et de `include_router()` s'appliquent également aux réponses frontend. Cela peut être utile pour protéger un frontend avec une authentification par cookie ou similaire. + ## Sortie de build statique uniquement { #static-build-output-only } `app.frontend()` sert des fichiers déjà générés par votre build frontend. From 38c668601586dbdf38a6d8c4200c6ab6ab745e1b Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Wed, 15 Jul 2026 08:12:46 +0000 Subject: [PATCH 444/462] =?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 6636a123f..9f3ef6f46 100644 --- a/docs/en/docs/release-notes.md +++ b/docs/en/docs/release-notes.md @@ -9,6 +9,7 @@ hide: ### Translations +* 🌐 Update translations for ko (update-outdated). PR [#16004](https://github.com/fastapi/fastapi/pull/16004) by [@tiangolo](https://github.com/tiangolo). * 🌐 Update translations for zh (update-outdated). PR [#16001](https://github.com/fastapi/fastapi/pull/16001) by [@tiangolo](https://github.com/tiangolo). * 🌐 Update translations for uk (update-outdated). PR [#16003](https://github.com/fastapi/fastapi/pull/16003) by [@tiangolo](https://github.com/tiangolo). * 🌐 Update translations for ja (update-outdated). PR [#15998](https://github.com/fastapi/fastapi/pull/15998) by [@tiangolo](https://github.com/tiangolo). From 5ca69d462685929d2c418a0a393d9c13d3d24504 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebasti=C3=A1n=20Ram=C3=ADrez?= Date: Wed, 15 Jul 2026 10:13:02 +0200 Subject: [PATCH 445/462] =?UTF-8?q?=F0=9F=8C=90=20Update=20translations=20?= =?UTF-8?q?for=20zh-hant=20(update-outdated)=20(#15996)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: github-actions[bot] --- docs/zh-hant/docs/tutorial/frontend.md | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/docs/zh-hant/docs/tutorial/frontend.md b/docs/zh-hant/docs/tutorial/frontend.md index 0c568b9f5..fbfd8b3c5 100644 --- a/docs/zh-hant/docs/tutorial/frontend.md +++ b/docs/zh-hant/docs/tutorial/frontend.md @@ -126,6 +126,12 @@ npm run build 應用程式中的任何一般*路徑操作*仍會優先,包括其他 router 中的路徑操作。 +## 依賴項與中介軟體 { #dependencies-and-middleware } + +前端回應會在一般的 **FastAPI** 應用程式內執行,因此 HTTP middleware 會套用到它們。 + +來自 app、`APIRouter` 和 `include_router()` 的 dependencies 也會套用到前端回應。這對使用 cookie authentication 或類似方式保護前端很有用。 + ## 僅限靜態建置輸出 { #static-build-output-only } `app.frontend()` 會提供你的前端建置已經產生的檔案。 From 8f93206768d362c75ba38e7c66a3e104df56222e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebasti=C3=A1n=20Ram=C3=ADrez?= Date: Wed, 15 Jul 2026 10:14:11 +0200 Subject: [PATCH 446/462] =?UTF-8?q?=F0=9F=8C=90=20Update=20translations=20?= =?UTF-8?q?for=20tr=20(update-outdated)=20(#16005)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: github-actions[bot] --- docs/tr/docs/tutorial/frontend.md | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/docs/tr/docs/tutorial/frontend.md b/docs/tr/docs/tutorial/frontend.md index 7918ca593..a9797dc61 100644 --- a/docs/tr/docs/tutorial/frontend.md +++ b/docs/tr/docs/tutorial/frontend.md @@ -126,6 +126,12 @@ Bu örnekte frontend path'leri `/app` altında sunulur. Uygulamadaki herhangi bir normal *path operation*, diğer router'larda olanlar dahil, yine öncelikli olur. +## Dependencies ve Middleware { #dependencies-and-middleware } + +Frontend response'ları normal **FastAPI** uygulaması içinde çalışır, bu yüzden HTTP middleware onlara uygulanır. + +Uygulamadan, bir `APIRouter`'dan ve `include_router()`'dan gelen dependencies de frontend response'larına uygulanır. Bu, bir frontend'i cookie authentication veya benzeri bir yöntemle korumak için kullanışlı olabilir. + ## Yalnızca Statik Build Çıktısı { #static-build-output-only } `app.frontend()`, frontend build'iniz tarafından önceden oluşturulmuş dosyaları sunar. From 061eb10016f5cd680a7796ba0320100ddce00710 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Wed, 15 Jul 2026 08:14:40 +0000 Subject: [PATCH 447/462] =?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 9f3ef6f46..459576f5f 100644 --- a/docs/en/docs/release-notes.md +++ b/docs/en/docs/release-notes.md @@ -9,6 +9,7 @@ hide: ### Translations +* 🌐 Update translations for de (update-outdated). PR [#15999](https://github.com/fastapi/fastapi/pull/15999) by [@tiangolo](https://github.com/tiangolo). * 🌐 Update translations for ko (update-outdated). PR [#16004](https://github.com/fastapi/fastapi/pull/16004) by [@tiangolo](https://github.com/tiangolo). * 🌐 Update translations for zh (update-outdated). PR [#16001](https://github.com/fastapi/fastapi/pull/16001) by [@tiangolo](https://github.com/tiangolo). * 🌐 Update translations for uk (update-outdated). PR [#16003](https://github.com/fastapi/fastapi/pull/16003) by [@tiangolo](https://github.com/tiangolo). From 20d332cb2e33ed5e6a406cffafa79f537852a307 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Wed, 15 Jul 2026 08:15:28 +0000 Subject: [PATCH 448/462] =?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 459576f5f..30fb333de 100644 --- a/docs/en/docs/release-notes.md +++ b/docs/en/docs/release-notes.md @@ -9,6 +9,7 @@ hide: ### Translations +* 🌐 Update translations for fr (update-outdated). PR [#16006](https://github.com/fastapi/fastapi/pull/16006) by [@tiangolo](https://github.com/tiangolo). * 🌐 Update translations for de (update-outdated). PR [#15999](https://github.com/fastapi/fastapi/pull/15999) by [@tiangolo](https://github.com/tiangolo). * 🌐 Update translations for ko (update-outdated). PR [#16004](https://github.com/fastapi/fastapi/pull/16004) by [@tiangolo](https://github.com/tiangolo). * 🌐 Update translations for zh (update-outdated). PR [#16001](https://github.com/fastapi/fastapi/pull/16001) by [@tiangolo](https://github.com/tiangolo). From b959b443577c5f2b870cdef13219b98aa32f8943 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Wed, 15 Jul 2026 08:19:54 +0000 Subject: [PATCH 449/462] =?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 30fb333de..e413e1707 100644 --- a/docs/en/docs/release-notes.md +++ b/docs/en/docs/release-notes.md @@ -9,6 +9,7 @@ hide: ### Translations +* 🌐 Update translations for zh-hant (update-outdated). PR [#15996](https://github.com/fastapi/fastapi/pull/15996) by [@tiangolo](https://github.com/tiangolo). * 🌐 Update translations for fr (update-outdated). PR [#16006](https://github.com/fastapi/fastapi/pull/16006) by [@tiangolo](https://github.com/tiangolo). * 🌐 Update translations for de (update-outdated). PR [#15999](https://github.com/fastapi/fastapi/pull/15999) by [@tiangolo](https://github.com/tiangolo). * 🌐 Update translations for ko (update-outdated). PR [#16004](https://github.com/fastapi/fastapi/pull/16004) by [@tiangolo](https://github.com/tiangolo). From 93b78f8646dea4543cc4d938f7e29b8547749a99 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Wed, 15 Jul 2026 08:21:27 +0000 Subject: [PATCH 450/462] =?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 e413e1707..bc784f269 100644 --- a/docs/en/docs/release-notes.md +++ b/docs/en/docs/release-notes.md @@ -9,6 +9,7 @@ hide: ### Translations +* 🌐 Update translations for tr (update-outdated). PR [#16005](https://github.com/fastapi/fastapi/pull/16005) by [@tiangolo](https://github.com/tiangolo). * 🌐 Update translations for zh-hant (update-outdated). PR [#15996](https://github.com/fastapi/fastapi/pull/15996) by [@tiangolo](https://github.com/tiangolo). * 🌐 Update translations for fr (update-outdated). PR [#16006](https://github.com/fastapi/fastapi/pull/16006) by [@tiangolo](https://github.com/tiangolo). * 🌐 Update translations for de (update-outdated). PR [#15999](https://github.com/fastapi/fastapi/pull/15999) by [@tiangolo](https://github.com/tiangolo). From e24d44cce4092a33b64e9536e96e7608a7dcb9b8 Mon Sep 17 00:00:00 2001 From: Yurii Motov <109919500+YuriiMotov@users.noreply.github.com> Date: Wed, 15 Jul 2026 16:36:37 +0200 Subject: [PATCH 451/462] =?UTF-8?q?=F0=9F=93=9D=20Fix=20topic=20repository?= =?UTF-8?q?=20list=20not=20being=20displayed=20and=20`skip=5Fusers`=20not?= =?UTF-8?q?=20being=20applied=20(#15995)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docs/en/data/skip_users.yml | 1 + docs/en/data/topic_repos.yml | 1 + docs/en/docs/external-links.md | 2 +- docs/en/docs/fastapi-people.md | 14 +++++++------- scripts/topic_repos.py | 2 +- 5 files changed, 11 insertions(+), 9 deletions(-) diff --git a/docs/en/data/skip_users.yml b/docs/en/data/skip_users.yml index cf24003af..26b2247bf 100644 --- a/docs/en/data/skip_users.yml +++ b/docs/en/data/skip_users.yml @@ -1,3 +1,4 @@ +users: - tiangolo - codecov - github-actions diff --git a/docs/en/data/topic_repos.yml b/docs/en/data/topic_repos.yml index ecfad6cb4..eff9f8078 100644 --- a/docs/en/data/topic_repos.yml +++ b/docs/en/data/topic_repos.yml @@ -1,3 +1,4 @@ +repos: - name: headroom html_url: https://github.com/headroomlabs-ai/headroom stars: 55017 diff --git a/docs/en/docs/external-links.md b/docs/en/docs/external-links.md index d614c64eb..7138c3425 100644 --- a/docs/en/docs/external-links.md +++ b/docs/en/docs/external-links.md @@ -23,7 +23,7 @@ But now that FastAPI is the backend framework with the most GitHub stars across Most starred [GitHub repositories with the topic `fastapi`](https://github.com/topics/fastapi): -{% for repo in topic_repos %} +{% for repo in topic_repos.repos %}
★ {{repo.stars}} - {{repo.name}} by @{{repo.owner_login}}. diff --git a/docs/en/docs/fastapi-people.md b/docs/en/docs/fastapi-people.md index e79928fb3..73cd8c613 100644 --- a/docs/en/docs/fastapi-people.md +++ b/docs/en/docs/fastapi-people.md @@ -97,7 +97,7 @@ These are the users that have been [helping others the most with questions in Gi {% for user in people.last_month_experts[:10] %} -{% if user.login not in skip_users %} +{% if user.login not in skip_users.users %}
@{{ user.login }}
Questions replied: {{ user.count }}
@@ -115,7 +115,7 @@ These are the users that have been [helping others the most with questions in Gi {% for user in people.three_months_experts[:10] %} -{% if user.login not in skip_users %} +{% if user.login not in skip_users.users %}
@{{ user.login }}
Questions replied: {{ user.count }}
@@ -133,7 +133,7 @@ These are the users that have been [helping others the most with questions in Gi {% for user in people.six_months_experts[:10] %} -{% if user.login not in skip_users %} +{% if user.login not in skip_users.users %}
@{{ user.login }}
Questions replied: {{ user.count }}
@@ -151,7 +151,7 @@ These are the users that have been [helping others the most with questions in Gi {% for user in people.one_year_experts[:20] %} -{% if user.login not in skip_users %} +{% if user.login not in skip_users.users %}
@{{ user.login }}
Questions replied: {{ user.count }}
@@ -171,7 +171,7 @@ These are the users that have [helped others the most with questions in GitHub]( {% for user in people.experts[:50] %} -{% if user.login not in skip_users %} +{% if user.login not in skip_users.users %}
@{{ user.login }}
Questions replied: {{ user.count }}
@@ -193,7 +193,7 @@ They have contributed source code, documentation, etc. 📦 {% for user in (contributors.values() | list)[:50] %} -{% if user.login not in skip_users %} +{% if user.login not in skip_users.users %}
@{{ user.login }}
Pull Requests: {{ user.count }}
@@ -214,7 +214,7 @@ Translation reviewers have the **power to approve translations** of the document
{% for user in (translation_reviewers.values() | list)[:50] %} -{% if user.login not in skip_users %} +{% if user.login not in skip_users.users %}
@{{ user.login }}
Reviews: {{ user.count }}
diff --git a/scripts/topic_repos.py b/scripts/topic_repos.py index 94379d384..ac2991b11 100644 --- a/scripts/topic_repos.py +++ b/scripts/topic_repos.py @@ -44,7 +44,7 @@ def main() -> None: owner_html_url=repo.owner.html_url, ) ) - data = [repo.model_dump() for repo in final_repos] + data = {"repos": [repo.model_dump() for repo in final_repos]} # Local development # repos_path = Path("../docs/en/data/topic_repos.yml") From 9b8410bdc9fa1fd679ea7e65b926535c7045ab87 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Wed, 15 Jul 2026 14:37:13 +0000 Subject: [PATCH 452/462] =?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 bc784f269..35e8bcb7a 100644 --- a/docs/en/docs/release-notes.md +++ b/docs/en/docs/release-notes.md @@ -7,6 +7,10 @@ hide: ## Latest Changes +### Docs + +* 📝 Fix topic repository list not being displayed and `skip_users` not being applied. PR [#15995](https://github.com/fastapi/fastapi/pull/15995) by [@YuriiMotov](https://github.com/YuriiMotov). + ### Translations * 🌐 Update translations for tr (update-outdated). PR [#16005](https://github.com/fastapi/fastapi/pull/16005) by [@tiangolo](https://github.com/tiangolo). From eb75fd078e83aed935016bcdf0705cd58bbf0d0e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebasti=C3=A1n=20Ram=C3=ADrez?= Date: Thu, 16 Jul 2026 10:59:23 +0200 Subject: [PATCH 453/462] =?UTF-8?q?=F0=9F=90=9B=20Fix=20frontend=20fallbac?= =?UTF-8?q?k=20support=20for=20doted=20paths=20like=20`/users/john.doe`=20?= =?UTF-8?q?(#16011)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docs/en/docs/tutorial/frontend.md | 2 +- fastapi/routing.py | 17 +++-------------- tests/test_frontend.py | 23 +++++++++++++++-------- 3 files changed, 19 insertions(+), 23 deletions(-) diff --git a/docs/en/docs/tutorial/frontend.md b/docs/en/docs/tutorial/frontend.md index 433cea275..0dacc73ba 100644 --- a/docs/en/docs/tutorial/frontend.md +++ b/docs/en/docs/tutorial/frontend.md @@ -52,7 +52,7 @@ For that, use `fallback="index.html"`: {* ../../docs_src/frontend/tutorial002_py310.py hl[5] *} -**FastAPI** uses this fallback only for `GET` and `HEAD` requests that look like browser navigation. Missing files like JavaScript, CSS, and images still return `404`. +**FastAPI** uses this fallback only for `GET` and `HEAD` requests that explicitly accept HTML with `Accept: text/html` or `Accept: application/xhtml+xml`, as browser navigation requests normally do. Missing files like JavaScript, CSS, and images still return `404`. Requests with other methods, like `POST` or `PUT`, to paths that only match the frontend fallback also return `404`. Regular **FastAPI** *path operations* still have higher priority than frontend routes. diff --git a/fastapi/routing.py b/fastapi/routing.py index c442b122b..28694b4e5 100644 --- a/fastapi/routing.py +++ b/fastapi/routing.py @@ -1984,24 +1984,13 @@ def _iter_accept_media_types(accept: str) -> Iterator[tuple[str, float]]: def _is_frontend_navigation_request(scope: Scope) -> bool: - route_path = get_route_path(scope) - final_segment = route_path.rsplit("/", 1)[-1] - if os.path.splitext(final_segment)[1]: - return False request = Request(scope) - wildcard_accepted = False - html_rejected = False for media_type, quality in _iter_accept_media_types( request.headers.get("accept", "") ): - if media_type in {"text/html", "application/xhtml+xml"}: - if quality == 0: - html_rejected = True - else: - return True - elif media_type == "*/*" and quality != 0: - wildcard_accepted = True - return wildcard_accepted and not html_rejected + if media_type in {"text/html", "application/xhtml+xml"} and quality != 0: + return True + return False class _FrontendRoute(BaseRoute): diff --git a/tests/test_frontend.py b/tests/test_frontend.py index b8dd62fb8..d647037e7 100644 --- a/tests/test_frontend.py +++ b/tests/test_frontend.py @@ -32,7 +32,7 @@ def test_frontend_exact_prefix_path_serves_index(tmp_path: Path): app = FastAPI() app.frontend("/", directory=dist) - response = TestClient(app).get("/app") + response = TestClient(app).get("/app", headers={"accept": "text/html"}) assert response.status_code == 200 assert response.text == "app" @@ -617,15 +617,21 @@ def test_api_route_404_is_not_replaced_by_frontend_fallback(tmp_path: Path): assert response.json() == {"detail": "api missing"} -def test_index_fallback_for_navigation_request(tmp_path: Path): +@pytest.mark.parametrize( + ("path", "accept"), + [ + ("/dashboard/settings", "text/html"), + ("/users/jane.doe", "text/html"), + ("/v/1.2.3", "application/xhtml+xml"), + ], +) +def test_index_fallback_for_navigation_request(tmp_path: Path, path: str, accept: str): dist = tmp_path / "dist" write_file(dist / "index.html", "app shell") app = FastAPI() app.frontend("/", directory=dist, fallback="index.html") - response = TestClient(app).get( - "/dashboard/settings", headers={"accept": "text/html"} - ) + response = TestClient(app).get(path, headers={"accept": accept}) assert response.status_code == 200 assert response.text == "app shell" @@ -638,7 +644,8 @@ def test_index_fallback_parses_accept_parameters(tmp_path: Path): app.frontend("/", directory=dist, fallback="index.html") response = TestClient(app).get( - "/dashboard/settings", headers={"accept": "text/html; q=0.8"} + "/dashboard/settings", + headers={"accept": "text/html; charset=utf-8; q=0.8"}, ) assert response.status_code == 200 @@ -697,10 +704,10 @@ def test_index_fallback_respects_explicit_xhtml_rejection_with_wildcard( ("/assets/missing.css", "text/css"), ("/assets/missing.png", "image/png"), ("/api/missing", "application/json"), - ("/users/jane.doe", "text/html"), + ("/dashboard/settings", ""), ], ) -def test_index_fallback_does_not_handle_asset_like_or_non_html_requests( +def test_index_fallback_requires_explicit_html_acceptance( tmp_path: Path, path: str, accept: str ): dist = tmp_path / "dist" From 2acc4fbf155caf016e3bd2602c0d2ec52723e635 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Thu, 16 Jul 2026 09:00:03 +0000 Subject: [PATCH 454/462] =?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 35e8bcb7a..024f01d1a 100644 --- a/docs/en/docs/release-notes.md +++ b/docs/en/docs/release-notes.md @@ -7,6 +7,10 @@ hide: ## Latest Changes +### Fixes + +* 🐛 Fix frontend fallback support for doted paths like `/users/john.doe`. PR [#16011](https://github.com/fastapi/fastapi/pull/16011) by [@tiangolo](https://github.com/tiangolo). + ### Docs * 📝 Fix topic repository list not being displayed and `skip_users` not being applied. PR [#15995](https://github.com/fastapi/fastapi/pull/15995) by [@YuriiMotov](https://github.com/YuriiMotov). From c48e67b1ce9c03fc9bd4b1ac72350e51ad5a6e8a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebasti=C3=A1n=20Ram=C3=ADrez?= Date: Thu, 16 Jul 2026 11:09:10 +0200 Subject: [PATCH 455/462] =?UTF-8?q?=F0=9F=94=96=20Release=20version=200.13?= =?UTF-8?q?9.1=20(#16012)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: github-actions[bot] --- docs/en/docs/release-notes.md | 2 ++ fastapi/__init__.py | 2 +- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/docs/en/docs/release-notes.md b/docs/en/docs/release-notes.md index 024f01d1a..17ecbd136 100644 --- a/docs/en/docs/release-notes.md +++ b/docs/en/docs/release-notes.md @@ -7,6 +7,8 @@ hide: ## Latest Changes +## 0.139.1 (2026-07-16) + ### Fixes * 🐛 Fix frontend fallback support for doted paths like `/users/john.doe`. PR [#16011](https://github.com/fastapi/fastapi/pull/16011) by [@tiangolo](https://github.com/tiangolo). diff --git a/fastapi/__init__.py b/fastapi/__init__.py index df55e7a6c..ee04d9887 100644 --- a/fastapi/__init__.py +++ b/fastapi/__init__.py @@ -1,6 +1,6 @@ """FastAPI framework, high performance, easy to learn, fast to code, ready for production""" -__version__ = "0.139.0" +__version__ = "0.139.1" from starlette import status as status From 7fe315c21afb8a57a2b559772e0f7ced7e5d071a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebasti=C3=A1n=20Ram=C3=ADrez?= Date: Thu, 16 Jul 2026 16:57:38 +0200 Subject: [PATCH 456/462] =?UTF-8?q?=F0=9F=90=9B=20Refactor=20router=20rout?= =?UTF-8?q?e=20building=20to=20make=20it=20thread-safe,=20mainly=20relevan?= =?UTF-8?q?t=20for=20tests=20running=20in=20parallel=20threads=20(uncommon?= =?UTF-8?q?)=20(#16013)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- fastapi/routing.py | 79 ++++++++++++++++------------ tests/test_router_include_context.py | 62 ++++++++++++++++++++++ 2 files changed, 108 insertions(+), 33 deletions(-) diff --git a/fastapi/routing.py b/fastapi/routing.py index 28694b4e5..78207778a 100644 --- a/fastapi/routing.py +++ b/fastapi/routing.py @@ -7,6 +7,7 @@ import inspect import json import os import stat +import threading import types from collections.abc import ( AsyncIterator, @@ -1571,6 +1572,9 @@ class RouteContext: class _IncludedRouter(BaseRoute): original_router: "APIRouter" include_context: _RouterIncludeContext + _effective_routes_lock: Any = field( + default_factory=threading.Lock, repr=False, compare=False + ) _effective_candidates: list["_EffectiveRouteContext | _IncludedRouter"] = field( default_factory=list ) @@ -1584,44 +1588,53 @@ class _IncludedRouter(BaseRoute): routes_version = self.original_router._get_routes_version() if routes_version == self._effective_candidates_version: return self._effective_candidates - self._effective_candidates = [] - candidates = self.original_router.routes - for route in candidates: - if isinstance(route, _IncludedRouter): - child_context = self.include_context.combine(route.include_context) - child_branch = _IncludedRouter( - original_router=route.original_router, - include_context=child_context, - ) - self._effective_candidates.append(child_branch) - continue - route_context = self._build_effective_context(route) - if route_context is not None: - self._effective_candidates.append(route_context) - self._effective_candidates_version = routes_version - return self._effective_candidates + with self._effective_routes_lock: + routes_version = self.original_router._get_routes_version() + if routes_version == self._effective_candidates_version: + return self._effective_candidates + effective_candidates: list[_EffectiveRouteContext | _IncludedRouter] = [] + for route in self.original_router.routes: + if isinstance(route, _IncludedRouter): + child_context = self.include_context.combine(route.include_context) + child_branch = _IncludedRouter( + original_router=route.original_router, + include_context=child_context, + ) + effective_candidates.append(child_branch) + continue + route_context = self._build_effective_context(route) + if route_context is not None: + effective_candidates.append(route_context) + self._effective_candidates = effective_candidates + self._effective_candidates_version = routes_version + return effective_candidates def effective_low_priority_routes(self) -> list["_EffectiveRouteContext"]: routes_version = self.original_router._get_routes_version() if routes_version == self._effective_low_priority_routes_version: return self._effective_low_priority_routes - self._effective_low_priority_routes = [] - for route in self.original_router._low_priority_routes: - route_context = self._build_effective_context(route) - if route_context is not None: - self._effective_low_priority_routes.append(route_context) - for route in self.original_router.routes: - if isinstance(route, _IncludedRouter): - child_context = self.include_context.combine(route.include_context) - child_branch = _IncludedRouter( - original_router=route.original_router, - include_context=child_context, - ) - self._effective_low_priority_routes.extend( - child_branch.effective_low_priority_routes() - ) - self._effective_low_priority_routes_version = routes_version - return self._effective_low_priority_routes + with self._effective_routes_lock: + routes_version = self.original_router._get_routes_version() + if routes_version == self._effective_low_priority_routes_version: + return self._effective_low_priority_routes + effective_low_priority_routes: list[_EffectiveRouteContext] = [] + for route in self.original_router._low_priority_routes: + route_context = self._build_effective_context(route) + if route_context is not None: + effective_low_priority_routes.append(route_context) + for route in self.original_router.routes: + if isinstance(route, _IncludedRouter): + child_context = self.include_context.combine(route.include_context) + child_branch = _IncludedRouter( + original_router=route.original_router, + include_context=child_context, + ) + effective_low_priority_routes.extend( + child_branch.effective_low_priority_routes() + ) + self._effective_low_priority_routes = effective_low_priority_routes + self._effective_low_priority_routes_version = routes_version + return effective_low_priority_routes def _build_effective_context( self, route: BaseRoute diff --git a/tests/test_router_include_context.py b/tests/test_router_include_context.py index cb8dc81fa..e74d79e44 100644 --- a/tests/test_router_include_context.py +++ b/tests/test_router_include_context.py @@ -1,3 +1,5 @@ +import threading +from collections.abc import Sequence from typing import Annotated, cast import pytest @@ -898,6 +900,66 @@ async def test_included_unknown_route_is_ignored_and_can_return_default_404(): assert messages[0]["status"] == 404 +def test_included_router_candidate_cache_is_thread_safe(): + router = APIRouter() + route_count = 120 + thread_count = 6 + for index in range(route_count): + + @router.get(f"/items/{index}") + def read_item(index: int = index): + return {"index": index} + + app = FastAPI() + app.include_router(router) + included_router = cast(_IncludedRouter, app.router.routes[-1]) + barrier = threading.Barrier(thread_count) + results: list[Sequence[object]] = [] + + def build_candidates() -> None: + barrier.wait() + results.append(included_router.effective_candidates()) + + threads = [threading.Thread(target=build_candidates) for _ in range(thread_count)] + for thread in threads: + thread.start() + for thread in threads: + thread.join() + + assert len(results) == thread_count + assert all(result is results[0] for result in results) + assert len(results[0]) == route_count + assert TestClient(app).get("/items/0").json() == {"index": 0} + + +def test_included_router_low_priority_cache_rechecks_version_after_lock(monkeypatch): + router = APIRouter() + app = FastAPI() + app.include_router(router) + included_router = cast(_IncludedRouter, app.router.routes[-1]) + routes_version = router._get_routes_version() + version_checked = threading.Event() + + def get_routes_version() -> int: + version_checked.set() + return routes_version + + monkeypatch.setattr(router, "_get_routes_version", get_routes_version) + result: list[Sequence[object]] = [] + + def build_low_priority_routes() -> None: + result.append(included_router.effective_low_priority_routes()) + + with included_router._effective_routes_lock: + thread = threading.Thread(target=build_low_priority_routes) + thread.start() + assert version_checked.wait(timeout=1) + included_router._effective_low_priority_routes_version = routes_version + thread.join() + + assert result == [[]] + + def test_no_prefix_include_validation_sees_effective_starlette_route_candidates(): def endpoint(request): # pragma: no cover return PlainTextResponse("ok") From 7b3effea754619f0c305af576be23a51865292a3 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Thu, 16 Jul 2026 14:58:20 +0000 Subject: [PATCH 457/462] =?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 17ecbd136..1bea3f1f7 100644 --- a/docs/en/docs/release-notes.md +++ b/docs/en/docs/release-notes.md @@ -7,6 +7,10 @@ hide: ## Latest Changes +### Fixes + +* 🐛 Refactor router route building to make it thread-safe, mainly relevant for tests running in parallel threads (uncommon). PR [#16013](https://github.com/fastapi/fastapi/pull/16013) by [@tiangolo](https://github.com/tiangolo). + ## 0.139.1 (2026-07-16) ### Fixes From 866b7a3d0ce1025a3811f23aea4846d01a2b16a8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebasti=C3=A1n=20Ram=C3=ADrez?= Date: Thu, 16 Jul 2026 17:04:54 +0200 Subject: [PATCH 458/462] =?UTF-8?q?=F0=9F=94=96=20Release=20version=200.13?= =?UTF-8?q?9.2=20(#16014)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: github-actions[bot] --- docs/en/docs/release-notes.md | 2 ++ fastapi/__init__.py | 2 +- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/docs/en/docs/release-notes.md b/docs/en/docs/release-notes.md index 1bea3f1f7..57116f26d 100644 --- a/docs/en/docs/release-notes.md +++ b/docs/en/docs/release-notes.md @@ -7,6 +7,8 @@ hide: ## Latest Changes +## 0.139.2 (2026-07-16) + ### Fixes * 🐛 Refactor router route building to make it thread-safe, mainly relevant for tests running in parallel threads (uncommon). PR [#16013](https://github.com/fastapi/fastapi/pull/16013) by [@tiangolo](https://github.com/tiangolo). diff --git a/fastapi/__init__.py b/fastapi/__init__.py index ee04d9887..5177ea094 100644 --- a/fastapi/__init__.py +++ b/fastapi/__init__.py @@ -1,6 +1,6 @@ """FastAPI framework, high performance, easy to learn, fast to code, ready for production""" -__version__ = "0.139.1" +__version__ = "0.139.2" from starlette import status as status From e735449bae685102d448d2a443a88e1d3304abbd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebasti=C3=A1n=20Ram=C3=ADrez?= Date: Thu, 16 Jul 2026 20:25:14 +0200 Subject: [PATCH 459/462] =?UTF-8?q?=F0=9F=93=9D=20Restructure=20FastAPI=20?= =?UTF-8?q?People=20and=20related=20pages=20(#16015)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docs/en/data/members.yml | 18 ++-- docs/en/docs/fastapi-people.md | 163 +++++++-------------------------- docs/en/docs/help-fastapi.md | 20 ++-- docs/en/docs/management.md | 10 -- docs/en/mkdocs.yml | 2 +- 5 files changed, 47 insertions(+), 166 deletions(-) diff --git a/docs/en/data/members.yml b/docs/en/data/members.yml index 7ec16e917..caf5953ff 100644 --- a/docs/en/data/members.yml +++ b/docs/en/data/members.yml @@ -2,21 +2,21 @@ members: - login: tiangolo avatar_url: https://avatars.githubusercontent.com/u/1326112 url: https://github.com/tiangolo -- login: Kludex - avatar_url: https://avatars.githubusercontent.com/u/7353520 - url: https://github.com/Kludex -- login: alejsdev - avatar_url: https://avatars.githubusercontent.com/u/90076947 - url: https://github.com/alejsdev -- login: svlandeg - avatar_url: https://avatars.githubusercontent.com/u/8796347 - url: https://github.com/svlandeg - login: YuriiMotov avatar_url: https://avatars.githubusercontent.com/u/109919500 url: https://github.com/YuriiMotov +- login: svlandeg + avatar_url: https://avatars.githubusercontent.com/u/8796347 + url: https://github.com/svlandeg +- login: alejsdev + avatar_url: https://avatars.githubusercontent.com/u/90076947 + url: https://github.com/alejsdev - login: patrick91 avatar_url: https://avatars.githubusercontent.com/u/667029 url: https://github.com/patrick91 - login: luzzodev avatar_url: https://avatars.githubusercontent.com/u/27291415 url: https://github.com/luzzodev +- login: Kludex + avatar_url: https://avatars.githubusercontent.com/u/7353520 + url: https://github.com/Kludex diff --git a/docs/en/docs/fastapi-people.md b/docs/en/docs/fastapi-people.md index 73cd8c613..a914385d0 100644 --- a/docs/en/docs/fastapi-people.md +++ b/docs/en/docs/fastapi-people.md @@ -1,7 +1,4 @@ --- -hide: - - navigation - include_yaml: github_sponsors: data/github_sponsors.yml people: data/people.yml @@ -33,22 +30,6 @@ This is me: I'm the creator of **FastAPI**. You can read more about that in [Help FastAPI - Follow the author](help-fastapi.md#follow-the-author). -...But here I want to show you the community. - ---- - -**FastAPI** receives a lot of support from the community. And I want to highlight their contributions. - -These are the people that: - -* [Help others with questions in GitHub](help-fastapi.md#help-others-with-questions-in-github). -* Create or review Pull Requests. -* Help [manage the repository](https://tiangolo.com/open-source/management-tasks/) (team members). - -All these tasks help maintain the repository. - -A round of applause to them. 👏 🙇 - ## Team This is the current list of team members. 😎 @@ -65,111 +46,17 @@ They have different levels of involvement and permissions, they can perform [rep
-Although the team members have the permissions to perform privileged tasks, all the help from others maintaining FastAPI is very much appreciated! 🙇‍♂️ - ## FastAPI Experts -These are the users that have been [helping others the most with questions in GitHub](help-fastapi.md#help-others-with-questions-in-github). 🙇 - -They have proven to be **FastAPI Experts** by helping many others. ✨ - -/// tip - -You could become an official FastAPI Expert too! - -Just [help others with questions in GitHub](help-fastapi.md#help-others-with-questions-in-github). 🤓 - -/// - -You can see the **FastAPI Experts** for: - -* [Last Month](#fastapi-experts-last-month) 🤓 -* [3 Months](#fastapi-experts-3-months) 😎 -* [6 Months](#fastapi-experts-6-months) 🧐 -* [1 Year](#fastapi-experts-1-year) 🧑‍🔬 -* [**All Time**](#fastapi-experts-all-time) 🧙 - -### FastAPI Experts - Last Month - -These are the users that have been [helping others the most with questions in GitHub](help-fastapi.md#help-others-with-questions-in-github) during the last month. 🤓 - -
- -{% for user in people.last_month_experts[:10] %} - -{% if user.login not in skip_users.users %} - -
@{{ user.login }}
Questions replied: {{ user.count }}
- -{% endif %} - -{% endfor %} - -
- -### FastAPI Experts - 3 Months - -These are the users that have been [helping others the most with questions in GitHub](help-fastapi.md#help-others-with-questions-in-github) during the last 3 months. 😎 - -
- -{% for user in people.three_months_experts[:10] %} - -{% if user.login not in skip_users.users %} - -
@{{ user.login }}
Questions replied: {{ user.count }}
- -{% endif %} - -{% endfor %} - -
- -### FastAPI Experts - 6 Months - -These are the users that have been [helping others the most with questions in GitHub](help-fastapi.md#help-others-with-questions-in-github) during the last 6 months. 🧐 - -
- -{% for user in people.six_months_experts[:10] %} - -{% if user.login not in skip_users.users %} - -
@{{ user.login }}
Questions replied: {{ user.count }}
- -{% endif %} +For a long time, answering questions from the community in GitHub Discussions was done by other community volunteers. -{% endfor %} +They proved they are **FastAPI Experts** by helping many others. ✨ -
- -### FastAPI Experts - 1 Year - -These are the users that have been [helping others the most with questions in GitHub](help-fastapi.md#help-others-with-questions-in-github) during the last year. 🧑‍🔬 +Here's the hall of fame of the first FastAPI Experts:
-{% for user in people.one_year_experts[:20] %} - -{% if user.login not in skip_users.users %} - -
@{{ user.login }}
Questions replied: {{ user.count }}
- -{% endif %} - -{% endfor %} - -
- -### FastAPI Experts - All Time - -Here are the all time **FastAPI Experts**. 🤓🤯 - -These are the users that have [helped others the most with questions in GitHub](help-fastapi.md#help-others-with-questions-in-github) through *all time*. 🧙 - -
- -{% for user in people.experts[:50] %} +{% for user in people.experts[:30] %} {% if user.login not in skip_users.users %} @@ -183,15 +70,17 @@ These are the users that have [helped others the most with questions in GitHub]( ## Top Contributors -Here are the **Top Contributors**. 👷 +Currently, most of the code changes in FastAPI are done by the team. + +But over the years, there have also been many contributions made by others. -These users have created the most Pull Requests that have been *merged*. +They contributed source code, documentation, etc. 📦 -They have contributed source code, documentation, etc. 📦 +Here's the hall of fame of the first **Top Contributors**. 👷
-{% for user in (contributors.values() | list)[:50] %} +{% for user in (contributors.values() | list)[:30] %} {% if user.login not in skip_users.users %} @@ -207,12 +96,14 @@ There are hundreds of other contributors, you can see them all in the [FastAPI G ## Top Translation Reviewers -These users are the **Top Translation Reviewers**. 🕵️ +Currently, translations are done using AI tools, steered by the FastAPI team and native speakers. -Translation reviewers have the **power to approve translations** of the documentation. Without them, there wouldn't be documentation in several other languages. +At some point, FastAPI had some documentation pages that community members translated into other languages by hand. + +Here's the hall of fame of the first **Top Translation Reviewers**. 🕵️
-{% for user in (translation_reviewers.values() | list)[:50] %} +{% for user in (translation_reviewers.values() | list)[:30] %} {% if user.login not in skip_users.users %} @@ -226,9 +117,7 @@ Translation reviewers have the **power to approve translations** of the document ## Sponsors -These are the **Sponsors**. 😎 - -They are supporting my work with **FastAPI** (and others), mainly through [GitHub Sponsors](https://github.com/sponsors/tiangolo). +**Sponsors** support **FastAPI** and friends, mainly through [GitHub Sponsors](https://github.com/sponsors/tiangolo). ✨ {% if sponsors %} @@ -283,12 +172,22 @@ They are supporting my work with **FastAPI** (and others), mainly through [GitHu ## About the data - technical details -The main intention of this page is to highlight the effort of the community to help others. +The main intention of this page has been to highlight the effort of the community to help others, especially efforts that were normally less visible and, in many cases, more arduous, like helping others with questions and reviewing Pull Requests with translations. + +It also highlights contributions from sponsors. + +The data used to be calculated continuously, each month. + +As of July 2026, most of the work has been done by (paid) team members for quite some time. + +GitHub Discussions are answered mostly by team members. + +Most of the code changes are done by team members. -Especially including efforts that are normally less visible, and in many cases more arduous, like helping others with questions and reviewing Pull Requests with translations. +And translations are continuously done for the entire documentation in multiple languages, using AI tools, managed by team members. -The data is calculated each month, you can read the [source code here](https://github.com/fastapi/fastapi/blob/master/scripts/). +Additionally, in recent months, there's been an overwhelming amount of AI spam, mainly to cheat the FastAPI Experts system or to get a PR merged by any means and thereby be considered a contributor. You can read more about the point of view in [Automated Code and AI](https://tiangolo.com/open-source/contributing/#automated-code-and-ai). -Here I'm also highlighting contributions from sponsors. +Because of this, the data for the FastAPI Experts, Top Contributors, and Top Translation Reviewers is no longer continuously updated. -I also reserve the right to update the algorithm, sections, thresholds, etc (just in case 🤷). +This section is currently kept as a tribute to the humans that helped shape what FastAPI is today. 🙌 diff --git a/docs/en/docs/help-fastapi.md b/docs/en/docs/help-fastapi.md index 14bd05646..f995d899f 100644 --- a/docs/en/docs/help-fastapi.md +++ b/docs/en/docs/help-fastapi.md @@ -45,20 +45,6 @@ You can follow [me (Sebastián Ramírez / `tiangolo`)](https://tiangolo.com), th * [@tiangolo.com on **Bluesky**](https://bsky.app/profile/tiangolo.com) * [@tiangolo on **LinkedIn**](https://www.linkedin.com/in/tiangolo/). -## Help others with questions in GitHub { #help-others-with-questions-in-github } - -You can try and help others with their questions in [GitHub Discussions](https://github.com/fastapi/fastapi/discussions/categories/questions?discussions_q=category%3AQuestions+is%3Aunanswered). - -In many cases you might already know the answer for those questions. 🤓 - -If you are helping a lot of people with their questions, you will become an official [FastAPI Expert](fastapi-people.md#fastapi-experts). 🎉 - -Just remember, the most important point is: try to be kind. 🤗 - -### How to Help { #how-to-help } - -Follow the [guide on how to help](https://tiangolo.com/open-source/help/#help-others-with-questions-in-github) here. - ## Ask Questions { #ask-questions } You can [create a new question](https://github.com/fastapi/fastapi/discussions/new?category=questions) in the GitHub repository, for example to: @@ -85,3 +71,9 @@ Keep in mind that as chats allow more "free conversation", it's easy to ask ques In GitHub, the template will guide you to write the right question so that you can more easily get a good answer, or even solve the problem yourself even before asking. Conversations in the chat systems are also not as easily searchable as in GitHub, they get lost. + +## Try FastAPI Cloud { #try-fastapi-cloud } + +The main funding for FastAPI and friends comes from [**FastAPI Cloud**](https://fastapicloud.com), a platform to deploy FastAPI applications in a simple and fast way, with a single command, `fastapi deploy`. + +FastAPI Cloud is built by the same team behind FastAPI. You can try it and consider it for your projects. diff --git a/docs/en/docs/management.md b/docs/en/docs/management.md index 740494768..a1a9bff1f 100644 --- a/docs/en/docs/management.md +++ b/docs/en/docs/management.md @@ -13,13 +13,3 @@ I normally give the final review to each PR before merging them. I make the fina There's a team of people that help manage and maintain the project. 😎 Learn more about it in [tiangolo.com - GitHub FastAPI](https://tiangolo.com/github-fastapi/). - -## FastAPI Experts - -The people that help others the most in GitHub Discussions can become [**FastAPI Experts**](./fastapi-people.md#fastapi-experts). - -This is normally the best way to contribute to the project. - -## External Help - -External help is very much appreciated. There are many ways to [help](./help-fastapi.md). ☕️ diff --git a/docs/en/mkdocs.yml b/docs/en/mkdocs.yml index 884307dcf..9a2321e04 100644 --- a/docs/en/mkdocs.yml +++ b/docs/en/mkdocs.yml @@ -223,9 +223,9 @@ nav: - reference/staticfiles.md - reference/templating.md - reference/testclient.md -- fastapi-people.md - "": - resources/index.md + - fastapi-people.md - help-fastapi.md - contributing.md - translations.md From efcf8a183026edb97e342ee3fb38a0a3416798ac Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Thu, 16 Jul 2026 18:25:46 +0000 Subject: [PATCH 460/462] =?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 57116f26d..61313d3f1 100644 --- a/docs/en/docs/release-notes.md +++ b/docs/en/docs/release-notes.md @@ -7,6 +7,10 @@ hide: ## Latest Changes +### Docs + +* 📝 Restructure FastAPI People and related pages. PR [#16015](https://github.com/fastapi/fastapi/pull/16015) by [@tiangolo](https://github.com/tiangolo). + ## 0.139.2 (2026-07-16) ### Fixes From 7f05e26d0898e8e1491df331c2dd4368f5e35054 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebasti=C3=A1n=20Ram=C3=ADrez?= Date: Thu, 16 Jul 2026 20:38:36 +0200 Subject: [PATCH 461/462] =?UTF-8?q?=F0=9F=94=A5=20Remove=20now-obsolete=20?= =?UTF-8?q?scripts=20to=20generate=20data=20for=20FastAPI=20People=20(#160?= =?UTF-8?q?16)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .github/workflows/contributors.yml | 56 ---- .github/workflows/people.yml | 57 ---- scripts/contributors.py | 316 ------------------- scripts/people.py | 483 ----------------------------- 4 files changed, 912 deletions(-) delete mode 100644 .github/workflows/contributors.yml delete mode 100644 .github/workflows/people.yml delete mode 100644 scripts/contributors.py delete mode 100644 scripts/people.py diff --git a/.github/workflows/contributors.yml b/.github/workflows/contributors.yml deleted file mode 100644 index 04d82c34a..000000000 --- a/.github/workflows/contributors.yml +++ /dev/null @@ -1,56 +0,0 @@ -name: FastAPI People Contributors - -on: - schedule: - - cron: "0 3 1 * *" - workflow_dispatch: - inputs: - debug_enabled: - description: "Run the build with tmate debugging enabled (https://github.com/marketplace/actions/debugging-with-tmate)" - required: false - default: "false" - -permissions: {} - -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@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0 - with: - persist-credentials: true # Required for `git push` in `contributors.py` - - name: Set up Python - uses: actions/setup-python@ece7cb06caefa5fff74198d8649806c4678c61a1 # v6.3.0 - with: - python-version-file: ".python-version" - - name: Setup uv - uses: astral-sh/setup-uv@d31148d669074a8d0a63714ba94f3201e7020bc3 # v8.3.0 - with: - # Before upgrading uv version, make sure astral-sh/setup-uv knows its checksum. - # See: https://github.com/astral-sh/setup-uv/issues/851#issuecomment-4282017837 - version: "0.11.18" - enable-cache: true - cache-dependency-glob: | - pyproject.toml - uv.lock - - name: Install Dependencies - run: uv sync --locked --no-dev --group github-actions - # Allow debugging with tmate - - name: Setup tmate session - uses: mxschmitt/action-tmate@35b54afac29c97fb54faba5b513f8fbd1882f113 # v3.24 - if: ${{ github.event_name == 'workflow_dispatch' && github.event.inputs.debug_enabled == 'true' }} - with: - limit-access-to-actor: true - env: - GITHUB_TOKEN: ${{ secrets.FASTAPI_PR_TOKEN }} # zizmor: ignore[secrets-outside-env] - - name: FastAPI People Contributors - run: uv run ./scripts/contributors.py - env: - GITHUB_TOKEN: ${{ secrets.FASTAPI_PR_TOKEN }} # zizmor: ignore[secrets-outside-env] diff --git a/.github/workflows/people.yml b/.github/workflows/people.yml deleted file mode 100644 index a7dd8a4fb..000000000 --- a/.github/workflows/people.yml +++ /dev/null @@ -1,57 +0,0 @@ -name: FastAPI People - -on: - schedule: - - cron: "0 14 1 * *" - workflow_dispatch: - inputs: - debug_enabled: - description: Run the build with tmate debugging enabled (https://github.com/marketplace/actions/debugging-with-tmate) - required: false - default: "false" - -permissions: {} - -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@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0 - with: - persist-credentials: true # Required for `git push` in `people.py` - - name: Set up Python - uses: actions/setup-python@ece7cb06caefa5fff74198d8649806c4678c61a1 # v6.3.0 - with: - python-version-file: ".python-version" - - name: Setup uv - uses: astral-sh/setup-uv@d31148d669074a8d0a63714ba94f3201e7020bc3 # v8.3.0 - with: - # Before upgrading uv version, make sure astral-sh/setup-uv knows its checksum. - # See: https://github.com/astral-sh/setup-uv/issues/851#issuecomment-4282017837 - version: "0.11.18" - enable-cache: true - cache-dependency-glob: | - pyproject.toml - uv.lock - - name: Install Dependencies - run: uv sync --locked --no-dev --group github-actions - # Allow debugging with tmate - - name: Setup tmate session - uses: mxschmitt/action-tmate@35b54afac29c97fb54faba5b513f8fbd1882f113 # v3.24 - if: ${{ github.event_name == 'workflow_dispatch' && github.event.inputs.debug_enabled == 'true' }} - with: - limit-access-to-actor: true - env: - GITHUB_TOKEN: ${{ secrets.FASTAPI_PEOPLE }} # zizmor: ignore[secrets-outside-env] - - name: FastAPI People Experts - run: uv run ./scripts/people.py - env: - GITHUB_TOKEN: ${{ secrets.FASTAPI_PEOPLE }} # zizmor: ignore[secrets-outside-env] - SLEEP_INTERVAL: ${{ vars.PEOPLE_SLEEP_INTERVAL }} diff --git a/scripts/contributors.py b/scripts/contributors.py deleted file mode 100644 index 5e9d72d64..000000000 --- a/scripts/contributors.py +++ /dev/null @@ -1,316 +0,0 @@ -import logging -import secrets -import subprocess -from collections import Counter -from datetime import datetime -from pathlib import Path -from typing import Any - -import httpx -import yaml -from github import Github -from pydantic import BaseModel, SecretStr -from pydantic_settings import BaseSettings - -github_graphql_url = "https://api.github.com/graphql" - - -prs_query = """ -query Q($after: String) { - repository(name: "fastapi", owner: "fastapi") { - pullRequests(first: 100, after: $after) { - edges { - cursor - node { - number - labels(first: 100) { - nodes { - name - } - } - author { - login - avatarUrl - url - } - title - createdAt - lastEditedAt - updatedAt - state - reviews(first:100) { - nodes { - author { - login - avatarUrl - url - } - state - } - } - } - } - } - } -} -""" - - -class Author(BaseModel): - login: str - avatarUrl: str - url: str - - -class LabelNode(BaseModel): - name: str - - -class Labels(BaseModel): - nodes: list[LabelNode] - - -class ReviewNode(BaseModel): - author: Author | None = None - state: str - - -class Reviews(BaseModel): - nodes: list[ReviewNode] - - -class PullRequestNode(BaseModel): - number: int - labels: Labels - author: Author | None = None - title: str - createdAt: datetime - lastEditedAt: datetime | None = None - updatedAt: datetime | None = None - state: str - reviews: Reviews - - -class PullRequestEdge(BaseModel): - cursor: str - node: PullRequestNode - - -class PullRequests(BaseModel): - edges: list[PullRequestEdge] - - -class PRsRepository(BaseModel): - pullRequests: PullRequests - - -class PRsResponseData(BaseModel): - repository: PRsRepository - - -class PRsResponse(BaseModel): - data: PRsResponseData - - -class Settings(BaseSettings): - github_token: SecretStr - github_repository: str - httpx_timeout: int = 30 - - -def get_graphql_response( - *, - settings: Settings, - query: str, - after: str | None = None, -) -> dict[str, Any]: - headers = {"Authorization": f"token {settings.github_token.get_secret_value()}"} - variables = {"after": after} - response = httpx.post( - github_graphql_url, - headers=headers, - timeout=settings.httpx_timeout, - json={"query": query, "variables": variables, "operationName": "Q"}, - ) - if response.status_code != 200: - logging.error(f"Response was not 200, after: {after}") - logging.error(response.text) - raise RuntimeError(response.text) - data = response.json() - if "errors" in data: - logging.error(f"Errors in response, after: {after}") - logging.error(data["errors"]) - logging.error(response.text) - raise RuntimeError(response.text) - return data - - -def get_graphql_pr_edges( - *, settings: Settings, after: str | None = None -) -> list[PullRequestEdge]: - data = get_graphql_response(settings=settings, query=prs_query, after=after) - graphql_response = PRsResponse.model_validate(data) - return graphql_response.data.repository.pullRequests.edges - - -def get_pr_nodes(settings: Settings) -> list[PullRequestNode]: - pr_nodes: list[PullRequestNode] = [] - pr_edges = get_graphql_pr_edges(settings=settings) - - while pr_edges: - for edge in pr_edges: - pr_nodes.append(edge.node) - last_edge = pr_edges[-1] - pr_edges = get_graphql_pr_edges(settings=settings, after=last_edge.cursor) - return pr_nodes - - -class ContributorsResults(BaseModel): - contributors: Counter[str] - translation_reviewers: Counter[str] - translators: Counter[str] - authors: dict[str, Author] - - -def get_contributors(pr_nodes: list[PullRequestNode]) -> ContributorsResults: - contributors = Counter[str]() - translation_reviewers = Counter[str]() - translators = Counter[str]() - authors: dict[str, Author] = {} - - for pr in pr_nodes: - if pr.author: - authors[pr.author.login] = pr.author - is_lang = False - for label in pr.labels.nodes: - if label.name == "lang-all": - is_lang = True - break - for review in pr.reviews.nodes: - if review.author: - authors[review.author.login] = review.author - if is_lang: - translation_reviewers[review.author.login] += 1 - if pr.state == "MERGED" and pr.author: - if is_lang: - translators[pr.author.login] += 1 - else: - contributors[pr.author.login] += 1 - return ContributorsResults( - contributors=contributors, - translation_reviewers=translation_reviewers, - translators=translators, - authors=authors, - ) - - -def get_users_to_write( - *, - counter: Counter[str], - authors: dict[str, Author], - min_count: int = 2, -) -> dict[str, Any]: - users: dict[str, Any] = {} - for user, count in counter.most_common(): - if count >= min_count: - author = authors[user] - users[user] = { - "login": user, - "count": count, - "avatarUrl": author.avatarUrl, - "url": author.url, - } - return users - - -def update_content(*, content_path: Path, new_content: Any) -> bool: - old_content = content_path.read_text(encoding="utf-8") - - new_content = yaml.dump(new_content, sort_keys=False, width=200, allow_unicode=True) - if old_content == new_content: - logging.info(f"The content hasn't changed for {content_path}") - return False - content_path.write_text(new_content, encoding="utf-8") - logging.info(f"Updated {content_path}") - return True - - -def main() -> None: - logging.basicConfig(level=logging.INFO) - settings = Settings() # ty: ignore[missing-argument] - logging.info(f"Using config: {settings.model_dump_json()}") - g = Github(settings.github_token.get_secret_value()) - repo = g.get_repo(settings.github_repository) - - pr_nodes = get_pr_nodes(settings=settings) - contributors_results = get_contributors(pr_nodes=pr_nodes) - authors = contributors_results.authors - - top_contributors = get_users_to_write( - counter=contributors_results.contributors, - authors=authors, - ) - - top_translators = get_users_to_write( - counter=contributors_results.translators, - authors=authors, - ) - top_translations_reviewers = get_users_to_write( - counter=contributors_results.translation_reviewers, - authors=authors, - ) - - # For local development - # contributors_path = Path("../docs/en/data/contributors.yml") - contributors_path = Path("./docs/en/data/contributors.yml") - # translators_path = Path("../docs/en/data/translators.yml") - translators_path = Path("./docs/en/data/translators.yml") - # translation_reviewers_path = Path("../docs/en/data/translation_reviewers.yml") - translation_reviewers_path = Path("./docs/en/data/translation_reviewers.yml") - - updated = [ - update_content(content_path=contributors_path, new_content=top_contributors), - update_content(content_path=translators_path, new_content=top_translators), - update_content( - content_path=translation_reviewers_path, - new_content=top_translations_reviewers, - ), - ] - - if not any(updated): - logging.info("The data hasn't changed, finishing.") - return - - logging.info("Setting up GitHub Actions git user") - subprocess.run(["git", "config", "user.name", "github-actions[bot]"], check=True) - subprocess.run( - ["git", "config", "user.email", "github-actions[bot]@users.noreply.github.com"], - check=True, - ) - branch_name = f"fastapi-people-contributors-{secrets.token_hex(4)}" - logging.info(f"Creating a new branch {branch_name}") - subprocess.run(["git", "checkout", "-b", branch_name], check=True) - logging.info("Adding updated file") - subprocess.run( - [ - "git", - "add", - str(contributors_path), - str(translators_path), - str(translation_reviewers_path), - ], - check=True, - ) - logging.info("Committing updated file") - message = "👥 Update FastAPI People - Contributors and Translators" - subprocess.run(["git", "commit", "-m", message], check=True) - logging.info("Pushing branch") - subprocess.run(["git", "push", "origin", branch_name], check=True) - logging.info("Creating PR") - pr = repo.create_pull(title=message, body=message, base="master", head=branch_name) - logging.info(f"Created PR: {pr.number}") - logging.info("Finished") - - -if __name__ == "__main__": - main() diff --git a/scripts/people.py b/scripts/people.py deleted file mode 100644 index 72b591367..000000000 --- a/scripts/people.py +++ /dev/null @@ -1,483 +0,0 @@ -import logging -import secrets -import subprocess -import time -from collections import Counter -from collections.abc import Container -from datetime import datetime, timedelta, timezone -from math import ceil -from pathlib import Path -from typing import Annotated, Any - -import httpx -import yaml -from github import Github -from pydantic import BaseModel, BeforeValidator, SecretStr -from pydantic_settings import BaseSettings - -github_graphql_url = "https://api.github.com/graphql" -questions_category_id = "DIC_kwDOCZduT84B6E2a" - - -POINTS_PER_MINUTE_LIMIT = 84 # 5000 points per hour - -MINIMIZED_COMMENTS_REASONS_TO_EXCLUDE = {"abuse", "off-topic", "duplicate", "spam"} - - -class RateLimiter: - def __init__(self) -> None: - self.last_query_cost: int = 1 - self.remaining_points: int = 5000 - self.reset_at: datetime = datetime.fromtimestamp(0, timezone.utc) - self.last_request_start_time: datetime = datetime.fromtimestamp(0, timezone.utc) - self.speed_multiplier: float = 1.0 - - def __enter__(self) -> "RateLimiter": - now = datetime.now(tz=timezone.utc) - - # Handle primary rate limits - primary_limit_wait_time = 0.0 - if self.remaining_points <= self.last_query_cost: - primary_limit_wait_time = (self.reset_at - now).total_seconds() + 2 - logging.warning( - f"Approaching GitHub API rate limit, remaining points: {self.remaining_points}, " - f"reset time in {primary_limit_wait_time} seconds" - ) - - # Handle secondary rate limits - secondary_limit_wait_time = 0.0 - points_per_minute = POINTS_PER_MINUTE_LIMIT * self.speed_multiplier - interval = 60 / (points_per_minute / self.last_query_cost) - time_since_last_request = (now - self.last_request_start_time).total_seconds() - if time_since_last_request < interval: - secondary_limit_wait_time = interval - time_since_last_request - - final_wait_time = ceil(max(primary_limit_wait_time, secondary_limit_wait_time)) - logging.info(f"Sleeping for {final_wait_time} seconds to respect rate limit") - time.sleep(max(final_wait_time, 1)) - - self.last_request_start_time = datetime.now(tz=timezone.utc) - return self - - def __exit__(self, exc_type, exc_val, exc_tb) -> None: - pass - - def update_request_info(self, cost: int, remaining: int, reset_at: str) -> None: - self.last_query_cost = cost - self.remaining_points = remaining - self.reset_at = datetime.fromisoformat(reset_at.replace("Z", "+00:00")) - - -rate_limiter = RateLimiter() - - -discussions_query = """ -query Q($after: String, $category_id: ID) { - repository(name: "fastapi", owner: "fastapi") { - discussions(first: 30, after: $after, categoryId: $category_id) { - edges { - cursor - node { - number - author { - login - avatarUrl - url - } - createdAt - comments(first: 50) { - totalCount - nodes { - createdAt - author { - login - avatarUrl - url - } - isAnswer - replies(first: 10) { - totalCount - nodes { - createdAt - author { - login - avatarUrl - url - } - minimizedReason - } - } - minimizedReason - } - } - } - } - } - } - rateLimit { - cost - remaining - resetAt - } -} -""" - -LowerStr = Annotated[ - str, BeforeValidator(lambda v: v.lower() if isinstance(v, str) else v) -] - - -class Author(BaseModel): - login: str - avatarUrl: str | None = None - url: str | None = None - - -class CommentsNode(BaseModel): - createdAt: datetime - author: Author | None = None - minimizedReason: LowerStr | None = None - - -class Replies(BaseModel): - totalCount: int - nodes: list[CommentsNode] - - -class DiscussionsCommentsNode(CommentsNode): - minimizedReason: LowerStr | None = None - replies: Replies - - -class DiscussionsComments(BaseModel): - totalCount: int - nodes: list[DiscussionsCommentsNode] - - -class DiscussionsNode(BaseModel): - number: int - author: Author | None = None - title: str | None = None - createdAt: datetime - comments: DiscussionsComments - - -class DiscussionsEdge(BaseModel): - cursor: str - node: DiscussionsNode - - -class Discussions(BaseModel): - edges: list[DiscussionsEdge] - - -class DiscussionsRepository(BaseModel): - discussions: Discussions - - -class DiscussionsResponseData(BaseModel): - repository: DiscussionsRepository - - -class DiscussionsResponse(BaseModel): - data: DiscussionsResponseData - - -class Settings(BaseSettings): - github_token: SecretStr - github_repository: str - httpx_timeout: int = 30 - speed_multiplier: float = 1.0 - - -def get_graphql_response( - *, - settings: Settings, - query: str, - after: str | None = None, - category_id: str | None = None, -) -> dict[str, Any]: - headers = {"Authorization": f"token {settings.github_token.get_secret_value()}"} - variables = {"after": after, "category_id": category_id} - response = httpx.post( - github_graphql_url, - headers=headers, - timeout=settings.httpx_timeout, - json={"query": query, "variables": variables, "operationName": "Q"}, - ) - if response.status_code != 200: - logging.error( - f"Response was not 200, after: {after}, category_id: {category_id}" - ) - logging.error(response.text) - raise RuntimeError(response.text) - data = response.json() - if "errors" in data: - logging.error(f"Errors in response, after: {after}, category_id: {category_id}") - logging.error(data["errors"]) - logging.error(response.text) - raise RuntimeError(response.text) - return data - - -def get_graphql_question_discussion_edges( - *, - settings: Settings, - after: str | None = None, -) -> list[DiscussionsEdge]: - with rate_limiter: - data = get_graphql_response( - settings=settings, - query=discussions_query, - after=after, - category_id=questions_category_id, - ) - - rate_limiter.update_request_info( - cost=data["data"]["rateLimit"]["cost"], - remaining=data["data"]["rateLimit"]["remaining"], - reset_at=data["data"]["rateLimit"]["resetAt"], - ) - graphql_response = DiscussionsResponse.model_validate(data) - return graphql_response.data.repository.discussions.edges - - -class DiscussionExpertsResults(BaseModel): - commenters: Counter[str] - last_month_commenters: Counter[str] - three_months_commenters: Counter[str] - six_months_commenters: Counter[str] - one_year_commenters: Counter[str] - authors: dict[str, Author] - - -def get_discussion_nodes(settings: Settings) -> list[DiscussionsNode]: - discussion_nodes: list[DiscussionsNode] = [] - discussion_edges = get_graphql_question_discussion_edges(settings=settings) - - while discussion_edges: - for discussion_edge in discussion_edges: - discussion_nodes.append(discussion_edge.node) - last_edge = discussion_edges[-1] - discussion_edges = get_graphql_question_discussion_edges( - settings=settings, after=last_edge.cursor - ) - return discussion_nodes - - -def get_discussions_experts( - discussion_nodes: list[DiscussionsNode], -) -> DiscussionExpertsResults: - commenters = Counter[str]() - last_month_commenters = Counter[str]() - three_months_commenters = Counter[str]() - six_months_commenters = Counter[str]() - one_year_commenters = Counter[str]() - authors: dict[str, Author] = {} - - now = datetime.now(tz=timezone.utc) - one_month_ago = now - timedelta(days=30) - three_months_ago = now - timedelta(days=90) - six_months_ago = now - timedelta(days=180) - one_year_ago = now - timedelta(days=365) - - for discussion in discussion_nodes: - discussion_author_name = None - if discussion.author: - authors[discussion.author.login] = discussion.author - discussion_author_name = discussion.author.login - discussion_commentors: dict[str, datetime] = {} - for comment in discussion.comments.nodes: - if ( - comment.minimizedReason not in MINIMIZED_COMMENTS_REASONS_TO_EXCLUDE - and comment.author - ): - authors[comment.author.login] = comment.author - if comment.author.login != discussion_author_name: - author_time = discussion_commentors.get( - comment.author.login, comment.createdAt - ) - discussion_commentors[comment.author.login] = max( - author_time, comment.createdAt - ) - for reply in comment.replies.nodes: - if ( - reply.minimizedReason not in MINIMIZED_COMMENTS_REASONS_TO_EXCLUDE - and reply.author - ): - authors[reply.author.login] = reply.author - if reply.author.login != discussion_author_name: - author_time = discussion_commentors.get( - reply.author.login, reply.createdAt - ) - discussion_commentors[reply.author.login] = max( - author_time, reply.createdAt - ) - for author_name, author_time in discussion_commentors.items(): - commenters[author_name] += 1 - if author_time > one_month_ago: - last_month_commenters[author_name] += 1 - if author_time > three_months_ago: - three_months_commenters[author_name] += 1 - if author_time > six_months_ago: - six_months_commenters[author_name] += 1 - if author_time > one_year_ago: - one_year_commenters[author_name] += 1 - discussion_experts_results = DiscussionExpertsResults( - authors=authors, - commenters=commenters, - last_month_commenters=last_month_commenters, - three_months_commenters=three_months_commenters, - six_months_commenters=six_months_commenters, - one_year_commenters=one_year_commenters, - ) - return discussion_experts_results - - -def get_top_users( - *, - counter: Counter[str], - authors: dict[str, Author], - skip_users: Container[str], - min_count: int = 2, -) -> list[dict[str, Any]]: - users: list[dict[str, Any]] = [] - for commenter, count in counter.most_common(50): - if commenter in skip_users: - continue - if count >= min_count: - author = authors[commenter] - users.append( - { - "login": commenter, - "count": count, - "avatarUrl": author.avatarUrl, - "url": author.url, - } - ) - return users - - -def get_users_to_write( - *, - counter: Counter[str], - authors: dict[str, Author], - min_count: int = 2, -) -> list[dict[str, Any]]: - users: dict[str, Any] = {} - users_list: list[dict[str, Any]] = [] - for user, count in counter.most_common(60): - if count >= min_count: - author = authors[user] - user_data = { - "login": user, - "count": count, - "avatarUrl": author.avatarUrl, - "url": author.url, - } - users[user] = user_data - users_list.append(user_data) - return users_list - - -def update_content(*, content_path: Path, new_content: Any) -> bool: - old_content = content_path.read_text(encoding="utf-8") - - new_content = yaml.dump(new_content, sort_keys=False, width=200, allow_unicode=True) - if old_content == new_content: - logging.info(f"The content hasn't changed for {content_path}") - return False - content_path.write_text(new_content, encoding="utf-8") - logging.info(f"Updated {content_path}") - return True - - -def main() -> None: - logging.basicConfig(level=logging.INFO) - settings = Settings() # ty: ignore[missing-argument] - logging.info(f"Using config: {settings.model_dump_json()}") - rate_limiter.speed_multiplier = settings.speed_multiplier - g = Github(settings.github_token.get_secret_value()) - repo = g.get_repo(settings.github_repository) - - discussion_nodes = get_discussion_nodes(settings=settings) - experts_results = get_discussions_experts(discussion_nodes=discussion_nodes) - - authors = experts_results.authors - maintainers_logins = {"tiangolo"} - maintainers = [] - for login in maintainers_logins: - user = authors[login] - maintainers.append( - { - "login": login, - "answers": experts_results.commenters[login], - "avatarUrl": user.avatarUrl, - "url": user.url, - } - ) - - experts = get_users_to_write( - counter=experts_results.commenters, - authors=authors, - ) - last_month_experts = get_users_to_write( - counter=experts_results.last_month_commenters, - authors=authors, - ) - three_months_experts = get_users_to_write( - counter=experts_results.three_months_commenters, - authors=authors, - ) - six_months_experts = get_users_to_write( - counter=experts_results.six_months_commenters, - authors=authors, - ) - one_year_experts = get_users_to_write( - counter=experts_results.one_year_commenters, - authors=authors, - ) - - people = { - "maintainers": maintainers, - "experts": experts, - "last_month_experts": last_month_experts, - "three_months_experts": three_months_experts, - "six_months_experts": six_months_experts, - "one_year_experts": one_year_experts, - } - - # For local development - # people_path = Path("../docs/en/data/people.yml") - people_path = Path("./docs/en/data/people.yml") - - updated = update_content(content_path=people_path, new_content=people) - - if not updated: - logging.info("The data hasn't changed, finishing.") - return - - logging.info("Setting up GitHub Actions git user") - subprocess.run(["git", "config", "user.name", "github-actions[bot]"], check=True) - subprocess.run( - ["git", "config", "user.email", "github-actions[bot]@users.noreply.github.com"], - check=True, - ) - branch_name = f"fastapi-people-experts-{secrets.token_hex(4)}" - logging.info(f"Creating a new branch {branch_name}") - subprocess.run(["git", "checkout", "-b", branch_name], check=True) - logging.info("Adding updated file") - subprocess.run(["git", "add", str(people_path)], check=True) - logging.info("Committing updated file") - message = "👥 Update FastAPI People - Experts" - subprocess.run(["git", "commit", "-m", message], check=True) - logging.info("Pushing branch") - subprocess.run(["git", "push", "origin", branch_name], check=True) - logging.info("Creating PR") - pr = repo.create_pull(title=message, body=message, base="master", head=branch_name) - logging.info(f"Created PR: {pr.number}") - logging.info("Finished") - - -if __name__ == "__main__": - main() From afe41126f624af30038cc8e17b2aaf60ebd4b838 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Thu, 16 Jul 2026 18:39:08 +0000 Subject: [PATCH 462/462] =?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 61313d3f1..212368dad 100644 --- a/docs/en/docs/release-notes.md +++ b/docs/en/docs/release-notes.md @@ -11,6 +11,10 @@ hide: * 📝 Restructure FastAPI People and related pages. PR [#16015](https://github.com/fastapi/fastapi/pull/16015) by [@tiangolo](https://github.com/tiangolo). +### Internal + +* 🔥 Remove now-obsolete scripts to generate data for FastAPI People. PR [#16016](https://github.com/fastapi/fastapi/pull/16016) by [@tiangolo](https://github.com/tiangolo). + ## 0.139.2 (2026-07-16) ### Fixes