Skip to content

Module omnipy.modules.general.typedefs

Overview

View Source
from collections import UserDict

from types import MappingProxyType

from typing import Generic, Sequence, TypeVar

_KeyT = TypeVar('_KeyT')

_ValT = TypeVar('_ValT')

# Unfortunately, MappingProxyType is declared as a final class, which means it cannot be subclassed.

# Inheriting from UserDict is a workaround.

class FrozenDict(UserDict[_KeyT, _ValT], Generic[_KeyT, _ValT]):

    """

    FrozenDict works exactly like a dict except that it cannot be modified after initialisation:

        >>> from omnipy import FrozenDict, print_exception

        >>> from types import MappingProxyType

        >>>

        >>> my_dict = FrozenDict({'temperature': 'chilly'})

        >>> my_dict

        mappingproxy({'temperature': 'chilly'})

        >>> my_dict['temperature']

        'chilly'

        >>> with print_exception:

        ...     my_dict['temperature'] = 'scorching'

        TypeError: 'mappingproxy' object does not support item assignment

    In contrast to types.MappingProxyType, FrozenDict can be initialized without parameters:

        >>> with print_exception:

        ...     MappingProxyType()

        TypeError: mappingproxy() missing required argument 'mapping' (pos 1)

        >>> FrozenDict()

        mappingproxy({})

    Typically, this would be a rather useless thing to do, as the resulting object would be an empty

    dictionary that cannot be changed. With Omnipy it actually makes sense, though, as the Model

    class calls the type argument without parameters to determine the default value of the model.

    Note:

        Mutable objects within a FrozenDict are still mutable:

        >>> my_dict = FrozenDict({'temp_map': {'cold': 'chilly', 'hot': 'scorching'}})

        >>> my_dict['temp_map']['hot'] = 'blazing'

        >>> my_dict

        mappingproxy({'temp_map': {'cold': 'chilly', 'hot': 'blazing'}})

        To implement a fully immutable nested data structure, one would need a mechanism that makes

        sure only immutable types are allowed within a FrozenDict (or a tuple, which is the

        immutable list counterpart). Luckily, Omnipy provides just that guarantee with

        NestedFrozenDictsModel, NestedTuplesModel and NestedFrozenCollectionsModel.

    """

    def __init__(self,

                 unfrozen_dict: dict[_KeyT, _ValT] | Sequence[tuple[_KeyT, _ValT]] | None = None,

                 /,

                 **kwargs):

        super().__init__(unfrozen_dict, **kwargs)

        self.data: MappingProxyType[_KeyT, _ValT] = MappingProxyType(self.data)  # type: ignore

Classes

FrozenDict

class FrozenDict(
    unfrozen_dict: Union[dict[~_KeyT, ~_ValT], Sequence[tuple[~_KeyT, ~_ValT]], NoneType] = None,
    /,
    **kwargs
)

FrozenDict works exactly like a dict except that it cannot be modified after initialisation:

from omnipy import FrozenDict, print_exception >>> from types import MappingProxyType >>> >>> my_dict = FrozenDict({'temperature': 'chilly'}) >>> my_dict mappingproxy({'temperature': 'chilly'}) >>> my_dict['temperature'] 'chilly' >>> with print_exception: ... my_dict['temperature'] = 'scorching' TypeError: 'mappingproxy' object does not support item assignment

In contrast to types.MappingProxyType, FrozenDict can be initialized without parameters:

>>> with print_exception:
...     MappingProxyType()
TypeError: mappingproxy() missing required argument 'mapping' (pos 1)
>>> FrozenDict()
mappingproxy({})

Typically, this would be a rather useless thing to do, as the resulting object would be an empty dictionary that cannot be changed. With Omnipy it actually makes sense, though, as the Model class calls the type argument without parameters to determine the default value of the model.

Note: Mutable objects within a FrozenDict are still mutable:

>>> my_dict = FrozenDict({'temp_map': {'cold': 'chilly', 'hot': 'scorching'}})
>>> my_dict['temp_map']['hot'] = 'blazing'
>>> my_dict
mappingproxy({'temp_map': {'cold': 'chilly', 'hot': 'blazing'}})

To implement a fully immutable nested data structure, one would need a mechanism that makes
sure only immutable types are allowed within a FrozenDict (or a tuple, which is the
immutable list counterpart). Luckily, Omnipy provides just that guarantee with
NestedFrozenDictsModel, NestedTuplesModel and NestedFrozenCollectionsModel.
View Source
class FrozenDict(UserDict[_KeyT, _ValT], Generic[_KeyT, _ValT]):

    """

    FrozenDict works exactly like a dict except that it cannot be modified after initialisation:

        >>> from omnipy import FrozenDict, print_exception

        >>> from types import MappingProxyType

        >>>

        >>> my_dict = FrozenDict({'temperature': 'chilly'})

        >>> my_dict

        mappingproxy({'temperature': 'chilly'})

        >>> my_dict['temperature']

        'chilly'

        >>> with print_exception:

        ...     my_dict['temperature'] = 'scorching'

        TypeError: 'mappingproxy' object does not support item assignment

    In contrast to types.MappingProxyType, FrozenDict can be initialized without parameters:

        >>> with print_exception:

        ...     MappingProxyType()

        TypeError: mappingproxy() missing required argument 'mapping' (pos 1)

        >>> FrozenDict()

        mappingproxy({})

    Typically, this would be a rather useless thing to do, as the resulting object would be an empty

    dictionary that cannot be changed. With Omnipy it actually makes sense, though, as the Model

    class calls the type argument without parameters to determine the default value of the model.

    Note:

        Mutable objects within a FrozenDict are still mutable:

        >>> my_dict = FrozenDict({'temp_map': {'cold': 'chilly', 'hot': 'scorching'}})

        >>> my_dict['temp_map']['hot'] = 'blazing'

        >>> my_dict

        mappingproxy({'temp_map': {'cold': 'chilly', 'hot': 'blazing'}})

        To implement a fully immutable nested data structure, one would need a mechanism that makes

        sure only immutable types are allowed within a FrozenDict (or a tuple, which is the

        immutable list counterpart). Luckily, Omnipy provides just that guarantee with

        NestedFrozenDictsModel, NestedTuplesModel and NestedFrozenCollectionsModel.

    """

    def __init__(self,

                 unfrozen_dict: dict[_KeyT, _ValT] | Sequence[tuple[_KeyT, _ValT]] | None = None,

                 /,

                 **kwargs):

        super().__init__(unfrozen_dict, **kwargs)

        self.data: MappingProxyType[_KeyT, _ValT] = MappingProxyType(self.data)  # type: ignore