How to use the datafiles.converters.Converter function in datafiles

To help you get started, we’ve selected a few datafiles examples, based on popular ways it is used in public projects.

Secure your code as it's written. Use Snyk Code to scan source code in minutes - no build needed - and fix issues immediately.

github jacebrowning / datafiles / datafiles / converters.py View on Github external
def as_optional(cls):
        name = 'Optional' + cls.__name__
        return type(name, (cls,), {'DEFAULT': None})

    @classmethod
    @abstractmethod
    def to_python_value(cls, deserialized_data, *, target):
        raise NotImplementedError

    @classmethod
    @abstractmethod
    def to_preserialization_data(cls, python_value, *, skip=Missing):
        raise NotImplementedError


class Boolean(Converter):
    """Converter for `bool` literals."""

    TYPE = bool
    DEFAULT = False
    _FALSY = {'false', 'f', 'no', 'n', 'disabled', 'off', '0'}

    # pylint: disable=unused-argument

    @classmethod
    def to_python_value(cls, deserialized_data, *, target=None):
        if isinstance(deserialized_data, str):
            value = deserialized_data.lower() not in cls._FALSY
        else:
            value = cls.TYPE(deserialized_data)
        return value
github jacebrowning / datafiles / datafiles / converters.py View on Github external
    @classmethod
    def to_python_value(cls, deserialized_data, *, target=None):
        value = cls.to_preserialization_data(deserialized_data).strip()
        if '\n' in value:
            value = value + '\n'
        return value

    @classmethod
    def to_preserialization_data(cls, python_value, *, skip=Missing):
        data = super().to_preserialization_data(python_value).strip()
        if '\n' in data:
            return LiteralScalarString(data + '\n')
        return data


class List(Converter):
    """Base converter for homogeneous lists of another converter."""

    CONVERTER = None

    @classmethod
    def subclass(cls, converter: type):
        name = f'{converter.__name__}List'  # type: ignore
        bases = (cls,)
        attributes = {'CONVERTER': converter}
        return type(name, bases, attributes)

    @classmethod
    def to_python_value(cls, deserialized_data, *, target):
        if target is None:
            value = []  # type: ignore
        else:
github jacebrowning / datafiles / datafiles / converters.py View on Github external
# pylint: disable=unused-argument

    @classmethod
    def to_python_value(cls, deserialized_data, *, target=None):
        value = cls.to_preserialization_data(deserialized_data)
        return value

    @classmethod
    def to_preserialization_data(cls, python_value, *, skip=Missing):
        if python_value is None:
            return cls.DEFAULT
        return cls.TYPE(python_value)


class Integer(Converter):
    """Converter for `int` literals."""

    TYPE = int
    DEFAULT = 0

    # pylint: disable=unused-argument

    @classmethod
    def to_python_value(cls, deserialized_data, *, target=None):
        value = cls.to_preserialization_data(deserialized_data)
        return value

    @classmethod
    def to_preserialization_data(cls, python_value, *, skip=Missing):
        if python_value is None:
            return cls.DEFAULT
github jacebrowning / datafiles / datafiles / mappers.py View on Github external
for item in value:
                                if not isinstance(item, item_cls):
                                    log.warn(f'{name!r} list type cannot be inferred')
                                    item_cls = Converter
                                    break
                        else:
                            log.warn(f'{name!r} list type cannot be inferred')
                            item_cls = Converter

                        log.debug(f'Inferring {name!r} type: {cls} of {item_cls}')
                        self.attrs[name] = map_type(cls, name=name, item_cls=item_cls)
                    elif issubclass(cls, dict):
                        cls.__origin__ = dict

                        log.debug(f'Inferring {name!r} type: {cls}')
                        self.attrs[name] = map_type(cls, name=name, item_cls=Converter)
                    else:
                        log.debug(f'Inferring {name!r} type: {cls}')
                        self.attrs[name] = map_type(cls, name=name)

            for name, converter in self.attrs.items():
                log.debug(f"Converting '{name}' data with {converter}")

                if getattr(converter, 'DATACLASS', None):
                    self._set_dataclass_value(data, name, converter)
                else:
                    self._set_attribute_value(data, name, converter, _first)

            hooks.apply(self._instance, self)

        self.modified = False
