owlmixin — owlmixin documentation

# 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

    class OwlMixin(DictTransformer, JsonTransformer, YamlTransformer, metaclass=OwlMeta):
        @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

        @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
            )

        @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
                ]
            )

        @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
            )

        @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
            )

        @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
            )

        @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()
                }
            )

        @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
            )

        @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,
            )

        @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,
            )

        @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,
            )

        @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,
            )

        @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,
            )

        @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,
            )

        @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,
            )

        @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,
            )

        @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,
            )

        @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,
            )

        @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,
            )

        @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,
            )

        @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,
            )

        @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,
            )

        @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,
            )