Skip to content

Ethereum Test Base Types package

Common definitions and types.

Address

Bases: FixedSizeBytes[20]

Class that helps represent Ethereum addresses in tests.

Source code in packages/testing/src/execution_testing/base_types/base_types.py
class Address(FixedSizeBytes[20]):  # type: ignore
    """Class that helps represent Ethereum addresses in tests."""

    label: str | None = None

    def __new__(
        cls,
        input_bytes: "FixedSizeBytesConvertible | Address",
        *args: Any,
        label: str | None = None,
        **kwargs: Any,
    ) -> Self:
        """Create a new Address object with an optional label."""
        instance = super(Address, cls).__new__(
            cls, input_bytes, *args, **kwargs
        )
        if isinstance(input_bytes, Address) and label is None:
            instance.label = input_bytes.label
        else:
            instance.label = label
        return instance

__new__(input_bytes, *args, label=None, **kwargs)

Create a new Address object with an optional label.

Source code in packages/testing/src/execution_testing/base_types/base_types.py
def __new__(
    cls,
    input_bytes: "FixedSizeBytesConvertible | Address",
    *args: Any,
    label: str | None = None,
    **kwargs: Any,
) -> Self:
    """Create a new Address object with an optional label."""
    instance = super(Address, cls).__new__(
        cls, input_bytes, *args, **kwargs
    )
    if isinstance(input_bytes, Address) and label is None:
        instance.label = input_bytes.label
    else:
        instance.label = label
    return instance

Bloom

Bases: FixedSizeBytes[256]

Class that helps represent blooms in tests.

Source code in packages/testing/src/execution_testing/base_types/base_types.py
class Bloom(FixedSizeBytes[256]):  # type: ignore
    """Class that helps represent blooms in tests."""

    pass

BLSPublicKey

Bases: FixedSizeBytes[48]

Class that helps represent BLS public keys in tests.

Source code in packages/testing/src/execution_testing/base_types/base_types.py
class BLSPublicKey(FixedSizeBytes[48]):  # type: ignore
    """Class that helps represent BLS public keys in tests."""

    pass

BLSSignature

Bases: FixedSizeBytes[96]

Class that helps represent BLS signatures in tests.

Source code in packages/testing/src/execution_testing/base_types/base_types.py
class BLSSignature(FixedSizeBytes[96]):  # type: ignore
    """Class that helps represent BLS signatures in tests."""

    pass

Bytes

Bases: bytes, ToStringSchema

Class that helps represent bytes of variable length in tests.

Source code in packages/testing/src/execution_testing/base_types/base_types.py
class Bytes(bytes, ToStringSchema):
    """Class that helps represent bytes of variable length in tests."""

    def __new__(cls, input_bytes: BytesConvertible = b"") -> Self:
        """Create a new Bytes object."""
        if type(input_bytes) is cls:
            return input_bytes
        return super(Bytes, cls).__new__(cls, to_bytes(input_bytes))

    __hash__ = bytes.__hash__

    def __str__(self) -> str:
        """Return the hexadecimal representation of the bytes."""
        return self.hex()

    def hex(self, *args: Any, **kwargs: Any) -> str:
        """Return the hexadecimal representation of the bytes."""
        return "0x" + super().hex(*args, **kwargs)

    def keccak256(self) -> "Hash":
        """Return the keccak256 hash of the opcode byte representation."""
        # Imported lazily so that merely importing the test framework does not
        # import the `ethereum` package: on xdist workers that import would
        # happen before pytest-cov starts the worker's coverage session,
        # making coverage report `ethereum` as "module-not-measured".
        from ethereum.crypto.hash import keccak256 as _keccak256

        return Hash(_keccak256(self))

    def sha256(self) -> "Hash":
        """Return the sha256 hash of the opcode byte representation."""
        return Hash(sha256(self).digest())

    @staticmethod
    def __get_pydantic_core_schema__(
        source_type: Any, handler: GetCoreSchemaHandler
    ) -> PlainValidatorFunctionSchema:
        """
        Call the class constructor without info and appends the serialization
        schema.
        """
        return no_info_plain_validator_function(
            source_type,
            serialization=to_string_ser_schema(),
            json_schema_input_schema=handler(
                Annotated[
                    str, StringConstraints(pattern=r"^0x([0-9a-fA-F]{2})*$")
                ]
            ),
        )

__new__(input_bytes=b'')

Create a new Bytes object.

Source code in packages/testing/src/execution_testing/base_types/base_types.py
def __new__(cls, input_bytes: BytesConvertible = b"") -> Self:
    """Create a new Bytes object."""
    if type(input_bytes) is cls:
        return input_bytes
    return super(Bytes, cls).__new__(cls, to_bytes(input_bytes))

__str__()

Return the hexadecimal representation of the bytes.

Source code in packages/testing/src/execution_testing/base_types/base_types.py
def __str__(self) -> str:
    """Return the hexadecimal representation of the bytes."""
    return self.hex()

hex(*args, **kwargs)

Return the hexadecimal representation of the bytes.

Source code in packages/testing/src/execution_testing/base_types/base_types.py
def hex(self, *args: Any, **kwargs: Any) -> str:
    """Return the hexadecimal representation of the bytes."""
    return "0x" + super().hex(*args, **kwargs)

keccak256()

Return the keccak256 hash of the opcode byte representation.

Source code in packages/testing/src/execution_testing/base_types/base_types.py
def keccak256(self) -> "Hash":
    """Return the keccak256 hash of the opcode byte representation."""
    # Imported lazily so that merely importing the test framework does not
    # import the `ethereum` package: on xdist workers that import would
    # happen before pytest-cov starts the worker's coverage session,
    # making coverage report `ethereum` as "module-not-measured".
    from ethereum.crypto.hash import keccak256 as _keccak256

    return Hash(_keccak256(self))

sha256()

Return the sha256 hash of the opcode byte representation.

Source code in packages/testing/src/execution_testing/base_types/base_types.py
def sha256(self) -> "Hash":
    """Return the sha256 hash of the opcode byte representation."""
    return Hash(sha256(self).digest())

__get_pydantic_core_schema__(source_type, handler) staticmethod

Call the class constructor without info and appends the serialization schema.

Source code in packages/testing/src/execution_testing/base_types/base_types.py
@staticmethod
def __get_pydantic_core_schema__(
    source_type: Any, handler: GetCoreSchemaHandler
) -> PlainValidatorFunctionSchema:
    """
    Call the class constructor without info and appends the serialization
    schema.
    """
    return no_info_plain_validator_function(
        source_type,
        serialization=to_string_ser_schema(),
        json_schema_input_schema=handler(
            Annotated[
                str, StringConstraints(pattern=r"^0x([0-9a-fA-F]{2})*$")
            ]
        ),
    )

BytesConcatenation

Bases: SupportsBytes, Sized

A class that can be concatenated with bytes.

Source code in packages/testing/src/execution_testing/base_types/base_types.py
class BytesConcatenation(SupportsBytes, Sized, metaclass=ABCMeta):
    """A class that can be concatenated with bytes."""

    def __len__(self) -> int:
        """Return length of the object when converted to bytes."""
        return len(bytes(self))

    def __add__(self, other: bytes | SupportsBytes) -> bytes:
        """Concatenates the object with another bytes object."""
        return bytes(self) + bytes(other)

    def __radd__(self, other: bytes | SupportsBytes) -> bytes:
        """Concatenates the object with another bytes object."""
        return bytes(other) + bytes(self)

__len__()

Return length of the object when converted to bytes.

Source code in packages/testing/src/execution_testing/base_types/base_types.py
def __len__(self) -> int:
    """Return length of the object when converted to bytes."""
    return len(bytes(self))

__add__(other)

Concatenates the object with another bytes object.

Source code in packages/testing/src/execution_testing/base_types/base_types.py
def __add__(self, other: bytes | SupportsBytes) -> bytes:
    """Concatenates the object with another bytes object."""
    return bytes(self) + bytes(other)

__radd__(other)

Concatenates the object with another bytes object.

Source code in packages/testing/src/execution_testing/base_types/base_types.py
def __radd__(self, other: bytes | SupportsBytes) -> bytes:
    """Concatenates the object with another bytes object."""
    return bytes(other) + bytes(self)

CoerceBytes

Bases: Bytes

Class that helps represent bytes of variable length in tests and supports removing white spaces anywhere in the string.

Source code in packages/testing/src/execution_testing/base_types/base_types.py
class CoerceBytes(Bytes):
    """
    Class that helps represent bytes of variable length in tests and
    supports removing white spaces anywhere in the string.
    """

    def __new__(cls, input_bytes: BytesConvertible = b"") -> Self:
        """Create a new CoerceBytes object."""
        if type(input_bytes) is cls:
            return input_bytes
        if isinstance(input_bytes, str):
            input_bytes = sub(r"\s+", "", input_bytes)
        return super(Bytes, cls).__new__(cls, to_bytes(input_bytes))

__new__(input_bytes=b'')

Create a new CoerceBytes object.

Source code in packages/testing/src/execution_testing/base_types/base_types.py
def __new__(cls, input_bytes: BytesConvertible = b"") -> Self:
    """Create a new CoerceBytes object."""
    if type(input_bytes) is cls:
        return input_bytes
    if isinstance(input_bytes, str):
        input_bytes = sub(r"\s+", "", input_bytes)
    return super(Bytes, cls).__new__(cls, to_bytes(input_bytes))

FixedSizeBytes

Bases: Bytes

Class that helps represent bytes of fixed length in tests.