github jacebrowning / datafiles / datafiles / converters.py View on Github external
    @classmethod
    def to_python_value(cls, deserialized_data, *, target=None):
        if isinstance(deserialized_data, str):
            value = deserialized_data.lower() not in cls._FALSY
        else:
            value = cls.TYPE(deserialized_data)
        return value

    @classmethod
    def to_preserialization_data(cls, python_value, *, skip=Missing):
        if python_value is None:
            return cls.DEFAULT
        return cls.TYPE(python_value)


class Float(Converter):
    """Converter for `float` literals."""

    TYPE = float
    DEFAULT = 0.0

    # pylint: disable=unused-argument

    @classmethod
    def to_python_value(cls, deserialized_data, *, target=None):
        value = cls.to_preserialization_data(deserialized_data)
        return value

    @classmethod
    def to_preserialization_data(cls, python_value, *, skip=Missing):
        if python_value is None:
            return cls.DEFAULT
github jacebrowning / datafiles / datafiles / converters.py View on Github external
value.clear()
            value.update(data)

        return value

    @classmethod
    def to_preserialization_data(cls, python_value, *, skip=Missing):
        data = dict(python_value)

        if data == skip:
            data.clear()

        return data


class Object(Converter):
    """Base converter for dataclasses."""

    DATACLASS = None
    CONVERTERS = None

    @classmethod
    def subclass(cls, dataclass, converters: Dict[str, type]):
        name = f'{dataclass.__name__}Converter'
        bases = (cls,)
        attributes = {'DATACLASS': dataclass, 'CONVERTERS': converters}
        return type(name, bases, attributes)

    @classmethod
    def to_python_value(cls, deserialized_data, *, target):
        if isinstance(deserialized_data, dict):
            data = deserialized_data.copy()
github jacebrowning / datafiles / datafiles / converters.py View on Github external
converter = Dictionary.subclass(key, value)

        elif cls.__origin__ == Union:
            converter = map_type(cls.__args__[0])
            assert len(cls.__args__) == 2
            assert cls.__args__[1] == type(None)
            converter = converter.as_optional()

        if converter:
            log.debug(f'Mapped {cls!r} to new converter: {converter}')
            return converter

        raise TypeError(f'Unsupported container type: {cls.__origin__}')

    else:
        for converter in Converter.__subclasses__():
            if converter.TYPE == cls:
                log.debug(f'Mapped {cls!r} to existing converter: {converter}')
                return converter

    if not isclass(cls):
        raise TypeError(f'Annotation is not a type: {cls!r}')

    if issubclass(cls, Converter):
        log.debug(f'Mapped {cls!r} to existing converter (itself)')
        return cls

    raise TypeError(f'Could not map type: {cls}')
github jacebrowning / datafiles / datafiles / config.py View on Github external
"""Configuration defaults for each model."""

from __future__ import annotations

from contextlib import suppress
from dataclasses import dataclass
from typing import TYPE_CHECKING, Dict, Optional


if TYPE_CHECKING:
    from .converters import Converter


@dataclass
class Meta:
    datafile_attrs: Optional[Dict[str, Converter]] = None
    datafile_pattern: Optional[str] = None

    datafile_manual: bool = False
    datafile_defaults: bool = False
    datafile_auto_load: bool = True
    datafile_auto_save: bool = True
    datafile_auto_attr: bool = False


def load(obj) -> Meta:
    meta = Meta()

    with suppress(AttributeError):
        meta.datafile_attrs = obj.Meta.datafile_attrs
    with suppress(AttributeError):
        meta.datafile_pattern = obj.Meta.datafile_pattern
github jacebrowning / datafiles / datafiles / converters.py View on Github external
class Number(Float):
    """Converter for integers or floats."""

    DEFAULT = 0

    # pylint: disable=unused-argument

    @classmethod
    def to_preserialization_data(cls, python_value, *, skip=Missing):
        data = super().to_preserialization_data(python_value)
        if int(data) == data:
            return int(data)
        return data


class String(Converter):
    """Converter for `str` literals."""

    TYPE = str
    DEFAULT = ""

    # pylint: disable=unused-argument

    @classmethod
    def to_python_value(cls, deserialized_data, *, target=None):
        value = cls.to_preserialization_data(deserialized_data)
        return value

    @classmethod
    def to_preserialization_data(cls, python_value, *, skip=Missing):
        if python_value is None:
            return cls.DEFAULT