ethereum_types.frozen

Dataclass extension that supports immutability.

SlottedFreezable

A Protocol implemented by data classes annotated with @slotted_freezable.

21
@mypyc_attr(native_class=False)
22
@runtime_checkable
class SlottedFreezable:

_frozen

32
    _frozen: bool

_MUTATE_MESSAGE

35
_MUTATE_MESSAGE = "Mutating frozen dataclasses is not allowed."

_setattr_function

def _setattr_function(self: Any, ​​attr: str, ​​value: Any) -> None:
39
    if getattr(self, "_frozen", None):
40
        raise AttributeError(_MUTATE_MESSAGE)
41
    else:
42
        object.__setattr__(self, attr, value)

_delattr_function

def _delattr_function(self: Any, ​​attr: str) -> None:
46
    if self._frozen:
47
        raise AttributeError(_MUTATE_MESSAGE)
48
    else:
49
        object.__delattr__(self, attr)

_S

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

_P

53
_P = ParamSpec("_P")

_make_init_function

def _make_init_function(f: Callable[Concatenate[_S, _P], None]) -> Callable[Concatenate[_S, _P], None]:
59
    @wraps(f)
60
    def init_function(self: _S, *args: _P.args, **kwargs: _P.kwargs) -> None:
61
        will_be_frozen = kwargs.pop("_frozen", True)
62
        assert isinstance(will_be_frozen, bool)
63
        object.__setattr__(self, "_frozen", False)
64
        f(self, *args, **kwargs)
65
        self._frozen = will_be_frozen
66
67
    return cast("Callable[Concatenate[_S, _P], None]", 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:
71
    <snip>
78
    cls.__slots__ = ("_frozen", *tuple(cls.__annotations__))
79
    cls.__init__ = _make_init_function(cls.__init__)
80
    cls.__setattr__ = _setattr_function
81
    cls.__delattr__ = _delattr_function
82
    return type(cls)(cls.__name__, cls.__bases__, dict(cls.__dict__))

S

85
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:
89
    <snip>
95
    assert is_dataclass(obj)
96
    assert isinstance(obj, SlottedFreezable)
97
    new_obj = replace(obj, _frozen=False)  # type: ignore[unreachable]
98
    f(new_obj)
99
    new_obj._frozen = True
100
    return new_obj