Source code in packages/testing/src/execution_testing/base_types/base_types.py
class FixedSizeBytes(Bytes):
    """Class that helps represent bytes of fixed length in tests."""

    byte_length: ClassVar[int]
    _sized_: ClassVar[Type["FixedSizeBytes"]]

    def __class_getitem__(cls, length: int) -> Type["FixedSizeBytes"]:
        """Create a new FixedSizeBytes class with the given length."""

        class Sized(cls):  # type: ignore
            byte_length = length

        Sized._sized_ = Sized
        return Sized

    def __new__(
        cls,
        input_bytes: FixedSizeBytesConvertible | Self,
        *,
        left_padding: bool = False,
        right_padding: bool = False,
    ) -> Self:
        """Create a new FixedSizeBytes object."""
        if type(input_bytes) is cls:
            return input_bytes
        return super(FixedSizeBytes, cls).__new__(
            cls,
            to_fixed_size_bytes(
                input_bytes,
                cls.byte_length,
                left_padding=left_padding,
                right_padding=right_padding,
            ),
        )

    # Defining `__eq__` drops the inherited hash, so restore the C one.
    __hash__ = bytes.__hash__

    def __eq__(self, other: object) -> bool:
        """Compare two FixedSizeBytes objects to be equal."""
        if other is None:
            return False
        if not isinstance(other, FixedSizeBytes):
            if not (
                isinstance(other, str)
                or isinstance(other, int)
                or isinstance(other, bytes)
                or isinstance(other, SupportsBytes)
            ):
                return False
            other = self._sized_(other)
        return super().__eq__(other)

    def __ne__(self, other: object) -> bool:
        """Compare two FixedSizeBytes objects to be not equal."""
        return not self.__eq__(other)

    @classmethod
    def __get_pydantic_core_schema__(
        cls, source_type: Any, handler: GetCoreSchemaHandler
    ) -> PlainValidatorFunctionSchema:
        """
        Call the class constructor without info and appends the serialization
        schema.
        """
        pattern = f"^0x([0-9a-fA-F]{{{cls.byte_length * 2}}})*$"
        return no_info_plain_validator_function(
            source_type,
            serialization=to_string_ser_schema(),
            json_schema_input_schema=handler(
                Annotated[str, StringConstraints(pattern=pattern)]
            ),
        )

__class_getitem__(length)

Create a new FixedSizeBytes class with the given length.

Source code in packages/testing/src/execution_testing/base_types/base_types.py
def __class_getitem__(cls, length: int) -> Type["FixedSizeBytes"]:
    """Create a new FixedSizeBytes class with the given length."""

    class Sized(cls):  # type: ignore
        byte_length = length

    Sized._sized_ = Sized
    return Sized

__new__(input_bytes, *, left_padding=False, right_padding=False)

Create a new FixedSizeBytes object.

Source code in packages/testing/src/execution_testing/base_types/base_types.py
def __new__(
    cls,
    input_bytes: FixedSizeBytesConvertible | Self,
    *,
    left_padding: bool = False,
    right_padding: bool = False,
) -> Self:
    """Create a new FixedSizeBytes object."""
    if type(input_bytes) is cls:
        return input_bytes
    return super(FixedSizeBytes, cls).__new__(
        cls,
        to_fixed_size_bytes(
            input_bytes,
            cls.byte_length,
            left_padding=left_padding,
            right_padding=right_padding,
        ),
    )

__eq__(other)

Compare two FixedSizeBytes objects to be equal.

Source code in packages/testing/src/execution_testing/base_types/base_types.py
def __eq__(self, other: object) -> bool:
    """Compare two FixedSizeBytes objects to be equal."""
    if other is None:
        return False
    if not isinstance(other, FixedSizeBytes):
        if not (
            isinstance(other, str)
            or isinstance(other, int)
            or isinstance(other, bytes)
            or isinstance(other, SupportsBytes)
        ):
            return False
        other = self._sized_(other)
    return super().__eq__(other)

__ne__(other)

Compare two FixedSizeBytes objects to be not equal.

Source code in packages/testing/src/execution_testing/base_types/base_types.py
def __ne__(self, other: object) -> bool:
    """Compare two FixedSizeBytes objects to be not equal."""
    return not self.__eq__(other)

__get_pydantic_core_schema__(source_type, handler) classmethod

Call the class constructor without info and appends the serialization schema.

Source code in packages/testing/src/execution_testing/base_types/base_types.py
@classmethod
def __get_pydantic_core_schema__(
    cls, source_type: Any, handler: GetCoreSchemaHandler
) -> PlainValidatorFunctionSchema:
    """
    Call the class constructor without info and appends the serialization
    schema.
    """
    pattern = f"^0x([0-9a-fA-F]{{{cls.byte_length * 2}}})*$"
    return no_info_plain_validator_function(
        source_type,
        serialization=to_string_ser_schema(),
        json_schema_input_schema=handler(
            Annotated[str, StringConstraints(pattern=pattern)]
        ),
    )

ForkHash

Bases: FixedSizeBytes[4]

Class that helps represent the CRC config hashes and identifiers of a fork.

Source code in packages/testing/src/execution_testing/base_types/base_types.py
class ForkHash(FixedSizeBytes[4]):  # type: ignore
    """
    Class that helps represent the CRC config hashes and identifiers of a fork.
    """

    pass

Hash

Bases: FixedSizeBytes[32]

Class that helps represent hashes in tests.

Source code in packages/testing/src/execution_testing/base_types/base_types.py
class Hash(FixedSizeBytes[32]):  # type: ignore
    """Class that helps represent hashes in tests."""

    pass

HashInt

Bases: FixedSizeHexNumber[32]

Class that helps represent hashes in tests.

Source code in packages/testing/src/execution_testing/base_types/base_types.py
class HashInt(FixedSizeHexNumber[32]):  # type: ignore
    """Class that helps represent hashes in tests."""

    pass

HeaderNonce

Bases: FixedSizeBytes[8]

Class that helps represent the header nonce in tests.

Source code in packages/testing/src/execution_testing/base_types/base_types.py
class HeaderNonce(FixedSizeBytes[8]):  # type: ignore
    """Class that helps represent the header nonce in tests."""

    pass

HexNumber

Bases: Number

Class that helps represent hexadecimal numbers in tests.

Source code in packages/testing/src/execution_testing/base_types/base_types.py
class HexNumber(Number):
    """Class that helps represent hexadecimal numbers in tests."""

    def __str__(self) -> str:
        """Return the string representation of the number."""
        return self.hex()

    @staticmethod
    def __get_pydantic_core_schema__(
        source_type: Any, handler: GetCoreSchemaHandler
    ) -> PlainValidatorFunctionSchema:
        """
        Call the class constructor without info and appends the serialization
        schema.
        """
        return no_info_plain_validator_function(
            source_type,
            serialization=to_string_ser_schema(),
            json_schema_input_schema=handler(
                Annotated[str, StringConstraints(pattern=r"^0x[0-9a-fA-F]*$")]
            ),
        )

__str__()

Return the string representation of the number.

Source code in packages/testing/src/execution_testing/base_types/base_types.py
def __str__(self) -> str:
    """Return the string representation of the number."""
    return self.hex()

__get_pydantic_core_schema__(source_type, handler) staticmethod

Call the class constructor without info and appends the serialization schema.

Source code in packages/testing/src/execution_testing/base_types/base_types.py
@staticmethod
def __get_pydantic_core_schema__(
    source_type: Any, handler: GetCoreSchemaHandler
) -> PlainValidatorFunctionSchema:
    """
    Call the class constructor without info and appends the serialization
    schema.
    """
    return no_info_plain_validator_function(
        source_type,
        serialization=to_string_ser_schema(),
        json_schema_input_schema=handler(
            Annotated[str, StringConstraints(pattern=r"^0x[0-9a-fA-F]*$")]
        ),
    )

Number

Bases: int, ToStringSchema

Class that helps represent numbers in tests.

Source code in packages/testing/src/execution_testing/base_types/base_types.py
class Number(int, ToStringSchema):
    """Class that helps represent numbers in tests."""

    def __new__(cls, input_number: NumberConvertible | Self) -> Self:
        """Create a new Number object."""
        return super(Number, cls).__new__(cls, to_number(input_number))

    def __str__(self) -> str:
        """Return the string representation of the number."""
        return str(int(self))

    def hex(self) -> str:
        """Return the hexadecimal representation of the number."""
        return hex(self)

__new__(input_number)

Create a new Number object.

Source code in packages/testing/src/execution_testing/base_types/base_types.py
def __new__(cls, input_number: NumberConvertible | Self) -> Self:
    """Create a new Number object."""
    return super(Number, cls).__new__(cls, to_number(input_number))

__str__()

Return the string representation of the number.

Source code in packages/testing/src/execution_testing/base_types/base_types.py
def __str__(self) -> str:
    """Return the string representation of the number."""
    return str(int(self))

hex()

Return the hexadecimal representation of the number.

Source code in packages/testing/src/execution_testing/base_types/base_types.py
def hex(self) -> str:
    """Return the hexadecimal representation of the number."""
    return hex(self)

StorageKey

Bases: FixedSizeBytes[32]

Storage key type that automatically applies left padding for values shorter than 32 bytes.

Source code in packages/testing/src/execution_testing/base_types/base_types.py
class StorageKey(FixedSizeBytes[32]):  # type: ignore
    """
    Storage key type that automatically applies left padding for values shorter
    than 32 bytes.
    """

    def __new__(
        cls,
        input_bytes: FixedSizeBytesConvertible | FixedSizeBytes,
        **kwargs: Any,
    ) -> Self:
        """Create a new StorageKey with automatic left padding."""
        # Always apply left_padding for storage keys unless explicitly set to
        # False
        if "left_padding" not in kwargs:
            kwargs["left_padding"] = True
        return super().__new__(cls, input_bytes, **kwargs)

