From 610eb2dee38000b485d0b7f7ec4ce69bdf50ac3d Mon Sep 17 00:00:00 2001 From: Eduard Fischer-Szava Date: Sat, 30 May 2026 16:42:25 +0200 Subject: [PATCH] Handle broken optional JSON imports Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- fastapi/responses.py | 4 ++-- tests/test_deprecated_responses.py | 23 +++++++++++++++++++++++ 2 files changed, 25 insertions(+), 2 deletions(-) diff --git a/fastapi/responses.py b/fastapi/responses.py index 29df4b7a61..0c9caa4d04 100644 --- a/fastapi/responses.py +++ b/fastapi/responses.py @@ -26,13 +26,13 @@ class _OrjsonModule(Protocol): try: ujson = cast(_UjsonModule, importlib.import_module("ujson")) -except ModuleNotFoundError: # pragma: nocover +except ImportError: # pragma: nocover ujson = None # type: ignore[assignment] try: orjson = cast(_OrjsonModule, importlib.import_module("orjson")) -except ModuleNotFoundError: # pragma: nocover +except ImportError: # pragma: nocover orjson = None # type: ignore[assignment] diff --git a/tests/test_deprecated_responses.py b/tests/test_deprecated_responses.py index 8cbd9c11fe..44ee3f0b82 100644 --- a/tests/test_deprecated_responses.py +++ b/tests/test_deprecated_responses.py @@ -1,3 +1,4 @@ +import importlib import warnings import pytest @@ -77,3 +78,25 @@ def test_ujson_response_returns_correct_data(): def test_ujson_response_emits_deprecation_warning(): with pytest.warns(FastAPIDeprecationWarning, match="UJSONResponse is deprecated"): UJSONResponse(content={"hello": "world"}) + + +@pytest.mark.parametrize("module_name", ["orjson", "ujson"]) +def test_importing_fastapi_responses_ignores_broken_optional_json_installs( + monkeypatch: pytest.MonkeyPatch, module_name: str +) -> None: + import fastapi.responses as responses + + real_import_module = importlib.import_module + + def fake_import_module(name: str, package: str | None = None): + if name == module_name: + raise ImportError(f"simulated broken {module_name} install") + return real_import_module(name, package) + + monkeypatch.setattr(importlib, "import_module", fake_import_module) + try: + reloaded = importlib.reload(responses) + assert getattr(reloaded, module_name) is None + finally: + monkeypatch.setattr(importlib, "import_module", real_import_module) + importlib.reload(responses)