Skip to content

Faust integration

This library also has support to generate Avro Schemas from a faust.Record using AvroRecord. AvroRecord is just a class that inherits from faust.Record and AvroModel respectively.

Note

All the AvroModel features like serialization, parsing objects, validation and fake, are available with AvroRecord

Example:

Basic usage
import typing
from faust.models import fields
from dataclasses_avroschema.faust import AvroRecord


class UserAdvance(AvroRecord):
    name: str
    age: int
    pets: typing.List[str] = fields.StringField(required=False, default=["dog", "cat"])
    accounts: typing.Dict[str, int] = fields.IntegerField(required=False, default={"key": 1})
    has_car: bool = fields.BooleanField(required=False, default=False)
    favorite_colors: typing.Tuple[str] = fields.StringField(required=False, default=("BLUE", "YELLOW", "GREEN"))
    country: str = fields.StringField(required=False, default="Argentina")
    address: typing.Optional[str] = None

    class Meta:
        schema_doc = False


UserAdvance.avro_schema()

resulting in

{
  "type": "record",
  "name": "UserAdvance",
  "fields": [
    {
      "name": "name",
      "type": "string"
    },
    {
      "name": "age",
      "type": "long"
    },
    {
      "name": "pets",
      "type": {
        "type": "array",
        "items": "string",
        "name": "pet"
      },
      "default": ["dog", "cat"]
    },
    {
      "name": "accounts",
      "type": {
        "type": "map",
        "values": "long",
        "name": "account"
      },
      "default": {"key": 1}
    },
    {
      "name": "has_car",
      "type": "boolean",
      "default": false
    },
    {
      "name": "favorite_colors", 
      "type": {
        "type": "array", "items": "string", "name": "favorite_color",
        "default": ["BLUE", "YELLOW", "GREEN"]
      }
    },
    {
      "name": "country",
      "type": "string",
      "default": "Argentina"
    },
    {
      "name": "address",
      "type": ["null", "string"],
      "default": null
    }
  ]
}

(This script is complete, it should run "as is")

Data validation

For models there is no validation of data by default in Faust, however there is an option that will enable validation for all common JSON fields (int, float, str, etc.), and some commonly used Python ones (datetime, Decimal, etc.)

In order to validate the data validation=True must be used as is described in tha faust documenation

Data validation
import typing
from faust.models import fields
from dataclasses_avroschema.faust import AvroRecord


class UserAdvance(AvroRecord, validation=True):
    name: str
    age: int
    pets: typing.List[str] = fields.StringField(required=False, default=['dog', 'cat'])
    accounts: typing.Dict[str, int] = fields.IntegerField(required=False, default={"key": 1})
    has_car: bool = fields.BooleanField(required=False, default=False)
    favorite_colors: typing.Tuple[str] = fields.StringField(required=False, default=("BLUE", "YELLOW", "GREEN"))
    country: str = fields.StringField(required=False, default="Argentina")
    address: typing.Optional[str] = None

    class Meta:
        schema_doc = False

UserAdvance(name="marcos", age="bond")

ValueError: invalid literal for int() with base 10: 'bond'
import typing

from dataclasses_avroschema.faust import AvroRecord


class UserAdvance(AvroRecord):
    name: str
    age: int
    pets: typing.List[str] = fields.StringField(required=False, default=['dog', 'cat'])
    accounts: typing.Dict[str, int] = fields.IntegerField(required=False, default={"key": 1})
    has_car: bool = fields.BooleanField(required=False, default=False)
    favorite_colors: typing.Tuple[str] = fields.StringField(required=False, default=("BLUE", "YELLOW", "GREEN"))
    country: str = fields.StringField(required=False, default="Argentina")
    address: typing.Optional[str] = None

    class Meta:
        schema_doc = False

UserAdvance(name="marcos", age="juan")  # WRONG data

(This script is complete, it should run "as is")

Faust and dataclasses_avroschema batteries

To dict, to json and serialization

import typing

from faust.models import fields

from dataclasses_avroschema.faust import AvroRecord


class Address(AvroRecord):
    street: str
    street_number: int


class UserAdvance(AvroRecord):
    name: str
    age: int
    address: Address
    pets: typing.List[str] = fields.StringField(required=False, default=['dog', 'cat'])
    accounts: typing.Dict[str, int] = fields.IntegerField(required=False, default={"key": 1})
    has_car: bool = fields.BooleanField(required=False, default=False)
    favorite_colors: typing.Tuple[str] = fields.StringField(required=False, default=("BLUE", "YELLOW", "GREEN"))
    country: str = fields.StringField(required=False, default="Argentina")

    class Meta:
        schema_doc = False


user = UserAdvance(
    name="bond",
    age=50, 
    address=Address(
        street="Wilhelminastraat",
        street_number=29,
    )
)


assert user.to_dict() == {
    'name': 'bond', 'age': 50, 
    'address': {
        'street': 'Wilhelminastraat', 
        'street_number': 29
    }, 
    'pets': ['dog', 'cat'], 
    'accounts': {'key': 1},
    'has_car': False,
    'favorite_colors': ('BLUE', 'YELLOW', 'GREEN'), 
    'country': 'Argentina'
}

assert user.to_json(separators=(",",":",)) == """{"name":"bond","age":50,"address":{"street":"Wilhelminastraat","street_number":29},"pets":["dog","cat"],"accounts":{"key":1},"has_car":false,"favorite_colors":["BLUE","YELLOW","GREEN"],"country":"Argentina"}"""

event = user.serialize()
assert event == b'\x08bondd Wilhelminastraat:\x04\x06dog\x06cat\x00\x02\x06key\x02\x00\x00\x06\x08BLUE\x0cYELLOW\nGREEN\x00\x12Argentina'

assert UserAdvance.deserialize(data=event) == UserAdvance(name='bond', age=50, address=Address(street='Wilhelminastraat', street_number=29), pets=['dog', 'cat'], accounts={'key': 1}, has_car=False, favorite_colors=('BLUE', 'YELLOW', 'GREEN'), country='Argentina')