mirror of
https://github.com/fastapi/fastapi.git
synced 2025-12-25 15:18:36 -05:00
Compare commits
32 Commits
refactor-i
...
0.76.0
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
9090c771ee | ||
|
|
8df8b037f2 | ||
|
|
792285a047 | ||
|
|
66f6344820 | ||
|
|
b44e85ca8a | ||
|
|
33d61430cf | ||
|
|
146f57b8f7 | ||
|
|
1920c3dd16 | ||
|
|
07b12c8e41 | ||
|
|
4642d5bb86 | ||
|
|
0fd99ec337 | ||
|
|
7c8383c96b | ||
|
|
2b54432a9c | ||
|
|
acd2287b57 | ||
|
|
1d106bd959 | ||
|
|
77fc14eb69 | ||
|
|
41d75b6d1c | ||
|
|
ddd9da3db4 | ||
|
|
197c1d6dd7 | ||
|
|
d9e7a541fd | ||
|
|
c449ae5c74 | ||
|
|
1d8d81a6d5 | ||
|
|
d81c908132 | ||
|
|
cb4da93643 | ||
|
|
3cbfae16cf | ||
|
|
0def8382b8 | ||
|
|
02fae6a38e | ||
|
|
75af472029 | ||
|
|
e1135eddb5 | ||
|
|
acf8a91c25 | ||
|
|
c4f361c0c4 | ||
|
|
cc57bfcf60 |
4
.github/workflows/test.yml
vendored
4
.github/workflows/test.yml
vendored
@@ -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
|
||||
|
||||
@@ -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 -->
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -2,10 +2,11 @@ logins:
|
||||
- jina-ai
|
||||
- deta
|
||||
- investsuite
|
||||
- vimsoHQ
|
||||
- mikeckennedy
|
||||
- koaning
|
||||
- deepset-ai
|
||||
- cryptapi
|
||||
- DropbaseHQ
|
||||
- Striveworks
|
||||
- xoflare
|
||||
- InesIvanova
|
||||
- DropbaseHQ
|
||||
- VincentParedes
|
||||
|
||||
22
docs/en/docs/img/sponsors/budget-insight.svg
Normal file
22
docs/en/docs/img/sponsors/budget-insight.svg
Normal file
File diff suppressed because one or more lines are too long
|
After Width: | Height: | Size: 36 KiB |
BIN
docs/en/docs/img/sponsors/exoflare.png
Normal file
BIN
docs/en/docs/img/sponsors/exoflare.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 10 KiB |
BIN
docs/en/docs/img/sponsors/fastapi-course-bundle-banner.png
Normal file
BIN
docs/en/docs/img/sponsors/fastapi-course-bundle-banner.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 16 KiB |
BIN
docs/en/docs/img/sponsors/ines-course.jpg
Normal file
BIN
docs/en/docs/img/sponsors/ines-course.jpg
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 12 KiB |
@@ -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
|
||||
|
||||
@@ -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 %}
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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:
|
||||
|
||||
@@ -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:
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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()
|
||||
|
||||
@@ -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',
|
||||
]
|
||||
|
||||
@@ -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"},
|
||||
|
||||
@@ -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"},
|
||||
|
||||
@@ -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"},
|
||||
|
||||
@@ -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"},
|
||||
|
||||
@@ -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"
|
||||
|
||||
@@ -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"},
|
||||
|
||||
@@ -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"},
|
||||
|
||||
@@ -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"},
|
||||
|
||||
@@ -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"},
|
||||
|
||||
@@ -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"},
|
||||
|
||||
@@ -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"},
|
||||
|
||||
@@ -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"},
|
||||
|
||||
@@ -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"},
|
||||
|
||||
@@ -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"},
|
||||
|
||||
@@ -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"},
|
||||
|
||||
@@ -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"},
|
||||
|
||||
@@ -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"},
|
||||
|
||||
@@ -36,7 +36,7 @@ schema = {
|
||||
"ValidationError": {
|
||||
"properties": {
|
||||
"loc": {
|
||||
"items": {"type": "string"},
|
||||
"items": {"anyOf": [{"type": "string"}, {"type": "integer"}]},
|
||||
"title": "Location",
|
||||
"type": "array",
|
||||
},
|
||||
|
||||
@@ -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"},
|
||||
|
||||
@@ -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"},
|
||||
|
||||
@@ -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"},
|
||||
|
||||
@@ -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"},
|
||||
|
||||
@@ -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"},
|
||||
|
||||
@@ -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"},
|
||||
|
||||
@@ -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"},
|
||||
|
||||
@@ -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"},
|
||||
|
||||
@@ -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"},
|
||||
|
||||
@@ -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"},
|
||||
|
||||
@@ -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"},
|
||||
|
||||
@@ -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"},
|
||||
|
||||
@@ -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"},
|
||||
|
||||
@@ -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"},
|
||||
|
||||
@@ -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"},
|
||||
|
||||
@@ -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"},
|
||||
|
||||
@@ -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"},
|
||||
|
||||
@@ -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"},
|
||||
|
||||
@@ -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"},
|
||||
|
||||
@@ -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"},
|
||||
|
||||
@@ -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"},
|
||||
|
||||
@@ -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"},
|
||||
|
||||
@@ -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"},
|
||||
|
||||
@@ -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"},
|
||||
|
||||
@@ -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"},
|
||||
|
||||
@@ -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"},
|
||||
|
||||
@@ -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"},
|
||||
|
||||
@@ -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"},
|
||||
|
||||
@@ -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"},
|
||||
|
||||
@@ -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"},
|
||||
|
||||
@@ -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"},
|
||||
|
||||
@@ -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"},
|
||||
|
||||
@@ -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"},
|
||||
|
||||
@@ -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"},
|
||||
|
||||
@@ -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"},
|
||||
|
||||
@@ -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"},
|
||||
|
||||
@@ -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"},
|
||||
|
||||
@@ -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"},
|
||||
|
||||
@@ -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"},
|
||||
|
||||
@@ -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"},
|
||||
|
||||
@@ -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"},
|
||||
|
||||
@@ -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"},
|
||||
|
||||
@@ -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"},
|
||||
|
||||
@@ -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"},
|
||||
|
||||
@@ -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"},
|
||||
|
||||
@@ -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"},
|
||||
|
||||
@@ -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"},
|
||||
|
||||
@@ -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"},
|
||||
|
||||
@@ -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"},
|
||||
|
||||
@@ -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"},
|
||||
|
||||
@@ -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"},
|
||||
|
||||
@@ -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"},
|
||||
|
||||
@@ -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"},
|
||||
|
||||
@@ -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"},
|
||||
|
||||
@@ -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"},
|
||||
|
||||
@@ -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"},
|
||||
|
||||
@@ -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"},
|
||||
|
||||
@@ -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"},
|
||||
|
||||
@@ -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"},
|
||||
|
||||
@@ -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"},
|
||||
|
||||
@@ -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
Reference in New Issue
Block a user