__new__(input_bytes, **kwargs)

Create a new StorageKey with automatic left padding.

Source code in packages/testing/src/execution_testing/base_types/base_types.py
def __new__(
    cls,
    input_bytes: FixedSizeBytesConvertible | FixedSizeBytes,
    **kwargs: Any,
) -> Self:
    """Create a new StorageKey with automatic left padding."""
    # Always apply left_padding for storage keys unless explicitly set to
    # False
    if "left_padding" not in kwargs:
        kwargs["left_padding"] = True
    return super().__new__(cls, input_bytes, **kwargs)

Wei

Bases: Number

Class that helps represent wei that can be parsed from strings.

Source code in packages/testing/src/execution_testing/base_types/base_types.py
class Wei(Number):
    """Class that helps represent wei that can be parsed from strings."""

    def __new__(cls, input_number: NumberConvertible | Self) -> Self:
        """Create a new Number object."""
        if isinstance(input_number, str):
            words = input_number.split()
            multiplier = 1
            assert len(words) <= 2
            value_str = words[0]
            if len(words) > 1:
                unit = words[1].lower()
                multiplier = cls._get_multiplier(unit)
            value: float
            if "**" in value_str:
                base, exp = value_str.split("**")
                value = float(base) ** int(exp)
            else:
                value = (
                    int(value_str)
                    if value_str.isdecimal()
                    else float(value_str)
                )
            return super(Number, cls).__new__(cls, value * multiplier)
        return super(Number, cls).__new__(cls, to_number(input_number))

    @staticmethod
    def _get_multiplier(unit: str) -> int:
        """
        Return the multiplier for the given unit of wei, handling synonyms.
        """
        match unit:
            case "wei":
                return 1
            case "kwei" | "babbage" | "femtoether":
                return 10**3
            case "mwei" | "lovelace" | "picoether":
                return 10**6
            case "gwei" | "shannon" | "nanoether" | "nano":
                return 10**9
            case "szabo" | "microether" | "micro":
                return 10**12
            case "finney" | "milliether" | "milli":
                return 10**15
            case "ether" | "eth":
                return 10**18
            case _:
                raise ValueError(f"Invalid unit {unit}")

__new__(input_number)

Create a new Number object.

Source code in packages/testing/src/execution_testing/base_types/base_types.py
def __new__(cls, input_number: NumberConvertible | Self) -> Self:
    """Create a new Number object."""
    if isinstance(input_number, str):
        words = input_number.split()
        multiplier = 1
        assert len(words) <= 2
        value_str = words[0]
        if len(words) > 1:
            unit = words[1].lower()
            multiplier = cls._get_multiplier(unit)
        value: float
        if "**" in value_str:
            base, exp = value_str.split("**")
            value = float(base) ** int(exp)
        else:
            value = (
                int(value_str)
                if value_str.isdecimal()
                else float(value_str)
            )
        return super(Number, cls).__new__(cls, value * multiplier)
    return super(Number, cls).__new__(cls, to_number(input_number))

ZeroPaddedHexNumber

Bases: HexNumber

Class that helps represent zero padded hexadecimal numbers in tests.

Source code in packages/testing/src/execution_testing/base_types/base_types.py
class ZeroPaddedHexNumber(HexNumber):
    """Class that helps represent zero padded hexadecimal numbers in tests."""

    def hex(self) -> str:
        """Return the hexadecimal representation of the number."""
        if self == 0:
            return "0x00"
        hex_str = hex(self)[2:]
        if len(hex_str) % 2 == 1:
            return "0x0" + hex_str
        return "0x" + hex_str

    @staticmethod
    def __get_pydantic_core_schema__(
        source_type: Any, handler: GetCoreSchemaHandler
    ) -> PlainValidatorFunctionSchema:
        """
        Call the class constructor without info and appends the serialization
        schema.
        """
        return no_info_plain_validator_function(
            source_type,
            serialization=to_string_ser_schema(),
            json_schema_input_schema=handler(
                Annotated[
                    str, StringConstraints(pattern=r"^0x([0-9a-fA-F]{2})*$")
                ]
            ),
        )

hex()

Return the hexadecimal representation of the number.

Source code in packages/testing/src/execution_testing/base_types/base_types.py
def hex(self) -> str:
    """Return the hexadecimal representation of the number."""
    if self == 0:
        return "0x00"
    hex_str = hex(self)[2:]
    if len(hex_str) % 2 == 1:
        return "0x0" + hex_str
    return "0x" + hex_str

__get_pydantic_core_schema__(source_type, handler) staticmethod

Call the class constructor without info and appends the serialization schema.

Source code in packages/testing/src/execution_testing/base_types/base_types.py
@staticmethod
def __get_pydantic_core_schema__(
    source_type: Any, handler: GetCoreSchemaHandler
) -> PlainValidatorFunctionSchema:
    """
    Call the class constructor without info and appends the serialization
    schema.
    """
    return no_info_plain_validator_function(
        source_type,
        serialization=to_string_ser_schema(),
        json_schema_input_schema=handler(
            Annotated[
                str, StringConstraints(pattern=r"^0x([0-9a-fA-F]{2})*$")
            ]
        ),
    )

to_json(input_model)

Convert a model to its json data representation.

Source code in packages/testing/src/execution_testing/base_types/base_types_json.py
def to_json(
    input_model: (
        EthereumTestBaseModel
        | EthereumTestRootModel
        | AnyStr
        | List[EthereumTestBaseModel | EthereumTestRootModel | AnyStr]
    ),
) -> Any:
    """Convert a model to its json data representation."""
    if isinstance(input_model, list):
        return [to_json(item) for item in input_model]
    elif isinstance(
        input_model, (EthereumTestBaseModel, EthereumTestRootModel)
    ):
        return input_model.model_dump(
            mode="json", by_alias=True, exclude_none=True
        )
    else:
        return str(input_model)

AccessList

Bases: CamelModel, RLPSerializable

Access List for transactions.

Source code in packages/testing/src/execution_testing/base_types/composite_types.py
class AccessList(CamelModel, RLPSerializable):
    """Access List for transactions."""

    address: Address
    storage_keys: List[Hash]

    rlp_fields: ClassVar[List[str]] = ["address", "storage_keys"]

Account

Bases: CamelModel

State associated with an address.

Source code in packages/testing/src/execution_testing/base_types/composite_types.py
class Account(CamelModel):
    """State associated with an address."""

    nonce: ZeroPaddedHexNumber = ZeroPaddedHexNumber(0)
    """
    The scalar value equal to a) the number of transactions sent by an
    Externally Owned Account, b) the amount of contracts created by a contract.
    """
    balance: ZeroPaddedHexNumber = ZeroPaddedHexNumber(0)
    """The amount of Wei (10<sup>-18</sup> Eth) the account has."""
    code: Bytes = Bytes(b"")
    """Bytecode contained by the account."""
    storage: Storage = Field(default_factory=Storage)
    """Storage within a contract."""

    model_config = {
        **CamelModel.model_config,
        "frozen": True,
    }

    @model_validator(mode="after")
    def _freeze_storage(self) -> Self:
        """
        Freeze the storage along with the account, so that accounts shared
        between allocations cannot change under any of them.
        """
        self.storage.freeze()
        return self

nonce = ZeroPaddedHexNumber(0) class-attribute instance-attribute

The scalar value equal to a) the number of transactions sent by an Externally Owned Account, b) the amount of contracts created by a contract.

balance = ZeroPaddedHexNumber(0) class-attribute instance-attribute

The amount of Wei (10-18 Eth) the account has.

code = Bytes(b'') class-attribute instance-attribute

Bytecode contained by the account.

storage = Field(default_factory=Storage) class-attribute instance-attribute

Storage within a contract.

Alloc

Bases: EthereumTestRootModel[Dict[Address, Account | None]]

Allocation of accounts in the state, pre and post test execution.

Source code in packages/testing/src/execution_testing/base_types/composite_types.py
class Alloc(EthereumTestRootModel[Dict[Address, Account | None]]):
    """Allocation of accounts in the state, pre and post test execution."""

    root: Dict[Address, Account | None] = Field(
        default_factory=dict, validate_default=True
    )

    def get(self, address: Address) -> Account | None:
        """Get an account if it's present in the allocation, otherwise None."""
        account = self.root.get(address)
        if not account:
            return None
        return account

get(address)

Get an account if it's present in the allocation, otherwise None.

Source code in packages/testing/src/execution_testing/base_types/composite_types.py
def get(self, address: Address) -> Account | None:
    """Get an account if it's present in the allocation, otherwise None."""
    account = self.root.get(address)
    if not account:
        return None
    return account

BlobSchedule

Bases: EthereumTestRootModel[Dict[str, ForkBlobSchedule]]

Blob schedule configuration dictionary.

Source code in packages/testing/src/execution_testing/base_types/composite_types.py
class BlobSchedule(EthereumTestRootModel[Dict[str, ForkBlobSchedule]]):
    """Blob schedule configuration dictionary."""

    root: Dict[str, ForkBlobSchedule] = Field(
        default_factory=dict, validate_default=True
    )

    def append(self, *, fork: str, schedule: Any) -> None:
        """Append a new fork schedule."""
        if not isinstance(schedule, ForkBlobSchedule):
            schedule = ForkBlobSchedule(**schedule)
        self.root[fork] = schedule

    def last(self) -> ForkBlobSchedule | None:
        """Return the last schedule."""
        if len(self.root) == 0:
            return None
        return list(self.root.values())[-1]

    def __getitem__(self, key: str) -> ForkBlobSchedule:
        """Return the schedule for a given fork."""
        return self.root[key]

append(*, fork, schedule)

Append a new fork schedule.

