From da0bfd22aa91ebdac4bc04e4af8b6755303bcd25 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Thu, 3 Nov 2022 12:44:51 +0100 Subject: [PATCH 01/97] =?UTF-8?q?=F0=9F=91=A5=20Update=20FastAPI=20People?= =?UTF-8?q?=20(#5571)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: github-actions --- docs/en/data/github_sponsors.yml | 101 ++++++++++++------- docs/en/data/people.yml | 164 +++++++++++++++---------------- 2 files changed, 146 insertions(+), 119 deletions(-) diff --git a/docs/en/data/github_sponsors.yml b/docs/en/data/github_sponsors.yml index aaf7c9b80a..3d0b37dac7 100644 --- a/docs/en/data/github_sponsors.yml +++ b/docs/en/data/github_sponsors.yml @@ -32,13 +32,13 @@ sponsors: - login: VincentParedes avatarUrl: https://avatars.githubusercontent.com/u/103889729?v=4 url: https://github.com/VincentParedes +- - login: getsentry + avatarUrl: https://avatars.githubusercontent.com/u/1396951?v=4 + url: https://github.com/getsentry - - login: InesIvanova avatarUrl: https://avatars.githubusercontent.com/u/22920417?u=409882ec1df6dbd77455788bb383a8de223dbf6f&v=4 url: https://github.com/InesIvanova -- - login: zopyx - avatarUrl: https://avatars.githubusercontent.com/u/594239?u=8e5ce882664f47fd61002bed51718c78c3799d24&v=4 - url: https://github.com/zopyx - - login: SendCloud +- - login: SendCloud avatarUrl: https://avatars.githubusercontent.com/u/7831959?v=4 url: https://github.com/SendCloud - login: mercedes-benz @@ -62,21 +62,21 @@ sponsors: - login: Trivie avatarUrl: https://avatars.githubusercontent.com/u/8161763?v=4 url: https://github.com/Trivie - - login: wdwinslow - avatarUrl: https://avatars.githubusercontent.com/u/11562137?u=dc01daafb354135603a263729e3d26d939c0c452&v=4 - url: https://github.com/wdwinslow - - login: moellenbeck avatarUrl: https://avatars.githubusercontent.com/u/169372?v=4 url: https://github.com/moellenbeck + - login: AccentDesign + avatarUrl: https://avatars.githubusercontent.com/u/2429332?v=4 + url: https://github.com/AccentDesign - login: RodneyU215 avatarUrl: https://avatars.githubusercontent.com/u/3329665?u=ec6a9adf8e7e8e306eed7d49687c398608d1604f&v=4 url: https://github.com/RodneyU215 - login: tizz98 avatarUrl: https://avatars.githubusercontent.com/u/5739698?u=f095a3659e3a8e7c69ccd822696990b521ea25f9&v=4 url: https://github.com/tizz98 - - login: Vikka + - login: dorianturba avatarUrl: https://avatars.githubusercontent.com/u/9381120?u=4bfc7032a824d1ed1994aa8256dfa597c8f187ad&v=4 - url: https://github.com/Vikka + url: https://github.com/dorianturba - login: jmaralc avatarUrl: https://avatars.githubusercontent.com/u/21101214?u=b15a9f07b7cbf6c9dcdbcb6550bbd2c52f55aa50&v=4 url: https://github.com/jmaralc @@ -89,13 +89,19 @@ sponsors: - login: DelfinaCare avatarUrl: https://avatars.githubusercontent.com/u/83734439?v=4 url: https://github.com/DelfinaCare +- - login: karelhusa + avatarUrl: https://avatars.githubusercontent.com/u/11407706?u=4f787cffc30ea198b15935c751940f0b48a26a17&v=4 + url: https://github.com/karelhusa - - login: povilasb avatarUrl: https://avatars.githubusercontent.com/u/1213442?u=b11f58ed6ceea6e8297c9b310030478ebdac894d&v=4 url: https://github.com/povilasb - login: primer-io avatarUrl: https://avatars.githubusercontent.com/u/62146168?v=4 url: https://github.com/primer-io -- - login: A-Edge +- - login: DucNgn + avatarUrl: https://avatars.githubusercontent.com/u/43587865?u=a9f9f61569aebdc0ce74df85b8cc1a219a7ab570&v=4 + url: https://github.com/DucNgn + - login: A-Edge avatarUrl: https://avatars.githubusercontent.com/u/59514131?v=4 url: https://github.com/A-Edge - - login: Kludex @@ -113,6 +119,9 @@ sponsors: - login: kamalgill avatarUrl: https://avatars.githubusercontent.com/u/133923?u=0df9181d97436ce330e9acf90ab8a54b7022efe7&v=4 url: https://github.com/kamalgill + - login: gazpachoking + avatarUrl: https://avatars.githubusercontent.com/u/187133?v=4 + url: https://github.com/gazpachoking - login: dekoza avatarUrl: https://avatars.githubusercontent.com/u/210980?u=c03c78a8ae1039b500dfe343665536ebc51979b2&v=4 url: https://github.com/dekoza @@ -170,15 +179,15 @@ sponsors: - login: zsinx6 avatarUrl: https://avatars.githubusercontent.com/u/3532625?u=ba75a5dc744d1116ccfeaaf30d41cb2fe81fe8dd&v=4 url: https://github.com/zsinx6 + - login: bauyrzhanospan + avatarUrl: https://avatars.githubusercontent.com/u/3536037?u=25c86201d0212497aefcc1688cccf509057a1dc4&v=4 + url: https://github.com/bauyrzhanospan - login: MarekBleschke avatarUrl: https://avatars.githubusercontent.com/u/3616870?v=4 url: https://github.com/MarekBleschke - login: aacayaco avatarUrl: https://avatars.githubusercontent.com/u/3634801?u=eaadda178c964178fcb64886f6c732172c8f8219&v=4 url: https://github.com/aacayaco - - login: anomaly - avatarUrl: https://avatars.githubusercontent.com/u/3654837?v=4 - url: https://github.com/anomaly - login: peterHoburg avatarUrl: https://avatars.githubusercontent.com/u/3860655?u=f55f47eb2d6a9b495e806ac5a044e3ae01ccc1fa&v=4 url: https://github.com/peterHoburg @@ -194,15 +203,15 @@ sponsors: - login: oliverxchen avatarUrl: https://avatars.githubusercontent.com/u/4471774?u=534191f25e32eeaadda22dfab4b0a428733d5489&v=4 url: https://github.com/oliverxchen - - login: CINOAdam - avatarUrl: https://avatars.githubusercontent.com/u/4728508?u=76ef23f06ae7c604e009873bc27cf0ea9ba738c9&v=4 - url: https://github.com/CINOAdam - login: ScrimForever avatarUrl: https://avatars.githubusercontent.com/u/5040124?u=091ec38bfe16d6e762099e91309b59f248616a65&v=4 url: https://github.com/ScrimForever - login: ennui93 avatarUrl: https://avatars.githubusercontent.com/u/5300907?u=5b5452725ddb391b2caaebf34e05aba873591c3a&v=4 url: https://github.com/ennui93 + - login: ternaus + avatarUrl: https://avatars.githubusercontent.com/u/5481618?u=fabc8d75c921b3380126adb5a931c5da6e7db04f&v=4 + url: https://github.com/ternaus - login: Yaleesa avatarUrl: https://avatars.githubusercontent.com/u/6135475?v=4 url: https://github.com/Yaleesa @@ -216,7 +225,7 @@ sponsors: avatarUrl: https://avatars.githubusercontent.com/u/6347418?u=98f5918b32e214a168a2f5d59b0b8ebdf57dca0d&v=4 url: https://github.com/pkucmus - login: s3ich4n - avatarUrl: https://avatars.githubusercontent.com/u/6926298?u=ba3025d698e1c986655e776ae383a3d60d9d578e&v=4 + avatarUrl: https://avatars.githubusercontent.com/u/6926298?u=6690c5403bc1d9a1837886defdc5256e9a43b1db&v=4 url: https://github.com/s3ich4n - login: Rehket avatarUrl: https://avatars.githubusercontent.com/u/7015688?u=3afb0ba200feebbc7f958950e92db34df2a3c172&v=4 @@ -227,6 +236,9 @@ sponsors: - login: Shackelford-Arden avatarUrl: https://avatars.githubusercontent.com/u/7362263?v=4 url: https://github.com/Shackelford-Arden + - login: wdwinslow + avatarUrl: https://avatars.githubusercontent.com/u/11562137?u=dc01daafb354135603a263729e3d26d939c0c452&v=4 + url: https://github.com/wdwinslow - login: Ge0f3 avatarUrl: https://avatars.githubusercontent.com/u/11887760?u=ccd80f1ac36dcb8517ef5c4e702e8cc5a80cad2f&v=4 url: https://github.com/Ge0f3 @@ -239,6 +251,9 @@ sponsors: - login: dannywade avatarUrl: https://avatars.githubusercontent.com/u/13680237?u=418ee985bd41577b20fde81417fb2d901e875e8a&v=4 url: https://github.com/dannywade + - login: khadrawy + avatarUrl: https://avatars.githubusercontent.com/u/13686061?u=59f25ef42ecf04c22657aac4238ce0e2d3d30304&v=4 + url: https://github.com/khadrawy - login: pablonnaoji avatarUrl: https://avatars.githubusercontent.com/u/15187159?u=afc15bd5a4ba9c5c7206bbb1bcaeef606a0932e0&v=4 url: https://github.com/pablonnaoji @@ -302,20 +317,17 @@ sponsors: - login: rafsaf avatarUrl: https://avatars.githubusercontent.com/u/51059348?u=f8f0d6d6e90fac39fa786228158ba7f013c74271&v=4 url: https://github.com/rafsaf - - login: yezz123 - avatarUrl: https://avatars.githubusercontent.com/u/52716203?u=636b4f79645176df4527dd45c12d5dbb5a4193cf&v=4 - url: https://github.com/yezz123 - login: dudikbender avatarUrl: https://avatars.githubusercontent.com/u/53487583?u=494f85229115076121b3639a3806bbac1c6ae7f6&v=4 url: https://github.com/dudikbender - - login: llamington - avatarUrl: https://avatars.githubusercontent.com/u/54869395?u=42ea59b76f49449f41a4d106bb65a130797e8d7c&v=4 - url: https://github.com/llamington + - login: dazeddd + avatarUrl: https://avatars.githubusercontent.com/u/59472056?u=7a1b668449bf8b448db13e4c575576d24d7d658b&v=4 + url: https://github.com/dazeddd - login: yakkonaut avatarUrl: https://avatars.githubusercontent.com/u/60633704?u=90a71fd631aa998ba4a96480788f017c9904e07b&v=4 url: https://github.com/yakkonaut - login: patsatsia - avatarUrl: https://avatars.githubusercontent.com/u/61111267?u=419516384f798a35e9d9e2dd81282cc46c151b58&v=4 + avatarUrl: https://avatars.githubusercontent.com/u/61111267?u=3271b85f7a37b479c8d0ae0a235182e83c166edf&v=4 url: https://github.com/patsatsia - login: predictionmachine avatarUrl: https://avatars.githubusercontent.com/u/63719559?v=4 @@ -332,9 +344,15 @@ sponsors: - login: dotlas avatarUrl: https://avatars.githubusercontent.com/u/88832003?v=4 url: https://github.com/dotlas + - login: programvx + avatarUrl: https://avatars.githubusercontent.com/u/96057906?v=4 + url: https://github.com/programvx - login: pyt3h avatarUrl: https://avatars.githubusercontent.com/u/99658549?v=4 url: https://github.com/pyt3h + - login: Dagmaara + avatarUrl: https://avatars.githubusercontent.com/u/115501964?v=4 + url: https://github.com/Dagmaara - - login: linux-china avatarUrl: https://avatars.githubusercontent.com/u/46711?v=4 url: https://github.com/linux-china @@ -419,6 +437,9 @@ sponsors: - login: pawamoy avatarUrl: https://avatars.githubusercontent.com/u/3999221?u=b030e4c89df2f3a36bc4710b925bdeb6745c9856&v=4 url: https://github.com/pawamoy + - login: nikeee + avatarUrl: https://avatars.githubusercontent.com/u/4068864?u=63f8eee593f25138e0f1032ef442e9ad24907d4c&v=4 + url: https://github.com/nikeee - login: Alisa-lisa avatarUrl: https://avatars.githubusercontent.com/u/4137964?u=e7e393504f554f4ff15863a1e01a5746863ef9ce&v=4 url: https://github.com/Alisa-lisa @@ -426,7 +447,7 @@ sponsors: avatarUrl: https://avatars.githubusercontent.com/u/4472301?v=4 url: https://github.com/danielunderwood - login: unredundant - avatarUrl: https://avatars.githubusercontent.com/u/5607577?u=57dd0023365bec03f4fc566df6b81bc0a264a47d&v=4 + avatarUrl: https://avatars.githubusercontent.com/u/5607577?u=1ffbf39f5bb8736b75c0d235707d6e8f803725c5&v=4 url: https://github.com/unredundant - login: Baghdady92 avatarUrl: https://avatars.githubusercontent.com/u/5708590?v=4 @@ -434,6 +455,9 @@ sponsors: - login: holec avatarUrl: https://avatars.githubusercontent.com/u/6438041?u=f5af71ec85b3a9d7b8139cb5af0512b02fa9ab1e&v=4 url: https://github.com/holec + - login: mattwelke + avatarUrl: https://avatars.githubusercontent.com/u/7719209?u=5d963ead289969257190b133250653bd99df06ba&v=4 + url: https://github.com/mattwelke - login: hcristea avatarUrl: https://avatars.githubusercontent.com/u/7814406?u=61d7a4fcf846983a4606788eac25e1c6c1209ba8&v=4 url: https://github.com/hcristea @@ -470,9 +494,6 @@ sponsors: - login: logan-connolly avatarUrl: https://avatars.githubusercontent.com/u/16244943?u=8ae66dfbba936463cc8aa0dd7a6d2b4c0cc757eb&v=4 url: https://github.com/logan-connolly - - login: sanghunka - avatarUrl: https://avatars.githubusercontent.com/u/16280020?u=7d8fafd8bfe6d7900bb1e52d5a5d5da0c02bc164&v=4 - url: https://github.com/sanghunka - login: stevenayers avatarUrl: https://avatars.githubusercontent.com/u/16361214?u=098b797d8d48afb8cd964b717847943b61d24a6d&v=4 url: https://github.com/stevenayers @@ -494,6 +515,12 @@ sponsors: - login: fstau avatarUrl: https://avatars.githubusercontent.com/u/24669867?u=60e7c8c09f8dafabee8fc3edcd6f9e19abbff918&v=4 url: https://github.com/fstau + - login: pers0n4 + avatarUrl: https://avatars.githubusercontent.com/u/24864600?u=444441027bc2c9f9db68e8047d65ff23d25699cf&v=4 + url: https://github.com/pers0n4 + - login: SebTota + avatarUrl: https://avatars.githubusercontent.com/u/25122511?v=4 + url: https://github.com/SebTota - login: mertguvencli avatarUrl: https://avatars.githubusercontent.com/u/29762151?u=16a906d90df96c8cff9ea131a575c4bc171b1523&v=4 url: https://github.com/mertguvencli @@ -563,12 +590,12 @@ sponsors: - login: pondDevThai avatarUrl: https://avatars.githubusercontent.com/u/71592181?u=08af9a59bccfd8f6b101de1005aa9822007d0a44&v=4 url: https://github.com/pondDevThai -- - login: mattwelke - avatarUrl: https://avatars.githubusercontent.com/u/7719209?u=5d963ead289969257190b133250653bd99df06ba&v=4 - url: https://github.com/mattwelke - - login: cesarfreire - avatarUrl: https://avatars.githubusercontent.com/u/21126103?u=5d428f77f9b63c741f0e9ca5e15a689017b66fe8&v=4 - url: https://github.com/cesarfreire + - login: marlonmartins2 + avatarUrl: https://avatars.githubusercontent.com/u/87719558?u=d07ffecfdabf4fd9aca987f8b5cd9128c65e598e&v=4 + url: https://github.com/marlonmartins2 +- - login: 2niuhe + avatarUrl: https://avatars.githubusercontent.com/u/13382324?u=ac918d72e0329c87ba29b3bf85e03e98a4ee9427&v=4 + url: https://github.com/2niuhe - login: gabrielmbmb avatarUrl: https://avatars.githubusercontent.com/u/29572918?u=6d1e00b5d558e96718312ff910a2318f47cc3145&v=4 url: https://github.com/gabrielmbmb @@ -578,6 +605,6 @@ sponsors: - login: Moises6669 avatarUrl: https://avatars.githubusercontent.com/u/66188523?u=96af25b8d5be9f983cb96e9dd7c605c716caf1f5&v=4 url: https://github.com/Moises6669 - - login: zahariev-webbersof - avatarUrl: https://avatars.githubusercontent.com/u/68993494?u=b341c94a8aa0624e05e201bcf8ae5b2697e3be2f&v=4 - url: https://github.com/zahariev-webbersof + - login: su-shubham + avatarUrl: https://avatars.githubusercontent.com/u/75021117?v=4 + url: https://github.com/su-shubham diff --git a/docs/en/data/people.yml b/docs/en/data/people.yml index c7354eb44b..730528795c 100644 --- a/docs/en/data/people.yml +++ b/docs/en/data/people.yml @@ -1,12 +1,12 @@ maintainers: - login: tiangolo - answers: 1271 - prs: 338 + answers: 1315 + prs: 342 avatarUrl: https://avatars.githubusercontent.com/u/1326112?u=740f11212a731f56798f558ceddb0bd07642afa7&v=4 url: https://github.com/tiangolo experts: - login: Kludex - count: 364 + count: 367 avatarUrl: https://avatars.githubusercontent.com/u/7353520?u=62adc405ef418f4b6c8caa93d3eb8ab107bc4927&v=4 url: https://github.com/Kludex - login: dmontagu @@ -21,14 +21,14 @@ experts: count: 207 avatarUrl: https://avatars.githubusercontent.com/u/1405026?v=4 url: https://github.com/Mause +- login: JarroVGIT + count: 187 + avatarUrl: https://avatars.githubusercontent.com/u/13659033?u=e8bea32d07a5ef72f7dde3b2079ceb714923ca05&v=4 + url: https://github.com/JarroVGIT - login: euri10 count: 166 avatarUrl: https://avatars.githubusercontent.com/u/1104190?u=321a2e953e6645a7d09b732786c7a8061e0f8a8b&v=4 url: https://github.com/euri10 -- login: JarroVGIT - count: 163 - avatarUrl: https://avatars.githubusercontent.com/u/13659033?u=e8bea32d07a5ef72f7dde3b2079ceb714923ca05&v=4 - url: https://github.com/JarroVGIT - login: phy25 count: 130 avatarUrl: https://avatars.githubusercontent.com/u/331403?v=4 @@ -37,20 +37,20 @@ experts: count: 77 avatarUrl: https://avatars.githubusercontent.com/u/10202690?u=e6f86f5c0c3026a15d6b51792fa3e532b12f1371&v=4 url: https://github.com/raphaelauv +- login: iudeen + count: 76 + avatarUrl: https://avatars.githubusercontent.com/u/10519440?u=2843b3303282bff8b212dcd4d9d6689452e4470c&v=4 + url: https://github.com/iudeen - login: ArcLightSlavik count: 71 avatarUrl: https://avatars.githubusercontent.com/u/31127044?u=b0f2c37142f4b762e41ad65dc49581813422bd71&v=4 url: https://github.com/ArcLightSlavik -- login: iudeen - count: 65 - avatarUrl: https://avatars.githubusercontent.com/u/10519440?u=2843b3303282bff8b212dcd4d9d6689452e4470c&v=4 - url: https://github.com/iudeen - login: falkben count: 58 avatarUrl: https://avatars.githubusercontent.com/u/653031?u=0c8d8f33d87f1aa1a6488d3f02105e9abc838105&v=4 url: https://github.com/falkben - login: sm-Fifteen - count: 49 + count: 50 avatarUrl: https://avatars.githubusercontent.com/u/516999?u=437c0c5038558c67e887ccd863c1ba0f846c03da&v=4 url: https://github.com/sm-Fifteen - login: insomnes @@ -58,11 +58,11 @@ experts: avatarUrl: https://avatars.githubusercontent.com/u/16958893?u=f8be7088d5076d963984a21f95f44e559192d912&v=4 url: https://github.com/insomnes - login: jgould22 - count: 45 + count: 46 avatarUrl: https://avatars.githubusercontent.com/u/4335847?u=ed77f67e0bb069084639b24d812dbb2a2b1dc554&v=4 url: https://github.com/jgould22 - login: Dustyposa - count: 43 + count: 45 avatarUrl: https://avatars.githubusercontent.com/u/27180793?u=5cf2877f50b3eb2bc55086089a78a36f07042889&v=4 url: https://github.com/Dustyposa - login: adriangb @@ -89,6 +89,10 @@ experts: count: 31 avatarUrl: https://avatars.githubusercontent.com/u/1144727?u=85c025e3fcc7bd79a5665c63ee87cdf8aae13374&v=4 url: https://github.com/frankie567 +- login: acidjunk + count: 31 + avatarUrl: https://avatars.githubusercontent.com/u/685002?u=b5094ab4527fc84b006c0ac9ff54367bdebb2267&v=4 + url: https://github.com/acidjunk - login: krishnardt count: 31 avatarUrl: https://avatars.githubusercontent.com/u/31960541?u=47f4829c77f4962ab437ffb7995951e41eeebe9b&v=4 @@ -101,10 +105,6 @@ experts: count: 29 avatarUrl: https://avatars.githubusercontent.com/u/41326348?u=ba2fda6b30110411ecbf406d187907e2b420ac19&v=4 url: https://github.com/panla -- login: acidjunk - count: 27 - avatarUrl: https://avatars.githubusercontent.com/u/685002?u=b5094ab4527fc84b006c0ac9ff54367bdebb2267&v=4 - url: https://github.com/acidjunk - login: ghandic count: 25 avatarUrl: https://avatars.githubusercontent.com/u/23500353?u=e2e1d736f924d9be81e8bfc565b6d8836ba99773&v=4 @@ -117,6 +117,10 @@ experts: count: 24 avatarUrl: https://avatars.githubusercontent.com/u/9435877?u=719327b7d2c4c62212456d771bfa7c6b8dbb9eac&v=4 url: https://github.com/SirTelemak +- login: odiseo0 + count: 23 + avatarUrl: https://avatars.githubusercontent.com/u/87550035?u=16f9255804161c6ff3c8b7ef69848f0126bcd405&v=4 + url: https://github.com/odiseo0 - login: acnebs count: 22 avatarUrl: https://avatars.githubusercontent.com/u/9054108?u=c27e50269f1ef8ea950cc6f0268c8ec5cebbe9c9&v=4 @@ -129,10 +133,6 @@ experts: count: 21 avatarUrl: https://avatars.githubusercontent.com/u/565544?v=4 url: https://github.com/chris-allnutt -- login: odiseo0 - count: 21 - avatarUrl: https://avatars.githubusercontent.com/u/87550035?u=ab724eae71c3fe1cf81e8dc76e73415da926ef7d&v=4 - url: https://github.com/odiseo0 - login: retnikt count: 19 avatarUrl: https://avatars.githubusercontent.com/u/24581770?v=4 @@ -161,6 +161,10 @@ experts: count: 16 avatarUrl: https://avatars.githubusercontent.com/u/39515546?u=ec35139777597cdbbbddda29bf8b9d4396b429a9&v=4 url: https://github.com/waynerv +- login: yinziyan1206 + count: 16 + avatarUrl: https://avatars.githubusercontent.com/u/37829370?v=4 + url: https://github.com/yinziyan1206 - login: dstlny count: 16 avatarUrl: https://avatars.githubusercontent.com/u/41964673?u=9f2174f9d61c15c6e3a4c9e3aeee66f711ce311f&v=4 @@ -177,10 +181,6 @@ experts: count: 13 avatarUrl: https://avatars.githubusercontent.com/u/58201?u=dd40d99a3e1935d0b768f122bfe2258d6ea53b2b&v=4 url: https://github.com/haizaar -- login: yinziyan1206 - count: 13 - avatarUrl: https://avatars.githubusercontent.com/u/37829370?v=4 - url: https://github.com/yinziyan1206 - login: valentin994 count: 13 avatarUrl: https://avatars.githubusercontent.com/u/42819267?u=fdeeaa9242a59b243f8603496b00994f6951d5a2&v=4 @@ -193,35 +193,27 @@ experts: count: 12 avatarUrl: https://avatars.githubusercontent.com/u/2964996?v=4 url: https://github.com/n8sty -- login: zoliknemet +- login: mbroton count: 12 - avatarUrl: https://avatars.githubusercontent.com/u/22326718?u=31ba446ac290e23e56eea8e4f0c558aaf0b40779&v=4 - url: https://github.com/zoliknemet + avatarUrl: https://avatars.githubusercontent.com/u/50829834?u=a48610bf1bffaa9c75d03228926e2eb08a2e24ee&v=4 + url: https://github.com/mbroton last_month_active: - login: JarroVGIT - count: 27 + count: 18 avatarUrl: https://avatars.githubusercontent.com/u/13659033?u=e8bea32d07a5ef72f7dde3b2079ceb714923ca05&v=4 url: https://github.com/JarroVGIT - login: iudeen - count: 16 + count: 8 avatarUrl: https://avatars.githubusercontent.com/u/10519440?u=2843b3303282bff8b212dcd4d9d6689452e4470c&v=4 url: https://github.com/iudeen - login: mbroton - count: 6 + count: 4 avatarUrl: https://avatars.githubusercontent.com/u/50829834?u=a48610bf1bffaa9c75d03228926e2eb08a2e24ee&v=4 url: https://github.com/mbroton -- login: csrgxtu - count: 6 - avatarUrl: https://avatars.githubusercontent.com/u/5053620?u=9655a3e9661492fcdaaf99193eb16d5cbcc3849e&v=4 - url: https://github.com/csrgxtu -- login: Kludex - count: 4 - avatarUrl: https://avatars.githubusercontent.com/u/7353520?u=62adc405ef418f4b6c8caa93d3eb8ab107bc4927&v=4 - url: https://github.com/Kludex -- login: jgould22 +- login: yinziyan1206 count: 3 - avatarUrl: https://avatars.githubusercontent.com/u/4335847?u=ed77f67e0bb069084639b24d812dbb2a2b1dc554&v=4 - url: https://github.com/jgould22 + avatarUrl: https://avatars.githubusercontent.com/u/37829370?v=4 + url: https://github.com/yinziyan1206 top_contributors: - login: waynerv count: 25 @@ -243,6 +235,10 @@ top_contributors: count: 15 avatarUrl: https://avatars.githubusercontent.com/u/7353520?u=62adc405ef418f4b6c8caa93d3eb8ab107bc4927&v=4 url: https://github.com/Kludex +- login: dependabot + count: 14 + avatarUrl: https://avatars.githubusercontent.com/in/29110?v=4 + url: https://github.com/apps/dependabot - login: euri10 count: 13 avatarUrl: https://avatars.githubusercontent.com/u/1104190?u=321a2e953e6645a7d09b732786c7a8061e0f8a8b&v=4 @@ -255,10 +251,6 @@ top_contributors: count: 10 avatarUrl: https://avatars.githubusercontent.com/u/16785985?v=4 url: https://github.com/Smlep -- login: dependabot - count: 9 - avatarUrl: https://avatars.githubusercontent.com/in/29110?v=4 - url: https://github.com/apps/dependabot - login: Serrones count: 8 avatarUrl: https://avatars.githubusercontent.com/u/22691749?u=4795b880e13ca33a73e52fc0ef7dc9c60c8fce47&v=4 @@ -271,6 +263,14 @@ top_contributors: count: 7 avatarUrl: https://avatars.githubusercontent.com/u/9651103?u=95db33927bbff1ed1c07efddeb97ac2ff33068ed&v=4 url: https://github.com/hard-coders +- login: rjNemo + count: 7 + avatarUrl: https://avatars.githubusercontent.com/u/56785022?u=d5c3a02567c8649e146fcfc51b6060ccaf8adef8&v=4 + url: https://github.com/rjNemo +- login: pre-commit-ci + count: 6 + avatarUrl: https://avatars.githubusercontent.com/in/68672?v=4 + url: https://github.com/apps/pre-commit-ci - login: wshayes count: 5 avatarUrl: https://avatars.githubusercontent.com/u/365303?u=07ca03c5ee811eb0920e633cc3c3db73dbec1aa5&v=4 @@ -285,12 +285,16 @@ top_contributors: url: https://github.com/Attsun1031 - login: ComicShrimp count: 5 - avatarUrl: https://avatars.githubusercontent.com/u/43503750?u=b3e4d9a14d9a65d429ce62c566aef73178b7111d&v=4 + avatarUrl: https://avatars.githubusercontent.com/u/43503750?u=f440bc9062afb3c43b9b9c6cdfdcfe31d58699ef&v=4 url: https://github.com/ComicShrimp - login: jekirl count: 4 avatarUrl: https://avatars.githubusercontent.com/u/2546697?u=a027452387d85bd4a14834e19d716c99255fb3b7&v=4 url: https://github.com/jekirl +- login: samuelcolvin + count: 4 + avatarUrl: https://avatars.githubusercontent.com/u/4039449?u=807390ba9cfe23906c3bf8a0d56aaca3cf2bfa0d&v=4 + url: https://github.com/samuelcolvin - login: jfunez count: 4 avatarUrl: https://avatars.githubusercontent.com/u/805749?v=4 @@ -307,10 +311,6 @@ top_contributors: count: 4 avatarUrl: https://avatars.githubusercontent.com/u/3360631?u=5fa1f475ad784d64eb9666bdd43cc4d285dcc773&v=4 url: https://github.com/hitrust -- login: rjNemo - count: 4 - avatarUrl: https://avatars.githubusercontent.com/u/56785022?u=d5c3a02567c8649e146fcfc51b6060ccaf8adef8&v=4 - url: https://github.com/rjNemo - login: lsglucas count: 4 avatarUrl: https://avatars.githubusercontent.com/u/61513630?u=320e43fe4dc7bc6efc64e9b8f325f8075634fd20&v=4 @@ -319,19 +319,23 @@ top_contributors: count: 4 avatarUrl: https://avatars.githubusercontent.com/u/79563565?u=1741703bd6c8f491503354b363a86e879b4c1cab&v=4 url: https://github.com/NinaHwang -- login: pre-commit-ci +- login: batlopes count: 4 - avatarUrl: https://avatars.githubusercontent.com/in/68672?v=4 - url: https://github.com/apps/pre-commit-ci + avatarUrl: https://avatars.githubusercontent.com/u/33462923?u=0fb3d7acb316764616f11e4947faf080e49ad8d9&v=4 + url: https://github.com/batlopes top_reviewers: - login: Kludex - count: 101 + count: 108 avatarUrl: https://avatars.githubusercontent.com/u/7353520?u=62adc405ef418f4b6c8caa93d3eb8ab107bc4927&v=4 url: https://github.com/Kludex - login: BilalAlpaslan - count: 64 + count: 65 avatarUrl: https://avatars.githubusercontent.com/u/47563997?u=63ed66e304fe8d765762c70587d61d9196e5c82d&v=4 url: https://github.com/BilalAlpaslan +- login: yezz123 + count: 56 + avatarUrl: https://avatars.githubusercontent.com/u/52716203?u=636b4f79645176df4527dd45c12d5dbb5a4193cf&v=4 + url: https://github.com/yezz123 - login: tokusumi count: 50 avatarUrl: https://avatars.githubusercontent.com/u/41147016?u=55010621aece725aa702270b54fed829b6a1fe60&v=4 @@ -344,10 +348,6 @@ top_reviewers: count: 47 avatarUrl: https://avatars.githubusercontent.com/u/59285379?v=4 url: https://github.com/Laineyzhang55 -- login: yezz123 - count: 46 - avatarUrl: https://avatars.githubusercontent.com/u/52716203?u=636b4f79645176df4527dd45c12d5dbb5a4193cf&v=4 - url: https://github.com/yezz123 - login: ycd count: 45 avatarUrl: https://avatars.githubusercontent.com/u/62724709?u=fa40e037060d62bf82e16b505d870a2866725f38&v=4 @@ -356,6 +356,10 @@ top_reviewers: count: 41 avatarUrl: https://avatars.githubusercontent.com/u/24587499?u=e772190a051ab0eaa9c8542fcff1892471638f2b&v=4 url: https://github.com/cikay +- login: JarroVGIT + count: 34 + avatarUrl: https://avatars.githubusercontent.com/u/13659033?u=e8bea32d07a5ef72f7dde3b2079ceb714923ca05&v=4 + url: https://github.com/JarroVGIT - login: AdrianDeAnda count: 33 avatarUrl: https://avatars.githubusercontent.com/u/1024932?u=b2ea249c6b41ddf98679c8d110d0f67d4a3ebf93&v=4 @@ -364,16 +368,16 @@ top_reviewers: count: 31 avatarUrl: https://avatars.githubusercontent.com/u/31127044?u=b0f2c37142f4b762e41ad65dc49581813422bd71&v=4 url: https://github.com/ArcLightSlavik -- login: JarroVGIT - count: 31 - avatarUrl: https://avatars.githubusercontent.com/u/13659033?u=e8bea32d07a5ef72f7dde3b2079ceb714923ca05&v=4 - url: https://github.com/JarroVGIT +- login: iudeen + count: 26 + avatarUrl: https://avatars.githubusercontent.com/u/10519440?u=2843b3303282bff8b212dcd4d9d6689452e4470c&v=4 + url: https://github.com/iudeen - login: cassiobotaro count: 25 avatarUrl: https://avatars.githubusercontent.com/u/3127847?u=b0a652331da17efeb85cd6e3a4969182e5004804&v=4 url: https://github.com/cassiobotaro - login: lsglucas - count: 24 + count: 25 avatarUrl: https://avatars.githubusercontent.com/u/61513630?u=320e43fe4dc7bc6efc64e9b8f325f8075634fd20&v=4 url: https://github.com/lsglucas - login: dmontagu @@ -392,6 +396,14 @@ top_reviewers: count: 19 avatarUrl: https://avatars.githubusercontent.com/u/63915557?u=47debaa860fd52c9b98c97ef357ddcec3b3fb399&v=4 url: https://github.com/0417taehyun +- login: rjNemo + count: 17 + avatarUrl: https://avatars.githubusercontent.com/u/56785022?u=d5c3a02567c8649e146fcfc51b6060ccaf8adef8&v=4 + url: https://github.com/rjNemo +- login: Smlep + count: 17 + avatarUrl: https://avatars.githubusercontent.com/u/16785985?v=4 + url: https://github.com/Smlep - login: zy7y count: 17 avatarUrl: https://avatars.githubusercontent.com/u/67154681?u=5d634834cc514028ea3f9115f7030b99a1f4d5a4&v=4 @@ -404,14 +416,6 @@ top_reviewers: count: 16 avatarUrl: https://avatars.githubusercontent.com/u/52768429?u=6a3aa15277406520ad37f6236e89466ed44bc5b8&v=4 url: https://github.com/SwftAlpc -- login: rjNemo - count: 16 - avatarUrl: https://avatars.githubusercontent.com/u/56785022?u=d5c3a02567c8649e146fcfc51b6060ccaf8adef8&v=4 - url: https://github.com/rjNemo -- login: Smlep - count: 16 - avatarUrl: https://avatars.githubusercontent.com/u/16785985?v=4 - url: https://github.com/Smlep - login: DevDae count: 16 avatarUrl: https://avatars.githubusercontent.com/u/87962045?u=08e10fa516e844934f4b3fc7c38b33c61697e4a1&v=4 @@ -424,10 +428,10 @@ top_reviewers: count: 15 avatarUrl: https://avatars.githubusercontent.com/u/63476957?u=6c86e59b48e0394d4db230f37fc9ad4d7e2c27c7&v=4 url: https://github.com/delhi09 -- login: iudeen +- login: odiseo0 count: 14 - avatarUrl: https://avatars.githubusercontent.com/u/10519440?u=2843b3303282bff8b212dcd4d9d6689452e4470c&v=4 - url: https://github.com/iudeen + avatarUrl: https://avatars.githubusercontent.com/u/87550035?u=16f9255804161c6ff3c8b7ef69848f0126bcd405&v=4 + url: https://github.com/odiseo0 - login: sh0nk count: 13 avatarUrl: https://avatars.githubusercontent.com/u/6478810?u=af15d724875cec682ed8088a86d36b2798f981c0&v=4 @@ -436,10 +440,6 @@ top_reviewers: count: 12 avatarUrl: https://avatars.githubusercontent.com/u/31848542?u=efb5b45b55584450507834f279ce48d4d64dea2f&v=4 url: https://github.com/RunningIkkyu -- login: odiseo0 - count: 12 - avatarUrl: https://avatars.githubusercontent.com/u/87550035?u=ab724eae71c3fe1cf81e8dc76e73415da926ef7d&v=4 - url: https://github.com/odiseo0 - login: LorhanSohaky count: 11 avatarUrl: https://avatars.githubusercontent.com/u/16273730?u=095b66f243a2cd6a0aadba9a095009f8aaf18393&v=4 @@ -462,7 +462,7 @@ top_reviewers: url: https://github.com/maoyibo - login: ComicShrimp count: 10 - avatarUrl: https://avatars.githubusercontent.com/u/43503750?u=b3e4d9a14d9a65d429ce62c566aef73178b7111d&v=4 + avatarUrl: https://avatars.githubusercontent.com/u/43503750?u=f440bc9062afb3c43b9b9c6cdfdcfe31d58699ef&v=4 url: https://github.com/ComicShrimp - login: graingert count: 9 From 876ea7978fd5a8413a1cdc0c655a1894c0d0c5a7 Mon Sep 17 00:00:00 2001 From: github-actions Date: Thu, 3 Nov 2022 11:45:26 +0000 Subject: [PATCH 02/97] =?UTF-8?q?=F0=9F=93=9D=20Update=20release=20notes?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docs/en/docs/release-notes.md | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/en/docs/release-notes.md b/docs/en/docs/release-notes.md index c6911566aa..5d39e04833 100644 --- a/docs/en/docs/release-notes.md +++ b/docs/en/docs/release-notes.md @@ -2,6 +2,7 @@ ## Latest Changes +* 👥 Update FastAPI People. PR [#5571](https://github.com/tiangolo/fastapi/pull/5571) by [@github-actions[bot]](https://github.com/apps/github-actions). ## 0.85.2 From 058cb6e88e56a48708e65d0b1b210201fb96eb2a Mon Sep 17 00:00:00 2001 From: jaystone776 Date: Thu, 3 Nov 2022 19:50:48 +0800 Subject: [PATCH 03/97] =?UTF-8?q?=F0=9F=8C=90=20Update=20Chinese=20transla?= =?UTF-8?q?tion=20for=20`docs/tutorial/security/oauth2-jwt.md`=20(#3846)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Sebastián Ramírez --- docs/zh/docs/tutorial/security/oauth2-jwt.md | 193 ++++++++++--------- 1 file changed, 99 insertions(+), 94 deletions(-) diff --git a/docs/zh/docs/tutorial/security/oauth2-jwt.md b/docs/zh/docs/tutorial/security/oauth2-jwt.md index 82ef9b897e..054198545e 100644 --- a/docs/zh/docs/tutorial/security/oauth2-jwt.md +++ b/docs/zh/docs/tutorial/security/oauth2-jwt.md @@ -1,34 +1,34 @@ -# 使用(哈希)密码和 JWT Bearer 令牌的 OAuth2 +# OAuth2 实现密码哈希与 Bearer JWT 令牌验证 -既然我们已经有了所有的安全流程,就让我们来使用 JWT 令牌和安全哈希密码让应用程序真正地安全吧。 +至此,我们已经编写了所有安全流,本章学习如何使用 JWT 令牌(Token)和安全密码哈希(Hash)实现真正的安全机制。 -你可以在应用程序中真正地使用这些代码,在数据库中保存密码哈希值,等等。 +本章的示例代码真正实现了在应用的数据库中保存哈希密码等功能。 -我们将从上一章结束的位置开始,然后对示例进行扩充。 +接下来,我们紧接上一章,继续完善安全机制。 -## 关于 JWT +## JWT 简介 -JWT 表示 「JSON Web Tokens」。 +JWT 即**JSON 网络令牌**(JSON Web Tokens)。 -它是一个将 JSON 对象编码为密集且没有空格的长字符串的标准。字符串看起来像这样: +JWT 是一种将 JSON 对象编码为没有空格,且难以理解的长字符串的标准。JWT 的内容如下所示: ``` eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c ``` -它没有被加密,因此任何人都可以从字符串内容中还原数据。 +JWT 字符串没有加密,任何人都能用它恢复原始信息。 -但它经过了签名。因此,当你收到一个由你发出的令牌时,可以校验令牌是否真的由你发出。 +但 JWT 使用了签名机制。接受令牌时,可以用签名校验令牌。 -通过这种方式,你可以创建一个有效期为 1 周的令牌。然后当用户第二天使用令牌重新访问时,你知道该用户仍然处于登入状态。 +使用 JWT 创建有效期为一周的令牌。第二天,用户持令牌再次访问时,仍为登录状态。 -一周后令牌将会过期,用户将不会通过认证,必须再次登录才能获得一个新令牌。而且如果用户(或第三方)试图修改令牌以篡改过期时间,你将因为签名不匹配而能够发觉。 +令牌于一周后过期,届时,用户身份验证就会失败。只有再次登录,才能获得新的令牌。如果用户(或第三方)篡改令牌的过期时间,因为签名不匹配会导致身份验证失败。 -如果你想上手体验 JWT 令牌并了解其工作方式,可访问 https://jwt.io。 +如需深入了解 JWT 令牌,了解它的工作方式,请参阅 https://jwt.io。 ## 安装 `python-jose` -我们需要安装 `python-jose` 以在 Python 中生成和校验 JWT 令牌: +安装 `python-jose`,在 Python 中生成和校验 JWT 令牌:
@@ -40,38 +40,39 @@ $ pip install python-jose[cryptography]
-Python-jose 需要一个额外的加密后端。 +Python-jose 需要安装配套的加密后端。 -这里我们使用的是推荐的后端:pyca/cryptography。 +本教程推荐的后端是:pyca/cryptography。 -!!! tip - 本教程曾经使用过 PyJWT。 +!!! tip "提示" - 但是后来更新为使用 Python-jose,因为它提供了 PyJWT 的所有功能,以及之后与其他工具进行集成时你可能需要的一些其他功能。 + 本教程以前使用 PyJWT。 -## 哈希密码 + 但后来换成了 Python-jose,因为 Python-jose 支持 PyJWT 的所有功能,还支持与其它工具集成时可能会用到的一些其它功能。 -「哈希」的意思是:将某些内容(在本例中为密码)转换为看起来像乱码的字节序列(只是一个字符串)。 +## 密码哈希 -每次你传入完全相同的内容(完全相同的密码)时,你都会得到完全相同的乱码。 +**哈希**是指把特定内容(本例中为密码)转换为乱码形式的字节序列(其实就是字符串)。 -但是你不能从乱码转换回密码。 +每次传入完全相同的内容时(比如,完全相同的密码),返回的都是完全相同的乱码。 -### 为什么使用哈希密码 +但这个乱码无法转换回传入的密码。 -如果你的数据库被盗,小偷将无法获得用户的明文密码,只能拿到哈希值。 +### 为什么使用密码哈希 -因此,小偷将无法尝试在另一个系统中使用这些相同的密码(由于许多用户在任何地方都使用相同的密码,因此这很危险)。 +原因很简单,假如数据库被盗,窃贼无法获取用户的明文密码,得到的只是哈希值。 + +这样一来,窃贼就无法在其它应用中使用窃取的密码,要知道,很多用户在所有系统中都使用相同的密码,风险超大)。 ## 安装 `passlib` -PassLib 是一个用于处理哈希密码的很棒的 Python 包。 +Passlib 是处理密码哈希的 Python 包。 -它支持许多安全哈希算法以及配合算法使用的实用程序。 +它支持很多安全哈希算法及配套工具。 -推荐的算法是 「Bcrypt」。 +本教程推荐的算法是 **Bcrypt**。 -因此,安装附带 Bcrypt 的 PassLib: +因此,请先安装附带 Bcrypt 的 PassLib:
@@ -83,46 +84,49 @@ $ pip install passlib[bcrypt]
-!!! tip - 使用 `passlib`,你甚至可以将其配置为能够读取 Django,Flask 的安全扩展或许多其他工具创建的密码。 +!!! tip "提示" - 因此,你将能够,举个例子,将数据库中来自 Django 应用的数据共享给一个 FastAPI 应用。或者使用同一数据库但逐渐将应用从 Django 迁移到 FastAPI。 + `passlib` 甚至可以读取 Django、Flask 的安全插件等工具创建的密码。 - 而你的用户将能够同时从 Django 应用或 FastAPI 应用登录。 + 例如,把 Django 应用的数据共享给 FastAPI 应用的数据库。或利用同一个数据库,可以逐步把应用从 Django 迁移到 FastAPI。 -## 哈希并校验密码 + 并且,用户可以同时从 Django 应用或 FastAPI 应用登录。 -从 `passlib` 导入我们需要的工具。 +## 密码哈希与校验 -创建一个 PassLib 「上下文」。这将用于哈希和校验密码。 +从 `passlib` 导入所需工具。 -!!! tip - PassLib 上下文还具有使用不同哈希算法的功能,包括仅允许用于校验的已弃用的旧算法等。 +创建用于密码哈希和身份校验的 PassLib **上下文**。 - 例如,你可以使用它来读取和校验由另一个系统(例如Django)生成的密码,但是使用其他算法例如 Bcrypt 生成新的密码哈希值。 +!!! tip "提示" - 并同时兼容所有的这些功能。 + PassLib 上下文还支持使用不同哈希算法的功能,包括只能校验的已弃用旧算法等。 -创建一个工具函数以哈希来自用户的密码。 + 例如,用它读取和校验其它系统(如 Django)生成的密码,但要使用其它算法,如 Bcrypt,生成新的哈希密码。 -然后创建另一个工具函数,用于校验接收的密码是否与存储的哈希值匹配。 + 同时,这些功能都是兼容的。 -再创建另一个工具函数用于认证并返回用户。 +接下来,创建三个工具函数,其中一个函数用于哈希用户的密码。 + +第一个函数用于校验接收的密码是否匹配存储的哈希值。 + +第三个函数用于身份验证,并返回用户。 ```Python hl_lines="7 48 55-56 59-60 69-75" {!../../../docs_src/security/tutorial004.py!} ``` -!!! note - 如果你查看新的(伪)数据库 `fake_users_db`,你将看到哈希后的密码现在的样子:`"$2b$12$EixZaYVK1fsbw1ZfbX3OXePaWxn96p36WQoeG6Lruj3vjPGga31lW"`。 +!!! note "笔记" + + 查看新的(伪)数据库 `fake_users_db`,就能看到哈希后的密码:`"$2b$12$EixZaYVK1fsbw1ZfbX3OXePaWxn96p36WQoeG6Lruj3vjPGga31lW"`。 ## 处理 JWT 令牌 导入已安装的模块。 -创建一个随机密钥,该密钥将用于对 JWT 令牌进行签名。 +创建用于 JWT 令牌签名的随机密钥。 -要生成一个安全的随机密钥,可使用以下命令: +使用以下命令,生成安全的随机密钥:
@@ -134,15 +138,15 @@ $ openssl rand -hex 32
-然后将输出复制到变量 「SECRET_KEY」 中(不要使用示例中的这个)。 +然后,把生成的密钥复制到变量**SECRET_KEY**,注意,不要使用本例所示的密钥。 -创建用于设定 JWT 令牌签名算法的变量 「ALGORITHM」,并将其设置为 `"HS256"`。 +创建指定 JWT 令牌签名算法的变量 **ALGORITHM**,本例中的值为 `"HS256"`。 -创建一个设置令牌过期时间的变量。 +创建设置令牌过期时间的变量。 -定义一个将在令牌端点中用于响应的 Pydantic 模型。 +定义令牌端点响应的 Pydantic 模型。 -创建一个生成新的访问令牌的工具函数。 +创建生成新的访问令牌的工具函数。 ```Python hl_lines="6 12-14 28-30 78-86" {!../../../docs_src/security/tutorial004.py!} @@ -150,11 +154,11 @@ $ openssl rand -hex 32 ## 更新依赖项 -更新 `get_current_user` 以接收与之前相同的令牌,但这次使用的是 JWT 令牌。 +更新 `get_current_user` 以接收与之前相同的令牌,但这里用的是 JWT 令牌。 -解码接收到的令牌,对其进行校验,然后返回当前用户。 +解码并校验接收到的令牌,然后,返回当前用户。 -如果令牌无效,立即返回一个 HTTP 错误。 +如果令牌无效,则直接返回 HTTP 错误。 ```Python hl_lines="89-106" {!../../../docs_src/security/tutorial004.py!} @@ -162,57 +166,57 @@ $ openssl rand -hex 32 ## 更新 `/token` *路径操作* -使用令牌的过期时间创建一个 `timedelta` 对象。 +用令牌过期时间创建 `timedelta` 对象。 -创建一个真实的 JWT 访问令牌并返回它。 +创建并返回真正的 JWT 访问令牌。 ```Python hl_lines="115-128" {!../../../docs_src/security/tutorial004.py!} ``` -### 关于 JWT 「主题」 `sub` 的技术细节 +### JWT `sub` 的技术细节 -JWT 的规范中提到有一个 `sub` 键,值为该令牌的主题。 +JWT 规范还包括 `sub` 键,值是令牌的主题。 -使用它并不是必须的,但这是你放置用户标识的地方,所以我们在示例中使用了它。 +该键是可选的,但要把用户标识放在这个键里,所以本例使用了该键。 -除了识别用户并允许他们直接在你的 API 上执行操作之外,JWT 还可以用于其他事情。 +除了识别用户与许可用户在 API 上直接执行操作之外,JWT 还可能用于其它事情。 -例如,你可以识别一个 「汽车」 或 「博客文章」。 +例如,识别**汽车**或**博客**。 -然后你可以添加关于该实体的权限,比如「驾驶」(汽车)或「编辑」(博客)。 +接着,为实体添加权限,比如**驾驶**(汽车)或**编辑**(博客)。 -然后,你可以将 JWT 令牌交给用户(或机器人),他们可以使用它来执行这些操作(驾驶汽车,或编辑博客文章),甚至不需要有一个账户,只需使用你的 API 为其生成的 JWT 令牌。 +然后,把 JWT 令牌交给用户(或机器人),他们就可以执行驾驶汽车,或编辑博客等操作。无需注册账户,只要有 API 生成的 JWT 令牌就可以。 -使用这样的思路,JWT 可以用于更复杂的场景。 +同理,JWT 可以用于更复杂的场景。 -在这些情况下,几个实体可能有相同的 ID,比如说 `foo`(一个用户 `foo`,一辆车 `foo`,一篇博客文章 `foo`)。 +在这些情况下,多个实体的 ID 可能是相同的,以 ID `foo` 为例,用户的 ID 是 `foo`,车的 ID 是 `foo`,博客的 ID 也是 `foo`。 -因此,为了避免 ID 冲突,当为用户创建 JWT 令牌时,你可以在 `sub` 键的值前加上前缀,例如 `username:`。所以,在这个例子中,`sub` 的值可以是:`username:johndoe`。 +为了避免 ID 冲突,在给用户创建 JWT 令牌时,可以为 `sub` 键的值加上前缀,例如 `username:`。因此,在本例中,`sub` 的值可以是:`username:johndoe`。 -要记住的重点是,`sub` 键在整个应用程序中应该有一个唯一的标识符,而且应该是一个字符串。 +注意,划重点,`sub` 键在整个应用中应该只有一个唯一的标识符,而且应该是字符串。 -## 检查效果 +## 检查 运行服务器并访问文档: http://127.0.0.1:8000/docs。 -你会看到如下用户界面: +可以看到如下用户界面: -像以前一样对应用程序进行认证。 +用与上一章同样的方式实现应用授权。 使用如下凭证: -用户名: `johndoe` -密码: `secret` +用户名: `johndoe` 密码: `secret` -!!! check - 请注意,代码中没有任何地方记录了明文密码 「`secret`」,我们只保存了其哈希值。 +!!! check "检查" + + 注意,代码中没有明文密码**`secret`**,只保存了它的哈希值。 -访问 `/users/me/` 端点,你将获得如下响应: +调用 `/users/me/` 端点,收到下面的响应: ```JSON { @@ -225,41 +229,42 @@ JWT 的规范中提到有一个 `sub` 键,值为该令牌的主题。 -如果你打开开发者工具,将看到数据是如何发送的并且其中仅包含了令牌,只有在第一个请求中发送了密码以校验用户身份并获取该访问令牌,但之后都不会再发送密码: +打开浏览器的开发者工具,查看数据是怎么发送的,而且数据里只包含了令牌,只有验证用户的第一个请求才发送密码,并获取访问令牌,但之后不会再发送密码: -!!! note - 注意请求中的 `Authorization` 首部,其值以 `Bearer` 开头。 +!!! note "笔记" -## 使用 `scopes` 的进阶用法 + 注意,请求中 `Authorization` 响应头的值以 `Bearer` 开头。 -OAuth2 具有「作用域」的概念。 +## `scopes` 高级用法 -你可以使用它们向 JWT 令牌添加一组特定的权限。 +OAuth2 支持**`scopes`**(作用域)。 -然后,你可以将此令牌直接提供给用户或第三方,使其在一些限制下与你的 API 进行交互。 +**`scopes`**为 JWT 令牌添加指定权限。 -你可以在之后的**进阶用户指南**中了解如何使用它们以及如何将它们集成到 **FastAPI** 中。 +让持有令牌的用户或第三方在指定限制条件下与 API 交互。 -## 总结 +**高级用户指南**中将介绍如何使用 `scopes`,及如何把 `scopes` 集成至 **FastAPI**。 -通过目前你所看到的,你可以使用像 OAuth2 和 JWT 这样的标准来构建一个安全的 **FastAPI** 应用程序。 +## 小结 -在几乎所有的框架中,处理安全性问题都很容易成为一个相当复杂的话题。 +至此,您可以使用 OAuth2 和 JWT 等标准配置安全的 **FastAPI** 应用。 -许多高度简化了安全流程的软件包不得不在数据模型、数据库和可用功能上做出很多妥协。而这些过于简化流程的软件包中,有些其实隐含了安全漏洞。 +几乎在所有框架中,处理安全问题很快都会变得非常复杂。 + +有些包为了简化安全流,不得不在数据模型、数据库和功能上做出妥协。而有些过于简化的软件包其实存在了安全隐患。 --- -**FastAPI** 不对任何数据库、数据模型或工具做任何妥协。 +**FastAPI** 不向任何数据库、数据模型或工具做妥协。 -它给了你所有的灵活性来选择最适合你项目的前者。 +开发者可以灵活选择最适合项目的安全机制。 -你可以直接使用许多维护良好且使用广泛的包,如 `passlib` 和 `python-jose`,因为 **FastAPI** 不需要任何复杂的机制来集成外部包。 +还可以直接使用 `passlib` 和 `python-jose` 等维护良好、使用广泛的包,这是因为 **FastAPI** 不需要任何复杂机制,就能集成外部的包。 -但它为你提供了一些工具,在不影响灵活性、健壮性和安全性的前提下,尽可能地简化这个过程。 +而且,**FastAPI** 还提供了一些工具,在不影响灵活、稳定和安全的前提下,尽可能地简化安全机制。 -而且你可以用相对简单的方式使用和实现安全、标准的协议,比如 OAuth2。 +**FastAPI** 还支持以相对简单的方式,使用 OAuth2 等安全、标准的协议。 -你可以在**进阶用户指南**中了解更多关于如何使用 OAuth2 「作用域」的信息,以实现更精细的权限系统,并同样遵循这些标准。带有作用域的 OAuth2 是很多大的认证提供商使用的机制,比如 Facebook、Google、GitHub、微软、Twitter 等,授权第三方应用代表用户与他们的 API 进行交互。 +**高级用户指南**中详细介绍了 OAuth2**`scopes`**的内容,遵循同样的标准,实现更精密的权限系统。OAuth2 的作用域是脸书、谷歌、GitHub、微软、推特等第三方身份验证应用使用的机制,让用户授权第三方应用与 API 交互。 From c9308cf07071b2fa96430748292bded1ae6d9d51 Mon Sep 17 00:00:00 2001 From: github-actions Date: Thu, 3 Nov 2022 11:51:26 +0000 Subject: [PATCH 04/97] =?UTF-8?q?=F0=9F=93=9D=20Update=20release=20notes?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docs/en/docs/release-notes.md | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/en/docs/release-notes.md b/docs/en/docs/release-notes.md index 5d39e04833..e557f8bca0 100644 --- a/docs/en/docs/release-notes.md +++ b/docs/en/docs/release-notes.md @@ -2,6 +2,7 @@ ## Latest Changes +* 🌐 Update Chinese translation for `docs/tutorial/security/oauth2-jwt.md`. PR [#3846](https://github.com/tiangolo/fastapi/pull/3846) by [@jaystone776](https://github.com/jaystone776). * 👥 Update FastAPI People. PR [#5571](https://github.com/tiangolo/fastapi/pull/5571) by [@github-actions[bot]](https://github.com/apps/github-actions). ## 0.85.2 From 9a85535e7fa278682536ceb28dc4fb239db16bdd Mon Sep 17 00:00:00 2001 From: Vladislav Kramorenko <85196001+Xewus@users.noreply.github.com> Date: Thu, 3 Nov 2022 14:51:44 +0300 Subject: [PATCH 05/97] =?UTF-8?q?=F0=9F=8C=90=20Add=20Russian=20translatio?= =?UTF-8?q?n=20for=20`docs/ru/docs/deployment/index.md`=20(#5336)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Sebastián Ramírez --- docs/ru/docs/deployment/index.md | 21 +++++++++++++++++++++ docs/ru/mkdocs.yml | 4 +++- 2 files changed, 24 insertions(+), 1 deletion(-) create mode 100644 docs/ru/docs/deployment/index.md diff --git a/docs/ru/docs/deployment/index.md b/docs/ru/docs/deployment/index.md new file mode 100644 index 0000000000..4dc4e482ed --- /dev/null +++ b/docs/ru/docs/deployment/index.md @@ -0,0 +1,21 @@ +# Развёртывание - Введение + +Развернуть приложение **FastAPI** довольно просто. + +## Да что такое это ваше - "развёртывание"?! + +Термин **развёртывание** (приложения) означает выполнение необходимых шагов, чтобы сделать приложение **доступным для пользователей**. + +Обычно **веб-приложения** размещают на удалённом компьютере с серверной программой, которая обеспечивает хорошую производительность, стабильность и т. д., Чтобы ваши пользователи могли эффективно, беспрерывно и беспроблемно обращаться к приложению. + +Это отличется от **разработки**, когда вы постоянно меняете код, делаете в нём намеренные ошибки и исправляете их, останавливаете и перезапускаете сервер разработки и т. д. + +## Стратегии развёртывания + +В зависимости от вашего конкретного случая, есть несколько способов сделать это. + +Вы можете **развернуть сервер** самостоятельно, используя различные инструменты. Например, можно использовать **облачный сервис**, который выполнит часть работы за вас. Также возможны и другие варианты. + +В этом блоке я покажу вам некоторые из основных концепций, которые вы, вероятно, должны иметь в виду при развертывании приложения **FastAPI** (хотя большинство из них применимо к любому другому типу веб-приложений). + +В последующих разделах вы узнаете больше деталей и методов, необходимых для этого. ✨ diff --git a/docs/ru/mkdocs.yml b/docs/ru/mkdocs.yml index 381775ac6d..f35ee968c9 100644 --- a/docs/ru/mkdocs.yml +++ b/docs/ru/mkdocs.yml @@ -59,13 +59,15 @@ nav: - uk: /uk/ - zh: /zh/ - features.md +- fastapi-people.md - python-types.md - Учебник - руководство пользователя: - tutorial/background-tasks.md -- external-links.md - async.md - Развёртывание: + - deployment/index.md - deployment/versions.md +- external-links.md markdown_extensions: - toc: permalink: true From ed9425ef5049910251dd2302b9dd3095cefe1b1c Mon Sep 17 00:00:00 2001 From: github-actions Date: Thu, 3 Nov 2022 11:52:17 +0000 Subject: [PATCH 06/97] =?UTF-8?q?=F0=9F=93=9D=20Update=20release=20notes?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docs/en/docs/release-notes.md | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/en/docs/release-notes.md b/docs/en/docs/release-notes.md index e557f8bca0..53eb4a8cb3 100644 --- a/docs/en/docs/release-notes.md +++ b/docs/en/docs/release-notes.md @@ -2,6 +2,7 @@ ## Latest Changes +* 🌐 Add Russian translation for `docs/ru/docs/deployment/index.md`. PR [#5336](https://github.com/tiangolo/fastapi/pull/5336) by [@Xewus](https://github.com/Xewus). * 🌐 Update Chinese translation for `docs/tutorial/security/oauth2-jwt.md`. PR [#3846](https://github.com/tiangolo/fastapi/pull/3846) by [@jaystone776](https://github.com/jaystone776). * 👥 Update FastAPI People. PR [#5571](https://github.com/tiangolo/fastapi/pull/5571) by [@github-actions[bot]](https://github.com/apps/github-actions). From ac9f56ea5ecc738eabd9282feae4679852155669 Mon Sep 17 00:00:00 2001 From: Adrian Garcia Badaracco <1755071+adriangb@users.noreply.github.com> Date: Thu, 3 Nov 2022 07:06:52 -0500 Subject: [PATCH 07/97] =?UTF-8?q?=F0=9F=90=9B=20Close=20FormData=20(upload?= =?UTF-8?q?ed=20files)=20after=20the=20request=20is=20done=20(#5465)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Sebastián Ramírez --- fastapi/routing.py | 4 ++++ tests/test_datastructures.py | 28 +++++++++++++++++++++++++++- 2 files changed, 31 insertions(+), 1 deletion(-) diff --git a/fastapi/routing.py b/fastapi/routing.py index 7caf018b55..8c0bec5e61 100644 --- a/fastapi/routing.py +++ b/fastapi/routing.py @@ -3,6 +3,7 @@ import dataclasses import email.message import inspect import json +from contextlib import AsyncExitStack from enum import Enum, IntEnum from typing import ( Any, @@ -190,6 +191,9 @@ def get_request_handler( if body_field: if is_body_form: body = await request.form() + stack = request.scope.get("fastapi_astack") + assert isinstance(stack, AsyncExitStack) + stack.push_async_callback(body.close) else: body_bytes = await request.body() if body_bytes: diff --git a/tests/test_datastructures.py b/tests/test_datastructures.py index 43f1a116cb..2e6217d34e 100644 --- a/tests/test_datastructures.py +++ b/tests/test_datastructures.py @@ -1,6 +1,10 @@ +from pathlib import Path +from typing import List + import pytest -from fastapi import UploadFile +from fastapi import FastAPI, UploadFile from fastapi.datastructures import Default +from fastapi.testclient import TestClient def test_upload_file_invalid(): @@ -20,3 +24,25 @@ def test_default_placeholder_bool(): placeholder_b = Default("") assert placeholder_a assert not placeholder_b + + +def test_upload_file_is_closed(tmp_path: Path): + path = tmp_path / "test.txt" + path.write_bytes(b"") + app = FastAPI() + + testing_file_store: List[UploadFile] = [] + + @app.post("/uploadfile/") + def create_upload_file(file: UploadFile): + testing_file_store.append(file) + return {"filename": file.filename} + + client = TestClient(app) + with path.open("rb") as file: + response = client.post("/uploadfile/", files={"file": file}) + assert response.status_code == 200, response.text + assert response.json() == {"filename": "test.txt"} + + assert testing_file_store + assert testing_file_store[0].file.closed From 54aa27ca0726ea9954e2ad0e3cc4cca332c5a8d2 Mon Sep 17 00:00:00 2001 From: github-actions Date: Thu, 3 Nov 2022 12:07:29 +0000 Subject: [PATCH 08/97] =?UTF-8?q?=F0=9F=93=9D=20Update=20release=20notes?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docs/en/docs/release-notes.md | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/en/docs/release-notes.md b/docs/en/docs/release-notes.md index 53eb4a8cb3..991dfad55f 100644 --- a/docs/en/docs/release-notes.md +++ b/docs/en/docs/release-notes.md @@ -2,6 +2,7 @@ ## Latest Changes +* 🐛 Close FormData (uploaded files) after the request is done. PR [#5465](https://github.com/tiangolo/fastapi/pull/5465) by [@adriangb](https://github.com/adriangb). * 🌐 Add Russian translation for `docs/ru/docs/deployment/index.md`. PR [#5336](https://github.com/tiangolo/fastapi/pull/5336) by [@Xewus](https://github.com/Xewus). * 🌐 Update Chinese translation for `docs/tutorial/security/oauth2-jwt.md`. PR [#3846](https://github.com/tiangolo/fastapi/pull/3846) by [@jaystone776](https://github.com/jaystone776). * 👥 Update FastAPI People. PR [#5571](https://github.com/tiangolo/fastapi/pull/5571) by [@github-actions[bot]](https://github.com/apps/github-actions). From a0c677ef0d43b8dde652ddba687cc89a14805f5d Mon Sep 17 00:00:00 2001 From: ZHCai Date: Thu, 3 Nov 2022 20:07:49 +0800 Subject: [PATCH 09/97] =?UTF-8?q?=F0=9F=8C=90=20Update=20wording=20in=20Ch?= =?UTF-8?q?inese=20translation=20for=20`docs/zh/docs/python-types.md`=20(#?= =?UTF-8?q?5416)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docs/zh/docs/python-types.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/zh/docs/python-types.md b/docs/zh/docs/python-types.md index 67a1612f00..6cdb4b5883 100644 --- a/docs/zh/docs/python-types.md +++ b/docs/zh/docs/python-types.md @@ -194,7 +194,7 @@ John Doe 这表示: -* 变量 `items_t` 是一个 `tuple`,其中的每个元素都是 `int` 类型。 +* 变量 `items_t` 是一个 `tuple`,其中的前两个元素都是 `int` 类型, 最后一个元素是 `str` 类型。 * 变量 `items_s` 是一个 `set`,其中的每个元素都是 `bytes` 类型。 #### 字典 From 4cf90758091db36b10991f9192f3c67ecd4b4c51 Mon Sep 17 00:00:00 2001 From: github-actions Date: Thu, 3 Nov 2022 12:08:23 +0000 Subject: [PATCH 10/97] =?UTF-8?q?=F0=9F=93=9D=20Update=20release=20notes?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docs/en/docs/release-notes.md | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/en/docs/release-notes.md b/docs/en/docs/release-notes.md index 991dfad55f..c95550039a 100644 --- a/docs/en/docs/release-notes.md +++ b/docs/en/docs/release-notes.md @@ -2,6 +2,7 @@ ## Latest Changes +* 🌐 Update wording in Chinese translation for `docs/zh/docs/python-types.md`. PR [#5416](https://github.com/tiangolo/fastapi/pull/5416) by [@supercaizehua](https://github.com/supercaizehua). * 🐛 Close FormData (uploaded files) after the request is done. PR [#5465](https://github.com/tiangolo/fastapi/pull/5465) by [@adriangb](https://github.com/adriangb). * 🌐 Add Russian translation for `docs/ru/docs/deployment/index.md`. PR [#5336](https://github.com/tiangolo/fastapi/pull/5336) by [@Xewus](https://github.com/Xewus). * 🌐 Update Chinese translation for `docs/tutorial/security/oauth2-jwt.md`. PR [#3846](https://github.com/tiangolo/fastapi/pull/3846) by [@jaystone776](https://github.com/jaystone776). From d62f5c1b288dbc098a718f94f90784c11c1e7c24 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebasti=C3=A1n=20Ram=C3=ADrez?= Date: Thu, 3 Nov 2022 13:26:48 +0100 Subject: [PATCH 11/97] =?UTF-8?q?=E2=9C=85=20Enable=20tests=20for=20Python?= =?UTF-8?q?=203.11=20(#4881)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .github/workflows/test.yml | 2 +- pyproject.toml | 5 +++++ 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 3e6225db33..9e492c1ada 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -12,7 +12,7 @@ jobs: runs-on: ubuntu-latest strategy: matrix: - python-version: ["3.7", "3.8", "3.9", "3.10"] + python-version: ["3.7", "3.8", "3.9", "3.10", "3.11"] fail-fast: false steps: diff --git a/pyproject.toml b/pyproject.toml index 543ba15c1d..ad088ce335 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -136,6 +136,11 @@ filterwarnings = [ # TODO: needed by asyncio in Python 3.9.7 https://bugs.python.org/issue45097, try to remove on 3.9.8 'ignore:The loop argument is deprecated since Python 3\.8, and scheduled for removal in Python 3\.10:DeprecationWarning:asyncio', 'ignore:starlette.middleware.wsgi is deprecated and will be removed in a future release\..*:DeprecationWarning:starlette', + # TODO: remove after upgrading HTTPX to a version newer than 0.23.0 + # Including PR: https://github.com/encode/httpx/pull/2309 + "ignore:'cgi' is deprecated:DeprecationWarning", + # For passlib + "ignore:'crypt' is deprecated and slated for removal in Python 3.13:DeprecationWarning", # see https://trio.readthedocs.io/en/stable/history.html#trio-0-22-0-2022-09-28 "ignore:You seem to already have a custom.*:RuntimeWarning:trio", "ignore::trio.TrioDeprecationWarning", From cf730518bc64cd8377e867942c1446b70ffca012 Mon Sep 17 00:00:00 2001 From: github-actions Date: Thu, 3 Nov 2022 12:27:24 +0000 Subject: [PATCH 12/97] =?UTF-8?q?=F0=9F=93=9D=20Update=20release=20notes?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docs/en/docs/release-notes.md | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/en/docs/release-notes.md b/docs/en/docs/release-notes.md index c95550039a..48992f0783 100644 --- a/docs/en/docs/release-notes.md +++ b/docs/en/docs/release-notes.md @@ -2,6 +2,7 @@ ## Latest Changes +* ✅ Enable tests for Python 3.11. PR [#4881](https://github.com/tiangolo/fastapi/pull/4881) by [@tiangolo](https://github.com/tiangolo). * 🌐 Update wording in Chinese translation for `docs/zh/docs/python-types.md`. PR [#5416](https://github.com/tiangolo/fastapi/pull/5416) by [@supercaizehua](https://github.com/supercaizehua). * 🐛 Close FormData (uploaded files) after the request is done. PR [#5465](https://github.com/tiangolo/fastapi/pull/5465) by [@adriangb](https://github.com/adriangb). * 🌐 Add Russian translation for `docs/ru/docs/deployment/index.md`. PR [#5336](https://github.com/tiangolo/fastapi/pull/5336) by [@Xewus](https://github.com/Xewus). From be3e29fb3cdc1c7858dac0d54ad67edd2ac30d8c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebasti=C3=A1n=20Ram=C3=ADrez?= Date: Thu, 3 Nov 2022 21:00:29 +0100 Subject: [PATCH 13/97] =?UTF-8?q?=F0=9F=91=B7=20Switch=20from=20Codecov=20?= =?UTF-8?q?to=20Smokeshow=20plus=20pytest-cov=20to=20pure=20coverage=20for?= =?UTF-8?q?=20internal=20tests=20(#5583)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .github/workflows/smokeshow.yml | 35 +++++++++++++++++++++++++++++ .github/workflows/test.yml | 40 +++++++++++++++++++++++++++++++-- pyproject.toml | 11 ++++++++- scripts/test-cov-html.sh | 5 ++++- scripts/test.sh | 2 +- 5 files changed, 88 insertions(+), 5 deletions(-) create mode 100644 .github/workflows/smokeshow.yml diff --git a/.github/workflows/smokeshow.yml b/.github/workflows/smokeshow.yml new file mode 100644 index 0000000000..606633a99d --- /dev/null +++ b/.github/workflows/smokeshow.yml @@ -0,0 +1,35 @@ +name: Smokeshow + +on: + workflow_run: + workflows: [Test] + types: [completed] + +permissions: + statuses: write + +jobs: + smokeshow: + if: ${{ github.event.workflow_run.conclusion == 'success' }} + runs-on: ubuntu-latest + + steps: + - uses: actions/setup-python@v4 + with: + python-version: '3.9' + + - run: pip install smokeshow + + - uses: dawidd6/action-download-artifact@v2 + with: + workflow: test.yml + commit: ${{ github.event.workflow_run.head_sha }} + + - run: smokeshow upload coverage-html + env: + SMOKESHOW_GITHUB_STATUS_DESCRIPTION: Coverage {coverage-percentage} + SMOKESHOW_GITHUB_COVERAGE_THRESHOLD: 100 + SMOKESHOW_GITHUB_CONTEXT: coverage + SMOKESHOW_GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + SMOKESHOW_GITHUB_PR_HEAD_SHA: ${{ github.event.workflow_run.head_sha }} + SMOKESHOW_AUTH_KEY: ${{ secrets.SMOKESHOW_AUTH_KEY }} diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 9e492c1ada..7f87be700b 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -31,7 +31,43 @@ jobs: run: pip install -e .[all,dev,doc,test] - name: Lint run: bash scripts/lint.sh + - run: mkdir coverage - name: Test run: bash scripts/test.sh - - name: Upload coverage - uses: codecov/codecov-action@v3 + env: + COVERAGE_FILE: coverage/.coverage.${{ runner.os }}-py${{ matrix.python-version }} + CONTEXT: ${{ runner.os }}-py${{ matrix.python-version }} + - name: Store coverage files + uses: actions/upload-artifact@v3 + with: + name: coverage + path: coverage + coverage-combine: + needs: [test] + runs-on: ubuntu-latest + + steps: + - uses: actions/checkout@v3 + + - uses: actions/setup-python@v4 + with: + python-version: '3.8' + + - name: Get coverage files + uses: actions/download-artifact@v3 + with: + name: coverage + path: coverage + + - run: pip install coverage[toml] + + - run: ls -la coverage + - run: coverage combine coverage + - run: coverage report + - run: coverage html --show-contexts --title "Coverage for ${{ github.sha }}" + + - name: Store coverage HTML + uses: actions/upload-artifact@v3 + with: + name: coverage-html + path: htmlcov diff --git a/pyproject.toml b/pyproject.toml index ad088ce335..d7b848502c 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -50,7 +50,7 @@ Documentation = "https://fastapi.tiangolo.com/" [project.optional-dependencies] test = [ "pytest >=7.1.3,<8.0.0", - "pytest-cov >=2.12.0,<5.0.0", + "coverage[toml] >= 6.5.0,<7.0", "mypy ==0.982", "flake8 >=3.8.3,<6.0.0", "black == 22.8.0", @@ -147,3 +147,12 @@ filterwarnings = [ # TODO remove pytest-cov 'ignore::pytest.PytestDeprecationWarning:pytest_cov', ] + +[tool.coverage.run] +parallel = true +source = [ + "docs_src", + "tests", + "fastapi" +] +context = '${CONTEXT}' diff --git a/scripts/test-cov-html.sh b/scripts/test-cov-html.sh index 7957277fc3..d1bdfced2a 100755 --- a/scripts/test-cov-html.sh +++ b/scripts/test-cov-html.sh @@ -3,4 +3,7 @@ set -e set -x -bash scripts/test.sh --cov-report=html ${@} +bash scripts/test.sh ${@} +coverage combine +coverage report --show-missing +coverage html diff --git a/scripts/test.sh b/scripts/test.sh index d445ca1742..62449ea415 100755 --- a/scripts/test.sh +++ b/scripts/test.sh @@ -6,4 +6,4 @@ set -x # Check README.md is up to date python ./scripts/docs.py verify-readme export PYTHONPATH=./docs_src -pytest --cov=fastapi --cov=tests --cov=docs_src --cov-report=term-missing:skip-covered --cov-report=xml tests ${@} +coverage run -m pytest tests ${@} From b6ea8414a9b27411ff084d673327b9c58f3cea99 Mon Sep 17 00:00:00 2001 From: github-actions Date: Thu, 3 Nov 2022 20:01:17 +0000 Subject: [PATCH 14/97] =?UTF-8?q?=F0=9F=93=9D=20Update=20release=20notes?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docs/en/docs/release-notes.md | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/en/docs/release-notes.md b/docs/en/docs/release-notes.md index 48992f0783..f2b16e2e70 100644 --- a/docs/en/docs/release-notes.md +++ b/docs/en/docs/release-notes.md @@ -2,6 +2,7 @@ ## Latest Changes +* 👷 Switch from Codecov to Smokeshow plus pytest-cov to pure coverage for internal tests. PR [#5583](https://github.com/tiangolo/fastapi/pull/5583) by [@tiangolo](https://github.com/tiangolo). * ✅ Enable tests for Python 3.11. PR [#4881](https://github.com/tiangolo/fastapi/pull/4881) by [@tiangolo](https://github.com/tiangolo). * 🌐 Update wording in Chinese translation for `docs/zh/docs/python-types.md`. PR [#5416](https://github.com/tiangolo/fastapi/pull/5416) by [@supercaizehua](https://github.com/supercaizehua). * 🐛 Close FormData (uploaded files) after the request is done. PR [#5465](https://github.com/tiangolo/fastapi/pull/5465) by [@adriangb](https://github.com/adriangb). From 5cd99a9517a555242e48dabee8fc7628efca2588 Mon Sep 17 00:00:00 2001 From: Irfanuddin Shafi Ahmed Date: Fri, 4 Nov 2022 01:36:00 +0530 Subject: [PATCH 15/97] =?UTF-8?q?=F0=9F=8E=A8=20Format=20OpenAPI=20JSON=20?= =?UTF-8?q?in=20`test=5Fstarlette=5Fexception.py`=20(#5379)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- tests/test_starlette_exception.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/tests/test_starlette_exception.py b/tests/test_starlette_exception.py index 2b6712f7b6..418ddff7dd 100644 --- a/tests/test_starlette_exception.py +++ b/tests/test_starlette_exception.py @@ -47,10 +47,10 @@ openapi_schema = { "responses": { "200": { "content": {"application/json": {"schema": {}}}, - "description": "Successful " "Response", + "description": "Successful Response", } }, - "summary": "No Body " "Status " "Code " "Exception", + "summary": "No Body Status Code Exception", } }, "/http-no-body-statuscode-with-detail-exception": { @@ -59,7 +59,7 @@ openapi_schema = { "responses": { "200": { "content": {"application/json": {"schema": {}}}, - "description": "Successful " "Response", + "description": "Successful Response", } }, "summary": "No Body Status Code With Detail Exception", From 5f4680201c6ede7066b54821bc91995d6878695d Mon Sep 17 00:00:00 2001 From: github-actions Date: Thu, 3 Nov 2022 20:06:36 +0000 Subject: [PATCH 16/97] =?UTF-8?q?=F0=9F=93=9D=20Update=20release=20notes?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docs/en/docs/release-notes.md | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/en/docs/release-notes.md b/docs/en/docs/release-notes.md index f2b16e2e70..9375f0d189 100644 --- a/docs/en/docs/release-notes.md +++ b/docs/en/docs/release-notes.md @@ -2,6 +2,7 @@ ## Latest Changes +* 🎨 Format OpenAPI JSON in `test_starlette_exception.py`. PR [#5379](https://github.com/tiangolo/fastapi/pull/5379) by [@iudeen](https://github.com/iudeen). * 👷 Switch from Codecov to Smokeshow plus pytest-cov to pure coverage for internal tests. PR [#5583](https://github.com/tiangolo/fastapi/pull/5583) by [@tiangolo](https://github.com/tiangolo). * ✅ Enable tests for Python 3.11. PR [#4881](https://github.com/tiangolo/fastapi/pull/4881) by [@tiangolo](https://github.com/tiangolo). * 🌐 Update wording in Chinese translation for `docs/zh/docs/python-types.md`. PR [#5416](https://github.com/tiangolo/fastapi/pull/5416) by [@supercaizehua](https://github.com/supercaizehua). From 4fa4965beb7eda6b429a6fad033a0c61883b9df1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebasti=C3=A1n=20Ram=C3=ADrez?= Date: Thu, 3 Nov 2022 21:55:00 +0100 Subject: [PATCH 17/97] =?UTF-8?q?=F0=9F=93=9D=20Update=20coverage=20badge?= =?UTF-8?q?=20to=20use=20Samuel=20Colvin's=20Smokeshow=20(#5585)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 4 ++-- docs/en/docs/index.md | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index 9d4f1cd902..fe0ad49de1 100644 --- a/README.md +++ b/README.md @@ -8,8 +8,8 @@ Test - - Coverage + + Coverage Package version diff --git a/docs/en/docs/index.md b/docs/en/docs/index.md index afdd62ceec..1ad9c76068 100644 --- a/docs/en/docs/index.md +++ b/docs/en/docs/index.md @@ -8,8 +8,8 @@ Test - - Coverage + + Coverage Package version From 9a442c9730636d6528c23c92ec6ee0ecc0436533 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebasti=C3=A1n=20Ram=C3=ADrez?= Date: Thu, 3 Nov 2022 21:55:32 +0100 Subject: [PATCH 18/97] =?UTF-8?q?=F0=9F=91=B7=20Update=20FastAPI=20People?= =?UTF-8?q?=20to=20exclude=20bots:=20pre-commit-ci,=20dependabot=20(#5586)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .github/actions/people/app/main.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/actions/people/app/main.py b/.github/actions/people/app/main.py index cdf423b97b..31756a5fcb 100644 --- a/.github/actions/people/app/main.py +++ b/.github/actions/people/app/main.py @@ -433,7 +433,7 @@ if __name__ == "__main__": ) authors = {**issue_authors, **pr_authors} maintainers_logins = {"tiangolo"} - bot_names = {"codecov", "github-actions"} + bot_names = {"codecov", "github-actions", "pre-commit-ci", "dependabot"} maintainers = [] for login in maintainers_logins: user = authors[login] From 8a5befd099da0109f3eb81ee1b16605de0716600 Mon Sep 17 00:00:00 2001 From: github-actions Date: Thu, 3 Nov 2022 20:56:13 +0000 Subject: [PATCH 19/97] =?UTF-8?q?=F0=9F=93=9D=20Update=20release=20notes?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docs/en/docs/release-notes.md | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/en/docs/release-notes.md b/docs/en/docs/release-notes.md index 9375f0d189..a60b0e75ae 100644 --- a/docs/en/docs/release-notes.md +++ b/docs/en/docs/release-notes.md @@ -2,6 +2,7 @@ ## Latest Changes +* 👷 Update FastAPI People to exclude bots: pre-commit-ci, dependabot. PR [#5586](https://github.com/tiangolo/fastapi/pull/5586) by [@tiangolo](https://github.com/tiangolo). * 🎨 Format OpenAPI JSON in `test_starlette_exception.py`. PR [#5379](https://github.com/tiangolo/fastapi/pull/5379) by [@iudeen](https://github.com/iudeen). * 👷 Switch from Codecov to Smokeshow plus pytest-cov to pure coverage for internal tests. PR [#5583](https://github.com/tiangolo/fastapi/pull/5583) by [@tiangolo](https://github.com/tiangolo). * ✅ Enable tests for Python 3.11. PR [#4881](https://github.com/tiangolo/fastapi/pull/4881) by [@tiangolo](https://github.com/tiangolo). From d4e2bdb33a803da12800f8049811a32a6a5a4eeb Mon Sep 17 00:00:00 2001 From: Vivek Ashokkumar Date: Fri, 4 Nov 2022 02:30:28 +0530 Subject: [PATCH 20/97] =?UTF-8?q?=E2=9C=8F=20Fix=20typo=20in=20`docs/en/do?= =?UTF-8?q?cs/tutorial/security/oauth2-jwt.md`=20(#5584)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Sebastián Ramírez --- docs/en/docs/tutorial/security/oauth2-jwt.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/en/docs/tutorial/security/oauth2-jwt.md b/docs/en/docs/tutorial/security/oauth2-jwt.md index 09557f1ac5..41f00fd41e 100644 --- a/docs/en/docs/tutorial/security/oauth2-jwt.md +++ b/docs/en/docs/tutorial/security/oauth2-jwt.md @@ -257,7 +257,7 @@ Call the endpoint `/users/me/`, you will get the response as: -If you open the developer tools, you could see how the data sent and only includes the token, the password is only sent in the first request to authenticate the user and get that access token, but not afterwards: +If you open the developer tools, you could see how the data sent only includes the token, the password is only sent in the first request to authenticate the user and get that access token, but not afterwards: From fbc13d1f5b2b779cd0df366b5544ed1ea2650497 Mon Sep 17 00:00:00 2001 From: github-actions Date: Thu, 3 Nov 2022 21:01:09 +0000 Subject: [PATCH 21/97] =?UTF-8?q?=F0=9F=93=9D=20Update=20release=20notes?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docs/en/docs/release-notes.md | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/en/docs/release-notes.md b/docs/en/docs/release-notes.md index a60b0e75ae..855de6bb6f 100644 --- a/docs/en/docs/release-notes.md +++ b/docs/en/docs/release-notes.md @@ -2,6 +2,7 @@ ## Latest Changes +* ✏ Fix typo in `docs/en/docs/tutorial/security/oauth2-jwt.md`. PR [#5584](https://github.com/tiangolo/fastapi/pull/5584) by [@vivekashok1221](https://github.com/vivekashok1221). * 👷 Update FastAPI People to exclude bots: pre-commit-ci, dependabot. PR [#5586](https://github.com/tiangolo/fastapi/pull/5586) by [@tiangolo](https://github.com/tiangolo). * 🎨 Format OpenAPI JSON in `test_starlette_exception.py`. PR [#5379](https://github.com/tiangolo/fastapi/pull/5379) by [@iudeen](https://github.com/iudeen). * 👷 Switch from Codecov to Smokeshow plus pytest-cov to pure coverage for internal tests. PR [#5583](https://github.com/tiangolo/fastapi/pull/5583) by [@tiangolo](https://github.com/tiangolo). From 85e602d7ccebc4009422e96b2afaf5eec9578d33 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebasti=C3=A1n=20Ram=C3=ADrez?= Date: Thu, 3 Nov 2022 22:03:00 +0100 Subject: [PATCH 22/97] =?UTF-8?q?=F0=9F=93=9D=20Update=20release=20notes?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docs/en/docs/release-notes.md | 24 +++++++++++++++++++----- 1 file changed, 19 insertions(+), 5 deletions(-) diff --git a/docs/en/docs/release-notes.md b/docs/en/docs/release-notes.md index 855de6bb6f..392ce84515 100644 --- a/docs/en/docs/release-notes.md +++ b/docs/en/docs/release-notes.md @@ -2,15 +2,29 @@ ## Latest Changes +### Features + +* ✅ Enable tests for Python 3.11. PR [#4881](https://github.com/tiangolo/fastapi/pull/4881) by [@tiangolo](https://github.com/tiangolo). + +### Fixes + +* 🐛 Close FormData (uploaded files) after the request is done. PR [#5465](https://github.com/tiangolo/fastapi/pull/5465) by [@adriangb](https://github.com/adriangb). + +### Docs + * ✏ Fix typo in `docs/en/docs/tutorial/security/oauth2-jwt.md`. PR [#5584](https://github.com/tiangolo/fastapi/pull/5584) by [@vivekashok1221](https://github.com/vivekashok1221). + +### Translations + +* 🌐 Update wording in Chinese translation for `docs/zh/docs/python-types.md`. PR [#5416](https://github.com/tiangolo/fastapi/pull/5416) by [@supercaizehua](https://github.com/supercaizehua). +* 🌐 Add Russian translation for `docs/ru/docs/deployment/index.md`. PR [#5336](https://github.com/tiangolo/fastapi/pull/5336) by [@Xewus](https://github.com/Xewus). +* 🌐 Update Chinese translation for `docs/tutorial/security/oauth2-jwt.md`. PR [#3846](https://github.com/tiangolo/fastapi/pull/3846) by [@jaystone776](https://github.com/jaystone776). + +### Internal + * 👷 Update FastAPI People to exclude bots: pre-commit-ci, dependabot. PR [#5586](https://github.com/tiangolo/fastapi/pull/5586) by [@tiangolo](https://github.com/tiangolo). * 🎨 Format OpenAPI JSON in `test_starlette_exception.py`. PR [#5379](https://github.com/tiangolo/fastapi/pull/5379) by [@iudeen](https://github.com/iudeen). * 👷 Switch from Codecov to Smokeshow plus pytest-cov to pure coverage for internal tests. PR [#5583](https://github.com/tiangolo/fastapi/pull/5583) by [@tiangolo](https://github.com/tiangolo). -* ✅ Enable tests for Python 3.11. PR [#4881](https://github.com/tiangolo/fastapi/pull/4881) by [@tiangolo](https://github.com/tiangolo). -* 🌐 Update wording in Chinese translation for `docs/zh/docs/python-types.md`. PR [#5416](https://github.com/tiangolo/fastapi/pull/5416) by [@supercaizehua](https://github.com/supercaizehua). -* 🐛 Close FormData (uploaded files) after the request is done. PR [#5465](https://github.com/tiangolo/fastapi/pull/5465) by [@adriangb](https://github.com/adriangb). -* 🌐 Add Russian translation for `docs/ru/docs/deployment/index.md`. PR [#5336](https://github.com/tiangolo/fastapi/pull/5336) by [@Xewus](https://github.com/Xewus). -* 🌐 Update Chinese translation for `docs/tutorial/security/oauth2-jwt.md`. PR [#3846](https://github.com/tiangolo/fastapi/pull/3846) by [@jaystone776](https://github.com/jaystone776). * 👥 Update FastAPI People. PR [#5571](https://github.com/tiangolo/fastapi/pull/5571) by [@github-actions[bot]](https://github.com/apps/github-actions). ## 0.85.2 From 10fbfd6dc7a085f681d8e4cceee1533d6968da9b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebasti=C3=A1n=20Ram=C3=ADrez?= Date: Thu, 3 Nov 2022 22:12:43 +0100 Subject: [PATCH 23/97] =?UTF-8?q?=E2=AC=86=20Add=20Python=203.11=20to=20th?= =?UTF-8?q?e=20officially=20supported=20versions=20(#5587)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- pyproject.toml | 1 + 1 file changed, 1 insertion(+) diff --git a/pyproject.toml b/pyproject.toml index d7b848502c..a23289fb1e 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -34,6 +34,7 @@ classifiers = [ "Programming Language :: Python :: 3.8", "Programming Language :: Python :: 3.9", "Programming Language :: Python :: 3.10", + "Programming Language :: Python :: 3.11", "Topic :: Internet :: WWW/HTTP :: HTTP Servers", "Topic :: Internet :: WWW/HTTP", ] From 51e768e85ada8641b96ea970d388cfeae489ee8d Mon Sep 17 00:00:00 2001 From: github-actions Date: Thu, 3 Nov 2022 21:13:25 +0000 Subject: [PATCH 24/97] =?UTF-8?q?=F0=9F=93=9D=20Update=20release=20notes?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docs/en/docs/release-notes.md | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/en/docs/release-notes.md b/docs/en/docs/release-notes.md index 392ce84515..6a92061ece 100644 --- a/docs/en/docs/release-notes.md +++ b/docs/en/docs/release-notes.md @@ -2,6 +2,7 @@ ## Latest Changes +* ⬆ Add Python 3.11 to the officially supported versions. PR [#5587](https://github.com/tiangolo/fastapi/pull/5587) by [@tiangolo](https://github.com/tiangolo). ### Features * ✅ Enable tests for Python 3.11. PR [#4881](https://github.com/tiangolo/fastapi/pull/4881) by [@tiangolo](https://github.com/tiangolo). From 066cfae56edc6338e649e76421d0dc418c3bb739 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebasti=C3=A1n=20Ram=C3=ADrez?= Date: Thu, 3 Nov 2022 22:16:37 +0100 Subject: [PATCH 25/97] =?UTF-8?q?=F0=9F=93=9D=20Update=20release=20notes?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docs/en/docs/release-notes.md | 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 6a92061ece..fc7b54fdfe 100644 --- a/docs/en/docs/release-notes.md +++ b/docs/en/docs/release-notes.md @@ -2,9 +2,9 @@ ## Latest Changes -* ⬆ Add Python 3.11 to the officially supported versions. PR [#5587](https://github.com/tiangolo/fastapi/pull/5587) by [@tiangolo](https://github.com/tiangolo). ### Features +* ⬆ Add Python 3.11 to the officially supported versions. PR [#5587](https://github.com/tiangolo/fastapi/pull/5587) by [@tiangolo](https://github.com/tiangolo). * ✅ Enable tests for Python 3.11. PR [#4881](https://github.com/tiangolo/fastapi/pull/4881) by [@tiangolo](https://github.com/tiangolo). ### Fixes From ccd242348fb9e7e214d5cb2ff7f6c5996f96e4dc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebasti=C3=A1n=20Ram=C3=ADrez?= Date: Thu, 3 Nov 2022 22:17:44 +0100 Subject: [PATCH 26/97] =?UTF-8?q?=F0=9F=94=96=20Release=20version=200.86.0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docs/en/docs/release-notes.md | 3 +++ fastapi/__init__.py | 2 +- 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/docs/en/docs/release-notes.md b/docs/en/docs/release-notes.md index fc7b54fdfe..dbbd5e41e9 100644 --- a/docs/en/docs/release-notes.md +++ b/docs/en/docs/release-notes.md @@ -2,6 +2,9 @@ ## Latest Changes + +## 0.86.0 + ### Features * ⬆ Add Python 3.11 to the officially supported versions. PR [#5587](https://github.com/tiangolo/fastapi/pull/5587) by [@tiangolo](https://github.com/tiangolo). diff --git a/fastapi/__init__.py b/fastapi/__init__.py index cb1b063aae..a5c7aeb176 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.85.2" +__version__ = "0.86.0" from starlette import status as status From 5f0e0956897333a03145c02d059e976831ad2303 Mon Sep 17 00:00:00 2001 From: github-actions Date: Fri, 4 Nov 2022 19:20:29 +0000 Subject: [PATCH 27/97] =?UTF-8?q?=F0=9F=93=9D=20Update=20release=20notes?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docs/en/docs/release-notes.md | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/en/docs/release-notes.md b/docs/en/docs/release-notes.md index dbbd5e41e9..b005a31e73 100644 --- a/docs/en/docs/release-notes.md +++ b/docs/en/docs/release-notes.md @@ -2,6 +2,7 @@ ## Latest Changes +* 📝 Update coverage badge to use Samuel Colvin's Smokeshow. PR [#5585](https://github.com/tiangolo/fastapi/pull/5585) by [@tiangolo](https://github.com/tiangolo). ## 0.86.0 From f36d2e2b2b1b4144ee683cfb832e2d5fd8ff5b61 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 9 Nov 2022 12:46:14 +0100 Subject: [PATCH 28/97] =?UTF-8?q?=E2=AC=86=20Bump=20dawidd6/action-downloa?= =?UTF-8?q?d-artifact=20from=202.24.0=20to=202.24.1=20(#5603)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Bumps [dawidd6/action-download-artifact](https://github.com/dawidd6/action-download-artifact) from 2.24.0 to 2.24.1. - [Release notes](https://github.com/dawidd6/action-download-artifact/releases) - [Commits](https://github.com/dawidd6/action-download-artifact/compare/v2.24.0...v2.24.1) --- updated-dependencies: - dependency-name: dawidd6/action-download-artifact dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/preview-docs.yml | 2 +- .github/workflows/smokeshow.yml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/preview-docs.yml b/.github/workflows/preview-docs.yml index 15c59d4bd4..4bab6df000 100644 --- a/.github/workflows/preview-docs.yml +++ b/.github/workflows/preview-docs.yml @@ -12,7 +12,7 @@ jobs: steps: - uses: actions/checkout@v3 - name: Download Artifact Docs - uses: dawidd6/action-download-artifact@v2.24.0 + uses: dawidd6/action-download-artifact@v2.24.1 with: github_token: ${{ secrets.GITHUB_TOKEN }} workflow: build-docs.yml diff --git a/.github/workflows/smokeshow.yml b/.github/workflows/smokeshow.yml index 606633a99d..6901f2ab03 100644 --- a/.github/workflows/smokeshow.yml +++ b/.github/workflows/smokeshow.yml @@ -20,7 +20,7 @@ jobs: - run: pip install smokeshow - - uses: dawidd6/action-download-artifact@v2 + - uses: dawidd6/action-download-artifact@v2.24.1 with: workflow: test.yml commit: ${{ github.event.workflow_run.head_sha }} From a7edd0b80dab658c350c46fcaa68d8a6224347c0 Mon Sep 17 00:00:00 2001 From: github-actions Date: Wed, 9 Nov 2022 11:46:50 +0000 Subject: [PATCH 29/97] =?UTF-8?q?=F0=9F=93=9D=20Update=20release=20notes?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docs/en/docs/release-notes.md | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/en/docs/release-notes.md b/docs/en/docs/release-notes.md index b005a31e73..261dbc6c0f 100644 --- a/docs/en/docs/release-notes.md +++ b/docs/en/docs/release-notes.md @@ -2,6 +2,7 @@ ## Latest Changes +* ⬆ Bump dawidd6/action-download-artifact from 2.24.0 to 2.24.1. PR [#5603](https://github.com/tiangolo/fastapi/pull/5603) by [@dependabot[bot]](https://github.com/apps/dependabot). * 📝 Update coverage badge to use Samuel Colvin's Smokeshow. PR [#5585](https://github.com/tiangolo/fastapi/pull/5585) by [@tiangolo](https://github.com/tiangolo). ## 0.86.0 From 678d35994a1fad6c94bcfa6399d99c0712caf0d0 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 10 Nov 2022 12:15:55 +0100 Subject: [PATCH 30/97] =?UTF-8?q?=E2=AC=86=20Bump=20dawidd6/action-downloa?= =?UTF-8?q?d-artifact=20from=202.24.1=20to=202.24.2=20(#5609)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Bumps [dawidd6/action-download-artifact](https://github.com/dawidd6/action-download-artifact) from 2.24.1 to 2.24.2. - [Release notes](https://github.com/dawidd6/action-download-artifact/releases) - [Commits](https://github.com/dawidd6/action-download-artifact/compare/v2.24.1...v2.24.2) --- updated-dependencies: - dependency-name: dawidd6/action-download-artifact dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/preview-docs.yml | 2 +- .github/workflows/smokeshow.yml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/preview-docs.yml b/.github/workflows/preview-docs.yml index 4bab6df000..a2e5976fba 100644 --- a/.github/workflows/preview-docs.yml +++ b/.github/workflows/preview-docs.yml @@ -12,7 +12,7 @@ jobs: steps: - uses: actions/checkout@v3 - name: Download Artifact Docs - uses: dawidd6/action-download-artifact@v2.24.1 + uses: dawidd6/action-download-artifact@v2.24.2 with: github_token: ${{ secrets.GITHUB_TOKEN }} workflow: build-docs.yml diff --git a/.github/workflows/smokeshow.yml b/.github/workflows/smokeshow.yml index 6901f2ab03..7559c24c06 100644 --- a/.github/workflows/smokeshow.yml +++ b/.github/workflows/smokeshow.yml @@ -20,7 +20,7 @@ jobs: - run: pip install smokeshow - - uses: dawidd6/action-download-artifact@v2.24.1 + - uses: dawidd6/action-download-artifact@v2.24.2 with: workflow: test.yml commit: ${{ github.event.workflow_run.head_sha }} From 0ed9ca78bccc34c3edbbf71a704f9e3090ad5c18 Mon Sep 17 00:00:00 2001 From: github-actions Date: Thu, 10 Nov 2022 11:16:30 +0000 Subject: [PATCH 31/97] =?UTF-8?q?=F0=9F=93=9D=20Update=20release=20notes?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docs/en/docs/release-notes.md | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/en/docs/release-notes.md b/docs/en/docs/release-notes.md index 261dbc6c0f..62ccd7da38 100644 --- a/docs/en/docs/release-notes.md +++ b/docs/en/docs/release-notes.md @@ -2,6 +2,7 @@ ## Latest Changes +* ⬆ Bump dawidd6/action-download-artifact from 2.24.1 to 2.24.2. PR [#5609](https://github.com/tiangolo/fastapi/pull/5609) by [@dependabot[bot]](https://github.com/apps/dependabot). * ⬆ Bump dawidd6/action-download-artifact from 2.24.0 to 2.24.1. PR [#5603](https://github.com/tiangolo/fastapi/pull/5603) by [@dependabot[bot]](https://github.com/apps/dependabot). * 📝 Update coverage badge to use Samuel Colvin's Smokeshow. PR [#5585](https://github.com/tiangolo/fastapi/pull/5585) by [@tiangolo](https://github.com/tiangolo). From a0c717d784686c06f6dd98da46ec8596a3373346 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebasti=C3=A1n=20Ram=C3=ADrez?= Date: Thu, 10 Nov 2022 13:22:25 +0100 Subject: [PATCH 32/97] =?UTF-8?q?=F0=9F=9B=A0=20Add=20Arabic=20issue=20num?= =?UTF-8?q?ber=20to=20Notify=20Translations=20GitHub=20Action=20(#5610)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .github/actions/notify-translations/app/translations.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/actions/notify-translations/app/translations.yml b/.github/actions/notify-translations/app/translations.yml index b43aba01d0..4338e1326e 100644 --- a/.github/actions/notify-translations/app/translations.yml +++ b/.github/actions/notify-translations/app/translations.yml @@ -18,3 +18,4 @@ uz: 4883 sv: 5146 he: 5157 ta: 5434 +ar: 3349 From 41735d2de9afbb2c01541d0f3052c718cb9f4f30 Mon Sep 17 00:00:00 2001 From: github-actions Date: Thu, 10 Nov 2022 12:22:58 +0000 Subject: [PATCH 33/97] =?UTF-8?q?=F0=9F=93=9D=20Update=20release=20notes?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docs/en/docs/release-notes.md | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/en/docs/release-notes.md b/docs/en/docs/release-notes.md index 62ccd7da38..95e466ea95 100644 --- a/docs/en/docs/release-notes.md +++ b/docs/en/docs/release-notes.md @@ -2,6 +2,7 @@ ## Latest Changes +* 🛠 Add Arabic issue number to Notify Translations GitHub Action. PR [#5610](https://github.com/tiangolo/fastapi/pull/5610) by [@tiangolo](https://github.com/tiangolo). * ⬆ Bump dawidd6/action-download-artifact from 2.24.1 to 2.24.2. PR [#5609](https://github.com/tiangolo/fastapi/pull/5609) by [@dependabot[bot]](https://github.com/apps/dependabot). * ⬆ Bump dawidd6/action-download-artifact from 2.24.0 to 2.24.1. PR [#5603](https://github.com/tiangolo/fastapi/pull/5603) by [@dependabot[bot]](https://github.com/apps/dependabot). * 📝 Update coverage badge to use Samuel Colvin's Smokeshow. PR [#5585](https://github.com/tiangolo/fastapi/pull/5585) by [@tiangolo](https://github.com/tiangolo). From 0781a91d194e994eccddae14c2afe892ac0d572b Mon Sep 17 00:00:00 2001 From: nikkie Date: Sun, 13 Nov 2022 22:57:52 +0900 Subject: [PATCH 34/97] =?UTF-8?q?=F0=9F=8C=90=20Fix=20highlight=20lines=20?= =?UTF-8?q?for=20Japanese=20translation=20for=20`docs/tutorial/query-param?= =?UTF-8?q?s.md`=20(#2969)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Sebastián Ramírez Fix https://github.com/tiangolo/fastapi/issues/2966 --- docs/ja/docs/tutorial/query-params.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/docs/ja/docs/tutorial/query-params.md b/docs/ja/docs/tutorial/query-params.md index 9f8c6ab9f2..5202009ef8 100644 --- a/docs/ja/docs/tutorial/query-params.md +++ b/docs/ja/docs/tutorial/query-params.md @@ -64,7 +64,7 @@ http://127.0.0.1:8000/items/?skip=20 同様に、デフォルト値を `None` とすることで、オプショナルなクエリパラメータを宣言できます: -```Python hl_lines="7" +```Python hl_lines="9" {!../../../docs_src/query_params/tutorial002.py!} ``` @@ -82,7 +82,7 @@ http://127.0.0.1:8000/items/?skip=20 `bool` 型も宣言できます。これは以下の様に変換されます: -```Python hl_lines="7" +```Python hl_lines="9" {!../../../docs_src/query_params/tutorial003.py!} ``` @@ -126,7 +126,7 @@ http://127.0.0.1:8000/items/foo?short=yes 名前で判別されます: -```Python hl_lines="6 8" +```Python hl_lines="8 10" {!../../../docs_src/query_params/tutorial004.py!} ``` @@ -184,7 +184,7 @@ http://127.0.0.1:8000/items/foo-item?needy=sooooneedy そして当然、あるパラメータを必須に、別のパラメータにデフォルト値を設定し、また別のパラメータをオプショナルにできます: -```Python hl_lines="7" +```Python hl_lines="10" {!../../../docs_src/query_params/tutorial006.py!} ``` From 59208e4ddcbb14a64eabc99c37acf8424a8d30a2 Mon Sep 17 00:00:00 2001 From: Ryusei Ishikawa <51394682+xryuseix@users.noreply.github.com> Date: Sun, 13 Nov 2022 22:58:31 +0900 Subject: [PATCH 35/97] =?UTF-8?q?=F0=9F=8C=90=20Add=20Japanese=20translati?= =?UTF-8?q?on=20for=20`docs/ja/docs/advanced/websockets.md`=20(#4983)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: tokusumi <41147016+tokusumi@users.noreply.github.com> Co-authored-by: komtaki <39375566+komtaki@users.noreply.github.com> --- docs/ja/docs/advanced/websockets.md | 186 ++++++++++++++++++++++++++++ docs/ja/mkdocs.yml | 1 + 2 files changed, 187 insertions(+) create mode 100644 docs/ja/docs/advanced/websockets.md diff --git a/docs/ja/docs/advanced/websockets.md b/docs/ja/docs/advanced/websockets.md new file mode 100644 index 0000000000..65e4112a6b --- /dev/null +++ b/docs/ja/docs/advanced/websockets.md @@ -0,0 +1,186 @@ +# WebSocket + +**FastAPI**でWebSocketが使用できます。 + +## `WebSockets`のインストール + +まず `WebSockets`のインストールが必要です。 + +
+ +```console +$ pip install websockets + +---> 100% +``` + +
+ +## WebSocket クライアント + +### 本番環境 + +本番環境では、React、Vue.js、Angularなどの最新のフレームワークで作成されたフロントエンドを使用しているでしょう。 + +そして、バックエンドとWebSocketを使用して通信するために、おそらくフロントエンドのユーティリティを使用することになるでしょう。 + +または、ネイティブコードでWebSocketバックエンドと直接通信するネイティブモバイルアプリケーションがあるかもしれません。 + +他にも、WebSocketのエンドポイントと通信する方法があるかもしれません。 + +--- + +ただし、この例では非常にシンプルなHTML文書といくつかのJavaScriptを、すべてソースコードの中に入れて使用することにします。 + +もちろん、これは最適な方法ではありませんし、本番環境で使うことはないでしょう。 + +本番環境では、上記の方法のいずれかの選択肢を採用することになるでしょう。 + +しかし、これはWebSocketのサーバーサイドに焦点を当て、実用的な例を示す最も簡単な方法です。 + +```Python hl_lines="2 6-38 41-43" +{!../../../docs_src/websockets/tutorial001.py!} +``` + +## `websocket` を作成する + +**FastAPI** アプリケーションで、`websocket` を作成します。 + +```Python hl_lines="1 46-47" +{!../../../docs_src/websockets/tutorial001.py!} +``` + +!!! note "技術詳細" + `from starlette.websockets import WebSocket` を使用しても構いません. + + **FastAPI** は開発者の利便性のために、同じ `WebSocket` を提供します。しかし、こちらはStarletteから直接提供されるものです。 + +## メッセージの送受信 + +WebSocketルートでは、 `await` を使ってメッセージの送受信ができます。 + +```Python hl_lines="48-52" +{!../../../docs_src/websockets/tutorial001.py!} +``` + +バイナリやテキストデータ、JSONデータを送受信できます。 + +## 試してみる + +ファイル名が `main.py` である場合、以下の方法でアプリケーションを実行します。 + +
+ +```console +$ uvicorn main:app --reload + +INFO: Uvicorn running on http://127.0.0.1:8000 (Press CTRL+C to quit) +``` + +
+ +ブラウザで http://127.0.0.1:8000 を開きます。 + +次のようなシンプルなページが表示されます。 + + + +入力ボックスにメッセージを入力して送信できます。 + + + +そして、 WebSocketを使用した**FastAPI**アプリケーションが応答します。 + + + +複数のメッセージを送信(および受信)できます。 + + + +そして、これらの通信はすべて同じWebSocket接続を使用します。 + +## 依存関係 + +WebSocketエンドポイントでは、`fastapi` から以下をインポートして使用できます。 + +* `Depends` +* `Security` +* `Cookie` +* `Header` +* `Path` +* `Query` + +これらは、他のFastAPI エンドポイント/*path operation* の場合と同じように機能します。 + +```Python hl_lines="58-65 68-83" +{!../../../docs_src/websockets/tutorial002.py!} +``` + +!!! info "情報" + WebSocket で `HTTPException` を発生させることはあまり意味がありません。したがって、WebSocketの接続を直接閉じる方がよいでしょう。 + + クロージングコードは、仕様で定義された有効なコードの中から使用することができます。 + + 将来的には、どこからでも `raise` できる `WebSocketException` が用意され、専用の例外ハンドラを追加できるようになる予定です。これは、Starlette の PR #527 に依存するものです。 + +### 依存関係を用いてWebSocketsを試してみる + +ファイル名が `main.py` である場合、以下の方法でアプリケーションを実行します。 + +
+ +```console +$ uvicorn main:app --reload + +INFO: Uvicorn running on http://127.0.0.1:8000 (Press CTRL+C to quit) +``` + +
+ +ブラウザで http://127.0.0.1:8000 を開きます。 + +クライアントが設定できる項目は以下の通りです。 + +* パスで使用される「Item ID」 +* クエリパラメータとして使用される「Token」 + +!!! tip "豆知識" + クエリ `token` は依存パッケージによって処理されることに注意してください。 + +これにより、WebSocketに接続してメッセージを送受信できます。 + + + +## 切断や複数クライアントへの対応 + +WebSocket接続が閉じられると、 `await websocket.receive_text()` は例外 `WebSocketDisconnect` を発生させ、この例のようにキャッチして処理することができます。 + +```Python hl_lines="81-83" +{!../../../docs_src/websockets/tutorial003.py!} +``` + +試してみるには、 + +* いくつかのブラウザタブでアプリを開きます。 +* それらのタブでメッセージを記入してください。 +* そして、タブのうち1つを閉じてください。 + +これにより例外 `WebSocketDisconnect` が発生し、他のすべてのクライアントは次のようなメッセージを受信します。 + +``` +Client #1596980209979 left the chat +``` + +!!! tip "豆知識" + 上記のアプリは、複数の WebSocket 接続に対してメッセージを処理し、ブロードキャストする方法を示すための最小限のシンプルな例です。 + + しかし、すべての接続がメモリ内の単一のリストで処理されるため、プロセスの実行中にのみ機能し、単一のプロセスでのみ機能することに注意してください。 + + もしFastAPIと簡単に統合できて、RedisやPostgreSQLなどでサポートされている、より堅牢なものが必要なら、encode/broadcaster を確認してください。 + +## その他のドキュメント + +オプションの詳細については、Starletteのドキュメントを確認してください。 + +* `WebSocket` クラス +* クラスベースのWebSocket処理 diff --git a/docs/ja/mkdocs.yml b/docs/ja/mkdocs.yml index b3f18bbdd3..5bbcce6059 100644 --- a/docs/ja/mkdocs.yml +++ b/docs/ja/mkdocs.yml @@ -86,6 +86,7 @@ nav: - advanced/response-directly.md - advanced/custom-response.md - advanced/nosql-databases.md + - advanced/websockets.md - advanced/conditional-openapi.md - async.md - デプロイ: From 86d4073632e642fd7253b0b2ec30d384183994d5 Mon Sep 17 00:00:00 2001 From: github-actions Date: Sun, 13 Nov 2022 13:59:09 +0000 Subject: [PATCH 36/97] =?UTF-8?q?=F0=9F=93=9D=20Update=20release=20notes?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docs/en/docs/release-notes.md | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/en/docs/release-notes.md b/docs/en/docs/release-notes.md index 95e466ea95..9e210532e7 100644 --- a/docs/en/docs/release-notes.md +++ b/docs/en/docs/release-notes.md @@ -2,6 +2,7 @@ ## Latest Changes +* 🌐 Add Japanese translation for `docs/ja/docs/advanced/websockets.md`. PR [#4983](https://github.com/tiangolo/fastapi/pull/4983) by [@xryuseix](https://github.com/xryuseix). * 🛠 Add Arabic issue number to Notify Translations GitHub Action. PR [#5610](https://github.com/tiangolo/fastapi/pull/5610) by [@tiangolo](https://github.com/tiangolo). * ⬆ Bump dawidd6/action-download-artifact from 2.24.1 to 2.24.2. PR [#5609](https://github.com/tiangolo/fastapi/pull/5609) by [@dependabot[bot]](https://github.com/apps/dependabot). * ⬆ Bump dawidd6/action-download-artifact from 2.24.0 to 2.24.1. PR [#5603](https://github.com/tiangolo/fastapi/pull/5603) by [@dependabot[bot]](https://github.com/apps/dependabot). From c040e3602a9c061e98d3c779e436998dffcfacdc Mon Sep 17 00:00:00 2001 From: Bruno Artur Torres Lopes Pereira <33462923+batlopes@users.noreply.github.com> Date: Sun, 13 Nov 2022 10:59:16 -0300 Subject: [PATCH 37/97] =?UTF-8?q?=F0=9F=8C=90=20Add=20Portuguese=20transla?= =?UTF-8?q?tion=20for=20`docs/pt/docs/tutorial/request-forms-and-files.md`?= =?UTF-8?q?=20(#5579)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> --- .../docs/tutorial/request-forms-and-files.md | 36 +++++++++++++++++++ docs/pt/mkdocs.yml | 1 + 2 files changed, 37 insertions(+) create mode 100644 docs/pt/docs/tutorial/request-forms-and-files.md diff --git a/docs/pt/docs/tutorial/request-forms-and-files.md b/docs/pt/docs/tutorial/request-forms-and-files.md new file mode 100644 index 0000000000..259f262f44 --- /dev/null +++ b/docs/pt/docs/tutorial/request-forms-and-files.md @@ -0,0 +1,36 @@ +# Formulários e Arquivos da Requisição + +Você pode definir arquivos e campos de formulário ao mesmo tempo usando `File` e `Form`. + +!!! info "Informação" + Para receber arquivos carregados e/ou dados de formulário, primeiro instale `python-multipart`. + + Por exemplo: `pip install python-multipart`. + + +## Importe `File` e `Form` + +```Python hl_lines="1" +{!../../../docs_src/request_forms_and_files/tutorial001.py!} +``` + +## Defina parâmetros de `File` e `Form` + +Crie parâmetros de arquivo e formulário da mesma forma que você faria para `Body` ou `Query`: + +```Python hl_lines="8" +{!../../../docs_src/request_forms_and_files/tutorial001.py!} +``` + +Os arquivos e campos de formulário serão carregados como dados de formulário e você receberá os arquivos e campos de formulário. + +E você pode declarar alguns dos arquivos como `bytes` e alguns como `UploadFile`. + +!!! warning "Aviso" + Você pode declarar vários parâmetros `File` e `Form` em uma *operação de caminho*, mas não é possível declarar campos `Body` para receber como JSON, pois a requisição terá o corpo codificado usando `multipart/form-data` ao invés de `application/json`. + + Isso não é uma limitação do **FastAPI** , é parte do protocolo HTTP. + +## Recapitulando + +Usar `File` e `Form` juntos quando precisar receber dados e arquivos na mesma requisição. diff --git a/docs/pt/mkdocs.yml b/docs/pt/mkdocs.yml index 3c50cc5f80..fdef810fa1 100644 --- a/docs/pt/mkdocs.yml +++ b/docs/pt/mkdocs.yml @@ -75,6 +75,7 @@ nav: - tutorial/header-params.md - tutorial/response-status-code.md - tutorial/request-forms.md + - tutorial/request-forms-and-files.md - tutorial/handling-errors.md - Segurança: - tutorial/security/index.md From f57ccd8ef36b80749342af150430f95530abb45c Mon Sep 17 00:00:00 2001 From: github-actions Date: Sun, 13 Nov 2022 13:59:55 +0000 Subject: [PATCH 38/97] =?UTF-8?q?=F0=9F=93=9D=20Update=20release=20notes?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docs/en/docs/release-notes.md | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/en/docs/release-notes.md b/docs/en/docs/release-notes.md index 9e210532e7..f62b6de716 100644 --- a/docs/en/docs/release-notes.md +++ b/docs/en/docs/release-notes.md @@ -2,6 +2,7 @@ ## Latest Changes +* 🌐 Add Portuguese translation for `docs/pt/docs/tutorial/request-forms-and-files.md`. PR [#5579](https://github.com/tiangolo/fastapi/pull/5579) by [@batlopes](https://github.com/batlopes). * 🌐 Add Japanese translation for `docs/ja/docs/advanced/websockets.md`. PR [#4983](https://github.com/tiangolo/fastapi/pull/4983) by [@xryuseix](https://github.com/xryuseix). * 🛠 Add Arabic issue number to Notify Translations GitHub Action. PR [#5610](https://github.com/tiangolo/fastapi/pull/5610) by [@tiangolo](https://github.com/tiangolo). * ⬆ Bump dawidd6/action-download-artifact from 2.24.1 to 2.24.2. PR [#5609](https://github.com/tiangolo/fastapi/pull/5609) by [@dependabot[bot]](https://github.com/apps/dependabot). From ba5310f73138eb23b8bcca43d6bbe95e1d3a9b3d Mon Sep 17 00:00:00 2001 From: axel584 Date: Sun, 13 Nov 2022 15:03:48 +0100 Subject: [PATCH 39/97] =?UTF-8?q?=F0=9F=8C=90=20Add=20French=20translation?= =?UTF-8?q?=20for=20`docs/fr/docs/advanced/additional-status-code.md`=20(#?= =?UTF-8?q?5477)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Julian Maurin Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> Co-authored-by: Sebastián Ramírez --- docs/fr/docs/advanced/additional-responses.md | 240 ++++++++++++++++++ .../docs/advanced/additional-status-codes.md | 37 +++ docs/fr/mkdocs.yml | 3 + 3 files changed, 280 insertions(+) create mode 100644 docs/fr/docs/advanced/additional-responses.md create mode 100644 docs/fr/docs/advanced/additional-status-codes.md diff --git a/docs/fr/docs/advanced/additional-responses.md b/docs/fr/docs/advanced/additional-responses.md new file mode 100644 index 0000000000..35b57594d5 --- /dev/null +++ b/docs/fr/docs/advanced/additional-responses.md @@ -0,0 +1,240 @@ +# Réponses supplémentaires dans OpenAPI + +!!! Attention + Ceci concerne un sujet plutôt avancé. + + Si vous débutez avec **FastAPI**, vous n'en aurez peut-être pas besoin. + +Vous pouvez déclarer des réponses supplémentaires, avec des codes HTTP, des types de médias, des descriptions, etc. + +Ces réponses supplémentaires seront incluses dans le schéma OpenAPI, elles apparaîtront donc également dans la documentation de l'API. + +Mais pour ces réponses supplémentaires, vous devez vous assurer de renvoyer directement une `Response` comme `JSONResponse`, avec votre code HTTP et votre contenu. + +## Réponse supplémentaire avec `model` + +Vous pouvez ajouter à votre décorateur de *paramètre de chemin* un paramètre `responses`. + +Il prend comme valeur un `dict` dont les clés sont des codes HTTP pour chaque réponse, comme `200`, et la valeur de ces clés sont d'autres `dict` avec des informations pour chacun d'eux. + +Chacun de ces `dict` de réponse peut avoir une clé `model`, contenant un modèle Pydantic, tout comme `response_model`. + +**FastAPI** prendra ce modèle, générera son schéma JSON et l'inclura au bon endroit dans OpenAPI. + +Par exemple, pour déclarer une autre réponse avec un code HTTP `404` et un modèle Pydantic `Message`, vous pouvez écrire : + +```Python hl_lines="18 22" +{!../../../docs_src/additional_responses/tutorial001.py!} +``` + +!!! Remarque + Gardez à l'esprit que vous devez renvoyer directement `JSONResponse`. + +!!! Info + La clé `model` ne fait pas partie d'OpenAPI. + + **FastAPI** prendra le modèle Pydantic à partir de là, générera le `JSON Schema` et le placera au bon endroit. + + Le bon endroit est : + + * Dans la clé `content`, qui a pour valeur un autre objet JSON (`dict`) qui contient : + * Une clé avec le type de support, par ex. `application/json`, qui contient comme valeur un autre objet JSON, qui contient : + * Une clé `schema`, qui a pour valeur le schéma JSON du modèle, voici le bon endroit. + * **FastAPI** ajoute ici une référence aux schémas JSON globaux à un autre endroit de votre OpenAPI au lieu de l'inclure directement. De cette façon, d'autres applications et clients peuvent utiliser ces schémas JSON directement, fournir de meilleurs outils de génération de code, etc. + +Les réponses générées au format OpenAPI pour cette *opération de chemin* seront : + +```JSON hl_lines="3-12" +{ + "responses": { + "404": { + "description": "Additional Response", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Message" + } + } + } + }, + "200": { + "description": "Successful Response", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Item" + } + } + } + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + } + } + } +} +``` + +Les schémas sont référencés à un autre endroit du modèle OpenAPI : + +```JSON hl_lines="4-16" +{ + "components": { + "schemas": { + "Message": { + "title": "Message", + "required": [ + "message" + ], + "type": "object", + "properties": { + "message": { + "title": "Message", + "type": "string" + } + } + }, + "Item": { + "title": "Item", + "required": [ + "id", + "value" + ], + "type": "object", + "properties": { + "id": { + "title": "Id", + "type": "string" + }, + "value": { + "title": "Value", + "type": "string" + } + } + }, + "ValidationError": { + "title": "ValidationError", + "required": [ + "loc", + "msg", + "type" + ], + "type": "object", + "properties": { + "loc": { + "title": "Location", + "type": "array", + "items": { + "type": "string" + } + }, + "msg": { + "title": "Message", + "type": "string" + }, + "type": { + "title": "Error Type", + "type": "string" + } + } + }, + "HTTPValidationError": { + "title": "HTTPValidationError", + "type": "object", + "properties": { + "detail": { + "title": "Detail", + "type": "array", + "items": { + "$ref": "#/components/schemas/ValidationError" + } + } + } + } + } + } +} +``` + +## Types de médias supplémentaires pour la réponse principale + +Vous pouvez utiliser ce même paramètre `responses` pour ajouter différents types de médias pour la même réponse principale. + +Par exemple, vous pouvez ajouter un type de média supplémentaire `image/png`, en déclarant que votre *opération de chemin* peut renvoyer un objet JSON (avec le type de média `application/json`) ou une image PNG : + +```Python hl_lines="19-24 28" +{!../../../docs_src/additional_responses/tutorial002.py!} +``` + +!!! Remarque + Notez que vous devez retourner l'image en utilisant directement un `FileResponse`. + +!!! Info + À moins que vous ne spécifiiez explicitement un type de média différent dans votre paramètre `responses`, FastAPI supposera que la réponse a le même type de média que la classe de réponse principale (par défaut `application/json`). + + Mais si vous avez spécifié une classe de réponse personnalisée avec `None` comme type de média, FastAPI utilisera `application/json` pour toute réponse supplémentaire associée à un modèle. + +## Combinaison d'informations + +Vous pouvez également combiner des informations de réponse provenant de plusieurs endroits, y compris les paramètres `response_model`, `status_code` et `responses`. + +Vous pouvez déclarer un `response_model`, en utilisant le code HTTP par défaut `200` (ou un code personnalisé si vous en avez besoin), puis déclarer des informations supplémentaires pour cette même réponse dans `responses`, directement dans le schéma OpenAPI. + +**FastAPI** conservera les informations supplémentaires des `responses` et les combinera avec le schéma JSON de votre modèle. + +Par exemple, vous pouvez déclarer une réponse avec un code HTTP `404` qui utilise un modèle Pydantic et a une `description` personnalisée. + +Et une réponse avec un code HTTP `200` qui utilise votre `response_model`, mais inclut un `example` personnalisé : + +```Python hl_lines="20-31" +{!../../../docs_src/additional_responses/tutorial003.py!} +``` + +Tout sera combiné et inclus dans votre OpenAPI, et affiché dans la documentation de l'API : + + + +## Combinez les réponses prédéfinies et les réponses personnalisées + +Vous voulez peut-être avoir des réponses prédéfinies qui s'appliquent à de nombreux *paramètre de chemin*, mais vous souhaitez les combiner avec des réponses personnalisées nécessaires à chaque *opération de chemin*. + +Dans ces cas, vous pouvez utiliser la technique Python "d'affection par décomposition" (appelé _unpacking_ en anglais) d'un `dict` avec `**dict_to_unpack` : + +``` Python +old_dict = { + "old key": "old value", + "second old key": "second old value", +} +new_dict = {**old_dict, "new key": "new value"} +``` + +Ici, `new_dict` contiendra toutes les paires clé-valeur de `old_dict` plus la nouvelle paire clé-valeur : + +``` Python +{ + "old key": "old value", + "second old key": "second old value", + "new key": "new value", +} +``` + +Vous pouvez utiliser cette technique pour réutiliser certaines réponses prédéfinies dans vos *paramètres de chemin* et les combiner avec des réponses personnalisées supplémentaires. + +Par exemple: + +```Python hl_lines="13-17 26" +{!../../../docs_src/additional_responses/tutorial004.py!} +``` + +## Plus d'informations sur les réponses OpenAPI + +Pour voir exactement ce que vous pouvez inclure dans les réponses, vous pouvez consulter ces sections dans la spécification OpenAPI : + +* Objet Responses de OpenAPI , il inclut le `Response Object`. +* Objet Response de OpenAPI , vous pouvez inclure n'importe quoi directement dans chaque réponse à l'intérieur de votre paramètre `responses`. Y compris `description`, `headers`, `content` (à l'intérieur de cela, vous déclarez différents types de médias et schémas JSON) et `links`. diff --git a/docs/fr/docs/advanced/additional-status-codes.md b/docs/fr/docs/advanced/additional-status-codes.md new file mode 100644 index 0000000000..e7b003707b --- /dev/null +++ b/docs/fr/docs/advanced/additional-status-codes.md @@ -0,0 +1,37 @@ +# Codes HTTP supplémentaires + +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`. + +Il utilisera le code HTTP par défaut ou celui que vous avez défini dans votre *chemin d'accès*. + +## Codes HTTP supplémentaires + +Si vous souhaitez renvoyer des codes HTTP supplémentaires en plus du code principal, vous pouvez le faire en renvoyant directement une `Response`, comme une `JSONResponse`, et en définissant directement le code HTTP supplémentaire. + +Par exemple, disons que vous voulez avoir un *chemin d'accès* qui permet de mettre à jour les éléments et renvoie les codes HTTP 200 "OK" en cas de succès. + +Mais vous voulez aussi qu'il accepte de nouveaux éléments. Et lorsque les éléments n'existaient pas auparavant, il les crée et renvoie un code HTTP de 201 "Créé". + +Pour y parvenir, importez `JSONResponse` et renvoyez-y directement votre contenu, en définissant le `status_code` que vous souhaitez : + +```Python hl_lines="4 25" +{!../../../docs_src/additional_status_codes/tutorial001.py!} +``` + +!!! Attention + Lorsque vous renvoyez une `Response` directement, comme dans l'exemple ci-dessus, elle sera renvoyée directement. + + Elle ne sera pas sérialisée avec un modèle. + + Assurez-vous qu'il contient les données souhaitées et que les valeurs soient dans un format JSON valides (si vous utilisez une `JSONResponse`). + +!!! note "Détails techniques" + Vous pouvez également utiliser `from starlette.responses import JSONResponse`. + + Pour plus de commodités, **FastAPI** fournit les objets `starlette.responses` sous forme d'un alias accessible par `fastapi.responses`. Mais la plupart des réponses disponibles proviennent directement de Starlette. Il en est de même avec l'objet `statut`. + +## Documents OpenAPI et API + +Si vous renvoyez directement des codes HTTP et des réponses supplémentaires, ils ne seront pas inclus dans le schéma OpenAPI (la documentation de l'API), car FastAPI n'a aucun moyen de savoir à l'avance ce que vous allez renvoyer. + +Mais vous pouvez documenter cela dans votre code, en utilisant : [Réponses supplémentaires dans OpenAPI](additional-responses.md){.internal-link target=_blank}. diff --git a/docs/fr/mkdocs.yml b/docs/fr/mkdocs.yml index 1c4f45682f..7dce4b1276 100644 --- a/docs/fr/mkdocs.yml +++ b/docs/fr/mkdocs.yml @@ -67,6 +67,9 @@ nav: - tutorial/query-params.md - tutorial/body.md - tutorial/background-tasks.md +- Guide utilisateur avancé: + - advanced/additional-status-codes.md + - advanced/additional-responses.md - async.md - Déploiement: - deployment/index.md From 5f67ac6fd61a1269a8f3a9c896b98906019e2b32 Mon Sep 17 00:00:00 2001 From: github-actions Date: Sun, 13 Nov 2022 14:04:27 +0000 Subject: [PATCH 40/97] =?UTF-8?q?=F0=9F=93=9D=20Update=20release=20notes?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docs/en/docs/release-notes.md | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/en/docs/release-notes.md b/docs/en/docs/release-notes.md index f62b6de716..1378e45d5d 100644 --- a/docs/en/docs/release-notes.md +++ b/docs/en/docs/release-notes.md @@ -2,6 +2,7 @@ ## Latest Changes +* 🌐 Add French translation for `docs/fr/docs/advanced/additional-status-code.md`. PR [#5477](https://github.com/tiangolo/fastapi/pull/5477) by [@axel584](https://github.com/axel584). * 🌐 Add Portuguese translation for `docs/pt/docs/tutorial/request-forms-and-files.md`. PR [#5579](https://github.com/tiangolo/fastapi/pull/5579) by [@batlopes](https://github.com/batlopes). * 🌐 Add Japanese translation for `docs/ja/docs/advanced/websockets.md`. PR [#4983](https://github.com/tiangolo/fastapi/pull/4983) by [@xryuseix](https://github.com/xryuseix). * 🛠 Add Arabic issue number to Notify Translations GitHub Action. PR [#5610](https://github.com/tiangolo/fastapi/pull/5610) by [@tiangolo](https://github.com/tiangolo). From fdbd48be5fc6ef4bfd9bdd4582006f70b7a52317 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Rubin?= Date: Sun, 13 Nov 2022 15:26:09 +0100 Subject: [PATCH 41/97] =?UTF-8?q?=E2=AC=86=20Upgrade=20Starlette=20to=20`0?= =?UTF-8?q?.21.0`,=20including=20the=20new=20[`TestClient`=20based=20on=20?= =?UTF-8?q?HTTPX](https://github.com/encode/starlette/releases/tag/0.21.0)?= =?UTF-8?q?=20(#5471)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Paweł Rubin Co-authored-by: Sebastián Ramírez --- fastapi/security/api_key.py | 2 +- fastapi/security/http.py | 8 ++++---- fastapi/security/oauth2.py | 6 +++--- fastapi/security/open_id_connect_url.py | 2 +- fastapi/security/utils.py | 6 ++++-- pyproject.toml | 2 +- tests/test_enforce_once_required_parameter.py | 2 +- tests/test_extra_routes.py | 2 +- tests/test_get_request_body.py | 2 +- tests/test_param_include_in_schema.py | 9 ++++++--- tests/test_security_api_key_cookie.py | 7 ++++--- .../test_security_api_key_cookie_description.py | 7 ++++--- tests/test_security_api_key_cookie_optional.py | 7 ++++--- tests/test_tuples.py | 8 +++----- .../test_advanced_middleware/test_tutorial001.py | 2 +- .../test_tutorial/test_body/test_tutorial001.py | 16 +++++++++------- .../test_body/test_tutorial001_py310.py | 16 +++++++++------- .../test_cookie_params/test_tutorial001.py | 5 ++--- .../test_cookie_params/test_tutorial001_py310.py | 15 +++++---------- .../test_tutorial001.py | 2 +- .../test_custom_response/test_tutorial006.py | 2 +- .../test_custom_response/test_tutorial006b.py | 2 +- .../test_custom_response/test_tutorial006c.py | 2 +- .../test_tutorial006.py | 2 +- .../test_tutorial007.py | 6 +++--- .../test_websockets/test_tutorial002.py | 12 +++++++----- 26 files changed, 79 insertions(+), 73 deletions(-) diff --git a/fastapi/security/api_key.py b/fastapi/security/api_key.py index bca5c721a6..24ddbf4825 100644 --- a/fastapi/security/api_key.py +++ b/fastapi/security/api_key.py @@ -54,7 +54,7 @@ class APIKeyHeader(APIKeyBase): self.auto_error = auto_error async def __call__(self, request: Request) -> Optional[str]: - api_key: str = request.headers.get(self.model.name) + api_key = request.headers.get(self.model.name) if not api_key: if self.auto_error: raise HTTPException( diff --git a/fastapi/security/http.py b/fastapi/security/http.py index 1b473c69e7..8b677299dd 100644 --- a/fastapi/security/http.py +++ b/fastapi/security/http.py @@ -38,7 +38,7 @@ class HTTPBase(SecurityBase): async def __call__( self, request: Request ) -> Optional[HTTPAuthorizationCredentials]: - authorization: str = request.headers.get("Authorization") + authorization = request.headers.get("Authorization") scheme, credentials = get_authorization_scheme_param(authorization) if not (authorization and scheme and credentials): if self.auto_error: @@ -67,7 +67,7 @@ class HTTPBasic(HTTPBase): async def __call__( # type: ignore self, request: Request ) -> Optional[HTTPBasicCredentials]: - authorization: str = request.headers.get("Authorization") + authorization = request.headers.get("Authorization") scheme, param = get_authorization_scheme_param(authorization) if self.realm: unauthorized_headers = {"WWW-Authenticate": f'Basic realm="{self.realm}"'} @@ -113,7 +113,7 @@ class HTTPBearer(HTTPBase): async def __call__( self, request: Request ) -> Optional[HTTPAuthorizationCredentials]: - authorization: str = request.headers.get("Authorization") + authorization = request.headers.get("Authorization") scheme, credentials = get_authorization_scheme_param(authorization) if not (authorization and scheme and credentials): if self.auto_error: @@ -148,7 +148,7 @@ class HTTPDigest(HTTPBase): async def __call__( self, request: Request ) -> Optional[HTTPAuthorizationCredentials]: - authorization: str = request.headers.get("Authorization") + authorization = request.headers.get("Authorization") scheme, credentials = get_authorization_scheme_param(authorization) if not (authorization and scheme and credentials): if self.auto_error: diff --git a/fastapi/security/oauth2.py b/fastapi/security/oauth2.py index 653c3010e5..eb6b4277cf 100644 --- a/fastapi/security/oauth2.py +++ b/fastapi/security/oauth2.py @@ -126,7 +126,7 @@ class OAuth2(SecurityBase): self.auto_error = auto_error async def __call__(self, request: Request) -> Optional[str]: - authorization: str = request.headers.get("Authorization") + authorization = request.headers.get("Authorization") if not authorization: if self.auto_error: raise HTTPException( @@ -157,7 +157,7 @@ class OAuth2PasswordBearer(OAuth2): ) async def __call__(self, request: Request) -> Optional[str]: - authorization: str = request.headers.get("Authorization") + authorization = request.headers.get("Authorization") scheme, param = get_authorization_scheme_param(authorization) if not authorization or scheme.lower() != "bearer": if self.auto_error: @@ -200,7 +200,7 @@ class OAuth2AuthorizationCodeBearer(OAuth2): ) async def __call__(self, request: Request) -> Optional[str]: - authorization: str = request.headers.get("Authorization") + authorization = request.headers.get("Authorization") scheme, param = get_authorization_scheme_param(authorization) if not authorization or scheme.lower() != "bearer": if self.auto_error: diff --git a/fastapi/security/open_id_connect_url.py b/fastapi/security/open_id_connect_url.py index dfe9f7b255..393614f7cb 100644 --- a/fastapi/security/open_id_connect_url.py +++ b/fastapi/security/open_id_connect_url.py @@ -23,7 +23,7 @@ class OpenIdConnect(SecurityBase): self.auto_error = auto_error async def __call__(self, request: Request) -> Optional[str]: - authorization: str = request.headers.get("Authorization") + authorization = request.headers.get("Authorization") if not authorization: if self.auto_error: raise HTTPException( diff --git a/fastapi/security/utils.py b/fastapi/security/utils.py index 2da0dd20f3..fa7a450b74 100644 --- a/fastapi/security/utils.py +++ b/fastapi/security/utils.py @@ -1,7 +1,9 @@ -from typing import Tuple +from typing import Optional, Tuple -def get_authorization_scheme_param(authorization_header_value: str) -> Tuple[str, str]: +def get_authorization_scheme_param( + authorization_header_value: Optional[str], +) -> Tuple[str, str]: if not authorization_header_value: return "", "" scheme, _, param = authorization_header_value.partition(" ") diff --git a/pyproject.toml b/pyproject.toml index a23289fb1e..fc4602ea8e 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -39,7 +39,7 @@ classifiers = [ "Topic :: Internet :: WWW/HTTP", ] dependencies = [ - "starlette==0.20.4", + "starlette==0.21.0", "pydantic >=1.6.2,!=1.7,!=1.7.1,!=1.7.2,!=1.7.3,!=1.8,!=1.8.1,<2.0.0", ] dynamic = ["version"] diff --git a/tests/test_enforce_once_required_parameter.py b/tests/test_enforce_once_required_parameter.py index ba8c7353fa..bf05aa5852 100644 --- a/tests/test_enforce_once_required_parameter.py +++ b/tests/test_enforce_once_required_parameter.py @@ -101,7 +101,7 @@ def test_schema(): def test_get_invalid(): - response = client.get("/foo", params={"client_id": None}) + response = client.get("/foo") assert response.status_code == status.HTTP_422_UNPROCESSABLE_ENTITY diff --git a/tests/test_extra_routes.py b/tests/test_extra_routes.py index 491ba61c68..e979628a5c 100644 --- a/tests/test_extra_routes.py +++ b/tests/test_extra_routes.py @@ -333,7 +333,7 @@ def test_get_api_route_not_decorated(): def test_delete(): - response = client.delete("/items/foo", json={"name": "Foo"}) + response = client.request("DELETE", "/items/foo", json={"name": "Foo"}) assert response.status_code == 200, response.text assert response.json() == {"item_id": "foo", "item": {"name": "Foo", "price": None}} diff --git a/tests/test_get_request_body.py b/tests/test_get_request_body.py index 88b9d839f5..52a052faab 100644 --- a/tests/test_get_request_body.py +++ b/tests/test_get_request_body.py @@ -104,5 +104,5 @@ def test_openapi_schema(): def test_get_with_body(): body = {"name": "Foo", "description": "Some description", "price": 5.5} - response = client.get("/product", json=body) + response = client.request("GET", "/product", json=body) assert response.json() == body diff --git a/tests/test_param_include_in_schema.py b/tests/test_param_include_in_schema.py index 214f039b67..cb182a1cd4 100644 --- a/tests/test_param_include_in_schema.py +++ b/tests/test_param_include_in_schema.py @@ -33,8 +33,6 @@ async def hidden_query( return {"hidden_query": hidden_query} -client = TestClient(app) - openapi_shema = { "openapi": "3.0.2", "info": {"title": "FastAPI", "version": "0.1.0"}, @@ -161,6 +159,7 @@ openapi_shema = { def test_openapi_schema(): + client = TestClient(app) response = client.get("/openapi.json") assert response.status_code == 200 assert response.json() == openapi_shema @@ -184,7 +183,8 @@ def test_openapi_schema(): ], ) def test_hidden_cookie(path, cookies, expected_status, expected_response): - response = client.get(path, cookies=cookies) + client = TestClient(app, cookies=cookies) + response = client.get(path) assert response.status_code == expected_status assert response.json() == expected_response @@ -207,12 +207,14 @@ def test_hidden_cookie(path, cookies, expected_status, expected_response): ], ) def test_hidden_header(path, headers, expected_status, expected_response): + client = TestClient(app) response = client.get(path, headers=headers) assert response.status_code == expected_status assert response.json() == expected_response def test_hidden_path(): + client = TestClient(app) response = client.get("/hidden_path/hidden_path") assert response.status_code == 200 assert response.json() == {"hidden_path": "hidden_path"} @@ -234,6 +236,7 @@ def test_hidden_path(): ], ) def test_hidden_query(path, expected_status, expected_response): + client = TestClient(app) response = client.get(path) assert response.status_code == expected_status assert response.json() == expected_response diff --git a/tests/test_security_api_key_cookie.py b/tests/test_security_api_key_cookie.py index a5b2e44f0c..0bf4e9bb3a 100644 --- a/tests/test_security_api_key_cookie.py +++ b/tests/test_security_api_key_cookie.py @@ -22,8 +22,6 @@ def read_current_user(current_user: User = Depends(get_current_user)): return current_user -client = TestClient(app) - openapi_schema = { "openapi": "3.0.2", "info": {"title": "FastAPI", "version": "0.1.0"}, @@ -51,18 +49,21 @@ openapi_schema = { def test_openapi_schema(): + client = TestClient(app) response = client.get("/openapi.json") assert response.status_code == 200, response.text assert response.json() == openapi_schema def test_security_api_key(): - response = client.get("/users/me", cookies={"key": "secret"}) + client = TestClient(app, cookies={"key": "secret"}) + response = client.get("/users/me") assert response.status_code == 200, response.text assert response.json() == {"username": "secret"} def test_security_api_key_no_key(): + client = TestClient(app) response = client.get("/users/me") assert response.status_code == 403, response.text assert response.json() == {"detail": "Not authenticated"} diff --git a/tests/test_security_api_key_cookie_description.py b/tests/test_security_api_key_cookie_description.py index 2cd3565b43..ed4e652394 100644 --- a/tests/test_security_api_key_cookie_description.py +++ b/tests/test_security_api_key_cookie_description.py @@ -22,8 +22,6 @@ def read_current_user(current_user: User = Depends(get_current_user)): return current_user -client = TestClient(app) - openapi_schema = { "openapi": "3.0.2", "info": {"title": "FastAPI", "version": "0.1.0"}, @@ -56,18 +54,21 @@ openapi_schema = { def test_openapi_schema(): + client = TestClient(app) response = client.get("/openapi.json") assert response.status_code == 200, response.text assert response.json() == openapi_schema def test_security_api_key(): - response = client.get("/users/me", cookies={"key": "secret"}) + client = TestClient(app, cookies={"key": "secret"}) + response = client.get("/users/me") assert response.status_code == 200, response.text assert response.json() == {"username": "secret"} def test_security_api_key_no_key(): + client = TestClient(app) response = client.get("/users/me") assert response.status_code == 403, response.text assert response.json() == {"detail": "Not authenticated"} diff --git a/tests/test_security_api_key_cookie_optional.py b/tests/test_security_api_key_cookie_optional.py index 96a64f09a6..3e7aa81c07 100644 --- a/tests/test_security_api_key_cookie_optional.py +++ b/tests/test_security_api_key_cookie_optional.py @@ -29,8 +29,6 @@ def read_current_user(current_user: User = Depends(get_current_user)): return current_user -client = TestClient(app) - openapi_schema = { "openapi": "3.0.2", "info": {"title": "FastAPI", "version": "0.1.0"}, @@ -58,18 +56,21 @@ openapi_schema = { def test_openapi_schema(): + client = TestClient(app) response = client.get("/openapi.json") assert response.status_code == 200, response.text assert response.json() == openapi_schema def test_security_api_key(): - response = client.get("/users/me", cookies={"key": "secret"}) + client = TestClient(app, cookies={"key": "secret"}) + response = client.get("/users/me") assert response.status_code == 200, response.text assert response.json() == {"username": "secret"} def test_security_api_key_no_key(): + client = TestClient(app) response = client.get("/users/me") assert response.status_code == 200, response.text assert response.json() == {"msg": "Create an account first"} diff --git a/tests/test_tuples.py b/tests/test_tuples.py index 18ec2d0489..6e2cc0db67 100644 --- a/tests/test_tuples.py +++ b/tests/test_tuples.py @@ -252,16 +252,14 @@ def test_tuple_with_model_invalid(): def test_tuple_form_valid(): - response = client.post("/tuple-form/", data=[("values", "1"), ("values", "2")]) + response = client.post("/tuple-form/", data={"values": ("1", "2")}) assert response.status_code == 200, response.text assert response.json() == [1, 2] def test_tuple_form_invalid(): - response = client.post( - "/tuple-form/", data=[("values", "1"), ("values", "2"), ("values", "3")] - ) + response = client.post("/tuple-form/", data={"values": ("1", "2", "3")}) assert response.status_code == 422, response.text - response = client.post("/tuple-form/", data=[("values", "1")]) + response = client.post("/tuple-form/", data={"values": ("1")}) assert response.status_code == 422, response.text diff --git a/tests/test_tutorial/test_advanced_middleware/test_tutorial001.py b/tests/test_tutorial/test_advanced_middleware/test_tutorial001.py index 17165c0fc6..157fa5caf1 100644 --- a/tests/test_tutorial/test_advanced_middleware/test_tutorial001.py +++ b/tests/test_tutorial/test_advanced_middleware/test_tutorial001.py @@ -9,6 +9,6 @@ def test_middleware(): assert response.status_code == 200, response.text client = TestClient(app) - response = client.get("/", allow_redirects=False) + response = client.get("/", follow_redirects=False) assert response.status_code == 307, response.text assert response.headers["location"] == "https://testserver/" diff --git a/tests/test_tutorial/test_body/test_tutorial001.py b/tests/test_tutorial/test_body/test_tutorial001.py index 8dbaf15dbe..65cdc758ad 100644 --- a/tests/test_tutorial/test_body/test_tutorial001.py +++ b/tests/test_tutorial/test_body/test_tutorial001.py @@ -176,7 +176,7 @@ def test_post_broken_body(): response = client.post( "/items/", headers={"content-type": "application/json"}, - data="{some broken json}", + content="{some broken json}", ) assert response.status_code == 422, response.text assert response.json() == { @@ -214,7 +214,7 @@ def test_post_form_for_json(): def test_explicit_content_type(): response = client.post( "/items/", - data='{"name": "Foo", "price": 50.5}', + content='{"name": "Foo", "price": 50.5}', headers={"Content-Type": "application/json"}, ) assert response.status_code == 200, response.text @@ -223,7 +223,7 @@ def test_explicit_content_type(): def test_geo_json(): response = client.post( "/items/", - data='{"name": "Foo", "price": 50.5}', + content='{"name": "Foo", "price": 50.5}', headers={"Content-Type": "application/geo+json"}, ) assert response.status_code == 200, response.text @@ -232,7 +232,7 @@ def test_geo_json(): def test_no_content_type_is_json(): response = client.post( "/items/", - data='{"name": "Foo", "price": 50.5}', + content='{"name": "Foo", "price": 50.5}', ) assert response.status_code == 200, response.text assert response.json() == { @@ -255,17 +255,19 @@ def test_wrong_headers(): ] } - response = client.post("/items/", data=data, headers={"Content-Type": "text/plain"}) + response = client.post( + "/items/", content=data, headers={"Content-Type": "text/plain"} + ) assert response.status_code == 422, response.text assert response.json() == invalid_dict response = client.post( - "/items/", data=data, headers={"Content-Type": "application/geo+json-seq"} + "/items/", content=data, headers={"Content-Type": "application/geo+json-seq"} ) assert response.status_code == 422, response.text assert response.json() == invalid_dict response = client.post( - "/items/", data=data, headers={"Content-Type": "application/not-really-json"} + "/items/", content=data, headers={"Content-Type": "application/not-really-json"} ) assert response.status_code == 422, response.text assert response.json() == invalid_dict diff --git a/tests/test_tutorial/test_body/test_tutorial001_py310.py b/tests/test_tutorial/test_body/test_tutorial001_py310.py index dd9d9911e4..83bcb68f30 100644 --- a/tests/test_tutorial/test_body/test_tutorial001_py310.py +++ b/tests/test_tutorial/test_body/test_tutorial001_py310.py @@ -185,7 +185,7 @@ def test_post_broken_body(client: TestClient): response = client.post( "/items/", headers={"content-type": "application/json"}, - data="{some broken json}", + content="{some broken json}", ) assert response.status_code == 422, response.text assert response.json() == { @@ -225,7 +225,7 @@ def test_post_form_for_json(client: TestClient): def test_explicit_content_type(client: TestClient): response = client.post( "/items/", - data='{"name": "Foo", "price": 50.5}', + content='{"name": "Foo", "price": 50.5}', headers={"Content-Type": "application/json"}, ) assert response.status_code == 200, response.text @@ -235,7 +235,7 @@ def test_explicit_content_type(client: TestClient): def test_geo_json(client: TestClient): response = client.post( "/items/", - data='{"name": "Foo", "price": 50.5}', + content='{"name": "Foo", "price": 50.5}', headers={"Content-Type": "application/geo+json"}, ) assert response.status_code == 200, response.text @@ -245,7 +245,7 @@ def test_geo_json(client: TestClient): def test_no_content_type_is_json(client: TestClient): response = client.post( "/items/", - data='{"name": "Foo", "price": 50.5}', + content='{"name": "Foo", "price": 50.5}', ) assert response.status_code == 200, response.text assert response.json() == { @@ -269,17 +269,19 @@ def test_wrong_headers(client: TestClient): ] } - response = client.post("/items/", data=data, headers={"Content-Type": "text/plain"}) + response = client.post( + "/items/", content=data, headers={"Content-Type": "text/plain"} + ) assert response.status_code == 422, response.text assert response.json() == invalid_dict response = client.post( - "/items/", data=data, headers={"Content-Type": "application/geo+json-seq"} + "/items/", content=data, headers={"Content-Type": "application/geo+json-seq"} ) assert response.status_code == 422, response.text assert response.json() == invalid_dict response = client.post( - "/items/", data=data, headers={"Content-Type": "application/not-really-json"} + "/items/", content=data, headers={"Content-Type": "application/not-really-json"} ) assert response.status_code == 422, response.text assert response.json() == invalid_dict diff --git a/tests/test_tutorial/test_cookie_params/test_tutorial001.py b/tests/test_tutorial/test_cookie_params/test_tutorial001.py index edccffec1e..38ae211db3 100644 --- a/tests/test_tutorial/test_cookie_params/test_tutorial001.py +++ b/tests/test_tutorial/test_cookie_params/test_tutorial001.py @@ -3,8 +3,6 @@ from fastapi.testclient import TestClient from docs_src.cookie_params.tutorial001 import app -client = TestClient(app) - openapi_schema = { "openapi": "3.0.2", "info": {"title": "FastAPI", "version": "0.1.0"}, @@ -88,6 +86,7 @@ openapi_schema = { ], ) def test(path, cookies, expected_status, expected_response): - response = client.get(path, cookies=cookies) + client = TestClient(app, cookies=cookies) + response = client.get(path) assert response.status_code == expected_status assert response.json() == expected_response diff --git a/tests/test_tutorial/test_cookie_params/test_tutorial001_py310.py b/tests/test_tutorial/test_cookie_params/test_tutorial001_py310.py index 5caa5c4400..5ad52fb5e1 100644 --- a/tests/test_tutorial/test_cookie_params/test_tutorial001_py310.py +++ b/tests/test_tutorial/test_cookie_params/test_tutorial001_py310.py @@ -70,14 +70,6 @@ openapi_schema = { } -@pytest.fixture(name="client") -def get_client(): - from docs_src.cookie_params.tutorial001_py310 import app - - client = TestClient(app) - return client - - @needs_py310 @pytest.mark.parametrize( "path,cookies,expected_status,expected_response", @@ -94,7 +86,10 @@ def get_client(): ("/items", {"session": "cookiesession"}, 200, {"ads_id": None}), ], ) -def test(path, cookies, expected_status, expected_response, client: TestClient): - response = client.get(path, cookies=cookies) +def test(path, cookies, expected_status, expected_response): + from docs_src.cookie_params.tutorial001_py310 import app + + client = TestClient(app, cookies=cookies) + response = client.get(path) assert response.status_code == expected_status assert response.json() == expected_response diff --git a/tests/test_tutorial/test_custom_request_and_route/test_tutorial001.py b/tests/test_tutorial/test_custom_request_and_route/test_tutorial001.py index 3eb5822e28..e6da630e88 100644 --- a/tests/test_tutorial/test_custom_request_and_route/test_tutorial001.py +++ b/tests/test_tutorial/test_custom_request_and_route/test_tutorial001.py @@ -26,7 +26,7 @@ def test_gzip_request(compress): data = gzip.compress(data) headers["Content-Encoding"] = "gzip" headers["Content-Type"] = "application/json" - response = client.post("/sum", data=data, headers=headers) + response = client.post("/sum", content=data, headers=headers) assert response.json() == {"sum": n} diff --git a/tests/test_tutorial/test_custom_response/test_tutorial006.py b/tests/test_tutorial/test_custom_response/test_tutorial006.py index 72bbfd2777..9b10916e58 100644 --- a/tests/test_tutorial/test_custom_response/test_tutorial006.py +++ b/tests/test_tutorial/test_custom_response/test_tutorial006.py @@ -32,6 +32,6 @@ def test_openapi_schema(): def test_get(): - response = client.get("/typer", allow_redirects=False) + response = client.get("/typer", follow_redirects=False) assert response.status_code == 307, response.text assert response.headers["location"] == "https://typer.tiangolo.com" diff --git a/tests/test_tutorial/test_custom_response/test_tutorial006b.py b/tests/test_tutorial/test_custom_response/test_tutorial006b.py index ac5a76d34d..b3e60e86a3 100644 --- a/tests/test_tutorial/test_custom_response/test_tutorial006b.py +++ b/tests/test_tutorial/test_custom_response/test_tutorial006b.py @@ -27,6 +27,6 @@ def test_openapi_schema(): def test_redirect_response_class(): - response = client.get("/fastapi", allow_redirects=False) + response = client.get("/fastapi", follow_redirects=False) assert response.status_code == 307 assert response.headers["location"] == "https://fastapi.tiangolo.com" diff --git a/tests/test_tutorial/test_custom_response/test_tutorial006c.py b/tests/test_tutorial/test_custom_response/test_tutorial006c.py index 009225e8c5..0cb6ddaa33 100644 --- a/tests/test_tutorial/test_custom_response/test_tutorial006c.py +++ b/tests/test_tutorial/test_custom_response/test_tutorial006c.py @@ -27,6 +27,6 @@ def test_openapi_schema(): def test_redirect_status_code(): - response = client.get("/pydantic", allow_redirects=False) + response = client.get("/pydantic", follow_redirects=False) assert response.status_code == 302 assert response.headers["location"] == "https://pydantic-docs.helpmanual.io/" diff --git a/tests/test_tutorial/test_path_operation_advanced_configurations/test_tutorial006.py b/tests/test_tutorial/test_path_operation_advanced_configurations/test_tutorial006.py index 5533b29571..330b4e2c79 100644 --- a/tests/test_tutorial/test_path_operation_advanced_configurations/test_tutorial006.py +++ b/tests/test_tutorial/test_path_operation_advanced_configurations/test_tutorial006.py @@ -47,7 +47,7 @@ def test_openapi_schema(): def test_post(): - response = client.post("/items/", data=b"this is actually not validated") + response = client.post("/items/", content=b"this is actually not validated") assert response.status_code == 200, response.text assert response.json() == { "size": 30, diff --git a/tests/test_tutorial/test_path_operation_advanced_configurations/test_tutorial007.py b/tests/test_tutorial/test_path_operation_advanced_configurations/test_tutorial007.py index cb5dbc8eb0..076f60b2f0 100644 --- a/tests/test_tutorial/test_path_operation_advanced_configurations/test_tutorial007.py +++ b/tests/test_tutorial/test_path_operation_advanced_configurations/test_tutorial007.py @@ -58,7 +58,7 @@ def test_post(): - x-men - x-avengers """ - response = client.post("/items/", data=yaml_data) + response = client.post("/items/", content=yaml_data) assert response.status_code == 200, response.text assert response.json() == { "name": "Deadpoolio", @@ -74,7 +74,7 @@ def test_post_broken_yaml(): x - x-men x - x-avengers """ - response = client.post("/items/", data=yaml_data) + response = client.post("/items/", content=yaml_data) assert response.status_code == 422, response.text assert response.json() == {"detail": "Invalid YAML"} @@ -88,7 +88,7 @@ def test_post_invalid(): - x-avengers - sneaky: object """ - response = client.post("/items/", data=yaml_data) + response = client.post("/items/", content=yaml_data) assert response.status_code == 422, response.text assert response.json() == { "detail": [ diff --git a/tests/test_tutorial/test_websockets/test_tutorial002.py b/tests/test_tutorial/test_websockets/test_tutorial002.py index a8523c9c4f..bb5ccbf8ef 100644 --- a/tests/test_tutorial/test_websockets/test_tutorial002.py +++ b/tests/test_tutorial/test_websockets/test_tutorial002.py @@ -4,20 +4,18 @@ from fastapi.websockets import WebSocketDisconnect from docs_src.websockets.tutorial002 import app -client = TestClient(app) - def test_main(): + client = TestClient(app) response = client.get("/") assert response.status_code == 200, response.text assert b"" in response.content def test_websocket_with_cookie(): + client = TestClient(app, cookies={"session": "fakesession"}) with pytest.raises(WebSocketDisconnect): - with client.websocket_connect( - "/items/foo/ws", cookies={"session": "fakesession"} - ) as websocket: + with client.websocket_connect("/items/foo/ws") as websocket: message = "Message one" websocket.send_text(message) data = websocket.receive_text() @@ -33,6 +31,7 @@ def test_websocket_with_cookie(): def test_websocket_with_header(): + client = TestClient(app) with pytest.raises(WebSocketDisconnect): with client.websocket_connect("/items/bar/ws?token=some-token") as websocket: message = "Message one" @@ -50,6 +49,7 @@ def test_websocket_with_header(): def test_websocket_with_header_and_query(): + client = TestClient(app) with pytest.raises(WebSocketDisconnect): with client.websocket_connect("/items/2/ws?q=3&token=some-token") as websocket: message = "Message one" @@ -71,6 +71,7 @@ def test_websocket_with_header_and_query(): def test_websocket_no_credentials(): + client = TestClient(app) with pytest.raises(WebSocketDisconnect): with client.websocket_connect("/items/foo/ws"): pytest.fail( @@ -79,6 +80,7 @@ def test_websocket_no_credentials(): def test_websocket_invalid_data(): + client = TestClient(app) with pytest.raises(WebSocketDisconnect): with client.websocket_connect("/items/foo/ws?q=bar&token=some-token"): pytest.fail( From 46b903f70b586ae0019185e6793c6a400e6bb90c Mon Sep 17 00:00:00 2001 From: github-actions Date: Sun, 13 Nov 2022 14:26:43 +0000 Subject: [PATCH 42/97] =?UTF-8?q?=F0=9F=93=9D=20Update=20release=20notes?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docs/en/docs/release-notes.md | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/en/docs/release-notes.md b/docs/en/docs/release-notes.md index 1378e45d5d..f5d30d7ef8 100644 --- a/docs/en/docs/release-notes.md +++ b/docs/en/docs/release-notes.md @@ -2,6 +2,7 @@ ## Latest Changes +* ⬆ Upgrade Starlette to `0.21.0`, including the new [`TestClient` based on HTTPX](https://github.com/encode/starlette/releases/tag/0.21.0). PR [#5471](https://github.com/tiangolo/fastapi/pull/5471) by [@pawelrubin](https://github.com/pawelrubin). * 🌐 Add French translation for `docs/fr/docs/advanced/additional-status-code.md`. PR [#5477](https://github.com/tiangolo/fastapi/pull/5477) by [@axel584](https://github.com/axel584). * 🌐 Add Portuguese translation for `docs/pt/docs/tutorial/request-forms-and-files.md`. PR [#5579](https://github.com/tiangolo/fastapi/pull/5579) by [@batlopes](https://github.com/batlopes). * 🌐 Add Japanese translation for `docs/ja/docs/advanced/websockets.md`. PR [#4983](https://github.com/tiangolo/fastapi/pull/4983) by [@xryuseix](https://github.com/xryuseix). From 57141ccac48c6f585bf13141d0f8315ea639c2cb Mon Sep 17 00:00:00 2001 From: github-actions Date: Sun, 13 Nov 2022 14:35:13 +0000 Subject: [PATCH 43/97] =?UTF-8?q?=F0=9F=93=9D=20Update=20release=20notes?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docs/en/docs/release-notes.md | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/en/docs/release-notes.md b/docs/en/docs/release-notes.md index f5d30d7ef8..b6c4f4a9a6 100644 --- a/docs/en/docs/release-notes.md +++ b/docs/en/docs/release-notes.md @@ -2,6 +2,7 @@ ## Latest Changes +* 🌐 Fix highlight lines for Japanese translation for `docs/tutorial/query-params.md`. PR [#2969](https://github.com/tiangolo/fastapi/pull/2969) by [@ftnext](https://github.com/ftnext). * ⬆ Upgrade Starlette to `0.21.0`, including the new [`TestClient` based on HTTPX](https://github.com/encode/starlette/releases/tag/0.21.0). PR [#5471](https://github.com/tiangolo/fastapi/pull/5471) by [@pawelrubin](https://github.com/pawelrubin). * 🌐 Add French translation for `docs/fr/docs/advanced/additional-status-code.md`. PR [#5477](https://github.com/tiangolo/fastapi/pull/5477) by [@axel584](https://github.com/axel584). * 🌐 Add Portuguese translation for `docs/pt/docs/tutorial/request-forms-and-files.md`. PR [#5579](https://github.com/tiangolo/fastapi/pull/5579) by [@batlopes](https://github.com/batlopes). From f92f87d379cc5d3c9b3c159d74639411617cb0da Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebasti=C3=A1n=20Ram=C3=ADrez?= Date: Sun, 13 Nov 2022 16:20:05 +0100 Subject: [PATCH 44/97] =?UTF-8?q?=F0=9F=93=9D=20Update=20references=20to?= =?UTF-8?q?=20Requests=20for=20tests=20to=20HTTPX,=20and=20add=20HTTPX=20t?= =?UTF-8?q?o=20extras=20(#5628)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 4 ++-- docs/az/docs/index.md | 2 +- docs/de/docs/features.md | 2 +- docs/de/docs/index.md | 2 +- docs/en/docs/advanced/async-tests.md | 14 ++++---------- docs/en/docs/advanced/openapi-callbacks.md | 4 ++-- docs/en/docs/alternatives.md | 2 +- docs/en/docs/features.md | 2 +- docs/en/docs/index.md | 4 ++-- docs/en/docs/tutorial/testing.md | 12 ++++++------ docs/es/docs/features.md | 2 +- docs/es/docs/index.md | 4 ++-- docs/fa/docs/index.md | 4 ++-- docs/fr/docs/index.md | 4 ++-- docs/he/docs/index.md | 2 +- docs/id/docs/index.md | 4 ++-- docs/it/docs/index.md | 4 ++-- docs/ja/docs/features.md | 2 +- docs/ja/docs/index.md | 4 ++-- docs/ja/docs/tutorial/testing.md | 8 ++++---- docs/ko/docs/index.md | 4 ++-- docs/nl/docs/index.md | 4 ++-- docs/pl/docs/index.md | 4 ++-- docs/pt/docs/features.md | 2 +- docs/pt/docs/index.md | 4 ++-- docs/ru/docs/features.md | 2 +- docs/ru/docs/index.md | 4 ++-- docs/sq/docs/index.md | 4 ++-- docs/sv/docs/index.md | 4 ++-- docs/tr/docs/features.md | 2 +- docs/tr/docs/index.md | 4 ++-- docs/uk/docs/index.md | 4 ++-- docs/zh/docs/features.md | 2 +- docs/zh/docs/index.md | 4 ++-- pyproject.toml | 3 +-- tests/test_security_http_basic_optional.py | 4 +--- tests/test_security_http_basic_realm.py | 4 +--- .../test_security_http_basic_realm_description.py | 4 +--- .../test_security/test_tutorial006.py | 4 +--- 39 files changed, 69 insertions(+), 84 deletions(-) diff --git a/README.md b/README.md index fe0ad49de1..7c4a6c4b4f 100644 --- a/README.md +++ b/README.md @@ -427,7 +427,7 @@ For a more complete example including more features, see the Strawberry and other libraries. * Many extra features (thanks to Starlette) as: * **WebSockets** - * extremely easy tests based on `requests` and `pytest` + * extremely easy tests based on HTTPX and `pytest` * **CORS** * **Cookie Sessions** * ...and more. @@ -447,7 +447,7 @@ Used by Pydantic: Used by Starlette: -* requests - Required if you want to use the `TestClient`. +* httpx - Required if you want to use the `TestClient`. * jinja2 - Required if you want to use the default template configuration. * python-multipart - Required if you want to support form "parsing", with `request.form()`. * itsdangerous - Required for `SessionMiddleware` support. diff --git a/docs/az/docs/index.md b/docs/az/docs/index.md index 3129f9dc6d..282c150322 100644 --- a/docs/az/docs/index.md +++ b/docs/az/docs/index.md @@ -446,7 +446,7 @@ Used by Pydantic: Used by Starlette: -* requests - Required if you want to use the `TestClient`. +* httpx - Required if you want to use the `TestClient`. * jinja2 - Required if you want to use the default template configuration. * python-multipart - Required if you want to support form "parsing", with `request.form()`. * itsdangerous - Required for `SessionMiddleware` support. diff --git a/docs/de/docs/features.md b/docs/de/docs/features.md index f825472a9a..f281afd1ed 100644 --- a/docs/de/docs/features.md +++ b/docs/de/docs/features.md @@ -169,7 +169,7 @@ Mit **FastAPI** bekommen Sie viele von **Starlette**'s Funktionen (da FastAPI nu * **WebSocket**-Unterstützung. * Hintergrundaufgaben im selben Prozess. * Ereignisse für das Starten und Herunterfahren. -* Testclient basierend auf `requests`. +* Testclient basierend auf HTTPX. * **CORS**, GZip, statische Dateien, Antwortfluss. * **Sitzungs und Cookie** Unterstützung. * 100% Testabdeckung. diff --git a/docs/de/docs/index.md b/docs/de/docs/index.md index 07f51b1be7..68fc8b753a 100644 --- a/docs/de/docs/index.md +++ b/docs/de/docs/index.md @@ -445,7 +445,7 @@ Used by Pydantic: Used by Starlette: -* requests - Required if you want to use the `TestClient`. +* httpx - Required if you want to use the `TestClient`. * jinja2 - Required if you want to use the default template configuration. * python-multipart - Required if you want to support form "parsing", with `request.form()`. * itsdangerous - Required for `SessionMiddleware` support. diff --git a/docs/en/docs/advanced/async-tests.md b/docs/en/docs/advanced/async-tests.md index e34f48f173..9b39d70fca 100644 --- a/docs/en/docs/advanced/async-tests.md +++ b/docs/en/docs/advanced/async-tests.md @@ -1,6 +1,6 @@ # Async Tests -You have already seen how to test your **FastAPI** applications using the provided `TestClient`, but with it, you can't test or run any other `async` function in your (synchronous) pytest functions. +You have already seen how to test your **FastAPI** applications using the provided `TestClient`. Up to now, you have only seen how to write synchronous tests, without using `async` functions. Being able to use asynchronous functions in your tests could be useful, for example, when you're querying your database asynchronously. Imagine you want to test sending requests to your FastAPI application and then verify that your backend successfully wrote the correct data in the database, while using an async database library. @@ -8,7 +8,7 @@ Let's look at how we can make that work. ## pytest.mark.anyio -If we want to call asynchronous functions in our tests, our test functions have to be asynchronous. Anyio provides a neat plugin for this, that allows us to specify that some test functions are to be called asynchronously. +If we want to call asynchronous functions in our tests, our test functions have to be asynchronous. AnyIO provides a neat plugin for this, that allows us to specify that some test functions are to be called asynchronously. ## HTTPX @@ -16,13 +16,7 @@ Even if your **FastAPI** application uses normal `def` functions instead of `asy The `TestClient` does some magic inside to call the asynchronous FastAPI application in your normal `def` test functions, using standard pytest. But that magic doesn't work anymore when we're using it inside asynchronous functions. By running our tests asynchronously, we can no longer use the `TestClient` inside our test functions. -Luckily there's a nice alternative, called HTTPX. - -HTTPX is an HTTP client for Python 3 that allows us to query our FastAPI application similarly to how we did it with the `TestClient`. - -If you're familiar with the Requests library, you'll find that the API of HTTPX is almost identical. - -The important difference for us is that with HTTPX we are not limited to synchronous, but can also make asynchronous requests. +The `TestClient` is based on HTTPX, and luckily, we can use it directly to test the API. ## Example @@ -85,7 +79,7 @@ This is the equivalent to: response = client.get('/') ``` -that we used to make our requests with the `TestClient`. +...that we used to make our requests with the `TestClient`. !!! tip Note that we're using async/await with the new `AsyncClient` - the request is asynchronous. diff --git a/docs/en/docs/advanced/openapi-callbacks.md b/docs/en/docs/advanced/openapi-callbacks.md index 656ddbb3f5..71924ce8b2 100644 --- a/docs/en/docs/advanced/openapi-callbacks.md +++ b/docs/en/docs/advanced/openapi-callbacks.md @@ -50,7 +50,7 @@ It could be just one or two lines of code, like: ```Python callback_url = "https://example.com/api/v1/invoices/events/" -requests.post(callback_url, json={"description": "Invoice paid", "paid": True}) +httpx.post(callback_url, json={"description": "Invoice paid", "paid": True}) ``` But possibly the most important part of the callback is making sure that your API user (the external developer) implements the *external API* correctly, according to the data that *your API* is going to send in the request body of the callback, etc. @@ -64,7 +64,7 @@ This example doesn't implement the callback itself (that could be just a line of !!! tip The actual callback is just an HTTP request. - When implementing the callback yourself, you could use something like HTTPX or Requests. + When implementing the callback yourself, you could use something like HTTPX or Requests. ## Write the callback documentation code diff --git a/docs/en/docs/alternatives.md b/docs/en/docs/alternatives.md index bcd406bf9d..0f074ccf32 100644 --- a/docs/en/docs/alternatives.md +++ b/docs/en/docs/alternatives.md @@ -367,7 +367,7 @@ It has: * WebSocket support. * In-process background tasks. * Startup and shutdown events. -* Test client built on requests. +* Test client built on HTTPX. * CORS, GZip, Static Files, Streaming responses. * Session and Cookie support. * 100% test coverage. diff --git a/docs/en/docs/features.md b/docs/en/docs/features.md index 02bb3ac1f2..387ff86c99 100644 --- a/docs/en/docs/features.md +++ b/docs/en/docs/features.md @@ -166,7 +166,7 @@ With **FastAPI** you get all of **Starlette**'s features (as FastAPI is just Sta * **WebSocket** support. * In-process background tasks. * Startup and shutdown events. -* Test client built on `requests`. +* Test client built on HTTPX. * **CORS**, GZip, Static Files, Streaming responses. * **Session and Cookie** support. * 100% test coverage. diff --git a/docs/en/docs/index.md b/docs/en/docs/index.md index 1ad9c76068..deb8ab5d54 100644 --- a/docs/en/docs/index.md +++ b/docs/en/docs/index.md @@ -424,7 +424,7 @@ For a more complete example including more features, see the Strawberry and other libraries. * Many extra features (thanks to Starlette) as: * **WebSockets** - * extremely easy tests based on `requests` and `pytest` + * extremely easy tests based on HTTPX and `pytest` * **CORS** * **Cookie Sessions** * ...and more. @@ -444,7 +444,7 @@ Used by Pydantic: Used by Starlette: -* requests - Required if you want to use the `TestClient`. +* httpx - Required if you want to use the `TestClient`. * jinja2 - Required if you want to use the default template configuration. * python-multipart - Required if you want to support form "parsing", with `request.form()`. * itsdangerous - Required for `SessionMiddleware` support. diff --git a/docs/en/docs/tutorial/testing.md b/docs/en/docs/tutorial/testing.md index d2ccd7dc77..be07aab37d 100644 --- a/docs/en/docs/tutorial/testing.md +++ b/docs/en/docs/tutorial/testing.md @@ -2,16 +2,16 @@ Thanks to Starlette, testing **FastAPI** applications is easy and enjoyable. -It is based on Requests, so it's very familiar and intuitive. +It is based on HTTPX, which in turn is designed based on Requests, so it's very familiar and intuitive. With it, you can use pytest directly with **FastAPI**. ## Using `TestClient` !!! info - To use `TestClient`, first install `requests`. + To use `TestClient`, first install `httpx`. - E.g. `pip install requests`. + E.g. `pip install httpx`. Import `TestClient`. @@ -19,7 +19,7 @@ Create a `TestClient` by passing your **FastAPI** application to it. Create functions with a name that starts with `test_` (this is standard `pytest` conventions). -Use the `TestClient` object the same way as you do with `requests`. +Use the `TestClient` object the same way as you do with `httpx`. Write simple `assert` statements with the standard Python expressions that you need to check (again, standard `pytest`). @@ -130,7 +130,7 @@ You could then update `test_main.py` with the extended tests: {!> ../../../docs_src/app_testing/app_b/test_main.py!} ``` -Whenever you need the client to pass information in the request and you don't know how to, you can search (Google) how to do it in `requests`. +Whenever you need the client to pass information in the request and you don't know how to, you can search (Google) how to do it in `httpx`, or even how to do it with `requests`, as HTTPX's design is based on Requests' design. Then you just do the same in your tests. @@ -142,7 +142,7 @@ E.g.: * To pass *headers*, use a `dict` in the `headers` parameter. * For *cookies*, a `dict` in the `cookies` parameter. -For more information about how to pass data to the backend (using `requests` or the `TestClient`) check the Requests documentation. +For more information about how to pass data to the backend (using `httpx` or the `TestClient`) check the HTTPX documentation. !!! info Note that the `TestClient` receives data that can be converted to JSON, not Pydantic models. diff --git a/docs/es/docs/features.md b/docs/es/docs/features.md index 3c59eb88c0..5d6b6509a7 100644 --- a/docs/es/docs/features.md +++ b/docs/es/docs/features.md @@ -167,7 +167,7 @@ Con **FastAPI** obtienes todas las características de **Starlette** (porque Fas * Soporte para **GraphQL**. * Tareas en background. * Eventos de startup y shutdown. -* Cliente de pruebas construido con `requests`. +* Cliente de pruebas construido con HTTPX. * **CORS**, GZip, Static Files, Streaming responses. * Soporte para **Session and Cookie**. * Cobertura de pruebas al 100%. diff --git a/docs/es/docs/index.md b/docs/es/docs/index.md index aa3fa22280..727a6617b5 100644 --- a/docs/es/docs/index.md +++ b/docs/es/docs/index.md @@ -418,7 +418,7 @@ Para un ejemplo más completo que incluye más características ve el requests - Requerido si quieres usar el `TestClient`. +* httpx - Requerido si quieres usar el `TestClient`. * jinja2 - Requerido si quieres usar la configuración por defecto de templates. * python-multipart - Requerido si quieres dar soporte a "parsing" de formularios, con `request.form()`. * itsdangerous - Requerido para dar soporte a `SessionMiddleware`. diff --git a/docs/fa/docs/index.md b/docs/fa/docs/index.md index 0f7cd569ae..dfc4d24e33 100644 --- a/docs/fa/docs/index.md +++ b/docs/fa/docs/index.md @@ -421,7 +421,7 @@ item: Item * قابلیت‌های اضافی دیگر (بر اساس Starlette) شامل: * **وب‌سوکت** * **GraphQL** - * تست‌های خودکار آسان مبتنی بر `requests` و `pytest` + * تست‌های خودکار آسان مبتنی بر HTTPX و `pytest` * **CORS** * **Cookie Sessions** * و موارد بیشمار دیگر. @@ -441,7 +441,7 @@ item: Item استفاده شده توسط Starlette: -* requests - در صورتی که می‌خواهید از `TestClient` استفاده کنید. +* HTTPX - در صورتی که می‌خواهید از `TestClient` استفاده کنید. * aiofiles - در صورتی که می‌خواهید از `FileResponse` و `StaticFiles` استفاده کنید. * jinja2 - در صورتی که بخواهید از پیکربندی پیش‌فرض برای قالب‌ها استفاده کنید. * python-multipart - در صورتی که بخواهید با استفاده از `request.form()` از قابلیت "تجزیه (parse)" فرم استفاده کنید. diff --git a/docs/fr/docs/index.md b/docs/fr/docs/index.md index 6952044588..e7fb9947d5 100644 --- a/docs/fr/docs/index.md +++ b/docs/fr/docs/index.md @@ -426,7 +426,7 @@ For a more complete example including more features, see the requests - Required if you want to use the `TestClient`. +* HTTPX - Required if you want to use the `TestClient`. * jinja2 - Required if you want to use the default template configuration. * python-multipart - Required if you want to support form "parsing", with `request.form()`. * itsdangerous - Required for `SessionMiddleware` support. diff --git a/docs/he/docs/index.md b/docs/he/docs/index.md index fa63d8cb7c..19f2f20413 100644 --- a/docs/he/docs/index.md +++ b/docs/he/docs/index.md @@ -445,7 +445,7 @@ item: Item בשימוש Starlette: -- requests - דרוש אם ברצונכם להשתמש ב - `TestClient`. +- httpx - דרוש אם ברצונכם להשתמש ב - `TestClient`. - jinja2 - דרוש אם ברצונכם להשתמש בברירת המחדל של תצורת הטמפלייטים. - python-multipart - דרוש אם ברצונכם לתמוך ב "פרסור" טפסים, באצמעות request.form(). - itsdangerous - דרוש אם ברצונכם להשתמש ב - `SessionMiddleware`. diff --git a/docs/id/docs/index.md b/docs/id/docs/index.md index 3129f9dc6d..66fc2859e7 100644 --- a/docs/id/docs/index.md +++ b/docs/id/docs/index.md @@ -426,7 +426,7 @@ For a more complete example including more features, see the requests - Required if you want to use the `TestClient`. +* httpx - Required if you want to use the `TestClient`. * jinja2 - Required if you want to use the default template configuration. * python-multipart - Required if you want to support form "parsing", with `request.form()`. * itsdangerous - Required for `SessionMiddleware` support. diff --git a/docs/it/docs/index.md b/docs/it/docs/index.md index 852a5e56e8..9d95dd6d72 100644 --- a/docs/it/docs/index.md +++ b/docs/it/docs/index.md @@ -423,7 +423,7 @@ For a more complete example including more features, see the requests - Required if you want to use the `TestClient`. +* httpx - Required if you want to use the `TestClient`. * jinja2 - Required if you want to use the default template configuration. * python-multipart - Required if you want to support form "parsing", with `request.form()`. * itsdangerous - Required for `SessionMiddleware` support. diff --git a/docs/ja/docs/features.md b/docs/ja/docs/features.md index 5ea68515da..a40b48cf0e 100644 --- a/docs/ja/docs/features.md +++ b/docs/ja/docs/features.md @@ -169,7 +169,7 @@ FastAPIには非常に使いやすく、非常に強力なrequests - 使用 `TestClient` 时安装。 +* httpx - 使用 `TestClient` 时安装。 * jinja2 - 使用默认模板配置时安装。 * python-multipart - 需要通过 `request.form()` 对表单进行「解析」时安装。 * itsdangerous - 需要 `SessionMiddleware` 支持时安装。 diff --git a/pyproject.toml b/pyproject.toml index fc4602ea8e..af20c8ef78 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -56,7 +56,6 @@ test = [ "flake8 >=3.8.3,<6.0.0", "black == 22.8.0", "isort >=5.0.6,<6.0.0", - "requests >=2.24.0,<3.0.0", "httpx >=0.23.0,<0.24.0", "email_validator >=1.1.1,<2.0.0", # TODO: once removing databases from tutorial, upgrade SQLAlchemy @@ -94,7 +93,7 @@ dev = [ "pre-commit >=2.17.0,<3.0.0", ] all = [ - "requests >=2.24.0,<3.0.0", + "httpx >=0.23.0,<0.24.0", "jinja2 >=2.11.2,<4.0.0", "python-multipart >=0.0.5,<0.0.6", "itsdangerous >=1.1.0,<3.0.0", diff --git a/tests/test_security_http_basic_optional.py b/tests/test_security_http_basic_optional.py index 289bd5c74c..91824d2234 100644 --- a/tests/test_security_http_basic_optional.py +++ b/tests/test_security_http_basic_optional.py @@ -4,7 +4,6 @@ from typing import Optional from fastapi import FastAPI, Security from fastapi.security import HTTPBasic, HTTPBasicCredentials from fastapi.testclient import TestClient -from requests.auth import HTTPBasicAuth app = FastAPI() @@ -51,8 +50,7 @@ def test_openapi_schema(): def test_security_http_basic(): - auth = HTTPBasicAuth(username="john", password="secret") - response = client.get("/users/me", auth=auth) + response = client.get("/users/me", auth=("john", "secret")) assert response.status_code == 200, response.text assert response.json() == {"username": "john", "password": "secret"} diff --git a/tests/test_security_http_basic_realm.py b/tests/test_security_http_basic_realm.py index 54867c2e01..6d760c0f92 100644 --- a/tests/test_security_http_basic_realm.py +++ b/tests/test_security_http_basic_realm.py @@ -3,7 +3,6 @@ from base64 import b64encode from fastapi import FastAPI, Security from fastapi.security import HTTPBasic, HTTPBasicCredentials from fastapi.testclient import TestClient -from requests.auth import HTTPBasicAuth app = FastAPI() @@ -48,8 +47,7 @@ def test_openapi_schema(): def test_security_http_basic(): - auth = HTTPBasicAuth(username="john", password="secret") - response = client.get("/users/me", auth=auth) + response = client.get("/users/me", auth=("john", "secret")) assert response.status_code == 200, response.text assert response.json() == {"username": "john", "password": "secret"} diff --git a/tests/test_security_http_basic_realm_description.py b/tests/test_security_http_basic_realm_description.py index 6ff9d9d07f..7cc5475614 100644 --- a/tests/test_security_http_basic_realm_description.py +++ b/tests/test_security_http_basic_realm_description.py @@ -3,7 +3,6 @@ from base64 import b64encode from fastapi import FastAPI, Security from fastapi.security import HTTPBasic, HTTPBasicCredentials from fastapi.testclient import TestClient -from requests.auth import HTTPBasicAuth app = FastAPI() @@ -54,8 +53,7 @@ def test_openapi_schema(): def test_security_http_basic(): - auth = HTTPBasicAuth(username="john", password="secret") - response = client.get("/users/me", auth=auth) + response = client.get("/users/me", auth=("john", "secret")) assert response.status_code == 200, response.text assert response.json() == {"username": "john", "password": "secret"} diff --git a/tests/test_tutorial/test_security/test_tutorial006.py b/tests/test_tutorial/test_security/test_tutorial006.py index 3b0a36ebca..bbfef9f7c4 100644 --- a/tests/test_tutorial/test_security/test_tutorial006.py +++ b/tests/test_tutorial/test_security/test_tutorial006.py @@ -1,7 +1,6 @@ from base64 import b64encode from fastapi.testclient import TestClient -from requests.auth import HTTPBasicAuth from docs_src.security.tutorial006 import app @@ -38,8 +37,7 @@ def test_openapi_schema(): def test_security_http_basic(): - auth = HTTPBasicAuth(username="john", password="secret") - response = client.get("/users/me", auth=auth) + response = client.get("/users/me", auth=("john", "secret")) assert response.status_code == 200, response.text assert response.json() == {"username": "john", "password": "secret"} From 1c93d5523a74fa6fe47534ad0e01392e20b31087 Mon Sep 17 00:00:00 2001 From: github-actions Date: Sun, 13 Nov 2022 15:20:44 +0000 Subject: [PATCH 45/97] =?UTF-8?q?=F0=9F=93=9D=20Update=20release=20notes?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docs/en/docs/release-notes.md | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/en/docs/release-notes.md b/docs/en/docs/release-notes.md index b6c4f4a9a6..18a9efbdac 100644 --- a/docs/en/docs/release-notes.md +++ b/docs/en/docs/release-notes.md @@ -2,6 +2,7 @@ ## Latest Changes +* 📝 Update references to Requests for tests to HTTPX, and add HTTPX to extras. PR [#5628](https://github.com/tiangolo/fastapi/pull/5628) by [@tiangolo](https://github.com/tiangolo). * 🌐 Fix highlight lines for Japanese translation for `docs/tutorial/query-params.md`. PR [#2969](https://github.com/tiangolo/fastapi/pull/2969) by [@ftnext](https://github.com/ftnext). * ⬆ Upgrade Starlette to `0.21.0`, including the new [`TestClient` based on HTTPX](https://github.com/encode/starlette/releases/tag/0.21.0). PR [#5471](https://github.com/tiangolo/fastapi/pull/5471) by [@pawelrubin](https://github.com/pawelrubin). * 🌐 Add French translation for `docs/fr/docs/advanced/additional-status-code.md`. PR [#5477](https://github.com/tiangolo/fastapi/pull/5477) by [@axel584](https://github.com/axel584). From d537ee93d707d392d75ffbe7ff08e4ff70b75729 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebasti=C3=A1n=20Ram=C3=ADrez?= Date: Sun, 13 Nov 2022 17:10:54 +0100 Subject: [PATCH 46/97] =?UTF-8?q?=E2=9C=A8=20Re-export=20Starlette's=20`We?= =?UTF-8?q?bSocketException`=20and=20add=20it=20to=20docs=20(#5629)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docs/en/docs/advanced/websockets.md | 6 ++---- docs_src/websockets/tutorial002.py | 12 ++++++++++-- fastapi/__init__.py | 1 + fastapi/exceptions.py | 1 + 4 files changed, 14 insertions(+), 6 deletions(-) diff --git a/docs/en/docs/advanced/websockets.md b/docs/en/docs/advanced/websockets.md index 0e9bc5b06b..3cf840819f 100644 --- a/docs/en/docs/advanced/websockets.md +++ b/docs/en/docs/advanced/websockets.md @@ -112,17 +112,15 @@ In WebSocket endpoints you can import from `fastapi` and use: They work the same way as for other FastAPI endpoints/*path operations*: -```Python hl_lines="58-65 68-83" +```Python hl_lines="66-77 76-91" {!../../../docs_src/websockets/tutorial002.py!} ``` !!! info - In a WebSocket it doesn't really make sense to raise an `HTTPException`. So it's better to close the WebSocket connection directly. + As this is a WebSocket it doesn't really make sense to raise an `HTTPException`, instead we raise a `WebSocketException`. You can use a closing code from the valid codes defined in the specification. - In the future, there will be a `WebSocketException` that you will be able to `raise` from anywhere, and add exception handlers for it. It depends on the PR #527 in Starlette. - ### Try the WebSockets with dependencies If your file is named `main.py`, run your application with: diff --git a/docs_src/websockets/tutorial002.py b/docs_src/websockets/tutorial002.py index cf5c7e805a..cab749e4db 100644 --- a/docs_src/websockets/tutorial002.py +++ b/docs_src/websockets/tutorial002.py @@ -1,6 +1,14 @@ from typing import Union -from fastapi import Cookie, Depends, FastAPI, Query, WebSocket, status +from fastapi import ( + Cookie, + Depends, + FastAPI, + Query, + WebSocket, + WebSocketException, + status, +) from fastapi.responses import HTMLResponse app = FastAPI() @@ -61,7 +69,7 @@ async def get_cookie_or_token( token: Union[str, None] = Query(default=None), ): if session is None and token is None: - await websocket.close(code=status.WS_1008_POLICY_VIOLATION) + raise WebSocketException(code=status.WS_1008_POLICY_VIOLATION) return session or token diff --git a/fastapi/__init__.py b/fastapi/__init__.py index a5c7aeb176..70f363c89c 100644 --- a/fastapi/__init__.py +++ b/fastapi/__init__.py @@ -8,6 +8,7 @@ from .applications import FastAPI as FastAPI from .background import BackgroundTasks as BackgroundTasks from .datastructures import UploadFile as UploadFile from .exceptions import HTTPException as HTTPException +from .exceptions import WebSocketException as WebSocketException from .param_functions import Body as Body from .param_functions import Cookie as Cookie from .param_functions import Depends as Depends diff --git a/fastapi/exceptions.py b/fastapi/exceptions.py index 0f50acc6c5..ca097b1cef 100644 --- a/fastapi/exceptions.py +++ b/fastapi/exceptions.py @@ -3,6 +3,7 @@ from typing import Any, Dict, Optional, Sequence, Type from pydantic import BaseModel, ValidationError, create_model from pydantic.error_wrappers import ErrorList from starlette.exceptions import HTTPException as StarletteHTTPException +from starlette.exceptions import WebSocketException as WebSocketException # noqa: F401 class HTTPException(StarletteHTTPException): From bcd9ab95e1fc4b702350b3075f27672ab6e356ba Mon Sep 17 00:00:00 2001 From: github-actions Date: Sun, 13 Nov 2022 16:11:29 +0000 Subject: [PATCH 47/97] =?UTF-8?q?=F0=9F=93=9D=20Update=20release=20notes?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docs/en/docs/release-notes.md | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/en/docs/release-notes.md b/docs/en/docs/release-notes.md index 18a9efbdac..ae78141d0b 100644 --- a/docs/en/docs/release-notes.md +++ b/docs/en/docs/release-notes.md @@ -2,6 +2,7 @@ ## Latest Changes +* ✨ Re-export Starlette's `WebSocketException` and add it to docs. PR [#5629](https://github.com/tiangolo/fastapi/pull/5629) by [@tiangolo](https://github.com/tiangolo). * 📝 Update references to Requests for tests to HTTPX, and add HTTPX to extras. PR [#5628](https://github.com/tiangolo/fastapi/pull/5628) by [@tiangolo](https://github.com/tiangolo). * 🌐 Fix highlight lines for Japanese translation for `docs/tutorial/query-params.md`. PR [#2969](https://github.com/tiangolo/fastapi/pull/2969) by [@ftnext](https://github.com/ftnext). * ⬆ Upgrade Starlette to `0.21.0`, including the new [`TestClient` based on HTTPX](https://github.com/encode/starlette/releases/tag/0.21.0). PR [#5471](https://github.com/tiangolo/fastapi/pull/5471) by [@pawelrubin](https://github.com/pawelrubin). From fa74093440aaff710009ed23646eb804417b26fc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebasti=C3=A1n=20Ram=C3=ADrez?= Date: Sun, 13 Nov 2022 19:19:04 +0100 Subject: [PATCH 48/97] =?UTF-8?q?=E2=9C=A8=20Use=20Ruff=20for=20linting=20?= =?UTF-8?q?(#5630)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .flake8 | 5 ---- .pre-commit-config.yaml | 15 ++++-------- docs_src/security/tutorial005.py | 2 +- docs_src/security/tutorial005_py310.py | 2 +- docs_src/security/tutorial005_py39.py | 2 +- fastapi/dependencies/utils.py | 12 +++++----- fastapi/routing.py | 2 +- pyproject.toml | 32 +++++++++++++++++++++++--- scripts/docs.py | 4 ++-- scripts/format.sh | 2 +- scripts/lint.sh | 2 +- tests/test_custom_route_class.py | 6 ++--- tests/test_ws_router.py | 2 +- 13 files changed, 51 insertions(+), 37 deletions(-) delete mode 100644 .flake8 diff --git a/.flake8 b/.flake8 deleted file mode 100644 index 47ef7c07fc..0000000000 --- a/.flake8 +++ /dev/null @@ -1,5 +0,0 @@ -[flake8] -max-line-length = 88 -select = C,E,F,W,B,B9 -ignore = E203, E501, W503 -exclude = __init__.py diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index bd5b8641ad..e59e05abe4 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -18,19 +18,12 @@ repos: args: - --py3-plus - --keep-runtime-typing -- repo: https://github.com/PyCQA/autoflake - rev: v1.7.7 +- repo: https://github.com/charliermarsh/ruff-pre-commit + rev: v0.0.114 hooks: - - id: autoflake + - id: ruff args: - - --recursive - - --in-place - - --remove-all-unused-imports - - --remove-unused-variables - - --expand-star-imports - - --exclude - - __init__.py - - --remove-duplicate-keys + - --fix - repo: https://github.com/pycqa/isort rev: 5.10.1 hooks: diff --git a/docs_src/security/tutorial005.py b/docs_src/security/tutorial005.py index ab3af9a6a9..bd0a33581c 100644 --- a/docs_src/security/tutorial005.py +++ b/docs_src/security/tutorial005.py @@ -107,7 +107,7 @@ async def get_current_user( if security_scopes.scopes: authenticate_value = f'Bearer scope="{security_scopes.scope_str}"' else: - authenticate_value = f"Bearer" + authenticate_value = "Bearer" credentials_exception = HTTPException( status_code=status.HTTP_401_UNAUTHORIZED, detail="Could not validate credentials", diff --git a/docs_src/security/tutorial005_py310.py b/docs_src/security/tutorial005_py310.py index c6a095d2cc..ba756ef4f4 100644 --- a/docs_src/security/tutorial005_py310.py +++ b/docs_src/security/tutorial005_py310.py @@ -106,7 +106,7 @@ async def get_current_user( if security_scopes.scopes: authenticate_value = f'Bearer scope="{security_scopes.scope_str}"' else: - authenticate_value = f"Bearer" + authenticate_value = "Bearer" credentials_exception = HTTPException( status_code=status.HTTP_401_UNAUTHORIZED, detail="Could not validate credentials", diff --git a/docs_src/security/tutorial005_py39.py b/docs_src/security/tutorial005_py39.py index 38391308af..9e4dbcffba 100644 --- a/docs_src/security/tutorial005_py39.py +++ b/docs_src/security/tutorial005_py39.py @@ -107,7 +107,7 @@ async def get_current_user( if security_scopes.scopes: authenticate_value = f'Bearer scope="{security_scopes.scope_str}"' else: - authenticate_value = f"Bearer" + authenticate_value = "Bearer" credentials_exception = HTTPException( status_code=status.HTTP_401_UNAUTHORIZED, detail="Could not validate credentials", diff --git a/fastapi/dependencies/utils.py b/fastapi/dependencies/utils.py index 64a6c12765..3df5ccfc8b 100644 --- a/fastapi/dependencies/utils.py +++ b/fastapi/dependencies/utils.py @@ -426,21 +426,21 @@ def is_coroutine_callable(call: Callable[..., Any]) -> bool: return inspect.iscoroutinefunction(call) if inspect.isclass(call): return False - dunder_call = getattr(call, "__call__", None) + dunder_call = getattr(call, "__call__", None) # noqa: B004 return inspect.iscoroutinefunction(dunder_call) def is_async_gen_callable(call: Callable[..., Any]) -> bool: if inspect.isasyncgenfunction(call): return True - dunder_call = getattr(call, "__call__", None) + dunder_call = getattr(call, "__call__", None) # noqa: B004 return inspect.isasyncgenfunction(dunder_call) def is_gen_callable(call: Callable[..., Any]) -> bool: if inspect.isgeneratorfunction(call): return True - dunder_call = getattr(call, "__call__", None) + dunder_call = getattr(call, "__call__", None) # noqa: B004 return inspect.isgeneratorfunction(dunder_call) @@ -724,14 +724,14 @@ def get_body_field(*, dependant: Dependant, name: str) -> Optional[ModelField]: # in case a sub-dependency is evaluated with a single unique body field # That is combined (embedded) with other body fields for param in flat_dependant.body_params: - setattr(param.field_info, "embed", True) + setattr(param.field_info, "embed", True) # noqa: B010 model_name = "Body_" + name BodyModel: Type[BaseModel] = create_model(model_name) for f in flat_dependant.body_params: BodyModel.__fields__[f.name] = f required = any(True for f in flat_dependant.body_params if f.required) - BodyFieldInfo_kwargs: Dict[str, Any] = dict(default=None) + BodyFieldInfo_kwargs: Dict[str, Any] = {"default": None} if any(isinstance(f.field_info, params.File) for f in flat_dependant.body_params): BodyFieldInfo: Type[params.Body] = params.File elif any(isinstance(f.field_info, params.Form) for f in flat_dependant.body_params): @@ -740,7 +740,7 @@ def get_body_field(*, dependant: Dependant, name: str) -> Optional[ModelField]: BodyFieldInfo = params.Body body_param_media_types = [ - getattr(f.field_info, "media_type") + f.field_info.media_type for f in flat_dependant.body_params if isinstance(f.field_info, params.Body) ] diff --git a/fastapi/routing.py b/fastapi/routing.py index 8c0bec5e61..9a7d88efc8 100644 --- a/fastapi/routing.py +++ b/fastapi/routing.py @@ -701,7 +701,7 @@ class APIRouter(routing.Router): ), "A path prefix must not end with '/', as the routes will start with '/'" else: for r in router.routes: - path = getattr(r, "path") + path = getattr(r, "path") # noqa: B009 name = getattr(r, "name", "unknown") if path is not None and not path: raise Exception( diff --git a/pyproject.toml b/pyproject.toml index af20c8ef78..3f7fd4e00e 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -53,7 +53,7 @@ test = [ "pytest >=7.1.3,<8.0.0", "coverage[toml] >= 6.5.0,<7.0", "mypy ==0.982", - "flake8 >=3.8.3,<6.0.0", + "ruff ==0.0.114", "black == 22.8.0", "isort >=5.0.6,<6.0.0", "httpx >=0.23.0,<0.24.0", @@ -87,8 +87,7 @@ doc = [ "pyyaml >=5.3.1,<7.0.0", ] dev = [ - "autoflake >=1.4.0,<2.0.0", - "flake8 >=3.8.3,<6.0.0", + "ruff ==0.0.114", "uvicorn[standard] >=0.12.0,<0.19.0", "pre-commit >=2.17.0,<3.0.0", ] @@ -156,3 +155,30 @@ source = [ "fastapi" ] context = '${CONTEXT}' + +[tool.ruff] +select = [ + "E", # pycodestyle errors + "W", # pycodestyle warnings + "F", # pyflakes + # "I", # isort + "C", # flake8-comprehensions + "B", # flake8-bugbear +] +ignore = [ + "E501", # line too long, handled by black + "B008", # do not perform function calls in argument defaults +] + +[tool.ruff.per-file-ignores] +"__init__.py" = ["F401"] +"docs_src/dependencies/tutorial007.py" = ["F821"] +"docs_src/dependencies/tutorial008.py" = ["F821"] +"docs_src/dependencies/tutorial009.py" = ["F821"] +"docs_src/dependencies/tutorial010.py" = ["F821"] +"docs_src/custom_response/tutorial007.py" = ["B007"] +"docs_src/dataclasses/tutorial003.py" = ["I001"] + + +[tool.ruff.isort] +known-third-party = ["fastapi", "pydantic", "starlette"] diff --git a/scripts/docs.py b/scripts/docs.py index d5fbacf59d..622ba9202e 100644 --- a/scripts/docs.py +++ b/scripts/docs.py @@ -332,7 +332,7 @@ def serve(): os.chdir("site") server_address = ("", 8008) server = HTTPServer(server_address, SimpleHTTPRequestHandler) - typer.echo(f"Serving at: http://127.0.0.1:8008") + typer.echo("Serving at: http://127.0.0.1:8008") server.serve_forever() @@ -420,7 +420,7 @@ def get_file_to_nav_map(nav: list) -> Dict[str, Tuple[str, ...]]: file_to_nav = {} for item in nav: if type(item) is str: - file_to_nav[item] = tuple() + file_to_nav[item] = () elif type(item) is dict: item_key = list(item.keys())[0] sub_nav = item[item_key] diff --git a/scripts/format.sh b/scripts/format.sh index ee4fbf1a5b..3ac1fead86 100755 --- a/scripts/format.sh +++ b/scripts/format.sh @@ -1,6 +1,6 @@ #!/bin/sh -e set -x -autoflake --remove-all-unused-imports --recursive --remove-unused-variables --in-place docs_src fastapi tests scripts --exclude=__init__.py +ruff fastapi tests docs_src scripts --fix black fastapi tests docs_src scripts isort fastapi tests docs_src scripts diff --git a/scripts/lint.sh b/scripts/lint.sh index 2e2072cf18..0feb973a87 100755 --- a/scripts/lint.sh +++ b/scripts/lint.sh @@ -4,6 +4,6 @@ set -e set -x mypy fastapi -flake8 fastapi tests +ruff fastapi tests docs_src scripts black fastapi tests --check isort fastapi tests docs_src scripts --check-only diff --git a/tests/test_custom_route_class.py b/tests/test_custom_route_class.py index 1a9ea7199a..2e8d9c6de5 100644 --- a/tests/test_custom_route_class.py +++ b/tests/test_custom_route_class.py @@ -110,6 +110,6 @@ def test_route_classes(): for r in app.router.routes: assert isinstance(r, Route) routes[r.path] = r - assert getattr(routes["/a/"], "x_type") == "A" - assert getattr(routes["/a/b/"], "x_type") == "B" - assert getattr(routes["/a/b/c/"], "x_type") == "C" + assert getattr(routes["/a/"], "x_type") == "A" # noqa: B009 + assert getattr(routes["/a/b/"], "x_type") == "B" # noqa: B009 + assert getattr(routes["/a/b/c/"], "x_type") == "C" # noqa: B009 diff --git a/tests/test_ws_router.py b/tests/test_ws_router.py index 206d743bac..c312821e96 100644 --- a/tests/test_ws_router.py +++ b/tests/test_ws_router.py @@ -111,7 +111,7 @@ def test_router_ws_depends(): def test_router_ws_depends_with_override(): client = TestClient(app) - app.dependency_overrides[ws_dependency] = lambda: "Override" + app.dependency_overrides[ws_dependency] = lambda: "Override" # noqa: E731 with client.websocket_connect("/router-ws-depends/") as websocket: assert websocket.receive_text() == "Override" From a0852e2f5350271805b7c690e3bda0ea70153c23 Mon Sep 17 00:00:00 2001 From: github-actions Date: Sun, 13 Nov 2022 18:19:43 +0000 Subject: [PATCH 49/97] =?UTF-8?q?=F0=9F=93=9D=20Update=20release=20notes?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docs/en/docs/release-notes.md | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/en/docs/release-notes.md b/docs/en/docs/release-notes.md index ae78141d0b..2ec54c52cb 100644 --- a/docs/en/docs/release-notes.md +++ b/docs/en/docs/release-notes.md @@ -2,6 +2,7 @@ ## Latest Changes +* ✨ Use Ruff for linting. PR [#5630](https://github.com/tiangolo/fastapi/pull/5630) by [@tiangolo](https://github.com/tiangolo). * ✨ Re-export Starlette's `WebSocketException` and add it to docs. PR [#5629](https://github.com/tiangolo/fastapi/pull/5629) by [@tiangolo](https://github.com/tiangolo). * 📝 Update references to Requests for tests to HTTPX, and add HTTPX to extras. PR [#5628](https://github.com/tiangolo/fastapi/pull/5628) by [@tiangolo](https://github.com/tiangolo). * 🌐 Fix highlight lines for Japanese translation for `docs/tutorial/query-params.md`. PR [#2969](https://github.com/tiangolo/fastapi/pull/2969) by [@ftnext](https://github.com/ftnext). From 50ea75ae98a319a059adeb6d6abcc09d4fbd2554 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebasti=C3=A1n=20Ram=C3=ADrez?= Date: Sun, 13 Nov 2022 20:34:09 +0100 Subject: [PATCH 50/97] =?UTF-8?q?=F0=9F=93=9D=20Update=20Help=20FastAPI:?= =?UTF-8?q?=20Help=20Maintain=20FastAPI=20(#5632)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docs/en/docs/help-fastapi.md | 114 ++++++++++++++++++++++++++++++++++- 1 file changed, 112 insertions(+), 2 deletions(-) diff --git a/docs/en/docs/help-fastapi.md b/docs/en/docs/help-fastapi.md index 8d8d708ed9..047462c413 100644 --- a/docs/en/docs/help-fastapi.md +++ b/docs/en/docs/help-fastapi.md @@ -47,7 +47,7 @@ You can: * Follow me on **GitHub**. * See other Open Source projects I have created that could help you. * Follow me to see when I create a new Open Source project. -* Follow me on **Twitter**. +* Follow me on **Twitter** or Mastodon. * Tell me how you use FastAPI (I love to hear that). * Hear when I make announcements or release new tools. * You can also follow @fastapi on Twitter (a separate account). @@ -67,13 +67,54 @@ I love to hear about how **FastAPI** is being used, what you have liked in it, i * Vote for **FastAPI** in Slant. * Vote for **FastAPI** in AlternativeTo. +* Say you use **FastAPI** on StackShare. ## Help others with issues in GitHub -You can see existing issues and try and help others, most of the times they are questions that you might already know the answer for. 🤓 +You can see existing issues and try and help others, most of the times those issues are questions that you might already know the answer for. 🤓 If you are helping a lot of people with issues, you might become an official [FastAPI Expert](fastapi-people.md#experts){.internal-link target=_blank}. 🎉 +Just remember, the most important point is: try to be kind. People come with their frustrations and in many cases don't ask in the best way, but try as best as you can to be kind. 🤗 + +The idea is for the **FastAPI** community to be kind and welcoming. At the same time, don't accept bullying or disrespectful behavior towards others. We have to take care of each other. + +--- + +Here's how to help others with issues: + +### Understand the question + +* Check if you can understand what is the **purpose** and use case of the person asking. + +* Then check if the question (the vast majority are questions) is **clear**. + +* In many cases the question asked is about an imaginary solution from the user, but there might be a **better** one. If you can understand the problem and use case better, you might be able to suggest a better **alternative solution**. + +* If you can't understand the question, ask for more **details**. + +### Reproduce the problem + +For most of the cases and most of the questions there's something related to the person's **original code**. + +In many cases they will only copy a fragment of the code, but that's not enough to **reproduce the problem**. + +* You can ask them to provide a minimal, reproducible, example, that you can **copy-paste** and run locally to see the same error or behavior they are seeing, or to understand their use case better. + +* If you are feeling too generous, you can try to **create an example** like that yourself, just based on the description of the problem. Just have in mind that this might take a lot of time and it might be better to ask them to clarify the problem first. + +### Suggest solutions + +* After being able to understand the question, you can give them a possible **answer**. + +* In many cases, it's better to understand their **underlying problem or use case**, because there might be a better way to solve it than what they are trying to do. + +### Ask to close + +If they reply, there's a high chance you will have solved their problem, congrats, **you're a hero**! 🦸 + +* Now you can ask them, if that solved their problem, to **close the issue**. + ## Watch the GitHub repository You can "watch" FastAPI in GitHub (clicking the "watch" button at the top right): https://github.com/tiangolo/fastapi. 👀 @@ -91,6 +132,57 @@ You can . * `allow_credentials` - Indicate that cookies should be supported for cross-origin requests. Defaults to `False`. Also, `allow_origins` cannot be set to `['*']` for credentials to be allowed, origins must be specified. * `expose_headers` - Indicate any response headers that should be made accessible to the browser. Defaults to `[]`. * `max_age` - Sets a maximum time in seconds for browsers to cache CORS responses. Defaults to `600`. From ad0e923fed74b6cc0342a99e2f5843aedda7e6a6 Mon Sep 17 00:00:00 2001 From: github-actions Date: Sun, 13 Nov 2022 20:29:15 +0000 Subject: [PATCH 54/97] =?UTF-8?q?=F0=9F=93=9D=20Update=20release=20notes?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docs/en/docs/release-notes.md | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/en/docs/release-notes.md b/docs/en/docs/release-notes.md index 068084f628..439c0889fe 100644 --- a/docs/en/docs/release-notes.md +++ b/docs/en/docs/release-notes.md @@ -2,6 +2,7 @@ ## Latest Changes +* ✏️ Clarify docs on CORS. PR [#5627](https://github.com/tiangolo/fastapi/pull/5627) by [@paxcodes](https://github.com/paxcodes). ### Features From 9c483505e346a7a5e24dcc0c908f3d10e9d1fa08 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebasti=C3=A1n=20Ram=C3=ADrez?= Date: Sun, 13 Nov 2022 21:29:23 +0100 Subject: [PATCH 55/97] =?UTF-8?q?=E2=9C=8F=EF=B8=8F=20Tweak=20Help=20FastA?= =?UTF-8?q?PI=20from=20PR=20review=20after=20merging=20(#5633)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docs/en/docs/help-fastapi.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/en/docs/help-fastapi.md b/docs/en/docs/help-fastapi.md index 047462c413..a7ac9415fc 100644 --- a/docs/en/docs/help-fastapi.md +++ b/docs/en/docs/help-fastapi.md @@ -111,7 +111,7 @@ In many cases they will only copy a fragment of the code, but that's not enough ### Ask to close -If they reply, there's a high chance you will have solved their problem, congrats, **you're a hero**! 🦸 +If they reply, there's a high chance you would have solved their problem, congrats, **you're a hero**! 🦸 * Now you can ask them, if that solved their problem, to **close the issue**. @@ -136,7 +136,7 @@ You can =2.17.0,<3.0.0", ] all = [ - "httpx >=0.23.0,<0.24.0", - "jinja2 >=2.11.2,<4.0.0", - "python-multipart >=0.0.5,<0.0.6", - "itsdangerous >=1.1.0,<3.0.0", - "pyyaml >=5.3.1,<7.0.0", - "ujson >=4.0.1,!=4.0.2,!=4.1.0,!=4.2.0,!=4.3.0,!=5.0.0,!=5.1.0,<6.0.0", - "orjson >=3.2.1,<4.0.0", - "email_validator >=1.1.1,<2.0.0", - "uvicorn[standard] >=0.12.0,<0.19.0", + "httpx >=0.23.0", + "jinja2 >=2.11.2", + "python-multipart >=0.0.5", + "itsdangerous >=1.1.0", + "pyyaml >=5.3.1", + "ujson >=4.0.1,!=4.0.2,!=4.1.0,!=4.2.0,!=4.3.0,!=5.0.0,!=5.1.0", + "orjson >=3.2.1", + "email_validator >=1.1.1", + "uvicorn[standard] >=0.12.0", ] [tool.hatch.version] From 1d416c4c5361661d0bdbbea360cad6f38bfa8fff Mon Sep 17 00:00:00 2001 From: github-actions Date: Sun, 13 Nov 2022 20:51:19 +0000 Subject: [PATCH 58/97] =?UTF-8?q?=F0=9F=93=9D=20Update=20release=20notes?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docs/en/docs/release-notes.md | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/en/docs/release-notes.md b/docs/en/docs/release-notes.md index bd36f6d529..075bdb4ffe 100644 --- a/docs/en/docs/release-notes.md +++ b/docs/en/docs/release-notes.md @@ -2,6 +2,7 @@ ## Latest Changes +* ⬆️ Upgrade and relax dependencies for extras "all". PR [#5634](https://github.com/tiangolo/fastapi/pull/5634) by [@tiangolo](https://github.com/tiangolo). * ✏️ Tweak Help FastAPI from PR review after merging. PR [#5633](https://github.com/tiangolo/fastapi/pull/5633) by [@tiangolo](https://github.com/tiangolo). * ✏️ Clarify docs on CORS. PR [#5627](https://github.com/tiangolo/fastapi/pull/5627) by [@paxcodes](https://github.com/paxcodes). From 46a509649da88637953e0cd679ac17b05c632e42 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebasti=C3=A1n=20Ram=C3=ADrez?= Date: Sun, 13 Nov 2022 22:26:43 +0100 Subject: [PATCH 59/97] =?UTF-8?q?=F0=9F=93=9D=20Update=20release=20notes?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docs/en/docs/release-notes.md | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/docs/en/docs/release-notes.md b/docs/en/docs/release-notes.md index 075bdb4ffe..a34a5969de 100644 --- a/docs/en/docs/release-notes.md +++ b/docs/en/docs/release-notes.md @@ -2,18 +2,26 @@ ## Latest Changes -* ⬆️ Upgrade and relax dependencies for extras "all". PR [#5634](https://github.com/tiangolo/fastapi/pull/5634) by [@tiangolo](https://github.com/tiangolo). -* ✏️ Tweak Help FastAPI from PR review after merging. PR [#5633](https://github.com/tiangolo/fastapi/pull/5633) by [@tiangolo](https://github.com/tiangolo). -* ✏️ Clarify docs on CORS. PR [#5627](https://github.com/tiangolo/fastapi/pull/5627) by [@paxcodes](https://github.com/paxcodes). +Highlights of this release: + +* [Upgraded Starlette](https://github.com/encode/starlette/releases/tag/0.21.0) + * Now the `TestClient` is based on HTTPX instead of Requests. 🚀 + * There are some possible **breaking changes** in the `TestClient` usage, but [@Kludex](https://github.com/Kludex) built [bump-testclient](https://github.com/Kludex/bump-testclient) to help you automatize migrating your tests. Make sure you are using Git and that you can undo any unnecessary changes (false positive changes, etc) before using `bump-testclient`. +* New [WebSocketException (and docs)](https://fastapi.tiangolo.com/advanced/websockets/#using-depends-and-others), re-exported from Starlette. +* Upgraded and relaxed dependencies for package extras `all` (including new Uvicorn version), when you install `"fastapi[all]"`. +* New docs about how to [**Help Maintain FastAPI**](https://fastapi.tiangolo.com/help-fastapi/#help-maintain-fastapi). ### Features +* ⬆️ Upgrade and relax dependencies for extras "all". PR [#5634](https://github.com/tiangolo/fastapi/pull/5634) by [@tiangolo](https://github.com/tiangolo). * ✨ Re-export Starlette's `WebSocketException` and add it to docs. PR [#5629](https://github.com/tiangolo/fastapi/pull/5629) by [@tiangolo](https://github.com/tiangolo). * 📝 Update references to Requests for tests to HTTPX, and add HTTPX to extras. PR [#5628](https://github.com/tiangolo/fastapi/pull/5628) by [@tiangolo](https://github.com/tiangolo). * ⬆ Upgrade Starlette to `0.21.0`, including the new [`TestClient` based on HTTPX](https://github.com/encode/starlette/releases/tag/0.21.0). PR [#5471](https://github.com/tiangolo/fastapi/pull/5471) by [@pawelrubin](https://github.com/pawelrubin). ### Docs +* ✏️ Tweak Help FastAPI from PR review after merging. PR [#5633](https://github.com/tiangolo/fastapi/pull/5633) by [@tiangolo](https://github.com/tiangolo). +* ✏️ Clarify docs on CORS. PR [#5627](https://github.com/tiangolo/fastapi/pull/5627) by [@paxcodes](https://github.com/paxcodes). * 📝 Update Help FastAPI: Help Maintain FastAPI. PR [#5632](https://github.com/tiangolo/fastapi/pull/5632) by [@tiangolo](https://github.com/tiangolo). ### Translations From da1c67338f39491e85be3e5ff7b6e3ca2f347ed8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebasti=C3=A1n=20Ram=C3=ADrez?= Date: Sun, 13 Nov 2022 22:27:53 +0100 Subject: [PATCH 60/97] =?UTF-8?q?=F0=9F=94=96=20Release=20version=200.87.0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docs/en/docs/release-notes.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/docs/en/docs/release-notes.md b/docs/en/docs/release-notes.md index a34a5969de..9cc866f773 100644 --- a/docs/en/docs/release-notes.md +++ b/docs/en/docs/release-notes.md @@ -2,6 +2,9 @@ ## Latest Changes + +## 0.87.0 + Highlights of this release: * [Upgraded Starlette](https://github.com/encode/starlette/releases/tag/0.21.0) From 63a5ffcf577abc6015d021f65857b3826d8db74e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebasti=C3=A1n=20Ram=C3=ADrez?= Date: Sun, 13 Nov 2022 22:36:53 +0100 Subject: [PATCH 61/97] =?UTF-8?q?=F0=9F=94=96=20Release=20version=200.87.0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- fastapi/__init__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/fastapi/__init__.py b/fastapi/__init__.py index 70f363c89c..afdc94874c 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.86.0" +__version__ = "0.87.0" from starlette import status as status From 3c01b2469f6395c87d9a36b3bbff2222e47f95f8 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Sun, 13 Nov 2022 23:06:28 +0100 Subject: [PATCH 62/97] =?UTF-8?q?=E2=AC=86=20Bump=20black=20from=2022.8.0?= =?UTF-8?q?=20to=2022.10.0=20(#5569)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Bumps [black](https://github.com/psf/black) from 22.8.0 to 22.10.0. - [Release notes](https://github.com/psf/black/releases) - [Changelog](https://github.com/psf/black/blob/main/CHANGES.md) - [Commits](https://github.com/psf/black/compare/22.8.0...22.10.0) --- updated-dependencies: - dependency-name: black dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: Sebastián Ramírez --- pyproject.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pyproject.toml b/pyproject.toml index de6bd24f34..9549cc47da 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -54,7 +54,7 @@ test = [ "coverage[toml] >= 6.5.0,<7.0", "mypy ==0.982", "ruff ==0.0.114", - "black == 22.8.0", + "black == 22.10.0", "isort >=5.0.6,<6.0.0", "httpx >=0.23.0,<0.24.0", "email_validator >=1.1.1,<2.0.0", From 4638b2c64e259b90bef6a44748e00e405825a111 Mon Sep 17 00:00:00 2001 From: github-actions Date: Sun, 13 Nov 2022 22:07:03 +0000 Subject: [PATCH 63/97] =?UTF-8?q?=F0=9F=93=9D=20Update=20release=20notes?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docs/en/docs/release-notes.md | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/en/docs/release-notes.md b/docs/en/docs/release-notes.md index 9cc866f773..1eb2fad322 100644 --- a/docs/en/docs/release-notes.md +++ b/docs/en/docs/release-notes.md @@ -2,6 +2,7 @@ ## Latest Changes +* ⬆ Bump black from 22.8.0 to 22.10.0. PR [#5569](https://github.com/tiangolo/fastapi/pull/5569) by [@dependabot[bot]](https://github.com/apps/dependabot). ## 0.87.0 From 6883f362a54122e949b3eb622293ade1f9658513 Mon Sep 17 00:00:00 2001 From: Muhammad Abdur Rakib <103581704+rifatrakib@users.noreply.github.com> Date: Tue, 22 Nov 2022 19:29:57 +0600 Subject: [PATCH 64/97] =?UTF-8?q?=E2=9C=8F=EF=B8=8F=20Fix=20typo=20in=20do?= =?UTF-8?q?cs=20for=20`docs/en/docs/advanced/middleware.md`=20(#5376)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Fix typo in documentation A full-stop was missing in `TrustedHostMiddleware` section Co-authored-by: Sebastián Ramírez --- docs/en/docs/advanced/middleware.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/en/docs/advanced/middleware.md b/docs/en/docs/advanced/middleware.md index ed90f29be7..3bf49e3922 100644 --- a/docs/en/docs/advanced/middleware.md +++ b/docs/en/docs/advanced/middleware.md @@ -68,7 +68,7 @@ Enforces that all incoming requests have a correctly set `Host` header, in order The following arguments are supported: -* `allowed_hosts` - A list of domain names that should be allowed as hostnames. Wildcard domains such as `*.example.com` are supported for matching subdomains to allow any hostname either use `allowed_hosts=["*"]` or omit the middleware. +* `allowed_hosts` - A list of domain names that should be allowed as hostnames. Wildcard domains such as `*.example.com` are supported for matching subdomains. To allow any hostname either use `allowed_hosts=["*"]` or omit the middleware. If an incoming request does not validate correctly then a `400` response will be sent. From 0eb05cabbf9db9ce5cd121f6470b90c4003a1787 Mon Sep 17 00:00:00 2001 From: github-actions Date: Tue, 22 Nov 2022 13:30:37 +0000 Subject: [PATCH 65/97] =?UTF-8?q?=F0=9F=93=9D=20Update=20release=20notes?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docs/en/docs/release-notes.md | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/en/docs/release-notes.md b/docs/en/docs/release-notes.md index 1eb2fad322..d99f153c22 100644 --- a/docs/en/docs/release-notes.md +++ b/docs/en/docs/release-notes.md @@ -2,6 +2,7 @@ ## Latest Changes +* ✏️ Fix typo in docs for `docs/en/docs/advanced/middleware.md`. PR [#5376](https://github.com/tiangolo/fastapi/pull/5376) by [@rifatrakib](https://github.com/rifatrakib). * ⬆ Bump black from 22.8.0 to 22.10.0. PR [#5569](https://github.com/tiangolo/fastapi/pull/5569) by [@dependabot[bot]](https://github.com/apps/dependabot). ## 0.87.0 From 22837ee20255dfdbd2d0d4eb8effd3d8e5345fce Mon Sep 17 00:00:00 2001 From: Michael Adkins Date: Fri, 25 Nov 2022 05:38:55 -0600 Subject: [PATCH 66/97] =?UTF-8?q?=F0=9F=91=B7=20Update=20`setup-python`=20?= =?UTF-8?q?action=20in=20tests=20to=20use=20new=20caching=20feature=20(#56?= =?UTF-8?q?80)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .github/workflows/test.yml | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 7f87be700b..85779af18b 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -19,15 +19,13 @@ jobs: - uses: actions/checkout@v3 - name: Set up Python uses: actions/setup-python@v4 + id: setup-python with: python-version: ${{ matrix.python-version }} - - uses: actions/cache@v3 - id: cache - with: - path: ${{ env.pythonLocation }} - key: ${{ runner.os }}-python-${{ env.pythonLocation }}-${{ hashFiles('pyproject.toml') }}-test-v02 + cache: "pip" + cache-dependency-path: pyproject.toml - name: Install Dependencies - if: steps.cache.outputs.cache-hit != 'true' + if: steps.setup-python.outputs.cache-hit != 'true' run: pip install -e .[all,dev,doc,test] - name: Lint run: bash scripts/lint.sh From ec30c3001d0ab2f3c2a0ac5402b31d6b40b17af6 Mon Sep 17 00:00:00 2001 From: github-actions Date: Fri, 25 Nov 2022 11:39:33 +0000 Subject: [PATCH 67/97] =?UTF-8?q?=F0=9F=93=9D=20Update=20release=20notes?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docs/en/docs/release-notes.md | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/en/docs/release-notes.md b/docs/en/docs/release-notes.md index d99f153c22..ea3e5ab430 100644 --- a/docs/en/docs/release-notes.md +++ b/docs/en/docs/release-notes.md @@ -2,6 +2,7 @@ ## Latest Changes +* 👷 Update `setup-python` action in tests to use new caching feature. PR [#5680](https://github.com/tiangolo/fastapi/pull/5680) by [@madkinsz](https://github.com/madkinsz). * ✏️ Fix typo in docs for `docs/en/docs/advanced/middleware.md`. PR [#5376](https://github.com/tiangolo/fastapi/pull/5376) by [@rifatrakib](https://github.com/rifatrakib). * ⬆ Bump black from 22.8.0 to 22.10.0. PR [#5569](https://github.com/tiangolo/fastapi/pull/5569) by [@dependabot[bot]](https://github.com/apps/dependabot). From 0c07e542a7b8e560bfa3b71ce65e3c67e7860a8a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebasti=C3=A1n=20Ram=C3=ADrez?= Date: Sun, 27 Nov 2022 14:11:22 +0100 Subject: [PATCH 68/97] =?UTF-8?q?=F0=9F=91=B7=20Fix=20and=20tweak=20CI=20c?= =?UTF-8?q?ache=20handling=20(#5696)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .github/workflows/publish.yml | 2 ++ .github/workflows/smokeshow.yml | 2 ++ .github/workflows/test.yml | 10 ++++++++-- 3 files changed, 12 insertions(+), 2 deletions(-) diff --git a/.github/workflows/publish.yml b/.github/workflows/publish.yml index fe4c5ee86c..ab27d4b855 100644 --- a/.github/workflows/publish.yml +++ b/.github/workflows/publish.yml @@ -18,6 +18,8 @@ jobs: uses: actions/setup-python@v4 with: python-version: "3.7" + cache: "pip" + cache-dependency-path: pyproject.toml - uses: actions/cache@v3 id: cache with: diff --git a/.github/workflows/smokeshow.yml b/.github/workflows/smokeshow.yml index 7559c24c06..55d64517f5 100644 --- a/.github/workflows/smokeshow.yml +++ b/.github/workflows/smokeshow.yml @@ -17,6 +17,8 @@ jobs: - uses: actions/setup-python@v4 with: python-version: '3.9' + cache: "pip" + cache-dependency-path: pyproject.toml - run: pip install smokeshow diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 85779af18b..ddc43c942b 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -19,13 +19,17 @@ jobs: - uses: actions/checkout@v3 - name: Set up Python uses: actions/setup-python@v4 - id: setup-python with: python-version: ${{ matrix.python-version }} cache: "pip" cache-dependency-path: pyproject.toml + - uses: actions/cache@v3 + id: cache + with: + path: ${{ env.pythonLocation }} + key: ${{ runner.os }}-python-${{ env.pythonLocation }}-${{ hashFiles('pyproject.toml') }}-test-v03 - name: Install Dependencies - if: steps.setup-python.outputs.cache-hit != 'true' + if: steps.cache.outputs.cache-hit != 'true' run: pip install -e .[all,dev,doc,test] - name: Lint run: bash scripts/lint.sh @@ -50,6 +54,8 @@ jobs: - uses: actions/setup-python@v4 with: python-version: '3.8' + cache: "pip" + cache-dependency-path: pyproject.toml - name: Get coverage files uses: actions/download-artifact@v3 From c77384fc8f13b39ea1571f495a30c570a2fb56dc Mon Sep 17 00:00:00 2001 From: github-actions Date: Sun, 27 Nov 2022 13:12:12 +0000 Subject: [PATCH 69/97] =?UTF-8?q?=F0=9F=93=9D=20Update=20release=20notes?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docs/en/docs/release-notes.md | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/en/docs/release-notes.md b/docs/en/docs/release-notes.md index ea3e5ab430..f6fd36be04 100644 --- a/docs/en/docs/release-notes.md +++ b/docs/en/docs/release-notes.md @@ -2,6 +2,7 @@ ## Latest Changes +* 👷 Fix and tweak CI cache handling. PR [#5696](https://github.com/tiangolo/fastapi/pull/5696) by [@tiangolo](https://github.com/tiangolo). * 👷 Update `setup-python` action in tests to use new caching feature. PR [#5680](https://github.com/tiangolo/fastapi/pull/5680) by [@madkinsz](https://github.com/madkinsz). * ✏️ Fix typo in docs for `docs/en/docs/advanced/middleware.md`. PR [#5376](https://github.com/tiangolo/fastapi/pull/5376) by [@rifatrakib](https://github.com/rifatrakib). * ⬆ Bump black from 22.8.0 to 22.10.0. PR [#5569](https://github.com/tiangolo/fastapi/pull/5569) by [@dependabot[bot]](https://github.com/apps/dependabot). From c942a9b8d0ec7eca32f7547c580cff578bc1b88b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebasti=C3=A1n=20Ram=C3=ADrez?= Date: Sun, 27 Nov 2022 14:39:17 +0100 Subject: [PATCH 70/97] =?UTF-8?q?=F0=9F=92=9A=20Fix=20pip=20cache=20for=20?= =?UTF-8?q?Smokeshow=20(#5697)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .github/workflows/smokeshow.yml | 1 - 1 file changed, 1 deletion(-) diff --git a/.github/workflows/smokeshow.yml b/.github/workflows/smokeshow.yml index 55d64517f5..c83d16f15c 100644 --- a/.github/workflows/smokeshow.yml +++ b/.github/workflows/smokeshow.yml @@ -18,7 +18,6 @@ jobs: with: python-version: '3.9' cache: "pip" - cache-dependency-path: pyproject.toml - run: pip install smokeshow From 0b53ee505b47bdc6a2087367e41269ffcb5587d8 Mon Sep 17 00:00:00 2001 From: github-actions Date: Sun, 27 Nov 2022 13:40:03 +0000 Subject: [PATCH 71/97] =?UTF-8?q?=F0=9F=93=9D=20Update=20release=20notes?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docs/en/docs/release-notes.md | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/en/docs/release-notes.md b/docs/en/docs/release-notes.md index f6fd36be04..4d77f5f825 100644 --- a/docs/en/docs/release-notes.md +++ b/docs/en/docs/release-notes.md @@ -2,6 +2,7 @@ ## Latest Changes +* 💚 Fix pip cache for Smokeshow. PR [#5697](https://github.com/tiangolo/fastapi/pull/5697) by [@tiangolo](https://github.com/tiangolo). * 👷 Fix and tweak CI cache handling. PR [#5696](https://github.com/tiangolo/fastapi/pull/5696) by [@tiangolo](https://github.com/tiangolo). * 👷 Update `setup-python` action in tests to use new caching feature. PR [#5680](https://github.com/tiangolo/fastapi/pull/5680) by [@madkinsz](https://github.com/madkinsz). * ✏️ Fix typo in docs for `docs/en/docs/advanced/middleware.md`. PR [#5376](https://github.com/tiangolo/fastapi/pull/5376) by [@rifatrakib](https://github.com/rifatrakib). From fcc4dd61f17aa13f954d866e000c6c42fa2cedb6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebasti=C3=A1n=20Ram=C3=ADrez?= Date: Sun, 27 Nov 2022 14:53:13 +0100 Subject: [PATCH 72/97] =?UTF-8?q?=F0=9F=91=B7=20Remove=20pip=20cache=20for?= =?UTF-8?q?=20Smokeshow=20as=20it=20depends=20on=20a=20requirements.txt=20?= =?UTF-8?q?(#5700)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .github/workflows/smokeshow.yml | 1 - 1 file changed, 1 deletion(-) diff --git a/.github/workflows/smokeshow.yml b/.github/workflows/smokeshow.yml index c83d16f15c..7559c24c06 100644 --- a/.github/workflows/smokeshow.yml +++ b/.github/workflows/smokeshow.yml @@ -17,7 +17,6 @@ jobs: - uses: actions/setup-python@v4 with: python-version: '3.9' - cache: "pip" - run: pip install smokeshow From 91e5a5d1cf13696383f0f3cdd89277a0c52aba9c Mon Sep 17 00:00:00 2001 From: github-actions Date: Sun, 27 Nov 2022 13:53:52 +0000 Subject: [PATCH 73/97] =?UTF-8?q?=F0=9F=93=9D=20Update=20release=20notes?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docs/en/docs/release-notes.md | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/en/docs/release-notes.md b/docs/en/docs/release-notes.md index 4d77f5f825..ec976f5109 100644 --- a/docs/en/docs/release-notes.md +++ b/docs/en/docs/release-notes.md @@ -2,6 +2,7 @@ ## Latest Changes +* 👷 Remove pip cache for Smokeshow as it depends on a requirements.txt. PR [#5700](https://github.com/tiangolo/fastapi/pull/5700) by [@tiangolo](https://github.com/tiangolo). * 💚 Fix pip cache for Smokeshow. PR [#5697](https://github.com/tiangolo/fastapi/pull/5697) by [@tiangolo](https://github.com/tiangolo). * 👷 Fix and tweak CI cache handling. PR [#5696](https://github.com/tiangolo/fastapi/pull/5696) by [@tiangolo](https://github.com/tiangolo). * 👷 Update `setup-python` action in tests to use new caching feature. PR [#5680](https://github.com/tiangolo/fastapi/pull/5680) by [@madkinsz](https://github.com/madkinsz). From 7c5626bef7ab09d93083c9e1b593b23ba84dd78b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebasti=C3=A1n=20Ram=C3=ADrez?= Date: Sun, 27 Nov 2022 14:59:32 +0100 Subject: [PATCH 74/97] =?UTF-8?q?=E2=AC=86=EF=B8=8F=20Upgrade=20Ruff=20(#5?= =?UTF-8?q?698)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .pre-commit-config.yaml | 2 +- fastapi/dependencies/utils.py | 4 ++-- fastapi/encoders.py | 2 +- fastapi/utils.py | 2 +- pyproject.toml | 8 +++++--- 5 files changed, 10 insertions(+), 8 deletions(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index e59e05abe4..4e34cc7ede 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -19,7 +19,7 @@ repos: - --py3-plus - --keep-runtime-typing - repo: https://github.com/charliermarsh/ruff-pre-commit - rev: v0.0.114 + rev: v0.0.138 hooks: - id: ruff args: diff --git a/fastapi/dependencies/utils.py b/fastapi/dependencies/utils.py index 3df5ccfc8b..4c817d5d0b 100644 --- a/fastapi/dependencies/utils.py +++ b/fastapi/dependencies/utils.py @@ -105,10 +105,10 @@ def check_file_field(field: ModelField) -> None: assert parse_options_header except ImportError: logger.error(multipart_incorrect_install_error) - raise RuntimeError(multipart_incorrect_install_error) + raise RuntimeError(multipart_incorrect_install_error) from None except ImportError: logger.error(multipart_not_installed_error) - raise RuntimeError(multipart_not_installed_error) + raise RuntimeError(multipart_not_installed_error) from None def get_param_sub_dependant( diff --git a/fastapi/encoders.py b/fastapi/encoders.py index 6bde9f4abf..2f95bcbf66 100644 --- a/fastapi/encoders.py +++ b/fastapi/encoders.py @@ -157,7 +157,7 @@ def jsonable_encoder( data = vars(obj) except Exception as e: errors.append(e) - raise ValueError(errors) + raise ValueError(errors) from e return jsonable_encoder( data, include=include, diff --git a/fastapi/utils.py b/fastapi/utils.py index b94dacecc5..b15f6a2cfb 100644 --- a/fastapi/utils.py +++ b/fastapi/utils.py @@ -89,7 +89,7 @@ def create_response_field( except RuntimeError: raise fastapi.exceptions.FastAPIError( f"Invalid args for response field! Hint: check that {type_} is a valid pydantic field type" - ) + ) from None def create_cloned_field( diff --git a/pyproject.toml b/pyproject.toml index 9549cc47da..4ae3809864 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -53,7 +53,7 @@ test = [ "pytest >=7.1.3,<8.0.0", "coverage[toml] >= 6.5.0,<7.0", "mypy ==0.982", - "ruff ==0.0.114", + "ruff ==0.0.138", "black == 22.10.0", "isort >=5.0.6,<6.0.0", "httpx >=0.23.0,<0.24.0", @@ -87,7 +87,7 @@ doc = [ "pyyaml >=5.3.1,<7.0.0", ] dev = [ - "ruff ==0.0.114", + "ruff ==0.0.138", "uvicorn[standard] >=0.12.0,<0.19.0", "pre-commit >=2.17.0,<3.0.0", ] @@ -168,6 +168,7 @@ select = [ ignore = [ "E501", # line too long, handled by black "B008", # do not perform function calls in argument defaults + "C901", # too complex ] [tool.ruff.per-file-ignores] @@ -178,7 +179,8 @@ ignore = [ "docs_src/dependencies/tutorial010.py" = ["F821"] "docs_src/custom_response/tutorial007.py" = ["B007"] "docs_src/dataclasses/tutorial003.py" = ["I001"] - +"docs_src/path_operation_advanced_configuration/tutorial007.py" = ["B904"] +"docs_src/custom_request_and_route/tutorial002.py" = ["B904"] [tool.ruff.isort] known-third-party = ["fastapi", "pydantic", "starlette"] From 99d8470a8e1cf76da8c5274e4e372630efc95736 Mon Sep 17 00:00:00 2001 From: github-actions Date: Sun, 27 Nov 2022 14:00:09 +0000 Subject: [PATCH 75/97] =?UTF-8?q?=F0=9F=93=9D=20Update=20release=20notes?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docs/en/docs/release-notes.md | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/en/docs/release-notes.md b/docs/en/docs/release-notes.md index ec976f5109..132d61aa90 100644 --- a/docs/en/docs/release-notes.md +++ b/docs/en/docs/release-notes.md @@ -2,6 +2,7 @@ ## Latest Changes +* ⬆️ Upgrade Ruff. PR [#5698](https://github.com/tiangolo/fastapi/pull/5698) by [@tiangolo](https://github.com/tiangolo). * 👷 Remove pip cache for Smokeshow as it depends on a requirements.txt. PR [#5700](https://github.com/tiangolo/fastapi/pull/5700) by [@tiangolo](https://github.com/tiangolo). * 💚 Fix pip cache for Smokeshow. PR [#5697](https://github.com/tiangolo/fastapi/pull/5697) by [@tiangolo](https://github.com/tiangolo). * 👷 Fix and tweak CI cache handling. PR [#5696](https://github.com/tiangolo/fastapi/pull/5696) by [@tiangolo](https://github.com/tiangolo). From ebd917a530b0f5be7ff0395f202befbd1ec6db0f Mon Sep 17 00:00:00 2001 From: Ayrton Freeman Date: Sun, 27 Nov 2022 11:13:50 -0300 Subject: [PATCH 76/97] =?UTF-8?q?=F0=9F=8C=90=20Add=20Portuguese=20transla?= =?UTF-8?q?tion=20for=20`docs/pt/docs/deployment/docker.md`=20(#5663)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> Co-authored-by: Sebastián Ramírez --- docs/pt/docs/deployment/docker.md | 701 ++++++++++++++++++++++++++++++ docs/pt/mkdocs.yml | 1 + 2 files changed, 702 insertions(+) create mode 100644 docs/pt/docs/deployment/docker.md diff --git a/docs/pt/docs/deployment/docker.md b/docs/pt/docs/deployment/docker.md new file mode 100644 index 0000000000..42c31db29a --- /dev/null +++ b/docs/pt/docs/deployment/docker.md @@ -0,0 +1,701 @@ +# FastAPI em contêineres - Docker + +Ao fazer o deploy de aplicações FastAPI uma abordagem comum é construir uma **imagem de contêiner Linux**. Isso normalmente é feito usando o **Docker**. Você pode a partir disso fazer o deploy dessa imagem de algumas maneiras. + +Usando contêineres Linux você tem diversas vantagens incluindo **segurança**, **replicabilidade**, **simplicidade**, entre outras. + +!!! Dica + Está com pressa e já sabe dessas coisas? Pode ir direto para [`Dockerfile` abaixo 👇](#build-a-docker-image-for-fastapi). + + +
+Visualização do Dockerfile 👀 + +```Dockerfile +FROM python:3.9 + +WORKDIR /code + +COPY ./requirements.txt /code/requirements.txt + +RUN pip install --no-cache-dir --upgrade -r /code/requirements.txt + +COPY ./app /code/app + +CMD ["uvicorn", "app.main:app", "--host", "0.0.0.0", "--port", "80"] + +# If running behind a proxy like Nginx or Traefik add --proxy-headers +# CMD ["uvicorn", "app.main:app", "--host", "0.0.0.0", "--port", "80", "--proxy-headers"] +``` + +
+ +## O que é um Contêiner + +Contêineres (especificamente contêineres Linux) são um jeito muito **leve** de empacotar aplicações contendo todas as dependências e arquivos necessários enquanto os mantém isolados de outros contêineres (outras aplicações ou componentes) no mesmo sistema. + +Contêineres Linux rodam usando o mesmo kernel Linux do hospedeiro (máquina, máquina virtual, servidor na nuvem, etc). Isso simplesmente significa que eles são muito leves (comparados com máquinas virtuais emulando um sistema operacional completo). + +Dessa forma, contêineres consomem **poucos recursos**, uma quantidade comparável com rodar os processos diretamente (uma máquina virtual consumiria muito mais). + +Contêineres também possuem seus próprios processos (comumente um único processo), sistema de arquivos e rede **isolados** simplificando deploy, segurança, desenvolvimento, etc. + +## O que é uma Imagem de Contêiner + +Um **contêiner** roda a partir de uma **imagem de contêiner**. + +Uma imagem de contêiner é uma versão **estática** de todos os arquivos, variáveis de ambiente e do comando/programa padrão que deve estar presente num contêiner. **Estática** aqui significa que a **imagem** de contêiner não está rodando, não está sendo executada, somente contém os arquivos e metadados empacotados. + +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). + +Uma imagem de contêiner é comparável ao arquivo de **programa** e seus conteúdos, ex.: `python` e algum arquivo `main.py`. + +E o **contêiner** em si (em contraste à **imagem de contêiner**) é a própria instância da imagem rodando, comparável a um **processo**. Na verdade, um contêiner está rodando somente quando há um **processo rodando** (e normalmente é somente um processo). O contêiner finaliza quando não há um processo rodando nele. + +## Imagens de contêiner + +Docker tem sido uma das principais ferramentas para criar e gerenciar **imagens de contêiner** e **contêineres**. + +E existe um Docker Hub público com **imagens de contêiner oficiais** pré-prontas para diversas ferramentas, ambientes, bancos de dados e aplicações. + +Por exemplo, há uma Imagem Python oficial. + +E existe muitas outras imagens para diferentes coisas, como bancos de dados, por exemplo: + +* PostgreSQL +* MySQL +* MongoDB +* Redis, etc. + +Usando imagens de contêiner pré-prontas é muito fácil **combinar** e usar diferentes ferramentas. Por exemplo, para testar um novo banco de dados. Em muitos casos, você pode usar as **imagens oficiais** precisando somente de variáveis de ambiente para configurá-las. + +Dessa forma, em muitos casos você pode aprender sobre contêineres e Docker e re-usar essa experiência com diversos componentes e ferramentas. + +Então, você rodaria **vários contêineres** com coisas diferentes, como um banco de dados, uma aplicação Python, um servidor web com uma aplicação frontend React, e conectá-los juntos via sua rede interna. + +Todos os sistemas de gerenciamento de contêineres (como Docker ou Kubernetes) possuem essas funcionalidades de rede integradas a eles. + +## Contêineres e Processos + +Uma **imagem de contêiner** normalmente inclui em seus metadados o programa padrão ou comando que deve ser executado quando o **contêiner** é iniciado e os parâmetros a serem passados para esse programa. Muito similar ao que seria se estivesse na linha de comando. + +Quando um **contêiner** é iniciado, ele irá rodar esse comando/programa (embora você possa sobrescrevê-lo e fazer com que ele rode um comando/programa diferente). + +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. + +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. + +## Construindo uma Imagem Docker para FastAPI + +Okay, vamos construir algo agora! 🚀 + +Eu vou mostrar como construir uma **imagem Docker** para FastAPI **do zero**, baseado na **imagem oficial do Python**. + +Isso é o que você quer fazer na **maioria dos casos**, por exemplo: + +* Usando **Kubernetes** ou ferramentas similares +* Quando rodando em uma **Raspberry Pi** +* Usando um serviço em nuvem que irá rodar uma imagem de contêiner para você, etc. + +### O Pacote Requirements + +Você normalmente teria os **requisitos do pacote** para sua aplicação em algum arquivo. + +Isso pode depender principalmente da ferramenta que você usa para **instalar** esses requisitos. + +O caminho mais comum de fazer isso é ter um arquivo `requirements.txt` com os nomes dos pacotes e suas versões, um por linha. + +Você, naturalmente, usaria as mesmas ideias que você leu em [Sobre Versões do FastAPI](./versions.md){.internal-link target=_blank} para definir os intervalos de versões. + +Por exemplo, seu `requirements.txt` poderia parecer com: + +``` +fastapi>=0.68.0,<0.69.0 +pydantic>=1.8.0,<2.0.0 +uvicorn>=0.15.0,<0.16.0 +``` + +E você normalmente instalaria essas dependências de pacote com `pip`, por exemplo: + +
+ +```console +$ pip install -r requirements.txt +---> 100% +Successfully installed fastapi pydantic uvicorn +``` + +
+ +!!! info + Há outros formatos e ferramentas para definir e instalar dependências de pacote. + + Eu vou mostrar um exemplo depois usando Poetry em uma seção abaixo. 👇 + +### Criando o Código do **FastAPI** + +* Crie um diretório `app` e entre nele. +* Crie um arquivo vazio `__init__.py`. +* Crie um arquivo `main.py` com: + +```Python +from typing import Optional + +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: Union[str, None] = None): + return {"item_id": item_id, "q": q} +``` + +### Dockerfile + +Agora, no mesmo diretório do projeto, crie um arquivo `Dockerfile` com: + +```{ .dockerfile .annotate } +# (1) +FROM python:3.9 + +# (2) +WORKDIR /code + +# (3) +COPY ./requirements.txt /code/requirements.txt + +# (4) +RUN pip install --no-cache-dir --upgrade -r /code/requirements.txt + +# (5) +COPY ./app /code/app + +# (6) +CMD ["uvicorn", "app.main:app", "--host", "0.0.0.0", "--port", "80"] +``` + +1. Inicie a partir da imagem base oficial do Python. + +2. Defina o diretório de trabalho atual para `/code`. + + Esse é o diretório onde colocaremos o arquivo `requirements.txt` e o diretório `app`. + +3. Copie o arquivo com os requisitos para o diretório `/code`. + + Copie **somente** o arquivo com os requisitos primeiro, não o resto do código. + + Como esse arquivo **não muda com frequência**, o Docker irá detectá-lo e usar o **cache** para esse passo, habilitando o cache para o próximo passo também. + +4. Instale as dependências de pacote vindas do arquivo de requisitos. + + A opção `--no-cache-dir` diz ao `pip` para não salvar os pacotes baixados localmente, pois isso só aconteceria se `pip` fosse executado novamente para instalar os mesmos pacotes, mas esse não é o caso quando trabalhamos com contêineres. + + !!! note + `--no-cache-dir` é apenas relacionado ao `pip`, não tem nada a ver com Docker ou contêineres. + + A opção `--upgrade` diz ao `pip` para atualizar os pacotes se eles já estiverem instalados. + + Por causa do passo anterior de copiar o arquivo, ele pode ser detectado pelo **cache do Docker**, esse passo também **usará o cache do Docker** quando disponível. + + Usando o cache nesse passo irá **salvar** muito **tempo** quando você for construir a imagem repetidas vezes durante o desenvolvimento, ao invés de **baixar e instalar** todas as dependências **toda vez**. + +5. Copie o diretório `./app` dentro do diretório `/code`. + + Como isso tem todo o código contendo o que **muda com mais frequência**, o **cache do Docker** não será usado para esse passo ou para **qualquer passo seguinte** facilmente. + + Então, é importante colocar isso **perto do final** do `Dockerfile`, para otimizar o tempo de construção da imagem do contêiner. + +6. Defina o **comando** para rodar o servidor `uvicorn`. + + `CMD` recebe uma lista de strings, cada uma dessas strings é o que você digitaria na linha de comando separado por espaços. + + Esse comando será executado a partir do **diretório de trabalho atual**, o mesmo diretório `/code` que você definiu acima com `WORKDIR /code`. + + Porque o programa será iniciado em `/code` e dentro dele está o diretório `./app` com seu código, o **Uvicorn** será capaz de ver e **importar** `app` de `app.main`. + +!!! tip + Revise o que cada linha faz clicando em cada bolha com o número no código. 👆 + +Agora você deve ter uma estrutura de diretório como: + +``` +. +├── app +│   ├── __init__.py +│ └── main.py +├── Dockerfile +└── requirements.txt +``` + +#### Por Trás de um Proxy de Terminação TLS + +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 confie nos cabeçalhos enviados por esse proxy, informando que o aplicativo está sendo executado atrás do HTTPS, etc. + +```Dockerfile +CMD ["uvicorn", "app.main:app", "--proxy-headers", "--host", "0.0.0.0", "--port", "80"] +``` + +#### Cache Docker + +Existe um truque importante nesse `Dockerfile`, primeiro copiamos o **arquivo com as dependências sozinho**, não o resto do código. Deixe-me te contar o porquê disso. + +```Dockerfile +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 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. + +Somente evitar a cópia de arquivos não melhora muito as coisas, mas porque ele usou o cache para esse passo, ele pode **usar o cache para o próximo passo**. Por exemplo, ele pode usar o cache para a instrução que instala as dependências com: + +```Dockerfile +RUN pip install --no-cache-dir --upgrade -r /code/requirements.txt +``` + +O arquivo com os requisitos de pacote **não muda com frequência**. Então, ao copiar apenas esse arquivo, o Docker será capaz de **usar o cache** para esse passo. + +E então, o Docker será capaz de **usar o cache para o próximo passo** que baixa e instala essas dependências. E é aqui que **salvamos muito tempo**. ✨ ...e evitamos tédio esperando. 😪😆 + +Baixar e instalar as dependências do pacote **pode levar minutos**, mas usando o **cache** leva **segundos** no máximo. + +E como você estaria construindo a imagem do contêiner novamente e novamente durante o desenvolvimento para verificar se suas alterações de código estão funcionando, há muito tempo acumulado que isso economizaria. + +A partir daí, perto do final do `Dockerfile`, copiamos todo o código. Como isso é o que **muda com mais frequência**, colocamos perto do final, porque quase sempre, qualquer coisa depois desse passo não será capaz de usar o cache. + +```Dockerfile +COPY ./app /code/app +``` + +### Construindo a Imagem Docker + +Agora que todos os arquivos estão no lugar, vamos construir a imagem do contêiner. + +* Vá para o diretório do projeto (onde está o seu `Dockerfile`, contendo o diretório `app`). +* Construa sua imagem FastAPI: + +
+ +```console +$ docker build -t myimage . + +---> 100% +``` + +
+ +!!! tip + Note o `.` no final, é equivalente a `./`, ele diz ao Docker o diretório a ser usado para construir a imagem do contêiner. + + Nesse caso, é o mesmo diretório atual (`.`). + +### Inicie o contêiner Docker + +* Execute um contêiner baseado na sua imagem: + +
+ +```console +$ docker run -d --name mycontêiner -p 80:80 myimage +``` + +
+ +## Verifique + +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 ou http://127.0.0.1/items/5?q=somequery (ou equivalente, usando seu host Docker). + +Você verá algo como: + +```JSON +{"item_id": 5, "q": "somequery"} +``` + +## Documentação interativa da API + +Agora você pode ir para http://192.168.99.100/docs ou http://127.0.0.1/docs (ou equivalente, usando seu host Docker). + +Você verá a documentação interativa automática da API (fornecida pelo Swagger UI): + +![Swagger UI](https://fastapi.tiangolo.com/img/index/index-01-swagger-ui-simple.png) + +## Documentação alternativa da API + +E você também pode ir para http://192.168.99.100/redoc ou http://127.0.0.1/redoc (ou equivalente, usando seu host Docker). + +Você verá a documentação alternativa automática (fornecida pela ReDoc): + +![ReDoc](https://fastapi.tiangolo.com/img/index/index-02-redoc-simple.png) + +## Construindo uma Imagem Docker com um Arquivo Único FastAPI + +Se seu FastAPI for um único arquivo, por exemplo, `main.py` sem um diretório `./app`, sua estrutura de arquivos poderia ser assim: + +``` +. +├── Dockerfile +├── main.py +└── requirements.txt +``` + +Então você só teria que alterar os caminhos correspondentes para copiar o arquivo dentro do `Dockerfile`: + +```{ .dockerfile .annotate hl_lines="10 13" } +FROM python:3.9 + +WORKDIR /code + +COPY ./requirements.txt /code/requirements.txt + +RUN pip install --no-cache-dir --upgrade -r /code/requirements.txt + +# (1) +COPY ./main.py /code/ + +# (2) +CMD ["uvicorn", "main:app", "--host", "0.0.0.0", "--port", "80"] +``` + +1. Copie o arquivo `main.py` para o diretório `/code` diretamente (sem nenhum diretório `./app`). + +2. Execute o Uvicorn e diga a ele para importar o objeto `app` de `main` (em vez de importar de `app.main`). + +Então ajuste o comando Uvicorn para usar o novo módulo `main` em vez de `app.main` para importar o objeto FastAPI `app`. + +## Conceitos de Implantação + +Vamos falar novamente sobre alguns dos mesmos [Conceitos de Implantação](./concepts.md){.internal-link target=_blank} em termos de contêineres. + +Contêineres são principalmente uma ferramenta para simplificar o processo de **construção e implantação** de um aplicativo, mas eles não impõem uma abordagem particular para lidar com esses **conceitos de implantação** e existem várias estratégias possíveis. + +A **boa notícia** é que com cada estratégia diferente há uma maneira de cobrir todos os conceitos de implantação. 🎉 + +Vamos revisar esses **conceitos de implantação** em termos de contêineres: + +* HTTPS +* Executando na inicialização +* Reinicializações +* Replicação (número de processos rodando) +* Memória +* Passos anteriores antes de começar + +## HTTPS + +Se nos concentrarmos apenas na **imagem do contêiner** para um aplicativo FastAPI (e posteriormente no **contêiner** em execução), o HTTPS normalmente seria tratado **externamente** por outra ferramenta. + +Isso poderia ser outro contêiner, por exemplo, com Traefik, lidando com **HTTPS** e aquisição **automática** de **certificados**. + +!!! tip + Traefik tem integrações com Docker, Kubernetes e outros, portanto, é muito fácil configurar e configurar o HTTPS para seus contêineres com ele. + +Alternativamente, o HTTPS poderia ser tratado por um provedor de nuvem como um de seus serviços (enquanto ainda executasse o aplicativo em um contêiner). + +## Executando na inicialização e reinicializações + +Normalmente, outra ferramenta é responsável por **iniciar e executar** seu contêiner. + +Ela poderia ser o **Docker** diretamente, **Docker Compose**, **Kubernetes**, um **serviço de nuvem**, etc. + +Na maioria (ou em todos) os casos, há uma opção simples para habilitar a execução do contêiner na inicialização e habilitar reinicializações em falhas. Por exemplo, no Docker, é a opção de linha de comando `--restart`. + +Sem usar contêineres, fazer aplicativos executarem na inicialização e com reinicializações pode ser trabalhoso e difícil. Mas quando **trabalhando com contêineres** em muitos casos essa funcionalidade é incluída por padrão. ✨ + +## Replicação - Número de Processos + +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 o Gunicorn 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**. + +Nesses casos, você provavelmente desejará criar uma **imagem do contêiner do zero** como [explicado acima](#dockerfile), instalando suas dependências e executando **um único processo Uvicorn** em vez de executar algo como Gunicorn com trabalhadores Uvicorn. + +### Balanceamento de Carga + +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 trabalhadores de uma maneira (esperançosamente) **balanceada**, ele também é comumente chamado de **Balanceador de Carga**. + +!!! tip + O mesmo componente **Proxy de Terminação TLS** usado para HTTPS provavelmente também seria um **Balanceador de Carga**. + +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. + +### Um Balanceador de Carga - Múltiplos Contêineres de Workers + +Quando trabalhando com **Kubernetes** ou sistemas similares de gerenciamento de contêiner distribuído, usando seus mecanismos de rede internos permitiria que o único **balanceador de carga** que estivesse escutando na **porta principal** transmitisse comunicação (solicitações) 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 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. + +### Um Processo por Contêiner + +Nesse tipo de cenário, provavelmente você desejará ter **um único processo (Uvicorn) por contêiner**, pois já estaria lidando com a replicação no nível do cluster. + +Então, nesse caso, você **não** desejará ter um gerenciador de processos como o Gunicorn com trabalhadores Uvicorn, ou o Uvicorn usando seus próprios trabalhadores Uvicorn. Você desejará ter apenas um **único processo Uvicorn** por contêiner (mas provavelmente vários contêineres). + +Tendo outro gerenciador de processos dentro do contêiner (como seria com o Gunicorn ou o Uvicorn gerenciando trabalhadores Uvicorn) só adicionaria **complexidade desnecessária** que você provavelmente já está cuidando com seu sistema de cluster. + +### Contêineres com Múltiplos Processos e Casos Especiais + +Claro, existem **casos especiais** em que você pode querer ter um **contêiner** com um **gerenciador de processos Gunicorn** iniciando vários **processos trabalhadores Uvicorn** dentro. + +Nesses casos, você pode usar a **imagem oficial do Docker** que inclui o **Gunicorn** como um gerenciador de processos executando vários **processos trabalhadores Uvicorn**, e algumas configurações padrão para ajustar o número de trabalhadores com base nos atuais núcleos da CPU automaticamente. Eu vou te contar mais sobre isso abaixo em [Imagem Oficial do Docker com Gunicorn - Uvicorn](#imagem-oficial-do-docker-com-gunicorn-uvicorn). + +Aqui estão alguns exemplos de quando isso pode fazer sentido: + +#### Um Aplicativo Simples + +Você pode querer um gerenciador de processos no contêiner se seu aplicativo for **simples o suficiente** para que você não precise (pelo menos não agora) ajustar muito o número de processos, e você pode simplesmente usar um padrão automatizado (com a imagem oficial do Docker), e você está executando em um **único servidor**, não em um cluster. + +#### Docker Compose + +Você pode estar implantando em um **único servidor** (não em um cluster) com o **Docker Compose**, então você não teria uma maneira fácil de gerenciar a replicação de contêineres (com o Docker Compose) enquanto preserva a rede compartilhada e o **balanceamento de carga**. + +Então você pode querer ter **um único contêiner** com um **gerenciador de processos** iniciando **vários processos trabalhadores** dentro. + +#### Prometheus and Outros Motivos + +Você também pode ter **outros motivos** que tornariam mais fácil ter um **único contêiner** com **múltiplos processos** em vez de ter **múltiplos contêineres** com **um único processo** em cada um deles. + +Por exemplo (dependendo de sua configuração), você poderia ter alguma ferramenta como um exportador do Prometheus no mesmo contêiner que deve ter acesso a **cada uma das solicitações** que chegam. + +Nesse caso, se você tivesse **múltiplos contêineres**, por padrão, quando o Prometheus fosse **ler as métricas**, ele receberia as métricas de **um único contêiner cada vez** (para o contêiner que tratou essa solicitação específica), em vez de receber as **métricas acumuladas** de todos os contêineres replicados. + +Então, nesse caso, poderia ser mais simples ter **um único contêiner** com **múltiplos processos**, e uma ferramenta local (por exemplo, um exportador do Prometheus) no mesmo contêiner coletando métricas do Prometheus para todos os processos internos e expor essas métricas no único contêiner. + +--- + +O ponto principal é que **nenhum** desses são **regras escritas em pedra** que você deve seguir cegamente. Você pode usar essas idéias para **avaliar seu próprio caso de uso** e decidir qual é a melhor abordagem para seu sistema, verificando como gerenciar os conceitos de: + +* Segurança - HTTPS +* Executando na inicialização +* Reinicializações +* Replicação (o número de processos em execução) +* Memória +* Passos anteriores antes de inicializar + +## Memória + +Se você executar **um único processo por contêiner**, terá uma quantidade mais ou menos bem definida, estável e limitada de memória consumida por cada um desses contêineres (mais de um se eles forem replicados). + +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 você executar **múltiplos processos por contêiner** (por exemplo, com a imagem oficial do Docker), deve garantir que o número de processos iniciados não **consuma mais memória** do que o disponível. + +## Passos anteriores antes de inicializar e contêineres + +Se você estiver usando contêineres (por exemplo, Docker, Kubernetes), existem duas abordagens principais que você pode usar. + +### Contêineres Múltiplos + +Se você tiver **múltiplos contêineres**, provavelmente cada um executando um **único processo** (por exemplo, em um cluster do **Kubernetes**), então provavelmente você gostaria de ter um **contêiner separado** fazendo o trabalho dos **passos anteriores** em um único contêiner, executando um único processo, **antes** de executar os contêineres trabalhadores replicados. + +!!! info + Se você estiver usando o Kubernetes, provavelmente será um Init Container. + +Se no seu caso de uso não houver problema em executar esses passos anteriores **em paralelo várias vezes** (por exemplo, se você não estiver executando migrações de banco de dados, mas apenas verificando se o banco de dados está pronto), então você também pode colocá-los em cada contêiner logo antes de iniciar o processo principal. + +### Contêiner Único + +Se você tiver uma configuração simples, com um **único contêiner** que então inicia vários **processos trabalhadores** (ou também apenas um processo), então poderia executar esses passos anteriores no mesmo contêiner, logo antes de iniciar o processo com o aplicativo. A imagem oficial do Docker suporta isso internamente. + +## Imagem Oficial do Docker com Gunicorn - Uvicorn + +Há uma imagem oficial do Docker que inclui o Gunicorn executando com trabalhadores Uvicorn, conforme detalhado em um capítulo anterior: [Server Workers - Gunicorn com Uvicorn](./server-workers.md){.internal-link target=_blank}. + +Essa imagem seria útil principalmente nas situações descritas acima em: [Contêineres com Múltiplos Processos e Casos Especiais](#contêineres-com-múltiplos-processos-e-casos-Especiais). + +* tiangolo/uvicorn-gunicorn-fastapi. + +!!! warning + Existe uma grande chance de que você **não** precise dessa imagem base ou de qualquer outra semelhante, e seria melhor construir a imagem do zero, como [descrito acima em: Construa uma Imagem Docker para o FastAPI](#construa-uma-imagem-docker-para-o-fastapi). + +Essa imagem tem um mecanismo de **auto-ajuste** incluído para definir o **número de processos trabalhadores** com base nos núcleos de CPU disponíveis. + +Isso tem **padrões sensíveis**, mas você ainda pode alterar e atualizar todas as configurações com **variáveis de ambiente** ou arquivos de configuração. + +Há também suporte para executar **passos anteriores antes de iniciar** com um script. + +!!! tip + Para ver todas as configurações e opções, vá para a página da imagem Docker: tiangolo/uvicorn-gunicorn-fastapi. + +### Número de Processos na Imagem Oficial do Docker + +O **número de processos** nesta imagem é **calculado automaticamente** a partir dos **núcleos de CPU** disponíveis. + +Isso significa que ele tentará **aproveitar** o máximo de **desempenho** da CPU possível. + +Você também pode ajustá-lo com as configurações usando **variáveis de ambiente**, etc. + +Mas isso também significa que, como o número de processos depende da CPU do contêiner em execução, a **quantidade de memória consumida** também dependerá disso. + +Então, se seu aplicativo consumir muito memória (por exemplo, com modelos de aprendizado de máquina), e seu servidor tiver muitos núcleos de CPU **mas pouca memória**, então seu contêiner pode acabar tentando usar mais memória do que está disponível e degradar o desempenho muito (ou até mesmo travar). 🚨 + +### Criando um `Dockerfile` + +Aqui está como você criaria um `Dockerfile` baseado nessa imagem: + +```Dockerfile +FROM tiangolo/uvicorn-gunicorn-fastapi:python3.9 + +COPY ./requirements.txt /app/requirements.txt + +RUN pip install --no-cache-dir --upgrade -r /app/requirements.txt + +COPY ./app /app +``` + +### Aplicações Maiores + +Se você seguiu a seção sobre a criação de [Aplicações Maiores com Múltiplos Arquivos](../tutorial/bigger-applications.md){.internal-link target=_blank}, seu `Dockerfile` pode parecer com isso: + +```Dockerfile + +```Dockerfile hl_lines="7" +FROM tiangolo/uvicorn-gunicorn-fastapi:python3.9 + +COPY ./requirements.txt /app/requirements.txt + +RUN pip install --no-cache-dir --upgrade -r /app/requirements.txt + +COPY ./app /app/app +``` + +### Quando Usar + +Você provavelmente **não** deve usar essa imagem base oficial (ou qualquer outra semelhante) se estiver usando **Kubernetes** (ou outros) e já estiver definindo **replicação** no nível do cluster, com vários **contêineres**. Nesses casos, é melhor **construir uma imagem do zero** conforme descrito acima: [Construindo uma Imagem Docker para FastAPI](#construindo-uma-imagem-docker-para-fastapi). + +Essa imagem seria útil principalmente nos casos especiais descritos acima em [Contêineres com Múltiplos Processos e Casos Especiais](#contêineres-com-múltiplos-processos-e-casos-Especiais). Por exemplo, se sua aplicação for **simples o suficiente** para que a configuração padrão de número de processos com base na CPU funcione bem, você não quer se preocupar com a configuração manual da replicação no nível do cluster e não está executando mais de um contêiner com seu aplicativo. Ou se você estiver implantando com **Docker Compose**, executando em um único servidor, etc. + +## Deploy da Imagem do Contêiner + +Depois de ter uma imagem de contêiner (Docker), existem várias maneiras de implantá-la. + +Por exemplo: + +* Com **Docker Compose** em um único servidor +* Com um cluster **Kubernetes** +* Com um cluster Docker Swarm Mode +* Com outra ferramenta como o Nomad +* Com um serviço de nuvem que pega sua imagem de contêiner e a implanta + +## Imagem Docker com Poetry + +Se você usa Poetry para gerenciar as dependências do seu projeto, pode usar a construção multi-estágio do Docker: + +```{ .dockerfile .annotate } +# (1) +FROM python:3.9 as requirements-stage + +# (2) +WORKDIR /tmp + +# (3) +RUN pip install poetry + +# (4) +COPY ./pyproject.toml ./poetry.lock* /tmp/ + +# (5) +RUN poetry export -f requirements.txt --output requirements.txt --without-hashes + +# (6) +FROM python:3.9 + +# (7) +WORKDIR /code + +# (8) +COPY --from=requirements-stage /tmp/requirements.txt /code/requirements.txt + +# (9) +RUN pip install --no-cache-dir --upgrade -r /code/requirements.txt + +# (10) +COPY ./app /code/app + +# (11) +CMD ["uvicorn", "app.main:app", "--host", "0.0.0.0", "--port", "80"] +``` + +1. Esse é o primeiro estágio, ele é chamado `requirements-stage`. + +2. Defina `/tmp` como o diretório de trabalho atual. + + Aqui é onde geraremos o arquivo `requirements.txt` + +3. Instale o Poetry nesse estágio do Docker. + +4. Copie os arquivos `pyproject.toml` e `poetry.lock` para o diretório `/tmp`. + + Porque está usando `./poetry.lock*` (terminando com um `*`), não irá falhar se esse arquivo ainda não estiver disponível. + +5. Gere o arquivo `requirements.txt`. + +6. Este é o estágio final, tudo aqui será preservado na imagem final do contêiner. + +7. Defina o diretório de trabalho atual como `/code`. + +8. Copie o arquivo `requirements.txt` para o diretório `/code`. + + Essse arquivo só existe no estágio anterior do Docker, é por isso que usamos `--from-requirements-stage` para copiá-lo. + +9. Instale as dependências de pacote do arquivo `requirements.txt` gerado. + +10. Copie o diretório `app` para o diretório `/code`. + +11. Execute o comando `uvicorn`, informando-o para usar o objeto `app` importado de `app.main`. + +!!! tip + Clique nos números das bolhas para ver o que cada linha faz. + +Um **estágio do Docker** é uma parte de um `Dockerfile` que funciona como uma **imagem temporária do contêiner** que só é usada para gerar alguns arquivos para serem usados posteriormente. + +O primeiro estágio será usado apenas para **instalar Poetry** e para **gerar o `requirements.txt`** com as dependências do seu projeto a partir do arquivo `pyproject.toml` do Poetry. + +Esse arquivo `requirements.txt` será usado com `pip` mais tarde no **próximo estágio**. + +Na imagem final do contêiner, **somente o estágio final** é preservado. Os estágios anteriores serão descartados. + +Quando usar Poetry, faz sentido usar **construções multi-estágio do Docker** porque você realmente não precisa ter o Poetry e suas dependências instaladas na imagem final do contêiner, você **apenas precisa** ter o arquivo `requirements.txt` gerado para instalar as dependências do seu projeto. + +Então, no próximo (e último) estágio, você construiria a imagem mais ou menos da mesma maneira descrita anteriormente. + +### Por trás de um proxy de terminação TLS - Poetry + +Novamente, se você estiver 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` ao comando: + +```Dockerfile +CMD ["uvicorn", "app.main:app", "--proxy-headers", "--host", "0.0.0.0", "--port", "80"] +``` + +## Recapitulando + +Usando sistemas de contêiner (por exemplo, com **Docker** e **Kubernetes**), torna-se bastante simples lidar com todos os **conceitos de implantação**: + +* HTTPS +* Executando na inicialização +* Reinícios +* Replicação (o número de processos rodando) +* Memória +* Passos anteriores antes de inicializar + +Na maioria dos casos, você provavelmente não desejará usar nenhuma imagem base e, em vez disso, **construir uma imagem de contêiner do zero** baseada na imagem oficial do Docker Python. + +Tendo cuidado com a **ordem** das instruções no `Dockerfile` e o **cache do Docker**, você pode **minimizar os tempos de construção**, para maximizar sua produtividade (e evitar a tédio). 😎 + +Em alguns casos especiais, você pode querer usar a imagem oficial do Docker para o FastAPI. 🤓 diff --git a/docs/pt/mkdocs.yml b/docs/pt/mkdocs.yml index fdef810fa1..0858de0624 100644 --- a/docs/pt/mkdocs.yml +++ b/docs/pt/mkdocs.yml @@ -87,6 +87,7 @@ nav: - deployment/versions.md - deployment/https.md - deployment/deta.md + - deployment/docker.md - alternatives.md - history-design-future.md - external-links.md From 991db7b05a1babfd722741abb170cf2f785d0268 Mon Sep 17 00:00:00 2001 From: github-actions Date: Sun, 27 Nov 2022 14:14:28 +0000 Subject: [PATCH 77/97] =?UTF-8?q?=F0=9F=93=9D=20Update=20release=20notes?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docs/en/docs/release-notes.md | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/en/docs/release-notes.md b/docs/en/docs/release-notes.md index 132d61aa90..32352b4c04 100644 --- a/docs/en/docs/release-notes.md +++ b/docs/en/docs/release-notes.md @@ -2,6 +2,7 @@ ## Latest Changes +* 🌐 Add Portuguese translation for `docs/pt/docs/deployment/docker.md`. PR [#5663](https://github.com/tiangolo/fastapi/pull/5663) by [@ayr-ton](https://github.com/ayr-ton). * ⬆️ Upgrade Ruff. PR [#5698](https://github.com/tiangolo/fastapi/pull/5698) by [@tiangolo](https://github.com/tiangolo). * 👷 Remove pip cache for Smokeshow as it depends on a requirements.txt. PR [#5700](https://github.com/tiangolo/fastapi/pull/5700) by [@tiangolo](https://github.com/tiangolo). * 💚 Fix pip cache for Smokeshow. PR [#5697](https://github.com/tiangolo/fastapi/pull/5697) by [@tiangolo](https://github.com/tiangolo). From 9b4e85f088271b1288c58f1fa81a7f70bf3a1f38 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Sun, 27 Nov 2022 15:22:03 +0100 Subject: [PATCH 78/97] =?UTF-8?q?=E2=AC=86=20[pre-commit.ci]=20pre-commit?= =?UTF-8?q?=20autoupdate=20(#5566)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> Co-authored-by: Sebastián Ramírez --- .pre-commit-config.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 4e34cc7ede..96f097caa1 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -12,7 +12,7 @@ repos: - id: end-of-file-fixer - id: trailing-whitespace - repo: https://github.com/asottile/pyupgrade - rev: v3.1.0 + rev: v3.2.2 hooks: - id: pyupgrade args: From 884203676dfaf1d03c08fc79945493458b53e675 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebasti=C3=A1n=20Ram=C3=ADrez?= Date: Sun, 27 Nov 2022 15:22:30 +0100 Subject: [PATCH 79/97] =?UTF-8?q?=F0=9F=91=B7=20Tweak=20build-docs=20to=20?= =?UTF-8?q?improve=20CI=20performance=20(#5699)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- scripts/docs.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/scripts/docs.py b/scripts/docs.py index 622ba9202e..e0953b8edb 100644 --- a/scripts/docs.py +++ b/scripts/docs.py @@ -284,7 +284,9 @@ def build_all(): continue langs.append(lang.name) cpu_count = os.cpu_count() or 1 - with Pool(cpu_count * 2) as p: + process_pool_size = cpu_count * 4 + typer.echo(f"Using process pool size: {process_pool_size}") + with Pool(process_pool_size) as p: p.map(build_lang, langs) From 128c925c35b5f98f5335f5b4a297259bb48fd6bd Mon Sep 17 00:00:00 2001 From: github-actions Date: Sun, 27 Nov 2022 14:22:41 +0000 Subject: [PATCH 80/97] =?UTF-8?q?=F0=9F=93=9D=20Update=20release=20notes?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docs/en/docs/release-notes.md | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/en/docs/release-notes.md b/docs/en/docs/release-notes.md index 32352b4c04..1af3a9c85e 100644 --- a/docs/en/docs/release-notes.md +++ b/docs/en/docs/release-notes.md @@ -2,6 +2,7 @@ ## Latest Changes +* ⬆ [pre-commit.ci] pre-commit autoupdate. PR [#5566](https://github.com/tiangolo/fastapi/pull/5566) by [@pre-commit-ci[bot]](https://github.com/apps/pre-commit-ci). * 🌐 Add Portuguese translation for `docs/pt/docs/deployment/docker.md`. PR [#5663](https://github.com/tiangolo/fastapi/pull/5663) by [@ayr-ton](https://github.com/ayr-ton). * ⬆️ Upgrade Ruff. PR [#5698](https://github.com/tiangolo/fastapi/pull/5698) by [@tiangolo](https://github.com/tiangolo). * 👷 Remove pip cache for Smokeshow as it depends on a requirements.txt. PR [#5700](https://github.com/tiangolo/fastapi/pull/5700) by [@tiangolo](https://github.com/tiangolo). From 89ec1f2d36e6a9aa5564c5ef49e8233efb69172c Mon Sep 17 00:00:00 2001 From: github-actions Date: Sun, 27 Nov 2022 14:23:13 +0000 Subject: [PATCH 81/97] =?UTF-8?q?=F0=9F=93=9D=20Update=20release=20notes?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docs/en/docs/release-notes.md | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/en/docs/release-notes.md b/docs/en/docs/release-notes.md index 1af3a9c85e..68cb5c7cef 100644 --- a/docs/en/docs/release-notes.md +++ b/docs/en/docs/release-notes.md @@ -2,6 +2,7 @@ ## Latest Changes +* 👷 Tweak build-docs to improve CI performance. PR [#5699](https://github.com/tiangolo/fastapi/pull/5699) by [@tiangolo](https://github.com/tiangolo). * ⬆ [pre-commit.ci] pre-commit autoupdate. PR [#5566](https://github.com/tiangolo/fastapi/pull/5566) by [@pre-commit-ci[bot]](https://github.com/apps/pre-commit-ci). * 🌐 Add Portuguese translation for `docs/pt/docs/deployment/docker.md`. PR [#5663](https://github.com/tiangolo/fastapi/pull/5663) by [@ayr-ton](https://github.com/ayr-ton). * ⬆️ Upgrade Ruff. PR [#5698](https://github.com/tiangolo/fastapi/pull/5698) by [@tiangolo](https://github.com/tiangolo). From 46974c510e89c35456f40ca35d432fe0b94e0f97 Mon Sep 17 00:00:00 2001 From: Eugenio Panadero Date: Sun, 27 Nov 2022 15:46:06 +0100 Subject: [PATCH 82/97] =?UTF-8?q?=E2=AC=86=20Bump=20Starlette=20to=20versi?= =?UTF-8?q?on=20`0.22.0`=20to=20fix=20bad=20encoding=20for=20query=20param?= =?UTF-8?q?eters=20in=20`TestClient`=20(#5659)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit closes https://github.com/tiangolo/fastapi/issues/5646 --- pyproject.toml | 2 +- tests/test_starlette_urlconvertors.py | 14 +++++++++++++- 2 files changed, 14 insertions(+), 2 deletions(-) diff --git a/pyproject.toml b/pyproject.toml index 4ae3809864..06f8a97b2e 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -39,7 +39,7 @@ classifiers = [ "Topic :: Internet :: WWW/HTTP", ] dependencies = [ - "starlette==0.21.0", + "starlette==0.22.0", "pydantic >=1.6.2,!=1.7,!=1.7.1,!=1.7.2,!=1.7.3,!=1.8,!=1.8.1,<2.0.0", ] dynamic = ["version"] diff --git a/tests/test_starlette_urlconvertors.py b/tests/test_starlette_urlconvertors.py index 5a980cbf6d..5ef1b819cd 100644 --- a/tests/test_starlette_urlconvertors.py +++ b/tests/test_starlette_urlconvertors.py @@ -1,4 +1,4 @@ -from fastapi import FastAPI, Path +from fastapi import FastAPI, Path, Query from fastapi.testclient import TestClient app = FastAPI() @@ -19,6 +19,11 @@ def path_convertor(param: str = Path()): return {"path": param} +@app.get("/query/") +def query_convertor(param: str = Query()): + return {"query": param} + + client = TestClient(app) @@ -45,6 +50,13 @@ def test_route_converters_path(): assert response.json() == {"path": "some/example"} +def test_route_converters_query(): + # Test query conversion + response = client.get("/query", params={"param": "Qué tal!"}) + assert response.status_code == 200, response.text + assert response.json() == {"query": "Qué tal!"} + + def test_url_path_for_path_convertor(): assert ( app.url_path_for("path_convertor", param="some/example") == "/path/some/example" From c458ca6f0792669259afd0b9a9df9e28b0228075 Mon Sep 17 00:00:00 2001 From: github-actions Date: Sun, 27 Nov 2022 14:46:48 +0000 Subject: [PATCH 83/97] =?UTF-8?q?=F0=9F=93=9D=20Update=20release=20notes?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docs/en/docs/release-notes.md | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/en/docs/release-notes.md b/docs/en/docs/release-notes.md index 68cb5c7cef..d4981bc552 100644 --- a/docs/en/docs/release-notes.md +++ b/docs/en/docs/release-notes.md @@ -2,6 +2,7 @@ ## Latest Changes +* ⬆ Bump Starlette to version `0.22.0` to fix bad encoding for query parameters in `TestClient`. PR [#5659](https://github.com/tiangolo/fastapi/pull/5659) by [@azogue](https://github.com/azogue). * 👷 Tweak build-docs to improve CI performance. PR [#5699](https://github.com/tiangolo/fastapi/pull/5699) by [@tiangolo](https://github.com/tiangolo). * ⬆ [pre-commit.ci] pre-commit autoupdate. PR [#5566](https://github.com/tiangolo/fastapi/pull/5566) by [@pre-commit-ci[bot]](https://github.com/apps/pre-commit-ci). * 🌐 Add Portuguese translation for `docs/pt/docs/deployment/docker.md`. PR [#5663](https://github.com/tiangolo/fastapi/pull/5663) by [@ayr-ton](https://github.com/ayr-ton). From 46bb5d2c4b0af42ee7a700af9d224c62c343f1d3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebasti=C3=A1n=20Ram=C3=ADrez?= Date: Sun, 27 Nov 2022 15:49:33 +0100 Subject: [PATCH 84/97] =?UTF-8?q?=F0=9F=93=9D=20Update=20release=20notes?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docs/en/docs/release-notes.md | 17 ++++++++++++++--- 1 file changed, 14 insertions(+), 3 deletions(-) diff --git a/docs/en/docs/release-notes.md b/docs/en/docs/release-notes.md index d4981bc552..2d32f27808 100644 --- a/docs/en/docs/release-notes.md +++ b/docs/en/docs/release-notes.md @@ -2,16 +2,27 @@ ## Latest Changes -* ⬆ Bump Starlette to version `0.22.0` to fix bad encoding for query parameters in `TestClient`. PR [#5659](https://github.com/tiangolo/fastapi/pull/5659) by [@azogue](https://github.com/azogue). +### Upgrades + +* ⬆ Bump Starlette to version `0.22.0` to fix bad encoding for query parameters in new `TestClient`. PR [#5659](https://github.com/tiangolo/fastapi/pull/5659) by [@azogue](https://github.com/azogue). + +### Docs + +* ✏️ Fix typo in docs for `docs/en/docs/advanced/middleware.md`. PR [#5376](https://github.com/tiangolo/fastapi/pull/5376) by [@rifatrakib](https://github.com/rifatrakib). + +### Translations + +* 🌐 Add Portuguese translation for `docs/pt/docs/deployment/docker.md`. PR [#5663](https://github.com/tiangolo/fastapi/pull/5663) by [@ayr-ton](https://github.com/ayr-ton). + +### Internal + * 👷 Tweak build-docs to improve CI performance. PR [#5699](https://github.com/tiangolo/fastapi/pull/5699) by [@tiangolo](https://github.com/tiangolo). * ⬆ [pre-commit.ci] pre-commit autoupdate. PR [#5566](https://github.com/tiangolo/fastapi/pull/5566) by [@pre-commit-ci[bot]](https://github.com/apps/pre-commit-ci). -* 🌐 Add Portuguese translation for `docs/pt/docs/deployment/docker.md`. PR [#5663](https://github.com/tiangolo/fastapi/pull/5663) by [@ayr-ton](https://github.com/ayr-ton). * ⬆️ Upgrade Ruff. PR [#5698](https://github.com/tiangolo/fastapi/pull/5698) by [@tiangolo](https://github.com/tiangolo). * 👷 Remove pip cache for Smokeshow as it depends on a requirements.txt. PR [#5700](https://github.com/tiangolo/fastapi/pull/5700) by [@tiangolo](https://github.com/tiangolo). * 💚 Fix pip cache for Smokeshow. PR [#5697](https://github.com/tiangolo/fastapi/pull/5697) by [@tiangolo](https://github.com/tiangolo). * 👷 Fix and tweak CI cache handling. PR [#5696](https://github.com/tiangolo/fastapi/pull/5696) by [@tiangolo](https://github.com/tiangolo). * 👷 Update `setup-python` action in tests to use new caching feature. PR [#5680](https://github.com/tiangolo/fastapi/pull/5680) by [@madkinsz](https://github.com/madkinsz). -* ✏️ Fix typo in docs for `docs/en/docs/advanced/middleware.md`. PR [#5376](https://github.com/tiangolo/fastapi/pull/5376) by [@rifatrakib](https://github.com/rifatrakib). * ⬆ Bump black from 22.8.0 to 22.10.0. PR [#5569](https://github.com/tiangolo/fastapi/pull/5569) by [@dependabot[bot]](https://github.com/apps/dependabot). ## 0.87.0 From 612b8ff168beee33fcf0c0bdff9718b4c8b1ac63 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebasti=C3=A1n=20Ram=C3=ADrez?= Date: Sun, 27 Nov 2022 15:50:32 +0100 Subject: [PATCH 85/97] =?UTF-8?q?=F0=9F=94=96=20Release=20version=200.88.0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docs/en/docs/release-notes.md | 3 +++ fastapi/__init__.py | 2 +- 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/docs/en/docs/release-notes.md b/docs/en/docs/release-notes.md index 2d32f27808..e741b86ed7 100644 --- a/docs/en/docs/release-notes.md +++ b/docs/en/docs/release-notes.md @@ -2,6 +2,9 @@ ## Latest Changes + +## 0.88.0 + ### Upgrades * ⬆ Bump Starlette to version `0.22.0` to fix bad encoding for query parameters in new `TestClient`. PR [#5659](https://github.com/tiangolo/fastapi/pull/5659) by [@azogue](https://github.com/azogue). diff --git a/fastapi/__init__.py b/fastapi/__init__.py index afdc94874c..037d9804b5 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.87.0" +__version__ = "0.88.0" from starlette import status as status From 7e4e0d22aeb264a512819f1c1c7045c2002ac69b Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 28 Nov 2022 08:12:37 +0100 Subject: [PATCH 86/97] =?UTF-8?q?=E2=AC=86=20Update=20typer[all]=20require?= =?UTF-8?q?ment=20from=20<0.7.0,>=3D0.6.1=20to=20>=3D0.6.1,<0.8.0=20(#5639?= =?UTF-8?q?)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Updates the requirements on [typer[all]](https://github.com/tiangolo/typer) to permit the latest version. - [Release notes](https://github.com/tiangolo/typer/releases) - [Changelog](https://github.com/tiangolo/typer/blob/master/docs/release-notes.md) - [Commits](https://github.com/tiangolo/typer/compare/0.6.1...0.7.0) --- updated-dependencies: - dependency-name: typer[all] dependency-type: direct:production ... Signed-off-by: dependabot[bot] Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: Sebastián Ramírez --- pyproject.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pyproject.toml b/pyproject.toml index 06f8a97b2e..be3080ae83 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -83,7 +83,7 @@ doc = [ "mkdocs-markdownextradata-plugin >=0.1.7,<0.3.0", # TODO: upgrade and enable typer-cli once it supports Click 8.x.x # "typer-cli >=0.0.12,<0.0.13", - "typer[all] >=0.6.1,<0.7.0", + "typer[all] >=0.6.1,<0.8.0", "pyyaml >=5.3.1,<7.0.0", ] dev = [ From 5c4054ab8a3f5bd3a466af47d8f83036f0e628e4 Mon Sep 17 00:00:00 2001 From: github-actions Date: Mon, 28 Nov 2022 07:13:14 +0000 Subject: [PATCH 87/97] =?UTF-8?q?=F0=9F=93=9D=20Update=20release=20notes?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docs/en/docs/release-notes.md | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/en/docs/release-notes.md b/docs/en/docs/release-notes.md index e741b86ed7..d667e9e5e8 100644 --- a/docs/en/docs/release-notes.md +++ b/docs/en/docs/release-notes.md @@ -2,6 +2,7 @@ ## Latest Changes +* ⬆ Update typer[all] requirement from <0.7.0,>=0.6.1 to >=0.6.1,<0.8.0. PR [#5639](https://github.com/tiangolo/fastapi/pull/5639) by [@dependabot[bot]](https://github.com/apps/dependabot). ## 0.88.0 From 8bdab084f9cbe0e483df4f6fa4bc0c004bccce7c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebasti=C3=A1n=20Ram=C3=ADrez?= Date: Tue, 29 Nov 2022 19:05:40 +0100 Subject: [PATCH 88/97] =?UTF-8?q?=F0=9F=94=A7=20Update=20sponsors,=20disab?= =?UTF-8?q?le=20course=20bundle=20(#5713)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docs/en/overrides/main.html | 12 ------------ 1 file changed, 12 deletions(-) diff --git a/docs/en/overrides/main.html b/docs/en/overrides/main.html index c5eb94870d..e9b9f60eb6 100644 --- a/docs/en/overrides/main.html +++ b/docs/en/overrides/main.html @@ -22,12 +22,6 @@
- -
From 83bcdc40d853e50752d4d4a30bbc8b23a8dbc4c1 Mon Sep 17 00:00:00 2001 From: github-actions Date: Tue, 29 Nov 2022 18:06:22 +0000 Subject: [PATCH 89/97] =?UTF-8?q?=F0=9F=93=9D=20Update=20release=20notes?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docs/en/docs/release-notes.md | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/en/docs/release-notes.md b/docs/en/docs/release-notes.md index d667e9e5e8..4252d68c55 100644 --- a/docs/en/docs/release-notes.md +++ b/docs/en/docs/release-notes.md @@ -2,6 +2,7 @@ ## Latest Changes +* 🔧 Update sponsors, disable course bundle. PR [#5713](https://github.com/tiangolo/fastapi/pull/5713) by [@tiangolo](https://github.com/tiangolo). * ⬆ Update typer[all] requirement from <0.7.0,>=0.6.1 to >=0.6.1,<0.8.0. PR [#5639](https://github.com/tiangolo/fastapi/pull/5639) by [@dependabot[bot]](https://github.com/apps/dependabot). ## 0.88.0 From 41db4cba4c31ae1bebbab95d26727f200d582aad Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Fri, 2 Dec 2022 18:22:33 +0100 Subject: [PATCH 90/97] =?UTF-8?q?=F0=9F=91=A5=20Update=20FastAPI=20People?= =?UTF-8?q?=20(#5722)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: github-actions --- docs/en/data/github_sponsors.yml | 124 +++++++++++---------- docs/en/data/people.yml | 178 ++++++++++++++++--------------- 2 files changed, 161 insertions(+), 141 deletions(-) diff --git a/docs/en/data/github_sponsors.yml b/docs/en/data/github_sponsors.yml index 3d0b37dac7..1953df801e 100644 --- a/docs/en/data/github_sponsors.yml +++ b/docs/en/data/github_sponsors.yml @@ -8,12 +8,15 @@ sponsors: - login: cryptapi avatarUrl: https://avatars.githubusercontent.com/u/44925437?u=61369138589bc7fee6c417f3fbd50fbd38286cc4&v=4 url: https://github.com/cryptapi -- - login: ObliviousAI + - login: jrobbins-LiveData + avatarUrl: https://avatars.githubusercontent.com/u/79278744?u=bae8175fc3f09db281aca1f97a9ddc1a914a8c4f&v=4 + url: https://github.com/jrobbins-LiveData +- - login: nihpo + avatarUrl: https://avatars.githubusercontent.com/u/1841030?u=0264956d7580f7e46687a762a7baa629f84cf97c&v=4 + url: https://github.com/nihpo + - login: ObliviousAI avatarUrl: https://avatars.githubusercontent.com/u/65656077?v=4 url: https://github.com/ObliviousAI - - login: Lovage-Labs - avatarUrl: https://avatars.githubusercontent.com/u/71685552?v=4 - url: https://github.com/Lovage-Labs - login: chaserowbotham avatarUrl: https://avatars.githubusercontent.com/u/97751084?v=4 url: https://github.com/chaserowbotham @@ -38,9 +41,18 @@ sponsors: - - login: InesIvanova avatarUrl: https://avatars.githubusercontent.com/u/22920417?u=409882ec1df6dbd77455788bb383a8de223dbf6f&v=4 url: https://github.com/InesIvanova -- - login: SendCloud +- - login: vyos + avatarUrl: https://avatars.githubusercontent.com/u/5647000?v=4 + url: https://github.com/vyos + - login: SendCloud avatarUrl: https://avatars.githubusercontent.com/u/7831959?v=4 url: https://github.com/SendCloud + - login: matallan + avatarUrl: https://avatars.githubusercontent.com/u/12107723?v=4 + url: https://github.com/matallan + - login: takashi-yoneya + avatarUrl: https://avatars.githubusercontent.com/u/33813153?u=2d0522bceba0b8b69adf1f2db866503bd96f944e&v=4 + url: https://github.com/takashi-yoneya - login: mercedes-benz avatarUrl: https://avatars.githubusercontent.com/u/34240465?v=4 url: https://github.com/mercedes-benz @@ -56,12 +68,18 @@ sponsors: - - login: johnadjei avatarUrl: https://avatars.githubusercontent.com/u/767860?v=4 url: https://github.com/johnadjei + - login: gvisniuc + avatarUrl: https://avatars.githubusercontent.com/u/1614747?u=502dfdb2b087ddcf5460026297c98c7907bc2795&v=4 + url: https://github.com/gvisniuc - login: HiredScore avatarUrl: https://avatars.githubusercontent.com/u/3908850?v=4 url: https://github.com/HiredScore - login: Trivie avatarUrl: https://avatars.githubusercontent.com/u/8161763?v=4 url: https://github.com/Trivie + - login: Lovage-Labs + avatarUrl: https://avatars.githubusercontent.com/u/71685552?v=4 + url: https://github.com/Lovage-Labs - - login: moellenbeck avatarUrl: https://avatars.githubusercontent.com/u/169372?v=4 url: https://github.com/moellenbeck @@ -80,27 +98,18 @@ sponsors: - login: jmaralc avatarUrl: https://avatars.githubusercontent.com/u/21101214?u=b15a9f07b7cbf6c9dcdbcb6550bbd2c52f55aa50&v=4 url: https://github.com/jmaralc - - login: takashi-yoneya - avatarUrl: https://avatars.githubusercontent.com/u/33813153?u=2d0522bceba0b8b69adf1f2db866503bd96f944e&v=4 - url: https://github.com/takashi-yoneya - login: mainframeindustries avatarUrl: https://avatars.githubusercontent.com/u/55092103?v=4 url: https://github.com/mainframeindustries - - login: DelfinaCare - avatarUrl: https://avatars.githubusercontent.com/u/83734439?v=4 - url: https://github.com/DelfinaCare -- - login: karelhusa - avatarUrl: https://avatars.githubusercontent.com/u/11407706?u=4f787cffc30ea198b15935c751940f0b48a26a17&v=4 - url: https://github.com/karelhusa - - login: povilasb avatarUrl: https://avatars.githubusercontent.com/u/1213442?u=b11f58ed6ceea6e8297c9b310030478ebdac894d&v=4 url: https://github.com/povilasb - login: primer-io avatarUrl: https://avatars.githubusercontent.com/u/62146168?v=4 url: https://github.com/primer-io -- - login: DucNgn - avatarUrl: https://avatars.githubusercontent.com/u/43587865?u=a9f9f61569aebdc0ce74df85b8cc1a219a7ab570&v=4 - url: https://github.com/DucNgn +- - login: indeedeng + avatarUrl: https://avatars.githubusercontent.com/u/2905043?v=4 + url: https://github.com/indeedeng - login: A-Edge avatarUrl: https://avatars.githubusercontent.com/u/59514131?v=4 url: https://github.com/A-Edge @@ -119,9 +128,6 @@ sponsors: - login: kamalgill avatarUrl: https://avatars.githubusercontent.com/u/133923?u=0df9181d97436ce330e9acf90ab8a54b7022efe7&v=4 url: https://github.com/kamalgill - - login: gazpachoking - avatarUrl: https://avatars.githubusercontent.com/u/187133?v=4 - url: https://github.com/gazpachoking - login: dekoza avatarUrl: https://avatars.githubusercontent.com/u/210980?u=c03c78a8ae1039b500dfe343665536ebc51979b2&v=4 url: https://github.com/dekoza @@ -155,6 +161,12 @@ sponsors: - login: ltieman avatarUrl: https://avatars.githubusercontent.com/u/1084689?u=e69b17de17cb3ca141a17daa7ccbe173ceb1eb17&v=4 url: https://github.com/ltieman + - login: mrkmcknz + avatarUrl: https://avatars.githubusercontent.com/u/1089376?u=2b9b8a8c25c33a4f6c220095638bd821cdfd13a3&v=4 + url: https://github.com/mrkmcknz + - login: coffeewasmyidea + avatarUrl: https://avatars.githubusercontent.com/u/1636488?u=8e32a4f200eff54dd79cd79d55d254bfce5e946d&v=4 + url: https://github.com/coffeewasmyidea - login: corleyma avatarUrl: https://avatars.githubusercontent.com/u/2080732?u=aed2ff652294a87d666b1c3f6dbe98104db76d26&v=4 url: https://github.com/corleyma @@ -170,8 +182,11 @@ sponsors: - login: Shark009 avatarUrl: https://avatars.githubusercontent.com/u/3163309?u=0c6f4091b0eda05c44c390466199826e6dc6e431&v=4 url: https://github.com/Shark009 + - login: ColliotL + avatarUrl: https://avatars.githubusercontent.com/u/3412402?u=ca64b07ecbef2f9da1cc2cac3f37522aa4814902&v=4 + url: https://github.com/ColliotL - login: grillazz - avatarUrl: https://avatars.githubusercontent.com/u/3415861?u=0b32b7073ae1ab8b7f6d2db0188c2e1e357ff451&v=4 + avatarUrl: https://avatars.githubusercontent.com/u/3415861?u=453cd1725c8d7fe3e258016bc19cff861d4fcb53&v=4 url: https://github.com/grillazz - login: dblackrun avatarUrl: https://avatars.githubusercontent.com/u/3528486?v=4 @@ -179,20 +194,20 @@ sponsors: - login: zsinx6 avatarUrl: https://avatars.githubusercontent.com/u/3532625?u=ba75a5dc744d1116ccfeaaf30d41cb2fe81fe8dd&v=4 url: https://github.com/zsinx6 - - login: bauyrzhanospan - avatarUrl: https://avatars.githubusercontent.com/u/3536037?u=25c86201d0212497aefcc1688cccf509057a1dc4&v=4 - url: https://github.com/bauyrzhanospan - login: MarekBleschke avatarUrl: https://avatars.githubusercontent.com/u/3616870?v=4 url: https://github.com/MarekBleschke - login: aacayaco avatarUrl: https://avatars.githubusercontent.com/u/3634801?u=eaadda178c964178fcb64886f6c732172c8f8219&v=4 url: https://github.com/aacayaco + - login: anomaly + avatarUrl: https://avatars.githubusercontent.com/u/3654837?v=4 + url: https://github.com/anomaly - login: peterHoburg avatarUrl: https://avatars.githubusercontent.com/u/3860655?u=f55f47eb2d6a9b495e806ac5a044e3ae01ccc1fa&v=4 url: https://github.com/peterHoburg - login: jgreys - avatarUrl: https://avatars.githubusercontent.com/u/4136890?u=b579fd97033269a5e703ab509c7d5478b146cc2d&v=4 + avatarUrl: https://avatars.githubusercontent.com/u/4136890?u=c66ae617d614f6c886f1f1c1799d22100b3c848d&v=4 url: https://github.com/jgreys - login: gorhack avatarUrl: https://avatars.githubusercontent.com/u/4141690?u=ec119ebc4bdf00a7bc84657a71aa17834f4f27f3&v=4 @@ -203,6 +218,9 @@ sponsors: - login: oliverxchen avatarUrl: https://avatars.githubusercontent.com/u/4471774?u=534191f25e32eeaadda22dfab4b0a428733d5489&v=4 url: https://github.com/oliverxchen + - login: Rey8d01 + avatarUrl: https://avatars.githubusercontent.com/u/4836190?u=5942598a23a377602c1669522334ab5ebeaf9165&v=4 + url: https://github.com/Rey8d01 - login: ScrimForever avatarUrl: https://avatars.githubusercontent.com/u/5040124?u=091ec38bfe16d6e762099e91309b59f248616a65&v=4 url: https://github.com/ScrimForever @@ -239,9 +257,9 @@ sponsors: - login: wdwinslow avatarUrl: https://avatars.githubusercontent.com/u/11562137?u=dc01daafb354135603a263729e3d26d939c0c452&v=4 url: https://github.com/wdwinslow - - login: Ge0f3 - avatarUrl: https://avatars.githubusercontent.com/u/11887760?u=ccd80f1ac36dcb8517ef5c4e702e8cc5a80cad2f&v=4 - url: https://github.com/Ge0f3 + - login: bapi24 + avatarUrl: https://avatars.githubusercontent.com/u/11890901?u=45cc721d8f66ad2f62b086afc3d4761d0c16b9c6&v=4 + url: https://github.com/bapi24 - login: svats2k avatarUrl: https://avatars.githubusercontent.com/u/12378398?u=ecf28c19f61052e664bdfeb2391f8107d137915c&v=4 url: https://github.com/svats2k @@ -257,15 +275,12 @@ sponsors: - login: pablonnaoji avatarUrl: https://avatars.githubusercontent.com/u/15187159?u=afc15bd5a4ba9c5c7206bbb1bcaeef606a0932e0&v=4 url: https://github.com/pablonnaoji - - login: robintully - avatarUrl: https://avatars.githubusercontent.com/u/17059673?u=862b9bb01513f5acd30df97433cb97a24dbfb772&v=4 - url: https://github.com/robintully - login: wedwardbeck avatarUrl: https://avatars.githubusercontent.com/u/19333237?u=1de4ae2bf8d59eb4c013f21d863cbe0f2010575f&v=4 url: https://github.com/wedwardbeck - - login: RedCarpetUp - avatarUrl: https://avatars.githubusercontent.com/u/20360440?v=4 - url: https://github.com/RedCarpetUp + - login: m4knV + avatarUrl: https://avatars.githubusercontent.com/u/19666130?u=843383978814886be93c137d10d2e20e9f13af07&v=4 + url: https://github.com/m4knV - login: Filimoa avatarUrl: https://avatars.githubusercontent.com/u/21352040?u=75e02d102d2ee3e3d793e555fa5c63045913ccb0&v=4 url: https://github.com/Filimoa @@ -302,6 +317,9 @@ sponsors: - login: ProteinQure avatarUrl: https://avatars.githubusercontent.com/u/33707203?v=4 url: https://github.com/ProteinQure + - login: faviasono + avatarUrl: https://avatars.githubusercontent.com/u/37707874?u=f0b75ca4248987c08ed8fb8ed682e7e74d5d7091&v=4 + url: https://github.com/faviasono - login: ybressler avatarUrl: https://avatars.githubusercontent.com/u/40807730?u=41e2c00f1eebe3c402635f0325e41b4e6511462c&v=4 url: https://github.com/ybressler @@ -341,9 +359,12 @@ sponsors: - login: anthonycepeda avatarUrl: https://avatars.githubusercontent.com/u/72019805?u=4252c6b6dc5024af502a823a3ac5e7a03a69963f&v=4 url: https://github.com/anthonycepeda - - login: dotlas - avatarUrl: https://avatars.githubusercontent.com/u/88832003?v=4 - url: https://github.com/dotlas + - login: fpiem + avatarUrl: https://avatars.githubusercontent.com/u/77389987?u=f667a25cd4832b28801189013b74450e06cc232c&v=4 + url: https://github.com/fpiem + - login: DelfinaCare + avatarUrl: https://avatars.githubusercontent.com/u/83734439?v=4 + url: https://github.com/DelfinaCare - login: programvx avatarUrl: https://avatars.githubusercontent.com/u/96057906?v=4 url: https://github.com/programvx @@ -354,7 +375,7 @@ sponsors: avatarUrl: https://avatars.githubusercontent.com/u/115501964?v=4 url: https://github.com/Dagmaara - - login: linux-china - avatarUrl: https://avatars.githubusercontent.com/u/46711?v=4 + avatarUrl: https://avatars.githubusercontent.com/u/46711?u=cd77c65338b158750eb84dc7ff1acf3209ccfc4f&v=4 url: https://github.com/linux-china - login: ddanier avatarUrl: https://avatars.githubusercontent.com/u/113563?u=ed1dc79de72f93bd78581f88ebc6952b62f472da&v=4 @@ -371,15 +392,9 @@ sponsors: - login: hhatto avatarUrl: https://avatars.githubusercontent.com/u/150309?u=3e8f63c27bf996bfc68464b0ce3f7a3e40e6ea7f&v=4 url: https://github.com/hhatto - - login: yourkin - avatarUrl: https://avatars.githubusercontent.com/u/178984?u=b43a7e5f8818f7d9083d3b110118d9c27d48a794&v=4 - url: https://github.com/yourkin - login: slafs avatarUrl: https://avatars.githubusercontent.com/u/210173?v=4 url: https://github.com/slafs - - login: assem-ch - avatarUrl: https://avatars.githubusercontent.com/u/315228?u=e0c5ab30726d3243a40974bb9bae327866e42d9b&v=4 - url: https://github.com/assem-ch - login: adamghill avatarUrl: https://avatars.githubusercontent.com/u/317045?u=f1349d5ffe84a19f324e204777859fbf69ddf633&v=4 url: https://github.com/adamghill @@ -494,9 +509,6 @@ sponsors: - login: logan-connolly avatarUrl: https://avatars.githubusercontent.com/u/16244943?u=8ae66dfbba936463cc8aa0dd7a6d2b4c0cc757eb&v=4 url: https://github.com/logan-connolly - - login: stevenayers - avatarUrl: https://avatars.githubusercontent.com/u/16361214?u=098b797d8d48afb8cd964b717847943b61d24a6d&v=4 - url: https://github.com/stevenayers - login: cdsre avatarUrl: https://avatars.githubusercontent.com/u/16945936?v=4 url: https://github.com/cdsre @@ -521,6 +533,9 @@ sponsors: - login: SebTota avatarUrl: https://avatars.githubusercontent.com/u/25122511?v=4 url: https://github.com/SebTota + - login: joerambo + avatarUrl: https://avatars.githubusercontent.com/u/26282974?v=4 + url: https://github.com/joerambo - login: mertguvencli avatarUrl: https://avatars.githubusercontent.com/u/29762151?u=16a906d90df96c8cff9ea131a575c4bc171b1523&v=4 url: https://github.com/mertguvencli @@ -533,6 +548,9 @@ sponsors: - login: engineerjoe440 avatarUrl: https://avatars.githubusercontent.com/u/33275230?u=eb223cad27017bb1e936ee9b429b450d092d0236&v=4 url: https://github.com/engineerjoe440 + - login: bnkc + avatarUrl: https://avatars.githubusercontent.com/u/34930566?u=20f362505e2a994805233f42e69f9f14b4a9dd0c&v=4 + url: https://github.com/bnkc - login: declon avatarUrl: https://avatars.githubusercontent.com/u/36180226?v=4 url: https://github.com/declon @@ -590,12 +608,9 @@ sponsors: - login: pondDevThai avatarUrl: https://avatars.githubusercontent.com/u/71592181?u=08af9a59bccfd8f6b101de1005aa9822007d0a44&v=4 url: https://github.com/pondDevThai - - login: marlonmartins2 - avatarUrl: https://avatars.githubusercontent.com/u/87719558?u=d07ffecfdabf4fd9aca987f8b5cd9128c65e598e&v=4 - url: https://github.com/marlonmartins2 -- - login: 2niuhe - avatarUrl: https://avatars.githubusercontent.com/u/13382324?u=ac918d72e0329c87ba29b3bf85e03e98a4ee9427&v=4 - url: https://github.com/2niuhe +- - login: wardal + avatarUrl: https://avatars.githubusercontent.com/u/15804042?v=4 + url: https://github.com/wardal - login: gabrielmbmb avatarUrl: https://avatars.githubusercontent.com/u/29572918?u=6d1e00b5d558e96718312ff910a2318f47cc3145&v=4 url: https://github.com/gabrielmbmb @@ -605,6 +620,3 @@ sponsors: - login: Moises6669 avatarUrl: https://avatars.githubusercontent.com/u/66188523?u=96af25b8d5be9f983cb96e9dd7c605c716caf1f5&v=4 url: https://github.com/Moises6669 - - login: su-shubham - avatarUrl: https://avatars.githubusercontent.com/u/75021117?v=4 - url: https://github.com/su-shubham diff --git a/docs/en/data/people.yml b/docs/en/data/people.yml index 730528795c..51940a6b13 100644 --- a/docs/en/data/people.yml +++ b/docs/en/data/people.yml @@ -1,12 +1,12 @@ maintainers: - login: tiangolo - answers: 1315 - prs: 342 + answers: 1837 + prs: 360 avatarUrl: https://avatars.githubusercontent.com/u/1326112?u=740f11212a731f56798f558ceddb0bd07642afa7&v=4 url: https://github.com/tiangolo experts: - login: Kludex - count: 367 + count: 374 avatarUrl: https://avatars.githubusercontent.com/u/7353520?u=62adc405ef418f4b6c8caa93d3eb8ab107bc4927&v=4 url: https://github.com/Kludex - login: dmontagu @@ -15,14 +15,14 @@ experts: url: https://github.com/dmontagu - login: ycd count: 221 - avatarUrl: https://avatars.githubusercontent.com/u/62724709?u=fa40e037060d62bf82e16b505d870a2866725f38&v=4 + avatarUrl: https://avatars.githubusercontent.com/u/62724709?u=bba5af018423a2858d49309bed2a899bb5c34ac5&v=4 url: https://github.com/ycd - login: Mause count: 207 avatarUrl: https://avatars.githubusercontent.com/u/1405026?v=4 url: https://github.com/Mause - login: JarroVGIT - count: 187 + count: 192 avatarUrl: https://avatars.githubusercontent.com/u/13659033?u=e8bea32d07a5ef72f7dde3b2079ceb714923ca05&v=4 url: https://github.com/JarroVGIT - login: euri10 @@ -33,22 +33,26 @@ experts: count: 130 avatarUrl: https://avatars.githubusercontent.com/u/331403?v=4 url: https://github.com/phy25 +- login: iudeen + count: 87 + avatarUrl: https://avatars.githubusercontent.com/u/10519440?u=2843b3303282bff8b212dcd4d9d6689452e4470c&v=4 + url: https://github.com/iudeen - login: raphaelauv count: 77 avatarUrl: https://avatars.githubusercontent.com/u/10202690?u=e6f86f5c0c3026a15d6b51792fa3e532b12f1371&v=4 url: https://github.com/raphaelauv -- login: iudeen - count: 76 - avatarUrl: https://avatars.githubusercontent.com/u/10519440?u=2843b3303282bff8b212dcd4d9d6689452e4470c&v=4 - url: https://github.com/iudeen - login: ArcLightSlavik count: 71 avatarUrl: https://avatars.githubusercontent.com/u/31127044?u=b0f2c37142f4b762e41ad65dc49581813422bd71&v=4 url: https://github.com/ArcLightSlavik - login: falkben - count: 58 + count: 59 avatarUrl: https://avatars.githubusercontent.com/u/653031?u=0c8d8f33d87f1aa1a6488d3f02105e9abc838105&v=4 url: https://github.com/falkben +- login: jgould22 + count: 55 + avatarUrl: https://avatars.githubusercontent.com/u/4335847?u=ed77f67e0bb069084639b24d812dbb2a2b1dc554&v=4 + url: https://github.com/jgould22 - login: sm-Fifteen count: 50 avatarUrl: https://avatars.githubusercontent.com/u/516999?u=437c0c5038558c67e887ccd863c1ba0f846c03da&v=4 @@ -57,10 +61,6 @@ experts: count: 46 avatarUrl: https://avatars.githubusercontent.com/u/16958893?u=f8be7088d5076d963984a21f95f44e559192d912&v=4 url: https://github.com/insomnes -- login: jgould22 - count: 46 - avatarUrl: https://avatars.githubusercontent.com/u/4335847?u=ed77f67e0bb069084639b24d812dbb2a2b1dc554&v=4 - url: https://github.com/jgould22 - login: Dustyposa count: 45 avatarUrl: https://avatars.githubusercontent.com/u/27180793?u=5cf2877f50b3eb2bc55086089a78a36f07042889&v=4 @@ -78,19 +78,19 @@ experts: avatarUrl: https://avatars.githubusercontent.com/u/5167622?u=de8f597c81d6336fcebc37b32dfd61a3f877160c&v=4 url: https://github.com/STeveShary - login: chbndrhnns - count: 35 + count: 36 avatarUrl: https://avatars.githubusercontent.com/u/7534547?v=4 url: https://github.com/chbndrhnns +- login: frankie567 + count: 33 + avatarUrl: https://avatars.githubusercontent.com/u/1144727?u=85c025e3fcc7bd79a5665c63ee87cdf8aae13374&v=4 + url: https://github.com/frankie567 - login: prostomarkeloff count: 33 avatarUrl: https://avatars.githubusercontent.com/u/28061158?u=72309cc1f2e04e40fa38b29969cb4e9d3f722e7b&v=4 url: https://github.com/prostomarkeloff -- login: frankie567 - count: 31 - avatarUrl: https://avatars.githubusercontent.com/u/1144727?u=85c025e3fcc7bd79a5665c63ee87cdf8aae13374&v=4 - url: https://github.com/frankie567 - login: acidjunk - count: 31 + count: 32 avatarUrl: https://avatars.githubusercontent.com/u/685002?u=b5094ab4527fc84b006c0ac9ff54367bdebb2267&v=4 url: https://github.com/acidjunk - login: krishnardt @@ -113,12 +113,16 @@ experts: count: 25 avatarUrl: https://avatars.githubusercontent.com/u/43723790?u=9bcce836bbce55835291c5b2ac93a4e311f4b3c3&v=4 url: https://github.com/dbanty +- login: yinziyan1206 + count: 25 + avatarUrl: https://avatars.githubusercontent.com/u/37829370?u=da44ca53aefd5c23f346fab8e9fd2e108294c179&v=4 + url: https://github.com/yinziyan1206 - login: SirTelemak count: 24 avatarUrl: https://avatars.githubusercontent.com/u/9435877?u=719327b7d2c4c62212456d771bfa7c6b8dbb9eac&v=4 url: https://github.com/SirTelemak - login: odiseo0 - count: 23 + count: 24 avatarUrl: https://avatars.githubusercontent.com/u/87550035?u=16f9255804161c6ff3c8b7ef69848f0126bcd405&v=4 url: https://github.com/odiseo0 - login: acnebs @@ -137,14 +141,14 @@ experts: count: 19 avatarUrl: https://avatars.githubusercontent.com/u/24581770?v=4 url: https://github.com/retnikt +- login: rafsaf + count: 19 + avatarUrl: https://avatars.githubusercontent.com/u/51059348?u=f8f0d6d6e90fac39fa786228158ba7f013c74271&v=4 + url: https://github.com/rafsaf - login: Hultner count: 18 avatarUrl: https://avatars.githubusercontent.com/u/2669034?u=115e53df959309898ad8dc9443fbb35fee71df07&v=4 url: https://github.com/Hultner -- login: rafsaf - count: 18 - avatarUrl: https://avatars.githubusercontent.com/u/51059348?u=f8f0d6d6e90fac39fa786228158ba7f013c74271&v=4 - url: https://github.com/rafsaf - login: jorgerpo count: 17 avatarUrl: https://avatars.githubusercontent.com/u/12537771?u=7444d20019198e34911082780cc7ad73f2b97cb3&v=4 @@ -161,10 +165,6 @@ experts: count: 16 avatarUrl: https://avatars.githubusercontent.com/u/39515546?u=ec35139777597cdbbbddda29bf8b9d4396b429a9&v=4 url: https://github.com/waynerv -- login: yinziyan1206 - count: 16 - avatarUrl: https://avatars.githubusercontent.com/u/37829370?v=4 - url: https://github.com/yinziyan1206 - login: dstlny count: 16 avatarUrl: https://avatars.githubusercontent.com/u/41964673?u=9f2174f9d61c15c6e3a4c9e3aeee66f711ce311f&v=4 @@ -173,6 +173,10 @@ experts: count: 15 avatarUrl: https://avatars.githubusercontent.com/u/26334101?u=071c062d2861d3dd127f6b4a5258cd8ef55d4c50&v=4 url: https://github.com/jonatasoli +- login: mbroton + count: 15 + avatarUrl: https://avatars.githubusercontent.com/u/50829834?u=a48610bf1bffaa9c75d03228926e2eb08a2e24ee&v=4 + url: https://github.com/mbroton - login: hellocoldworld count: 14 avatarUrl: https://avatars.githubusercontent.com/u/47581948?u=3d2186796434c507a6cb6de35189ab0ad27c356f&v=4 @@ -193,27 +197,39 @@ experts: count: 12 avatarUrl: https://avatars.githubusercontent.com/u/2964996?v=4 url: https://github.com/n8sty -- login: mbroton - count: 12 - avatarUrl: https://avatars.githubusercontent.com/u/50829834?u=a48610bf1bffaa9c75d03228926e2eb08a2e24ee&v=4 - url: https://github.com/mbroton last_month_active: -- login: JarroVGIT - count: 18 - avatarUrl: https://avatars.githubusercontent.com/u/13659033?u=e8bea32d07a5ef72f7dde3b2079ceb714923ca05&v=4 - url: https://github.com/JarroVGIT +- login: jgould22 + count: 9 + avatarUrl: https://avatars.githubusercontent.com/u/4335847?u=ed77f67e0bb069084639b24d812dbb2a2b1dc554&v=4 + url: https://github.com/jgould22 +- login: yinziyan1206 + count: 9 + avatarUrl: https://avatars.githubusercontent.com/u/37829370?u=da44ca53aefd5c23f346fab8e9fd2e108294c179&v=4 + url: https://github.com/yinziyan1206 - login: iudeen count: 8 avatarUrl: https://avatars.githubusercontent.com/u/10519440?u=2843b3303282bff8b212dcd4d9d6689452e4470c&v=4 url: https://github.com/iudeen -- login: mbroton +- login: Kludex + count: 5 + avatarUrl: https://avatars.githubusercontent.com/u/7353520?u=62adc405ef418f4b6c8caa93d3eb8ab107bc4927&v=4 + url: https://github.com/Kludex +- login: JarroVGIT + count: 5 + avatarUrl: https://avatars.githubusercontent.com/u/13659033?u=e8bea32d07a5ef72f7dde3b2079ceb714923ca05&v=4 + url: https://github.com/JarroVGIT +- login: TheJumpyWizard count: 4 + avatarUrl: https://avatars.githubusercontent.com/u/90986815?u=67e9c13c9f063dd4313db7beb64eaa2f3a37f1fe&v=4 + url: https://github.com/TheJumpyWizard +- login: mbroton + count: 3 avatarUrl: https://avatars.githubusercontent.com/u/50829834?u=a48610bf1bffaa9c75d03228926e2eb08a2e24ee&v=4 url: https://github.com/mbroton -- login: yinziyan1206 +- login: mateoradman count: 3 - avatarUrl: https://avatars.githubusercontent.com/u/37829370?v=4 - url: https://github.com/yinziyan1206 + avatarUrl: https://avatars.githubusercontent.com/u/48420316?u=066f36b8e8e263b0d90798113b0f291d3266db7c&v=4 + url: https://github.com/mateoradman top_contributors: - login: waynerv count: 25 @@ -223,22 +239,18 @@ top_contributors: count: 22 avatarUrl: https://avatars.githubusercontent.com/u/41147016?u=55010621aece725aa702270b54fed829b6a1fe60&v=4 url: https://github.com/tokusumi +- login: jaystone776 + count: 17 + avatarUrl: https://avatars.githubusercontent.com/u/11191137?u=299205a95e9b6817a43144a48b643346a5aac5cc&v=4 + url: https://github.com/jaystone776 - login: dmontagu count: 16 avatarUrl: https://avatars.githubusercontent.com/u/35119617?u=58ed2a45798a4339700e2f62b2e12e6e54bf0396&v=4 url: https://github.com/dmontagu -- login: jaystone776 - count: 16 - avatarUrl: https://avatars.githubusercontent.com/u/11191137?u=299205a95e9b6817a43144a48b643346a5aac5cc&v=4 - url: https://github.com/jaystone776 - login: Kludex count: 15 avatarUrl: https://avatars.githubusercontent.com/u/7353520?u=62adc405ef418f4b6c8caa93d3eb8ab107bc4927&v=4 url: https://github.com/Kludex -- login: dependabot - count: 14 - avatarUrl: https://avatars.githubusercontent.com/in/29110?v=4 - url: https://github.com/apps/dependabot - login: euri10 count: 13 avatarUrl: https://avatars.githubusercontent.com/u/1104190?u=321a2e953e6645a7d09b732786c7a8061e0f8a8b&v=4 @@ -267,10 +279,6 @@ top_contributors: count: 7 avatarUrl: https://avatars.githubusercontent.com/u/56785022?u=d5c3a02567c8649e146fcfc51b6060ccaf8adef8&v=4 url: https://github.com/rjNemo -- login: pre-commit-ci - count: 6 - avatarUrl: https://avatars.githubusercontent.com/in/68672?v=4 - url: https://github.com/apps/pre-commit-ci - login: wshayes count: 5 avatarUrl: https://avatars.githubusercontent.com/u/365303?u=07ca03c5ee811eb0920e633cc3c3db73dbec1aa5&v=4 @@ -287,6 +295,10 @@ top_contributors: count: 5 avatarUrl: https://avatars.githubusercontent.com/u/43503750?u=f440bc9062afb3c43b9b9c6cdfdcfe31d58699ef&v=4 url: https://github.com/ComicShrimp +- login: batlopes + count: 5 + avatarUrl: https://avatars.githubusercontent.com/u/33462923?u=0fb3d7acb316764616f11e4947faf080e49ad8d9&v=4 + url: https://github.com/batlopes - login: jekirl count: 4 avatarUrl: https://avatars.githubusercontent.com/u/2546697?u=a027452387d85bd4a14834e19d716c99255fb3b7&v=4 @@ -301,7 +313,7 @@ top_contributors: url: https://github.com/jfunez - login: ycd count: 4 - avatarUrl: https://avatars.githubusercontent.com/u/62724709?u=fa40e037060d62bf82e16b505d870a2866725f38&v=4 + avatarUrl: https://avatars.githubusercontent.com/u/62724709?u=bba5af018423a2858d49309bed2a899bb5c34ac5&v=4 url: https://github.com/ycd - login: komtaki count: 4 @@ -319,21 +331,17 @@ top_contributors: count: 4 avatarUrl: https://avatars.githubusercontent.com/u/79563565?u=1741703bd6c8f491503354b363a86e879b4c1cab&v=4 url: https://github.com/NinaHwang -- login: batlopes - count: 4 - avatarUrl: https://avatars.githubusercontent.com/u/33462923?u=0fb3d7acb316764616f11e4947faf080e49ad8d9&v=4 - url: https://github.com/batlopes top_reviewers: - login: Kludex - count: 108 + count: 109 avatarUrl: https://avatars.githubusercontent.com/u/7353520?u=62adc405ef418f4b6c8caa93d3eb8ab107bc4927&v=4 url: https://github.com/Kludex - login: BilalAlpaslan - count: 65 + count: 70 avatarUrl: https://avatars.githubusercontent.com/u/47563997?u=63ed66e304fe8d765762c70587d61d9196e5c82d&v=4 url: https://github.com/BilalAlpaslan - login: yezz123 - count: 56 + count: 59 avatarUrl: https://avatars.githubusercontent.com/u/52716203?u=636b4f79645176df4527dd45c12d5dbb5a4193cf&v=4 url: https://github.com/yezz123 - login: tokusumi @@ -350,7 +358,7 @@ top_reviewers: url: https://github.com/Laineyzhang55 - login: ycd count: 45 - avatarUrl: https://avatars.githubusercontent.com/u/62724709?u=fa40e037060d62bf82e16b505d870a2866725f38&v=4 + avatarUrl: https://avatars.githubusercontent.com/u/62724709?u=bba5af018423a2858d49309bed2a899bb5c34ac5&v=4 url: https://github.com/ycd - login: cikay count: 41 @@ -364,30 +372,30 @@ top_reviewers: count: 33 avatarUrl: https://avatars.githubusercontent.com/u/1024932?u=b2ea249c6b41ddf98679c8d110d0f67d4a3ebf93&v=4 url: https://github.com/AdrianDeAnda +- login: iudeen + count: 33 + avatarUrl: https://avatars.githubusercontent.com/u/10519440?u=2843b3303282bff8b212dcd4d9d6689452e4470c&v=4 + url: https://github.com/iudeen - login: ArcLightSlavik count: 31 avatarUrl: https://avatars.githubusercontent.com/u/31127044?u=b0f2c37142f4b762e41ad65dc49581813422bd71&v=4 url: https://github.com/ArcLightSlavik -- login: iudeen - count: 26 - avatarUrl: https://avatars.githubusercontent.com/u/10519440?u=2843b3303282bff8b212dcd4d9d6689452e4470c&v=4 - url: https://github.com/iudeen +- login: komtaki + count: 27 + avatarUrl: https://avatars.githubusercontent.com/u/39375566?u=260ad6b1a4b34c07dbfa728da5e586f16f6d1824&v=4 + url: https://github.com/komtaki - login: cassiobotaro - count: 25 + count: 26 avatarUrl: https://avatars.githubusercontent.com/u/3127847?u=b0a652331da17efeb85cd6e3a4969182e5004804&v=4 url: https://github.com/cassiobotaro - login: lsglucas - count: 25 + count: 26 avatarUrl: https://avatars.githubusercontent.com/u/61513630?u=320e43fe4dc7bc6efc64e9b8f325f8075634fd20&v=4 url: https://github.com/lsglucas - login: dmontagu count: 23 avatarUrl: https://avatars.githubusercontent.com/u/35119617?u=58ed2a45798a4339700e2f62b2e12e6e54bf0396&v=4 url: https://github.com/dmontagu -- login: komtaki - count: 21 - avatarUrl: https://avatars.githubusercontent.com/u/39375566?u=260ad6b1a4b34c07dbfa728da5e586f16f6d1824&v=4 - url: https://github.com/komtaki - login: hard-coders count: 20 avatarUrl: https://avatars.githubusercontent.com/u/9651103?u=95db33927bbff1ed1c07efddeb97ac2ff33068ed&v=4 @@ -429,7 +437,7 @@ top_reviewers: avatarUrl: https://avatars.githubusercontent.com/u/63476957?u=6c86e59b48e0394d4db230f37fc9ad4d7e2c27c7&v=4 url: https://github.com/delhi09 - login: odiseo0 - count: 14 + count: 15 avatarUrl: https://avatars.githubusercontent.com/u/87550035?u=16f9255804161c6ff3c8b7ef69848f0126bcd405&v=4 url: https://github.com/odiseo0 - login: sh0nk @@ -464,6 +472,14 @@ top_reviewers: count: 10 avatarUrl: https://avatars.githubusercontent.com/u/43503750?u=f440bc9062afb3c43b9b9c6cdfdcfe31d58699ef&v=4 url: https://github.com/ComicShrimp +- login: peidrao + count: 10 + avatarUrl: https://avatars.githubusercontent.com/u/32584628?u=88c2cb42a99e0f50cdeae3606992568184783ee5&v=4 + url: https://github.com/peidrao +- login: izaguerreiro + count: 9 + avatarUrl: https://avatars.githubusercontent.com/u/2241504?v=4 + url: https://github.com/izaguerreiro - login: graingert count: 9 avatarUrl: https://avatars.githubusercontent.com/u/413772?u=64b77b6aa405c68a9c6bcf45f84257c66eea5f32&v=4 @@ -480,10 +496,6 @@ top_reviewers: count: 9 avatarUrl: https://avatars.githubusercontent.com/u/69092910?u=4ac58eab99bd37d663f3d23551df96d4fbdbf760&v=4 url: https://github.com/bezaca -- login: izaguerreiro - count: 8 - avatarUrl: https://avatars.githubusercontent.com/u/2241504?v=4 - url: https://github.com/izaguerreiro - login: raphaelauv count: 8 avatarUrl: https://avatars.githubusercontent.com/u/10202690?u=e6f86f5c0c3026a15d6b51792fa3e532b12f1371&v=4 @@ -504,6 +516,10 @@ top_reviewers: count: 8 avatarUrl: https://avatars.githubusercontent.com/u/662249?v=4 url: https://github.com/dimaqq +- login: Xewus + count: 8 + avatarUrl: https://avatars.githubusercontent.com/u/85196001?u=4bdd4a0300530a504987db27488ba79c37f2fb18&v=4 + url: https://github.com/Xewus - login: Serrones count: 7 avatarUrl: https://avatars.githubusercontent.com/u/22691749?u=4795b880e13ca33a73e52fc0ef7dc9c60c8fce47&v=4 @@ -512,11 +528,3 @@ top_reviewers: count: 7 avatarUrl: https://avatars.githubusercontent.com/u/21287303?u=b049eac3e51a4c0473c2efe66b4d28a7d8f2b572&v=4 url: https://github.com/jovicon -- login: ryuckel - count: 7 - avatarUrl: https://avatars.githubusercontent.com/u/36391432?u=094eec0cfddd5013f76f31e55e56147d78b19553&v=4 - url: https://github.com/ryuckel -- login: NastasiaSaby - count: 7 - avatarUrl: https://avatars.githubusercontent.com/u/8245071?u=b3afd005f9e4bf080c219ef61a592b3a8004b764&v=4 - url: https://github.com/NastasiaSaby From 5f1cc3a5ff71b51c194e6fffe43b57501bfa22b0 Mon Sep 17 00:00:00 2001 From: github-actions Date: Fri, 2 Dec 2022 17:23:12 +0000 Subject: [PATCH 91/97] =?UTF-8?q?=F0=9F=93=9D=20Update=20release=20notes?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docs/en/docs/release-notes.md | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/en/docs/release-notes.md b/docs/en/docs/release-notes.md index 4252d68c55..29632574e8 100644 --- a/docs/en/docs/release-notes.md +++ b/docs/en/docs/release-notes.md @@ -2,6 +2,7 @@ ## Latest Changes +* 👥 Update FastAPI People. PR [#5722](https://github.com/tiangolo/fastapi/pull/5722) by [@github-actions[bot]](https://github.com/apps/github-actions). * 🔧 Update sponsors, disable course bundle. PR [#5713](https://github.com/tiangolo/fastapi/pull/5713) by [@tiangolo](https://github.com/tiangolo). * ⬆ Update typer[all] requirement from <0.7.0,>=0.6.1 to >=0.6.1,<0.8.0. PR [#5639](https://github.com/tiangolo/fastapi/pull/5639) by [@dependabot[bot]](https://github.com/apps/dependabot). From 1ba515a18d563df8efff0dfafd19d187586dd9bd Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Sat, 3 Dec 2022 23:25:39 +0100 Subject: [PATCH 92/97] =?UTF-8?q?=E2=AC=86=20Bump=20pypa/gh-action-pypi-pu?= =?UTF-8?q?blish=20from=201.5.1=20to=201.5.2=20(#5714)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Bumps [pypa/gh-action-pypi-publish](https://github.com/pypa/gh-action-pypi-publish) from 1.5.1 to 1.5.2. - [Release notes](https://github.com/pypa/gh-action-pypi-publish/releases) - [Commits](https://github.com/pypa/gh-action-pypi-publish/compare/v1.5.1...v1.5.2) --- updated-dependencies: - dependency-name: pypa/gh-action-pypi-publish dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/publish.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/publish.yml b/.github/workflows/publish.yml index ab27d4b855..8ffb493a4f 100644 --- a/.github/workflows/publish.yml +++ b/.github/workflows/publish.yml @@ -31,7 +31,7 @@ jobs: - name: Build distribution run: python -m build - name: Publish - uses: pypa/gh-action-pypi-publish@v1.5.1 + uses: pypa/gh-action-pypi-publish@v1.5.2 with: password: ${{ secrets.PYPI_API_TOKEN }} - name: Dump GitHub context From 97f04ab58c2c047d6d2ff7d803890a90190109c9 Mon Sep 17 00:00:00 2001 From: github-actions Date: Sat, 3 Dec 2022 22:26:17 +0000 Subject: [PATCH 93/97] =?UTF-8?q?=F0=9F=93=9D=20Update=20release=20notes?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docs/en/docs/release-notes.md | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/en/docs/release-notes.md b/docs/en/docs/release-notes.md index 29632574e8..6771edb08b 100644 --- a/docs/en/docs/release-notes.md +++ b/docs/en/docs/release-notes.md @@ -2,6 +2,7 @@ ## Latest Changes +* ⬆ Bump pypa/gh-action-pypi-publish from 1.5.1 to 1.5.2. PR [#5714](https://github.com/tiangolo/fastapi/pull/5714) by [@dependabot[bot]](https://github.com/apps/dependabot). * 👥 Update FastAPI People. PR [#5722](https://github.com/tiangolo/fastapi/pull/5722) by [@github-actions[bot]](https://github.com/apps/github-actions). * 🔧 Update sponsors, disable course bundle. PR [#5713](https://github.com/tiangolo/fastapi/pull/5713) by [@tiangolo](https://github.com/tiangolo). * ⬆ Update typer[all] requirement from <0.7.0,>=0.6.1 to >=0.6.1,<0.8.0. PR [#5639](https://github.com/tiangolo/fastapi/pull/5639) by [@dependabot[bot]](https://github.com/apps/dependabot). From 9efab1bd96ef061edf1753626573a0a2be1eef09 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebasti=C3=A1n=20Ram=C3=ADrez?= Date: Fri, 16 Dec 2022 22:11:03 +0400 Subject: [PATCH 94/97] =?UTF-8?q?=F0=9F=91=B7=20Refactor=20CI=20artifact?= =?UTF-8?q?=20upload/download=20for=20docs=20previews=20(#5793)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .github/workflows/build-docs.yml | 2 +- .github/workflows/preview-docs.yml | 7 ++++++- scripts/zip-docs.sh | 4 +++- 3 files changed, 10 insertions(+), 3 deletions(-) diff --git a/.github/workflows/build-docs.yml b/.github/workflows/build-docs.yml index 3052ec1e2b..3bf9862742 100644 --- a/.github/workflows/build-docs.yml +++ b/.github/workflows/build-docs.yml @@ -36,7 +36,7 @@ jobs: - uses: actions/upload-artifact@v3 with: name: docs-zip - path: ./docs.zip + path: ./site/docs.zip - name: Deploy to Netlify uses: nwtgck/actions-netlify@v1.2.4 with: diff --git a/.github/workflows/preview-docs.yml b/.github/workflows/preview-docs.yml index a2e5976fba..bb3e9ebf64 100644 --- a/.github/workflows/preview-docs.yml +++ b/.github/workflows/preview-docs.yml @@ -11,6 +11,10 @@ jobs: runs-on: ubuntu-latest steps: - uses: actions/checkout@v3 + - name: Clean site + run: | + rm -rf ./site + mkdir ./site - name: Download Artifact Docs uses: dawidd6/action-download-artifact@v2.24.2 with: @@ -18,9 +22,10 @@ jobs: workflow: build-docs.yml run_id: ${{ github.event.workflow_run.id }} name: docs-zip + path: ./site/ - name: Unzip docs run: | - rm -rf ./site + cd ./site unzip docs.zip rm -f docs.zip - name: Deploy to Netlify diff --git a/scripts/zip-docs.sh b/scripts/zip-docs.sh index f2b7ba3be3..69315f5ddd 100644 --- a/scripts/zip-docs.sh +++ b/scripts/zip-docs.sh @@ -3,7 +3,9 @@ set -x set -e +cd ./site + if [ -f docs.zip ]; then rm -rf docs.zip fi -zip -r docs.zip ./site +zip -r docs.zip ./ From dc9fb1305a7665a6f36053fc09e9bd1804928827 Mon Sep 17 00:00:00 2001 From: github-actions Date: Fri, 16 Dec 2022 18:11:45 +0000 Subject: [PATCH 95/97] =?UTF-8?q?=F0=9F=93=9D=20Update=20release=20notes?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docs/en/docs/release-notes.md | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/en/docs/release-notes.md b/docs/en/docs/release-notes.md index 6771edb08b..e444624582 100644 --- a/docs/en/docs/release-notes.md +++ b/docs/en/docs/release-notes.md @@ -2,6 +2,7 @@ ## Latest Changes +* 👷 Refactor CI artifact upload/download for docs previews. PR [#5793](https://github.com/tiangolo/fastapi/pull/5793) by [@tiangolo](https://github.com/tiangolo). * ⬆ Bump pypa/gh-action-pypi-publish from 1.5.1 to 1.5.2. PR [#5714](https://github.com/tiangolo/fastapi/pull/5714) by [@dependabot[bot]](https://github.com/apps/dependabot). * 👥 Update FastAPI People. PR [#5722](https://github.com/tiangolo/fastapi/pull/5722) by [@github-actions[bot]](https://github.com/apps/github-actions). * 🔧 Update sponsors, disable course bundle. PR [#5713](https://github.com/tiangolo/fastapi/pull/5713) by [@tiangolo](https://github.com/tiangolo). From 63ad0ed4a66453fedb25dc002372cdfc4e9138dc Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 16 Dec 2022 23:10:29 +0400 Subject: [PATCH 96/97] =?UTF-8?q?=E2=AC=86=20Bump=20nwtgck/actions-netlify?= =?UTF-8?q?=20from=201.2.4=20to=202.0.0=20(#5757)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/build-docs.yml | 2 +- .github/workflows/preview-docs.yml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/build-docs.yml b/.github/workflows/build-docs.yml index 3bf9862742..b9bd521b3f 100644 --- a/.github/workflows/build-docs.yml +++ b/.github/workflows/build-docs.yml @@ -38,7 +38,7 @@ jobs: name: docs-zip path: ./site/docs.zip - name: Deploy to Netlify - uses: nwtgck/actions-netlify@v1.2.4 + uses: nwtgck/actions-netlify@v2.0.0 with: publish-dir: './site' production-branch: master diff --git a/.github/workflows/preview-docs.yml b/.github/workflows/preview-docs.yml index bb3e9ebf64..7d31a9c64e 100644 --- a/.github/workflows/preview-docs.yml +++ b/.github/workflows/preview-docs.yml @@ -30,7 +30,7 @@ jobs: rm -f docs.zip - name: Deploy to Netlify id: netlify - uses: nwtgck/actions-netlify@v1.2.4 + uses: nwtgck/actions-netlify@v2.0.0 with: publish-dir: './site' production-deploy: false From 10500dbc035b09dbe92ee05031aeca62364b5e31 Mon Sep 17 00:00:00 2001 From: github-actions Date: Fri, 16 Dec 2022 19:11:14 +0000 Subject: [PATCH 97/97] =?UTF-8?q?=F0=9F=93=9D=20Update=20release=20notes?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docs/en/docs/release-notes.md | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/en/docs/release-notes.md b/docs/en/docs/release-notes.md index e444624582..b65460294b 100644 --- a/docs/en/docs/release-notes.md +++ b/docs/en/docs/release-notes.md @@ -2,6 +2,7 @@ ## Latest Changes +* ⬆ Bump nwtgck/actions-netlify from 1.2.4 to 2.0.0. PR [#5757](https://github.com/tiangolo/fastapi/pull/5757) by [@dependabot[bot]](https://github.com/apps/dependabot). * 👷 Refactor CI artifact upload/download for docs previews. PR [#5793](https://github.com/tiangolo/fastapi/pull/5793) by [@tiangolo](https://github.com/tiangolo). * ⬆ Bump pypa/gh-action-pypi-publish from 1.5.1 to 1.5.2. PR [#5714](https://github.com/tiangolo/fastapi/pull/5714) by [@dependabot[bot]](https://github.com/apps/dependabot). * 👥 Update FastAPI People. PR [#5722](https://github.com/tiangolo/fastapi/pull/5722) by [@github-actions[bot]](https://github.com/apps/github-actions).