marcosschroh / dataclasses-avroschema

Generate avro schemas from python dataclasses, Pydantic models and Faust Records. Code generation from avro schemas. Serialize/Deserialize python instances with avro schemas.
https://marcosschroh.github.io/dataclasses-avroschema/
MIT License
216 stars 66 forks source link

Field and type with same name not parsed correctly by Pydantic #769

Open Masqueey opened 1 week ago

Masqueey commented 1 week ago

Describe the bug A schema with a field name that is identical to a class name will fail to be parsed by Pydantic (and also create the wrong fake()data) when it is within a type definition (e.g. as typing.List[ExampleType]).

To Reproduce

  1. Have a datamodel that uses the AvroBaseModel from dataclasses_avroschema.pydantic.
  2. Have a field in the model that has the same name as a class, but within a type-specified field.

As an example:

class MessageHeader(AvroBaseModel):
    version: str
    MessageType: str

class MessageHeader(AvroBaseModel):
    MessageHeader: typing.Optional[typing.List[MessageHeader]]
    MessageBody: str
  1. Try for instance .fake() on the model. It will generate either None or [None]

To Bypass

  1. Rename the class name, for instance add _
  2. Add metadata to the class to keep its old name when a schema is generated using this model.

To bypass the error in the above example:

class _MessageHeader(AvroBaseModel):
    version: str
    MessageType: str

    class Meta:
        schema_name = "MessageHeader"

class MessageHeader(AvroBaseModel):
    MessageHeader: typing.Optional[typing.List[_MessageHeader]]
    MessageBody: str

Expected behavior Have the model be usable in the same way when not using any typing specifications like optional or list without changing the name or having to add metadata to the model.

marcosschroh commented 16 hours ago

Both classes are called in the same way, should it not be something like

class MessageHeader(AvroBaseModel):
    version: str
    MessageType: str

class Message(AvroBaseModel):
    MessageHeader: typing.Optional[typing.List[MessageHeader]]
    MessageBody: str