Skip to content

Commit 94bafcf

Browse files
authored
fix: model generatation fixed when field name and field type hint clashes on arrays and maps (#795)
1 parent 03248bb commit 94bafcf

5 files changed

Lines changed: 187 additions & 7 deletions

File tree

dataclasses_avroschema/model_generator/lang/python/base.py

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -453,13 +453,19 @@ def render_field(self, field: JsonDict, model_name: str, parent_field_name: str)
453453
type_hint = self.parse_logical_type(field=field)
454454
elif isinstance(avro_type, dict):
455455
type_hint = ""
456-
children = [self.render_field(field=avro_type, model_name=model_name, parent_field_name=name)]
456+
children = [
457+
self.render_field(field=avro_type, model_name=model_name, parent_field_name=name or parent_field_name)
458+
]
457459
elif isinstance(avro_type, list):
458460
type_hint, children = self.parse_union(field_types=avro_type, model_name=model_name, parent_field_name=name)
459461
elif avro_type == field_utils.ARRAY:
460-
type_hint, children = self.parse_array(field=field, model_name=model_name, parent_field_name=name)
462+
type_hint, children = self.parse_array(
463+
field=field, model_name=model_name, parent_field_name=name or parent_field_name
464+
)
461465
elif avro_type == field_utils.MAP:
462-
type_hint, children = self.parse_map(field=field, model_name=model_name, parent_field_name=name)
466+
type_hint, children = self.parse_map(
467+
field=field, model_name=model_name, parent_field_name=name or parent_field_name
468+
)
463469
elif avro_type == field_utils.ENUM:
464470
type_hint = self.parse_enum(field=field)
465471
# We must set the default Enums type level default to dataclasses.MISSING

tests/model_generator/conftest.py

Lines changed: 61 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -473,7 +473,7 @@ def schema_one_to_one_relationship() -> JsonDict:
473473

474474

475475
@pytest.fixture
476-
def schema_one_to_many_relationship_clashes_types() -> JsonDict:
476+
def schema_one_to_many_relationship_array_clashes_types() -> JsonDict:
477477
return {
478478
"type": "record",
479479
"name": "Message",
@@ -498,6 +498,66 @@ def schema_one_to_many_relationship_clashes_types() -> JsonDict:
498498
],
499499
"default": None,
500500
},
501+
{
502+
"name": "Sender",
503+
"type": {
504+
"type": "array",
505+
"items": {
506+
"type": "record",
507+
"name": "Sender",
508+
"fields": [
509+
{"name": "company", "type": "string"},
510+
{"name": "delivered", "type": {"type": "long", "logicalType": "timestamp-millis"}},
511+
],
512+
},
513+
},
514+
"default": [],
515+
},
516+
],
517+
}
518+
519+
520+
@pytest.fixture
521+
def schema_one_to_many_relationship_map_clashes_types() -> JsonDict:
522+
return {
523+
"type": "record",
524+
"name": "Message",
525+
"fields": [
526+
{"name": "MessageBody", "type": "string"},
527+
{
528+
"name": "MessageHeader",
529+
"type": [
530+
"null",
531+
{
532+
"type": "map",
533+
"name": "MessageHeader",
534+
"values": {
535+
"type": "record",
536+
"name": "MessageHeader",
537+
"fields": [
538+
{"name": "version", "type": "string"},
539+
{"name": "MessageType", "type": "string"},
540+
],
541+
},
542+
},
543+
],
544+
"default": None,
545+
},
546+
{
547+
"name": "Sender",
548+
"type": {
549+
"type": "map",
550+
"values": {
551+
"type": "record",
552+
"name": "Sender",
553+
"fields": [
554+
{"name": "company", "type": "string"},
555+
{"name": "delivered", "type": {"type": "long", "logicalType": "timestamp-millis"}},
556+
],
557+
},
558+
},
559+
"default": {},
560+
},
501561
],
502562
}
503563

tests/model_generator/test_model_generator.py

Lines changed: 50 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -469,12 +469,13 @@ class User(AvroModel):
469469
assert result.strip() == expected_result.strip()
470470

471471

