Skip to content

refactor(pytest,fill): removed solc dependency (#1759) #1779

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

Open
wants to merge 3 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
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
1 change: 1 addition & 0 deletions docs/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ Users can select any of the artifacts depending on their testing needs for their
#### πŸ”€ Refactoring

- πŸ”€ Move `TransactionType` enum from test file to proper module location in `ethereum_test_types.transaction_types` for better code organization and reusability.
- πŸ”€ Remove dependency `solc-select` and in CI instead fetch solc 0.8.24 from the official GitHub release. Code changes required involved porting a few Python tests that made use of Yul to our Opcode language ([#1779](https://github.com/ethereum/execution-spec-tests/pull/1779)).
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could you clarify the extent of how much we've removed the solc dependency?

As I understand, this PR removes the dep of solc to fill Python tests, right? But it is still required for the static tests? Which is generally only performed by EEST maintainers or CI). Therefore, we can remove solc-select as a regular test implementer need not be concerned with solc at all. Is this correct?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looking at the pytest ini files, this is the case. I think the CHANGELOG needs more detailed explanation to help power users understand the changes in this PR.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think it needs to be much clearer (probably worth a note at the top of the release section in the CHANGELOG) that test implementers should no longer use Yul source in their Python test code and that the Yul and YulCompiler objects are no longer available to do this. Not a breaking change in fixture formats, but a breaking change in test implementing standards :)

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes exactly, good point I will clarify this in the changelog.


#### `fill`

Expand Down
2 changes: 1 addition & 1 deletion docs/writing_tests/tutorials/state_transition.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ The most effective method of learning how to write tests is to study a couple of

### Yul Test

You can find the source code for the Yul test in [tests/homestead/yul/test_yul_example.py](../../tests/homestead/yul/test_yul_example/index.md).
You can find the source code for the Yul test in `tests/homestead/yul/test_yul_example.py`.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This file no longer exists. We should remove any reference to it in the documentation and ensure that we don't lead test implementers to use Yul in the Python test code.

It is the spec test equivalent of this [static test](https://github.com/ethereum/tests/blob/develop/src/GeneralStateTestsFiller/stExample/yulExampleFiller.yml).

Lets examine each section.
Expand Down
2 changes: 1 addition & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,6 @@ dependencies = [
"semver>=3.0.1,<4",
"pydantic>=2.10.0,<3",
"rich>=13.7.0,<14",
"solc-select>=1.0.4,<2",
"filelock>=3.15.1,<4",
"ethereum-types>=0.2.1,<0.3",
"pyyaml>=6.0.2,<7",
Expand All @@ -50,6 +49,7 @@ dependencies = [
"pytest-regex>=0.2.0,<0.3",
"eth-abi>=5.2.0",
"joblib>=1.4.2",
"ckzg>=2.1.1,<3",
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Did this unintentionally sneak in here?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes sorry, it's from the pending blob pr

]

[project.urls]
Expand Down
1 change: 0 additions & 1 deletion pytest-check-eip-versions.ini
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,6 @@ addopts =
-p pytest_plugins.spec_version_checker.spec_version_checker
-p pytest_plugins.concurrency
-p pytest_plugins.filler.pre_alloc
-p pytest_plugins.solc.solc
-p pytest_plugins.filler.filler
-p pytest_plugins.shared.execute_fill
-p pytest_plugins.forks.forks
Expand Down
1 change: 0 additions & 1 deletion pytest-execute-hive.ini
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,6 @@ addopts =
-p pytest_plugins.concurrency
-p pytest_plugins.execute.sender
-p pytest_plugins.execute.pre_alloc
-p pytest_plugins.solc.solc
-p pytest_plugins.execute.rpc.hive
-p pytest_plugins.execute.execute
-p pytest_plugins.shared.execute_fill
Expand Down
1 change: 0 additions & 1 deletion pytest-execute.ini
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,6 @@ addopts =
-p pytest_plugins.concurrency
-p pytest_plugins.execute.sender
-p pytest_plugins.execute.pre_alloc
-p pytest_plugins.solc.solc
-p pytest_plugins.execute.execute
-p pytest_plugins.shared.execute_fill
-p pytest_plugins.execute.rpc.remote_seed_sender
Expand Down
2 changes: 0 additions & 2 deletions pytest.ini
Original file line number Diff line number Diff line change
Expand Up @@ -11,9 +11,7 @@ markers =
addopts =
-p pytest_plugins.concurrency
-p pytest_plugins.filler.pre_alloc
-p pytest_plugins.solc.solc
-p pytest_plugins.filler.filler
-p pytest_plugins.filler.static_filler
-p pytest_plugins.filler.ported_tests
-p pytest_plugins.shared.execute_fill
-p pytest_plugins.forks.forks
Expand Down
4 changes: 0 additions & 4 deletions src/ethereum_test_tools/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -82,8 +82,6 @@
Initcode,
Switch,
While,
Yul,
YulCompiler,
)
from .utility.generators import (
DeploymentTestType,
Expand Down Expand Up @@ -157,8 +155,6 @@
"While",
"Withdrawal",
"WithdrawalRequest",
"Yul",
"YulCompiler",
"add_kzg_version",
"call_return_code",
"ceiling_division",
Expand Down
5 changes: 5 additions & 0 deletions src/pytest_plugins/filler/filler.py
Original file line number Diff line number Diff line change
Expand Up @@ -764,6 +764,11 @@ def fixture_collector(
Return configured fixture collector instance used for all tests
in one test module.
"""
# Dynamically load the 'static_filler' and 'solc' plugins if needed
if request.config.getoption("fill_static_tests_enabled"):
request.config.pluginmanager.import_plugin("pytest_plugins.filler.static_filler")
request.config.pluginmanager.import_plugin("pytest_plugins.solc.solc")

fixture_collector = FixtureCollector(
output_dir=fixture_output.directory,
flat_output=fixture_output.flat_output,
Expand Down
62 changes: 49 additions & 13 deletions src/pytest_plugins/filler/static_filler.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,13 @@
from _pytest.python import Module

from ethereum_test_fixtures import BaseFixture, LabeledFixtureFormat
from ethereum_test_forks import Fork
from ethereum_test_forks import (
Fork,
get_closest_fork_with_solc_support,
get_forks_with_solc_support,
)
from ethereum_test_specs import BaseStaticTest, BaseTest
from ethereum_test_tools.code.yul import Yul

from ..forks.forks import ValidityMarker, get_intersection_set
from ..shared.helpers import labeled_format_parameter_set
Expand Down Expand Up @@ -109,18 +114,6 @@ def get_all_combinations_from_parametrize_marks(
return all_argument_names, all_value_combinations


def pytest_addoption(parser: pytest.Parser):
"""Add command-line options to pytest."""
static_filler_group = parser.getgroup("static", "Arguments defining static filler behavior")
static_filler_group.addoption(
"--fill-static-tests",
action="store_true",
dest="fill_static_tests_enabled",
default=None,
help=("Enable reading and filling from static test files."),
)


def pytest_collect_file(file_path: Path, parent) -> pytest.Collector | None:
"""Pytest hook that collects test cases from static files and fills them into test fixtures."""
fill_static_tests_enabled = parent.config.getoption("fill_static_tests_enabled")
Expand Down Expand Up @@ -334,3 +327,46 @@ def runtest(self):
def reportinfo(self):
"""Provide information for test reporting."""
return self.fspath, 0, f"Static file test: {self.name}"


@pytest.fixture
def yul(fork: Fork, request: pytest.FixtureRequest):
"""
Fixture that allows contract code to be defined with Yul code.

This fixture defines a class that wraps the ::ethereum_test_tools.Yul
class so that upon instantiation within the test case, it provides the
test case's current fork parameter. The forks is then available for use
in solc's arguments for the Yul code compilation.

Test cases can override the default value by specifying a fixed version
with the @pytest.mark.compile_yul_with(FORK) marker.
"""
solc_target_fork: Fork | None
marker = request.node.get_closest_marker("compile_yul_with")
assert hasattr(request.config, "solc_version"), "solc_version not set in pytest config."
if marker:
if not marker.args[0]:
pytest.fail(
f"{request.node.name}: Expected one argument in 'compile_yul_with' marker."
)
for fork in request.config.all_forks: # type: ignore
if fork.name() == marker.args[0]:
solc_target_fork = fork
break
else:
pytest.fail(f"{request.node.name}: Fork {marker.args[0]} not found in forks list.")
assert solc_target_fork in get_forks_with_solc_support(request.config.solc_version)
else:
solc_target_fork = get_closest_fork_with_solc_support(fork, request.config.solc_version)
assert solc_target_fork is not None, "No fork supports provided solc version."
if solc_target_fork != fork and request.config.getoption("verbose") >= 1:
warnings.warn(
f"Compiling Yul for {solc_target_fork.name()}, not {fork.name()}.", stacklevel=2
)

class YulWrapper(Yul):
def __new__(cls, *args, **kwargs):
return super(YulWrapper, cls).__new__(cls, *args, **kwargs, fork=solc_target_fork)

return YulWrapper
1 change: 0 additions & 1 deletion src/pytest_plugins/help/tests/test_help.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@
FILL_TEST_ARGS = (
"--evm-bin",
"--traces",
"--solc-bin",
"--filler-path",
"--output",
"--forks",
Expand Down
62 changes: 12 additions & 50 deletions src/pytest_plugins/shared/execute_fill.py
Original file line number Diff line number Diff line change
@@ -1,19 +1,12 @@
"""Shared pytest fixtures and hooks for EEST generation modes (fill and execute)."""

import warnings
from typing import List

import pytest

from ethereum_test_execution import BaseExecute, LabeledExecuteFormat
from ethereum_test_fixtures import BaseFixture, LabeledFixtureFormat
from ethereum_test_forks import (
Fork,
get_closest_fork_with_solc_support,
get_forks_with_solc_support,
)
from ethereum_test_specs import BaseTest
from ethereum_test_tools import Yul
from pytest_plugins.spec_version_checker.spec_version_checker import EIPSpecTestItem


Expand Down Expand Up @@ -102,49 +95,6 @@ def pytest_configure(config: pytest.Config):
)


@pytest.fixture
def yul(fork: Fork, request: pytest.FixtureRequest):
"""
Fixture that allows contract code to be defined with Yul code.

This fixture defines a class that wraps the ::ethereum_test_tools.Yul
class so that upon instantiation within the test case, it provides the
test case's current fork parameter. The forks is then available for use
in solc's arguments for the Yul code compilation.

Test cases can override the default value by specifying a fixed version
with the @pytest.mark.compile_yul_with(FORK) marker.
"""
solc_target_fork: Fork | None
marker = request.node.get_closest_marker("compile_yul_with")
assert hasattr(request.config, "solc_version"), "solc_version not set in pytest config."
if marker:
if not marker.args[0]:
pytest.fail(
f"{request.node.name}: Expected one argument in 'compile_yul_with' marker."
)
for fork in request.config.all_forks: # type: ignore
if fork.name() == marker.args[0]:
solc_target_fork = fork
break
else:
pytest.fail(f"{request.node.name}: Fork {marker.args[0]} not found in forks list.")
assert solc_target_fork in get_forks_with_solc_support(request.config.solc_version)
else:
solc_target_fork = get_closest_fork_with_solc_support(fork, request.config.solc_version)
assert solc_target_fork is not None, "No fork supports provided solc version."
if solc_target_fork != fork and request.config.getoption("verbose") >= 1:
warnings.warn(
f"Compiling Yul for {solc_target_fork.name()}, not {fork.name()}.", stacklevel=2
)

class YulWrapper(Yul):
def __new__(cls, *args, **kwargs):
return super(YulWrapper, cls).__new__(cls, *args, **kwargs, fork=solc_target_fork)

return YulWrapper


@pytest.fixture(scope="function")
def test_case_description(request: pytest.FixtureRequest) -> str:
"""Fixture to extract and combine docstrings from the test class and the test function."""
Expand Down Expand Up @@ -198,3 +148,15 @@ def __init__(self, message):
+ "properly generate a test: "
+ ", ".join(SPEC_TYPES_PARAMETERS)
)


def pytest_addoption(parser: pytest.Parser):
"""Add command-line options to pytest."""
static_filler_group = parser.getgroup("static", "Arguments defining static filler behavior")
static_filler_group.addoption(
"--fill-static-tests",
action="store_true",
dest="fill_static_tests_enabled",
default=None,
help=("Enable reading and filling from static test files."),
)
Loading
Loading