Custom Types

Additional types are supported though custom type as annotations.

Single Inheritance

Custom types can be saved and loaded by extending one of the included converter classes:

Class Description
converters.Converter Base class for all converters.
converters.Boolean Converts to bool before serialization.
converters.Integer Converts to int before serialization.
converters.Float Converts to float before serialization.
converters.String Converts to str before serialization.

For example, here is a custom converter that ensures floating point numbers are always rounded to two decimal places:

from datafiles import converters


class RoundedFloat(converters.Float):

    @classmethod
    def to_preserialization_data(cls, python_value, **kwargs):
        number = super().to_preserialization_data(python_value, **kwargs)
        return round(number, 2)


@datafile("sample.yml")
class Result:
    total: RoundedFloat = 0.0

which can be constructed like so:

result = Result(1.2345)

to save this sample.yml file:

total: 1.23

that can be loaded as follows:

>>> result = Result()
>>> result.total
1.23

Multiple Inheritance

It's also possible to extend an existing class in order to have instances inherit the functionality of that class. For example, here is a custom converter based on the datetime class that serializes using the ISO format:

from datetime import datetime

from datafiles import converters, datafile


class MyDateTime(converters.Converter, datetime):

    @classmethod
    def to_preserialization_data(cls, python_value, **kwargs):
        # Convert `MyDateTime` to a value that can be serialized
        return python_value.isoformat()

    @classmethod
    def to_python_value(cls, deserialized_data, **kwargs):
        # Convert file value back into a `MyDateTime` object
        return MyDateTime.fromisoformat(deserialized_data)

    # Any additional methods could go here...


@datafile("sample.yml")
class Timestamp:
    my_datetime: MyDateTime = None

which can be constructed like so:

timestamp = Timestamp(datetime.now())

to save this sample.yml file:

my_datetime: 2019-01-30T23:17:45

that can be loaded as follows:

>>> timestamp = Timestamp()
>>> timestamp.my_datetime
datetime.datetime(2019, 1, 30, 23, 17, 45)

Converter Registration

Finally, if you'd rather not have to modify your own classes (or don't have control over the source of a class), you can also register a custom converter for any class:

from datetime import datetime

from datafiles import converters, datafile


class DateTimeConverter(converters.Converter):

    @classmethod
    def to_preserialization_data(cls, python_value, **kwargs):
        # Convert `datetime` to a value that can be serialized
        return python_value.isoformat()

    @classmethod
    def to_python_value(cls, deserialized_data, **kwargs):
        # Convert file value back into a `datetime` object
        return datetime.fromisoformat(deserialized_data)


converters.register(datetime, DateTimeConverter)


@datafile("sample.yml")
class Timestamp:
    my_datetime: datetime = None

which can be constructed like so:

timestamp = Timestamp(datetime.now())

to save this sample.yml file:

my_datetime: 2019-01-30T23:18:30

that can be loaded as follows:

>>> timestamp = Timestamp()
>>> timestamp.my_datetime
datetime.datetime(2019, 1, 30, 23, 18, 30)