Skip to content

Commit

Permalink
fix: do not uppercase enums keys when the key already exist. Closes #399
Browse files Browse the repository at this point in the history
  • Loading branch information
Marcos Schroh committed Aug 30, 2023
1 parent d1e856e commit 311f398
Show file tree
Hide file tree
Showing 4 changed files with 105 additions and 2 deletions.
12 changes: 10 additions & 2 deletions dataclasses_avroschema/model_generator/generator.py
Original file line number Diff line number Diff line change
Expand Up @@ -424,10 +424,18 @@ def parse_enum(self, field: JsonDict) -> str:

field_name: str = field["name"]
enum_name = casefy.pascalcase(field_name)

symbols_map = {}
for symbol in field["symbols"]:
key = casefy.uppercase(symbol)
if key in symbols_map:
key = symbol
symbols_map[key] = symbol

symbols = self.field_identation.join(
[
templates.enum_symbol_template.safe_substitute(key=casefy.uppercase(symbol), value=f'"{symbol}"')
for symbol in field["symbols"]
templates.enum_symbol_template.safe_substitute(key=key, value=f'"{value}"')
for key, value in symbols_map.items()
]
)
docstring = self.render_docstring(docstring=field.get("doc"))
Expand Down
55 changes: 55 additions & 0 deletions docs/model_generator.md
Original file line number Diff line number Diff line change
Expand Up @@ -411,3 +411,58 @@ class User(AvroModel):
class Meta:
field_order = ['has_pets', 'name', 'age', 'money']
```

## Enums and case sensitivity

Sometimes there are schemas that contains the `symbols` which are case sensivity, for example `"symbols": ["P", "p"]`.
Having something like that is NOT reccomended at all because it is meaninless, really hard to undestand the intention of it. Avoid it!!!

When the schema generator encounter this situation it can not generated the proper `enum` with `uppercases` key so it will use the `symbol` without any transformation

```python
from dataclasses_avroschema import ModelGenerator

schema = {
"type": "record",
"name": "User",
"fields": [
{
"name": "unit_multi_player",
"type": {
"type": "enum",
"name": "unit_multi_player",
"symbols": ["P", "p"],
},
}
],
}

model_generator = ModelGenerator()
result = model_generator.render(schema=schema)

# save the result in a file
with open("models.py", mode="+w") as f:
f.write(result)
```

Then the result will be:

```python
# models.py
from dataclasses_avroschema import AvroModel
import dataclasses
import enum


class UnitMultiPlayer(enum.Enum):
P = "P"
p = "p"


@dataclasses.dataclass
class User(AvroModel):
unit_multi_player: UnitMultiPlayer

```

As the example shows the second enum member `UnitMultiPlayer.p` is not in uppercase otherwise will collide with the first member `UnitMultiPlayer.P`
18 changes: 18 additions & 0 deletions tests/model_generator/conftest.py
Original file line number Diff line number Diff line change
Expand Up @@ -212,6 +212,24 @@ def schema_with_enum_types() -> Dict:
}


@pytest.fixture
def schema_with_enum_types_case_sensitivity() -> Dict:
return {
"type": "record",
"name": "User",
"fields": [
{
"name": "unit_multi_player",
"type": {
"type": "enum",
"name": "unit_multi_player",
"symbols": ["P", "p"],
},
}
],
}


@pytest.fixture
def schema_one_to_one_relationship() -> JsonDict:
return {
Expand Down
22 changes: 22 additions & 0 deletions tests/model_generator/test_model_generator.py
Original file line number Diff line number Diff line change
Expand Up @@ -204,6 +204,28 @@ class User(AvroModel):
assert result.strip() == expected_result.strip()


def test_schema_with_enum_types_case_sensitivity(schema_with_enum_types_case_sensitivity: types.JsonDict) -> None:
expected_result = """
from dataclasses_avroschema import AvroModel
import dataclasses
import enum
class UnitMultiPlayer(enum.Enum):
P = "P"
p = "p"
@dataclasses.dataclass
class User(AvroModel):
unit_multi_player: UnitMultiPlayer
"""
model_generator = ModelGenerator()
result = model_generator.render(schema=schema_with_enum_types_case_sensitivity)
assert result.strip() == expected_result.strip()


def test_schema_one_to_one_relationship(schema_one_to_one_relationship: types.JsonDict) -> None:
expected_result = """
from dataclasses_avroschema import AvroModel
Expand Down

0 comments on commit 311f398

Please sign in to comment.