Source code in packages/testing/src/execution_testing/base_types/composite_types.py
def append(self, *, fork: str, schedule: Any) -> None:
    """Append a new fork schedule."""
    if not isinstance(schedule, ForkBlobSchedule):
        schedule = ForkBlobSchedule(**schedule)
    self.root[fork] = schedule

last()

Return the last schedule.

Source code in packages/testing/src/execution_testing/base_types/composite_types.py
def last(self) -> ForkBlobSchedule | None:
    """Return the last schedule."""
    if len(self.root) == 0:
        return None
    return list(self.root.values())[-1]

__getitem__(key)

Return the schedule for a given fork.

Source code in packages/testing/src/execution_testing/base_types/composite_types.py
def __getitem__(self, key: str) -> ForkBlobSchedule:
    """Return the schedule for a given fork."""
    return self.root[key]

ForkBlobSchedule

Bases: CamelModel

Representation of the blob schedule of a given fork.

Source code in packages/testing/src/execution_testing/base_types/composite_types.py
class ForkBlobSchedule(CamelModel):
    """Representation of the blob schedule of a given fork."""

    target_blobs_per_block: HexNumber = Field(..., alias="target")
    max_blobs_per_block: HexNumber = Field(..., alias="max")
    base_fee_update_fraction: HexNumber = Field(...)

StateCommitment

Bases: Enum

The state-commitment scheme used to compute an allocation's state root.

Source code in packages/testing/src/execution_testing/base_types/composite_types.py
class StateCommitment(Enum):
    """
    The state-commitment scheme used to compute an allocation's state root.
    """

    MPT = auto()
    """Merkle-Patricia trie."""

MPT = auto() class-attribute instance-attribute

Merkle-Patricia trie.

Storage

Bases: EthereumTestRootModel[Dict[StorageKeyValueType, StorageKeyValueType]]

Definition of contract storage in the pre or post state of a test.

This model accepts a dictionary with keys and values as any of: str, int, bytes, or any type that supports conversion to bytes, and automatically casts them to HashInt.

Source code in packages/testing/src/execution_testing/base_types/composite_types.py
class Storage(
    EthereumTestRootModel[Dict[StorageKeyValueType, StorageKeyValueType]]
):
    """
    Definition of contract storage in the `pre` or `post` state of a test.

    This model accepts a dictionary with keys and values as any of: str, int,
    bytes, or any type that supports conversion to bytes, and automatically
    casts them to `HashInt`.
    """

    # internal storage is maintained as a dict with HashInt keys and values.
    root: Dict[StorageKeyValueType, StorageKeyValueType] = Field(
        default_factory=dict
    )

    _current_slot: int = PrivateAttr(0)
    _hint_map: Dict[StorageKeyValueType, str] = PrivateAttr(
        default_factory=dict
    )
    _any_map: Dict[StorageKeyValueType, bool] = PrivateAttr(
        default_factory=dict
    )
    _frozen: bool = PrivateAttr(False)
    """
    Set once the storage belongs to an `Account`, which may be shared
    between allocations, so that no write can reach the others.
    """

    StorageDictType: ClassVar[TypeAlias] = Dict[
        str | int | bytes | SupportsBytes, str | int | bytes | SupportsBytes
    ]
    """
    Dictionary type to be used when defining an input to initialize a storage.
    """

    @dataclass(kw_only=True)
    class InvalidTypeError(Exception):
        """
        Invalid type used when describing test's expected storage key or value.
        """

        key_or_value: Any

        def __init__(self, key_or_value: Any, *args: Any) -> None:
            """Initialize the exception with the invalid type."""
            super().__init__(args)
            self.key_or_value = key_or_value

        def __str__(self) -> str:
            """Print exception string."""
            return f"invalid type for key/value: {self.key_or_value}"

    @dataclass(kw_only=True)
    class InvalidValueError(Exception):
        """
        Invalid value used when describing test's expected storage key or
        value.
        """

        key_or_value: Any

        def __init__(self, key_or_value: Any, *args: Any) -> None:
            """Initialize the exception with the invalid value."""
            super().__init__(args)
            self.key_or_value = key_or_value

        def __str__(self) -> str:
            """Print exception string."""
            return f"invalid value for key/value: {self.key_or_value}"

    @dataclass(kw_only=True)
    class MissingKeyError(Exception):
        """Test expected to find a storage key set but key was missing."""

        key: int

        def __init__(self, key: int, *args: Any) -> None:
            """Initialize the exception with the missing key."""
            super().__init__(args)
            self.key = key

        def __str__(self) -> str:
            """Print exception string."""
            return "key {0} not found in storage".format(Hash(self.key))

    @dataclass(kw_only=True)
    class KeyValueMismatchError(Exception):
        """
        Test expected a certain value in a storage key but value found was
        different.
        """

        address: Address
        key: int
        want: int
        got: int
        hint: str

        def __init__(
            self,
            address: Address,
            key: int,
            want: int,
            got: int,
            hint: str = "",
            *args: Any,
        ) -> None:
            """
            Initialize the exception with the address, key, wanted and got
            values.
            """
            super().__init__(args)
            self.address = address
            self.key = key
            self.want = want
            self.got = got
            self.hint = hint

        def __str__(self) -> str:
            """Print exception string."""
            label_str = ""
            if self.address.label is not None:
                label_str = f" ({self.address.label})"
            hint_str = f" ({self.hint})" if self.hint else ""
            return (
                f"incorrect value in address {self.address}{label_str} for "
                + f"key {Hash(self.key)}{hint_str}:"
                + f" want {HexNumber(self.want)} (dec:{int(self.want)}),"
                + f" got {HexNumber(self.got)} (dec:{int(self.got)})"
            )

    def __contains__(
        self, key: StorageKeyValueTypeConvertible | StorageKeyValueType
    ) -> bool:
        """Check for an item in the storage."""
        return StorageKeyValueTypeAdapter.validate_python(key) in self.root

    def __getitem__(
        self, key: StorageKeyValueTypeConvertible | StorageKeyValueType
    ) -> StorageKeyValueType:
        """Return an item from the storage."""
        return self.root[StorageKeyValueTypeAdapter.validate_python(key)]

    def freeze(self) -> "Storage":
        """Reject any further writes to the storage, and return it."""
        self._frozen = True
        return self

    def _require_mutable(self) -> None:
        """Raise if the storage is frozen."""
        if self._frozen:
            raise TypeError(
                "Storage is frozen: it belongs to an Account, which may be "
                "shared between allocations. Build the storage before "
                "creating the Account, or replace the account with "
                "`model_copy(update={'storage': ...})`."
            )

    def __setitem__(
        self,
        key: StorageKeyValueTypeConvertible | StorageKeyValueType,
        value: StorageKeyValueTypeConvertible | StorageKeyValueType,
    ) -> None:
        """Set an item in the storage."""
        self._require_mutable()
        self.root[StorageKeyValueTypeAdapter.validate_python(key)] = (
            StorageKeyValueTypeAdapter.validate_python(value)
        )

    def __delitem__(
        self, key: StorageKeyValueTypeConvertible | StorageKeyValueType
    ) -> None:
        """Delete an item from the storage."""
        self._require_mutable()
        del self.root[StorageKeyValueTypeAdapter.validate_python(key)]

    def __iter__(self) -> Iterator[StorageKeyValueType]:  # type: ignore [override]
        """Return an iterator over the storage."""
        return iter(self.root)

    def __eq__(self, other: object) -> bool:
        """Return True if both storages are equal."""
        if not isinstance(other, Storage):
            return False
        return self.root == other.root

    def __ne__(self, other: object) -> bool:
        """Return True if both storages are not equal."""
        if not isinstance(other, Storage):
            return False
        return self.root != other.root

    def __bool__(self) -> bool:
        """Return True if the storage is not empty."""
        return any(v for v in self.root.values())

    def __add__(self, other: "Storage") -> "Storage":
        """Return a new storage that is the sum of two storages."""
        return Storage({**self.root, **other.root})

    def __len__(self) -> int:
        """
        Return the number of keys that have been explicitly set in the storage.
        """
        return len(self.root)

    def keys(self) -> set[StorageKeyValueType]:
        """Return the keys of the storage."""
        return set(self.root.keys())

    def set_next_slot(self, slot: int) -> "Storage":
        """Set the next slot to be used by `store_next`."""
        self._require_mutable()
        self._current_slot = slot
        return self

    def items(self) -> ItemsView[StorageKeyValueType, StorageKeyValueType]:
        """Return the items of the storage."""
        return self.root.items()

    def set_expect_any(
        self, key: StorageKeyValueTypeConvertible | StorageKeyValueType
    ) -> None:
        """
        Mark key to be able to have any expected value when comparing storages.
        """
        self._require_mutable()
        self._any_map[StorageKeyValueTypeAdapter.validate_python(key)] = True

    def store_next(
        self,
        value: StorageKeyValueTypeConvertible | StorageKeyValueType | bool,
        hint: str = "",
    ) -> StorageKeyValueType:
        """
        Store a value in the storage and return the key where the value is
        stored.

        Increments the key counter so the next time this function is called,
        the next key is used.
        """
        self._require_mutable()
        slot = StorageKeyValueTypeAdapter.validate_python(self._current_slot)
        self._current_slot += 1
        if hint:
            self._hint_map[slot] = hint
        self[slot] = StorageKeyValueTypeAdapter.validate_python(value)
        return slot

    def peek_slot(self) -> int:
        """Peek the next slot that will be used by `store_next`."""
        return self._current_slot

    def contains(self, other: "Storage") -> bool:
        """
        Return True if self contains all keys with equal value as contained by
        second storage. Used for comparison with test expected post state and
        alloc returned by the transition tool.
        """
        for key in other.keys():
            if key not in self:
                return False
            if self[key] != other[key]:
                return False
        return True

    def must_contain(self, address: Address, other: "Storage") -> None:
        """
        Succeeds only if self contains all keys with equal value as contained
        by second storage. Used for comparison with test expected post state
        and alloc returned by the transition tool. Raises detailed exception
        when a difference is found.
        """
        for key in other.keys():
            if key not in self:
                # storage[key]==0 is equal to missing storage
                if other[key] != 0:
                    raise Storage.MissingKeyError(key=key)
            elif self[key] != other[key]:
                raise Storage.KeyValueMismatchError(
                    address=address,
                    key=key,
                    want=self[key],
                    got=other[key],
                    hint=self._hint_map.get(key, ""),
                )

    def must_be_equal(self, address: Address, other: "Storage | None") -> None:
        """Succeed only if "self" is equal to "other" storage."""
        # Test keys contained in both storage objects
        if other is None:
            other = Storage({})
        for key in self.keys() & other.keys():
            if self[key] != other[key]:
                raise Storage.KeyValueMismatchError(
                    address=address,
                    key=key,
                    want=self[key],
                    got=other[key],
                    hint=self._hint_map.get(key, ""),
                )

        # Test keys contained in either one of the storage objects
        for key in self.keys() ^ other.keys():
            if key in self:
                if self[key] != 0:
                    raise Storage.KeyValueMismatchError(
                        address=address,
                        key=key,
                        want=self[key],
                        got=0,
                        hint=self._hint_map.get(key, ""),
                    )

            elif other[key] != 0:
                # Skip key verification if we allow this key to be ANY
                if self._any_map.get(key) is True:
                    continue
                raise Storage.KeyValueMismatchError(
                    address=address,
                    key=key,
                    want=0,
                    got=other[key],
                    hint=self._hint_map.get(key, ""),
                )

    def canary(self) -> "Storage":
        """
        Return a canary storage filled with non-zero values where the current
        storage expects zero values, to guarantee that the test overwrites the
        storage.
        """
        return Storage(
            {key: HashInt(0xBA5E) for key in self.keys() if self[key] == 0}
        )

