diff --git a/.github/workflows/deploy-docs.yml b/.github/workflows/deploy-docs.yml
index d9ed61910..0b3096143 100644
--- a/.github/workflows/deploy-docs.yml
+++ b/.github/workflows/deploy-docs.yml
@@ -64,7 +64,7 @@ jobs:
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 ) }}
# TODO: Use v3 when it's fixed, probably in v3.11
# https://github.com/cloudflare/wrangler-action/issues/307
- uses: cloudflare/wrangler-action@v3.13
+ uses: cloudflare/wrangler-action@v3.14
# uses: cloudflare/wrangler-action@v3
with:
apiToken: ${{ secrets.CLOUDFLARE_API_TOKEN }}
diff --git a/README.md b/README.md
index d5d5ced52..9a1260b90 100644
--- a/README.md
+++ b/README.md
@@ -57,6 +57,7 @@ The key features are:
+
diff --git a/docs/az/docs/index.md b/docs/az/docs/index.md
index ad78d7d06..fbbbce130 100644
--- a/docs/az/docs/index.md
+++ b/docs/az/docs/index.md
@@ -6,7 +6,7 @@
-
+
diff --git a/docs/bn/docs/index.md b/docs/bn/docs/index.md
index 678ac9ca9..74ee230a1 100644
--- a/docs/bn/docs/index.md
+++ b/docs/bn/docs/index.md
@@ -5,15 +5,18 @@
FastAPI উচ্চক্ষমতা সম্পন্ন, সহজে শেখার এবং দ্রুত কোড করে প্রোডাকশনের জন্য ফ্রামওয়ার্ক।
-
+
diff --git a/docs/de/docs/tutorial/query-params-str-validations.md b/docs/de/docs/tutorial/query-params-str-validations.md
index f181d501c..de8879ce8 100644
--- a/docs/de/docs/tutorial/query-params-str-validations.md
+++ b/docs/de/docs/tutorial/query-params-str-validations.md
@@ -315,22 +315,6 @@ Wenn Sie einen Parameter erforderlich machen wollen, während Sie `Query` verwen
{* ../../docs_src/query_params_str_validations/tutorial006_an_py39.py hl[9] *}
-### Erforderlich mit Ellipse (`...`)
-
-Es gibt eine Alternative, die explizit deklariert, dass ein Wert erforderlich ist. Sie können als Default das Literal `...` setzen:
-
-{* ../../docs_src/query_params_str_validations/tutorial006b_an_py39.py hl[9] *}
-
-/// info
-
-Falls Sie das `...` bisher noch nicht gesehen haben: Es ist ein spezieller einzelner Wert, Teil von Python und wird „Ellipsis“ genannt (Deutsch: Ellipse).
-
-Es wird von Pydantic und FastAPI verwendet, um explizit zu deklarieren, dass ein Wert erforderlich ist.
-
-///
-
-Dies wird **FastAPI** wissen lassen, dass dieser Parameter erforderlich ist.
-
### Erforderlich, kann `None` sein
Sie können deklarieren, dass ein Parameter `None` akzeptiert, aber dennoch erforderlich ist. Das zwingt Clients, den Wert zu senden, selbst wenn er `None` ist.
diff --git a/docs/em/docs/index.md b/docs/em/docs/index.md
index 16b2019d3..57be59b07 100644
--- a/docs/em/docs/index.md
+++ b/docs/em/docs/index.md
@@ -12,7 +12,7 @@
-
+
diff --git a/docs/em/docs/tutorial/query-params-str-validations.md b/docs/em/docs/tutorial/query-params-str-validations.md
index dbaab5735..fd077bf8f 100644
--- a/docs/em/docs/tutorial/query-params-str-validations.md
+++ b/docs/em/docs/tutorial/query-params-str-validations.md
@@ -148,22 +148,6 @@ q: Union[str, None] = Query(default=None, min_length=3)
{* ../../docs_src/query_params_str_validations/tutorial006.py hl[7] *}
-### ✔ ⏮️ ❕ (`...`)
-
-📤 🎛 🌌 🎯 📣 👈 💲 ✔. 👆 💪 ⚒ `default` 🔢 🔑 💲 `...`:
-
-{* ../../docs_src/query_params_str_validations/tutorial006b.py hl[7] *}
-
-/// info
-
-🚥 👆 🚫 👀 👈 `...` ⏭: ⚫️ 🎁 👁 💲, ⚫️ 🍕 🐍 & 🤙 "❕".
-
-⚫️ ⚙️ Pydantic & FastAPI 🎯 📣 👈 💲 ✔.
-
-///
-
-👉 🔜 ➡️ **FastAPI** 💭 👈 👉 🔢 ✔.
-
### ✔ ⏮️ `None`
👆 💪 📣 👈 🔢 💪 🚫 `None`, ✋️ 👈 ⚫️ ✔. 👉 🔜 ⚡ 👩💻 📨 💲, 🚥 💲 `None`.
@@ -178,18 +162,6 @@ Pydantic, ❔ ⚫️❔ 🏋️ 🌐 💽 🔬 & 🛠️ FastAPI, ✔️
///
-### ⚙️ Pydantic `Required` ↩️ ❕ (`...`)
-
-🚥 👆 💭 😬 ⚙️ `...`, 👆 💪 🗄 & ⚙️ `Required` ⚪️➡️ Pydantic:
-
-{* ../../docs_src/query_params_str_validations/tutorial006d.py hl[2,8] *}
-
-/// tip
-
-💭 👈 🌅 💼, 🕐❔ 🕳 🚚, 👆 💪 🎯 🚫 `default` 🔢, 👆 🛎 🚫 ✔️ ⚙️ `...` 🚫 `Required`.
-
-///
-
## 🔢 🔢 📇 / 💗 💲
🕐❔ 👆 🔬 🔢 🔢 🎯 ⏮️ `Query` 👆 💪 📣 ⚫️ 📨 📇 💲, ⚖️ 🙆♀ 🎏 🌌, 📨 💗 💲.
diff --git a/docs/en/data/members.yml b/docs/en/data/members.yml
index cf016eae1..7ec16e917 100644
--- a/docs/en/data/members.yml
+++ b/docs/en/data/members.yml
@@ -17,3 +17,6 @@ members:
- login: patrick91
avatar_url: https://avatars.githubusercontent.com/u/667029
url: https://github.com/patrick91
+- login: luzzodev
+ avatar_url: https://avatars.githubusercontent.com/u/27291415
+ url: https://github.com/luzzodev
diff --git a/docs/en/data/sponsors.yml b/docs/en/data/sponsors.yml
index f9bf33ae9..b994e533a 100644
--- a/docs/en/data/sponsors.yml
+++ b/docs/en/data/sponsors.yml
@@ -32,6 +32,9 @@ gold:
- url: https://docs.render.com/deploy-fastapi?utm_source=deploydoc&utm_medium=referral&utm_campaign=fastapi
title: Deploy & scale any full-stack web app on Render. Focus on building apps, not infra.
img: https://fastapi.tiangolo.com/img/sponsors/render.svg
+ - url: https://www.coderabbit.ai/?utm_source=fastapi&utm_medium=badge&utm_campaign=fastapi
+ title: Cut Code Review Time & Bugs in Half with CodeRabbit
+ img: https://fastapi.tiangolo.com/img/sponsors/coderabbit.png
silver:
- url: https://github.com/deepset-ai/haystack/
title: Build powerful search from composable, open source building blocks
@@ -58,3 +61,6 @@ bronze:
- url: https://testdriven.io/courses/tdd-fastapi/
title: Learn to build high-quality web apps with best practices
img: https://fastapi.tiangolo.com/img/sponsors/testdriven.svg
+ - url: https://lambdatest.com/?utm_source=fastapi&utm_medium=partner&utm_campaign=sponsor&utm_term=opensource&utm_content=webpage
+ title: LambdaTest, AI-Powered Cloud-based Test Orchestration Platform
+ img: https://fastapi.tiangolo.com/img/sponsors/lambdatest.png
diff --git a/docs/en/docs/img/sponsors/coderabbit-banner.png b/docs/en/docs/img/sponsors/coderabbit-banner.png
new file mode 100644
index 000000000..da3bb3482
Binary files /dev/null and b/docs/en/docs/img/sponsors/coderabbit-banner.png differ
diff --git a/docs/en/docs/img/sponsors/coderabbit.png b/docs/en/docs/img/sponsors/coderabbit.png
new file mode 100644
index 000000000..74c25e884
Binary files /dev/null and b/docs/en/docs/img/sponsors/coderabbit.png differ
diff --git a/docs/en/docs/img/sponsors/lambdatest.png b/docs/en/docs/img/sponsors/lambdatest.png
new file mode 100644
index 000000000..674cbcb89
Binary files /dev/null and b/docs/en/docs/img/sponsors/lambdatest.png differ
diff --git a/docs/en/docs/release-notes.md b/docs/en/docs/release-notes.md
index 013cbfc7c..84d680d91 100644
--- a/docs/en/docs/release-notes.md
+++ b/docs/en/docs/release-notes.md
@@ -7,12 +7,34 @@ hide:
## Latest Changes
+### Refactors
+
+* ✅ Simplify tests for `query_params_str_validations`. PR [#13218](https://github.com/fastapi/fastapi/pull/13218) by [@alv2017](https://github.com/alv2017).
+* ✅ Simplify tests for `app_testing`. PR [#13220](https://github.com/fastapi/fastapi/pull/13220) by [@alv2017](https://github.com/alv2017).
+* ✅ Simplify tests for `dependency_testing`. PR [#13223](https://github.com/fastapi/fastapi/pull/13223) by [@alv2017](https://github.com/alv2017).
+
### Docs
+* 🩺 Unify the badges across all tutorial translations. PR [#13329](https://github.com/fastapi/fastapi/pull/13329) by [@svlandeg](https://github.com/svlandeg).
+* 📝 Fix typos in virtual environments documentation. PR [#13396](https://github.com/fastapi/fastapi/pull/13396) by [@bullet-ant](https://github.com/bullet-ant).
+* 🐛 Fix issue with Swagger theme change example in the official tutorial. PR [#13289](https://github.com/fastapi/fastapi/pull/13289) by [@Zerohertz](https://github.com/Zerohertz).
+* 📝 Add more precise description of HTTP status code range in docs. PR [#13347](https://github.com/fastapi/fastapi/pull/13347) by [@DanielYang59](https://github.com/DanielYang59).
+* 🔥 Remove manual type annotations in JWT tutorial to avoid typing expectations (JWT doesn't provide more types). PR [#13378](https://github.com/fastapi/fastapi/pull/13378) by [@tiangolo](https://github.com/tiangolo).
+* 📝 Update docs for Query Params and String Validations, remove obsolete Ellipsis docs (`...`). PR [#13377](https://github.com/fastapi/fastapi/pull/13377) by [@tiangolo](https://github.com/tiangolo).
+* ✏️ Remove duplicate title in docs `body-multiple-params`. PR [#13345](https://github.com/fastapi/fastapi/pull/13345) by [@DanielYang59](https://github.com/DanielYang59).
* 📝 Fix test badge. PR [#13313](https://github.com/fastapi/fastapi/pull/13313) by [@esadek](https://github.com/esadek).
### Translations
+* 🌐 Add Ukrainian translation for `docs/uk/docs/tutorial/header-params.md`. PR [#13381](https://github.com/fastapi/fastapi/pull/13381) by [@valentinDruzhinin](https://github.com/valentinDruzhinin).
+* 🌐 Add Ukrainian translation for `docs/uk/docs/tutorial/request-files.md`. PR [#13395](https://github.com/fastapi/fastapi/pull/13395) by [@valentinDruzhinin](https://github.com/valentinDruzhinin).
+* 🌐 Add Ukrainian translation for `docs/uk/docs/tutorial/request-form-models.md`. PR [#13384](https://github.com/fastapi/fastapi/pull/13384) by [@valentinDruzhinin](https://github.com/valentinDruzhinin).
+* 🌐 Add Ukrainian translation for `docs/uk/docs/tutorial/request-forms-and-files.md`. PR [#13386](https://github.com/fastapi/fastapi/pull/13386) by [@valentinDruzhinin](https://github.com/valentinDruzhinin).
+* 🌐 Update Korean translation for `docs/ko/docs/help-fastapi.md`. PR [#13262](https://github.com/fastapi/fastapi/pull/13262) by [@Zerohertz](https://github.com/Zerohertz).
+* 🌐 Add Korean translation for `docs/ko/docs/advanced/custom-response.md`. PR [#13265](https://github.com/fastapi/fastapi/pull/13265) by [@11kkw](https://github.com/11kkw).
+* 🌐 Update Korean translation for `docs/ko/docs/tutorial/security/simple-oauth2.md`. PR [#13335](https://github.com/fastapi/fastapi/pull/13335) by [@yes0ng](https://github.com/yes0ng).
+* 🌐 Add Russian translation for `docs/ru/docs/advanced/response-cookies.md`. PR [#13327](https://github.com/fastapi/fastapi/pull/13327) by [@Stepakinoyan](https://github.com/Stepakinoyan).
+* 🌐 Add Vietnamese translation for `docs/vi/docs/tutorial/static-files.md`. PR [#11291](https://github.com/fastapi/fastapi/pull/11291) by [@ptt3199](https://github.com/ptt3199).
* 🌐 Add Korean translation for `docs/ko/docs/tutorial/dependencies/dependencies-with-yield.md`. PR [#13257](https://github.com/fastapi/fastapi/pull/13257) by [@11kkw](https://github.com/11kkw).
* 🌐 Add Vietnamese translation for `docs/vi/docs/virtual-environments.md`. PR [#13282](https://github.com/fastapi/fastapi/pull/13282) by [@ptt3199](https://github.com/ptt3199).
* 🌐 Add Ukrainian translation for `docs/uk/docs/tutorial/static-files.md`. PR [#13285](https://github.com/fastapi/fastapi/pull/13285) by [@valentinDruzhinin](https://github.com/valentinDruzhinin).
@@ -26,6 +48,10 @@ hide:
### Internal
+* 🔧 Update sponsors: add CodeRabbit. PR [#13402](https://github.com/fastapi/fastapi/pull/13402) by [@tiangolo](https://github.com/tiangolo).
+* 🔧 Update team: Add Ludovico. PR [#13390](https://github.com/fastapi/fastapi/pull/13390) by [@tiangolo](https://github.com/tiangolo).
+* 🔧 Update sponsors: Add LambdaTest. PR [#13389](https://github.com/fastapi/fastapi/pull/13389) by [@tiangolo](https://github.com/tiangolo).
+* ⬆ Bump cloudflare/wrangler-action from 3.13 to 3.14. PR [#13350](https://github.com/fastapi/fastapi/pull/13350) by [@dependabot[bot]](https://github.com/apps/dependabot).
* ⬆ Bump mkdocs-material from 9.5.18 to 9.6.1. PR [#13301](https://github.com/fastapi/fastapi/pull/13301) by [@dependabot[bot]](https://github.com/apps/dependabot).
* ⬆ Bump pillow from 11.0.0 to 11.1.0. PR [#13300](https://github.com/fastapi/fastapi/pull/13300) by [@dependabot[bot]](https://github.com/apps/dependabot).
* 👥 Update FastAPI People - Sponsors. PR [#13295](https://github.com/fastapi/fastapi/pull/13295) by [@tiangolo](https://github.com/tiangolo).
diff --git a/docs/en/docs/tutorial/body-multiple-params.md b/docs/en/docs/tutorial/body-multiple-params.md
index 9fced9652..71b308bb4 100644
--- a/docs/en/docs/tutorial/body-multiple-params.md
+++ b/docs/en/docs/tutorial/body-multiple-params.md
@@ -10,8 +10,6 @@ And you can also declare body parameters as optional, by setting the default to
{* ../../docs_src/body_multiple_params/tutorial001_an_py310.py hl[18:20] *}
-## Multiple body parameters
-
/// note
Notice that, in this case, the `item` that would be taken from the body is optional. As it has a `None` default value.
diff --git a/docs/en/docs/tutorial/query-params-str-validations.md b/docs/en/docs/tutorial/query-params-str-validations.md
index 1bf16334d..511099186 100644
--- a/docs/en/docs/tutorial/query-params-str-validations.md
+++ b/docs/en/docs/tutorial/query-params-str-validations.md
@@ -6,13 +6,13 @@ Let's take this application as example:
{* ../../docs_src/query_params_str_validations/tutorial001_py310.py hl[7] *}
-The query parameter `q` is of type `Union[str, None]` (or `str | None` in Python 3.10), that means that it's of type `str` but could also be `None`, and indeed, the default value is `None`, so FastAPI will know it's not required.
+The query parameter `q` is of type `str | None`, that means that it's of type `str` but could also be `None`, and indeed, the default value is `None`, so FastAPI will know it's not required.
/// note
FastAPI will know that the value of `q` is not required because of the default value `= None`.
-The `Union` in `Union[str, None]` will allow your editor to give you better support and detect errors.
+Having `str | None` will allow your editor to give you better support and detect errors.
///
@@ -25,29 +25,9 @@ We are going to enforce that even though `q` is optional, whenever it is provide
To achieve that, first import:
* `Query` from `fastapi`
-* `Annotated` from `typing` (or from `typing_extensions` in Python below 3.9)
+* `Annotated` from `typing`
-//// tab | Python 3.10+
-
-In Python 3.9 or above, `Annotated` is part of the standard library, so you can import it from `typing`.
-
-```Python hl_lines="1 3"
-{!> ../../docs_src/query_params_str_validations/tutorial002_an_py310.py!}
-```
-
-////
-
-//// tab | Python 3.8+
-
-In versions of Python below Python 3.9 you import `Annotated` from `typing_extensions`.
-
-It will already be installed with FastAPI.
-
-```Python hl_lines="3-4"
-{!> ../../docs_src/query_params_str_validations/tutorial002_an.py!}
-```
-
-////
+{* ../../docs_src/query_params_str_validations/tutorial002_an_py310.py hl[1,3] *}
/// info
@@ -145,54 +125,23 @@ As in this case (without using `Annotated`) we have to replace the default value
So:
-```Python
-q: Union[str, None] = Query(default=None)
-```
-
-...makes the parameter optional, with a default value of `None`, the same as:
-
-```Python
-q: Union[str, None] = None
-```
-
-And in Python 3.10 and above:
-
```Python
q: str | None = Query(default=None)
```
...makes the parameter optional, with a default value of `None`, the same as:
-```Python
-q: str | None = None
-```
-
-But the `Query` versions declare it explicitly as being a query parameter.
-
-/// info
-
-Keep in mind that the most important part to make a parameter optional is the part:
```Python
-= None
-```
-
-or the:
-
-```Python
-= Query(default=None)
+q: str | None = None
```
-as it will use that `None` as the default value, and that way make the parameter **not required**.
-
-The `Union[str, None]` part allows your editor to provide better support, but it is not what tells FastAPI that this parameter is not required.
-
-///
+But the `Query` version declares it explicitly as being a query parameter.
Then, we can pass more parameters to `Query`. In this case, the `max_length` parameter that applies to strings:
```Python
-q: Union[str, None] = Query(default=None, max_length=50)
+q: str | None = Query(default=None, max_length=50)
```
This will validate the data, show a clear error when the data is not valid, and document the parameter in the OpenAPI schema *path operation*.
@@ -201,7 +150,7 @@ This will validate the data, show a clear error when the data is not valid, and
Keep in mind that when using `Query` inside of `Annotated` you cannot use the `default` parameter for `Query`.
-Instead use the actual default value of the function parameter. Otherwise, it would be inconsistent.
+Instead, use the actual default value of the function parameter. Otherwise, it would be inconsistent.
For example, this is not allowed:
@@ -255,7 +204,7 @@ This specific regular expression pattern checks that the received parameter valu
If you feel lost with all these **"regular expression"** ideas, don't worry. They are a hard topic for many people. You can still do a lot of stuff without needing regular expressions yet.
-But whenever you need them and go and learn them, know that you can already use them directly in **FastAPI**.
+Now you know that whenever you need them you can use them in **FastAPI**.
### Pydantic v1 `regex` instead of `pattern`
@@ -296,7 +245,7 @@ q: str
instead of:
```Python
-q: Union[str, None] = None
+q: str | None = None
```
But we are now declaring it with `Query`, for example like:
@@ -304,15 +253,7 @@ But we are now declaring it with `Query`, for example like:
//// tab | Annotated
```Python
-q: Annotated[Union[str, None], Query(min_length=3)] = None
-```
-
-////
-
-//// tab | non-Annotated
-
-```Python
-q: Union[str, None] = Query(default=None, min_length=3)
+q: Annotated[str | None, Query(min_length=3)] = None
```
////
@@ -321,42 +262,14 @@ So, when you need to declare a value as required while using `Query`, you can si
{* ../../docs_src/query_params_str_validations/tutorial006_an_py39.py hl[9] *}
-### Required with Ellipsis (`...`)
-
-There's an alternative way to explicitly declare that a value is required. You can set the default to the literal value `...`:
-
-{* ../../docs_src/query_params_str_validations/tutorial006b_an_py39.py hl[9] *}
-
-/// info
-
-If you hadn't seen that `...` before: it is a special single value, it is part of Python and is called "Ellipsis".
-
-It is used by Pydantic and FastAPI to explicitly declare that a value is required.
-
-///
-
-This will let **FastAPI** know that this parameter is required.
-
### Required, can be `None`
You can declare that a parameter can accept `None`, but that it's still required. This would force clients to send a value, even if the value is `None`.
-To do that, you can declare that `None` is a valid type but still use `...` as the default:
+To do that, you can declare that `None` is a valid type but simply do not declare a default value:
{* ../../docs_src/query_params_str_validations/tutorial006c_an_py310.py hl[9] *}
-/// tip
-
-Pydantic, which is what powers all the data validation and serialization in FastAPI, has a special behavior when you use `Optional` or `Union[Something, None]` without a default value, you can read more about it in the Pydantic docs about Required fields.
-
-///
-
-/// tip
-
-Remember that in most of the cases, when something is required, you can simply omit the default, so you normally don't have to use `...`.
-
-///
-
## Query parameter list / multiple values
When you define a query parameter explicitly with `Query` you can also declare it to receive a list of values, or said in another way, to receive multiple values.
@@ -396,7 +309,7 @@ The interactive API docs will update accordingly, to allow multiple values:
### Query parameter list / multiple values with defaults
-And you can also define a default `list` of values if none are provided:
+You can also define a default `list` of values if none are provided:
{* ../../docs_src/query_params_str_validations/tutorial012_an_py39.py hl[9] *}
@@ -419,7 +332,7 @@ the default of `q` will be: `["foo", "bar"]` and your response will be:
#### Using just `list`
-You can also use `list` directly instead of `List[str]` (or `list[str]` in Python 3.9+):
+You can also use `list` directly instead of `list[str]`:
{* ../../docs_src/query_params_str_validations/tutorial013_an_py39.py hl[9] *}
@@ -427,7 +340,7 @@ You can also use `list` directly instead of `List[str]` (or `list[str]` in Pytho
Keep in mind that in this case, FastAPI won't check the contents of the list.
-For example, `List[int]` would check (and document) that the contents of the list are integers. But `list` alone wouldn't.
+For example, `list[int]` would check (and document) that the contents of the list are integers. But `list` alone wouldn't.
///
diff --git a/docs/en/docs/tutorial/response-status-code.md b/docs/en/docs/tutorial/response-status-code.md
index 711042a46..41bf02a8f 100644
--- a/docs/en/docs/tutorial/response-status-code.md
+++ b/docs/en/docs/tutorial/response-status-code.md
@@ -53,16 +53,16 @@ These status codes have a name associated to recognize them, but the important p
In short:
-* `100` and above are for "Information". You rarely use them directly. Responses with these status codes cannot have a body.
-* **`200`** and above are for "Successful" responses. These are the ones you would use the most.
+* `100 - 199` are for "Information". You rarely use them directly. Responses with these status codes cannot have a body.
+* **`200 - 299`** are for "Successful" responses. These are the ones you would use the most.
* `200` is the default status code, which means everything was "OK".
* Another example would be `201`, "Created". It is commonly used after creating a new record in the database.
* A special case is `204`, "No Content". This response is used when there is no content to return to the client, and so the response must not have a body.
-* **`300`** and above are for "Redirection". Responses with these status codes may or may not have a body, except for `304`, "Not Modified", which must not have one.
-* **`400`** and above are for "Client error" responses. These are the second type you would probably use the most.
+* **`300 - 399`** are for "Redirection". Responses with these status codes may or may not have a body, except for `304`, "Not Modified", which must not have one.
+* **`400 - 499`** are for "Client error" responses. These are the second type you would probably use the most.
* An example is `404`, for a "Not Found" response.
* For generic errors from the client, you can just use `400`.
-* `500` and above are for server errors. You almost never use them directly. When something goes wrong at some part in your application code, or server, it will automatically return one of these status codes.
+* `500 - 599` are for server errors. You almost never use them directly. When something goes wrong at some part in your application code, or server, it will automatically return one of these status codes.
/// tip
diff --git a/docs/en/docs/virtual-environments.md b/docs/en/docs/virtual-environments.md
index b75be18c3..4f65b3b80 100644
--- a/docs/en/docs/virtual-environments.md
+++ b/docs/en/docs/virtual-environments.md
@@ -668,7 +668,7 @@ After activating the virtual environment, the `PATH` variable would look somethi
/home/user/code/awesome-project/.venv/bin:/usr/bin:/bin:/usr/sbin:/sbin
```
-That means that the system will now start looking first look for programs in:
+That means that the system will now start looking first for programs in:
```plaintext
/home/user/code/awesome-project/.venv/bin
@@ -692,7 +692,7 @@ and use that one.
C:\Users\user\code\awesome-project\.venv\Scripts;C:\Windows\System32
```
-That means that the system will now start looking first look for programs in:
+That means that the system will now start looking first for programs in:
```plaintext
C:\Users\user\code\awesome-project\.venv\Scripts
diff --git a/docs/en/overrides/main.html b/docs/en/overrides/main.html
index b58ed8818..30973bfcb 100644
--- a/docs/en/overrides/main.html
+++ b/docs/en/overrides/main.html
@@ -88,6 +88,12 @@
+
-
+
diff --git a/docs/es/docs/tutorial/query-params-str-validations.md b/docs/es/docs/tutorial/query-params-str-validations.md
index f378b9dce..9cb76156f 100644
--- a/docs/es/docs/tutorial/query-params-str-validations.md
+++ b/docs/es/docs/tutorial/query-params-str-validations.md
@@ -321,22 +321,6 @@ Así que, cuando necesites declarar un valor como requerido mientras usas `Query
{* ../../docs_src/query_params_str_validations/tutorial006_an_py39.py hl[9] *}
-### Requerido con Puntos suspensivos (`...`)
-
-Hay una manera alternativa de declarar explícitamente que un valor es requerido. Puedes establecer el valor por defecto al valor literal `...`:
-
-{* ../../docs_src/query_params_str_validations/tutorial006b_an_py39.py hl[9] *}
-
-/// info | Información
-
-Si no habías visto eso `...` antes: es un valor especial único, es parte de Python y se llama "Ellipsis".
-
-Se usa por Pydantic y FastAPI para declarar explícitamente que un valor es requerido.
-
-///
-
-Esto le permitirá a **FastAPI** saber que este parámetro es requerido.
-
### Requerido, puede ser `None`
Puedes declarar que un parámetro puede aceptar `None`, pero que aún así es requerido. Esto obligaría a los clientes a enviar un valor, incluso si el valor es `None`.
diff --git a/docs/fa/docs/index.md b/docs/fa/docs/index.md
index 6addce763..0aa0bec36 100644
--- a/docs/fa/docs/index.md
+++ b/docs/fa/docs/index.md
@@ -11,11 +11,11 @@
فریمورک FastAPI، کارایی بالا، یادگیری آسان، کدنویسی سریع، آماده برای استفاده در محیط پروداکشن
-
-
+
+
-
-
+
+
diff --git a/docs/fr/docs/index.md b/docs/fr/docs/index.md
index 695429008..d25f7a939 100644
--- a/docs/fr/docs/index.md
+++ b/docs/fr/docs/index.md
@@ -12,7 +12,7 @@
-
+
diff --git a/docs/he/docs/index.md b/docs/he/docs/index.md
index 6498d15e1..bd166f205 100644
--- a/docs/he/docs/index.md
+++ b/docs/he/docs/index.md
@@ -12,10 +12,10 @@
-
+
-
-
+
+
diff --git a/docs/hu/docs/index.md b/docs/hu/docs/index.md
index c6f596650..45ff49c3b 100644
--- a/docs/hu/docs/index.md
+++ b/docs/hu/docs/index.md
@@ -6,7 +6,7 @@
-
+
diff --git a/docs/id/docs/index.md b/docs/id/docs/index.md
index 7fdd1cc7a..5fb0c4c9c 100644
--- a/docs/id/docs/index.md
+++ b/docs/id/docs/index.md
@@ -12,7 +12,7 @@
-
FastAPI framework, alte prestazioni, facile da imparare, rapido da implementare, pronto per il rilascio in produzione
+
diff --git a/docs/it/docs/index.md b/docs/it/docs/index.md
index 8a1039bc5..dc8f5b846 100644
--- a/docs/it/docs/index.md
+++ b/docs/it/docs/index.md
@@ -4,15 +4,19 @@
-
+
diff --git a/docs/pl/docs/index.md b/docs/pl/docs/index.md
index 9a96c6553..0e13d2631 100644
--- a/docs/pl/docs/index.md
+++ b/docs/pl/docs/index.md
@@ -11,15 +11,18 @@
FastAPI to szybki, prosty w nauce i gotowy do użycia w produkcji framework
-
+
diff --git a/docs/ru/docs/advanced/response-cookies.md b/docs/ru/docs/advanced/response-cookies.md
new file mode 100644
index 000000000..e04ff577c
--- /dev/null
+++ b/docs/ru/docs/advanced/response-cookies.md
@@ -0,0 +1,48 @@
+
+# Cookies в ответе
+
+## Использование параметра `Response`
+
+Вы можете объявить параметр типа `Response` в вашей функции эндпоинта.
+
+Затем установить cookies в этом временном объекте ответа.
+
+{* ../../docs_src/response_cookies/tutorial002.py hl[1, 8:9] *}
+
+После этого можно вернуть любой объект, как и раньше (например, `dict`, объект модели базы данных и так далее).
+
+Если вы указали `response_model`, он всё равно будет использоваться для фильтрации и преобразования возвращаемого объекта.
+
+**FastAPI** извлечет cookies (а также заголовки и коды состояния) из временного ответа и включит их в окончательный ответ, содержащий ваше возвращаемое значение, отфильтрованное через `response_model`.
+
+Вы также можете объявить параметр типа Response в зависимостях и устанавливать cookies (и заголовки) там.
+
+## Возвращение `Response` напрямую
+
+Вы также можете установить cookies, если возвращаете `Response` напрямую в вашем коде.
+
+Для этого создайте объект `Response`, как описано в разделе [Возвращение ответа напрямую](response-directly.md){.target=_blank}.
+
+Затем установите cookies и верните этот объект:
+
+{* ../../docs_src/response_cookies/tutorial001.py hl[10:12] *}
+
+/// tip | Примечание
+Имейте в виду, что если вы возвращаете ответ напрямую, вместо использования параметра `Response`, **FastAPI** отправит его без дополнительной обработки.
+
+Убедитесь, что ваши данные имеют корректный тип. Например, они должны быть совместимы с JSON, если вы используете `JSONResponse`.
+
+Также убедитесь, что вы не отправляете данные, которые должны были быть отфильтрованы через `response_model`.
+///
+
+### Дополнительная информация
+
+/// note | Технические детали
+Вы также можете использовать `from starlette.responses import Response` или `from starlette.responses import JSONResponse`.
+
+**FastAPI** предоставляет `fastapi.responses`, которые являются теми же объектами, что и `starlette.responses`, просто для удобства. Однако большинство доступных типов ответов поступает непосредственно из **Starlette**.
+
+Для установки заголовков и cookies `Response` используется часто, поэтому **FastAPI** также предоставляет его через `fastapi.responses`.
+///
+
+Чтобы увидеть все доступные параметры и настройки, ознакомьтесь с документацией Starlette.
diff --git a/docs/ru/docs/index.md b/docs/ru/docs/index.md
index 5ebe1494b..a9546cf1e 100644
--- a/docs/ru/docs/index.md
+++ b/docs/ru/docs/index.md
@@ -12,10 +12,10 @@
-
+
-
-
+
+
diff --git a/docs/ru/docs/tutorial/query-params-str-validations.md b/docs/ru/docs/tutorial/query-params-str-validations.md
index 32a98ff22..13b7015db 100644
--- a/docs/ru/docs/tutorial/query-params-str-validations.md
+++ b/docs/ru/docs/tutorial/query-params-str-validations.md
@@ -291,22 +291,6 @@ q: Union[str, None] = Query(default=None, min_length=3)
{* ../../docs_src/query_params_str_validations/tutorial006_an_py39.py hl[9] *}
-### Обязательный параметр с Ellipsis (`...`)
-
-Альтернативный способ указать обязательность параметра запроса - это указать параметр `default` через многоточие `...`:
-
-{* ../../docs_src/query_params_str_validations/tutorial006b_an_py39.py hl[9] *}
-
-/// info | Дополнительная информация
-
-Если вы ранее не сталкивались с `...`: это специальное значение, часть языка Python и называется "Ellipsis".
-
-Используется в Pydantic и FastAPI для определения, что значение требуется обязательно.
-
-///
-
-Таким образом, **FastAPI** определяет, что параметр является обязательным.
-
### Обязательный параметр с `None`
Вы можете определить, что параметр может принимать `None`, но всё ещё является обязательным. Это может потребоваться для того, чтобы пользователи явно указали параметр, даже если его значение будет `None`.
@@ -321,18 +305,6 @@ Pydantic, мощь которого используется в FastAPI для
///
-### Использование Pydantic's `Required` вместо Ellipsis (`...`)
-
-Если вас смущает `...`, вы можете использовать `Required` из Pydantic:
-
-{* ../../docs_src/query_params_str_validations/tutorial006d_an_py39.py hl[4,10] *}
-
-/// tip | Подсказка
-
-Запомните, когда вам необходимо объявить query-параметр обязательным, вы можете просто не указывать параметр `default`. Таким образом, вам редко придётся использовать `...` или `Required`.
-
-///
-
## Множество значений для query-параметра
Для query-параметра `Query` можно указать, что он принимает список значений (множество значений).
diff --git a/docs/tr/docs/index.md b/docs/tr/docs/index.md
index 7ecaf1ba3..f666e2d06 100644
--- a/docs/tr/docs/index.md
+++ b/docs/tr/docs/index.md
@@ -12,7 +12,7 @@
-
+
diff --git a/docs/uk/docs/index.md b/docs/uk/docs/index.md
index 012bac2e2..b573ee259 100644
--- a/docs/uk/docs/index.md
+++ b/docs/uk/docs/index.md
@@ -6,7 +6,7 @@
-
+
diff --git a/docs/uk/docs/tutorial/header-params.md b/docs/uk/docs/tutorial/header-params.md
new file mode 100644
index 000000000..09c70a4f6
--- /dev/null
+++ b/docs/uk/docs/tutorial/header-params.md
@@ -0,0 +1,91 @@
+# Header-параметри
+
+Ви можете визначати параметри заголовків, так само як визначаєте `Query`, `Path` і `Cookie` параметри.
+
+## Імпорт `Header`
+
+Спочатку імпортуйте `Header`:
+
+{* ../../docs_src/header_params/tutorial001_an_py310.py hl[3] *}
+
+## Оголошення параметрів `Header`
+
+Потім оголосіть параметри заголовків, використовуючи ту ж структуру, що й для `Path`, `Query` та `Cookie`.
+
+Ви можете визначити значення за замовчуванням, а також усі додаткові параметри валідації або анотації:
+
+{* ../../docs_src/header_params/tutorial001_an_py310.py hl[9] *}
+
+/// note | Технічні деталі
+
+`Header`є "сестринським" класом для `Path`, `Query` і `Cookie`. Він також успадковується від загального класу `Param`.
+
+Але пам’ятайте, що при імпорті `Query`, `Path`, `Header` та інших із `fastapi`, то насправді вони є функціями, які повертають спеціальні класи.
+
+///
+
+/// info | Інформація
+
+Щоб оголосити заголовки, потрібно використовувати `Header`, інакше параметри будуть інтерпретуватися як параметри запиту.
+
+///
+
+## Автоматичне перетворення
+
+`Header` має додатковий функціонал порівняно з `Path`, `Query` та `Cookie`.
+
+Більшість стандартних заголовків розділяються символом «дефіс», також відомим як «мінус» (`-`).
+
+Але змінна, така як `user-agent`, є недійсною в Python.
+
+Тому, за замовчуванням, `Header` автоматично перетворює символи підкреслення (`_`) на дефіси (`-`) для отримання та документування заголовків.
+
+Оскільки заголовки HTTP не чутливі до регістру, Ви можете використовувати стандартний стиль Python ("snake_case").
+
+Тому Ви можете використовувати `user_agent`, як зазвичай у коді Python, замість того щоб писати з великої літери, як `User_Agent` або щось подібне.
+
+Якщо Вам потрібно вимкнути автоматичне перетворення підкреслень у дефіси, встановіть `convert_underscores` в `Header` значення `False`:
+
+{* ../../docs_src/header_params/tutorial002_an_py310.py hl[10] *}
+
+/// warning | Увага
+
+Перед тим як встановити значення `False` для `convert_underscores` пам’ятайте, що деякі HTTP-проксі та сервери не підтримують заголовки з підкресленнями.
+
+///
+
+## Дубльовані заголовки
+
+Можливо отримати дубльовані заголовки, тобто той самий заголовок із кількома значеннями.
+
+Це можна визначити, використовуючи список у типізації параметра.
+
+Ви отримаєте всі значення дубльованого заголовка у вигляді `list` у Python.
+
+Наприклад, щоб оголосити заголовок `X-Token`, який може з’являтися більше ніж один раз:
+
+{* ../../docs_src/header_params/tutorial003_an_py310.py hl[9] *}
+
+Якщо Ви взаємодієте з цією операцією шляху, надсилаючи два HTTP-заголовки, наприклад:
+
+```
+X-Token: foo
+X-Token: bar
+```
+
+Відповідь буде така:
+
+```JSON
+{
+ "X-Token values": [
+ "bar",
+ "foo"
+ ]
+}
+```
+
+## Підсумок
+
+Оголошуйте заголовки за допомогою `Header`, використовуючи той самий підхід, що й для `Query`, `Path` та `Cookie`.
+
+Не хвилюйтеся про підкреслення у змінних — **FastAPI** автоматично конвертує їх.
diff --git a/docs/uk/docs/tutorial/request-files.md b/docs/uk/docs/tutorial/request-files.md
new file mode 100644
index 000000000..18b7cc01c
--- /dev/null
+++ b/docs/uk/docs/tutorial/request-files.md
@@ -0,0 +1,175 @@
+# Запит файлів
+
+Ви можете визначити файли, які будуть завантажуватися клієнтом, використовуючи `File`.
+
+/// info | Інформація
+
+Щоб отримувати завантажені файли, спочатку встановіть python-multipart.
+
+Переконайтеся, що Ви створили [віртуальне середовище](../virtual-environments.md){.internal-link target=_blank}, активували його та встановили пакет, наприклад:
+
+```console
+$ pip install python-multipart
+```
+
+Це необхідно, оскільки завантажені файли передаються у вигляді "форматованих даних форми".
+
+///
+
+## Імпорт `File`
+
+Імпортуйте `File` та `UploadFile` з `fastapi`:
+
+{* ../../docs_src/request_files/tutorial001_an_py39.py hl[3] *}
+
+## Визначення параметрів `File`
+
+Створіть параметри файлів так само як Ви б створювали `Body` або `Form`:
+
+{* ../../docs_src/request_files/tutorial001_an_py39.py hl[9] *}
+
+/// info | Інформація
+
+`File` — це клас, який безпосередньо успадковує `Form`.
+
+Але пам’ятайте, що коли Ви імпортуєте `Query`, `Path`, `File` та інші з `fastapi`, це насправді функції, які повертають спеціальні класи.
+
+///
+
+/// tip | Підказка
+
+Щоб оголосити тіла файлів, Вам потрібно використовувати `File`, тому що інакше параметри будуть інтерпретовані як параметри запиту або параметри тіла (JSON).
+
+///
+
+Файли будуть завантажені у вигляді "форматованих даних форми".
+
+Якщо Ви оголосите тип параметра функції обробника маршруту як `bytes`, **FastAPI** прочитає файл за Вас, і Ви отримаєте його вміст у вигляді `bytes`.
+
+Однак майте на увазі, що весь вміст буде збережено в пам'яті. Це працюватиме добре для малих файлів.
+
+Але в деяких випадках Вам може знадобитися `UploadFile`.
+
+## Параметри файлу з `UploadFile`
+
+Визначте параметр файлу з типом `UploadFile`:
+
+{* ../../docs_src/request_files/tutorial001_an_py39.py hl[14] *}
+
+Використання `UploadFile` має кілька переваг перед `bytes`:
+
+* Вам не потрібно використовувати `File()` у значенні за замовчуванням параметра.
+* Використовується "буферизований" файл:
+ * Файл зберігається в пам'яті до досягнення певного обмеження, після чого він записується на диск.
+* Це означає, що він добре працює для великих файлів, таких як зображення, відео, великі двійкові файли тощо, не споживаючи всю пам'ять.
+Ви можете отримати метадані про завантажений файл.
+* Він має file-like `асинхронний файловий інтерфейс` interface.
+* Він надає фактичний об'єкт Python `SpooledTemporaryFile`, який можна передавати безпосередньо іншим бібліотекам.
+
+### `UploadFile`
+
+`UploadFile` має такі атрибути:
+
+* `filename`: Рядок `str` з оригінальною назвою файлу, який був завантажений (наприклад, `myimage.jpg`).
+* `content_type`: Рядок `str` з MIME-типом (наприклад, `image/jpeg`).
+* `file`: Об'єкт SpooledTemporaryFile (файлоподібний об'єкт). Це фактичний файловий об'єкт Python, який можна безпосередньо передавати іншим функціям або бібліотекам, що очікують "файлоподібний" об'єкт.
+
+`UploadFile` має такі асинхронні `async` методи. Вони викликають відповідні методи файлу під капотом (використовуючи внутрішній `SpooledTemporaryFile`).
+
+* `write(data)`: Записує `data` (`str` або `bytes`) у файл.
+* `read(size)`: Читає `size` (`int`) байтів/символів з файлу.
+* `seek(offset)`: Переміщується до позиції `offset` (`int`) у файлі.
+ * Наприклад, `await myfile.seek(0)` поверне курсор на початок файлу.
+ * This is especially useful if you run `await myfile.read()` once and then need to read the contents again. Це особливо корисно, якщо Ви виконуєте await `await myfile.read()` один раз, а потім потрібно знову прочитати вміст.
+* `close()`: Закриває файл.
+
+Оскільки всі ці методи є асинхронними `async`, Вам потрібно використовувати "await":
+
+Наприклад, всередині `async` *функції обробки шляху* Ви можете отримати вміст за допомогою:
+
+```Python
+contents = await myfile.read()
+```
+Якщо Ви знаходитесь у звичайній `def` *функції обробки шляху*, Ви можете отримати доступ до `UploadFile.file` безпосередньо, наприклад:
+
+```Python
+contents = myfile.file.read()
+```
+
+/// note | Технічні деталі `async`
+
+Коли Ви використовуєте `async` методи, **FastAPI** виконує файлові операції у пулі потоків та очікує їх завершення.
+
+///
+
+/// note | Технічні деталі Starlette
+
+`UploadFile` у **FastAPI** успадковується безпосередньо від `UploadFile` у **Starlette**, але додає деякі необхідні частини, щоб зробити його сумісним із **Pydantic** та іншими компонентами FastAPI.
+
+///
+
+## Що таке "Form Data"
+
+Спосіб, у який HTML-форми (`
POST
.
+
+///
+
+/// warning | Увага
+
+Ви можете оголосити кілька параметрів `File` і `Form` в *операції шляху*, але Ви не можете одночасно оголошувати поля `Body`, які мають надходити у форматі JSON, оскільки тіло запиту буде закодоване у форматі `multipart/form-data`, а не `application/json`.
+
+Це не обмеження **FastAPI**, а особливість протоколу HTTP.
+
+///
+
+## Опціональне Завантаження Файлів
+
+Файл можна зробити необов’язковим, використовуючи стандартні анотації типів і встановлюючи значення за замовчуванням `None`:
+
+{* ../../docs_src/request_files/tutorial001_02_an_py310.py hl[9,17] *}
+
+## `UploadFile` із Додатковими Мета Даними
+
+Ви також можете використовувати `File()` разом із `UploadFile`, наприклад, для встановлення додаткових метаданих:
+
+{* ../../docs_src/request_files/tutorial001_03_an_py39.py hl[9,15] *}
+
+## Завантаження Кількох Файлів
+
+Можна завантажувати кілька файлів одночасно.
+
+Вони будуть пов’язані з одним і тим самим "form field", який передається у вигляді "form data".
+
+Щоб це реалізувати, потрібно оголосити список `bytes` або `UploadFile`:
+
+{* ../../docs_src/request_files/tutorial002_an_py39.py hl[10,15] *}
+
+Ви отримаєте, як і було оголошено, `list` із `bytes` або `UploadFile`.
+
+/// note | Технічні деталі
+
+Ви також можете використати `from starlette.responses import HTMLResponse`.
+
+**FastAPI** надає ті ж самі `starlette.responses`, що й `fastapi.responses`, для зручності розробників. Однак більшість доступних відповідей надходять безпосередньо від Starlette.
+
+///
+
+### Завантаження декількох файлів із додатковими метаданими
+
+Так само як і раніше, Ви можете використовувати `File()`, щоб встановити додаткові параметри навіть для `UploadFile`:
+
+{* ../../docs_src/request_files/tutorial003_an_py39.py hl[11,18:20] *}
+
+## Підсумок
+
+Використовуйте `File`, `bytes`та `UploadFile`, щоб оголошувати файли для завантаження у запитах, які надсилаються у вигляді form data.
diff --git a/docs/uk/docs/tutorial/request-form-models.md b/docs/uk/docs/tutorial/request-form-models.md
new file mode 100644
index 000000000..7f5759e79
--- /dev/null
+++ b/docs/uk/docs/tutorial/request-form-models.md
@@ -0,0 +1,78 @@
+# Моделі форм (Form Models)
+
+У FastAPI Ви можете використовувати **Pydantic-моделі** для оголошення **полів форми**.
+
+/// info | Інформація
+
+Щоб використовувати форми, спочатку встановіть python-multipart.
+
+Переконайтеся, що Ви створили [віртуальне середовище](../virtual-environments.md){.internal-link target=_blank}, активували його, а потім встановили бібліотеку, наприклад:
+
+```console
+$ pip install python-multipart
+```
+
+///
+
+/// note | Підказка
+
+Ця функція підтримується, починаючи з FastAPI версії `0.113.0`. 🤓
+
+///
+
+## Використання Pydantic-моделей для форм
+
+Вам просто потрібно оголосити **Pydantic-модель** з полями, які Ви хочете отримати як **поля форми**, а потім оголосити параметр як `Form`:
+
+{* ../../docs_src/request_form_models/tutorial001_an_py39.py hl[9:11,15] *}
+
+**FastAPI** **витягне** дані для **кожного поля** з **формових даних** у запиті та надасть вам Pydantic-модель, яку Ви визначили.
+
+## Перевірка документації
+
+Ви можете перевірити це в UI документації за `/docs`:
+
+
-
+
diff --git a/docs/vi/docs/tutorial/static-files.md b/docs/vi/docs/tutorial/static-files.md
new file mode 100644
index 000000000..ecf8c2485
--- /dev/null
+++ b/docs/vi/docs/tutorial/static-files.md
@@ -0,0 +1,40 @@
+# Tệp tĩnh (Static Files)
+
+Bạn có thể triển khai tệp tĩnh tự động từ một thư mục bằng cách sử dụng StaticFiles.
+
+## Sử dụng `Tệp tĩnh`
+
+- Nhập `StaticFiles`.
+- "Mount" a `StaticFiles()` instance in a specific path.
+
+{* ../../docs_src/static_files/tutorial001.py hl[2,6] *}
+
+/// note | Chi tiết kỹ thuật
+
+Bạn cũng có thể sử dụng `from starlette.staticfiles import StaticFiles`.
+
+**FastAPI** cung cấp cùng `starlette.staticfiles` như `fastapi.staticfiles` giúp đơn giản hóa việc sử dụng, nhưng nó thực sự đến từ Starlette.
+
+///
+
+### "Mounting" là gì
+
+"Mounting" có nghĩa là thêm một ứng dụng "độc lập" hoàn chỉnh vào một đường dẫn cụ thể, sau đó ứng dụng đó sẽ chịu trách nhiệm xử lý tất cả các đường dẫn con.
+
+Điều này khác với việc sử dụng `APIRouter` vì một ứng dụng được gắn kết là hoàn toàn độc lập. OpenAPI và tài liệu từ ứng dụng chính của bạn sẽ không bao gồm bất kỳ thứ gì từ ứng dụng được gắn kết, v.v.
+
+Bạn có thể đọc thêm về điều này trong [Hướng dẫn Người dùng Nâng cao](../advanced/index.md){.internal-link target=\_blank}.
+
+## Chi tiết
+
+Đường dẫn đầu tiên `"/static"` là đường dẫn con mà "ứng dụng con" này sẽ được "gắn" vào. Vì vậy, bất kỳ đường dẫn nào bắt đầu bằng `"/static"` sẽ được xử lý bởi nó.
+
+Đường dẫn `directory="static"` là tên của thư mục chứa tệp tĩnh của bạn.
+
+Tham số `name="static"` đặt tên cho nó để có thể được sử dụng bên trong **FastAPI**.
+
+Tất cả các tham số này có thể khác với `static`, điều chỉnh chúng với phù hợp với ứng dụng của bạn.
+
+## Thông tin thêm
+
+Để biết thêm chi tiết và tùy chọn, hãy xem Starlette's docs about Static Files.
diff --git a/docs/yo/docs/index.md b/docs/yo/docs/index.md
index 3ad1483de..d6aa78b3d 100644
--- a/docs/yo/docs/index.md
+++ b/docs/yo/docs/index.md
@@ -12,7 +12,7 @@
-
+
diff --git a/docs/zh-hant/docs/index.md b/docs/zh-hant/docs/index.md
index 137a17284..81d99ede4 100644
--- a/docs/zh-hant/docs/index.md
+++ b/docs/zh-hant/docs/index.md
@@ -6,7 +6,7 @@
-
+
diff --git a/docs/zh/docs/index.md b/docs/zh/docs/index.md
index d3e9e3112..94cf8745c 100644
--- a/docs/zh/docs/index.md
+++ b/docs/zh/docs/index.md
@@ -11,11 +11,11 @@
FastAPI 框架,高性能,易于学习,高效编码,生产可用
-
-
+
+
-
-
+
+
diff --git a/docs/zh/docs/tutorial/query-params-str-validations.md b/docs/zh/docs/tutorial/query-params-str-validations.md
index 2fba671f7..c2f9a7e9f 100644
--- a/docs/zh/docs/tutorial/query-params-str-validations.md
+++ b/docs/zh/docs/tutorial/query-params-str-validations.md
@@ -108,21 +108,6 @@ q: Union[str, None] = Query(default=None, min_length=3)
{* ../../docs_src/query_params_str_validations/tutorial006.py hl[7] *}
-### 使用省略号(`...`)声明必需参数
-
-有另一种方法可以显式的声明一个值是必需的,即将默认参数的默认值设为 `...` :
-
-{* ../../docs_src/query_params_str_validations/tutorial006b.py hl[7] *}
-
-/// info
-
-如果你之前没见过 `...` 这种用法:它是一个特殊的单独值,它是 Python 的一部分并且被称为“Ellipsis”(意为省略号 —— 译者注)。
-Pydantic 和 FastAPI 使用它来显式的声明需要一个值。
-
-///
-
-这将使 **FastAPI** 知道此查询参数是必需的。
-
### 使用`None`声明必需参数
你可以声明一个参数可以接收`None`值,但它仍然是必需的。这将强制客户端发送一个值,即使该值是`None`。
@@ -137,18 +122,6 @@ Pydantic 是 FastAPI 中所有数据验证和序列化的核心,当你在没
///
-### 使用Pydantic中的`Required`代替省略号(`...`)
-
-如果你觉得使用 `...` 不舒服,你也可以从 Pydantic 导入并使用 `Required`:
-
-{* ../../docs_src/query_params_str_validations/tutorial006d.py hl[2,8] *}
-
-/// tip
-
-请记住,在大多数情况下,当你需要某些东西时,可以简单地省略 `default` 参数,因此你通常不必使用 `...` 或 `Required`
-
-///
-
## 查询参数列表 / 多个值
当你使用 `Query` 显式地定义查询参数时,你还可以声明它去接收一组值,或换句话来说,接收多个值。
diff --git a/docs_src/configure_swagger_ui/tutorial002.py b/docs_src/configure_swagger_ui/tutorial002.py
index cc569ce45..cc75c2196 100644
--- a/docs_src/configure_swagger_ui/tutorial002.py
+++ b/docs_src/configure_swagger_ui/tutorial002.py
@@ -1,6 +1,6 @@
from fastapi import FastAPI
-app = FastAPI(swagger_ui_parameters={"syntaxHighlight.theme": "obsidian"})
+app = FastAPI(swagger_ui_parameters={"syntaxHighlight": {"theme": "obsidian"}})
@app.get("/users/{username}")
diff --git a/docs_src/query_params_str_validations/tutorial006b.py b/docs_src/query_params_str_validations/tutorial006b.py
deleted file mode 100644
index a8d69c889..000000000
--- a/docs_src/query_params_str_validations/tutorial006b.py
+++ /dev/null
@@ -1,11 +0,0 @@
-from fastapi import FastAPI, Query
-
-app = FastAPI()
-
-
-@app.get("/items/")
-async def read_items(q: str = Query(default=..., min_length=3)):
- results = {"items": [{"item_id": "Foo"}, {"item_id": "Bar"}]}
- if q:
- results.update({"q": q})
- return results
diff --git a/docs_src/query_params_str_validations/tutorial006b_an.py b/docs_src/query_params_str_validations/tutorial006b_an.py
deleted file mode 100644
index ea3b02583..000000000
--- a/docs_src/query_params_str_validations/tutorial006b_an.py
+++ /dev/null
@@ -1,12 +0,0 @@
-from fastapi import FastAPI, Query
-from typing_extensions import Annotated
-
-app = FastAPI()
-
-
-@app.get("/items/")
-async def read_items(q: Annotated[str, Query(min_length=3)] = ...):
- results = {"items": [{"item_id": "Foo"}, {"item_id": "Bar"}]}
- if q:
- results.update({"q": q})
- return results
diff --git a/docs_src/query_params_str_validations/tutorial006b_an_py39.py b/docs_src/query_params_str_validations/tutorial006b_an_py39.py
deleted file mode 100644
index 687a9f544..000000000
--- a/docs_src/query_params_str_validations/tutorial006b_an_py39.py
+++ /dev/null
@@ -1,13 +0,0 @@
-from typing import Annotated
-
-from fastapi import FastAPI, Query
-
-app = FastAPI()
-
-
-@app.get("/items/")
-async def read_items(q: Annotated[str, Query(min_length=3)] = ...):
- results = {"items": [{"item_id": "Foo"}, {"item_id": "Bar"}]}
- if q:
- results.update({"q": q})
- return results
diff --git a/docs_src/query_params_str_validations/tutorial006c.py b/docs_src/query_params_str_validations/tutorial006c.py
index 2ac148c94..0a0e820da 100644
--- a/docs_src/query_params_str_validations/tutorial006c.py
+++ b/docs_src/query_params_str_validations/tutorial006c.py
@@ -6,7 +6,7 @@ app = FastAPI()
@app.get("/items/")
-async def read_items(q: Union[str, None] = Query(default=..., min_length=3)):
+async def read_items(q: Union[str, None] = Query(min_length=3)):
results = {"items": [{"item_id": "Foo"}, {"item_id": "Bar"}]}
if q:
results.update({"q": q})
diff --git a/docs_src/query_params_str_validations/tutorial006c_an.py b/docs_src/query_params_str_validations/tutorial006c_an.py
index 10bf26a57..55c4f4adc 100644
--- a/docs_src/query_params_str_validations/tutorial006c_an.py
+++ b/docs_src/query_params_str_validations/tutorial006c_an.py
@@ -7,7 +7,7 @@ app = FastAPI()
@app.get("/items/")
-async def read_items(q: Annotated[Union[str, None], Query(min_length=3)] = ...):
+async def read_items(q: Annotated[Union[str, None], Query(min_length=3)]):
results = {"items": [{"item_id": "Foo"}, {"item_id": "Bar"}]}
if q:
results.update({"q": q})
diff --git a/docs_src/query_params_str_validations/tutorial006c_an_py310.py b/docs_src/query_params_str_validations/tutorial006c_an_py310.py
index 1ab0a7d53..2995d9c97 100644
--- a/docs_src/query_params_str_validations/tutorial006c_an_py310.py
+++ b/docs_src/query_params_str_validations/tutorial006c_an_py310.py
@@ -6,7 +6,7 @@ app = FastAPI()
@app.get("/items/")
-async def read_items(q: Annotated[str | None, Query(min_length=3)] = ...):
+async def read_items(q: Annotated[str | None, Query(min_length=3)]):
results = {"items": [{"item_id": "Foo"}, {"item_id": "Bar"}]}
if q:
results.update({"q": q})
diff --git a/docs_src/query_params_str_validations/tutorial006c_an_py39.py b/docs_src/query_params_str_validations/tutorial006c_an_py39.py
index ac1273331..76a1cd49a 100644
--- a/docs_src/query_params_str_validations/tutorial006c_an_py39.py
+++ b/docs_src/query_params_str_validations/tutorial006c_an_py39.py
@@ -6,7 +6,7 @@ app = FastAPI()
@app.get("/items/")
-async def read_items(q: Annotated[Union[str, None], Query(min_length=3)] = ...):
+async def read_items(q: Annotated[Union[str, None], Query(min_length=3)]):
results = {"items": [{"item_id": "Foo"}, {"item_id": "Bar"}]}
if q:
results.update({"q": q})
diff --git a/docs_src/query_params_str_validations/tutorial006c_py310.py b/docs_src/query_params_str_validations/tutorial006c_py310.py
index 82dd9e5d7..88b499c7a 100644
--- a/docs_src/query_params_str_validations/tutorial006c_py310.py
+++ b/docs_src/query_params_str_validations/tutorial006c_py310.py
@@ -4,7 +4,7 @@ app = FastAPI()
@app.get("/items/")
-async def read_items(q: str | None = Query(default=..., min_length=3)):
+async def read_items(q: str | None = Query(min_length=3)):
results = {"items": [{"item_id": "Foo"}, {"item_id": "Bar"}]}
if q:
results.update({"q": q})
diff --git a/docs_src/query_params_str_validations/tutorial006d.py b/docs_src/query_params_str_validations/tutorial006d.py
deleted file mode 100644
index a8d69c889..000000000
--- a/docs_src/query_params_str_validations/tutorial006d.py
+++ /dev/null
@@ -1,11 +0,0 @@
-from fastapi import FastAPI, Query
-
-app = FastAPI()
-
-
-@app.get("/items/")
-async def read_items(q: str = Query(default=..., min_length=3)):
- results = {"items": [{"item_id": "Foo"}, {"item_id": "Bar"}]}
- if q:
- results.update({"q": q})
- return results
diff --git a/docs_src/query_params_str_validations/tutorial006d_an.py b/docs_src/query_params_str_validations/tutorial006d_an.py
deleted file mode 100644
index ea3b02583..000000000
--- a/docs_src/query_params_str_validations/tutorial006d_an.py
+++ /dev/null
@@ -1,12 +0,0 @@
-from fastapi import FastAPI, Query
-from typing_extensions import Annotated
-
-app = FastAPI()
-
-
-@app.get("/items/")
-async def read_items(q: Annotated[str, Query(min_length=3)] = ...):
- results = {"items": [{"item_id": "Foo"}, {"item_id": "Bar"}]}
- if q:
- results.update({"q": q})
- return results
diff --git a/docs_src/query_params_str_validations/tutorial006d_an_py39.py b/docs_src/query_params_str_validations/tutorial006d_an_py39.py
deleted file mode 100644
index 687a9f544..000000000
--- a/docs_src/query_params_str_validations/tutorial006d_an_py39.py
+++ /dev/null
@@ -1,13 +0,0 @@
-from typing import Annotated
-
-from fastapi import FastAPI, Query
-
-app = FastAPI()
-
-
-@app.get("/items/")
-async def read_items(q: Annotated[str, Query(min_length=3)] = ...):
- results = {"items": [{"item_id": "Foo"}, {"item_id": "Bar"}]}
- if q:
- results.update({"q": q})
- return results
diff --git a/docs_src/security/tutorial004.py b/docs_src/security/tutorial004.py
index 91d161b8a..222589618 100644
--- a/docs_src/security/tutorial004.py
+++ b/docs_src/security/tutorial004.py
@@ -95,7 +95,7 @@ async def get_current_user(token: str = Depends(oauth2_scheme)):
)
try:
payload = jwt.decode(token, SECRET_KEY, algorithms=[ALGORITHM])
- username: str = payload.get("sub")
+ username = payload.get("sub")
if username is None:
raise credentials_exception
token_data = TokenData(username=username)
diff --git a/docs_src/security/tutorial004_an.py b/docs_src/security/tutorial004_an.py
index df50754af..e2221cd39 100644
--- a/docs_src/security/tutorial004_an.py
+++ b/docs_src/security/tutorial004_an.py
@@ -96,7 +96,7 @@ async def get_current_user(token: Annotated[str, Depends(oauth2_scheme)]):
)
try:
payload = jwt.decode(token, SECRET_KEY, algorithms=[ALGORITHM])
- username: str = payload.get("sub")
+ username = payload.get("sub")
if username is None:
raise credentials_exception
token_data = TokenData(username=username)
diff --git a/docs_src/security/tutorial004_an_py310.py b/docs_src/security/tutorial004_an_py310.py
index eff54ef01..a3f74fc0e 100644
--- a/docs_src/security/tutorial004_an_py310.py
+++ b/docs_src/security/tutorial004_an_py310.py
@@ -95,7 +95,7 @@ async def get_current_user(token: Annotated[str, Depends(oauth2_scheme)]):
)
try:
payload = jwt.decode(token, SECRET_KEY, algorithms=[ALGORITHM])
- username: str = payload.get("sub")
+ username = payload.get("sub")
if username is None:
raise credentials_exception
token_data = TokenData(username=username)
diff --git a/docs_src/security/tutorial004_an_py39.py b/docs_src/security/tutorial004_an_py39.py
index 0455b500c..b33d677ed 100644
--- a/docs_src/security/tutorial004_an_py39.py
+++ b/docs_src/security/tutorial004_an_py39.py
@@ -95,7 +95,7 @@ async def get_current_user(token: Annotated[str, Depends(oauth2_scheme)]):
)
try:
payload = jwt.decode(token, SECRET_KEY, algorithms=[ALGORITHM])
- username: str = payload.get("sub")
+ username = payload.get("sub")
if username is None:
raise credentials_exception
token_data = TokenData(username=username)
diff --git a/docs_src/security/tutorial004_py310.py b/docs_src/security/tutorial004_py310.py
index 78bee22a3..d46ce26bf 100644
--- a/docs_src/security/tutorial004_py310.py
+++ b/docs_src/security/tutorial004_py310.py
@@ -94,7 +94,7 @@ async def get_current_user(token: str = Depends(oauth2_scheme)):
)
try:
payload = jwt.decode(token, SECRET_KEY, algorithms=[ALGORITHM])
- username: str = payload.get("sub")
+ username = payload.get("sub")
if username is None:
raise credentials_exception
token_data = TokenData(username=username)
diff --git a/docs_src/security/tutorial005_an.py b/docs_src/security/tutorial005_an.py
index 5b67cb145..2e8bb3bdb 100644
--- a/docs_src/security/tutorial005_an.py
+++ b/docs_src/security/tutorial005_an.py
@@ -117,7 +117,7 @@ async def get_current_user(
)
try:
payload = jwt.decode(token, SECRET_KEY, algorithms=[ALGORITHM])
- username: str = payload.get("sub")
+ username = payload.get("sub")
if username is None:
raise credentials_exception
token_scopes = payload.get("scopes", [])
diff --git a/docs_src/security/tutorial005_an_py310.py b/docs_src/security/tutorial005_an_py310.py
index 297193e35..90781587f 100644
--- a/docs_src/security/tutorial005_an_py310.py
+++ b/docs_src/security/tutorial005_an_py310.py
@@ -116,7 +116,7 @@ async def get_current_user(
)
try:
payload = jwt.decode(token, SECRET_KEY, algorithms=[ALGORITHM])
- username: str = payload.get("sub")
+ username = payload.get("sub")
if username is None:
raise credentials_exception
token_scopes = payload.get("scopes", [])
diff --git a/docs_src/security/tutorial005_an_py39.py b/docs_src/security/tutorial005_an_py39.py
index 1acf47bdc..a5192d8d6 100644
--- a/docs_src/security/tutorial005_an_py39.py
+++ b/docs_src/security/tutorial005_an_py39.py
@@ -1,5 +1,5 @@
from datetime import datetime, timedelta, timezone
-from typing import Annotated, List, Union
+from typing import Annotated, Union
import jwt
from fastapi import Depends, FastAPI, HTTPException, Security, status
@@ -44,7 +44,7 @@ class Token(BaseModel):
class TokenData(BaseModel):
username: Union[str, None] = None
- scopes: List[str] = []
+ scopes: list[str] = []
class User(BaseModel):
@@ -116,7 +116,7 @@ async def get_current_user(
)
try:
payload = jwt.decode(token, SECRET_KEY, algorithms=[ALGORITHM])
- username: str = payload.get("sub")
+ username = payload.get("sub")
if username is None:
raise credentials_exception
token_scopes = payload.get("scopes", [])
diff --git a/tests/test_tutorial/test_configure_swagger_ui/test_tutorial002.py b/tests/test_tutorial/test_configure_swagger_ui/test_tutorial002.py
index 166901188..d06a385b5 100644
--- a/tests/test_tutorial/test_configure_swagger_ui/test_tutorial002.py
+++ b/tests/test_tutorial/test_configure_swagger_ui/test_tutorial002.py
@@ -12,7 +12,7 @@ def test_swagger_ui():
'"syntaxHighlight": false' not in response.text
), "not used parameters should not be included"
assert (
- '"syntaxHighlight.theme": "obsidian"' in response.text
+ '"syntaxHighlight": {"theme": "obsidian"}' in response.text
), "parameters with middle dots should be included in a JSON compatible way"
assert (
'"dom_id": "#swagger-ui"' in response.text
diff --git a/tests/test_tutorial/test_query_params_str_validations/test_tutorial010.py b/tests/test_tutorial/test_query_params_str_validations/test_tutorial010.py
index 4f52d6ff7..e08e16963 100644
--- a/tests/test_tutorial/test_query_params_str_validations/test_tutorial010.py
+++ b/tests/test_tutorial/test_query_params_str_validations/test_tutorial010.py
@@ -1,14 +1,29 @@
+import importlib
+
import pytest
from dirty_equals import IsDict
from fastapi._compat import PYDANTIC_VERSION_MINOR_TUPLE
from fastapi.testclient import TestClient
+from ...utils import needs_py39, needs_py310
+
-@pytest.fixture(name="client")
-def get_client():
- from docs_src.query_params_str_validations.tutorial010 import app
+@pytest.fixture(
+ name="client",
+ params=[
+ "tutorial010",
+ pytest.param("tutorial010_py310", marks=needs_py310),
+ "tutorial010_an",
+ pytest.param("tutorial010_an_py39", marks=needs_py39),
+ pytest.param("tutorial010_an_py310", marks=needs_py310),
+ ],
+)
+def get_client(request: pytest.FixtureRequest):
+ mod = importlib.import_module(
+ f"docs_src.query_params_str_validations.{request.param}"
+ )
- client = TestClient(app)
+ client = TestClient(mod.app)
return client
diff --git a/tests/test_tutorial/test_query_params_str_validations/test_tutorial010_an.py b/tests/test_tutorial/test_query_params_str_validations/test_tutorial010_an.py
deleted file mode 100644
index 5daca1e70..000000000
--- a/tests/test_tutorial/test_query_params_str_validations/test_tutorial010_an.py
+++ /dev/null
@@ -1,168 +0,0 @@
-import pytest
-from dirty_equals import IsDict
-from fastapi._compat import PYDANTIC_VERSION_MINOR_TUPLE
-from fastapi.testclient import TestClient
-
-
-@pytest.fixture(name="client")
-def get_client():
- from docs_src.query_params_str_validations.tutorial010_an import app
-
- client = TestClient(app)
- return client
-
-
-def test_query_params_str_validations_no_query(client: TestClient):
- response = client.get("/items/")
- assert response.status_code == 200
- assert response.json() == {"items": [{"item_id": "Foo"}, {"item_id": "Bar"}]}
-
-
-def test_query_params_str_validations_item_query_fixedquery(client: TestClient):
- response = client.get("/items/", params={"item-query": "fixedquery"})
- assert response.status_code == 200
- assert response.json() == {
- "items": [{"item_id": "Foo"}, {"item_id": "Bar"}],
- "q": "fixedquery",
- }
-
-
-def test_query_params_str_validations_q_fixedquery(client: TestClient):
- response = client.get("/items/", params={"q": "fixedquery"})
- assert response.status_code == 200
- assert response.json() == {"items": [{"item_id": "Foo"}, {"item_id": "Bar"}]}
-
-
-def test_query_params_str_validations_item_query_nonregexquery(client: TestClient):
- response = client.get("/items/", params={"item-query": "nonregexquery"})
- assert response.status_code == 422
- assert response.json() == IsDict(
- {
- "detail": [
- {
- "type": "string_pattern_mismatch",
- "loc": ["query", "item-query"],
- "msg": "String should match pattern '^fixedquery$'",
- "input": "nonregexquery",
- "ctx": {"pattern": "^fixedquery$"},
- }
- ]
- }
- ) | IsDict(
- # TODO: remove when deprecating Pydantic v1
- {
- "detail": [
- {
- "ctx": {"pattern": "^fixedquery$"},
- "loc": ["query", "item-query"],
- "msg": 'string does not match regex "^fixedquery$"',
- "type": "value_error.str.regex",
- }
- ]
- }
- )
-
-
-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/": {
- "get": {
- "responses": {
- "200": {
- "description": "Successful Response",
- "content": {"application/json": {"schema": {}}},
- },
- "422": {
- "description": "Validation Error",
- "content": {
- "application/json": {
- "schema": {
- "$ref": "#/components/schemas/HTTPValidationError"
- }
- }
- },
- },
- },
- "summary": "Read Items",
- "operationId": "read_items_items__get",
- "parameters": [
- {
- "description": "Query string for the items to search in the database that have a good match",
- "required": False,
- "deprecated": True,
- "schema": IsDict(
- {
- "anyOf": [
- {
- "type": "string",
- "minLength": 3,
- "maxLength": 50,
- "pattern": "^fixedquery$",
- },
- {"type": "null"},
- ],
- "title": "Query string",
- "description": "Query string for the items to search in the database that have a good match",
- # See https://github.com/pydantic/pydantic/blob/80353c29a824c55dea4667b328ba8f329879ac9f/tests/test_fastapi.sh#L25-L34.
- **(
- {"deprecated": True}
- if PYDANTIC_VERSION_MINOR_TUPLE >= (2, 10)
- else {}
- ),
- }
- )
- | IsDict(
- # TODO: remove when deprecating Pydantic v1
- {
- "title": "Query string",
- "maxLength": 50,
- "minLength": 3,
- "pattern": "^fixedquery$",
- "type": "string",
- "description": "Query string for the items to search in the database that have a good match",
- }
- ),
- "name": "item-query",
- "in": "query",
- }
- ],
- }
- }
- },
- "components": {
- "schemas": {
- "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"},
- }
- },
- },
- }
- },
- }
diff --git a/tests/test_tutorial/test_query_params_str_validations/test_tutorial010_an_py310.py b/tests/test_tutorial/test_query_params_str_validations/test_tutorial010_an_py310.py
deleted file mode 100644
index 89da4d82e..000000000
--- a/tests/test_tutorial/test_query_params_str_validations/test_tutorial010_an_py310.py
+++ /dev/null
@@ -1,175 +0,0 @@
-import pytest
-from dirty_equals import IsDict
-from fastapi._compat import PYDANTIC_VERSION_MINOR_TUPLE
-from fastapi.testclient import TestClient
-
-from ...utils import needs_py310
-
-
-@pytest.fixture(name="client")
-def get_client():
- from docs_src.query_params_str_validations.tutorial010_an_py310 import app
-
- client = TestClient(app)
- return client
-
-
-@needs_py310
-def test_query_params_str_validations_no_query(client: TestClient):
- response = client.get("/items/")
- assert response.status_code == 200
- assert response.json() == {"items": [{"item_id": "Foo"}, {"item_id": "Bar"}]}
-
-
-@needs_py310
-def test_query_params_str_validations_item_query_fixedquery(client: TestClient):
- response = client.get("/items/", params={"item-query": "fixedquery"})
- assert response.status_code == 200
- assert response.json() == {
- "items": [{"item_id": "Foo"}, {"item_id": "Bar"}],
- "q": "fixedquery",
- }
-
-
-@needs_py310
-def test_query_params_str_validations_q_fixedquery(client: TestClient):
- response = client.get("/items/", params={"q": "fixedquery"})
- assert response.status_code == 200
- assert response.json() == {"items": [{"item_id": "Foo"}, {"item_id": "Bar"}]}
-
-
-@needs_py310
-def test_query_params_str_validations_item_query_nonregexquery(client: TestClient):
- response = client.get("/items/", params={"item-query": "nonregexquery"})
- assert response.status_code == 422
- assert response.json() == IsDict(
- {
- "detail": [
- {
- "type": "string_pattern_mismatch",
- "loc": ["query", "item-query"],
- "msg": "String should match pattern '^fixedquery$'",
- "input": "nonregexquery",
- "ctx": {"pattern": "^fixedquery$"},
- }
- ]
- }
- ) | IsDict(
- # TODO: remove when deprecating Pydantic v1
- {
- "detail": [
- {
- "ctx": {"pattern": "^fixedquery$"},
- "loc": ["query", "item-query"],
- "msg": 'string does not match regex "^fixedquery$"',
- "type": "value_error.str.regex",
- }
- ]
- }
- )
-
-
-@needs_py310
-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/": {
- "get": {
- "responses": {
- "200": {
- "description": "Successful Response",
- "content": {"application/json": {"schema": {}}},
- },
- "422": {
- "description": "Validation Error",
- "content": {
- "application/json": {
- "schema": {
- "$ref": "#/components/schemas/HTTPValidationError"
- }
- }
- },
- },
- },
- "summary": "Read Items",
- "operationId": "read_items_items__get",
- "parameters": [
- {
- "description": "Query string for the items to search in the database that have a good match",
- "required": False,
- "deprecated": True,
- "schema": IsDict(
- {
- "anyOf": [
- {
- "type": "string",
- "minLength": 3,
- "maxLength": 50,
- "pattern": "^fixedquery$",
- },
- {"type": "null"},
- ],
- "title": "Query string",
- "description": "Query string for the items to search in the database that have a good match",
- # See https://github.com/pydantic/pydantic/blob/80353c29a824c55dea4667b328ba8f329879ac9f/tests/test_fastapi.sh#L25-L34.
- **(
- {"deprecated": True}
- if PYDANTIC_VERSION_MINOR_TUPLE >= (2, 10)
- else {}
- ),
- }
- )
- | IsDict(
- # TODO: remove when deprecating Pydantic v1
- {
- "title": "Query string",
- "maxLength": 50,
- "minLength": 3,
- "pattern": "^fixedquery$",
- "type": "string",
- "description": "Query string for the items to search in the database that have a good match",
- }
- ),
- "name": "item-query",
- "in": "query",
- }
- ],
- }
- }
- },
- "components": {
- "schemas": {
- "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"},
- }
- },
- },
- }
- },
- }
diff --git a/tests/test_tutorial/test_query_params_str_validations/test_tutorial010_an_py39.py b/tests/test_tutorial/test_query_params_str_validations/test_tutorial010_an_py39.py
deleted file mode 100644
index f5f692b06..000000000
--- a/tests/test_tutorial/test_query_params_str_validations/test_tutorial010_an_py39.py
+++ /dev/null
@@ -1,175 +0,0 @@
-import pytest
-from dirty_equals import IsDict
-from fastapi._compat import PYDANTIC_VERSION_MINOR_TUPLE
-from fastapi.testclient import TestClient
-
-from ...utils import needs_py39
-
-
-@pytest.fixture(name="client")
-def get_client():
- from docs_src.query_params_str_validations.tutorial010_an_py39 import app
-
- client = TestClient(app)
- return client
-
-
-@needs_py39
-def test_query_params_str_validations_no_query(client: TestClient):
- response = client.get("/items/")
- assert response.status_code == 200
- assert response.json() == {"items": [{"item_id": "Foo"}, {"item_id": "Bar"}]}
-
-
-@needs_py39
-def test_query_params_str_validations_item_query_fixedquery(client: TestClient):
- response = client.get("/items/", params={"item-query": "fixedquery"})
- assert response.status_code == 200
- assert response.json() == {
- "items": [{"item_id": "Foo"}, {"item_id": "Bar"}],
- "q": "fixedquery",
- }
-
-
-@needs_py39
-def test_query_params_str_validations_q_fixedquery(client: TestClient):
- response = client.get("/items/", params={"q": "fixedquery"})
- assert response.status_code == 200
- assert response.json() == {"items": [{"item_id": "Foo"}, {"item_id": "Bar"}]}
-
-
-@needs_py39
-def test_query_params_str_validations_item_query_nonregexquery(client: TestClient):
- response = client.get("/items/", params={"item-query": "nonregexquery"})
- assert response.status_code == 422
- assert response.json() == IsDict(
- {
- "detail": [
- {
- "type": "string_pattern_mismatch",
- "loc": ["query", "item-query"],
- "msg": "String should match pattern '^fixedquery$'",
- "input": "nonregexquery",
- "ctx": {"pattern": "^fixedquery$"},
- }
- ]
- }
- ) | IsDict(
- # TODO: remove when deprecating Pydantic v1
- {
- "detail": [
- {
- "ctx": {"pattern": "^fixedquery$"},
- "loc": ["query", "item-query"],
- "msg": 'string does not match regex "^fixedquery$"',
- "type": "value_error.str.regex",
- }
- ]
- }
- )
-
-
-@needs_py39
-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/": {
- "get": {
- "responses": {
- "200": {
- "description": "Successful Response",
- "content": {"application/json": {"schema": {}}},
- },
- "422": {
- "description": "Validation Error",
- "content": {
- "application/json": {
- "schema": {
- "$ref": "#/components/schemas/HTTPValidationError"
- }
- }
- },
- },
- },
- "summary": "Read Items",
- "operationId": "read_items_items__get",
- "parameters": [
- {
- "description": "Query string for the items to search in the database that have a good match",
- "required": False,
- "deprecated": True,
- "schema": IsDict(
- {
- "anyOf": [
- {
- "type": "string",
- "minLength": 3,
- "maxLength": 50,
- "pattern": "^fixedquery$",
- },
- {"type": "null"},
- ],
- "title": "Query string",
- "description": "Query string for the items to search in the database that have a good match",
- # See https://github.com/pydantic/pydantic/blob/80353c29a824c55dea4667b328ba8f329879ac9f/tests/test_fastapi.sh#L25-L34.
- **(
- {"deprecated": True}
- if PYDANTIC_VERSION_MINOR_TUPLE >= (2, 10)
- else {}
- ),
- }
- )
- | IsDict(
- # TODO: remove when deprecating Pydantic v1
- {
- "title": "Query string",
- "maxLength": 50,
- "minLength": 3,
- "pattern": "^fixedquery$",
- "type": "string",
- "description": "Query string for the items to search in the database that have a good match",
- }
- ),
- "name": "item-query",
- "in": "query",
- }
- ],
- }
- }
- },
- "components": {
- "schemas": {
- "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"},
- }
- },
- },
- }
- },
- }
diff --git a/tests/test_tutorial/test_query_params_str_validations/test_tutorial010_py310.py b/tests/test_tutorial/test_query_params_str_validations/test_tutorial010_py310.py
deleted file mode 100644
index 5b62c969f..000000000
--- a/tests/test_tutorial/test_query_params_str_validations/test_tutorial010_py310.py
+++ /dev/null
@@ -1,175 +0,0 @@
-import pytest
-from dirty_equals import IsDict
-from fastapi._compat import PYDANTIC_VERSION_MINOR_TUPLE
-from fastapi.testclient import TestClient
-
-from ...utils import needs_py310
-
-
-@pytest.fixture(name="client")
-def get_client():
- from docs_src.query_params_str_validations.tutorial010_py310 import app
-
- client = TestClient(app)
- return client
-
-
-@needs_py310
-def test_query_params_str_validations_no_query(client: TestClient):
- response = client.get("/items/")
- assert response.status_code == 200
- assert response.json() == {"items": [{"item_id": "Foo"}, {"item_id": "Bar"}]}
-
-
-@needs_py310
-def test_query_params_str_validations_item_query_fixedquery(client: TestClient):
- response = client.get("/items/", params={"item-query": "fixedquery"})
- assert response.status_code == 200
- assert response.json() == {
- "items": [{"item_id": "Foo"}, {"item_id": "Bar"}],
- "q": "fixedquery",
- }
-
-
-@needs_py310
-def test_query_params_str_validations_q_fixedquery(client: TestClient):
- response = client.get("/items/", params={"q": "fixedquery"})
- assert response.status_code == 200
- assert response.json() == {"items": [{"item_id": "Foo"}, {"item_id": "Bar"}]}
-
-
-@needs_py310
-def test_query_params_str_validations_item_query_nonregexquery(client: TestClient):
- response = client.get("/items/", params={"item-query": "nonregexquery"})
- assert response.status_code == 422
- assert response.json() == IsDict(
- {
- "detail": [
- {
- "type": "string_pattern_mismatch",
- "loc": ["query", "item-query"],
- "msg": "String should match pattern '^fixedquery$'",
- "input": "nonregexquery",
- "ctx": {"pattern": "^fixedquery$"},
- }
- ]
- }
- ) | IsDict(
- # TODO: remove when deprecating Pydantic v1
- {
- "detail": [
- {
- "ctx": {"pattern": "^fixedquery$"},
- "loc": ["query", "item-query"],
- "msg": 'string does not match regex "^fixedquery$"',
- "type": "value_error.str.regex",
- }
- ]
- }
- )
-
-
-@needs_py310
-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/": {
- "get": {
- "responses": {
- "200": {
- "description": "Successful Response",
- "content": {"application/json": {"schema": {}}},
- },
- "422": {
- "description": "Validation Error",
- "content": {
- "application/json": {
- "schema": {
- "$ref": "#/components/schemas/HTTPValidationError"
- }
- }
- },
- },
- },
- "summary": "Read Items",
- "operationId": "read_items_items__get",
- "parameters": [
- {
- "description": "Query string for the items to search in the database that have a good match",
- "required": False,
- "deprecated": True,
- "schema": IsDict(
- {
- "anyOf": [
- {
- "type": "string",
- "minLength": 3,
- "maxLength": 50,
- "pattern": "^fixedquery$",
- },
- {"type": "null"},
- ],
- "title": "Query string",
- "description": "Query string for the items to search in the database that have a good match",
- # See https://github.com/pydantic/pydantic/blob/80353c29a824c55dea4667b328ba8f329879ac9f/tests/test_fastapi.sh#L25-L34.
- **(
- {"deprecated": True}
- if PYDANTIC_VERSION_MINOR_TUPLE >= (2, 10)
- else {}
- ),
- }
- )
- | IsDict(
- # TODO: remove when deprecating Pydantic v1
- {
- "title": "Query string",
- "maxLength": 50,
- "minLength": 3,
- "pattern": "^fixedquery$",
- "type": "string",
- "description": "Query string for the items to search in the database that have a good match",
- }
- ),
- "name": "item-query",
- "in": "query",
- }
- ],
- }
- }
- },
- "components": {
- "schemas": {
- "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"},
- }
- },
- },
- }
- },
- }
diff --git a/tests/test_tutorial/test_query_params_str_validations/test_tutorial011.py b/tests/test_tutorial/test_query_params_str_validations/test_tutorial011.py
index 5ba39b05d..f4da25752 100644
--- a/tests/test_tutorial/test_query_params_str_validations/test_tutorial011.py
+++ b/tests/test_tutorial/test_query_params_str_validations/test_tutorial011.py
@@ -1,26 +1,47 @@
+import importlib
+
+import pytest
from dirty_equals import IsDict
from fastapi.testclient import TestClient
-from docs_src.query_params_str_validations.tutorial011 import app
+from ...utils import needs_py39, needs_py310
+
+
+@pytest.fixture(
+ name="client",
+ params=[
+ "tutorial011",
+ pytest.param("tutorial011_py39", marks=needs_py310),
+ pytest.param("tutorial011_py310", marks=needs_py310),
+ "tutorial011_an",
+ pytest.param("tutorial011_an_py39", marks=needs_py39),
+ pytest.param("tutorial011_an_py310", marks=needs_py310),
+ ],
+)
+def get_client(request: pytest.FixtureRequest):
+ mod = importlib.import_module(
+ f"docs_src.query_params_str_validations.{request.param}"
+ )
-client = TestClient(app)
+ client = TestClient(mod.app)
+ return client
-def test_multi_query_values():
+def test_multi_query_values(client: TestClient):
url = "/items/?q=foo&q=bar"
response = client.get(url)
assert response.status_code == 200, response.text
assert response.json() == {"q": ["foo", "bar"]}
-def test_query_no_values():
+def test_query_no_values(client: TestClient):
url = "/items/"
response = client.get(url)
assert response.status_code == 200, response.text
assert response.json() == {"q": None}
-def test_openapi_schema():
+def test_openapi_schema(client: TestClient):
response = client.get("/openapi.json")
assert response.status_code == 200, response.text
assert response.json() == {
diff --git a/tests/test_tutorial/test_query_params_str_validations/test_tutorial011_an.py b/tests/test_tutorial/test_query_params_str_validations/test_tutorial011_an.py
deleted file mode 100644
index 3942ea77a..000000000
--- a/tests/test_tutorial/test_query_params_str_validations/test_tutorial011_an.py
+++ /dev/null
@@ -1,108 +0,0 @@
-from dirty_equals import IsDict
-from fastapi.testclient import TestClient
-
-from docs_src.query_params_str_validations.tutorial011_an import app
-
-client = TestClient(app)
-
-
-def test_multi_query_values():
- url = "/items/?q=foo&q=bar"
- response = client.get(url)
- assert response.status_code == 200, response.text
- assert response.json() == {"q": ["foo", "bar"]}
-
-
-def test_query_no_values():
- url = "/items/"
- response = client.get(url)
- assert response.status_code == 200, response.text
- assert response.json() == {"q": None}
-
-
-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/": {
- "get": {
- "responses": {
- "200": {
- "description": "Successful Response",
- "content": {"application/json": {"schema": {}}},
- },
- "422": {
- "description": "Validation Error",
- "content": {
- "application/json": {
- "schema": {
- "$ref": "#/components/schemas/HTTPValidationError"
- }
- }
- },
- },
- },
- "summary": "Read Items",
- "operationId": "read_items_items__get",
- "parameters": [
- {
- "required": False,
- "schema": IsDict(
- {
- "anyOf": [
- {"type": "array", "items": {"type": "string"}},
- {"type": "null"},
- ],
- "title": "Q",
- }
- )
- | IsDict(
- # TODO: remove when deprecating Pydantic v1
- {
- "title": "Q",
- "type": "array",
- "items": {"type": "string"},
- }
- ),
- "name": "q",
- "in": "query",
- }
- ],
- }
- }
- },
- "components": {
- "schemas": {
- "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"},
- }
- },
- },
- }
- },
- }
diff --git a/tests/test_tutorial/test_query_params_str_validations/test_tutorial011_an_py310.py b/tests/test_tutorial/test_query_params_str_validations/test_tutorial011_an_py310.py
deleted file mode 100644
index f2ec38c95..000000000
--- a/tests/test_tutorial/test_query_params_str_validations/test_tutorial011_an_py310.py
+++ /dev/null
@@ -1,118 +0,0 @@
-import pytest
-from dirty_equals import IsDict
-from fastapi.testclient import TestClient
-
-from ...utils import needs_py310
-
-
-@pytest.fixture(name="client")
-def get_client():
- from docs_src.query_params_str_validations.tutorial011_an_py310 import app
-
- client = TestClient(app)
- return client
-
-
-@needs_py310
-def test_multi_query_values(client: TestClient):
- url = "/items/?q=foo&q=bar"
- response = client.get(url)
- assert response.status_code == 200, response.text
- assert response.json() == {"q": ["foo", "bar"]}
-
-
-@needs_py310
-def test_query_no_values(client: TestClient):
- url = "/items/"
- response = client.get(url)
- assert response.status_code == 200, response.text
- assert response.json() == {"q": None}
-
-
-@needs_py310
-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/": {
- "get": {
- "responses": {
- "200": {
- "description": "Successful Response",
- "content": {"application/json": {"schema": {}}},
- },
- "422": {
- "description": "Validation Error",
- "content": {
- "application/json": {
- "schema": {
- "$ref": "#/components/schemas/HTTPValidationError"
- }
- }
- },
- },
- },
- "summary": "Read Items",
- "operationId": "read_items_items__get",
- "parameters": [
- {
- "required": False,
- "schema": IsDict(
- {
- "anyOf": [
- {"type": "array", "items": {"type": "string"}},
- {"type": "null"},
- ],
- "title": "Q",
- }
- )
- | IsDict(
- # TODO: remove when deprecating Pydantic v1
- {
- "title": "Q",
- "type": "array",
- "items": {"type": "string"},
- }
- ),
- "name": "q",
- "in": "query",
- }
- ],
- }
- }
- },
- "components": {
- "schemas": {
- "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"},
- }
- },
- },
- }
- },
- }
diff --git a/tests/test_tutorial/test_query_params_str_validations/test_tutorial011_an_py39.py b/tests/test_tutorial/test_query_params_str_validations/test_tutorial011_an_py39.py
deleted file mode 100644
index cd7b15679..000000000
--- a/tests/test_tutorial/test_query_params_str_validations/test_tutorial011_an_py39.py
+++ /dev/null
@@ -1,118 +0,0 @@
-import pytest
-from dirty_equals import IsDict
-from fastapi.testclient import TestClient
-
-from ...utils import needs_py39
-
-
-@pytest.fixture(name="client")
-def get_client():
- from docs_src.query_params_str_validations.tutorial011_an_py39 import app
-
- client = TestClient(app)
- return client
-
-
-@needs_py39
-def test_multi_query_values(client: TestClient):
- url = "/items/?q=foo&q=bar"
- response = client.get(url)
- assert response.status_code == 200, response.text
- assert response.json() == {"q": ["foo", "bar"]}
-
-
-@needs_py39
-def test_query_no_values(client: TestClient):
- url = "/items/"
- response = client.get(url)
- assert response.status_code == 200, response.text
- assert response.json() == {"q": None}
-
-
-@needs_py39
-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/": {
- "get": {
- "responses": {
- "200": {
- "description": "Successful Response",
- "content": {"application/json": {"schema": {}}},
- },
- "422": {
- "description": "Validation Error",
- "content": {
- "application/json": {
- "schema": {
- "$ref": "#/components/schemas/HTTPValidationError"
- }
- }
- },
- },
- },
- "summary": "Read Items",
- "operationId": "read_items_items__get",
- "parameters": [
- {
- "required": False,
- "schema": IsDict(
- {
- "anyOf": [
- {"type": "array", "items": {"type": "string"}},
- {"type": "null"},
- ],
- "title": "Q",
- }
- )
- | IsDict(
- # TODO: remove when deprecating Pydantic v1
- {
- "title": "Q",
- "type": "array",
- "items": {"type": "string"},
- }
- ),
- "name": "q",
- "in": "query",
- }
- ],
- }
- }
- },
- "components": {
- "schemas": {
- "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"},
- }
- },
- },
- }
- },
- }
diff --git a/tests/test_tutorial/test_query_params_str_validations/test_tutorial011_py310.py b/tests/test_tutorial/test_query_params_str_validations/test_tutorial011_py310.py
deleted file mode 100644
index bdc729516..000000000
--- a/tests/test_tutorial/test_query_params_str_validations/test_tutorial011_py310.py
+++ /dev/null
@@ -1,118 +0,0 @@
-import pytest
-from dirty_equals import IsDict
-from fastapi.testclient import TestClient
-
-from ...utils import needs_py310
-
-
-@pytest.fixture(name="client")
-def get_client():
- from docs_src.query_params_str_validations.tutorial011_py310 import app
-
- client = TestClient(app)
- return client
-
-
-@needs_py310
-def test_multi_query_values(client: TestClient):
- url = "/items/?q=foo&q=bar"
- response = client.get(url)
- assert response.status_code == 200, response.text
- assert response.json() == {"q": ["foo", "bar"]}
-
-
-@needs_py310
-def test_query_no_values(client: TestClient):
- url = "/items/"
- response = client.get(url)
- assert response.status_code == 200, response.text
- assert response.json() == {"q": None}
-
-
-@needs_py310
-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/": {
- "get": {
- "responses": {
- "200": {
- "description": "Successful Response",
- "content": {"application/json": {"schema": {}}},
- },
- "422": {
- "description": "Validation Error",
- "content": {
- "application/json": {
- "schema": {
- "$ref": "#/components/schemas/HTTPValidationError"
- }
- }
- },
- },
- },
- "summary": "Read Items",
- "operationId": "read_items_items__get",
- "parameters": [
- {
- "required": False,
- "schema": IsDict(
- {
- "anyOf": [
- {"type": "array", "items": {"type": "string"}},
- {"type": "null"},
- ],
- "title": "Q",
- }
- )
- | IsDict(
- # TODO: remove when deprecating Pydantic v1
- {
- "title": "Q",
- "type": "array",
- "items": {"type": "string"},
- }
- ),
- "name": "q",
- "in": "query",
- }
- ],
- }
- }
- },
- "components": {
- "schemas": {
- "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"},
- }
- },
- },
- }
- },
- }
diff --git a/tests/test_tutorial/test_query_params_str_validations/test_tutorial011_py39.py b/tests/test_tutorial/test_query_params_str_validations/test_tutorial011_py39.py
deleted file mode 100644
index 26ac56b2f..000000000
--- a/tests/test_tutorial/test_query_params_str_validations/test_tutorial011_py39.py
+++ /dev/null
@@ -1,118 +0,0 @@
-import pytest
-from dirty_equals import IsDict
-from fastapi.testclient import TestClient
-
-from ...utils import needs_py39
-
-
-@pytest.fixture(name="client")
-def get_client():
- from docs_src.query_params_str_validations.tutorial011_py39 import app
-
- client = TestClient(app)
- return client
-
-
-@needs_py39
-def test_multi_query_values(client: TestClient):
- url = "/items/?q=foo&q=bar"
- response = client.get(url)
- assert response.status_code == 200, response.text
- assert response.json() == {"q": ["foo", "bar"]}
-
-
-@needs_py39
-def test_query_no_values(client: TestClient):
- url = "/items/"
- response = client.get(url)
- assert response.status_code == 200, response.text
- assert response.json() == {"q": None}
-
-
-@needs_py39
-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/": {
- "get": {
- "responses": {
- "200": {
- "description": "Successful Response",
- "content": {"application/json": {"schema": {}}},
- },
- "422": {
- "description": "Validation Error",
- "content": {
- "application/json": {
- "schema": {
- "$ref": "#/components/schemas/HTTPValidationError"
- }
- }
- },
- },
- },
- "summary": "Read Items",
- "operationId": "read_items_items__get",
- "parameters": [
- {
- "required": False,
- "schema": IsDict(
- {
- "anyOf": [
- {"type": "array", "items": {"type": "string"}},
- {"type": "null"},
- ],
- "title": "Q",
- }
- )
- | IsDict(
- # TODO: remove when deprecating Pydantic v1
- {
- "title": "Q",
- "type": "array",
- "items": {"type": "string"},
- }
- ),
- "name": "q",
- "in": "query",
- }
- ],
- }
- }
- },
- "components": {
- "schemas": {
- "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"},
- }
- },
- },
- }
- },
- }
diff --git a/tests/test_tutorial/test_query_params_str_validations/test_tutorial012.py b/tests/test_tutorial/test_query_params_str_validations/test_tutorial012.py
index 1436db384..549a90519 100644
--- a/tests/test_tutorial/test_query_params_str_validations/test_tutorial012.py
+++ b/tests/test_tutorial/test_query_params_str_validations/test_tutorial012.py
@@ -1,25 +1,44 @@
+import importlib
+
+import pytest
from fastapi.testclient import TestClient
-from docs_src.query_params_str_validations.tutorial012 import app
+from ...utils import needs_py39
+
+
+@pytest.fixture(
+ name="client",
+ params=[
+ "tutorial012",
+ pytest.param("tutorial012_py39", marks=needs_py39),
+ "tutorial012_an",
+ pytest.param("tutorial012_an_py39", marks=needs_py39),
+ ],
+)
+def get_client(request: pytest.FixtureRequest):
+ mod = importlib.import_module(
+ f"docs_src.query_params_str_validations.{request.param}"
+ )
-client = TestClient(app)
+ client = TestClient(mod.app)
+ return client
-def test_default_query_values():
+def test_default_query_values(client: TestClient):
url = "/items/"
response = client.get(url)
assert response.status_code == 200, response.text
assert response.json() == {"q": ["foo", "bar"]}
-def test_multi_query_values():
+def test_multi_query_values(client: TestClient):
url = "/items/?q=baz&q=foobar"
response = client.get(url)
assert response.status_code == 200, response.text
assert response.json() == {"q": ["baz", "foobar"]}
-def test_openapi_schema():
+def test_openapi_schema(client: TestClient):
response = client.get("/openapi.json")
assert response.status_code == 200, response.text
assert response.json() == {
diff --git a/tests/test_tutorial/test_query_params_str_validations/test_tutorial012_an.py b/tests/test_tutorial/test_query_params_str_validations/test_tutorial012_an.py
deleted file mode 100644
index 270763f1d..000000000
--- a/tests/test_tutorial/test_query_params_str_validations/test_tutorial012_an.py
+++ /dev/null
@@ -1,96 +0,0 @@
-from fastapi.testclient import TestClient
-
-from docs_src.query_params_str_validations.tutorial012_an import app
-
-client = TestClient(app)
-
-
-def test_default_query_values():
- url = "/items/"
- response = client.get(url)
- assert response.status_code == 200, response.text
- assert response.json() == {"q": ["foo", "bar"]}
-
-
-def test_multi_query_values():
- url = "/items/?q=baz&q=foobar"
- response = client.get(url)
- assert response.status_code == 200, response.text
- assert response.json() == {"q": ["baz", "foobar"]}
-
-
-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/": {
- "get": {
- "responses": {
- "200": {
- "description": "Successful Response",
- "content": {"application/json": {"schema": {}}},
- },
- "422": {
- "description": "Validation Error",
- "content": {
- "application/json": {
- "schema": {
- "$ref": "#/components/schemas/HTTPValidationError"
- }
- }
- },
- },
- },
- "summary": "Read Items",
- "operationId": "read_items_items__get",
- "parameters": [
- {
- "required": False,
- "schema": {
- "title": "Q",
- "type": "array",
- "items": {"type": "string"},
- "default": ["foo", "bar"],
- },
- "name": "q",
- "in": "query",
- }
- ],
- }
- }
- },
- "components": {
- "schemas": {
- "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"},
- }
- },
- },
- }
- },
- }
diff --git a/tests/test_tutorial/test_query_params_str_validations/test_tutorial012_an_py39.py b/tests/test_tutorial/test_query_params_str_validations/test_tutorial012_an_py39.py
deleted file mode 100644
index 548391683..000000000
--- a/tests/test_tutorial/test_query_params_str_validations/test_tutorial012_an_py39.py
+++ /dev/null
@@ -1,106 +0,0 @@
-import pytest
-from fastapi.testclient import TestClient
-
-from ...utils import needs_py39
-
-
-@pytest.fixture(name="client")
-def get_client():
- from docs_src.query_params_str_validations.tutorial012_an_py39 import app
-
- client = TestClient(app)
- return client
-
-
-@needs_py39
-def test_default_query_values(client: TestClient):
- url = "/items/"
- response = client.get(url)
- assert response.status_code == 200, response.text
- assert response.json() == {"q": ["foo", "bar"]}
-
-
-@needs_py39
-def test_multi_query_values(client: TestClient):
- url = "/items/?q=baz&q=foobar"
- response = client.get(url)
- assert response.status_code == 200, response.text
- assert response.json() == {"q": ["baz", "foobar"]}
-
-
-@needs_py39
-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/": {
- "get": {
- "responses": {
- "200": {
- "description": "Successful Response",
- "content": {"application/json": {"schema": {}}},
- },
- "422": {
- "description": "Validation Error",
- "content": {
- "application/json": {
- "schema": {
- "$ref": "#/components/schemas/HTTPValidationError"
- }
- }
- },
- },
- },
- "summary": "Read Items",
- "operationId": "read_items_items__get",
- "parameters": [
- {
- "required": False,
- "schema": {
- "title": "Q",
- "type": "array",
- "items": {"type": "string"},
- "default": ["foo", "bar"],
- },
- "name": "q",
- "in": "query",
- }
- ],
- }
- }
- },
- "components": {
- "schemas": {
- "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"},
- }
- },
- },
- }
- },
- }
diff --git a/tests/test_tutorial/test_query_params_str_validations/test_tutorial012_py39.py b/tests/test_tutorial/test_query_params_str_validations/test_tutorial012_py39.py
deleted file mode 100644
index e7d745154..000000000
--- a/tests/test_tutorial/test_query_params_str_validations/test_tutorial012_py39.py
+++ /dev/null
@@ -1,106 +0,0 @@
-import pytest
-from fastapi.testclient import TestClient
-
-from ...utils import needs_py39
-
-
-@pytest.fixture(name="client")
-def get_client():
- from docs_src.query_params_str_validations.tutorial012_py39 import app
-
- client = TestClient(app)
- return client
-
-
-@needs_py39
-def test_default_query_values(client: TestClient):
- url = "/items/"
- response = client.get(url)
- assert response.status_code == 200, response.text
- assert response.json() == {"q": ["foo", "bar"]}
-
-
-@needs_py39
-def test_multi_query_values(client: TestClient):
- url = "/items/?q=baz&q=foobar"
- response = client.get(url)
- assert response.status_code == 200, response.text
- assert response.json() == {"q": ["baz", "foobar"]}
-
-
-@needs_py39
-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/": {
- "get": {
- "responses": {
- "200": {
- "description": "Successful Response",
- "content": {"application/json": {"schema": {}}},
- },
- "422": {
- "description": "Validation Error",
- "content": {
- "application/json": {
- "schema": {
- "$ref": "#/components/schemas/HTTPValidationError"
- }
- }
- },
- },
- },
- "summary": "Read Items",
- "operationId": "read_items_items__get",
- "parameters": [
- {
- "required": False,
- "schema": {
- "title": "Q",
- "type": "array",
- "items": {"type": "string"},
- "default": ["foo", "bar"],
- },
- "name": "q",
- "in": "query",
- }
- ],
- }
- }
- },
- "components": {
- "schemas": {
- "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"},
- }
- },
- },
- }
- },
- }
diff --git a/tests/test_tutorial/test_query_params_str_validations/test_tutorial013.py b/tests/test_tutorial/test_query_params_str_validations/test_tutorial013.py
index 1ba1fdf61..f2f5f7a85 100644
--- a/tests/test_tutorial/test_query_params_str_validations/test_tutorial013.py
+++ b/tests/test_tutorial/test_query_params_str_validations/test_tutorial013.py
@@ -1,25 +1,43 @@
+import importlib
+
+import pytest
from fastapi.testclient import TestClient
-from docs_src.query_params_str_validations.tutorial013 import app
+from ...utils import needs_py39
+
+
+@pytest.fixture(
+ name="client",
+ params=[
+ "tutorial013",
+ "tutorial013_an",
+ pytest.param("tutorial013_an_py39", marks=needs_py39),
+ ],
+)
+def get_client(request: pytest.FixtureRequest):
+ mod = importlib.import_module(
+ f"docs_src.query_params_str_validations.{request.param}"
+ )
-client = TestClient(app)
+ client = TestClient(mod.app)
+ return client
-def test_multi_query_values():
+def test_multi_query_values(client: TestClient):
url = "/items/?q=foo&q=bar"
response = client.get(url)
assert response.status_code == 200, response.text
assert response.json() == {"q": ["foo", "bar"]}
-def test_query_no_values():
+def test_query_no_values(client: TestClient):
url = "/items/"
response = client.get(url)
assert response.status_code == 200, response.text
assert response.json() == {"q": []}
-def test_openapi_schema():
+def test_openapi_schema(client: TestClient):
response = client.get("/openapi.json")
assert response.status_code == 200, response.text
assert response.json() == {
diff --git a/tests/test_tutorial/test_query_params_str_validations/test_tutorial013_an.py b/tests/test_tutorial/test_query_params_str_validations/test_tutorial013_an.py
deleted file mode 100644
index 343261748..000000000
--- a/tests/test_tutorial/test_query_params_str_validations/test_tutorial013_an.py
+++ /dev/null
@@ -1,96 +0,0 @@
-from fastapi.testclient import TestClient
-
-from docs_src.query_params_str_validations.tutorial013_an import app
-
-client = TestClient(app)
-
-
-def test_multi_query_values():
- url = "/items/?q=foo&q=bar"
- response = client.get(url)
- assert response.status_code == 200, response.text
- assert response.json() == {"q": ["foo", "bar"]}
-
-
-def test_query_no_values():
- url = "/items/"
- response = client.get(url)
- assert response.status_code == 200, response.text
- assert response.json() == {"q": []}
-
-
-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/": {
- "get": {
- "responses": {
- "200": {
- "description": "Successful Response",
- "content": {"application/json": {"schema": {}}},
- },
- "422": {
- "description": "Validation Error",
- "content": {
- "application/json": {
- "schema": {
- "$ref": "#/components/schemas/HTTPValidationError"
- }
- }
- },
- },
- },
- "summary": "Read Items",
- "operationId": "read_items_items__get",
- "parameters": [
- {
- "required": False,
- "schema": {
- "title": "Q",
- "type": "array",
- "items": {},
- "default": [],
- },
- "name": "q",
- "in": "query",
- }
- ],
- }
- }
- },
- "components": {
- "schemas": {
- "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"},
- }
- },
- },
- }
- },
- }
diff --git a/tests/test_tutorial/test_query_params_str_validations/test_tutorial013_an_py39.py b/tests/test_tutorial/test_query_params_str_validations/test_tutorial013_an_py39.py
deleted file mode 100644
index 537d6325b..000000000
--- a/tests/test_tutorial/test_query_params_str_validations/test_tutorial013_an_py39.py
+++ /dev/null
@@ -1,106 +0,0 @@
-import pytest
-from fastapi.testclient import TestClient
-
-from ...utils import needs_py39
-
-
-@pytest.fixture(name="client")
-def get_client():
- from docs_src.query_params_str_validations.tutorial013_an_py39 import app
-
- client = TestClient(app)
- return client
-
-
-@needs_py39
-def test_multi_query_values(client: TestClient):
- url = "/items/?q=foo&q=bar"
- response = client.get(url)
- assert response.status_code == 200, response.text
- assert response.json() == {"q": ["foo", "bar"]}
-
-
-@needs_py39
-def test_query_no_values(client: TestClient):
- url = "/items/"
- response = client.get(url)
- assert response.status_code == 200, response.text
- assert response.json() == {"q": []}
-
-
-@needs_py39
-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/": {
- "get": {
- "responses": {
- "200": {
- "description": "Successful Response",
- "content": {"application/json": {"schema": {}}},
- },
- "422": {
- "description": "Validation Error",
- "content": {
- "application/json": {
- "schema": {
- "$ref": "#/components/schemas/HTTPValidationError"
- }
- }
- },
- },
- },
- "summary": "Read Items",
- "operationId": "read_items_items__get",
- "parameters": [
- {
- "required": False,
- "schema": {
- "title": "Q",
- "type": "array",
- "items": {},
- "default": [],
- },
- "name": "q",
- "in": "query",
- }
- ],
- }
- }
- },
- "components": {
- "schemas": {
- "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"},
- }
- },
- },
- }
- },
- }
diff --git a/tests/test_tutorial/test_query_params_str_validations/test_tutorial014.py b/tests/test_tutorial/test_query_params_str_validations/test_tutorial014.py
index 7bce7590c..edd40bb1a 100644
--- a/tests/test_tutorial/test_query_params_str_validations/test_tutorial014.py
+++ b/tests/test_tutorial/test_query_params_str_validations/test_tutorial014.py
@@ -1,23 +1,43 @@
+import importlib
+
+import pytest
from fastapi.testclient import TestClient
-from docs_src.query_params_str_validations.tutorial014 import app
+from ...utils import needs_py39, needs_py310
+
+
+@pytest.fixture(
+ name="client",
+ params=[
+ "tutorial014",
+ pytest.param("tutorial014_py310", marks=needs_py310),
+ "tutorial014_an",
+ pytest.param("tutorial014_an_py39", marks=needs_py39),
+ pytest.param("tutorial014_an_py310", marks=needs_py310),
+ ],
+)
+def get_client(request: pytest.FixtureRequest):
+ mod = importlib.import_module(
+ f"docs_src.query_params_str_validations.{request.param}"
+ )
-client = TestClient(app)
+ client = TestClient(mod.app)
+ return client
-def test_hidden_query():
+def test_hidden_query(client: TestClient):
response = client.get("/items?hidden_query=somevalue")
assert response.status_code == 200, response.text
assert response.json() == {"hidden_query": "somevalue"}
-def test_no_hidden_query():
+def test_no_hidden_query(client: TestClient):
response = client.get("/items")
assert response.status_code == 200, response.text
assert response.json() == {"hidden_query": "Not found"}
-def test_openapi_schema():
+def test_openapi_schema(client: TestClient):
response = client.get("/openapi.json")
assert response.status_code == 200, response.text
assert response.json() == {
diff --git a/tests/test_tutorial/test_query_params_str_validations/test_tutorial014_an.py b/tests/test_tutorial/test_query_params_str_validations/test_tutorial014_an.py
deleted file mode 100644
index 2182e87b7..000000000
--- a/tests/test_tutorial/test_query_params_str_validations/test_tutorial014_an.py
+++ /dev/null
@@ -1,81 +0,0 @@
-from fastapi.testclient import TestClient
-
-from docs_src.query_params_str_validations.tutorial014_an import app
-
-client = TestClient(app)
-
-
-def test_hidden_query():
- response = client.get("/items?hidden_query=somevalue")
- assert response.status_code == 200, response.text
- assert response.json() == {"hidden_query": "somevalue"}
-
-
-def test_no_hidden_query():
- response = client.get("/items")
- assert response.status_code == 200, response.text
- assert response.json() == {"hidden_query": "Not found"}
-
-
-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/": {
- "get": {
- "summary": "Read Items",
- "operationId": "read_items_items__get",
- "responses": {
- "200": {
- "description": "Successful Response",
- "content": {"application/json": {"schema": {}}},
- },
- "422": {
- "description": "Validation Error",
- "content": {
- "application/json": {
- "schema": {
- "$ref": "#/components/schemas/HTTPValidationError"
- }
- }
- },
- },
- },
- }
- }
- },
- "components": {
- "schemas": {
- "HTTPValidationError": {
- "title": "HTTPValidationError",
- "type": "object",
- "properties": {
- "detail": {
- "title": "Detail",
- "type": "array",
- "items": {"$ref": "#/components/schemas/ValidationError"},
- }
- },
- },
- "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"},
- },
- },
- }
- },
- }
diff --git a/tests/test_tutorial/test_query_params_str_validations/test_tutorial014_an_py310.py b/tests/test_tutorial/test_query_params_str_validations/test_tutorial014_an_py310.py
deleted file mode 100644
index 344004d01..000000000
--- a/tests/test_tutorial/test_query_params_str_validations/test_tutorial014_an_py310.py
+++ /dev/null
@@ -1,91 +0,0 @@
-import pytest
-from fastapi.testclient import TestClient
-
-from ...utils import needs_py310
-
-
-@pytest.fixture(name="client")
-def get_client():
- from docs_src.query_params_str_validations.tutorial014_an_py310 import app
-
- client = TestClient(app)
- return client
-
-
-@needs_py310
-def test_hidden_query(client: TestClient):
- response = client.get("/items?hidden_query=somevalue")
- assert response.status_code == 200, response.text
- assert response.json() == {"hidden_query": "somevalue"}
-
-
-@needs_py310
-def test_no_hidden_query(client: TestClient):
- response = client.get("/items")
- assert response.status_code == 200, response.text
- assert response.json() == {"hidden_query": "Not found"}
-
-
-@needs_py310
-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/": {
- "get": {
- "summary": "Read Items",
- "operationId": "read_items_items__get",
- "responses": {
- "200": {
- "description": "Successful Response",
- "content": {"application/json": {"schema": {}}},
- },
- "422": {
- "description": "Validation Error",
- "content": {
- "application/json": {
- "schema": {
- "$ref": "#/components/schemas/HTTPValidationError"
- }
- }
- },
- },
- },
- }
- }
- },
- "components": {
- "schemas": {
- "HTTPValidationError": {
- "title": "HTTPValidationError",
- "type": "object",
- "properties": {
- "detail": {
- "title": "Detail",
- "type": "array",
- "items": {"$ref": "#/components/schemas/ValidationError"},
- }
- },
- },
- "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"},
- },
- },
- }
- },
- }
diff --git a/tests/test_tutorial/test_query_params_str_validations/test_tutorial014_an_py39.py b/tests/test_tutorial/test_query_params_str_validations/test_tutorial014_an_py39.py
deleted file mode 100644
index 5d4f6df3d..000000000
--- a/tests/test_tutorial/test_query_params_str_validations/test_tutorial014_an_py39.py
+++ /dev/null
@@ -1,91 +0,0 @@
-import pytest
-from fastapi.testclient import TestClient
-
-from ...utils import needs_py310
-
-
-@pytest.fixture(name="client")
-def get_client():
- from docs_src.query_params_str_validations.tutorial014_an_py39 import app
-
- client = TestClient(app)
- return client
-
-
-@needs_py310
-def test_hidden_query(client: TestClient):
- response = client.get("/items?hidden_query=somevalue")
- assert response.status_code == 200, response.text
- assert response.json() == {"hidden_query": "somevalue"}
-
-
-@needs_py310
-def test_no_hidden_query(client: TestClient):
- response = client.get("/items")
- assert response.status_code == 200, response.text
- assert response.json() == {"hidden_query": "Not found"}
-
-
-@needs_py310
-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/": {
- "get": {
- "summary": "Read Items",
- "operationId": "read_items_items__get",
- "responses": {
- "200": {
- "description": "Successful Response",
- "content": {"application/json": {"schema": {}}},
- },
- "422": {
- "description": "Validation Error",
- "content": {
- "application/json": {
- "schema": {
- "$ref": "#/components/schemas/HTTPValidationError"
- }
- }
- },
- },
- },
- }
- }
- },
- "components": {
- "schemas": {
- "HTTPValidationError": {
- "title": "HTTPValidationError",
- "type": "object",
- "properties": {
- "detail": {
- "title": "Detail",
- "type": "array",
- "items": {"$ref": "#/components/schemas/ValidationError"},
- }
- },
- },
- "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"},
- },
- },
- }
- },
- }
diff --git a/tests/test_tutorial/test_query_params_str_validations/test_tutorial014_py310.py b/tests/test_tutorial/test_query_params_str_validations/test_tutorial014_py310.py
deleted file mode 100644
index dad49fb12..000000000
--- a/tests/test_tutorial/test_query_params_str_validations/test_tutorial014_py310.py
+++ /dev/null
@@ -1,91 +0,0 @@
-import pytest
-from fastapi.testclient import TestClient
-
-from ...utils import needs_py310
-
-
-@pytest.fixture(name="client")
-def get_client():
- from docs_src.query_params_str_validations.tutorial014_py310 import app
-
- client = TestClient(app)
- return client
-
-
-@needs_py310
-def test_hidden_query(client: TestClient):
- response = client.get("/items?hidden_query=somevalue")
- assert response.status_code == 200, response.text
- assert response.json() == {"hidden_query": "somevalue"}
-
-
-@needs_py310
-def test_no_hidden_query(client: TestClient):
- response = client.get("/items")
- assert response.status_code == 200, response.text
- assert response.json() == {"hidden_query": "Not found"}
-
-
-@needs_py310
-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/": {
- "get": {
- "summary": "Read Items",
- "operationId": "read_items_items__get",
- "responses": {
- "200": {
- "description": "Successful Response",
- "content": {"application/json": {"schema": {}}},
- },
- "422": {
- "description": "Validation Error",
- "content": {
- "application/json": {
- "schema": {
- "$ref": "#/components/schemas/HTTPValidationError"
- }
- }
- },
- },
- },
- }
- }
- },
- "components": {
- "schemas": {
- "HTTPValidationError": {
- "title": "HTTPValidationError",
- "type": "object",
- "properties": {
- "detail": {
- "title": "Detail",
- "type": "array",
- "items": {"$ref": "#/components/schemas/ValidationError"},
- }
- },
- },
- "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"},
- },
- },
- }
- },
- }
diff --git a/tests/test_tutorial/test_testing/test_main_b.py b/tests/test_tutorial/test_testing/test_main_b.py
index 1e1836f5b..aa7f969c6 100644
--- a/tests/test_tutorial/test_testing/test_main_b.py
+++ b/tests/test_tutorial/test_testing/test_main_b.py
@@ -1,7 +1,28 @@
-from docs_src.app_testing.app_b import test_main
+import importlib
+from types import ModuleType
+import pytest
-def test_app():
+from ...utils import needs_py39, needs_py310
+
+
+@pytest.fixture(
+ name="test_module",
+ params=[
+ "app_b.test_main",
+ pytest.param("app_b_py310.test_main", marks=needs_py310),
+ "app_b_an.test_main",
+ pytest.param("app_b_an_py39.test_main", marks=needs_py39),
+ pytest.param("app_b_an_py310.test_main", marks=needs_py310),
+ ],
+)
+def get_test_module(request: pytest.FixtureRequest) -> ModuleType:
+ mod: ModuleType = importlib.import_module(f"docs_src.app_testing.{request.param}")
+ return mod
+
+
+def test_app(test_module: ModuleType):
+ test_main = test_module
test_main.test_create_existing_item()
test_main.test_create_item()
test_main.test_create_item_bad_token()
diff --git a/tests/test_tutorial/test_testing/test_main_b_an.py b/tests/test_tutorial/test_testing/test_main_b_an.py
deleted file mode 100644
index e53fc3224..000000000
--- a/tests/test_tutorial/test_testing/test_main_b_an.py
+++ /dev/null
@@ -1,10 +0,0 @@
-from docs_src.app_testing.app_b_an import test_main
-
-
-def test_app():
- test_main.test_create_existing_item()
- test_main.test_create_item()
- test_main.test_create_item_bad_token()
- test_main.test_read_nonexistent_item()
- test_main.test_read_item()
- test_main.test_read_item_bad_token()
diff --git a/tests/test_tutorial/test_testing/test_main_b_an_py310.py b/tests/test_tutorial/test_testing/test_main_b_an_py310.py
deleted file mode 100644
index c974e5dc1..000000000
--- a/tests/test_tutorial/test_testing/test_main_b_an_py310.py
+++ /dev/null
@@ -1,13 +0,0 @@
-from ...utils import needs_py310
-
-
-@needs_py310
-def test_app():
- from docs_src.app_testing.app_b_an_py310 import test_main
-
- test_main.test_create_existing_item()
- test_main.test_create_item()
- test_main.test_create_item_bad_token()
- test_main.test_read_nonexistent_item()
- test_main.test_read_item()
- test_main.test_read_item_bad_token()
diff --git a/tests/test_tutorial/test_testing/test_main_b_an_py39.py b/tests/test_tutorial/test_testing/test_main_b_an_py39.py
deleted file mode 100644
index 71f99726c..000000000
--- a/tests/test_tutorial/test_testing/test_main_b_an_py39.py
+++ /dev/null
@@ -1,13 +0,0 @@
-from ...utils import needs_py39
-
-
-@needs_py39
-def test_app():
- from docs_src.app_testing.app_b_an_py39 import test_main
-
- test_main.test_create_existing_item()
- test_main.test_create_item()
- test_main.test_create_item_bad_token()
- test_main.test_read_nonexistent_item()
- test_main.test_read_item()
- test_main.test_read_item_bad_token()
diff --git a/tests/test_tutorial/test_testing/test_main_b_py310.py b/tests/test_tutorial/test_testing/test_main_b_py310.py
deleted file mode 100644
index e30cdc073..000000000
--- a/tests/test_tutorial/test_testing/test_main_b_py310.py
+++ /dev/null
@@ -1,13 +0,0 @@
-from ...utils import needs_py310
-
-
-@needs_py310
-def test_app():
- from docs_src.app_testing.app_b_py310 import test_main
-
- test_main.test_create_existing_item()
- test_main.test_create_item()
- test_main.test_create_item_bad_token()
- test_main.test_read_nonexistent_item()
- test_main.test_read_item()
- test_main.test_read_item_bad_token()
diff --git a/tests/test_tutorial/test_testing_dependencies/test_tutorial001.py b/tests/test_tutorial/test_testing_dependencies/test_tutorial001.py
index af26307f5..00ee6ab1e 100644
--- a/tests/test_tutorial/test_testing_dependencies/test_tutorial001.py
+++ b/tests/test_tutorial/test_testing_dependencies/test_tutorial001.py
@@ -1,25 +1,48 @@
-from docs_src.dependency_testing.tutorial001 import (
- app,
- client,
- test_override_in_items,
- test_override_in_items_with_params,
- test_override_in_items_with_q,
+import importlib
+from types import ModuleType
+
+import pytest
+
+from ...utils import needs_py39, needs_py310
+
+
+@pytest.fixture(
+ name="test_module",
+ params=[
+ "tutorial001",
+ pytest.param("tutorial001_py310", marks=needs_py310),
+ "tutorial001_an",
+ pytest.param("tutorial001_an_py39", marks=needs_py39),
+ pytest.param("tutorial001_an_py310", marks=needs_py310),
+ ],
)
+def get_test_module(request: pytest.FixtureRequest) -> ModuleType:
+ mod: ModuleType = importlib.import_module(
+ f"docs_src.dependency_testing.{request.param}"
+ )
+ return mod
-def test_override_in_items_run():
+def test_override_in_items_run(test_module: ModuleType):
+ test_override_in_items = test_module.test_override_in_items
+
test_override_in_items()
-def test_override_in_items_with_q_run():
+def test_override_in_items_with_q_run(test_module: ModuleType):
+ test_override_in_items_with_q = test_module.test_override_in_items_with_q
+
test_override_in_items_with_q()
-def test_override_in_items_with_params_run():
+def test_override_in_items_with_params_run(test_module: ModuleType):
+ test_override_in_items_with_params = test_module.test_override_in_items_with_params
+
test_override_in_items_with_params()
-def test_override_in_users():
+def test_override_in_users(test_module: ModuleType):
+ client = test_module.client
response = client.get("/users/")
assert response.status_code == 200, response.text
assert response.json() == {
@@ -28,7 +51,8 @@ def test_override_in_users():
}
-def test_override_in_users_with_q():
+def test_override_in_users_with_q(test_module: ModuleType):
+ client = test_module.client
response = client.get("/users/?q=foo")
assert response.status_code == 200, response.text
assert response.json() == {
@@ -37,7 +61,8 @@ def test_override_in_users_with_q():
}
-def test_override_in_users_with_params():
+def test_override_in_users_with_params(test_module: ModuleType):
+ client = test_module.client
response = client.get("/users/?q=foo&skip=100&limit=200")
assert response.status_code == 200, response.text
assert response.json() == {
@@ -46,7 +71,9 @@ def test_override_in_users_with_params():
}
-def test_normal_app():
+def test_normal_app(test_module: ModuleType):
+ app = test_module.app
+ client = test_module.client
app.dependency_overrides = None
response = client.get("/items/?q=foo&skip=100&limit=200")
assert response.status_code == 200, response.text
diff --git a/tests/test_tutorial/test_testing_dependencies/test_tutorial001_an.py b/tests/test_tutorial/test_testing_dependencies/test_tutorial001_an.py
deleted file mode 100644
index fc1f9149a..000000000
--- a/tests/test_tutorial/test_testing_dependencies/test_tutorial001_an.py
+++ /dev/null
@@ -1,56 +0,0 @@
-from docs_src.dependency_testing.tutorial001_an import (
- app,
- client,
- test_override_in_items,
- test_override_in_items_with_params,
- test_override_in_items_with_q,
-)
-
-
-def test_override_in_items_run():
- test_override_in_items()
-
-
-def test_override_in_items_with_q_run():
- test_override_in_items_with_q()
-
-
-def test_override_in_items_with_params_run():
- test_override_in_items_with_params()
-
-
-def test_override_in_users():
- response = client.get("/users/")
- assert response.status_code == 200, response.text
- assert response.json() == {
- "message": "Hello Users!",
- "params": {"q": None, "skip": 5, "limit": 10},
- }
-
-
-def test_override_in_users_with_q():
- response = client.get("/users/?q=foo")
- assert response.status_code == 200, response.text
- assert response.json() == {
- "message": "Hello Users!",
- "params": {"q": "foo", "skip": 5, "limit": 10},
- }
-
-
-def test_override_in_users_with_params():
- response = client.get("/users/?q=foo&skip=100&limit=200")
- assert response.status_code == 200, response.text
- assert response.json() == {
- "message": "Hello Users!",
- "params": {"q": "foo", "skip": 5, "limit": 10},
- }
-
-
-def test_normal_app():
- app.dependency_overrides = None
- response = client.get("/items/?q=foo&skip=100&limit=200")
- assert response.status_code == 200, response.text
- assert response.json() == {
- "message": "Hello Items!",
- "params": {"q": "foo", "skip": 100, "limit": 200},
- }
diff --git a/tests/test_tutorial/test_testing_dependencies/test_tutorial001_an_py310.py b/tests/test_tutorial/test_testing_dependencies/test_tutorial001_an_py310.py
deleted file mode 100644
index a3d27f47f..000000000
--- a/tests/test_tutorial/test_testing_dependencies/test_tutorial001_an_py310.py
+++ /dev/null
@@ -1,75 +0,0 @@
-from ...utils import needs_py310
-
-
-@needs_py310
-def test_override_in_items_run():
- from docs_src.dependency_testing.tutorial001_an_py310 import test_override_in_items
-
- test_override_in_items()
-
-
-@needs_py310
-def test_override_in_items_with_q_run():
- from docs_src.dependency_testing.tutorial001_an_py310 import (
- test_override_in_items_with_q,
- )
-
- test_override_in_items_with_q()
-
-
-@needs_py310
-def test_override_in_items_with_params_run():
- from docs_src.dependency_testing.tutorial001_an_py310 import (
- test_override_in_items_with_params,
- )
-
- test_override_in_items_with_params()
-
-
-@needs_py310
-def test_override_in_users():
- from docs_src.dependency_testing.tutorial001_an_py310 import client
-
- response = client.get("/users/")
- assert response.status_code == 200, response.text
- assert response.json() == {
- "message": "Hello Users!",
- "params": {"q": None, "skip": 5, "limit": 10},
- }
-
-
-@needs_py310
-def test_override_in_users_with_q():
- from docs_src.dependency_testing.tutorial001_an_py310 import client
-
- response = client.get("/users/?q=foo")
- assert response.status_code == 200, response.text
- assert response.json() == {
- "message": "Hello Users!",
- "params": {"q": "foo", "skip": 5, "limit": 10},
- }
-
-
-@needs_py310
-def test_override_in_users_with_params():
- from docs_src.dependency_testing.tutorial001_an_py310 import client
-
- response = client.get("/users/?q=foo&skip=100&limit=200")
- assert response.status_code == 200, response.text
- assert response.json() == {
- "message": "Hello Users!",
- "params": {"q": "foo", "skip": 5, "limit": 10},
- }
-
-
-@needs_py310
-def test_normal_app():
- from docs_src.dependency_testing.tutorial001_an_py310 import app, client
-
- app.dependency_overrides = None
- response = client.get("/items/?q=foo&skip=100&limit=200")
- assert response.status_code == 200, response.text
- assert response.json() == {
- "message": "Hello Items!",
- "params": {"q": "foo", "skip": 100, "limit": 200},
- }
diff --git a/tests/test_tutorial/test_testing_dependencies/test_tutorial001_an_py39.py b/tests/test_tutorial/test_testing_dependencies/test_tutorial001_an_py39.py
deleted file mode 100644
index f03ed5e07..000000000
--- a/tests/test_tutorial/test_testing_dependencies/test_tutorial001_an_py39.py
+++ /dev/null
@@ -1,75 +0,0 @@
-from ...utils import needs_py39
-
-
-@needs_py39
-def test_override_in_items_run():
- from docs_src.dependency_testing.tutorial001_an_py39 import test_override_in_items
-
- test_override_in_items()
-
-
-@needs_py39
-def test_override_in_items_with_q_run():
- from docs_src.dependency_testing.tutorial001_an_py39 import (
- test_override_in_items_with_q,
- )
-
- test_override_in_items_with_q()
-
-
-@needs_py39
-def test_override_in_items_with_params_run():
- from docs_src.dependency_testing.tutorial001_an_py39 import (
- test_override_in_items_with_params,
- )
-
- test_override_in_items_with_params()
-
-
-@needs_py39
-def test_override_in_users():
- from docs_src.dependency_testing.tutorial001_an_py39 import client
-
- response = client.get("/users/")
- assert response.status_code == 200, response.text
- assert response.json() == {
- "message": "Hello Users!",
- "params": {"q": None, "skip": 5, "limit": 10},
- }
-
-
-@needs_py39
-def test_override_in_users_with_q():
- from docs_src.dependency_testing.tutorial001_an_py39 import client
-
- response = client.get("/users/?q=foo")
- assert response.status_code == 200, response.text
- assert response.json() == {
- "message": "Hello Users!",
- "params": {"q": "foo", "skip": 5, "limit": 10},
- }
-
-
-@needs_py39
-def test_override_in_users_with_params():
- from docs_src.dependency_testing.tutorial001_an_py39 import client
-
- response = client.get("/users/?q=foo&skip=100&limit=200")
- assert response.status_code == 200, response.text
- assert response.json() == {
- "message": "Hello Users!",
- "params": {"q": "foo", "skip": 5, "limit": 10},
- }
-
-
-@needs_py39
-def test_normal_app():
- from docs_src.dependency_testing.tutorial001_an_py39 import app, client
-
- app.dependency_overrides = None
- response = client.get("/items/?q=foo&skip=100&limit=200")
- assert response.status_code == 200, response.text
- assert response.json() == {
- "message": "Hello Items!",
- "params": {"q": "foo", "skip": 100, "limit": 200},
- }
diff --git a/tests/test_tutorial/test_testing_dependencies/test_tutorial001_py310.py b/tests/test_tutorial/test_testing_dependencies/test_tutorial001_py310.py
deleted file mode 100644
index 776b916ff..000000000
--- a/tests/test_tutorial/test_testing_dependencies/test_tutorial001_py310.py
+++ /dev/null
@@ -1,75 +0,0 @@
-from ...utils import needs_py310
-
-
-@needs_py310
-def test_override_in_items_run():
- from docs_src.dependency_testing.tutorial001_py310 import test_override_in_items
-
- test_override_in_items()
-
-
-@needs_py310
-def test_override_in_items_with_q_run():
- from docs_src.dependency_testing.tutorial001_py310 import (
- test_override_in_items_with_q,
- )
-
- test_override_in_items_with_q()
-
-
-@needs_py310
-def test_override_in_items_with_params_run():
- from docs_src.dependency_testing.tutorial001_py310 import (
- test_override_in_items_with_params,
- )
-
- test_override_in_items_with_params()
-
-
-@needs_py310
-def test_override_in_users():
- from docs_src.dependency_testing.tutorial001_py310 import client
-
- response = client.get("/users/")
- assert response.status_code == 200, response.text
- assert response.json() == {
- "message": "Hello Users!",
- "params": {"q": None, "skip": 5, "limit": 10},
- }
-
-
-@needs_py310
-def test_override_in_users_with_q():
- from docs_src.dependency_testing.tutorial001_py310 import client
-
- response = client.get("/users/?q=foo")
- assert response.status_code == 200, response.text
- assert response.json() == {
- "message": "Hello Users!",
- "params": {"q": "foo", "skip": 5, "limit": 10},
- }
-
-
-@needs_py310
-def test_override_in_users_with_params():
- from docs_src.dependency_testing.tutorial001_py310 import client
-
- response = client.get("/users/?q=foo&skip=100&limit=200")
- assert response.status_code == 200, response.text
- assert response.json() == {
- "message": "Hello Users!",
- "params": {"q": "foo", "skip": 5, "limit": 10},
- }
-
-
-@needs_py310
-def test_normal_app():
- from docs_src.dependency_testing.tutorial001_py310 import app, client
-
- app.dependency_overrides = None
- response = client.get("/items/?q=foo&skip=100&limit=200")
- assert response.status_code == 200, response.text
- assert response.json() == {
- "message": "Hello Items!",
- "params": {"q": "foo", "skip": 100, "limit": 200},
- }