Compare commits

..

32 Commits

Author SHA1 Message Date
Sebastián Ramírez
9090c771ee 🔖 Release version 0.76.0 2022-05-05 17:26:05 -05:00
Sebastián Ramírez
8df8b037f2 📝 Update release notes 2022-05-05 17:25:14 -05:00
github-actions
792285a047 📝 Update release notes 2022-05-05 22:22:57 +00:00
github-actions[bot]
66f6344820 👥 Update FastAPI People (#4847)
Co-authored-by: github-actions <github-actions@github.com>
2022-05-05 17:22:25 -05:00
github-actions
b44e85ca8a 📝 Update release notes 2022-05-05 22:20:33 +00:00
Marcelo Trylesinski
33d61430cf ⬆ Upgrade Starlette from 0.17.1 to 0.18.0 (#4483)
Co-authored-by: Sebastián Ramírez <tiangolo@gmail.com>
2022-05-05 17:19:59 -05:00
github-actions
146f57b8f7 📝 Update release notes 2022-04-25 10:02:17 +00:00
Sebastián Ramírez
1920c3dd16 🔧 Add Budget Insight sponsor (#4824) 2022-04-25 10:01:39 +00:00
github-actions
07b12c8e41 📝 Update release notes 2022-04-24 15:53:04 +00:00
Sebastián Ramírez
4642d5bb86 🍱 Update sponsor, ExoFlare badge (#4822) 2022-04-24 15:52:31 +00:00
github-actions
0fd99ec337 📝 Update release notes 2022-04-24 15:31:48 +00:00
Sebastián Ramírez
7c8383c96b 🔧 Update sponsors, enable Dropbase again, update TalkPython link (#4821) 2022-04-24 17:31:12 +02:00
Sebastián Ramírez
2b54432a9c 🔖 Release version 0.75.2 2022-04-17 23:08:37 +02:00
Sebastián Ramírez
acd2287b57 📝 Update release notes 2022-04-17 23:07:27 +02:00
github-actions
1d106bd959 📝 Update release notes 2022-04-17 21:01:21 +00:00
Sebastián Ramírez
77fc14eb69 🔧 Update sponsors, add: ExoFlare, Ines Course; remove: Dropbase, Vim.so, Calmcode; update: Striveworks, TalkPython and TestDriven.io (#4805) 2022-04-17 23:00:49 +02:00
github-actions
41d75b6d1c 📝 Update release notes 2022-04-17 20:56:09 +00:00
Sebastián Ramírez
ddd9da3db4 Fix new/recent tests with new fixed ValidationError JSON Schema (#4806) 2022-04-17 20:55:36 +00:00
Sebastián Ramírez
197c1d6dd7 📝 Update release notes 2022-04-17 21:02:49 +02:00
github-actions
d9e7a541fd 📝 Update release notes 2022-04-17 17:42:18 +00:00
dconathan
c449ae5c74 🐛 Fix JSON Schema for ValidationError at field loc (#3810)
Co-authored-by: Devin Conathan <dconatha@amfam.com>
2022-04-17 19:41:46 +02:00
github-actions
1d8d81a6d5 📝 Update release notes 2022-04-17 17:22:26 +00:00
Marcelo Trylesinski
d81c908132 🐛 Fix support for prefix on APIRouter WebSockets (#2640)
Co-authored-by: Sebastián Ramírez <tiangolo@gmail.com>
2022-04-17 19:21:53 +02:00
github-actions
cb4da93643 📝 Update release notes 2022-04-17 16:18:35 +00:00
Sebastián Ramírez
3cbfae16cf ⬆️ Update ujson ranges for CVE-2021-45958 (#4804) 2022-04-17 16:17:59 +00:00
github-actions
0def8382b8 📝 Update release notes 2022-04-17 15:52:12 +00:00
Sebastián Ramírez
02fae6a38e ⬆️ Upgrade dependencies upper range for extras "all" (#4803) 2022-04-17 15:51:42 +00:00
Sebastián Ramírez
75af472029 📝 Update release notes 2022-04-17 16:55:37 +02:00
github-actions
e1135eddb5 📝 Update release notes 2022-04-17 14:47:55 +00:00
Alan Wright
acf8a91c25 ⬆ Upgrade Swagger UI - swagger-ui-dist@4 (#4347)
Co-authored-by: Sebastián Ramírez <tiangolo@gmail.com>
2022-04-17 14:47:14 +00:00
github-actions
c4f361c0c4 📝 Update release notes 2022-04-16 08:18:43 +00:00
Sebastián Ramírez
cc57bfcf60 ⬆️ Upgrade Codecov GitHub Action (#4801) 2022-04-16 08:18:08 +00:00
145 changed files with 562 additions and 949 deletions

View File

@@ -25,7 +25,7 @@ jobs:
id: cache
with:
path: ${{ env.pythonLocation }}
key: ${{ runner.os }}-python-${{ env.pythonLocation }}-${{ hashFiles('pyproject.toml') }}-test
key: ${{ runner.os }}-python-${{ env.pythonLocation }}-${{ hashFiles('pyproject.toml') }}-test-v02
- name: Install Flit
if: steps.cache.outputs.cache-hit != 'true'
run: pip install flit
@@ -38,4 +38,4 @@ jobs:
- name: Test
run: bash scripts/test.sh
- name: Upload coverage
uses: codecov/codecov-action@v1
uses: codecov/codecov-action@v2

View File

@@ -49,15 +49,15 @@ The key features are:
<a href="https://bit.ly/2QSouzH" target="_blank" title="Jina: build neural search-as-a-service for any kind of data in just minutes."><img src="https://fastapi.tiangolo.com/img/sponsors/jina.svg"></a>
<a href="https://cryptapi.io/" target="_blank" title="CryptAPI: Your easy to use, secure and privacy oriented payment gateway."><img src="https://fastapi.tiangolo.com/img/sponsors/cryptapi.svg"></a>
<a href="https://www.dropbase.io/careers" target="_blank" title="Dropbase - seamlessly collect, clean, and centralize data."><img src="https://fastapi.tiangolo.com/img/sponsors/dropbase.svg"></a>
<a href="https://striveworks.us/careers?utm_source=fastapi&utm_medium=sponsor_banner&utm_campaign=feb_march#openings" target="_blank" title="https://striveworks.us/careers"><img src="https://fastapi.tiangolo.com/img/sponsors/striveworks.png"></a>
<a href="https://classiq.link/n4s" target="_blank" title="Join the team building a new SaaS platform that will change the computing world"><img src="https://fastapi.tiangolo.com/img/sponsors/classiq.png"></a>
<a href="https://www.dropbase.io/careers" target="_blank" title="Dropbase - seamlessly collect, clean, and centralize data."><img src="https://fastapi.tiangolo.com/img/sponsors/dropbase.svg"></a>
<a href="https://www.deta.sh/?ref=fastapi" target="_blank" title="The launchpad for all your (team's) ideas"><img src="https://fastapi.tiangolo.com/img/sponsors/deta.svg"></a>
<a href="https://www.investsuite.com/jobs" target="_blank" title="Wealthtech jobs with FastAPI"><img src="https://fastapi.tiangolo.com/img/sponsors/investsuite.svg"></a>
<a href="https://www.vim.so/?utm_source=FastAPI" target="_blank" title="We help you master vim with interactive exercises"><img src="https://fastapi.tiangolo.com/img/sponsors/vimso.png"></a>
<a href="https://talkpython.fm/fastapi-sponsor" target="_blank" title="FastAPI video courses on demand from people you trust"><img src="https://fastapi.tiangolo.com/img/sponsors/talkpython.png"></a>
<a href="https://training.talkpython.fm/fastapi-courses" target="_blank" title="FastAPI video courses on demand from people you trust"><img src="https://fastapi.tiangolo.com/img/sponsors/talkpython.png"></a>
<a href="https://testdriven.io/courses/tdd-fastapi/" target="_blank" title="Learn to build high-quality web apps with best practices"><img src="https://fastapi.tiangolo.com/img/sponsors/testdriven.svg"></a>
<a href="https://github.com/deepset-ai/haystack/" target="_blank" title="Build powerful search from composable, open source building blocks"><img src="https://fastapi.tiangolo.com/img/sponsors/haystack-fastapi.svg"></a>
<a href="https://www.udemy.com/course/fastapi-rest/" target="_blank" title="Learn FastAPI by building a complete project. Extend your knowledge on advanced web development-AWS, Payments, Emails."><img src="https://fastapi.tiangolo.com/img/sponsors/ines-course.jpg"></a>
<a href="https://careers.budget-insight.com/" target="_blank" title="Budget Insight is hiring!"><img src="https://fastapi.tiangolo.com/img/sponsors/budget-insight.svg"></a>
<!-- /sponsors -->

View File

@@ -5,10 +5,13 @@ sponsors:
- login: jina-ai
avatarUrl: https://avatars.githubusercontent.com/u/60539444?v=4
url: https://github.com/jina-ai
- - login: InesIvanova
avatarUrl: https://avatars.githubusercontent.com/u/22920417?u=409882ec1df6dbd77455788bb383a8de223dbf6f&v=4
url: https://github.com/InesIvanova
- - login: chaserowbotham
- login: DropbaseHQ
avatarUrl: https://avatars.githubusercontent.com/u/85367855?v=4
url: https://github.com/DropbaseHQ
- - login: sushi2all
avatarUrl: https://avatars.githubusercontent.com/u/1043732?v=4
url: https://github.com/sushi2all
- login: chaserowbotham
avatarUrl: https://avatars.githubusercontent.com/u/97751084?v=4
url: https://github.com/chaserowbotham
- - login: mikeckennedy
@@ -26,7 +29,19 @@ sponsors:
- login: investsuite
avatarUrl: https://avatars.githubusercontent.com/u/73833632?v=4
url: https://github.com/investsuite
- - login: qaas
- login: VincentParedes
avatarUrl: https://avatars.githubusercontent.com/u/103889729?v=4
url: https://github.com/VincentParedes
- - login: plocher
avatarUrl: https://avatars.githubusercontent.com/u/1082871?v=4
url: https://github.com/plocher
- - login: InesIvanova
avatarUrl: https://avatars.githubusercontent.com/u/22920417?u=409882ec1df6dbd77455788bb383a8de223dbf6f&v=4
url: https://github.com/InesIvanova
- - login: SendCloud
avatarUrl: https://avatars.githubusercontent.com/u/7831959?v=4
url: https://github.com/SendCloud
- login: qaas
avatarUrl: https://avatars.githubusercontent.com/u/8503759?u=10a6b4391ad6ab4cf9487ce54e3fcb61322d1efc&v=4
url: https://github.com/qaas
- login: xoflare
@@ -44,9 +59,6 @@ sponsors:
- login: HiredScore
avatarUrl: https://avatars.githubusercontent.com/u/3908850?v=4
url: https://github.com/HiredScore
- login: spackle0
avatarUrl: https://avatars.githubusercontent.com/u/6148423?u=750e21b7366c0de69c305a8bcda1365d921ae477&v=4
url: https://github.com/spackle0
- login: wdwinslow
avatarUrl: https://avatars.githubusercontent.com/u/11562137?u=dc01daafb354135603a263729e3d26d939c0c452&v=4
url: https://github.com/wdwinslow
@@ -57,7 +69,7 @@ sponsors:
avatarUrl: https://avatars.githubusercontent.com/u/3329665?u=ec6a9adf8e7e8e306eed7d49687c398608d1604f&v=4
url: https://github.com/RodneyU215
- login: grillazz
avatarUrl: https://avatars.githubusercontent.com/u/3415861?u=16d7d0ffa5dfb99f8834f8f76d90e138ba09b94a&v=4
avatarUrl: https://avatars.githubusercontent.com/u/3415861?u=0b32b7073ae1ab8b7f6d2db0188c2e1e357ff451&v=4
url: https://github.com/grillazz
- login: tizz98
avatarUrl: https://avatars.githubusercontent.com/u/5739698?u=f095a3659e3a8e7c69ccd822696990b521ea25f9&v=4
@@ -65,11 +77,8 @@ sponsors:
- login: jmaralc
avatarUrl: https://avatars.githubusercontent.com/u/21101214?u=b15a9f07b7cbf6c9dcdbcb6550bbd2c52f55aa50&v=4
url: https://github.com/jmaralc
- login: Filimoa
avatarUrl: https://avatars.githubusercontent.com/u/21352040?u=75e02d102d2ee3e3d793e555fa5c63045913ccb0&v=4
url: https://github.com/Filimoa
- login: marutoraman
avatarUrl: https://avatars.githubusercontent.com/u/33813153?v=4
avatarUrl: https://avatars.githubusercontent.com/u/33813153?u=2d0522bceba0b8b69adf1f2db866503bd96f944e&v=4
url: https://github.com/marutoraman
- login: mainframeindustries
avatarUrl: https://avatars.githubusercontent.com/u/55092103?v=4
@@ -77,10 +86,10 @@ sponsors:
- login: A-Edge
avatarUrl: https://avatars.githubusercontent.com/u/59514131?v=4
url: https://github.com/A-Edge
- - login: hcristea
avatarUrl: https://avatars.githubusercontent.com/u/7814406?u=61d7a4fcf846983a4606788eac25e1c6c1209ba8&v=4
url: https://github.com/hcristea
- - login: samuelcolvin
- - login: Kludex
avatarUrl: https://avatars.githubusercontent.com/u/7353520?u=62adc405ef418f4b6c8caa93d3eb8ab107bc4927&v=4
url: https://github.com/Kludex
- login: samuelcolvin
avatarUrl: https://avatars.githubusercontent.com/u/4039449?u=807390ba9cfe23906c3bf8a0d56aaca3cf2bfa0d&v=4
url: https://github.com/samuelcolvin
- login: jokull
@@ -110,18 +119,12 @@ sponsors:
- login: jqueguiner
avatarUrl: https://avatars.githubusercontent.com/u/690878?u=e4835b2a985a0f2d52018e4926cb5a58c26a62e8&v=4
url: https://github.com/jqueguiner
- login: Mazyod
avatarUrl: https://avatars.githubusercontent.com/u/860511?v=4
url: https://github.com/Mazyod
- login: ltieman
avatarUrl: https://avatars.githubusercontent.com/u/1084689?u=e69b17de17cb3ca141a17daa7ccbe173ceb1eb17&v=4
url: https://github.com/ltieman
- login: westonsteimel
avatarUrl: https://avatars.githubusercontent.com/u/1593939?u=0f2c0e3647f916fe295d62fa70da7a4c177115e3&v=4
url: https://github.com/westonsteimel
- login: timdrijvers
avatarUrl: https://avatars.githubusercontent.com/u/1694939?v=4
url: https://github.com/timdrijvers
- login: corleyma
avatarUrl: https://avatars.githubusercontent.com/u/2080732?u=aed2ff652294a87d666b1c3f6dbe98104db76d26&v=4
url: https://github.com/corleyma
@@ -185,15 +188,9 @@ sponsors:
- login: Rehket
avatarUrl: https://avatars.githubusercontent.com/u/7015688?u=3afb0ba200feebbc7f958950e92db34df2a3c172&v=4
url: https://github.com/Rehket
- login: christippett
avatarUrl: https://avatars.githubusercontent.com/u/7218120?u=f21f93b9c14edefef75645bf4d64c819b7d4afd7&v=4
url: https://github.com/christippett
- login: hiancdtrsnm
avatarUrl: https://avatars.githubusercontent.com/u/7343177?v=4
url: https://github.com/hiancdtrsnm
- login: Kludex
avatarUrl: https://avatars.githubusercontent.com/u/7353520?u=62adc405ef418f4b6c8caa93d3eb8ab107bc4927&v=4
url: https://github.com/Kludex
- login: Shackelford-Arden
avatarUrl: https://avatars.githubusercontent.com/u/7362263?v=4
url: https://github.com/Shackelford-Arden
@@ -215,9 +212,6 @@ sponsors:
- login: robintully
avatarUrl: https://avatars.githubusercontent.com/u/17059673?u=862b9bb01513f5acd30df97433cb97a24dbfb772&v=4
url: https://github.com/robintully
- login: tobiasfeil
avatarUrl: https://avatars.githubusercontent.com/u/17533713?u=bc6b0bec46f342d13c41695db90685d1c58d534e&v=4
url: https://github.com/tobiasfeil
- login: wedwardbeck
avatarUrl: https://avatars.githubusercontent.com/u/19333237?u=1de4ae2bf8d59eb4c013f21d863cbe0f2010575f&v=4
url: https://github.com/wedwardbeck
@@ -230,21 +224,21 @@ sponsors:
- login: RedCarpetUp
avatarUrl: https://avatars.githubusercontent.com/u/20360440?v=4
url: https://github.com/RedCarpetUp
- login: Filimoa
avatarUrl: https://avatars.githubusercontent.com/u/21352040?u=75e02d102d2ee3e3d793e555fa5c63045913ccb0&v=4
url: https://github.com/Filimoa
- login: shuheng-liu
avatarUrl: https://avatars.githubusercontent.com/u/22414322?u=813c45f30786c6b511b21a661def025d8f7b609e&v=4
url: https://github.com/shuheng-liu
- login: comoelcometa
avatarUrl: https://avatars.githubusercontent.com/u/25950317?u=c6751efa038561b9bc5fa56d1033d5174e10cd65&v=4
url: https://github.com/comoelcometa
- login: cometa-haley
avatarUrl: https://avatars.githubusercontent.com/u/25950317?u=cec1a3e0643b785288ae8260cc295a85ab344995&v=4
url: https://github.com/cometa-haley
- login: LarryGF
avatarUrl: https://avatars.githubusercontent.com/u/26148349?u=431bb34d36d41c172466252242175281ae132152&v=4
url: https://github.com/LarryGF
- login: veprimk
avatarUrl: https://avatars.githubusercontent.com/u/29689749?u=f8cb5a15a286e522e5b189bc572d5a1a90217fb2&v=4
url: https://github.com/veprimk
- login: orihomie
avatarUrl: https://avatars.githubusercontent.com/u/29889683?u=6bc2135a52fcb3a49e69e7d50190796618185fda&v=4
url: https://github.com/orihomie
- login: meysam81
avatarUrl: https://avatars.githubusercontent.com/u/30233243?u=64dc9fc62d039892c6fb44d804251cad5537132b&v=4
url: https://github.com/meysam81
@@ -266,6 +260,9 @@ sponsors:
- login: ybressler
avatarUrl: https://avatars.githubusercontent.com/u/40807730?u=6621dc9ab53b697912ab2a32211bb29ae90a9112&v=4
url: https://github.com/ybressler
- login: iamkarshe
avatarUrl: https://avatars.githubusercontent.com/u/43641892?u=d08c901b359c931784501740610d416558ff3e24&v=4
url: https://github.com/iamkarshe
- login: dbanty
avatarUrl: https://avatars.githubusercontent.com/u/43723790?u=9bcce836bbce55835291c5b2ac93a4e311f4b3c3&v=4
url: https://github.com/dbanty
@@ -278,6 +275,9 @@ sponsors:
- login: daisuke8000
avatarUrl: https://avatars.githubusercontent.com/u/55035595?u=5025e379cd3655ae1a96039efc85223a873d2e38&v=4
url: https://github.com/daisuke8000
- login: yakkonaut
avatarUrl: https://avatars.githubusercontent.com/u/60633704?u=90a71fd631aa998ba4a96480788f017c9904e07b&v=4
url: https://github.com/yakkonaut
- login: primer-io
avatarUrl: https://avatars.githubusercontent.com/u/62146168?v=4
url: https://github.com/primer-io
@@ -293,9 +293,6 @@ sponsors:
- login: anthonycepeda
avatarUrl: https://avatars.githubusercontent.com/u/72019805?u=892f700c79f9732211bd5221bf16eec32356a732&v=4
url: https://github.com/anthonycepeda
- login: abdurrahim84
avatarUrl: https://avatars.githubusercontent.com/u/79488613?v=4
url: https://github.com/abdurrahim84
- login: NinaHwang
avatarUrl: https://avatars.githubusercontent.com/u/79563565?u=1741703bd6c8f491503354b363a86e879b4c1cab&v=4
url: https://github.com/NinaHwang
@@ -305,9 +302,6 @@ sponsors:
- login: pyt3h
avatarUrl: https://avatars.githubusercontent.com/u/99658549?v=4
url: https://github.com/pyt3h
- - login: '837477'
avatarUrl: https://avatars.githubusercontent.com/u/37999795?u=543b0bd0e8f283db0fc50754e5d13f6afba8cbea&v=4
url: https://github.com/837477
- - login: linux-china
avatarUrl: https://avatars.githubusercontent.com/u/46711?v=4
url: https://github.com/linux-china
@@ -353,9 +347,9 @@ sponsors:
- login: hardbyte
avatarUrl: https://avatars.githubusercontent.com/u/855189?u=aa29e92f34708814d6b67fcd47ca4cf2ce1c04ed&v=4
url: https://github.com/hardbyte
- login: clstaudt
avatarUrl: https://avatars.githubusercontent.com/u/875194?u=46a92f9f837d0ba150ae0f1d91091dd2f4ebb6cc&v=4
url: https://github.com/clstaudt
- login: janfilips
avatarUrl: https://avatars.githubusercontent.com/u/870699?u=6034d81731ecb41ae5c717e56a901ed46fc039a8&v=4
url: https://github.com/janfilips
- login: scari
avatarUrl: https://avatars.githubusercontent.com/u/964251?v=4
url: https://github.com/scari
@@ -398,12 +392,12 @@ sponsors:
- login: holec
avatarUrl: https://avatars.githubusercontent.com/u/6438041?u=f5af71ec85b3a9d7b8139cb5af0512b02fa9ab1e&v=4
url: https://github.com/holec
- login: moonape1226
avatarUrl: https://avatars.githubusercontent.com/u/8532038?u=d9f8b855a429fff9397c3833c2ff83849ebf989d&v=4
url: https://github.com/moonape1226
- login: davanstrien
avatarUrl: https://avatars.githubusercontent.com/u/8995957?u=fb2aad2b52bb4e7b56db6d7c8ecc9ae1eac1b984&v=4
url: https://github.com/davanstrien
- login: and-semakin
avatarUrl: https://avatars.githubusercontent.com/u/9129071?u=ea77ddf7de4bc375d546bf2825ed420eaddb7666&v=4
url: https://github.com/and-semakin
- login: yenchenLiu
avatarUrl: https://avatars.githubusercontent.com/u/9199638?u=8cdf5ae507448430d90f6f3518d1665a23afe99b&v=4
url: https://github.com/yenchenLiu
@@ -419,6 +413,9 @@ sponsors:
- login: hard-coders
avatarUrl: https://avatars.githubusercontent.com/u/9651103?u=95db33927bbff1ed1c07efddeb97ac2ff33068ed&v=4
url: https://github.com/hard-coders
- login: satwikkansal
avatarUrl: https://avatars.githubusercontent.com/u/10217535?u=b12d6ef74ea297de9e46da6933b1a5b7ba9e6a61&v=4
url: https://github.com/satwikkansal
- login: pheanex
avatarUrl: https://avatars.githubusercontent.com/u/10408624?u=5b6bab6ee174aa6e991333e06eb29f628741013d&v=4
url: https://github.com/pheanex
@@ -458,18 +455,15 @@ sponsors:
- login: d-e-h-i-o
avatarUrl: https://avatars.githubusercontent.com/u/36816716?v=4
url: https://github.com/d-e-h-i-o
- login: askurihin
avatarUrl: https://avatars.githubusercontent.com/u/37978981?v=4
url: https://github.com/askurihin
- login: ilias-ant
avatarUrl: https://avatars.githubusercontent.com/u/42189572?u=a2d6121bac4d125d92ec207460fa3f1842d37e66&v=4
url: https://github.com/ilias-ant
- login: arrrrrmin
avatarUrl: https://avatars.githubusercontent.com/u/43553423?u=fee5739394fea074cb0b66929d070114a5067aae&v=4
url: https://github.com/arrrrrmin
- login: igorezersky
avatarUrl: https://avatars.githubusercontent.com/u/46680020?u=a20a595c881dbe5658c906fecc7eff125efb4fd4&v=4
url: https://github.com/igorezersky
- login: Nephilim-Jack
avatarUrl: https://avatars.githubusercontent.com/u/48372168?u=6f2bb405238d7efc467536fe01f58df6779c58a9&v=4
url: https://github.com/Nephilim-Jack
- login: akanz1
avatarUrl: https://avatars.githubusercontent.com/u/51492342?u=2280f57134118714645e16b535c1a37adf6b369b&v=4
url: https://github.com/akanz1
@@ -488,20 +482,14 @@ sponsors:
- login: alessio-proietti
avatarUrl: https://avatars.githubusercontent.com/u/67370599?u=8ac73db1e18e946a7681f173abdb640516f88515&v=4
url: https://github.com/alessio-proietti
- - login: spyker77
avatarUrl: https://avatars.githubusercontent.com/u/4953435?u=03c724c6f8fbab5cd6575b810c0c91c652fa4f79&v=4
url: https://github.com/spyker77
- login: backbord
- - login: backbord
avatarUrl: https://avatars.githubusercontent.com/u/6814946?v=4
url: https://github.com/backbord
- login: sadikkuzu
avatarUrl: https://avatars.githubusercontent.com/u/23168063?u=765ed469c44c004560079210ccdad5b29938eaa9&v=4
url: https://github.com/sadikkuzu
- login: MoronVV
avatarUrl: https://avatars.githubusercontent.com/u/24293616?v=4
url: https://github.com/MoronVV
- login: gabrielmbmb
avatarUrl: https://avatars.githubusercontent.com/u/29572918?u=92084ed7242160dee4d20aece923a10c59758ee5&v=4
avatarUrl: https://avatars.githubusercontent.com/u/29572918?u=6d1e00b5d558e96718312ff910a2318f47cc3145&v=4
url: https://github.com/gabrielmbmb
- login: danburonline
avatarUrl: https://avatars.githubusercontent.com/u/34251194?u=2cad4388c1544e539ecb732d656e42fb07b4ff2d&v=4

View File

@@ -1,12 +1,12 @@
maintainers:
- login: tiangolo
answers: 1240
prs: 291
answers: 1243
prs: 300
avatarUrl: https://avatars.githubusercontent.com/u/1326112?u=5cad72c846b7aba2e960546af490edc7375dafc4&v=4
url: https://github.com/tiangolo
experts:
- login: Kludex
count: 330
count: 335
avatarUrl: https://avatars.githubusercontent.com/u/7353520?u=62adc405ef418f4b6c8caa93d3eb8ab107bc4927&v=4
url: https://github.com/Kludex
- login: dmontagu
@@ -35,7 +35,7 @@ experts:
url: https://github.com/raphaelauv
- login: ArcLightSlavik
count: 71
avatarUrl: https://avatars.githubusercontent.com/u/31127044?u=81a84af39c89b898b0fbc5a04e8834f60f23e55a&v=4
avatarUrl: https://avatars.githubusercontent.com/u/31127044?u=b0f2c37142f4b762e41ad65dc49581813422bd71&v=4
url: https://github.com/ArcLightSlavik
- login: falkben
count: 58
@@ -57,10 +57,18 @@ experts:
count: 39
avatarUrl: https://avatars.githubusercontent.com/u/11836741?u=8bd5ef7e62fe6a82055e33c4c0e0a7879ff8cfb6&v=4
url: https://github.com/includeamin
- login: jgould22
count: 38
avatarUrl: https://avatars.githubusercontent.com/u/4335847?u=ed77f67e0bb069084639b24d812dbb2a2b1dc554&v=4
url: https://github.com/jgould22
- login: STeveShary
count: 37
avatarUrl: https://avatars.githubusercontent.com/u/5167622?u=de8f597c81d6336fcebc37b32dfd61a3f877160c&v=4
url: https://github.com/STeveShary
- login: adriangb
count: 36
avatarUrl: https://avatars.githubusercontent.com/u/1755071?u=81f0262df34e1460ca546fbd0c211169c2478532&v=4
url: https://github.com/adriangb
- login: prostomarkeloff
count: 33
avatarUrl: https://avatars.githubusercontent.com/u/28061158?u=72309cc1f2e04e40fa38b29969cb4e9d3f722e7b&v=4
@@ -69,10 +77,6 @@ experts:
count: 31
avatarUrl: https://avatars.githubusercontent.com/u/1144727?u=85c025e3fcc7bd79a5665c63ee87cdf8aae13374&v=4
url: https://github.com/frankie567
- login: adriangb
count: 31
avatarUrl: https://avatars.githubusercontent.com/u/1755071?u=81f0262df34e1460ca546fbd0c211169c2478532&v=4
url: https://github.com/adriangb
- login: krishnardt
count: 31
avatarUrl: https://avatars.githubusercontent.com/u/31960541?u=47f4829c77f4962ab437ffb7995951e41eeebe9b&v=4
@@ -82,7 +86,7 @@ experts:
avatarUrl: https://avatars.githubusercontent.com/u/365303?u=07ca03c5ee811eb0920e633cc3c3db73dbec1aa5&v=4
url: https://github.com/wshayes
- login: chbndrhnns
count: 26
count: 28
avatarUrl: https://avatars.githubusercontent.com/u/7534547?v=4
url: https://github.com/chbndrhnns
- login: panla
@@ -101,10 +105,6 @@ experts:
count: 24
avatarUrl: https://avatars.githubusercontent.com/u/9435877?u=719327b7d2c4c62212456d771bfa7c6b8dbb9eac&v=4
url: https://github.com/SirTelemak
- login: jgould22
count: 23
avatarUrl: https://avatars.githubusercontent.com/u/4335847?u=ed77f67e0bb069084639b24d812dbb2a2b1dc554&v=4
url: https://github.com/jgould22
- login: acnebs
count: 22
avatarUrl: https://avatars.githubusercontent.com/u/9054108?u=c27e50269f1ef8ea950cc6f0268c8ec5cebbe9c9&v=4
@@ -141,6 +141,10 @@ experts:
count: 17
avatarUrl: https://avatars.githubusercontent.com/u/1765494?u=5b1ab7c582db4b4016fa31affe977d10af108ad4&v=4
url: https://github.com/harunyasar
- login: rafsaf
count: 17
avatarUrl: https://avatars.githubusercontent.com/u/51059348?u=be9f06b8ced2d2b677297decc781fa8ce4f7ddbd&v=4
url: https://github.com/rafsaf
- login: waynerv
count: 16
avatarUrl: https://avatars.githubusercontent.com/u/39515546?u=ec35139777597cdbbbddda29bf8b9d4396b429a9&v=4
@@ -149,14 +153,14 @@ experts:
count: 16
avatarUrl: https://avatars.githubusercontent.com/u/41964673?u=9f2174f9d61c15c6e3a4c9e3aeee66f711ce311f&v=4
url: https://github.com/dstlny
- login: rafsaf
count: 15
avatarUrl: https://avatars.githubusercontent.com/u/51059348?u=be9f06b8ced2d2b677297decc781fa8ce4f7ddbd&v=4
url: https://github.com/rafsaf
- login: haizaar
count: 13
avatarUrl: https://avatars.githubusercontent.com/u/58201?u=4f1f9843d69433ca0d380d95146cfe119e5fdac4&v=4
url: https://github.com/haizaar
- login: valentin994
count: 13
avatarUrl: https://avatars.githubusercontent.com/u/42819267?u=fdeeaa9242a59b243f8603496b00994f6951d5a2&v=4
url: https://github.com/valentin994
- login: hellocoldworld
count: 12
avatarUrl: https://avatars.githubusercontent.com/u/47581948?v=4
@@ -165,6 +169,14 @@ experts:
count: 12
avatarUrl: https://avatars.githubusercontent.com/u/17401854?u=474680c02b94cba810cb9032fb7eb787d9cc9d22&v=4
url: https://github.com/David-Lor
- login: yinziyan1206
count: 12
avatarUrl: https://avatars.githubusercontent.com/u/37829370?v=4
url: https://github.com/yinziyan1206
- login: jonatasoli
count: 12
avatarUrl: https://avatars.githubusercontent.com/u/26334101?u=071c062d2861d3dd127f6b4a5258cd8ef55d4c50&v=4
url: https://github.com/jonatasoli
- login: lowercase00
count: 11
avatarUrl: https://avatars.githubusercontent.com/u/21188280?v=4
@@ -177,55 +189,35 @@ experts:
count: 11
avatarUrl: https://avatars.githubusercontent.com/u/8134632?v=4
url: https://github.com/juntatalor
- login: valentin994
- login: n8sty
count: 11
avatarUrl: https://avatars.githubusercontent.com/u/42819267?u=fdeeaa9242a59b243f8603496b00994f6951d5a2&v=4
url: https://github.com/valentin994
avatarUrl: https://avatars.githubusercontent.com/u/2964996?v=4
url: https://github.com/n8sty
- login: aalifadv
count: 11
avatarUrl: https://avatars.githubusercontent.com/u/78442260?v=4
url: https://github.com/aalifadv
- login: stefanondisponibile
count: 10
avatarUrl: https://avatars.githubusercontent.com/u/20441825?u=ee1e59446b98f8ec2363caeda4c17164d0d9cc7d&v=4
url: https://github.com/stefanondisponibile
- login: oligond
count: 10
avatarUrl: https://avatars.githubusercontent.com/u/2858306?u=1bb1182a5944e93624b7fb26585f22c8f7a9d76e&v=4
url: https://github.com/oligond
- login: n8sty
count: 10
avatarUrl: https://avatars.githubusercontent.com/u/2964996?v=4
url: https://github.com/n8sty
last_month_active:
- login: yinziyan1206
count: 5
avatarUrl: https://avatars.githubusercontent.com/u/37829370?v=4
url: https://github.com/yinziyan1206
- login: Kludex
count: 5
avatarUrl: https://avatars.githubusercontent.com/u/7353520?u=62adc405ef418f4b6c8caa93d3eb8ab107bc4927&v=4
url: https://github.com/Kludex
- login: jd-0001
count: 4
avatarUrl: https://avatars.githubusercontent.com/u/47495003?u=322eedc0931b62827cf5f239654f77bfaff76b46&v=4
url: https://github.com/jd-0001
- login: harunyasar
count: 3
avatarUrl: https://avatars.githubusercontent.com/u/1765494?u=5b1ab7c582db4b4016fa31affe977d10af108ad4&v=4
url: https://github.com/harunyasar
- login: wmcgee3
count: 3
avatarUrl: https://avatars.githubusercontent.com/u/61711986?u=c51ebfaf8a995019fda8288690f4a009ecf070f0&v=4
url: https://github.com/wmcgee3
- login: tasercake
count: 3
avatarUrl: https://avatars.githubusercontent.com/u/13855549?v=4
url: https://github.com/tasercake
- login: jgould22
count: 3
count: 15
avatarUrl: https://avatars.githubusercontent.com/u/4335847?u=ed77f67e0bb069084639b24d812dbb2a2b1dc554&v=4
url: https://github.com/jgould22
- login: accelleon
count: 5
avatarUrl: https://avatars.githubusercontent.com/u/5001614?v=4
url: https://github.com/accelleon
- login: jonatasoli
count: 4
avatarUrl: https://avatars.githubusercontent.com/u/26334101?u=071c062d2861d3dd127f6b4a5258cd8ef55d4c50&v=4
url: https://github.com/jonatasoli
- login: Kludex
count: 4
avatarUrl: https://avatars.githubusercontent.com/u/7353520?u=62adc405ef418f4b6c8caa93d3eb8ab107bc4927&v=4
url: https://github.com/Kludex
- login: yinziyan1206
count: 3
avatarUrl: https://avatars.githubusercontent.com/u/37829370?v=4
url: https://github.com/yinziyan1206
top_contributors:
- login: waynerv
count: 25
@@ -259,14 +251,14 @@ top_contributors:
count: 8
avatarUrl: https://avatars.githubusercontent.com/u/22691749?u=4795b880e13ca33a73e52fc0ef7dc9c60c8fce47&v=4
url: https://github.com/Serrones
- login: Kludex
count: 8
avatarUrl: https://avatars.githubusercontent.com/u/7353520?u=62adc405ef418f4b6c8caa93d3eb8ab107bc4927&v=4
url: https://github.com/Kludex
- login: RunningIkkyu
count: 7
avatarUrl: https://avatars.githubusercontent.com/u/31848542?u=706e1ee3f248245f2d68b976d149d06fd5a2010d&v=4
url: https://github.com/RunningIkkyu
- login: Kludex
count: 7
avatarUrl: https://avatars.githubusercontent.com/u/7353520?u=62adc405ef418f4b6c8caa93d3eb8ab107bc4927&v=4
url: https://github.com/Kludex
- login: hard-coders
count: 7
avatarUrl: https://avatars.githubusercontent.com/u/9651103?u=95db33927bbff1ed1c07efddeb97ac2ff33068ed&v=4
@@ -328,30 +320,34 @@ top_reviewers:
count: 41
avatarUrl: https://avatars.githubusercontent.com/u/24587499?u=e772190a051ab0eaa9c8542fcff1892471638f2b&v=4
url: https://github.com/cikay
- login: BilalAlpaslan
count: 40
avatarUrl: https://avatars.githubusercontent.com/u/47563997?u=63ed66e304fe8d765762c70587d61d9196e5c82d&v=4
url: https://github.com/BilalAlpaslan
- login: AdrianDeAnda
count: 33
avatarUrl: https://avatars.githubusercontent.com/u/1024932?u=bb7f8a0d6c9de4e9d0320a9f271210206e202250&v=4
url: https://github.com/AdrianDeAnda
- login: ArcLightSlavik
count: 31
avatarUrl: https://avatars.githubusercontent.com/u/31127044?u=81a84af39c89b898b0fbc5a04e8834f60f23e55a&v=4
avatarUrl: https://avatars.githubusercontent.com/u/31127044?u=b0f2c37142f4b762e41ad65dc49581813422bd71&v=4
url: https://github.com/ArcLightSlavik
- login: BilalAlpaslan
count: 28
avatarUrl: https://avatars.githubusercontent.com/u/47563997?u=63ed66e304fe8d765762c70587d61d9196e5c82d&v=4
url: https://github.com/BilalAlpaslan
- login: cassiobotaro
count: 25
avatarUrl: https://avatars.githubusercontent.com/u/3127847?u=b0a652331da17efeb85cd6e3a4969182e5004804&v=4
url: https://github.com/cassiobotaro
- login: dmontagu
count: 23
avatarUrl: https://avatars.githubusercontent.com/u/35119617?u=58ed2a45798a4339700e2f62b2e12e6e54bf0396&v=4
url: https://github.com/dmontagu
- login: cassiobotaro
count: 23
avatarUrl: https://avatars.githubusercontent.com/u/3127847?u=b0a652331da17efeb85cd6e3a4969182e5004804&v=4
url: https://github.com/cassiobotaro
- login: komtaki
count: 21
avatarUrl: https://avatars.githubusercontent.com/u/39375566?u=260ad6b1a4b34c07dbfa728da5e586f16f6d1824&v=4
url: https://github.com/komtaki
- login: yezz123
count: 19
avatarUrl: https://avatars.githubusercontent.com/u/52716203?u=636b4f79645176df4527dd45c12d5dbb5a4193cf&v=4
url: https://github.com/yezz123
- login: hard-coders
count: 19
avatarUrl: https://avatars.githubusercontent.com/u/9651103?u=95db33927bbff1ed1c07efddeb97ac2ff33068ed&v=4
@@ -364,10 +360,6 @@ top_reviewers:
count: 17
avatarUrl: https://avatars.githubusercontent.com/u/67154681?u=5d634834cc514028ea3f9115f7030b99a1f4d5a4&v=4
url: https://github.com/zy7y
- login: yezz123
count: 16
avatarUrl: https://avatars.githubusercontent.com/u/52716203?u=636b4f79645176df4527dd45c12d5dbb5a4193cf&v=4
url: https://github.com/yezz123
- login: yanever
count: 16
avatarUrl: https://avatars.githubusercontent.com/u/21978760?v=4
@@ -452,6 +444,10 @@ top_reviewers:
count: 8
avatarUrl: https://avatars.githubusercontent.com/u/43503750?u=b3e4d9a14d9a65d429ce62c566aef73178b7111d&v=4
url: https://github.com/ComicShrimp
- login: NinaHwang
count: 8
avatarUrl: https://avatars.githubusercontent.com/u/79563565?u=1741703bd6c8f491503354b363a86e879b4c1cab&v=4
url: https://github.com/NinaHwang
- login: dimaqq
count: 8
avatarUrl: https://avatars.githubusercontent.com/u/662249?v=4
@@ -476,14 +472,14 @@ top_reviewers:
count: 7
avatarUrl: https://avatars.githubusercontent.com/u/1405026?v=4
url: https://github.com/Mause
- login: AlexandreBiguet
count: 7
avatarUrl: https://avatars.githubusercontent.com/u/1483079?u=ff926455cd4cab03c6c49441aa5dc2b21df3e266&v=4
url: https://github.com/AlexandreBiguet
- login: krocdort
count: 7
avatarUrl: https://avatars.githubusercontent.com/u/34248814?v=4
url: https://github.com/krocdort
- login: NinaHwang
count: 7
avatarUrl: https://avatars.githubusercontent.com/u/79563565?u=1741703bd6c8f491503354b363a86e879b4c1cab&v=4
url: https://github.com/NinaHwang
- login: jovicon
count: 6
avatarUrl: https://avatars.githubusercontent.com/u/21287303?u=b049eac3e51a4c0473c2efe66b4d28a7d8f2b572&v=4
@@ -496,7 +492,3 @@ top_reviewers:
count: 6
avatarUrl: https://avatars.githubusercontent.com/u/32584628?u=88c2cb42a99e0f50cdeae3606992568184783ee5&v=4
url: https://github.com/peidrao
- login: diogoduartec
count: 5
avatarUrl: https://avatars.githubusercontent.com/u/31852339?u=b50fc11c531e9b77922e19edfc9e7233d4d7b92e&v=4
url: https://github.com/diogoduartec

View File

@@ -5,15 +5,12 @@ gold:
- url: https://cryptapi.io/
title: "CryptAPI: Your easy to use, secure and privacy oriented payment gateway."
img: https://fastapi.tiangolo.com/img/sponsors/cryptapi.svg
- url: https://www.dropbase.io/careers
title: Dropbase - seamlessly collect, clean, and centralize data.
img: https://fastapi.tiangolo.com/img/sponsors/dropbase.svg
- url: https://striveworks.us/careers?utm_source=fastapi&utm_medium=sponsor_banner&utm_campaign=feb_march#openings
title: https://striveworks.us/careers
img: https://fastapi.tiangolo.com/img/sponsors/striveworks.png
- url: https://classiq.link/n4s
title: Join the team building a new SaaS platform that will change the computing world
img: https://fastapi.tiangolo.com/img/sponsors/classiq.png
- url: https://www.dropbase.io/careers
title: Dropbase - seamlessly collect, clean, and centralize data.
img: https://fastapi.tiangolo.com/img/sponsors/dropbase.svg
silver:
- url: https://www.deta.sh/?ref=fastapi
title: The launchpad for all your (team's) ideas
@@ -21,10 +18,7 @@ silver:
- url: https://www.investsuite.com/jobs
title: Wealthtech jobs with FastAPI
img: https://fastapi.tiangolo.com/img/sponsors/investsuite.svg
- url: https://www.vim.so/?utm_source=FastAPI
title: We help you master vim with interactive exercises
img: https://fastapi.tiangolo.com/img/sponsors/vimso.png
- url: https://talkpython.fm/fastapi-sponsor
- url: https://training.talkpython.fm/fastapi-courses
title: FastAPI video courses on demand from people you trust
img: https://fastapi.tiangolo.com/img/sponsors/talkpython.png
- url: https://testdriven.io/courses/tdd-fastapi/
@@ -33,7 +27,16 @@ silver:
- url: https://github.com/deepset-ai/haystack/
title: Build powerful search from composable, open source building blocks
img: https://fastapi.tiangolo.com/img/sponsors/haystack-fastapi.svg
- url: https://www.udemy.com/course/fastapi-rest/
title: Learn FastAPI by building a complete project. Extend your knowledge on advanced web development-AWS, Payments, Emails.
img: https://fastapi.tiangolo.com/img/sponsors/ines-course.jpg
- url: https://careers.budget-insight.com/
title: Budget Insight is hiring!
img: https://fastapi.tiangolo.com/img/sponsors/budget-insight.svg
bronze:
- url: https://calmcode.io
title: Code. Simply. Clearly. Calmly.
img: https://fastapi.tiangolo.com/img/sponsors/calmcode.jpg
- url: https://www.exoflare.com/open-source/?utm_source=FastAPI&utm_campaign=open_source
title: Biosecurity risk assessments made easy.
img: https://fastapi.tiangolo.com/img/sponsors/exoflare.png
- url: https://striveworks.us/careers?utm_source=fastapi&utm_medium=sponsor_banner&utm_campaign=feb_march#openings
title: https://striveworks.us/careers
img: https://fastapi.tiangolo.com/img/sponsors/striveworks.png

View File

@@ -2,10 +2,11 @@ logins:
- jina-ai
- deta
- investsuite
- vimsoHQ
- mikeckennedy
- koaning
- deepset-ai
- cryptapi
- DropbaseHQ
- Striveworks
- xoflare
- InesIvanova
- DropbaseHQ
- VincentParedes

View File

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 36 KiB

View File

Binary file not shown.

After

Width:  |  Height:  |  Size: 10 KiB

View File

Binary file not shown.

After

Width:  |  Height:  |  Size: 16 KiB

View File

Binary file not shown.

After

Width:  |  Height:  |  Size: 12 KiB

View File

@@ -3,6 +3,40 @@
## Latest Changes
## 0.76.0
### Upgrades
* ⬆ Upgrade Starlette from 0.17.1 to 0.18.0. PR [#4483](https://github.com/tiangolo/fastapi/pull/4483) by [@Kludex](https://github.com/Kludex).
### Internal
* 👥 Update FastAPI People. PR [#4847](https://github.com/tiangolo/fastapi/pull/4847) by [@github-actions[bot]](https://github.com/apps/github-actions).
* 🔧 Add Budget Insight sponsor. PR [#4824](https://github.com/tiangolo/fastapi/pull/4824) by [@tiangolo](https://github.com/tiangolo).
* 🍱 Update sponsor, ExoFlare badge. PR [#4822](https://github.com/tiangolo/fastapi/pull/4822) by [@tiangolo](https://github.com/tiangolo).
* 🔧 Update sponsors, enable Dropbase again, update TalkPython link. PR [#4821](https://github.com/tiangolo/fastapi/pull/4821) by [@tiangolo](https://github.com/tiangolo).
## 0.75.2
This release includes upgrades to third-party packages that handle security issues. Although there's a chance these issues don't affect you in particular, please upgrade as soon as possible.
### Fixes
* ✅ Fix new/recent tests with new fixed `ValidationError` JSON Schema. PR [#4806](https://github.com/tiangolo/fastapi/pull/4806) by [@tiangolo](https://github.com/tiangolo).
* 🐛 Fix JSON Schema for `ValidationError` at field `loc`. PR [#3810](https://github.com/tiangolo/fastapi/pull/3810) by [@dconathan](https://github.com/dconathan).
* 🐛 Fix support for prefix on APIRouter WebSockets. PR [#2640](https://github.com/tiangolo/fastapi/pull/2640) by [@Kludex](https://github.com/Kludex).
### Upgrades
* ⬆️ Update ujson ranges for CVE-2021-45958. PR [#4804](https://github.com/tiangolo/fastapi/pull/4804) by [@tiangolo](https://github.com/tiangolo).
* ⬆️ Upgrade dependencies upper range for extras "all". PR [#4803](https://github.com/tiangolo/fastapi/pull/4803) by [@tiangolo](https://github.com/tiangolo).
* ⬆ Upgrade Swagger UI - swagger-ui-dist@4. This handles a security issue in Swagger UI itself where it could be possible to inject HTML into Swagger UI. Please upgrade as soon as you can, in particular if you expose your Swagger UI (`/docs`) publicly to non-expert users. PR [#4347](https://github.com/tiangolo/fastapi/pull/4347) by [@RAlanWright](https://github.com/RAlanWright).
### Internal
* 🔧 Update sponsors, add: ExoFlare, Ines Course; remove: Dropbase, Vim.so, Calmcode; update: Striveworks, TalkPython and TestDriven.io. PR [#4805](https://github.com/tiangolo/fastapi/pull/4805) by [@tiangolo](https://github.com/tiangolo).
* ⬆️ Upgrade Codecov GitHub Action. PR [#4801](https://github.com/tiangolo/fastapi/pull/4801) by [@tiangolo](https://github.com/tiangolo).
## 0.75.1
### Translations

View File

@@ -22,16 +22,10 @@
</div>
</div>
<div id="announce-right" style="position: relative;">
<!-- <div class="item">
<a title="The launchpad for all your (team's) ideas" style="display: block; position: relative;" href="https://www.deta.sh/?ref=fastapi" target="_blank">
<span class="sponsor-badge">sponsor</span>
<img class="sponsor-image" src="/img/sponsors/deta-banner.svg" />
</a>
</div> -->
<div class="item">
<a title="Get three courses at 10% off their current prices! Plus, we'll be donating 10% of all profits from sales of this bundle to the FastAPI team." style="display: block; position: relative;" href="https://testdriven.io/talkpython/" target="_blank">
<span class="sponsor-badge">sponsor</span>
<img class="sponsor-image" src="/img/sponsors/fastapi-course-bundle-banner.svg" />
<img class="sponsor-image" src="/img/sponsors/fastapi-course-bundle-banner.png" />
</a>
</div>
<div class="item">
@@ -46,24 +40,18 @@
<img class="sponsor-image" src="/img/sponsors/cryptapi-banner.svg" />
</a>
</div>
<div class="item">
<a title="Dropbase - seamlessly collect, clean, and centralize data." style="display: block; position: relative;" href="https://www.dropbase.io/careers" target="_blank">
<span class="sponsor-badge">sponsor</span>
<img class="sponsor-image" src="/img/sponsors/dropbase-banner.svg" />
</a>
</div>
<div class="item">
<a title="https://striveworks.us/careers" style="display: block; position: relative;" href="https://striveworks.us/careers?utm_source=fastapi&utm_medium=small_banner&utm_campaign=feb_march#openings" target="_blank">
<span class="sponsor-badge">sponsor</span>
<img class="sponsor-image" src="/img/sponsors/striveworks-banner.png" />
</a>
</div>
<div class="item">
<a title="Join the team building a new SaaS platform that will change the computing world" style="display: block; position: relative;" href="https://classiq.link/mzg" target="_blank">
<span class="sponsor-badge">sponsor</span>
<img class="sponsor-image" src="/img/sponsors/classiq-banner.png" />
</a>
</div>
<div class="item">
<a title="Dropbase - seamlessly collect, clean, and centralize data." style="display: block; position: relative;" href="https://www.dropbase.io/careers" target="_blank">
<span class="sponsor-badge">sponsor</span>
<img class="sponsor-image" src="/img/sponsors/dropbase-banner.svg" />
</a>
</div>
</div>
</div>
{% endblock %}

View File

@@ -1,6 +1,6 @@
"""FastAPI framework, high performance, easy to learn, fast to code, ready for production"""
__version__ = "0.75.1"
__version__ = "0.76.0"
from starlette import status as status

View File

@@ -137,10 +137,6 @@ class FastAPI(Starlette):
self.middleware_stack: ASGIApp = self.build_middleware_stack()
self.setup()
@property
def routes(self) -> List[BaseRoute]:
return list(self.router.iter_all_routes())
def build_middleware_stack(self) -> ASGIApp:
# Duplicate/override from Starlette to add AsyncExitStackMiddleware
# inside of ExceptionMiddleware, inside of custom user middlewares

View File

@@ -25,7 +25,7 @@ async def contextmanager_in_threadpool(
try:
yield await run_in_threadpool(cm.__enter__)
except Exception as e:
ok = await run_in_threadpool(cm.__exit__, type(e), e, None)
ok: bool = await run_in_threadpool(cm.__exit__, type(e), e, None)
if not ok:
raise e
else:

View File

@@ -462,13 +462,10 @@ async def solve_dependencies(
]:
values: Dict[str, Any] = {}
errors: List[ErrorWrapper] = []
response = response or Response(
content=None,
status_code=None, # type: ignore
headers=None, # type: ignore # in Starlette
media_type=None, # type: ignore # in Starlette
background=None, # type: ignore # in Starlette
)
if response is None:
response = Response()
del response.headers["content-length"]
response.status_code = None # type: ignore
dependency_cache = dependency_cache or {}
sub_dependant: Dependant
for sub_dependant in dependant.dependencies:

View File

@@ -17,8 +17,8 @@ def get_swagger_ui_html(
*,
openapi_url: str,
title: str,
swagger_js_url: str = "https://cdn.jsdelivr.net/npm/swagger-ui-dist@3/swagger-ui-bundle.js",
swagger_css_url: str = "https://cdn.jsdelivr.net/npm/swagger-ui-dist@3/swagger-ui.css",
swagger_js_url: str = "https://cdn.jsdelivr.net/npm/swagger-ui-dist@4/swagger-ui-bundle.js",
swagger_css_url: str = "https://cdn.jsdelivr.net/npm/swagger-ui-dist@4/swagger-ui.css",
swagger_favicon_url: str = "https://fastapi.tiangolo.com/img/favicon.png",
oauth2_redirect_url: Optional[str] = None,
init_oauth: Optional[Dict[str, Any]] = None,

View File

@@ -38,7 +38,11 @@ validation_error_definition = {
"title": "ValidationError",
"type": "object",
"properties": {
"loc": {"title": "Location", "type": "array", "items": {"type": "string"}},
"loc": {
"title": "Location",
"type": "array",
"items": {"anyOf": [{"type": "string"}, {"type": "integer"}]},
},
"msg": {"title": "Message", "type": "string"},
"type": {"title": "Error Type", "type": "string"},
},
@@ -152,7 +156,7 @@ def generate_operation_id(
)
if route.operation_id:
return route.operation_id
path: str = route._route_full_path_format
path: str = route.path_format
return generate_operation_id_for_path(name=route.name, path=path, method=method)
@@ -243,7 +247,7 @@ def get_openapi_path(
model_name_map=model_name_map,
operation_ids=operation_ids,
)
callbacks[callback.name] = {callback._route_full_path: cb_path}
callbacks[callback.name] = {callback.path: cb_path}
operation["callbacks"] = callbacks
if route.status_code is not None:
status_code = str(route.status_code)
@@ -422,7 +426,7 @@ def get_openapi(
if result:
path, security_schemes, path_definitions = result
if path:
paths.setdefault(route._route_full_path_format, {}).update(path)
paths.setdefault(route.path_format, {}).update(path)
if security_schemes:
components.setdefault("securitySchemes", {}).update(
security_schemes

View File

@@ -9,14 +9,12 @@ from typing import (
Callable,
Coroutine,
Dict,
Iterator,
List,
Optional,
Sequence,
Set,
Tuple,
Type,
TypeVar,
Union,
)
@@ -59,10 +57,6 @@ from starlette.status import WS_1008_POLICY_VIOLATION
from starlette.types import ASGIApp, Scope
from starlette.websockets import WebSocket
APIRouteType = TypeVar("APIRouteType", bound="APIRoute")
APIRouterType = TypeVar("APIRouterType", bound="APIRouter")
APIMountType = TypeVar("APIMountType", bound="APIMount")
def _prepare_response_content(
res: Any,
@@ -133,7 +127,7 @@ async def serialize_response(
if is_coroutine:
value, errors_ = field.validate(response_content, {}, loc=("response",))
else:
value, errors_ = await run_in_threadpool(
value, errors_ = await run_in_threadpool( # type: ignore[misc]
field.validate, response_content, {}, loc=("response",)
)
if isinstance(errors_, ErrorWrapper):
@@ -311,8 +305,6 @@ class APIWebSocketRoute(routing.WebSocketRoute):
class APIRoute(routing.Route):
_route_full_path_format: str # only for mypy
def __init__(
self,
path: str,
@@ -346,13 +338,13 @@ class APIRoute(routing.Route):
generate_unique_id_function: Union[
Callable[["APIRoute"], str], DefaultPlaceholder
] = Default(generate_unique_id),
router: Optional["APIRouter"] = None,
) -> None:
self.path = path
self.endpoint = endpoint
self.response_model = response_model
self.summary = summary
self.response_description = response_description
self.deprecated = deprecated
self.operation_id = operation_id
self.response_model_include = response_model_include
self.response_model_exclude = response_model_exclude
@@ -360,128 +352,34 @@ class APIRoute(routing.Route):
self.response_model_exclude_unset = response_model_exclude_unset
self.response_model_exclude_defaults = response_model_exclude_defaults
self.response_model_exclude_none = response_model_exclude_none
self.include_in_schema = include_in_schema
self.response_class = response_class
self.dependency_overrides_provider = dependency_overrides_provider
self.callbacks = callbacks
self.openapi_extra = openapi_extra
self.router = router
self.generate_unique_id_function = generate_unique_id_function
self.tags = tags or []
self.responses = responses or {}
self.name = get_name(endpoint) if name is None else name
self.path_regex, self.path_format, self.param_convertors = compile_path(path)
if methods is None:
methods = ["GET"]
self.methods: Set[str] = set([method.upper() for method in methods])
if isinstance(generate_unique_id_function, DefaultPlaceholder):
current_generate_unique_id: Callable[
["APIRoute"], str
] = generate_unique_id_function.value
else:
current_generate_unique_id = generate_unique_id_function
self.unique_id = self.operation_id or current_generate_unique_id(self)
# normalize enums e.g. http.HTTPStatus
if isinstance(status_code, IntEnum):
status_code = int(status_code)
self.status_code = status_code
if methods is None:
methods = ["GET"]
self.methods: Set[str] = set([method.upper() for method in methods])
self.description = description or inspect.cleandoc(self.endpoint.__doc__ or "")
# if a "form feed" character (page break) is found in the description text,
# truncate description text to the content preceding the first "form feed"
self.description = self.description.split("\f")[0]
assert callable(endpoint), "An endpoint must be a callable"
self.path_regex, self.path_format, self.param_convertors = compile_path(
self.path
)
# Attributes set in route used to compute resolved attributes
self._route_deprecated = deprecated
self._route_include_in_schema = include_in_schema
self._route_response_class = response_class
self._route_callbacks = callbacks
self._route_generate_unique_id_function = generate_unique_id_function
self._route_tags = tags or []
self._route_responses = responses or {}
if dependencies:
self._route_dependencies = dependencies
else:
self._route_dependencies = []
self.setup()
def setup(self) -> None:
# setup full path
self._route_full_path = self.path
if self.router:
self._route_full_path = self.router._router_full_path + self.path
# setup dependencies
self.dependencies: List[params.Depends] = []
if self.router:
self.dependencies.extend(self.router.dependencies)
self.dependencies.extend(self._route_dependencies)
# setup generate_unique_id
generate_unique_id_functions: List[
Union[Callable[[APIRoute], str], DefaultPlaceholder]
] = [self._route_generate_unique_id_function]
if self.router:
generate_unique_id_functions.append(self.router.generate_unique_id_function)
current_generate_unique_id_function = get_value_or_default(
*generate_unique_id_functions
)
self.generate_unique_id_function: Union[
Callable[[APIRoute], str], DefaultPlaceholder
] = current_generate_unique_id_function
# setup responses
responses: Dict[Union[int, str], Dict[str, Any]] = {}
if self.router:
responses.update(self.router.responses)
responses.update(self._route_responses)
self.responses: Dict[Union[int, str], Dict[str, Any]] = responses
# setup default_response_class
default_response_classes: List[Union[Type[Response], DefaultPlaceholder]] = [
self._route_response_class
]
if self.router:
default_response_classes.append(self.router.default_response_class)
current_default_response_class = get_value_or_default(*default_response_classes)
self.response_class: Union[
Type[Response], DefaultPlaceholder
] = current_default_response_class
# setup tags
self.tags: List[Union[str, Enum]] = []
if self.router:
self.tags.extend(self.router.tags)
self.tags.extend(self._route_tags)
# setup callbacks
callbacks: List[BaseRoute] = []
if self.router:
callbacks.extend(self.router.callbacks)
if self._route_callbacks:
callbacks.extend(self._route_callbacks)
self.callbacks = callbacks
# setup deprecated
self.deprecated = self._route_deprecated
if self.router:
self.deprecated = self._route_deprecated or self.router.deprecated
# setup include_in_schema
self.include_in_schema = self._route_include_in_schema
if self.router:
self.include_in_schema = (
self._route_include_in_schema and self.router.include_in_schema
)
_, self._route_full_path_format, _ = compile_path(self._route_full_path)
if isinstance(self.generate_unique_id_function, DefaultPlaceholder):
resolved_generate_unique_id: Callable[
["APIRoute"], str
] = self.generate_unique_id_function.value
else:
resolved_generate_unique_id = self.generate_unique_id_function
self.unique_id = self.operation_id or resolved_generate_unique_id(self)
if self.response_model:
assert (
self.status_code not in STATUS_CODES_WITH_NO_BODY
), f"Status code {self.status_code} must not have a response body"
status_code not in STATUS_CODES_WITH_NO_BODY
), f"Status code {status_code} must not have a response body"
response_name = "Response_" + self.unique_id
self.response_field = create_response_field(
name=response_name, type_=self.response_model
@@ -499,7 +397,14 @@ class APIRoute(routing.Route):
else:
self.response_field = None # type: ignore
self.secure_cloned_response_field = None
if dependencies:
self.dependencies = list(dependencies)
else:
self.dependencies = []
self.description = description or inspect.cleandoc(self.endpoint.__doc__ or "")
# if a "form feed" character (page break) is found in the description text,
# truncate description text to the content preceding the first "form feed"
self.description = self.description.split("\f")[0]
response_fields = {}
for additional_status_code, response in self.responses.items():
assert isinstance(response, dict), "An additional response must be a dict"
@@ -516,50 +421,16 @@ class APIRoute(routing.Route):
else:
self.response_fields = {}
self.dependant = get_dependant(
path=self._route_full_path_format, call=self.endpoint
)
assert callable(endpoint), "An endpoint must be a callable"
self.dependant = get_dependant(path=self.path_format, call=self.endpoint)
for depends in self.dependencies[::-1]:
self.dependant.dependencies.insert(
0,
get_parameterless_sub_dependant(
depends=depends, path=self._route_full_path_format
),
get_parameterless_sub_dependant(depends=depends, path=self.path_format),
)
self.body_field = get_body_field(dependant=self.dependant, name=self.unique_id)
self.app = request_response(self.get_route_handler())
def copy(self: APIRouteType) -> APIRouteType:
return type(self)(
path=self.path,
endpoint=self.endpoint,
response_model=self.response_model,
status_code=self.status_code,
tags=self._route_tags,
dependencies=self._route_dependencies,
summary=self.summary,
description=self.description,
response_description=self.response_description,
responses=self._route_responses,
deprecated=self._route_deprecated,
name=self.name,
methods=self.methods,
operation_id=self.operation_id,
response_model_include=self.response_model_include,
response_model_exclude=self.response_model_exclude,
response_model_by_alias=self.response_model_by_alias,
response_model_exclude_unset=self.response_model_exclude_unset,
response_model_exclude_defaults=self.response_model_exclude_defaults,
response_model_exclude_none=self.response_model_exclude_none,
include_in_schema=self._route_include_in_schema,
response_class=self._route_response_class,
dependency_overrides_provider=self.dependency_overrides_provider,
callbacks=self._route_callbacks,
openapi_extra=self.openapi_extra,
generate_unique_id_function=self._route_generate_unique_id_function,
router=self.router,
)
def get_route_handler(self) -> Callable[[Request], Coroutine[Any, Any, Response]]:
return get_request_handler(
dependant=self.dependant,
@@ -605,7 +476,6 @@ class APIRouter(routing.Router):
generate_unique_id_function: Callable[[APIRoute], str] = Default(
generate_unique_id
),
parent_router: Optional["APIRouter"] = None,
) -> None:
super().__init__(
routes=routes, # type: ignore # in Starlette
@@ -620,151 +490,16 @@ class APIRouter(routing.Router):
"/"
), "A path prefix must not end with '/', as the routes will start with '/'"
self.prefix = prefix
self.tags: List[Union[str, Enum]] = tags or []
self.dependencies = list(dependencies or []) or []
self.deprecated = deprecated
self.include_in_schema = include_in_schema
self.responses = responses or {}
self.callbacks = callbacks or []
self.dependency_overrides_provider = dependency_overrides_provider
self.route_class = route_class
self.parent_router = parent_router
# Attributes set in router used to compute resolved attributes
self._router_dependencies = list(dependencies or []) or []
self._router_generate_unique_id_function = generate_unique_id_function
self._router_responses = responses or {}
self._router_default_response_class = default_response_class
self._router_tags: List[Union[str, Enum]] = tags or []
self._router_callbacks = callbacks or []
self._router_deprecated = deprecated
self._router_include_in_schema = include_in_schema
self._router_has_empty_route = False
self._router_has_root_route = False
self.setup()
def setup(self) -> None:
# setup full path
self._router_full_path = self.prefix
if self.parent_router:
self._router_full_path = self.parent_router._router_full_path + self.prefix
# setup dependencies
self.dependencies: List[params.Depends] = []
if self.parent_router:
self.dependencies.extend(self.parent_router.dependencies)
self.dependencies.extend(self._router_dependencies)
# setup generate_unique_id
generate_unique_id_functions: List[
Union[Callable[[APIRoute], str], DefaultPlaceholder]
] = [self._router_generate_unique_id_function]
if self.parent_router:
generate_unique_id_functions.append(
self.parent_router.generate_unique_id_function
)
current_generate_unique_id_function = get_value_or_default(
*generate_unique_id_functions
)
self.generate_unique_id_function: Union[
Callable[[APIRoute], str], DefaultPlaceholder
] = current_generate_unique_id_function
# setup responses
responses: Dict[Union[int, str], Dict[str, Any]] = {}
if self.parent_router:
responses.update(self.parent_router.responses)
responses.update(self._router_responses)
self.responses: Dict[Union[int, str], Dict[str, Any]] = responses
# setup default_response_class
default_response_classes: List[Union[Type[Response], DefaultPlaceholder]] = [
self._router_default_response_class
]
if self.parent_router:
default_response_classes.append(self.parent_router.default_response_class)
current_default_response_class = get_value_or_default(*default_response_classes)
self.default_response_class: Union[
Type[Response], DefaultPlaceholder
] = current_default_response_class
# setup tags
self.tags: List[Union[str, Enum]] = []
if self.parent_router:
self.tags.extend(self.parent_router.tags)
self.tags.extend(self._router_tags)
# setup callbacks
self.callbacks: List[BaseRoute] = []
if self.parent_router:
self.callbacks.extend(self.parent_router.callbacks)
self.callbacks.extend(self._router_callbacks)
# setup deprecated
self.deprecated = self._router_deprecated
if self.parent_router:
self.deprecated = self._router_deprecated or self.parent_router.deprecated
# setup include_in_schema
self.include_in_schema = self._router_include_in_schema
if self.parent_router:
self.include_in_schema = (
self._router_include_in_schema and self.parent_router.include_in_schema
)
# setup routes
for route in self.routes:
if isinstance(route, APIRoute):
route.router = self
route.setup()
elif isinstance(route, APIMount):
route.parent_router = self
route.setup()
def copy(self: APIRouterType) -> APIRouterType:
routes: List[routing.BaseRoute] = []
for route in self.routes:
if isinstance(route, APIRoute):
routes.append(route.copy())
elif isinstance(route, APIMount):
routes.append(route.copy())
else:
routes.append(route)
copied_router = type(self)(
prefix=self.prefix,
tags=self._router_tags,
dependencies=self._router_dependencies,
default_response_class=self._router_default_response_class,
responses=self._router_responses,
callbacks=self._router_callbacks,
routes=routes,
redirect_slashes=self.redirect_slashes,
default=self.default,
dependency_overrides_provider=self.dependency_overrides_provider,
route_class=self.route_class,
on_startup=self.on_startup,
on_shutdown=self.on_shutdown,
deprecated=self._router_deprecated,
include_in_schema=self._router_include_in_schema,
generate_unique_id_function=self._router_generate_unique_id_function,
parent_router=self.parent_router,
)
copied_router._router_has_empty_route = self._router_has_empty_route
copied_router._router_has_root_route = self._router_has_root_route
for route in copied_router.routes:
if isinstance(route, APIRoute):
route.router = copied_router
route.setup()
elif isinstance(route, Mount):
if isinstance(route.app, APIRouter):
route.app.setup()
return copied_router
def iter_all_routes(self) -> Iterator[routing.BaseRoute]:
for route in self.routes:
if isinstance(route, Mount):
if isinstance(route.app, APIRouter):
yield from route.app.iter_all_routes()
else:
yield route
def api_mount(self, router: "APIRouter", name: Optional[str] = None) -> None:
route = APIMount(router=router, name=name, parent_router=self)
self.routes.append(route)
self.default_response_class = default_response_class
self.generate_unique_id_function = generate_unique_id_function
def add_api_route(
self,
@@ -802,18 +537,34 @@ class APIRouter(routing.Router):
) -> None:
route_class = route_class_override or self.route_class
responses = responses or {}
combined_responses = {**self.responses, **responses}
current_response_class = get_value_or_default(
response_class, self.default_response_class
)
current_tags = self.tags.copy()
if tags:
current_tags.extend(tags)
current_dependencies = self.dependencies.copy()
if dependencies:
current_dependencies.extend(dependencies)
current_callbacks = self.callbacks.copy()
if callbacks:
current_callbacks.extend(callbacks)
current_generate_unique_id = get_value_or_default(
generate_unique_id_function, self.generate_unique_id_function
)
route = route_class(
path,
self.prefix + path,
endpoint=endpoint,
response_model=response_model,
status_code=status_code,
tags=tags,
dependencies=dependencies,
tags=current_tags,
dependencies=current_dependencies,
summary=summary,
description=description,
response_description=response_description,
responses=responses,
deprecated=deprecated,
responses=combined_responses,
deprecated=deprecated or self.deprecated,
methods=methods,
operation_id=operation_id,
response_model_include=response_model_include,
@@ -822,20 +573,15 @@ class APIRouter(routing.Router):
response_model_exclude_unset=response_model_exclude_unset,
response_model_exclude_defaults=response_model_exclude_defaults,
response_model_exclude_none=response_model_exclude_none,
include_in_schema=include_in_schema,
response_class=response_class,
include_in_schema=include_in_schema and self.include_in_schema,
response_class=current_response_class,
name=name,
dependency_overrides_provider=self.dependency_overrides_provider,
callbacks=callbacks,
callbacks=current_callbacks,
openapi_extra=openapi_extra,
generate_unique_id_function=generate_unique_id_function,
router=self,
generate_unique_id_function=current_generate_unique_id,
)
self.routes.append(route)
if not path:
self._router_has_empty_route = True
if path == "/":
self._router_has_root_route = True
def api_route(
self,
@@ -903,7 +649,7 @@ class APIRouter(routing.Router):
self, path: str, endpoint: Callable[..., Any], name: Optional[str] = None
) -> None:
route = APIWebSocketRoute(
path,
self.prefix + path,
endpoint=endpoint,
name=name,
dependency_overrides_provider=self.dependency_overrides_provider,
@@ -934,197 +680,103 @@ class APIRouter(routing.Router):
generate_unique_id_function: Callable[[APIRoute], str] = Default(
generate_unique_id
),
copy_flat_routes: Optional[bool] = None,
) -> None:
if prefix:
assert prefix.startswith("/"), "A path prefix must start with '/'"
assert not prefix.endswith(
"/"
), "A path prefix must not end with '/', as the routes will start with '/'"
resolved_copy_flat_routes = copy_flat_routes
if resolved_copy_flat_routes is None:
resolved_copy_flat_routes = not (prefix or router.prefix)
if not resolved_copy_flat_routes:
included_router = router.copy()
if (
prefix
or tags
or dependencies
or not isinstance(default_response_class, DefaultPlaceholder)
or responses
or callbacks
or deprecated is not None
or include_in_schema is not True
or not isinstance(generate_unique_id_function, DefaultPlaceholder)
):
current_router = type(self)(
prefix=prefix,
tags=tags,
dependencies=dependencies,
default_response_class=default_response_class,
responses=responses,
callbacks=callbacks,
deprecated=deprecated,
include_in_schema=include_in_schema,
generate_unique_id_function=generate_unique_id_function,
parent_router=self,
)
# current_router.api_mount(included_router)
current_router.include_router(included_router)
if included_router._router_has_empty_route and not self.prefix:
current_router._router_has_empty_route = True
current_router._router_has_root_route = (
included_router._router_has_root_route
)
self.api_mount(current_router)
included_router.parent_router = current_router
else:
self.api_mount(included_router)
included_router.parent_router = self
included_router.setup()
else:
# TODO: remove this and its test, as a subrouter can mount another
# subrouter (done automatically of other things are overwritten) and both
# can omit a prefix, this would error out
# for r in router.routes:
# path = getattr(r, "path")
# name = getattr(r, "name", "unknown")
# if path is not None and not path:
# raise Exception(
# f"Prefix and path cannot be both empty (path operation: {name})"
# )
if responses is None:
responses = {}
for route in router.routes:
if isinstance(route, APIRoute):
combined_responses = {}
if route.router:
combined_responses.update(route.router.responses)
combined_responses.update(responses)
combined_responses.update(route.responses)
response_classes: List[
Union[Type[Response], DefaultPlaceholder]
] = []
if route.router:
response_classes.append(route.router.default_response_class)
response_classes.extend(
[
route.response_class,
router.default_response_class,
default_response_class,
self.default_response_class,
]
for r in router.routes:
path = getattr(r, "path")
name = getattr(r, "name", "unknown")
if path is not None and not path:
raise Exception(
f"Prefix and path cannot be both empty (path operation: {name})"
)
use_response_class = get_value_or_default(*response_classes)
current_tags = []
if route.router:
current_tags.extend(route.router.tags)
if tags:
current_tags.extend(tags)
if route.tags:
current_tags.extend(route.tags)
current_dependencies: List[params.Depends] = []
if route.router:
current_dependencies.extend(route.router.dependencies)
if dependencies:
current_dependencies.extend(dependencies)
if route.dependencies:
current_dependencies.extend(route.dependencies)
current_callbacks = []
if route.router:
current_callbacks.extend(route.router.callbacks)
if callbacks:
current_callbacks.extend(callbacks)
if route.callbacks:
current_callbacks.extend(route.callbacks)
generate_unique_id_functions: List[
Union[Callable[[APIRoute], str], DefaultPlaceholder]
] = []
if route.router:
generate_unique_id_functions.append(
route.router.generate_unique_id_function
)
generate_unique_id_functions.extend(
[
route.generate_unique_id_function,
router.generate_unique_id_function,
generate_unique_id_function,
self.generate_unique_id_function,
]
)
current_generate_unique_id_function = get_value_or_default(
*generate_unique_id_functions
)
path = prefix + route.path
if route.router:
path = prefix + route.router.prefix + path
self.add_api_route(
path,
route.endpoint,
response_model=route.response_model,
status_code=route.status_code,
tags=current_tags,
dependencies=current_dependencies,
summary=route.summary,
description=route.description,
response_description=route.response_description,
responses=combined_responses,
deprecated=route.deprecated or deprecated or self.deprecated,
methods=route.methods,
operation_id=route.operation_id,
response_model_include=route.response_model_include,
response_model_exclude=route.response_model_exclude,
response_model_by_alias=route.response_model_by_alias,
response_model_exclude_unset=route.response_model_exclude_unset,
response_model_exclude_defaults=route.response_model_exclude_defaults,
response_model_exclude_none=route.response_model_exclude_none,
include_in_schema=route.include_in_schema
and self.include_in_schema
and include_in_schema,
response_class=use_response_class,
name=route.name,
route_class_override=type(route),
callbacks=current_callbacks,
openapi_extra=route.openapi_extra,
generate_unique_id_function=current_generate_unique_id_function,
)
elif isinstance(route, APIMount):
self.include_router(
route.app,
prefix=prefix,
tags=tags,
dependencies=dependencies,
default_response_class=default_response_class,
responses=responses,
callbacks=callbacks,
deprecated=deprecated,
include_in_schema=include_in_schema,
generate_unique_id_function=generate_unique_id_function,
)
elif isinstance(route, routing.Route):
methods = list(route.methods or []) # type: ignore # in Starlette
self.add_route(
prefix + route.path,
route.endpoint,
methods=methods,
include_in_schema=route.include_in_schema,
name=route.name,
)
elif isinstance(route, APIWebSocketRoute):
self.add_api_websocket_route(
prefix + route.path, route.endpoint, name=route.name
)
elif isinstance(route, routing.WebSocketRoute):
self.add_websocket_route(
prefix + route.path, route.endpoint, name=route.name
)
for handler in router.on_startup:
self.add_event_handler("startup", handler)
for handler in router.on_shutdown:
self.add_event_handler("shutdown", handler)
if responses is None:
responses = {}
for route in router.routes:
if isinstance(route, APIRoute):
combined_responses = {**responses, **route.responses}
use_response_class = get_value_or_default(
route.response_class,
router.default_response_class,
default_response_class,
self.default_response_class,
)
current_tags = []
if tags:
current_tags.extend(tags)
if route.tags:
current_tags.extend(route.tags)
current_dependencies: List[params.Depends] = []
if dependencies:
current_dependencies.extend(dependencies)
if route.dependencies:
current_dependencies.extend(route.dependencies)
current_callbacks = []
if callbacks:
current_callbacks.extend(callbacks)
if route.callbacks:
current_callbacks.extend(route.callbacks)
current_generate_unique_id = get_value_or_default(
route.generate_unique_id_function,
router.generate_unique_id_function,
generate_unique_id_function,
self.generate_unique_id_function,
)
self.add_api_route(
prefix + route.path,
route.endpoint,
response_model=route.response_model,
status_code=route.status_code,
tags=current_tags,
dependencies=current_dependencies,
summary=route.summary,
description=route.description,
response_description=route.response_description,
responses=combined_responses,
deprecated=route.deprecated or deprecated or self.deprecated,
methods=route.methods,
operation_id=route.operation_id,
response_model_include=route.response_model_include,
response_model_exclude=route.response_model_exclude,
response_model_by_alias=route.response_model_by_alias,
response_model_exclude_unset=route.response_model_exclude_unset,
response_model_exclude_defaults=route.response_model_exclude_defaults,
response_model_exclude_none=route.response_model_exclude_none,
include_in_schema=route.include_in_schema
and self.include_in_schema
and include_in_schema,
response_class=use_response_class,
name=route.name,
route_class_override=type(route),
callbacks=current_callbacks,
openapi_extra=route.openapi_extra,
generate_unique_id_function=current_generate_unique_id,
)
elif isinstance(route, routing.Route):
methods = list(route.methods or []) # type: ignore # in Starlette
self.add_route(
prefix + route.path,
route.endpoint,
methods=methods,
include_in_schema=route.include_in_schema,
name=route.name,
)
elif isinstance(route, APIWebSocketRoute):
self.add_api_websocket_route(
prefix + route.path, route.endpoint, name=route.name
)
elif isinstance(route, routing.WebSocketRoute):
self.add_websocket_route(
prefix + route.path, route.endpoint, name=route.name
)
for handler in router.on_startup:
self.add_event_handler("startup", handler)
for handler in router.on_shutdown:
self.add_event_handler("shutdown", handler)
def get(
self,
@@ -1574,100 +1226,3 @@ class APIRouter(routing.Router):
openapi_extra=openapi_extra,
generate_unique_id_function=generate_unique_id_function,
)
class APIMount(routing.Mount):
def __init__(
self,
router: APIRouter,
*,
name: Optional[str] = None,
parent_router: Optional[APIRouter] = None,
) -> None:
self.name = name # type: ignore # in Starlette
self.parent_router = parent_router
self.router = router
self.setup()
def setup(self) -> None:
self.app: APIRouter = self.router.copy()
if self.parent_router:
self.app.parent_router = self.parent_router
self.app.setup()
self.path = self.app.prefix
self.path_regex, self.path_format, self.param_convertors = compile_path(
self.path + "/{path:path}"
)
# Add custom additional root without trailing slash for compatibility with
# include_router and possibly app migrations
# Ref: https://github.com/tiangolo/fastapi/issues/414
(
self._root_path_regex,
self._root_path_format,
self._root_param_convertors,
) = compile_path(self.path)
(
self._root_path_regex_trailing,
self._root_path_format_trailing,
self._root_param_convertors_trailing,
) = compile_path(self.path + "/")
def copy(self: APIMountType) -> APIMountType:
return type(self)(
router=self.router.copy(),
name=self.name,
parent_router=self.parent_router,
)
def matches(self, scope: Scope) -> Tuple[Match, Scope]:
if scope["type"] in ("http", "websocket"):
path = scope["path"]
if self.app._router_has_empty_route:
# Custom logic to support paths without trailing slash
# Ref: https://github.com/tiangolo/fastapi/issues/414
# This mixes the code in
# starlette.routing.Route.matches() and starlette.routing.Mount.matches()
match = self._root_path_regex.match(path)
if match:
matched_params = match.groupdict()
for key, value in matched_params.items():
matched_params[key] = self.param_convertors[key].convert(value)
path_params = dict(scope.get("path_params", {}))
path_params.update(matched_params)
root_path = scope.get("root_path", "")
child_scope = {
"path_params": path_params,
"app_root_path": scope.get("app_root_path", root_path),
"root_path": root_path,
"path": "",
"endpoint": self.app,
}
return Match.FULL, child_scope
if not self.app._router_has_root_route:
match = self._root_path_regex_trailing.match(path)
if match:
return Match.NONE, {}
# End of custom logic
# Duplicated code from Starlette
match = self.path_regex.match(path)
if match:
matched_params = match.groupdict()
for key, value in matched_params.items():
matched_params[key] = self.param_convertors[key].convert(value)
remaining_path = "/" + matched_params.pop("path")
matched_path = path[: -len(remaining_path)]
path_params = dict(scope.get("path_params", {}))
path_params.update(matched_params)
root_path = scope.get("root_path", "")
child_scope = {
"path_params": path_params,
"app_root_path": scope.get("app_root_path", root_path),
"root_path": root_path + matched_path,
"path": remaining_path,
"endpoint": self.app,
}
return Match.FULL, child_scope
return Match.NONE, {}
# End of duplicated code from Starlette

View File

@@ -139,7 +139,7 @@ def generate_operation_id_for_path(
def generate_unique_id(route: "APIRoute") -> str:
operation_id = route.name + route._route_full_path_format
operation_id = route.name + route.path_format
operation_id = re.sub("[^0-9a-zA-Z_]", "_", operation_id)
assert route.methods
operation_id = operation_id + "_" + list(route.methods)[0].lower()

View File

@@ -35,7 +35,7 @@ classifiers = [
"Topic :: Internet :: WWW/HTTP",
]
requires = [
"starlette ==0.17.1",
"starlette ==0.18.0",
"pydantic >=1.6.2,!=1.7,!=1.7.1,!=1.7.2,!=1.7.3,!=1.8,!=1.8.1,<2.0.0",
]
description-file = "README.md"
@@ -59,15 +59,15 @@ test = [
"peewee >=3.13.3,<4.0.0",
"databases[sqlite] >=0.3.2,<0.6.0",
"orjson >=3.2.1,<4.0.0",
"ujson >=4.0.1,<5.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",
"python-multipart >=0.0.5,<0.0.6",
"flask >=1.1.2,<3.0.0",
"anyio[trio] >=3.2.1,<4.0.0",
# types
"types-ujson ==0.1.1",
"types-orjson ==3.6.0",
"types-dataclasses ==0.1.7; python_version<'3.7'",
"types-ujson ==4.2.1",
"types-orjson ==3.6.2",
"types-dataclasses ==0.6.5; python_version<'3.7'",
]
doc = [
"mkdocs >=1.1.2,<2.0.0",
@@ -77,25 +77,25 @@ doc = [
# TODO: upgrade and enable typer-cli once it supports Click 8.x.x
# "typer-cli >=0.0.12,<0.0.13",
"typer >=0.4.1,<0.5.0",
"pyyaml >=5.3.1,<6.0.0"
"pyyaml >=5.3.1,<7.0.0",
]
dev = [
"python-jose[cryptography] >=3.3.0,<4.0.0",
"passlib[bcrypt] >=1.7.2,<2.0.0",
"autoflake >=1.4.0,<2.0.0",
"flake8 >=3.8.3,<4.0.0",
"uvicorn[standard] >=0.12.0,<0.16.0",
"uvicorn[standard] >=0.12.0,<0.18.0",
]
all = [
"requests >=2.24.0,<3.0.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,<6.0.0",
"ujson >=4.0.1,<5.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.16.0",
"uvicorn[standard] >=0.12.0,<0.18.0",
]
[tool.isort]
@@ -140,4 +140,6 @@ filterwarnings = [
"error",
# 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',
# TODO: remove after dropping support for Python 3.6
'ignore:Python 3.6 is no longer supported by the Python core team. Therefore, support for it is deprecated in cryptography and will be removed in a future release.:UserWarning:jose',
]

View File

@@ -76,7 +76,7 @@ openapi_schema = {
"loc": {
"title": "Location",
"type": "array",
"items": {"type": "string"},
"items": {"anyOf": [{"type": "string"}, {"type": "integer"}]},
},
"msg": {"title": "Message", "type": "string"},
"type": {"title": "Error Type", "type": "string"},

View File

@@ -119,7 +119,7 @@ openapi_schema = {
"loc": {
"title": "Location",
"type": "array",
"items": {"type": "string"},
"items": {"anyOf": [{"type": "string"}, {"type": "integer"}]},
},
"msg": {"title": "Message", "type": "string"},
"type": {"title": "Error Type", "type": "string"},

View File

@@ -54,7 +54,7 @@ openapi_schema = {
"loc": {
"title": "Location",
"type": "array",
"items": {"type": "string"},
"items": {"anyOf": [{"type": "string"}, {"type": "integer"}]},
},
"msg": {"title": "Message", "type": "string"},
"type": {"title": "Error Type", "type": "string"},

View File

@@ -1101,7 +1101,7 @@ openapi_schema = {
"loc": {
"title": "Location",
"type": "array",
"items": {"type": "string"},
"items": {"anyOf": [{"type": "string"}, {"type": "integer"}]},
},
"msg": {"title": "Message", "type": "string"},
"type": {"title": "Error Type", "type": "string"},

View File

@@ -2,6 +2,7 @@ import pytest
from fastapi import APIRouter, FastAPI
from fastapi.routing import APIRoute
from fastapi.testclient import TestClient
from starlette.routing import Route
app = FastAPI()
@@ -106,9 +107,9 @@ def test_get_path(path, expected_status, expected_response):
def test_route_classes():
routes = {}
for r in app.router.iter_all_routes():
if isinstance(r, APIRoute):
routes[r._route_full_path_format] = r
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"

View File

@@ -177,7 +177,7 @@ openapi_schema = {
"loc": {
"title": "Location",
"type": "array",
"items": {"type": "string"},
"items": {"anyOf": [{"type": "string"}, {"type": "integer"}]},
},
"msg": {"title": "Message", "type": "string"},
"type": {"title": "Error Type", "type": "string"},

View File

@@ -292,7 +292,7 @@ openapi_schema = {
"loc": {
"title": "Location",
"type": "array",
"items": {"type": "string"},
"items": {"anyOf": [{"type": "string"}, {"type": "integer"}]},
},
"msg": {"title": "Message", "type": "string"},
"type": {"title": "Error Type", "type": "string"},

View File

@@ -116,7 +116,7 @@ openapi_schema = {
"loc": {
"title": "Location",
"type": "array",
"items": {"type": "string"},
"items": {"anyOf": [{"type": "string"}, {"type": "integer"}]},
},
"msg": {"title": "Message", "type": "string"},
"type": {"title": "Error Type", "type": "string"},

View File

@@ -217,7 +217,9 @@ def test_top_level_generate_unique_id():
"loc": {
"title": "Location",
"type": "array",
"items": {"type": "string"},
"items": {
"anyOf": [{"type": "string"}, {"type": "integer"}]
},
},
"msg": {"title": "Message", "type": "string"},
"type": {"title": "Error Type", "type": "string"},
@@ -416,7 +418,9 @@ def test_router_overrides_generate_unique_id():
"loc": {
"title": "Location",
"type": "array",
"items": {"type": "string"},
"items": {
"anyOf": [{"type": "string"}, {"type": "integer"}]
},
},
"msg": {"title": "Message", "type": "string"},
"type": {"title": "Error Type", "type": "string"},
@@ -615,7 +619,9 @@ def test_router_include_overrides_generate_unique_id():
"loc": {
"title": "Location",
"type": "array",
"items": {"type": "string"},
"items": {
"anyOf": [{"type": "string"}, {"type": "integer"}]
},
},
"msg": {"title": "Message", "type": "string"},
"type": {"title": "Error Type", "type": "string"},
@@ -887,7 +893,9 @@ def test_subrouter_top_level_include_overrides_generate_unique_id():
"loc": {
"title": "Location",
"type": "array",
"items": {"type": "string"},
"items": {
"anyOf": [{"type": "string"}, {"type": "integer"}]
},
},
"msg": {"title": "Message", "type": "string"},
"type": {"title": "Error Type", "type": "string"},
@@ -1089,7 +1097,9 @@ def test_router_path_operation_overrides_generate_unique_id():
"loc": {
"title": "Location",
"type": "array",
"items": {"type": "string"},
"items": {
"anyOf": [{"type": "string"}, {"type": "integer"}]
},
},
"msg": {"title": "Message", "type": "string"},
"type": {"title": "Error Type", "type": "string"},
@@ -1295,7 +1305,9 @@ def test_app_path_operation_overrides_generate_unique_id():
"loc": {
"title": "Location",
"type": "array",
"items": {"type": "string"},
"items": {
"anyOf": [{"type": "string"}, {"type": "integer"}]
},
},
"msg": {"title": "Message", "type": "string"},
"type": {"title": "Error Type", "type": "string"},
@@ -1579,7 +1591,9 @@ def test_callback_override_generate_unique_id():
"loc": {
"title": "Location",
"type": "array",
"items": {"type": "string"},
"items": {
"anyOf": [{"type": "string"}, {"type": "integer"}]
},
},
"msg": {"title": "Message", "type": "string"},
"type": {"title": "Error Type", "type": "string"},

View File

@@ -85,7 +85,7 @@ openapi_schema = {
"loc": {
"title": "Location",
"type": "array",
"items": {"type": "string"},
"items": {"anyOf": [{"type": "string"}, {"type": "integer"}]},
},
"msg": {"title": "Message", "type": "string"},
"type": {"title": "Error Type", "type": "string"},

View File

@@ -6612,7 +6612,7 @@ openapi_schema = {
"loc": {
"title": "Location",
"type": "array",
"items": {"type": "string"},
"items": {"anyOf": [{"type": "string"}, {"type": "integer"}]},
},
"msg": {"title": "Message", "type": "string"},
"type": {"title": "Error Type", "type": "string"},

View File

@@ -101,7 +101,7 @@ openapi_schema = {
"loc": {
"title": "Location",
"type": "array",
"items": {"type": "string"},
"items": {"anyOf": [{"type": "string"}, {"type": "integer"}]},
},
"msg": {"title": "Message", "type": "string"},
"type": {"title": "Error Type", "type": "string"},

View File

@@ -79,7 +79,7 @@ openapi_schema = {
"loc": {
"title": "Location",
"type": "array",
"items": {"type": "string"},
"items": {"anyOf": [{"type": "string"}, {"type": "integer"}]},
},
"msg": {"title": "Message", "type": "string"},
"type": {"title": "Error Type", "type": "string"},

View File

@@ -63,7 +63,7 @@ openapi_schema = {
"loc": {
"title": "Location",
"type": "array",
"items": {"type": "string"},
"items": {"anyOf": [{"type": "string"}, {"type": "integer"}]},
},
"msg": {"title": "Message", "type": "string"},
"type": {"title": "Error Type", "type": "string"},

View File

@@ -71,7 +71,7 @@ openapi_schema = {
"loc": {
"title": "Location",
"type": "array",
"items": {"type": "string"},
"items": {"anyOf": [{"type": "string"}, {"type": "integer"}]},
},
"msg": {"title": "Message", "type": "string"},
"type": {"title": "Error Type", "type": "string"},

View File

@@ -149,7 +149,7 @@ openapi_shema = {
"loc": {
"title": "Location",
"type": "array",
"items": {"type": "string"},
"items": {"anyOf": [{"type": "string"}, {"type": "integer"}]},
},
"msg": {"title": "Message", "type": "string"},
"type": {"title": "Error Type", "type": "string"},

View File

@@ -57,7 +57,7 @@ openapi_schema = {
"loc": {
"title": "Location",
"type": "array",
"items": {"type": "string"},
"items": {"anyOf": [{"type": "string"}, {"type": "integer"}]},
},
"msg": {"title": "Message", "type": "string"},
"type": {"title": "Error Type", "type": "string"},

View File

@@ -36,7 +36,7 @@ schema = {
"ValidationError": {
"properties": {
"loc": {
"items": {"type": "string"},
"items": {"anyOf": [{"type": "string"}, {"type": "integer"}]},
"title": "Location",
"type": "array",
},

View File

@@ -830,7 +830,7 @@ openapi_schema = {
"loc": {
"title": "Location",
"type": "array",
"items": {"type": "string"},
"items": {"anyOf": [{"type": "string"}, {"type": "integer"}]},
},
"msg": {"title": "Message", "type": "string"},
"type": {"title": "Error Type", "type": "string"},

View File

@@ -117,7 +117,7 @@ openapi_schema = {
"loc": {
"title": "Location",
"type": "array",
"items": {"type": "string"},
"items": {"anyOf": [{"type": "string"}, {"type": "integer"}]},
},
"msg": {"title": "Message", "type": "string"},
"type": {"title": "Error Type", "type": "string"},

View File

@@ -121,7 +121,7 @@ openapi_schema = {
"loc": {
"title": "Location",
"type": "array",
"items": {"type": "string"},
"items": {"anyOf": [{"type": "string"}, {"type": "integer"}]},
},
"msg": {"title": "Message", "type": "string"},
"type": {"title": "Error Type", "type": "string"},

View File

@@ -122,7 +122,7 @@ openapi_schema = {
"loc": {
"title": "Location",
"type": "array",
"items": {"type": "string"},
"items": {"anyOf": [{"type": "string"}, {"type": "integer"}]},
},
"msg": {"title": "Message", "type": "string"},
"type": {"title": "Error Type", "type": "string"},

View File

@@ -102,7 +102,7 @@ openapi_schema = {
"loc": {
"title": "Location",
"type": "array",
"items": {"type": "string"},
"items": {"anyOf": [{"type": "string"}, {"type": "integer"}]},
},
"msg": {"title": "Message", "type": "string"},
"type": {"title": "Error Type", "type": "string"},

View File

@@ -256,7 +256,7 @@ openapi_schema = {
"loc": {
"title": "Location",
"type": "array",
"items": {"type": "string"},
"items": {"anyOf": [{"type": "string"}, {"type": "integer"}]},
},
"msg": {"title": "Message", "type": "string"},
"type": {"title": "Error Type", "type": "string"},

View File

@@ -200,7 +200,7 @@ openapi_schema = {
"loc": {
"title": "Location",
"type": "array",
"items": {"type": "string"},
"items": {"anyOf": [{"type": "string"}, {"type": "integer"}]},
},
"msg": {"title": "Message", "type": "string"},
"type": {"title": "Error Type", "type": "string"},

View File

@@ -76,7 +76,7 @@ openapi_schema = {
"loc": {
"title": "Location",
"type": "array",
"items": {"type": "string"},
"items": {"anyOf": [{"type": "string"}, {"type": "integer"}]},
},
"msg": {"title": "Message", "type": "string"},
"type": {"title": "Error Type", "type": "string"},

View File

@@ -72,7 +72,7 @@ openapi_schema = {
"loc": {
"title": "Location",
"type": "array",
"items": {"type": "string"},
"items": {"anyOf": [{"type": "string"}, {"type": "integer"}]},
},
"msg": {"title": "Message", "type": "string"},
"type": {"title": "Error Type", "type": "string"},

View File

@@ -77,7 +77,7 @@ openapi_schema = {
"loc": {
"title": "Location",
"type": "array",
"items": {"type": "string"},
"items": {"anyOf": [{"type": "string"}, {"type": "integer"}]},
},
"msg": {"title": "Message", "type": "string"},
"type": {"title": "Error Type", "type": "string"},

View File

@@ -75,7 +75,7 @@ openapi_schema = {
"loc": {
"title": "Location",
"type": "array",
"items": {"type": "string"},
"items": {"anyOf": [{"type": "string"}, {"type": "integer"}]},
},
"msg": {"title": "Message", "type": "string"},
"type": {"title": "Error Type", "type": "string"},

View File

@@ -88,7 +88,7 @@ openapi_schema = {
"loc": {
"title": "Location",
"type": "array",
"items": {"type": "string"},
"items": {"anyOf": [{"type": "string"}, {"type": "integer"}]},
},
"msg": {"title": "Message", "type": "string"},
"type": {"title": "Error Type", "type": "string"},

View File

@@ -323,7 +323,7 @@ openapi_schema = {
"loc": {
"title": "Location",
"type": "array",
"items": {"type": "string"},
"items": {"anyOf": [{"type": "string"}, {"type": "integer"}]},
},
"msg": {"title": "Message", "type": "string"},
"type": {"title": "Error Type", "type": "string"},

View File

@@ -63,7 +63,7 @@ openapi_schema = {
"loc": {
"title": "Location",
"type": "array",
"items": {"type": "string"},
"items": {"anyOf": [{"type": "string"}, {"type": "integer"}]},
},
"msg": {"title": "Message", "type": "string"},
"type": {"title": "Error Type", "type": "string"},

View File

@@ -61,7 +61,7 @@ openapi_schema = {
"loc": {
"title": "Location",
"type": "array",
"items": {"type": "string"},
"items": {"anyOf": [{"type": "string"}, {"type": "integer"}]},
},
"msg": {"title": "Message", "type": "string"},
"type": {"title": "Error Type", "type": "string"},

View File

@@ -87,7 +87,7 @@ openapi_schema = {
"loc": {
"title": "Location",
"type": "array",
"items": {"type": "string"},
"items": {"anyOf": [{"type": "string"}, {"type": "integer"}]},
},
"msg": {"title": "Message", "type": "string"},
"type": {"title": "Error Type", "type": "string"},

View File

@@ -84,7 +84,7 @@ openapi_schema = {
"loc": {
"title": "Location",
"type": "array",
"items": {"type": "string"},
"items": {"anyOf": [{"type": "string"}, {"type": "integer"}]},
},
"msg": {"title": "Message", "type": "string"},
"type": {"title": "Error Type", "type": "string"},

View File

@@ -79,7 +79,7 @@ openapi_schema = {
"loc": {
"title": "Location",
"type": "array",
"items": {"type": "string"},
"items": {"anyOf": [{"type": "string"}, {"type": "integer"}]},
},
"msg": {"title": "Message", "type": "string"},
"type": {"title": "Error Type", "type": "string"},

View File

@@ -77,7 +77,7 @@ openapi_schema = {
"loc": {
"title": "Location",
"type": "array",
"items": {"type": "string"},
"items": {"anyOf": [{"type": "string"}, {"type": "integer"}]},
},
"msg": {"title": "Message", "type": "string"},
"type": {"title": "Error Type", "type": "string"},

View File

@@ -90,7 +90,7 @@ openapi_schema = {
"loc": {
"title": "Location",
"type": "array",
"items": {"type": "string"},
"items": {"anyOf": [{"type": "string"}, {"type": "integer"}]},
},
"msg": {"title": "Message", "type": "string"},
"type": {"title": "Error Type", "type": "string"},

View File

@@ -88,7 +88,7 @@ openapi_schema = {
"loc": {
"title": "Location",
"type": "array",
"items": {"type": "string"},
"items": {"anyOf": [{"type": "string"}, {"type": "integer"}]},
},
"msg": {"title": "Message", "type": "string"},
"type": {"title": "Error Type", "type": "string"},

View File

@@ -53,7 +53,7 @@ openapi_schema = {
"loc": {
"title": "Location",
"type": "array",
"items": {"type": "string"},
"items": {"anyOf": [{"type": "string"}, {"type": "integer"}]},
},
"msg": {"title": "Message", "type": "string"},
"type": {"title": "Error Type", "type": "string"},

View File

@@ -52,7 +52,7 @@ openapi_schema = {
"loc": {
"title": "Location",
"type": "array",
"items": {"type": "string"},
"items": {"anyOf": [{"type": "string"}, {"type": "integer"}]},
},
"msg": {"title": "Message", "type": "string"},
"type": {"title": "Error Type", "type": "string"},

View File

@@ -109,7 +109,7 @@ openapi_schema = {
"loc": {
"title": "Location",
"type": "array",
"items": {"type": "string"},
"items": {"anyOf": [{"type": "string"}, {"type": "integer"}]},
},
"msg": {"title": "Message", "type": "string"},
"type": {"title": "Error Type", "type": "string"},

View File

@@ -108,7 +108,7 @@ openapi_schema = {
"loc": {
"title": "Location",
"type": "array",
"items": {"type": "string"},
"items": {"anyOf": [{"type": "string"}, {"type": "integer"}]},
},
"msg": {"title": "Message", "type": "string"},
"type": {"title": "Error Type", "type": "string"},

View File

@@ -108,7 +108,7 @@ openapi_schema = {
"loc": {
"title": "Location",
"type": "array",
"items": {"type": "string"},
"items": {"anyOf": [{"type": "string"}, {"type": "integer"}]},
},
"msg": {"title": "Message", "type": "string"},
"type": {"title": "Error Type", "type": "string"},

View File

@@ -50,7 +50,7 @@ openapi_schema = {
"loc": {
"title": "Location",
"type": "array",
"items": {"type": "string"},
"items": {"anyOf": [{"type": "string"}, {"type": "integer"}]},
},
"msg": {"title": "Message", "type": "string"},
"type": {"title": "Error Type", "type": "string"},

View File

@@ -48,7 +48,7 @@ openapi_schema = {
"loc": {
"title": "Location",
"type": "array",
"items": {"type": "string"},
"items": {"anyOf": [{"type": "string"}, {"type": "integer"}]},
},
"msg": {"title": "Message", "type": "string"},
"type": {"title": "Error Type", "type": "string"},

View File

@@ -71,7 +71,7 @@ openapi_schema = {
"loc": {
"title": "Location",
"type": "array",
"items": {"type": "string"},
"items": {"anyOf": [{"type": "string"}, {"type": "integer"}]},
},
"msg": {"title": "Message", "type": "string"},
"type": {"title": "Error Type", "type": "string"},

View File

@@ -118,7 +118,7 @@ openapi_schema = {
"loc": {
"title": "Location",
"type": "array",
"items": {"type": "string"},
"items": {"anyOf": [{"type": "string"}, {"type": "integer"}]},
},
"msg": {"title": "Message", "type": "string"},
"type": {"title": "Error Type", "type": "string"},

View File

@@ -104,7 +104,7 @@ openapi_schema = {
"loc": {
"title": "Location",
"type": "array",
"items": {"type": "string"},
"items": {"anyOf": [{"type": "string"}, {"type": "integer"}]},
},
"msg": {"title": "Message", "type": "string"},
"type": {"title": "Error Type", "type": "string"},

View File

@@ -102,7 +102,7 @@ openapi_schema = {
"loc": {
"title": "Location",
"type": "array",
"items": {"type": "string"},
"items": {"anyOf": [{"type": "string"}, {"type": "integer"}]},
},
"msg": {"title": "Message", "type": "string"},
"type": {"title": "Error Type", "type": "string"},

View File

@@ -62,7 +62,7 @@ openapi_schema = {
"loc": {
"title": "Location",
"type": "array",
"items": {"type": "string"},
"items": {"anyOf": [{"type": "string"}, {"type": "integer"}]},
},
"msg": {"title": "Message", "type": "string"},
"type": {"title": "Error Type", "type": "string"},

View File

@@ -60,7 +60,7 @@ openapi_schema = {
"loc": {
"title": "Location",
"type": "array",
"items": {"type": "string"},
"items": {"anyOf": [{"type": "string"}, {"type": "integer"}]},
},
"msg": {"title": "Message", "type": "string"},
"type": {"title": "Error Type", "type": "string"},

View File

@@ -55,7 +55,7 @@ openapi_schema = {
"loc": {
"title": "Location",
"type": "array",
"items": {"type": "string"},
"items": {"anyOf": [{"type": "string"}, {"type": "integer"}]},
},
"msg": {"title": "Message", "type": "string"},
"type": {"title": "Error Type", "type": "string"},

View File

@@ -102,7 +102,7 @@ openapi_schema = {
"loc": {
"title": "Location",
"type": "array",
"items": {"type": "string"},
"items": {"anyOf": [{"type": "string"}, {"type": "integer"}]},
},
"msg": {"title": "Message", "type": "string"},
"type": {"title": "Error Type", "type": "string"},

View File

@@ -47,7 +47,7 @@ openapi_schema = {
"loc": {
"title": "Location",
"type": "array",
"items": {"type": "string"},
"items": {"anyOf": [{"type": "string"}, {"type": "integer"}]},
},
"msg": {"title": "Message", "type": "string"},
"type": {"title": "Error Type", "type": "string"},

View File

@@ -89,7 +89,7 @@ openapi_schema = {
"loc": {
"title": "Location",
"type": "array",
"items": {"type": "string"},
"items": {"anyOf": [{"type": "string"}, {"type": "integer"}]},
},
"msg": {"title": "Message", "type": "string"},
"type": {"title": "Error Type", "type": "string"},

View File

@@ -87,7 +87,7 @@ openapi_schema = {
"loc": {
"title": "Location",
"type": "array",
"items": {"type": "string"},
"items": {"anyOf": [{"type": "string"}, {"type": "integer"}]},
},
"msg": {"title": "Message", "type": "string"},
"type": {"title": "Error Type", "type": "string"},

View File

@@ -78,7 +78,7 @@ openapi_schema = {
"loc": {
"title": "Location",
"type": "array",
"items": {"type": "string"},
"items": {"anyOf": [{"type": "string"}, {"type": "integer"}]},
},
"msg": {"title": "Message", "type": "string"},
"type": {"title": "Error Type", "type": "string"},

View File

@@ -77,7 +77,7 @@ openapi_schema = {
"loc": {
"title": "Location",
"type": "array",
"items": {"type": "string"},
"items": {"anyOf": [{"type": "string"}, {"type": "integer"}]},
},
"msg": {"title": "Message", "type": "string"},
"type": {"title": "Error Type", "type": "string"},

View File

@@ -147,7 +147,7 @@ openapi_schema = {
"loc": {
"title": "Location",
"type": "array",
"items": {"type": "string"},
"items": {"anyOf": [{"type": "string"}, {"type": "integer"}]},
},
"msg": {"title": "Message", "type": "string"},
"type": {"title": "Error Type", "type": "string"},

View File

@@ -49,7 +49,7 @@ openapi_schema = {
"loc": {
"title": "Location",
"type": "array",
"items": {"type": "string"},
"items": {"anyOf": [{"type": "string"}, {"type": "integer"}]},
},
"msg": {"title": "Message", "type": "string"},
"type": {"title": "Error Type", "type": "string"},

View File

@@ -49,7 +49,7 @@ openapi_schema = {
"loc": {
"title": "Location",
"type": "array",
"items": {"type": "string"},
"items": {"anyOf": [{"type": "string"}, {"type": "integer"}]},
},
"msg": {"title": "Message", "type": "string"},
"type": {"title": "Error Type", "type": "string"},

View File

@@ -49,7 +49,7 @@ openapi_schema = {
"loc": {
"title": "Location",
"type": "array",
"items": {"type": "string"},
"items": {"anyOf": [{"type": "string"}, {"type": "integer"}]},
},
"msg": {"title": "Message", "type": "string"},
"type": {"title": "Error Type", "type": "string"},

View File

@@ -49,7 +49,7 @@ openapi_schema = {
"loc": {
"title": "Location",
"type": "array",
"items": {"type": "string"},
"items": {"anyOf": [{"type": "string"}, {"type": "integer"}]},
},
"msg": {"title": "Message", "type": "string"},
"type": {"title": "Error Type", "type": "string"},

View File

@@ -69,7 +69,7 @@ openapi_schema = {
"loc": {
"title": "Location",
"type": "array",
"items": {"type": "string"},
"items": {"anyOf": [{"type": "string"}, {"type": "integer"}]},
},
"msg": {"title": "Message", "type": "string"},
"type": {"title": "Error Type", "type": "string"},

View File

@@ -49,7 +49,7 @@ openapi_schema = {
"loc": {
"title": "Location",
"type": "array",
"items": {"type": "string"},
"items": {"anyOf": [{"type": "string"}, {"type": "integer"}]},
},
"msg": {"title": "Message", "type": "string"},
"type": {"title": "Error Type", "type": "string"},

View File

@@ -51,7 +51,7 @@ openapi_schema = {
"loc": {
"title": "Location",
"type": "array",
"items": {"type": "string"},
"items": {"anyOf": [{"type": "string"}, {"type": "integer"}]},
},
"msg": {"title": "Message", "type": "string"},
"type": {"title": "Error Type", "type": "string"},

View File

@@ -48,7 +48,7 @@ openapi_schema = {
"loc": {
"title": "Location",
"type": "array",
"items": {"type": "string"},
"items": {"anyOf": [{"type": "string"}, {"type": "integer"}]},
},
"msg": {"title": "Message", "type": "string"},
"type": {"title": "Error Type", "type": "string"},

View File

@@ -143,7 +143,7 @@ openapi_schema = {
"loc": {
"title": "Location",
"type": "array",
"items": {"type": "string"},
"items": {"anyOf": [{"type": "string"}, {"type": "integer"}]},
},
"msg": {"title": "Message", "type": "string"},
"type": {"title": "Error Type", "type": "string"},

View File

@@ -72,7 +72,7 @@ openapi_schema = {
"loc": {
"title": "Location",
"type": "array",
"items": {"type": "string"},
"items": {"anyOf": [{"type": "string"}, {"type": "integer"}]},
},
"msg": {"title": "Message", "type": "string"},
"type": {"title": "Error Type", "type": "string"},

View File

@@ -72,7 +72,7 @@ openapi_schema = {
"loc": {
"title": "Location",
"type": "array",
"items": {"type": "string"},
"items": {"anyOf": [{"type": "string"}, {"type": "integer"}]},
},
"msg": {"title": "Message", "type": "string"},
"type": {"title": "Error Type", "type": "string"},

View File

@@ -71,7 +71,7 @@ openapi_schema = {
"loc": {
"title": "Location",
"type": "array",
"items": {"type": "string"},
"items": {"anyOf": [{"type": "string"}, {"type": "integer"}]},
},
"msg": {"title": "Message", "type": "string"},
"type": {"title": "Error Type", "type": "string"},

View File

@@ -71,7 +71,7 @@ openapi_schema = {
"loc": {
"title": "Location",
"type": "array",
"items": {"type": "string"},
"items": {"anyOf": [{"type": "string"}, {"type": "integer"}]},
},
"msg": {"title": "Message", "type": "string"},
"type": {"title": "Error Type", "type": "string"},

View File

@@ -49,7 +49,7 @@ openapi_schema = {
"loc": {
"title": "Location",
"type": "array",
"items": {"type": "string"},
"items": {"anyOf": [{"type": "string"}, {"type": "integer"}]},
},
"msg": {"title": "Message", "type": "string"},
"type": {"title": "Error Type", "type": "string"},

View File

@@ -54,7 +54,7 @@ openapi_schema = {
"loc": {
"title": "Location",
"type": "array",
"items": {"type": "string"},
"items": {"anyOf": [{"type": "string"}, {"type": "integer"}]},
},
"msg": {"title": "Message", "type": "string"},
"type": {"title": "Error Type", "type": "string"},
@@ -138,7 +138,7 @@ openapi_schema2 = {
"loc": {
"title": "Location",
"type": "array",
"items": {"type": "string"},
"items": {"anyOf": [{"type": "string"}, {"type": "integer"}]},
},
"msg": {"title": "Message", "type": "string"},
"type": {"title": "Error Type", "type": "string"},

View File

@@ -56,7 +56,7 @@ openapi_schema = {
"loc": {
"title": "Location",
"type": "array",
"items": {"type": "string"},
"items": {"anyOf": [{"type": "string"}, {"type": "integer"}]},
},
"msg": {"title": "Message", "type": "string"},
"type": {"title": "Error Type", "type": "string"},

View File

@@ -68,7 +68,7 @@ openapi_schema = {
"loc": {
"title": "Location",
"type": "array",
"items": {"type": "string"},
"items": {"anyOf": [{"type": "string"}, {"type": "integer"}]},
},
"msg": {"title": "Message", "type": "string"},
"type": {"title": "Error Type", "type": "string"},

View File

@@ -66,7 +66,7 @@ openapi_schema = {
"loc": {
"title": "Location",
"type": "array",
"items": {"type": "string"},
"items": {"anyOf": [{"type": "string"}, {"type": "integer"}]},
},
"msg": {"title": "Message", "type": "string"},
"type": {"title": "Error Type", "type": "string"},

View File

@@ -59,7 +59,7 @@ openapi_schema = {
"loc": {
"title": "Location",
"type": "array",
"items": {"type": "string"},
"items": {"anyOf": [{"type": "string"}, {"type": "integer"}]},
},
"msg": {"title": "Message", "type": "string"},
"type": {"title": "Error Type", "type": "string"},

Some files were not shown because too many files have changed in this diff Show More