472-
def test_schema_one_to_many_relationship_clashes_types(
473-
schema_one_to_many_relationship_clashes_types: types.JsonDict,
472+
def test_schema_one_to_many_relationship_array_clashes_types(
473+
schema_one_to_many_relationship_array_clashes_types: types.JsonDict,
474474
) -> None:
475475
expected_result = """
476476
from dataclasses_avroschema import AvroModel
477477
import dataclasses
478+
import datetime
478479
import typing
479480
480481
@@ -486,13 +487,59 @@ class MessageHeader(AvroModel):
486487
_MessageHeader = MessageHeader
487488
488489
490+
@dataclasses.dataclass
491+
class Sender(AvroModel):
492+
company: str
493+
delivered: datetime.datetime
494+
495+
_Sender = Sender
496+
497+
489498
@dataclasses.dataclass
490499
class Message(AvroModel):
491500
MessageBody: str
492501
MessageHeader: typing.Optional[typing.List[_MessageHeader]] = None
502+
Sender: typing.List[_Sender] = dataclasses.field(default_factory=list)
503+
"""
504+
model_generator = ModelGenerator()
505+
result = model_generator.render(schema=schema_one_to_many_relationship_array_clashes_types)
506+
assert result.strip() == expected_result.strip()
507+
508+
509+
def test_schema_one_to_many_relationship_map_clashes_types(
510+
schema_one_to_many_relationship_map_clashes_types: types.JsonDict,
511+
) -> None:
512+
expected_result = """
513+
from dataclasses_avroschema import AvroModel
514+
import dataclasses
515+
import datetime
516+
import typing
517+
518+
519+
@dataclasses.dataclass
520+
class MessageHeader(AvroModel):
521+
version: str
522+
MessageType: str
523+
524+
_MessageHeader = MessageHeader
525+
526+
527+
@dataclasses.dataclass
528+
class Sender(AvroModel):
529+
company: str
530+
delivered: datetime.datetime
531+
532+
_Sender = Sender
533+
534+
535+
@dataclasses.dataclass
536+
class Message(AvroModel):
537+
MessageBody: str
538+
MessageHeader: typing.Optional[typing.Dict[str, _MessageHeader]] = None
539+
Sender: typing.Dict[str, _Sender] = dataclasses.field(default_factory=dict)
493540
"""
494541
model_generator = ModelGenerator()
495-
result = model_generator.render(schema=schema_one_to_many_relationship_clashes_types)
542+
result = model_generator.render(schema=schema_one_to_many_relationship_map_clashes_types)
496543
assert result.strip() == expected_result.strip()
497544

498545

tests/schemas/avro/clashes_types_schema.avsc renamed to tests/schemas/avro/clashes_types_array_schema.avsc

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,22 @@
3030
}
3131
],
3232
"default": null
33+
},
34+
{
35+
"name": "Sender",
36+
"type": {
37+
"type": "array",
38+
"name": "Sender",
39+
"items": {
40+
"type": "record",
41+
"name": "Sender",
42+
"fields": [
43+
{"name": "company", "type": "string"},
44+
{"name": "delivered", "type": {"type": "long", "logicalType": "timestamp-millis"}}
45+
]
46+
}
47+
},
48+
"default": []
3349
}
3450
]
3551
}
Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
{
2+
"type": "record",
3+
"name": "Message",
4+
"fields": [
5+
{
6+
"name": "MessageBody",
7+
"type": "string"
8+
},
9+
{
10+
"name": "MessageHeader",
11+
"type": [
12+
"null",
13+
{
14+
"type": "map",
15+
"values": {
16+
"type": "record",
17+
"name": "MessageHeader",
18+
"fields": [
19+
{
20+
"name": "version",
21+
"type": "string"
22+
},
23+
{
24+
"name": "MessageType",
25+
"type": "string"
26+
}
27+
]
28+
},
29+
"name": "MessageHeader"
30+
}
31+
],
32+
"default": null
33+
},
34+
{
35+
"name": "Sender",
36+
"type": {
37+
"type": "array",
38+
"name": "Sender",
39+
"items": {
40+
"type": "record",
41+
"name": "Sender",
42+
"fields": [
43+
{"name": "company", "type": "string"},
44+
{"name": "delivered", "type": {"type": "long", "logicalType": "timestamp-millis"}}
45+
]
46+
}
47+
},
48+
"default": []
49+
}
50+
]
51+
}

0 commit comments

Comments
 (0)