Skip to content

Commit 3aff3e9

Browse files
authored
Merge pull request #5 from marcosschroh/fix/factory-pattern
ref: Factory pattern implemented.
2 parents 87ffc1a + 4aeb1f5 commit 3aff3e9

5 files changed

Lines changed: 63 additions & 45 deletions

File tree

dataclasses_avroschema/fields.py

Lines changed: 42 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -65,37 +65,51 @@ def __post_init__(self):
6565
if isinstance(self.type, typing._GenericAlias):
6666
# means that could be a list, tuple or dict
6767
origin = self.type.__origin__
68-
69-
if origin is list:
70-
# because avro can have only one type, we take the first one
71-
items_type = self.type.__args__[0]
72-
73-
if items_type in PYTHON_PRIMITIVE_TYPES:
74-
self.items_type = PYTHON_TYPE_TO_AVRO[items_type]
75-
else:
76-
# means is a custom type
77-
self.items_type = schema_generator.SchemaGenerator(
78-
items_type).avro_schema_to_python()
79-
elif origin is dict:
80-
# because avro can have only one type, we take the first one
81-
values_type = self.type.__args__[1]
82-
83-
if values_type in PYTHON_PRIMITIVE_TYPES:
84-
self.values_type = PYTHON_TYPE_TO_AVRO[values_type]
85-
else:
86-
self.values_type = schema_generator.SchemaGenerator(
87-
values_type).avro_schema_to_python()
88-
89-
elif origin is tuple:
90-
self.symbols = list(self.default)
91-
else:
92-
# we do not accept any other typing._GenericAlias like a set
93-
# we should raise an exception
94-
raise ValueError(
95-
f"Invalid Type for field {self.name}. Accepted types are list, tuple or dict")
68+
processor = self.get_processor(origin)
69+
processor()
9670

9771
self.type = origin
9872

73+
def get_processor(self, origin):
74+
if origin is list:
75+
return self._process_list_type
76+
elif origin is dict:
77+
return self._process_dict_type
78+
elif origin is tuple:
79+
return self._process_tuple_type
80+
else:
81+
# we do not accept any other typing._GenericAlias like a set
82+
# we should raise an exception
83+
raise ValueError(
84+
f"Invalid Type for field {self.name}. Accepted types are list, tuple or dict")
85+
86+
def _process_list_type(self):
87+
# because avro can have only one type, we take the first one
88+
items_type = self.type.__args__[0]
89+
90+
if items_type in PYTHON_PRIMITIVE_TYPES:
91+
self.items_type = PYTHON_TYPE_TO_AVRO[items_type]
92+
elif isinstance(items_type, typing._GenericAlias):
93+
# Checking for a self reference. Maybe is a typing.ForwardRef
94+
self.items_type = self._process_self_reference_type(items_type)
95+
else:
96+
# means is a custom type
97+
self.items_type = schema_generator.SchemaGenerator(
98+
items_type).avro_schema_to_python()
99+
100+
def _process_dict_type(self):
101+
# because avro can have only one type, we take the first one
102+
values_type = self.type.__args__[1]
103+
104+
if values_type in PYTHON_PRIMITIVE_TYPES:
105+
self.values_type = PYTHON_TYPE_TO_AVRO[values_type]
106+
else:
107+
self.values_type = schema_generator.SchemaGenerator(
108+
values_type).avro_schema_to_python()
109+
110+
def _process_tuple_type(self):
111+
self.symbols = list(self.default)
112+
99113
@staticmethod
100114
def get_singular_name(name):
101115
singular = p.singular_noun(name)

dataclasses_avroschema/schema_definition.py

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -43,12 +43,6 @@ def __post_init__(self):
4343
self.generate_extra_avro_attributes()
4444
self.fields = self.parse_dataclasses_fields()
4545

46-
# def parse_dataclasses_fields(self) -> typing.List["Field"]:
47-
# return [
48-
# fields.Field(dataclass_field.name, dataclass_field.type, dataclass_field.default)
49-
# for dataclass_field in dataclasses.fields(self.klass_or_instance)
50-
# ]
51-
5246
def parse_dataclasses_fields(self) -> typing.List["fields.Field"]:
5347
return [
5448
fields.Field(

dataclasses_avroschema/schema_generator.py

Lines changed: 12 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -23,17 +23,22 @@ def generate_schema(self, schema_type: str = "avro"):
2323
return self.schema_definition
2424

2525
if schema_type == "avro":
26-
# cache the schema
27-
self.schema_definition = AvroSchemaDefinition(
28-
"record",
29-
self.dataclass,
30-
include_schema_doc=self.include_schema_doc
31-
)
26+
schema_definition = self._generate_avro_schema()
3227
else:
33-
raise
28+
raise ValueError("Invalid type. Expected avro schema type.")
29+
30+
# cache the schema
31+
self.schema_definition = schema_definition
3432

3533
return self.schema_definition.render()
3634

35+
def _generate_avro_schema(self) -> AvroSchemaDefinition:
36+
return AvroSchemaDefinition(
37+
"record",
38+
self.dataclass,
39+
include_schema_doc=self.include_schema_doc
40+
)
41+
3742
def avro_schema(self) -> str:
3843
return json.dumps(self.generate_schema(schema_type="avro"))
3944

@@ -46,4 +51,3 @@ def get_fields(self) -> typing.List["Field"]:
4651
self.generate_schema()
4752

4853
return self.schema_definition.fields
49-

tests/test_schema.py

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -114,3 +114,9 @@ def extra_avro_attributes():
114114
msg = "Dict must be returned type in extra_avro_attributes method"
115115
with pytest.raises(AssertionError, match=msg):
116116
SchemaGenerator(User).avro_schema()
117+
118+
119+
def test_invalid_schema_type(user_dataclass):
120+
msg = "Invalid type. Expected avro schema type."
121+
with pytest.raises(ValueError, match=msg):
122+
SchemaGenerator(user_dataclass).generate_schema(schema_type="json")

tests/test_schema_parse.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -79,7 +79,7 @@ class UserAdvance:
7979
assert parse_schema(schema.avro_schema_to_python())
8080

8181

82-
def test_one_to_one_schema(user_advance_with_defaults_dataclass):
82+
def test_one_to_one_schema():
8383
"""
8484
Test schema relationship one-to-one
8585
"""
@@ -97,7 +97,7 @@ class User:
9797
assert parse_schema(SchemaGenerator(User).avro_schema_to_python())
9898

9999

100-
def test_one_to_many_schema(user_advance_with_defaults_dataclass):
100+
def test_one_to_many_schema():
101101
"""
102102
Test schema relationship one-to-many
103103
"""
@@ -115,7 +115,7 @@ class User:
115115
assert parse_schema(SchemaGenerator(User).avro_schema_to_python())
116116

117117

118-
def test_one_to_many_with_map_schema(user_advance_with_defaults_dataclass):
118+
def test_one_to_many_with_map_schema():
119119
"""
120120
Test schema relationship one-to-many using a map
121121
"""

0 commit comments

Comments
 (0)