Source code for owlmixin

# coding: utf-8
# pylint: disable=too-many-lines

import inspect
import sys
from typing import Any, Iterable, List, Optional, Sequence, TypeVar

from owlmixin import util
from owlmixin.errors import InvalidTypeError, RequiredError, UnknownPropertiesError
from owlmixin.owlcollections import TDict, TIterator, TList

# Avoid for breaking changes (import will be not working...)
from owlmixin.owlenum import (
    OwlEnum,
    OwlObjectEnum,
)
from owlmixin.transformers import (
    DictTransformer,
    JsonTransformer,
    TOption,
    ValueTransformer,
    YamlTransformer,
    traverse_dict,  # Avoid for breaking changes (import will be not working...)
)

T = TypeVar("T", bound="OwlMixin")


def _is_generic(type_):
    return hasattr(type_, "__origin__")


def assert_extra(cls_properties, arg_dict, cls):
    extra_keys: set = set(arg_dict.keys()) - {n for n, t in cls_properties}
    if extra_keys:
        raise UnknownPropertiesError(cls=cls, props=sorted(extra_keys))


def assert_none(value, type_, cls, name):
    if value is None:
        raise RequiredError(cls=cls, prop=name, type_=type_)


def assert_types(value, types: tuple, cls, name):
    if not isinstance(value, types):
        raise InvalidTypeError(
            cls=cls, prop=name, value=value, expected=types, actual=type(value)
        )


def traverse(
    type_, name, value, cls, force_snake_case: bool, force_cast: bool, restrict: bool
) -> Any:
    # pylint: disable=too-many-return-statements,too-many-branches,too-many-arguments
    if isinstance(type_, str):
        type_ = sys.modules[cls.__module__].__dict__.get(type_)
    if hasattr(type_, "__forward_arg__"):
        # `_ForwardRef` (3.6) or `ForwardRef` (>= 3.7) includes __forward_arg__
        # PEP 563 -- Postponed Evaluation of Annotations
        type_ = sys.modules[cls.__module__].__dict__.get(type_.__forward_arg__)

    if not _is_generic(type_):
        assert_none(value, type_, cls, name)
        if type_ is any:
            return value
        if type_ is Any:
            return value
        if isinstance(value, type_):
            return value
        if issubclass(type_, OwlMixin):
            assert_types(value, (type_, dict), cls, name)
            return type_.from_dict(
                value,
                force_snake_case=force_snake_case,
                force_cast=force_cast,
                restrict=restrict,
            )
        if issubclass(type_, ValueTransformer):
            return type_.from_value(value)
        if force_cast:
            return type_(value)

        assert_types(value, (type_,), cls, name)
        return value

    o_type = type_.__origin__
    g_type = type_.__args__

    if o_type == TList:
        assert_none(value, type_, cls, name)
        assert_types(value, (list,), cls, name)
        return TList(
            [
                traverse(
                    g_type[0],
                    f"{name}.{i}",
                    v,
                    cls,
                    force_snake_case,
                    force_cast,
                    restrict,
                )
                for i, v in enumerate(value)
            ]
        )
    if o_type == TIterator:
        assert_none(value, type_, cls, name)
        assert_types(value, (Iterable,), cls, name)
        return TIterator(
            traverse(
                g_type[0], f"{name}.{i}", v, cls, force_snake_case, force_cast, restrict
            )
            for i, v in enumerate(value)
        )
    if o_type == TDict:
        assert_none(value, type_, cls, name)
        assert_types(value, (dict,), cls, name)
        return TDict(
            {
                k: traverse(
                    g_type[0],
                    f"{name}.{k}",
                    v,
                    cls,
                    force_snake_case,
                    force_cast,
                    restrict,
                )
                for k, v in value.items()
            }
        )
    if o_type == TOption:
        v = value.get() if isinstance(value, TOption) else value
        # TODO: Fot `from_csvf`... need to more simple!!
        if (isinstance(v, str) and v) or (not isinstance(v, str) and v is not None):
            return TOption(
                traverse(
                    g_type[0], name, v, cls, force_snake_case, force_cast, restrict
                )
            )
        return TOption(None)

    raise RuntimeError(f"This generics is not supported `{o_type}`")


