From 8c6ddd5233d51bc8937dc6a7e84d8b95f381fc80 Mon Sep 17 00:00:00 2001 From: protolambda Date: Tue, 18 Jun 2019 02:18:00 +0200 Subject: [PATCH] container field coercion --- test_libs/pyspec/eth2spec/utils/ssz/ssz_typing.py | 12 +++++++++++- .../pyspec/eth2spec/utils/ssz/test_ssz_typing.py | 14 ++++++++++++++ 2 files changed, 25 insertions(+), 1 deletion(-) diff --git a/test_libs/pyspec/eth2spec/utils/ssz/ssz_typing.py b/test_libs/pyspec/eth2spec/utils/ssz/ssz_typing.py index efcb8f207..942095622 100644 --- a/test_libs/pyspec/eth2spec/utils/ssz/ssz_typing.py +++ b/test_libs/pyspec/eth2spec/utils/ssz/ssz_typing.py @@ -1,4 +1,4 @@ -from typing import Tuple, Dict, Iterator +from typing import Tuple, Iterator from types import GeneratorType @@ -142,6 +142,16 @@ class Container(Series, metaclass=SSZType): from .ssz_impl import signing_root return signing_root(self) + def __setattr__(self, name, value): + if name not in self.__class__.__annotations__: + raise AttributeError("Cannot change non-existing SSZ-container attribute") + field_typ = self.__class__.__annotations__[name] + value = coerce_type_maybe(value, field_typ) + if not isinstance(value, field_typ): + raise ValueCheckError(f"Cannot set field of {self.__class__}:" + f" field: {name} type: {field_typ} value: {value} value type: {type(value)}") + super().__setattr__(name, value) + def get_field_values(self) -> Tuple[SSZValue, ...]: cls = self.__class__ return tuple(getattr(self, field) for field in cls.get_field_names()) diff --git a/test_libs/pyspec/eth2spec/utils/ssz/test_ssz_typing.py b/test_libs/pyspec/eth2spec/utils/ssz/test_ssz_typing.py index 99416e333..291c4b955 100644 --- a/test_libs/pyspec/eth2spec/utils/ssz/test_ssz_typing.py +++ b/test_libs/pyspec/eth2spec/utils/ssz/test_ssz_typing.py @@ -105,6 +105,20 @@ def test_container(): assert v.type().elem_type == uint8 assert v.type().length == 1024 + y.a = 42 + y.a = uint16(255) + try: + y.a = uint16(256) + assert False + except ValueError: + pass + + try: + y.not_here = 5 + assert False + except AttributeError: + pass + def test_list(): typ = List[uint64, 128]