Source code for dataclass_wizard.environ.loaders

from datetime import datetime, date, timezone
from typing import (
    Type, Dict, List, Tuple, Iterable, Sequence,
    Union, AnyStr, Optional, Callable,
)

from ..abstractions import AbstractParser
from ..bases import META
from ..decorators import _single_arg_alias
from ..loaders import LoadMixin, load_func_for_dataclass
from ..type_def import (
    FrozenKeys, DefFactory, M, N, U, DD, LSQ, NT, T, JSONObject
)
from ..utils.type_conv import (
    as_datetime, as_date, as_list, as_dict
)


[docs] class EnvLoader(LoadMixin): """ This Mixin class derives its name from the eponymous `json.loads` function. Essentially it contains helper methods to convert JSON strings (or a Python dictionary object) to a `dataclass` which can often contain complex types such as lists, dicts, or even other dataclasses nested within it. Refer to the :class:`AbstractLoader` class for documentation on any of the implemented methods. """ __slots__ = () def __init_subclass__(cls, **kwargs): super().__init_subclass__() cls.register_load_hook(bytes, cls.load_to_bytes) cls.register_load_hook(bytearray, cls.load_to_byte_array)
[docs] @staticmethod def load_to_bytes( o: AnyStr, base_type: Type[bytes], encoding='utf-8') -> bytes: return base_type(o, encoding)
[docs] @staticmethod def load_to_byte_array( o: AnyStr, base_type: Type[bytearray], encoding='utf-8') -> bytearray: return base_type(o, encoding) if isinstance(o, str) else base_type(o)
[docs] @staticmethod @_single_arg_alias('base_type') def load_to_uuid(o: Union[AnyStr, U], base_type: Type[U]) -> U: # alias: base_type(o) ...
[docs] @staticmethod def load_to_iterable( o: Iterable, base_type: Type[LSQ], elem_parser: AbstractParser) -> LSQ: return super(EnvLoader, EnvLoader).load_to_iterable( as_list(o), base_type, elem_parser)
[docs] @staticmethod def load_to_tuple( o: Union[List, Tuple], base_type: Type[Tuple], elem_parsers: Sequence[AbstractParser]) -> Tuple: return super(EnvLoader, EnvLoader).load_to_tuple( as_list(o), base_type, elem_parsers)
[docs] @staticmethod def load_to_named_tuple( o: Union[Dict, List, Tuple], base_type: Type[NT], field_to_parser: 'FieldToParser', field_parsers: List[AbstractParser]) -> NT: # TODO check for both list and dict return super(EnvLoader, EnvLoader).load_to_named_tuple( as_list(o), base_type, field_to_parser, field_parsers)
[docs] @staticmethod def load_to_named_tuple_untyped( o: Union[Dict, List, Tuple], base_type: Type[NT], dict_parser: AbstractParser, list_parser: AbstractParser) -> NT: return super(EnvLoader, EnvLoader).load_to_named_tuple_untyped( as_list(o), base_type, dict_parser, list_parser)
[docs] @staticmethod def load_to_dict( o: Dict, base_type: Type[M], key_parser: AbstractParser, val_parser: AbstractParser) -> M: return super(EnvLoader, EnvLoader).load_to_dict( as_dict(o), base_type, key_parser, val_parser)
[docs] @staticmethod def load_to_defaultdict( o: Dict, base_type: Type[DD], default_factory: DefFactory, key_parser: AbstractParser, val_parser: AbstractParser) -> DD: return super(EnvLoader, EnvLoader).load_to_defaultdict( as_dict(o), base_type, default_factory, key_parser, val_parser)
[docs] @staticmethod def load_to_typed_dict( o: Dict, base_type: Type[M], key_to_parser: 'FieldToParser', required_keys: FrozenKeys, optional_keys: FrozenKeys) -> M: return super(EnvLoader, EnvLoader).load_to_typed_dict( as_dict(o), base_type, key_to_parser, required_keys, optional_keys)
[docs] @staticmethod def load_to_datetime( o: Union[str, N], base_type: Type[datetime]) -> datetime: if isinstance(o, str): # Check if it's a string in numeric format, like '1.23' if o.replace('.', '', 1).isdigit(): return base_type.fromtimestamp(float(o), tz=timezone.utc) return base_type.fromisoformat(o.replace('Z', '+00:00', 1)) # default: as_datetime return as_datetime(o, base_type)
[docs] @staticmethod def load_to_date(o: Union[str, N], base_type: Type[date]) -> date: if isinstance(o, str): # Check if it's a string in numeric format, like '1.23' if o.replace('.', '', 1).isdigit(): return base_type.fromtimestamp(float(o)) return base_type.fromisoformat(o) # default: as_date return as_date(o, base_type)
[docs] @staticmethod def load_func_for_dataclass( cls: Type[T], config: Optional[META], is_main_class: bool = False, ) -> Callable[['str | JSONObject | T', Type[T]], T]: load = load_func_for_dataclass( cls, is_main_class=False, config=config, # override the loader class loader_cls=EnvLoader, ) def load_to_dataclass(o: 'str | JSONObject | T', *_) -> T: """ Receives either a string or a `dict` as an input, and return a dataclass instance of type `cls`. """ if type(o) is cls: return o return load(as_dict(o)) return load_to_dataclass