Coverage for tests/serializers/pydantic/test_json_backend.py: 100%
40 statements
« prev ^ index » next coverage.py v7.17.3, created at 2026-11-13 05:19 +0000
« prev ^ index » next coverage.py v7.17.3, created at 2026-11-13 05:19 +0000
1"""`fast_depends.pydantic._compat` picks its JSON backend at import time.
3Which branch runs depends on what happens to be installed, so the module is
4re-executed here against stubbed `sys.modules` entries instead. Coverage keys
5line data off the file, so re-executing the real file from disk does measure
6the real branches, and nothing is imported into the live module tree.
7"""
9import importlib.util 1abcdefghijklmno
10import json 1abcdefghijklmno
11import sys 1abcdefghijklmno
12from types import ModuleType 1abcdefghijklmno
14import pytest 1abcdefghijklmno
16import fast_depends.pydantic._compat as live_compat 1abcdefghijklmno
18BACKENDS = ("orjson", "ujson") 1abcdefghijklmno
21def make_backend(name: str) -> ModuleType: 1abcdefghijklmno
22 stub = ModuleType(name) 1abcdefghijklmno
23 stub.loads = json.loads # type: ignore[attr-defined] 1abcdefghijklmno
24 stub.dumps = json.dumps # type: ignore[attr-defined] 1abcdefghijklmno
25 return stub 1abcdefghijklmno
28def reload_compat( 1abcdefghijklmno
29 monkeypatch: pytest.MonkeyPatch,
30 installed: dict[str, ModuleType],
31) -> ModuleType:
32 for name in BACKENDS: 1abcdefghijklmno
33 # a `None` entry makes the import fail the same way a missing
34 # distribution would
35 monkeypatch.setitem(sys.modules, name, installed.get(name)) 1abcdefghijklmno
37 spec = importlib.util.spec_from_file_location( 1abcdefghijklmno
38 "fast_depends_compat_probe",
39 live_compat.__file__,
40 )
41 assert spec is not None 1abcdefghijklmno
42 assert spec.loader is not None 1abcdefghijklmno
44 module = importlib.util.module_from_spec(spec) 1abcdefghijklmno
45 spec.loader.exec_module(module) 1abcdefghijklmno
46 return module 1abcdefghijklmno
49def test_orjson_is_preferred(monkeypatch: pytest.MonkeyPatch) -> None: 1abcdefghijklmno
50 orjson, ujson = make_backend("orjson"), make_backend("ujson") 1abcdefghijklmno
52 compat = reload_compat(monkeypatch, {"orjson": orjson, "ujson": ujson}) 1abcdefghijklmno
54 assert compat.orjson is orjson 1abcdefghijklmno
55 assert compat.ujson is ujson 1abcdefghijklmno
56 assert compat.json_loads is orjson.loads 1abcdefghijklmno
57 # orjson already returns `bytes`, so it is used as is
58 assert compat.json_dumps is orjson.dumps 1abcdefghijklmno
61def test_ujson_is_used_without_orjson(monkeypatch: pytest.MonkeyPatch) -> None: 1abcdefghijklmno
62 ujson = make_backend("ujson") 1abcdefghijklmno
64 compat = reload_compat(monkeypatch, {"ujson": ujson}) 1abcdefghijklmno
66 assert compat.orjson is None 1abcdefghijklmno
67 assert compat.json_loads is ujson.loads 1abcdefghijklmno
68 # ujson returns `str`, so the wrapper has to encode it
69 assert compat.json_dumps({"a": 1}) == b'{"a": 1}' 1abcdefghijklmno
72def test_stdlib_json_is_the_fallback(monkeypatch: pytest.MonkeyPatch) -> None: 1abcdefghijklmno
73 compat = reload_compat(monkeypatch, {}) 1abcdefghijklmno
75 assert compat.orjson is None 1abcdefghijklmno
76 assert compat.ujson is None 1abcdefghijklmno
77 assert compat.json_loads is json.loads 1abcdefghijklmno
78 assert compat.json_dumps({"a": 1}) == b'{"a": 1}' 1abcdefghijklmno