Skip to content

Commit c8bcac4

Browse files
authored
Merge pull request #131 from Exabyte-io/feature/SOF-7755
7755 update: add snake case
2 parents f19b253 + a91ddb0 commit c8bcac4

File tree

3 files changed

+75
-2
lines changed

3 files changed

+75
-2
lines changed

src/py/mat3ra/code/entity.py

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,8 @@
22

33
import jsonschema
44
from mat3ra.utils import object as object_utils
5-
from pydantic import BaseModel
5+
from pydantic import BaseModel, ConfigDict
6+
from pydantic.alias_generators import to_snake
67
from typing_extensions import Self
78

89
from . import BaseUnderscoreJsonPropsHandler
@@ -86,6 +87,14 @@ def clone(self: T, extra_context: Optional[Dict[str, Any]] = None, deep=True) ->
8687
return self.model_copy(update=extra_context or {}, deep=deep)
8788

8889

90+
class InMemoryEntitySnakeCase(InMemoryEntityPydantic):
91+
model_config = ConfigDict(
92+
arbitrary_types_allowed=True,
93+
alias_generator=to_snake,
94+
populate_by_name=True,
95+
)
96+
97+
8998
# TODO: remove in the next PR
9099
class InMemoryEntity(BaseUnderscoreJsonPropsHandler):
91100
jsonSchema: Optional[Dict] = None

tests/py/unit/__init__.py

Lines changed: 31 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,8 @@
11
import json
22
from enum import Enum
3+
from typing import Optional
34

4-
from mat3ra.code.entity import InMemoryEntityPydantic
5+
from mat3ra.code.entity import InMemoryEntityPydantic, InMemoryEntitySnakeCase
56
from pydantic import BaseModel
67

78
REFERENCE_OBJECT_VALID = {"key1": "value1", "key2": 1}
@@ -68,3 +69,32 @@ class SampleModelWithEnum(BaseModel):
6869

6970
class SampleEntityWithEnum(SampleModelWithEnum, InMemoryEntityPydantic):
7071
pass
72+
73+
74+
class CamelCaseSchema(BaseModel):
75+
applicationName: str
76+
applicationVersion: Optional[str] = None
77+
executableName: Optional[str] = None
78+
79+
80+
class SnakeCaseEntity(CamelCaseSchema, InMemoryEntitySnakeCase):
81+
pass
82+
83+
84+
SNAKE_CASE_CONFIG = {
85+
"application_name": "espresso",
86+
"application_version": "7.2",
87+
"executable_name": "pw.x",
88+
}
89+
90+
CAMEL_CASE_CONFIG = {
91+
"applicationName": "espresso",
92+
"applicationVersion": "7.2",
93+
"executableName": "pw.x",
94+
}
95+
96+
MIXED_CASE_CONFIG = {
97+
"application_name": "espresso",
98+
"applicationVersion": "7.2",
99+
"executable_name": "pw.x",
100+
}

tests/py/unit/test_entity.py

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,11 @@
11
import json
22

3+
import pytest
4+
35
from . import (
6+
CAMEL_CASE_CONFIG,
7+
CAMEL_CASE_CONFIG as EXPECTED_CAMEL_CASE_OUTPUT,
8+
MIXED_CASE_CONFIG,
49
REFERENCE_OBJECT_DOUBLE_NESTED_VALID,
510
REFERENCE_OBJECT_INVALID,
611
REFERENCE_OBJECT_NESTED_VALID,
@@ -10,6 +15,7 @@
1015
REFERENCE_OBJECT_VALID_UPDATED,
1116
REFERENCE_OBJECT_VALID_WITH_EXTRA_KEY,
1217
REFERENCE_OBJECT_VALID_WITH_MISSING_KEY,
18+
SNAKE_CASE_CONFIG,
1319
ExampleClass,
1420
ExampleDefaultableClass,
1521
ExampleDoubleNestedKeyAsClassInstancesClass,
@@ -20,6 +26,7 @@
2026
ExampleSchema,
2127
SampleEnum,
2228
SampleEntityWithEnum,
29+
SnakeCaseEntity,
2330
)
2431

2532

@@ -211,3 +218,30 @@ def test_clone_deep():
211218
cloned_entity_deep.key1 = "adjusted_value"
212219
assert entity.key1 == "value1"
213220
assert cloned_entity_deep.key1 == "adjusted_value"
221+
222+
223+
@pytest.mark.parametrize(
224+
"config,expected_output",
225+
[
226+
(SNAKE_CASE_CONFIG, EXPECTED_CAMEL_CASE_OUTPUT),
227+
(CAMEL_CASE_CONFIG, EXPECTED_CAMEL_CASE_OUTPUT),
228+
(MIXED_CASE_CONFIG, EXPECTED_CAMEL_CASE_OUTPUT),
229+
],
230+
)
231+
def test_create_entity_snake_case(config, expected_output):
232+
entity = SnakeCaseEntity(**config)
233+
assert entity.applicationName == expected_output["applicationName"]
234+
assert entity.applicationVersion == expected_output["applicationVersion"]
235+
assert entity.executableName == expected_output["executableName"]
236+
237+
result_dict = entity.to_dict()
238+
assert result_dict == expected_output
239+
assert "applicationName" in result_dict
240+
assert "application_name" not in result_dict
241+
242+
result_json = json.loads(entity.to_json())
243+
assert result_json == expected_output
244+
245+
entity_from_create = SnakeCaseEntity.create(config)
246+
assert entity_from_create.to_dict() == expected_output
247+

0 commit comments

Comments
 (0)