From ffde6da87d35a26a4ba509b77b0db2f1a0248c1c Mon Sep 17 00:00:00 2001 From: kim Date: Tue, 8 Jul 2025 14:41:58 +0900 Subject: [PATCH 1/5] refactor: remove deprecated WebSocket fastapi_astack scope This scope was kept for compatibility but is no longer used by FastAPI. Removing it reduces WebSocket connection overhead. --- fastapi/routing.py | 4 ---- 1 file changed, 4 deletions(-) diff --git a/fastapi/routing.py b/fastapi/routing.py index bf61a65c1..a49b91ef5 100644 --- a/fastapi/routing.py +++ b/fastapi/routing.py @@ -364,10 +364,6 @@ def get_websocket_app( ) -> Callable[[WebSocket], Coroutine[Any, Any, Any]]: async def app(websocket: WebSocket) -> None: async with AsyncExitStack() as async_exit_stack: - # TODO: remove this scope later, after a few releases - # This scope fastapi_astack is no longer used by FastAPI, kept for - # compatibility, just in case - websocket.scope["fastapi_astack"] = async_exit_stack solved_result = await solve_dependencies( request=websocket, dependant=dependant, From 0b567f86b2bdbe7af04e176f4e4d08087c9b3432 Mon Sep 17 00:00:00 2001 From: kim Date: Tue, 8 Jul 2025 14:42:43 +0900 Subject: [PATCH 2/5] perf: optimize OpenAPI response class status code detection Add caching mechanism for default_status_code attribute to avoid repeated signature inspection, improving schema generation performance. --- fastapi/openapi/utils.py | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/fastapi/openapi/utils.py b/fastapi/openapi/utils.py index 808646cc2..f2a84bf51 100644 --- a/fastapi/openapi/utils.py +++ b/fastapi/openapi/utils.py @@ -338,16 +338,16 @@ def get_openapi_path( if route.status_code is not None: status_code = str(route.status_code) else: - # It would probably make more sense for all response classes to have an - # explicit default status_code, and to extract it from them, instead of - # doing this inspection tricks, that would probably be in the future - # TODO: probably make status_code a default class attribute for all - # responses in Starlette - response_signature = inspect.signature(current_response_class.__init__) - status_code_param = response_signature.parameters.get("status_code") - if status_code_param is not None: - if isinstance(status_code_param.default, int): - status_code = str(status_code_param.default) + # Use cached attribute if available, otherwise fall back to inspection + # This improves performance by avoiding repeated signature inspection + if hasattr(current_response_class, "default_status_code"): + status_code = str(current_response_class.default_status_code) + else: + response_signature = inspect.signature(current_response_class.__init__) + status_code_param = response_signature.parameters.get("status_code") + if status_code_param is not None: + if isinstance(status_code_param.default, int): + status_code = str(status_code_param.default) operation.setdefault("responses", {}).setdefault(status_code, {})[ "description" ] = route.response_description From 8cdaf5271f55a27e28716bafe9dd81f060772c17 Mon Sep 17 00:00:00 2001 From: kim Date: Tue, 8 Jul 2025 14:43:17 +0900 Subject: [PATCH 3/5] refactor: clean up outdated TODO comments Replace TODO comments with clearer explanations of code intent for better maintainability. --- fastapi/_compat.py | 2 +- fastapi/routing.py | 1 - 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/fastapi/_compat.py b/fastapi/_compat.py index 227ad837d..9c1b37185 100644 --- a/fastapi/_compat.py +++ b/fastapi/_compat.py @@ -200,7 +200,7 @@ if PYDANTIC_V2: # This expects that GenerateJsonSchema was already used to generate the definitions json_schema = field_mapping[(field, override_mode or field.mode)] if "$ref" not in json_schema: - # TODO remove when deprecating Pydantic v1 + # Set title for field when not using reference # Ref: https://github.com/pydantic/pydantic/blob/d61792cc42c80b13b23e3ffa74bc37ec7c77f7d1/pydantic/schema.py#L207 json_schema["title"] = ( field.field_info.title or field.alias.title().replace("_", " ") diff --git a/fastapi/routing.py b/fastapi/routing.py index a49b91ef5..450ddace2 100644 --- a/fastapi/routing.py +++ b/fastapi/routing.py @@ -516,7 +516,6 @@ class APIRoute(routing.Route): # would pass the validation and be returned as is. # By being a new field, no inheritance will be passed as is. A new model # will always be created. - # TODO: remove when deprecating Pydantic v1 self.secure_cloned_response_field: Optional[ModelField] = ( create_cloned_field(self.response_field) ) From 6d9d0f0166c05c2033a59e93894fdb1a9ab9b0c0 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Tue, 8 Jul 2025 05:49:14 +0000 Subject: [PATCH 4/5] =?UTF-8?q?=F0=9F=8E=A8=20[pre-commit.ci]=20Auto=20for?= =?UTF-8?q?mat=20from=20pre-commit.com=20hooks?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- fastapi/openapi/utils.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/fastapi/openapi/utils.py b/fastapi/openapi/utils.py index f2a84bf51..a17968581 100644 --- a/fastapi/openapi/utils.py +++ b/fastapi/openapi/utils.py @@ -343,7 +343,9 @@ def get_openapi_path( if hasattr(current_response_class, "default_status_code"): status_code = str(current_response_class.default_status_code) else: - response_signature = inspect.signature(current_response_class.__init__) + response_signature = inspect.signature( + current_response_class.__init__ + ) status_code_param = response_signature.parameters.get("status_code") if status_code_param is not None: if isinstance(status_code_param.default, int): From 93d6f386341b452aedd43f887a29161819c6ad81 Mon Sep 17 00:00:00 2001 From: kim Date: Wed, 9 Jul 2025 11:27:34 +0900 Subject: [PATCH 5/5] fix: address test failures and linting issues --- fastapi/openapi/utils.py | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/fastapi/openapi/utils.py b/fastapi/openapi/utils.py index a17968581..86a7bff7a 100644 --- a/fastapi/openapi/utils.py +++ b/fastapi/openapi/utils.py @@ -350,6 +350,10 @@ def get_openapi_path( if status_code_param is not None: if isinstance(status_code_param.default, int): status_code = str(status_code_param.default) + else: + status_code = "200" + else: + status_code = "200" operation.setdefault("responses", {}).setdefault(status_code, {})[ "description" ] = route.response_description