Skip to content

Commit

Permalink
fix: add aliases to field when field name is not a valid identifier. …
Browse files Browse the repository at this point in the history
…Related to #628 (#654)
  • Loading branch information
marcosschroh authored Jun 7, 2024
1 parent 5a13cd0 commit 9722254
Show file tree
Hide file tree
Showing 5 changed files with 49 additions and 6 deletions.
17 changes: 14 additions & 3 deletions dataclasses_avroschema/model_generator/lang/python/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -186,7 +186,8 @@ def render_field(self, field: JsonDict, model_name: str) -> FieldRepresentation:
3. If the field is a LogicalType, it may not have the
the `name` property and the type is a `native` one
"""
name = self.generate_field_name(field.get("name", ""))
name = self.generate_field_name(field)

type: AvroTypeRepr = field["type"]
default = field.get("default", dataclasses.MISSING)
field_metadata = self.get_field_metadata(field)
Expand Down Expand Up @@ -256,9 +257,19 @@ def render_field(self, field: JsonDict, model_name: str) -> FieldRepresentation:
return FieldRepresentation(name=name, string_representation=result, has_default=has_default)

@staticmethod
def generate_field_name(field_name: str) -> str:
def generate_field_name(field: JsonDict) -> str:
field_name = field.get("name", "")

if field_name and not field_name.isidentifier():
return casefy.snakecase(field_name)
valid_identifier = casefy.snakecase(field_name)
if valid_identifier != field_name:
aliases = field.get("aliases", [])

if valid_identifier not in aliases:
aliases.append(field_name)
field["aliases"] = aliases

return valid_identifier
return field_name

@staticmethod
Expand Down
2 changes: 1 addition & 1 deletion scripts/format
Original file line number Diff line number Diff line change
Expand Up @@ -6,4 +6,4 @@ if [ -d '.venv' ] ; then
fi

${PREFIX}ruff format dataclasses_avroschema tests
${PREFIX}ruff dataclasses_avroschema tests --fix
${PREFIX}ruff check dataclasses_avroschema tests --fix
2 changes: 2 additions & 0 deletions tests/model_generator/conftest.py
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,8 @@ def schema_with_invalid_python_identifiers() -> Dict:
"fields": [
{"name": "street-name", "type": "string"},
{"name": "street-number", "type": "long"},
{"name": "street-zipcode", "type": "string", "aliases": ["zipcode"]},
{"name": "city_name", "type": "string", "aliases": ["city-name"]},
{"name": "ValidIdentifier", "type": "string"},
{"name": "anotherIdentifier", "type": "string"},
{"name": "_private", "type": "string"},
Expand Down
6 changes: 4 additions & 2 deletions tests/model_generator/test_model_generator.py
Original file line number Diff line number Diff line change
Expand Up @@ -47,8 +47,10 @@ class Address(AvroModel):
\"""
An Address
\"""
street_name: str
street_number: int
street_name: str = dataclasses.field(metadata={'aliases': ['street-name']})
street_number: int = dataclasses.field(metadata={'aliases': ['street-number']})
street_zipcode: str = dataclasses.field(metadata={'aliases': ['zipcode', 'street-zipcode']})
city_name: str = dataclasses.field(metadata={'aliases': ['city-name']})
ValidIdentifier: str
anotherIdentifier: str
_private: str
Expand Down
28 changes: 28 additions & 0 deletions tests/model_generator/test_model_pydantic_generator.py
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,34 @@ class User(AvroBaseModel):
assert result.strip() == expected_result.strip()


def test_avro_pydantic_invalid_python_identifiers(schema_with_invalid_python_identifiers: types.JsonDict) -> None:
expected_result = """
from dataclasses_avroschema.pydantic import AvroBaseModel
from pydantic import Field
class Address(AvroBaseModel):
\"""
An Address
\"""
street_name: str = Field(metadata={'aliases': ['street-name']})
street_number: int = Field(metadata={'aliases': ['street-number']})
street_zipcode: str = Field(metadata={'aliases': ['zipcode', 'street-zipcode']})
city_name: str = Field(metadata={'aliases': ['city-name']})
ValidIdentifier: str
anotherIdentifier: str
_private: str
"""
model_generator = ModelGenerator()
result = model_generator.render(
schema=schema_with_invalid_python_identifiers, model_type=ModelType.AVRODANTIC.value
)
assert result.strip() == expected_result.strip()


def test_avro_pydantic_model_with_meta_fields(
schema_one_to_self_relationship: types.JsonDict,
) -> None:
Expand Down

0 comments on commit 9722254

Please sign in to comment.