Skip to content

SOURCE CODE diot.utils DOCS

"""Utilities for diot"""
from typing import TYPE_CHECKING, Any, Iterable


if TYPE_CHECKING:
    from .diot import Diot


class DiotFrozenError(Exception):DOCS
    """When try to modify a frozen diot"""


def nest(DOCS
    value: Any,
    types: Iterable[type],
    dest_type: type,
    frozen: bool,
) -> Any:
    """Convert values with certain types recursively"""
    # nothing to convert
    if not types or not isinstance(value, tuple(types)):  # type: ignore
        return value

    if (list in types and isinstance(value, list)) or (  # type: ignore
        tuple in types and isinstance(value, tuple)  # type: ignore
    ):
        # use value.__class__ to keep user-subclassed list or tuple
        out = [nest(val, types, dest_type, frozen) for val in value]
        try:
            return value.__class__(out)
        except Exception:  # pragma: no cover
            return out

    if dict in types and isinstance(value, dict):  # type: ignore
        if issubclass(value.__class__, dest_type):
            return value

        return dest_type(
            [
                (key, nest(val, types, dest_type, frozen))
                for key, val in value.items()
            ]
        )
    return value


def to_dict(value: "Diot") -> dict:DOCS
    """Convert converted Diot objects back to dict"""
    if isinstance(value, dict):
        return {key: to_dict(val) for key, val in value.items()}
    if isinstance(value, tuple):
        return tuple((to_dict(val) for val in value))
    if isinstance(value, list):
        return [to_dict(val) for val in value]
    return value