From 58b0f71feeefe346590390b6306e7524ad022d17 Mon Sep 17 00:00:00 2001 From: Callum Forrester Date: Fri, 21 Apr 2023 15:49:17 +0100 Subject: [PATCH 1/3] Allow use of snake case on pydantic models internally --- src/blueapi/utils/base_model.py | 1 + 1 file changed, 1 insertion(+) diff --git a/src/blueapi/utils/base_model.py b/src/blueapi/utils/base_model.py index 03d8b1de3..73d8a7742 100644 --- a/src/blueapi/utils/base_model.py +++ b/src/blueapi/utils/base_model.py @@ -14,6 +14,7 @@ class BlueapiModelConfig(BaseConfig): alias_generator = _to_camel extra = Extra.forbid + allow_population_by_field_name = True class BlueapiPlanModelConfig(BlueapiModelConfig): From 011ffc40f5e0feb3c31a355ff35d8d8de90c7e21 Mon Sep 17 00:00:00 2001 From: Callum Forrester Date: Fri, 21 Apr 2023 15:53:01 +0100 Subject: [PATCH 2/3] Test camelCase models to avoid regression --- tests/utils/test_base_model.py | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) create mode 100644 tests/utils/test_base_model.py diff --git a/tests/utils/test_base_model.py b/tests/utils/test_base_model.py new file mode 100644 index 000000000..24171dd23 --- /dev/null +++ b/tests/utils/test_base_model.py @@ -0,0 +1,25 @@ +from blueapi.utils import BlueapiBaseModel + + +class FooBar(BlueapiBaseModel): + hello: str = "hello" + hello_world: str = "hello world" + + +def test_snake_case_constructor() -> None: + FooBar( + hello="hello", + hello_world="hello world", + ) + + +def test_camel_case_parsing() -> None: + assert FooBar.parse_obj( + { + "hello": "hello", + "helloWorld": "hello world", + } + ) == FooBar( + hello="hello", + hello_world="hello world", + ) From d0c1be5e6d64dde6f5cfcec47d8142ae1b90a520 Mon Sep 17 00:00:00 2001 From: Callum Forrester Date: Fri, 21 Apr 2023 16:21:16 +0100 Subject: [PATCH 3/3] Serialize by alias --- src/blueapi/utils/serialization.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/blueapi/utils/serialization.py b/src/blueapi/utils/serialization.py index 141d0b702..bf1774013 100644 --- a/src/blueapi/utils/serialization.py +++ b/src/blueapi/utils/serialization.py @@ -17,7 +17,9 @@ def serialize(obj: Any) -> Any: """ if isinstance(obj, BaseModel): - return obj.dict() + # Serialize by alias so that our camelCase models leave the service + # with camelCase field names + return obj.dict(by_alias=True) elif hasattr(obj, "__pydantic_model__"): return serialize(getattr(obj, "__pydantic_model__")) else: