diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml
index 21413fc66..7af88b5aa 100644
--- a/.pre-commit-config.yaml
+++ b/.pre-commit-config.yaml
@@ -14,7 +14,7 @@ repos:
- id: end-of-file-fixer
- id: trailing-whitespace
- repo: https://github.com/astral-sh/ruff-pre-commit
- rev: v0.11.12
+ rev: v0.11.13
hooks:
- id: ruff
args:
diff --git a/README.md b/README.md
index da9446e2b..ab5143084 100644
--- a/README.md
+++ b/README.md
@@ -48,7 +48,6 @@ The key features are:
-
@@ -57,7 +56,7 @@ The key features are:
-
+
diff --git a/docs/de/docs/advanced/generate-clients.md b/docs/de/docs/advanced/generate-clients.md
index 38a69031c..f491d29af 100644
--- a/docs/de/docs/advanced/generate-clients.md
+++ b/docs/de/docs/advanced/generate-clients.md
@@ -20,7 +20,7 @@ Einige von diesen ✨ [**sponsern FastAPI**](../help-fastapi.md#den-autor-sponse
Und es zeigt deren wahres Engagement für FastAPI und seine **Community** (Sie), da diese Ihnen nicht nur einen **guten Service** bieten möchten, sondern auch sicherstellen möchten, dass Sie über ein **gutes und gesundes Framework** verfügen, FastAPI. 🙇
-Beispielsweise könnten Sie Speakeasy ausprobieren.
+Beispielsweise könnten Sie Speakeasy ausprobieren.
Es gibt auch mehrere andere Unternehmen, welche ähnliche Dienste anbieten und die Sie online suchen und finden können. 🤓
diff --git a/docs/en/data/sponsors.yml b/docs/en/data/sponsors.yml
index 897ca7b8d..f712b6179 100644
--- a/docs/en/data/sponsors.yml
+++ b/docs/en/data/sponsors.yml
@@ -5,9 +5,6 @@ gold:
- url: https://platform.sh/try-it-now/?utm_source=fastapi-signup&utm_medium=banner&utm_campaign=FastAPI-signup-June-2023
title: "Build, run and scale your apps on a modern, reliable, and secure PaaS."
img: https://fastapi.tiangolo.com/img/sponsors/platform-sh.png
- - url: https://www.porter.run
- title: Deploy FastAPI on AWS with a few clicks
- img: https://fastapi.tiangolo.com/img/sponsors/porter.png
- url: https://github.com/scalar/scalar/?utm_source=fastapi&utm_medium=website&utm_campaign=main-badge
title: "Scalar: Beautiful Open-Source API References from Swagger/OpenAPI files"
img: https://fastapi.tiangolo.com/img/sponsors/scalar.svg
@@ -33,7 +30,7 @@ silver:
- url: https://databento.com/
title: Pay as you go for market data
img: https://fastapi.tiangolo.com/img/sponsors/databento.svg
- - url: https://speakeasy.com?utm_source=fastapi+repo&utm_medium=github+sponsorship
+ - url: https://speakeasy.com/editor?utm_source=fastapi+repo&utm_medium=github+sponsorship
title: SDKs for your API | Speakeasy
img: https://fastapi.tiangolo.com/img/sponsors/speakeasy.png
- url: https://www.svix.com/
diff --git a/docs/en/docs/advanced/generate-clients.md b/docs/en/docs/advanced/generate-clients.md
index b2aef5037..55e6a08b1 100644
--- a/docs/en/docs/advanced/generate-clients.md
+++ b/docs/en/docs/advanced/generate-clients.md
@@ -22,7 +22,7 @@ And it shows their true commitment to FastAPI and its **community** (you), as th
For example, you might want to try:
-* Speakeasy
+* Speakeasy
* Stainless
* liblab
diff --git a/docs/en/docs/advanced/response-directly.md b/docs/en/docs/advanced/response-directly.md
index 691b1e7cd..759b762b5 100644
--- a/docs/en/docs/advanced/response-directly.md
+++ b/docs/en/docs/advanced/response-directly.md
@@ -58,7 +58,7 @@ You could put your XML content in a string, put that in a `Response`, and return
## Notes
-When you return a `Response` directly its data is not validated, converted (serialized), nor documented automatically.
+When you return a `Response` directly its data is not validated, converted (serialized), or documented automatically.
But you can still document it as described in [Additional Responses in OpenAPI](additional-responses.md){.internal-link target=_blank}.
diff --git a/docs/en/docs/async.md b/docs/en/docs/async.md
index 63bd8ca68..8207ec480 100644
--- a/docs/en/docs/async.md
+++ b/docs/en/docs/async.md
@@ -40,7 +40,7 @@ def results():
---
-If your application (somehow) doesn't have to communicate with anything else and wait for it to respond, use `async def`.
+If your application (somehow) doesn't have to communicate with anything else and wait for it to respond, use `async def`, even if you don't need to use `await` inside.
---
diff --git a/docs/en/docs/release-notes.md b/docs/en/docs/release-notes.md
index b5d7f8d3a..68eeaae7b 100644
--- a/docs/en/docs/release-notes.md
+++ b/docs/en/docs/release-notes.md
@@ -7,12 +7,40 @@ hide:
## Latest Changes
+### Docs
+
+* Misprint. PR [#13800](https://github.com/fastapi/fastapi/pull/13800) by [@NavesSapnis](https://github.com/NavesSapnis).
+* 📝 Update Speakeasy URL to Speakeasy Sandbox. PR [#13697](https://github.com/fastapi/fastapi/pull/13697) by [@ndimares](https://github.com/ndimares).
+
+### Translations
+
+* 🌐 Add Russian translation for `docs/ru/docs/advanced/index.md`. PR [#13797](https://github.com/fastapi/fastapi/pull/13797) by [@NavesSapnis](https://github.com/NavesSapnis).
+
+## 0.115.13
+
+### Fixes
+
+* 🐛 Fix truncating the model's description with form feed (`\f`) character for Pydantic V2. PR [#13698](https://github.com/fastapi/fastapi/pull/13698) by [@YuriiMotov](https://github.com/YuriiMotov).
+
+### Refactors
+
+* ✨ Add `refreshUrl` parameter in `OAuth2PasswordBearer`. PR [#11460](https://github.com/fastapi/fastapi/pull/11460) by [@snosratiershad](https://github.com/snosratiershad).
+* 🚸 Set format to password for fields `password` and `client_secret` in `OAuth2PasswordRequestForm`, make docs show password fields for passwords. PR [#11032](https://github.com/fastapi/fastapi/pull/11032) by [@Thodoris1999](https://github.com/Thodoris1999).
+* ✅ Simplify tests for `settings`. PR [#13505](https://github.com/fastapi/fastapi/pull/13505) by [@valentinDruzhinin](https://github.com/valentinDruzhinin).
+* ✅ Simplify tests for `validate_response_recursive`. PR [#13507](https://github.com/fastapi/fastapi/pull/13507) by [@valentinDruzhinin](https://github.com/valentinDruzhinin).
+
### Upgrades
* ⬆️ Update ReDoc to version 2.x. PR [#9700](https://github.com/fastapi/fastapi/pull/9700) by [@joakimnordling](https://github.com/joakimnordling).
### Docs
+* 📝 Add annotations to HTTP middleware example. PR [#11530](https://github.com/fastapi/fastapi/pull/11530) by [@Kilo59](https://github.com/Kilo59).
+* 📝 Clarify in CORS docs that wildcards and credentials are mutually exclusive. PR [#9829](https://github.com/fastapi/fastapi/pull/9829) by [@dfioravanti](https://github.com/dfioravanti).
+* ✏️ Fix typo in docstring. PR [#13532](https://github.com/fastapi/fastapi/pull/13532) by [@comp64](https://github.com/comp64).
+* 📝 Clarify guidance on using `async def` without `await`. PR [#13642](https://github.com/fastapi/fastapi/pull/13642) by [@swastikpradhan1999](https://github.com/swastikpradhan1999).
+* 📝 Update exclude-parameters-from-openapi documentation links. PR [#13600](https://github.com/fastapi/fastapi/pull/13600) by [@timonrieger](https://github.com/timonrieger).
+* 📝 Clarify the middleware execution order in docs. PR [#13699](https://github.com/fastapi/fastapi/pull/13699) by [@YuriiMotov](https://github.com/YuriiMotov).
* 🍱 Update Drawio diagrams SVGs, single file per diagram, sans-serif font. PR [#13706](https://github.com/fastapi/fastapi/pull/13706) by [@tiangolo](https://github.com/tiangolo).
* 📝 Update docs for "Help FastAPI", simplify and reduce "sponsor" section. PR [#13670](https://github.com/fastapi/fastapi/pull/13670) by [@tiangolo](https://github.com/tiangolo).
* 📝 Remove unnecessary bullet from docs. PR [#13641](https://github.com/fastapi/fastapi/pull/13641) by [@Adamowoc](https://github.com/Adamowoc).
@@ -24,6 +52,10 @@ hide:
### Translations
+* 🌐 Add Russian Translation for `docs/ru/docs/advanced/response-change-status-code.md`. PR [#13791](https://github.com/fastapi/fastapi/pull/13791) by [@NavesSapnis](https://github.com/NavesSapnis).
+* 🌐 Add Persian translation for `docs/fa/docs/learn/index.md`. PR [#13518](https://github.com/fastapi/fastapi/pull/13518) by [@Mohammad222PR](https://github.com/Mohammad222PR).
+* 🌐 Add Korean translation for `docs/ko/docs/advanced/sub-applications.md`. PR [#4543](https://github.com/fastapi/fastapi/pull/4543) by [@NinaHwang](https://github.com/NinaHwang).
+* 🌐 Add Ukrainian translation for `docs/uk/docs/tutorial/schema-extra-example.md`. PR [#13769](https://github.com/fastapi/fastapi/pull/13769) by [@valentinDruzhinin](https://github.com/valentinDruzhinin).
* ✏️ Remove redundant words in docs/zh/docs/python-types.md. PR [#13774](https://github.com/fastapi/fastapi/pull/13774) by [@CharleeWa](https://github.com/CharleeWa).
* 🌐 Add Ukrainian translation for `docs/uk/docs/tutorial/query-param-models.md`. PR [#13748](https://github.com/fastapi/fastapi/pull/13748) by [@valentinDruzhinin](https://github.com/valentinDruzhinin).
* 🌐 Add Bengali translation for `docs/bn/docs/environment-variables.md`. PR [#13629](https://github.com/fastapi/fastapi/pull/13629) by [@SakibSibly](https://github.com/SakibSibly).
@@ -47,6 +79,9 @@ hide:
### Internal
+* 🔨 Resolve Pydantic deprecation warnings in internal script. PR [#13696](https://github.com/fastapi/fastapi/pull/13696) by [@emmanuel-ferdman](https://github.com/emmanuel-ferdman).
+* 🔧 Update sponsors: remove Porter. PR [#13783](https://github.com/fastapi/fastapi/pull/13783) by [@tiangolo](https://github.com/tiangolo).
+* ⬆ [pre-commit.ci] pre-commit autoupdate. PR [#13781](https://github.com/fastapi/fastapi/pull/13781) by [@pre-commit-ci[bot]](https://github.com/apps/pre-commit-ci).
* ⬆ [pre-commit.ci] pre-commit autoupdate. PR [#13757](https://github.com/fastapi/fastapi/pull/13757) by [@pre-commit-ci[bot]](https://github.com/apps/pre-commit-ci).
* ⬆ Bump griffe-typingdoc from 0.2.7 to 0.2.8. PR [#13751](https://github.com/fastapi/fastapi/pull/13751) by [@dependabot[bot]](https://github.com/apps/dependabot).
* 🍱 Update sponsors: Dribia badge size. PR [#13773](https://github.com/fastapi/fastapi/pull/13773) by [@tiangolo](https://github.com/tiangolo).
diff --git a/docs/en/docs/tutorial/cors.md b/docs/en/docs/tutorial/cors.md
index cf31cfcf5..5ca4437b3 100644
--- a/docs/en/docs/tutorial/cors.md
+++ b/docs/en/docs/tutorial/cors.md
@@ -57,7 +57,10 @@ The following arguments are supported:
* `allow_origin_regex` - A regex string to match against origins that should be permitted to make cross-origin requests. e.g. `'https://.*\.example\.org'`.
* `allow_methods` - A list of HTTP methods that should be allowed for cross-origin requests. Defaults to `['GET']`. You can use `['*']` to allow all standard methods.
* `allow_headers` - A list of HTTP request headers that should be supported for cross-origin requests. Defaults to `[]`. You can use `['*']` to allow all headers. The `Accept`, `Accept-Language`, `Content-Language` and `Content-Type` headers are always allowed for simple CORS requests.
-* `allow_credentials` - Indicate that cookies should be supported for cross-origin requests. Defaults to `False`. Also, `allow_origins` cannot be set to `['*']` for credentials to be allowed, origins must be specified.
+* `allow_credentials` - Indicate that cookies should be supported for cross-origin requests. Defaults to `False`.
+
+ None of `allow_origins`, `allow_methods` and `allow_headers` can be set to `['*']` if `allow_credentials` is set to `True`. All of them must be explicitly specified.
+
* `expose_headers` - Indicate any response headers that should be made accessible to the browser. Defaults to `[]`.
* `max_age` - Sets a maximum time in seconds for browsers to cache CORS responses. Defaults to `600`.
diff --git a/docs/en/docs/tutorial/middleware.md b/docs/en/docs/tutorial/middleware.md
index 4f7980165..b7c03a319 100644
--- a/docs/en/docs/tutorial/middleware.md
+++ b/docs/en/docs/tutorial/middleware.md
@@ -65,6 +65,29 @@ Here we use
-
diff --git a/docs/es/docs/advanced/generate-clients.md b/docs/es/docs/advanced/generate-clients.md
index bf2e5cb4f..b664bceac 100644
--- a/docs/es/docs/advanced/generate-clients.md
+++ b/docs/es/docs/advanced/generate-clients.md
@@ -22,7 +22,7 @@ Y muestra su verdadero compromiso con FastAPI y su **comunidad** (tú), ya que n
Por ejemplo, podrías querer probar:
-* Speakeasy
+*
Speakeasy
*
Stainless
*
liblab
diff --git a/docs/fa/docs/learn/index.md b/docs/fa/docs/learn/index.md
new file mode 100644
index 000000000..06aa7f00e
--- /dev/null
+++ b/docs/fa/docs/learn/index.md
@@ -0,0 +1,5 @@
+# یادگیری
+
+اینجا بخشهای مقدماتی و آموزشهایی هستن که برای یادگیری **FastAPI** بهت کمک میکنن.
+
+میتونی اینو یه **کتاب**، یه **دوره آموزشی**، یا راه **رسمی** و پیشنهادی برای یادگیری FastAPI در نظر بگیری. 😎
diff --git a/docs/ko/docs/advanced/sub-applications.md b/docs/ko/docs/advanced/sub-applications.md
new file mode 100644
index 000000000..c5835de15
--- /dev/null
+++ b/docs/ko/docs/advanced/sub-applications.md
@@ -0,0 +1,67 @@
+# 하위 응용프로그램 - 마운트
+
+만약 각각의 독립적인 OpenAPI와 문서 UI를 갖는 두 개의 독립적인 FastAPI 응용프로그램이 필요하다면, 메인 어플리케이션에 하나 (또는 그 이상의) 하위-응용프로그램(들)을 “마운트"해서 사용할 수 있습니다.
+
+## **FastAPI** 응용프로그램 마운트
+
+“마운트"이란 완전히 “독립적인" 응용프로그램을 특정 경로에 추가하여 해당 하위 응용프로그램에서 선언된 *경로 동작*을 통해 해당 경로 아래에 있는 모든 작업들을 처리할 수 있도록 하는 것을 의미합니다.
+
+### 최상단 응용프로그램
+
+먼저, 메인, 최상단의 **FastAPI** 응용프로그램과 이것의 *경로 동작*을 생성합니다:
+
+{* ../../docs_src/sub_applications/tutorial001.py hl[3, 6:8] *}
+
+### 하위 응용프로그램
+
+다음으로, 하위 응용프로그램과 이것의 *경로 동작*을 생성합니다:
+
+이 하위 응용프로그램은 또 다른 표준 FastAPI 응용프로그램입니다. 다만 이것은 “마운트”될 것입니다:
+
+{* ../../docs_src/sub_applications/tutorial001.py hl[11, 14:16] *}
+
+### 하위 응용프로그램 마운트
+
+최상단 응용프로그램, `app`에 하위 응용프로그램, `subapi`를 마운트합니다.
+
+이 예시에서, 하위 응용프로그램션은 `/subapi` 경로에 마운트 될 것입니다:
+
+{* ../../docs_src/sub_applications/tutorial001.py hl[11, 19] *}
+
+### 자동으로 생성된 API 문서 확인
+
+이제, `uvicorn`으로 메인 응용프로그램을 실행하십시오. 당신의 파일이 `main.py`라면, 이렇게 실행합니다:
+
+
+
+```console
+$ uvicorn main:app --reload
+
+INFO: Uvicorn running on http://127.0.0.1:8000 (Press CTRL+C to quit)
+```
+
+
+
+그리고
http://127.0.0.1:8000/docs에서 문서를 여십시오.
+
+메인 응용프로그램의 *경로 동작*만을 포함하는, 메인 응용프로그램에 대한 자동 API 문서를 확인할 수 있습니다:
+
+

+
+다음으로,
http://127.0.0.1:8000/subapi/docs에서 하위 응용프로그램의 문서를 여십시오.
+
+하위 경로 접두사 `/subapi` 아래에 선언된 *경로 동작* 을 포함하는, 하위 응용프로그램에 대한 자동 API 문서를 확인할 수 있습니다:
+
+

+
+두 사용자 인터페이스 중 어느 하나를 사용해야하는 경우, 브라우저는 특정 응용프로그램 또는 하위 응용프로그램과 각각 통신할 수 있기 때문에 올바르게 동작할 것입니다.
+
+### 기술적 세부사항: `root_path`
+
+위에 설명된 것과 같이 하위 응용프로그램을 마운트하는 경우, FastAPI는 `root_path`라고 하는 ASGI 명세의 매커니즘을 사용하여 하위 응용프로그램에 대한 마운트 경로 통신을 처리합니다.
+
+이를 통해, 하위 응용프로그램은 문서 UI를 위해 경로 접두사를 사용해야 한다는 사실을 인지합니다.
+
+하위 응용프로그램에도 역시 다른 하위 응용프로그램을 마운트하는 것이 가능하며 FastAPI가 모든 `root_path` 들을 자동적으로 처리하기 때문에 모든 것은 올바르게 동작할 것입니다.
+
+`root_path`와 이것을 사용하는 방법에 대해서는 [프록시의 뒷단](./behind-a-proxy.md){.internal-link target=_blank} 섹션에서 배울 수 있습니다.
diff --git a/docs/pt/docs/advanced/generate-clients.md b/docs/pt/docs/advanced/generate-clients.md
index 04d7c0071..dc6b29511 100644
--- a/docs/pt/docs/advanced/generate-clients.md
+++ b/docs/pt/docs/advanced/generate-clients.md
@@ -22,7 +22,7 @@ E isso mostra o verdadeiro compromisso deles com o FastAPI e sua **comunidade**
Por exemplo, você pode querer experimentar:
-*
Speakeasy
+*
Speakeasy
*
Stainless
*
liblab
diff --git a/docs/ru/docs/advanced/index.md b/docs/ru/docs/advanced/index.md
new file mode 100644
index 000000000..b5cb733e7
--- /dev/null
+++ b/docs/ru/docs/advanced/index.md
@@ -0,0 +1,21 @@
+# Расширенное руководство пользователя
+
+## Дополнительные возможности
+
+Основное [Учебник - Руководство пользователя](../tutorial/index.md){.internal-link target=_blank} должно быть достаточно, чтобы познакомить вас со всеми основными функциями **FastAPI**.
+
+В следующих разделах вы увидите другие варианты, конфигурации и дополнительные возможности.
+
+/// tip
+
+Следующие разделы **не обязательно являются "продвинутыми"**.
+
+И вполне возможно, что для вашего случая использования решение находится в одном из них.
+
+///
+
+## Сначала прочитайте Учебник - Руководство пользователя
+
+Вы все еще можете использовать большинство функций **FastAPI** со знаниями из [Учебник - Руководство пользователя](../tutorial/index.md){.internal-link target=_blank}.
+
+И следующие разделы предполагают, что вы уже прочитали его, и предполагают, что вы знаете эти основные идеи.
diff --git a/docs/ru/docs/advanced/response-change-status-code.md b/docs/ru/docs/advanced/response-change-status-code.md
new file mode 100644
index 000000000..37dade99f
--- /dev/null
+++ b/docs/ru/docs/advanced/response-change-status-code.md
@@ -0,0 +1,31 @@
+# Response - Изменение cтатус кода
+
+Вы, вероятно, уже читали о том, что можно установить [Состояние ответа по умолчанию](../tutorial/response-status-code.md){.internal-link target=_blank}.
+
+Но в некоторых случаях вам нужно вернуть код состояния, отличный от установленного по умолчанию.
+
+## Пример использования
+
+Например, представьте, что вы хотите возвращать HTTP код состояния "OK" `200` по умолчанию.
+
+Но если данные не существовали, вы хотите создать их и вернуть HTTP код состояния "CREATED" `201`.
+
+При этом вы всё ещё хотите иметь возможность фильтровать и преобразовывать возвращаемые данные с помощью `response_model`.
+
+Для таких случаев вы можете использовать параметр `Response`.
+
+## Использование параметра `Response`
+
+Вы можете объявить параметр типа `Response` в вашей *функции обработки пути* (так же как для cookies и headers).
+
+И затем вы можете установить `status_code` в этом *временном* объекте ответа.
+
+{* ../../docs_src/response_change_status_code/tutorial001.py hl[1,9,12] *}
+
+После этого вы можете вернуть любой объект, который вам нужен, как обычно (`dict`, модель базы данных и т.д.).
+
+И если вы объявили `response_model`, он всё равно будет использоваться для фильтрации и преобразования возвращаемого объекта.
+
+**FastAPI** будет использовать этот *временный* ответ для извлечения кода состояния (а также cookies и headers) и поместит их в финальный ответ, который содержит возвращаемое вами значение, отфильтрованное любым `response_model`.
+
+Вы также можете объявить параметр `Response` в зависимостях и установить код состояния в них. Но помните, что последнее установленное значение будет иметь приоритет.
diff --git a/docs/uk/docs/tutorial/schema-extra-example.md b/docs/uk/docs/tutorial/schema-extra-example.md
new file mode 100644
index 000000000..853fd5e65
--- /dev/null
+++ b/docs/uk/docs/tutorial/schema-extra-example.md
@@ -0,0 +1,222 @@
+# Декларування прикладів вхідних даних
+
+Ви можете задати приклади даних, які Ваш застосунок може отримувати.
+
+Ось кілька способів, як це зробити.
+
+## Додаткові дані JSON-схеми в моделях Pydantic
+
+Ви можете задати `examples` для моделі Pydantic, які буде додано до згенерованої JSON-схеми.
+
+//// tab | Pydantic v2
+
+{* ../../docs_src/schema_extra_example/tutorial001_py310.py hl[13:24] *}
+
+////
+
+//// tab | Pydantic v1
+
+{* ../../docs_src/schema_extra_example/tutorial001_pv1_py310.py hl[13:23] *}
+
+////
+
+Ця додаткова інформація буде додана як є до **JSON-схеми**, і вона буде використовуватися в документації до API.
+
+//// tab | Pydantic v2
+
+У версії Pydantic 2 використовується атрибут `model_config`, який приймає `dict`, як описано в
документації Pydantic: Конфігурація.
+
+Ви можете встановити `"json_schema_extra"` як `dict`, що містить будь-які додаткові дані, які Ви хочете відобразити у згенерованій JSON-схемі, включаючи `examples`.
+
+////
+
+//// tab | Pydantic v1
+
+У версії Pydantic 1 використовується внутрішній клас `Config` і параметр `schema_extra`, як описано в
документації Pydantic: Налаштування схеми.
+
+Ви можете задати `schema_extra` як `dict`, що містить будь-які додаткові дані, які Ви хочете бачити у згенерованій JSON-схемі, включаючи `examples`.
+
+////
+
+/// tip | Підказка
+
+Ви можете використати ту ж техніку, щоб розширити JSON-схему і додати власну додаткову інформацію.
+
+Наприклад, Ви можете використати її для додавання метаданих для інтерфейсу користувача на фронтенді тощо.
+
+///
+
+/// info | Інформація
+
+OpenAPI 3.1.0 (який використовується починаючи з FastAPI 0.99.0) додав підтримку `examples`, що є частиною стандарту **JSON-схеми**.
+
+До цього підтримувався лише ключ `example` з одним прикладом. Він все ще підтримується в OpenAPI 3.1.0, але є застарілим і не входить до стандарту JSON Schema. Тому рекомендується перейти з `example` на `examples`. 🤓
+
+Більше про це можна прочитати в кінці цієї сторінки.
+
+///
+
+## Додаткові аргументи `Field`
+
+Коли ви використовуєте `Field()` у моделях Pydantic, Ви також можете вказати додаткові `examples`:
+
+{* ../../docs_src/schema_extra_example/tutorial002_py310.py hl[2,8:11] *}
+
+## `examples` у JSON-схемі — OpenAPI
+
+При використанні будь-кого з наступного:
+
+* `Path()`
+* `Query()`
+* `Header()`
+* `Cookie()`
+* `Body()`
+* `Form()`
+* `File()`
+
+Ви також можете задати набір `examples` з додатковою інформацією, яка буде додана до їхніх **JSON-схем** у **OpenAPI**.
+
+### `Body` з `examples`
+
+Тут ми передаємо `examples`, які містять один приклад очікуваних даних у `Body()`:
+
+{* ../../docs_src/schema_extra_example/tutorial003_an_py310.py hl[22:29] *}
+
+### Приклад у UI документації
+
+За допомогою будь-якого з наведених вище методів це виглядатиме так у документації за `/docs`:
+
+

+
+### `Body` з кількома `examples`
+
+Звичайно, Ви також можете передати кілька `examples`:
+
+{* ../../docs_src/schema_extra_example/tutorial004_an_py310.py hl[23:38] *}
+
+Коли Ви це робите, приклади будуть частиною внутрішньої **JSON-схеми** для цих даних.
+
+Втім, на момент написання цього (
26 серпня 2023), Swagger UI — інструмент, який відповідає за відображення UI документації — не підтримує показ кількох прикладів у **JSON-схеми**. Але нижче можна прочитати про обхідний шлях.
+
+### Специфічні для OpenAPI `examples`
+
+Ще до того, як **JSON-схема** почала підтримувати `examples`, OpenAPI вже мала підтримку поля з такою ж назвою — `examples`.
+
+Це **специфічне для OpenAPI** поле `examples` розміщується в іншій частині специфікації OpenAPI — у **деталях кожної *операції шляху***, а не всередині самої JSON-схеми.
+
+Swagger UI вже давно підтримує це поле `examples`. Тому Ви можете використовувати його, щоб **відображати** кілька **прикладів у документації**.
+
+Це поле `examples` у специфікації OpenAPI — це `dict` (словник) з **кількома прикладами** (а не список `list`), кожен із яких може містити додаткову інформацію, що буде додана до **OpenAPI**.
+
+Воно не включається до JSON Schema кожного параметра, а розміщується зовні, безпосередньо в *операції шляху*.
+
+### Використання параметра `openapi_examples`
+
+Ви можете оголосити специфічні для OpenAPI `examples` у FastAPI за допомогою параметра `openapi_examples` для:
+
+* `Path()`
+* `Query()`
+* `Header()`
+* `Cookie()`
+* `Body()`
+* `Form()`
+* `File()`
+
+Ключі словника (`dict`) ідентифікують кожен приклад, а кожне значення `dict` — кожен специфічний словник `dict` в `examples` може містити:
+
+* `summary`: короткий опис прикладу.
+* `description`: розгорнутий опис (може містити Markdown).
+* `value`: сам приклад, наприклад, словник (`dict`).
+* `externalValue`: альтернатива `value`, URL-адреса, що вказує на приклад. Проте ця опція може не підтримуватися більшістю інструментів, на відміну від `value`.
+
+Використання виглядає так:
+
+{* ../../docs_src/schema_extra_example/tutorial005_an_py310.py hl[23:49] *}
+
+### Приклади OpenAPI у UI документації
+
+З параметром `openapi_examples`, доданим до `Body()`, документація `/docs` виглядатиме так:
+
+

+
+## Технічні деталі
+
+/// tip | Підказка
+
+Якщо Ви вже використовуєте **FastAPI** версії **0.99.0 або вище**, Ви можете **пропустити** цей розділ.
+
+Він більш актуальний для старих версій, до появи OpenAPI 3.1.0.
+
+Можна вважати це коротким **історичним екскурсом** у OpenAPI та JSON Schema. 🤓
+
+///
+
+/// warning | Попередження
+
+Це дуже технічна інформація про стандарти **JSON Schema** і **OpenAPI**.
+
+Якщо вищезгадані ідеї вже працюють у Вас — можете не заглиблюватися в ці деталі.
+
+///
+
+До OpenAPI 3.1.0 специфікація використовувала стару та модифіковану версію **JSON Schema**.
+
+Оскільки JSON Schema раніше не підтримувала `examples`, OpenAPI додала власне поле `examples`.
+
+OpenAPI також додала `example` і `examples` до інших частин специфікації:
+
+*
`Parameter Object` (в специфікації) використовується FastAPI для:
+ * `Path()`
+ * `Query()`
+ * `Header()`
+ * `Cookie()`
+*
`Request Body Object`, в полі `content`, в `Media Type Object` (в специфікації) використовується FastAPI для:
+ * `Body()`
+ * `File()`
+ * `Form()`
+
+/// info | Інформація
+
+Цей старий параметр `examples`, специфічний для OpenAPI, тепер називається `openapi_examples`, починаючи з FastAPI версії `0.103.0`.
+
+///
+
+### Поле `examples` у JSON Schema
+
+Пізніше JSON Schema додала поле
`examples` у нову версію специфікації.
+
+І вже OpenAPI 3.1.0 базується на цій новій версії (JSON Schema 2020-12), яка включає поле `examples`.
+
+Тепер це поле `examples` є пріоритетним і замінює старе (і кастомне) поле `example`, яке стало застарілим.
+
+Нове поле `examples` у JSON Schema — це **просто список (`list`)** прикладів, без додаткових метаданих (на відміну від OpenAPI).
+
+/// info | Інформація
+
+Навіть після того, як з'явився OpenAPI 3.1.0, який підтримував examples у JSON Schema, інструмент Swagger UI ще деякий час не підтримував цю версію (підтримка з’явилась з версії 5.0.0 🎉).
+
+Через це версії FastAPI до 0.99.0 все ще використовували версії OpenAPI нижчі за 3.1.0.
+
+///
+
+### `Examples` в Pydantic і FastAPI
+
+Коли Ви додаєте `examples` у модель Pydantic через `schema_extra` або `Field(examples=["something"])`, ці приклади додаються до **JSON Schema** цієї моделі.
+
+І ця **JSON Schema** Pydantic-моделі включається до **OpenAPI** Вашого API, а потім використовується в UI документації (docs UI).
+
+У версіях FastAPI до 0.99.0 (починаючи з 0.99.0 використовується новіший OpenAPI 3.1.0), коли Ви використовували `example` або `examples` з іншими утилітами (`Query()`, `Body()` тощо), ці приклади не додавалися до JSON Schema, який описує ці дані (навіть не до власної версії JSON Schema у OpenAPI). Натомість вони додавалися безпосередньо до опису *обробника шляху* *(path operation)* в OpenAPI (тобто поза межами частин, які використовують JSON Schema).
+
+Але тепер, коли FastAPI 0.99.0 і вище використовують OpenAPI 3.1.0, а той — JSON Schema 2020-12, разом із Swagger UI 5.0.0 і вище — все стало більш узгодженим, і examples тепер включаються до JSON Schema.
+
+### Swagger UI та специфічні для OpenAPI `examples`
+
+Раніше (станом на 26 серпня 2023 року) Swagger UI не підтримував кілька прикладів у JSON Schema, тому користувачі не мали можливості показати декілька прикладів у документації.
+
+Щоб вирішити це, FastAPI починаючи з версії 0.103.0 **додав підтримку** старого **OpenAPI-специфічного** поля `examples` через новий параметр `openapi_examples`. 🤓
+
+### Підсумок
+
+Раніше я казав, що не люблю історію... а тепер ось я — розповідаю "технічні історичні" лекції. 😅
+
+Коротко: **оновіться до FastAPI 0.99.0 або вище** — і все стане значно **простішим, узгодженим та інтуїтивно зрозумілим**, і Вам не доведеться знати всі ці історичні деталі. 😎
diff --git a/fastapi/__init__.py b/fastapi/__init__.py
index 80eb783da..1768d0204 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.115.12"
+__version__ = "0.115.13"
from starlette import status as status
diff --git a/fastapi/_compat.py b/fastapi/_compat.py
index c07e4a3b0..227ad837d 100644
--- a/fastapi/_compat.py
+++ b/fastapi/_compat.py
@@ -16,6 +16,7 @@ from typing import (
Tuple,
Type,
Union,
+ cast,
)
from fastapi.exceptions import RequestErrorModel
@@ -231,6 +232,10 @@ if PYDANTIC_V2:
field_mapping, definitions = schema_generator.generate_definitions(
inputs=inputs
)
+ for item_def in cast(Dict[str, Dict[str, Any]], definitions).values():
+ if "description" in item_def:
+ item_description = cast(str, item_def["description"]).split("\f")[0]
+ item_def["description"] = item_description
return field_mapping, definitions # type: ignore[return-value]
def is_scalar_field(field: ModelField) -> bool:
diff --git a/fastapi/applications.py b/fastapi/applications.py
index 6d427cdc2..05c7bd2be 100644
--- a/fastapi/applications.py
+++ b/fastapi/applications.py
@@ -748,7 +748,7 @@ class FastAPI(Starlette):
This affects the generated OpenAPI (e.g. visible at `/docs`).
Read more about it in the
- [FastAPI docs for Query Parameters and String Validations](https://fastapi.tiangolo.com/tutorial/query-params-str-validations/#exclude-from-openapi).
+ [FastAPI docs for Query Parameters and String Validations](https://fastapi.tiangolo.com/tutorial/query-params-str-validations/#exclude-parameters-from-openapi).
"""
),
] = True,
@@ -1720,7 +1720,7 @@ class FastAPI(Starlette):
This affects the generated OpenAPI (e.g. visible at `/docs`).
Read more about it in the
- [FastAPI docs for Query Parameters and String Validations](https://fastapi.tiangolo.com/tutorial/query-params-str-validations/#exclude-from-openapi).
+ [FastAPI docs for Query Parameters and String Validations](https://fastapi.tiangolo.com/tutorial/query-params-str-validations/#exclude-parameters-from-openapi).
"""
),
] = True,
@@ -2093,7 +2093,7 @@ class FastAPI(Starlette):
This affects the generated OpenAPI (e.g. visible at `/docs`).
Read more about it in the
- [FastAPI docs for Query Parameters and String Validations](https://fastapi.tiangolo.com/tutorial/query-params-str-validations/#exclude-from-openapi).
+ [FastAPI docs for Query Parameters and String Validations](https://fastapi.tiangolo.com/tutorial/query-params-str-validations/#exclude-parameters-from-openapi).
"""
),
] = True,
@@ -2471,7 +2471,7 @@ class FastAPI(Starlette):
This affects the generated OpenAPI (e.g. visible at `/docs`).
Read more about it in the
- [FastAPI docs for Query Parameters and String Validations](https://fastapi.tiangolo.com/tutorial/query-params-str-validations/#exclude-from-openapi).
+ [FastAPI docs for Query Parameters and String Validations](https://fastapi.tiangolo.com/tutorial/query-params-str-validations/#exclude-parameters-from-openapi).
"""
),
] = True,
@@ -2849,7 +2849,7 @@ class FastAPI(Starlette):
This affects the generated OpenAPI (e.g. visible at `/docs`).
Read more about it in the
- [FastAPI docs for Query Parameters and String Validations](https://fastapi.tiangolo.com/tutorial/query-params-str-validations/#exclude-from-openapi).
+ [FastAPI docs for Query Parameters and String Validations](https://fastapi.tiangolo.com/tutorial/query-params-str-validations/#exclude-parameters-from-openapi).
"""
),
] = True,
@@ -3222,7 +3222,7 @@ class FastAPI(Starlette):
This affects the generated OpenAPI (e.g. visible at `/docs`).
Read more about it in the
- [FastAPI docs for Query Parameters and String Validations](https://fastapi.tiangolo.com/tutorial/query-params-str-validations/#exclude-from-openapi).
+ [FastAPI docs for Query Parameters and String Validations](https://fastapi.tiangolo.com/tutorial/query-params-str-validations/#exclude-parameters-from-openapi).
"""
),
] = True,
@@ -3595,7 +3595,7 @@ class FastAPI(Starlette):
This affects the generated OpenAPI (e.g. visible at `/docs`).
Read more about it in the
- [FastAPI docs for Query Parameters and String Validations](https://fastapi.tiangolo.com/tutorial/query-params-str-validations/#exclude-from-openapi).
+ [FastAPI docs for Query Parameters and String Validations](https://fastapi.tiangolo.com/tutorial/query-params-str-validations/#exclude-parameters-from-openapi).
"""
),
] = True,
@@ -3968,7 +3968,7 @@ class FastAPI(Starlette):
This affects the generated OpenAPI (e.g. visible at `/docs`).
Read more about it in the
- [FastAPI docs for Query Parameters and String Validations](https://fastapi.tiangolo.com/tutorial/query-params-str-validations/#exclude-from-openapi).
+ [FastAPI docs for Query Parameters and String Validations](https://fastapi.tiangolo.com/tutorial/query-params-str-validations/#exclude-parameters-from-openapi).
"""
),
] = True,
@@ -4346,7 +4346,7 @@ class FastAPI(Starlette):
This affects the generated OpenAPI (e.g. visible at `/docs`).
Read more about it in the
- [FastAPI docs for Query Parameters and String Validations](https://fastapi.tiangolo.com/tutorial/query-params-str-validations/#exclude-from-openapi).
+ [FastAPI docs for Query Parameters and String Validations](https://fastapi.tiangolo.com/tutorial/query-params-str-validations/#exclude-parameters-from-openapi).
"""
),
] = True,
@@ -4425,7 +4425,7 @@ class FastAPI(Starlette):
app = FastAPI()
- @app.put("/items/{item_id}")
+ @app.trace("/items/{item_id}")
def trace_item(item_id: str):
return None
```
@@ -4515,14 +4515,17 @@ class FastAPI(Starlette):
```python
import time
+ from typing import Awaitable, Callable
- from fastapi import FastAPI, Request
+ from fastapi import FastAPI, Request, Response
app = FastAPI()
@app.middleware("http")
- async def add_process_time_header(request: Request, call_next):
+ async def add_process_time_header(
+ request: Request, call_next: Callable[[Request], Awaitable[Response]]
+ ) -> Response:
start_time = time.time()
response = await call_next(request)
process_time = time.time() - start_time
diff --git a/fastapi/routing.py b/fastapi/routing.py
index 457481e32..bf61a65c1 100644
--- a/fastapi/routing.py
+++ b/fastapi/routing.py
@@ -814,7 +814,7 @@ class APIRouter(routing.Router):
This affects the generated OpenAPI (e.g. visible at `/docs`).
Read more about it in the
- [FastAPI docs for Query Parameters and String Validations](https://fastapi.tiangolo.com/tutorial/query-params-str-validations/#exclude-from-openapi).
+ [FastAPI docs for Query Parameters and String Validations](https://fastapi.tiangolo.com/tutorial/query-params-str-validations/#exclude-parameters-from-openapi).
"""
),
] = True,
@@ -1626,7 +1626,7 @@ class APIRouter(routing.Router):
This affects the generated OpenAPI (e.g. visible at `/docs`).
Read more about it in the
- [FastAPI docs for Query Parameters and String Validations](https://fastapi.tiangolo.com/tutorial/query-params-str-validations/#exclude-from-openapi).
+ [FastAPI docs for Query Parameters and String Validations](https://fastapi.tiangolo.com/tutorial/query-params-str-validations/#exclude-parameters-from-openapi).
"""
),
] = True,
@@ -2003,7 +2003,7 @@ class APIRouter(routing.Router):
This affects the generated OpenAPI (e.g. visible at `/docs`).
Read more about it in the
- [FastAPI docs for Query Parameters and String Validations](https://fastapi.tiangolo.com/tutorial/query-params-str-validations/#exclude-from-openapi).
+ [FastAPI docs for Query Parameters and String Validations](https://fastapi.tiangolo.com/tutorial/query-params-str-validations/#exclude-parameters-from-openapi).
"""
),
] = True,
@@ -2385,7 +2385,7 @@ class APIRouter(routing.Router):
This affects the generated OpenAPI (e.g. visible at `/docs`).
Read more about it in the
- [FastAPI docs for Query Parameters and String Validations](https://fastapi.tiangolo.com/tutorial/query-params-str-validations/#exclude-from-openapi).
+ [FastAPI docs for Query Parameters and String Validations](https://fastapi.tiangolo.com/tutorial/query-params-str-validations/#exclude-parameters-from-openapi).
"""
),
] = True,
@@ -2767,7 +2767,7 @@ class APIRouter(routing.Router):
This affects the generated OpenAPI (e.g. visible at `/docs`).
Read more about it in the
- [FastAPI docs for Query Parameters and String Validations](https://fastapi.tiangolo.com/tutorial/query-params-str-validations/#exclude-from-openapi).
+ [FastAPI docs for Query Parameters and String Validations](https://fastapi.tiangolo.com/tutorial/query-params-str-validations/#exclude-parameters-from-openapi).
"""
),
] = True,
@@ -3144,7 +3144,7 @@ class APIRouter(routing.Router):
This affects the generated OpenAPI (e.g. visible at `/docs`).
Read more about it in the
- [FastAPI docs for Query Parameters and String Validations](https://fastapi.tiangolo.com/tutorial/query-params-str-validations/#exclude-from-openapi).
+ [FastAPI docs for Query Parameters and String Validations](https://fastapi.tiangolo.com/tutorial/query-params-str-validations/#exclude-parameters-from-openapi).
"""
),
] = True,
@@ -3521,7 +3521,7 @@ class APIRouter(routing.Router):
This affects the generated OpenAPI (e.g. visible at `/docs`).
Read more about it in the
- [FastAPI docs for Query Parameters and String Validations](https://fastapi.tiangolo.com/tutorial/query-params-str-validations/#exclude-from-openapi).
+ [FastAPI docs for Query Parameters and String Validations](https://fastapi.tiangolo.com/tutorial/query-params-str-validations/#exclude-parameters-from-openapi).
"""
),
] = True,
@@ -3903,7 +3903,7 @@ class APIRouter(routing.Router):
This affects the generated OpenAPI (e.g. visible at `/docs`).
Read more about it in the
- [FastAPI docs for Query Parameters and String Validations](https://fastapi.tiangolo.com/tutorial/query-params-str-validations/#exclude-from-openapi).
+ [FastAPI docs for Query Parameters and String Validations](https://fastapi.tiangolo.com/tutorial/query-params-str-validations/#exclude-parameters-from-openapi).
"""
),
] = True,
@@ -4285,7 +4285,7 @@ class APIRouter(routing.Router):
This affects the generated OpenAPI (e.g. visible at `/docs`).
Read more about it in the
- [FastAPI docs for Query Parameters and String Validations](https://fastapi.tiangolo.com/tutorial/query-params-str-validations/#exclude-from-openapi).
+ [FastAPI docs for Query Parameters and String Validations](https://fastapi.tiangolo.com/tutorial/query-params-str-validations/#exclude-parameters-from-openapi).
"""
),
] = True,
diff --git a/fastapi/security/oauth2.py b/fastapi/security/oauth2.py
index 9efa65a4c..51065e4e2 100644
--- a/fastapi/security/oauth2.py
+++ b/fastapi/security/oauth2.py
@@ -85,7 +85,7 @@ class OAuth2PasswordRequestForm:
],
password: Annotated[
str,
- Form(),
+ Form(json_schema_extra={"format": "password"}),
Doc(
"""
`password` string. The OAuth2 spec requires the exact field name
@@ -130,7 +130,7 @@ class OAuth2PasswordRequestForm:
] = None,
client_secret: Annotated[
Union[str, None],
- Form(),
+ Form(json_schema_extra={"format": "password"}),
Doc(
"""
If there's a `client_password` (and a `client_id`), they can be sent
@@ -459,11 +459,26 @@ class OAuth2PasswordBearer(OAuth2):
"""
),
] = True,
+ refreshUrl: Annotated[
+ Optional[str],
+ Doc(
+ """
+ The URL to refresh the token and obtain a new one.
+ """
+ ),
+ ] = None,
):
if not scopes:
scopes = {}
flows = OAuthFlowsModel(
- password=cast(Any, {"tokenUrl": tokenUrl, "scopes": scopes})
+ password=cast(
+ Any,
+ {
+ "tokenUrl": tokenUrl,
+ "refreshUrl": refreshUrl,
+ "scopes": scopes,
+ },
+ )
)
super().__init__(
flows=flows,
diff --git a/scripts/label_approved.py b/scripts/label_approved.py
index 271444504..81de92efb 100644
--- a/scripts/label_approved.py
+++ b/scripts/label_approved.py
@@ -27,7 +27,7 @@ if settings.debug:
logging.basicConfig(level=logging.DEBUG)
else:
logging.basicConfig(level=logging.INFO)
-logging.debug(f"Using config: {settings.json()}")
+logging.debug(f"Using config: {settings.model_dump_json()}")
g = Github(settings.token.get_secret_value())
repo = g.get_repo(settings.github_repository)
for pr in repo.get_pulls(state="open"):
@@ -48,7 +48,7 @@ for pr in repo.get_pulls(state="open"):
]
config = settings.config or default_config
for approved_label, conf in config.items():
- logging.debug(f"Processing config: {conf.json()}")
+ logging.debug(f"Processing config: {conf.model_dump_json()}")
if conf.await_label is None or (conf.await_label in pr_label_by_name):
logging.debug(f"Processable PR: {pr.number}")
if len(approved_reviews) >= conf.number:
diff --git a/tests/test_openapi_model_description_trim_on_formfeed.py b/tests/test_openapi_model_description_trim_on_formfeed.py
new file mode 100644
index 000000000..e18d4f6b2
--- /dev/null
+++ b/tests/test_openapi_model_description_trim_on_formfeed.py
@@ -0,0 +1,31 @@
+from fastapi import FastAPI
+from fastapi.testclient import TestClient
+from pydantic import BaseModel
+
+app = FastAPI()
+
+
+class MyModel(BaseModel):
+ """
+ A model with a form feed character in the title.
+ \f
+ Text after form feed character.
+ """
+
+
+@app.get("/foo")
+def foo(v: MyModel): # pragma: no cover
+ pass
+
+
+client = TestClient(app)
+
+
+def test_openapi():
+ response = client.get("/openapi.json")
+ assert response.status_code == 200, response.text
+ openapi_schema = response.json()
+
+ assert openapi_schema["components"]["schemas"]["MyModel"]["description"] == (
+ "A model with a form feed character in the title.\n"
+ )
diff --git a/tests/test_tutorial/test_security/test_tutorial003.py b/tests/test_tutorial/test_security/test_tutorial003.py
index 37fc2618f..2bbb2e851 100644
--- a/tests/test_tutorial/test_security/test_tutorial003.py
+++ b/tests/test_tutorial/test_security/test_tutorial003.py
@@ -163,7 +163,11 @@ def test_openapi_schema(client: TestClient):
}
),
"username": {"title": "Username", "type": "string"},
- "password": {"title": "Password", "type": "string"},
+ "password": {
+ "title": "Password",
+ "type": "string",
+ "format": "password",
+ },
"scope": {"title": "Scope", "type": "string", "default": ""},
"client_id": IsDict(
{
@@ -179,11 +183,16 @@ def test_openapi_schema(client: TestClient):
{
"title": "Client Secret",
"anyOf": [{"type": "string"}, {"type": "null"}],
+ "format": "password",
}
)
| IsDict(
# TODO: remove when deprecating Pydantic v1
- {"title": "Client Secret", "type": "string"}
+ {
+ "title": "Client Secret",
+ "type": "string",
+ "format": "password",
+ }
),
},
},
diff --git a/tests/test_tutorial/test_security/test_tutorial005.py b/tests/test_tutorial/test_security/test_tutorial005.py
index 88c3d7815..ad644d61b 100644
--- a/tests/test_tutorial/test_security/test_tutorial005.py
+++ b/tests/test_tutorial/test_security/test_tutorial005.py
@@ -377,7 +377,11 @@ def test_openapi_schema(mod: ModuleType):
}
),
"username": {"title": "Username", "type": "string"},
- "password": {"title": "Password", "type": "string"},
+ "password": {
+ "title": "Password",
+ "type": "string",
+ "format": "password",
+ },
"scope": {"title": "Scope", "type": "string", "default": ""},
"client_id": IsDict(
{
@@ -393,11 +397,16 @@ def test_openapi_schema(mod: ModuleType):
{
"title": "Client Secret",
"anyOf": [{"type": "string"}, {"type": "null"}],
+ "format": "password",
}
)
| IsDict(
# TODO: remove when deprecating Pydantic v1
- {"title": "Client Secret", "type": "string"}
+ {
+ "title": "Client Secret",
+ "type": "string",
+ "format": "password",
+ }
),
},
},
diff --git a/tests/test_tutorial/test_settings/test_tutorial001.py b/tests/test_tutorial/test_settings/test_tutorial001.py
index eb30dbcee..92a5782d4 100644
--- a/tests/test_tutorial/test_settings/test_tutorial001.py
+++ b/tests/test_tutorial/test_settings/test_tutorial001.py
@@ -1,14 +1,26 @@
+import importlib
+
+import pytest
from fastapi.testclient import TestClient
from pytest import MonkeyPatch
-from ...utils import needs_pydanticv2
+from ...utils import needs_pydanticv1, needs_pydanticv2
-@needs_pydanticv2
-def test_settings(monkeypatch: MonkeyPatch):
+@pytest.fixture(
+ name="app",
+ params=[
+ pytest.param("tutorial001", marks=needs_pydanticv2),
+ pytest.param("tutorial001_pv1", marks=needs_pydanticv1),
+ ],
+)
+def get_app(request: pytest.FixtureRequest, monkeypatch: MonkeyPatch):
monkeypatch.setenv("ADMIN_EMAIL", "admin@example.com")
- from docs_src.settings.tutorial001 import app
+ mod = importlib.import_module(f"docs_src.settings.{request.param}")
+ return mod.app
+
+def test_settings(app):
client = TestClient(app)
response = client.get("/info")
assert response.status_code == 200, response.text
diff --git a/tests/test_tutorial/test_settings/test_tutorial001_pv1.py b/tests/test_tutorial/test_settings/test_tutorial001_pv1.py
deleted file mode 100644
index e4659de66..000000000
--- a/tests/test_tutorial/test_settings/test_tutorial001_pv1.py
+++ /dev/null
@@ -1,19 +0,0 @@
-from fastapi.testclient import TestClient
-from pytest import MonkeyPatch
-
-from ...utils import needs_pydanticv1
-
-
-@needs_pydanticv1
-def test_settings(monkeypatch: MonkeyPatch):
- monkeypatch.setenv("ADMIN_EMAIL", "admin@example.com")
- from docs_src.settings.tutorial001_pv1 import app
-
- client = TestClient(app)
- response = client.get("/info")
- assert response.status_code == 200, response.text
- assert response.json() == {
- "app_name": "Awesome API",
- "admin_email": "admin@example.com",
- "items_per_user": 50,
- }
diff --git a/tests/test_validate_response_recursive/app_pv1.py b/tests/test_validate_response_recursive/app.py
similarity index 79%
rename from tests/test_validate_response_recursive/app_pv1.py
rename to tests/test_validate_response_recursive/app.py
index 4cfc4b3ee..d23d27980 100644
--- a/tests/test_validate_response_recursive/app_pv1.py
+++ b/tests/test_validate_response_recursive/app.py
@@ -1,6 +1,7 @@
from typing import List
from fastapi import FastAPI
+from fastapi._compat import PYDANTIC_V2
from pydantic import BaseModel
app = FastAPI()
@@ -11,9 +12,6 @@ class RecursiveItem(BaseModel):
name: str
-RecursiveItem.update_forward_refs()
-
-
class RecursiveSubitemInSubmodel(BaseModel):
sub_items2: List["RecursiveItemViaSubmodel"] = []
name: str
@@ -24,7 +22,13 @@ class RecursiveItemViaSubmodel(BaseModel):
name: str
-RecursiveSubitemInSubmodel.update_forward_refs()
+if PYDANTIC_V2:
+ RecursiveItem.model_rebuild()
+ RecursiveSubitemInSubmodel.model_rebuild()
+ RecursiveItemViaSubmodel.model_rebuild()
+else:
+ RecursiveItem.update_forward_refs()
+ RecursiveSubitemInSubmodel.update_forward_refs()
@app.get("/items/recursive", response_model=RecursiveItem)
diff --git a/tests/test_validate_response_recursive/app_pv2.py b/tests/test_validate_response_recursive/app_pv2.py
deleted file mode 100644
index 8c93a8349..000000000
--- a/tests/test_validate_response_recursive/app_pv2.py
+++ /dev/null
@@ -1,51 +0,0 @@
-from typing import List
-
-from fastapi import FastAPI
-from pydantic import BaseModel
-
-app = FastAPI()
-
-
-class RecursiveItem(BaseModel):
- sub_items: List["RecursiveItem"] = []
- name: str
-
-
-RecursiveItem.model_rebuild()
-
-
-class RecursiveSubitemInSubmodel(BaseModel):
- sub_items2: List["RecursiveItemViaSubmodel"] = []
- name: str
-
-
-class RecursiveItemViaSubmodel(BaseModel):
- sub_items1: List[RecursiveSubitemInSubmodel] = []
- name: str
-
-
-RecursiveSubitemInSubmodel.model_rebuild()
-RecursiveItemViaSubmodel.model_rebuild()
-
-
-@app.get("/items/recursive", response_model=RecursiveItem)
-def get_recursive():
- return {"name": "item", "sub_items": [{"name": "subitem", "sub_items": []}]}
-
-
-@app.get("/items/recursive-submodel", response_model=RecursiveItemViaSubmodel)
-def get_recursive_submodel():
- return {
- "name": "item",
- "sub_items1": [
- {
- "name": "subitem",
- "sub_items2": [
- {
- "name": "subsubitem",
- "sub_items1": [{"name": "subsubsubitem", "sub_items2": []}],
- }
- ],
- }
- ],
- }
diff --git a/tests/test_validate_response_recursive/test_validate_response_recursive_pv2.py b/tests/test_validate_response_recursive/test_validate_response_recursive.py
similarity index 90%
rename from tests/test_validate_response_recursive/test_validate_response_recursive_pv2.py
rename to tests/test_validate_response_recursive/test_validate_response_recursive.py
index 7d45e7fe4..21a299ab8 100644
--- a/tests/test_validate_response_recursive/test_validate_response_recursive_pv2.py
+++ b/tests/test_validate_response_recursive/test_validate_response_recursive.py
@@ -1,12 +1,9 @@
from fastapi.testclient import TestClient
-from ..utils import needs_pydanticv2
+from .app import app
-@needs_pydanticv2
def test_recursive():
- from .app_pv2 import app
-
client = TestClient(app)
response = client.get("/items/recursive")
assert response.status_code == 200, response.text
diff --git a/tests/test_validate_response_recursive/test_validate_response_recursive_pv1.py b/tests/test_validate_response_recursive/test_validate_response_recursive_pv1.py
deleted file mode 100644
index de578ae03..000000000
--- a/tests/test_validate_response_recursive/test_validate_response_recursive_pv1.py
+++ /dev/null
@@ -1,33 +0,0 @@
-from fastapi.testclient import TestClient
-
-from ..utils import needs_pydanticv1
-
-
-@needs_pydanticv1
-def test_recursive():
- from .app_pv1 import app
-
- client = TestClient(app)
- response = client.get("/items/recursive")
- assert response.status_code == 200, response.text
- assert response.json() == {
- "sub_items": [{"name": "subitem", "sub_items": []}],
- "name": "item",
- }
-
- response = client.get("/items/recursive-submodel")
- assert response.status_code == 200, response.text
- assert response.json() == {
- "name": "item",
- "sub_items1": [
- {
- "name": "subitem",
- "sub_items2": [
- {
- "name": "subsubitem",
- "sub_items1": [{"name": "subsubsubitem", "sub_items2": []}],
- }
- ],
- }
- ],
- }