StorageDictType = Dict[str | int | bytes | SupportsBytes, str | int | bytes | SupportsBytes] class-attribute

Dictionary type to be used when defining an input to initialize a storage.

InvalidTypeError dataclass

Bases: Exception

Invalid type used when describing test's expected storage key or value.

Source code in packages/testing/src/execution_testing/base_types/composite_types.py
@dataclass(kw_only=True)
class InvalidTypeError(Exception):
    """
    Invalid type used when describing test's expected storage key or value.
    """

    key_or_value: Any

    def __init__(self, key_or_value: Any, *args: Any) -> None:
        """Initialize the exception with the invalid type."""
        super().__init__(args)
        self.key_or_value = key_or_value

    def __str__(self) -> str:
        """Print exception string."""
        return f"invalid type for key/value: {self.key_or_value}"

__init__(key_or_value, *args)

Initialize the exception with the invalid type.

Source code in packages/testing/src/execution_testing/base_types/composite_types.py
def __init__(self, key_or_value: Any, *args: Any) -> None:
    """Initialize the exception with the invalid type."""
    super().__init__(args)
    self.key_or_value = key_or_value

__str__()

Print exception string.

Source code in packages/testing/src/execution_testing/base_types/composite_types.py
def __str__(self) -> str:
    """Print exception string."""
    return f"invalid type for key/value: {self.key_or_value}"

InvalidValueError dataclass

Bases: Exception

Invalid value used when describing test's expected storage key or value.

Source code in packages/testing/src/execution_testing/base_types/composite_types.py
@dataclass(kw_only=True)
class InvalidValueError(Exception):
    """
    Invalid value used when describing test's expected storage key or
    value.
    """

    key_or_value: Any

    def __init__(self, key_or_value: Any, *args: Any) -> None:
        """Initialize the exception with the invalid value."""
        super().__init__(args)
        self.key_or_value = key_or_value

    def __str__(self) -> str:
        """Print exception string."""
        return f"invalid value for key/value: {self.key_or_value}"

__init__(key_or_value, *args)

Initialize the exception with the invalid value.

Source code in packages/testing/src/execution_testing/base_types/composite_types.py
def __init__(self, key_or_value: Any, *args: Any) -> None:
    """Initialize the exception with the invalid value."""
    super().__init__(args)
    self.key_or_value = key_or_value

__str__()

Print exception string.

Source code in packages/testing/src/execution_testing/base_types/composite_types.py
def __str__(self) -> str:
    """Print exception string."""
    return f"invalid value for key/value: {self.key_or_value}"

MissingKeyError dataclass

Bases: Exception

Test expected to find a storage key set but key was missing.

Source code in packages/testing/src/execution_testing/base_types/composite_types.py
@dataclass(kw_only=True)
class MissingKeyError(Exception):
    """Test expected to find a storage key set but key was missing."""

    key: int

    def __init__(self, key: int, *args: Any) -> None:
        """Initialize the exception with the missing key."""
        super().__init__(args)
        self.key = key

    def __str__(self) -> str:
        """Print exception string."""
        return "key {0} not found in storage".format(Hash(self.key))

__init__(key, *args)

Initialize the exception with the missing key.

Source code in packages/testing/src/execution_testing/base_types/composite_types.py
def __init__(self, key: int, *args: Any) -> None:
    """Initialize the exception with the missing key."""
    super().__init__(args)
    self.key = key

__str__()

Print exception string.

Source code in packages/testing/src/execution_testing/base_types/composite_types.py
def __str__(self) -> str:
    """Print exception string."""
    return "key {0} not found in storage".format(Hash(self.key))

KeyValueMismatchError dataclass

Bases: Exception

Test expected a certain value in a storage key but value found was different.

Source code in packages/testing/src/execution_testing/base_types/composite_types.py
@dataclass(kw_only=True)
class KeyValueMismatchError(Exception):
    """
    Test expected a certain value in a storage key but value found was
    different.
    """

    address: Address
    key: int
    want: int
    got: int
    hint: str

    def __init__(
        self,
        address: Address,
        key: int,
        want: int,
        got: int,
        hint: str = "",
        *args: Any,
    ) -> None:
        """
        Initialize the exception with the address, key, wanted and got
        values.
        """
        super().__init__(args)
        self.address = address
        self.key = key
        self.want = want
        self.got = got
        self.hint = hint

    def __str__(self) -> str:
        """Print exception string."""
        label_str = ""
        if self.address.label is not None:
            label_str = f" ({self.address.label})"
        hint_str = f" ({self.hint})" if self.hint else ""
        return (
            f"incorrect value in address {self.address}{label_str} for "
            + f"key {Hash(self.key)}{hint_str}:"
            + f" want {HexNumber(self.want)} (dec:{int(self.want)}),"
            + f" got {HexNumber(self.got)} (dec:{int(self.got)})"
        )

__init__(address, key, want, got, hint='', *args)

Initialize the exception with the address, key, wanted and got values.

Source code in packages/testing/src/execution_testing/base_types/composite_types.py
def __init__(
    self,
    address: Address,
    key: int,
    want: int,
    got: int,
    hint: str = "",
    *args: Any,
) -> None:
    """
    Initialize the exception with the address, key, wanted and got
    values.
    """
    super().__init__(args)
    self.address = address
    self.key = key
    self.want = want
    self.got = got
    self.hint = hint

__str__()

Print exception string.

Source code in packages/testing/src/execution_testing/base_types/composite_types.py
def __str__(self) -> str:
    """Print exception string."""
    label_str = ""
    if self.address.label is not None:
        label_str = f" ({self.address.label})"
    hint_str = f" ({self.hint})" if self.hint else ""
    return (
        f"incorrect value in address {self.address}{label_str} for "
        + f"key {Hash(self.key)}{hint_str}:"
        + f" want {HexNumber(self.want)} (dec:{int(self.want)}),"
        + f" got {HexNumber(self.got)} (dec:{int(self.got)})"
    )

__contains__(key)

Check for an item in the storage.

Source code in packages/testing/src/execution_testing/base_types/composite_types.py
def __contains__(
    self, key: StorageKeyValueTypeConvertible | StorageKeyValueType
) -> bool:
    """Check for an item in the storage."""
    return StorageKeyValueTypeAdapter.validate_python(key) in self.root

__getitem__(key)

Return an item from the storage.

Source code in packages/testing/src/execution_testing/base_types/composite_types.py
def __getitem__(
    self, key: StorageKeyValueTypeConvertible | StorageKeyValueType
) -> StorageKeyValueType:
    """Return an item from the storage."""
    return self.root[StorageKeyValueTypeAdapter.validate_python(key)]

freeze()

Reject any further writes to the storage, and return it.

Source code in packages/testing/src/execution_testing/base_types/composite_types.py
def freeze(self) -> "Storage":
    """Reject any further writes to the storage, and return it."""
    self._frozen = True
    return self

__setitem__(key, value)

Set an item in the storage.

Source code in packages/testing/src/execution_testing/base_types/composite_types.py
def __setitem__(
    self,
    key: StorageKeyValueTypeConvertible | StorageKeyValueType,
    value: StorageKeyValueTypeConvertible | StorageKeyValueType,
) -> None:
    """Set an item in the storage."""
    self._require_mutable()
    self.root[StorageKeyValueTypeAdapter.validate_python(key)] = (
        StorageKeyValueTypeAdapter.validate_python(value)
    )

__delitem__(key)

Delete an item from the storage.

