Skip to content

Commit

Permalink
Merge pull request #113 from DaanRademaker/allow_optional_enum
Browse files Browse the repository at this point in the history
allow processing of optional enum values
  • Loading branch information
DaanRademaker authored Aug 9, 2024
2 parents 524e19d + 51c7106 commit fdc718d
Show file tree
Hide file tree
Showing 2 changed files with 66 additions and 8 deletions.
13 changes: 11 additions & 2 deletions src/pydantic_avro/from_avro/types.py
Original file line number Diff line number Diff line change
Expand Up @@ -56,10 +56,19 @@ def logical_type_handler(t: dict) -> str:

def enum_type_handler(t: dict) -> str:
"""Gets the enum type of a given Avro enum type and adds it to the class registry"""
name = t["type"].get("name")
if t["type"] == "enum":
# comes from a unioned enum (e.g. ["null", "enum"])
type_info = t
else:
# comes from a direct enum
type_info = t["type"]

name = type_info["name"]
symbols = type_info["symbols"]

if not ClassRegistry().has_class(name):
enum_class = f"class {name}(str, Enum):\n"
for s in t["type"].get("symbols"):
for s in symbols:
enum_class += f' {s} = "{s}"\n'
ClassRegistry().add_class(name, enum_class)
return name
Expand Down
61 changes: 55 additions & 6 deletions tests/test_from_avro.py
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,10 @@ def test_avsc_to_pydantic_map():
"name": "Test",
"type": "record",
"fields": [
{"name": "col1", "type": {"type": "map", "values": "string", "default": {}}},
{
"name": "col1",
"type": {"type": "map", "values": "string", "default": {}},
},
],
}
)
Expand All @@ -73,7 +76,10 @@ def test_avsc_to_pydantic_map_missing_values():
"name": "Test",
"type": "record",
"fields": [
{"name": "col1", "type": {"type": "map", "values": None, "default": {}}},
{
"name": "col1",
"type": {"type": "map", "values": None, "default": {}},
},
],
}
)
Expand Down Expand Up @@ -215,7 +221,11 @@ def test_default():
"fields": [
{"name": "col1", "type": "string", "default": "test"},
{"name": "col2_1", "type": ["null", "string"], "default": None},
{"name": "col2_2", "type": ["string", "null"], "default": "default_str"},
{
"name": "col2_2",
"type": ["string", "null"],
"default": "default_str",
},
{
"name": "col3",
"type": {"type": "map", "values": "string"},
Expand Down Expand Up @@ -245,7 +255,11 @@ def test_enums():
"fields": [
{
"name": "c1",
"type": {"type": "enum", "symbols": ["passed", "failed"], "name": "Status"},
"type": {
"type": "enum",
"symbols": ["passed", "failed"],
"name": "Status",
},
},
],
}
Expand All @@ -256,6 +270,32 @@ def test_enums():
assert "class Status(str, Enum):\n" ' passed = "passed"\n' ' failed = "failed"' in pydantic_code


def test_enums_nullable():
pydantic_code = avsc_to_pydantic(
{
"name": "Test",
"type": "record",
"fields": [
{
"name": "c1",
"type": [
"null",
{
"type": "enum",
"symbols": ["passed", "failed"],
"name": "Status",
},
],
},
],
}
)

assert "class Test(BaseModel):\n" " c1: Optional[Status]" in pydantic_code

assert "class Status(str, Enum):\n" ' passed = "passed"\n' ' failed = "failed"' in pydantic_code


def test_enums_reuse():
pydantic_code = avsc_to_pydantic(
{
Expand All @@ -264,7 +304,11 @@ def test_enums_reuse():
"fields": [
{
"name": "c1",
"type": {"type": "enum", "symbols": ["passed", "failed"], "name": "Status"},
"type": {
"type": "enum",
"symbols": ["passed", "failed"],
"name": "Status",
},
},
{"name": "c2", "type": "Status"},
],
Expand All @@ -291,7 +335,12 @@ def test_unions():
{
"type": "record",
"name": "ARecord",
"fields": [{"name": "values", "type": {"type": "map", "values": "string"}}],
"fields": [
{
"name": "values",
"type": {"type": "map", "values": "string"},
}
],
},
],
},
Expand Down

0 comments on commit fdc718d

Please sign in to comment.