diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml
index cc906eaf6d..eb2b6b64ee 100644
--- a/.github/workflows/test.yml
+++ b/.github/workflows/test.yml
@@ -44,35 +44,22 @@ jobs:
matrix:
os: [ windows-latest, macos-latest ]
python-version: [ "3.14" ]
- pydantic-version: [ "pydantic>=2.0.2,<3.0.0" ]
include:
- os: ubuntu-latest
python-version: "3.9"
- pydantic-version: "pydantic>=1.10.0,<2.0.0"
coverage: coverage
- os: macos-latest
python-version: "3.10"
- pydantic-version: "pydantic>=2.0.2,<3.0.0"
- - os: windows-latest
- python-version: "3.11"
- pydantic-version: "pydantic>=1.10.0,<2.0.0"
- - os: ubuntu-latest
- python-version: "3.12"
- pydantic-version: "pydantic>=2.0.2,<3.0.0"
- - os: macos-latest
- python-version: "3.13"
- pydantic-version: "pydantic>=1.10.0,<2.0.0"
- - os: windows-latest
- python-version: "3.13"
- pydantic-version: "pydantic>=2.0.2,<3.0.0"
coverage: coverage
+ - os: windows-latest
+ python-version: "3.12"
+ coverage: coverage
+ # Ubuntu with 3.13 needs coverage for CodSpeed benchmarks
- os: ubuntu-latest
python-version: "3.13"
- pydantic-version: "pydantic>=2.0.2,<3.0.0"
coverage: coverage
- os: ubuntu-latest
python-version: "3.14"
- pydantic-version: "pydantic>=2.0.2,<3.0.0"
coverage: coverage
fail-fast: false
runs-on: ${{ matrix.os }}
@@ -96,8 +83,6 @@ jobs:
pyproject.toml
- name: Install Dependencies
run: uv pip install -r requirements-tests.txt
- - name: Install Pydantic
- run: uv pip install "${{ matrix.pydantic-version }}"
- run: mkdir coverage
- name: Test
run: bash scripts/test.sh
@@ -105,7 +90,7 @@ jobs:
COVERAGE_FILE: coverage/.coverage.${{ runner.os }}-py${{ matrix.python-version }}
CONTEXT: ${{ runner.os }}-py${{ matrix.python-version }}
- name: CodSpeed benchmarks
- if: matrix.os == 'ubuntu-latest' && matrix.python-version == '3.13' && matrix.pydantic-version == 'pydantic>=2.0.2,<3.0.0'
+ if: matrix.os == 'ubuntu-latest' && matrix.python-version == '3.13'
uses: CodSpeedHQ/action@v4
env:
COVERAGE_FILE: coverage/.coverage.${{ runner.os }}-py${{ matrix.python-version }}
diff --git a/docs/en/docs/advanced/path-operation-advanced-configuration.md b/docs/en/docs/advanced/path-operation-advanced-configuration.md
index 01196af79e..e0e3c96a0e 100644
--- a/docs/en/docs/advanced/path-operation-advanced-configuration.md
+++ b/docs/en/docs/advanced/path-operation-advanced-configuration.md
@@ -153,48 +153,16 @@ And you could do this even if the data type in the request is not JSON.
For example, in this application we don't use FastAPI's integrated functionality to extract the JSON Schema from Pydantic models nor the automatic validation for JSON. In fact, we are declaring the request content type as YAML, not JSON:
-//// tab | Pydantic v2
-
{* ../../docs_src/path_operation_advanced_configuration/tutorial007_py39.py hl[15:20, 22] *}
-////
-
-//// tab | Pydantic v1
-
-{* ../../docs_src/path_operation_advanced_configuration/tutorial007_pv1_py39.py hl[15:20, 22] *}
-
-////
-
-/// info
-
-In Pydantic version 1 the method to get the JSON Schema for a model was called `Item.schema()`, in Pydantic version 2, the method is called `Item.model_json_schema()`.
-
-///
-
Nevertheless, although we are not using the default integrated functionality, we are still using a Pydantic model to manually generate the JSON Schema for the data that we want to receive in YAML.
Then we use the request directly, and extract the body as `bytes`. This means that FastAPI won't even try to parse the request payload as JSON.
And then in our code, we parse that YAML content directly, and then we are again using the same Pydantic model to validate the YAML content:
-//// tab | Pydantic v2
-
{* ../../docs_src/path_operation_advanced_configuration/tutorial007_py39.py hl[24:31] *}
-////
-
-//// tab | Pydantic v1
-
-{* ../../docs_src/path_operation_advanced_configuration/tutorial007_pv1_py39.py hl[24:31] *}
-
-////
-
-/// info
-
-In Pydantic version 1 the method to parse and validate an object was `Item.parse_obj()`, in Pydantic version 2, the method is called `Item.model_validate()`.
-
-///
-
/// tip
Here we reuse the same Pydantic model.
diff --git a/docs/en/docs/advanced/settings.md b/docs/en/docs/advanced/settings.md
index 268983f1ef..cded9b80b8 100644
--- a/docs/en/docs/advanced/settings.md
+++ b/docs/en/docs/advanced/settings.md
@@ -46,12 +46,6 @@ $ pip install "fastapi[all]"
-/// info
-
-In Pydantic v1 it came included with the main package. Now it is distributed as this independent package so that you can choose to install it or not if you don't need that functionality.
-
-///
-
### Create the `Settings` object { #create-the-settings-object }
Import `BaseSettings` from Pydantic and create a sub-class, very much like with a Pydantic model.
@@ -60,24 +54,8 @@ The same way as with Pydantic models, you declare class attributes with type ann
You can use all the same validation features and tools you use for Pydantic models, like different data types and additional validations with `Field()`.
-//// tab | Pydantic v2
-
{* ../../docs_src/settings/tutorial001_py39.py hl[2,5:8,11] *}
-////
-
-//// tab | Pydantic v1
-
-/// info
-
-In Pydantic v1 you would import `BaseSettings` directly from `pydantic` instead of from `pydantic_settings`.
-
-///
-
-{* ../../docs_src/settings/tutorial001_pv1_py39.py hl[2,5:8,11] *}
-
-////
-
/// tip
If you want something quick to copy and paste, don't use this example, use the last one below.
@@ -215,8 +193,6 @@ APP_NAME="ChimichangApp"
And then update your `config.py` with:
-//// tab | Pydantic v2
-
{* ../../docs_src/settings/app03_an_py39/config.py hl[9] *}
/// tip
@@ -225,26 +201,6 @@ The `model_config` attribute is used just for Pydantic configuration. You can re
///
-////
-
-//// tab | Pydantic v1
-
-{* ../../docs_src/settings/app03_an_py39/config_pv1.py hl[9:10] *}
-
-/// tip
-
-The `Config` class is used just for Pydantic configuration. You can read more at Pydantic Model Config.
-
-///
-
-////
-
-/// info
-
-In Pydantic version 1 the configuration was done in an internal class `Config`, in Pydantic version 2 it's done in an attribute `model_config`. This attribute takes a `dict`, and to get autocompletion and inline errors you can import and use `SettingsConfigDict` to define that `dict`.
-
-///
-
Here we define the config `env_file` inside of your Pydantic `Settings` class, and set the value to the filename with the dotenv file we want to use.
### Creating the `Settings` only once with `lru_cache` { #creating-the-settings-only-once-with-lru-cache }
diff --git a/docs/en/docs/how-to/migrate-from-pydantic-v1-to-pydantic-v2.md b/docs/en/docs/how-to/migrate-from-pydantic-v1-to-pydantic-v2.md
index e85d122be8..fc90220b89 100644
--- a/docs/en/docs/how-to/migrate-from-pydantic-v1-to-pydantic-v2.md
+++ b/docs/en/docs/how-to/migrate-from-pydantic-v1-to-pydantic-v2.md
@@ -2,21 +2,23 @@
If you have an old FastAPI app, you might be using Pydantic version 1.
-FastAPI has had support for either Pydantic v1 or v2 since version 0.100.0.
+FastAPI version 0.100.0 had support for either Pydantic v1 or v2. It would use whichever you had installed.
-If you had installed Pydantic v2, it would use it. If instead you had Pydantic v1, it would use that.
+FastAPI version 0.119.0 introduced partial support for Pydantic v1 from inside of Pydantic v2 (as `pydantic.v1`), to facilitate the migration to v2.
-Pydantic v1 is now deprecated and support for it will be removed in the next versions of FastAPI, you should **migrate to Pydantic v2**. This way you will get the latest features, improvements, and fixes.
+FastAPI 0.126.0 dropped support for Pydantic v1, while still supporting `pydantic.v1` for a little while.
/// warning
-Also, the Pydantic team stopped support for Pydantic v1 for the latest versions of Python, starting with **Python 3.14**.
+The Pydantic team stopped support for Pydantic v1 for the latest versions of Python, starting with **Python 3.14**.
+
+This includes `pydantic.v1`, which is no longer supported in Python 3.14 and above.
If you want to use the latest features of Python, you will need to make sure you use Pydantic v2.
///
-If you have an old FastAPI app with Pydantic v1, here I'll show you how to migrate it to Pydantic v2, and the **new features in FastAPI 0.119.0** to help you with a gradual migration.
+If you have an old FastAPI app with Pydantic v1, here I'll show you how to migrate it to Pydantic v2, and the **features in FastAPI 0.119.0** to help you with a gradual migration.
## Official Guide { #official-guide }
@@ -44,7 +46,7 @@ After this, you can run the tests and check if everything works. If it does, you
## Pydantic v1 in v2 { #pydantic-v1-in-v2 }
-Pydantic v2 includes everything from Pydantic v1 as a submodule `pydantic.v1`.
+Pydantic v2 includes everything from Pydantic v1 as a submodule `pydantic.v1`. But this is no longer supported in versions above Python 3.13.
This means that you can install the latest version of Pydantic v2 and import and use the old Pydantic v1 components from this submodule, as if you had the old Pydantic v1 installed.
diff --git a/docs/en/docs/how-to/separate-openapi-schemas.md b/docs/en/docs/how-to/separate-openapi-schemas.md
index 3c78a56d36..d790c600bb 100644
--- a/docs/en/docs/how-to/separate-openapi-schemas.md
+++ b/docs/en/docs/how-to/separate-openapi-schemas.md
@@ -1,6 +1,6 @@
# Separate OpenAPI Schemas for Input and Output or Not { #separate-openapi-schemas-for-input-and-output-or-not }
-When using **Pydantic v2**, the generated OpenAPI is a bit more exact and **correct** than before. 😎
+Since **Pydantic v2** was released, the generated OpenAPI is a bit more exact and **correct** than before. 😎
In fact, in some cases, it will even have **two JSON Schemas** in OpenAPI for the same Pydantic model, for input and output, depending on if they have **default values**.
@@ -100,5 +100,3 @@ And now there will be one single schema for input and output for the model, only
-
-This is the same behavior as in Pydantic v1. 🤓
diff --git a/docs/en/docs/tutorial/body-updates.md b/docs/en/docs/tutorial/body-updates.md
index baeb53ec6f..1b7fd70661 100644
--- a/docs/en/docs/tutorial/body-updates.md
+++ b/docs/en/docs/tutorial/body-updates.md
@@ -50,14 +50,6 @@ If you want to receive partial updates, it's very useful to use the parameter `e
Like `item.model_dump(exclude_unset=True)`.
-/// info
-
-In Pydantic v1 the method was called `.dict()`, it was deprecated (but still supported) in Pydantic v2, and renamed to `.model_dump()`.
-
-The examples here use `.dict()` for compatibility with Pydantic v1, but you should use `.model_dump()` instead if you can use Pydantic v2.
-
-///
-
That would generate a `dict` with only the data that was set when creating the `item` model, excluding default values.
Then you can use this to generate a `dict` with only the data that was set (sent in the request), omitting default values:
@@ -68,14 +60,6 @@ Then you can use this to generate a `dict` with only the data that was set (sent
Now, you can create a copy of the existing model using `.model_copy()`, and pass the `update` parameter with a `dict` containing the data to update.
-/// info
-
-In Pydantic v1 the method was called `.copy()`, it was deprecated (but still supported) in Pydantic v2, and renamed to `.model_copy()`.
-
-The examples here use `.copy()` for compatibility with Pydantic v1, but you should use `.model_copy()` instead if you can use Pydantic v2.
-
-///
-
Like `stored_item_model.model_copy(update=update_data)`:
{* ../../docs_src/body_updates/tutorial002_py310.py hl[33] *}
diff --git a/docs/en/docs/tutorial/body.md b/docs/en/docs/tutorial/body.md
index 25087b8406..2d0dfcbb59 100644
--- a/docs/en/docs/tutorial/body.md
+++ b/docs/en/docs/tutorial/body.md
@@ -128,14 +128,6 @@ Inside of the function, you can access all the attributes of the model object di
{* ../../docs_src/body/tutorial002_py310.py *}
-/// info
-
-In Pydantic v1 the method was called `.dict()`, it was deprecated (but still supported) in Pydantic v2, and renamed to `.model_dump()`.
-
-The examples here use `.dict()` for compatibility with Pydantic v1, but you should use `.model_dump()` instead if you can use Pydantic v2.
-
-///
-
## Request body + path parameters { #request-body-path-parameters }
You can declare path parameters and request body at the same time.
diff --git a/docs/en/docs/tutorial/extra-models.md b/docs/en/docs/tutorial/extra-models.md
index 7079bf73da..d82df561fa 100644
--- a/docs/en/docs/tutorial/extra-models.md
+++ b/docs/en/docs/tutorial/extra-models.md
@@ -22,22 +22,13 @@ Here's a general idea of how the models could look like with their password fiel
{* ../../docs_src/extra_models/tutorial001_py310.py hl[7,9,14,20,22,27:28,31:33,38:39] *}
+### About `**user_in.model_dump()` { #about-user-in-model-dump }
-/// info
-
-In Pydantic v1 the method was called `.dict()`, it was deprecated (but still supported) in Pydantic v2, and renamed to `.model_dump()`.
-
-The examples here use `.dict()` for compatibility with Pydantic v1, but you should use `.model_dump()` instead if you can use Pydantic v2.
-
-///
-
-### About `**user_in.dict()` { #about-user-in-dict }
-
-#### Pydantic's `.dict()` { #pydantics-dict }
+#### Pydantic's `.model_dump()` { #pydantics-model-dump }
`user_in` is a Pydantic model of class `UserIn`.
-Pydantic models have a `.dict()` method that returns a `dict` with the model's data.
+Pydantic models have a `.model_dump()` method that returns a `dict` with the model's data.
So, if we create a Pydantic object `user_in` like:
@@ -48,7 +39,7 @@ user_in = UserIn(username="john", password="secret", email="john.doe@example.com
and then we call:
```Python
-user_dict = user_in.dict()
+user_dict = user_in.model_dump()
```
we now have a `dict` with the data in the variable `user_dict` (it's a `dict` instead of a Pydantic model object).
@@ -104,20 +95,20 @@ UserInDB(
#### A Pydantic model from the contents of another { #a-pydantic-model-from-the-contents-of-another }
-As in the example above we got `user_dict` from `user_in.dict()`, this code:
+As in the example above we got `user_dict` from `user_in.model_dump()`, this code:
```Python
-user_dict = user_in.dict()
+user_dict = user_in.model_dump()
UserInDB(**user_dict)
```
would be equivalent to:
```Python
-UserInDB(**user_in.dict())
+UserInDB(**user_in.model_dump())
```
-...because `user_in.dict()` is a `dict`, and then we make Python "unpack" it by passing it to `UserInDB` prefixed with `**`.
+...because `user_in.model_dump()` is a `dict`, and then we make Python "unpack" it by passing it to `UserInDB` prefixed with `**`.
So, we get a Pydantic model from the data in another Pydantic model.
@@ -126,7 +117,7 @@ So, we get a Pydantic model from the data in another Pydantic model.
And then adding the extra keyword argument `hashed_password=hashed_password`, like in:
```Python
-UserInDB(**user_in.dict(), hashed_password=hashed_password)
+UserInDB(**user_in.model_dump(), hashed_password=hashed_password)
```
...ends up being like:
@@ -181,7 +172,6 @@ When defining a its `exclude_unset` parameter to achieve this.
-
-///
-
-/// info
-
You can also use:
* `response_model_exclude_defaults=True`
diff --git a/docs/en/docs/tutorial/schema-extra-example.md b/docs/en/docs/tutorial/schema-extra-example.md
index f3ddaf3697..daaea73c87 100644
--- a/docs/en/docs/tutorial/schema-extra-example.md
+++ b/docs/en/docs/tutorial/schema-extra-example.md
@@ -8,36 +8,14 @@ Here are several ways to do it.
You can declare `examples` for a Pydantic model that will be added to the generated JSON Schema.
-//// tab | Pydantic v2
-
{* ../../docs_src/schema_extra_example/tutorial001_py310.py hl[13:24] *}
-////
-
-//// tab | Pydantic v1
-
-{* ../../docs_src/schema_extra_example/tutorial001_pv1_py310.py hl[13:23] *}
-
-////
-
That extra info will be added as-is to the output **JSON Schema** for that model, and it will be used in the API docs.
-//// tab | Pydantic v2
-
-In Pydantic version 2, you would use the attribute `model_config`, that takes a `dict` as described in Pydantic's docs: Configuration.
+You can use the attribute `model_config` that takes a `dict` as described in Pydantic's docs: Configuration.
You can set `"json_schema_extra"` with a `dict` containing any additional data you would like to show up in the generated JSON Schema, including `examples`.
-////
-
-//// tab | Pydantic v1
-
-In Pydantic version 1, you would use an internal class `Config` and `schema_extra`, as described in Pydantic's docs: Schema customization.
-
-You can set `schema_extra` with a `dict` containing any additional data you would like to show up in the generated JSON Schema, including `examples`.
-
-////
-
/// tip
You could use the same technique to extend the JSON Schema and add your own custom extra info.
diff --git a/docs_src/body/tutorial002_py310.py b/docs_src/body/tutorial002_py310.py
index 454c45c886..a829a4dc9d 100644
--- a/docs_src/body/tutorial002_py310.py
+++ b/docs_src/body/tutorial002_py310.py
@@ -14,7 +14,7 @@ app = FastAPI()
@app.post("/items/")
async def create_item(item: Item):
- item_dict = item.dict()
+ item_dict = item.model_dump()
if item.tax is not None:
price_with_tax = item.price + item.tax
item_dict.update({"price_with_tax": price_with_tax})
diff --git a/docs_src/body/tutorial002_py39.py b/docs_src/body/tutorial002_py39.py
index 5cd86216b3..fb212e8e79 100644
--- a/docs_src/body/tutorial002_py39.py
+++ b/docs_src/body/tutorial002_py39.py
@@ -16,7 +16,7 @@ app = FastAPI()
@app.post("/items/")
async def create_item(item: Item):
- item_dict = item.dict()
+ item_dict = item.model_dump()
if item.tax is not None:
price_with_tax = item.price + item.tax
item_dict.update({"price_with_tax": price_with_tax})
diff --git a/docs_src/body/tutorial003_py310.py b/docs_src/body/tutorial003_py310.py
index 440b210e6b..51ac8aafac 100644
--- a/docs_src/body/tutorial003_py310.py
+++ b/docs_src/body/tutorial003_py310.py
@@ -14,4 +14,4 @@ app = FastAPI()
@app.put("/items/{item_id}")
async def update_item(item_id: int, item: Item):
- return {"item_id": item_id, **item.dict()}
+ return {"item_id": item_id, **item.model_dump()}
diff --git a/docs_src/body/tutorial003_py39.py b/docs_src/body/tutorial003_py39.py
index 2f33cc0389..636ba2275a 100644
--- a/docs_src/body/tutorial003_py39.py
+++ b/docs_src/body/tutorial003_py39.py
@@ -16,4 +16,4 @@ app = FastAPI()
@app.put("/items/{item_id}")
async def update_item(item_id: int, item: Item):
- return {"item_id": item_id, **item.dict()}
+ return {"item_id": item_id, **item.model_dump()}
diff --git a/docs_src/body/tutorial004_py310.py b/docs_src/body/tutorial004_py310.py
index b352b70ab6..53b10d97b6 100644
--- a/docs_src/body/tutorial004_py310.py
+++ b/docs_src/body/tutorial004_py310.py
@@ -14,7 +14,7 @@ app = FastAPI()
@app.put("/items/{item_id}")
async def update_item(item_id: int, item: Item, q: str | None = None):
- result = {"item_id": item_id, **item.dict()}
+ result = {"item_id": item_id, **item.model_dump()}
if q:
result.update({"q": q})
return result
diff --git a/docs_src/body/tutorial004_py39.py b/docs_src/body/tutorial004_py39.py
index 0671e0a278..2c157abfa1 100644
--- a/docs_src/body/tutorial004_py39.py
+++ b/docs_src/body/tutorial004_py39.py
@@ -16,7 +16,7 @@ app = FastAPI()
@app.put("/items/{item_id}")
async def update_item(item_id: int, item: Item, q: Union[str, None] = None):
- result = {"item_id": item_id, **item.dict()}
+ result = {"item_id": item_id, **item.model_dump()}
if q:
result.update({"q": q})
return result
diff --git a/docs_src/body_updates/tutorial002_py310.py b/docs_src/body_updates/tutorial002_py310.py
index 3498414966..e5db711108 100644
--- a/docs_src/body_updates/tutorial002_py310.py
+++ b/docs_src/body_updates/tutorial002_py310.py
@@ -29,7 +29,7 @@ async def read_item(item_id: str):
async def update_item(item_id: str, item: Item):
stored_item_data = items[item_id]
stored_item_model = Item(**stored_item_data)
- update_data = item.dict(exclude_unset=True)
- updated_item = stored_item_model.copy(update=update_data)
+ update_data = item.model_dump(exclude_unset=True)
+ updated_item = stored_item_model.model_copy(update=update_data)
items[item_id] = jsonable_encoder(updated_item)
return updated_item
diff --git a/docs_src/body_updates/tutorial002_py39.py b/docs_src/body_updates/tutorial002_py39.py
index eb35b35215..eddd7af716 100644
--- a/docs_src/body_updates/tutorial002_py39.py
+++ b/docs_src/body_updates/tutorial002_py39.py
@@ -31,7 +31,7 @@ async def read_item(item_id: str):
async def update_item(item_id: str, item: Item):
stored_item_data = items[item_id]
stored_item_model = Item(**stored_item_data)
- update_data = item.dict(exclude_unset=True)
- updated_item = stored_item_model.copy(update=update_data)
+ update_data = item.model_dump(exclude_unset=True)
+ updated_item = stored_item_model.model_copy(update=update_data)
items[item_id] = jsonable_encoder(updated_item)
return updated_item
diff --git a/docs_src/cookie_param_models/tutorial002_pv1_an_py310.py b/docs_src/cookie_param_models/tutorial002_pv1_an_py310.py
deleted file mode 100644
index ac00360b60..0000000000
--- a/docs_src/cookie_param_models/tutorial002_pv1_an_py310.py
+++ /dev/null
@@ -1,20 +0,0 @@
-from typing import Annotated
-
-from fastapi import Cookie, FastAPI
-from pydantic import BaseModel
-
-app = FastAPI()
-
-
-class Cookies(BaseModel):
- class Config:
- extra = "forbid"
-
- session_id: str
- fatebook_tracker: str | None = None
- googall_tracker: str | None = None
-
-
-@app.get("/items/")
-async def read_items(cookies: Annotated[Cookies, Cookie()]):
- return cookies
diff --git a/docs_src/cookie_param_models/tutorial002_pv1_an_py39.py b/docs_src/cookie_param_models/tutorial002_pv1_an_py39.py
deleted file mode 100644
index 573caea4b1..0000000000
--- a/docs_src/cookie_param_models/tutorial002_pv1_an_py39.py
+++ /dev/null
@@ -1,20 +0,0 @@
-from typing import Annotated, Union
-
-from fastapi import Cookie, FastAPI
-from pydantic import BaseModel
-
-app = FastAPI()
-
-
-class Cookies(BaseModel):
- class Config:
- extra = "forbid"
-
- session_id: str
- fatebook_tracker: Union[str, None] = None
- googall_tracker: Union[str, None] = None
-
-
-@app.get("/items/")
-async def read_items(cookies: Annotated[Cookies, Cookie()]):
- return cookies
diff --git a/docs_src/cookie_param_models/tutorial002_pv1_py310.py b/docs_src/cookie_param_models/tutorial002_pv1_py310.py
deleted file mode 100644
index 2c59aad123..0000000000
--- a/docs_src/cookie_param_models/tutorial002_pv1_py310.py
+++ /dev/null
@@ -1,18 +0,0 @@
-from fastapi import Cookie, FastAPI
-from pydantic import BaseModel
-
-app = FastAPI()
-
-
-class Cookies(BaseModel):
- class Config:
- extra = "forbid"
-
- session_id: str
- fatebook_tracker: str | None = None
- googall_tracker: str | None = None
-
-
-@app.get("/items/")
-async def read_items(cookies: Cookies = Cookie()):
- return cookies
diff --git a/docs_src/cookie_param_models/tutorial002_pv1_py39.py b/docs_src/cookie_param_models/tutorial002_pv1_py39.py
deleted file mode 100644
index 13f78b850e..0000000000
--- a/docs_src/cookie_param_models/tutorial002_pv1_py39.py
+++ /dev/null
@@ -1,20 +0,0 @@
-from typing import Union
-
-from fastapi import Cookie, FastAPI
-from pydantic import BaseModel
-
-app = FastAPI()
-
-
-class Cookies(BaseModel):
- class Config:
- extra = "forbid"
-
- session_id: str
- fatebook_tracker: Union[str, None] = None
- googall_tracker: Union[str, None] = None
-
-
-@app.get("/items/")
-async def read_items(cookies: Cookies = Cookie()):
- return cookies
diff --git a/docs_src/extra_models/tutorial001_py310.py b/docs_src/extra_models/tutorial001_py310.py
index 669386ae6e..cf39142e4a 100644
--- a/docs_src/extra_models/tutorial001_py310.py
+++ b/docs_src/extra_models/tutorial001_py310.py
@@ -30,7 +30,7 @@ def fake_password_hasher(raw_password: str):
def fake_save_user(user_in: UserIn):
hashed_password = fake_password_hasher(user_in.password)
- user_in_db = UserInDB(**user_in.dict(), hashed_password=hashed_password)
+ user_in_db = UserInDB(**user_in.model_dump(), hashed_password=hashed_password)
print("User saved! ..not really")
return user_in_db
diff --git a/docs_src/extra_models/tutorial001_py39.py b/docs_src/extra_models/tutorial001_py39.py
index 4be56cd2a7..327ffcdf09 100644
--- a/docs_src/extra_models/tutorial001_py39.py
+++ b/docs_src/extra_models/tutorial001_py39.py
@@ -32,7 +32,7 @@ def fake_password_hasher(raw_password: str):
def fake_save_user(user_in: UserIn):
hashed_password = fake_password_hasher(user_in.password)
- user_in_db = UserInDB(**user_in.dict(), hashed_password=hashed_password)
+ user_in_db = UserInDB(**user_in.model_dump(), hashed_password=hashed_password)
print("User saved! ..not really")
return user_in_db
diff --git a/docs_src/extra_models/tutorial002_py310.py b/docs_src/extra_models/tutorial002_py310.py
index 5b8ed7de3d..e8a4f5f29b 100644
--- a/docs_src/extra_models/tutorial002_py310.py
+++ b/docs_src/extra_models/tutorial002_py310.py
@@ -28,7 +28,7 @@ def fake_password_hasher(raw_password: str):
def fake_save_user(user_in: UserIn):
hashed_password = fake_password_hasher(user_in.password)
- user_in_db = UserInDB(**user_in.dict(), hashed_password=hashed_password)
+ user_in_db = UserInDB(**user_in.model_dump(), hashed_password=hashed_password)
print("User saved! ..not really")
return user_in_db
diff --git a/docs_src/extra_models/tutorial002_py39.py b/docs_src/extra_models/tutorial002_py39.py
index 70fa16441d..6543796015 100644
--- a/docs_src/extra_models/tutorial002_py39.py
+++ b/docs_src/extra_models/tutorial002_py39.py
@@ -30,7 +30,7 @@ def fake_password_hasher(raw_password: str):
def fake_save_user(user_in: UserIn):
hashed_password = fake_password_hasher(user_in.password)
- user_in_db = UserInDB(**user_in.dict(), hashed_password=hashed_password)
+ user_in_db = UserInDB(**user_in.model_dump(), hashed_password=hashed_password)
print("User saved! ..not really")
return user_in_db
diff --git a/docs_src/header_param_models/tutorial002_pv1_an_py310.py b/docs_src/header_param_models/tutorial002_pv1_an_py310.py
deleted file mode 100644
index e99e24ea55..0000000000
--- a/docs_src/header_param_models/tutorial002_pv1_an_py310.py
+++ /dev/null
@@ -1,22 +0,0 @@
-from typing import Annotated
-
-from fastapi import FastAPI, Header
-from pydantic import BaseModel
-
-app = FastAPI()
-
-
-class CommonHeaders(BaseModel):
- class Config:
- extra = "forbid"
-
- host: str
- save_data: bool
- if_modified_since: str | None = None
- traceparent: str | None = None
- x_tag: list[str] = []
-
-
-@app.get("/items/")
-async def read_items(headers: Annotated[CommonHeaders, Header()]):
- return headers
diff --git a/docs_src/header_param_models/tutorial002_pv1_an_py39.py b/docs_src/header_param_models/tutorial002_pv1_an_py39.py
deleted file mode 100644
index 18398b726c..0000000000
--- a/docs_src/header_param_models/tutorial002_pv1_an_py39.py
+++ /dev/null
@@ -1,22 +0,0 @@
-from typing import Annotated, Union
-
-from fastapi import FastAPI, Header
-from pydantic import BaseModel
-
-app = FastAPI()
-
-
-class CommonHeaders(BaseModel):
- class Config:
- extra = "forbid"
-
- host: str
- save_data: bool
- if_modified_since: Union[str, None] = None
- traceparent: Union[str, None] = None
- x_tag: list[str] = []
-
-
-@app.get("/items/")
-async def read_items(headers: Annotated[CommonHeaders, Header()]):
- return headers
diff --git a/docs_src/header_param_models/tutorial002_pv1_py310.py b/docs_src/header_param_models/tutorial002_pv1_py310.py
deleted file mode 100644
index 3dbff9d7bf..0000000000
--- a/docs_src/header_param_models/tutorial002_pv1_py310.py
+++ /dev/null
@@ -1,20 +0,0 @@
-from fastapi import FastAPI, Header
-from pydantic import BaseModel
-
-app = FastAPI()
-
-
-class CommonHeaders(BaseModel):
- class Config:
- extra = "forbid"
-
- host: str
- save_data: bool
- if_modified_since: str | None = None
- traceparent: str | None = None
- x_tag: list[str] = []
-
-
-@app.get("/items/")
-async def read_items(headers: CommonHeaders = Header()):
- return headers
diff --git a/docs_src/header_param_models/tutorial002_pv1_py39.py b/docs_src/header_param_models/tutorial002_pv1_py39.py
deleted file mode 100644
index 86e19be0d1..0000000000
--- a/docs_src/header_param_models/tutorial002_pv1_py39.py
+++ /dev/null
@@ -1,22 +0,0 @@
-from typing import Union
-
-from fastapi import FastAPI, Header
-from pydantic import BaseModel
-
-app = FastAPI()
-
-
-class CommonHeaders(BaseModel):
- class Config:
- extra = "forbid"
-
- host: str
- save_data: bool
- if_modified_since: Union[str, None] = None
- traceparent: Union[str, None] = None
- x_tag: list[str] = []
-
-
-@app.get("/items/")
-async def read_items(headers: CommonHeaders = Header()):
- return headers
diff --git a/docs_src/path_operation_advanced_configuration/tutorial007_pv1_py39.py b/docs_src/path_operation_advanced_configuration/tutorial007_pv1_py39.py
index 831966553f..849f648e12 100644
--- a/docs_src/path_operation_advanced_configuration/tutorial007_pv1_py39.py
+++ b/docs_src/path_operation_advanced_configuration/tutorial007_pv1_py39.py
@@ -1,6 +1,6 @@
import yaml
from fastapi import FastAPI, HTTPException, Request
-from pydantic import BaseModel, ValidationError
+from pydantic.v1 import BaseModel, ValidationError
app = FastAPI()
diff --git a/docs_src/query_param_models/tutorial002_pv1_an_py310.py b/docs_src/query_param_models/tutorial002_pv1_an_py310.py
deleted file mode 100644
index d635aae88f..0000000000
--- a/docs_src/query_param_models/tutorial002_pv1_an_py310.py
+++ /dev/null
@@ -1,21 +0,0 @@
-from typing import Annotated, Literal
-
-from fastapi import FastAPI, Query
-from pydantic import BaseModel, Field
-
-app = FastAPI()
-
-
-class FilterParams(BaseModel):
- class Config:
- extra = "forbid"
-
- limit: int = Field(100, gt=0, le=100)
- offset: int = Field(0, ge=0)
- order_by: Literal["created_at", "updated_at"] = "created_at"
- tags: list[str] = []
-
-
-@app.get("/items/")
-async def read_items(filter_query: Annotated[FilterParams, Query()]):
- return filter_query
diff --git a/docs_src/query_param_models/tutorial002_pv1_an_py39.py b/docs_src/query_param_models/tutorial002_pv1_an_py39.py
deleted file mode 100644
index d635aae88f..0000000000
--- a/docs_src/query_param_models/tutorial002_pv1_an_py39.py
+++ /dev/null
@@ -1,21 +0,0 @@
-from typing import Annotated, Literal
-
-from fastapi import FastAPI, Query
-from pydantic import BaseModel, Field
-
-app = FastAPI()
-
-
-class FilterParams(BaseModel):
- class Config:
- extra = "forbid"
-
- limit: int = Field(100, gt=0, le=100)
- offset: int = Field(0, ge=0)
- order_by: Literal["created_at", "updated_at"] = "created_at"
- tags: list[str] = []
-
-
-@app.get("/items/")
-async def read_items(filter_query: Annotated[FilterParams, Query()]):
- return filter_query
diff --git a/docs_src/query_param_models/tutorial002_pv1_py310.py b/docs_src/query_param_models/tutorial002_pv1_py310.py
deleted file mode 100644
index 9ffdeefc06..0000000000
--- a/docs_src/query_param_models/tutorial002_pv1_py310.py
+++ /dev/null
@@ -1,21 +0,0 @@
-from typing import Literal
-
-from fastapi import FastAPI, Query
-from pydantic import BaseModel, Field
-
-app = FastAPI()
-
-
-class FilterParams(BaseModel):
- class Config:
- extra = "forbid"
-
- limit: int = Field(100, gt=0, le=100)
- offset: int = Field(0, ge=0)
- order_by: Literal["created_at", "updated_at"] = "created_at"
- tags: list[str] = []
-
-
-@app.get("/items/")
-async def read_items(filter_query: FilterParams = Query()):
- return filter_query
diff --git a/docs_src/query_param_models/tutorial002_pv1_py39.py b/docs_src/query_param_models/tutorial002_pv1_py39.py
deleted file mode 100644
index 9ffdeefc06..0000000000
--- a/docs_src/query_param_models/tutorial002_pv1_py39.py
+++ /dev/null
@@ -1,21 +0,0 @@
-from typing import Literal
-
-from fastapi import FastAPI, Query
-from pydantic import BaseModel, Field
-
-app = FastAPI()
-
-
-class FilterParams(BaseModel):
- class Config:
- extra = "forbid"
-
- limit: int = Field(100, gt=0, le=100)
- offset: int = Field(0, ge=0)
- order_by: Literal["created_at", "updated_at"] = "created_at"
- tags: list[str] = []
-
-
-@app.get("/items/")
-async def read_items(filter_query: FilterParams = Query()):
- return filter_query
diff --git a/docs_src/request_form_models/tutorial002_pv1_an_py39.py b/docs_src/request_form_models/tutorial002_pv1_an_py39.py
index 942d5d4118..392e6873cb 100644
--- a/docs_src/request_form_models/tutorial002_pv1_an_py39.py
+++ b/docs_src/request_form_models/tutorial002_pv1_an_py39.py
@@ -1,7 +1,8 @@
from typing import Annotated
-from fastapi import FastAPI, Form
-from pydantic import BaseModel
+from fastapi import FastAPI
+from fastapi.temp_pydantic_v1_params import Form
+from pydantic.v1 import BaseModel
app = FastAPI()
diff --git a/docs_src/request_form_models/tutorial002_pv1_py39.py b/docs_src/request_form_models/tutorial002_pv1_py39.py
index d5f7db2a67..da160b3a54 100644
--- a/docs_src/request_form_models/tutorial002_pv1_py39.py
+++ b/docs_src/request_form_models/tutorial002_pv1_py39.py
@@ -1,5 +1,6 @@
-from fastapi import FastAPI, Form
-from pydantic import BaseModel
+from fastapi import FastAPI
+from fastapi.temp_pydantic_v1_params import Form
+from pydantic.v1 import BaseModel
app = FastAPI()
diff --git a/docs_src/schema_extra_example/tutorial001_pv1_py310.py b/docs_src/schema_extra_example/tutorial001_pv1_py310.py
index ec83f1112f..b13b8a8c2c 100644
--- a/docs_src/schema_extra_example/tutorial001_pv1_py310.py
+++ b/docs_src/schema_extra_example/tutorial001_pv1_py310.py
@@ -1,5 +1,5 @@
from fastapi import FastAPI
-from pydantic import BaseModel
+from pydantic.v1 import BaseModel
app = FastAPI()
diff --git a/docs_src/schema_extra_example/tutorial001_pv1_py39.py b/docs_src/schema_extra_example/tutorial001_pv1_py39.py
index 6ab96ff859..3240b35d6d 100644
--- a/docs_src/schema_extra_example/tutorial001_pv1_py39.py
+++ b/docs_src/schema_extra_example/tutorial001_pv1_py39.py
@@ -1,7 +1,7 @@
from typing import Union
from fastapi import FastAPI
-from pydantic import BaseModel
+from pydantic.v1 import BaseModel
app = FastAPI()
diff --git a/docs_src/settings/app03_an_py39/config_pv1.py b/docs_src/settings/app03_an_py39/config_pv1.py
index e1c3ee3006..7ae66ef77c 100644
--- a/docs_src/settings/app03_an_py39/config_pv1.py
+++ b/docs_src/settings/app03_an_py39/config_pv1.py
@@ -1,4 +1,4 @@
-from pydantic import BaseSettings
+from pydantic.v1 import BaseSettings
class Settings(BaseSettings):
diff --git a/docs_src/settings/app03_py39/config_pv1.py b/docs_src/settings/app03_py39/config_pv1.py
index e1c3ee3006..7ae66ef77c 100644
--- a/docs_src/settings/app03_py39/config_pv1.py
+++ b/docs_src/settings/app03_py39/config_pv1.py
@@ -1,4 +1,4 @@
-from pydantic import BaseSettings
+from pydantic.v1 import BaseSettings
class Settings(BaseSettings):
diff --git a/docs_src/settings/tutorial001_pv1_py39.py b/docs_src/settings/tutorial001_pv1_py39.py
index 0cfd1b6632..20ad2bbf62 100644
--- a/docs_src/settings/tutorial001_pv1_py39.py
+++ b/docs_src/settings/tutorial001_pv1_py39.py
@@ -1,5 +1,5 @@
from fastapi import FastAPI
-from pydantic import BaseSettings
+from pydantic.v1 import BaseSettings
class Settings(BaseSettings):
diff --git a/fastapi/_compat/__init__.py b/fastapi/_compat/__init__.py
index 0aadd68de2..fd1df8c6a7 100644
--- a/fastapi/_compat/__init__.py
+++ b/fastapi/_compat/__init__.py
@@ -11,7 +11,6 @@ from .main import _is_model_class as _is_model_class
from .main import _is_model_field as _is_model_field
from .main import _is_undefined as _is_undefined
from .main import _model_dump as _model_dump
-from .main import _model_rebuild as _model_rebuild
from .main import copy_field_info as copy_field_info
from .main import create_body_model as create_body_model
from .main import evaluate_forwardref as evaluate_forwardref
diff --git a/fastapi/_compat/main.py b/fastapi/_compat/main.py
index 2043a66781..95053a2374 100644
--- a/fastapi/_compat/main.py
+++ b/fastapi/_compat/main.py
@@ -6,43 +6,26 @@ from typing import (
)
from fastapi._compat import may_v1
-from fastapi._compat.shared import PYDANTIC_V2, lenient_issubclass
+from fastapi._compat.shared import lenient_issubclass
from fastapi.types import ModelNameMap
from pydantic import BaseModel
from typing_extensions import Literal
+from . import v2
from .model_field import ModelField
-
-if PYDANTIC_V2:
- from .v2 import BaseConfig as BaseConfig
- from .v2 import FieldInfo as FieldInfo
- from .v2 import PydanticSchemaGenerationError as PydanticSchemaGenerationError
- from .v2 import RequiredParam as RequiredParam
- from .v2 import Undefined as Undefined
- from .v2 import UndefinedType as UndefinedType
- from .v2 import Url as Url
- from .v2 import Validator as Validator
- from .v2 import evaluate_forwardref as evaluate_forwardref
- from .v2 import get_missing_field_error as get_missing_field_error
- from .v2 import (
- with_info_plain_validator_function as with_info_plain_validator_function,
- )
-else:
- from .v1 import BaseConfig as BaseConfig # type: ignore[assignment]
- from .v1 import FieldInfo as FieldInfo
- from .v1 import ( # type: ignore[assignment]
- PydanticSchemaGenerationError as PydanticSchemaGenerationError,
- )
- from .v1 import RequiredParam as RequiredParam
- from .v1 import Undefined as Undefined
- from .v1 import UndefinedType as UndefinedType
- from .v1 import Url as Url # type: ignore[assignment]
- from .v1 import Validator as Validator
- from .v1 import evaluate_forwardref as evaluate_forwardref
- from .v1 import get_missing_field_error as get_missing_field_error
- from .v1 import ( # type: ignore[assignment]
- with_info_plain_validator_function as with_info_plain_validator_function,
- )
+from .v2 import BaseConfig as BaseConfig
+from .v2 import FieldInfo as FieldInfo
+from .v2 import PydanticSchemaGenerationError as PydanticSchemaGenerationError
+from .v2 import RequiredParam as RequiredParam
+from .v2 import Undefined as Undefined
+from .v2 import UndefinedType as UndefinedType
+from .v2 import Url as Url
+from .v2 import Validator as Validator
+from .v2 import evaluate_forwardref as evaluate_forwardref
+from .v2 import get_missing_field_error as get_missing_field_error
+from .v2 import (
+ with_info_plain_validator_function as with_info_plain_validator_function,
+)
@lru_cache
@@ -50,7 +33,7 @@ def get_cached_model_fields(model: type[BaseModel]) -> list[ModelField]:
if lenient_issubclass(model, may_v1.BaseModel):
from fastapi._compat import v1
- return v1.get_model_fields(model)
+ return v1.get_model_fields(model) # type: ignore[arg-type,return-value]
else:
from . import v2
@@ -60,11 +43,8 @@ def get_cached_model_fields(model: type[BaseModel]) -> list[ModelField]:
def _is_undefined(value: object) -> bool:
if isinstance(value, may_v1.UndefinedType):
return True
- elif PYDANTIC_V2:
- from . import v2
- return isinstance(value, v2.UndefinedType)
- return False
+ return isinstance(value, v2.UndefinedType)
def _get_model_config(model: BaseModel) -> Any:
@@ -72,10 +52,8 @@ def _get_model_config(model: BaseModel) -> Any:
from fastapi._compat import v1
return v1._get_model_config(model)
- elif PYDANTIC_V2:
- from . import v2
- return v2._get_model_config(model)
+ return v2._get_model_config(model)
def _model_dump(
@@ -85,20 +63,15 @@ def _model_dump(
from fastapi._compat import v1
return v1._model_dump(model, mode=mode, **kwargs)
- elif PYDANTIC_V2:
- from . import v2
- return v2._model_dump(model, mode=mode, **kwargs)
+ return v2._model_dump(model, mode=mode, **kwargs)
def _is_error_wrapper(exc: Exception) -> bool:
if isinstance(exc, may_v1.ErrorWrapper):
return True
- elif PYDANTIC_V2:
- from . import v2
- return isinstance(exc, v2.ErrorWrapper)
- return False
+ return isinstance(exc, v2.ErrorWrapper)
def copy_field_info(*, field_info: FieldInfo, annotation: Any) -> FieldInfo:
@@ -106,11 +79,8 @@ def copy_field_info(*, field_info: FieldInfo, annotation: Any) -> FieldInfo:
from fastapi._compat import v1
return v1.copy_field_info(field_info=field_info, annotation=annotation)
- else:
- assert PYDANTIC_V2
- from . import v2
- return v2.copy_field_info(field_info=field_info, annotation=annotation)
+ return v2.copy_field_info(field_info=field_info, annotation=annotation)
def create_body_model(
@@ -120,11 +90,8 @@ def create_body_model(
from fastapi._compat import v1
return v1.create_body_model(fields=fields, model_name=model_name)
- else:
- assert PYDANTIC_V2
- from . import v2
- return v2.create_body_model(fields=fields, model_name=model_name) # type: ignore[arg-type]
+ return v2.create_body_model(fields=fields, model_name=model_name) # type: ignore[arg-type]
def get_annotation_from_field_info(
@@ -136,13 +103,10 @@ def get_annotation_from_field_info(
return v1.get_annotation_from_field_info(
annotation=annotation, field_info=field_info, field_name=field_name
)
- else:
- assert PYDANTIC_V2
- from . import v2
- return v2.get_annotation_from_field_info(
- annotation=annotation, field_info=field_info, field_name=field_name
- )
+ return v2.get_annotation_from_field_info(
+ annotation=annotation, field_info=field_info, field_name=field_name
+ )
def is_bytes_field(field: ModelField) -> bool:
@@ -150,11 +114,8 @@ def is_bytes_field(field: ModelField) -> bool:
from fastapi._compat import v1
return v1.is_bytes_field(field)
- else:
- assert PYDANTIC_V2
- from . import v2
- return v2.is_bytes_field(field) # type: ignore[arg-type]
+ return v2.is_bytes_field(field) # type: ignore[arg-type]
def is_bytes_sequence_field(field: ModelField) -> bool:
@@ -162,11 +123,8 @@ def is_bytes_sequence_field(field: ModelField) -> bool:
from fastapi._compat import v1
return v1.is_bytes_sequence_field(field)
- else:
- assert PYDANTIC_V2
- from . import v2
- return v2.is_bytes_sequence_field(field) # type: ignore[arg-type]
+ return v2.is_bytes_sequence_field(field) # type: ignore[arg-type]
def is_scalar_field(field: ModelField) -> bool:
@@ -174,23 +132,12 @@ def is_scalar_field(field: ModelField) -> bool:
from fastapi._compat import v1
return v1.is_scalar_field(field)
- else:
- assert PYDANTIC_V2
- from . import v2
- return v2.is_scalar_field(field) # type: ignore[arg-type]
+ return v2.is_scalar_field(field) # type: ignore[arg-type]
def is_scalar_sequence_field(field: ModelField) -> bool:
- if isinstance(field, may_v1.ModelField):
- from fastapi._compat import v1
-
- return v1.is_scalar_sequence_field(field)
- else:
- assert PYDANTIC_V2
- from . import v2
-
- return v2.is_scalar_sequence_field(field) # type: ignore[arg-type]
+ return v2.is_scalar_sequence_field(field) # type: ignore[arg-type]
def is_sequence_field(field: ModelField) -> bool:
@@ -198,11 +145,8 @@ def is_sequence_field(field: ModelField) -> bool:
from fastapi._compat import v1
return v1.is_sequence_field(field)
- else:
- assert PYDANTIC_V2
- from . import v2
- return v2.is_sequence_field(field) # type: ignore[arg-type]
+ return v2.is_sequence_field(field) # type: ignore[arg-type]
def serialize_sequence_value(*, field: ModelField, value: Any) -> Sequence[Any]:
@@ -210,22 +154,8 @@ def serialize_sequence_value(*, field: ModelField, value: Any) -> Sequence[Any]:
from fastapi._compat import v1
return v1.serialize_sequence_value(field=field, value=value)
- else:
- assert PYDANTIC_V2
- from . import v2
- return v2.serialize_sequence_value(field=field, value=value) # type: ignore[arg-type]
-
-
-def _model_rebuild(model: type[BaseModel]) -> None:
- if lenient_issubclass(model, may_v1.BaseModel):
- from fastapi._compat import v1
-
- v1._model_rebuild(model)
- elif PYDANTIC_V2:
- from . import v2
-
- v2._model_rebuild(model)
+ return v2.serialize_sequence_value(field=field, value=value) # type: ignore[arg-type]
def get_compat_model_name_map(fields: list[ModelField]) -> ModelNameMap:
@@ -236,27 +166,18 @@ def get_compat_model_name_map(fields: list[ModelField]) -> ModelNameMap:
from fastapi._compat import v1
v1_flat_models = v1.get_flat_models_from_fields(
- v1_model_fields, known_models=set()
+ v1_model_fields, # type: ignore[arg-type]
+ known_models=set(),
)
all_flat_models = v1_flat_models
else:
all_flat_models = set()
- if PYDANTIC_V2:
- from . import v2
- v2_model_fields = [
- field for field in fields if isinstance(field, v2.ModelField)
- ]
- v2_flat_models = v2.get_flat_models_from_fields(
- v2_model_fields, known_models=set()
- )
- all_flat_models = all_flat_models.union(v2_flat_models)
+ v2_model_fields = [field for field in fields if isinstance(field, v2.ModelField)]
+ v2_flat_models = v2.get_flat_models_from_fields(v2_model_fields, known_models=set())
+ all_flat_models = all_flat_models.union(v2_flat_models) # type: ignore[arg-type]
- model_name_map = v2.get_model_name_map(all_flat_models)
- return model_name_map
- from fastapi._compat import v1
-
- model_name_map = v1.get_model_name_map(all_flat_models)
+ model_name_map = v2.get_model_name_map(all_flat_models) # type: ignore[arg-type]
return model_name_map
@@ -275,29 +196,23 @@ def get_definitions(
if sys.version_info < (3, 14):
v1_fields = [field for field in fields if isinstance(field, may_v1.ModelField)]
v1_field_maps, v1_definitions = may_v1.get_definitions(
- fields=v1_fields,
+ fields=v1_fields, # type: ignore[arg-type]
model_name_map=model_name_map,
separate_input_output_schemas=separate_input_output_schemas,
)
- if not PYDANTIC_V2:
- return v1_field_maps, v1_definitions
- else:
- from . import v2
- v2_fields = [field for field in fields if isinstance(field, v2.ModelField)]
- v2_field_maps, v2_definitions = v2.get_definitions(
- fields=v2_fields,
- model_name_map=model_name_map,
- separate_input_output_schemas=separate_input_output_schemas,
- )
- all_definitions = {**v1_definitions, **v2_definitions}
- all_field_maps = {**v1_field_maps, **v2_field_maps}
- return all_field_maps, all_definitions
+ v2_fields = [field for field in fields if isinstance(field, v2.ModelField)]
+ v2_field_maps, v2_definitions = v2.get_definitions(
+ fields=v2_fields,
+ model_name_map=model_name_map,
+ separate_input_output_schemas=separate_input_output_schemas,
+ )
+ all_definitions = {**v1_definitions, **v2_definitions}
+ all_field_maps = {**v1_field_maps, **v2_field_maps} # type: ignore[misc]
+ return all_field_maps, all_definitions
# Pydantic v1 is not supported since Python 3.14
else:
- from . import v2
-
v2_fields = [field for field in fields if isinstance(field, v2.ModelField)]
v2_field_maps, v2_definitions = v2.get_definitions(
fields=v2_fields,
@@ -326,33 +241,24 @@ def get_schema_from_model_field(
field_mapping=field_mapping,
separate_input_output_schemas=separate_input_output_schemas,
)
- else:
- assert PYDANTIC_V2
- from . import v2
- return v2.get_schema_from_model_field(
- field=field, # type: ignore[arg-type]
- model_name_map=model_name_map,
- field_mapping=field_mapping, # type: ignore[arg-type]
- separate_input_output_schemas=separate_input_output_schemas,
- )
+ return v2.get_schema_from_model_field(
+ field=field, # type: ignore[arg-type]
+ model_name_map=model_name_map,
+ field_mapping=field_mapping, # type: ignore[arg-type]
+ separate_input_output_schemas=separate_input_output_schemas,
+ )
def _is_model_field(value: Any) -> bool:
if isinstance(value, may_v1.ModelField):
return True
- elif PYDANTIC_V2:
- from . import v2
- return isinstance(value, v2.ModelField)
- return False
+ return isinstance(value, v2.ModelField)
def _is_model_class(value: Any) -> bool:
if lenient_issubclass(value, may_v1.BaseModel):
return True
- elif PYDANTIC_V2:
- from . import v2
- return lenient_issubclass(value, v2.BaseModel) # type: ignore[attr-defined]
- return False
+ return lenient_issubclass(value, v2.BaseModel) # type: ignore[attr-defined]
diff --git a/fastapi/_compat/may_v1.py b/fastapi/_compat/may_v1.py
index c772162283..3ac86aa98b 100644
--- a/fastapi/_compat/may_v1.py
+++ b/fastapi/_compat/may_v1.py
@@ -102,7 +102,7 @@ def _normalize_errors(errors: Sequence[Any]) -> list[dict[str, Any]]:
use_errors: list[Any] = []
for error in errors:
if isinstance(error, ErrorWrapper):
- new_errors = ValidationError( # type: ignore[call-arg]
+ new_errors = ValidationError(
errors=[error], model=RequestErrorModel
).errors()
use_errors.extend(new_errors)
diff --git a/fastapi/_compat/v1.py b/fastapi/_compat/v1.py
index b29a61f734..b0a9dd35f1 100644
--- a/fastapi/_compat/v1.py
+++ b/fastapi/_compat/v1.py
@@ -11,6 +11,44 @@ from typing import (
from fastapi._compat import shared
from fastapi.openapi.constants import REF_PREFIX as REF_PREFIX
from fastapi.types import ModelNameMap
+from pydantic.v1 import BaseConfig as BaseConfig
+from pydantic.v1 import BaseModel as BaseModel
+from pydantic.v1 import ValidationError as ValidationError
+from pydantic.v1 import create_model as create_model
+from pydantic.v1.class_validators import Validator as Validator
+from pydantic.v1.color import Color as Color
+from pydantic.v1.error_wrappers import ErrorWrapper as ErrorWrapper
+from pydantic.v1.fields import (
+ SHAPE_FROZENSET,
+ SHAPE_LIST,
+ SHAPE_SEQUENCE,
+ SHAPE_SET,
+ SHAPE_SINGLETON,
+ SHAPE_TUPLE,
+ SHAPE_TUPLE_ELLIPSIS,
+)
+from pydantic.v1.fields import FieldInfo as FieldInfo
+from pydantic.v1.fields import ModelField as ModelField
+from pydantic.v1.fields import Undefined as Undefined
+from pydantic.v1.fields import UndefinedType as UndefinedType
+from pydantic.v1.networks import AnyUrl as AnyUrl
+from pydantic.v1.networks import NameEmail as NameEmail
+from pydantic.v1.schema import TypeModelSet as TypeModelSet
+from pydantic.v1.schema import field_schema, model_process_schema
+from pydantic.v1.schema import (
+ get_annotation_from_field_info as get_annotation_from_field_info,
+)
+from pydantic.v1.schema import (
+ get_flat_models_from_field as get_flat_models_from_field,
+)
+from pydantic.v1.schema import (
+ get_flat_models_from_fields as get_flat_models_from_fields,
+)
+from pydantic.v1.schema import get_model_name_map as get_model_name_map
+from pydantic.v1.types import SecretBytes as SecretBytes
+from pydantic.v1.types import SecretStr as SecretStr
+from pydantic.v1.typing import evaluate_forwardref as evaluate_forwardref
+from pydantic.v1.utils import lenient_issubclass as lenient_issubclass
from pydantic.version import VERSION as PYDANTIC_VERSION
from typing_extensions import Literal
@@ -20,103 +58,6 @@ PYDANTIC_V2 = PYDANTIC_VERSION_MINOR_TUPLE[0] == 2
# shadowing typing.Required.
RequiredParam: Any = Ellipsis
-if not PYDANTIC_V2:
- from pydantic import BaseConfig as BaseConfig
- from pydantic import BaseModel as BaseModel
- from pydantic import ValidationError as ValidationError
- from pydantic import create_model as create_model
- from pydantic.class_validators import Validator as Validator
- from pydantic.color import Color as Color
- from pydantic.error_wrappers import ErrorWrapper as ErrorWrapper
- from pydantic.errors import MissingError
- from pydantic.fields import ( # type: ignore[attr-defined]
- SHAPE_FROZENSET,
- SHAPE_LIST,
- SHAPE_SEQUENCE,
- SHAPE_SET,
- SHAPE_SINGLETON,
- SHAPE_TUPLE,
- SHAPE_TUPLE_ELLIPSIS,
- )
- from pydantic.fields import FieldInfo as FieldInfo
- from pydantic.fields import ModelField as ModelField # type: ignore[attr-defined]
- from pydantic.fields import Undefined as Undefined # type: ignore[attr-defined]
- from pydantic.fields import ( # type: ignore[attr-defined]
- UndefinedType as UndefinedType,
- )
- from pydantic.networks import AnyUrl as AnyUrl
- from pydantic.networks import NameEmail as NameEmail
- from pydantic.schema import TypeModelSet as TypeModelSet
- from pydantic.schema import (
- field_schema,
- model_process_schema,
- )
- from pydantic.schema import (
- get_annotation_from_field_info as get_annotation_from_field_info,
- )
- from pydantic.schema import get_flat_models_from_field as get_flat_models_from_field
- from pydantic.schema import (
- get_flat_models_from_fields as get_flat_models_from_fields,
- )
- from pydantic.schema import get_model_name_map as get_model_name_map
- from pydantic.types import SecretBytes as SecretBytes
- from pydantic.types import SecretStr as SecretStr
- from pydantic.typing import evaluate_forwardref as evaluate_forwardref
- from pydantic.utils import lenient_issubclass as lenient_issubclass
-
-
-else:
- from pydantic.v1 import BaseConfig as BaseConfig # type: ignore[assignment]
- from pydantic.v1 import BaseModel as BaseModel # type: ignore[assignment]
- from pydantic.v1 import ( # type: ignore[assignment]
- ValidationError as ValidationError,
- )
- from pydantic.v1 import create_model as create_model # type: ignore[no-redef]
- from pydantic.v1.class_validators import Validator as Validator
- from pydantic.v1.color import Color as Color # type: ignore[assignment]
- from pydantic.v1.error_wrappers import ErrorWrapper as ErrorWrapper
- from pydantic.v1.errors import MissingError
- from pydantic.v1.fields import (
- SHAPE_FROZENSET,
- SHAPE_LIST,
- SHAPE_SEQUENCE,
- SHAPE_SET,
- SHAPE_SINGLETON,
- SHAPE_TUPLE,
- SHAPE_TUPLE_ELLIPSIS,
- )
- from pydantic.v1.fields import FieldInfo as FieldInfo # type: ignore[assignment]
- from pydantic.v1.fields import ModelField as ModelField
- from pydantic.v1.fields import Undefined as Undefined
- from pydantic.v1.fields import UndefinedType as UndefinedType
- from pydantic.v1.networks import AnyUrl as AnyUrl
- from pydantic.v1.networks import ( # type: ignore[assignment]
- NameEmail as NameEmail,
- )
- from pydantic.v1.schema import TypeModelSet as TypeModelSet
- from pydantic.v1.schema import (
- field_schema,
- model_process_schema,
- )
- from pydantic.v1.schema import (
- get_annotation_from_field_info as get_annotation_from_field_info,
- )
- from pydantic.v1.schema import (
- get_flat_models_from_field as get_flat_models_from_field,
- )
- from pydantic.v1.schema import (
- get_flat_models_from_fields as get_flat_models_from_fields,
- )
- from pydantic.v1.schema import get_model_name_map as get_model_name_map
- from pydantic.v1.types import ( # type: ignore[assignment]
- SecretBytes as SecretBytes,
- )
- from pydantic.v1.types import ( # type: ignore[assignment]
- SecretStr as SecretStr,
- )
- from pydantic.v1.typing import evaluate_forwardref as evaluate_forwardref
- from pydantic.v1.utils import lenient_issubclass as lenient_issubclass
-
GetJsonSchemaHandler = Any
JsonSchemaValue = dict[str, Any]
@@ -200,24 +141,6 @@ def is_pv1_scalar_field(field: ModelField) -> bool:
return True
-def is_pv1_scalar_sequence_field(field: ModelField) -> bool:
- if (field.shape in sequence_shapes) and not lenient_issubclass(
- field.type_, BaseModel
- ):
- if field.sub_fields is not None:
- for sub_field in field.sub_fields:
- if not is_pv1_scalar_field(sub_field):
- return False
- return True
- if shared._annotation_is_sequence(field.type_):
- return True
- return False
-
-
-def _model_rebuild(model: type[BaseModel]) -> None:
- model.update_forward_refs()
-
-
def _model_dump(
model: BaseModel, mode: Literal["json", "python"] = "json", **kwargs: Any
) -> Any:
@@ -225,7 +148,7 @@ def _model_dump(
def _get_model_config(model: BaseModel) -> Any:
- return model.__config__ # type: ignore[attr-defined]
+ return model.__config__
def get_schema_from_model_field(
@@ -237,8 +160,10 @@ def get_schema_from_model_field(
],
separate_input_output_schemas: bool = True,
) -> dict[str, Any]:
- return field_schema( # type: ignore[no-any-return]
- field, model_name_map=model_name_map, ref_prefix=REF_PREFIX
+ return field_schema(
+ field,
+ model_name_map=model_name_map, # type: ignore[arg-type]
+ ref_prefix=REF_PREFIX,
)[0]
@@ -257,7 +182,7 @@ def get_definitions(
dict[str, dict[str, Any]],
]:
models = get_flat_models_from_fields(fields, known_models=set())
- return {}, get_model_definitions(flat_models=models, model_name_map=model_name_map)
+ return {}, get_model_definitions(flat_models=models, model_name_map=model_name_map) # type: ignore[arg-type]
def is_scalar_field(field: ModelField) -> bool:
@@ -268,12 +193,8 @@ def is_sequence_field(field: ModelField) -> bool:
return field.shape in sequence_shapes or shared._annotation_is_sequence(field.type_)
-def is_scalar_sequence_field(field: ModelField) -> bool:
- return is_pv1_scalar_sequence_field(field)
-
-
def is_bytes_field(field: ModelField) -> bool:
- return lenient_issubclass(field.type_, bytes) # type: ignore[no-any-return]
+ return lenient_issubclass(field.type_, bytes)
def is_bytes_sequence_field(field: ModelField) -> bool:
@@ -288,20 +209,14 @@ def serialize_sequence_value(*, field: ModelField, value: Any) -> Sequence[Any]:
return sequence_shape_to_type[field.shape](value) # type: ignore[no-any-return]
-def get_missing_field_error(loc: tuple[str, ...]) -> dict[str, Any]:
- missing_field_error = ErrorWrapper(MissingError(), loc=loc)
- new_error = ValidationError([missing_field_error], RequestErrorModel)
- return new_error.errors()[0] # type: ignore[return-value]
-
-
def create_body_model(
*, fields: Sequence[ModelField], model_name: str
) -> type[BaseModel]:
BodyModel = create_model(model_name)
for f in fields:
- BodyModel.__fields__[f.name] = f # type: ignore[index]
+ BodyModel.__fields__[f.name] = f
return BodyModel
def get_model_fields(model: type[BaseModel]) -> list[ModelField]:
- return list(model.__fields__.values()) # type: ignore[attr-defined]
+ return list(model.__fields__.values())
diff --git a/fastapi/_compat/v2.py b/fastapi/_compat/v2.py
index c4fa49e403..cbcb98e1a2 100644
--- a/fastapi/_compat/v2.py
+++ b/fastapi/_compat/v2.py
@@ -216,10 +216,6 @@ def get_annotation_from_field_info(
return annotation
-def _model_rebuild(model: type[BaseModel]) -> None:
- model.model_rebuild()
-
-
def _model_dump(
model: BaseModel, mode: Literal["json", "python"] = "json", **kwargs: Any
) -> Any:
diff --git a/fastapi/datastructures.py b/fastapi/datastructures.py
index b38a326def..492cbfcccb 100644
--- a/fastapi/datastructures.py
+++ b/fastapi/datastructures.py
@@ -1,4 +1,3 @@
-from collections.abc import Iterable
from typing import (
Annotated,
Any,
@@ -135,27 +134,12 @@ class UploadFile(StarletteUploadFile):
"""
return await super().close()
- @classmethod
- def __get_validators__(cls: type["UploadFile"]) -> Iterable[Callable[..., Any]]:
- yield cls.validate
-
- @classmethod
- def validate(cls: type["UploadFile"], v: Any) -> Any:
- if not isinstance(v, StarletteUploadFile):
- raise ValueError(f"Expected UploadFile, received: {type(v)}")
- return v
-
@classmethod
def _validate(cls, __input_value: Any, _: Any) -> "UploadFile":
if not isinstance(__input_value, StarletteUploadFile):
raise ValueError(f"Expected UploadFile, received: {type(__input_value)}")
return cast(UploadFile, __input_value)
- # TODO: remove when deprecating Pydantic v1
- @classmethod
- def __modify_schema__(cls, field_schema: dict[str, Any]) -> None:
- field_schema.update({"type": "string", "format": "binary"})
-
@classmethod
def __get_pydantic_json_schema__(
cls, core_schema: CoreSchema, handler: GetJsonSchemaHandler
diff --git a/fastapi/dependencies/utils.py b/fastapi/dependencies/utils.py
index 3db006a918..0ba93524c4 100644
--- a/fastapi/dependencies/utils.py
+++ b/fastapi/dependencies/utils.py
@@ -18,7 +18,6 @@ from typing import (
import anyio
from fastapi import params
from fastapi._compat import (
- PYDANTIC_V2,
ModelField,
RequiredParam,
Undefined,
@@ -410,7 +409,8 @@ def analyze_param(
if isinstance(fastapi_annotation, (FieldInfo, may_v1.FieldInfo)):
# Copy `field_info` because we mutate `field_info.default` below.
field_info = copy_field_info(
- field_info=fastapi_annotation, annotation=use_annotation
+ field_info=fastapi_annotation, # type: ignore[arg-type]
+ annotation=use_annotation,
)
assert field_info.default in {
Undefined,
@@ -444,10 +444,9 @@ def analyze_param(
"Cannot specify FastAPI annotations in `Annotated` and default value"
f" together for {param_name!r}"
)
- field_info = value
- if PYDANTIC_V2:
- if isinstance(field_info, FieldInfo):
- field_info.annotation = type_annotation
+ field_info = value # type: ignore[assignment]
+ if isinstance(field_info, FieldInfo):
+ field_info.annotation = type_annotation
# Get Depends from type annotation
if depends is not None and depends.dependency is None:
@@ -485,7 +484,7 @@ def analyze_param(
field_info = params.File(annotation=use_annotation, default=default_value)
elif not field_annotation_is_scalar(annotation=type_annotation):
if annotation_is_pydantic_v1(use_annotation):
- field_info = temp_pydantic_v1_params.Body(
+ field_info = temp_pydantic_v1_params.Body( # type: ignore[assignment]
annotation=use_annotation, default=default_value
)
else:
diff --git a/fastapi/encoders.py b/fastapi/encoders.py
index cbeeee4559..549da32797 100644
--- a/fastapi/encoders.py
+++ b/fastapi/encoders.py
@@ -228,11 +228,11 @@ def jsonable_encoder(
# TODO: remove when deprecating Pydantic v1
encoders: dict[Any, Any] = {}
if isinstance(obj, may_v1.BaseModel):
- encoders = getattr(obj.__config__, "json_encoders", {}) # type: ignore[attr-defined]
+ encoders = getattr(obj.__config__, "json_encoders", {})
if custom_encoder:
encoders = {**encoders, **custom_encoder}
obj_dict = _model_dump(
- obj,
+ obj, # type: ignore[arg-type]
mode="json",
include=include,
exclude=exclude,
diff --git a/fastapi/openapi/models.py b/fastapi/openapi/models.py
index 7aa80f5cb0..680f678325 100644
--- a/fastapi/openapi/models.py
+++ b/fastapi/openapi/models.py
@@ -3,11 +3,9 @@ from enum import Enum
from typing import Annotated, Any, Callable, Optional, Union
from fastapi._compat import (
- PYDANTIC_V2,
CoreSchema,
GetJsonSchemaHandler,
JsonSchemaValue,
- _model_rebuild,
with_info_plain_validator_function,
)
from fastapi.logger import logger
@@ -57,13 +55,7 @@ except ImportError: # pragma: no cover
class BaseModelWithConfig(BaseModel):
- if PYDANTIC_V2:
- model_config = {"extra": "allow"}
-
- else:
-
- class Config:
- extra = "allow"
+ model_config = {"extra": "allow"}
class Contact(BaseModelWithConfig):
@@ -226,13 +218,7 @@ class Example(TypedDict, total=False):
value: Optional[Any]
externalValue: Optional[AnyUrl]
- if PYDANTIC_V2: # type: ignore [misc]
- __pydantic_config__ = {"extra": "allow"}
-
- else:
-
- class Config:
- extra = "allow"
+ __pydantic_config__ = {"extra": "allow"} # type: ignore[misc]
class ParameterInType(Enum):
@@ -447,6 +433,6 @@ class OpenAPI(BaseModelWithConfig):
externalDocs: Optional[ExternalDocumentation] = None
-_model_rebuild(Schema)
-_model_rebuild(Operation)
-_model_rebuild(Encoding)
+Schema.model_rebuild()
+Operation.model_rebuild()
+Encoding.model_rebuild()
diff --git a/fastapi/params.py b/fastapi/params.py
index 4990d0e70e..c776c4a59e 100644
--- a/fastapi/params.py
+++ b/fastapi/params.py
@@ -9,8 +9,6 @@ from pydantic.fields import FieldInfo
from typing_extensions import Literal, deprecated
from ._compat import (
- PYDANTIC_V2,
- PYDANTIC_VERSION_MINOR_TUPLE,
Undefined,
)
@@ -111,29 +109,24 @@ class Param(FieldInfo): # type: ignore[misc]
stacklevel=4,
)
current_json_schema_extra = json_schema_extra or extra
- if PYDANTIC_VERSION_MINOR_TUPLE < (2, 7):
- self.deprecated = deprecated
- else:
- kwargs["deprecated"] = deprecated
- if PYDANTIC_V2:
- if serialization_alias in (_Unset, None) and isinstance(alias, str):
- serialization_alias = alias
- if validation_alias in (_Unset, None):
- validation_alias = alias
- kwargs.update(
- {
- "annotation": annotation,
- "alias_priority": alias_priority,
- "validation_alias": validation_alias,
- "serialization_alias": serialization_alias,
- "strict": strict,
- "json_schema_extra": current_json_schema_extra,
- }
- )
- kwargs["pattern"] = pattern or regex
- else:
- kwargs["regex"] = pattern or regex
- kwargs.update(**current_json_schema_extra)
+ kwargs["deprecated"] = deprecated
+
+ if serialization_alias in (_Unset, None) and isinstance(alias, str):
+ serialization_alias = alias
+ if validation_alias in (_Unset, None):
+ validation_alias = alias
+ kwargs.update(
+ {
+ "annotation": annotation,
+ "alias_priority": alias_priority,
+ "validation_alias": validation_alias,
+ "serialization_alias": serialization_alias,
+ "strict": strict,
+ "json_schema_extra": current_json_schema_extra,
+ }
+ )
+ kwargs["pattern"] = pattern or regex
+
use_kwargs = {k: v for k, v in kwargs.items() if v is not _Unset}
super().__init__(**use_kwargs)
@@ -571,29 +564,22 @@ class Body(FieldInfo): # type: ignore[misc]
stacklevel=4,
)
current_json_schema_extra = json_schema_extra or extra
- if PYDANTIC_VERSION_MINOR_TUPLE < (2, 7):
- self.deprecated = deprecated
- else:
- kwargs["deprecated"] = deprecated
- if PYDANTIC_V2:
- if serialization_alias in (_Unset, None) and isinstance(alias, str):
- serialization_alias = alias
- if validation_alias in (_Unset, None):
- validation_alias = alias
- kwargs.update(
- {
- "annotation": annotation,
- "alias_priority": alias_priority,
- "validation_alias": validation_alias,
- "serialization_alias": serialization_alias,
- "strict": strict,
- "json_schema_extra": current_json_schema_extra,
- }
- )
- kwargs["pattern"] = pattern or regex
- else:
- kwargs["regex"] = pattern or regex
- kwargs.update(**current_json_schema_extra)
+ kwargs["deprecated"] = deprecated
+ if serialization_alias in (_Unset, None) and isinstance(alias, str):
+ serialization_alias = alias
+ if validation_alias in (_Unset, None):
+ validation_alias = alias
+ kwargs.update(
+ {
+ "annotation": annotation,
+ "alias_priority": alias_priority,
+ "validation_alias": validation_alias,
+ "serialization_alias": serialization_alias,
+ "strict": strict,
+ "json_schema_extra": current_json_schema_extra,
+ }
+ )
+ kwargs["pattern"] = pattern or regex
use_kwargs = {k: v for k, v in kwargs.items() if v is not _Unset}
diff --git a/fastapi/routing.py b/fastapi/routing.py
index fa6904a6b6..a1f2e44bb4 100644
--- a/fastapi/routing.py
+++ b/fastapi/routing.py
@@ -1,4 +1,3 @@
-import dataclasses
import email.message
import functools
import inspect
@@ -30,6 +29,7 @@ from fastapi._compat import (
_model_dump,
_normalize_errors,
lenient_issubclass,
+ may_v1,
)
from fastapi.datastructures import Default, DefaultPlaceholder
from fastapi.dependencies.models import Dependant
@@ -58,7 +58,6 @@ from fastapi.utils import (
get_value_or_default,
is_body_allowed_for_status_code,
)
-from pydantic import BaseModel
from starlette import routing
from starlette._exception_handler import wrap_app_handling_exceptions
from starlette._utils import is_async_callable
@@ -153,8 +152,8 @@ def _prepare_response_content(
exclude_defaults: bool = False,
exclude_none: bool = False,
) -> Any:
- if isinstance(res, BaseModel):
- read_with_orm_mode = getattr(_get_model_config(res), "read_with_orm_mode", None)
+ if isinstance(res, may_v1.BaseModel):
+ read_with_orm_mode = getattr(_get_model_config(res), "read_with_orm_mode", None) # type: ignore[arg-type]
if read_with_orm_mode:
# Let from_orm extract the data from this model instead of converting
# it now to a dict.
@@ -162,7 +161,7 @@ def _prepare_response_content(
# access instead of dict iteration, e.g. lazy relationships.
return res
return _model_dump(
- res,
+ res, # type: ignore[arg-type]
by_alias=True,
exclude_unset=exclude_unset,
exclude_defaults=exclude_defaults,
@@ -188,9 +187,6 @@ def _prepare_response_content(
)
for k, v in res.items()
}
- elif dataclasses.is_dataclass(res):
- assert not isinstance(res, type)
- return dataclasses.asdict(res)
return res
diff --git a/fastapi/temp_pydantic_v1_params.py b/fastapi/temp_pydantic_v1_params.py
index b6c804dc44..1bda0ea9b2 100644
--- a/fastapi/temp_pydantic_v1_params.py
+++ b/fastapi/temp_pydantic_v1_params.py
@@ -6,12 +6,11 @@ from fastapi.params import ParamTypes
from typing_extensions import deprecated
from ._compat.may_v1 import FieldInfo, Undefined
-from ._compat.shared import PYDANTIC_VERSION_MINOR_TUPLE
_Unset: Any = Undefined
-class Param(FieldInfo): # type: ignore[misc]
+class Param(FieldInfo):
in_: ParamTypes
def __init__(
@@ -98,10 +97,7 @@ class Param(FieldInfo): # type: ignore[misc]
stacklevel=4,
)
current_json_schema_extra = json_schema_extra or extra
- if PYDANTIC_VERSION_MINOR_TUPLE < (2, 7):
- self.deprecated = deprecated
- else:
- kwargs["deprecated"] = deprecated
+ kwargs["deprecated"] = deprecated
kwargs["regex"] = pattern or regex
kwargs.update(**current_json_schema_extra)
use_kwargs = {k: v for k, v in kwargs.items() if v is not _Unset}
@@ -112,7 +108,7 @@ class Param(FieldInfo): # type: ignore[misc]
return f"{self.__class__.__name__}({self.default})"
-class Path(Param): # type: ignore[misc]
+class Path(Param):
in_ = ParamTypes.path
def __init__(
@@ -198,7 +194,7 @@ class Path(Param): # type: ignore[misc]
)
-class Query(Param): # type: ignore[misc]
+class Query(Param):
in_ = ParamTypes.query
def __init__(
@@ -282,7 +278,7 @@ class Query(Param): # type: ignore[misc]
)
-class Header(Param): # type: ignore[misc]
+class Header(Param):
in_ = ParamTypes.header
def __init__(
@@ -368,7 +364,7 @@ class Header(Param): # type: ignore[misc]
)
-class Cookie(Param): # type: ignore[misc]
+class Cookie(Param):
in_ = ParamTypes.cookie
def __init__(
@@ -452,7 +448,7 @@ class Cookie(Param): # type: ignore[misc]
)
-class Body(FieldInfo): # type: ignore[misc]
+class Body(FieldInfo):
def __init__(
self,
default: Any = Undefined,
@@ -541,10 +537,7 @@ class Body(FieldInfo): # type: ignore[misc]
stacklevel=4,
)
current_json_schema_extra = json_schema_extra or extra
- if PYDANTIC_VERSION_MINOR_TUPLE < (2, 7):
- self.deprecated = deprecated
- else:
- kwargs["deprecated"] = deprecated
+ kwargs["deprecated"] = deprecated
kwargs["regex"] = pattern or regex
kwargs.update(**current_json_schema_extra)
@@ -556,7 +549,7 @@ class Body(FieldInfo): # type: ignore[misc]
return f"{self.__class__.__name__}({self.default})"
-class Form(Body): # type: ignore[misc]
+class Form(Body):
def __init__(
self,
default: Any = Undefined,
@@ -640,7 +633,7 @@ class Form(Body): # type: ignore[misc]
)
-class File(Form): # type: ignore[misc]
+class File(Form):
def __init__(
self,
default: Any = Undefined,
diff --git a/fastapi/utils.py b/fastapi/utils.py
index 5b93b9af8e..c4631d7ed2 100644
--- a/fastapi/utils.py
+++ b/fastapi/utils.py
@@ -1,7 +1,6 @@
import re
import warnings
from collections.abc import MutableMapping
-from dataclasses import is_dataclass
from typing import (
TYPE_CHECKING,
Any,
@@ -13,7 +12,6 @@ from weakref import WeakKeyDictionary
import fastapi
from fastapi._compat import (
- PYDANTIC_V2,
BaseConfig,
ModelField,
PydanticSchemaGenerationError,
@@ -29,6 +27,8 @@ from pydantic import BaseModel
from pydantic.fields import FieldInfo
from typing_extensions import Literal
+from ._compat import v2
+
if TYPE_CHECKING: # pragma: nocover
from .routing import APIRoute
@@ -105,14 +105,12 @@ def create_model_field(
from fastapi._compat import v1
try:
- return v1.ModelField(**v1_kwargs) # type: ignore[no-any-return]
+ return v1.ModelField(**v1_kwargs) # type: ignore[return-value]
except RuntimeError:
raise fastapi.exceptions.FastAPIError(
_invalid_args_message.format(type_=type_)
) from None
- elif PYDANTIC_V2:
- from ._compat import v2
-
+ else:
field_info = field_info or FieldInfo(
annotation=type_, default=default, alias=alias
)
@@ -128,7 +126,7 @@ def create_model_field(
from fastapi._compat import v1
try:
- return v1.ModelField(**v1_kwargs) # type: ignore[no-any-return]
+ return v1.ModelField(**v1_kwargs)
except RuntimeError:
raise fastapi.exceptions.FastAPIError(
_invalid_args_message.format(type_=type_)
@@ -140,11 +138,8 @@ def create_cloned_field(
*,
cloned_types: Optional[MutableMapping[type[BaseModel], type[BaseModel]]] = None,
) -> ModelField:
- if PYDANTIC_V2:
- from ._compat import v2
-
- if isinstance(field, v2.ModelField):
- return field
+ if isinstance(field, v2.ModelField):
+ return field
from fastapi._compat import v1
@@ -154,8 +149,6 @@ def create_cloned_field(
cloned_types = _CLONED_TYPES_CACHE
original_type = field.type_
- if is_dataclass(original_type) and hasattr(original_type, "__pydantic_model__"):
- original_type = original_type.__pydantic_model__
use_type = original_type
if lenient_issubclass(original_type, v1.BaseModel):
original_type = cast(type[v1.BaseModel], original_type)
diff --git a/pyproject.toml b/pyproject.toml
index dd16e1f8fa..ae97cb71bd 100644
--- a/pyproject.toml
+++ b/pyproject.toml
@@ -30,7 +30,6 @@ classifiers = [
"Framework :: AsyncIO",
"Framework :: FastAPI",
"Framework :: Pydantic",
- "Framework :: Pydantic :: 1",
"Framework :: Pydantic :: 2",
"Intended Audience :: Developers",
"Programming Language :: Python :: 3 :: Only",
@@ -45,7 +44,7 @@ classifiers = [
]
dependencies = [
"starlette>=0.40.0,<0.51.0",
- "pydantic>=1.7.4,!=1.8,!=1.8.1,!=2.0.0,!=2.0.1,!=2.1.0,<3.0.0",
+ "pydantic>=2.7.0",
"typing-extensions>=4.8.0",
"annotated-doc>=0.0.2",
]
@@ -71,11 +70,10 @@ standard = [
"email-validator >=2.0.0",
# Uvicorn with uvloop
"uvicorn[standard] >=0.12.0",
- # TODO: this should be part of some pydantic optional extra dependencies
# # Settings management
- # "pydantic-settings >=2.0.0",
+ "pydantic-settings >=2.0.0",
# # Extra Pydantic data types
- # "pydantic-extra-types >=2.0.0",
+ "pydantic-extra-types >=2.0.0",
]
standard-no-fastapi-cloud-cli = [
@@ -90,11 +88,10 @@ standard-no-fastapi-cloud-cli = [
"email-validator >=2.0.0",
# Uvicorn with uvloop
"uvicorn[standard] >=0.12.0",
- # TODO: this should be part of some pydantic optional extra dependencies
# # Settings management
- # "pydantic-settings >=2.0.0",
+ "pydantic-settings >=2.0.0",
# # Extra Pydantic data types
- # "pydantic-extra-types >=2.0.0",
+ "pydantic-extra-types >=2.0.0",
]
all = [
@@ -183,8 +180,6 @@ filterwarnings = [
# Ref: https://github.com/python-trio/trio/pull/3054
# Remove once there's a new version of Trio
'ignore:The `hash` argument is deprecated*:DeprecationWarning:trio',
- # Ignore flaky coverage / pytest warning about SQLite connection, only applies to Python 3.13 and Pydantic v1
- 'ignore:Exception ignored in. = (3, 14):
skip_module_if_py_gte_314()
@@ -588,23 +588,14 @@ def test_openapi_schema():
"required": True,
"content": {
"application/json": {
- "schema": pydantic_snapshot(
- v1=snapshot(
+ "schema": {
+ "title": "Body",
+ "allOf": [
{
"$ref": "#/components/schemas/Body_update_item_items__item_id__put"
}
- ),
- v2=snapshot(
- {
- "title": "Body",
- "allOf": [
- {
- "$ref": "#/components/schemas/Body_update_item_items__item_id__put"
- }
- ],
- }
- ),
- ),
+ ],
+ }
}
},
},
@@ -809,23 +800,14 @@ def test_openapi_schema():
"requestBody": {
"content": {
"application/json": {
- "schema": pydantic_snapshot(
- v1=snapshot(
+ "schema": {
+ "allOf": [
{
"$ref": "#/components/schemas/Body_create_item_embed_items_embed__post"
}
- ),
- v2=snapshot(
- {
- "allOf": [
- {
- "$ref": "#/components/schemas/Body_create_item_embed_items_embed__post"
- }
- ],
- "title": "Body",
- }
- ),
- ),
+ ],
+ "title": "Body",
+ }
}
},
"required": True,
@@ -855,23 +837,14 @@ def test_openapi_schema():
"requestBody": {
"content": {
"application/x-www-form-urlencoded": {
- "schema": pydantic_snapshot(
- v1=snapshot(
+ "schema": {
+ "allOf": [
{
"$ref": "#/components/schemas/Body_submit_form_form_data__post"
}
- ),
- v2=snapshot(
- {
- "allOf": [
- {
- "$ref": "#/components/schemas/Body_submit_form_form_data__post"
- }
- ],
- "title": "Body",
- }
- ),
- ),
+ ],
+ "title": "Body",
+ }
}
},
"required": True,
@@ -901,23 +874,14 @@ def test_openapi_schema():
"requestBody": {
"content": {
"multipart/form-data": {
- "schema": pydantic_snapshot(
- v1=snapshot(
+ "schema": {
+ "allOf": [
{
"$ref": "#/components/schemas/Body_upload_file_upload__post"
}
- ),
- v2=snapshot(
- {
- "allOf": [
- {
- "$ref": "#/components/schemas/Body_upload_file_upload__post"
- }
- ],
- "title": "Body",
- }
- ),
- ),
+ ],
+ "title": "Body",
+ },
}
},
"required": True,
@@ -947,23 +911,14 @@ def test_openapi_schema():
"requestBody": {
"content": {
"multipart/form-data": {
- "schema": pydantic_snapshot(
- v1=snapshot(
+ "schema": {
+ "allOf": [
{
"$ref": "#/components/schemas/Body_upload_multiple_files_upload_multiple__post"
}
- ),
- v2=snapshot(
- {
- "allOf": [
- {
- "$ref": "#/components/schemas/Body_upload_multiple_files_upload_multiple__post"
- }
- ],
- "title": "Body",
- }
- ),
- ),
+ ],
+ "title": "Body",
+ }
}
},
"required": True,
@@ -990,21 +945,12 @@ def test_openapi_schema():
"components": {
"schemas": {
"Body_create_item_embed_items_embed__post": {
- "properties": pydantic_snapshot(
- v1=snapshot(
- {"item": {"$ref": "#/components/schemas/Item"}}
- ),
- v2=snapshot(
- {
- "item": {
- "allOf": [
- {"$ref": "#/components/schemas/Item"}
- ],
- "title": "Item",
- }
- }
- ),
- ),
+ "properties": {
+ "item": {
+ "allOf": [{"$ref": "#/components/schemas/Item"}],
+ "title": "Item",
+ }
+ },
"type": "object",
"required": ["item"],
"title": "Body_create_item_embed_items_embed__post",
@@ -1030,17 +976,10 @@ def test_openapi_schema():
},
"Body_update_item_items__item_id__put": {
"properties": {
- "item": pydantic_snapshot(
- v1=snapshot({"$ref": "#/components/schemas/Item"}),
- v2=snapshot(
- {
- "allOf": [
- {"$ref": "#/components/schemas/Item"}
- ],
- "title": "Item",
- }
- ),
- ),
+ "item": {
+ "allOf": [{"$ref": "#/components/schemas/Item"}],
+ "title": "Item",
+ },
"importance": {
"type": "integer",
"maximum": 10.0,
diff --git a/tests/test_computed_fields.py b/tests/test_computed_fields.py
index f2e42999b3..e7f969f7cf 100644
--- a/tests/test_computed_fields.py
+++ b/tests/test_computed_fields.py
@@ -2,8 +2,6 @@ import pytest
from fastapi import FastAPI
from fastapi.testclient import TestClient
-from .utils import needs_pydanticv2
-
@pytest.fixture(name="client")
def get_client(request):
@@ -35,7 +33,6 @@ def get_client(request):
@pytest.mark.parametrize("client", [True, False], indirect=True)
@pytest.mark.parametrize("path", ["/", "/responses"])
-@needs_pydanticv2
def test_get(client: TestClient, path: str):
response = client.get(path)
assert response.status_code == 200, response.text
@@ -43,7 +40,6 @@ def test_get(client: TestClient, path: str):
@pytest.mark.parametrize("client", [True, False], indirect=True)
-@needs_pydanticv2
def test_openapi_schema(client: TestClient):
response = client.get("/openapi.json")
assert response.status_code == 200, response.text
diff --git a/tests/test_custom_schema_fields.py b/tests/test_custom_schema_fields.py
index bc3e1c5ec3..60b795e9ba 100644
--- a/tests/test_custom_schema_fields.py
+++ b/tests/test_custom_schema_fields.py
@@ -1,12 +1,8 @@
from typing import Annotated, Optional
from fastapi import FastAPI
-from fastapi._compat import PYDANTIC_V2
from fastapi.testclient import TestClient
-from pydantic import BaseModel
-
-if PYDANTIC_V2:
- from pydantic import WithJsonSchema
+from pydantic import BaseModel, WithJsonSchema
app = FastAPI()
@@ -14,23 +10,15 @@ app = FastAPI()
class Item(BaseModel):
name: str
- if PYDANTIC_V2:
- description: Annotated[
- Optional[str], WithJsonSchema({"type": ["string", "null"]})
- ] = None
+ description: Annotated[
+ Optional[str], WithJsonSchema({"type": ["string", "null"]})
+ ] = None
- model_config = {
- "json_schema_extra": {
- "x-something-internal": {"level": 4},
- }
+ model_config = {
+ "json_schema_extra": {
+ "x-something-internal": {"level": 4},
}
- else:
- description: Optional[str] = None # type: ignore[no-redef]
-
- class Config:
- schema_extra = {
- "x-something-internal": {"level": 4},
- }
+ }
@app.get("/foo", response_model=Item)
@@ -55,7 +43,7 @@ item_schema = {
},
"description": {
"title": "Description",
- "type": ["string", "null"] if PYDANTIC_V2 else "string",
+ "type": ["string", "null"],
},
},
}
diff --git a/tests/test_datastructures.py b/tests/test_datastructures.py
index c175147bc3..29a70cae0c 100644
--- a/tests/test_datastructures.py
+++ b/tests/test_datastructures.py
@@ -7,12 +7,6 @@ from fastapi.datastructures import Default
from fastapi.testclient import TestClient
-# TODO: remove when deprecating Pydantic v1
-def test_upload_file_invalid():
- with pytest.raises(ValueError):
- UploadFile.validate("not a Starlette UploadFile")
-
-
def test_upload_file_invalid_pydantic_v2():
with pytest.raises(ValueError):
UploadFile._validate("not a Starlette UploadFile", {})
diff --git a/tests/test_datetime_custom_encoder.py b/tests/test_datetime_custom_encoder.py
index 3aa77c0b1d..822651f4f1 100644
--- a/tests/test_datetime_custom_encoder.py
+++ b/tests/test_datetime_custom_encoder.py
@@ -4,10 +4,9 @@ from fastapi import FastAPI
from fastapi.testclient import TestClient
from pydantic import BaseModel
-from .utils import needs_pydanticv1, needs_pydanticv2
+from .utils import needs_pydanticv1
-@needs_pydanticv2
def test_pydanticv2():
from pydantic import field_serializer
@@ -34,7 +33,9 @@ def test_pydanticv2():
# TODO: remove when deprecating Pydantic v1
@needs_pydanticv1
def test_pydanticv1():
- class ModelWithDatetimeField(BaseModel):
+ from pydantic import v1
+
+ class ModelWithDatetimeField(v1.BaseModel):
dt_field: datetime
class Config:
diff --git a/tests/test_filter_pydantic_sub_model/app_pv1.py b/tests/test_filter_pydantic_sub_model/app_pv1.py
index 657e8c5d12..0b6ab53e04 100644
--- a/tests/test_filter_pydantic_sub_model/app_pv1.py
+++ b/tests/test_filter_pydantic_sub_model/app_pv1.py
@@ -1,7 +1,7 @@
from typing import Optional
from fastapi import Depends, FastAPI
-from pydantic import BaseModel, validator
+from pydantic.v1 import BaseModel, validator
app = FastAPI()
@@ -18,6 +18,7 @@ class ModelA(BaseModel):
name: str
description: Optional[str] = None
model_b: ModelB
+ tags: dict[str, str] = {}
@validator("name")
def lower_username(cls, name: str, values):
@@ -32,4 +33,9 @@ async def get_model_c() -> ModelC:
@app.get("/model/{name}", response_model=ModelA)
async def get_model_a(name: str, model_c=Depends(get_model_c)):
- return {"name": name, "description": "model-a-desc", "model_b": model_c}
+ return {
+ "name": name,
+ "description": "model-a-desc",
+ "model_b": model_c,
+ "tags": {"key1": "value1", "key2": "value2"},
+ }
diff --git a/tests/test_filter_pydantic_sub_model/test_filter_pydantic_sub_model_pv1.py b/tests/test_filter_pydantic_sub_model/test_filter_pydantic_sub_model_pv1.py
index 48732dbf06..b464b4f572 100644
--- a/tests/test_filter_pydantic_sub_model/test_filter_pydantic_sub_model_pv1.py
+++ b/tests/test_filter_pydantic_sub_model/test_filter_pydantic_sub_model_pv1.py
@@ -1,6 +1,7 @@
import pytest
from fastapi.exceptions import ResponseValidationError
from fastapi.testclient import TestClient
+from inline_snapshot import snapshot
from ..utils import needs_pydanticv1
@@ -21,6 +22,7 @@ def test_filter_sub_model(client: TestClient):
"name": "modelA",
"description": "model-a-desc",
"model_b": {"username": "test-user"},
+ "tags": {"key1": "value1", "key2": "value2"},
}
@@ -41,90 +43,104 @@ def test_validator_is_cloned(client: TestClient):
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": {
- "/model/{name}": {
- "get": {
- "summary": "Get Model A",
- "operationId": "get_model_a_model__name__get",
- "parameters": [
- {
- "required": True,
- "schema": {"title": "Name", "type": "string"},
- "name": "name",
- "in": "path",
- }
- ],
- "responses": {
- "200": {
- "description": "Successful Response",
- "content": {
- "application/json": {
- "schema": {"$ref": "#/components/schemas/ModelA"}
- }
+ assert response.json() == snapshot(
+ {
+ "openapi": "3.1.0",
+ "info": {"title": "FastAPI", "version": "0.1.0"},
+ "paths": {
+ "/model/{name}": {
+ "get": {
+ "summary": "Get Model A",
+ "operationId": "get_model_a_model__name__get",
+ "parameters": [
+ {
+ "required": True,
+ "schema": {"title": "Name", "type": "string"},
+ "name": "name",
+ "in": "path",
+ }
+ ],
+ "responses": {
+ "200": {
+ "description": "Successful Response",
+ "content": {
+ "application/json": {
+ "schema": {
+ "$ref": "#/components/schemas/ModelA"
+ }
+ }
+ },
+ },
+ "422": {
+ "description": "Validation Error",
+ "content": {
+ "application/json": {
+ "schema": {
+ "$ref": "#/components/schemas/HTTPValidationError"
+ }
+ }
+ },
},
},
- "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"
+ },
+ }
+ },
+ },
+ "ModelA": {
+ "title": "ModelA",
+ "required": ["name", "model_b"],
+ "type": "object",
+ "properties": {
+ "name": {"title": "Name", "type": "string"},
+ "description": {"title": "Description", "type": "string"},
+ "model_b": {"$ref": "#/components/schemas/ModelB"},
+ "tags": {
+ "additionalProperties": {"type": "string"},
+ "type": "object",
+ "title": "Tags",
+ "default": {},
},
},
},
+ "ModelB": {
+ "title": "ModelB",
+ "required": ["username"],
+ "type": "object",
+ "properties": {
+ "username": {"title": "Username", "type": "string"}
+ },
+ },
+ "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"},
+ },
+ },
}
- }
- },
- "components": {
- "schemas": {
- "HTTPValidationError": {
- "title": "HTTPValidationError",
- "type": "object",
- "properties": {
- "detail": {
- "title": "Detail",
- "type": "array",
- "items": {"$ref": "#/components/schemas/ValidationError"},
- }
- },
- },
- "ModelA": {
- "title": "ModelA",
- "required": ["name", "model_b"],
- "type": "object",
- "properties": {
- "name": {"title": "Name", "type": "string"},
- "description": {"title": "Description", "type": "string"},
- "model_b": {"$ref": "#/components/schemas/ModelB"},
- },
- },
- "ModelB": {
- "title": "ModelB",
- "required": ["username"],
- "type": "object",
- "properties": {"username": {"title": "Username", "type": "string"}},
- },
- "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_filter_pydantic_sub_model_pv2.py b/tests/test_filter_pydantic_sub_model_pv2.py
index 2e2c26ddcb..d70f530435 100644
--- a/tests/test_filter_pydantic_sub_model_pv2.py
+++ b/tests/test_filter_pydantic_sub_model_pv2.py
@@ -5,8 +5,7 @@ from dirty_equals import HasRepr, IsDict, IsOneOf
from fastapi import Depends, FastAPI
from fastapi.exceptions import ResponseValidationError
from fastapi.testclient import TestClient
-
-from .utils import needs_pydanticv2
+from inline_snapshot import snapshot
@pytest.fixture(name="client")
@@ -25,6 +24,7 @@ def get_client():
name: str
description: Optional[str] = None
foo: ModelB
+ tags: dict[str, str] = {}
@field_validator("name")
def lower_username(cls, name: str, info: ValidationInfo):
@@ -37,13 +37,17 @@ def get_client():
@app.get("/model/{name}", response_model=ModelA)
async def get_model_a(name: str, model_c=Depends(get_model_c)):
- return {"name": name, "description": "model-a-desc", "foo": model_c}
+ return {
+ "name": name,
+ "description": "model-a-desc",
+ "foo": model_c,
+ "tags": {"key1": "value1", "key2": "value2"},
+ }
client = TestClient(app)
return client
-@needs_pydanticv2
def test_filter_sub_model(client: TestClient):
response = client.get("/model/modelA")
assert response.status_code == 200, response.text
@@ -51,10 +55,10 @@ def test_filter_sub_model(client: TestClient):
"name": "modelA",
"description": "model-a-desc",
"foo": {"username": "test-user"},
+ "tags": {"key1": "value1", "key2": "value2"},
}
-@needs_pydanticv2
def test_validator_is_cloned(client: TestClient):
with pytest.raises(ResponseValidationError) as err:
client.get("/model/modelX")
@@ -79,106 +83,119 @@ def test_validator_is_cloned(client: TestClient):
]
-@needs_pydanticv2
def test_openapi_schema(client: TestClient):
response = client.get("/openapi.json")
assert response.status_code == 200, response.text
- assert response.json() == {
- "openapi": "3.1.0",
- "info": {"title": "FastAPI", "version": "0.1.0"},
- "paths": {
- "/model/{name}": {
- "get": {
- "summary": "Get Model A",
- "operationId": "get_model_a_model__name__get",
- "parameters": [
- {
- "required": True,
- "schema": {"title": "Name", "type": "string"},
- "name": "name",
- "in": "path",
- }
- ],
- "responses": {
- "200": {
- "description": "Successful Response",
- "content": {
- "application/json": {
- "schema": {"$ref": "#/components/schemas/ModelA"}
- }
+ assert response.json() == snapshot(
+ {
+ "openapi": "3.1.0",
+ "info": {"title": "FastAPI", "version": "0.1.0"},
+ "paths": {
+ "/model/{name}": {
+ "get": {
+ "summary": "Get Model A",
+ "operationId": "get_model_a_model__name__get",
+ "parameters": [
+ {
+ "required": True,
+ "schema": {"title": "Name", "type": "string"},
+ "name": "name",
+ "in": "path",
+ }
+ ],
+ "responses": {
+ "200": {
+ "description": "Successful Response",
+ "content": {
+ "application/json": {
+ "schema": {
+ "$ref": "#/components/schemas/ModelA"
+ }
+ }
+ },
+ },
+ "422": {
+ "description": "Validation Error",
+ "content": {
+ "application/json": {
+ "schema": {
+ "$ref": "#/components/schemas/HTTPValidationError"
+ }
+ }
+ },
},
},
- "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"
+ },
+ }
+ },
+ },
+ "ModelA": {
+ "title": "ModelA",
+ "required": IsOneOf(
+ ["name", "description", "foo"],
+ # TODO remove when deprecating Pydantic v1
+ ["name", "foo"],
+ ),
+ "type": "object",
+ "properties": {
+ "name": {"title": "Name", "type": "string"},
+ "description": IsDict(
+ {
+ "title": "Description",
+ "anyOf": [{"type": "string"}, {"type": "null"}],
}
+ )
+ |
+ # TODO remove when deprecating Pydantic v1
+ IsDict({"title": "Description", "type": "string"}),
+ "foo": {"$ref": "#/components/schemas/ModelB"},
+ "tags": {
+ "additionalProperties": {"type": "string"},
+ "type": "object",
+ "title": "Tags",
+ "default": {},
},
},
},
+ "ModelB": {
+ "title": "ModelB",
+ "required": ["username"],
+ "type": "object",
+ "properties": {
+ "username": {"title": "Username", "type": "string"}
+ },
+ },
+ "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"},
+ },
+ },
}
- }
- },
- "components": {
- "schemas": {
- "HTTPValidationError": {
- "title": "HTTPValidationError",
- "type": "object",
- "properties": {
- "detail": {
- "title": "Detail",
- "type": "array",
- "items": {"$ref": "#/components/schemas/ValidationError"},
- }
- },
- },
- "ModelA": {
- "title": "ModelA",
- "required": IsOneOf(
- ["name", "description", "foo"],
- # TODO remove when deprecating Pydantic v1
- ["name", "foo"],
- ),
- "type": "object",
- "properties": {
- "name": {"title": "Name", "type": "string"},
- "description": IsDict(
- {
- "title": "Description",
- "anyOf": [{"type": "string"}, {"type": "null"}],
- }
- )
- |
- # TODO remove when deprecating Pydantic v1
- IsDict({"title": "Description", "type": "string"}),
- "foo": {"$ref": "#/components/schemas/ModelB"},
- },
- },
- "ModelB": {
- "title": "ModelB",
- "required": ["username"],
- "type": "object",
- "properties": {"username": {"title": "Username", "type": "string"}},
- },
- "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_forms_single_model.py b/tests/test_forms_single_model.py
index b149b76539..c401cc9374 100644
--- a/tests/test_forms_single_model.py
+++ b/tests/test_forms_single_model.py
@@ -2,7 +2,6 @@ from typing import Annotated, Optional
from dirty_equals import IsDict
from fastapi import FastAPI, Form
-from fastapi._compat import PYDANTIC_V2
from fastapi.testclient import TestClient
from pydantic import BaseModel, Field
@@ -20,12 +19,7 @@ class FormModel(BaseModel):
class FormModelExtraAllow(BaseModel):
param: str
- if PYDANTIC_V2:
- model_config = {"extra": "allow"}
- else:
-
- class Config:
- extra = "allow"
+ model_config = {"extra": "allow"}
@app.post("/form/")
diff --git a/tests/test_get_model_definitions_formfeed_escape.py b/tests/test_get_model_definitions_formfeed_escape.py
index 215d06a072..50d799a571 100644
--- a/tests/test_get_model_definitions_formfeed_escape.py
+++ b/tests/test_get_model_definitions_formfeed_escape.py
@@ -1,181 +1,169 @@
-from collections.abc import Iterator
-from typing import Any
-
-import fastapi._compat
-import fastapi.openapi.utils
-import pydantic.schema
import pytest
from fastapi import FastAPI
-from pydantic import BaseModel
-from starlette.testclient import TestClient
+from fastapi.testclient import TestClient
+from inline_snapshot import snapshot
from .utils import needs_pydanticv1
-class Address(BaseModel):
- """
- This is a public description of an Address
- \f
- You can't see this part of the docstring, it's private!
- """
+@pytest.fixture(
+ name="client",
+ params=[
+ pytest.param("pydantic-v1", marks=needs_pydanticv1),
+ "pydantic-v2",
+ ],
+)
+def client_fixture(request: pytest.FixtureRequest) -> TestClient:
+ if request.param == "pydantic-v1":
+ from pydantic.v1 import BaseModel
+ else:
+ from pydantic import BaseModel
- line_1: str
- city: str
- state_province: str
+ class Address(BaseModel):
+ """
+ This is a public description of an Address
+ \f
+ You can't see this part of the docstring, it's private!
+ """
+
+ line_1: str
+ city: str
+ state_province: str
+
+ class Facility(BaseModel):
+ id: str
+ address: Address
+
+ app = FastAPI()
+
+ @app.get("/facilities/{facility_id}")
+ def get_facility(facility_id: str) -> Facility:
+ return Facility(
+ id=facility_id,
+ address=Address(line_1="123 Main St", city="Anytown", state_province="CA"),
+ )
+
+ client = TestClient(app)
+ return client
-class Facility(BaseModel):
- id: str
- address: Address
+def test_get(client: TestClient):
+ response = client.get("/facilities/42")
+ assert response.status_code == 200, response.text
+ assert response.json() == {
+ "id": "42",
+ "address": {
+ "line_1": "123 Main St",
+ "city": "Anytown",
+ "state_province": "CA",
+ },
+ }
-app = FastAPI()
-
-client = TestClient(app)
-
-
-@app.get("/facilities/{facility_id}")
-def get_facility(facility_id: str) -> Facility: ...
-
-
-openapi_schema = {
- "components": {
- "schemas": {
- "Address": {
- # NOTE: the description of this model shows only the public-facing text, before the `\f` in docstring
- "description": "This is a public description of an Address\n",
- "properties": {
- "city": {"title": "City", "type": "string"},
- "line_1": {"title": "Line 1", "type": "string"},
- "state_province": {"title": "State Province", "type": "string"},
- },
- "required": ["line_1", "city", "state_province"],
- "title": "Address",
- "type": "object",
- },
- "Facility": {
- "properties": {
- "address": {"$ref": "#/components/schemas/Address"},
- "id": {"title": "Id", "type": "string"},
- },
- "required": ["id", "address"],
- "title": "Facility",
- "type": "object",
- },
- "HTTPValidationError": {
- "properties": {
- "detail": {
- "items": {"$ref": "#/components/schemas/ValidationError"},
- "title": "Detail",
- "type": "array",
- }
- },
- "title": "HTTPValidationError",
- "type": "object",
- },
- "ValidationError": {
- "properties": {
- "loc": {
- "items": {"anyOf": [{"type": "string"}, {"type": "integer"}]},
- "title": "Location",
- "type": "array",
- },
- "msg": {"title": "Message", "type": "string"},
- "type": {"title": "Error Type", "type": "string"},
- },
- "required": ["loc", "msg", "type"],
- "title": "ValidationError",
- "type": "object",
- },
- }
- },
- "info": {"title": "FastAPI", "version": "0.1.0"},
- "openapi": "3.1.0",
- "paths": {
- "/facilities/{facility_id}": {
- "get": {
- "operationId": "get_facility_facilities__facility_id__get",
- "parameters": [
- {
- "in": "path",
- "name": "facility_id",
- "required": True,
- "schema": {"title": "Facility Id", "type": "string"},
- }
- ],
- "responses": {
- "200": {
- "content": {
- "application/json": {
- "schema": {"$ref": "#/components/schemas/Facility"}
- }
- },
- "description": "Successful Response",
- },
- "422": {
- "content": {
- "application/json": {
- "schema": {
- "$ref": "#/components/schemas/HTTPValidationError"
- }
- }
- },
- "description": "Validation Error",
- },
- },
- "summary": "Get Facility",
- }
- }
- },
-}
-
-
-def test_openapi_schema():
+def test_openapi_schema(client: TestClient):
"""
Sanity check to ensure our app's openapi schema renders as we expect
"""
response = client.get("/openapi.json")
assert response.status_code == 200, response.text
- assert response.json() == openapi_schema
-
-
-class SortedTypeSet(set):
- """
- Set of Types whose `__iter__()` method yields results sorted by the type names
- """
-
- def __init__(self, seq: set[type[Any]], *, sort_reversed: bool):
- super().__init__(seq)
- self.sort_reversed = sort_reversed
-
- def __iter__(self) -> Iterator[type[Any]]:
- members_sorted = sorted(
- super().__iter__(),
- key=lambda type_: type_.__name__,
- reverse=self.sort_reversed,
- )
- yield from members_sorted
-
-
-@needs_pydanticv1
-@pytest.mark.parametrize("sort_reversed", [True, False])
-def test_model_description_escaped_with_formfeed(sort_reversed: bool):
- """
- Regression test for bug fixed by https://github.com/fastapi/fastapi/pull/6039.
-
- Test `get_model_definitions` with models passed in different order.
- """
- from fastapi._compat import v1
-
- all_fields = fastapi.openapi.utils.get_fields_from_routes(app.routes)
-
- flat_models = v1.get_flat_models_from_fields(all_fields, known_models=set())
- model_name_map = pydantic.schema.get_model_name_map(flat_models)
-
- expected_address_description = "This is a public description of an Address\n"
-
- models = v1.get_model_definitions(
- flat_models=SortedTypeSet(flat_models, sort_reversed=sort_reversed),
- model_name_map=model_name_map,
+ assert response.json() == snapshot(
+ {
+ "components": {
+ "schemas": {
+ "Address": {
+ # NOTE: the description of this model shows only the public-facing text, before the `\f` in docstring
+ "description": "This is a public description of an Address\n",
+ "properties": {
+ "city": {"title": "City", "type": "string"},
+ "line_1": {"title": "Line 1", "type": "string"},
+ "state_province": {
+ "title": "State Province",
+ "type": "string",
+ },
+ },
+ "required": ["line_1", "city", "state_province"],
+ "title": "Address",
+ "type": "object",
+ },
+ "Facility": {
+ "properties": {
+ "address": {"$ref": "#/components/schemas/Address"},
+ "id": {"title": "Id", "type": "string"},
+ },
+ "required": ["id", "address"],
+ "title": "Facility",
+ "type": "object",
+ },
+ "HTTPValidationError": {
+ "properties": {
+ "detail": {
+ "items": {
+ "$ref": "#/components/schemas/ValidationError"
+ },
+ "title": "Detail",
+ "type": "array",
+ }
+ },
+ "title": "HTTPValidationError",
+ "type": "object",
+ },
+ "ValidationError": {
+ "properties": {
+ "loc": {
+ "items": {
+ "anyOf": [{"type": "string"}, {"type": "integer"}]
+ },
+ "title": "Location",
+ "type": "array",
+ },
+ "msg": {"title": "Message", "type": "string"},
+ "type": {"title": "Error Type", "type": "string"},
+ },
+ "required": ["loc", "msg", "type"],
+ "title": "ValidationError",
+ "type": "object",
+ },
+ }
+ },
+ "info": {"title": "FastAPI", "version": "0.1.0"},
+ "openapi": "3.1.0",
+ "paths": {
+ "/facilities/{facility_id}": {
+ "get": {
+ "operationId": "get_facility_facilities__facility_id__get",
+ "parameters": [
+ {
+ "in": "path",
+ "name": "facility_id",
+ "required": True,
+ "schema": {"title": "Facility Id", "type": "string"},
+ }
+ ],
+ "responses": {
+ "200": {
+ "content": {
+ "application/json": {
+ "schema": {
+ "$ref": "#/components/schemas/Facility"
+ }
+ }
+ },
+ "description": "Successful Response",
+ },
+ "422": {
+ "content": {
+ "application/json": {
+ "schema": {
+ "$ref": "#/components/schemas/HTTPValidationError"
+ }
+ }
+ },
+ "description": "Validation Error",
+ },
+ },
+ "summary": "Get Facility",
+ }
+ }
+ },
+ }
)
- assert models["Address"]["description"] == expected_address_description
diff --git a/tests/test_inherited_custom_class.py b/tests/test_inherited_custom_class.py
index fe9350f4ef..7f29fe33ed 100644
--- a/tests/test_inherited_custom_class.py
+++ b/tests/test_inherited_custom_class.py
@@ -5,7 +5,7 @@ from fastapi import FastAPI
from fastapi.testclient import TestClient
from pydantic import BaseModel
-from .utils import needs_pydanticv1, needs_pydanticv2
+from .utils import needs_pydanticv1
class MyUuid:
@@ -26,7 +26,6 @@ class MyUuid:
raise TypeError("vars() argument must have __dict__ attribute")
-@needs_pydanticv2
def test_pydanticv2():
from pydantic import field_serializer
@@ -73,6 +72,8 @@ def test_pydanticv2():
# TODO: remove when deprecating Pydantic v1
@needs_pydanticv1
def test_pydanticv1():
+ from pydantic import v1
+
app = FastAPI()
@app.get("/fast_uuid")
@@ -84,7 +85,7 @@ def test_pydanticv1():
vars(asyncpg_uuid)
return {"fast_uuid": asyncpg_uuid}
- class SomeCustomClass(BaseModel):
+ class SomeCustomClass(v1.BaseModel):
class Config:
arbitrary_types_allowed = True
json_encoders = {uuid.UUID: str}
diff --git a/tests/test_jsonable_encoder.py b/tests/test_jsonable_encoder.py
index 3b6513e27b..81bf94ece0 100644
--- a/tests/test_jsonable_encoder.py
+++ b/tests/test_jsonable_encoder.py
@@ -8,11 +8,11 @@ from pathlib import PurePath, PurePosixPath, PureWindowsPath
from typing import Optional
import pytest
-from fastapi._compat import PYDANTIC_V2, Undefined
+from fastapi._compat import Undefined
from fastapi.encoders import jsonable_encoder
from pydantic import BaseModel, Field, ValidationError
-from .utils import needs_pydanticv1, needs_pydanticv2
+from .utils import needs_pydanticv1
class Person:
@@ -59,12 +59,7 @@ class RoleEnum(Enum):
class ModelWithConfig(BaseModel):
role: Optional[RoleEnum] = None
- if PYDANTIC_V2:
- model_config = {"use_enum_values": True}
- else:
-
- class Config:
- use_enum_values = True
+ model_config = {"use_enum_values": True}
class ModelWithAlias(BaseModel):
@@ -89,6 +84,18 @@ def test_encode_dict():
}
+def test_encode_dict_include_exclude_list():
+ pet = {"name": "Firulais", "owner": {"name": "Foo"}}
+ assert jsonable_encoder(pet) == {"name": "Firulais", "owner": {"name": "Foo"}}
+ assert jsonable_encoder(pet, include=["name"]) == {"name": "Firulais"}
+ assert jsonable_encoder(pet, exclude=["owner"]) == {"name": "Firulais"}
+ assert jsonable_encoder(pet, include=[]) == {}
+ assert jsonable_encoder(pet, exclude=[]) == {
+ "name": "Firulais",
+ "owner": {"name": "Foo"},
+ }
+
+
def test_encode_class():
person = Person(name="Foo")
pet = Pet(owner=person, name="Firulais")
@@ -130,7 +137,6 @@ def test_encode_unsupported():
jsonable_encoder(unserializable)
-@needs_pydanticv2
def test_encode_custom_json_encoders_model_pydanticv2():
from pydantic import field_serializer
@@ -153,7 +159,9 @@ def test_encode_custom_json_encoders_model_pydanticv2():
# TODO: remove when deprecating Pydantic v1
@needs_pydanticv1
def test_encode_custom_json_encoders_model_pydanticv1():
- class ModelWithCustomEncoder(BaseModel):
+ from pydantic import v1
+
+ class ModelWithCustomEncoder(v1.BaseModel):
dt_field: datetime
class Config:
@@ -208,10 +216,12 @@ def test_encode_model_with_default():
@needs_pydanticv1
def test_custom_encoders():
+ from pydantic import v1
+
class safe_datetime(datetime):
pass
- class MyModel(BaseModel):
+ class MyModel(v1.BaseModel):
dt_field: safe_datetime
instance = MyModel(dt_field=safe_datetime.now())
@@ -244,12 +254,7 @@ def test_encode_model_with_pure_path():
class ModelWithPath(BaseModel):
path: PurePath
- if PYDANTIC_V2:
- model_config = {"arbitrary_types_allowed": True}
- else:
-
- class Config:
- arbitrary_types_allowed = True
+ model_config = {"arbitrary_types_allowed": True}
test_path = PurePath("/foo", "bar")
obj = ModelWithPath(path=test_path)
@@ -260,12 +265,7 @@ def test_encode_model_with_pure_posix_path():
class ModelWithPath(BaseModel):
path: PurePosixPath
- if PYDANTIC_V2:
- model_config = {"arbitrary_types_allowed": True}
- else:
-
- class Config:
- arbitrary_types_allowed = True
+ model_config = {"arbitrary_types_allowed": True}
obj = ModelWithPath(path=PurePosixPath("/foo", "bar"))
assert jsonable_encoder(obj) == {"path": "/foo/bar"}
@@ -275,45 +275,44 @@ def test_encode_model_with_pure_windows_path():
class ModelWithPath(BaseModel):
path: PureWindowsPath
- if PYDANTIC_V2:
- model_config = {"arbitrary_types_allowed": True}
- else:
-
- class Config:
- arbitrary_types_allowed = True
+ model_config = {"arbitrary_types_allowed": True}
obj = ModelWithPath(path=PureWindowsPath("/foo", "bar"))
assert jsonable_encoder(obj) == {"path": "\\foo\\bar"}
+def test_encode_pure_path():
+ test_path = PurePath("/foo", "bar")
+
+ assert jsonable_encoder({"path": test_path}) == {"path": str(test_path)}
+
+
@needs_pydanticv1
def test_encode_root():
- class ModelWithRoot(BaseModel):
+ from pydantic import v1
+
+ class ModelWithRoot(v1.BaseModel):
__root__: str
model = ModelWithRoot(__root__="Foo")
assert jsonable_encoder(model) == "Foo"
-@needs_pydanticv2
def test_decimal_encoder_float():
data = {"value": Decimal(1.23)}
assert jsonable_encoder(data) == {"value": 1.23}
-@needs_pydanticv2
def test_decimal_encoder_int():
data = {"value": Decimal(2)}
assert jsonable_encoder(data) == {"value": 2}
-@needs_pydanticv2
def test_decimal_encoder_nan():
data = {"value": Decimal("NaN")}
assert isnan(jsonable_encoder(data)["value"])
-@needs_pydanticv2
def test_decimal_encoder_infinity():
data = {"value": Decimal("Infinity")}
assert isinf(jsonable_encoder(data)["value"])
@@ -330,7 +329,6 @@ def test_encode_deque_encodes_child_models():
assert jsonable_encoder(dq)[0]["test"] == "test"
-@needs_pydanticv2
def test_encode_pydantic_undefined():
data = {"value": Undefined}
assert jsonable_encoder(data) == {"value": None}
diff --git a/tests/test_no_schema_split.py b/tests/test_no_schema_split.py
index 6169867ba3..131a3755e7 100644
--- a/tests/test_no_schema_split.py
+++ b/tests/test_no_schema_split.py
@@ -9,8 +9,6 @@ from fastapi.testclient import TestClient
from inline_snapshot import snapshot
from pydantic import BaseModel, Field
-from tests.utils import pydantic_snapshot
-
class MessageEventType(str, Enum):
alpha = "alpha"
@@ -126,47 +124,21 @@ def test_openapi_schema():
},
"MessageEvent": {
"properties": {
- "event_type": pydantic_snapshot(
- v2=snapshot(
- {
- "$ref": "#/components/schemas/MessageEventType",
- "default": "alpha",
- }
- ),
- v1=snapshot(
- {
- "allOf": [
- {
- "$ref": "#/components/schemas/MessageEventType"
- }
- ],
- "default": "alpha",
- }
- ),
- ),
+ "event_type": {
+ "$ref": "#/components/schemas/MessageEventType",
+ "default": "alpha",
+ },
"output": {"type": "string", "title": "Output"},
},
"type": "object",
"required": ["output"],
"title": "MessageEvent",
},
- "MessageEventType": pydantic_snapshot(
- v2=snapshot(
- {
- "type": "string",
- "enum": ["alpha", "beta"],
- "title": "MessageEventType",
- }
- ),
- v1=snapshot(
- {
- "type": "string",
- "enum": ["alpha", "beta"],
- "title": "MessageEventType",
- "description": "An enumeration.",
- }
- ),
- ),
+ "MessageEventType": {
+ "type": "string",
+ "enum": ["alpha", "beta"],
+ "title": "MessageEventType",
+ },
"MessageOutput": {
"properties": {
"body": {"type": "string", "title": "Body", "default": ""},
diff --git a/tests/test_openapi_separate_input_output_schemas.py b/tests/test_openapi_separate_input_output_schemas.py
index bfe5e9a712..1891f0bde0 100644
--- a/tests/test_openapi_separate_input_output_schemas.py
+++ b/tests/test_openapi_separate_input_output_schemas.py
@@ -3,37 +3,30 @@ from typing import Optional
from fastapi import FastAPI
from fastapi.testclient import TestClient
from inline_snapshot import snapshot
-from pydantic import BaseModel
-
-from .utils import PYDANTIC_V2, needs_pydanticv2
+from pydantic import BaseModel, computed_field
class SubItem(BaseModel):
subname: str
sub_description: Optional[str] = None
tags: list[str] = []
- if PYDANTIC_V2:
- model_config = {"json_schema_serialization_defaults_required": True}
+ model_config = {"json_schema_serialization_defaults_required": True}
class Item(BaseModel):
name: str
description: Optional[str] = None
sub: Optional[SubItem] = None
- if PYDANTIC_V2:
- model_config = {"json_schema_serialization_defaults_required": True}
+ model_config = {"json_schema_serialization_defaults_required": True}
-if PYDANTIC_V2:
- from pydantic import computed_field
+class WithComputedField(BaseModel):
+ name: str
- class WithComputedField(BaseModel):
- name: str
-
- @computed_field
- @property
- def computed_field(self) -> str:
- return f"computed {self.name}"
+ @computed_field
+ @property
+ def computed_field(self) -> str:
+ return f"computed {self.name}"
def get_app_client(separate_input_output_schemas: bool = True) -> TestClient:
@@ -58,13 +51,11 @@ def get_app_client(separate_input_output_schemas: bool = True) -> TestClient:
Item(name="Plumbus"),
]
- if PYDANTIC_V2:
-
- @app.post("/with-computed-field/")
- def create_with_computed_field(
- with_computed_field: WithComputedField,
- ) -> WithComputedField:
- return with_computed_field
+ @app.post("/with-computed-field/")
+ def create_with_computed_field(
+ with_computed_field: WithComputedField,
+ ) -> WithComputedField:
+ return with_computed_field
client = TestClient(app)
return client
@@ -151,7 +142,6 @@ def test_read_items():
)
-@needs_pydanticv2
def test_with_computed_field():
client = get_app_client()
client_no = get_app_client(separate_input_output_schemas=False)
@@ -168,7 +158,6 @@ def test_with_computed_field():
)
-@needs_pydanticv2
def test_openapi_schema():
client = get_app_client()
response = client.get("/openapi.json")
@@ -449,7 +438,6 @@ def test_openapi_schema():
)
-@needs_pydanticv2
def test_openapi_schema_no_separate():
client = get_app_client(separate_input_output_schemas=False)
response = client.get("/openapi.json")
diff --git a/tests/test_pydantic_v1_v2_01.py b/tests/test_pydantic_v1_v2_01.py
index ebf86b99f0..83536cafa2 100644
--- a/tests/test_pydantic_v1_v2_01.py
+++ b/tests/test_pydantic_v1_v2_01.py
@@ -1,7 +1,7 @@
import sys
from typing import Any, Union
-from tests.utils import pydantic_snapshot, skip_module_if_py_gte_314
+from tests.utils import skip_module_if_py_gte_314
if sys.version_info >= (3, 14):
skip_module_if_py_gte_314()
@@ -225,21 +225,12 @@ def test_openapi_schema():
"requestBody": {
"content": {
"application/json": {
- "schema": pydantic_snapshot(
- v2=snapshot(
- {
- "allOf": [
- {
- "$ref": "#/components/schemas/SubItem"
- }
- ],
- "title": "Data",
- }
- ),
- v1=snapshot(
+ "schema": {
+ "allOf": [
{"$ref": "#/components/schemas/SubItem"}
- ),
- )
+ ],
+ "title": "Data",
+ }
}
},
"required": True,
@@ -275,21 +266,12 @@ def test_openapi_schema():
"requestBody": {
"content": {
"application/json": {
- "schema": pydantic_snapshot(
- v2=snapshot(
- {
- "allOf": [
- {
- "$ref": "#/components/schemas/SubItem"
- }
- ],
- "title": "Data",
- }
- ),
- v1=snapshot(
+ "schema": {
+ "allOf": [
{"$ref": "#/components/schemas/SubItem"}
- ),
- )
+ ],
+ "title": "Data",
+ }
}
},
"required": True,
@@ -325,21 +307,12 @@ def test_openapi_schema():
"requestBody": {
"content": {
"application/json": {
- "schema": pydantic_snapshot(
- v2=snapshot(
- {
- "allOf": [
- {
- "$ref": "#/components/schemas/Item"
- }
- ],
- "title": "Data",
- }
- ),
- v1=snapshot(
+ "schema": {
+ "allOf": [
{"$ref": "#/components/schemas/Item"}
- ),
- )
+ ],
+ "title": "Data",
+ }
}
},
"required": True,
@@ -373,21 +346,12 @@ def test_openapi_schema():
"requestBody": {
"content": {
"application/json": {
- "schema": pydantic_snapshot(
- v2=snapshot(
- {
- "allOf": [
- {
- "$ref": "#/components/schemas/Item"
- }
- ],
- "title": "Data",
- }
- ),
- v1=snapshot(
+ "schema": {
+ "allOf": [
{"$ref": "#/components/schemas/Item"}
- ),
- )
+ ],
+ "title": "Data",
+ }
}
},
"required": True,
diff --git a/tests/test_pydantic_v1_v2_list.py b/tests/test_pydantic_v1_v2_list.py
index 8879b010de..4ddcbf240d 100644
--- a/tests/test_pydantic_v1_v2_list.py
+++ b/tests/test_pydantic_v1_v2_list.py
@@ -1,7 +1,7 @@
import sys
from typing import Any, Union
-from tests.utils import pydantic_snapshot, skip_module_if_py_gte_314
+from tests.utils import skip_module_if_py_gte_314
if sys.version_info >= (3, 14):
skip_module_if_py_gte_314()
@@ -375,21 +375,12 @@ def test_openapi_schema():
"requestBody": {
"content": {
"application/json": {
- "schema": pydantic_snapshot(
- v2=snapshot(
- {
- "allOf": [
- {
- "$ref": "#/components/schemas/Item"
- }
- ],
- "title": "Data",
- }
- ),
- v1=snapshot(
+ "schema": {
+ "allOf": [
{"$ref": "#/components/schemas/Item"}
- ),
- )
+ ],
+ "title": "Data",
+ }
}
},
"required": True,
@@ -429,21 +420,12 @@ def test_openapi_schema():
"requestBody": {
"content": {
"application/json": {
- "schema": pydantic_snapshot(
- v2=snapshot(
- {
- "allOf": [
- {
- "$ref": "#/components/schemas/Item"
- }
- ],
- "title": "Data",
- }
- ),
- v1=snapshot(
+ "schema": {
+ "allOf": [
{"$ref": "#/components/schemas/Item"}
- ),
- )
+ ],
+ "title": "Data",
+ }
}
},
"required": True,
diff --git a/tests/test_pydantic_v1_v2_mixed.py b/tests/test_pydantic_v1_v2_mixed.py
index e66583cd54..61e5bb5827 100644
--- a/tests/test_pydantic_v1_v2_mixed.py
+++ b/tests/test_pydantic_v1_v2_mixed.py
@@ -1,7 +1,7 @@
import sys
from typing import Any, Union
-from tests.utils import pydantic_snapshot, skip_module_if_py_gte_314
+from tests.utils import skip_module_if_py_gte_314
if sys.version_info >= (3, 14):
skip_module_if_py_gte_314()
@@ -668,38 +668,20 @@ def test_v2_to_v1_validation_error():
assert response.status_code == 422, response.text
assert response.json() == snapshot(
{
- "detail": pydantic_snapshot(
- v2=snapshot(
- [
- {
- "type": "missing",
- "loc": ["body", "new_size"],
- "msg": "Field required",
- "input": {"new_title": "Missing fields"},
- },
- {
- "type": "missing",
- "loc": ["body", "new_sub"],
- "msg": "Field required",
- "input": {"new_title": "Missing fields"},
- },
- ]
- ),
- v1=snapshot(
- [
- {
- "loc": ["body", "new_size"],
- "msg": "field required",
- "type": "value_error.missing",
- },
- {
- "loc": ["body", "new_sub"],
- "msg": "field required",
- "type": "value_error.missing",
- },
- ]
- ),
- )
+ "detail": [
+ {
+ "type": "missing",
+ "loc": ["body", "new_size"],
+ "msg": "Field required",
+ "input": {"new_title": "Missing fields"},
+ },
+ {
+ "type": "missing",
+ "loc": ["body", "new_sub"],
+ "msg": "Field required",
+ "input": {"new_title": "Missing fields"},
+ },
+ ]
}
)
@@ -717,23 +699,12 @@ def test_v2_to_v1_nested_validation_error():
assert response.json() == snapshot(
{
"detail": [
- pydantic_snapshot(
- v2=snapshot(
- {
- "type": "missing",
- "loc": ["body", "new_sub", "new_sub_name"],
- "msg": "Field required",
- "input": {"wrong_field": "value"},
- }
- ),
- v1=snapshot(
- {
- "loc": ["body", "new_sub", "new_sub_name"],
- "msg": "field required",
- "type": "value_error.missing",
- }
- ),
- )
+ {
+ "type": "missing",
+ "loc": ["body", "new_sub", "new_sub_name"],
+ "msg": "Field required",
+ "input": {"wrong_field": "value"},
+ }
]
}
)
@@ -777,38 +748,20 @@ def test_v2_list_validation_error():
assert response.status_code == 422, response.text
assert response.json() == snapshot(
{
- "detail": pydantic_snapshot(
- v2=snapshot(
- [
- {
- "type": "missing",
- "loc": ["body", 1, "new_size"],
- "msg": "Field required",
- "input": {"new_title": "Invalid"},
- },
- {
- "type": "missing",
- "loc": ["body", 1, "new_sub"],
- "msg": "Field required",
- "input": {"new_title": "Invalid"},
- },
- ]
- ),
- v1=snapshot(
- [
- {
- "loc": ["body", 1, "new_size"],
- "msg": "field required",
- "type": "value_error.missing",
- },
- {
- "loc": ["body", 1, "new_sub"],
- "msg": "field required",
- "type": "value_error.missing",
- },
- ]
- ),
- )
+ "detail": [
+ {
+ "type": "missing",
+ "loc": ["body", 1, "new_size"],
+ "msg": "Field required",
+ "input": {"new_title": "Invalid"},
+ },
+ {
+ "type": "missing",
+ "loc": ["body", 1, "new_sub"],
+ "msg": "Field required",
+ "input": {"new_title": "Invalid"},
+ },
+ ]
}
)
@@ -844,31 +797,18 @@ def test_invalid_list_structure_v2():
assert response.status_code == 422, response.text
assert response.json() == snapshot(
{
- "detail": pydantic_snapshot(
- v2=snapshot(
- [
- {
- "type": "list_type",
- "loc": ["body"],
- "msg": "Input should be a valid list",
- "input": {
- "new_title": "Not a list",
- "new_size": 100,
- "new_sub": {"new_sub_name": "Sub"},
- },
- }
- ]
- ),
- v1=snapshot(
- [
- {
- "loc": ["body"],
- "msg": "value is not a valid list",
- "type": "type_error.list",
- }
- ]
- ),
- )
+ "detail": [
+ {
+ "type": "list_type",
+ "loc": ["body"],
+ "msg": "Input should be a valid list",
+ "input": {
+ "new_title": "Not a list",
+ "new_size": 100,
+ "new_sub": {"new_sub_name": "Sub"},
+ },
+ }
+ ]
}
)
@@ -888,21 +828,12 @@ def test_openapi_schema():
"requestBody": {
"content": {
"application/json": {
- "schema": pydantic_snapshot(
- v2=snapshot(
- {
- "allOf": [
- {
- "$ref": "#/components/schemas/Item"
- }
- ],
- "title": "Data",
- }
- ),
- v1=snapshot(
+ "schema": {
+ "allOf": [
{"$ref": "#/components/schemas/Item"}
- ),
- )
+ ],
+ "title": "Data",
+ }
}
},
"required": True,
@@ -938,21 +869,12 @@ def test_openapi_schema():
"requestBody": {
"content": {
"application/json": {
- "schema": pydantic_snapshot(
- v2=snapshot(
- {
- "allOf": [
- {
- "$ref": "#/components/schemas/Item"
- }
- ],
- "title": "Data",
- }
- ),
- v1=snapshot(
+ "schema": {
+ "allOf": [
{"$ref": "#/components/schemas/Item"}
- ),
- )
+ ],
+ "title": "Data",
+ }
}
},
"required": True,
@@ -1056,21 +978,12 @@ def test_openapi_schema():
"requestBody": {
"content": {
"application/json": {
- "schema": pydantic_snapshot(
- v2=snapshot(
- {
- "allOf": [
- {
- "$ref": "#/components/schemas/Item"
- }
- ],
- "title": "Data",
- }
- ),
- v1=snapshot(
+ "schema": {
+ "allOf": [
{"$ref": "#/components/schemas/Item"}
- ),
- )
+ ],
+ "title": "Data",
+ }
}
},
"required": True,
@@ -1440,17 +1353,10 @@ def test_openapi_schema():
"properties": {
"new_title": {"type": "string", "title": "New Title"},
"new_size": {"type": "integer", "title": "New Size"},
- "new_description": pydantic_snapshot(
- v2=snapshot(
- {
- "anyOf": [{"type": "string"}, {"type": "null"}],
- "title": "New Description",
- }
- ),
- v1=snapshot(
- {"type": "string", "title": "New Description"}
- ),
- ),
+ "new_description": {
+ "anyOf": [{"type": "string"}, {"type": "null"}],
+ "title": "New Description",
+ },
"new_sub": {"$ref": "#/components/schemas/NewSubItem"},
"new_multi": {
"items": {"$ref": "#/components/schemas/NewSubItem"},
diff --git a/tests/test_pydantic_v1_v2_multifile/test_multifile.py b/tests/test_pydantic_v1_v2_multifile/test_multifile.py
index e66d102fb3..32d9019616 100644
--- a/tests/test_pydantic_v1_v2_multifile/test_multifile.py
+++ b/tests/test_pydantic_v1_v2_multifile/test_multifile.py
@@ -1,6 +1,6 @@
import sys
-from tests.utils import pydantic_snapshot, skip_module_if_py_gte_314
+from tests.utils import skip_module_if_py_gte_314
if sys.version_info >= (3, 14):
skip_module_if_py_gte_314()
@@ -292,23 +292,14 @@ def test_openapi_schema():
"requestBody": {
"content": {
"application/json": {
- "schema": pydantic_snapshot(
- v2=snapshot(
- {
- "allOf": [
- {
- "$ref": "#/components/schemas/tests__test_pydantic_v1_v2_multifile__modelsv1__Item"
- }
- ],
- "title": "Data",
- }
- ),
- v1=snapshot(
+ "schema": {
+ "allOf": [
{
"$ref": "#/components/schemas/tests__test_pydantic_v1_v2_multifile__modelsv1__Item"
}
- ),
- )
+ ],
+ "title": "Data",
+ }
}
},
"required": True,
@@ -344,18 +335,9 @@ def test_openapi_schema():
"requestBody": {
"content": {
"application/json": {
- "schema": pydantic_snapshot(
- v2=snapshot(
- {
- "$ref": "#/components/schemas/tests__test_pydantic_v1_v2_multifile__modelsv2__Item-Input"
- }
- ),
- v1=snapshot(
- {
- "$ref": "#/components/schemas/tests__test_pydantic_v1_v2_multifile__modelsv2__Item"
- }
- ),
- ),
+ "schema": {
+ "$ref": "#/components/schemas/tests__test_pydantic_v1_v2_multifile__modelsv2__Item-Input"
+ },
}
},
"required": True,
@@ -391,23 +373,14 @@ def test_openapi_schema():
"requestBody": {
"content": {
"application/json": {
- "schema": pydantic_snapshot(
- v2=snapshot(
- {
- "allOf": [
- {
- "$ref": "#/components/schemas/tests__test_pydantic_v1_v2_multifile__modelsv1__Item"
- }
- ],
- "title": "Data",
- }
- ),
- v1=snapshot(
+ "schema": {
+ "allOf": [
{
"$ref": "#/components/schemas/tests__test_pydantic_v1_v2_multifile__modelsv1__Item"
}
- ),
- )
+ ],
+ "title": "Data",
+ }
}
},
"required": True,
@@ -535,18 +508,9 @@ def test_openapi_schema():
"requestBody": {
"content": {
"application/json": {
- "schema": pydantic_snapshot(
- v2=snapshot(
- {
- "$ref": "#/components/schemas/tests__test_pydantic_v1_v2_multifile__modelsv2__Item-Input"
- }
- ),
- v1=snapshot(
- {
- "$ref": "#/components/schemas/tests__test_pydantic_v1_v2_multifile__modelsv2__Item"
- }
- ),
- ),
+ "schema": {
+ "$ref": "#/components/schemas/tests__test_pydantic_v1_v2_multifile__modelsv2__Item-Input"
+ },
}
},
"required": True,
@@ -587,18 +551,9 @@ def test_openapi_schema():
"content": {
"application/json": {
"schema": {
- "items": pydantic_snapshot(
- v2=snapshot(
- {
- "$ref": "#/components/schemas/tests__test_pydantic_v1_v2_multifile__modelsv2__Item-Input"
- }
- ),
- v1=snapshot(
- {
- "$ref": "#/components/schemas/tests__test_pydantic_v1_v2_multifile__modelsv2__Item"
- }
- ),
- ),
+ "items": {
+ "$ref": "#/components/schemas/tests__test_pydantic_v1_v2_multifile__modelsv2__Item-Input"
+ },
"type": "array",
"title": "Data",
}
@@ -642,18 +597,9 @@ def test_openapi_schema():
"content": {
"application/json": {
"schema": {
- "items": pydantic_snapshot(
- v2=snapshot(
- {
- "$ref": "#/components/schemas/tests__test_pydantic_v1_v2_multifile__modelsv2__Item-Input"
- }
- ),
- v1=snapshot(
- {
- "$ref": "#/components/schemas/tests__test_pydantic_v1_v2_multifile__modelsv2__Item"
- }
- ),
- ),
+ "items": {
+ "$ref": "#/components/schemas/tests__test_pydantic_v1_v2_multifile__modelsv2__Item-Input"
+ },
"type": "array",
"title": "Data",
}
@@ -767,460 +713,239 @@ def test_openapi_schema():
},
},
"components": {
- "schemas": pydantic_snapshot(
- v1=snapshot(
- {
- "Body_handle_v2_items_in_list_to_v1_item_in_list_v2_to_v1_list_of_items_to_list_of_items_post": {
- "properties": {
- "data1": {
- "items": {
- "$ref": "#/components/schemas/tests__test_pydantic_v1_v2_multifile__modelsv2__ItemInList"
- },
- "type": "array",
- "title": "Data1",
- },
- "data2": {
- "items": {
- "$ref": "#/components/schemas/tests__test_pydantic_v1_v2_multifile__modelsv2b__ItemInList"
- },
- "type": "array",
- "title": "Data2",
- },
+ "schemas": {
+ "Body_handle_v2_items_in_list_to_v1_item_in_list_v2_to_v1_list_of_items_to_list_of_items_post": {
+ "properties": {
+ "data1": {
+ "items": {
+ "$ref": "#/components/schemas/tests__test_pydantic_v1_v2_multifile__modelsv2__ItemInList"
},
- "type": "object",
- "required": ["data1", "data2"],
- "title": "Body_handle_v2_items_in_list_to_v1_item_in_list_v2_to_v1_list_of_items_to_list_of_items_post",
+ "type": "array",
+ "title": "Data1",
},
- "Body_handle_v2_same_name_to_v1_v2_to_v1_same_name_post": {
- "properties": {
- "item1": {
- "$ref": "#/components/schemas/tests__test_pydantic_v1_v2_multifile__modelsv2__Item"
- },
- "item2": {
- "$ref": "#/components/schemas/tests__test_pydantic_v1_v2_multifile__modelsv2b__Item"
- },
+ "data2": {
+ "items": {
+ "$ref": "#/components/schemas/tests__test_pydantic_v1_v2_multifile__modelsv2b__ItemInList"
},
- "type": "object",
- "required": ["item1", "item2"],
- "title": "Body_handle_v2_same_name_to_v1_v2_to_v1_same_name_post",
+ "type": "array",
+ "title": "Data2",
},
- "HTTPValidationError": {
- "properties": {
- "detail": {
- "items": {
- "$ref": "#/components/schemas/ValidationError"
- },
- "type": "array",
- "title": "Detail",
- }
+ },
+ "type": "object",
+ "required": ["data1", "data2"],
+ "title": "Body_handle_v2_items_in_list_to_v1_item_in_list_v2_to_v1_list_of_items_to_list_of_items_post",
+ },
+ "Body_handle_v2_same_name_to_v1_v2_to_v1_same_name_post": {
+ "properties": {
+ "item1": {
+ "$ref": "#/components/schemas/tests__test_pydantic_v1_v2_multifile__modelsv2__Item-Input"
+ },
+ "item2": {
+ "$ref": "#/components/schemas/tests__test_pydantic_v1_v2_multifile__modelsv2b__Item"
+ },
+ },
+ "type": "object",
+ "required": ["item1", "item2"],
+ "title": "Body_handle_v2_same_name_to_v1_v2_to_v1_same_name_post",
+ },
+ "HTTPValidationError": {
+ "properties": {
+ "detail": {
+ "items": {
+ "$ref": "#/components/schemas/ValidationError"
},
- "type": "object",
- "title": "HTTPValidationError",
- },
- "ValidationError": {
- "properties": {
- "loc": {
- "items": {
- "anyOf": [
- {"type": "string"},
- {"type": "integer"},
- ]
- },
- "type": "array",
- "title": "Location",
- },
- "msg": {"type": "string", "title": "Message"},
- "type": {"type": "string", "title": "Error Type"},
+ "type": "array",
+ "title": "Detail",
+ }
+ },
+ "type": "object",
+ "title": "HTTPValidationError",
+ },
+ "ValidationError": {
+ "properties": {
+ "loc": {
+ "items": {
+ "anyOf": [
+ {"type": "string"},
+ {"type": "integer"},
+ ]
},
- "type": "object",
- "required": ["loc", "msg", "type"],
- "title": "ValidationError",
+ "type": "array",
+ "title": "Location",
},
- "tests__test_pydantic_v1_v2_multifile__modelsv1__Item": {
- "properties": {
- "title": {"type": "string", "title": "Title"},
- "size": {"type": "integer", "title": "Size"},
- "description": {
- "type": "string",
- "title": "Description",
- },
- "sub": {
- "$ref": "#/components/schemas/tests__test_pydantic_v1_v2_multifile__modelsv1__SubItem"
- },
- "multi": {
- "items": {
- "$ref": "#/components/schemas/tests__test_pydantic_v1_v2_multifile__modelsv1__SubItem"
- },
- "type": "array",
- "title": "Multi",
- "default": [],
- },
+ "msg": {"type": "string", "title": "Message"},
+ "type": {"type": "string", "title": "Error Type"},
+ },
+ "type": "object",
+ "required": ["loc", "msg", "type"],
+ "title": "ValidationError",
+ },
+ "tests__test_pydantic_v1_v2_multifile__modelsv1__Item": {
+ "properties": {
+ "title": {"type": "string", "title": "Title"},
+ "size": {"type": "integer", "title": "Size"},
+ "description": {
+ "type": "string",
+ "title": "Description",
+ },
+ "sub": {
+ "$ref": "#/components/schemas/tests__test_pydantic_v1_v2_multifile__modelsv1__SubItem"
+ },
+ "multi": {
+ "items": {
+ "$ref": "#/components/schemas/tests__test_pydantic_v1_v2_multifile__modelsv1__SubItem"
},
- "type": "object",
- "required": ["title", "size", "sub"],
- "title": "Item",
+ "type": "array",
+ "title": "Multi",
+ "default": [],
},
- "tests__test_pydantic_v1_v2_multifile__modelsv1__ItemInList": {
- "properties": {
- "name1": {"type": "string", "title": "Name1"}
+ },
+ "type": "object",
+ "required": ["title", "size", "sub"],
+ "title": "Item",
+ },
+ "tests__test_pydantic_v1_v2_multifile__modelsv1__ItemInList": {
+ "properties": {"name1": {"type": "string", "title": "Name1"}},
+ "type": "object",
+ "required": ["name1"],
+ "title": "ItemInList",
+ },
+ "tests__test_pydantic_v1_v2_multifile__modelsv1__SubItem": {
+ "properties": {"name": {"type": "string", "title": "Name"}},
+ "type": "object",
+ "required": ["name"],
+ "title": "SubItem",
+ },
+ "tests__test_pydantic_v1_v2_multifile__modelsv2__Item": {
+ "properties": {
+ "new_title": {
+ "type": "string",
+ "title": "New Title",
+ },
+ "new_size": {
+ "type": "integer",
+ "title": "New Size",
+ },
+ "new_description": {
+ "anyOf": [{"type": "string"}, {"type": "null"}],
+ "title": "New Description",
+ },
+ "new_sub": {
+ "$ref": "#/components/schemas/tests__test_pydantic_v1_v2_multifile__modelsv2__SubItem"
+ },
+ "new_multi": {
+ "items": {
+ "$ref": "#/components/schemas/tests__test_pydantic_v1_v2_multifile__modelsv2__SubItem"
},
- "type": "object",
- "required": ["name1"],
- "title": "ItemInList",
+ "type": "array",
+ "title": "New Multi",
+ "default": [],
},
- "tests__test_pydantic_v1_v2_multifile__modelsv1__SubItem": {
- "properties": {
- "name": {"type": "string", "title": "Name"}
+ },
+ "type": "object",
+ "required": ["new_title", "new_size", "new_sub"],
+ "title": "Item",
+ },
+ "tests__test_pydantic_v1_v2_multifile__modelsv2__Item-Input": {
+ "properties": {
+ "new_title": {
+ "type": "string",
+ "title": "New Title",
+ },
+ "new_size": {
+ "type": "integer",
+ "title": "New Size",
+ },
+ "new_description": {
+ "anyOf": [{"type": "string"}, {"type": "null"}],
+ "title": "New Description",
+ },
+ "new_sub": {
+ "$ref": "#/components/schemas/tests__test_pydantic_v1_v2_multifile__modelsv2__SubItem"
+ },
+ "new_multi": {
+ "items": {
+ "$ref": "#/components/schemas/tests__test_pydantic_v1_v2_multifile__modelsv2__SubItem"
},
- "type": "object",
- "required": ["name"],
- "title": "SubItem",
+ "type": "array",
+ "title": "New Multi",
+ "default": [],
},
- "tests__test_pydantic_v1_v2_multifile__modelsv2__Item": {
- "properties": {
- "new_title": {
- "type": "string",
- "title": "New Title",
- },
- "new_size": {
- "type": "integer",
- "title": "New Size",
- },
- "new_description": {
- "type": "string",
- "title": "New Description",
- },
- "new_sub": {
- "$ref": "#/components/schemas/tests__test_pydantic_v1_v2_multifile__modelsv2__SubItem"
- },
- "new_multi": {
- "items": {
- "$ref": "#/components/schemas/tests__test_pydantic_v1_v2_multifile__modelsv2__SubItem"
- },
- "type": "array",
- "title": "New Multi",
- "default": [],
- },
+ },
+ "type": "object",
+ "required": ["new_title", "new_size", "new_sub"],
+ "title": "Item",
+ },
+ "tests__test_pydantic_v1_v2_multifile__modelsv2__ItemInList": {
+ "properties": {"name2": {"type": "string", "title": "Name2"}},
+ "type": "object",
+ "required": ["name2"],
+ "title": "ItemInList",
+ },
+ "tests__test_pydantic_v1_v2_multifile__modelsv2__SubItem": {
+ "properties": {
+ "new_sub_name": {
+ "type": "string",
+ "title": "New Sub Name",
+ }
+ },
+ "type": "object",
+ "required": ["new_sub_name"],
+ "title": "SubItem",
+ },
+ "tests__test_pydantic_v1_v2_multifile__modelsv2b__Item": {
+ "properties": {
+ "dup_title": {
+ "type": "string",
+ "title": "Dup Title",
+ },
+ "dup_size": {
+ "type": "integer",
+ "title": "Dup Size",
+ },
+ "dup_description": {
+ "anyOf": [{"type": "string"}, {"type": "null"}],
+ "title": "Dup Description",
+ },
+ "dup_sub": {
+ "$ref": "#/components/schemas/tests__test_pydantic_v1_v2_multifile__modelsv2b__SubItem"
+ },
+ "dup_multi": {
+ "items": {
+ "$ref": "#/components/schemas/tests__test_pydantic_v1_v2_multifile__modelsv2b__SubItem"
},
- "type": "object",
- "required": ["new_title", "new_size", "new_sub"],
- "title": "Item",
+ "type": "array",
+ "title": "Dup Multi",
+ "default": [],
},
- "tests__test_pydantic_v1_v2_multifile__modelsv2__ItemInList": {
- "properties": {
- "name2": {"type": "string", "title": "Name2"}
- },
- "type": "object",
- "required": ["name2"],
- "title": "ItemInList",
- },
- "tests__test_pydantic_v1_v2_multifile__modelsv2__SubItem": {
- "properties": {
- "new_sub_name": {
- "type": "string",
- "title": "New Sub Name",
- }
- },
- "type": "object",
- "required": ["new_sub_name"],
- "title": "SubItem",
- },
- "tests__test_pydantic_v1_v2_multifile__modelsv2b__Item": {
- "properties": {
- "dup_title": {
- "type": "string",
- "title": "Dup Title",
- },
- "dup_size": {
- "type": "integer",
- "title": "Dup Size",
- },
- "dup_description": {
- "type": "string",
- "title": "Dup Description",
- },
- "dup_sub": {
- "$ref": "#/components/schemas/tests__test_pydantic_v1_v2_multifile__modelsv2b__SubItem"
- },
- "dup_multi": {
- "items": {
- "$ref": "#/components/schemas/tests__test_pydantic_v1_v2_multifile__modelsv2b__SubItem"
- },
- "type": "array",
- "title": "Dup Multi",
- "default": [],
- },
- },
- "type": "object",
- "required": ["dup_title", "dup_size", "dup_sub"],
- "title": "Item",
- },
- "tests__test_pydantic_v1_v2_multifile__modelsv2b__ItemInList": {
- "properties": {
- "dup_name2": {
- "type": "string",
- "title": "Dup Name2",
- }
- },
- "type": "object",
- "required": ["dup_name2"],
- "title": "ItemInList",
- },
- "tests__test_pydantic_v1_v2_multifile__modelsv2b__SubItem": {
- "properties": {
- "dup_sub_name": {
- "type": "string",
- "title": "Dup Sub Name",
- }
- },
- "type": "object",
- "required": ["dup_sub_name"],
- "title": "SubItem",
- },
- }
- ),
- v2=snapshot(
- {
- "Body_handle_v2_items_in_list_to_v1_item_in_list_v2_to_v1_list_of_items_to_list_of_items_post": {
- "properties": {
- "data1": {
- "items": {
- "$ref": "#/components/schemas/tests__test_pydantic_v1_v2_multifile__modelsv2__ItemInList"
- },
- "type": "array",
- "title": "Data1",
- },
- "data2": {
- "items": {
- "$ref": "#/components/schemas/tests__test_pydantic_v1_v2_multifile__modelsv2b__ItemInList"
- },
- "type": "array",
- "title": "Data2",
- },
- },
- "type": "object",
- "required": ["data1", "data2"],
- "title": "Body_handle_v2_items_in_list_to_v1_item_in_list_v2_to_v1_list_of_items_to_list_of_items_post",
- },
- "Body_handle_v2_same_name_to_v1_v2_to_v1_same_name_post": {
- "properties": {
- "item1": {
- "$ref": "#/components/schemas/tests__test_pydantic_v1_v2_multifile__modelsv2__Item-Input"
- },
- "item2": {
- "$ref": "#/components/schemas/tests__test_pydantic_v1_v2_multifile__modelsv2b__Item"
- },
- },
- "type": "object",
- "required": ["item1", "item2"],
- "title": "Body_handle_v2_same_name_to_v1_v2_to_v1_same_name_post",
- },
- "HTTPValidationError": {
- "properties": {
- "detail": {
- "items": {
- "$ref": "#/components/schemas/ValidationError"
- },
- "type": "array",
- "title": "Detail",
- }
- },
- "type": "object",
- "title": "HTTPValidationError",
- },
- "ValidationError": {
- "properties": {
- "loc": {
- "items": {
- "anyOf": [
- {"type": "string"},
- {"type": "integer"},
- ]
- },
- "type": "array",
- "title": "Location",
- },
- "msg": {"type": "string", "title": "Message"},
- "type": {"type": "string", "title": "Error Type"},
- },
- "type": "object",
- "required": ["loc", "msg", "type"],
- "title": "ValidationError",
- },
- "tests__test_pydantic_v1_v2_multifile__modelsv1__Item": {
- "properties": {
- "title": {"type": "string", "title": "Title"},
- "size": {"type": "integer", "title": "Size"},
- "description": {
- "type": "string",
- "title": "Description",
- },
- "sub": {
- "$ref": "#/components/schemas/tests__test_pydantic_v1_v2_multifile__modelsv1__SubItem"
- },
- "multi": {
- "items": {
- "$ref": "#/components/schemas/tests__test_pydantic_v1_v2_multifile__modelsv1__SubItem"
- },
- "type": "array",
- "title": "Multi",
- "default": [],
- },
- },
- "type": "object",
- "required": ["title", "size", "sub"],
- "title": "Item",
- },
- "tests__test_pydantic_v1_v2_multifile__modelsv1__ItemInList": {
- "properties": {
- "name1": {"type": "string", "title": "Name1"}
- },
- "type": "object",
- "required": ["name1"],
- "title": "ItemInList",
- },
- "tests__test_pydantic_v1_v2_multifile__modelsv1__SubItem": {
- "properties": {
- "name": {"type": "string", "title": "Name"}
- },
- "type": "object",
- "required": ["name"],
- "title": "SubItem",
- },
- "tests__test_pydantic_v1_v2_multifile__modelsv2__Item": {
- "properties": {
- "new_title": {
- "type": "string",
- "title": "New Title",
- },
- "new_size": {
- "type": "integer",
- "title": "New Size",
- },
- "new_description": {
- "anyOf": [{"type": "string"}, {"type": "null"}],
- "title": "New Description",
- },
- "new_sub": {
- "$ref": "#/components/schemas/tests__test_pydantic_v1_v2_multifile__modelsv2__SubItem"
- },
- "new_multi": {
- "items": {
- "$ref": "#/components/schemas/tests__test_pydantic_v1_v2_multifile__modelsv2__SubItem"
- },
- "type": "array",
- "title": "New Multi",
- "default": [],
- },
- },
- "type": "object",
- "required": ["new_title", "new_size", "new_sub"],
- "title": "Item",
- },
- "tests__test_pydantic_v1_v2_multifile__modelsv2__Item-Input": {
- "properties": {
- "new_title": {
- "type": "string",
- "title": "New Title",
- },
- "new_size": {
- "type": "integer",
- "title": "New Size",
- },
- "new_description": {
- "anyOf": [{"type": "string"}, {"type": "null"}],
- "title": "New Description",
- },
- "new_sub": {
- "$ref": "#/components/schemas/tests__test_pydantic_v1_v2_multifile__modelsv2__SubItem"
- },
- "new_multi": {
- "items": {
- "$ref": "#/components/schemas/tests__test_pydantic_v1_v2_multifile__modelsv2__SubItem"
- },
- "type": "array",
- "title": "New Multi",
- "default": [],
- },
- },
- "type": "object",
- "required": ["new_title", "new_size", "new_sub"],
- "title": "Item",
- },
- "tests__test_pydantic_v1_v2_multifile__modelsv2__ItemInList": {
- "properties": {
- "name2": {"type": "string", "title": "Name2"}
- },
- "type": "object",
- "required": ["name2"],
- "title": "ItemInList",
- },
- "tests__test_pydantic_v1_v2_multifile__modelsv2__SubItem": {
- "properties": {
- "new_sub_name": {
- "type": "string",
- "title": "New Sub Name",
- }
- },
- "type": "object",
- "required": ["new_sub_name"],
- "title": "SubItem",
- },
- "tests__test_pydantic_v1_v2_multifile__modelsv2b__Item": {
- "properties": {
- "dup_title": {
- "type": "string",
- "title": "Dup Title",
- },
- "dup_size": {
- "type": "integer",
- "title": "Dup Size",
- },
- "dup_description": {
- "anyOf": [{"type": "string"}, {"type": "null"}],
- "title": "Dup Description",
- },
- "dup_sub": {
- "$ref": "#/components/schemas/tests__test_pydantic_v1_v2_multifile__modelsv2b__SubItem"
- },
- "dup_multi": {
- "items": {
- "$ref": "#/components/schemas/tests__test_pydantic_v1_v2_multifile__modelsv2b__SubItem"
- },
- "type": "array",
- "title": "Dup Multi",
- "default": [],
- },
- },
- "type": "object",
- "required": ["dup_title", "dup_size", "dup_sub"],
- "title": "Item",
- },
- "tests__test_pydantic_v1_v2_multifile__modelsv2b__ItemInList": {
- "properties": {
- "dup_name2": {
- "type": "string",
- "title": "Dup Name2",
- }
- },
- "type": "object",
- "required": ["dup_name2"],
- "title": "ItemInList",
- },
- "tests__test_pydantic_v1_v2_multifile__modelsv2b__SubItem": {
- "properties": {
- "dup_sub_name": {
- "type": "string",
- "title": "Dup Sub Name",
- }
- },
- "type": "object",
- "required": ["dup_sub_name"],
- "title": "SubItem",
- },
- }
- ),
- ),
+ },
+ "type": "object",
+ "required": ["dup_title", "dup_size", "dup_sub"],
+ "title": "Item",
+ },
+ "tests__test_pydantic_v1_v2_multifile__modelsv2b__ItemInList": {
+ "properties": {
+ "dup_name2": {
+ "type": "string",
+ "title": "Dup Name2",
+ }
+ },
+ "type": "object",
+ "required": ["dup_name2"],
+ "title": "ItemInList",
+ },
+ "tests__test_pydantic_v1_v2_multifile__modelsv2b__SubItem": {
+ "properties": {
+ "dup_sub_name": {
+ "type": "string",
+ "title": "Dup Sub Name",
+ }
+ },
+ "type": "object",
+ "required": ["dup_sub_name"],
+ "title": "SubItem",
+ },
+ },
},
}
)
diff --git a/tests/test_pydantic_v1_v2_noneable.py b/tests/test_pydantic_v1_v2_noneable.py
index 3e86469908..2cb6c3d6b4 100644
--- a/tests/test_pydantic_v1_v2_noneable.py
+++ b/tests/test_pydantic_v1_v2_noneable.py
@@ -1,7 +1,7 @@
import sys
from typing import Any, Union
-from tests.utils import pydantic_snapshot, skip_module_if_py_gte_314
+from tests.utils import skip_module_if_py_gte_314
if sys.version_info >= (3, 14):
skip_module_if_py_gte_314()
@@ -312,38 +312,20 @@ def test_v2_to_v1_validation_error():
assert response.status_code == 422, response.text
assert response.json() == snapshot(
{
- "detail": pydantic_snapshot(
- v2=snapshot(
- [
- {
- "type": "missing",
- "loc": ["body", "new_size"],
- "msg": "Field required",
- "input": {"new_title": "Missing fields"},
- },
- {
- "type": "missing",
- "loc": ["body", "new_sub"],
- "msg": "Field required",
- "input": {"new_title": "Missing fields"},
- },
- ]
- ),
- v1=snapshot(
- [
- {
- "loc": ["body", "new_size"],
- "msg": "field required",
- "type": "value_error.missing",
- },
- {
- "loc": ["body", "new_sub"],
- "msg": "field required",
- "type": "value_error.missing",
- },
- ]
- ),
- )
+ "detail": [
+ {
+ "type": "missing",
+ "loc": ["body", "new_size"],
+ "msg": "Field required",
+ "input": {"new_title": "Missing fields"},
+ },
+ {
+ "type": "missing",
+ "loc": ["body", "new_sub"],
+ "msg": "Field required",
+ "input": {"new_title": "Missing fields"},
+ },
+ ]
}
)
@@ -361,23 +343,12 @@ def test_v2_to_v1_nested_validation_error():
assert response.json() == snapshot(
{
"detail": [
- pydantic_snapshot(
- v2=snapshot(
- {
- "type": "missing",
- "loc": ["body", "new_sub", "new_sub_name"],
- "msg": "Field required",
- "input": {"wrong_field": "value"},
- }
- ),
- v1=snapshot(
- {
- "loc": ["body", "new_sub", "new_sub_name"],
- "msg": "field required",
- "type": "value_error.missing",
- }
- ),
- )
+ {
+ "type": "missing",
+ "loc": ["body", "new_sub", "new_sub_name"],
+ "msg": "Field required",
+ "input": {"wrong_field": "value"},
+ }
]
}
)
@@ -396,23 +367,12 @@ def test_v2_to_v1_type_validation_error():
assert response.json() == snapshot(
{
"detail": [
- pydantic_snapshot(
- v2=snapshot(
- {
- "type": "int_parsing",
- "loc": ["body", "new_size"],
- "msg": "Input should be a valid integer, unable to parse string as an integer",
- "input": "not_a_number",
- }
- ),
- v1=snapshot(
- {
- "loc": ["body", "new_size"],
- "msg": "value is not a valid integer",
- "type": "type_error.integer",
- }
- ),
- )
+ {
+ "type": "int_parsing",
+ "loc": ["body", "new_size"],
+ "msg": "Input should be a valid integer, unable to parse string as an integer",
+ "input": "not_a_number",
+ }
]
}
)
@@ -483,21 +443,12 @@ def test_openapi_schema():
"requestBody": {
"content": {
"application/json": {
- "schema": pydantic_snapshot(
- v2=snapshot(
- {
- "allOf": [
- {
- "$ref": "#/components/schemas/Item"
- }
- ],
- "title": "Data",
- }
- ),
- v1=snapshot(
+ "schema": {
+ "allOf": [
{"$ref": "#/components/schemas/Item"}
- ),
- )
+ ],
+ "title": "Data",
+ }
}
},
"required": True,
@@ -507,22 +458,15 @@ def test_openapi_schema():
"description": "Successful Response",
"content": {
"application/json": {
- "schema": pydantic_snapshot(
- v2=snapshot(
+ "schema": {
+ "anyOf": [
{
- "anyOf": [
- {
- "$ref": "#/components/schemas/NewItem"
- },
- {"type": "null"},
- ],
- "title": "Response Handle V1 Item To V2 V1 To V2 Post",
- }
- ),
- v1=snapshot(
- {"$ref": "#/components/schemas/NewItem"}
- ),
- )
+ "$ref": "#/components/schemas/NewItem"
+ },
+ {"type": "null"},
+ ],
+ "title": "Response Handle V1 Item To V2 V1 To V2 Post",
+ }
}
},
},
@@ -546,21 +490,12 @@ def test_openapi_schema():
"requestBody": {
"content": {
"application/json": {
- "schema": pydantic_snapshot(
- v2=snapshot(
- {
- "allOf": [
- {
- "$ref": "#/components/schemas/Item"
- }
- ],
- "title": "Data",
- }
- ),
- v1=snapshot(
+ "schema": {
+ "allOf": [
{"$ref": "#/components/schemas/Item"}
- ),
- )
+ ],
+ "title": "Data",
+ }
}
},
"required": True,
@@ -570,22 +505,15 @@ def test_openapi_schema():
"description": "Successful Response",
"content": {
"application/json": {
- "schema": pydantic_snapshot(
- v2=snapshot(
+ "schema": {
+ "anyOf": [
{
- "anyOf": [
- {
- "$ref": "#/components/schemas/NewItem"
- },
- {"type": "null"},
- ],
- "title": "Response Handle V1 Item To V2 Filter V1 To V2 Item Filter Post",
- }
- ),
- v1=snapshot(
- {"$ref": "#/components/schemas/NewItem"}
- ),
- )
+ "$ref": "#/components/schemas/NewItem"
+ },
+ {"type": "null"},
+ ],
+ "title": "Response Handle V1 Item To V2 Filter V1 To V2 Item Filter Post",
+ }
}
},
},
@@ -707,17 +635,10 @@ def test_openapi_schema():
"properties": {
"new_title": {"type": "string", "title": "New Title"},
"new_size": {"type": "integer", "title": "New Size"},
- "new_description": pydantic_snapshot(
- v2=snapshot(
- {
- "anyOf": [{"type": "string"}, {"type": "null"}],
- "title": "New Description",
- }
- ),
- v1=snapshot(
- {"type": "string", "title": "New Description"}
- ),
- ),
+ "new_description": {
+ "anyOf": [{"type": "string"}, {"type": "null"}],
+ "title": "New Description",
+ },
"new_sub": {"$ref": "#/components/schemas/NewSubItem"},
"new_multi": {
"items": {"$ref": "#/components/schemas/NewSubItem"},
diff --git a/tests/test_query_cookie_header_model_extra_params.py b/tests/test_query_cookie_header_model_extra_params.py
index f4ebefb3f3..d361e1e533 100644
--- a/tests/test_query_cookie_header_model_extra_params.py
+++ b/tests/test_query_cookie_header_model_extra_params.py
@@ -1,5 +1,4 @@
from fastapi import Cookie, FastAPI, Header, Query
-from fastapi._compat import PYDANTIC_V2
from fastapi.testclient import TestClient
from pydantic import BaseModel
@@ -9,12 +8,7 @@ app = FastAPI()
class Model(BaseModel):
param: str
- if PYDANTIC_V2:
- model_config = {"extra": "allow"}
- else:
-
- class Config:
- extra = "allow"
+ model_config = {"extra": "allow"}
@app.get("/query")
diff --git a/tests/test_read_with_orm_mode.py b/tests/test_read_with_orm_mode.py
index b359874439..5858f8e801 100644
--- a/tests/test_read_with_orm_mode.py
+++ b/tests/test_read_with_orm_mode.py
@@ -4,10 +4,9 @@ from fastapi import FastAPI
from fastapi.testclient import TestClient
from pydantic import BaseModel, ConfigDict
-from .utils import needs_pydanticv1, needs_pydanticv2
+from .utils import needs_pydanticv1
-@needs_pydanticv2
def test_read_with_orm_mode() -> None:
class PersonBase(BaseModel):
name: str
@@ -48,7 +47,9 @@ def test_read_with_orm_mode() -> None:
@needs_pydanticv1
def test_read_with_orm_mode_pv1() -> None:
- class PersonBase(BaseModel):
+ from pydantic import v1
+
+ class PersonBase(v1.BaseModel):
name: str
lastname: str
diff --git a/tests/test_request_param_model_by_alias.py b/tests/test_request_param_model_by_alias.py
index a6f759f23b..c29130d7a6 100644
--- a/tests/test_request_param_model_by_alias.py
+++ b/tests/test_request_param_model_by_alias.py
@@ -1,6 +1,5 @@
from dirty_equals import IsPartialDict
from fastapi import Cookie, FastAPI, Header, Query
-from fastapi._compat import PYDANTIC_V2
from fastapi.testclient import TestClient
from pydantic import BaseModel, Field
@@ -53,8 +52,7 @@ def test_query_model_with_alias_by_name():
response = client.get("/query", params={"param": "value"})
assert response.status_code == 422, response.text
details = response.json()
- if PYDANTIC_V2:
- assert details["detail"][0]["input"] == {"param": "value"}
+ assert details["detail"][0]["input"] == {"param": "value"}
def test_header_model_with_alias_by_name():
@@ -62,8 +60,7 @@ def test_header_model_with_alias_by_name():
response = client.get("/header", headers={"param": "value"})
assert response.status_code == 422, response.text
details = response.json()
- if PYDANTIC_V2:
- assert details["detail"][0]["input"] == IsPartialDict({"param": "value"})
+ assert details["detail"][0]["input"] == IsPartialDict({"param": "value"})
def test_cookie_model_with_alias_by_name():
@@ -72,5 +69,4 @@ def test_cookie_model_with_alias_by_name():
response = client.get("/cookie")
assert response.status_code == 422, response.text
details = response.json()
- if PYDANTIC_V2:
- assert details["detail"][0]["input"] == {"param": "value"}
+ assert details["detail"][0]["input"] == {"param": "value"}
diff --git a/tests/test_request_params/test_body/test_list.py b/tests/test_request_params/test_body/test_list.py
index b2503a1c44..0048da0f8b 100644
--- a/tests/test_request_params/test_body/test_list.py
+++ b/tests/test_request_params/test_body/test_list.py
@@ -6,8 +6,6 @@ from fastapi import Body, FastAPI
from fastapi.testclient import TestClient
from pydantic import BaseModel, Field
-from tests.utils import needs_pydanticv2
-
from .utils import get_body_model_name
app = FastAPI()
@@ -246,7 +244,6 @@ async def read_model_required_list_validation_alias(
return {"p": p.p}
-@needs_pydanticv2
@pytest.mark.parametrize(
"path",
["/required-list-validation-alias", "/model-required-list-validation-alias"],
@@ -269,7 +266,6 @@ def test_required_list_validation_alias_schema(path: str):
}
-@needs_pydanticv2
@pytest.mark.parametrize("json", [None, {}])
@pytest.mark.parametrize(
"path",
@@ -294,7 +290,6 @@ def test_required_list_validation_alias_missing(path: str, json: Union[dict, Non
}
-@needs_pydanticv2
@pytest.mark.parametrize(
"path",
[
@@ -319,7 +314,6 @@ def test_required_list_validation_alias_by_name(path: str):
}
-@needs_pydanticv2
@pytest.mark.parametrize(
"path",
[
@@ -364,7 +358,6 @@ def read_model_required_list_alias_and_validation_alias(
return {"p": p.p}
-@needs_pydanticv2
@pytest.mark.parametrize(
"path",
[
@@ -390,7 +383,6 @@ def test_required_list_alias_and_validation_alias_schema(path: str):
}
-@needs_pydanticv2
@pytest.mark.parametrize("json", [None, {}])
@pytest.mark.parametrize(
"path",
@@ -415,7 +407,6 @@ def test_required_list_alias_and_validation_alias_missing(path: str, json):
}
-@needs_pydanticv2
@pytest.mark.parametrize(
"path",
[
@@ -442,7 +433,6 @@ def test_required_list_alias_and_validation_alias_by_name(path: str):
}
-@needs_pydanticv2
@pytest.mark.parametrize(
"path",
[
@@ -467,7 +457,6 @@ def test_required_list_alias_and_validation_alias_by_alias(path: str):
}
-@needs_pydanticv2
@pytest.mark.parametrize(
"path",
[
diff --git a/tests/test_request_params/test_body/test_optional_list.py b/tests/test_request_params/test_body/test_optional_list.py
index ede635f840..960e8890f3 100644
--- a/tests/test_request_params/test_body/test_optional_list.py
+++ b/tests/test_request_params/test_body/test_optional_list.py
@@ -6,8 +6,6 @@ from fastapi import Body, FastAPI
from fastapi.testclient import TestClient
from pydantic import BaseModel, Field
-from tests.utils import needs_pydanticv2
-
from .utils import get_body_model_name
app = FastAPI()
@@ -283,7 +281,6 @@ def read_model_optional_list_validation_alias(
return {"p": p.p}
-@needs_pydanticv2
@pytest.mark.parametrize(
"path",
["/optional-list-validation-alias", "/model-optional-list-validation-alias"],
@@ -369,7 +366,6 @@ def test_optional_list_validation_alias_missing_empty_dict(path: str):
assert response.json() == {"p": None}
-@needs_pydanticv2
@pytest.mark.parametrize(
"path",
[
@@ -384,7 +380,6 @@ def test_optional_list_validation_alias_by_name(path: str):
assert response.json() == {"p": None}
-@needs_pydanticv2
@pytest.mark.parametrize(
"path",
[
@@ -432,7 +427,6 @@ def read_model_optional_list_alias_and_validation_alias(
return {"p": p.p}
-@needs_pydanticv2
@pytest.mark.parametrize(
"path",
[
@@ -524,7 +518,6 @@ def test_optional_list_alias_and_validation_alias_missing_empty_dict(path: str):
assert response.json() == {"p": None}
-@needs_pydanticv2
@pytest.mark.parametrize(
"path",
[
@@ -539,7 +532,6 @@ def test_optional_list_alias_and_validation_alias_by_name(path: str):
assert response.json() == {"p": None}
-@needs_pydanticv2
@pytest.mark.parametrize(
"path",
[
@@ -554,7 +546,6 @@ def test_optional_list_alias_and_validation_alias_by_alias(path: str):
assert response.json() == {"p": None}
-@needs_pydanticv2
@pytest.mark.parametrize(
"path",
[
diff --git a/tests/test_request_params/test_body/test_optional_str.py b/tests/test_request_params/test_body/test_optional_str.py
index 9e0c7217cc..59732688a2 100644
--- a/tests/test_request_params/test_body/test_optional_str.py
+++ b/tests/test_request_params/test_body/test_optional_str.py
@@ -6,8 +6,6 @@ from fastapi import Body, FastAPI
from fastapi.testclient import TestClient
from pydantic import BaseModel, Field
-from tests.utils import needs_pydanticv2
-
from .utils import get_body_model_name
app = FastAPI()
@@ -268,7 +266,6 @@ def read_model_optional_validation_alias(
return {"p": p.p}
-@needs_pydanticv2
@pytest.mark.parametrize(
"path",
["/optional-validation-alias", "/model-optional-validation-alias"],
@@ -300,7 +297,6 @@ def test_optional_validation_alias_schema(path: str):
)
-@needs_pydanticv2
def test_optional_validation_alias_missing():
client = TestClient(app)
response = client.post("/optional-validation-alias")
@@ -308,7 +304,6 @@ def test_optional_validation_alias_missing():
assert response.json() == {"p": None}
-@needs_pydanticv2
def test_model_optional_validation_alias_missing():
client = TestClient(app)
response = client.post("/model-optional-validation-alias")
@@ -338,7 +333,6 @@ def test_model_optional_validation_alias_missing():
)
-@needs_pydanticv2
@pytest.mark.parametrize(
"path",
["/optional-validation-alias", "/model-optional-validation-alias"],
@@ -350,7 +344,6 @@ def test_model_optional_validation_alias_missing_empty_dict(path: str):
assert response.json() == {"p": None}
-@needs_pydanticv2
@pytest.mark.parametrize(
"path",
[
@@ -365,7 +358,6 @@ def test_optional_validation_alias_by_name(path: str):
assert response.json() == {"p": None}
-@needs_pydanticv2
@pytest.mark.parametrize(
"path",
[
@@ -410,7 +402,6 @@ def read_model_optional_alias_and_validation_alias(
return {"p": p.p}
-@needs_pydanticv2
@pytest.mark.parametrize(
"path",
[
@@ -445,7 +436,6 @@ def test_optional_alias_and_validation_alias_schema(path: str):
)
-@needs_pydanticv2
def test_optional_alias_and_validation_alias_missing():
client = TestClient(app)
response = client.post("/optional-alias-and-validation-alias")
@@ -453,7 +443,6 @@ def test_optional_alias_and_validation_alias_missing():
assert response.json() == {"p": None}
-@needs_pydanticv2
def test_model_optional_alias_and_validation_alias_missing():
client = TestClient(app)
response = client.post("/model-optional-alias-and-validation-alias")
@@ -483,7 +472,6 @@ def test_model_optional_alias_and_validation_alias_missing():
)
-@needs_pydanticv2
@pytest.mark.parametrize(
"path",
[
@@ -498,7 +486,6 @@ def test_model_optional_alias_and_validation_alias_missing_empty_dict(path: str)
assert response.json() == {"p": None}
-@needs_pydanticv2
@pytest.mark.parametrize(
"path",
[
@@ -513,7 +500,6 @@ def test_optional_alias_and_validation_alias_by_name(path: str):
assert response.json() == {"p": None}
-@needs_pydanticv2
@pytest.mark.parametrize(
"path",
[
@@ -528,7 +514,6 @@ def test_optional_alias_and_validation_alias_by_alias(path: str):
assert response.json() == {"p": None}
-@needs_pydanticv2
@pytest.mark.parametrize(
"path",
[
diff --git a/tests/test_request_params/test_body/test_required_str.py b/tests/test_request_params/test_body/test_required_str.py
index aa47a4ede3..5571ba5d5a 100644
--- a/tests/test_request_params/test_body/test_required_str.py
+++ b/tests/test_request_params/test_body/test_required_str.py
@@ -6,8 +6,6 @@ from fastapi import Body, FastAPI
from fastapi.testclient import TestClient
from pydantic import BaseModel, Field
-from tests.utils import needs_pydanticv2
-
from .utils import get_body_model_name
app = FastAPI()
@@ -236,7 +234,6 @@ def read_model_required_validation_alias(
return {"p": p.p}
-@needs_pydanticv2
@pytest.mark.parametrize(
"path",
["/required-validation-alias", "/model-required-validation-alias"],
@@ -255,7 +252,6 @@ def test_required_validation_alias_schema(path: str):
}
-@needs_pydanticv2
@pytest.mark.parametrize("json", [None, {}])
@pytest.mark.parametrize(
"path",
@@ -282,7 +278,6 @@ def test_required_validation_alias_missing(
}
-@needs_pydanticv2
@pytest.mark.parametrize(
"path",
[
@@ -307,7 +302,6 @@ def test_required_validation_alias_by_name(path: str):
}
-@needs_pydanticv2
@pytest.mark.parametrize(
"path",
[
@@ -353,7 +347,6 @@ def read_model_required_alias_and_validation_alias(
return {"p": p.p}
-@needs_pydanticv2
@pytest.mark.parametrize(
"path",
[
@@ -375,7 +368,6 @@ def test_required_alias_and_validation_alias_schema(path: str):
}
-@needs_pydanticv2
@pytest.mark.parametrize("json", [None, {}])
@pytest.mark.parametrize(
"path",
@@ -402,7 +394,6 @@ def test_required_alias_and_validation_alias_missing(
}
-@needs_pydanticv2
@pytest.mark.parametrize(
"path",
[
@@ -430,7 +421,6 @@ def test_required_alias_and_validation_alias_by_name(path: str):
}
-@needs_pydanticv2
@pytest.mark.parametrize(
"path",
[
@@ -455,7 +445,6 @@ def test_required_alias_and_validation_alias_by_alias(path: str):
}
-@needs_pydanticv2
@pytest.mark.parametrize(
"path",
[
diff --git a/tests/test_request_params/test_cookie/test_optional_str.py b/tests/test_request_params/test_cookie/test_optional_str.py
index f2d02dae54..b2f7f9cef5 100644
--- a/tests/test_request_params/test_cookie/test_optional_str.py
+++ b/tests/test_request_params/test_cookie/test_optional_str.py
@@ -6,8 +6,6 @@ from fastapi import Cookie, FastAPI
from fastapi.testclient import TestClient
from pydantic import BaseModel, Field
-from tests.utils import needs_pydanticv2
-
app = FastAPI()
# =====================================================================================
@@ -189,7 +187,6 @@ def read_model_optional_validation_alias(
return {"p": p.p}
-@needs_pydanticv2
@pytest.mark.parametrize(
"path",
["/optional-validation-alias", "/model-optional-validation-alias"],
@@ -208,7 +205,6 @@ def test_optional_validation_alias_schema(path: str):
]
-@needs_pydanticv2
@pytest.mark.parametrize(
"path",
["/optional-validation-alias", "/model-optional-validation-alias"],
@@ -220,7 +216,6 @@ def test_optional_validation_alias_missing(path: str):
assert response.json() == {"p": None}
-@needs_pydanticv2
@pytest.mark.parametrize(
"path",
[
@@ -236,7 +231,6 @@ def test_optional_validation_alias_by_name(path: str):
assert response.json() == {"p": None}
-@needs_pydanticv2
@pytest.mark.parametrize(
"path",
[
@@ -276,7 +270,6 @@ def read_model_optional_alias_and_validation_alias(
return {"p": p.p}
-@needs_pydanticv2
@pytest.mark.parametrize(
"path",
[
@@ -298,7 +291,6 @@ def test_optional_alias_and_validation_alias_schema(path: str):
]
-@needs_pydanticv2
@pytest.mark.parametrize(
"path",
[
@@ -313,7 +305,6 @@ def test_optional_alias_and_validation_alias_missing(path: str):
assert response.json() == {"p": None}
-@needs_pydanticv2
@pytest.mark.parametrize(
"path",
[
@@ -329,7 +320,6 @@ def test_optional_alias_and_validation_alias_by_name(path: str):
assert response.json() == {"p": None}
-@needs_pydanticv2
@pytest.mark.parametrize(
"path",
[
@@ -345,7 +335,6 @@ def test_optional_alias_and_validation_alias_by_alias(path: str):
assert response.json() == {"p": None}
-@needs_pydanticv2
@pytest.mark.parametrize(
"path",
[
diff --git a/tests/test_request_params/test_cookie/test_required_str.py b/tests/test_request_params/test_cookie/test_required_str.py
index 3255857d44..58bb7af5b9 100644
--- a/tests/test_request_params/test_cookie/test_required_str.py
+++ b/tests/test_request_params/test_cookie/test_required_str.py
@@ -6,8 +6,6 @@ from fastapi import Cookie, FastAPI
from fastapi.testclient import TestClient
from pydantic import BaseModel, Field
-from tests.utils import needs_pydanticv2
-
app = FastAPI()
# =====================================================================================
@@ -231,7 +229,6 @@ def read_model_required_validation_alias(
return {"p": p.p}
-@needs_pydanticv2
@pytest.mark.parametrize(
"path",
["/required-validation-alias", "/model-required-validation-alias"],
@@ -247,7 +244,6 @@ def test_required_validation_alias_schema(path: str):
]
-@needs_pydanticv2
@pytest.mark.parametrize(
"path",
[
@@ -274,7 +270,6 @@ def test_required_validation_alias_missing(path: str):
}
-@needs_pydanticv2
@pytest.mark.parametrize(
"path",
[
@@ -300,7 +295,6 @@ def test_required_validation_alias_by_name(path: str):
}
-@needs_pydanticv2
@pytest.mark.parametrize(
"path",
[
@@ -339,7 +333,6 @@ def read_model_required_alias_and_validation_alias(
return {"p": p.p}
-@needs_pydanticv2
@pytest.mark.parametrize(
"path",
[
@@ -358,7 +351,6 @@ def test_required_alias_and_validation_alias_schema(path: str):
]
-@needs_pydanticv2
@pytest.mark.parametrize(
"path",
[
@@ -385,7 +377,6 @@ def test_required_alias_and_validation_alias_missing(path: str):
}
-@needs_pydanticv2
@pytest.mark.parametrize(
"path",
[
@@ -417,7 +408,6 @@ def test_required_alias_and_validation_alias_by_name(path: str):
}
-@needs_pydanticv2
@pytest.mark.parametrize(
"path",
[
@@ -446,7 +436,6 @@ def test_required_alias_and_validation_alias_by_alias(path: str):
}
-@needs_pydanticv2
@pytest.mark.parametrize(
"path",
[
diff --git a/tests/test_request_params/test_file/test_list.py b/tests/test_request_params/test_file/test_list.py
index 52b032e441..90f36e5f7c 100644
--- a/tests/test_request_params/test_file/test_list.py
+++ b/tests/test_request_params/test_file/test_list.py
@@ -5,8 +5,6 @@ from dirty_equals import IsDict
from fastapi import FastAPI, File, UploadFile
from fastapi.testclient import TestClient
-from tests.utils import needs_pydanticv2
-
from .utils import get_body_model_name
app = FastAPI()
@@ -280,7 +278,6 @@ def read_list_uploadfile_validation_alias(
return {"file_size": [file.size for file in p]}
-@needs_pydanticv2
@pytest.mark.parametrize(
"path",
[
@@ -322,7 +319,6 @@ def test_list_validation_alias_schema(path: str):
}
-@needs_pydanticv2
@pytest.mark.parametrize(
"path",
[
@@ -349,7 +345,6 @@ def test_list_validation_alias_missing(path: str):
}
-@needs_pydanticv2
@pytest.mark.parametrize(
"path",
[
@@ -374,7 +369,6 @@ def test_list_validation_alias_by_name(path: str):
}
-@needs_pydanticv2
@pytest.mark.parametrize(
"path",
[
@@ -417,7 +411,6 @@ def read_list_uploadfile_alias_and_validation_alias(
return {"file_size": [file.size for file in p]}
-@needs_pydanticv2
@pytest.mark.parametrize(
"path",
[
@@ -459,7 +452,6 @@ def test_list_alias_and_validation_alias_schema(path: str):
}
-@needs_pydanticv2
@pytest.mark.parametrize(
"path",
[
@@ -486,7 +478,6 @@ def test_list_alias_and_validation_alias_missing(path: str):
}
-@needs_pydanticv2
@pytest.mark.parametrize(
"path",
[
@@ -514,7 +505,6 @@ def test_list_alias_and_validation_alias_by_name(path: str):
}
-@needs_pydanticv2
@pytest.mark.parametrize(
"path",
[
@@ -539,7 +529,6 @@ def test_list_alias_and_validation_alias_by_alias(path: str):
}
-@needs_pydanticv2
@pytest.mark.parametrize(
"path",
[
diff --git a/tests/test_request_params/test_file/test_optional.py b/tests/test_request_params/test_file/test_optional.py
index b7177e071d..4e9564873c 100644
--- a/tests/test_request_params/test_file/test_optional.py
+++ b/tests/test_request_params/test_file/test_optional.py
@@ -5,8 +5,6 @@ from dirty_equals import IsDict
from fastapi import FastAPI, File, UploadFile
from fastapi.testclient import TestClient
-from tests.utils import needs_pydanticv2
-
from .utils import get_body_model_name
app = FastAPI()
@@ -204,7 +202,6 @@ def read_optional_uploadfile_validation_alias(
return {"file_size": p.size if p else None}
-@needs_pydanticv2
@pytest.mark.parametrize(
"path",
[
@@ -239,7 +236,6 @@ def test_optional_validation_alias_schema(path: str):
}
-@needs_pydanticv2
@pytest.mark.parametrize(
"path",
[
@@ -254,7 +250,6 @@ def test_optional_validation_alias_missing(path: str):
assert response.json() == {"file_size": None}
-@needs_pydanticv2
@pytest.mark.parametrize(
"path",
[
@@ -269,7 +264,6 @@ def test_optional_validation_alias_by_name(path: str):
assert response.json() == {"file_size": None}
-@needs_pydanticv2
@pytest.mark.parametrize(
"path",
[
@@ -312,7 +306,6 @@ def read_optional_uploadfile_alias_and_validation_alias(
return {"file_size": p.size if p else None}
-@needs_pydanticv2
@pytest.mark.parametrize(
"path",
[
@@ -347,7 +340,6 @@ def test_optional_alias_and_validation_alias_schema(path: str):
}
-@needs_pydanticv2
@pytest.mark.parametrize(
"path",
[
@@ -362,7 +354,6 @@ def test_optional_alias_and_validation_alias_missing(path: str):
assert response.json() == {"file_size": None}
-@needs_pydanticv2
@pytest.mark.parametrize(
"path",
[
@@ -377,7 +368,6 @@ def test_optional_alias_and_validation_alias_by_name(path: str):
assert response.json() == {"file_size": None}
-@needs_pydanticv2
@pytest.mark.parametrize(
"path",
[
@@ -392,7 +382,6 @@ def test_optional_alias_and_validation_alias_by_alias(path: str):
assert response.json() == {"file_size": None}
-@needs_pydanticv2
@pytest.mark.parametrize(
"path",
[
diff --git a/tests/test_request_params/test_file/test_optional_list.py b/tests/test_request_params/test_file/test_optional_list.py
index af9fe552c9..e18f36e152 100644
--- a/tests/test_request_params/test_file/test_optional_list.py
+++ b/tests/test_request_params/test_file/test_optional_list.py
@@ -5,8 +5,6 @@ from dirty_equals import IsDict
from fastapi import FastAPI, File, UploadFile
from fastapi.testclient import TestClient
-from tests.utils import needs_pydanticv2
-
from .utils import get_body_model_name
app = FastAPI()
@@ -217,7 +215,6 @@ def read_optional_list_uploadfile_validation_alias(
return {"file_size": [file.size for file in p] if p else None}
-@needs_pydanticv2
@pytest.mark.parametrize(
"path",
[
@@ -259,7 +256,6 @@ def test_optional_validation_alias_schema(path: str):
}
-@needs_pydanticv2
@pytest.mark.parametrize(
"path",
[
@@ -274,7 +270,6 @@ def test_optional_validation_alias_missing(path: str):
assert response.json() == {"file_size": None}
-@needs_pydanticv2
@pytest.mark.parametrize(
"path",
[
@@ -289,7 +284,6 @@ def test_optional_validation_alias_by_name(path: str):
assert response.json() == {"file_size": None}
-@needs_pydanticv2
@pytest.mark.parametrize(
"path",
[
@@ -329,7 +323,6 @@ def read_optional_list_uploadfile_alias_and_validation_alias(
return {"file_size": [file.size for file in p] if p else None}
-@needs_pydanticv2
@pytest.mark.parametrize(
"path",
[
@@ -371,7 +364,6 @@ def test_optional_list_alias_and_validation_alias_schema(path: str):
}
-@needs_pydanticv2
@pytest.mark.parametrize(
"path",
[
@@ -386,7 +378,6 @@ def test_optional_list_alias_and_validation_alias_missing(path: str):
assert response.json() == {"file_size": None}
-@needs_pydanticv2
@pytest.mark.parametrize(
"path",
[
@@ -401,7 +392,6 @@ def test_optional_list_alias_and_validation_alias_by_name(path: str):
assert response.json() == {"file_size": None}
-@needs_pydanticv2
@pytest.mark.parametrize(
"path",
[
@@ -416,7 +406,6 @@ def test_optional_list_alias_and_validation_alias_by_alias(path: str):
assert response.json() == {"file_size": None}
-@needs_pydanticv2
@pytest.mark.parametrize(
"path",
[
diff --git a/tests/test_request_params/test_file/test_required.py b/tests/test_request_params/test_file/test_required.py
index 2979a1040a..9783f4bceb 100644
--- a/tests/test_request_params/test_file/test_required.py
+++ b/tests/test_request_params/test_file/test_required.py
@@ -5,8 +5,6 @@ from dirty_equals import IsDict
from fastapi import FastAPI, File, UploadFile
from fastapi.testclient import TestClient
-from tests.utils import needs_pydanticv2
-
from .utils import get_body_model_name
app = FastAPI()
@@ -242,7 +240,6 @@ def read_required_uploadfile_validation_alias(
return {"file_size": p.size}
-@needs_pydanticv2
@pytest.mark.parametrize(
"path",
[
@@ -268,7 +265,6 @@ def test_required_validation_alias_schema(path: str):
}
-@needs_pydanticv2
@pytest.mark.parametrize(
"path",
[
@@ -295,7 +291,6 @@ def test_required_validation_alias_missing(path: str):
}
-@needs_pydanticv2
@pytest.mark.parametrize(
"path",
[
@@ -320,7 +315,6 @@ def test_required_validation_alias_by_name(path: str):
}
-@needs_pydanticv2
@pytest.mark.parametrize(
"path",
[
@@ -359,7 +353,6 @@ def read_required_uploadfile_alias_and_validation_alias(
return {"file_size": p.size}
-@needs_pydanticv2
@pytest.mark.parametrize(
"path",
[
@@ -385,7 +378,6 @@ def test_required_alias_and_validation_alias_schema(path: str):
}
-@needs_pydanticv2
@pytest.mark.parametrize(
"path",
[
@@ -412,7 +404,6 @@ def test_required_alias_and_validation_alias_missing(path: str):
}
-@needs_pydanticv2
@pytest.mark.parametrize(
"path",
[
@@ -440,7 +431,6 @@ def test_required_alias_and_validation_alias_by_name(path: str):
}
-@needs_pydanticv2
@pytest.mark.parametrize(
"path",
[
@@ -465,7 +455,6 @@ def test_required_alias_and_validation_alias_by_alias(path: str):
}
-@needs_pydanticv2
@pytest.mark.parametrize(
"path",
[
diff --git a/tests/test_request_params/test_form/test_list.py b/tests/test_request_params/test_form/test_list.py
index 9f45aa755d..600dba4ae9 100644
--- a/tests/test_request_params/test_form/test_list.py
+++ b/tests/test_request_params/test_form/test_list.py
@@ -6,8 +6,6 @@ from fastapi import FastAPI, Form
from fastapi.testclient import TestClient
from pydantic import BaseModel, Field
-from tests.utils import needs_pydanticv2
-
from .utils import get_body_model_name
app = FastAPI()
@@ -247,7 +245,6 @@ async def read_model_required_list_validation_alias(
return {"p": p.p}
-@needs_pydanticv2
@pytest.mark.parametrize(
"path",
["/required-list-validation-alias", "/model-required-list-validation-alias"],
@@ -270,7 +267,6 @@ def test_required_list_validation_alias_schema(path: str):
}
-@needs_pydanticv2
@pytest.mark.parametrize(
"path",
[
@@ -297,7 +293,6 @@ def test_required_list_validation_alias_missing(path: str):
}
-@needs_pydanticv2
@pytest.mark.parametrize(
"path",
[
@@ -322,7 +317,6 @@ def test_required_list_validation_alias_by_name(path: str):
}
-@needs_pydanticv2
@pytest.mark.parametrize(
"path",
["/required-list-validation-alias", "/model-required-list-validation-alias"],
@@ -363,7 +357,6 @@ def read_model_required_list_alias_and_validation_alias(
return {"p": p.p}
-@needs_pydanticv2
@pytest.mark.parametrize(
"path",
[
@@ -389,7 +382,6 @@ def test_required_list_alias_and_validation_alias_schema(path: str):
}
-@needs_pydanticv2
@pytest.mark.parametrize(
"path",
[
@@ -416,7 +408,6 @@ def test_required_list_alias_and_validation_alias_missing(path: str):
}
-@needs_pydanticv2
@pytest.mark.parametrize(
"path",
[
@@ -446,7 +437,6 @@ def test_required_list_alias_and_validation_alias_by_name(path: str):
}
-@needs_pydanticv2
@pytest.mark.parametrize(
"path",
[
@@ -470,7 +460,6 @@ def test_required_list_alias_and_validation_alias_by_alias(path: str):
}
-@needs_pydanticv2
@pytest.mark.parametrize(
"path",
[
diff --git a/tests/test_request_params/test_form/test_optional_list.py b/tests/test_request_params/test_form/test_optional_list.py
index 0af6d34777..4552623f51 100644
--- a/tests/test_request_params/test_form/test_optional_list.py
+++ b/tests/test_request_params/test_form/test_optional_list.py
@@ -6,8 +6,6 @@ from fastapi import FastAPI, Form
from fastapi.testclient import TestClient
from pydantic import BaseModel, Field
-from tests.utils import needs_pydanticv2
-
from .utils import get_body_model_name
app = FastAPI()
@@ -211,7 +209,6 @@ def read_model_optional_list_validation_alias(
return {"p": p.p}
-@needs_pydanticv2
@pytest.mark.parametrize(
"path",
["/optional-list-validation-alias", "/model-optional-list-validation-alias"],
@@ -250,7 +247,6 @@ def test_optional_list_validation_alias_schema(path: str):
)
-@needs_pydanticv2
@pytest.mark.parametrize(
"path",
["/optional-list-validation-alias", "/model-optional-list-validation-alias"],
@@ -262,7 +258,6 @@ def test_optional_list_validation_alias_missing(path: str):
assert response.json() == {"p": None}
-@needs_pydanticv2
@pytest.mark.parametrize(
"path",
[
@@ -277,7 +272,6 @@ def test_optional_list_validation_alias_by_name(path: str):
assert response.json() == {"p": None}
-@needs_pydanticv2
@pytest.mark.parametrize(
"path",
["/optional-list-validation-alias", "/model-optional-list-validation-alias"],
@@ -321,7 +315,6 @@ def read_model_optional_list_alias_and_validation_alias(
return {"p": p.p}
-@needs_pydanticv2
@pytest.mark.parametrize(
"path",
[
@@ -363,7 +356,6 @@ def test_optional_list_alias_and_validation_alias_schema(path: str):
)
-@needs_pydanticv2
@pytest.mark.parametrize(
"path",
[
@@ -378,7 +370,6 @@ def test_optional_list_alias_and_validation_alias_missing(path: str):
assert response.json() == {"p": None}
-@needs_pydanticv2
@pytest.mark.parametrize(
"path",
[
@@ -393,7 +384,6 @@ def test_optional_list_alias_and_validation_alias_by_name(path: str):
assert response.json() == {"p": None}
-@needs_pydanticv2
@pytest.mark.parametrize(
"path",
[
@@ -408,7 +398,6 @@ def test_optional_list_alias_and_validation_alias_by_alias(path: str):
assert response.json() == {"p": None}
-@needs_pydanticv2
@pytest.mark.parametrize(
"path",
[
diff --git a/tests/test_request_params/test_form/test_optional_str.py b/tests/test_request_params/test_form/test_optional_str.py
index 92329216ec..1b08299046 100644
--- a/tests/test_request_params/test_form/test_optional_str.py
+++ b/tests/test_request_params/test_form/test_optional_str.py
@@ -6,8 +6,6 @@ from fastapi import FastAPI, Form
from fastapi.testclient import TestClient
from pydantic import BaseModel, Field
-from tests.utils import needs_pydanticv2
-
from .utils import get_body_model_name
app = FastAPI()
@@ -194,7 +192,6 @@ def read_model_optional_validation_alias(
return {"p": p.p}
-@needs_pydanticv2
@pytest.mark.parametrize(
"path",
["/optional-validation-alias", "/model-optional-validation-alias"],
@@ -226,7 +223,6 @@ def test_optional_validation_alias_schema(path: str):
)
-@needs_pydanticv2
@pytest.mark.parametrize(
"path",
["/optional-validation-alias", "/model-optional-validation-alias"],
@@ -238,7 +234,6 @@ def test_optional_validation_alias_missing(path: str):
assert response.json() == {"p": None}
-@needs_pydanticv2
@pytest.mark.parametrize(
"path",
[
@@ -253,7 +248,6 @@ def test_optional_validation_alias_by_name(path: str):
assert response.json() == {"p": None}
-@needs_pydanticv2
@pytest.mark.parametrize(
"path",
[
@@ -298,7 +292,6 @@ def read_model_optional_alias_and_validation_alias(
return {"p": p.p}
-@needs_pydanticv2
@pytest.mark.parametrize(
"path",
[
@@ -333,7 +326,6 @@ def test_optional_alias_and_validation_alias_schema(path: str):
)
-@needs_pydanticv2
@pytest.mark.parametrize(
"path",
[
@@ -348,7 +340,6 @@ def test_optional_alias_and_validation_alias_missing(path: str):
assert response.json() == {"p": None}
-@needs_pydanticv2
@pytest.mark.parametrize(
"path",
[
@@ -363,7 +354,6 @@ def test_optional_alias_and_validation_alias_by_name(path: str):
assert response.json() == {"p": None}
-@needs_pydanticv2
@pytest.mark.parametrize(
"path",
[
@@ -378,7 +368,6 @@ def test_optional_alias_and_validation_alias_by_alias(path: str):
assert response.json() == {"p": None}
-@needs_pydanticv2
@pytest.mark.parametrize(
"path",
[
diff --git a/tests/test_request_params/test_form/test_required_str.py b/tests/test_request_params/test_form/test_required_str.py
index 1e33038040..1d2431b333 100644
--- a/tests/test_request_params/test_form/test_required_str.py
+++ b/tests/test_request_params/test_form/test_required_str.py
@@ -6,8 +6,6 @@ from fastapi import FastAPI, Form
from fastapi.testclient import TestClient
from pydantic import BaseModel, Field
-from tests.utils import needs_pydanticv2
-
from .utils import get_body_model_name
app = FastAPI()
@@ -232,7 +230,6 @@ def read_model_required_validation_alias(
return {"p": p.p}
-@needs_pydanticv2
@pytest.mark.parametrize(
"path",
["/required-validation-alias", "/model-required-validation-alias"],
@@ -251,7 +248,6 @@ def test_required_validation_alias_schema(path: str):
}
-@needs_pydanticv2
@pytest.mark.parametrize(
"path",
[
@@ -278,7 +274,6 @@ def test_required_validation_alias_missing(path: str):
}
-@needs_pydanticv2
@pytest.mark.parametrize(
"path",
[
@@ -303,7 +298,6 @@ def test_required_validation_alias_by_name(path: str):
}
-@needs_pydanticv2
@pytest.mark.parametrize(
"path",
[
@@ -347,7 +341,6 @@ def read_model_required_alias_and_validation_alias(
return {"p": p.p}
-@needs_pydanticv2
@pytest.mark.parametrize(
"path",
[
@@ -369,7 +362,6 @@ def test_required_alias_and_validation_alias_schema(path: str):
}
-@needs_pydanticv2
@pytest.mark.parametrize(
"path",
[
@@ -396,7 +388,6 @@ def test_required_alias_and_validation_alias_missing(path: str):
}
-@needs_pydanticv2
@pytest.mark.parametrize(
"path",
[
@@ -424,7 +415,6 @@ def test_required_alias_and_validation_alias_by_name(path: str):
}
-@needs_pydanticv2
@pytest.mark.parametrize(
"path",
[
@@ -449,7 +439,6 @@ def test_required_alias_and_validation_alias_by_alias(path: str):
}
-@needs_pydanticv2
@pytest.mark.parametrize(
"path",
[
diff --git a/tests/test_request_params/test_header/test_list.py b/tests/test_request_params/test_header/test_list.py
index 62f9f36ff6..2eba17559e 100644
--- a/tests/test_request_params/test_header/test_list.py
+++ b/tests/test_request_params/test_header/test_list.py
@@ -6,8 +6,6 @@ from fastapi import FastAPI, Header
from fastapi.testclient import TestClient
from pydantic import BaseModel, Field
-from tests.utils import needs_pydanticv2
-
app = FastAPI()
# =====================================================================================
@@ -234,7 +232,6 @@ async def read_model_required_list_validation_alias(
return {"p": p.p}
-@needs_pydanticv2
@pytest.mark.parametrize(
"path",
["/required-list-validation-alias", "/model-required-list-validation-alias"],
@@ -254,7 +251,6 @@ def test_required_list_validation_alias_schema(path: str):
]
-@needs_pydanticv2
@pytest.mark.parametrize(
"path",
[
@@ -281,7 +277,6 @@ def test_required_list_validation_alias_missing(path: str):
}
-@needs_pydanticv2
@pytest.mark.parametrize(
"path",
[
@@ -306,7 +301,6 @@ def test_required_list_validation_alias_by_name(path: str):
}
-@needs_pydanticv2
@pytest.mark.parametrize(
"path",
["/required-list-validation-alias", "/model-required-list-validation-alias"],
@@ -343,7 +337,6 @@ def read_model_required_list_alias_and_validation_alias(
return {"p": p.p}
-@needs_pydanticv2
@pytest.mark.parametrize(
"path",
[
@@ -366,7 +359,6 @@ def test_required_list_alias_and_validation_alias_schema(path: str):
]
-@needs_pydanticv2
@pytest.mark.parametrize(
"path",
[
@@ -393,7 +385,6 @@ def test_required_list_alias_and_validation_alias_missing(path: str):
}
-@needs_pydanticv2
@pytest.mark.parametrize(
"path",
[
@@ -423,7 +414,6 @@ def test_required_list_alias_and_validation_alias_by_name(path: str):
}
-@needs_pydanticv2
@pytest.mark.parametrize(
"path",
[
@@ -450,7 +440,6 @@ def test_required_list_alias_and_validation_alias_by_alias(path: str):
}
-@needs_pydanticv2
@pytest.mark.parametrize(
"path",
[
diff --git a/tests/test_request_params/test_header/test_optional_list.py b/tests/test_request_params/test_header/test_optional_list.py
index 88243f05a9..cd6167a183 100644
--- a/tests/test_request_params/test_header/test_optional_list.py
+++ b/tests/test_request_params/test_header/test_optional_list.py
@@ -6,8 +6,6 @@ from fastapi import FastAPI, Header
from fastapi.testclient import TestClient
from pydantic import BaseModel, Field
-from tests.utils import needs_pydanticv2
-
app = FastAPI()
# =====================================================================================
@@ -202,7 +200,6 @@ def read_model_optional_list_validation_alias(
return {"p": p.p}
-@needs_pydanticv2
@pytest.mark.parametrize(
"path",
["/optional-list-validation-alias", "/model-optional-list-validation-alias"],
@@ -224,7 +221,6 @@ def test_optional_list_validation_alias_schema(path: str):
]
-@needs_pydanticv2
@pytest.mark.parametrize(
"path",
["/optional-list-validation-alias", "/model-optional-list-validation-alias"],
@@ -236,7 +232,6 @@ def test_optional_list_validation_alias_missing(path: str):
assert response.json() == {"p": None}
-@needs_pydanticv2
@pytest.mark.parametrize(
"path",
[
@@ -251,7 +246,6 @@ def test_optional_list_validation_alias_by_name(path: str):
assert response.json() == {"p": None}
-@needs_pydanticv2
@pytest.mark.parametrize(
"path",
["/optional-list-validation-alias", "/model-optional-list-validation-alias"],
@@ -291,7 +285,6 @@ def read_model_optional_list_alias_and_validation_alias(
return {"p": p.p}
-@needs_pydanticv2
@pytest.mark.parametrize(
"path",
[
@@ -316,7 +309,6 @@ def test_optional_list_alias_and_validation_alias_schema(path: str):
]
-@needs_pydanticv2
@pytest.mark.parametrize(
"path",
[
@@ -331,7 +323,6 @@ def test_optional_list_alias_and_validation_alias_missing(path: str):
assert response.json() == {"p": None}
-@needs_pydanticv2
@pytest.mark.parametrize(
"path",
[
@@ -346,7 +337,6 @@ def test_optional_list_alias_and_validation_alias_by_name(path: str):
assert response.json() == {"p": None}
-@needs_pydanticv2
@pytest.mark.parametrize(
"path",
[
@@ -361,7 +351,6 @@ def test_optional_list_alias_and_validation_alias_by_alias(path: str):
assert response.json() == {"p": None}
-@needs_pydanticv2
@pytest.mark.parametrize(
"path",
[
diff --git a/tests/test_request_params/test_header/test_optional_str.py b/tests/test_request_params/test_header/test_optional_str.py
index e40b1669ee..d4f25cc1e7 100644
--- a/tests/test_request_params/test_header/test_optional_str.py
+++ b/tests/test_request_params/test_header/test_optional_str.py
@@ -6,8 +6,6 @@ from fastapi import FastAPI, Header
from fastapi.testclient import TestClient
from pydantic import BaseModel, Field
-from tests.utils import needs_pydanticv2
-
app = FastAPI()
# =====================================================================================
@@ -186,7 +184,6 @@ def read_model_optional_validation_alias(
return {"p": p.p}
-@needs_pydanticv2
@pytest.mark.parametrize(
"path",
["/optional-validation-alias", "/model-optional-validation-alias"],
@@ -205,7 +202,6 @@ def test_optional_validation_alias_schema(path: str):
]
-@needs_pydanticv2
@pytest.mark.parametrize(
"path",
["/optional-validation-alias", "/model-optional-validation-alias"],
@@ -217,7 +213,6 @@ def test_optional_validation_alias_missing(path: str):
assert response.json() == {"p": None}
-@needs_pydanticv2
@pytest.mark.parametrize(
"path",
[
@@ -232,7 +227,6 @@ def test_optional_validation_alias_by_name(path: str):
assert response.json() == {"p": None}
-@needs_pydanticv2
@pytest.mark.parametrize(
"path",
[
@@ -271,7 +265,6 @@ def read_model_optional_alias_and_validation_alias(
return {"p": p.p}
-@needs_pydanticv2
@pytest.mark.parametrize(
"path",
[
@@ -293,7 +286,6 @@ def test_optional_alias_and_validation_alias_schema(path: str):
]
-@needs_pydanticv2
@pytest.mark.parametrize(
"path",
[
@@ -308,7 +300,6 @@ def test_optional_alias_and_validation_alias_missing(path: str):
assert response.json() == {"p": None}
-@needs_pydanticv2
@pytest.mark.parametrize(
"path",
[
@@ -323,7 +314,6 @@ def test_optional_alias_and_validation_alias_by_name(path: str):
assert response.json() == {"p": None}
-@needs_pydanticv2
@pytest.mark.parametrize(
"path",
[
@@ -338,7 +328,6 @@ def test_optional_alias_and_validation_alias_by_alias(path: str):
assert response.json() == {"p": None}
-@needs_pydanticv2
@pytest.mark.parametrize(
"path",
[
diff --git a/tests/test_request_params/test_header/test_required_str.py b/tests/test_request_params/test_header/test_required_str.py
index 23554d3e4a..85bb43d5a8 100644
--- a/tests/test_request_params/test_header/test_required_str.py
+++ b/tests/test_request_params/test_header/test_required_str.py
@@ -6,8 +6,6 @@ from fastapi import FastAPI, Header
from fastapi.testclient import TestClient
from pydantic import BaseModel, Field
-from tests.utils import needs_pydanticv2
-
app = FastAPI()
# =====================================================================================
@@ -225,7 +223,6 @@ def read_model_required_validation_alias(
return {"p": p.p}
-@needs_pydanticv2
@pytest.mark.parametrize(
"path",
["/required-validation-alias", "/model-required-validation-alias"],
@@ -241,7 +238,6 @@ def test_required_validation_alias_schema(path: str):
]
-@needs_pydanticv2
@pytest.mark.parametrize(
"path",
[
@@ -268,7 +264,6 @@ def test_required_validation_alias_missing(path: str):
}
-@needs_pydanticv2
@pytest.mark.parametrize(
"path",
[
@@ -293,7 +288,6 @@ def test_required_validation_alias_by_name(path: str):
}
-@needs_pydanticv2
@pytest.mark.parametrize(
"path",
[
@@ -331,7 +325,6 @@ def read_model_required_alias_and_validation_alias(
return {"p": p.p}
-@needs_pydanticv2
@pytest.mark.parametrize(
"path",
[
@@ -350,7 +343,6 @@ def test_required_alias_and_validation_alias_schema(path: str):
]
-@needs_pydanticv2
@pytest.mark.parametrize(
"path",
[
@@ -377,7 +369,6 @@ def test_required_alias_and_validation_alias_missing(path: str):
}
-@needs_pydanticv2
@pytest.mark.parametrize(
"path",
[
@@ -408,7 +399,6 @@ def test_required_alias_and_validation_alias_by_name(path: str):
}
-@needs_pydanticv2
@pytest.mark.parametrize(
"path",
[
@@ -436,7 +426,6 @@ def test_required_alias_and_validation_alias_by_alias(path: str):
}
-@needs_pydanticv2
@pytest.mark.parametrize(
"path",
[
diff --git a/tests/test_request_params/test_path/test_required_str.py b/tests/test_request_params/test_path/test_required_str.py
index ecd4eb61cd..b2d63667e2 100644
--- a/tests/test_request_params/test_path/test_required_str.py
+++ b/tests/test_request_params/test_path/test_required_str.py
@@ -4,8 +4,6 @@ import pytest
from fastapi import FastAPI, Path
from fastapi.testclient import TestClient
-from tests.utils import needs_pydanticv2
-
app = FastAPI()
@@ -45,14 +43,12 @@ def read_required_alias_and_validation_alias(
"p_val_alias",
"P Val Alias",
id="required-validation-alias",
- marks=needs_pydanticv2,
),
pytest.param(
"/required-alias-and-validation-alias/{p_val_alias}",
"p_val_alias",
"P Val Alias",
id="required-alias-and-validation-alias",
- marks=needs_pydanticv2,
),
],
)
@@ -75,12 +71,10 @@ def test_schema(path: str, expected_name: str, expected_title: str):
pytest.param(
"/required-validation-alias",
id="required-validation-alias",
- marks=needs_pydanticv2,
),
pytest.param(
"/required-alias-and-validation-alias",
id="required-alias-and-validation-alias",
- marks=needs_pydanticv2,
),
],
)
diff --git a/tests/test_request_params/test_query/test_list.py b/tests/test_request_params/test_query/test_list.py
index 6a3000fbf6..dc21a85006 100644
--- a/tests/test_request_params/test_query/test_list.py
+++ b/tests/test_request_params/test_query/test_list.py
@@ -6,8 +6,6 @@ from fastapi import FastAPI, Query
from fastapi.testclient import TestClient
from pydantic import BaseModel, Field
-from tests.utils import needs_pydanticv2
-
app = FastAPI()
# =====================================================================================
@@ -234,7 +232,6 @@ async def read_model_required_list_validation_alias(
return {"p": p.p}
-@needs_pydanticv2
@pytest.mark.parametrize(
"path",
["/required-list-validation-alias", "/model-required-list-validation-alias"],
@@ -254,7 +251,6 @@ def test_required_list_validation_alias_schema(path: str):
]
-@needs_pydanticv2
@pytest.mark.parametrize(
"path",
[
@@ -281,7 +277,6 @@ def test_required_list_validation_alias_missing(path: str):
}
-@needs_pydanticv2
@pytest.mark.parametrize(
"path",
[
@@ -306,7 +301,6 @@ def test_required_list_validation_alias_by_name(path: str):
}
-@needs_pydanticv2
@pytest.mark.parametrize(
"path",
["/required-list-validation-alias", "/model-required-list-validation-alias"],
@@ -341,7 +335,6 @@ def read_model_required_list_alias_and_validation_alias(
return {"p": p.p}
-@needs_pydanticv2
@pytest.mark.parametrize(
"path",
[
@@ -364,7 +357,6 @@ def test_required_list_alias_and_validation_alias_schema(path: str):
]
-@needs_pydanticv2
@pytest.mark.parametrize(
"path",
[
@@ -391,7 +383,6 @@ def test_required_list_alias_and_validation_alias_missing(path: str):
}
-@needs_pydanticv2
@pytest.mark.parametrize(
"path",
[
@@ -426,7 +417,6 @@ def test_required_list_alias_and_validation_alias_by_name(path: str):
}
-@needs_pydanticv2
@pytest.mark.parametrize(
"path",
[
@@ -453,7 +443,6 @@ def test_required_list_alias_and_validation_alias_by_alias(path: str):
}
-@needs_pydanticv2
@pytest.mark.parametrize(
"path",
[
diff --git a/tests/test_request_params/test_query/test_optional_list.py b/tests/test_request_params/test_query/test_optional_list.py
index f4b8ec6a82..2a8f63a36a 100644
--- a/tests/test_request_params/test_query/test_optional_list.py
+++ b/tests/test_request_params/test_query/test_optional_list.py
@@ -6,8 +6,6 @@ from fastapi import FastAPI, Query
from fastapi.testclient import TestClient
from pydantic import BaseModel, Field
-from tests.utils import needs_pydanticv2
-
app = FastAPI()
# =====================================================================================
@@ -202,7 +200,6 @@ def read_model_optional_list_validation_alias(
return {"p": p.p}
-@needs_pydanticv2
@pytest.mark.parametrize(
"path",
["/optional-list-validation-alias", "/model-optional-list-validation-alias"],
@@ -224,7 +221,6 @@ def test_optional_list_validation_alias_schema(path: str):
]
-@needs_pydanticv2
@pytest.mark.parametrize(
"path",
["/optional-list-validation-alias", "/model-optional-list-validation-alias"],
@@ -236,7 +232,6 @@ def test_optional_list_validation_alias_missing(path: str):
assert response.json() == {"p": None}
-@needs_pydanticv2
@pytest.mark.parametrize(
"path",
[
@@ -251,7 +246,6 @@ def test_optional_list_validation_alias_by_name(path: str):
assert response.json() == {"p": None}
-@needs_pydanticv2
@pytest.mark.parametrize(
"path",
["/optional-list-validation-alias", "/model-optional-list-validation-alias"],
@@ -289,7 +283,6 @@ def read_model_optional_list_alias_and_validation_alias(
return {"p": p.p}
-@needs_pydanticv2
@pytest.mark.parametrize(
"path",
[
@@ -314,7 +307,6 @@ def test_optional_list_alias_and_validation_alias_schema(path: str):
]
-@needs_pydanticv2
@pytest.mark.parametrize(
"path",
[
@@ -329,7 +321,6 @@ def test_optional_list_alias_and_validation_alias_missing(path: str):
assert response.json() == {"p": None}
-@needs_pydanticv2
@pytest.mark.parametrize(
"path",
[
@@ -344,7 +335,6 @@ def test_optional_list_alias_and_validation_alias_by_name(path: str):
assert response.json() == {"p": None}
-@needs_pydanticv2
@pytest.mark.parametrize(
"path",
[
@@ -359,7 +349,6 @@ def test_optional_list_alias_and_validation_alias_by_alias(path: str):
assert response.json() == {"p": None}
-@needs_pydanticv2
@pytest.mark.parametrize(
"path",
[
diff --git a/tests/test_request_params/test_query/test_optional_str.py b/tests/test_request_params/test_query/test_optional_str.py
index c7d20e37d1..c6a70bc283 100644
--- a/tests/test_request_params/test_query/test_optional_str.py
+++ b/tests/test_request_params/test_query/test_optional_str.py
@@ -6,8 +6,6 @@ from fastapi import FastAPI, Query
from fastapi.testclient import TestClient
from pydantic import BaseModel, Field
-from tests.utils import needs_pydanticv2
-
app = FastAPI()
# =====================================================================================
@@ -186,7 +184,6 @@ def read_model_optional_validation_alias(
return {"p": p.p}
-@needs_pydanticv2
@pytest.mark.parametrize(
"path",
["/optional-validation-alias", "/model-optional-validation-alias"],
@@ -205,7 +202,6 @@ def test_optional_validation_alias_schema(path: str):
]
-@needs_pydanticv2
@pytest.mark.parametrize(
"path",
["/optional-validation-alias", "/model-optional-validation-alias"],
@@ -217,7 +213,6 @@ def test_optional_validation_alias_missing(path: str):
assert response.json() == {"p": None}
-@needs_pydanticv2
@pytest.mark.parametrize(
"path",
[
@@ -232,7 +227,6 @@ def test_optional_validation_alias_by_name(path: str):
assert response.json() == {"p": None}
-@needs_pydanticv2
@pytest.mark.parametrize(
"path",
[
@@ -271,7 +265,6 @@ def read_model_optional_alias_and_validation_alias(
return {"p": p.p}
-@needs_pydanticv2
@pytest.mark.parametrize(
"path",
[
@@ -293,7 +286,6 @@ def test_optional_alias_and_validation_alias_schema(path: str):
]
-@needs_pydanticv2
@pytest.mark.parametrize(
"path",
[
@@ -308,7 +300,6 @@ def test_optional_alias_and_validation_alias_missing(path: str):
assert response.json() == {"p": None}
-@needs_pydanticv2
@pytest.mark.parametrize(
"path",
[
@@ -323,7 +314,6 @@ def test_optional_alias_and_validation_alias_by_name(path: str):
assert response.json() == {"p": None}
-@needs_pydanticv2
@pytest.mark.parametrize(
"path",
[
@@ -338,7 +328,6 @@ def test_optional_alias_and_validation_alias_by_alias(path: str):
assert response.json() == {"p": None}
-@needs_pydanticv2
@pytest.mark.parametrize(
"path",
[
diff --git a/tests/test_request_params/test_query/test_required_str.py b/tests/test_request_params/test_query/test_required_str.py
index ce30f3b1f8..2ef1b0373d 100644
--- a/tests/test_request_params/test_query/test_required_str.py
+++ b/tests/test_request_params/test_query/test_required_str.py
@@ -6,8 +6,6 @@ from fastapi import FastAPI, Query
from fastapi.testclient import TestClient
from pydantic import BaseModel, Field
-from tests.utils import needs_pydanticv2
-
app = FastAPI()
# =====================================================================================
@@ -228,7 +226,6 @@ def read_model_required_validation_alias(
return {"p": p.p}
-@needs_pydanticv2
@pytest.mark.parametrize(
"path",
["/required-validation-alias", "/model-required-validation-alias"],
@@ -244,7 +241,6 @@ def test_required_validation_alias_schema(path: str):
]
-@needs_pydanticv2
@pytest.mark.parametrize(
"path",
[
@@ -271,7 +267,6 @@ def test_required_validation_alias_missing(path: str):
}
-@needs_pydanticv2
@pytest.mark.parametrize(
"path",
[
@@ -296,7 +291,6 @@ def test_required_validation_alias_by_name(path: str):
}
-@needs_pydanticv2
@pytest.mark.parametrize(
"path",
[
@@ -334,7 +328,6 @@ def read_model_required_alias_and_validation_alias(
return {"p": p.p}
-@needs_pydanticv2
@pytest.mark.parametrize(
"path",
[
@@ -353,7 +346,6 @@ def test_required_alias_and_validation_alias_schema(path: str):
]
-@needs_pydanticv2
@pytest.mark.parametrize(
"path",
[
@@ -380,7 +372,6 @@ def test_required_alias_and_validation_alias_missing(path: str):
}
-@needs_pydanticv2
@pytest.mark.parametrize(
"path",
[
@@ -411,7 +402,6 @@ def test_required_alias_and_validation_alias_by_name(path: str):
}
-@needs_pydanticv2
@pytest.mark.parametrize(
"path",
[
@@ -439,7 +429,6 @@ def test_required_alias_and_validation_alias_by_alias(path: str):
}
-@needs_pydanticv2
@pytest.mark.parametrize(
"path",
[
diff --git a/tests/test_response_by_alias.py b/tests/test_response_by_alias.py
index 5b241c76b6..807d2600b9 100644
--- a/tests/test_response_by_alias.py
+++ b/tests/test_response_by_alias.py
@@ -1,5 +1,4 @@
from fastapi import FastAPI
-from fastapi._compat import PYDANTIC_V2
from fastapi.testclient import TestClient
from pydantic import BaseModel, ConfigDict, Field
@@ -13,24 +12,14 @@ class Model(BaseModel):
class ModelNoAlias(BaseModel):
name: str
- if PYDANTIC_V2:
- model_config = ConfigDict(
- json_schema_extra={
- "description": (
- "response_model_by_alias=False is basically a quick hack, to support "
- "proper OpenAPI use another model with the correct field names"
- )
- }
- )
- else:
-
- class Config:
- schema_extra = {
- "description": (
- "response_model_by_alias=False is basically a quick hack, to support "
- "proper OpenAPI use another model with the correct field names"
- )
- }
+ model_config = ConfigDict(
+ json_schema_extra={
+ "description": (
+ "response_model_by_alias=False is basically a quick hack, to support "
+ "proper OpenAPI use another model with the correct field names"
+ )
+ }
+ )
@app.get("/dict", response_model=Model, response_model_by_alias=False)
diff --git a/tests/test_schema_compat_pydantic_v2.py b/tests/test_schema_compat_pydantic_v2.py
index 39626c0eca..737687f256 100644
--- a/tests/test_schema_compat_pydantic_v2.py
+++ b/tests/test_schema_compat_pydantic_v2.py
@@ -4,7 +4,7 @@ from fastapi.testclient import TestClient
from inline_snapshot import snapshot
from pydantic import BaseModel
-from tests.utils import needs_py310, needs_pydanticv2
+from tests.utils import needs_py310
@pytest.fixture(name="client")
@@ -32,14 +32,12 @@ def get_client():
@needs_py310
-@needs_pydanticv2
def test_get(client: TestClient):
response = client.get("/users")
assert response.json() == {"username": "alice", "role": "admin"}
@needs_py310
-@needs_pydanticv2
def test_openapi_schema(client: TestClient):
response = client.get("openapi.json")
assert response.json() == snapshot(
diff --git a/tests/test_schema_extra_examples.py b/tests/test_schema_extra_examples.py
index b313f47e90..176b5588d7 100644
--- a/tests/test_schema_extra_examples.py
+++ b/tests/test_schema_extra_examples.py
@@ -3,7 +3,6 @@ from typing import Union
import pytest
from dirty_equals import IsDict
from fastapi import Body, Cookie, FastAPI, Header, Path, Query
-from fastapi._compat import PYDANTIC_V2
from fastapi.testclient import TestClient
from pydantic import BaseModel, ConfigDict
@@ -14,14 +13,9 @@ def create_app():
class Item(BaseModel):
data: str
- if PYDANTIC_V2:
- model_config = ConfigDict(
- json_schema_extra={"example": {"data": "Data in schema_extra"}}
- )
- else:
-
- class Config:
- schema_extra = {"example": {"data": "Data in schema_extra"}}
+ model_config = ConfigDict(
+ json_schema_extra={"example": {"data": "Data in schema_extra"}}
+ )
@app.post("/schema_extra/")
def schema_extra(item: Item):
diff --git a/tests/test_schema_ref_pydantic_v2.py b/tests/test_schema_ref_pydantic_v2.py
index 119b76a529..69cb82a356 100644
--- a/tests/test_schema_ref_pydantic_v2.py
+++ b/tests/test_schema_ref_pydantic_v2.py
@@ -6,8 +6,6 @@ from fastapi.testclient import TestClient
from inline_snapshot import snapshot
from pydantic import BaseModel, ConfigDict, Field
-from tests.utils import needs_pydanticv2
-
@pytest.fixture(name="client")
def get_client():
@@ -25,13 +23,11 @@ def get_client():
return client
-@needs_pydanticv2
def test_get(client: TestClient):
response = client.get("/")
assert response.json() == {"$ref": "some-ref"}
-@needs_pydanticv2
def test_openapi_schema(client: TestClient):
response = client.get("openapi.json")
assert response.json() == snapshot(
diff --git a/tests/test_tutorial/test_body_updates/test_tutorial001.py b/tests/test_tutorial/test_body_updates/test_tutorial001.py
index 8bbc4d6992..0401eb7d0d 100644
--- a/tests/test_tutorial/test_body_updates/test_tutorial001.py
+++ b/tests/test_tutorial/test_body_updates/test_tutorial001.py
@@ -3,7 +3,7 @@ import importlib
import pytest
from fastapi.testclient import TestClient
-from ...utils import needs_py310, needs_pydanticv1, needs_pydanticv2
+from ...utils import needs_py310
@pytest.fixture(
@@ -45,7 +45,6 @@ def test_put(client: TestClient):
}
-@needs_pydanticv2
def test_openapi_schema(client: TestClient):
response = client.get("/openapi.json")
assert response.status_code == 200, response.text
@@ -185,137 +184,3 @@ def test_openapi_schema(client: TestClient):
}
},
}
-
-
-# TODO: remove when deprecating Pydantic v1
-@needs_pydanticv1
-def test_openapi_schema_pv1(client: TestClient):
- response = client.get("/openapi.json")
- assert response.status_code == 200, response.text
- assert response.json() == {
- "openapi": "3.1.0",
- "info": {"title": "FastAPI", "version": "0.1.0"},
- "paths": {
- "/items/{item_id}": {
- "get": {
- "responses": {
- "200": {
- "description": "Successful Response",
- "content": {
- "application/json": {
- "schema": {"$ref": "#/components/schemas/Item"}
- }
- },
- },
- "422": {
- "description": "Validation Error",
- "content": {
- "application/json": {
- "schema": {
- "$ref": "#/components/schemas/HTTPValidationError"
- }
- }
- },
- },
- },
- "summary": "Read Item",
- "operationId": "read_item_items__item_id__get",
- "parameters": [
- {
- "required": True,
- "schema": {"title": "Item Id", "type": "string"},
- "name": "item_id",
- "in": "path",
- }
- ],
- },
- "put": {
- "responses": {
- "200": {
- "description": "Successful Response",
- "content": {
- "application/json": {
- "schema": {"$ref": "#/components/schemas/Item"}
- }
- },
- },
- "422": {
- "description": "Validation Error",
- "content": {
- "application/json": {
- "schema": {
- "$ref": "#/components/schemas/HTTPValidationError"
- }
- }
- },
- },
- },
- "summary": "Update Item",
- "operationId": "update_item_items__item_id__put",
- "parameters": [
- {
- "required": True,
- "schema": {"title": "Item Id", "type": "string"},
- "name": "item_id",
- "in": "path",
- }
- ],
- "requestBody": {
- "content": {
- "application/json": {
- "schema": {"$ref": "#/components/schemas/Item"}
- }
- },
- "required": True,
- },
- },
- }
- },
- "components": {
- "schemas": {
- "Item": {
- "title": "Item",
- "type": "object",
- "properties": {
- "name": {"title": "Name", "type": "string"},
- "description": {"title": "Description", "type": "string"},
- "price": {"title": "Price", "type": "number"},
- "tax": {"title": "Tax", "type": "number", "default": 10.5},
- "tags": {
- "title": "Tags",
- "type": "array",
- "items": {"type": "string"},
- "default": [],
- },
- },
- },
- "ValidationError": {
- "title": "ValidationError",
- "required": ["loc", "msg", "type"],
- "type": "object",
- "properties": {
- "loc": {
- "title": "Location",
- "type": "array",
- "items": {
- "anyOf": [{"type": "string"}, {"type": "integer"}]
- },
- },
- "msg": {"title": "Message", "type": "string"},
- "type": {"title": "Error Type", "type": "string"},
- },
- },
- "HTTPValidationError": {
- "title": "HTTPValidationError",
- "type": "object",
- "properties": {
- "detail": {
- "title": "Detail",
- "type": "array",
- "items": {"$ref": "#/components/schemas/ValidationError"},
- }
- },
- },
- }
- },
- }
diff --git a/tests/test_tutorial/test_conditional_openapi/test_tutorial001.py b/tests/test_tutorial/test_conditional_openapi/test_tutorial001.py
index a425e893d8..ddc282d85e 100644
--- a/tests/test_tutorial/test_conditional_openapi/test_tutorial001.py
+++ b/tests/test_tutorial/test_conditional_openapi/test_tutorial001.py
@@ -2,8 +2,6 @@ import importlib
from fastapi.testclient import TestClient
-from ...utils import needs_pydanticv2
-
def get_client() -> TestClient:
from docs_src.conditional_openapi import tutorial001_py39
@@ -14,7 +12,6 @@ def get_client() -> TestClient:
return client
-@needs_pydanticv2
def test_disable_openapi(monkeypatch):
monkeypatch.setenv("OPENAPI_URL", "")
# Load the client after setting the env var
@@ -27,7 +24,6 @@ def test_disable_openapi(monkeypatch):
assert response.status_code == 404, response.text
-@needs_pydanticv2
def test_root():
client = get_client()
response = client.get("/")
@@ -35,7 +31,6 @@ def test_root():
assert response.json() == {"message": "Hello World"}
-@needs_pydanticv2
def test_default_openapi():
client = get_client()
response = client.get("/docs")
diff --git a/tests/test_tutorial/test_cookie_param_models/test_tutorial002.py b/tests/test_tutorial/test_cookie_param_models/test_tutorial002.py
index 4a826a5374..0fbf141e05 100644
--- a/tests/test_tutorial/test_cookie_param_models/test_tutorial002.py
+++ b/tests/test_tutorial/test_cookie_param_models/test_tutorial002.py
@@ -5,25 +5,16 @@ from dirty_equals import IsDict
from fastapi.testclient import TestClient
from inline_snapshot import snapshot
-from tests.utils import (
- needs_py310,
- needs_pydanticv1,
- needs_pydanticv2,
- pydantic_snapshot,
-)
+from tests.utils import needs_py310
@pytest.fixture(
name="client",
params=[
- pytest.param("tutorial002_py39", marks=needs_pydanticv2),
- pytest.param("tutorial002_py310", marks=[needs_py310, needs_pydanticv2]),
- pytest.param("tutorial002_an_py39", marks=needs_pydanticv2),
- pytest.param("tutorial002_an_py310", marks=[needs_py310, needs_pydanticv2]),
- pytest.param("tutorial002_pv1_py39", marks=needs_pydanticv1),
- pytest.param("tutorial002_pv1_py310", marks=[needs_py310, needs_pydanticv1]),
- pytest.param("tutorial002_pv1_an_py39", marks=needs_pydanticv1),
- pytest.param("tutorial002_pv1_an_py310", marks=[needs_py310, needs_pydanticv1]),
+ pytest.param("tutorial002_py39"),
+ pytest.param("tutorial002_py310", marks=[needs_py310]),
+ pytest.param("tutorial002_an_py39"),
+ pytest.param("tutorial002_an_py310", marks=[needs_py310]),
],
)
def get_client(request: pytest.FixtureRequest):
@@ -62,31 +53,16 @@ def test_cookie_param_model_defaults(client: TestClient):
def test_cookie_param_model_invalid(client: TestClient):
response = client.get("/items/")
assert response.status_code == 422
- assert response.json() == pydantic_snapshot(
- v2=snapshot(
+ assert response.json() == {
+ "detail": [
{
- "detail": [
- {
- "type": "missing",
- "loc": ["cookie", "session_id"],
- "msg": "Field required",
- "input": {},
- }
- ]
+ "type": "missing",
+ "loc": ["cookie", "session_id"],
+ "msg": "Field required",
+ "input": {},
}
- ),
- v1=snapshot(
- {
- "detail": [
- {
- "type": "value_error.missing",
- "loc": ["cookie", "session_id"],
- "msg": "field required",
- }
- ]
- }
- ),
- )
+ ]
+ }
def test_cookie_param_model_extra(client: TestClient):
@@ -146,24 +122,13 @@ def test_openapi_schema(client: TestClient):
"name": "fatebook_tracker",
"in": "cookie",
"required": False,
- "schema": pydantic_snapshot(
- v2=snapshot(
- {
- "anyOf": [
- {"type": "string"},
- {"type": "null"},
- ],
- "title": "Fatebook Tracker",
- }
- ),
- v1=snapshot(
- # TODO: remove when deprecating Pydantic v1
- {
- "type": "string",
- "title": "Fatebook Tracker",
- }
- ),
- ),
+ "schema": {
+ "anyOf": [
+ {"type": "string"},
+ {"type": "null"},
+ ],
+ "title": "Fatebook Tracker",
+ },
},
{
"name": "googall_tracker",
diff --git a/tests/test_tutorial/test_dataclasses/test_tutorial003.py b/tests/test_tutorial/test_dataclasses/test_tutorial003.py
index d8cc45dd69..cddf4a9be8 100644
--- a/tests/test_tutorial/test_dataclasses/test_tutorial003.py
+++ b/tests/test_tutorial/test_dataclasses/test_tutorial003.py
@@ -3,7 +3,7 @@ import importlib
import pytest
from fastapi.testclient import TestClient
-from ...utils import needs_py310, needs_pydanticv1, needs_pydanticv2
+from ...utils import needs_py310
@pytest.fixture(
@@ -67,7 +67,6 @@ def test_get_authors(client: TestClient):
]
-@needs_pydanticv2
def test_openapi_schema(client: TestClient):
response = client.get("/openapi.json")
assert response.status_code == 200
@@ -201,137 +200,3 @@ def test_openapi_schema(client: TestClient):
}
},
}
-
-
-# TODO: remove when deprecating Pydantic v1
-@needs_pydanticv1
-def test_openapi_schema_pv1(client: TestClient):
- response = client.get("/openapi.json")
- assert response.status_code == 200
- assert response.json() == {
- "openapi": "3.1.0",
- "info": {"title": "FastAPI", "version": "0.1.0"},
- "paths": {
- "/authors/{author_id}/items/": {
- "post": {
- "summary": "Create Author Items",
- "operationId": "create_author_items_authors__author_id__items__post",
- "parameters": [
- {
- "required": True,
- "schema": {"title": "Author Id", "type": "string"},
- "name": "author_id",
- "in": "path",
- }
- ],
- "requestBody": {
- "content": {
- "application/json": {
- "schema": {
- "title": "Items",
- "type": "array",
- "items": {"$ref": "#/components/schemas/Item"},
- }
- }
- },
- "required": True,
- },
- "responses": {
- "200": {
- "description": "Successful Response",
- "content": {
- "application/json": {
- "schema": {"$ref": "#/components/schemas/Author"}
- }
- },
- },
- "422": {
- "description": "Validation Error",
- "content": {
- "application/json": {
- "schema": {
- "$ref": "#/components/schemas/HTTPValidationError"
- }
- }
- },
- },
- },
- }
- },
- "/authors/": {
- "get": {
- "summary": "Get Authors",
- "operationId": "get_authors_authors__get",
- "responses": {
- "200": {
- "description": "Successful Response",
- "content": {
- "application/json": {
- "schema": {
- "title": "Response Get Authors Authors Get",
- "type": "array",
- "items": {
- "$ref": "#/components/schemas/Author"
- },
- }
- }
- },
- }
- },
- }
- },
- },
- "components": {
- "schemas": {
- "Author": {
- "title": "Author",
- "required": ["name"],
- "type": "object",
- "properties": {
- "name": {"title": "Name", "type": "string"},
- "items": {
- "title": "Items",
- "type": "array",
- "items": {"$ref": "#/components/schemas/Item"},
- },
- },
- },
- "HTTPValidationError": {
- "title": "HTTPValidationError",
- "type": "object",
- "properties": {
- "detail": {
- "title": "Detail",
- "type": "array",
- "items": {"$ref": "#/components/schemas/ValidationError"},
- }
- },
- },
- "Item": {
- "title": "Item",
- "required": ["name"],
- "type": "object",
- "properties": {
- "name": {"title": "Name", "type": "string"},
- "description": {"title": "Description", "type": "string"},
- },
- },
- "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_header_param_models/test_tutorial002.py b/tests/test_tutorial/test_header_param_models/test_tutorial002.py
index a7a271ba41..ed4743ebf9 100644
--- a/tests/test_tutorial/test_header_param_models/test_tutorial002.py
+++ b/tests/test_tutorial/test_header_param_models/test_tutorial002.py
@@ -5,20 +5,16 @@ from dirty_equals import IsDict
from fastapi.testclient import TestClient
from inline_snapshot import snapshot
-from tests.utils import needs_py310, needs_pydanticv1, needs_pydanticv2
+from tests.utils import needs_py310
@pytest.fixture(
name="client",
params=[
- pytest.param("tutorial002_py39", marks=needs_pydanticv2),
- pytest.param("tutorial002_py310", marks=[needs_py310, needs_pydanticv2]),
- pytest.param("tutorial002_an_py39", marks=needs_pydanticv2),
- pytest.param("tutorial002_an_py310", marks=[needs_py310, needs_pydanticv2]),
- pytest.param("tutorial002_pv1_py39", marks=needs_pydanticv1),
- pytest.param("tutorial002_pv1_py310", marks=[needs_py310, needs_pydanticv1]),
- pytest.param("tutorial002_pv1_an_py39", marks=needs_pydanticv1),
- pytest.param("tutorial002_pv1_an_py310", marks=[needs_py310, needs_pydanticv1]),
+ pytest.param("tutorial002_py39"),
+ pytest.param("tutorial002_py310", marks=[needs_py310]),
+ pytest.param("tutorial002_an_py39"),
+ pytest.param("tutorial002_an_py310", marks=[needs_py310]),
],
)
def get_client(request: pytest.FixtureRequest):
diff --git a/tests/test_tutorial/test_path_operation_advanced_configurations/test_tutorial004.py b/tests/test_tutorial/test_path_operation_advanced_configurations/test_tutorial004.py
index 3805536e76..a95540731d 100644
--- a/tests/test_tutorial/test_path_operation_advanced_configurations/test_tutorial004.py
+++ b/tests/test_tutorial/test_path_operation_advanced_configurations/test_tutorial004.py
@@ -3,7 +3,7 @@ import importlib
import pytest
from fastapi.testclient import TestClient
-from ...utils import needs_py310, needs_pydanticv1, needs_pydanticv2
+from ...utils import needs_py310
@pytest.fixture(
@@ -35,7 +35,6 @@ def test_query_params_str_validations(client: TestClient):
}
-@needs_pydanticv2
def test_openapi_schema(client: TestClient):
response = client.get("/openapi.json")
assert response.status_code == 200, response.text
@@ -135,100 +134,3 @@ def test_openapi_schema(client: TestClient):
}
},
}
-
-
-# TODO: remove when deprecating Pydantic v1
-@needs_pydanticv1
-def test_openapi_schema_pv1(client: TestClient):
- response = client.get("/openapi.json")
- assert response.status_code == 200, response.text
- assert response.json() == {
- "openapi": "3.1.0",
- "info": {"title": "FastAPI", "version": "0.1.0"},
- "paths": {
- "/items/": {
- "post": {
- "responses": {
- "200": {
- "description": "Successful Response",
- "content": {
- "application/json": {
- "schema": {"$ref": "#/components/schemas/Item"}
- }
- },
- },
- "422": {
- "description": "Validation Error",
- "content": {
- "application/json": {
- "schema": {
- "$ref": "#/components/schemas/HTTPValidationError"
- }
- }
- },
- },
- },
- "summary": "Create an item",
- "description": "Create an item with all the information:\n\n- **name**: each item must have a name\n- **description**: a long description\n- **price**: required\n- **tax**: if the item doesn't have tax, you can omit this\n- **tags**: a set of unique tag strings for this item",
- "operationId": "create_item_items__post",
- "requestBody": {
- "content": {
- "application/json": {
- "schema": {"$ref": "#/components/schemas/Item"}
- }
- },
- "required": True,
- },
- }
- }
- },
- "components": {
- "schemas": {
- "Item": {
- "title": "Item",
- "required": ["name", "price"],
- "type": "object",
- "properties": {
- "name": {"title": "Name", "type": "string"},
- "description": {"title": "Description", "type": "string"},
- "price": {"title": "Price", "type": "number"},
- "tax": {"title": "Tax", "type": "number"},
- "tags": {
- "title": "Tags",
- "uniqueItems": True,
- "type": "array",
- "items": {"type": "string"},
- "default": [],
- },
- },
- },
- "ValidationError": {
- "title": "ValidationError",
- "required": ["loc", "msg", "type"],
- "type": "object",
- "properties": {
- "loc": {
- "title": "Location",
- "type": "array",
- "items": {
- "anyOf": [{"type": "string"}, {"type": "integer"}]
- },
- },
- "msg": {"title": "Message", "type": "string"},
- "type": {"title": "Error Type", "type": "string"},
- },
- },
- "HTTPValidationError": {
- "title": "HTTPValidationError",
- "type": "object",
- "properties": {
- "detail": {
- "title": "Detail",
- "type": "array",
- "items": {"$ref": "#/components/schemas/ValidationError"},
- }
- },
- },
- }
- },
- }
diff --git a/tests/test_tutorial/test_path_operation_advanced_configurations/test_tutorial007.py b/tests/test_tutorial/test_path_operation_advanced_configurations/test_tutorial007.py
index 204cca09ed..d5f284e3bd 100644
--- a/tests/test_tutorial/test_path_operation_advanced_configurations/test_tutorial007.py
+++ b/tests/test_tutorial/test_path_operation_advanced_configurations/test_tutorial007.py
@@ -3,8 +3,6 @@ import importlib
import pytest
from fastapi.testclient import TestClient
-from ...utils import needs_pydanticv2
-
@pytest.fixture(
name="client",
@@ -21,7 +19,6 @@ def get_client(request: pytest.FixtureRequest):
return client
-@needs_pydanticv2
def test_post(client: TestClient):
yaml_data = """
name: Deadpoolio
@@ -38,7 +35,6 @@ def test_post(client: TestClient):
}
-@needs_pydanticv2
def test_post_broken_yaml(client: TestClient):
yaml_data = """
name: Deadpoolio
@@ -52,7 +48,6 @@ def test_post_broken_yaml(client: TestClient):
assert response.json() == {"detail": "Invalid YAML"}
-@needs_pydanticv2
def test_post_invalid(client: TestClient):
yaml_data = """
name: Deadpoolio
@@ -77,7 +72,6 @@ def test_post_invalid(client: TestClient):
}
-@needs_pydanticv2
def test_openapi_schema(client: TestClient):
response = client.get("/openapi.json")
assert response.status_code == 200, response.text
diff --git a/tests/test_tutorial/test_path_operation_configurations/test_tutorial005.py b/tests/test_tutorial/test_path_operation_configurations/test_tutorial005.py
index 2a7a2b78b2..c5a3aec1d9 100644
--- a/tests/test_tutorial/test_path_operation_configurations/test_tutorial005.py
+++ b/tests/test_tutorial/test_path_operation_configurations/test_tutorial005.py
@@ -3,7 +3,7 @@ import importlib
import pytest
from fastapi.testclient import TestClient
-from ...utils import needs_py310, needs_pydanticv1, needs_pydanticv2
+from ...utils import needs_py310
@pytest.fixture(
@@ -34,7 +34,6 @@ def test_query_params_str_validations(client: TestClient):
}
-@needs_pydanticv2
def test_openapi_schema(client: TestClient):
response = client.get("/openapi.json")
assert response.status_code == 200, response.text
@@ -134,100 +133,3 @@ def test_openapi_schema(client: TestClient):
}
},
}
-
-
-# TODO: remove when deprecating Pydantic v1
-@needs_pydanticv1
-def test_openapi_schema_pv1(client: TestClient):
- response = client.get("/openapi.json")
- assert response.status_code == 200, response.text
- assert response.json() == {
- "openapi": "3.1.0",
- "info": {"title": "FastAPI", "version": "0.1.0"},
- "paths": {
- "/items/": {
- "post": {
- "responses": {
- "200": {
- "description": "The created item",
- "content": {
- "application/json": {
- "schema": {"$ref": "#/components/schemas/Item"}
- }
- },
- },
- "422": {
- "description": "Validation Error",
- "content": {
- "application/json": {
- "schema": {
- "$ref": "#/components/schemas/HTTPValidationError"
- }
- }
- },
- },
- },
- "summary": "Create an item",
- "description": "Create an item with all the information:\n\n- **name**: each item must have a name\n- **description**: a long description\n- **price**: required\n- **tax**: if the item doesn't have tax, you can omit this\n- **tags**: a set of unique tag strings for this item",
- "operationId": "create_item_items__post",
- "requestBody": {
- "content": {
- "application/json": {
- "schema": {"$ref": "#/components/schemas/Item"}
- }
- },
- "required": True,
- },
- }
- }
- },
- "components": {
- "schemas": {
- "Item": {
- "title": "Item",
- "required": ["name", "price"],
- "type": "object",
- "properties": {
- "name": {"title": "Name", "type": "string"},
- "description": {"title": "Description", "type": "string"},
- "price": {"title": "Price", "type": "number"},
- "tax": {"title": "Tax", "type": "number"},
- "tags": {
- "title": "Tags",
- "uniqueItems": True,
- "type": "array",
- "items": {"type": "string"},
- "default": [],
- },
- },
- },
- "ValidationError": {
- "title": "ValidationError",
- "required": ["loc", "msg", "type"],
- "type": "object",
- "properties": {
- "loc": {
- "title": "Location",
- "type": "array",
- "items": {
- "anyOf": [{"type": "string"}, {"type": "integer"}]
- },
- },
- "msg": {"title": "Message", "type": "string"},
- "type": {"title": "Error Type", "type": "string"},
- },
- },
- "HTTPValidationError": {
- "title": "HTTPValidationError",
- "type": "object",
- "properties": {
- "detail": {
- "title": "Detail",
- "type": "array",
- "items": {"$ref": "#/components/schemas/ValidationError"},
- }
- },
- },
- }
- },
- }
diff --git a/tests/test_tutorial/test_pydantic_v1_in_v2/test_tutorial001.py b/tests/test_tutorial/test_pydantic_v1_in_v2/test_tutorial001.py
index ce53a36eb8..4090eba012 100644
--- a/tests/test_tutorial/test_pydantic_v1_in_v2/test_tutorial001.py
+++ b/tests/test_tutorial/test_pydantic_v1_in_v2/test_tutorial001.py
@@ -2,7 +2,6 @@ import sys
from typing import Any
import pytest
-from fastapi._compat import PYDANTIC_V2
from tests.utils import skip_module_if_py_gte_314
@@ -10,13 +9,8 @@ if sys.version_info >= (3, 14):
skip_module_if_py_gte_314()
-if not PYDANTIC_V2:
- pytest.skip("This test is only for Pydantic v2", allow_module_level=True)
-
import importlib
-import pytest
-
from ...utils import needs_py310
diff --git a/tests/test_tutorial/test_pydantic_v1_in_v2/test_tutorial002.py b/tests/test_tutorial/test_pydantic_v1_in_v2/test_tutorial002.py
index 57720bf489..266d25944d 100644
--- a/tests/test_tutorial/test_pydantic_v1_in_v2/test_tutorial002.py
+++ b/tests/test_tutorial/test_pydantic_v1_in_v2/test_tutorial002.py
@@ -1,7 +1,6 @@
import sys
import pytest
-from fastapi._compat import PYDANTIC_V2
from inline_snapshot import snapshot
from tests.utils import skip_module_if_py_gte_314
@@ -10,12 +9,8 @@ if sys.version_info >= (3, 14):
skip_module_if_py_gte_314()
-if not PYDANTIC_V2:
- pytest.skip("This test is only for Pydantic v2", allow_module_level=True)
-
import importlib
-import pytest
from fastapi.testclient import TestClient
from ...utils import needs_py310
diff --git a/tests/test_tutorial/test_pydantic_v1_in_v2/test_tutorial003.py b/tests/test_tutorial/test_pydantic_v1_in_v2/test_tutorial003.py
index f020d4a975..693c3ba290 100644
--- a/tests/test_tutorial/test_pydantic_v1_in_v2/test_tutorial003.py
+++ b/tests/test_tutorial/test_pydantic_v1_in_v2/test_tutorial003.py
@@ -1,7 +1,6 @@
import sys
import pytest
-from fastapi._compat import PYDANTIC_V2
from inline_snapshot import snapshot
from tests.utils import skip_module_if_py_gte_314
@@ -9,9 +8,6 @@ from tests.utils import skip_module_if_py_gte_314
if sys.version_info >= (3, 14):
skip_module_if_py_gte_314()
-if not PYDANTIC_V2:
- pytest.skip("This test is only for Pydantic v2", allow_module_level=True)
-
import importlib
diff --git a/tests/test_tutorial/test_pydantic_v1_in_v2/test_tutorial004.py b/tests/test_tutorial/test_pydantic_v1_in_v2/test_tutorial004.py
index daa6f0b050..0fd084c84b 100644
--- a/tests/test_tutorial/test_pydantic_v1_in_v2/test_tutorial004.py
+++ b/tests/test_tutorial/test_pydantic_v1_in_v2/test_tutorial004.py
@@ -1,7 +1,6 @@
import sys
import pytest
-from fastapi._compat import PYDANTIC_V2
from inline_snapshot import snapshot
from tests.utils import skip_module_if_py_gte_314
@@ -9,9 +8,6 @@ from tests.utils import skip_module_if_py_gte_314
if sys.version_info >= (3, 14):
skip_module_if_py_gte_314()
-if not PYDANTIC_V2:
- pytest.skip("This test is only for Pydantic v2", allow_module_level=True)
-
import importlib
diff --git a/tests/test_tutorial/test_query_param_models/test_tutorial002.py b/tests/test_tutorial/test_query_param_models/test_tutorial002.py
index e7de73f804..0e9c3351a0 100644
--- a/tests/test_tutorial/test_query_param_models/test_tutorial002.py
+++ b/tests/test_tutorial/test_query_param_models/test_tutorial002.py
@@ -5,20 +5,16 @@ from dirty_equals import IsDict
from fastapi.testclient import TestClient
from inline_snapshot import snapshot
-from tests.utils import needs_py310, needs_pydanticv1, needs_pydanticv2
+from tests.utils import needs_py310
@pytest.fixture(
name="client",
params=[
- pytest.param("tutorial002_py39", marks=needs_pydanticv2),
- pytest.param("tutorial002_py310", marks=[needs_py310, needs_pydanticv2]),
- pytest.param("tutorial002_an_py39", marks=needs_pydanticv2),
- pytest.param("tutorial002_an_py310", marks=[needs_py310, needs_pydanticv2]),
- pytest.param("tutorial002_pv1_py39", marks=needs_pydanticv1),
- pytest.param("tutorial002_pv1_py310", marks=[needs_py310, needs_pydanticv1]),
- pytest.param("tutorial002_pv1_an_py39", marks=needs_pydanticv1),
- pytest.param("tutorial002_pv1_an_py310", marks=[needs_py310, needs_pydanticv1]),
+ pytest.param("tutorial002_py39"),
+ pytest.param("tutorial002_py310", marks=[needs_py310]),
+ pytest.param("tutorial002_an_py39"),
+ pytest.param("tutorial002_an_py310", marks=[needs_py310]),
],
)
def get_client(request: pytest.FixtureRequest):
diff --git a/tests/test_tutorial/test_query_params_str_validations/test_tutorial015.py b/tests/test_tutorial/test_query_params_str_validations/test_tutorial015.py
index 50ebf711f5..82bb606a9b 100644
--- a/tests/test_tutorial/test_query_params_str_validations/test_tutorial015.py
+++ b/tests/test_tutorial/test_query_params_str_validations/test_tutorial015.py
@@ -5,14 +5,14 @@ from dirty_equals import IsStr
from fastapi.testclient import TestClient
from inline_snapshot import snapshot
-from ...utils import needs_py310, needs_pydanticv2
+from ...utils import needs_py310
@pytest.fixture(
name="client",
params=[
- pytest.param("tutorial015_an_py39", marks=needs_pydanticv2),
- pytest.param("tutorial015_an_py310", marks=(needs_py310, needs_pydanticv2)),
+ pytest.param("tutorial015_an_py39"),
+ pytest.param("tutorial015_an_py310", marks=[needs_py310]),
],
)
def get_client(request: pytest.FixtureRequest):
diff --git a/tests/test_tutorial/test_request_form_models/test_tutorial002.py b/tests/test_tutorial/test_request_form_models/test_tutorial002.py
index 9bb90fa064..238f8fa2ef 100644
--- a/tests/test_tutorial/test_request_form_models/test_tutorial002.py
+++ b/tests/test_tutorial/test_request_form_models/test_tutorial002.py
@@ -3,8 +3,6 @@ import importlib
import pytest
from fastapi.testclient import TestClient
-from ...utils import needs_pydanticv2
-
@pytest.fixture(
name="client",
@@ -20,14 +18,12 @@ def get_client(request: pytest.FixtureRequest):
return client
-@needs_pydanticv2
def test_post_body_form(client: TestClient):
response = client.post("/login/", data={"username": "Foo", "password": "secret"})
assert response.status_code == 200
assert response.json() == {"username": "Foo", "password": "secret"}
-@needs_pydanticv2
def test_post_body_extra_form(client: TestClient):
response = client.post(
"/login/", data={"username": "Foo", "password": "secret", "extra": "extra"}
@@ -45,7 +41,6 @@ def test_post_body_extra_form(client: TestClient):
}
-@needs_pydanticv2
def test_post_body_form_no_password(client: TestClient):
response = client.post("/login/", data={"username": "Foo"})
assert response.status_code == 422
@@ -61,7 +56,6 @@ def test_post_body_form_no_password(client: TestClient):
}
-@needs_pydanticv2
def test_post_body_form_no_username(client: TestClient):
response = client.post("/login/", data={"password": "secret"})
assert response.status_code == 422
@@ -77,7 +71,6 @@ def test_post_body_form_no_username(client: TestClient):
}
-@needs_pydanticv2
def test_post_body_form_no_data(client: TestClient):
response = client.post("/login/")
assert response.status_code == 422
@@ -99,7 +92,6 @@ def test_post_body_form_no_data(client: TestClient):
}
-@needs_pydanticv2
def test_post_body_json(client: TestClient):
response = client.post("/login/", json={"username": "Foo", "password": "secret"})
assert response.status_code == 422, response.text
@@ -121,7 +113,6 @@ def test_post_body_json(client: TestClient):
}
-@needs_pydanticv2
def test_openapi_schema(client: TestClient):
response = client.get("/openapi.json")
assert response.status_code == 200, response.text
diff --git a/tests/test_tutorial/test_request_form_models/test_tutorial002_pv1.py b/tests/test_tutorial/test_request_form_models/test_tutorial002_pv1.py
index 41c7833bef..9ab30086bb 100644
--- a/tests/test_tutorial/test_request_form_models/test_tutorial002_pv1.py
+++ b/tests/test_tutorial/test_request_form_models/test_tutorial002_pv1.py
@@ -118,87 +118,3 @@ def test_post_body_json(client: TestClient):
},
]
}
-
-
-# TODO: remove when deprecating Pydantic v1
-@needs_pydanticv1
-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": {
- "/login/": {
- "post": {
- "responses": {
- "200": {
- "description": "Successful Response",
- "content": {"application/json": {"schema": {}}},
- },
- "422": {
- "description": "Validation Error",
- "content": {
- "application/json": {
- "schema": {
- "$ref": "#/components/schemas/HTTPValidationError"
- }
- }
- },
- },
- },
- "summary": "Login",
- "operationId": "login_login__post",
- "requestBody": {
- "content": {
- "application/x-www-form-urlencoded": {
- "schema": {"$ref": "#/components/schemas/FormData"}
- }
- },
- "required": True,
- },
- }
- }
- },
- "components": {
- "schemas": {
- "FormData": {
- "properties": {
- "username": {"type": "string", "title": "Username"},
- "password": {"type": "string", "title": "Password"},
- },
- "additionalProperties": False,
- "type": "object",
- "required": ["username", "password"],
- "title": "FormData",
- },
- "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_response_directly/test_tutorial001.py b/tests/test_tutorial/test_response_directly/test_tutorial001.py
index 127f0e4c1d..2d0c387195 100644
--- a/tests/test_tutorial/test_response_directly/test_tutorial001.py
+++ b/tests/test_tutorial/test_response_directly/test_tutorial001.py
@@ -3,7 +3,7 @@ import importlib
import pytest
from fastapi.testclient import TestClient
-from ...utils import needs_py310, needs_pydanticv1, needs_pydanticv2
+from ...utils import needs_py310
@pytest.fixture(
@@ -37,7 +37,6 @@ def test_path_operation(client: TestClient):
}
-@needs_pydanticv2
def test_openapi_schema_pv2(client: TestClient):
response = client.get("/openapi.json")
assert response.status_code == 200, response.text
@@ -151,138 +150,3 @@ def test_openapi_schema_pv2(client: TestClient):
},
},
}
-
-
-@needs_pydanticv1
-def test_openapi_schema_pv1(client: TestClient):
- response = client.get("/openapi.json")
- assert response.status_code == 200, response.text
- assert response.json() == {
- "info": {
- "title": "FastAPI",
- "version": "0.1.0",
- },
- "openapi": "3.1.0",
- "paths": {
- "/items/{id}": {
- "put": {
- "operationId": "update_item_items__id__put",
- "parameters": [
- {
- "in": "path",
- "name": "id",
- "required": True,
- "schema": {
- "title": "Id",
- "type": "string",
- },
- },
- ],
- "requestBody": {
- "content": {
- "application/json": {
- "schema": {
- "$ref": "#/components/schemas/Item",
- },
- },
- },
- "required": True,
- },
- "responses": {
- "200": {
- "content": {
- "application/json": {
- "schema": {},
- },
- },
- "description": "Successful Response",
- },
- "422": {
- "content": {
- "application/json": {
- "schema": {
- "$ref": "#/components/schemas/HTTPValidationError",
- },
- },
- },
- "description": "Validation Error",
- },
- },
- "summary": "Update Item",
- },
- },
- },
- "components": {
- "schemas": {
- "HTTPValidationError": {
- "properties": {
- "detail": {
- "items": {
- "$ref": "#/components/schemas/ValidationError",
- },
- "title": "Detail",
- "type": "array",
- },
- },
- "title": "HTTPValidationError",
- "type": "object",
- },
- "Item": {
- "properties": {
- "description": {
- "title": "Description",
- "type": "string",
- },
- "timestamp": {
- "format": "date-time",
- "title": "Timestamp",
- "type": "string",
- },
- "title": {
- "title": "Title",
- "type": "string",
- },
- },
- "required": [
- "title",
- "timestamp",
- ],
- "title": "Item",
- "type": "object",
- },
- "ValidationError": {
- "properties": {
- "loc": {
- "items": {
- "anyOf": [
- {
- "type": "string",
- },
- {
- "type": "integer",
- },
- ],
- },
- "title": "Location",
- "type": "array",
- },
- "msg": {
- "title": "Message",
- "type": "string",
- },
- "type": {
- "title": "Error Type",
- "type": "string",
- },
- },
- "required": [
- "loc",
- "msg",
- "type",
- ],
- "title": "ValidationError",
- "type": "object",
- },
- },
- },
- }
diff --git a/tests/test_tutorial/test_schema_extra_example/test_tutorial001.py b/tests/test_tutorial/test_schema_extra_example/test_tutorial001.py
index 4d1808cf6a..82f69fd463 100644
--- a/tests/test_tutorial/test_schema_extra_example/test_tutorial001.py
+++ b/tests/test_tutorial/test_schema_extra_example/test_tutorial001.py
@@ -3,7 +3,7 @@ import importlib
import pytest
from fastapi.testclient import TestClient
-from ...utils import needs_py310, needs_pydanticv2
+from ...utils import needs_py310
@pytest.fixture(
@@ -20,7 +20,6 @@ def get_client(request: pytest.FixtureRequest):
return client
-@needs_pydanticv2
def test_post_body_example(client: TestClient):
response = client.put(
"/items/5",
@@ -34,7 +33,6 @@ def test_post_body_example(client: TestClient):
assert response.status_code == 200
-@needs_pydanticv2
def test_openapi_schema(client: TestClient):
response = client.get("/openapi.json")
assert response.status_code == 200, response.text
diff --git a/tests/test_tutorial/test_schema_extra_example/test_tutorial001_pv1.py b/tests/test_tutorial/test_schema_extra_example/test_tutorial001_pv1.py
index 552bb66970..6059962897 100644
--- a/tests/test_tutorial/test_schema_extra_example/test_tutorial001_pv1.py
+++ b/tests/test_tutorial/test_schema_extra_example/test_tutorial001_pv1.py
@@ -2,6 +2,7 @@ import importlib
import pytest
from fastapi.testclient import TestClient
+from inline_snapshot import snapshot
from ...utils import needs_py310, needs_pydanticv1
@@ -38,98 +39,106 @@ def test_post_body_example(client: TestClient):
def test_openapi_schema(client: TestClient):
response = client.get("/openapi.json")
assert response.status_code == 200, response.text
- # insert_assert(response.json())
- assert response.json() == {
- "openapi": "3.1.0",
- "info": {"title": "FastAPI", "version": "0.1.0"},
- "paths": {
- "/items/{item_id}": {
- "put": {
- "summary": "Update Item",
- "operationId": "update_item_items__item_id__put",
- "parameters": [
- {
- "required": True,
- "schema": {"type": "integer", "title": "Item Id"},
- "name": "item_id",
- "in": "path",
- }
- ],
- "requestBody": {
- "content": {
- "application/json": {
- "schema": {"$ref": "#/components/schemas/Item"}
+ assert response.json() == snapshot(
+ {
+ "openapi": "3.1.0",
+ "info": {"title": "FastAPI", "version": "0.1.0"},
+ "paths": {
+ "/items/{item_id}": {
+ "put": {
+ "summary": "Update Item",
+ "operationId": "update_item_items__item_id__put",
+ "parameters": [
+ {
+ "required": True,
+ "schema": {"type": "integer", "title": "Item Id"},
+ "name": "item_id",
+ "in": "path",
}
- },
- "required": True,
- },
- "responses": {
- "200": {
- "description": "Successful Response",
- "content": {"application/json": {"schema": {}}},
- },
- "422": {
- "description": "Validation Error",
+ ],
+ "requestBody": {
"content": {
"application/json": {
"schema": {
- "$ref": "#/components/schemas/HTTPValidationError"
+ "title": "Item",
+ "allOf": [
+ {"$ref": "#/components/schemas/Item"}
+ ],
}
}
},
+ "required": True,
},
+ "responses": {
+ "200": {
+ "description": "Successful Response",
+ "content": {"application/json": {"schema": {}}},
+ },
+ "422": {
+ "description": "Validation Error",
+ "content": {
+ "application/json": {
+ "schema": {
+ "$ref": "#/components/schemas/HTTPValidationError"
+ }
+ }
+ },
+ },
+ },
+ }
+ }
+ },
+ "components": {
+ "schemas": {
+ "HTTPValidationError": {
+ "properties": {
+ "detail": {
+ "items": {
+ "$ref": "#/components/schemas/ValidationError"
+ },
+ "type": "array",
+ "title": "Detail",
+ }
+ },
+ "type": "object",
+ "title": "HTTPValidationError",
+ },
+ "Item": {
+ "properties": {
+ "name": {"type": "string", "title": "Name"},
+ "description": {"type": "string", "title": "Description"},
+ "price": {"type": "number", "title": "Price"},
+ "tax": {"type": "number", "title": "Tax"},
+ },
+ "type": "object",
+ "required": ["name", "price"],
+ "title": "Item",
+ "examples": [
+ {
+ "name": "Foo",
+ "description": "A very nice Item",
+ "price": 35.4,
+ "tax": 3.2,
+ }
+ ],
+ },
+ "ValidationError": {
+ "properties": {
+ "loc": {
+ "items": {
+ "anyOf": [{"type": "string"}, {"type": "integer"}]
+ },
+ "type": "array",
+ "title": "Location",
+ },
+ "msg": {"type": "string", "title": "Message"},
+ "type": {"type": "string", "title": "Error Type"},
+ },
+ "type": "object",
+ "required": ["loc", "msg", "type"],
+ "title": "ValidationError",
},
}
- }
- },
- "components": {
- "schemas": {
- "HTTPValidationError": {
- "properties": {
- "detail": {
- "items": {"$ref": "#/components/schemas/ValidationError"},
- "type": "array",
- "title": "Detail",
- }
- },
- "type": "object",
- "title": "HTTPValidationError",
- },
- "Item": {
- "properties": {
- "name": {"type": "string", "title": "Name"},
- "description": {"type": "string", "title": "Description"},
- "price": {"type": "number", "title": "Price"},
- "tax": {"type": "number", "title": "Tax"},
- },
- "type": "object",
- "required": ["name", "price"],
- "title": "Item",
- "examples": [
- {
- "name": "Foo",
- "description": "A very nice Item",
- "price": 35.4,
- "tax": 3.2,
- }
- ],
- },
- "ValidationError": {
- "properties": {
- "loc": {
- "items": {
- "anyOf": [{"type": "string"}, {"type": "integer"}]
- },
- "type": "array",
- "title": "Location",
- },
- "msg": {"type": "string", "title": "Message"},
- "type": {"type": "string", "title": "Error Type"},
- },
- "type": "object",
- "required": ["loc", "msg", "type"],
- "title": "ValidationError",
- },
- }
- },
- }
+ },
+ }
+ )
diff --git a/tests/test_tutorial/test_separate_openapi_schemas/test_tutorial001.py b/tests/test_tutorial/test_separate_openapi_schemas/test_tutorial001.py
index b59d799a31..275b234877 100644
--- a/tests/test_tutorial/test_separate_openapi_schemas/test_tutorial001.py
+++ b/tests/test_tutorial/test_separate_openapi_schemas/test_tutorial001.py
@@ -3,7 +3,7 @@ import importlib
import pytest
from fastapi.testclient import TestClient
-from ...utils import needs_py310, needs_pydanticv2
+from ...utils import needs_py310
@pytest.fixture(
@@ -38,7 +38,6 @@ def test_read_items(client: TestClient) -> None:
]
-@needs_pydanticv2
def test_openapi_schema(client: TestClient) -> None:
response = client.get("/openapi.json")
assert response.status_code == 200, response.text
diff --git a/tests/test_tutorial/test_separate_openapi_schemas/test_tutorial002.py b/tests/test_tutorial/test_separate_openapi_schemas/test_tutorial002.py
index 61fbacfc34..8230e39226 100644
--- a/tests/test_tutorial/test_separate_openapi_schemas/test_tutorial002.py
+++ b/tests/test_tutorial/test_separate_openapi_schemas/test_tutorial002.py
@@ -3,7 +3,7 @@ import importlib
import pytest
from fastapi.testclient import TestClient
-from ...utils import needs_py310, needs_pydanticv2
+from ...utils import needs_py310
@pytest.fixture(
@@ -38,7 +38,6 @@ def test_read_items(client: TestClient) -> None:
]
-@needs_pydanticv2
def test_openapi_schema(client: TestClient) -> None:
response = client.get("/openapi.json")
assert response.status_code == 200, response.text
diff --git a/tests/test_tutorial/test_settings/test_app02.py b/tests/test_tutorial/test_settings/test_app02.py
index 9cedc5a526..9cbed4fd1b 100644
--- a/tests/test_tutorial/test_settings/test_app02.py
+++ b/tests/test_tutorial/test_settings/test_app02.py
@@ -4,8 +4,6 @@ from types import ModuleType
import pytest
from pytest import MonkeyPatch
-from ...utils import needs_pydanticv2
-
@pytest.fixture(
name="mod_path",
@@ -31,7 +29,6 @@ def get_test_main_mod(mod_path: str) -> ModuleType:
return test_main_mod
-@needs_pydanticv2
def test_settings(main_mod: ModuleType, monkeypatch: MonkeyPatch):
monkeypatch.setenv("ADMIN_EMAIL", "admin@example.com")
settings = main_mod.get_settings()
@@ -39,6 +36,5 @@ def test_settings(main_mod: ModuleType, monkeypatch: MonkeyPatch):
assert settings.items_per_user == 50
-@needs_pydanticv2
def test_override_settings(test_main_mod: ModuleType):
test_main_mod.test_app()
diff --git a/tests/test_tutorial/test_settings/test_app03.py b/tests/test_tutorial/test_settings/test_app03.py
index dbaf8f3f90..06e82398d1 100644
--- a/tests/test_tutorial/test_settings/test_app03.py
+++ b/tests/test_tutorial/test_settings/test_app03.py
@@ -5,7 +5,7 @@ import pytest
from fastapi.testclient import TestClient
from pytest import MonkeyPatch
-from ...utils import needs_pydanticv1, needs_pydanticv2
+from ...utils import needs_pydanticv1
@pytest.fixture(
@@ -26,7 +26,6 @@ def get_main_mod(mod_path: str) -> ModuleType:
return main_mod
-@needs_pydanticv2
def test_settings(main_mod: ModuleType, monkeypatch: MonkeyPatch):
monkeypatch.setenv("ADMIN_EMAIL", "admin@example.com")
settings = main_mod.get_settings()
@@ -45,7 +44,6 @@ def test_settings_pv1(mod_path: str, monkeypatch: MonkeyPatch):
assert settings.items_per_user == 50
-@needs_pydanticv2
def test_endpoint(main_mod: ModuleType, monkeypatch: MonkeyPatch):
monkeypatch.setenv("ADMIN_EMAIL", "admin@example.com")
client = TestClient(main_mod.app)
diff --git a/tests/test_tutorial/test_settings/test_tutorial001.py b/tests/test_tutorial/test_settings/test_tutorial001.py
index 2c6dce261f..6a08096989 100644
--- a/tests/test_tutorial/test_settings/test_tutorial001.py
+++ b/tests/test_tutorial/test_settings/test_tutorial001.py
@@ -4,13 +4,13 @@ import pytest
from fastapi.testclient import TestClient
from pytest import MonkeyPatch
-from ...utils import needs_pydanticv1, needs_pydanticv2
+from ...utils import needs_pydanticv1
@pytest.fixture(
name="app",
params=[
- pytest.param("tutorial001_py39", marks=needs_pydanticv2),
+ pytest.param("tutorial001_py39"),
pytest.param("tutorial001_pv1_py39", marks=needs_pydanticv1),
],
)
diff --git a/tests/test_union_body_discriminator.py b/tests/test_union_body_discriminator.py
index bf41a72915..40fd0065a9 100644
--- a/tests/test_union_body_discriminator.py
+++ b/tests/test_union_body_discriminator.py
@@ -7,10 +7,7 @@ from inline_snapshot import snapshot
from pydantic import BaseModel, Field
from typing_extensions import Literal
-from .utils import needs_pydanticv2
-
-@needs_pydanticv2
def test_discriminator_pydantic_v2() -> None:
from pydantic import Tag
diff --git a/tests/test_union_body_discriminator_annotated.py b/tests/test_union_body_discriminator_annotated.py
index f8108c8df4..42a6aed24c 100644
--- a/tests/test_union_body_discriminator_annotated.py
+++ b/tests/test_union_body_discriminator_annotated.py
@@ -8,8 +8,6 @@ from fastapi.testclient import TestClient
from inline_snapshot import snapshot
from pydantic import BaseModel
-from .utils import needs_pydanticv2
-
@pytest.fixture(name="client")
def client_fixture() -> TestClient:
@@ -47,21 +45,18 @@ def client_fixture() -> TestClient:
return client
-@needs_pydanticv2
def test_union_body_discriminator_assignment(client: TestClient) -> None:
response = client.post("/pet/assignment", json={"pet_type": "cat", "meows": 5})
assert response.status_code == 200, response.text
assert response.json() == {"pet_type": "cat", "meows": 5}
-@needs_pydanticv2
def test_union_body_discriminator_annotated(client: TestClient) -> None:
response = client.post("/pet/annotated", json={"pet_type": "dog", "barks": 3.5})
assert response.status_code == 200, response.text
assert response.json() == {"pet_type": "dog", "barks": 3.5}
-@needs_pydanticv2
def test_openapi_schema(client: TestClient) -> None:
response = client.get("/openapi.json")
assert response.status_code == 200, response.text
diff --git a/tests/test_validate_response_recursive/app.py b/tests/test_validate_response_recursive/app.py
index 8f76572ba6..d51aa848d0 100644
--- a/tests/test_validate_response_recursive/app.py
+++ b/tests/test_validate_response_recursive/app.py
@@ -1,5 +1,4 @@
from fastapi import FastAPI
-from fastapi._compat import PYDANTIC_V2
from pydantic import BaseModel
app = FastAPI()
@@ -20,13 +19,9 @@ class RecursiveItemViaSubmodel(BaseModel):
name: str
-if PYDANTIC_V2:
- RecursiveItem.model_rebuild()
- RecursiveSubitemInSubmodel.model_rebuild()
- RecursiveItemViaSubmodel.model_rebuild()
-else:
- RecursiveItem.update_forward_refs()
- RecursiveSubitemInSubmodel.update_forward_refs()
+RecursiveItem.model_rebuild()
+RecursiveSubitemInSubmodel.model_rebuild()
+RecursiveItemViaSubmodel.model_rebuild()
@app.get("/items/recursive", response_model=RecursiveItem)
diff --git a/tests/utils.py b/tests/utils.py
index 691e92bbfb..b896d4527f 100644
--- a/tests/utils.py
+++ b/tests/utils.py
@@ -1,43 +1,19 @@
import sys
import pytest
-from fastapi._compat import PYDANTIC_V2
-from inline_snapshot import Snapshot
needs_py39 = pytest.mark.skipif(sys.version_info < (3, 9), reason="requires python3.9+")
needs_py310 = pytest.mark.skipif(
sys.version_info < (3, 10), reason="requires python3.10+"
)
needs_py_lt_314 = pytest.mark.skipif(
- sys.version_info > (3, 13), reason="requires python3.13-"
+ sys.version_info >= (3, 14), reason="requires python3.13-"
)
-needs_pydanticv2 = pytest.mark.skipif(not PYDANTIC_V2, reason="requires Pydantic v2")
-needs_pydanticv1 = pytest.mark.skipif(PYDANTIC_V2, reason="requires Pydantic v1")
+
+needs_pydanticv1 = needs_py_lt_314
def skip_module_if_py_gte_314():
"""Skip entire module on Python 3.14+ at import time."""
if sys.version_info >= (3, 14):
pytest.skip("requires python3.13-", allow_module_level=True)
-
-
-def pydantic_snapshot(
- *,
- v2: Snapshot,
- v1: Snapshot, # TODO: remove v1 argument when deprecating Pydantic v1
-):
- """
- This function should be used like this:
-
- >>> assert value == pydantic_snapshot(v2=snapshot(),v1=snapshot())
-
- inline-snapshot will create the snapshots when pytest is executed for each versions of pydantic.
-
- It is also possible to use the function inside snapshots for version-specific values.
-
- >>> assert value == snapshot({
- "data": "some data",
- "version_specific": pydantic_snapshot(v2=snapshot(),v1=snapshot()),
- })
- """
- return v2 if PYDANTIC_V2 else v1