Skip to content

Commit

Permalink
feat: output_format (#21)
Browse files Browse the repository at this point in the history
* Add `output_format` kwarg
- Also deletes the temporary file after compilation
* Update tests & support RCs
Fix tests for vyper 0.4
  • Loading branch information
DanielSchiavini committed Sep 12, 2024
1 parent c6e273b commit bc1581f
Show file tree
Hide file tree
Showing 5 changed files with 76 additions and 41 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
### Changed
- Update contact information in `CONTRIBUTING.md`
- Update dependencies. Minimum python version is now 3.8 ([#22](https://github.com/vyperlang/vvm/pull/22))
- Add `output_format` argument to `compile_source` and `compile_files` ([#21](https://github.com/vyperlang/vvm/pull/21))

## [0.1.0](https://github.com/vyperlang/vvm/tree/v0.1.0) - 2020-10-07
### Added
Expand Down
24 changes: 13 additions & 11 deletions tests/conftest.py
Original file line number Diff line number Diff line change
Expand Up @@ -43,19 +43,19 @@ def pytest_collection(session):
vvm.install_vyper(version)


# auto-parametrize the all_versions fixture with all target vyper versions
# auto-parametrize the vyper_version fixture with all target vyper versions
def pytest_generate_tests(metafunc):
if "all_versions" in metafunc.fixturenames:
if "vyper_version" 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)
metafunc.parametrize("vyper_version", versions, indirect=True)


@pytest.fixture
def all_versions(request):
def vyper_version(request):
"""
Run a test against all vyper versions.
"""
Expand All @@ -65,11 +65,13 @@ def all_versions(request):


@pytest.fixture
def foo_source(all_versions):
visibility = "external" if all_versions >= Version("0.2.0") else "public"
interface = "IERC20" if all_versions >= Version("0.4.0a") else "ERC20"
import_path = "ethereum.ercs" if all_versions >= Version("0.4.0a") else "vyper.interfaces"
def foo_source(vyper_version):
visibility = "external" if vyper_version >= Version("0.2.0") else "public"
interface = "IERC20" if vyper_version >= Version("0.4.0a") else "ERC20"
import_path = "ethereum.ercs" if vyper_version >= Version("0.4.0a") else "vyper.interfaces"
pragma_version = "pragma version" if vyper_version >= Version("0.3.8") else "@version"
yield f"""
#{pragma_version} {vyper_version}
from {import_path} import {interface}
@{visibility}
Expand All @@ -79,16 +81,16 @@ def foo() -> int128:


@pytest.fixture
def foo_path(tmp_path_factory, foo_source, all_versions):
source = tmp_path_factory.getbasetemp().joinpath(f"Foo-{all_versions}.sol")
def foo_path(tmp_path_factory, foo_source, vyper_version):
source = tmp_path_factory.getbasetemp().joinpath(f"Foo-{vyper_version}.vy")
if not source.exists():
with source.open("w") as fp:
fp.write(foo_source)
return source


@pytest.fixture
def input_json(all_versions):
def input_json(vyper_version):
json = {
"language": "Vyper",
"sources": {},
Expand Down
22 changes: 18 additions & 4 deletions tests/test_compile_source.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,15 +4,15 @@
import vvm


def test_compile_source(foo_source, all_versions):
if Version("0.4.0b1") <= all_versions <= Version("0.4.0b5"):
def test_compile_source(foo_source, vyper_version):
if Version("0.4.0b1") <= vyper_version <= Version("0.4.0b5"):
pytest.skip("vyper 0.4.0b1 to 0.4.0b5 have a bug with combined_json")
output = vvm.compile_source(foo_source)
assert "<stdin>" in output


def test_compile_files(foo_path, all_versions):
if Version("0.4.0b1") <= all_versions <= Version("0.4.0b5"):
def test_compile_files(foo_path, vyper_version):
if Version("0.4.0b1") <= vyper_version <= Version("0.4.0b5"):
pytest.skip("vyper 0.4.0b1 to 0.4.0b5 have a bug with combined_json")
output = vvm.compile_files([foo_path])
assert foo_path.as_posix() in output
Expand All @@ -35,3 +35,17 @@ def foo() -> int128:
return 42
"""
vvm.compile_source(source, vyper_version=version_str)


def test_compile_metadata(foo_source, vyper_version):
if vyper_version <= Version("0.3.1"):
pytest.skip("metadata output not supported in vyper < 0.3.2")
output = vvm.compile_source(foo_source, output_format="metadata")
assert "function_info" in output


def test_compile_metadata_from_file(foo_path, vyper_version):
if vyper_version <= Version("0.3.1"):
pytest.skip("metadata output not supported in vyper < 0.3.2")
output = vvm.compile_files([foo_path], output_format="metadata")
assert "function_info" in output
6 changes: 3 additions & 3 deletions tests/test_install.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import vvm


def test_get_installed_vyper_versions(all_versions):
assert "exe" not in str(all_versions)
assert all_versions in vvm.install.get_installed_vyper_versions()
def test_get_installed_vyper_versions(vyper_version):
assert "exe" not in str(vyper_version)
assert vyper_version in vvm.install.get_installed_vyper_versions()
64 changes: 41 additions & 23 deletions vvm/main.py
Original file line number Diff line number Diff line change
Expand Up @@ -28,8 +28,9 @@ def compile_source(
base_path: Union[Path, str] = None,
evm_version: str = None,
vyper_binary: Union[str, Path] = None,
vyper_version: Version = None,
) -> Dict:
vyper_version: Union[str, Version, None] = None,
output_format: str = None,
) -> Any:
"""
Compile a Vyper contract.
Expand All @@ -51,34 +52,42 @@ def compile_source(
vyper_version: Version, optional
`vyper` version to use. If not given, the currently active version is used.
Ignored if `vyper_binary` is also given.
output_format: str, optional
Output format of the compiler. See `vyper --help` for more information.
Returns
-------
Dict
Compiler output. The source file name is given as `<stdin>`.
Any
Compiler output (depends on `output_format`).
For JSON output the return type is a dictionary, otherwise it is a string.
"""
source_path = tempfile.mkstemp(suffix=".vy", prefix="vyper-", text=True)[1]
with open(source_path, "w") as fp:
fp.write(source)

compiler_data = _compile(
vyper_binary=vyper_binary,
vyper_version=vyper_version,
source_files=[source_path],
base_path=base_path,
evm_version=evm_version,
)
with tempfile.NamedTemporaryFile(suffix=".vy", prefix="vyper-") as source_file:
source_file.write(source.encode())
source_file.flush()

compiler_data = _compile(
vyper_binary=vyper_binary,
vyper_version=vyper_version,
source_files=[source_file.name],
base_path=base_path,
evm_version=evm_version,
output_format=output_format,
)

return {"<stdin>": list(compiler_data.values())[0]}
if output_format in ("combined_json", None):
return {"<stdin>": list(compiler_data.values())[0]}
return compiler_data


def compile_files(
source_files: Union[List, Path, str],
base_path: Union[Path, str] = None,
evm_version: str = None,
vyper_binary: Union[str, Path] = None,
vyper_version: Version = None,
) -> Dict:
vyper_version: Union[str, Version, None] = None,
output_format: str = None,
) -> Any:
"""
Compile one or more Vyper source files.
Expand All @@ -100,36 +109,45 @@ def compile_files(
vyper_version: Version, optional
`vyper` version to use. If not given, the currently active version is used.
Ignored if `vyper_binary` is also given.
output_format: str, optional
Output format of the compiler. See `vyper --help` for more information.
Returns
-------
Dict
Compiler output
Any
Compiler output (depends on `output_format`).
For JSON output the return type is a dictionary, otherwise it is a string.
"""
return _compile(
vyper_binary=vyper_binary,
vyper_version=vyper_version,
source_files=source_files,
base_path=base_path,
evm_version=evm_version,
output_format=output_format,
)


def _compile(
base_path: Union[str, Path, None],
vyper_binary: Union[str, Path, None],
vyper_version: Optional[Version],
vyper_version: Union[str, Version, None],
output_format: Optional[str],
**kwargs: Any,
) -> Dict:
) -> Any:

if vyper_binary is None:
vyper_binary = get_executable(vyper_version)
if output_format is None:
output_format = "combined_json"

stdoutdata, stderrdata, command, proc = wrapper.vyper_wrapper(
vyper_binary=vyper_binary, f="combined_json", p=base_path, **kwargs
vyper_binary=vyper_binary, f=output_format, p=base_path, **kwargs
)

return json.loads(stdoutdata)
if output_format in ("combined_json", "standard_json", "metadata"):
return json.loads(stdoutdata)
return stdoutdata


def compile_standard(
Expand Down

0 comments on commit bc1581f

Please sign in to comment.