#!/usr/bin/python3 import pytest from requests import ConnectionError from packaging.version import Version import vvm def pytest_addoption(parser): parser.addoption( "--no-install", action="store_true", help="Only run vvm tests against already installed vyper versions", ) parser.addoption( "--vyper-versions", action="store", help="Only run tests against a specific version(s) of vyper", ) def pytest_configure(config): config.addinivalue_line("markers", "min_vyper: minimum version of vyper to run test against") config.addinivalue_line("markers", "max_vyper: maximum version of vyper to run test against") def pytest_collection(session): global VERSIONS if session.config.getoption("--vyper-versions"): VERSIONS = [Version(i) for i in session.config.getoption("--vyper-versions").split(",")] elif session.config.getoption("--no-install"): VERSIONS = vvm.get_installed_vyper_versions() else: try: VERSIONS = vvm.get_installable_vyper_versions() except ConnectionError: raise pytest.UsageError( "ConnectionError while attempting to get vyper versions.\n" "Use the --no-install flag to only run tests against already installed versions." ) for version in VERSIONS: vvm.install_vyper(version) # auto-parametrize the all_versions fixture with all target vyper versions def pytest_generate_tests(metafunc): if "all_versions" in metafunc.fixturenames: versions = VERSIONS.copy() for marker in metafunc.definition.iter_markers(name="min_vyper"): versions = [i for i in versions if i >= Version(marker.args[0])] for marker in metafunc.definition.iter_markers(name="max_vyper"): versions = [i for i in versions if i <= Version(marker.args[0])] metafunc.parametrize("all_versions", versions, indirect=True) @pytest.fixture def all_versions(request): """ Run a test against all vyper versions. """ version = request.param vvm.set_vyper_version(version) return version @pytest.fixture def foo_source(all_versions): visibility = "external" if all_versions >= Version("0.2.0") else "public" yield f""" from vyper.interfaces import ERC20 @{visibility} def foo() -> int128: return 13 """ @pytest.fixture def foo_path(tmp_path_factory, foo_source, all_versions): source = tmp_path_factory.getbasetemp().joinpath(f"Foo-{all_versions}.sol") if not source.exists(): with source.open("w") as fp: fp.write(foo_source) return source @pytest.fixture def input_json(all_versions): json = { "language": "Vyper", "sources": {}, "settings": {"outputSelection": {"*": {"*": ["evm.bytecode.object"]}}}, } yield json