Source code in packages/testing/src/execution_testing/base_types/composite_types.py
def __delitem__(
    self, key: StorageKeyValueTypeConvertible | StorageKeyValueType
) -> None:
    """Delete an item from the storage."""
    self._require_mutable()
    del self.root[StorageKeyValueTypeAdapter.validate_python(key)]

__iter__()

Return an iterator over the storage.

Source code in packages/testing/src/execution_testing/base_types/composite_types.py
def __iter__(self) -> Iterator[StorageKeyValueType]:  # type: ignore [override]
    """Return an iterator over the storage."""
    return iter(self.root)

__eq__(other)

Return True if both storages are equal.

Source code in packages/testing/src/execution_testing/base_types/composite_types.py
def __eq__(self, other: object) -> bool:
    """Return True if both storages are equal."""
    if not isinstance(other, Storage):
        return False
    return self.root == other.root

__ne__(other)

Return True if both storages are not equal.

Source code in packages/testing/src/execution_testing/base_types/composite_types.py
def __ne__(self, other: object) -> bool:
    """Return True if both storages are not equal."""
    if not isinstance(other, Storage):
        return False
    return self.root != other.root

__bool__()

Return True if the storage is not empty.

Source code in packages/testing/src/execution_testing/base_types/composite_types.py
def __bool__(self) -> bool:
    """Return True if the storage is not empty."""
    return any(v for v in self.root.values())

__add__(other)

Return a new storage that is the sum of two storages.

Source code in packages/testing/src/execution_testing/base_types/composite_types.py
def __add__(self, other: "Storage") -> "Storage":
    """Return a new storage that is the sum of two storages."""
    return Storage({**self.root, **other.root})

__len__()

Return the number of keys that have been explicitly set in the storage.

Source code in packages/testing/src/execution_testing/base_types/composite_types.py
def __len__(self) -> int:
    """
    Return the number of keys that have been explicitly set in the storage.
    """
    return len(self.root)

keys()

Return the keys of the storage.

Source code in packages/testing/src/execution_testing/base_types/composite_types.py
def keys(self) -> set[StorageKeyValueType]:
    """Return the keys of the storage."""
    return set(self.root.keys())

set_next_slot(slot)

Set the next slot to be used by store_next.

Source code in packages/testing/src/execution_testing/base_types/composite_types.py
def set_next_slot(self, slot: int) -> "Storage":
    """Set the next slot to be used by `store_next`."""
    self._require_mutable()
    self._current_slot = slot
    return self

items()

Return the items of the storage.

Source code in packages/testing/src/execution_testing/base_types/composite_types.py
def items(self) -> ItemsView[StorageKeyValueType, StorageKeyValueType]:
    """Return the items of the storage."""
    return self.root.items()

set_expect_any(key)

Mark key to be able to have any expected value when comparing storages.

Source code in packages/testing/src/execution_testing/base_types/composite_types.py
def set_expect_any(
    self, key: StorageKeyValueTypeConvertible | StorageKeyValueType
) -> None:
    """
    Mark key to be able to have any expected value when comparing storages.
    """
    self._require_mutable()
    self._any_map[StorageKeyValueTypeAdapter.validate_python(key)] = True

store_next(value, hint='')

Store a value in the storage and return the key where the value is stored.

Increments the key counter so the next time this function is called, the next key is used.

Source code in packages/testing/src/execution_testing/base_types/composite_types.py
def store_next(
    self,
    value: StorageKeyValueTypeConvertible | StorageKeyValueType | bool,
    hint: str = "",
) -> StorageKeyValueType:
    """
    Store a value in the storage and return the key where the value is
    stored.

    Increments the key counter so the next time this function is called,
    the next key is used.
    """
    self._require_mutable()
    slot = StorageKeyValueTypeAdapter.validate_python(self._current_slot)
    self._current_slot += 1
    if hint:
        self._hint_map[slot] = hint
    self[slot] = StorageKeyValueTypeAdapter.validate_python(value)
    return slot

peek_slot()

Peek the next slot that will be used by store_next.

Source code in packages/testing/src/execution_testing/base_types/composite_types.py
def peek_slot(self) -> int:
    """Peek the next slot that will be used by `store_next`."""
    return self._current_slot

contains(other)

Return True if self contains all keys with equal value as contained by second storage. Used for comparison with test expected post state and alloc returned by the transition tool.

Source code in packages/testing/src/execution_testing/base_types/composite_types.py
def contains(self, other: "Storage") -> bool:
    """
    Return True if self contains all keys with equal value as contained by
    second storage. Used for comparison with test expected post state and
    alloc returned by the transition tool.
    """
    for key in other.keys():
        if key not in self:
            return False
        if self[key] != other[key]:
            return False
    return True

must_contain(address, other)

Succeeds only if self contains all keys with equal value as contained by second storage. Used for comparison with test expected post state and alloc returned by the transition tool. Raises detailed exception when a difference is found.

Source code in packages/testing/src/execution_testing/base_types/composite_types.py
def must_contain(self, address: Address, other: "Storage") -> None:
    """
    Succeeds only if self contains all keys with equal value as contained
    by second storage. Used for comparison with test expected post state
    and alloc returned by the transition tool. Raises detailed exception
    when a difference is found.
    """
    for key in other.keys():
        if key not in self:
            # storage[key]==0 is equal to missing storage
            if other[key] != 0:
                raise Storage.MissingKeyError(key=key)
        elif self[key] != other[key]:
            raise Storage.KeyValueMismatchError(
                address=address,
                key=key,
                want=self[key],
                got=other[key],
                hint=self._hint_map.get(key, ""),
            )

must_be_equal(address, other)

Succeed only if "self" is equal to "other" storage.

Source code in packages/testing/src/execution_testing/base_types/composite_types.py
def must_be_equal(self, address: Address, other: "Storage | None") -> None:
    """Succeed only if "self" is equal to "other" storage."""
    # Test keys contained in both storage objects
    if other is None:
        other = Storage({})
    for key in self.keys() & other.keys():
        if self[key] != other[key]:
            raise Storage.KeyValueMismatchError(
                address=address,
                key=key,
                want=self[key],
                got=other[key],
                hint=self._hint_map.get(key, ""),
            )

    # Test keys contained in either one of the storage objects
    for key in self.keys() ^ other.keys():
        if key in self:
            if self[key] != 0:
                raise Storage.KeyValueMismatchError(
                    address=address,
                    key=key,
                    want=self[key],
                    got=0,
                    hint=self._hint_map.get(key, ""),
                )

        elif other[key] != 0:
            # Skip key verification if we allow this key to be ANY
            if self._any_map.get(key) is True:
                continue
            raise Storage.KeyValueMismatchError(
                address=address,
                key=key,
                want=0,
                got=other[key],
                hint=self._hint_map.get(key, ""),
            )

canary()

Return a canary storage filled with non-zero values where the current storage expects zero values, to guarantee that the test overwrites the storage.

Source code in packages/testing/src/execution_testing/base_types/composite_types.py
def canary(self) -> "Storage":
    """
    Return a canary storage filled with non-zero values where the current
    storage expects zero values, to guarantee that the test overwrites the
    storage.
    """
    return Storage(
        {key: HashInt(0xBA5E) for key in self.keys() if self[key] == 0}
    )

to_bytes(input_bytes)

Convert multiple types into bytes.

Source code in packages/testing/src/execution_testing/base_types/conversions.py
def to_bytes(input_bytes: BytesConvertible) -> bytes:
    """Convert multiple types into bytes."""
    if input_bytes is None:
        raise ValueError("Cannot convert `None` input to bytes")

    if isinstance(input_bytes, str):
        # We can have a hex representation of bytes with spaces for readability
        if input_bytes.startswith("0x"):
            input_bytes = input_bytes[2:]
        if len(input_bytes) % 2 == 1:
            input_bytes = "0" + input_bytes
        return bytes.fromhex(input_bytes)

    return bytes(input_bytes)

to_hex(input_bytes)

Convert multiple types into a bytes hex string.

Source code in packages/testing/src/execution_testing/base_types/conversions.py
def to_hex(input_bytes: BytesConvertible) -> str:
    """Convert multiple types into a bytes hex string."""
    return "0x" + to_bytes(input_bytes).hex()

CamelModel

Bases: CopyValidateModel

A base model that converts field names to camel case when serializing.

For example, the field name current_timestamp in a Python model will be represented as currentTimestamp when it is serialized to json.

Source code in packages/testing/src/execution_testing/base_types/pydantic.py
class CamelModel(CopyValidateModel):
    """
    A base model that converts field names to camel case when serializing.

    For example, the field name `current_timestamp` in a Python model will be
    represented as `currentTimestamp` when it is serialized to json.
    """

    model_config = ConfigDict(
        alias_generator=to_camel,
        populate_by_name=True,
        validate_default=True,
        extra="forbid",
    )

EthereumTestBaseModel

Bases: BaseModel, ModelCustomizationsMixin

Base model for all models for Ethereum tests.

Source code in packages/testing/src/execution_testing/base_types/pydantic.py
class EthereumTestBaseModel(BaseModel, ModelCustomizationsMixin):
    """Base model for all models for Ethereum tests."""

    pass

EthereumTestRootModel

Bases: RootModel[RootModelRootType], ModelCustomizationsMixin

Base model for all models for Ethereum tests.

Source code in packages/testing/src/execution_testing/base_types/pydantic.py
class EthereumTestRootModel(
    RootModel[RootModelRootType], ModelCustomizationsMixin
):
    """Base model for all models for Ethereum tests."""

    root: Any

ReferenceSpec

Reference Specification Description Abstract Class.

