pydantic-avro
pydantic-avro copied to clipboard
Support for List with Tuple and Union type defined in Pydantic class
The pydantic avro is unable to handle module below type mentioned for vertices
. It seems inside the list, Tuple and Union is not handled. Can you verify the same if it is supported by the module?
e.g.
class PolygonType(Enum):
triangle = 3
tetragon = 4
pentagon = 5
hexagon = 6
class PolygonModel(AvroBase):
polygon_type : PolygonType
vertices: List[Tuple[Union[int, float], Union[int, float]]]
PolygonModel.avro_schema()
error
---------------------------------------------------------------------------
AttributeError Traceback (most recent call last)
Cell In[13], line 1
----> 1 PolygonModel.avro_schema()
File ~/.pyenv/versions/3.11.0/envs/jupyter/lib/python3.11/site-packages/pydantic_avro/base.py:29, in AvroBase.avro_schema(cls, by_alias, namespace)
25 if namespace is None:
26 # default namespace will be based on title
27 namespace = schema["title"]
---> 29 return cls._avro_schema(schema, namespace)
File ~/.pyenv/versions/3.11.0/envs/jupyter/lib/python3.11/site-packages/pydantic_avro/base.py:186, in AvroBase._avro_schema(schema, namespace)
183 fields.append(avro_type_dict)
184 return fields
--> 186 fields = get_fields(schema)
187 print(fields)
188 return {"type": "record", "namespace": namespace, "name": schema["title"], "fields": fields}
File ~/.pyenv/versions/3.11.0/envs/jupyter/lib/python3.11/site-packages/pydantic_avro/base.py:167, in AvroBase._avro_schema.<locals>.get_fields(s)
165 required = s.get("required", [])
166 for key, value in s.get("properties", {}).items():
--> 167 avro_type_dict = get_type(value)
168 avro_type_dict["name"] = key
170 if key not in required:
File ~/.pyenv/versions/3.11.0/envs/jupyter/lib/python3.11/site-packages/pydantic_avro/base.py:90, in AvroBase._avro_schema.<locals>.get_type(value)
88 elif t == "array":
89 items = value.get("items")
---> 90 tn = get_type(items)
91 # If items in array are a object:
92 if "$ref" in items:
File ~/.pyenv/versions/3.11.0/envs/jupyter/lib/python3.11/site-packages/pydantic_avro/base.py:90, in AvroBase._avro_schema.<locals>.get_type(value)
88 elif t == "array":
89 items = value.get("items")
---> 90 tn = get_type(items)
91 # If items in array are a object:
92 if "$ref" in items:
File ~/.pyenv/versions/3.11.0/envs/jupyter/lib/python3.11/site-packages/pydantic_avro/base.py:48, in AvroBase._avro_schema.<locals>.get_type(value)
46 """Returns a type of a single field"""
47 print(value)
---> 48 t = value.get("type")
49 f = value.get("format")
50 r = value.get("$ref")
AttributeError: 'NoneType' object has no attribute 'get'
There are multiple issues here. I think the main one is that the pydantic-avro library is going to try and turn PolygonType
into an enum in the avro schema. Unfortunately enums in the avro schema have a requirement for the values of the enums (link to docs). Just a number is not going to work. Probably the easiest workaround is to either turn your enum to have matching string values like what is below or just turn the field into an int
.
With python 3.11 you can use StrEnum
(python docs):
class PolygonType(StrEnum):
triangle = auto()
tetragon = auto()
pentagon = auto()
hexagon = auto()
I have a PR open to support unions within the list. However there is another bug in which tuple
is not supported either. I'll see if I can put that into my existing PR as well.