Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat/pydantic: Use Pydantic library for types #486

Merged
merged 27 commits into from
Apr 4, 2024
Merged
Show file tree
Hide file tree
Changes from 18 commits
Commits
Show all changes
27 commits
Select commit Hold shift + click to select a range
10f0b49
setup: Add pydantic, update mypy
marioevz Mar 26, 2024
03b1917
refactor(fw): Use pydantic for base and common types
marioevz Mar 26, 2024
da6a4b3
refactor(spec): Use pydantic types for test specs
marioevz Mar 26, 2024
d3bf758
refactor(fw): Fix all tests
marioevz Mar 26, 2024
c7934d4
refactor(fw): Cleanup exported types
marioevz Mar 26, 2024
815d84c
refactor(evm_transition_tool): Return full dict on evaluate
marioevz Mar 26, 2024
bdd4f1c
fix(plugins): fix refactor issues
marioevz Mar 26, 2024
eeaa2c2
whilelist: Add pydantic
marioevz Mar 26, 2024
8165105
fix(tests): Pydantic required changes
marioevz Mar 26, 2024
3ed3bb2
changelog
marioevz Mar 26, 2024
f99e7e2
fix(fw): Fixture block types with and without rlp
marioevz Mar 27, 2024
7b76b13
fix(fw): Transaction "to" field validation
marioevz Mar 27, 2024
6547383
feat(fw): add FixtureBlockBase json test
marioevz Mar 27, 2024
7a3e5b8
fix(fw): base fixture json generation
marioevz Mar 27, 2024
2892ed5
fix(fw): account for zero values in storage on empty account check
marioevz Apr 1, 2024
78e6cc4
changelog
marioevz Apr 3, 2024
d6bb8cd
refactor(fw): ExceptionList as annotated type
marioevz Apr 3, 2024
d7eac86
fix(tests): exception lists
marioevz Apr 3, 2024
94f4a3f
chore: fix minor typos in blobgasfee test docstrings
danceratopz Apr 4, 2024
4ee0869
Apply suggestions from code review
marioevz Apr 4, 2024
7767076
fix(fw): Export Alloc
marioevz Apr 4, 2024
2e761e9
fix(fw): tox
marioevz Apr 4, 2024
4b853fd
fix(fw): add set/del item from Alloc
marioevz Apr 4, 2024
1297d90
fix(tests): Use Alloc in blobgasfee tests
marioevz Apr 4, 2024
64085f3
changelog
marioevz Apr 4, 2024
6f107ed
fix(fw): Alloc: don't pop on None assigment
marioevz Apr 4, 2024
e52c7af
fix(fw): Types: remove unused definitions
marioevz Apr 4, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions docs/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ Test fixtures for use by clients are available for each release on the [Github r

- 🐞 Fix incorrect `!=` operator for `FixedSizeBytes` ([#477](https://github.com/ethereum/execution-spec-tests/pull/477)).
- ✨ Add Macro enum that represents byte sequence of Op instructions ([#457](https://github.com/ethereum/execution-spec-tests/pull/457))
- ✨ Libraries have been refactored to use `pydantic` for type checking in most test types ([#486](https://github.com/ethereum/execution-spec-tests/pull/486)).

### 🔧 EVM Tools

Expand All @@ -22,6 +23,10 @@ Test fixtures for use by clients are available for each release on the [Github r
- 🐞 Fix CI by using Golang 1.21 in Github Actions to build geth ([#484](https://github.com/ethereum/execution-spec-tests/pull/484)).
- 💥 "Merge" has been renamed to "Paris" in the "network" field of the Blockchain tests, and in the "post" field of the State tests ([#480](https://github.com/ethereum/execution-spec-tests/pull/480)).
- ✨ Port entry point scripts to use [click](https://click.palletsprojects.com) and add tests ([#483](https://github.com/ethereum/execution-spec-tests/pull/483)).
- 💥 As part of the pydantic conversion, the fixtures have the following (possibly breaking) changes ([#486](https://github.com/ethereum/execution-spec-tests/pull/486)):
- `expectException` fields now print the exceptions in sorted order.
marioevz marked this conversation as resolved.
Show resolved Hide resolved
- State test field `transaction` now uses the proper zero-padded hex number format for fields `maxPriorityFeePerGas`, `maxFeePerGas`, and `maxFeePerBlobGas`
- Fixtures' hashes (in the `_info` field) are now calculated by removing the "_info" field entirely instead of it being set to an empty dict.

## 🔜 [v2.1.1](https://github.com/ethereum/execution-spec-tests/releases/tag/v2.1.1) - 2024-03-09

Expand Down
1 change: 1 addition & 0 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -12,3 +12,4 @@ line-length = 99

[tool.mypy]
mypy_path = "$MYPY_CONFIG_FILE_DIR/stubs"
plugins = ["pydantic.mypy"]
3 changes: 2 additions & 1 deletion setup.cfg
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ install_requires =
trie==2.1.1
semver==3.0.1
click>=8.0.0,<9
pydantic>=2.6.3

[options.package_data]
ethereum_test_tools =
Expand Down Expand Up @@ -61,7 +62,7 @@ test =

lint =
isort>=5.8,<6
mypy==0.982; implementation_name == "cpython"
mypy==0.991; implementation_name == "cpython"
types-requests
black==22.3.0; implementation_name == "cpython"
flake8-spellcheck>=0.24,<0.25
Expand Down
10 changes: 1 addition & 9 deletions src/ethereum_test_tools/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,11 +18,9 @@
AccessList,
Account,
Address,
marioevz marked this conversation as resolved.
Show resolved Hide resolved
Auto,
EngineAPIError,
Environment,
Hash,
JSONEncoder,
Removable,
Storage,
TestAddress,
Expand All @@ -39,9 +37,8 @@
copy_opcode_cost,
cost_memory_bytes,
eip_2028_transaction_data_cost,
transaction_list_root,
)
from .exceptions import BlockException, ExceptionList, ExceptionType, TransactionException
from .exceptions import BlockException, TransactionException
from .reference_spec import ReferenceSpec, ReferenceSpecTypes
from .spec import (
SPEC_TYPES,
Expand All @@ -62,7 +59,6 @@
"AccessList",
"Account",
"Address",
marioevz marked this conversation as resolved.
Show resolved Hide resolved
"Auto",
"BaseFixture",
"BaseTest",
"Block",
Expand All @@ -76,13 +72,10 @@
"Conditional",
"EngineAPIError",
"Environment",
"ExceptionList",
"ExceptionType",
"FixtureCollector",
"Hash",
"Header",
"Initcode",
"JSONEncoder",
"Opcode",
"Macro",
"OpcodeCallArg",
Expand Down Expand Up @@ -113,5 +106,4 @@
"cost_memory_bytes",
"eip_2028_transaction_data_cost",
"eip_2028_transaction_data_cost",
"transaction_list_root",
)
17 changes: 3 additions & 14 deletions src/ethereum_test_tools/common/__init__.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
"""
Common definitions and types.
"""

from .base_types import (
Address,
Bloom,
Expand All @@ -14,6 +15,7 @@
from .constants import (
AddrAA,
AddrBB,
EmptyOmmersRoot,
EmptyTrieRoot,
EngineAPIError,
TestAddress,
Expand All @@ -36,18 +38,11 @@
AccessList,
Account,
Alloc,
Auto,
Environment,
JSONEncoder,
Removable,
Storage,
Transaction,
Withdrawal,
alloc_to_accounts,
serialize_transactions,
str_or_none,
transaction_list_root,
withdrawals_root,
)

__all__ = (
Expand All @@ -57,16 +52,15 @@
"AddrAA",
"AddrBB",
"Alloc",
"Auto",
"Bloom",
"Bytes",
"EngineAPIError",
"EmptyOmmersRoot",
"EmptyTrieRoot",
"Environment",
"Hash",
"HeaderNonce",
"HexNumber",
"JSONEncoder",
"Number",
"Removable",
"Storage",
Expand All @@ -79,16 +73,11 @@
"Withdrawal",
"ZeroPaddedHexNumber",
"add_kzg_version",
"alloc_to_accounts",
"ceiling_division",
"compute_create_address",
"compute_create2_address",
"copy_opcode_cost",
"cost_memory_bytes",
"eip_2028_transaction_data_cost",
"serialize_transactions",
"str_or_none",
"to_json",
"transaction_list_root",
"withdrawals_root",
)
108 changes: 92 additions & 16 deletions src/ethereum_test_tools/common/base_types.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,14 @@
Basic type primitives used to define other types.
"""

from typing import ClassVar, SupportsBytes, Type, TypeVar
from typing import Any, ClassVar, SupportsBytes, Type, TypeVar

from pydantic import GetCoreSchemaHandler
from pydantic_core.core_schema import (
PlainValidatorFunctionSchema,
no_info_plain_validator_function,
to_string_ser_schema,
)

from .conversions import (
BytesConvertible,
Expand All @@ -12,12 +19,29 @@
to_fixed_size_bytes,
to_number,
)
from .json import JSONEncoder, SupportsJSON

N = TypeVar("N", bound="Number")


class Number(int, SupportsJSON):
class ToStringSchema:
"""
Type converter to add a simple pydantic schema that correctly parses and serializes the type.
"""

@staticmethod
def __get_pydantic_core_schema__(
source_type: Any, handler: GetCoreSchemaHandler
) -> PlainValidatorFunctionSchema:
"""
Calls the class constructor without info and appends the serialization schema.
"""
return no_info_plain_validator_function(
source_type,
serialization=to_string_ser_schema(),
)


class Number(int, ToStringSchema):
"""
Class that helps represent numbers in tests.
"""
Expand All @@ -34,12 +58,6 @@ def __str__(self) -> str:
"""
return str(int(self))

def __json__(self, encoder: JSONEncoder) -> str:
"""
Returns the JSON representation of the number.
"""
return str(self)

def hex(self) -> str:
"""
Returns the hexadecimal representation of the number.
Expand Down Expand Up @@ -85,7 +103,10 @@ def hex(self) -> str:
return "0x" + hex_str


class Bytes(bytes, SupportsJSON):
NumberBoundTypeVar = TypeVar("NumberBoundTypeVar", Number, HexNumber, ZeroPaddedHexNumber)


class Bytes(bytes, ToStringSchema):
"""
Class that helps represent bytes of variable length in tests.
"""
Expand All @@ -108,12 +129,6 @@ def __str__(self) -> str:
"""
return self.hex()

def __json__(self, encoder: JSONEncoder) -> str:
"""
Returns the JSON representation of the bytes.
"""
return str(self)

def hex(self, *args, **kwargs) -> str:
"""
Returns the hexadecimal representation of the bytes.
Expand All @@ -130,6 +145,67 @@ def or_none(cls, input: "Bytes | BytesConvertible | None") -> "Bytes | None":
return cls(input)


S = TypeVar("S", bound="FixedSizeHexNumber")


class FixedSizeHexNumber(int, ToStringSchema):
"""
Class that helps represent a number of fixed byte-length in tests.
marioevz marked this conversation as resolved.
Show resolved Hide resolved
"""

byte_length: ClassVar[int]
max_value: ClassVar[int]

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

class Sized(cls): # type: ignore
byte_length = length
max_value = 2 ** (8 * length) - 1

return Sized

def __new__(cls, input: NumberConvertible | N):
"""
Creates a new Number object.
"""
i = to_number(input)
if i > cls.max_value:
raise ValueError(f"Value {i} is too large for {cls.byte_length} bytes")
if i < 0:
i += cls.max_value + 1
if i <= 0:
raise ValueError(f"Value {i} is too small for {cls.byte_length} bytes")
return super(FixedSizeHexNumber, cls).__new__(cls, i)

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

def hex(self) -> str:
"""
Returns 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


class HashInt(FixedSizeHexNumber[32]): # type: ignore
"""
Class that helps represent hashes in tests.
"""

pass


T = TypeVar("T", bound="FixedSizeBytes")


Expand Down
Loading
Loading