Source code in packages/testing/src/execution_testing/base_types/reference_spec/reference_spec.py
class ReferenceSpec:
    """Reference Specification Description Abstract Class."""

    @abstractmethod
    def name(self) -> str:
        """Return the name of the spec."""
        pass

    @abstractmethod
    def has_known_version(self) -> bool:
        """
        Return true if the reference spec object is hard-coded with a latest
        known version.
        """
        pass

    @abstractmethod
    def known_version(self) -> str:
        """Return the latest known version in the reference."""
        pass

    @abstractmethod
    def api_url(self) -> str:
        """
        Return the URL required to poll the version from an API, if needed.
        """
        pass

    @abstractmethod
    def latest_version(self) -> str:
        """Return a digest that points to the latest version of the spec."""
        pass

    @abstractmethod
    def is_outdated(self) -> bool:
        """
        Check whether the reference specification has been updated since the
        test was last updated.
        """
        pass

    @abstractmethod
    def write_info(self, info: Dict[str, Dict[str, Any] | str]) -> None:
        """
        Write info about the reference specification used into the output
        fixture.
        """
        pass

    @staticmethod
    @abstractmethod
    def parseable_from_module(module_dict: Dict[str, Any]) -> bool:
        """
        Check whether the module's dict contains required reference spec
        information.
        """
        pass

    @staticmethod
    @abstractmethod
    def parse_from_module(
        module_dict: Dict[str, Any], github_token: Optional[str] = None
    ) -> "ReferenceSpec":
        """
        Parse the module's dict into a reference spec.

        Args:
            module_dict: Dictionary containing module information
            github_token: Optional GitHub token for API authentication

        """
        pass

name() abstractmethod

Return the name of the spec.

Source code in packages/testing/src/execution_testing/base_types/reference_spec/reference_spec.py
@abstractmethod
def name(self) -> str:
    """Return the name of the spec."""
    pass

has_known_version() abstractmethod

Return true if the reference spec object is hard-coded with a latest known version.

Source code in packages/testing/src/execution_testing/base_types/reference_spec/reference_spec.py
@abstractmethod
def has_known_version(self) -> bool:
    """
    Return true if the reference spec object is hard-coded with a latest
    known version.
    """
    pass

known_version() abstractmethod

Return the latest known version in the reference.

Source code in packages/testing/src/execution_testing/base_types/reference_spec/reference_spec.py
@abstractmethod
def known_version(self) -> str:
    """Return the latest known version in the reference."""
    pass

api_url() abstractmethod

Return the URL required to poll the version from an API, if needed.

Source code in packages/testing/src/execution_testing/base_types/reference_spec/reference_spec.py
@abstractmethod
def api_url(self) -> str:
    """
    Return the URL required to poll the version from an API, if needed.
    """
    pass

latest_version() abstractmethod

Return a digest that points to the latest version of the spec.

Source code in packages/testing/src/execution_testing/base_types/reference_spec/reference_spec.py
@abstractmethod
def latest_version(self) -> str:
    """Return a digest that points to the latest version of the spec."""
    pass

is_outdated() abstractmethod

Check whether the reference specification has been updated since the test was last updated.

Source code in packages/testing/src/execution_testing/base_types/reference_spec/reference_spec.py
@abstractmethod
def is_outdated(self) -> bool:
    """
    Check whether the reference specification has been updated since the
    test was last updated.
    """
    pass

write_info(info) abstractmethod

Write info about the reference specification used into the output fixture.

Source code in packages/testing/src/execution_testing/base_types/reference_spec/reference_spec.py
@abstractmethod
def write_info(self, info: Dict[str, Dict[str, Any] | str]) -> None:
    """
    Write info about the reference specification used into the output
    fixture.
    """
    pass

parseable_from_module(module_dict) abstractmethod staticmethod

Check whether the module's dict contains required reference spec information.

Source code in packages/testing/src/execution_testing/base_types/reference_spec/reference_spec.py
@staticmethod
@abstractmethod
def parseable_from_module(module_dict: Dict[str, Any]) -> bool:
    """
    Check whether the module's dict contains required reference spec
    information.
    """
    pass

parse_from_module(module_dict, github_token=None) abstractmethod staticmethod

Parse the module's dict into a reference spec.

Parameters:

Name Type Description Default
module_dict Dict[str, Any]

Dictionary containing module information

required
github_token Optional[str]

Optional GitHub token for API authentication

None
Source code in packages/testing/src/execution_testing/base_types/reference_spec/reference_spec.py
@staticmethod
@abstractmethod
def parse_from_module(
    module_dict: Dict[str, Any], github_token: Optional[str] = None
) -> "ReferenceSpec":
    """
    Parse the module's dict into a reference spec.

    Args:
        module_dict: Dictionary containing module information
        github_token: Optional GitHub token for API authentication

    """
    pass

KnownEncodedSize

Stand in for an item whose encoded size is already known.

Source code in packages/testing/src/execution_testing/base_types/serialization.py
class KnownEncodedSize:
    """Stand in for an item whose encoded size is already known."""

    __slots__ = ("size",)

    def __init__(self, size: int) -> None:
        """Record the encoded size of the item this stands in for."""
        self.size = size

__init__(size)

Record the encoded size of the item this stands in for.

Source code in packages/testing/src/execution_testing/base_types/serialization.py
def __init__(self, size: int) -> None:
    """Record the encoded size of the item this stands in for."""
    self.size = size

RLPSerializable

Class that adds RLP serialization to another class.

Source code in packages/testing/src/execution_testing/base_types/serialization.py
class RLPSerializable:
    """Class that adds RLP serialization to another class."""

    rlp_override: Bytes | None = None

    signable: ClassVar[bool] = False
    rlp_fields: ClassVar[List[str]]
    rlp_signing_fields: ClassVar[List[str]]
    rlp_exclude_none: ClassVar[bool] = False

    def get_rlp_fields(self) -> List[str]:
        """
        Return an ordered list of field names to be included in RLP
        serialization.

        Function can be overridden to customize the logic to return the fields.

        By default, rlp_fields class variable is used.

        The list can be nested list up to one extra level to represent nested
        fields.
        """
        return self.rlp_fields

    def get_rlp_signing_fields(self) -> List[str]:
        """
        Return an ordered list of field names to be included in the RLP
        serialization of the object signature.

        Function can be overridden to customize the logic to return the fields.

        By default, rlp_signing_fields class variable is used.

        The list can be nested list up to one extra level to represent nested
        fields.
        """
        return self.rlp_signing_fields

    def get_rlp_prefix(self) -> bytes:
        """
        Return a prefix that has to be appended to the serialized object.

        By default, an empty string is returned.
        """
        return b""

    def get_rlp_signing_prefix(self) -> bytes:
        """
        Return a prefix that has to be appended to the serialized signing
        object.

        By default, an empty string is returned.
        """
        return b""

    def sign(self) -> None:
        """Sign the current object for further serialization."""
        raise NotImplementedError(
            f'Object "{self.__class__.__name__}" cannot be signed.'
        )

    def to_list_from_fields(self, fields: List[str]) -> List[Any]:
        """
        Return an RLP serializable list that can be passed to `eth_rlp.encode`.

        Can be for signing purposes or the entire object.
        """
        values_list: List[Any] = []
        for field in fields:
            assert isinstance(field, str), (
                f'Unable to rlp serialize field "{field}" '
                f'in object type "{self.__class__.__name__}"'
            )
            assert hasattr(self, field), (
                f'Unable to rlp serialize field "{field}" '
                f'in object type "{self.__class__.__name__}"'
            )
            try:
                value = getattr(self, field)
                if self.rlp_exclude_none and value is None:
                    continue
                values_list.append(to_serializable_element(value))
            except Exception as e:
                raise Exception(
                    f'Unable to rlp serialize field "{field}" '
                    f'in object type "{self.__class__.__name__}"'
                ) from e
        return values_list

    def to_list(self, signing: bool = False) -> List[Any]:
        """
        Return an RLP serializable list that can be passed to `eth_rlp.encode`.

        Can be for signing purposes or the entire object.
        """
        field_list: List[str]
        if signing:
            if not self.signable:
                raise Exception(
                    f'Object "{self.__class__.__name__}" '
                    "does not support signing"
                )
            field_list = self.get_rlp_signing_fields()
        else:
            if self.signable:
                # Automatically sign signable objects during full
                # serialization: Ensures nested objects have valid signatures
                # in the final RLP.
                self.sign()
            field_list = self.get_rlp_fields()

        return self.to_list_from_fields(field_list)

    def rlp_signing_bytes(self) -> Bytes:
        """Return the signing serialized envelope used for signing."""
        return Bytes(
            self.get_rlp_signing_prefix()
            + eth_rlp.encode(self.to_list(signing=True))
        )

    def rlp(self) -> Bytes:
        """Return the serialized object."""
        if self.rlp_override is not None:
            return self.rlp_override
        return Bytes(
            self.get_rlp_prefix() + eth_rlp.encode(self.to_list(signing=False))
        )

    def rlp_size(self) -> int:
        """Return `len(self.rlp())` without building the encoding."""
        if self.rlp_override is not None:
            return len(self.rlp_override)
        return len(self.get_rlp_prefix()) + encoded_size(
            self.to_list(signing=False)
        )

    @classmethod
    def list_root(cls, element_list: Sequence[Self]) -> bytes:
        """Return the root of a list of the given type."""
        t = HexaryTrie(db={})
        for i, e in enumerate(element_list):
            t.set(
                eth_rlp.encode(Uint(i)),
                e.rlp(),
            )
        return t.root_hash

get_rlp_fields()

Return an ordered list of field names to be included in RLP serialization.

Function can be overridden to customize the logic to return the fields.

By default, rlp_fields class variable is used.

The list can be nested list up to one extra level to represent nested fields.

