From 076bdea6716a5fbfc84d2227066dea6bd91ffb94 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebasti=C3=A1n=20Ram=C3=ADrez?= Date: Fri, 28 Jul 2023 14:15:29 +0200 Subject: [PATCH 01/39] =?UTF-8?q?=F0=9F=8C=90=20Remove=20Vietnamese=20note?= =?UTF-8?q?=20about=20missing=20translation=20(#9957)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docs/en/mkdocs.yml | 6 ++++++ docs/uk/mkdocs.yml | 1 + docs/vi/docs/index.md | 4 ---- 3 files changed, 7 insertions(+), 4 deletions(-) create mode 100644 docs/uk/mkdocs.yml diff --git a/docs/en/mkdocs.yml b/docs/en/mkdocs.yml index 030bbe5d3eba1..a1861318589c9 100644 --- a/docs/en/mkdocs.yml +++ b/docs/en/mkdocs.yml @@ -59,6 +59,8 @@ nav: - pt: /pt/ - ru: /ru/ - tr: /tr/ + - uk: /uk/ + - vi: /vi/ - zh: /zh/ - features.md - fastapi-people.md @@ -236,6 +238,10 @@ extra: name: ru - русский язык - link: /tr/ name: tr - Türkçe + - link: /uk/ + name: uk + - link: /vi/ + name: vi - link: /zh/ name: zh - 汉语 extra_css: diff --git a/docs/uk/mkdocs.yml b/docs/uk/mkdocs.yml new file mode 100644 index 0000000000000..de18856f445aa --- /dev/null +++ b/docs/uk/mkdocs.yml @@ -0,0 +1 @@ +INHERIT: ../en/mkdocs.yml diff --git a/docs/vi/docs/index.md b/docs/vi/docs/index.md index ba5d681619c03..0e773a0110334 100644 --- a/docs/vi/docs/index.md +++ b/docs/vi/docs/index.md @@ -1,7 +1,3 @@ - -{!../../../docs/missing-translation.md!} - -

FastAPI

From cd6d75e451cd998cb511c20a72055110035b63ed Mon Sep 17 00:00:00 2001 From: github-actions Date: Fri, 28 Jul 2023 12:16:16 +0000 Subject: [PATCH 02/39] =?UTF-8?q?=F0=9F=93=9D=20Update=20release=20notes?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docs/en/docs/release-notes.md | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/en/docs/release-notes.md b/docs/en/docs/release-notes.md index b56941ec7843b..4addb83cc2816 100644 --- a/docs/en/docs/release-notes.md +++ b/docs/en/docs/release-notes.md @@ -2,6 +2,7 @@ ## Latest Changes +* 🌐 Remove Vietnamese note about missing translation. PR [#9957](https://github.com/tiangolo/fastapi/pull/9957) by [@tiangolo](https://github.com/tiangolo). ## 0.100.1 From a0b987224aa0f80689568b3d38e211b23a7d7e72 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebasti=C3=A1n=20Ram=C3=ADrez?= Date: Mon, 31 Jul 2023 21:54:07 +0200 Subject: [PATCH 03/39] =?UTF-8?q?=F0=9F=91=B7=20Update=20CI=20debug=20mode?= =?UTF-8?q?=20with=20Tmate=20(#9977)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .github/workflows/latest-changes.yml | 6 +++--- .github/workflows/notify-translations.yml | 11 ++++++++++- .github/workflows/people.yml | 4 ++-- 3 files changed, 15 insertions(+), 6 deletions(-) diff --git a/.github/workflows/latest-changes.yml b/.github/workflows/latest-changes.yml index 1f7ac7b28687d..0461f3dd3eb9f 100644 --- a/.github/workflows/latest-changes.yml +++ b/.github/workflows/latest-changes.yml @@ -14,7 +14,7 @@ on: debug_enabled: description: 'Run the build with tmate debugging enabled (https://github.com/marketplace/actions/debugging-with-tmate)' required: false - default: false + default: 'false' jobs: latest-changes: @@ -22,12 +22,12 @@ jobs: steps: - uses: actions/checkout@v3 with: - # To allow latest-changes to commit to master + # To allow latest-changes to commit to the main branch token: ${{ secrets.FASTAPI_LATEST_CHANGES }} # Allow debugging with tmate - name: Setup tmate session uses: mxschmitt/action-tmate@v3 - if: ${{ github.event_name == 'workflow_dispatch' && github.event.inputs.debug_enabled }} + if: ${{ github.event_name == 'workflow_dispatch' && github.event.inputs.debug_enabled == 'true' }} with: limit-access-to-actor: true - uses: docker://tiangolo/latest-changes:0.0.3 diff --git a/.github/workflows/notify-translations.yml b/.github/workflows/notify-translations.yml index 0926486e9b0db..cd7affbc395f9 100644 --- a/.github/workflows/notify-translations.yml +++ b/.github/workflows/notify-translations.yml @@ -5,6 +5,15 @@ on: types: - labeled - closed + workflow_dispatch: + inputs: + number: + description: PR number + required: true + debug_enabled: + description: 'Run the build with tmate debugging enabled (https://github.com/marketplace/actions/debugging-with-tmate)' + required: false + default: 'false' jobs: notify-translations: @@ -14,7 +23,7 @@ jobs: # Allow debugging with tmate - name: Setup tmate session uses: mxschmitt/action-tmate@v3 - if: ${{ github.event_name == 'workflow_dispatch' && github.event.inputs.debug_enabled }} + if: ${{ github.event_name == 'workflow_dispatch' && github.event.inputs.debug_enabled == 'true' }} with: limit-access-to-actor: true - uses: ./.github/actions/notify-translations diff --git a/.github/workflows/people.yml b/.github/workflows/people.yml index dac526a6c7f52..aa7f34464e2c9 100644 --- a/.github/workflows/people.yml +++ b/.github/workflows/people.yml @@ -8,7 +8,7 @@ on: debug_enabled: description: 'Run the build with tmate debugging enabled (https://github.com/marketplace/actions/debugging-with-tmate)' required: false - default: false + default: 'false' jobs: fastapi-people: @@ -22,7 +22,7 @@ jobs: # Allow debugging with tmate - name: Setup tmate session uses: mxschmitt/action-tmate@v3 - if: ${{ github.event_name == 'workflow_dispatch' && github.event.inputs.debug_enabled }} + if: ${{ github.event_name == 'workflow_dispatch' && github.event.inputs.debug_enabled == 'true' }} with: limit-access-to-actor: true - uses: ./.github/actions/people From d38e86ef203f5a1c710452737b32ad63466f23d7 Mon Sep 17 00:00:00 2001 From: github-actions Date: Mon, 31 Jul 2023 19:54:46 +0000 Subject: [PATCH 04/39] =?UTF-8?q?=F0=9F=93=9D=20Update=20release=20notes?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docs/en/docs/release-notes.md | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/en/docs/release-notes.md b/docs/en/docs/release-notes.md index 4addb83cc2816..14ce4137411c0 100644 --- a/docs/en/docs/release-notes.md +++ b/docs/en/docs/release-notes.md @@ -2,6 +2,7 @@ ## Latest Changes +* 👷 Update CI debug mode with Tmate. PR [#9977](https://github.com/tiangolo/fastapi/pull/9977) by [@tiangolo](https://github.com/tiangolo). * 🌐 Remove Vietnamese note about missing translation. PR [#9957](https://github.com/tiangolo/fastapi/pull/9957) by [@tiangolo](https://github.com/tiangolo). ## 0.100.1 From 1da0a7afbd53c66eefddc2455501159bf50f55ef Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebasti=C3=A1n=20Ram=C3=ADrez?= Date: Mon, 31 Jul 2023 23:49:19 +0200 Subject: [PATCH 05/39] =?UTF-8?q?=F0=9F=94=A7=20Update=20sponsor=20Fern=20?= =?UTF-8?q?(#9979)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 2 +- docs/en/data/sponsors.yml | 2 +- docs/en/docs/advanced/generate-clients.md | 5 +++++ docs/en/docs/alternatives.md | 2 ++ docs/en/docs/img/sponsors/fern-banner.svg | 1 + docs/en/docs/img/sponsors/fern.svg | 1 + docs/en/overrides/main.html | 2 +- 7 files changed, 12 insertions(+), 3 deletions(-) create mode 100644 docs/en/docs/img/sponsors/fern-banner.svg create mode 100644 docs/en/docs/img/sponsors/fern.svg diff --git a/README.md b/README.md index f0e76c4b6c317..50f80ded67f0b 100644 --- a/README.md +++ b/README.md @@ -48,7 +48,7 @@ The key features are: - + diff --git a/docs/en/data/sponsors.yml b/docs/en/data/sponsors.yml index 33d57c87383fa..53cdb9bad1588 100644 --- a/docs/en/data/sponsors.yml +++ b/docs/en/data/sponsors.yml @@ -7,7 +7,7 @@ gold: img: https://fastapi.tiangolo.com/img/sponsors/platform-sh.png - url: https://www.buildwithfern.com/?utm_source=tiangolo&utm_medium=website&utm_campaign=main-badge title: Fern | SDKs and API docs - img: https://fastapi.tiangolo.com/img/sponsors/fern.png + img: https://fastapi.tiangolo.com/img/sponsors/fern.svg silver: - url: https://www.deta.sh/?ref=fastapi title: The launchpad for all your (team's) ideas diff --git a/docs/en/docs/advanced/generate-clients.md b/docs/en/docs/advanced/generate-clients.md index f62c0b57c1818..3fed48b0bcf93 100644 --- a/docs/en/docs/advanced/generate-clients.md +++ b/docs/en/docs/advanced/generate-clients.md @@ -12,6 +12,11 @@ A common tool is openapi-typescript-codegen. +Another option you could consider for several languages is Fern. + +!!! info + Fern is also a FastAPI sponsor. 😎🎉 + ## Generate a TypeScript Frontend Client Let's start with a simple FastAPI application: diff --git a/docs/en/docs/alternatives.md b/docs/en/docs/alternatives.md index 0f074ccf32dcc..a777ddb98e0cd 100644 --- a/docs/en/docs/alternatives.md +++ b/docs/en/docs/alternatives.md @@ -119,6 +119,8 @@ That's why when talking about version 2.0 it's common to say "Swagger", and for These two were chosen for being fairly popular and stable, but doing a quick search, you could find dozens of additional alternative user interfaces for OpenAPI (that you can use with **FastAPI**). + For example, you could try Fern which is also a FastAPI sponsor. 😎🎉 + ### Flask REST frameworks There are several Flask REST frameworks, but after investing the time and work into investigating them, I found that many are discontinued or abandoned, with several standing issues that made them unfit. diff --git a/docs/en/docs/img/sponsors/fern-banner.svg b/docs/en/docs/img/sponsors/fern-banner.svg new file mode 100644 index 0000000000000..bb3a389f31a19 --- /dev/null +++ b/docs/en/docs/img/sponsors/fern-banner.svg @@ -0,0 +1 @@ + diff --git a/docs/en/docs/img/sponsors/fern.svg b/docs/en/docs/img/sponsors/fern.svg new file mode 100644 index 0000000000000..ad3842fe03eae --- /dev/null +++ b/docs/en/docs/img/sponsors/fern.svg @@ -0,0 +1 @@ + diff --git a/docs/en/overrides/main.html b/docs/en/overrides/main.html index fcd1704b9f94a..7e6c0f763417e 100644 --- a/docs/en/overrides/main.html +++ b/docs/en/overrides/main.html @@ -37,7 +37,7 @@ From 74de15d0df975f7da4b29e9ad49142d7da172b6c Mon Sep 17 00:00:00 2001 From: github-actions Date: Mon, 31 Jul 2023 21:49:56 +0000 Subject: [PATCH 06/39] =?UTF-8?q?=F0=9F=93=9D=20Update=20release=20notes?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docs/en/docs/release-notes.md | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/en/docs/release-notes.md b/docs/en/docs/release-notes.md index 14ce4137411c0..ead095d8d6b2c 100644 --- a/docs/en/docs/release-notes.md +++ b/docs/en/docs/release-notes.md @@ -2,6 +2,7 @@ ## Latest Changes +* 🔧 Update sponsor Fern. PR [#9979](https://github.com/tiangolo/fastapi/pull/9979) by [@tiangolo](https://github.com/tiangolo). * 👷 Update CI debug mode with Tmate. PR [#9977](https://github.com/tiangolo/fastapi/pull/9977) by [@tiangolo](https://github.com/tiangolo). * 🌐 Remove Vietnamese note about missing translation. PR [#9957](https://github.com/tiangolo/fastapi/pull/9957) by [@tiangolo](https://github.com/tiangolo). From d2169fbad9eb1b2537292996ce8d26e7584e9e2b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebasti=C3=A1n=20Ram=C3=ADrez?= Date: Tue, 1 Aug 2023 11:19:44 +0200 Subject: [PATCH 07/39] =?UTF-8?q?=F0=9F=91=B7=20Deploy=20docs=20to=20Cloud?= =?UTF-8?q?flare=20Pages=20(#9978)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .github/workflows/deploy-docs.yml | 23 +++++++++++------------ 1 file changed, 11 insertions(+), 12 deletions(-) diff --git a/.github/workflows/deploy-docs.yml b/.github/workflows/deploy-docs.yml index 312d835af8724..dcd6d7107b325 100644 --- a/.github/workflows/deploy-docs.yml +++ b/.github/workflows/deploy-docs.yml @@ -29,21 +29,20 @@ jobs: run_id: ${{ github.event.workflow_run.id }} name: docs-site path: ./site/ - - name: Deploy to Netlify + - name: Deploy to Cloudflare Pages if: steps.download.outputs.found_artifact == 'true' - id: netlify - uses: nwtgck/actions-netlify@v2.0.0 + id: deploy + uses: cloudflare/pages-action@v1 with: - publish-dir: './site' - production-deploy: ${{ github.event.workflow_run.head_repository.full_name == github.repository && github.event.workflow_run.head_branch == 'master' }} - github-token: ${{ secrets.FASTAPI_PREVIEW_DOCS_NETLIFY }} - enable-commit-comment: false - env: - NETLIFY_AUTH_TOKEN: ${{ secrets.NETLIFY_AUTH_TOKEN }} - NETLIFY_SITE_ID: ${{ secrets.NETLIFY_SITE_ID }} + apiToken: ${{ secrets.CLOUDFLARE_API_TOKEN }} + accountId: ${{ secrets.CLOUDFLARE_ACCOUNT_ID }} + projectName: fastapitiangolo + directory: './site' + gitHubToken: ${{ secrets.GITHUB_TOKEN }} + branch: ${{ ( github.event.workflow_run.head_repository.full_name == github.repository && github.event.workflow_run.head_branch == 'master' && 'main' ) || ( github.event.workflow_run.head_sha ) }} - name: Comment Deploy - if: steps.netlify.outputs.deploy-url != '' + if: steps.deploy.outputs.url != '' uses: ./.github/actions/comment-docs-preview-in-pr with: token: ${{ secrets.FASTAPI_PREVIEW_DOCS_COMMENT_DEPLOY }} - deploy_url: "${{ steps.netlify.outputs.deploy-url }}" + deploy_url: "${{ steps.deploy.outputs.url }}" From 6c8c3b788bb7c3338f1105493833c9815ba243a4 Mon Sep 17 00:00:00 2001 From: github-actions Date: Tue, 1 Aug 2023 09:20:23 +0000 Subject: [PATCH 08/39] =?UTF-8?q?=F0=9F=93=9D=20Update=20release=20notes?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docs/en/docs/release-notes.md | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/en/docs/release-notes.md b/docs/en/docs/release-notes.md index ead095d8d6b2c..2aed9859a279e 100644 --- a/docs/en/docs/release-notes.md +++ b/docs/en/docs/release-notes.md @@ -2,6 +2,7 @@ ## Latest Changes +* 👷 Deploy docs to Cloudflare Pages. PR [#9978](https://github.com/tiangolo/fastapi/pull/9978) by [@tiangolo](https://github.com/tiangolo). * 🔧 Update sponsor Fern. PR [#9979](https://github.com/tiangolo/fastapi/pull/9979) by [@tiangolo](https://github.com/tiangolo). * 👷 Update CI debug mode with Tmate. PR [#9977](https://github.com/tiangolo/fastapi/pull/9977) by [@tiangolo](https://github.com/tiangolo). * 🌐 Remove Vietnamese note about missing translation. PR [#9957](https://github.com/tiangolo/fastapi/pull/9957) by [@tiangolo](https://github.com/tiangolo). From c2a33f1087b5843054de839b47e7fe7200a62504 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebasti=C3=A1n=20Ram=C3=ADrez?= Date: Tue, 1 Aug 2023 23:39:22 +0200 Subject: [PATCH 09/39] =?UTF-8?q?=F0=9F=8D=B1=20Update=20sponsors,=20Fern?= =?UTF-8?q?=20badge=20(#9982)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docs/en/docs/img/sponsors/fern-banner.svg | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/en/docs/img/sponsors/fern-banner.svg b/docs/en/docs/img/sponsors/fern-banner.svg index bb3a389f31a19..e05ccc3a47aec 100644 --- a/docs/en/docs/img/sponsors/fern-banner.svg +++ b/docs/en/docs/img/sponsors/fern-banner.svg @@ -1 +1 @@ - + From 01f91fdb57e55b4540363ef5749480dc3f3e8bf6 Mon Sep 17 00:00:00 2001 From: github-actions Date: Tue, 1 Aug 2023 21:40:00 +0000 Subject: [PATCH 10/39] =?UTF-8?q?=F0=9F=93=9D=20Update=20release=20notes?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docs/en/docs/release-notes.md | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/en/docs/release-notes.md b/docs/en/docs/release-notes.md index 2aed9859a279e..895926cabc58a 100644 --- a/docs/en/docs/release-notes.md +++ b/docs/en/docs/release-notes.md @@ -2,6 +2,7 @@ ## Latest Changes +* 🍱 Update sponsors, Fern badge. PR [#9982](https://github.com/tiangolo/fastapi/pull/9982) by [@tiangolo](https://github.com/tiangolo). * 👷 Deploy docs to Cloudflare Pages. PR [#9978](https://github.com/tiangolo/fastapi/pull/9978) by [@tiangolo](https://github.com/tiangolo). * 🔧 Update sponsor Fern. PR [#9979](https://github.com/tiangolo/fastapi/pull/9979) by [@tiangolo](https://github.com/tiangolo). * 👷 Update CI debug mode with Tmate. PR [#9977](https://github.com/tiangolo/fastapi/pull/9977) by [@tiangolo](https://github.com/tiangolo). From 88d96799b15e530c068f749626595c739bce3fcf Mon Sep 17 00:00:00 2001 From: Nikita Date: Wed, 2 Aug 2023 18:14:19 +0300 Subject: [PATCH 11/39] =?UTF-8?q?=F0=9F=8C=90=20Add=20Russian=20translatio?= =?UTF-8?q?n=20for=20`docs/ru/docs/tutorial/security/index.md`=20(#9963)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: dedkot Co-authored-by: Vladislav Kramorenko <85196001+Xewus@users.noreply.github.com> --- docs/ru/docs/tutorial/security/index.md | 101 ++++++++++++++++++++++++ 1 file changed, 101 insertions(+) create mode 100644 docs/ru/docs/tutorial/security/index.md diff --git a/docs/ru/docs/tutorial/security/index.md b/docs/ru/docs/tutorial/security/index.md new file mode 100644 index 0000000000000..d5fe4e76f8940 --- /dev/null +++ b/docs/ru/docs/tutorial/security/index.md @@ -0,0 +1,101 @@ +# Настройка авторизации + +Существует множество способов обеспечения безопасности, аутентификации и авторизации. + +Обычно эта тема является достаточно сложной и трудной. + +Во многих фреймворках и системах только работа с определением доступов к приложению и аутентификацией требует значительных затрат усилий и написания множества кода (во многих случаях его объём может составлять более 50% от всего написанного кода). + +**FastAPI** предоставляет несколько инструментов, которые помогут вам настроить **Авторизацию** легко, быстро, стандартным способом, без необходимости изучать все её тонкости. + +Но сначала давайте рассмотрим некоторые небольшие концепции. + +## Куда-то торопишься? + +Если вам не нужна информация о каких-либо из следующих терминов и вам просто нужно добавить защиту с аутентификацией на основе логина и пароля *прямо сейчас*, переходите к следующим главам. + +## OAuth2 + +OAuth2 - это протокол, который определяет несколько способов обработки аутентификации и авторизации. + +Он довольно обширен и охватывает несколько сложных вариантов использования. + +OAuth2 включает в себя способы аутентификации с использованием "третьей стороны". + +Это то, что используют под собой все кнопки "вход с помощью Facebook, Google, Twitter, GitHub" на страницах авторизации. + +### OAuth 1 + +Ранее использовался протокол OAuth 1, который сильно отличается от OAuth2 и является более сложным, поскольку он включал прямые описания того, как шифровать сообщение. + +В настоящее время он не очень популярен и не используется. + +OAuth2 не указывает, как шифровать сообщение, он ожидает, что ваше приложение будет обслуживаться по протоколу HTTPS. + +!!! tip "Подсказка" + В разделе **Развертывание** вы увидите [как настроить протокол HTTPS бесплатно, используя Traefik и Let's Encrypt.](https://fastapi.tiangolo.com/ru/deployment/https/) + + +## OpenID Connect + +OpenID Connect - это еще один протокол, основанный на **OAuth2**. + +Он просто расширяет OAuth2, уточняя некоторые вещи, не имеющие однозначного определения в OAuth2, в попытке сделать его более совместимым. + +Например, для входа в Google используется OpenID Connect (который под собой использует OAuth2). + +Но вход в Facebook не поддерживает OpenID Connect. У него есть собственная вариация OAuth2. + +### OpenID (не "OpenID Connect") + +Также ранее использовался стандарт "OpenID", который пытался решить ту же проблему, что и **OpenID Connect**, но не был основан на OAuth2. + +Таким образом, это была полноценная дополнительная система. + +В настоящее время не очень популярен и не используется. + +## OpenAPI + +OpenAPI (ранее известный как Swagger) - это открытая спецификация для создания API (в настоящее время является частью Linux Foundation). + +**FastAPI** основан на **OpenAPI**. + +Это то, что делает возможным наличие множества автоматических интерактивных интерфейсов документирования, сгенерированного кода и т.д. + +В OpenAPI есть способ использовать несколько "схем" безопасности. + +Таким образом, вы можете воспользоваться преимуществами Всех этих стандартных инструментов, включая интерактивные системы документирования. + +OpenAPI может использовать следующие схемы авторизации: + +* `apiKey`: уникальный идентификатор для приложения, который может быть получен из: + * Параметров запроса. + * Заголовка. + * Cookies. +* `http`: стандартные системы аутентификации по протоколу HTTP, включая: + * `bearer`: заголовок `Authorization` со значением `Bearer {уникальный токен}`. Это унаследовано от OAuth2. + * Базовая аутентификация по протоколу HTTP. + * HTTP Digest и т.д. +* `oauth2`: все способы обеспечения безопасности OAuth2 называемые "потоки" (англ. "flows"). + * Некоторые из этих "потоков" подходят для реализации аутентификации через сторонний сервис использующий OAuth 2.0 (например, Google, Facebook, Twitter, GitHub и т.д.): + * `implicit` + * `clientCredentials` + * `authorizationCode` + * Но есть один конкретный "поток", который может быть идеально использован для обработки аутентификации непосредственно в том же приложении: + * `password`: в некоторых следующих главах будут рассмотрены примеры этого. +* `openIdConnect`: способ определить, как автоматически обнаруживать данные аутентификации OAuth2. + * Это автоматическое обнаружение определено в спецификации OpenID Connect. + + +!!! tip "Подсказка" + Интеграция сторонних сервисов для аутентификации/авторизации таких как Google, Facebook, Twitter, GitHub и т.д. осуществляется достаточно легко. + + Самой сложной проблемой является создание такого провайдера аутентификации/авторизации, но **FastAPI** предоставляет вам инструменты, позволяющие легко это сделать, выполняя при этом всю тяжелую работу за вас. + +## Преимущества **FastAPI** + +Fast API предоставляет несколько инструментов для каждой из этих схем безопасности в модуле `fastapi.security`, которые упрощают использование этих механизмов безопасности. + +В следующих главах вы увидите, как обезопасить свой API, используя инструменты, предоставляемые **FastAPI**. + +И вы также увидите, как он автоматически интегрируется в систему интерактивной документации. From 2d8a776836e1363e021b2a1233a72584f57b5d7a Mon Sep 17 00:00:00 2001 From: github-actions Date: Wed, 2 Aug 2023 15:15:10 +0000 Subject: [PATCH 12/39] =?UTF-8?q?=F0=9F=93=9D=20Update=20release=20notes?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docs/en/docs/release-notes.md | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/en/docs/release-notes.md b/docs/en/docs/release-notes.md index 895926cabc58a..fde398be5d914 100644 --- a/docs/en/docs/release-notes.md +++ b/docs/en/docs/release-notes.md @@ -2,6 +2,7 @@ ## Latest Changes +* 🌐 Add Russian translation for `docs/ru/docs/tutorial/security/index.md`. PR [#9963](https://github.com/tiangolo/fastapi/pull/9963) by [@eVery1337](https://github.com/eVery1337). * 🍱 Update sponsors, Fern badge. PR [#9982](https://github.com/tiangolo/fastapi/pull/9982) by [@tiangolo](https://github.com/tiangolo). * 👷 Deploy docs to Cloudflare Pages. PR [#9978](https://github.com/tiangolo/fastapi/pull/9978) by [@tiangolo](https://github.com/tiangolo). * 🔧 Update sponsor Fern. PR [#9979](https://github.com/tiangolo/fastapi/pull/9979) by [@tiangolo](https://github.com/tiangolo). From 37818f553ddb21b7adaaf16d18b95f9710065ad4 Mon Sep 17 00:00:00 2001 From: Irfanuddin Shafi Ahmed Date: Wed, 2 Aug 2023 20:58:34 +0530 Subject: [PATCH 13/39] =?UTF-8?q?=E2=9C=85=20Fix=20test=20error=20in=20Win?= =?UTF-8?q?dows=20for=20`jsonable=5Fencoder`=20(#9840)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Marcelo Trylesinski --- tests/test_jsonable_encoder.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/tests/test_jsonable_encoder.py b/tests/test_jsonable_encoder.py index ff3033ecdf427..7c8338ff376d0 100644 --- a/tests/test_jsonable_encoder.py +++ b/tests/test_jsonable_encoder.py @@ -247,8 +247,9 @@ class ModelWithPath(BaseModel): class Config: arbitrary_types_allowed = True - obj = ModelWithPath(path=PurePath("/foo", "bar")) - assert jsonable_encoder(obj) == {"path": "/foo/bar"} + test_path = PurePath("/foo", "bar") + obj = ModelWithPath(path=test_path) + assert jsonable_encoder(obj) == {"path": str(test_path)} def test_encode_model_with_pure_posix_path(): From b473cdd88d878b6657f0c80edb384b71971841a8 Mon Sep 17 00:00:00 2001 From: github-actions Date: Wed, 2 Aug 2023 15:29:13 +0000 Subject: [PATCH 14/39] =?UTF-8?q?=F0=9F=93=9D=20Update=20release=20notes?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docs/en/docs/release-notes.md | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/en/docs/release-notes.md b/docs/en/docs/release-notes.md index fde398be5d914..5065295e670c6 100644 --- a/docs/en/docs/release-notes.md +++ b/docs/en/docs/release-notes.md @@ -2,6 +2,7 @@ ## Latest Changes +* ✅ Fix test error in Windows for `jsonable_encoder`. PR [#9840](https://github.com/tiangolo/fastapi/pull/9840) by [@iudeen](https://github.com/iudeen). * 🌐 Add Russian translation for `docs/ru/docs/tutorial/security/index.md`. PR [#9963](https://github.com/tiangolo/fastapi/pull/9963) by [@eVery1337](https://github.com/eVery1337). * 🍱 Update sponsors, Fern badge. PR [#9982](https://github.com/tiangolo/fastapi/pull/9982) by [@tiangolo](https://github.com/tiangolo). * 👷 Deploy docs to Cloudflare Pages. PR [#9978](https://github.com/tiangolo/fastapi/pull/9978) by [@tiangolo](https://github.com/tiangolo). From 1e6bfa1f3931b841f3c2e173a5e673e854130a8d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebasti=C3=A1n=20Ram=C3=ADrez?= Date: Wed, 2 Aug 2023 17:57:20 +0200 Subject: [PATCH 15/39] =?UTF-8?q?=E2=99=BB=EF=B8=8F=20Update=20FastAPI=20P?= =?UTF-8?q?eople=20logic=20with=20new=20Pydantic=20(#9985)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .github/actions/people/Dockerfile | 2 +- .github/actions/people/app/main.py | 14 ++++++++------ 2 files changed, 9 insertions(+), 7 deletions(-) diff --git a/.github/actions/people/Dockerfile b/.github/actions/people/Dockerfile index fa4197e6a88d1..6d65f1c2bfce0 100644 --- a/.github/actions/people/Dockerfile +++ b/.github/actions/people/Dockerfile @@ -1,6 +1,6 @@ FROM python:3.7 -RUN pip install httpx PyGithub "pydantic==1.5.1" "pyyaml>=5.3.1,<6.0.0" +RUN pip install httpx PyGithub "pydantic==2.0.2" "pyyaml>=5.3.1,<6.0.0" COPY ./app /app diff --git a/.github/actions/people/app/main.py b/.github/actions/people/app/main.py index b11e3456db58a..cb6b229e8e67e 100644 --- a/.github/actions/people/app/main.py +++ b/.github/actions/people/app/main.py @@ -9,7 +9,8 @@ import httpx import yaml from github import Github -from pydantic import BaseModel, BaseSettings, SecretStr +from pydantic import BaseModel, SecretStr +from pydantic_settings import BaseSettings github_graphql_url = "https://api.github.com/graphql" questions_category_id = "MDE4OkRpc2N1c3Npb25DYXRlZ29yeTMyMDAxNDM0" @@ -382,6 +383,7 @@ def get_graphql_response( data = response.json() if "errors" in data: logging.error(f"Errors in response, after: {after}, category_id: {category_id}") + logging.error(data["errors"]) logging.error(response.text) raise RuntimeError(response.text) return data @@ -389,7 +391,7 @@ def get_graphql_response( def get_graphql_issue_edges(*, settings: Settings, after: Union[str, None] = None): data = get_graphql_response(settings=settings, query=issues_query, after=after) - graphql_response = IssuesResponse.parse_obj(data) + graphql_response = IssuesResponse.model_validate(data) return graphql_response.data.repository.issues.edges @@ -404,19 +406,19 @@ def get_graphql_question_discussion_edges( after=after, category_id=questions_category_id, ) - graphql_response = DiscussionsResponse.parse_obj(data) + graphql_response = DiscussionsResponse.model_validate(data) return graphql_response.data.repository.discussions.edges def get_graphql_pr_edges(*, settings: Settings, after: Union[str, None] = None): data = get_graphql_response(settings=settings, query=prs_query, after=after) - graphql_response = PRsResponse.parse_obj(data) + graphql_response = PRsResponse.model_validate(data) return graphql_response.data.repository.pullRequests.edges def get_graphql_sponsor_edges(*, settings: Settings, after: Union[str, None] = None): data = get_graphql_response(settings=settings, query=sponsors_query, after=after) - graphql_response = SponsorsResponse.parse_obj(data) + graphql_response = SponsorsResponse.model_validate(data) return graphql_response.data.user.sponsorshipsAsMaintainer.edges @@ -607,7 +609,7 @@ def get_top_users( if __name__ == "__main__": logging.basicConfig(level=logging.INFO) settings = Settings() - logging.info(f"Using config: {settings.json()}") + logging.info(f"Using config: {settings.model_dump_json()}") g = Github(settings.input_token.get_secret_value()) repo = g.get_repo(settings.github_repository) question_commentors, question_last_month_commentors, question_authors = get_experts( From 165f29fe5ec6be1d42b82cdef8b3d144300005f9 Mon Sep 17 00:00:00 2001 From: github-actions Date: Wed, 2 Aug 2023 15:57:57 +0000 Subject: [PATCH 16/39] =?UTF-8?q?=F0=9F=93=9D=20Update=20release=20notes?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docs/en/docs/release-notes.md | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/en/docs/release-notes.md b/docs/en/docs/release-notes.md index 5065295e670c6..d0b7c6a930bcf 100644 --- a/docs/en/docs/release-notes.md +++ b/docs/en/docs/release-notes.md @@ -2,6 +2,7 @@ ## Latest Changes +* ♻️ Update FastAPI People logic with new Pydantic. PR [#9985](https://github.com/tiangolo/fastapi/pull/9985) by [@tiangolo](https://github.com/tiangolo). * ✅ Fix test error in Windows for `jsonable_encoder`. PR [#9840](https://github.com/tiangolo/fastapi/pull/9840) by [@iudeen](https://github.com/iudeen). * 🌐 Add Russian translation for `docs/ru/docs/tutorial/security/index.md`. PR [#9963](https://github.com/tiangolo/fastapi/pull/9963) by [@eVery1337](https://github.com/eVery1337). * 🍱 Update sponsors, Fern badge. PR [#9982](https://github.com/tiangolo/fastapi/pull/9982) by [@tiangolo](https://github.com/tiangolo). From 53220b983227ef6147a43dfdc0528ff4e6c31f6c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebasti=C3=A1n=20Ram=C3=ADrez?= Date: Wed, 2 Aug 2023 20:57:48 +0200 Subject: [PATCH 17/39] =?UTF-8?q?=E2=9E=95=20Add=20pydantic-settings=20to?= =?UTF-8?q?=20FastAPI=20People=20dependencies=20(#9988)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .github/actions/people/Dockerfile | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/actions/people/Dockerfile b/.github/actions/people/Dockerfile index 6d65f1c2bfce0..f0f389c644cb3 100644 --- a/.github/actions/people/Dockerfile +++ b/.github/actions/people/Dockerfile @@ -1,6 +1,6 @@ -FROM python:3.7 +FROM python:3.11 -RUN pip install httpx PyGithub "pydantic==2.0.2" "pyyaml>=5.3.1,<6.0.0" +RUN pip install httpx PyGithub "pydantic==2.0.2" pydantic-settings "pyyaml>=5.3.1,<6.0.0" COPY ./app /app From 38291292451481ca9004a5031464fac036de0161 Mon Sep 17 00:00:00 2001 From: github-actions Date: Wed, 2 Aug 2023 18:58:29 +0000 Subject: [PATCH 18/39] =?UTF-8?q?=F0=9F=93=9D=20Update=20release=20notes?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docs/en/docs/release-notes.md | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/en/docs/release-notes.md b/docs/en/docs/release-notes.md index d0b7c6a930bcf..920886e5ddf5e 100644 --- a/docs/en/docs/release-notes.md +++ b/docs/en/docs/release-notes.md @@ -2,6 +2,7 @@ ## Latest Changes +* ➕ Add pydantic-settings to FastAPI People dependencies. PR [#9988](https://github.com/tiangolo/fastapi/pull/9988) by [@tiangolo](https://github.com/tiangolo). * ♻️ Update FastAPI People logic with new Pydantic. PR [#9985](https://github.com/tiangolo/fastapi/pull/9985) by [@tiangolo](https://github.com/tiangolo). * ✅ Fix test error in Windows for `jsonable_encoder`. PR [#9840](https://github.com/tiangolo/fastapi/pull/9840) by [@iudeen](https://github.com/iudeen). * 🌐 Add Russian translation for `docs/ru/docs/tutorial/security/index.md`. PR [#9963](https://github.com/tiangolo/fastapi/pull/9963) by [@eVery1337](https://github.com/eVery1337). From 89537a0497ef3ccacbe2f4959c3b4f31414319ee Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebasti=C3=A1n=20Ram=C3=ADrez?= Date: Thu, 3 Aug 2023 16:12:28 +0200 Subject: [PATCH 19/39] =?UTF-8?q?=F0=9F=90=B3=20Update=20Dockerfile=20with?= =?UTF-8?q?=20compatibility=20versions,=20to=20upgrade=20later=20(#9998)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .github/actions/people/Dockerfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/actions/people/Dockerfile b/.github/actions/people/Dockerfile index f0f389c644cb3..1455106bde3c8 100644 --- a/.github/actions/people/Dockerfile +++ b/.github/actions/people/Dockerfile @@ -1,4 +1,4 @@ -FROM python:3.11 +FROM python:3.9 RUN pip install httpx PyGithub "pydantic==2.0.2" pydantic-settings "pyyaml>=5.3.1,<6.0.0" From ad1d7f539ea53c3b75e9c23051d66663eac6146f Mon Sep 17 00:00:00 2001 From: github-actions Date: Thu, 3 Aug 2023 14:13:59 +0000 Subject: [PATCH 20/39] =?UTF-8?q?=F0=9F=93=9D=20Update=20release=20notes?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docs/en/docs/release-notes.md | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/en/docs/release-notes.md b/docs/en/docs/release-notes.md index 920886e5ddf5e..91745453caf14 100644 --- a/docs/en/docs/release-notes.md +++ b/docs/en/docs/release-notes.md @@ -2,6 +2,7 @@ ## Latest Changes +* 🐳 Update Dockerfile with compatibility versions, to upgrade later. PR [#9998](https://github.com/tiangolo/fastapi/pull/9998) by [@tiangolo](https://github.com/tiangolo). * ➕ Add pydantic-settings to FastAPI People dependencies. PR [#9988](https://github.com/tiangolo/fastapi/pull/9988) by [@tiangolo](https://github.com/tiangolo). * ♻️ Update FastAPI People logic with new Pydantic. PR [#9985](https://github.com/tiangolo/fastapi/pull/9985) by [@tiangolo](https://github.com/tiangolo). * ✅ Fix test error in Windows for `jsonable_encoder`. PR [#9840](https://github.com/tiangolo/fastapi/pull/9840) by [@iudeen](https://github.com/iudeen). From 3fa6cfbcc5d37cecfc6a936c42c832978ecbfba6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebasti=C3=A1n=20Ram=C3=ADrez?= Date: Thu, 3 Aug 2023 16:25:11 +0200 Subject: [PATCH 21/39] =?UTF-8?q?=F0=9F=91=A5=20Update=20FastAPI=20People?= =?UTF-8?q?=20(#9999)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: github-actions --- docs/en/data/github_sponsors.yml | 93 +++++++-------- docs/en/data/people.yml | 188 +++++++++++++++---------------- 2 files changed, 142 insertions(+), 139 deletions(-) diff --git a/docs/en/data/github_sponsors.yml b/docs/en/data/github_sponsors.yml index 56a886c68bdff..3a68ba62ba237 100644 --- a/docs/en/data/github_sponsors.yml +++ b/docs/en/data/github_sponsors.yml @@ -2,6 +2,9 @@ sponsors: - - login: cryptapi avatarUrl: https://avatars.githubusercontent.com/u/44925437?u=61369138589bc7fee6c417f3fbd50fbd38286cc4&v=4 url: https://github.com/cryptapi + - login: fern-api + avatarUrl: https://avatars.githubusercontent.com/u/102944815?v=4 + url: https://github.com/fern-api - login: nanram22 avatarUrl: https://avatars.githubusercontent.com/u/116367316?v=4 url: https://github.com/nanram22 @@ -29,15 +32,18 @@ sponsors: - login: VincentParedes avatarUrl: https://avatars.githubusercontent.com/u/103889729?v=4 url: https://github.com/VincentParedes +- - login: arcticfly + avatarUrl: https://avatars.githubusercontent.com/u/41524992?u=03c88529a86cf51f7a380e890d84d84c71468848&v=4 + url: https://github.com/arcticfly - - login: getsentry avatarUrl: https://avatars.githubusercontent.com/u/1396951?v=4 url: https://github.com/getsentry -- - login: takashi-yoneya +- - login: acsone + avatarUrl: https://avatars.githubusercontent.com/u/7601056?v=4 + url: https://github.com/acsone + - login: takashi-yoneya avatarUrl: https://avatars.githubusercontent.com/u/33813153?u=2d0522bceba0b8b69adf1f2db866503bd96f944e&v=4 url: https://github.com/takashi-yoneya - - login: mercedes-benz - avatarUrl: https://avatars.githubusercontent.com/u/34240465?v=4 - url: https://github.com/mercedes-benz - login: xoflare avatarUrl: https://avatars.githubusercontent.com/u/74335107?v=4 url: https://github.com/xoflare @@ -50,12 +56,12 @@ sponsors: - login: BoostryJP avatarUrl: https://avatars.githubusercontent.com/u/57932412?v=4 url: https://github.com/BoostryJP + - login: jina-ai + avatarUrl: https://avatars.githubusercontent.com/u/60539444?v=4 + url: https://github.com/jina-ai - - login: HiredScore avatarUrl: https://avatars.githubusercontent.com/u/3908850?v=4 url: https://github.com/HiredScore - - login: petebachant - avatarUrl: https://avatars.githubusercontent.com/u/4604869?u=b17a5a4ac82f77b7efff864d439e8068d2a36593&v=4 - url: https://github.com/petebachant - login: Trivie avatarUrl: https://avatars.githubusercontent.com/u/8161763?v=4 url: https://github.com/Trivie @@ -74,9 +80,6 @@ sponsors: - login: RodneyU215 avatarUrl: https://avatars.githubusercontent.com/u/3329665?u=ec6a9adf8e7e8e306eed7d49687c398608d1604f&v=4 url: https://github.com/RodneyU215 - - login: tizz98 - avatarUrl: https://avatars.githubusercontent.com/u/5739698?u=f095a3659e3a8e7c69ccd822696990b521ea25f9&v=4 - url: https://github.com/tizz98 - login: americanair avatarUrl: https://avatars.githubusercontent.com/u/12281813?v=4 url: https://github.com/americanair @@ -92,11 +95,17 @@ sponsors: - - login: indeedeng avatarUrl: https://avatars.githubusercontent.com/u/2905043?v=4 url: https://github.com/indeedeng + - login: iguit0 + avatarUrl: https://avatars.githubusercontent.com/u/12905770?u=63a1a96d1e6c27d85c4f946b84836599de047f65&v=4 + url: https://github.com/iguit0 + - login: JacobKochems + avatarUrl: https://avatars.githubusercontent.com/u/41692189?u=a75f62ddc0d060ee6233a91e19c433d2687b8eb6&v=4 + url: https://github.com/JacobKochems - - 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 + avatarUrl: https://avatars.githubusercontent.com/u/4039449?u=42eb3b833047c8c4b4f647a031eaef148c16d93f&v=4 url: https://github.com/samuelcolvin - login: jefftriplett avatarUrl: https://avatars.githubusercontent.com/u/50527?u=af1ddfd50f6afd6d99f333ba2ac8d0a5b245ea74&v=4 @@ -104,9 +113,6 @@ sponsors: - login: jstanden avatarUrl: https://avatars.githubusercontent.com/u/63288?u=c3658d57d2862c607a0e19c2101c3c51876e36ad&v=4 url: https://github.com/jstanden - - login: kamalgill - avatarUrl: https://avatars.githubusercontent.com/u/133923?u=0df9181d97436ce330e9acf90ab8a54b7022efe7&v=4 - url: https://github.com/kamalgill - login: dekoza avatarUrl: https://avatars.githubusercontent.com/u/210980?u=c03c78a8ae1039b500dfe343665536ebc51979b2&v=4 url: https://github.com/dekoza @@ -149,6 +155,9 @@ sponsors: - login: zsinx6 avatarUrl: https://avatars.githubusercontent.com/u/3532625?u=ba75a5dc744d1116ccfeaaf30d41cb2fe81fe8dd&v=4 url: https://github.com/zsinx6 + - login: kennywakeland + avatarUrl: https://avatars.githubusercontent.com/u/3631417?u=7c8f743f1ae325dfadea7c62bbf1abd6a824fc55&v=4 + url: https://github.com/kennywakeland - login: aacayaco avatarUrl: https://avatars.githubusercontent.com/u/3634801?u=eaadda178c964178fcb64886f6c732172c8f8219&v=4 url: https://github.com/aacayaco @@ -194,9 +203,6 @@ sponsors: - login: Shackelford-Arden avatarUrl: https://avatars.githubusercontent.com/u/7362263?v=4 url: https://github.com/Shackelford-Arden - - login: savannahostrowski - avatarUrl: https://avatars.githubusercontent.com/u/8949415?u=c3177aa099fb2b8c36aeba349278b77f9a8df211&v=4 - url: https://github.com/savannahostrowski - login: wdwinslow avatarUrl: https://avatars.githubusercontent.com/u/11562137?u=dc01daafb354135603a263729e3d26d939c0c452&v=4 url: https://github.com/wdwinslow @@ -236,9 +242,6 @@ sponsors: - login: ygorpontelo avatarUrl: https://avatars.githubusercontent.com/u/32963605?u=35f7103f9c4c4c2589ae5737ee882e9375ef072e&v=4 url: https://github.com/ygorpontelo - - login: AlrasheedA - avatarUrl: https://avatars.githubusercontent.com/u/33544979?u=7fe66bf62b47682612b222e3e8f4795ef3be769b&v=4 - url: https://github.com/AlrasheedA - login: ProteinQure avatarUrl: https://avatars.githubusercontent.com/u/33707203?v=4 url: https://github.com/ProteinQure @@ -281,9 +284,6 @@ sponsors: - login: DelfinaCare avatarUrl: https://avatars.githubusercontent.com/u/83734439?v=4 url: https://github.com/DelfinaCare - - login: khoadaniel - avatarUrl: https://avatars.githubusercontent.com/u/84840546?v=4 - url: https://github.com/khoadaniel - login: osawa-koki avatarUrl: https://avatars.githubusercontent.com/u/94336223?u=59c6fe6945bcbbaff87b2a794238671b060620d2&v=4 url: https://github.com/osawa-koki @@ -327,14 +327,11 @@ sponsors: avatarUrl: https://avatars.githubusercontent.com/u/861044?u=5abfca5588f3e906b31583d7ee62f6de4b68aa24&v=4 url: https://github.com/browniebroke - login: janfilips - avatarUrl: https://avatars.githubusercontent.com/u/870699?u=96df18ad355e58b9397accc55f4eeb7a86e959b0&v=4 + avatarUrl: https://avatars.githubusercontent.com/u/870699?u=80702ec63f14e675cd4cdcc6ce3821d2ed207fd7&v=4 url: https://github.com/janfilips - login: WillHogan avatarUrl: https://avatars.githubusercontent.com/u/1661551?u=7036c064cf29781470573865264ec8e60b6b809f&v=4 url: https://github.com/WillHogan - - login: NateShoffner - avatarUrl: https://avatars.githubusercontent.com/u/1712163?u=b43cc2fa3fd8bec54b7706e4b98b72543c7bfea8&v=4 - url: https://github.com/NateShoffner - login: my3 avatarUrl: https://avatars.githubusercontent.com/u/1825270?v=4 url: https://github.com/my3 @@ -344,12 +341,6 @@ sponsors: - login: cbonoz avatarUrl: https://avatars.githubusercontent.com/u/2351087?u=fd3e8030b2cc9fbfbb54a65e9890c548a016f58b&v=4 url: https://github.com/cbonoz - - login: Patechoc - avatarUrl: https://avatars.githubusercontent.com/u/2376641?u=23b49e9eda04f078cb74fa3f93593aa6a57bb138&v=4 - url: https://github.com/Patechoc - - login: larsvik - avatarUrl: https://avatars.githubusercontent.com/u/3442226?v=4 - url: https://github.com/larsvik - login: anthonycorletti avatarUrl: https://avatars.githubusercontent.com/u/3477132?v=4 url: https://github.com/anthonycorletti @@ -359,6 +350,9 @@ sponsors: - login: Alisa-lisa avatarUrl: https://avatars.githubusercontent.com/u/4137964?u=e7e393504f554f4ff15863a1e01a5746863ef9ce&v=4 url: https://github.com/Alisa-lisa + - login: piotrgredowski + avatarUrl: https://avatars.githubusercontent.com/u/4294480?v=4 + url: https://github.com/piotrgredowski - login: danielunderwood avatarUrl: https://avatars.githubusercontent.com/u/4472301?v=4 url: https://github.com/danielunderwood @@ -383,6 +377,9 @@ sponsors: - login: mattwelke avatarUrl: https://avatars.githubusercontent.com/u/7719209?u=80f02a799323b1472b389b836d95957c93a6d856&v=4 url: https://github.com/mattwelke + - login: harsh183 + avatarUrl: https://avatars.githubusercontent.com/u/7780198?v=4 + url: https://github.com/harsh183 - login: hcristea avatarUrl: https://avatars.githubusercontent.com/u/7814406?u=61d7a4fcf846983a4606788eac25e1c6c1209ba8&v=4 url: https://github.com/hcristea @@ -428,9 +425,6 @@ sponsors: - login: shuheng-liu avatarUrl: https://avatars.githubusercontent.com/u/22414322?u=813c45f30786c6b511b21a661def025d8f7b609e&v=4 url: https://github.com/shuheng-liu - - login: ghandic - avatarUrl: https://avatars.githubusercontent.com/u/23500353?u=e2e1d736f924d9be81e8bfc565b6d8836ba99773&v=4 - url: https://github.com/ghandic - login: pers0n4 avatarUrl: https://avatars.githubusercontent.com/u/24864600?u=f211a13a7b572cbbd7779b9c8d8cb428cc7ba07e&v=4 url: https://github.com/pers0n4 @@ -458,9 +452,6 @@ sponsors: - login: bnkc avatarUrl: https://avatars.githubusercontent.com/u/34930566?u=527044d90b5ebb7f8dad517db5da1f45253b774b&v=4 url: https://github.com/bnkc - - login: devbruce - avatarUrl: https://avatars.githubusercontent.com/u/35563380?u=ca4e811ac7f7b3eb1600fa63285119fcdee01188&v=4 - url: https://github.com/devbruce - login: declon avatarUrl: https://avatars.githubusercontent.com/u/36180226?v=4 url: https://github.com/declon @@ -476,6 +467,9 @@ sponsors: - login: ArtyomVancyan avatarUrl: https://avatars.githubusercontent.com/u/44609997?v=4 url: https://github.com/ArtyomVancyan + - login: josehenriqueroveda + avatarUrl: https://avatars.githubusercontent.com/u/46685746?u=2e672057a7dbe1dba47e57c378fc0cac336022eb&v=4 + url: https://github.com/josehenriqueroveda - login: hgalytoby avatarUrl: https://avatars.githubusercontent.com/u/50397689?u=f4888c2c54929bd86eed0d3971d09fcb306e5088&v=4 url: https://github.com/hgalytoby @@ -485,27 +479,36 @@ sponsors: - login: conservative-dude avatarUrl: https://avatars.githubusercontent.com/u/55538308?u=f250c44942ea6e73a6bd90739b381c470c192c11&v=4 url: https://github.com/conservative-dude - - login: leo-jp-edwards - avatarUrl: https://avatars.githubusercontent.com/u/58213433?u=2c128e8b0794b7a66211cd7d8ebe05db20b7e9c0&v=4 - url: https://github.com/leo-jp-edwards - login: 0417taehyun avatarUrl: https://avatars.githubusercontent.com/u/63915557?u=47debaa860fd52c9b98c97ef357ddcec3b3fb399&v=4 url: https://github.com/0417taehyun - - login: ssbarnea avatarUrl: https://avatars.githubusercontent.com/u/102495?u=b4bf6818deefe59952ac22fec6ed8c76de1b8f7c&v=4 url: https://github.com/ssbarnea - - login: tomast1337 - avatarUrl: https://avatars.githubusercontent.com/u/15125899?u=2c2f2907012d820499e2c43632389184923513fe&v=4 - url: https://github.com/tomast1337 + - login: Patechoc + avatarUrl: https://avatars.githubusercontent.com/u/2376641?u=23b49e9eda04f078cb74fa3f93593aa6a57bb138&v=4 + url: https://github.com/Patechoc + - login: LanceMoe + avatarUrl: https://avatars.githubusercontent.com/u/18505474?u=7fd3ead4364bdf215b6d75cb122b3811c391ef6b&v=4 + url: https://github.com/LanceMoe - login: sadikkuzu avatarUrl: https://avatars.githubusercontent.com/u/23168063?u=d179c06bb9f65c4167fcab118526819f8e0dac17&v=4 url: https://github.com/sadikkuzu - login: ruizdiazever avatarUrl: https://avatars.githubusercontent.com/u/29817086?u=2df54af55663d246e3a4dc8273711c37f1adb117&v=4 url: https://github.com/ruizdiazever + - login: samnimoh + avatarUrl: https://avatars.githubusercontent.com/u/33413170?u=147bc516be6cb647b28d7e3b3fea3a018a331145&v=4 + url: https://github.com/samnimoh - login: danburonline avatarUrl: https://avatars.githubusercontent.com/u/34251194?u=2cad4388c1544e539ecb732d656e42fb07b4ff2d&v=4 url: https://github.com/danburonline + - login: iharshgor + avatarUrl: https://avatars.githubusercontent.com/u/35490011?u=2dea054476e752d9e92c9d71a9a7cc919b1c2f8e&v=4 + url: https://github.com/iharshgor - login: rwxd avatarUrl: https://avatars.githubusercontent.com/u/40308458?u=cd04a39e3655923be4f25c2ba8a5a07b3da3230a&v=4 url: https://github.com/rwxd + - login: ThomasPalma1 + avatarUrl: https://avatars.githubusercontent.com/u/66331874?u=5763f7402d784ba189b60d704ff5849b4d0a63fb&v=4 + url: https://github.com/ThomasPalma1 diff --git a/docs/en/data/people.yml b/docs/en/data/people.yml index dd2dbe5ea9d01..89d189564c937 100644 --- a/docs/en/data/people.yml +++ b/docs/en/data/people.yml @@ -1,16 +1,16 @@ maintainers: - login: tiangolo - answers: 1844 - prs: 430 + answers: 1849 + prs: 466 avatarUrl: https://avatars.githubusercontent.com/u/1326112?u=740f11212a731f56798f558ceddb0bd07642afa7&v=4 url: https://github.com/tiangolo experts: - login: Kludex - count: 434 + count: 463 avatarUrl: https://avatars.githubusercontent.com/u/7353520?u=62adc405ef418f4b6c8caa93d3eb8ab107bc4927&v=4 url: https://github.com/Kludex - login: dmontagu - count: 237 + count: 239 avatarUrl: https://avatars.githubusercontent.com/u/35119617?u=540f30c937a6450812628b9592a1dfe91bbe148e&v=4 url: https://github.com/dmontagu - login: Mause @@ -25,34 +25,34 @@ experts: count: 193 avatarUrl: https://avatars.githubusercontent.com/u/13659033?u=e8bea32d07a5ef72f7dde3b2079ceb714923ca05&v=4 url: https://github.com/JarroVGIT -- login: euri10 - count: 152 - avatarUrl: https://avatars.githubusercontent.com/u/1104190?u=321a2e953e6645a7d09b732786c7a8061e0f8a8b&v=4 - url: https://github.com/euri10 - login: jgould22 - count: 139 + count: 157 avatarUrl: https://avatars.githubusercontent.com/u/4335847?u=ed77f67e0bb069084639b24d812dbb2a2b1dc554&v=4 url: https://github.com/jgould22 +- login: euri10 + count: 153 + avatarUrl: https://avatars.githubusercontent.com/u/1104190?u=321a2e953e6645a7d09b732786c7a8061e0f8a8b&v=4 + url: https://github.com/euri10 - login: phy25 count: 126 - avatarUrl: https://avatars.githubusercontent.com/u/331403?u=191cd73f0c936497c8d1931a217bb3039d050265&v=4 + avatarUrl: https://avatars.githubusercontent.com/u/331403?v=4 url: https://github.com/phy25 - login: iudeen - count: 118 + count: 121 avatarUrl: https://avatars.githubusercontent.com/u/10519440?u=2843b3303282bff8b212dcd4d9d6689452e4470c&v=4 url: https://github.com/iudeen - login: raphaelauv count: 83 avatarUrl: https://avatars.githubusercontent.com/u/10202690?u=e6f86f5c0c3026a15d6b51792fa3e532b12f1371&v=4 url: https://github.com/raphaelauv -- login: ghandic - count: 71 - avatarUrl: https://avatars.githubusercontent.com/u/23500353?u=e2e1d736f924d9be81e8bfc565b6d8836ba99773&v=4 - url: https://github.com/ghandic - login: ArcLightSlavik count: 71 avatarUrl: https://avatars.githubusercontent.com/u/31127044?u=b0f2c37142f4b762e41ad65dc49581813422bd71&v=4 url: https://github.com/ArcLightSlavik +- login: ghandic + count: 71 + avatarUrl: https://avatars.githubusercontent.com/u/23500353?u=e2e1d736f924d9be81e8bfc565b6d8836ba99773&v=4 + url: https://github.com/ghandic - login: falkben count: 57 avatarUrl: https://avatars.githubusercontent.com/u/653031?u=ad9838e089058c9e5a0bab94c0eec7cc181e0cd0&v=4 @@ -61,10 +61,10 @@ experts: count: 49 avatarUrl: https://avatars.githubusercontent.com/u/516999?u=437c0c5038558c67e887ccd863c1ba0f846c03da&v=4 url: https://github.com/sm-Fifteen -- login: adriangb +- login: insomnes count: 45 - avatarUrl: https://avatars.githubusercontent.com/u/1755071?u=612704256e38d6ac9cbed24f10e4b6ac2da74ecb&v=4 - url: https://github.com/adriangb + avatarUrl: https://avatars.githubusercontent.com/u/16958893?u=f8be7088d5076d963984a21f95f44e559192d912&v=4 + url: https://github.com/insomnes - login: yinziyan1206 count: 45 avatarUrl: https://avatars.githubusercontent.com/u/37829370?u=da44ca53aefd5c23f346fab8e9fd2e108294c179&v=4 @@ -73,22 +73,22 @@ experts: count: 45 avatarUrl: https://avatars.githubusercontent.com/u/685002?u=b5094ab4527fc84b006c0ac9ff54367bdebb2267&v=4 url: https://github.com/acidjunk -- login: insomnes - count: 45 - avatarUrl: https://avatars.githubusercontent.com/u/16958893?u=f8be7088d5076d963984a21f95f44e559192d912&v=4 - url: https://github.com/insomnes - login: Dustyposa count: 45 avatarUrl: https://avatars.githubusercontent.com/u/27180793?u=5cf2877f50b3eb2bc55086089a78a36f07042889&v=4 url: https://github.com/Dustyposa -- login: odiseo0 - count: 43 - avatarUrl: https://avatars.githubusercontent.com/u/87550035?u=2da05dab6cc8e1ade557801634760a56e4101796&v=4 - url: https://github.com/odiseo0 +- login: adriangb + count: 44 + avatarUrl: https://avatars.githubusercontent.com/u/1755071?u=612704256e38d6ac9cbed24f10e4b6ac2da74ecb&v=4 + url: https://github.com/adriangb - login: frankie567 count: 43 avatarUrl: https://avatars.githubusercontent.com/u/1144727?u=85c025e3fcc7bd79a5665c63ee87cdf8aae13374&v=4 url: https://github.com/frankie567 +- login: odiseo0 + count: 43 + avatarUrl: https://avatars.githubusercontent.com/u/87550035?u=241a71f6b7068738b81af3e57f45ffd723538401&v=4 + url: https://github.com/odiseo0 - login: includeamin count: 40 avatarUrl: https://avatars.githubusercontent.com/u/11836741?u=8bd5ef7e62fe6a82055e33c4c0e0a7879ff8cfb6&v=4 @@ -97,14 +97,14 @@ experts: count: 37 avatarUrl: https://avatars.githubusercontent.com/u/5167622?u=de8f597c81d6336fcebc37b32dfd61a3f877160c&v=4 url: https://github.com/STeveShary -- login: chbndrhnns - count: 35 - avatarUrl: https://avatars.githubusercontent.com/u/7534547?v=4 - url: https://github.com/chbndrhnns - login: krishnardt count: 35 avatarUrl: https://avatars.githubusercontent.com/u/31960541?u=47f4829c77f4962ab437ffb7995951e41eeebe9b&v=4 url: https://github.com/krishnardt +- login: chbndrhnns + count: 35 + avatarUrl: https://avatars.githubusercontent.com/u/7534547?v=4 + url: https://github.com/chbndrhnns - login: panla count: 32 avatarUrl: https://avatars.githubusercontent.com/u/41326348?u=ba2fda6b30110411ecbf406d187907e2b420ac19&v=4 @@ -121,38 +121,38 @@ experts: count: 25 avatarUrl: https://avatars.githubusercontent.com/u/365303?u=07ca03c5ee811eb0920e633cc3c3db73dbec1aa5&v=4 url: https://github.com/wshayes +- login: acnebs + count: 23 + avatarUrl: https://avatars.githubusercontent.com/u/9054108?v=4 + url: https://github.com/acnebs - login: SirTelemak count: 23 avatarUrl: https://avatars.githubusercontent.com/u/9435877?u=719327b7d2c4c62212456d771bfa7c6b8dbb9eac&v=4 url: https://github.com/SirTelemak -- login: acnebs - count: 22 - avatarUrl: https://avatars.githubusercontent.com/u/9054108?u=c27e50269f1ef8ea950cc6f0268c8ec5cebbe9c9&v=4 - url: https://github.com/acnebs - login: rafsaf count: 21 avatarUrl: https://avatars.githubusercontent.com/u/51059348?u=f8f0d6d6e90fac39fa786228158ba7f013c74271&v=4 url: https://github.com/rafsaf -- login: chris-allnutt +- login: n8sty count: 20 - avatarUrl: https://avatars.githubusercontent.com/u/565544?v=4 - url: https://github.com/chris-allnutt + avatarUrl: https://avatars.githubusercontent.com/u/2964996?v=4 + url: https://github.com/n8sty - login: nsidnev count: 20 avatarUrl: https://avatars.githubusercontent.com/u/22559461?u=a9cc3238217e21dc8796a1a500f01b722adb082c&v=4 url: https://github.com/nsidnev -- login: n8sty +- login: chris-allnutt + count: 20 + avatarUrl: https://avatars.githubusercontent.com/u/565544?v=4 + url: https://github.com/chris-allnutt +- login: zoliknemet count: 18 - avatarUrl: https://avatars.githubusercontent.com/u/2964996?v=4 - url: https://github.com/n8sty + avatarUrl: https://avatars.githubusercontent.com/u/22326718?u=31ba446ac290e23e56eea8e4f0c558aaf0b40779&v=4 + url: https://github.com/zoliknemet - login: retnikt count: 18 avatarUrl: https://avatars.githubusercontent.com/u/24581770?v=4 url: https://github.com/retnikt -- login: zoliknemet - count: 18 - avatarUrl: https://avatars.githubusercontent.com/u/22326718?u=31ba446ac290e23e56eea8e4f0c558aaf0b40779&v=4 - url: https://github.com/zoliknemet - login: Hultner count: 17 avatarUrl: https://avatars.githubusercontent.com/u/2669034?u=115e53df959309898ad8dc9443fbb35fee71df07&v=4 @@ -198,38 +198,30 @@ experts: avatarUrl: https://avatars.githubusercontent.com/u/12537771?u=7444d20019198e34911082780cc7ad73f2b97cb3&v=4 url: https://github.com/jorgerpo last_month_active: -- login: jgould22 - count: 15 - avatarUrl: https://avatars.githubusercontent.com/u/4335847?u=ed77f67e0bb069084639b24d812dbb2a2b1dc554&v=4 - url: https://github.com/jgould22 - login: Kludex - count: 13 + count: 24 avatarUrl: https://avatars.githubusercontent.com/u/7353520?u=62adc405ef418f4b6c8caa93d3eb8ab107bc4927&v=4 url: https://github.com/Kludex -- login: abhint - count: 5 - avatarUrl: https://avatars.githubusercontent.com/u/25699289?u=b5d219277b4d001ac26fb8be357fddd88c29d51b&v=4 - url: https://github.com/abhint -- login: chrisK824 - count: 4 - avatarUrl: https://avatars.githubusercontent.com/u/79946379?u=03d85b22d696a58a9603e55fbbbe2de6b0f4face&v=4 - url: https://github.com/chrisK824 +- login: jgould22 + count: 17 + avatarUrl: https://avatars.githubusercontent.com/u/4335847?u=ed77f67e0bb069084639b24d812dbb2a2b1dc554&v=4 + url: https://github.com/jgould22 - login: arjwilliams - count: 3 + count: 8 avatarUrl: https://avatars.githubusercontent.com/u/22227620?v=4 url: https://github.com/arjwilliams -- login: wu-clan - count: 3 - avatarUrl: https://avatars.githubusercontent.com/u/52145145?u=f8c9e5c8c259d248e1683fedf5027b4ee08a0967&v=4 - url: https://github.com/wu-clan - login: Ahmed-Abdou14 - count: 3 - avatarUrl: https://avatars.githubusercontent.com/u/104530599?u=d1e1c064d57c3ad5b6481716928da840f6d5a492&v=4 + count: 4 + avatarUrl: https://avatars.githubusercontent.com/u/104530599?u=05365b155a1ff911532e8be316acfad2e0736f98&v=4 url: https://github.com/Ahmed-Abdou14 -- login: esrefzeki +- login: iudeen count: 3 - avatarUrl: https://avatars.githubusercontent.com/u/54935247?u=193cf5a169ca05fc54995a4dceabc82c7dc6e5ea&v=4 - url: https://github.com/esrefzeki + avatarUrl: https://avatars.githubusercontent.com/u/10519440?u=2843b3303282bff8b212dcd4d9d6689452e4470c&v=4 + url: https://github.com/iudeen +- login: mikeedjones + count: 3 + avatarUrl: https://avatars.githubusercontent.com/u/4087139?u=cc4a242896ac2fcf88a53acfaf190d0fe0a1f0c9&v=4 + url: https://github.com/mikeedjones top_contributors: - login: waynerv count: 25 @@ -240,7 +232,7 @@ top_contributors: avatarUrl: https://avatars.githubusercontent.com/u/41147016?u=55010621aece725aa702270b54fed829b6a1fe60&v=4 url: https://github.com/tokusumi - login: Kludex - count: 20 + count: 21 avatarUrl: https://avatars.githubusercontent.com/u/7353520?u=62adc405ef418f4b6c8caa93d3eb8ab107bc4927&v=4 url: https://github.com/Kludex - login: jaystone776 @@ -264,7 +256,7 @@ top_contributors: avatarUrl: https://avatars.githubusercontent.com/u/11489395?u=4adb6986bf3debfc2b8216ae701f2bd47d73da7d&v=4 url: https://github.com/mariacamilagl - login: Smlep - count: 10 + count: 11 avatarUrl: https://avatars.githubusercontent.com/u/16785985?v=4 url: https://github.com/Smlep - login: Serrones @@ -287,6 +279,10 @@ top_contributors: count: 7 avatarUrl: https://avatars.githubusercontent.com/u/119126536?u=9fc0d48f3307817bafecc5861eb2168401a6cb04&v=4 url: https://github.com/Alexandrhub +- login: NinaHwang + count: 6 + avatarUrl: https://avatars.githubusercontent.com/u/79563565?u=eee6bfe9224c71193025ab7477f4f96ceaa05c62&v=4 + url: https://github.com/NinaHwang - login: batlopes count: 6 avatarUrl: https://avatars.githubusercontent.com/u/33462923?u=0fb3d7acb316764616f11e4947faf080e49ad8d9&v=4 @@ -297,7 +293,7 @@ top_contributors: url: https://github.com/wshayes - login: samuelcolvin count: 5 - avatarUrl: https://avatars.githubusercontent.com/u/4039449?u=807390ba9cfe23906c3bf8a0d56aaca3cf2bfa0d&v=4 + avatarUrl: https://avatars.githubusercontent.com/u/4039449?u=42eb3b833047c8c4b4f647a031eaef148c16d93f&v=4 url: https://github.com/samuelcolvin - login: SwftAlpc count: 5 @@ -311,10 +307,6 @@ top_contributors: count: 5 avatarUrl: https://avatars.githubusercontent.com/u/43503750?u=f440bc9062afb3c43b9b9c6cdfdcfe31d58699ef&v=4 url: https://github.com/ComicShrimp -- login: NinaHwang - count: 5 - avatarUrl: https://avatars.githubusercontent.com/u/79563565?u=eee6bfe9224c71193025ab7477f4f96ceaa05c62&v=4 - url: https://github.com/NinaHwang - login: jekirl count: 4 avatarUrl: https://avatars.githubusercontent.com/u/2546697?u=a027452387d85bd4a14834e19d716c99255fb3b7&v=4 @@ -335,10 +327,18 @@ top_contributors: count: 4 avatarUrl: https://avatars.githubusercontent.com/u/3360631?u=5fa1f475ad784d64eb9666bdd43cc4d285dcc773&v=4 url: https://github.com/hitrust +- login: JulianMaurin + count: 4 + avatarUrl: https://avatars.githubusercontent.com/u/63545168?u=b7d15ac865268cbefc2d739e2f23d9aeeac1a622&v=4 + url: https://github.com/JulianMaurin - login: lsglucas count: 4 avatarUrl: https://avatars.githubusercontent.com/u/61513630?u=320e43fe4dc7bc6efc64e9b8f325f8075634fd20&v=4 url: https://github.com/lsglucas +- login: iudeen + count: 4 + avatarUrl: https://avatars.githubusercontent.com/u/10519440?u=2843b3303282bff8b212dcd4d9d6689452e4470c&v=4 + url: https://github.com/iudeen - login: axel584 count: 4 avatarUrl: https://avatars.githubusercontent.com/u/1334088?u=9667041f5b15dc002b6f9665fda8c0412933ac04&v=4 @@ -349,7 +349,7 @@ top_contributors: url: https://github.com/ivan-abc top_reviewers: - login: Kludex - count: 122 + count: 136 avatarUrl: https://avatars.githubusercontent.com/u/7353520?u=62adc405ef418f4b6c8caa93d3eb8ab107bc4927&v=4 url: https://github.com/Kludex - login: BilalAlpaslan @@ -357,7 +357,7 @@ top_reviewers: avatarUrl: https://avatars.githubusercontent.com/u/47563997?u=63ed66e304fe8d765762c70587d61d9196e5c82d&v=4 url: https://github.com/BilalAlpaslan - login: yezz123 - count: 77 + count: 78 avatarUrl: https://avatars.githubusercontent.com/u/52716203?u=d7062cbc6eb7671d5dc9cc0e32a24ae335e0f225&v=4 url: https://github.com/yezz123 - login: tokusumi @@ -372,20 +372,20 @@ top_reviewers: count: 47 avatarUrl: https://avatars.githubusercontent.com/u/59285379?v=4 url: https://github.com/Laineyzhang55 +- login: iudeen + count: 46 + avatarUrl: https://avatars.githubusercontent.com/u/10519440?u=2843b3303282bff8b212dcd4d9d6689452e4470c&v=4 + url: https://github.com/iudeen - login: ycd count: 45 avatarUrl: https://avatars.githubusercontent.com/u/62724709?u=bba5af018423a2858d49309bed2a899bb5c34ac5&v=4 url: https://github.com/ycd -- login: iudeen - count: 44 - avatarUrl: https://avatars.githubusercontent.com/u/10519440?u=2843b3303282bff8b212dcd4d9d6689452e4470c&v=4 - url: https://github.com/iudeen - login: cikay count: 41 avatarUrl: https://avatars.githubusercontent.com/u/24587499?u=e772190a051ab0eaa9c8542fcff1892471638f2b&v=4 url: https://github.com/cikay - login: Xewus - count: 35 + count: 38 avatarUrl: https://avatars.githubusercontent.com/u/85196001?u=f8e2dc7e5104f109cef944af79050ea8d1b8f914&v=4 url: https://github.com/Xewus - login: JarroVGIT @@ -412,6 +412,10 @@ top_reviewers: count: 26 avatarUrl: https://avatars.githubusercontent.com/u/61513630?u=320e43fe4dc7bc6efc64e9b8f325f8075634fd20&v=4 url: https://github.com/lsglucas +- login: LorhanSohaky + count: 24 + avatarUrl: https://avatars.githubusercontent.com/u/16273730?u=095b66f243a2cd6a0aadba9a095009f8aaf18393&v=4 + url: https://github.com/LorhanSohaky - login: Ryandaydev count: 24 avatarUrl: https://avatars.githubusercontent.com/u/4292423?u=809f3d1074d04bbc28012a7f17f06ea56f5bd71a&v=4 @@ -420,10 +424,6 @@ top_reviewers: count: 23 avatarUrl: https://avatars.githubusercontent.com/u/35119617?u=540f30c937a6450812628b9592a1dfe91bbe148e&v=4 url: https://github.com/dmontagu -- login: LorhanSohaky - count: 23 - avatarUrl: https://avatars.githubusercontent.com/u/16273730?u=095b66f243a2cd6a0aadba9a095009f8aaf18393&v=4 - url: https://github.com/LorhanSohaky - login: rjNemo count: 21 avatarUrl: https://avatars.githubusercontent.com/u/56785022?u=d5c3a02567c8649e146fcfc51b6060ccaf8adef8&v=4 @@ -434,7 +434,7 @@ top_reviewers: url: https://github.com/hard-coders - login: odiseo0 count: 20 - avatarUrl: https://avatars.githubusercontent.com/u/87550035?u=2da05dab6cc8e1ade557801634760a56e4101796&v=4 + avatarUrl: https://avatars.githubusercontent.com/u/87550035?u=241a71f6b7068738b81af3e57f45ffd723538401&v=4 url: https://github.com/odiseo0 - login: 0417taehyun count: 19 @@ -456,6 +456,10 @@ top_reviewers: count: 16 avatarUrl: https://avatars.githubusercontent.com/u/52768429?u=6a3aa15277406520ad37f6236e89466ed44bc5b8&v=4 url: https://github.com/SwftAlpc +- login: axel584 + count: 16 + avatarUrl: https://avatars.githubusercontent.com/u/1334088?u=9667041f5b15dc002b6f9665fda8c0412933ac04&v=4 + url: https://github.com/axel584 - login: DevDae count: 16 avatarUrl: https://avatars.githubusercontent.com/u/87962045?u=08e10fa516e844934f4b3fc7c38b33c61697e4a1&v=4 @@ -488,10 +492,6 @@ top_reviewers: count: 12 avatarUrl: https://avatars.githubusercontent.com/u/31848542?u=494ecc298e3f26197495bb357ad0f57cfd5f7a32&v=4 url: https://github.com/RunningIkkyu -- login: axel584 - count: 12 - avatarUrl: https://avatars.githubusercontent.com/u/1334088?u=9667041f5b15dc002b6f9665fda8c0412933ac04&v=4 - url: https://github.com/axel584 - login: ivan-abc count: 12 avatarUrl: https://avatars.githubusercontent.com/u/36765187?u=c6e0ba571c1ccb6db9d94e62e4b8b5eda811a870&v=4 @@ -500,6 +500,10 @@ top_reviewers: count: 11 avatarUrl: https://avatars.githubusercontent.com/u/46193920?u=789927ee09cfabd752d3bd554fa6baf4850d2777&v=4 url: https://github.com/solomein-sv +- login: wdh99 + count: 11 + avatarUrl: https://avatars.githubusercontent.com/u/108172295?u=8a8fb95d5afe3e0fa33257b2aecae88d436249eb&v=4 + url: https://github.com/wdh99 - login: mariacamilagl count: 10 avatarUrl: https://avatars.githubusercontent.com/u/11489395?u=4adb6986bf3debfc2b8216ae701f2bd47d73da7d&v=4 @@ -540,7 +544,3 @@ top_reviewers: count: 9 avatarUrl: https://avatars.githubusercontent.com/u/69092910?u=4ac58eab99bd37d663f3d23551df96d4fbdbf760&v=4 url: https://github.com/bezaca -- login: oandersonmagalhaes - count: 9 - avatarUrl: https://avatars.githubusercontent.com/u/83456692?v=4 - url: https://github.com/oandersonmagalhaes From a73cdaed35d6d9a120ba4831c512b3a7cb25b697 Mon Sep 17 00:00:00 2001 From: github-actions Date: Thu, 3 Aug 2023 14:25:48 +0000 Subject: [PATCH 22/39] =?UTF-8?q?=F0=9F=93=9D=20Update=20release=20notes?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docs/en/docs/release-notes.md | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/en/docs/release-notes.md b/docs/en/docs/release-notes.md index 91745453caf14..ab8c6e68c89cb 100644 --- a/docs/en/docs/release-notes.md +++ b/docs/en/docs/release-notes.md @@ -2,6 +2,7 @@ ## Latest Changes +* 👥 Update FastAPI People. PR [#9999](https://github.com/tiangolo/fastapi/pull/9999) by [@tiangolo](https://github.com/tiangolo). * 🐳 Update Dockerfile with compatibility versions, to upgrade later. PR [#9998](https://github.com/tiangolo/fastapi/pull/9998) by [@tiangolo](https://github.com/tiangolo). * ➕ Add pydantic-settings to FastAPI People dependencies. PR [#9988](https://github.com/tiangolo/fastapi/pull/9988) by [@tiangolo](https://github.com/tiangolo). * ♻️ Update FastAPI People logic with new Pydantic. PR [#9985](https://github.com/tiangolo/fastapi/pull/9985) by [@tiangolo](https://github.com/tiangolo). From 4ab0363ad794fd60e1ebead224f57a1d01e6bd6b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebasti=C3=A1n=20Ram=C3=ADrez?= Date: Thu, 3 Aug 2023 17:24:31 +0200 Subject: [PATCH 23/39] =?UTF-8?q?=E2=9E=96=20Remove=20direct=20dependency?= =?UTF-8?q?=20on=20MkDocs,=20Material=20for=20MkDocs=20defines=20its=20own?= =?UTF-8?q?=20dependency=20(#9986)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .github/workflows/build-docs.yml | 8 ++++---- requirements-docs.txt | 1 - 2 files changed, 4 insertions(+), 5 deletions(-) diff --git a/.github/workflows/build-docs.yml b/.github/workflows/build-docs.yml index 19009447b0b15..eb816b72f7699 100644 --- a/.github/workflows/build-docs.yml +++ b/.github/workflows/build-docs.yml @@ -44,14 +44,14 @@ jobs: id: cache with: path: ${{ env.pythonLocation }} - key: ${{ runner.os }}-python-docs-${{ env.pythonLocation }}-${{ hashFiles('pyproject.toml', 'requirements-docs.txt') }}-v05 + key: ${{ runner.os }}-python-docs-${{ env.pythonLocation }}-${{ hashFiles('pyproject.toml', 'requirements-docs.txt') }}-v06 - name: Install docs extras if: steps.cache.outputs.cache-hit != 'true' run: pip install -r requirements-docs.txt # Install MkDocs Material Insiders here just to put it in the cache for the rest of the steps - name: Install Material for MkDocs Insiders if: ( github.event_name != 'pull_request' || github.event.pull_request.head.repo.fork == false ) && steps.cache.outputs.cache-hit != 'true' - run: pip install git+https://${{ secrets.FASTAPI_MKDOCS_MATERIAL_INSIDERS }}@github.com/squidfunk/mkdocs-material-insiders.git + run: pip install git+https://${{ secrets.FASTAPI_MKDOCS_MATERIAL_INSIDERS }}@github.com/squidfunk/mkdocs-material-insiders.git@9.1.21-insiders-4.38.0 - name: Export Language Codes id: show-langs run: | @@ -80,13 +80,13 @@ jobs: id: cache with: path: ${{ env.pythonLocation }} - key: ${{ runner.os }}-python-docs-${{ env.pythonLocation }}-${{ hashFiles('pyproject.toml', 'requirements-docs.txt') }}-v05 + key: ${{ runner.os }}-python-docs-${{ env.pythonLocation }}-${{ hashFiles('pyproject.toml', 'requirements-docs.txt') }}-v06 - name: Install docs extras if: steps.cache.outputs.cache-hit != 'true' run: pip install -r requirements-docs.txt - name: Install Material for MkDocs Insiders if: ( github.event_name != 'pull_request' || github.event.pull_request.head.repo.fork == false ) && steps.cache.outputs.cache-hit != 'true' - run: pip install git+https://${{ secrets.FASTAPI_MKDOCS_MATERIAL_INSIDERS }}@github.com/squidfunk/mkdocs-material-insiders.git + run: pip install git+https://${{ secrets.FASTAPI_MKDOCS_MATERIAL_INSIDERS }}@github.com/squidfunk/mkdocs-material-insiders.git@9.1.21-insiders-4.38.0 - name: Update Languages run: python ./scripts/docs.py update-languages - uses: actions/cache@v3 diff --git a/requirements-docs.txt b/requirements-docs.txt index df60ca4df14e3..7152ebf7b72b5 100644 --- a/requirements-docs.txt +++ b/requirements-docs.txt @@ -1,5 +1,4 @@ -e . -mkdocs==1.4.3 mkdocs-material==9.1.17 mdx-include >=1.4.1,<2.0.0 mkdocs-markdownextradata-plugin >=0.1.7,<0.3.0 From 94c48cfc8cb5987113c6a8558a7a428d27888cce Mon Sep 17 00:00:00 2001 From: github-actions Date: Thu, 3 Aug 2023 15:25:10 +0000 Subject: [PATCH 24/39] =?UTF-8?q?=F0=9F=93=9D=20Update=20release=20notes?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docs/en/docs/release-notes.md | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/en/docs/release-notes.md b/docs/en/docs/release-notes.md index ab8c6e68c89cb..caf74c3532267 100644 --- a/docs/en/docs/release-notes.md +++ b/docs/en/docs/release-notes.md @@ -2,6 +2,7 @@ ## Latest Changes +* 📍 Update MkDocs Material dependencies. PR [#9986](https://github.com/tiangolo/fastapi/pull/9986) by [@tiangolo](https://github.com/tiangolo). * 👥 Update FastAPI People. PR [#9999](https://github.com/tiangolo/fastapi/pull/9999) by [@tiangolo](https://github.com/tiangolo). * 🐳 Update Dockerfile with compatibility versions, to upgrade later. PR [#9998](https://github.com/tiangolo/fastapi/pull/9998) by [@tiangolo](https://github.com/tiangolo). * ➕ Add pydantic-settings to FastAPI People dependencies. PR [#9988](https://github.com/tiangolo/fastapi/pull/9988) by [@tiangolo](https://github.com/tiangolo). From 25694f5ae100741c9f7ee0d409e298609e71366e Mon Sep 17 00:00:00 2001 From: David Montague <35119617+dmontagu@users.noreply.github.com> Date: Thu, 3 Aug 2023 16:46:57 +0100 Subject: [PATCH 25/39] =?UTF-8?q?=E2=9C=85=20Fix=20tests=20for=20compatibi?= =?UTF-8?q?lity=20with=20pydantic=202.1.1=20(#9943)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> Co-authored-by: Sebastián Ramírez --- .github/workflows/test.yml | 4 +-- tests/test_filter_pydantic_sub_model_pv2.py | 4 +-- tests/test_multi_body_errors.py | 34 +++++++++++++++++++-- 3 files changed, 35 insertions(+), 7 deletions(-) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index b95358d0136d4..fbaf759c3238a 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -25,7 +25,7 @@ jobs: id: cache with: path: ${{ env.pythonLocation }} - key: ${{ runner.os }}-python-${{ env.pythonLocation }}-pydantic-v2-${{ hashFiles('pyproject.toml', 'requirements-tests.txt') }}-test-v03 + key: ${{ runner.os }}-python-${{ env.pythonLocation }}-pydantic-v2-${{ hashFiles('pyproject.toml', 'requirements-tests.txt') }}-test-v04 - name: Install Dependencies if: steps.cache.outputs.cache-hit != 'true' run: pip install -r requirements-tests.txt @@ -54,7 +54,7 @@ jobs: id: cache with: path: ${{ env.pythonLocation }} - key: ${{ runner.os }}-python-${{ env.pythonLocation }}-${{ matrix.pydantic-version }}-${{ hashFiles('pyproject.toml', 'requirements-tests.txt') }}-test-v03 + key: ${{ runner.os }}-python-${{ env.pythonLocation }}-${{ matrix.pydantic-version }}-${{ hashFiles('pyproject.toml', 'requirements-tests.txt') }}-test-v04 - name: Install Dependencies if: steps.cache.outputs.cache-hit != 'true' run: pip install -r requirements-tests.txt diff --git a/tests/test_filter_pydantic_sub_model_pv2.py b/tests/test_filter_pydantic_sub_model_pv2.py index 656332a010249..ae12179bdf314 100644 --- a/tests/test_filter_pydantic_sub_model_pv2.py +++ b/tests/test_filter_pydantic_sub_model_pv2.py @@ -1,7 +1,7 @@ from typing import Optional import pytest -from dirty_equals import IsDict +from dirty_equals import HasRepr, IsDict from fastapi import Depends, FastAPI from fastapi.exceptions import ResponseValidationError from fastapi.testclient import TestClient @@ -66,7 +66,7 @@ def test_validator_is_cloned(client: TestClient): "loc": ("response", "name"), "msg": "Value error, name must end in A", "input": "modelX", - "ctx": {"error": "name must end in A"}, + "ctx": {"error": HasRepr("ValueError('name must end in A')")}, "url": match_pydantic_error_url("value_error"), } ) diff --git a/tests/test_multi_body_errors.py b/tests/test_multi_body_errors.py index aa989c612874f..931f08fc1cf5c 100644 --- a/tests/test_multi_body_errors.py +++ b/tests/test_multi_body_errors.py @@ -51,7 +51,7 @@ def test_jsonable_encoder_requiring_error(): "loc": ["body", 0, "age"], "msg": "Input should be greater than 0", "input": -1.0, - "ctx": {"gt": 0.0}, + "ctx": {"gt": "0"}, "url": match_pydantic_error_url("greater_than"), } ] @@ -84,9 +84,23 @@ def test_put_incorrect_body_multiple(): "input": {"age": "five"}, "url": match_pydantic_error_url("missing"), }, + { + "ctx": {"class": "Decimal"}, + "input": "five", + "loc": ["body", 0, "age", "is-instance[Decimal]"], + "msg": "Input should be an instance of Decimal", + "type": "is_instance_of", + "url": match_pydantic_error_url("is_instance_of"), + }, { "type": "decimal_parsing", - "loc": ["body", 0, "age"], + "loc": [ + "body", + 0, + "age", + "function-after[to_decimal(), " + "union[int,constrained-str,function-plain[str()]]]", + ], "msg": "Input should be a valid decimal", "input": "five", }, @@ -97,9 +111,23 @@ def test_put_incorrect_body_multiple(): "input": {"age": "six"}, "url": match_pydantic_error_url("missing"), }, + { + "ctx": {"class": "Decimal"}, + "input": "six", + "loc": ["body", 1, "age", "is-instance[Decimal]"], + "msg": "Input should be an instance of Decimal", + "type": "is_instance_of", + "url": match_pydantic_error_url("is_instance_of"), + }, { "type": "decimal_parsing", - "loc": ["body", 1, "age"], + "loc": [ + "body", + 1, + "age", + "function-after[to_decimal(), " + "union[int,constrained-str,function-plain[str()]]]", + ], "msg": "Input should be a valid decimal", "input": "six", }, From 10b4c31f063d9a098e69dfc48a3a62028fab1261 Mon Sep 17 00:00:00 2001 From: github-actions Date: Thu, 3 Aug 2023 15:47:35 +0000 Subject: [PATCH 26/39] =?UTF-8?q?=F0=9F=93=9D=20Update=20release=20notes?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docs/en/docs/release-notes.md | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/en/docs/release-notes.md b/docs/en/docs/release-notes.md index caf74c3532267..91574addd150e 100644 --- a/docs/en/docs/release-notes.md +++ b/docs/en/docs/release-notes.md @@ -2,6 +2,7 @@ ## Latest Changes +* ✅ Fix tests for compatibility with pydantic 2.1.1. PR [#9943](https://github.com/tiangolo/fastapi/pull/9943) by [@dmontagu](https://github.com/dmontagu). * 📍 Update MkDocs Material dependencies. PR [#9986](https://github.com/tiangolo/fastapi/pull/9986) by [@tiangolo](https://github.com/tiangolo). * 👥 Update FastAPI People. PR [#9999](https://github.com/tiangolo/fastapi/pull/9999) by [@tiangolo](https://github.com/tiangolo). * 🐳 Update Dockerfile with compatibility versions, to upgrade later. PR [#9998](https://github.com/tiangolo/fastapi/pull/9998) by [@tiangolo](https://github.com/tiangolo). From 059fb128926ae06a52af472bd91b216ce45a5997 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebasti=C3=A1n=20Ram=C3=ADrez?= Date: Thu, 3 Aug 2023 17:59:41 +0200 Subject: [PATCH 27/39] =?UTF-8?q?=F0=9F=94=A7=20Update=20the=20Question=20?= =?UTF-8?q?template=20to=20ask=20for=20the=20Pydantic=20version=20(#10000)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .github/DISCUSSION_TEMPLATE/questions.yml | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/.github/DISCUSSION_TEMPLATE/questions.yml b/.github/DISCUSSION_TEMPLATE/questions.yml index 3726b7d18dfea..98424a341db7b 100644 --- a/.github/DISCUSSION_TEMPLATE/questions.yml +++ b/.github/DISCUSSION_TEMPLATE/questions.yml @@ -123,6 +123,20 @@ body: ``` validations: required: true + - type: input + id: pydantic-version + attributes: + label: Pydantic Version + description: | + What Pydantic version are you using? + + You can find the Pydantic version with: + + ```bash + python -c "import pydantic; print(pydantic.version.VERSION)" + ``` + validations: + required: true - type: input id: python-version attributes: From 3af7265a435ebb1016dfa190c196afb045451d4f Mon Sep 17 00:00:00 2001 From: github-actions Date: Thu, 3 Aug 2023 16:00:19 +0000 Subject: [PATCH 28/39] =?UTF-8?q?=F0=9F=93=9D=20Update=20release=20notes?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docs/en/docs/release-notes.md | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/en/docs/release-notes.md b/docs/en/docs/release-notes.md index 91574addd150e..c85ef0ad29cfd 100644 --- a/docs/en/docs/release-notes.md +++ b/docs/en/docs/release-notes.md @@ -2,6 +2,7 @@ ## Latest Changes +* 🔧 Update the Question template to ask for the Pydantic version. PR [#10000](https://github.com/tiangolo/fastapi/pull/10000) by [@tiangolo](https://github.com/tiangolo). * ✅ Fix tests for compatibility with pydantic 2.1.1. PR [#9943](https://github.com/tiangolo/fastapi/pull/9943) by [@dmontagu](https://github.com/dmontagu). * 📍 Update MkDocs Material dependencies. PR [#9986](https://github.com/tiangolo/fastapi/pull/9986) by [@tiangolo](https://github.com/tiangolo). * 👥 Update FastAPI People. PR [#9999](https://github.com/tiangolo/fastapi/pull/9999) by [@tiangolo](https://github.com/tiangolo). From 86e4e9f8f9266e471192aefaac7ef55cee957a3d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebasti=C3=A1n=20Ram=C3=ADrez?= Date: Fri, 4 Aug 2023 19:47:42 +0200 Subject: [PATCH 29/39] =?UTF-8?q?=F0=9F=94=A7=20Restore=20MkDocs=20Materia?= =?UTF-8?q?l=20pin=20after=20the=20fix=20(#10001)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .github/workflows/build-docs.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/build-docs.yml b/.github/workflows/build-docs.yml index eb816b72f7699..dedf23fb9417d 100644 --- a/.github/workflows/build-docs.yml +++ b/.github/workflows/build-docs.yml @@ -51,7 +51,7 @@ jobs: # Install MkDocs Material Insiders here just to put it in the cache for the rest of the steps - name: Install Material for MkDocs Insiders if: ( github.event_name != 'pull_request' || github.event.pull_request.head.repo.fork == false ) && steps.cache.outputs.cache-hit != 'true' - run: pip install git+https://${{ secrets.FASTAPI_MKDOCS_MATERIAL_INSIDERS }}@github.com/squidfunk/mkdocs-material-insiders.git@9.1.21-insiders-4.38.0 + run: pip install git+https://${{ secrets.FASTAPI_MKDOCS_MATERIAL_INSIDERS }}@github.com/squidfunk/mkdocs-material-insiders.git - name: Export Language Codes id: show-langs run: | @@ -86,7 +86,7 @@ jobs: run: pip install -r requirements-docs.txt - name: Install Material for MkDocs Insiders if: ( github.event_name != 'pull_request' || github.event.pull_request.head.repo.fork == false ) && steps.cache.outputs.cache-hit != 'true' - run: pip install git+https://${{ secrets.FASTAPI_MKDOCS_MATERIAL_INSIDERS }}@github.com/squidfunk/mkdocs-material-insiders.git@9.1.21-insiders-4.38.0 + run: pip install git+https://${{ secrets.FASTAPI_MKDOCS_MATERIAL_INSIDERS }}@github.com/squidfunk/mkdocs-material-insiders.git - name: Update Languages run: python ./scripts/docs.py update-languages - uses: actions/cache@v3 From b3a1f910048ea60a108a8f40ee5643778047b344 Mon Sep 17 00:00:00 2001 From: github-actions Date: Fri, 4 Aug 2023 17:48:24 +0000 Subject: [PATCH 30/39] =?UTF-8?q?=F0=9F=93=9D=20Update=20release=20notes?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docs/en/docs/release-notes.md | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/en/docs/release-notes.md b/docs/en/docs/release-notes.md index c85ef0ad29cfd..dc61f76f2e168 100644 --- a/docs/en/docs/release-notes.md +++ b/docs/en/docs/release-notes.md @@ -2,6 +2,7 @@ ## Latest Changes +* 🔧 Restore MkDocs Material pin after the fix. PR [#10001](https://github.com/tiangolo/fastapi/pull/10001) by [@tiangolo](https://github.com/tiangolo). * 🔧 Update the Question template to ask for the Pydantic version. PR [#10000](https://github.com/tiangolo/fastapi/pull/10000) by [@tiangolo](https://github.com/tiangolo). * ✅ Fix tests for compatibility with pydantic 2.1.1. PR [#9943](https://github.com/tiangolo/fastapi/pull/9943) by [@dmontagu](https://github.com/dmontagu). * 📍 Update MkDocs Material dependencies. PR [#9986](https://github.com/tiangolo/fastapi/pull/9986) by [@tiangolo](https://github.com/tiangolo). From ebdf952545cbd95a16d21d48421fea7aa07e3b69 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebasti=C3=A1n=20Ram=C3=ADrez?= Date: Fri, 4 Aug 2023 20:18:38 +0200 Subject: [PATCH 31/39] =?UTF-8?q?=F0=9F=91=B7=20Add=20GitHub=20Actions=20s?= =?UTF-8?q?tep=20dump=20context=20to=20debug=20external=20failures=20(#100?= =?UTF-8?q?08)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .github/workflows/issue-manager.yml | 4 ++++ .github/workflows/label-approved.yml | 4 ++++ .github/workflows/latest-changes.yml | 4 ++++ .github/workflows/notify-translations.yml | 4 ++++ .github/workflows/people.yml | 4 ++++ .github/workflows/smokeshow.yml | 4 ++++ .github/workflows/test.yml | 16 ++++++++++++++++ 7 files changed, 40 insertions(+) diff --git a/.github/workflows/issue-manager.yml b/.github/workflows/issue-manager.yml index 32462310312c5..bb967fa118362 100644 --- a/.github/workflows/issue-manager.yml +++ b/.github/workflows/issue-manager.yml @@ -19,6 +19,10 @@ jobs: if: github.repository_owner == 'tiangolo' runs-on: ubuntu-latest steps: + - name: Dump GitHub context + env: + GITHUB_CONTEXT: ${{ toJson(github) }} + run: echo "$GITHUB_CONTEXT" - uses: tiangolo/issue-manager@0.4.0 with: token: ${{ secrets.FASTAPI_ISSUE_MANAGER }} diff --git a/.github/workflows/label-approved.yml b/.github/workflows/label-approved.yml index 976d29f74d758..2113c468ac835 100644 --- a/.github/workflows/label-approved.yml +++ b/.github/workflows/label-approved.yml @@ -9,6 +9,10 @@ jobs: if: github.repository_owner == 'tiangolo' runs-on: ubuntu-latest steps: + - name: Dump GitHub context + env: + GITHUB_CONTEXT: ${{ toJson(github) }} + run: echo "$GITHUB_CONTEXT" - uses: docker://tiangolo/label-approved:0.0.2 with: token: ${{ secrets.FASTAPI_LABEL_APPROVED }} diff --git a/.github/workflows/latest-changes.yml b/.github/workflows/latest-changes.yml index 0461f3dd3eb9f..e38870f4648fb 100644 --- a/.github/workflows/latest-changes.yml +++ b/.github/workflows/latest-changes.yml @@ -20,6 +20,10 @@ jobs: latest-changes: runs-on: ubuntu-latest steps: + - name: Dump GitHub context + env: + GITHUB_CONTEXT: ${{ toJson(github) }} + run: echo "$GITHUB_CONTEXT" - uses: actions/checkout@v3 with: # To allow latest-changes to commit to the main branch diff --git a/.github/workflows/notify-translations.yml b/.github/workflows/notify-translations.yml index cd7affbc395f9..44ee83ec02422 100644 --- a/.github/workflows/notify-translations.yml +++ b/.github/workflows/notify-translations.yml @@ -19,6 +19,10 @@ jobs: notify-translations: runs-on: ubuntu-latest steps: + - name: Dump GitHub context + env: + GITHUB_CONTEXT: ${{ toJson(github) }} + run: echo "$GITHUB_CONTEXT" - uses: actions/checkout@v3 # Allow debugging with tmate - name: Setup tmate session diff --git a/.github/workflows/people.yml b/.github/workflows/people.yml index aa7f34464e2c9..4480a1427434e 100644 --- a/.github/workflows/people.yml +++ b/.github/workflows/people.yml @@ -15,6 +15,10 @@ jobs: if: github.repository_owner == 'tiangolo' runs-on: ubuntu-latest steps: + - name: Dump GitHub context + env: + GITHUB_CONTEXT: ${{ toJson(github) }} + run: echo "$GITHUB_CONTEXT" - uses: actions/checkout@v3 # Ref: https://github.com/actions/runner/issues/2033 - name: Fix git safe.directory in container diff --git a/.github/workflows/smokeshow.yml b/.github/workflows/smokeshow.yml index c6d894d9f61eb..4e689d95c1aa0 100644 --- a/.github/workflows/smokeshow.yml +++ b/.github/workflows/smokeshow.yml @@ -14,6 +14,10 @@ jobs: runs-on: ubuntu-latest steps: + - name: Dump GitHub context + env: + GITHUB_CONTEXT: ${{ toJson(github) }} + run: echo "$GITHUB_CONTEXT" - uses: actions/setup-python@v4 with: python-version: '3.9' diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index fbaf759c3238a..6a512a019b8a5 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -13,6 +13,10 @@ jobs: lint: runs-on: ubuntu-latest steps: + - name: Dump GitHub context + env: + GITHUB_CONTEXT: ${{ toJson(github) }} + run: echo "$GITHUB_CONTEXT" - uses: actions/checkout@v3 - name: Set up Python uses: actions/setup-python@v4 @@ -42,6 +46,10 @@ jobs: pydantic-version: ["pydantic-v1", "pydantic-v2"] fail-fast: false steps: + - name: Dump GitHub context + env: + GITHUB_CONTEXT: ${{ toJson(github) }} + run: echo "$GITHUB_CONTEXT" - uses: actions/checkout@v3 - name: Set up Python uses: actions/setup-python@v4 @@ -80,6 +88,10 @@ jobs: needs: [test] runs-on: ubuntu-latest steps: + - name: Dump GitHub context + env: + GITHUB_CONTEXT: ${{ toJson(github) }} + run: echo "$GITHUB_CONTEXT" - uses: actions/checkout@v3 - uses: actions/setup-python@v4 with: @@ -110,6 +122,10 @@ jobs: - coverage-combine runs-on: ubuntu-latest steps: + - name: Dump GitHub context + env: + GITHUB_CONTEXT: ${{ toJson(github) }} + run: echo "$GITHUB_CONTEXT" - name: Decide whether the needed jobs succeeded or failed uses: re-actors/alls-green@release/v1 with: From d943e02232081a795874b00e399dcb0a0b179daf Mon Sep 17 00:00:00 2001 From: github-actions Date: Fri, 4 Aug 2023 18:19:22 +0000 Subject: [PATCH 32/39] =?UTF-8?q?=F0=9F=93=9D=20Update=20release=20notes?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docs/en/docs/release-notes.md | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/en/docs/release-notes.md b/docs/en/docs/release-notes.md index dc61f76f2e168..e45373f7b0bfa 100644 --- a/docs/en/docs/release-notes.md +++ b/docs/en/docs/release-notes.md @@ -2,6 +2,7 @@ ## Latest Changes +* 👷 Add GitHub Actions step dump context to debug external failures. PR [#10008](https://github.com/tiangolo/fastapi/pull/10008) by [@tiangolo](https://github.com/tiangolo). * 🔧 Restore MkDocs Material pin after the fix. PR [#10001](https://github.com/tiangolo/fastapi/pull/10001) by [@tiangolo](https://github.com/tiangolo). * 🔧 Update the Question template to ask for the Pydantic version. PR [#10000](https://github.com/tiangolo/fastapi/pull/10000) by [@tiangolo](https://github.com/tiangolo). * ✅ Fix tests for compatibility with pydantic 2.1.1. PR [#9943](https://github.com/tiangolo/fastapi/pull/9943) by [@dmontagu](https://github.com/dmontagu). From 19a2c3bb54ecef5fab936b45e4c262b283e100f6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebasti=C3=A1n=20Ram=C3=ADrez?= Date: Fri, 4 Aug 2023 22:47:07 +0200 Subject: [PATCH 33/39] =?UTF-8?q?=E2=9C=A8=20Enable=20Pydantic's=20seriali?= =?UTF-8?q?zation=20mode=20for=20responses,=20add=20support=20for=20Pydant?= =?UTF-8?q?ic's=20`computed=5Ffield`,=20better=20OpenAPI=20for=20response?= =?UTF-8?q?=20models,=20proper=20required=20attributes,=20better=20generat?= =?UTF-8?q?ed=20clients=20(#10011)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * ✨ Enable Pydantic's serialization mode for responses * ✅ Update tests with new Pydantic v2 serialization mode * ✅ Add a test for Pydantic v2's computed_field --- fastapi/routing.py | 4 +- tests/test_computed_fields.py | 77 +++++++ tests/test_filter_pydantic_sub_model_pv2.py | 8 +- .../test_body_updates/test_tutorial001.py | 210 ++++++++++++++--- .../test_tutorial001_py310.py | 211 +++++++++++++++--- .../test_tutorial001_py39.py | 211 +++++++++++++++--- .../test_dataclasses/test_tutorial002.py | 12 +- .../test_dataclasses/test_tutorial003.py | 185 ++++++++++++--- .../test_extra_models/test_tutorial003.py | 13 +- .../test_tutorial003_py310.py | 13 +- .../test_tutorial004.py | 155 +++++++++++-- .../test_tutorial005.py | 155 +++++++++++-- .../test_tutorial005_py310.py | 156 +++++++++++-- .../test_tutorial005_py39.py | 156 +++++++++++-- .../test_response_model/test_tutorial003.py | 8 +- .../test_tutorial003_01.py | 8 +- .../test_tutorial003_01_py310.py | 8 +- .../test_tutorial003_py310.py | 8 +- .../test_response_model/test_tutorial004.py | 8 +- .../test_tutorial004_py310.py | 8 +- .../test_tutorial004_py39.py | 8 +- .../test_response_model/test_tutorial005.py | 8 +- .../test_tutorial005_py310.py | 8 +- .../test_response_model/test_tutorial006.py | 8 +- .../test_tutorial006_py310.py | 8 +- .../test_security/test_tutorial005.py | 8 +- .../test_security/test_tutorial005_an.py | 8 +- .../test_tutorial005_an_py310.py | 8 +- .../test_security/test_tutorial005_an_py39.py | 8 +- .../test_security/test_tutorial005_py310.py | 8 +- .../test_security/test_tutorial005_py39.py | 8 +- 31 files changed, 1446 insertions(+), 256 deletions(-) create mode 100644 tests/test_computed_fields.py diff --git a/fastapi/routing.py b/fastapi/routing.py index d8ff0579cb813..6efd40ff3bc9f 100644 --- a/fastapi/routing.py +++ b/fastapi/routing.py @@ -448,9 +448,7 @@ def __init__( self.response_field = create_response_field( name=response_name, type_=self.response_model, - # TODO: This should actually set mode='serialization', just, that changes the schemas - # mode="serialization", - mode="validation", + mode="serialization", ) # Create a clone of the field, so that a Pydantic submodel is not returned # as is just because it's an instance of a subclass of a more limited class diff --git a/tests/test_computed_fields.py b/tests/test_computed_fields.py new file mode 100644 index 0000000000000..5286507b2d348 --- /dev/null +++ b/tests/test_computed_fields.py @@ -0,0 +1,77 @@ +import pytest +from fastapi import FastAPI +from fastapi.testclient import TestClient + +from .utils import needs_pydanticv2 + + +@pytest.fixture(name="client") +def get_client(): + app = FastAPI() + + from pydantic import BaseModel, computed_field + + class Rectangle(BaseModel): + width: int + length: int + + @computed_field + @property + def area(self) -> int: + return self.width * self.length + + @app.get("/") + def read_root() -> Rectangle: + return Rectangle(width=3, length=4) + + client = TestClient(app) + return client + + +@needs_pydanticv2 +def test_get(client: TestClient): + response = client.get("/") + assert response.status_code == 200, response.text + assert response.json() == {"width": 3, "length": 4, "area": 12} + + +@needs_pydanticv2 +def test_openapi_schema(client: TestClient): + response = client.get("/openapi.json") + assert response.status_code == 200, response.text + assert response.json() == { + "openapi": "3.1.0", + "info": {"title": "FastAPI", "version": "0.1.0"}, + "paths": { + "/": { + "get": { + "summary": "Read Root", + "operationId": "read_root__get", + "responses": { + "200": { + "description": "Successful Response", + "content": { + "application/json": { + "schema": {"$ref": "#/components/schemas/Rectangle"} + } + }, + } + }, + } + } + }, + "components": { + "schemas": { + "Rectangle": { + "properties": { + "width": {"type": "integer", "title": "Width"}, + "length": {"type": "integer", "title": "Length"}, + "area": {"type": "integer", "title": "Area", "readOnly": True}, + }, + "type": "object", + "required": ["width", "length", "area"], + "title": "Rectangle", + } + } + }, + } diff --git a/tests/test_filter_pydantic_sub_model_pv2.py b/tests/test_filter_pydantic_sub_model_pv2.py index ae12179bdf314..9f5e6b08fb667 100644 --- a/tests/test_filter_pydantic_sub_model_pv2.py +++ b/tests/test_filter_pydantic_sub_model_pv2.py @@ -1,7 +1,7 @@ from typing import Optional import pytest -from dirty_equals import HasRepr, IsDict +from dirty_equals import HasRepr, IsDict, IsOneOf from fastapi import Depends, FastAPI from fastapi.exceptions import ResponseValidationError from fastapi.testclient import TestClient @@ -139,7 +139,11 @@ def test_openapi_schema(client: TestClient): }, "ModelA": { "title": "ModelA", - "required": ["name", "foo"], + "required": IsOneOf( + ["name", "description", "foo"], + # TODO remove when deprecating Pydantic v1 + ["name", "foo"], + ), "type": "object", "properties": { "name": {"title": "Name", "type": "string"}, diff --git a/tests/test_tutorial/test_body_updates/test_tutorial001.py b/tests/test_tutorial/test_body_updates/test_tutorial001.py index b02f7c81c3f86..f1a46210aadea 100644 --- a/tests/test_tutorial/test_body_updates/test_tutorial001.py +++ b/tests/test_tutorial/test_body_updates/test_tutorial001.py @@ -1,7 +1,8 @@ import pytest -from dirty_equals import IsDict from fastapi.testclient import TestClient +from ...utils import needs_pydanticv1, needs_pydanticv2 + @pytest.fixture(name="client") def get_client(): @@ -36,7 +37,181 @@ def test_put(client: TestClient): } +@needs_pydanticv2 def test_openapi_schema(client: TestClient): + response = client.get("/openapi.json") + assert response.status_code == 200, response.text + assert response.json() == { + "openapi": "3.1.0", + "info": {"title": "FastAPI", "version": "0.1.0"}, + "paths": { + "/items/{item_id}": { + "get": { + "responses": { + "200": { + "description": "Successful Response", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ItemOutput" + } + } + }, + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + }, + }, + "summary": "Read Item", + "operationId": "read_item_items__item_id__get", + "parameters": [ + { + "required": True, + "schema": {"title": "Item Id", "type": "string"}, + "name": "item_id", + "in": "path", + } + ], + }, + "put": { + "responses": { + "200": { + "description": "Successful Response", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ItemOutput" + } + } + }, + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + }, + }, + "summary": "Update Item", + "operationId": "update_item_items__item_id__put", + "parameters": [ + { + "required": True, + "schema": {"title": "Item Id", "type": "string"}, + "name": "item_id", + "in": "path", + } + ], + "requestBody": { + "content": { + "application/json": { + "schema": {"$ref": "#/components/schemas/ItemInput"} + } + }, + "required": True, + }, + }, + } + }, + "components": { + "schemas": { + "ItemInput": { + "title": "Item", + "type": "object", + "properties": { + "name": { + "title": "Name", + "anyOf": [{"type": "string"}, {"type": "null"}], + }, + "description": { + "title": "Description", + "anyOf": [{"type": "string"}, {"type": "null"}], + }, + "price": { + "title": "Price", + "anyOf": [{"type": "number"}, {"type": "null"}], + }, + "tax": {"title": "Tax", "type": "number", "default": 10.5}, + "tags": { + "title": "Tags", + "type": "array", + "items": {"type": "string"}, + "default": [], + }, + }, + }, + "ItemOutput": { + "title": "Item", + "type": "object", + "required": ["name", "description", "price", "tax", "tags"], + "properties": { + "name": { + "anyOf": [{"type": "string"}, {"type": "null"}], + "title": "Name", + }, + "description": { + "anyOf": [{"type": "string"}, {"type": "null"}], + "title": "Description", + }, + "price": { + "anyOf": [{"type": "number"}, {"type": "null"}], + "title": "Price", + }, + "tax": {"title": "Tax", "type": "number", "default": 10.5}, + "tags": { + "title": "Tags", + "type": "array", + "items": {"type": "string"}, + "default": [], + }, + }, + }, + "ValidationError": { + "title": "ValidationError", + "required": ["loc", "msg", "type"], + "type": "object", + "properties": { + "loc": { + "title": "Location", + "type": "array", + "items": { + "anyOf": [{"type": "string"}, {"type": "integer"}] + }, + }, + "msg": {"title": "Message", "type": "string"}, + "type": {"title": "Error Type", "type": "string"}, + }, + }, + "HTTPValidationError": { + "title": "HTTPValidationError", + "type": "object", + "properties": { + "detail": { + "title": "Detail", + "type": "array", + "items": {"$ref": "#/components/schemas/ValidationError"}, + } + }, + }, + } + }, + } + + +# TODO: remove when deprecating Pydantic v1 +@needs_pydanticv1 +def test_openapi_schema_pv1(client: TestClient): response = client.get("/openapi.json") assert response.status_code == 200, response.text assert response.json() == { @@ -124,36 +299,9 @@ def test_openapi_schema(client: TestClient): "title": "Item", "type": "object", "properties": { - "name": IsDict( - { - "title": "Name", - "anyOf": [{"type": "string"}, {"type": "null"}], - } - ) - | IsDict( - # TODO: remove when deprecating Pydantic v1 - {"title": "Name", "type": "string"} - ), - "description": IsDict( - { - "title": "Description", - "anyOf": [{"type": "string"}, {"type": "null"}], - } - ) - | IsDict( - # TODO: remove when deprecating Pydantic v1 - {"title": "Description", "type": "string"} - ), - "price": IsDict( - { - "title": "Price", - "anyOf": [{"type": "number"}, {"type": "null"}], - } - ) - | IsDict( - # TODO: remove when deprecating Pydantic v1 - {"title": "Price", "type": "number"} - ), + "name": {"title": "Name", "type": "string"}, + "description": {"title": "Description", "type": "string"}, + "price": {"title": "Price", "type": "number"}, "tax": {"title": "Tax", "type": "number", "default": 10.5}, "tags": { "title": "Tags", diff --git a/tests/test_tutorial/test_body_updates/test_tutorial001_py310.py b/tests/test_tutorial/test_body_updates/test_tutorial001_py310.py index 4af2652a78e36..ab696e4c8dfec 100644 --- a/tests/test_tutorial/test_body_updates/test_tutorial001_py310.py +++ b/tests/test_tutorial/test_body_updates/test_tutorial001_py310.py @@ -1,8 +1,7 @@ import pytest -from dirty_equals import IsDict from fastapi.testclient import TestClient -from ...utils import needs_py310 +from ...utils import needs_py310, needs_pydanticv1, needs_pydanticv2 @pytest.fixture(name="client") @@ -41,7 +40,182 @@ def test_put(client: TestClient): @needs_py310 +@needs_pydanticv2 def test_openapi_schema(client: TestClient): + response = client.get("/openapi.json") + assert response.status_code == 200, response.text + assert response.json() == { + "openapi": "3.1.0", + "info": {"title": "FastAPI", "version": "0.1.0"}, + "paths": { + "/items/{item_id}": { + "get": { + "responses": { + "200": { + "description": "Successful Response", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ItemOutput" + } + } + }, + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + }, + }, + "summary": "Read Item", + "operationId": "read_item_items__item_id__get", + "parameters": [ + { + "required": True, + "schema": {"title": "Item Id", "type": "string"}, + "name": "item_id", + "in": "path", + } + ], + }, + "put": { + "responses": { + "200": { + "description": "Successful Response", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ItemOutput" + } + } + }, + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + }, + }, + "summary": "Update Item", + "operationId": "update_item_items__item_id__put", + "parameters": [ + { + "required": True, + "schema": {"title": "Item Id", "type": "string"}, + "name": "item_id", + "in": "path", + } + ], + "requestBody": { + "content": { + "application/json": { + "schema": {"$ref": "#/components/schemas/ItemInput"} + } + }, + "required": True, + }, + }, + } + }, + "components": { + "schemas": { + "ItemInput": { + "title": "Item", + "type": "object", + "properties": { + "name": { + "title": "Name", + "anyOf": [{"type": "string"}, {"type": "null"}], + }, + "description": { + "title": "Description", + "anyOf": [{"type": "string"}, {"type": "null"}], + }, + "price": { + "title": "Price", + "anyOf": [{"type": "number"}, {"type": "null"}], + }, + "tax": {"title": "Tax", "type": "number", "default": 10.5}, + "tags": { + "title": "Tags", + "type": "array", + "items": {"type": "string"}, + "default": [], + }, + }, + }, + "ItemOutput": { + "title": "Item", + "type": "object", + "required": ["name", "description", "price", "tax", "tags"], + "properties": { + "name": { + "anyOf": [{"type": "string"}, {"type": "null"}], + "title": "Name", + }, + "description": { + "anyOf": [{"type": "string"}, {"type": "null"}], + "title": "Description", + }, + "price": { + "anyOf": [{"type": "number"}, {"type": "null"}], + "title": "Price", + }, + "tax": {"title": "Tax", "type": "number", "default": 10.5}, + "tags": { + "title": "Tags", + "type": "array", + "items": {"type": "string"}, + "default": [], + }, + }, + }, + "ValidationError": { + "title": "ValidationError", + "required": ["loc", "msg", "type"], + "type": "object", + "properties": { + "loc": { + "title": "Location", + "type": "array", + "items": { + "anyOf": [{"type": "string"}, {"type": "integer"}] + }, + }, + "msg": {"title": "Message", "type": "string"}, + "type": {"title": "Error Type", "type": "string"}, + }, + }, + "HTTPValidationError": { + "title": "HTTPValidationError", + "type": "object", + "properties": { + "detail": { + "title": "Detail", + "type": "array", + "items": {"$ref": "#/components/schemas/ValidationError"}, + } + }, + }, + } + }, + } + + +# TODO: remove when deprecating Pydantic v1 +@needs_py310 +@needs_pydanticv1 +def test_openapi_schema_pv1(client: TestClient): response = client.get("/openapi.json") assert response.status_code == 200, response.text assert response.json() == { @@ -129,36 +303,9 @@ def test_openapi_schema(client: TestClient): "title": "Item", "type": "object", "properties": { - "name": IsDict( - { - "title": "Name", - "anyOf": [{"type": "string"}, {"type": "null"}], - } - ) - | IsDict( - # TODO: remove when deprecating Pydantic v1 - {"title": "Name", "type": "string"} - ), - "description": IsDict( - { - "title": "Description", - "anyOf": [{"type": "string"}, {"type": "null"}], - } - ) - | IsDict( - # TODO: remove when deprecating Pydantic v1 - {"title": "Description", "type": "string"} - ), - "price": IsDict( - { - "title": "Price", - "anyOf": [{"type": "number"}, {"type": "null"}], - } - ) - | IsDict( - # TODO: remove when deprecating Pydantic v1 - {"title": "Price", "type": "number"} - ), + "name": {"title": "Name", "type": "string"}, + "description": {"title": "Description", "type": "string"}, + "price": {"title": "Price", "type": "number"}, "tax": {"title": "Tax", "type": "number", "default": 10.5}, "tags": { "title": "Tags", diff --git a/tests/test_tutorial/test_body_updates/test_tutorial001_py39.py b/tests/test_tutorial/test_body_updates/test_tutorial001_py39.py index 832f453884439..2ee6a5cb4c695 100644 --- a/tests/test_tutorial/test_body_updates/test_tutorial001_py39.py +++ b/tests/test_tutorial/test_body_updates/test_tutorial001_py39.py @@ -1,8 +1,7 @@ import pytest -from dirty_equals import IsDict from fastapi.testclient import TestClient -from ...utils import needs_py39 +from ...utils import needs_py39, needs_pydanticv1, needs_pydanticv2 @pytest.fixture(name="client") @@ -41,7 +40,182 @@ def test_put(client: TestClient): @needs_py39 +@needs_pydanticv2 def test_openapi_schema(client: TestClient): + response = client.get("/openapi.json") + assert response.status_code == 200, response.text + assert response.json() == { + "openapi": "3.1.0", + "info": {"title": "FastAPI", "version": "0.1.0"}, + "paths": { + "/items/{item_id}": { + "get": { + "responses": { + "200": { + "description": "Successful Response", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ItemOutput" + } + } + }, + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + }, + }, + "summary": "Read Item", + "operationId": "read_item_items__item_id__get", + "parameters": [ + { + "required": True, + "schema": {"title": "Item Id", "type": "string"}, + "name": "item_id", + "in": "path", + } + ], + }, + "put": { + "responses": { + "200": { + "description": "Successful Response", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ItemOutput" + } + } + }, + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + }, + }, + "summary": "Update Item", + "operationId": "update_item_items__item_id__put", + "parameters": [ + { + "required": True, + "schema": {"title": "Item Id", "type": "string"}, + "name": "item_id", + "in": "path", + } + ], + "requestBody": { + "content": { + "application/json": { + "schema": {"$ref": "#/components/schemas/ItemInput"} + } + }, + "required": True, + }, + }, + } + }, + "components": { + "schemas": { + "ItemInput": { + "title": "Item", + "type": "object", + "properties": { + "name": { + "title": "Name", + "anyOf": [{"type": "string"}, {"type": "null"}], + }, + "description": { + "title": "Description", + "anyOf": [{"type": "string"}, {"type": "null"}], + }, + "price": { + "title": "Price", + "anyOf": [{"type": "number"}, {"type": "null"}], + }, + "tax": {"title": "Tax", "type": "number", "default": 10.5}, + "tags": { + "title": "Tags", + "type": "array", + "items": {"type": "string"}, + "default": [], + }, + }, + }, + "ItemOutput": { + "title": "Item", + "type": "object", + "required": ["name", "description", "price", "tax", "tags"], + "properties": { + "name": { + "anyOf": [{"type": "string"}, {"type": "null"}], + "title": "Name", + }, + "description": { + "anyOf": [{"type": "string"}, {"type": "null"}], + "title": "Description", + }, + "price": { + "anyOf": [{"type": "number"}, {"type": "null"}], + "title": "Price", + }, + "tax": {"title": "Tax", "type": "number", "default": 10.5}, + "tags": { + "title": "Tags", + "type": "array", + "items": {"type": "string"}, + "default": [], + }, + }, + }, + "ValidationError": { + "title": "ValidationError", + "required": ["loc", "msg", "type"], + "type": "object", + "properties": { + "loc": { + "title": "Location", + "type": "array", + "items": { + "anyOf": [{"type": "string"}, {"type": "integer"}] + }, + }, + "msg": {"title": "Message", "type": "string"}, + "type": {"title": "Error Type", "type": "string"}, + }, + }, + "HTTPValidationError": { + "title": "HTTPValidationError", + "type": "object", + "properties": { + "detail": { + "title": "Detail", + "type": "array", + "items": {"$ref": "#/components/schemas/ValidationError"}, + } + }, + }, + } + }, + } + + +# TODO: remove when deprecating Pydantic v1 +@needs_py39 +@needs_pydanticv1 +def test_openapi_schema_pv1(client: TestClient): response = client.get("/openapi.json") assert response.status_code == 200, response.text assert response.json() == { @@ -129,36 +303,9 @@ def test_openapi_schema(client: TestClient): "title": "Item", "type": "object", "properties": { - "name": IsDict( - { - "title": "Name", - "anyOf": [{"type": "string"}, {"type": "null"}], - } - ) - | IsDict( - # TODO: remove when deprecating Pydantic v1 - {"title": "Name", "type": "string"} - ), - "description": IsDict( - { - "title": "Description", - "anyOf": [{"type": "string"}, {"type": "null"}], - } - ) - | IsDict( - # TODO: remove when deprecating Pydantic v1 - {"title": "Description", "type": "string"} - ), - "price": IsDict( - { - "title": "Price", - "anyOf": [{"type": "number"}, {"type": "null"}], - } - ) - | IsDict( - # TODO: remove when deprecating Pydantic v1 - {"title": "Price", "type": "number"} - ), + "name": {"title": "Name", "type": "string"}, + "description": {"title": "Description", "type": "string"}, + "price": {"title": "Price", "type": "number"}, "tax": {"title": "Tax", "type": "number", "default": 10.5}, "tags": { "title": "Tags", diff --git a/tests/test_tutorial/test_dataclasses/test_tutorial002.py b/tests/test_tutorial/test_dataclasses/test_tutorial002.py index 7d88e286168c4..4146f4cd65dfe 100644 --- a/tests/test_tutorial/test_dataclasses/test_tutorial002.py +++ b/tests/test_tutorial/test_dataclasses/test_tutorial002.py @@ -1,4 +1,4 @@ -from dirty_equals import IsDict +from dirty_equals import IsDict, IsOneOf from fastapi.testclient import TestClient from docs_src.dataclasses.tutorial002 import app @@ -21,8 +21,7 @@ def test_get_item(): def test_openapi_schema(): response = client.get("/openapi.json") assert response.status_code == 200 - data = response.json() - assert data == { + assert response.json() == { "openapi": "3.1.0", "info": {"title": "FastAPI", "version": "0.1.0"}, "paths": { @@ -47,7 +46,11 @@ def test_openapi_schema(): "schemas": { "Item": { "title": "Item", - "required": ["name", "price"], + "required": IsOneOf( + ["name", "price", "tags", "description", "tax"], + # TODO: remove when deprecating Pydantic v1 + ["name", "price"], + ), "type": "object", "properties": { "name": {"title": "Name", "type": "string"}, @@ -57,7 +60,6 @@ def test_openapi_schema(): "title": "Tags", "type": "array", "items": {"type": "string"}, - "default": [], } ) | IsDict( diff --git a/tests/test_tutorial/test_dataclasses/test_tutorial003.py b/tests/test_tutorial/test_dataclasses/test_tutorial003.py index 597757e0931c9..2e5809914f850 100644 --- a/tests/test_tutorial/test_dataclasses/test_tutorial003.py +++ b/tests/test_tutorial/test_dataclasses/test_tutorial003.py @@ -1,8 +1,9 @@ -from dirty_equals import IsDict from fastapi.testclient import TestClient from docs_src.dataclasses.tutorial003 import app +from ...utils import needs_pydanticv1, needs_pydanticv2 + client = TestClient(app) @@ -52,6 +53,7 @@ def test_get_authors(): ] +@needs_pydanticv2 def test_openapi_schema(): response = client.get("/openapi.json") assert response.status_code == 200 @@ -77,7 +79,7 @@ def test_openapi_schema(): "schema": { "title": "Items", "type": "array", - "items": {"$ref": "#/components/schemas/Item"}, + "items": {"$ref": "#/components/schemas/ItemInput"}, } } }, @@ -132,26 +134,164 @@ def test_openapi_schema(): "schemas": { "Author": { "title": "Author", + "required": ["name", "items"], + "type": "object", + "properties": { + "name": {"title": "Name", "type": "string"}, + "items": { + "title": "Items", + "type": "array", + "items": {"$ref": "#/components/schemas/ItemOutput"}, + }, + }, + }, + "HTTPValidationError": { + "title": "HTTPValidationError", + "type": "object", + "properties": { + "detail": { + "title": "Detail", + "type": "array", + "items": {"$ref": "#/components/schemas/ValidationError"}, + } + }, + }, + "ItemInput": { + "title": "Item", "required": ["name"], "type": "object", "properties": { "name": {"title": "Name", "type": "string"}, - "items": IsDict( - { - "title": "Items", - "type": "array", - "items": {"$ref": "#/components/schemas/Item"}, - "default": [], - } - ) - | IsDict( - # TODO: remove when deprecating Pydantic v1 - { - "title": "Items", - "type": "array", - "items": {"$ref": "#/components/schemas/Item"}, + "description": { + "title": "Description", + "anyOf": [{"type": "string"}, {"type": "null"}], + }, + }, + }, + "ItemOutput": { + "title": "Item", + "required": ["name", "description"], + "type": "object", + "properties": { + "name": {"title": "Name", "type": "string"}, + "description": { + "title": "Description", + "anyOf": [{"type": "string"}, {"type": "null"}], + }, + }, + }, + "ValidationError": { + "title": "ValidationError", + "required": ["loc", "msg", "type"], + "type": "object", + "properties": { + "loc": { + "title": "Location", + "type": "array", + "items": { + "anyOf": [{"type": "string"}, {"type": "integer"}] + }, + }, + "msg": {"title": "Message", "type": "string"}, + "type": {"title": "Error Type", "type": "string"}, + }, + }, + } + }, + } + + +# TODO: remove when deprecating Pydantic v1 +@needs_pydanticv1 +def test_openapi_schema_pv1(): + response = client.get("/openapi.json") + assert response.status_code == 200 + assert response.json() == { + "openapi": "3.1.0", + "info": {"title": "FastAPI", "version": "0.1.0"}, + "paths": { + "/authors/{author_id}/items/": { + "post": { + "summary": "Create Author Items", + "operationId": "create_author_items_authors__author_id__items__post", + "parameters": [ + { + "required": True, + "schema": {"title": "Author Id", "type": "string"}, + "name": "author_id", + "in": "path", + } + ], + "requestBody": { + "content": { + "application/json": { + "schema": { + "title": "Items", + "type": "array", + "items": {"$ref": "#/components/schemas/Item"}, + } } - ), + }, + "required": True, + }, + "responses": { + "200": { + "description": "Successful Response", + "content": { + "application/json": { + "schema": {"$ref": "#/components/schemas/Author"} + } + }, + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + }, + }, + } + }, + "/authors/": { + "get": { + "summary": "Get Authors", + "operationId": "get_authors_authors__get", + "responses": { + "200": { + "description": "Successful Response", + "content": { + "application/json": { + "schema": { + "title": "Response Get Authors Authors Get", + "type": "array", + "items": { + "$ref": "#/components/schemas/Author" + }, + } + } + }, + } + }, + } + }, + }, + "components": { + "schemas": { + "Author": { + "title": "Author", + "required": ["name"], + "type": "object", + "properties": { + "name": {"title": "Name", "type": "string"}, + "items": { + "title": "Items", + "type": "array", + "items": {"$ref": "#/components/schemas/Item"}, + }, }, }, "HTTPValidationError": { @@ -171,16 +311,7 @@ def test_openapi_schema(): "type": "object", "properties": { "name": {"title": "Name", "type": "string"}, - "description": IsDict( - { - "title": "Description", - "anyOf": [{"type": "string"}, {"type": "null"}], - } - ) - | IsDict( - # TODO: remove when deprecating Pydantic v1 - {"title": "Description", "type": "string"} - ), + "description": {"title": "Description", "type": "string"}, }, }, "ValidationError": { diff --git a/tests/test_tutorial/test_extra_models/test_tutorial003.py b/tests/test_tutorial/test_extra_models/test_tutorial003.py index 21192b7db752e..0ccb99948f381 100644 --- a/tests/test_tutorial/test_extra_models/test_tutorial003.py +++ b/tests/test_tutorial/test_extra_models/test_tutorial003.py @@ -1,3 +1,4 @@ +from dirty_equals import IsOneOf from fastapi.testclient import TestClient from docs_src.extra_models.tutorial003 import app @@ -76,7 +77,11 @@ def test_openapi_schema(): "schemas": { "PlaneItem": { "title": "PlaneItem", - "required": ["description", "size"], + "required": IsOneOf( + ["description", "type", "size"], + # TODO: remove when deprecating Pydantic v1 + ["description", "size"], + ), "type": "object", "properties": { "description": {"title": "Description", "type": "string"}, @@ -86,7 +91,11 @@ def test_openapi_schema(): }, "CarItem": { "title": "CarItem", - "required": ["description"], + "required": IsOneOf( + ["description", "type"], + # TODO: remove when deprecating Pydantic v1 + ["description"], + ), "type": "object", "properties": { "description": {"title": "Description", "type": "string"}, diff --git a/tests/test_tutorial/test_extra_models/test_tutorial003_py310.py b/tests/test_tutorial/test_extra_models/test_tutorial003_py310.py index c17ddbbe1d550..b2fe65fd9ffb6 100644 --- a/tests/test_tutorial/test_extra_models/test_tutorial003_py310.py +++ b/tests/test_tutorial/test_extra_models/test_tutorial003_py310.py @@ -1,4 +1,5 @@ import pytest +from dirty_equals import IsOneOf from fastapi.testclient import TestClient from ...utils import needs_py310 @@ -86,7 +87,11 @@ def test_openapi_schema(client: TestClient): "schemas": { "PlaneItem": { "title": "PlaneItem", - "required": ["description", "size"], + "required": IsOneOf( + ["description", "type", "size"], + # TODO: remove when deprecating Pydantic v1 + ["description", "size"], + ), "type": "object", "properties": { "description": {"title": "Description", "type": "string"}, @@ -96,7 +101,11 @@ def test_openapi_schema(client: TestClient): }, "CarItem": { "title": "CarItem", - "required": ["description"], + "required": IsOneOf( + ["description", "type"], + # TODO: remove when deprecating Pydantic v1 + ["description"], + ), "type": "object", "properties": { "description": {"title": "Description", "type": "string"}, diff --git a/tests/test_tutorial/test_path_operation_advanced_configurations/test_tutorial004.py b/tests/test_tutorial/test_path_operation_advanced_configurations/test_tutorial004.py index dd123f48d6e8c..3ffc0bca7ce62 100644 --- a/tests/test_tutorial/test_path_operation_advanced_configurations/test_tutorial004.py +++ b/tests/test_tutorial/test_path_operation_advanced_configurations/test_tutorial004.py @@ -1,8 +1,9 @@ -from dirty_equals import IsDict from fastapi.testclient import TestClient from docs_src.path_operation_advanced_configuration.tutorial004 import app +from ...utils import needs_pydanticv1, needs_pydanticv2 + client = TestClient(app) @@ -18,7 +19,137 @@ def test_query_params_str_validations(): } +@needs_pydanticv2 def test_openapi_schema(): + response = client.get("/openapi.json") + assert response.status_code == 200, response.text + assert response.json() == { + "openapi": "3.1.0", + "info": {"title": "FastAPI", "version": "0.1.0"}, + "paths": { + "/items/": { + "post": { + "responses": { + "200": { + "description": "Successful Response", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ItemOutput" + } + } + }, + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + }, + }, + "summary": "Create an item", + "description": "Create an item with all the information:\n\n- **name**: each item must have a name\n- **description**: a long description\n- **price**: required\n- **tax**: if the item doesn't have tax, you can omit this\n- **tags**: a set of unique tag strings for this item", + "operationId": "create_item_items__post", + "requestBody": { + "content": { + "application/json": { + "schema": {"$ref": "#/components/schemas/ItemInput"} + } + }, + "required": True, + }, + } + } + }, + "components": { + "schemas": { + "ItemInput": { + "title": "Item", + "required": ["name", "price"], + "type": "object", + "properties": { + "name": {"title": "Name", "type": "string"}, + "description": { + "title": "Description", + "anyOf": [{"type": "string"}, {"type": "null"}], + }, + "price": {"title": "Price", "type": "number"}, + "tax": { + "title": "Tax", + "anyOf": [{"type": "number"}, {"type": "null"}], + }, + "tags": { + "title": "Tags", + "uniqueItems": True, + "type": "array", + "items": {"type": "string"}, + "default": [], + }, + }, + }, + "ItemOutput": { + "title": "Item", + "required": ["name", "description", "price", "tax", "tags"], + "type": "object", + "properties": { + "name": {"title": "Name", "type": "string"}, + "description": { + "title": "Description", + "anyOf": [{"type": "string"}, {"type": "null"}], + }, + "price": {"title": "Price", "type": "number"}, + "tax": { + "title": "Tax", + "anyOf": [{"type": "number"}, {"type": "null"}], + }, + "tags": { + "title": "Tags", + "uniqueItems": True, + "type": "array", + "items": {"type": "string"}, + "default": [], + }, + }, + }, + "ValidationError": { + "title": "ValidationError", + "required": ["loc", "msg", "type"], + "type": "object", + "properties": { + "loc": { + "title": "Location", + "type": "array", + "items": { + "anyOf": [{"type": "string"}, {"type": "integer"}] + }, + }, + "msg": {"title": "Message", "type": "string"}, + "type": {"title": "Error Type", "type": "string"}, + }, + }, + "HTTPValidationError": { + "title": "HTTPValidationError", + "type": "object", + "properties": { + "detail": { + "title": "Detail", + "type": "array", + "items": {"$ref": "#/components/schemas/ValidationError"}, + } + }, + }, + } + }, + } + + +# TODO: remove when deprecating Pydantic v1 +@needs_pydanticv1 +def test_openapi_schema_pv1(): response = client.get("/openapi.json") assert response.status_code == 200, response.text assert response.json() == { @@ -69,27 +200,9 @@ def test_openapi_schema(): "type": "object", "properties": { "name": {"title": "Name", "type": "string"}, - "description": IsDict( - { - "title": "Description", - "anyOf": [{"type": "string"}, {"type": "null"}], - } - ) - | IsDict( - # TODO: remove when deprecating Pydantic v1 - {"title": "Description", "type": "string"} - ), + "description": {"title": "Description", "type": "string"}, "price": {"title": "Price", "type": "number"}, - "tax": IsDict( - { - "title": "Tax", - "anyOf": [{"type": "number"}, {"type": "null"}], - } - ) - | IsDict( - # TODO: remove when deprecating Pydantic v1 - {"title": "Tax", "type": "number"} - ), + "tax": {"title": "Tax", "type": "number"}, "tags": { "title": "Tags", "uniqueItems": True, diff --git a/tests/test_tutorial/test_path_operation_configurations/test_tutorial005.py b/tests/test_tutorial/test_path_operation_configurations/test_tutorial005.py index e7e9a982e1f33..ff98295a60a44 100644 --- a/tests/test_tutorial/test_path_operation_configurations/test_tutorial005.py +++ b/tests/test_tutorial/test_path_operation_configurations/test_tutorial005.py @@ -1,8 +1,9 @@ -from dirty_equals import IsDict from fastapi.testclient import TestClient from docs_src.path_operation_configuration.tutorial005 import app +from ...utils import needs_pydanticv1, needs_pydanticv2 + client = TestClient(app) @@ -18,7 +19,137 @@ def test_query_params_str_validations(): } +@needs_pydanticv2 def test_openapi_schema(): + response = client.get("/openapi.json") + assert response.status_code == 200, response.text + assert response.json() == { + "openapi": "3.1.0", + "info": {"title": "FastAPI", "version": "0.1.0"}, + "paths": { + "/items/": { + "post": { + "responses": { + "200": { + "description": "The created item", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ItemOutput" + } + } + }, + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + }, + }, + "summary": "Create an item", + "description": "Create an item with all the information:\n\n- **name**: each item must have a name\n- **description**: a long description\n- **price**: required\n- **tax**: if the item doesn't have tax, you can omit this\n- **tags**: a set of unique tag strings for this item", + "operationId": "create_item_items__post", + "requestBody": { + "content": { + "application/json": { + "schema": {"$ref": "#/components/schemas/ItemInput"} + } + }, + "required": True, + }, + } + } + }, + "components": { + "schemas": { + "ItemInput": { + "title": "Item", + "required": ["name", "price"], + "type": "object", + "properties": { + "name": {"title": "Name", "type": "string"}, + "description": { + "title": "Description", + "anyOf": [{"type": "string"}, {"type": "null"}], + }, + "price": {"title": "Price", "type": "number"}, + "tax": { + "title": "Tax", + "anyOf": [{"type": "number"}, {"type": "null"}], + }, + "tags": { + "title": "Tags", + "uniqueItems": True, + "type": "array", + "items": {"type": "string"}, + "default": [], + }, + }, + }, + "ItemOutput": { + "title": "Item", + "required": ["name", "description", "price", "tax", "tags"], + "type": "object", + "properties": { + "name": {"title": "Name", "type": "string"}, + "description": { + "anyOf": [{"type": "string"}, {"type": "null"}], + "title": "Description", + }, + "price": {"title": "Price", "type": "number"}, + "tax": { + "title": "Tax", + "anyOf": [{"type": "number"}, {"type": "null"}], + }, + "tags": { + "title": "Tags", + "uniqueItems": True, + "type": "array", + "items": {"type": "string"}, + "default": [], + }, + }, + }, + "ValidationError": { + "title": "ValidationError", + "required": ["loc", "msg", "type"], + "type": "object", + "properties": { + "loc": { + "title": "Location", + "type": "array", + "items": { + "anyOf": [{"type": "string"}, {"type": "integer"}] + }, + }, + "msg": {"title": "Message", "type": "string"}, + "type": {"title": "Error Type", "type": "string"}, + }, + }, + "HTTPValidationError": { + "title": "HTTPValidationError", + "type": "object", + "properties": { + "detail": { + "title": "Detail", + "type": "array", + "items": {"$ref": "#/components/schemas/ValidationError"}, + } + }, + }, + } + }, + } + + +# TODO: remove when deprecating Pydantic v1 +@needs_pydanticv1 +def test_openapi_schema_pv1(): response = client.get("/openapi.json") assert response.status_code == 200, response.text assert response.json() == { @@ -69,27 +200,9 @@ def test_openapi_schema(): "type": "object", "properties": { "name": {"title": "Name", "type": "string"}, - "description": IsDict( - { - "title": "Description", - "anyOf": [{"type": "string"}, {"type": "null"}], - } - ) - | IsDict( - # TODO: remove when deprecating Pydantic v1 - {"title": "Description", "type": "string"} - ), + "description": {"title": "Description", "type": "string"}, "price": {"title": "Price", "type": "number"}, - "tax": IsDict( - { - "title": "Tax", - "anyOf": [{"type": "number"}, {"type": "null"}], - } - ) - | IsDict( - # TODO: remove when deprecating Pydantic v1 - {"title": "Tax", "type": "number"} - ), + "tax": {"title": "Tax", "type": "number"}, "tags": { "title": "Tags", "uniqueItems": True, diff --git a/tests/test_tutorial/test_path_operation_configurations/test_tutorial005_py310.py b/tests/test_tutorial/test_path_operation_configurations/test_tutorial005_py310.py index ebfeb809cc3a1..ad1c09eaec508 100644 --- a/tests/test_tutorial/test_path_operation_configurations/test_tutorial005_py310.py +++ b/tests/test_tutorial/test_path_operation_configurations/test_tutorial005_py310.py @@ -1,8 +1,7 @@ import pytest -from dirty_equals import IsDict from fastapi.testclient import TestClient -from ...utils import needs_py310 +from ...utils import needs_py310, needs_pydanticv1, needs_pydanticv2 @pytest.fixture(name="client") @@ -27,7 +26,138 @@ def test_query_params_str_validations(client: TestClient): @needs_py310 +@needs_pydanticv2 def test_openapi_schema(client: TestClient): + response = client.get("/openapi.json") + assert response.status_code == 200, response.text + assert response.json() == { + "openapi": "3.1.0", + "info": {"title": "FastAPI", "version": "0.1.0"}, + "paths": { + "/items/": { + "post": { + "responses": { + "200": { + "description": "The created item", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ItemOutput" + } + } + }, + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + }, + }, + "summary": "Create an item", + "description": "Create an item with all the information:\n\n- **name**: each item must have a name\n- **description**: a long description\n- **price**: required\n- **tax**: if the item doesn't have tax, you can omit this\n- **tags**: a set of unique tag strings for this item", + "operationId": "create_item_items__post", + "requestBody": { + "content": { + "application/json": { + "schema": {"$ref": "#/components/schemas/ItemInput"} + } + }, + "required": True, + }, + } + } + }, + "components": { + "schemas": { + "ItemInput": { + "title": "Item", + "required": ["name", "price"], + "type": "object", + "properties": { + "name": {"title": "Name", "type": "string"}, + "description": { + "title": "Description", + "anyOf": [{"type": "string"}, {"type": "null"}], + }, + "price": {"title": "Price", "type": "number"}, + "tax": { + "title": "Tax", + "anyOf": [{"type": "number"}, {"type": "null"}], + }, + "tags": { + "title": "Tags", + "uniqueItems": True, + "type": "array", + "items": {"type": "string"}, + "default": [], + }, + }, + }, + "ItemOutput": { + "title": "Item", + "required": ["name", "description", "price", "tax", "tags"], + "type": "object", + "properties": { + "name": {"title": "Name", "type": "string"}, + "description": { + "anyOf": [{"type": "string"}, {"type": "null"}], + "title": "Description", + }, + "price": {"title": "Price", "type": "number"}, + "tax": { + "title": "Tax", + "anyOf": [{"type": "number"}, {"type": "null"}], + }, + "tags": { + "title": "Tags", + "uniqueItems": True, + "type": "array", + "items": {"type": "string"}, + "default": [], + }, + }, + }, + "ValidationError": { + "title": "ValidationError", + "required": ["loc", "msg", "type"], + "type": "object", + "properties": { + "loc": { + "title": "Location", + "type": "array", + "items": { + "anyOf": [{"type": "string"}, {"type": "integer"}] + }, + }, + "msg": {"title": "Message", "type": "string"}, + "type": {"title": "Error Type", "type": "string"}, + }, + }, + "HTTPValidationError": { + "title": "HTTPValidationError", + "type": "object", + "properties": { + "detail": { + "title": "Detail", + "type": "array", + "items": {"$ref": "#/components/schemas/ValidationError"}, + } + }, + }, + } + }, + } + + +# TODO: remove when deprecating Pydantic v1 +@needs_py310 +@needs_pydanticv1 +def test_openapi_schema_pv1(client: TestClient): response = client.get("/openapi.json") assert response.status_code == 200, response.text assert response.json() == { @@ -78,27 +208,9 @@ def test_openapi_schema(client: TestClient): "type": "object", "properties": { "name": {"title": "Name", "type": "string"}, - "description": IsDict( - { - "title": "Description", - "anyOf": [{"type": "string"}, {"type": "null"}], - } - ) - | IsDict( - # TODO: remove when deprecating Pydantic v1 - {"title": "Description", "type": "string"} - ), + "description": {"title": "Description", "type": "string"}, "price": {"title": "Price", "type": "number"}, - "tax": IsDict( - { - "title": "Tax", - "anyOf": [{"type": "number"}, {"type": "null"}], - } - ) - | IsDict( - # TODO: remove when deprecating Pydantic v1 - {"title": "Tax", "type": "number"} - ), + "tax": {"title": "Tax", "type": "number"}, "tags": { "title": "Tags", "uniqueItems": True, diff --git a/tests/test_tutorial/test_path_operation_configurations/test_tutorial005_py39.py b/tests/test_tutorial/test_path_operation_configurations/test_tutorial005_py39.py index 8e79afe968843..045d1d402c949 100644 --- a/tests/test_tutorial/test_path_operation_configurations/test_tutorial005_py39.py +++ b/tests/test_tutorial/test_path_operation_configurations/test_tutorial005_py39.py @@ -1,8 +1,7 @@ import pytest -from dirty_equals import IsDict from fastapi.testclient import TestClient -from ...utils import needs_py39 +from ...utils import needs_py39, needs_pydanticv1, needs_pydanticv2 @pytest.fixture(name="client") @@ -27,7 +26,138 @@ def test_query_params_str_validations(client: TestClient): @needs_py39 +@needs_pydanticv2 def test_openapi_schema(client: TestClient): + response = client.get("/openapi.json") + assert response.status_code == 200, response.text + assert response.json() == { + "openapi": "3.1.0", + "info": {"title": "FastAPI", "version": "0.1.0"}, + "paths": { + "/items/": { + "post": { + "responses": { + "200": { + "description": "The created item", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ItemOutput" + } + } + }, + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + }, + }, + "summary": "Create an item", + "description": "Create an item with all the information:\n\n- **name**: each item must have a name\n- **description**: a long description\n- **price**: required\n- **tax**: if the item doesn't have tax, you can omit this\n- **tags**: a set of unique tag strings for this item", + "operationId": "create_item_items__post", + "requestBody": { + "content": { + "application/json": { + "schema": {"$ref": "#/components/schemas/ItemInput"} + } + }, + "required": True, + }, + } + } + }, + "components": { + "schemas": { + "ItemInput": { + "title": "Item", + "required": ["name", "price"], + "type": "object", + "properties": { + "name": {"title": "Name", "type": "string"}, + "description": { + "title": "Description", + "anyOf": [{"type": "string"}, {"type": "null"}], + }, + "price": {"title": "Price", "type": "number"}, + "tax": { + "title": "Tax", + "anyOf": [{"type": "number"}, {"type": "null"}], + }, + "tags": { + "title": "Tags", + "uniqueItems": True, + "type": "array", + "items": {"type": "string"}, + "default": [], + }, + }, + }, + "ItemOutput": { + "title": "Item", + "required": ["name", "description", "price", "tax", "tags"], + "type": "object", + "properties": { + "name": {"title": "Name", "type": "string"}, + "description": { + "anyOf": [{"type": "string"}, {"type": "null"}], + "title": "Description", + }, + "price": {"title": "Price", "type": "number"}, + "tax": { + "title": "Tax", + "anyOf": [{"type": "number"}, {"type": "null"}], + }, + "tags": { + "title": "Tags", + "uniqueItems": True, + "type": "array", + "items": {"type": "string"}, + "default": [], + }, + }, + }, + "ValidationError": { + "title": "ValidationError", + "required": ["loc", "msg", "type"], + "type": "object", + "properties": { + "loc": { + "title": "Location", + "type": "array", + "items": { + "anyOf": [{"type": "string"}, {"type": "integer"}] + }, + }, + "msg": {"title": "Message", "type": "string"}, + "type": {"title": "Error Type", "type": "string"}, + }, + }, + "HTTPValidationError": { + "title": "HTTPValidationError", + "type": "object", + "properties": { + "detail": { + "title": "Detail", + "type": "array", + "items": {"$ref": "#/components/schemas/ValidationError"}, + } + }, + }, + } + }, + } + + +# TODO: remove when deprecating Pydantic v1 +@needs_py39 +@needs_pydanticv1 +def test_openapi_schema_pv1(client: TestClient): response = client.get("/openapi.json") assert response.status_code == 200, response.text assert response.json() == { @@ -78,27 +208,9 @@ def test_openapi_schema(client: TestClient): "type": "object", "properties": { "name": {"title": "Name", "type": "string"}, - "description": IsDict( - { - "title": "Description", - "anyOf": [{"type": "string"}, {"type": "null"}], - } - ) - | IsDict( - # TODO: remove when deprecating Pydantic v1 - {"title": "Description", "type": "string"} - ), + "description": {"title": "Description", "type": "string"}, "price": {"title": "Price", "type": "number"}, - "tax": IsDict( - { - "title": "Tax", - "anyOf": [{"type": "number"}, {"type": "null"}], - } - ) - | IsDict( - # TODO: remove when deprecating Pydantic v1 - {"title": "Tax", "type": "number"} - ), + "tax": {"title": "Tax", "type": "number"}, "tags": { "title": "Tags", "uniqueItems": True, diff --git a/tests/test_tutorial/test_response_model/test_tutorial003.py b/tests/test_tutorial/test_response_model/test_tutorial003.py index 20221399b14fd..384c8e0f146d0 100644 --- a/tests/test_tutorial/test_response_model/test_tutorial003.py +++ b/tests/test_tutorial/test_response_model/test_tutorial003.py @@ -1,4 +1,4 @@ -from dirty_equals import IsDict +from dirty_equals import IsDict, IsOneOf from fastapi.testclient import TestClient from docs_src.response_model.tutorial003 import app @@ -70,7 +70,11 @@ def test_openapi_schema(): "schemas": { "UserOut": { "title": "UserOut", - "required": ["username", "email"], + "required": IsOneOf( + ["username", "email", "full_name"], + # TODO: remove when deprecating Pydantic v1 + ["username", "email"], + ), "type": "object", "properties": { "username": {"title": "Username", "type": "string"}, diff --git a/tests/test_tutorial/test_response_model/test_tutorial003_01.py b/tests/test_tutorial/test_response_model/test_tutorial003_01.py index e8f0658f4c38b..3a6a0b20d9d20 100644 --- a/tests/test_tutorial/test_response_model/test_tutorial003_01.py +++ b/tests/test_tutorial/test_response_model/test_tutorial003_01.py @@ -1,4 +1,4 @@ -from dirty_equals import IsDict +from dirty_equals import IsDict, IsOneOf from fastapi.testclient import TestClient from docs_src.response_model.tutorial003_01 import app @@ -70,7 +70,11 @@ def test_openapi_schema(): "schemas": { "BaseUser": { "title": "BaseUser", - "required": ["username", "email"], + "required": IsOneOf( + ["username", "email", "full_name"], + # TODO: remove when deprecating Pydantic v1 + ["username", "email"], + ), "type": "object", "properties": { "username": {"title": "Username", "type": "string"}, diff --git a/tests/test_tutorial/test_response_model/test_tutorial003_01_py310.py b/tests/test_tutorial/test_response_model/test_tutorial003_01_py310.py index a69f8cc8debed..6985b9de6af74 100644 --- a/tests/test_tutorial/test_response_model/test_tutorial003_01_py310.py +++ b/tests/test_tutorial/test_response_model/test_tutorial003_01_py310.py @@ -1,5 +1,5 @@ import pytest -from dirty_equals import IsDict +from dirty_equals import IsDict, IsOneOf from fastapi.testclient import TestClient from ...utils import needs_py310 @@ -79,7 +79,11 @@ def test_openapi_schema(client: TestClient): "schemas": { "BaseUser": { "title": "BaseUser", - "required": ["username", "email"], + "required": IsOneOf( + ["username", "email", "full_name"], + # TODO: remove when deprecating Pydantic v1 + ["username", "email"], + ), "type": "object", "properties": { "username": {"title": "Username", "type": "string"}, diff --git a/tests/test_tutorial/test_response_model/test_tutorial003_py310.py b/tests/test_tutorial/test_response_model/test_tutorial003_py310.py index 64dcd6cbdf39c..3a3aee38aaffa 100644 --- a/tests/test_tutorial/test_response_model/test_tutorial003_py310.py +++ b/tests/test_tutorial/test_response_model/test_tutorial003_py310.py @@ -1,5 +1,5 @@ import pytest -from dirty_equals import IsDict +from dirty_equals import IsDict, IsOneOf from fastapi.testclient import TestClient from ...utils import needs_py310 @@ -79,7 +79,11 @@ def test_openapi_schema(client: TestClient): "schemas": { "UserOut": { "title": "UserOut", - "required": ["username", "email"], + "required": IsOneOf( + ["username", "email", "full_name"], + # TODO: remove when deprecating Pydantic v1 + ["username", "email"], + ), "type": "object", "properties": { "username": {"title": "Username", "type": "string"}, diff --git a/tests/test_tutorial/test_response_model/test_tutorial004.py b/tests/test_tutorial/test_response_model/test_tutorial004.py index 8beb847d1df7d..e9bde18dd58c3 100644 --- a/tests/test_tutorial/test_response_model/test_tutorial004.py +++ b/tests/test_tutorial/test_response_model/test_tutorial004.py @@ -1,5 +1,5 @@ import pytest -from dirty_equals import IsDict +from dirty_equals import IsDict, IsOneOf from fastapi.testclient import TestClient from docs_src.response_model.tutorial004 import app @@ -79,7 +79,11 @@ def test_openapi_schema(): "schemas": { "Item": { "title": "Item", - "required": ["name", "price"], + "required": IsOneOf( + ["name", "description", "price", "tax", "tags"], + # TODO: remove when deprecating Pydantic v1 + ["name", "price"], + ), "type": "object", "properties": { "name": {"title": "Name", "type": "string"}, diff --git a/tests/test_tutorial/test_response_model/test_tutorial004_py310.py b/tests/test_tutorial/test_response_model/test_tutorial004_py310.py index 28eb88c3478fd..6f8a3cbea8f09 100644 --- a/tests/test_tutorial/test_response_model/test_tutorial004_py310.py +++ b/tests/test_tutorial/test_response_model/test_tutorial004_py310.py @@ -1,5 +1,5 @@ import pytest -from dirty_equals import IsDict +from dirty_equals import IsDict, IsOneOf from fastapi.testclient import TestClient from ...utils import needs_py310 @@ -87,7 +87,11 @@ def test_openapi_schema(client: TestClient): "schemas": { "Item": { "title": "Item", - "required": ["name", "price"], + "required": IsOneOf( + ["name", "description", "price", "tax", "tags"], + # TODO: remove when deprecating Pydantic v1 + ["name", "price"], + ), "type": "object", "properties": { "name": {"title": "Name", "type": "string"}, diff --git a/tests/test_tutorial/test_response_model/test_tutorial004_py39.py b/tests/test_tutorial/test_response_model/test_tutorial004_py39.py index 9e1a21f8db6ae..cfaa1eba2152f 100644 --- a/tests/test_tutorial/test_response_model/test_tutorial004_py39.py +++ b/tests/test_tutorial/test_response_model/test_tutorial004_py39.py @@ -1,5 +1,5 @@ import pytest -from dirty_equals import IsDict +from dirty_equals import IsDict, IsOneOf from fastapi.testclient import TestClient from ...utils import needs_py39 @@ -87,7 +87,11 @@ def test_openapi_schema(client: TestClient): "schemas": { "Item": { "title": "Item", - "required": ["name", "price"], + "required": IsOneOf( + ["name", "description", "price", "tax", "tags"], + # TODO: remove when deprecating Pydantic v1 + ["name", "price"], + ), "type": "object", "properties": { "name": {"title": "Name", "type": "string"}, diff --git a/tests/test_tutorial/test_response_model/test_tutorial005.py b/tests/test_tutorial/test_response_model/test_tutorial005.py index 06e5d0fd153a3..b20864c07ab44 100644 --- a/tests/test_tutorial/test_response_model/test_tutorial005.py +++ b/tests/test_tutorial/test_response_model/test_tutorial005.py @@ -1,4 +1,4 @@ -from dirty_equals import IsDict +from dirty_equals import IsDict, IsOneOf from fastapi.testclient import TestClient from docs_src.response_model.tutorial005 import app @@ -102,7 +102,11 @@ def test_openapi_schema(): "schemas": { "Item": { "title": "Item", - "required": ["name", "price"], + "required": IsOneOf( + ["name", "description", "price", "tax"], + # TODO: remove when deprecating Pydantic v1 + ["name", "price"], + ), "type": "object", "properties": { "name": {"title": "Name", "type": "string"}, diff --git a/tests/test_tutorial/test_response_model/test_tutorial005_py310.py b/tests/test_tutorial/test_response_model/test_tutorial005_py310.py index 0f15662439b01..de552c8f22de5 100644 --- a/tests/test_tutorial/test_response_model/test_tutorial005_py310.py +++ b/tests/test_tutorial/test_response_model/test_tutorial005_py310.py @@ -1,5 +1,5 @@ import pytest -from dirty_equals import IsDict +from dirty_equals import IsDict, IsOneOf from fastapi.testclient import TestClient from ...utils import needs_py310 @@ -112,7 +112,11 @@ def test_openapi_schema(client: TestClient): "schemas": { "Item": { "title": "Item", - "required": ["name", "price"], + "required": IsOneOf( + ["name", "description", "price", "tax"], + # TODO: remove when deprecating Pydantic v1 + ["name", "price"], + ), "type": "object", "properties": { "name": {"title": "Name", "type": "string"}, diff --git a/tests/test_tutorial/test_response_model/test_tutorial006.py b/tests/test_tutorial/test_response_model/test_tutorial006.py index 6e6152b9f16cb..1e47e2eadb05e 100644 --- a/tests/test_tutorial/test_response_model/test_tutorial006.py +++ b/tests/test_tutorial/test_response_model/test_tutorial006.py @@ -1,4 +1,4 @@ -from dirty_equals import IsDict +from dirty_equals import IsDict, IsOneOf from fastapi.testclient import TestClient from docs_src.response_model.tutorial006 import app @@ -102,7 +102,11 @@ def test_openapi_schema(): "schemas": { "Item": { "title": "Item", - "required": ["name", "price"], + "required": IsOneOf( + ["name", "description", "price", "tax"], + # TODO: remove when deprecating Pydantic v1 + ["name", "price"], + ), "type": "object", "properties": { "name": {"title": "Name", "type": "string"}, diff --git a/tests/test_tutorial/test_response_model/test_tutorial006_py310.py b/tests/test_tutorial/test_response_model/test_tutorial006_py310.py index 9a980ab5b0ae5..40058b12dea45 100644 --- a/tests/test_tutorial/test_response_model/test_tutorial006_py310.py +++ b/tests/test_tutorial/test_response_model/test_tutorial006_py310.py @@ -1,5 +1,5 @@ import pytest -from dirty_equals import IsDict +from dirty_equals import IsDict, IsOneOf from fastapi.testclient import TestClient from ...utils import needs_py310 @@ -112,7 +112,11 @@ def test_openapi_schema(client: TestClient): "schemas": { "Item": { "title": "Item", - "required": ["name", "price"], + "required": IsOneOf( + ["name", "description", "price", "tax"], + # TODO: remove when deprecating Pydantic v1 + ["name", "price"], + ), "type": "object", "properties": { "name": {"title": "Name", "type": "string"}, diff --git a/tests/test_tutorial/test_security/test_tutorial005.py b/tests/test_tutorial/test_security/test_tutorial005.py index 22ae76f428f4a..c669c306ddb01 100644 --- a/tests/test_tutorial/test_security/test_tutorial005.py +++ b/tests/test_tutorial/test_security/test_tutorial005.py @@ -1,4 +1,4 @@ -from dirty_equals import IsDict +from dirty_equals import IsDict, IsOneOf from fastapi.testclient import TestClient from docs_src.security.tutorial005 import ( @@ -267,7 +267,11 @@ def test_openapi_schema(): "schemas": { "User": { "title": "User", - "required": ["username"], + "required": IsOneOf( + ["username", "email", "full_name", "disabled"], + # TODO: remove when deprecating Pydantic v1 + ["username"], + ), "type": "object", "properties": { "username": {"title": "Username", "type": "string"}, diff --git a/tests/test_tutorial/test_security/test_tutorial005_an.py b/tests/test_tutorial/test_security/test_tutorial005_an.py index 07239cc890051..aaab04f78fb4e 100644 --- a/tests/test_tutorial/test_security/test_tutorial005_an.py +++ b/tests/test_tutorial/test_security/test_tutorial005_an.py @@ -1,4 +1,4 @@ -from dirty_equals import IsDict +from dirty_equals import IsDict, IsOneOf from fastapi.testclient import TestClient from docs_src.security.tutorial005_an import ( @@ -267,7 +267,11 @@ def test_openapi_schema(): "schemas": { "User": { "title": "User", - "required": ["username"], + "required": IsOneOf( + ["username", "email", "full_name", "disabled"], + # TODO: remove when deprecating Pydantic v1 + ["username"], + ), "type": "object", "properties": { "username": {"title": "Username", "type": "string"}, diff --git a/tests/test_tutorial/test_security/test_tutorial005_an_py310.py b/tests/test_tutorial/test_security/test_tutorial005_an_py310.py index 1ab836639e6f9..243d0773c266c 100644 --- a/tests/test_tutorial/test_security/test_tutorial005_an_py310.py +++ b/tests/test_tutorial/test_security/test_tutorial005_an_py310.py @@ -1,5 +1,5 @@ import pytest -from dirty_equals import IsDict +from dirty_equals import IsDict, IsOneOf from fastapi.testclient import TestClient from ...utils import needs_py310 @@ -295,7 +295,11 @@ def test_openapi_schema(client: TestClient): "schemas": { "User": { "title": "User", - "required": ["username"], + "required": IsOneOf( + ["username", "email", "full_name", "disabled"], + # TODO: remove when deprecating Pydantic v1 + ["username"], + ), "type": "object", "properties": { "username": {"title": "Username", "type": "string"}, diff --git a/tests/test_tutorial/test_security/test_tutorial005_an_py39.py b/tests/test_tutorial/test_security/test_tutorial005_an_py39.py index 6aabbe04acc79..17a3f9aa2a548 100644 --- a/tests/test_tutorial/test_security/test_tutorial005_an_py39.py +++ b/tests/test_tutorial/test_security/test_tutorial005_an_py39.py @@ -1,5 +1,5 @@ import pytest -from dirty_equals import IsDict +from dirty_equals import IsDict, IsOneOf from fastapi.testclient import TestClient from ...utils import needs_py39 @@ -295,7 +295,11 @@ def test_openapi_schema(client: TestClient): "schemas": { "User": { "title": "User", - "required": ["username"], + "required": IsOneOf( + ["username", "email", "full_name", "disabled"], + # TODO: remove when deprecating Pydantic v1 + ["username"], + ), "type": "object", "properties": { "username": {"title": "Username", "type": "string"}, diff --git a/tests/test_tutorial/test_security/test_tutorial005_py310.py b/tests/test_tutorial/test_security/test_tutorial005_py310.py index c21884df83a98..06455cd632f09 100644 --- a/tests/test_tutorial/test_security/test_tutorial005_py310.py +++ b/tests/test_tutorial/test_security/test_tutorial005_py310.py @@ -1,5 +1,5 @@ import pytest -from dirty_equals import IsDict +from dirty_equals import IsDict, IsOneOf from fastapi.testclient import TestClient from ...utils import needs_py310 @@ -295,7 +295,11 @@ def test_openapi_schema(client: TestClient): "schemas": { "User": { "title": "User", - "required": ["username"], + "required": IsOneOf( + ["username", "email", "full_name", "disabled"], + # TODO: remove when deprecating Pydantic v1 + ["username"], + ), "type": "object", "properties": { "username": {"title": "Username", "type": "string"}, diff --git a/tests/test_tutorial/test_security/test_tutorial005_py39.py b/tests/test_tutorial/test_security/test_tutorial005_py39.py index 170c5d60b867d..9455bfb4ef6b9 100644 --- a/tests/test_tutorial/test_security/test_tutorial005_py39.py +++ b/tests/test_tutorial/test_security/test_tutorial005_py39.py @@ -1,5 +1,5 @@ import pytest -from dirty_equals import IsDict +from dirty_equals import IsDict, IsOneOf from fastapi.testclient import TestClient from ...utils import needs_py39 @@ -295,7 +295,11 @@ def test_openapi_schema(client: TestClient): "schemas": { "User": { "title": "User", - "required": ["username"], + "required": IsOneOf( + ["username", "email", "full_name", "disabled"], + # TODO: remove when deprecating Pydantic v1 + ["username"], + ), "type": "object", "properties": { "username": {"title": "Username", "type": "string"}, From 1c2051473865fcc76284eac177104fc342b51aeb Mon Sep 17 00:00:00 2001 From: github-actions Date: Fri, 4 Aug 2023 20:47:42 +0000 Subject: [PATCH 34/39] =?UTF-8?q?=F0=9F=93=9D=20Update=20release=20notes?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docs/en/docs/release-notes.md | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/en/docs/release-notes.md b/docs/en/docs/release-notes.md index e45373f7b0bfa..32224ffc0eba9 100644 --- a/docs/en/docs/release-notes.md +++ b/docs/en/docs/release-notes.md @@ -2,6 +2,7 @@ ## Latest Changes +* ✨ Enable Pydantic's serialization mode for responses, add support for Pydantic's `computed_field`, better OpenAPI for response models, proper required attributes, better generated clients. PR [#10011](https://github.com/tiangolo/fastapi/pull/10011) by [@tiangolo](https://github.com/tiangolo). * 👷 Add GitHub Actions step dump context to debug external failures. PR [#10008](https://github.com/tiangolo/fastapi/pull/10008) by [@tiangolo](https://github.com/tiangolo). * 🔧 Restore MkDocs Material pin after the fix. PR [#10001](https://github.com/tiangolo/fastapi/pull/10001) by [@tiangolo](https://github.com/tiangolo). * 🔧 Update the Question template to ask for the Pydantic version. PR [#10000](https://github.com/tiangolo/fastapi/pull/10000) by [@tiangolo](https://github.com/tiangolo). From 944c59180354e81988a7ed67454f3fdb879f5b2d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebasti=C3=A1n=20Ram=C3=ADrez?= Date: Fri, 4 Aug 2023 22:50:34 +0200 Subject: [PATCH 35/39] =?UTF-8?q?=F0=9F=93=9D=20Update=20release=20notes?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docs/en/docs/release-notes.md | 19 +++++++++++++++---- 1 file changed, 15 insertions(+), 4 deletions(-) diff --git a/docs/en/docs/release-notes.md b/docs/en/docs/release-notes.md index 32224ffc0eba9..c3756ebd3197c 100644 --- a/docs/en/docs/release-notes.md +++ b/docs/en/docs/release-notes.md @@ -2,23 +2,34 @@ ## Latest Changes +### Features + * ✨ Enable Pydantic's serialization mode for responses, add support for Pydantic's `computed_field`, better OpenAPI for response models, proper required attributes, better generated clients. PR [#10011](https://github.com/tiangolo/fastapi/pull/10011) by [@tiangolo](https://github.com/tiangolo). + +### Refactors + +* ✅ Fix tests for compatibility with pydantic 2.1.1. PR [#9943](https://github.com/tiangolo/fastapi/pull/9943) by [@dmontagu](https://github.com/dmontagu). +* ✅ Fix test error in Windows for `jsonable_encoder`. PR [#9840](https://github.com/tiangolo/fastapi/pull/9840) by [@iudeen](https://github.com/iudeen). + +### Translations + +* 🌐 Add Russian translation for `docs/ru/docs/tutorial/security/index.md`. PR [#9963](https://github.com/tiangolo/fastapi/pull/9963) by [@eVery1337](https://github.com/eVery1337). +* 🌐 Remove Vietnamese note about missing translation. PR [#9957](https://github.com/tiangolo/fastapi/pull/9957) by [@tiangolo](https://github.com/tiangolo). + +### Internal + * 👷 Add GitHub Actions step dump context to debug external failures. PR [#10008](https://github.com/tiangolo/fastapi/pull/10008) by [@tiangolo](https://github.com/tiangolo). * 🔧 Restore MkDocs Material pin after the fix. PR [#10001](https://github.com/tiangolo/fastapi/pull/10001) by [@tiangolo](https://github.com/tiangolo). * 🔧 Update the Question template to ask for the Pydantic version. PR [#10000](https://github.com/tiangolo/fastapi/pull/10000) by [@tiangolo](https://github.com/tiangolo). -* ✅ Fix tests for compatibility with pydantic 2.1.1. PR [#9943](https://github.com/tiangolo/fastapi/pull/9943) by [@dmontagu](https://github.com/dmontagu). * 📍 Update MkDocs Material dependencies. PR [#9986](https://github.com/tiangolo/fastapi/pull/9986) by [@tiangolo](https://github.com/tiangolo). * 👥 Update FastAPI People. PR [#9999](https://github.com/tiangolo/fastapi/pull/9999) by [@tiangolo](https://github.com/tiangolo). * 🐳 Update Dockerfile with compatibility versions, to upgrade later. PR [#9998](https://github.com/tiangolo/fastapi/pull/9998) by [@tiangolo](https://github.com/tiangolo). * ➕ Add pydantic-settings to FastAPI People dependencies. PR [#9988](https://github.com/tiangolo/fastapi/pull/9988) by [@tiangolo](https://github.com/tiangolo). * ♻️ Update FastAPI People logic with new Pydantic. PR [#9985](https://github.com/tiangolo/fastapi/pull/9985) by [@tiangolo](https://github.com/tiangolo). -* ✅ Fix test error in Windows for `jsonable_encoder`. PR [#9840](https://github.com/tiangolo/fastapi/pull/9840) by [@iudeen](https://github.com/iudeen). -* 🌐 Add Russian translation for `docs/ru/docs/tutorial/security/index.md`. PR [#9963](https://github.com/tiangolo/fastapi/pull/9963) by [@eVery1337](https://github.com/eVery1337). * 🍱 Update sponsors, Fern badge. PR [#9982](https://github.com/tiangolo/fastapi/pull/9982) by [@tiangolo](https://github.com/tiangolo). * 👷 Deploy docs to Cloudflare Pages. PR [#9978](https://github.com/tiangolo/fastapi/pull/9978) by [@tiangolo](https://github.com/tiangolo). * 🔧 Update sponsor Fern. PR [#9979](https://github.com/tiangolo/fastapi/pull/9979) by [@tiangolo](https://github.com/tiangolo). * 👷 Update CI debug mode with Tmate. PR [#9977](https://github.com/tiangolo/fastapi/pull/9977) by [@tiangolo](https://github.com/tiangolo). -* 🌐 Remove Vietnamese note about missing translation. PR [#9957](https://github.com/tiangolo/fastapi/pull/9957) by [@tiangolo](https://github.com/tiangolo). ## 0.100.1 From 77d1f69b1f2dced4fc7e2e0e934ffc259a4b4a98 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebasti=C3=A1n=20Ram=C3=ADrez?= Date: Fri, 4 Aug 2023 22:57:30 +0200 Subject: [PATCH 36/39] =?UTF-8?q?=F0=9F=93=8C=20Do=20not=20allow=20Pydanti?= =?UTF-8?q?c=202.1.0=20that=20breaks=20(require=202.1.1)=20(#10012)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- pyproject.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pyproject.toml b/pyproject.toml index f0917578f9d1d..9b7cca9c95db2 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -42,7 +42,7 @@ classifiers = [ ] dependencies = [ "starlette>=0.27.0,<0.28.0", - "pydantic>=1.7.4,!=1.8,!=1.8.1,!=2.0.0,!=2.0.1,<3.0.0", + "pydantic>=1.7.4,!=1.8,!=1.8.1,!=2.0.0,!=2.0.1,!=2.1.0,<3.0.0", "typing-extensions>=4.5.0", ] dynamic = ["version"] From 89a7cea56157837db092c8047d4c028193c30429 Mon Sep 17 00:00:00 2001 From: github-actions Date: Fri, 4 Aug 2023 20:58:08 +0000 Subject: [PATCH 37/39] =?UTF-8?q?=F0=9F=93=9D=20Update=20release=20notes?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docs/en/docs/release-notes.md | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/en/docs/release-notes.md b/docs/en/docs/release-notes.md index c3756ebd3197c..383be69ff5114 100644 --- a/docs/en/docs/release-notes.md +++ b/docs/en/docs/release-notes.md @@ -2,6 +2,7 @@ ## Latest Changes +* 📌 Do not allow Pydantic 2.1.0 that breaks (require 2.1.1). PR [#10012](https://github.com/tiangolo/fastapi/pull/10012) by [@tiangolo](https://github.com/tiangolo). ### Features * ✨ Enable Pydantic's serialization mode for responses, add support for Pydantic's `computed_field`, better OpenAPI for response models, proper required attributes, better generated clients. PR [#10011](https://github.com/tiangolo/fastapi/pull/10011) by [@tiangolo](https://github.com/tiangolo). From 4b5277744ad57a46fa28ea287012c83ba0a7f4f0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebasti=C3=A1n=20Ram=C3=ADrez?= Date: Fri, 4 Aug 2023 22:59:44 +0200 Subject: [PATCH 38/39] =?UTF-8?q?=F0=9F=93=9D=20Update=20release=20notes?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docs/en/docs/release-notes.md | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/docs/en/docs/release-notes.md b/docs/en/docs/release-notes.md index 383be69ff5114..a7a5a424e51a2 100644 --- a/docs/en/docs/release-notes.md +++ b/docs/en/docs/release-notes.md @@ -2,7 +2,6 @@ ## Latest Changes -* 📌 Do not allow Pydantic 2.1.0 that breaks (require 2.1.1). PR [#10012](https://github.com/tiangolo/fastapi/pull/10012) by [@tiangolo](https://github.com/tiangolo). ### Features * ✨ Enable Pydantic's serialization mode for responses, add support for Pydantic's `computed_field`, better OpenAPI for response models, proper required attributes, better generated clients. PR [#10011](https://github.com/tiangolo/fastapi/pull/10011) by [@tiangolo](https://github.com/tiangolo). @@ -12,6 +11,10 @@ * ✅ Fix tests for compatibility with pydantic 2.1.1. PR [#9943](https://github.com/tiangolo/fastapi/pull/9943) by [@dmontagu](https://github.com/dmontagu). * ✅ Fix test error in Windows for `jsonable_encoder`. PR [#9840](https://github.com/tiangolo/fastapi/pull/9840) by [@iudeen](https://github.com/iudeen). +### Upgrades + +* 📌 Do not allow Pydantic 2.1.0 that breaks (require 2.1.1). PR [#10012](https://github.com/tiangolo/fastapi/pull/10012) by [@tiangolo](https://github.com/tiangolo). + ### Translations * 🌐 Add Russian translation for `docs/ru/docs/tutorial/security/index.md`. PR [#9963](https://github.com/tiangolo/fastapi/pull/9963) by [@eVery1337](https://github.com/eVery1337). From 8adbafc0760c9fd0d97da748545b3a5f92dbb0ea Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebasti=C3=A1n=20Ram=C3=ADrez?= Date: Fri, 4 Aug 2023 23:00:17 +0200 Subject: [PATCH 39/39] =?UTF-8?q?=F0=9F=94=96=20Release=20version=200.101.?= =?UTF-8?q?0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docs/en/docs/release-notes.md | 3 +++ fastapi/__init__.py | 2 +- 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/docs/en/docs/release-notes.md b/docs/en/docs/release-notes.md index a7a5a424e51a2..5957a73c09ae0 100644 --- a/docs/en/docs/release-notes.md +++ b/docs/en/docs/release-notes.md @@ -2,6 +2,9 @@ ## Latest Changes + +## 0.101.0 + ### Features * ✨ Enable Pydantic's serialization mode for responses, add support for Pydantic's `computed_field`, better OpenAPI for response models, proper required attributes, better generated clients. PR [#10011](https://github.com/tiangolo/fastapi/pull/10011) by [@tiangolo](https://github.com/tiangolo). diff --git a/fastapi/__init__.py b/fastapi/__init__.py index 7dfeca0d48a19..c113ac1fd0874 100644 --- a/fastapi/__init__.py +++ b/fastapi/__init__.py @@ -1,6 +1,6 @@ """FastAPI framework, high performance, easy to learn, fast to code, ready for production""" -__version__ = "0.100.1" +__version__ = "0.101.0" from starlette import status as status