class OwlMeta(type):
    def __new__(cls, name, bases, class_dict):
        ret_cls = type.__new__(cls, name, bases, class_dict)
        ret_cls.__methods_dict__ = dict(inspect.getmembers(ret_cls, inspect.ismethod))
        return ret_cls


[docs]class OwlMixin(DictTransformer, JsonTransformer, YamlTransformer, metaclass=OwlMeta):
[docs] @classmethod def from_dict( cls, d: dict, *, force_snake_case: bool = True, force_cast: bool = False, restrict: bool = True, ) -> T: """From dict to instance :param d: Dict :param force_snake_case: Keys are transformed to snake case in order to compliant PEP8 if True :param force_cast: Cast forcibly if True :param restrict: Prohibit extra parameters if True :return: Instance Usage: >>> from owlmixin.samples import Human, Food, Japanese >>> human: Human = Human.from_dict({ ... "id": 1, ... "name": "Tom", ... "favorites": [ ... {"name": "Apple", "names_by_lang": {"en": "Apple", "de": "Apfel"}}, ... {"name": "Orange"} ... ] ... }) >>> human.id 1 >>> human.name 'Tom' >>> human.favorites[0].name 'Apple' >>> human.favorites[0].names_by_lang.get()["de"] 'Apfel' You can use default value >>> taro: Japanese = Japanese.from_dict({ ... "name": 'taro' ... }) # doctest: +NORMALIZE_WHITESPACE >>> taro.name 'taro' >>> taro.language 'japanese' If you don't set `force_snake=False` explicitly, keys are transformed to snake case as following. >>> human: Human = Human.from_dict({ ... "--id": 1, ... "<name>": "Tom", ... "favorites": [ ... {"name": "Apple", "namesByLang": {"en": "Apple"}} ... ] ... }) >>> human.id 1 >>> human.name 'Tom' >>> human.favorites[0].names_by_lang.get()["en"] 'Apple' You can allow extra parameters (like ``hogehoge``) if you set `restrict=False`. >>> apple: Food = Food.from_dict({ ... "name": "Apple", ... "hogehoge": "ooooooooooooooooooooo", ... }, restrict=False) >>> apple.to_dict() {'name': 'Apple'} You can prohibit extra parameters (like ``hogehoge``) if you set `restrict=True` (which is default). >>> human = Human.from_dict({ ... "id": 1, ... "name": "Tom", ... "hogehoge1": "ooooooooooooooooooooo", ... "hogehoge2": ["aaaaaaaaaaaaaaaaaa", "iiiiiiiiiiiiiiiii"], ... "favorites": [ ... {"name": "Apple", "namesByLang": {"en": "Apple", "de": "Apfel"}}, ... {"name": "Orange"} ... ] ... }) # doctest: +NORMALIZE_WHITESPACE Traceback (most recent call last): ... owlmixin.errors.UnknownPropertiesError: . ∧,,_∧ ,___________________ ⊂ ( ・ω・ )つ- < Unknown properties error /// /::/ `------------------- |::|/⊂ヽノ|::|」 / ̄ ̄旦 ̄ ̄ ̄/| ______/ | | |------ー----ー|/ <BLANKLINE> `owlmixin.samples.Human` has unknown properties ['hogehoge1', 'hogehoge2']!! <BLANKLINE> * If you want to allow unknown properties, set `restrict=False` * If you want to disallow unknown properties, add `hogehoge1` and `hogehoge2` to owlmixin.samples.Human <BLANKLINE> If you specify wrong type... >>> human: Human = Human.from_dict({ ... "id": 1, ... "name": "ichiro", ... "favorites": ["apple", "orange"] ... }) # doctest: +NORMALIZE_WHITESPACE Traceback (most recent call last): ... owlmixin.errors.InvalidTypeError: . ∧,,_∧ ,___________________ ⊂ ( ・ω・ )つ- < Invalid Type error /// /::/ `------------------- |::|/⊂ヽノ|::|」 / ̄ ̄旦 ̄ ̄ ̄/| ______/ | | |------ー----ー|/ <BLANKLINE> `owlmixin.samples.Human#favorites.0 = apple` doesn't match expected types. Expected type is one of ["<class 'owlmixin.samples.Food'>", "<class 'dict'>"], but actual type is `<class 'str'>` <BLANKLINE> * If you want to force cast, set `force_cast=True` * If you don't want to force cast, specify value which has correct type <BLANKLINE> If you don't specify required params... (ex. name >>> human: Human = Human.from_dict({ ... "id": 1 ... }) # doctest: +NORMALIZE_WHITESPACE Traceback (most recent call last): ... owlmixin.errors.RequiredError: . ∧,,_∧ ,___________________ ⊂ ( ・ω・ )つ- < Required error /// /::/ `------------------- |::|/⊂ヽノ|::|」 / ̄ ̄旦 ̄ ̄ ̄/| ______/ | | |------ー----ー|/ <BLANKLINE> `owlmixin.samples.Human#name: <class 'str'>` is empty!! <BLANKLINE> * If `name` is certainly required, specify anything. * If `name` is optional, change type from `<class 'str'>` to `TOption[<class 'str'>]` <BLANKLINE> """ if isinstance(d, cls): return d instance: T = cls() # type: ignore d = util.replace_keys(d, {"self": "_self"}, force_snake_case) properties = cls.__annotations__.items() if restrict: assert_extra(properties, d, cls) for n, t in properties: f = cls.__methods_dict__.get(f"_{cls.__name__}___{n}") # type: ignore arg_v = f(d.get(n)) if f else d.get(n) def_v = getattr(instance, n, None) setattr( instance, n, traverse( type_=t, name=n, value=def_v if arg_v is None else arg_v, cls=cls, force_snake_case=force_snake_case, force_cast=force_cast, restrict=restrict, ), ) return instance
[docs] @classmethod def from_optional_dict( cls, d: Optional[dict], *, force_snake_case: bool = True, force_cast: bool = False, restrict: bool = True, ) -> TOption[T]: """From dict to optional instance. :param d: Dict :param force_snake_case: Keys are transformed to snake case in order to compliant PEP8 if True :param force_cast: Cast forcibly if True :param restrict: Prohibit extra parameters if True :return: Instance Usage: >>> from owlmixin.samples import Human >>> Human.from_optional_dict(None).is_none() True >>> Human.from_optional_dict({}).get() # doctest: +NORMALIZE_WHITESPACE Traceback (most recent call last): ... owlmixin.errors.RequiredError: . ∧,,_∧ ,___________________ ⊂ ( ・ω・ )つ- < Required error /// /::/ `------------------- |::|/⊂ヽノ|::|」 / ̄ ̄旦 ̄ ̄ ̄/| ______/ | | |------ー----ー|/ <BLANKLINE> `owlmixin.samples.Human#id: <class 'int'>` is empty!! <BLANKLINE> * If `id` is certainly required, specify anything. * If `id` is optional, change type from `<class 'int'>` to `TOption[<class 'int'>]` <BLANKLINE> """ return TOption( cls.from_dict( d, force_snake_case=force_snake_case, force_cast=force_cast, restrict=restrict, ) if d is not None else None )
[docs] @classmethod def from_dicts( cls, ds: List[dict], *, force_snake_case: bool = True, force_cast: bool = False, restrict: bool = True, ) -> TList[T]: """From list of dict to list of instance :param ds: List of dict :param force_snake_case: Keys are transformed to snake case in order to compliant PEP8 if True :param force_cast: Cast forcibly if True :param restrict: Prohibit extra parameters if True :return: List of instance Usage: >>> from owlmixin.samples import Human >>> humans: TList[Human] = Human.from_dicts([ ... {"id": 1, "name": "Tom", "favorites": [{"name": "Apple"}]}, ... {"id": 2, "name": "John", "favorites": [{"name": "Orange"}]} ... ]) >>> humans[0].name 'Tom' >>> humans[1].name 'John' """ return TList( [ cls.from_dict( d, force_snake_case=force_snake_case, force_cast=force_cast, restrict=restrict, ) for d in ds ] )
[docs] @classmethod def from_iterable_dicts( cls, ds: Iterable[dict], *, force_snake_case: bool = True, force_cast: bool = False, restrict: bool = True, ) -> TIterator[T]: """From iterable dict to iterable instance :param ds: Iterable dict :param force_snake_case: Keys are transformed to snake case in order to compliant PEP8 if True :param force_cast: Cast forcibly if True :param restrict: Prohibit extra parameters if True :return: Iterator Usage: >>> from owlmixin.samples import Human >>> humans: TIterator[Human] = Human.from_iterable_dicts([ ... {"id": 1, "name": "Tom", "favorites": [{"name": "Apple"}]}, ... {"id": 2, "name": "John", "favorites": [{"name": "Orange"}]} ... ]) >>> humans.next_at(0).get().name 'Tom' >>> humans.next_at(0).get().name 'John' """ return TIterator( cls.from_dict( d, force_snake_case=force_snake_case, force_cast=force_cast, restrict=restrict, ) for d in ds )
[docs] @classmethod def from_optional_dicts( cls, ds: Optional[List[dict]], *, force_snake_case: bool = True, force_cast: bool = False, restrict: bool = True, ) -> TOption[TList[T]]: """From list of dict to optional list of instance. :param ds: List of dict :param force_snake_case: Keys are transformed to snake case in order to compliant PEP8 if True :param force_cast: Cast forcibly if True :param restrict: Prohibit extra parameters if True :return: List of instance Usage: >>> from owlmixin.samples import Human >>> Human.from_optional_dicts(None).is_none() True >>> Human.from_optional_dicts([]).get() [] """ return TOption( cls.from_dicts( ds, force_snake_case=force_snake_case, force_cast=force_cast, restrict=restrict, ) if ds is not None else None )
[docs] @classmethod def from_optional_iterable_dicts( cls, ds: Optional[Iterable[dict]], *, force_snake_case: bool = True, force_cast: bool = False, restrict: bool = True, ) -> TOption[TIterator[T]]: """From iterable dict to optional iterable instance. :param ds: Iterable dict :param force_snake_case: Keys are transformed to snake case in order to compliant PEP8 if True :param force_cast: Cast forcibly if True :param restrict: Prohibit extra parameters if True :return: Iterable instance Usage: >>> from owlmixin.samples import Human >>> Human.from_optional_dicts(None).is_none() True >>> Human.from_optional_dicts([]).get() [] """ return TOption( cls.from_iterable_dicts( ds, force_snake_case=force_snake_case, force_cast=force_cast, restrict=restrict, ) if ds is not None else None )
[docs] @classmethod def from_dicts_by_key( cls, ds: dict, *, force_snake_case: bool = True, force_cast: bool = False, restrict: bool = True, ) -> TDict[T]: """From dict of dict to dict of instance :param ds: Dict of dict :param force_snake_case: Keys are transformed to snake case in order to compliant PEP8 if True :param force_cast: Cast forcibly if True :param restrict: Prohibit extra parameters if True :return: Dict of instance Usage: >>> from owlmixin.samples import Human >>> humans_by_name: TDict[Human] = Human.from_dicts_by_key({ ... 'Tom': {"id": 1, "name": "Tom", "favorites": [{"name": "Apple"}]}, ... 'John': {"id": 2, "name": "John", "favorites": [{"name": "Orange"}]} ... }) >>> humans_by_name['Tom'].name 'Tom' >>> humans_by_name['John'].name 'John' """ return TDict( { k: cls.from_dict( v, force_snake_case=force_snake_case, force_cast=force_cast, restrict=restrict, ) for k, v in ds.items() } )
[docs] @classmethod def from_optional_dicts_by_key( cls, ds: Optional[dict], *, force_snake_case=True, force_cast: bool = False, restrict: bool = True, ) -> TOption[TDict[T]]: """From dict of dict to optional dict of instance. :param ds: Dict of dict :param force_snake_case: Keys are transformed to snake case in order to compliant PEP8 if True :param force_cast: Cast forcibly if True :param restrict: Prohibit extra parameters if True :return: Dict of instance Usage: >>> from owlmixin.samples import Human >>> Human.from_optional_dicts_by_key(None).is_none() True >>> Human.from_optional_dicts_by_key({}).get() {} """ return TOption( cls.from_dicts_by_key( ds, force_snake_case=force_snake_case, force_cast=force_cast, restrict=restrict, ) if ds is not None else None )
[docs] @classmethod def from_json( cls, data: str, *, force_snake_case=True, force_cast: bool = False, restrict: bool = False, ) -> T: """From json string to instance :param data: Json string :param force_snake_case: Keys are transformed to snake case in order to compliant PEP8 if True :param force_cast: Cast forcibly if True :param restrict: Prohibit extra parameters if True :return: Instance Usage: >>> from owlmixin.samples import Human >>> human: Human = Human.from_json('''{ ... "id": 1, ... "name": "Tom", ... "favorites": [ ... {"name": "Apple", "names_by_lang": {"en": "Apple", "de": "Apfel"}}, ... {"name": "Orange"} ... ] ... }''') >>> human.id 1 >>> human.name 'Tom' >>> human.favorites[0].names_by_lang.get()["de"] 'Apfel' """ return cls.from_dict( util.load_json(data), force_snake_case=force_snake_case, force_cast=force_cast, restrict=restrict, )
[docs] @classmethod def from_jsonf( cls, fpath: str, encoding: str = "utf8", *, force_snake_case=True, force_cast: bool = False, restrict: bool = False, ) -> T: """From json file path to instance :param fpath: Json file path :param encoding: Json file encoding :param force_snake_case: Keys are transformed to snake case in order to compliant PEP8 if True :param force_cast: Cast forcibly if True :param restrict: Prohibit extra parameters if True :return: Instance """ return cls.from_dict( util.load_jsonf(fpath, encoding), force_snake_case=force_snake_case, force_cast=force_cast, restrict=restrict, )
[docs] @classmethod def from_json_to_list( cls, data: str, *, force_snake_case=True, force_cast: bool = False, restrict: bool = False, ) -> TList[T]: """From json string to list of instance :param data: Json string :param force_snake_case: Keys are transformed to snake case in order to compliant PEP8 if True :param force_cast: Cast forcibly if True :param restrict: Prohibit extra parameters if True :return: List of instance Usage: >>> from owlmixin.samples import Human >>> humans: TList[Human] = Human.from_json_to_list('''[ ... {"id": 1, "name": "Tom", "favorites": [{"name": "Apple"}]}, ... {"id": 2, "name": "John", "favorites": [{"name": "Orange"}]} ... ]''') >>> humans[0].name 'Tom' >>> humans[1].name 'John' """ return cls.from_dicts( util.load_json(data), force_snake_case=force_snake_case, force_cast=force_cast, restrict=restrict, )
[docs] @classmethod def from_json_to_iterator( cls, data: str, *, force_snake_case=True, force_cast: bool = False, restrict: bool = False, ) -> TIterator[T]: """From json string to iterable instance :param data: Json string :param force_snake_case: Keys are transformed to snake case in order to compliant PEP8 if True :param force_cast: Cast forcibly if True :param restrict: Prohibit extra parameters if True :return: Iterable instance Usage: >>> from owlmixin.samples import Human >>> humans: TIterator[Human] = Human.from_json_to_iterator('''[ ... {"id": 1, "name": "Tom", "favorites": [{"name": "Apple"}]}, ... {"id": 2, "name": "John", "favorites": [{"name": "Orange"}]} ... ]''') >>> humans.next_at(1).get().name 'John' >>> humans.next_at(0).is_none() True """ return cls.from_iterable_dicts( util.load_json(data), force_snake_case=force_snake_case, force_cast=force_cast, restrict=restrict, )
[docs] @classmethod def from_jsonf_to_list( cls, fpath: str, encoding: str = "utf8", *, force_snake_case=True, force_cast: bool = False, restrict: bool = False, ) -> TList[T]: """From json file path to list of instance :param fpath: Json file path :param encoding: Json file encoding :param force_snake_case: Keys are transformed to snake case in order to compliant PEP8 if True :param force_cast: Cast forcibly if True :param restrict: Prohibit extra parameters if True :return: List of instance """ return cls.from_dicts( util.load_jsonf(fpath, encoding), force_snake_case=force_snake_case, force_cast=force_cast, restrict=restrict, )
[docs] @classmethod def from_jsonf_to_iterator( cls, fpath: str, encoding: str = "utf8", *, force_snake_case=True, force_cast: bool = False, restrict: bool = False, ) -> TIterator[T]: """From json file path to iterable instance :param fpath: Json file path :param encoding: Json file encoding :param force_snake_case: Keys are transformed to snake case in order to compliant PEP8 if True :param force_cast: Cast forcibly if True :param restrict: Prohibit extra parameters if True :return: Iterable instance """ return cls.from_iterable_dicts( util.load_jsonf(fpath, encoding), force_snake_case=force_snake_case, force_cast=force_cast, restrict=restrict, )
[docs] @classmethod def from_yaml( cls, data: str, *, force_snake_case=True, force_cast: bool = False, restrict: bool = True, ) -> T: """From yaml string to instance :param data: Yaml string :param force_snake_case: Keys are transformed to snake case in order to compliant PEP8 if True :param force_cast: Cast forcibly if True :param restrict: Prohibit extra parameters if True :return: Instance Usage: >>> from owlmixin.samples import Human >>> human: Human = Human.from_yaml(''' ... id: 1 ... name: Tom ... favorites: ... - name: Apple ... names_by_lang: ... en: Apple ... de: Apfel ... - name: Orange ... ''') >>> human.id 1 >>> human.name 'Tom' >>> human.favorites[0].names_by_lang.get()["de"] 'Apfel' """ return cls.from_dict( util.load_yaml(data), force_snake_case=force_snake_case, force_cast=force_cast, restrict=restrict, )
[docs] @classmethod def from_yamlf( cls, fpath: str, encoding: str = "utf8", *, force_snake_case=True, force_cast: bool = False, restrict: bool = True, ) -> T: """From yaml file path to instance :param fpath: Yaml file path :param encoding: Yaml file encoding :param force_snake_case: Keys are transformed to snake case in order to compliant PEP8 if True :param force_cast: Cast forcibly if True :param restrict: Prohibit extra parameters if True :return: Instance """ return cls.from_dict( util.load_yamlf(fpath, encoding), force_snake_case=force_snake_case, force_cast=force_cast, restrict=restrict, )
[docs] @classmethod def from_yaml_to_list( cls, data: str, *, force_snake_case=True, force_cast: bool = False, restrict: bool = True, ) -> TList[T]: """From yaml string to list of instance :param data: Yaml string :param force_snake_case: Keys are transformed to snake case in order to compliant PEP8 if True :param force_cast: Cast forcibly if True :param restrict: Prohibit extra parameters if True :return: List of instance Usage: >>> from owlmixin.samples import Human >>> humans: TList[Human] = Human.from_yaml_to_list(''' ... - id: 1 ... name: Tom ... favorites: ... - name: Apple ... - id: 2 ... name: John ... favorites: ... - name: Orange ... ''') >>> humans[0].name 'Tom' >>> humans[1].name 'John' >>> humans[0].favorites[0].name 'Apple' """ return cls.from_dicts( util.load_yaml(data), force_snake_case=force_snake_case, force_cast=force_cast, restrict=restrict, )
[docs] @classmethod def from_yaml_to_iterator( cls, data: str, *, force_snake_case=True, force_cast: bool = False, restrict: bool = True, ) -> TIterator[T]: """From yaml string to iterable instance :param data: Yaml string :param force_snake_case: Keys are transformed to snake case in order to compliant PEP8 if True :param force_cast: Cast forcibly if True :param restrict: Prohibit extra parameters if True :return: Iterable instance Usage: >>> from owlmixin.samples import Human >>> humans: TIterator[Human] = Human.from_yaml_to_iterator(''' ... - id: 1 ... name: Tom ... favorites: ... - name: Apple ... - id: 2 ... name: John ... favorites: ... - name: Orange ... ''') >>> human1 = humans.next_at(1).get() >>> human1.name 'John' >>> humans.next_at(0).is_none() True >>> human1.favorites[0].name 'Orange' """ return cls.from_iterable_dicts( util.load_yaml(data), force_snake_case=force_snake_case, force_cast=force_cast, restrict=restrict, )
[docs] @classmethod def from_yamlf_to_list( cls, fpath: str, encoding: str = "utf8", *, force_snake_case=True, force_cast: bool = False, restrict: bool = True, ) -> TList[T]: """From yaml file path to list of instance :param fpath: Yaml file path :param encoding: Yaml file encoding :param force_snake_case: Keys are transformed to snake case in order to compliant PEP8 if True :param force_cast: Cast forcibly if True :param restrict: Prohibit extra parameters if True :return: List of instance """ return cls.from_dicts( util.load_yamlf(fpath, encoding), force_snake_case=force_snake_case, force_cast=force_cast, restrict=restrict, )
[docs] @classmethod def from_yamlf_to_iterator( cls, fpath: str, encoding: str = "utf8", *, force_snake_case=True, force_cast: bool = False, restrict: bool = True, ) -> TIterator[T]: """From yaml file path to iterable instance :param fpath: Yaml file path :param encoding: Yaml file encoding :param force_snake_case: Keys are transformed to snake case in order to compliant PEP8 if True :param force_cast: Cast forcibly if True :param restrict: Prohibit extra parameters if True :return: Iterable instance """ return cls.from_iterable_dicts( util.load_yamlf(fpath, encoding), force_snake_case=force_snake_case, force_cast=force_cast, restrict=restrict, )
[docs] @classmethod def from_csvf_to_list( cls, fpath: str, fieldnames: Optional[Sequence[str]] = None, encoding: str = "utf8", *, force_snake_case: bool = True, restrict: bool = True, ) -> TList[T]: """From csv file path to list of instance :param fpath: Csv file path :param fieldnames: Specify csv header names if not included in the file :param encoding: Csv file encoding :param force_snake_case: Keys are transformed to snake case in order to compliant PEP8 if True :param restrict: Prohibit extra parameters if True :return: List of Instance """ return cls.from_dicts( list(util.load_csvf(fpath, fieldnames, encoding)), force_snake_case=force_snake_case, force_cast=True, restrict=restrict, )
[docs] @classmethod def from_csvf_to_iterator( cls, fpath: str, fieldnames: Optional[Sequence[str]] = None, encoding: str = "utf8", *, force_snake_case: bool = True, restrict: bool = True, ) -> TIterator[T]: """From csv file path to iterable instance :param fpath: Csv file path :param fieldnames: Specify csv header names if not included in the file :param encoding: Csv file encoding :param force_snake_case: Keys are transformed to snake case in order to compliant PEP8 if True :param restrict: Prohibit extra parameters if True :return: Iterable Instance """ return cls.from_iterable_dicts( util.load_csvf(fpath, fieldnames, encoding), force_snake_case=force_snake_case, force_cast=True, restrict=restrict, )
[docs] @classmethod def from_json_url( cls, url: str, *, force_snake_case=True, force_cast: bool = False, restrict: bool = False, ) -> T: """From url which returns json to instance :param url: Url which returns json :param force_snake_case: Keys are transformed to snake case in order to compliant PEP8 if True :param force_cast: Cast forcibly if True :param restrict: Prohibit extra parameters if True :return: Instance """ return cls.from_dict( util.load_json_url(url), force_snake_case=force_snake_case, force_cast=force_cast, restrict=restrict, )