Source code in packages/testing/src/execution_testing/base_types/serialization.py
def get_rlp_fields(self) -> List[str]:
    """
    Return an ordered list of field names to be included in RLP
    serialization.

    Function can be overridden to customize the logic to return the fields.

    By default, rlp_fields class variable is used.

    The list can be nested list up to one extra level to represent nested
    fields.
    """
    return self.rlp_fields

get_rlp_signing_fields()

Return an ordered list of field names to be included in the RLP serialization of the object signature.

Function can be overridden to customize the logic to return the fields.

By default, rlp_signing_fields class variable is used.

The list can be nested list up to one extra level to represent nested fields.

Source code in packages/testing/src/execution_testing/base_types/serialization.py
def get_rlp_signing_fields(self) -> List[str]:
    """
    Return an ordered list of field names to be included in the RLP
    serialization of the object signature.

    Function can be overridden to customize the logic to return the fields.

    By default, rlp_signing_fields class variable is used.

    The list can be nested list up to one extra level to represent nested
    fields.
    """
    return self.rlp_signing_fields

get_rlp_prefix()

Return a prefix that has to be appended to the serialized object.

By default, an empty string is returned.

Source code in packages/testing/src/execution_testing/base_types/serialization.py
def get_rlp_prefix(self) -> bytes:
    """
    Return a prefix that has to be appended to the serialized object.

    By default, an empty string is returned.
    """
    return b""

get_rlp_signing_prefix()

Return a prefix that has to be appended to the serialized signing object.

By default, an empty string is returned.

Source code in packages/testing/src/execution_testing/base_types/serialization.py
def get_rlp_signing_prefix(self) -> bytes:
    """
    Return a prefix that has to be appended to the serialized signing
    object.

    By default, an empty string is returned.
    """
    return b""

sign()

Sign the current object for further serialization.

Source code in packages/testing/src/execution_testing/base_types/serialization.py
def sign(self) -> None:
    """Sign the current object for further serialization."""
    raise NotImplementedError(
        f'Object "{self.__class__.__name__}" cannot be signed.'
    )

to_list_from_fields(fields)

Return an RLP serializable list that can be passed to eth_rlp.encode.

Can be for signing purposes or the entire object.

Source code in packages/testing/src/execution_testing/base_types/serialization.py
def to_list_from_fields(self, fields: List[str]) -> List[Any]:
    """
    Return an RLP serializable list that can be passed to `eth_rlp.encode`.

    Can be for signing purposes or the entire object.
    """
    values_list: List[Any] = []
    for field in fields:
        assert isinstance(field, str), (
            f'Unable to rlp serialize field "{field}" '
            f'in object type "{self.__class__.__name__}"'
        )
        assert hasattr(self, field), (
            f'Unable to rlp serialize field "{field}" '
            f'in object type "{self.__class__.__name__}"'
        )
        try:
            value = getattr(self, field)
            if self.rlp_exclude_none and value is None:
                continue
            values_list.append(to_serializable_element(value))
        except Exception as e:
            raise Exception(
                f'Unable to rlp serialize field "{field}" '
                f'in object type "{self.__class__.__name__}"'
            ) from e
    return values_list

to_list(signing=False)

Return an RLP serializable list that can be passed to eth_rlp.encode.

Can be for signing purposes or the entire object.

Source code in packages/testing/src/execution_testing/base_types/serialization.py
def to_list(self, signing: bool = False) -> List[Any]:
    """
    Return an RLP serializable list that can be passed to `eth_rlp.encode`.

    Can be for signing purposes or the entire object.
    """
    field_list: List[str]
    if signing:
        if not self.signable:
            raise Exception(
                f'Object "{self.__class__.__name__}" '
                "does not support signing"
            )
        field_list = self.get_rlp_signing_fields()
    else:
        if self.signable:
            # Automatically sign signable objects during full
            # serialization: Ensures nested objects have valid signatures
            # in the final RLP.
            self.sign()
        field_list = self.get_rlp_fields()

    return self.to_list_from_fields(field_list)

rlp_signing_bytes()

Return the signing serialized envelope used for signing.

Source code in packages/testing/src/execution_testing/base_types/serialization.py
def rlp_signing_bytes(self) -> Bytes:
    """Return the signing serialized envelope used for signing."""
    return Bytes(
        self.get_rlp_signing_prefix()
        + eth_rlp.encode(self.to_list(signing=True))
    )

rlp()

Return the serialized object.

Source code in packages/testing/src/execution_testing/base_types/serialization.py
def rlp(self) -> Bytes:
    """Return the serialized object."""
    if self.rlp_override is not None:
        return self.rlp_override
    return Bytes(
        self.get_rlp_prefix() + eth_rlp.encode(self.to_list(signing=False))
    )

rlp_size()

Return len(self.rlp()) without building the encoding.

Source code in packages/testing/src/execution_testing/base_types/serialization.py
def rlp_size(self) -> int:
    """Return `len(self.rlp())` without building the encoding."""
    if self.rlp_override is not None:
        return len(self.rlp_override)
    return len(self.get_rlp_prefix()) + encoded_size(
        self.to_list(signing=False)
    )

list_root(element_list) classmethod

Return the root of a list of the given type.

Source code in packages/testing/src/execution_testing/base_types/serialization.py
@classmethod
def list_root(cls, element_list: Sequence[Self]) -> bytes:
    """Return the root of a list of the given type."""
    t = HexaryTrie(db={})
    for i, e in enumerate(element_list):
        t.set(
            eth_rlp.encode(Uint(i)),
            e.rlp(),
        )
    return t.root_hash

SignableRLPSerializable

Bases: RLPSerializable

Class that adds RLP serialization to another class with signing support.

Source code in packages/testing/src/execution_testing/base_types/serialization.py
class SignableRLPSerializable(RLPSerializable):
    """
    Class that adds RLP serialization to another class with signing support.
    """

    signable: ClassVar[bool] = True

    def sign(self) -> None:
        """Sign the current object for further serialization."""
        raise NotImplementedError(
            f'Object "{self.__class__.__name__}" needs to implement `sign`.'
        )

sign()

Sign the current object for further serialization.

Source code in packages/testing/src/execution_testing/base_types/serialization.py
def sign(self) -> None:
    """Sign the current object for further serialization."""
    raise NotImplementedError(
        f'Object "{self.__class__.__name__}" needs to implement `sign`.'
    )

encoded_prefixed_size(payload_size)

Return the encoded size of an item with a payload of payload_size bytes, its length prefix included.

Source code in packages/testing/src/execution_testing/base_types/serialization.py
def encoded_prefixed_size(payload_size: int) -> int:
    """
    Return the encoded size of an item with a payload of `payload_size`
    bytes, its length prefix included.
    """
    if payload_size < 0x38:
        return 1 + payload_size
    return 1 + len(Uint(payload_size).to_be_bytes()) + payload_size

encoded_size(raw_data)

Return len(eth_rlp.encode(raw_data)) without building the encoding.

This covers the same cases as ethereum_rlp.encode, plus KnownEncodedSize placeholders, so measuring the size of a large structure costs a walk over it instead of megabytes of intermediate byte strings. The concrete types come first: the abstract Sequence check is slow enough to dominate the walk.

Source code in packages/testing/src/execution_testing/base_types/serialization.py
def encoded_size(raw_data: Any) -> int:
    """
    Return `len(eth_rlp.encode(raw_data))` without building the encoding.

    This covers the same cases as `ethereum_rlp.encode`, plus
    `KnownEncodedSize` placeholders, so measuring the size of a large
    structure costs a walk over it instead of megabytes of intermediate byte
    strings. The concrete types come first: the abstract
    `Sequence` check is slow enough to dominate the walk.
    """
    if isinstance(raw_data, (bytearray, bytes)):
        return _encoded_bytes_size(raw_data)
    elif isinstance(raw_data, (list, tuple)):
        return _encoded_sequence_size(raw_data)
    elif isinstance(raw_data, (Uint, FixedUnsigned)):
        return _encoded_unsigned_size(int(raw_data))
    elif isinstance(raw_data, KnownEncodedSize):
        return raw_data.size
    elif isinstance(raw_data, bool):
        return 1
    elif isinstance(raw_data, str):
        return _encoded_bytes_size(raw_data.encode())
    elif isinstance(raw_data, Sequence):
        return _encoded_sequence_size(raw_data)
    elif is_dataclass(raw_data) and not isinstance(raw_data, type):
        return _encoded_sequence_size(astuple(raw_data))
    else:
        raise EncodingError(
            "RLP encoded size of type {} is not supported".format(
                type(raw_data)
            )
        )

unwrap_annotation(hint)

Recursively unwrap Annotated and Union types to find the actual type.

This function is useful for introspecting complex type annotations like: - Annotated[int, ...] -> int - int | None -> int - Annotated[int, ...] | None -> int

Parameters:

Name Type Description Default
hint Any

Type annotation to unwrap

required

Returns:

Type Description
Any

The unwrapped base type

Source code in packages/testing/src/execution_testing/base_types/typing_utils.py
def unwrap_annotation(hint: Any) -> Any:
    """
    Recursively unwrap Annotated and Union types to find the actual type.

    This function is useful for introspecting complex type annotations like:
    - `Annotated[int, ...]` -> `int`
    - `int | None` -> `int`
    - `Annotated[int, ...] | None` -> `int`

    Args:
        hint: Type annotation to unwrap

    Returns:
        The unwrapped base type

    """
    type_args = get_args(hint)
    if not type_args:
        # Base case: simple type with no parameters
        return hint

    # For Union types (including Optional), find the first non-None type
    for arg in type_args:
        if arg is not type(None):
            # Recursively unwrap (handles nested Annotated/Union)
            return unwrap_annotation(arg)

    # All args were None (shouldn't happen in practice)
    return hint