From d626e40e9edde966c17b49db1ae2d043895c1c93 Mon Sep 17 00:00:00 2001 From: sanderegg <35365065+sanderegg@users.noreply.github.com> Date: Fri, 25 Oct 2024 15:32:43 +0200 Subject: [PATCH] moved tests --- .../tests/test_json_serialization.py | 97 +++++++++++++++++++ .../tests/test_utils_json_serialization.py | 70 +------------ 2 files changed, 98 insertions(+), 69 deletions(-) create mode 100644 packages/common-library/tests/test_json_serialization.py diff --git a/packages/common-library/tests/test_json_serialization.py b/packages/common-library/tests/test_json_serialization.py new file mode 100644 index 00000000000..7684497e493 --- /dev/null +++ b/packages/common-library/tests/test_json_serialization.py @@ -0,0 +1,97 @@ +# pylint: disable=redefined-outer-name +# pylint: disable=unused-argument +# pylint: disable=unused-variable + +import json +from copy import deepcopy +from typing import Annotated, Any, TypeAlias +from uuid import uuid4 + +import pytest +from common_library.json_serialization import ( + JsonNamespace, + SeparatorTuple, + json_dumps, + json_loads, +) +from faker import Faker +from pydantic import Field, TypeAdapter +from pydantic.json import pydantic_encoder + + +@pytest.fixture +def fake_data_dict(faker: Faker) -> dict[str, Any]: + data = { + "uuid_as_UUID": faker.uuid4(cast_to=None), + "uuid_as_str": faker.uuid4(), + "int": faker.pyint(), + "float": faker.pyfloat(), + "str": faker.pystr(), + "dict": faker.pydict(), + "list": faker.pylist(), + } + data["object"] = deepcopy(data) + return data + + +def test_json_dump_variants(): + + uuid_obj = uuid4() + + with pytest.raises(TypeError) as exc_info: + json.dumps(uuid_obj) + + assert str(exc_info.value) == "Object of type UUID is not JSON serializable" + + assert json_dumps(uuid_obj) == json.dumps(str(uuid_obj)) + + +def test_serialized_non_str_dict_keys(): + # tests orjson.OPT_NON_STR_KEYS option + + # if a dict has a key of a type other than str it will NOT raise + json_dumps({1: "foo"}) + + +ConstrainedFloat: TypeAlias = Annotated[float, Field(ge=0.0, le=1.0)] + + +def test_serialized_constraint_floats(): + # test extension of ENCODERS_BY_TYPE used in pydantic_encoder + + json_dumps({"value": 1.0}) + + # TypeError: Type is not JSON serializable: ProgressPercent + json_dumps({"value": TypeAdapter(ConstrainedFloat).validate_python(1.0)}) + + +def _expected_json_dumps(obj: Any, default=pydantic_encoder, **json_dumps_kwargs): + if "indent" not in json_dumps_kwargs: + json_dumps_kwargs.setdefault( + "separators", + SeparatorTuple(item_separator=",", key_separator=":"), # compact separators + ) + return json.dumps(obj, default=default, **json_dumps_kwargs) + + +@pytest.mark.parametrize( + "kwargs", + [ + pytest.param({}, id="no-kw"), + pytest.param({"sort_keys": True}, id="sort_keys-kw"), + pytest.param( + {"separators": (",", ":")}, id="default_separators-kw" + ), # NOTE: e.g. engineio.packet has `self.json.dumps(self.data, separators=(',', ':'))` + pytest.param( + {"indent": 2}, id="indent-kw" + ), # NOTE: only one-to-one with indent=2 + ], +) +def test_compatiblity_with_json_interface( + fake_data_dict: dict[str, Any], kwargs: dict[str, Any] +): + orjson_dump = JsonNamespace.dumps(fake_data_dict, **kwargs) + json_dump = _expected_json_dumps(fake_data_dict, **kwargs) + + # NOTE: cannot compare dumps directly because orjson compacts it more + assert json_loads(orjson_dump) == json_loads(json_dump) diff --git a/packages/models-library/tests/test_utils_json_serialization.py b/packages/models-library/tests/test_utils_json_serialization.py index 94b7458460f..a229c16b75d 100644 --- a/packages/models-library/tests/test_utils_json_serialization.py +++ b/packages/models-library/tests/test_utils_json_serialization.py @@ -3,43 +3,14 @@ # pylint: disable=unused-variable -import json from copy import deepcopy from typing import Any from uuid import uuid4 import pytest -from common_library.json_serialization import ( - JsonNamespace, - SeparatorTuple, - json_dumps, - json_loads, -) +from common_library.json_serialization import json_dumps, json_loads from faker import Faker -from models_library.api_schemas_long_running_tasks.base import ProgressPercent from models_library.utils.fastapi_encoders import jsonable_encoder -from pydantic.json import pydantic_encoder - - -def _expected_json_dumps(obj: Any, default=pydantic_encoder, **json_dumps_kwargs): - if "indent" not in json_dumps_kwargs: - json_dumps_kwargs.setdefault( - "separators", - SeparatorTuple(item_separator=",", key_separator=":"), # compact separators - ) - return json.dumps(obj, default=default, **json_dumps_kwargs) - - -def test_json_dump_variants(): - - uuid_obj = uuid4() - - with pytest.raises(TypeError) as exc_info: - json.dumps(uuid_obj) - - assert str(exc_info.value) == "Object of type UUID is not JSON serializable" - - assert json_dumps(uuid_obj) == json.dumps(str(uuid_obj)) @pytest.fixture @@ -75,42 +46,3 @@ def test_serialization_of_nested_dicts(fake_data_dict: dict[str, Any]): dump = json_dumps(obj) assert json_loads(dump) == jsonable_encoder(obj) - - -@pytest.mark.parametrize( - "kwargs", - [ - pytest.param({}, id="no-kw"), - pytest.param({"sort_keys": True}, id="sort_keys-kw"), - pytest.param( - {"separators": (",", ":")}, id="default_separators-kw" - ), # NOTE: e.g. engineio.packet has `self.json.dumps(self.data, separators=(',', ':'))` - pytest.param( - {"indent": 2}, id="indent-kw" - ), # NOTE: only one-to-one with indent=2 - ], -) -def test_compatiblity_with_json_interface( - fake_data_dict: dict[str, Any], kwargs: dict[str, Any] -): - orjson_dump = JsonNamespace.dumps(fake_data_dict, **kwargs) - json_dump = _expected_json_dumps(fake_data_dict, **kwargs) - - # NOTE: cannot compare dumps directly because orjson compacts it more - assert json_loads(orjson_dump) == json_loads(json_dump) - - -def test_serialized_non_str_dict_keys(): - # tests orjson.OPT_NON_STR_KEYS option - - # if a dict has a key of a type other than str it will NOT raise - json_dumps({1: "foo"}) - - -def test_serialized_constraint_floats(): - # test extension of ENCODERS_BY_TYPE used in pydantic_encoder - - json_dumps({"value": 1.0}) - - # TypeError: Type is not JSON serializable: ProgressPercent - json_dumps({"value": ProgressPercent(1.0)})