-from typing import Union
-
from fastapi import FastAPI
from pydantic import BaseModel
}
-@app.get("/items/{item_id}", response_model=Union[PlaneItem, CarItem])
+@app.get("/items/{item_id}", response_model=PlaneItem | CarItem)
async def read_item(item_id: str):
return items[item_id]
import re
-from typing import TypedDict, Union
+from typing import TypedDict
CODE_INCLUDE_RE = re.compile(r"^\{\*\s*(\S+)\s*(.*)\*\}$")
CODE_INCLUDE_PLACEHOLDER = "<CODE_INCLUDE>"
line_no: int
url: str
text: str
- title: Union[str, None]
- attributes: Union[str, None]
+ title: str | None
+ attributes: str | None
full_match: str
def _construct_markdown_link(
url: str,
text: str,
- title: Union[str, None],
- attributes: Union[str, None],
+ title: str | None,
+ attributes: str | None,
lang_code: str,
) -> str:
"""
return blocks
-def _split_hash_comment(line: str) -> tuple[str, Union[str, None]]:
+def _split_hash_comment(line: str) -> tuple[str, str | None]:
match = HASH_COMMENT_RE.match(line)
if match:
code = match.group("code").rstrip()
return line.rstrip(), None
-def _split_slashes_comment(line: str) -> tuple[str, Union[str, None]]:
+def _split_slashes_comment(line: str) -> tuple[str, str | None]:
match = SLASHES_COMMENT_RE.match(line)
if match:
code = match.group("code").rstrip()
return block_a["content"].copy() # We don't handle mermaid code blocks for now
code_block: list[str] = []
- for line_a, line_b in zip(block_a["content"], block_b["content"]):
- line_a_comment: Union[str, None] = None
- line_b_comment: Union[str, None] = None
+ for line_a, line_b in zip(block_a["content"], block_b["content"], strict=False):
+ line_a_comment: str | None = None
+ line_b_comment: str | None = None
# Handle comments based on language
if block_language in {
)
modified_text = text.copy()
- for block, original_block in zip(code_blocks, original_code_blocks):
+ for block, original_block in zip(code_blocks, original_code_blocks, strict=True):
updated_content = replace_multiline_code_block(block, original_block)
start_line_index = block["start_line_no"] - 1
from functools import lru_cache
from pathlib import Path
-from typing import Any, Union
+from typing import Any
import material
from mkdocs.config.defaults import MkDocsConfig
def generate_renamed_section_items(
- items: list[Union[Page, Section, Link]], *, config: MkDocsConfig
-) -> list[Union[Page, Section, Link]]:
- new_items: list[Union[Page, Section, Link]] = []
+ items: list[Page | Section | Link], *, config: MkDocsConfig
+) -> list[Page | Section | Link]:
+ new_items: list[Page | Section | Link] = []
for item in items:
if isinstance(item, Section):
new_title = item.title
import sys
import time
from pathlib import Path
-from typing import Any, Union, cast
+from typing import Any, cast
import httpx
from github import Github
github_repository: str
github_token: SecretStr
github_event_path: Path
- github_event_name: Union[str, None] = None
+ github_event_name: str | None = None
httpx_timeout: int = 30
- debug: Union[bool, None] = False
+ debug: bool | None = False
number: int | None = None
*,
settings: Settings,
query: str,
- after: Union[str, None] = None,
- category_id: Union[str, None] = None,
- discussion_number: Union[int, None] = None,
- discussion_id: Union[str, None] = None,
- comment_id: Union[str, None] = None,
- body: Union[str, None] = None,
+ after: str | None = None,
+ category_id: str | None = None,
+ discussion_number: int | None = None,
+ discussion_id: str | None = None,
+ comment_id: str | None = None,
+ body: str | None = None,
) -> dict[str, Any]:
headers = {"Authorization": f"token {settings.github_token.get_secret_value()}"}
variables = {
def get_graphql_translation_discussion_comments_edges(
- *, settings: Settings, discussion_number: int, after: Union[str, None] = None
+ *, settings: Settings, discussion_number: int, after: str | None = None
) -> list[CommentsEdge]:
data = get_graphql_response(
settings=settings,
f"Found a translation discussion for language: {lang} in discussion: #{discussion.number}"
)
- already_notified_comment: Union[Comment, None] = None
- already_done_comment: Union[Comment, None] = None
+ already_notified_comment: Comment | None = None
+ already_done_comment: Comment | None = None
logging.info(
f"Checking current comments in discussion: #{discussion.number} to see if already notified about this PR: #{pr.number}"
from collections.abc import Container
from datetime import datetime, timedelta, timezone
from pathlib import Path
-from typing import Any, Union
+from typing import Any
import httpx
import yaml
class CommentsNode(BaseModel):
createdAt: datetime
- author: Union[Author, None] = None
+ author: Author | None = None
class Replies(BaseModel):
class DiscussionsNode(BaseModel):
number: int
- author: Union[Author, None] = None
+ author: Author | None = None
title: str | None = None
createdAt: datetime
comments: DiscussionsComments
*,
settings: Settings,
query: str,
- after: Union[str, None] = None,
- category_id: Union[str, None] = None,
+ after: str | None = None,
+ category_id: str | None = None,
) -> dict[str, Any]:
headers = {"Authorization": f"token {settings.github_token.get_secret_value()}"}
variables = {"after": after, "category_id": category_id}
def get_graphql_question_discussion_edges(
*,
settings: Settings,
- after: Union[str, None] = None,
+ after: str | None = None,
) -> list[DiscussionsEdge]:
data = get_graphql_response(
settings=settings,
import http
-from typing import Optional
from fastapi import FastAPI, Path, Query
@app.get("/path/param/{item_id}")
-def get_path_param_id(item_id: Optional[str] = Path()):
+def get_path_param_id(item_id: str | None = Path()):
return item_id
@app.get("/query/int/optional")
-def get_query_type_optional(query: Optional[int] = None):
+def get_query_type_optional(query: int | None = None):
if query is None:
return "foo bar"
return f"foo bar {query}"
-from typing import Union
-
from fastapi import FastAPI
from fastapi.testclient import TestClient
from inline_snapshot import snapshot
@app.post("/")
async def post(
- foo: Union[Foo, None] = None,
+ foo: Foo | None = None,
):
return foo
See https://github.com/fastapi/fastapi/pull/14463
"""
-from typing import Union
-
from fastapi import FastAPI
from fastapi.testclient import TestClient
from inline_snapshot import snapshot
app = FastAPI(
responses={
500: {
- "model": Union[ModelA, ModelB],
+ "model": ModelA | ModelB,
"content": {"application/json": {"examples": {"Case A": {"value": "a"}}}},
}
}
from functools import partial
-from typing import Optional
from fastapi import FastAPI
from fastapi.testclient import TestClient
-def main(some_arg, q: Optional[str] = None):
+def main(some_arg, q: str | None = None):
return {"some_arg": some_arg, "q": q}
-from typing import Union
-
from fastapi import FastAPI, UploadFile
from fastapi._compat import (
Undefined,
from pydantic import BaseModel, ConfigDict
from pydantic.fields import FieldInfo
-from .utils import needs_py310
-
def test_model_field_default_required():
from fastapi._compat import v2
app = FastAPI()
@app.post("/")
- def foo(foo: Union[str, list[int]]):
+ def foo(foo: str | list[int]):
return foo
client = TestClient(app)
class EmbeddedModel(BaseModel):
model_config = ConfigDict(arbitrary_types_allowed=True)
- value: Union[str, Missing] = Missing()
+ value: str | Missing = Missing()
class Model(BaseModel):
model_config = ConfigDict(
arbitrary_types_allowed=True,
)
- value: Union[str, Missing] = Missing()
+ value: str | Missing = Missing()
embedded_model: EmbeddedModel = EmbeddedModel()
@app.post("/")
- def foo(req: Model) -> dict[str, Union[str, None]]:
+ def foo(req: Model) -> dict[str, str | None]:
return {
"value": req.value or None,
"embedded_value": req.embedded_model.value or None,
# TODO: in theory this would allow declaring types that could be lists of bytes
# to be read from files and other types, but I'm not even sure it's a good idea
# to support it as a first class "feature"
- assert is_bytes_sequence_annotation(Union[list[str], list[bytes]])
+ assert is_bytes_sequence_annotation(list[str] | list[bytes])
def test_is_uploadfile_sequence_annotation():
# TODO: in theory this would allow declaring types that could be lists of UploadFile
# and other types, but I'm not even sure it's a good idea to support it as a first
# class "feature"
- assert is_uploadfile_sequence_annotation(Union[list[str], list[UploadFile]])
+ assert is_uploadfile_sequence_annotation(list[str] | list[UploadFile])
def test_serialize_sequence_value_with_optional_list():
"""Test that serialize_sequence_value handles optional lists correctly."""
from fastapi._compat import v2
- field_info = FieldInfo(annotation=Union[list[str], None])
+ field_info = FieldInfo(annotation=list[str] | None)
field = v2.ModelField(name="items", field_info=field_info)
result = v2.serialize_sequence_value(field=field, value=["a", "b", "c"])
assert result == ["a", "b", "c"]
assert isinstance(result, list)
-@needs_py310
def test_serialize_sequence_value_with_optional_list_pipe_union():
"""Test that serialize_sequence_value handles optional lists correctly (with new syntax)."""
from fastapi._compat import v2
def test_serialize_sequence_value_with_none_first_in_union():
"""Test that serialize_sequence_value handles Union[None, List[...]] correctly."""
+ from typing import Union
+
from fastapi._compat import v2
- field_info = FieldInfo(annotation=Union[None, list[str]])
+ # Use Union[None, list[str]] to ensure None comes first in the union args
+ field_info = FieldInfo(annotation=Union[None, list[str]]) # noqa: UP007
field = v2.ModelField(name="items", field_info=field_info)
result = v2.serialize_sequence_value(field=field, value=["x", "y"])
assert result == ["x", "y"]
from pathlib import Path
-from typing import Optional
from fastapi import APIRouter, FastAPI, File, UploadFile
from fastapi.exceptions import HTTPException
max_content_size (optional): the maximum content size allowed in bytes, None for no limit
"""
- def __init__(self, app: APIRouter, max_content_size: Optional[int] = None):
+ def __init__(self, app: APIRouter, max_content_size: int | None = None):
self.app = app
self.max_content_size = max_content_size
-from typing import Annotated, Optional
+from typing import Annotated
from fastapi import FastAPI
from fastapi.testclient import TestClient
class Item(BaseModel):
name: str
- description: Annotated[
- Optional[str], WithJsonSchema({"type": ["string", "null"]})
- ] = None
+ description: Annotated[str | None, WithJsonSchema({"type": ["string", "null"]})] = (
+ None
+ )
model_config = {
"json_schema_extra": {
-from collections.abc import Awaitable
+from collections.abc import Awaitable, Callable
from contextvars import ContextVar
-from typing import Any, Callable, Optional
+from typing import Any
from fastapi import Depends, FastAPI, Request, Response
from fastapi.testclient import TestClient
-legacy_request_state_context_var: ContextVar[Optional[dict[str, Any]]] = ContextVar(
+legacy_request_state_context_var: ContextVar[dict[str, Any] | None] = ContextVar(
"legacy_request_state_context_var", default=None
)
-from typing import Optional
-
import pytest
from fastapi import APIRouter, Depends, FastAPI
from fastapi.testclient import TestClient
client = TestClient(app)
-async def overrider_dependency_simple(q: Optional[str] = None):
+async def overrider_dependency_simple(q: str | None = None):
return {"q": q, "skip": 5, "limit": 10}
-from typing import Annotated, Union
+from typing import Annotated
from fastapi import FastAPI, HTTPException, Security
from fastapi.security import (
def process_auth(
- credentials: Annotated[Union[str, None], Security(oauth2_scheme)],
+ credentials: Annotated[str | None, Security(oauth2_scheme)],
security_scopes: SecurityScopes,
):
# This is an incorrect way of using it, this is not checking if the scopes are
-from typing import Optional
-
from fastapi import Depends, FastAPI, Query
from fastapi.testclient import TestClient
from inline_snapshot import snapshot
return f"{client_id}_key"
-def _get_client_tag(client_id: Optional[str] = Query(None)) -> Optional[str]:
+def _get_client_tag(client_id: str | None = Query(None)) -> str | None:
if client_id is None:
return None
return f"{client_id}_tag"
@app.get("/foo")
def foo_handler(
client_key: str = Depends(_get_client_key),
- client_tag: Optional[str] = Depends(_get_client_tag),
+ client_tag: str | None = Depends(_get_client_tag),
):
return {"client_id": client_key, "client_tag": client_tag}
-from typing import Optional
-
from fastapi import FastAPI
from fastapi.responses import JSONResponse
from fastapi.testclient import TestClient
class Item(BaseModel):
name: str
- price: Optional[float] = None
+ price: float | None = None
@app.api_route("/items/{item_id}", methods=["GET"])
-from typing import Optional
-
import pytest
from dirty_equals import HasRepr
from fastapi import Depends, FastAPI
class ModelA(BaseModel):
name: str
- description: Optional[str] = None
+ description: str | None = None
foo: ModelB
tags: dict[str, str] = {}
-from typing import Annotated, Optional
+from typing import Annotated
from fastapi import FastAPI, File, Form
from starlette.testclient import TestClient
@app.post("/urlencoded")
-async def post_url_encoded(age: Annotated[Optional[int], Form()] = None):
+async def post_url_encoded(age: Annotated[int | None, Form()] = None):
return age
@app.post("/multipart")
async def post_multi_part(
- age: Annotated[Optional[int], Form()] = None,
- file: Annotated[Optional[bytes], File()] = None,
+ age: Annotated[int | None, Form()] = None,
+ file: Annotated[bytes | None, File()] = None,
):
return {"file": file, "age": age}
-from typing import Annotated, Optional
+from typing import Annotated
from fastapi import FastAPI, Form
from fastapi.testclient import TestClient
class FormModel(BaseModel):
username: str
lastname: str
- age: Optional[int] = None
+ age: int | None = None
tags: list[str] = ["foo", "bar"]
alias_with: str = Field(alias="with", default="nothing")
-from typing import Optional
-
from fastapi import APIRouter, FastAPI
from fastapi.testclient import TestClient
from inline_snapshot import snapshot
@item_router.get("/")
-def get_items(user_id: Optional[str] = None):
+def get_items(user_id: str | None = None):
if user_id is None:
return [{"item_id": "i1", "user_id": "u1"}, {"item_id": "i2", "user_id": "u2"}]
else:
@item_router.get("/{item_id}")
-def get_item(item_id: str, user_id: Optional[str] = None):
+def get_item(item_id: str, user_id: str | None = None):
if user_id is None:
return {"item_id": item_id}
else:
-from typing import Optional
-
import pytest
from fastapi import FastAPI, Query
from pydantic import BaseModel
title: str
@app.get("/items/")
- def read_items(q: Optional[dict] = Query(default=None)):
+ def read_items(q: dict | None = Query(default=None)):
pass # pragma: no cover
from enum import Enum
from math import isinf, isnan
from pathlib import PurePath, PurePosixPath, PureWindowsPath
-from typing import Optional, TypedDict
+from typing import TypedDict
import pytest
from fastapi._compat import Undefined
class ModelWithConfig(BaseModel):
- role: Optional[RoleEnum] = None
+ role: RoleEnum | None = None
model_config = {"use_enum_values": True}
-from typing import Union
-
from fastapi import Body, Cookie, FastAPI, Header, Path, Query
from fastapi.testclient import TestClient
from inline_snapshot import snapshot
@app.get("/query_examples/")
def query_examples(
- data: Union[str, None] = Query(
+ data: str | None = Query(
default=None,
examples=[
"json_schema_query1",
@app.get("/header_examples/")
def header_examples(
- data: Union[str, None] = Header(
+ data: str | None = Header(
default=None,
examples=[
"json_schema_header1",
@app.get("/cookie_examples/")
def cookie_examples(
- data: Union[str, None] = Cookie(
+ data: str | None = Cookie(
default=None,
examples=["json_schema_cookie1", "json_schema_cookie2"],
openapi_examples={
-from typing import Optional
-
from fastapi import FastAPI
from fastapi.testclient import TestClient
from inline_snapshot import snapshot
]
},
)
-def route_with_extra_query_parameters(standard_query_param: Optional[int] = 50):
+def route_with_extra_query_parameters(standard_query_param: int | None = 50):
return {}
-from typing import Optional, Union
-
import pytest
from fastapi.openapi.models import Schema, SchemaType
],
)
def test_allowed_schema_type(
- type_value: Optional[Union[SchemaType, list[SchemaType]]],
+ type_value: SchemaType | list[SchemaType] | None,
) -> None:
"""Test that Schema accepts SchemaType, List[SchemaType] and None for type field."""
schema = Schema(type=type_value)
-from typing import Optional
-
from fastapi import FastAPI
from fastapi.testclient import TestClient
from inline_snapshot import snapshot
class SubItem(BaseModel):
subname: str
- sub_description: Optional[str] = None
+ sub_description: str | None = None
tags: list[str] = []
model_config = {"json_schema_serialization_defaults_required": True}
class Item(BaseModel):
name: str
- description: Optional[str] = None
- sub: Optional[SubItem] = None
+ description: str | None = None
+ sub: SubItem | None = None
model_config = {"json_schema_serialization_defaults_required": True}
-from typing import Optional
-
from fastapi import FastAPI, File
from fastapi.testclient import TestClient
@app.post("/files")
-async def upload_files(files: Optional[list[bytes]] = File(None)):
+async def upload_files(files: list[bytes] | None = File(None)):
if files is None:
return {"files_count": 0}
return {"files_count": len(files), "sizes": [len(f) for f in files]}
-from typing import Optional
-
from fastapi import FastAPI
from fastapi.params import Param
from fastapi.testclient import TestClient
@app.get("/items/")
-def read_items(q: Optional[str] = Param(default=None)): # type: ignore
+def read_items(q: str | None = Param(default=None)): # type: ignore
return {"q": q}
-from typing import Optional
-
import pytest
from fastapi import Cookie, FastAPI, Header, Path, Query
from fastapi.testclient import TestClient
@app.get("/hidden_cookie")
async def hidden_cookie(
- hidden_cookie: Optional[str] = Cookie(default=None, include_in_schema=False),
+ hidden_cookie: str | None = Cookie(default=None, include_in_schema=False),
):
return {"hidden_cookie": hidden_cookie}
@app.get("/hidden_header")
async def hidden_header(
- hidden_header: Optional[str] = Header(default=None, include_in_schema=False),
+ hidden_header: str | None = Header(default=None, include_in_schema=False),
):
return {"hidden_header": hidden_header}
@app.get("/hidden_query")
async def hidden_query(
- hidden_query: Optional[str] = Query(default=None, include_in_schema=False),
+ hidden_query: str | None = Query(default=None, include_in_schema=False),
):
return {"hidden_query": hidden_query}
import sys
import warnings
-from typing import Union
import pytest
with pytest.raises(PydanticV1NotSupportedError):
@app.post("/union")
- def endpoint(data: Union[dict, ModelV1A]): # pragma: no cover
+ def endpoint(data: dict | ModelV1A): # pragma: no cover
return data
import uuid
from dataclasses import dataclass, field
-from typing import Union
from dirty_equals import IsUUID
from fastapi import FastAPI
name: str
price: float
tags: list[str] = field(default_factory=list)
- description: Union[str, None] = None
- tax: Union[float, None] = None
+ description: str | None = None
+ tax: float | None = None
app = FastAPI()
-from typing import Annotated, Union
+from typing import Annotated
import pytest
from dirty_equals import IsOneOf, IsPartialDict
"path",
["/required-list-str", "/model-required-list-str"],
)
-def test_required_list_str_missing(path: str, json: Union[dict, None]):
+def test_required_list_str_missing(path: str, json: dict | None):
client = TestClient(app)
response = client.post(path, json=json)
assert response.status_code == 422
"path",
["/required-list-alias", "/model-required-list-alias"],
)
-def test_required_list_alias_missing(path: str, json: Union[dict, None]):
+def test_required_list_alias_missing(path: str, json: dict | None):
client = TestClient(app)
response = client.post(path, json=json)
assert response.status_code == 422
"/model-required-list-validation-alias",
],
)
-def test_required_list_validation_alias_missing(path: str, json: Union[dict, None]):
+def test_required_list_validation_alias_missing(path: str, json: dict | None):
client = TestClient(app)
response = client.post(path, json=json)
assert response.status_code == 422
-from typing import Annotated, Optional
+from typing import Annotated
import pytest
from fastapi import Body, FastAPI
@app.post("/optional-list-str", operation_id="optional_list_str")
async def read_optional_list_str(
- p: Annotated[Optional[list[str]], Body(embed=True)] = None,
+ p: Annotated[list[str] | None, Body(embed=True)] = None,
):
return {"p": p}
class BodyModelOptionalListStr(BaseModel):
- p: Optional[list[str]] = None
+ p: list[str] | None = None
@app.post("/model-optional-list-str", operation_id="model_optional_list_str")
@app.post("/optional-list-alias", operation_id="optional_list_alias")
async def read_optional_list_alias(
- p: Annotated[Optional[list[str]], Body(embed=True, alias="p_alias")] = None,
+ p: Annotated[list[str] | None, Body(embed=True, alias="p_alias")] = None,
):
return {"p": p}
class BodyModelOptionalListAlias(BaseModel):
- p: Optional[list[str]] = Field(None, alias="p_alias")
+ p: list[str] | None = Field(None, alias="p_alias")
@app.post("/model-optional-list-alias", operation_id="model_optional_list_alias")
)
def read_optional_list_validation_alias(
p: Annotated[
- Optional[list[str]], Body(embed=True, validation_alias="p_val_alias")
+ list[str] | None, Body(embed=True, validation_alias="p_val_alias")
] = None,
):
return {"p": p}
class BodyModelOptionalListValidationAlias(BaseModel):
- p: Optional[list[str]] = Field(None, validation_alias="p_val_alias")
+ p: list[str] | None = Field(None, validation_alias="p_val_alias")
@app.post(
)
def read_optional_list_alias_and_validation_alias(
p: Annotated[
- Optional[list[str]],
+ list[str] | None,
Body(embed=True, alias="p_alias", validation_alias="p_val_alias"),
] = None,
):
class BodyModelOptionalListAliasAndValidationAlias(BaseModel):
- p: Optional[list[str]] = Field(
- None, alias="p_alias", validation_alias="p_val_alias"
- )
+ p: list[str] | None = Field(None, alias="p_alias", validation_alias="p_val_alias")
@app.post(
-from typing import Annotated, Optional
+from typing import Annotated
import pytest
from fastapi import Body, FastAPI
@app.post("/optional-str", operation_id="optional_str")
-async def read_optional_str(p: Annotated[Optional[str], Body(embed=True)] = None):
+async def read_optional_str(p: Annotated[str | None, Body(embed=True)] = None):
return {"p": p}
class BodyModelOptionalStr(BaseModel):
- p: Optional[str] = None
+ p: str | None = None
@app.post("/model-optional-str", operation_id="model_optional_str")
@app.post("/optional-alias", operation_id="optional_alias")
async def read_optional_alias(
- p: Annotated[Optional[str], Body(embed=True, alias="p_alias")] = None,
+ p: Annotated[str | None, Body(embed=True, alias="p_alias")] = None,
):
return {"p": p}
class BodyModelOptionalAlias(BaseModel):
- p: Optional[str] = Field(None, alias="p_alias")
+ p: str | None = Field(None, alias="p_alias")
@app.post("/model-optional-alias", operation_id="model_optional_alias")
@app.post("/optional-validation-alias", operation_id="optional_validation_alias")
def read_optional_validation_alias(
- p: Annotated[
- Optional[str], Body(embed=True, validation_alias="p_val_alias")
- ] = None,
+ p: Annotated[str | None, Body(embed=True, validation_alias="p_val_alias")] = None,
):
return {"p": p}
class BodyModelOptionalValidationAlias(BaseModel):
- p: Optional[str] = Field(None, validation_alias="p_val_alias")
+ p: str | None = Field(None, validation_alias="p_val_alias")
@app.post(
)
def read_optional_alias_and_validation_alias(
p: Annotated[
- Optional[str], Body(embed=True, alias="p_alias", validation_alias="p_val_alias")
+ str | None, Body(embed=True, alias="p_alias", validation_alias="p_val_alias")
] = None,
):
return {"p": p}
class BodyModelOptionalAliasAndValidationAlias(BaseModel):
- p: Optional[str] = Field(None, alias="p_alias", validation_alias="p_val_alias")
+ p: str | None = Field(None, alias="p_alias", validation_alias="p_val_alias")
@app.post(
-from typing import Annotated, Any, Union
+from typing import Annotated, Any
import pytest
from dirty_equals import IsOneOf
"path",
["/required-str", "/model-required-str"],
)
-def test_required_str_missing(path: str, json: Union[dict[str, Any], None]):
+def test_required_str_missing(path: str, json: dict[str, Any] | None):
client = TestClient(app)
response = client.post(path, json=json)
assert response.status_code == 422
"path",
["/required-alias", "/model-required-alias"],
)
-def test_required_alias_missing(path: str, json: Union[dict[str, Any], None]):
+def test_required_alias_missing(path: str, json: dict[str, Any] | None):
client = TestClient(app)
response = client.post(path, json=json)
assert response.status_code == 422
"/model-required-validation-alias",
],
)
-def test_required_validation_alias_missing(
- path: str, json: Union[dict[str, Any], None]
-):
+def test_required_validation_alias_missing(path: str, json: dict[str, Any] | None):
client = TestClient(app)
response = client.post(path, json=json)
assert response.status_code == 422
],
)
def test_required_alias_and_validation_alias_missing(
- path: str, json: Union[dict[str, Any], None]
+ path: str, json: dict[str, Any] | None
):
client = TestClient(app)
response = client.post(path, json=json)
-from typing import Annotated, Optional
+from typing import Annotated
import pytest
from fastapi import Cookie, FastAPI
@app.get("/optional-str")
-async def read_optional_str(p: Annotated[Optional[str], Cookie()] = None):
+async def read_optional_str(p: Annotated[str | None, Cookie()] = None):
return {"p": p}
class CookieModelOptionalStr(BaseModel):
- p: Optional[str] = None
+ p: str | None = None
@app.get("/model-optional-str")
@app.get("/optional-alias")
async def read_optional_alias(
- p: Annotated[Optional[str], Cookie(alias="p_alias")] = None,
+ p: Annotated[str | None, Cookie(alias="p_alias")] = None,
):
return {"p": p}
class CookieModelOptionalAlias(BaseModel):
- p: Optional[str] = Field(None, alias="p_alias")
+ p: str | None = Field(None, alias="p_alias")
@app.get("/model-optional-alias")
@app.get("/optional-validation-alias")
def read_optional_validation_alias(
- p: Annotated[Optional[str], Cookie(validation_alias="p_val_alias")] = None,
+ p: Annotated[str | None, Cookie(validation_alias="p_val_alias")] = None,
):
return {"p": p}
class CookieModelOptionalValidationAlias(BaseModel):
- p: Optional[str] = Field(None, validation_alias="p_val_alias")
+ p: str | None = Field(None, validation_alias="p_val_alias")
@app.get("/model-optional-validation-alias")
@app.get("/optional-alias-and-validation-alias")
def read_optional_alias_and_validation_alias(
p: Annotated[
- Optional[str], Cookie(alias="p_alias", validation_alias="p_val_alias")
+ str | None, Cookie(alias="p_alias", validation_alias="p_val_alias")
] = None,
):
return {"p": p}
class CookieModelOptionalAliasAndValidationAlias(BaseModel):
- p: Optional[str] = Field(None, alias="p_alias", validation_alias="p_val_alias")
+ p: str | None = Field(None, alias="p_alias", validation_alias="p_val_alias")
@app.get("/model-optional-alias-and-validation-alias")
-from typing import Annotated, Optional
+from typing import Annotated
import pytest
from fastapi import FastAPI, File, UploadFile
@app.post("/optional-bytes", operation_id="optional_bytes")
-async def read_optional_bytes(p: Annotated[Optional[bytes], File()] = None):
+async def read_optional_bytes(p: Annotated[bytes | None, File()] = None):
return {"file_size": len(p) if p else None}
@app.post("/optional-uploadfile", operation_id="optional_uploadfile")
-async def read_optional_uploadfile(p: Annotated[Optional[UploadFile], File()] = None):
+async def read_optional_uploadfile(p: Annotated[UploadFile | None, File()] = None):
return {"file_size": p.size if p else None}
@app.post("/optional-bytes-alias", operation_id="optional_bytes_alias")
async def read_optional_bytes_alias(
- p: Annotated[Optional[bytes], File(alias="p_alias")] = None,
+ p: Annotated[bytes | None, File(alias="p_alias")] = None,
):
return {"file_size": len(p) if p else None}
@app.post("/optional-uploadfile-alias", operation_id="optional_uploadfile_alias")
async def read_optional_uploadfile_alias(
- p: Annotated[Optional[UploadFile], File(alias="p_alias")] = None,
+ p: Annotated[UploadFile | None, File(alias="p_alias")] = None,
):
return {"file_size": p.size if p else None}
"/optional-bytes-validation-alias", operation_id="optional_bytes_validation_alias"
)
def read_optional_bytes_validation_alias(
- p: Annotated[Optional[bytes], File(validation_alias="p_val_alias")] = None,
+ p: Annotated[bytes | None, File(validation_alias="p_val_alias")] = None,
):
return {"file_size": len(p) if p else None}
operation_id="optional_uploadfile_validation_alias",
)
def read_optional_uploadfile_validation_alias(
- p: Annotated[Optional[UploadFile], File(validation_alias="p_val_alias")] = None,
+ p: Annotated[UploadFile | None, File(validation_alias="p_val_alias")] = None,
):
return {"file_size": p.size if p else None}
)
def read_optional_bytes_alias_and_validation_alias(
p: Annotated[
- Optional[bytes], File(alias="p_alias", validation_alias="p_val_alias")
+ bytes | None, File(alias="p_alias", validation_alias="p_val_alias")
] = None,
):
return {"file_size": len(p) if p else None}
)
def read_optional_uploadfile_alias_and_validation_alias(
p: Annotated[
- Optional[UploadFile], File(alias="p_alias", validation_alias="p_val_alias")
+ UploadFile | None, File(alias="p_alias", validation_alias="p_val_alias")
] = None,
):
return {"file_size": p.size if p else None}
-from typing import Annotated, Optional
+from typing import Annotated
import pytest
from fastapi import FastAPI, File, UploadFile
@app.post("/optional-list-bytes")
-async def read_optional_list_bytes(p: Annotated[Optional[list[bytes]], File()] = None):
+async def read_optional_list_bytes(p: Annotated[list[bytes] | None, File()] = None):
return {"file_size": [len(file) for file in p] if p else None}
@app.post("/optional-list-uploadfile")
async def read_optional_list_uploadfile(
- p: Annotated[Optional[list[UploadFile]], File()] = None,
+ p: Annotated[list[UploadFile] | None, File()] = None,
):
return {"file_size": [file.size for file in p] if p else None}
@app.post("/optional-list-bytes-alias")
async def read_optional_list_bytes_alias(
- p: Annotated[Optional[list[bytes]], File(alias="p_alias")] = None,
+ p: Annotated[list[bytes] | None, File(alias="p_alias")] = None,
):
return {"file_size": [len(file) for file in p] if p else None}
@app.post("/optional-list-uploadfile-alias")
async def read_optional_list_uploadfile_alias(
- p: Annotated[Optional[list[UploadFile]], File(alias="p_alias")] = None,
+ p: Annotated[list[UploadFile] | None, File(alias="p_alias")] = None,
):
return {"file_size": [file.size for file in p] if p else None}
@app.post("/optional-list-bytes-validation-alias")
def read_optional_list_bytes_validation_alias(
- p: Annotated[Optional[list[bytes]], File(validation_alias="p_val_alias")] = None,
+ p: Annotated[list[bytes] | None, File(validation_alias="p_val_alias")] = None,
):
return {"file_size": [len(file) for file in p] if p else None}
@app.post("/optional-list-uploadfile-validation-alias")
def read_optional_list_uploadfile_validation_alias(
- p: Annotated[
- Optional[list[UploadFile]], File(validation_alias="p_val_alias")
- ] = None,
+ p: Annotated[list[UploadFile] | None, File(validation_alias="p_val_alias")] = None,
):
return {"file_size": [file.size for file in p] if p else None}
@app.post("/optional-list-bytes-alias-and-validation-alias")
def read_optional_list_bytes_alias_and_validation_alias(
p: Annotated[
- Optional[list[bytes]], File(alias="p_alias", validation_alias="p_val_alias")
+ list[bytes] | None, File(alias="p_alias", validation_alias="p_val_alias")
] = None,
):
return {"file_size": [len(file) for file in p] if p else None}
@app.post("/optional-list-uploadfile-alias-and-validation-alias")
def read_optional_list_uploadfile_alias_and_validation_alias(
p: Annotated[
- Optional[list[UploadFile]],
+ list[UploadFile] | None,
File(alias="p_alias", validation_alias="p_val_alias"),
] = None,
):
-from typing import Annotated, Optional
+from typing import Annotated
import pytest
from fastapi import FastAPI, Form
@app.post("/optional-list-str", operation_id="optional_list_str")
async def read_optional_list_str(
- p: Annotated[Optional[list[str]], Form()] = None,
+ p: Annotated[list[str] | None, Form()] = None,
):
return {"p": p}
class FormModelOptionalListStr(BaseModel):
- p: Optional[list[str]] = None
+ p: list[str] | None = None
@app.post("/model-optional-list-str", operation_id="model_optional_list_str")
@app.post("/optional-list-alias", operation_id="optional_list_alias")
async def read_optional_list_alias(
- p: Annotated[Optional[list[str]], Form(alias="p_alias")] = None,
+ p: Annotated[list[str] | None, Form(alias="p_alias")] = None,
):
return {"p": p}
class FormModelOptionalListAlias(BaseModel):
- p: Optional[list[str]] = Field(None, alias="p_alias")
+ p: list[str] | None = Field(None, alias="p_alias")
@app.post("/model-optional-list-alias", operation_id="model_optional_list_alias")
"/optional-list-validation-alias", operation_id="optional_list_validation_alias"
)
def read_optional_list_validation_alias(
- p: Annotated[Optional[list[str]], Form(validation_alias="p_val_alias")] = None,
+ p: Annotated[list[str] | None, Form(validation_alias="p_val_alias")] = None,
):
return {"p": p}
class FormModelOptionalListValidationAlias(BaseModel):
- p: Optional[list[str]] = Field(None, validation_alias="p_val_alias")
+ p: list[str] | None = Field(None, validation_alias="p_val_alias")
@app.post(
)
def read_optional_list_alias_and_validation_alias(
p: Annotated[
- Optional[list[str]], Form(alias="p_alias", validation_alias="p_val_alias")
+ list[str] | None, Form(alias="p_alias", validation_alias="p_val_alias")
] = None,
):
return {"p": p}
class FormModelOptionalListAliasAndValidationAlias(BaseModel):
- p: Optional[list[str]] = Field(
- None, alias="p_alias", validation_alias="p_val_alias"
- )
+ p: list[str] | None = Field(None, alias="p_alias", validation_alias="p_val_alias")
@app.post(
-from typing import Annotated, Optional
+from typing import Annotated
import pytest
from fastapi import FastAPI, Form
@app.post("/optional-str", operation_id="optional_str")
-async def read_optional_str(p: Annotated[Optional[str], Form()] = None):
+async def read_optional_str(p: Annotated[str | None, Form()] = None):
return {"p": p}
class FormModelOptionalStr(BaseModel):
- p: Optional[str] = None
+ p: str | None = None
@app.post("/model-optional-str", operation_id="model_optional_str")
@app.post("/optional-alias", operation_id="optional_alias")
async def read_optional_alias(
- p: Annotated[Optional[str], Form(alias="p_alias")] = None,
+ p: Annotated[str | None, Form(alias="p_alias")] = None,
):
return {"p": p}
class FormModelOptionalAlias(BaseModel):
- p: Optional[str] = Field(None, alias="p_alias")
+ p: str | None = Field(None, alias="p_alias")
@app.post("/model-optional-alias", operation_id="model_optional_alias")
@app.post("/optional-validation-alias", operation_id="optional_validation_alias")
def read_optional_validation_alias(
- p: Annotated[Optional[str], Form(validation_alias="p_val_alias")] = None,
+ p: Annotated[str | None, Form(validation_alias="p_val_alias")] = None,
):
return {"p": p}
class FormModelOptionalValidationAlias(BaseModel):
- p: Optional[str] = Field(None, validation_alias="p_val_alias")
+ p: str | None = Field(None, validation_alias="p_val_alias")
@app.post(
)
def read_optional_alias_and_validation_alias(
p: Annotated[
- Optional[str], Form(alias="p_alias", validation_alias="p_val_alias")
+ str | None, Form(alias="p_alias", validation_alias="p_val_alias")
] = None,
):
return {"p": p}
class FormModelOptionalAliasAndValidationAlias(BaseModel):
- p: Optional[str] = Field(None, alias="p_alias", validation_alias="p_val_alias")
+ p: str | None = Field(None, alias="p_alias", validation_alias="p_val_alias")
@app.post(
-from typing import Annotated, Optional
+from typing import Annotated
import pytest
from fastapi import FastAPI, Header
@app.get("/optional-list-str")
async def read_optional_list_str(
- p: Annotated[Optional[list[str]], Header()] = None,
+ p: Annotated[list[str] | None, Header()] = None,
):
return {"p": p}
class HeaderModelOptionalListStr(BaseModel):
- p: Optional[list[str]] = None
+ p: list[str] | None = None
@app.get("/model-optional-list-str")
@app.get("/optional-list-alias")
async def read_optional_list_alias(
- p: Annotated[Optional[list[str]], Header(alias="p_alias")] = None,
+ p: Annotated[list[str] | None, Header(alias="p_alias")] = None,
):
return {"p": p}
class HeaderModelOptionalListAlias(BaseModel):
- p: Optional[list[str]] = Field(None, alias="p_alias")
+ p: list[str] | None = Field(None, alias="p_alias")
@app.get("/model-optional-list-alias")
@app.get("/optional-list-validation-alias")
def read_optional_list_validation_alias(
- p: Annotated[Optional[list[str]], Header(validation_alias="p_val_alias")] = None,
+ p: Annotated[list[str] | None, Header(validation_alias="p_val_alias")] = None,
):
return {"p": p}
class HeaderModelOptionalListValidationAlias(BaseModel):
- p: Optional[list[str]] = Field(None, validation_alias="p_val_alias")
+ p: list[str] | None = Field(None, validation_alias="p_val_alias")
@app.get("/model-optional-list-validation-alias")
@app.get("/optional-list-alias-and-validation-alias")
def read_optional_list_alias_and_validation_alias(
p: Annotated[
- Optional[list[str]], Header(alias="p_alias", validation_alias="p_val_alias")
+ list[str] | None, Header(alias="p_alias", validation_alias="p_val_alias")
] = None,
):
return {"p": p}
class HeaderModelOptionalListAliasAndValidationAlias(BaseModel):
- p: Optional[list[str]] = Field(
- None, alias="p_alias", validation_alias="p_val_alias"
- )
+ p: list[str] | None = Field(None, alias="p_alias", validation_alias="p_val_alias")
@app.get("/model-optional-list-alias-and-validation-alias")
-from typing import Annotated, Optional
+from typing import Annotated
import pytest
from fastapi import FastAPI, Header
@app.get("/optional-str")
-async def read_optional_str(p: Annotated[Optional[str], Header()] = None):
+async def read_optional_str(p: Annotated[str | None, Header()] = None):
return {"p": p}
class HeaderModelOptionalStr(BaseModel):
- p: Optional[str] = None
+ p: str | None = None
@app.get("/model-optional-str")
@app.get("/optional-alias")
async def read_optional_alias(
- p: Annotated[Optional[str], Header(alias="p_alias")] = None,
+ p: Annotated[str | None, Header(alias="p_alias")] = None,
):
return {"p": p}
class HeaderModelOptionalAlias(BaseModel):
- p: Optional[str] = Field(None, alias="p_alias")
+ p: str | None = Field(None, alias="p_alias")
@app.get("/model-optional-alias")
@app.get("/optional-validation-alias")
def read_optional_validation_alias(
- p: Annotated[Optional[str], Header(validation_alias="p_val_alias")] = None,
+ p: Annotated[str | None, Header(validation_alias="p_val_alias")] = None,
):
return {"p": p}
class HeaderModelOptionalValidationAlias(BaseModel):
- p: Optional[str] = Field(None, validation_alias="p_val_alias")
+ p: str | None = Field(None, validation_alias="p_val_alias")
@app.get("/model-optional-validation-alias")
@app.get("/optional-alias-and-validation-alias")
def read_optional_alias_and_validation_alias(
p: Annotated[
- Optional[str], Header(alias="p_alias", validation_alias="p_val_alias")
+ str | None, Header(alias="p_alias", validation_alias="p_val_alias")
] = None,
):
return {"p": p}
class HeaderModelOptionalAliasAndValidationAlias(BaseModel):
- p: Optional[str] = Field(None, alias="p_alias", validation_alias="p_val_alias")
+ p: str | None = Field(None, alias="p_alias", validation_alias="p_val_alias")
@app.get("/model-optional-alias-and-validation-alias")
-from typing import Annotated, Optional
+from typing import Annotated
import pytest
from fastapi import FastAPI, Query
@app.get("/optional-list-str")
async def read_optional_list_str(
- p: Annotated[Optional[list[str]], Query()] = None,
+ p: Annotated[list[str] | None, Query()] = None,
):
return {"p": p}
class QueryModelOptionalListStr(BaseModel):
- p: Optional[list[str]] = None
+ p: list[str] | None = None
@app.get("/model-optional-list-str")
@app.get("/optional-list-alias")
async def read_optional_list_alias(
- p: Annotated[Optional[list[str]], Query(alias="p_alias")] = None,
+ p: Annotated[list[str] | None, Query(alias="p_alias")] = None,
):
return {"p": p}
class QueryModelOptionalListAlias(BaseModel):
- p: Optional[list[str]] = Field(None, alias="p_alias")
+ p: list[str] | None = Field(None, alias="p_alias")
@app.get("/model-optional-list-alias")
@app.get("/optional-list-validation-alias")
def read_optional_list_validation_alias(
- p: Annotated[Optional[list[str]], Query(validation_alias="p_val_alias")] = None,
+ p: Annotated[list[str] | None, Query(validation_alias="p_val_alias")] = None,
):
return {"p": p}
class QueryModelOptionalListValidationAlias(BaseModel):
- p: Optional[list[str]] = Field(None, validation_alias="p_val_alias")
+ p: list[str] | None = Field(None, validation_alias="p_val_alias")
@app.get("/model-optional-list-validation-alias")
@app.get("/optional-list-alias-and-validation-alias")
def read_optional_list_alias_and_validation_alias(
p: Annotated[
- Optional[list[str]], Query(alias="p_alias", validation_alias="p_val_alias")
+ list[str] | None, Query(alias="p_alias", validation_alias="p_val_alias")
] = None,
):
return {"p": p}
class QueryModelOptionalListAliasAndValidationAlias(BaseModel):
- p: Optional[list[str]] = Field(
- None, alias="p_alias", validation_alias="p_val_alias"
- )
+ p: list[str] | None = Field(None, alias="p_alias", validation_alias="p_val_alias")
@app.get("/model-optional-list-alias-and-validation-alias")
-from typing import Annotated, Optional
+from typing import Annotated
import pytest
from fastapi import FastAPI, Query
@app.get("/optional-str")
-async def read_optional_str(p: Optional[str] = None):
+async def read_optional_str(p: str | None = None):
return {"p": p}
class QueryModelOptionalStr(BaseModel):
- p: Optional[str] = None
+ p: str | None = None
@app.get("/model-optional-str")
@app.get("/optional-alias")
async def read_optional_alias(
- p: Annotated[Optional[str], Query(alias="p_alias")] = None,
+ p: Annotated[str | None, Query(alias="p_alias")] = None,
):
return {"p": p}
class QueryModelOptionalAlias(BaseModel):
- p: Optional[str] = Field(None, alias="p_alias")
+ p: str | None = Field(None, alias="p_alias")
@app.get("/model-optional-alias")
@app.get("/optional-validation-alias")
def read_optional_validation_alias(
- p: Annotated[Optional[str], Query(validation_alias="p_val_alias")] = None,
+ p: Annotated[str | None, Query(validation_alias="p_val_alias")] = None,
):
return {"p": p}
class QueryModelOptionalValidationAlias(BaseModel):
- p: Optional[str] = Field(None, validation_alias="p_val_alias")
+ p: str | None = Field(None, validation_alias="p_val_alias")
@app.get("/model-optional-validation-alias")
@app.get("/optional-alias-and-validation-alias")
def read_optional_alias_and_validation_alias(
p: Annotated[
- Optional[str], Query(alias="p_alias", validation_alias="p_val_alias")
+ str | None, Query(alias="p_alias", validation_alias="p_val_alias")
] = None,
):
return {"p": p}
class QueryModelOptionalAliasAndValidationAlias(BaseModel):
- p: Optional[str] = Field(None, alias="p_alias", validation_alias="p_val_alias")
+ p: str | None = Field(None, alias="p_alias", validation_alias="p_val_alias")
@app.get("/model-optional-alias-and-validation-alias")
-from typing import Union
-
from fastapi import Body, FastAPI, Query
from fastapi.testclient import TestClient
@app.get("/query")
-def read_query(q: Union[str, None]):
+def read_query(q: str | None):
return q
@app.get("/explicit-query")
-def read_explicit_query(q: Union[str, None] = Query()):
+def read_explicit_query(q: str | None = Query()):
return q
@app.post("/body-embed")
-def send_body_embed(b: Union[str, None] = Body(embed=True)):
+def send_body_embed(b: str | None = Body(embed=True)):
return b
-from typing import Union
-
import pytest
from fastapi import FastAPI
from fastapi.exceptions import FastAPIError, ResponseValidationError
@app.get(
"/response_model_union-no_annotation-return_model1",
- response_model=Union[User, Item],
+ response_model=User | Item,
)
def response_model_union_no_annotation_return_model1():
return DBUser(name="John", surname="Doe", password_hash="secret")
@app.get(
"/response_model_union-no_annotation-return_model2",
- response_model=Union[User, Item],
+ response_model=User | Item,
)
def response_model_union_no_annotation_return_model2():
return Item(name="Foo", price=42.0)
@app.get("/no_response_model-annotation_union-return_model1")
-def no_response_model_annotation_union_return_model1() -> Union[User, Item]:
+def no_response_model_annotation_union_return_model1() -> User | Item:
return DBUser(name="John", surname="Doe", password_hash="secret")
@app.get("/no_response_model-annotation_union-return_model2")
-def no_response_model_annotation_union_return_model2() -> Union[User, Item]:
+def no_response_model_annotation_union_return_model2() -> User | Item:
return Item(name="Foo", price=42.0)
with pytest.raises(FastAPIError) as e:
@app.get("/")
- def read_root() -> Union[Response, None]:
+ def read_root() -> Response | None:
return Response(content="Foo") # pragma: no cover
assert "valid Pydantic field type" in e.value.args[0]
from collections.abc import AsyncGenerator
from contextlib import asynccontextmanager
-from typing import Union
import pytest
from fastapi import APIRouter, FastAPI, Request
@asynccontextmanager
async def lifespan(
app: FastAPI,
- ) -> AsyncGenerator[dict[str, Union[str, bool]], None]:
+ ) -> AsyncGenerator[dict[str, str | bool], None]:
yield {
"app_specific": True,
"overridden": "app",
@asynccontextmanager
async def router_lifespan(
app: FastAPI,
- ) -> AsyncGenerator[dict[str, Union[str, bool]], None]:
+ ) -> AsyncGenerator[dict[str, str | bool], None]:
yield {
"router_specific": True,
"overridden": "router", # should override parent
-from typing import Union
-
import pytest
from fastapi import Body, Cookie, FastAPI, Header, Path, Query
from fastapi.exceptions import FastAPIDeprecationWarning
@app.get("/query_example/")
def query_example(
- data: Union[str, None] = Query(
+ data: str | None = Query(
default=None,
example="query1",
),
@app.get("/query_examples/")
def query_examples(
- data: Union[str, None] = Query(
+ data: str | None = Query(
default=None,
examples=["query1", "query2"],
),
@app.get("/query_example_examples/")
def query_example_examples(
- data: Union[str, None] = Query(
+ data: str | None = Query(
default=None,
example="query_overridden",
examples=["query1", "query2"],
@app.get("/header_example/")
def header_example(
- data: Union[str, None] = Header(
+ data: str | None = Header(
default=None,
example="header1",
),
@app.get("/header_examples/")
def header_examples(
- data: Union[str, None] = Header(
+ data: str | None = Header(
default=None,
examples=[
"header1",
@app.get("/header_example_examples/")
def header_example_examples(
- data: Union[str, None] = Header(
+ data: str | None = Header(
default=None,
example="header_overridden",
examples=["header1", "header2"],
@app.get("/cookie_example/")
def cookie_example(
- data: Union[str, None] = Cookie(
+ data: str | None = Cookie(
default=None,
example="cookie1",
),
@app.get("/cookie_examples/")
def cookie_examples(
- data: Union[str, None] = Cookie(
+ data: str | None = Cookie(
default=None,
examples=["cookie1", "cookie2"],
),
@app.get("/cookie_example_examples/")
def cookie_example_examples(
- data: Union[str, None] = Cookie(
+ data: str | None = Cookie(
default=None,
example="cookie_overridden",
examples=["cookie1", "cookie2"],
-from typing import Optional
-
from fastapi import Depends, FastAPI, Security
from fastapi.security import APIKeyCookie
from fastapi.testclient import TestClient
username: str
-def get_current_user(oauth_header: Optional[str] = Security(api_key)):
+def get_current_user(oauth_header: str | None = Security(api_key)):
if oauth_header is None:
return None
user = User(username=oauth_header)
-from typing import Optional
-
from fastapi import Depends, FastAPI, Security
from fastapi.security import APIKeyHeader
from fastapi.testclient import TestClient
username: str
-def get_current_user(oauth_header: Optional[str] = Security(api_key)):
+def get_current_user(oauth_header: str | None = Security(api_key)):
if oauth_header is None:
return None
user = User(username=oauth_header)
@app.get("/users/me")
-def read_current_user(current_user: Optional[User] = Depends(get_current_user)):
+def read_current_user(current_user: User | None = Depends(get_current_user)):
if current_user is None:
return {"msg": "Create an account first"}
return current_user
-from typing import Optional
-
from fastapi import Depends, FastAPI, Security
from fastapi.security import APIKeyQuery
from fastapi.testclient import TestClient
username: str
-def get_current_user(oauth_header: Optional[str] = Security(api_key)):
+def get_current_user(oauth_header: str | None = Security(api_key)):
if oauth_header is None:
return None
user = User(username=oauth_header)
@app.get("/users/me")
-def read_current_user(current_user: Optional[User] = Depends(get_current_user)):
+def read_current_user(current_user: User | None = Depends(get_current_user)):
if current_user is None:
return {"msg": "Create an account first"}
return current_user
-from typing import Optional
-
from fastapi import FastAPI, Security
from fastapi.security.http import HTTPAuthorizationCredentials, HTTPBase
from fastapi.testclient import TestClient
@app.get("/users/me")
def read_current_user(
- credentials: Optional[HTTPAuthorizationCredentials] = Security(security),
+ credentials: HTTPAuthorizationCredentials | None = Security(security),
):
if credentials is None:
return {"msg": "Create an account first"}
from base64 import b64encode
-from typing import Optional
from fastapi import FastAPI, Security
from fastapi.security import HTTPBasic, HTTPBasicCredentials
@app.get("/users/me")
-def read_current_user(credentials: Optional[HTTPBasicCredentials] = Security(security)):
+def read_current_user(credentials: HTTPBasicCredentials | None = Security(security)):
if credentials is None:
return {"msg": "Create an account first"}
return {"username": credentials.username, "password": credentials.password}
-from typing import Optional
-
from fastapi import FastAPI, Security
from fastapi.security import HTTPAuthorizationCredentials, HTTPBearer
from fastapi.testclient import TestClient
@app.get("/users/me")
def read_current_user(
- credentials: Optional[HTTPAuthorizationCredentials] = Security(security),
+ credentials: HTTPAuthorizationCredentials | None = Security(security),
):
if credentials is None:
return {"msg": "Create an account first"}
-from typing import Optional
-
from fastapi import FastAPI, Security
from fastapi.security import HTTPAuthorizationCredentials, HTTPDigest
from fastapi.testclient import TestClient
@app.get("/users/me")
def read_current_user(
- credentials: Optional[HTTPAuthorizationCredentials] = Security(security),
+ credentials: HTTPAuthorizationCredentials | None = Security(security),
):
if credentials is None:
return {"msg": "Create an account first"}
-from typing import Optional
-
from fastapi import FastAPI, Security
from fastapi.security import OAuth2AuthorizationCodeBearer
from fastapi.testclient import TestClient
@app.get("/items/")
-async def read_items(token: Optional[str] = Security(oauth2_scheme)):
+async def read_items(token: str | None = Security(oauth2_scheme)):
return {"token": token}
-from typing import Optional
-
from fastapi import FastAPI, Security
from fastapi.security import OAuth2AuthorizationCodeBearer
from fastapi.testclient import TestClient
@app.get("/items/")
-async def read_items(token: Optional[str] = Security(oauth2_scheme)):
+async def read_items(token: str | None = Security(oauth2_scheme)):
return {"token": token}
# Ref: https://github.com/fastapi/fastapi/issues/14454
-from typing import Annotated, Optional
+from typing import Annotated
from fastapi import APIRouter, Depends, FastAPI, Security
from fastapi.security import OAuth2AuthorizationCodeBearer
@router.get("/items/")
-async def read_items(token: Optional[str] = Depends(oauth2_scheme)):
+async def read_items(token: str | None = Depends(oauth2_scheme)):
return {"token": token}
@router.post("/items/")
async def create_item(
- token: Optional[str] = Security(oauth2_scheme, scopes=["read", "write"]),
+ token: str | None = Security(oauth2_scheme, scopes=["read", "write"]),
):
return {"token": token}
-from typing import Optional
-
import pytest
from fastapi import Depends, FastAPI, Security
from fastapi.security import OAuth2, OAuth2PasswordRequestFormStrict
username: str
-def get_current_user(oauth_header: Optional[str] = Security(reusable_oauth2)):
+def get_current_user(oauth_header: str | None = Security(reusable_oauth2)):
if oauth_header is None:
return None
user = User(username=oauth_header)
@app.get("/users/me")
-def read_users_me(current_user: Optional[User] = Depends(get_current_user)):
+def read_users_me(current_user: User | None = Depends(get_current_user)):
if current_user is None:
return {"msg": "Create an account first"}
return current_user
-from typing import Optional
-
import pytest
from fastapi import Depends, FastAPI, Security
from fastapi.security import OAuth2, OAuth2PasswordRequestFormStrict
username: str
-def get_current_user(oauth_header: Optional[str] = Security(reusable_oauth2)):
+def get_current_user(oauth_header: str | None = Security(reusable_oauth2)):
if oauth_header is None:
return None
user = User(username=oauth_header)
@app.get("/users/me")
-def read_users_me(current_user: Optional[User] = Depends(get_current_user)):
+def read_users_me(current_user: User | None = Depends(get_current_user)):
if current_user is None:
return {"msg": "Create an account first"}
return current_user
-from typing import Optional
-
from fastapi import FastAPI, Security
from fastapi.security import OAuth2PasswordBearer
from fastapi.testclient import TestClient
@app.get("/items/")
-async def read_items(token: Optional[str] = Security(oauth2_scheme)):
+async def read_items(token: str | None = Security(oauth2_scheme)):
if token is None:
return {"msg": "Create an account first"}
return {"token": token}
-from typing import Optional
-
from fastapi import FastAPI, Security
from fastapi.security import OAuth2PasswordBearer
from fastapi.testclient import TestClient
@app.get("/items/")
-async def read_items(token: Optional[str] = Security(oauth2_scheme)):
+async def read_items(token: str | None = Security(oauth2_scheme)):
if token is None:
return {"msg": "Create an account first"}
return {"token": token}
-from typing import Optional
-
from fastapi import Depends, FastAPI, Security
from fastapi.security.open_id_connect_url import OpenIdConnect
from fastapi.testclient import TestClient
username: str
-def get_current_user(oauth_header: Optional[str] = Security(oid)):
+def get_current_user(oauth_header: str | None = Security(oid)):
if oauth_header is None:
return None
user = User(username=oauth_header)
@app.get("/users/me")
-def read_current_user(current_user: Optional[User] = Depends(get_current_user)):
+def read_current_user(current_user: User | None = Depends(get_current_user)):
if current_user is None:
return {"msg": "Create an account first"}
return current_user
-from typing import Optional
-
from fastapi import FastAPI
from fastapi.testclient import TestClient
from pydantic import BaseModel
class Item(BaseModel):
name: str
- price: Optional[float] = None
- owner_ids: Optional[list[int]] = None
+ price: float | None = None
+ owner_ids: list[int] | None = None
@app.get("/items/valid", response_model=Item)
from dataclasses import dataclass
from datetime import datetime
-from typing import Optional
from fastapi import FastAPI
from fastapi.testclient import TestClient
class Item:
name: str
date: datetime
- price: Optional[float] = None
- owner_ids: Optional[list[int]] = None
+ price: float | None = None
+ owner_ids: list[int] | None = None
@app.get("/items/valid", response_model=Item)
-from typing import Optional
-
from fastapi import FastAPI
from pydantic import BaseModel, Field
from starlette.testclient import TestClient
class Item(BaseModel):
name: str = Field(alias="aliased_name")
- price: Optional[float] = None
- owner_ids: Optional[list[int]] = None
+ price: float | None = None
+ owner_ids: list[int] | None = None
@app.get("/items/valid", response_model=Item)
-from typing import Optional
-
from fastapi import FastAPI
from fastapi.testclient import TestClient
from pydantic import BaseModel
class SubModel(BaseModel):
- a: Optional[str] = "foo"
+ a: str | None = "foo"
class Model(BaseModel):
- x: Optional[int] = None
+ x: int | None = None
sub: SubModel
class ModelSubclass(Model):
y: int
z: int = 0
- w: Optional[int] = None
+ w: int | None = None
class ModelDefaults(BaseModel):
- w: Optional[str] = None
- x: Optional[str] = None
+ w: str | None = None
+ x: str | None = None
y: str = "y"
z: str = "z"
-from typing import Optional
-
from fastapi import APIRouter, FastAPI
from fastapi.testclient import TestClient
from inline_snapshot import snapshot
class Invoice(BaseModel):
id: str
- title: Optional[str] = None
+ title: str | None = None
customer: str
total: float
@subrouter.post("/invoices/", callbacks=invoices_callback_router.routes)
-def create_invoice(invoice: Invoice, callback_url: Optional[HttpUrl] = None):
+def create_invoice(invoice: Invoice, callback_url: HttpUrl | None = None):
"""
Create an invoice.
-from typing import Optional, Union
-
from fastapi import FastAPI
from fastapi.testclient import TestClient
from inline_snapshot import snapshot
class Item(BaseModel):
- name: Optional[str] = None
+ name: str | None = None
class OtherItem(BaseModel):
@app.post("/items/")
-def save_union_body(item: Union[OtherItem, Item]):
+def save_union_body(item: OtherItem | Item):
return {"item": item}
-from typing import Annotated, Any, Union
+from typing import Annotated, Any, Literal
from fastapi import FastAPI
from fastapi.testclient import TestClient
from inline_snapshot import snapshot
from pydantic import BaseModel, Field
-from typing_extensions import Literal
def test_discriminator_pydantic_v2() -> None:
price: float
Item = Annotated[
- Union[Annotated[FirstItem, Tag("first")], Annotated[OtherItem, Tag("other")]],
+ Annotated[FirstItem, Tag("first")] | Annotated[OtherItem, Tag("other")],
Field(discriminator="value"),
]
# Ref: https://github.com/fastapi/fastapi/discussions/14495
-from typing import Annotated, Union
+from typing import Annotated
import pytest
from fastapi import FastAPI
return v.get("pet_type", "")
Pet = Annotated[
- Union[Annotated[Cat, Tag("cat")], Annotated[Dog, Tag("dog")]],
+ Annotated[Cat, Tag("cat")] | Annotated[Dog, Tag("dog")],
Discriminator(get_pet_type),
]
-from typing import Annotated, Union
+from typing import Annotated
from fastapi import FastAPI, Form
from fastapi.testclient import TestClient
@app.post("/form-union/")
-def post_union_form(data: Annotated[Union[UserForm, CompanyForm], Form()]):
+def post_union_form(data: Annotated[UserForm | CompanyForm, Form()]):
return {"received": data}
-from typing import Optional, Union
-
from fastapi import FastAPI
from fastapi.testclient import TestClient
from inline_snapshot import snapshot
class Item(BaseModel):
- name: Optional[str] = None
+ name: str | None = None
class ExtendedItem(Item):
@app.post("/items/")
-def save_union_different_body(item: Union[ExtendedItem, Item]):
+def save_union_different_body(item: ExtendedItem | Item):
return {"item": item}
-from typing import Optional, Union
-
import pytest
from fastapi import FastAPI
from fastapi.exceptions import ResponseValidationError
class Item(BaseModel):
name: str
- price: Optional[float] = None
- owner_ids: Optional[list[int]] = None
+ price: float | None = None
+ owner_ids: list[int] | None = None
@app.get("/items/invalid", response_model=Item)
return None
-@app.get("/items/validnone", response_model=Union[Item, None])
+@app.get("/items/validnone", response_model=Item | None)
def get_valid_none(send_none: bool = False):
if send_none:
return None
-from typing import Optional
-
import pytest
from fastapi import FastAPI
from fastapi.exceptions import ResponseValidationError
@dataclass
class Item:
name: str
- price: Optional[float] = None
- owner_ids: Optional[list[int]] = None
+ price: float | None = None
+ owner_ids: list[int] | None = None
@app.get("/items/invalid", response_model=Item)
import pytest
-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+"
)