import dataclasses
import inspect
from contextlib import contextmanager
-from copy import deepcopy
+from copy import copy, deepcopy
from typing import (
Any,
Callable,
), f"Cannot specify multiple `Annotated` FastAPI arguments for {param_name!r}"
fastapi_annotation = next(iter(fastapi_annotations), None)
if isinstance(fastapi_annotation, FieldInfo):
- field_info = fastapi_annotation
+ # Copy `field_info` because we mutate `field_info.default` below.
+ field_info = copy(fastapi_annotation)
assert field_info.default is Undefined or field_info.default is Required, (
f"`{field_info.__class__.__name__}` default value cannot be set in"
f" `Annotated` for {param_name!r}. Set the default value with `=` instead."
import pytest
-from fastapi import FastAPI, Query
+from fastapi import APIRouter, FastAPI, Query
from fastapi.testclient import TestClient
from typing_extensions import Annotated
response = client.get(path)
assert response.status_code == expected_status
assert response.json() == expected_response
+
+
+def test_multiple_path():
+ @app.get("/test1")
+ @app.get("/test2")
+ async def test(var: Annotated[str, Query()] = "bar"):
+ return {"foo": var}
+
+ response = client.get("/test1")
+ assert response.status_code == 200
+ assert response.json() == {"foo": "bar"}
+
+ response = client.get("/test1", params={"var": "baz"})
+ assert response.status_code == 200
+ assert response.json() == {"foo": "baz"}
+
+ response = client.get("/test2")
+ assert response.status_code == 200
+ assert response.json() == {"foo": "bar"}
+
+ response = client.get("/test2", params={"var": "baz"})
+ assert response.status_code == 200
+ assert response.json() == {"foo": "baz"}
+
+
+def test_nested_router():
+ app = FastAPI()
+
+ router = APIRouter(prefix="/nested")
+
+ @router.get("/test")
+ async def test(var: Annotated[str, Query()] = "bar"):
+ return {"foo": var}
+
+ app.include_router(router)
+
+ client = TestClient(app)
+
+ response = client.get("/nested/test")
+ assert response.status_code == 200
+ assert response.json() == {"foo": "bar"}