diff --git a/fastapi/dependencies/utils.py b/fastapi/dependencies/utils.py index caa18e118..ffa798b1c 100644 --- a/fastapi/dependencies/utils.py +++ b/fastapi/dependencies/utils.py @@ -208,16 +208,28 @@ def get_flat_params(dependant: Dependant) -> List[ModelField]: def get_typed_signature(call: Callable[..., Any]) -> inspect.Signature: signature = inspect.signature(call) globalns = getattr(call, "__globals__", {}) - fields = getattr(call, "model_fields", {}) + if PYDANTIC_V2: + fields = getattr(call, "model_fields", {}) + else: + fields = getattr(call, "__fields__", {}) if len(fields): alias_dict = {} query_extra_info = {} for param in fields: - query_extra_info[param] = dict(fields[param].__repr_args__()) + if PYDANTIC_V2: + query_extra_info[param] = dict(fields[param].__repr_args__()) + else: + query_extra_info[param] = dict(fields[param].field_info.__repr_args__()) + if "alias" in query_extra_info[param]: - query_extra_info[query_extra_info[param]["alias"]] = dict( - fields[param].__repr_args__() - ) + if PYDANTIC_V2: + query_extra_info[query_extra_info[param]["alias"]] = dict( + fields[param].__repr_args__() + ) + else: + query_extra_info[query_extra_info[param]["alias"]] = dict( + fields[param].field_info.__repr_args__() + ) alias_dict[query_extra_info[param]["alias"]] = param query_extra_info[param]["default"] = ( Required diff --git a/tests/test_dependency_schema_query.py b/tests/test_dependency_schema_query.py index 950ff6acd..d1d809c90 100644 --- a/tests/test_dependency_schema_query.py +++ b/tests/test_dependency_schema_query.py @@ -3,6 +3,10 @@ from typing import Optional from fastapi import Depends, FastAPI, Query, status from fastapi.testclient import TestClient from pydantic import BaseModel +from pydantic.version import VERSION as PYDANTIC_VERSION + + +PYDANTIC_V2 = PYDANTIC_VERSION.startswith("2.") app = FastAPI() @@ -39,7 +43,158 @@ async def item_with_query_dependency(item: Item = Depends()): client = TestClient(app) -openapi_schema_with_not_omitted_description = { +openapi_schema_with_not_omitted_description_pydantic_v1 = { + "openapi": "3.1.0", + "info": {"title": "FastAPI", "version": "0.1.0"}, + "paths": { + "/item": { + "get": { + "summary": "Item With Query Dependency", + "operationId": "item_with_query_dependency_item_get", + "parameters": [ + { + "description": "This is a name_required_with_default field.", + "required": False, + "schema": { + "type": "string", + "title": "Name Required With Default", + "description": "This is a name_required_with_default field.", + "default": "name default", + "extra": {}, + }, + "name": "name_required_with_default", + "in": "query", + }, + { + "description": "This is a name_required_without_default field.", + "required": True, + "schema": { + "type": "string", + "title": "Name Required Without Default", + "description": "This is a name_required_without_default field.", + "extra": {}, + }, + "name": "name_required_without_default", + "in": "query", + }, + { + "description": "This is a optional_int field", + "required": False, + "schema": { + "type": "integer", + "title": "Optional Int", + "description": "This is a optional_int field", + "extra": {}, + }, + "name": "optional_int", + "in": "query", + }, + { + "description": "This is a optional_str field", + "required": False, + "schema": { + "type": "string", + "title": "Optional Str", + "description": "This is a optional_str field", + "default": "default_exists", + "extra": {}, + }, + "name": "optional_str", + "in": "query", + }, + { + "required": True, + "schema": {"type": "string", "title": "Model", "extra": {}}, + "name": "model", + "in": "query", + }, + { + "required": True, + "schema": { + "type": "string", + "title": "Manufacturer", + "extra": {}, + }, + "name": "manufacturer", + "in": "query", + }, + { + "required": True, + "schema": {"type": "number", "title": "Price", "extra": {}}, + "name": "price", + "in": "query", + }, + { + "required": True, + "schema": {"type": "number", "title": "Tax", "extra": {}}, + "name": "tax", + "in": "query", + }, + { + "description": "This is a extra_optional_attributes field", + "required": False, + "schema": { + "type": "string", + "maxLength": 30, + "title": "Extra Optional Attributes Alias", + "description": "This is a extra_optional_attributes field", + "extra": {}, + }, + "name": "extra_optional_attributes_alias", + "in": "query", + }, + ], + "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", + }, + "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", + }, + } + }, +} + +openapi_schema_with_not_omitted_description_pydantic_v2 = { "openapi": "3.1.0", "info": {"title": "FastAPI", "version": "0.1.0"}, "paths": { @@ -202,8 +357,10 @@ openapi_schema_with_not_omitted_description = { def test_openapi_schema_with_query_dependency(): response = client.get("/openapi.json") assert response.status_code == 200, response.text - print(response.json()) - assert response.json() == openapi_schema_with_not_omitted_description + if PYDANTIC_V2: + assert response.json() == openapi_schema_with_not_omitted_description_pydantic_v2 + else: + assert response.json() == openapi_schema_with_not_omitted_description_pydantic_v1 def test_response():