ethereum_types.frozen

Dataclass extension that supports immutability.

SlottedFreezable

A Protocol implemented by data classes annotated with @slotted_freezable.

18
@runtime_checkable
class SlottedFreezable:

_frozen

28
    _frozen: bool

_setattr_function

def _setattr_function(self: Any, ​​attr: str, ​​value: Any) -> None:
32
    if getattr(self, "_frozen", None):
33
        raise AttributeError("Mutating frozen dataclasses is not allowed.")
34
    else:
35
        object.__setattr__(self, attr, value)

_delattr_function

def _delattr_function(self: Any, ​​attr: str) -> None:
39
    if self._frozen:
40
        raise AttributeError("Mutating frozen dataclasses is not allowed.")
41
    else:
42
        object.__delattr__(self, attr)

_S

45
_S = TypeVar("_S", bound=SlottedFreezable)

_P

46
_P = ParamSpec("_P")

_make_init_function

def _make_init_function(f: Callable[Concatenate[_S, _P], None]) -> Callable[Concatenate[_S, _P], None]:
53
    def init_function(self: _S, *args: _P.args, **kwargs: _P.kwargs) -> None:
54
        will_be_frozen = kwargs.pop("_frozen", True)
55
        assert isinstance(will_be_frozen, bool)
56
        object.__setattr__(self, "_frozen", False)
57
        f(self, *args, **kwargs)
58
        self._frozen = will_be_frozen
59
60
    return init_function

slotted_freezable

Monkey patches a dataclass so it can be frozen by setting _frozen to True and uses __slots__ for efficiency.

Instances will be created frozen by default unless you pass _frozen=False to __init__.

def slotted_freezable(cls: Any) -> Any:
64
    """
65
    Monkey patches a dataclass so it can be frozen by setting `_frozen` to
66
    `True` and uses `__slots__` for efficiency.
67
68
    Instances will be created frozen by default unless you pass `_frozen=False`
69
    to `__init__`.
70
    """
71
    cls.__slots__ = ("_frozen",) + tuple(cls.__annotations__)
72
    cls.__init__ = _make_init_function(cls.__init__)
73
    cls.__setattr__ = _setattr_function
74
    cls.__delattr__ = _delattr_function
75
    return type(cls)(cls.__name__, cls.__bases__, dict(cls.__dict__))

S

78
S = TypeVar("S")

modify

Create a copy of obj (which must be @slotted_freezable), and modify it by applying f. The returned copy will be frozen.

def modify(obj: S, ​​f: Callable[[S], None]) -> S:
82
    """
83
    Create a copy of `obj` (which must be [`@slotted_freezable`]), and modify
84
    it by applying `f`. The returned copy will be frozen.
85
86
    [`@slotted_freezable`]: ref:ethereum_types.frozen.slotted_freezable
87
    """
88
    assert is_dataclass(obj)
89
    assert isinstance(obj, SlottedFreezable)
90
    new_obj = replace(obj, _frozen=False)  # type: ignore[unreachable]
91
    f(new_obj)
92
    new_obj._frozen = True
93
    return new_obj