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 001/359] =?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 002/359] =?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 003/359] =?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 004/359] =?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 005/359] =?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 006/359] =?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 007/359] =?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 008/359] =?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 009/359] =?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 010/359] =?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 011/359] =?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 012/359] =?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 013/359] =?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 014/359] =?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 015/359] =?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 016/359] =?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 017/359] =?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 018/359] =?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 019/359] =?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 020/359] =?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 021/359] =?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 022/359] =?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 023/359] =?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 024/359] =?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 025/359] =?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 026/359] =?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 027/359] =?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 028/359] =?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 029/359] =?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 030/359] =?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 031/359] =?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 032/359] =?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 033/359] =?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 034/359] =?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 035/359] =?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 036/359] =?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 037/359] =?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 038/359] =?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 039/359] =?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 040/359] =?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 041/359] =?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 042/359] =?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 043/359] =?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 044/359] =?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 045/359] =?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 237/359] =?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 238/359] =?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 239/359] =?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 240/359] =?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 241/359] =?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 242/359] =?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 243/359] =?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 244/359] =?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 245/359] =?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 246/359] =?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 247/359] =?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 248/359] =?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 249/359] =?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 250/359] =?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 251/359] =?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 252/359] =?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 253/359] =?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 254/359] =?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 255/359] =?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 256/359] =?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 257/359] =?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 258/359] =?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 259/359] =?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 260/359] =?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 261/359] =?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 262/359] =?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 263/359] =?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 264/359] =?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 265/359] =?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 266/359] =?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 267/359] =?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 268/359] =?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 269/359] =?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 270/359] =?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 271/359] =?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 272/359] =?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 273/359] =?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 274/359] =?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 275/359] =?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 276/359] =?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 277/359] =?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 278/359] =?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 279/359] =?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 280/359] =?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 281/359] =?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 282/359] =?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 283/359] =?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 284/359] =?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 285/359] =?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 286/359] =?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 287/359] =?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 288/359] =?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 289/359] =?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 290/359] =?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 291/359] =?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 292/359] =?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 293/359] =?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 294/359] =?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 295/359] =?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 296/359] =?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 297/359] =?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 298/359] =?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 299/359] =?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 300/359] =?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 301/359] =?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 302/359] =?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 303/359] =?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 304/359] =?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 305/359] =?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 306/359] =?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 307/359] =?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 308/359] =?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 309/359] =?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 310/359] =?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 311/359] =?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 314/359] =?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 315/359] =?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 316/359] =?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 317/359] =?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 318/359] =?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 319/359] =?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 320/359] =?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 321/359] =?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 322/359] =?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 323/359] =?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 324/359] =?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 325/359] =?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 326/359] =?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 327/359] =?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 328/359] =?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 329/359] =?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 330/359] =?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 331/359] =?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 332/359] =?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 333/359] =?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 334/359] =?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 335/359] =?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 336/359] =?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 337/359] =?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 338/359] =?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 339/359] =?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 340/359] =?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 341/359] =?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 342/359] =?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 343/359] =?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 344/359] =?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 345/359] =?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 346/359] =?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 347/359] =?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 348/359] =?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 349/359] =?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 350/359] =?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 351/359] =?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 352/359] =?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 353/359] =?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 354/359] =?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 355/359] =?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 356/359] =?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 357/359] =?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 358/359] =?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 359/359] =?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).