|  | 
| 17 | 17 | from _pytest.python import Module | 
| 18 | 18 | 
 | 
| 19 | 19 | from ethereum_test_fixtures import BaseFixture, LabeledFixtureFormat | 
| 20 |  | -from ethereum_test_forks import Fork | 
|  | 20 | +from ethereum_test_forks import ( | 
|  | 21 | +    Fork, | 
|  | 22 | +    get_closest_fork_with_solc_support, | 
|  | 23 | +    get_forks_with_solc_support, | 
|  | 24 | +) | 
| 21 | 25 | from ethereum_test_specs import BaseStaticTest, BaseTest | 
|  | 26 | +from ethereum_test_tools.code.yul import Yul | 
| 22 | 27 | 
 | 
| 23 | 28 | from ..forks.forks import ValidityMarker, get_intersection_set | 
| 24 | 29 | from ..shared.helpers import labeled_format_parameter_set | 
| @@ -109,18 +114,6 @@ def get_all_combinations_from_parametrize_marks( | 
| 109 | 114 |     return all_argument_names, all_value_combinations | 
| 110 | 115 | 
 | 
| 111 | 116 | 
 | 
| 112 |  | -def pytest_addoption(parser: pytest.Parser): | 
| 113 |  | -    """Add command-line options to pytest.""" | 
| 114 |  | -    static_filler_group = parser.getgroup("static", "Arguments defining static filler behavior") | 
| 115 |  | -    static_filler_group.addoption( | 
| 116 |  | -        "--fill-static-tests", | 
| 117 |  | -        action="store_true", | 
| 118 |  | -        dest="fill_static_tests_enabled", | 
| 119 |  | -        default=None, | 
| 120 |  | -        help=("Enable reading and filling from static test files."), | 
| 121 |  | -    ) | 
| 122 |  | - | 
| 123 |  | - | 
| 124 | 117 | def pytest_collect_file(file_path: Path, parent) -> pytest.Collector | None: | 
| 125 | 118 |     """Pytest hook that collects test cases from static files and fills them into test fixtures.""" | 
| 126 | 119 |     fill_static_tests_enabled = parent.config.getoption("fill_static_tests_enabled") | 
| @@ -334,3 +327,46 @@ def runtest(self): | 
| 334 | 327 |     def reportinfo(self): | 
| 335 | 328 |         """Provide information for test reporting.""" | 
| 336 | 329 |         return self.fspath, 0, f"Static file test: {self.name}" | 
|  | 330 | + | 
|  | 331 | + | 
|  | 332 | +@pytest.fixture | 
|  | 333 | +def yul(fork: Fork, request: pytest.FixtureRequest): | 
|  | 334 | +    """ | 
|  | 335 | +    Fixture that allows contract code to be defined with Yul code. | 
|  | 336 | +
 | 
|  | 337 | +    This fixture defines a class that wraps the ::ethereum_test_tools.Yul | 
|  | 338 | +    class so that upon instantiation within the test case, it provides the | 
|  | 339 | +    test case's current fork parameter. The forks is then available for use | 
|  | 340 | +    in solc's arguments for the Yul code compilation. | 
|  | 341 | +
 | 
|  | 342 | +    Test cases can override the default value by specifying a fixed version | 
|  | 343 | +    with the @pytest.mark.compile_yul_with(FORK) marker. | 
|  | 344 | +    """ | 
|  | 345 | +    solc_target_fork: Fork | None | 
|  | 346 | +    marker = request.node.get_closest_marker("compile_yul_with") | 
|  | 347 | +    assert hasattr(request.config, "solc_version"), "solc_version not set in pytest config." | 
|  | 348 | +    if marker: | 
|  | 349 | +        if not marker.args[0]: | 
|  | 350 | +            pytest.fail( | 
|  | 351 | +                f"{request.node.name}: Expected one argument in 'compile_yul_with' marker." | 
|  | 352 | +            ) | 
|  | 353 | +        for fork in request.config.all_forks:  # type: ignore | 
|  | 354 | +            if fork.name() == marker.args[0]: | 
|  | 355 | +                solc_target_fork = fork | 
|  | 356 | +                break | 
|  | 357 | +        else: | 
|  | 358 | +            pytest.fail(f"{request.node.name}: Fork {marker.args[0]} not found in forks list.") | 
|  | 359 | +        assert solc_target_fork in get_forks_with_solc_support(request.config.solc_version) | 
|  | 360 | +    else: | 
|  | 361 | +        solc_target_fork = get_closest_fork_with_solc_support(fork, request.config.solc_version) | 
|  | 362 | +        assert solc_target_fork is not None, "No fork supports provided solc version." | 
|  | 363 | +        if solc_target_fork != fork and request.config.getoption("verbose") >= 1: | 
|  | 364 | +            warnings.warn( | 
|  | 365 | +                f"Compiling Yul for {solc_target_fork.name()}, not {fork.name()}.", stacklevel=2 | 
|  | 366 | +            ) | 
|  | 367 | + | 
|  | 368 | +    class YulWrapper(Yul): | 
|  | 369 | +        def __new__(cls, *args, **kwargs): | 
|  | 370 | +            return super(YulWrapper, cls).__new__(cls, *args, **kwargs, fork=solc_target_fork) | 
|  | 371 | + | 
|  | 372 | +    return YulWrapper | 
0 commit comments