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

refactor: internal handling of imports #3655

Merged
merged 63 commits into from
Nov 6, 2023
Merged
Show file tree
Hide file tree
Changes from 51 commits
Commits
Show all changes
63 commits
Select commit Hold shift + click to select a range
8eaec10
add input bundle abstraction
charles-cooper Sep 26, 2023
6b47ee4
wip - input bundle
charles-cooper Sep 26, 2023
fd17ecb
wip - remove interface_codes
charles-cooper Sep 29, 2023
03a2ce6
remove dead code
charles-cooper Oct 20, 2023
0405874
wip
charles-cooper Oct 20, 2023
5d4d938
Merge branch 'master' into refactor/imports
charles-cooper Oct 20, 2023
5b22274
wip - thread input bundle through compiler
charles-cooper Oct 20, 2023
d8801c5
wip - more threading, update add_import helper
charles-cooper Oct 20, 2023
6d9695f
wip - search path as context manager
charles-cooper Oct 21, 2023
07eba74
small refactor
charles-cooper Oct 21, 2023
0fbf89c
refactor builtins
charles-cooper Oct 21, 2023
bf7f068
slight refactor of load_file
charles-cooper Oct 21, 2023
0ecfc5c
slight hygiene
charles-cooper Oct 21, 2023
37c25b1
move builtin interfaces to be `.vy` files
charles-cooper Oct 21, 2023
8af2795
fix abi input
charles-cooper Oct 21, 2023
32f11fd
wip - another fix
charles-cooper Oct 21, 2023
7c4a0e4
fix typo
charles-cooper Oct 21, 2023
662ca5f
wip - clean up compile_json.py
charles-cooper Oct 21, 2023
266c1dc
fix json output with paths
charles-cooper Oct 22, 2023
2f4f018
simplify keccak check
charles-cooper Oct 29, 2023
771061f
merge sources and interfaces for standard input json
charles-cooper Oct 29, 2023
28aefcb
refactor input_bundle.py
charles-cooper Oct 29, 2023
e78e81a
use input_bundle.load_file in vyper_compile.py
charles-cooper Oct 29, 2023
a2b21b7
clean up _resolve_import
charles-cooper Oct 29, 2023
38865ad
fix some typing/lint issues
charles-cooper Oct 29, 2023
bdfce82
rewrite builtin loading
charles-cooper Oct 31, 2023
ed98b0d
fix inheritance on JSONInputBundle
charles-cooper Oct 31, 2023
91487b9
fix error messages
charles-cooper Nov 1, 2023
159e10c
api fixes for json input
charles-cooper Nov 1, 2023
ccf6b74
fix lint
charles-cooper Nov 1, 2023
ee25e4f
wip - fix some mypy things
charles-cooper Nov 1, 2023
442f304
wip - remove compile_codes API
charles-cooper Nov 2, 2023
3f266cb
remove some mypy hints
charles-cooper Nov 2, 2023
36f974d
some fixes for vyper cli
charles-cooper Nov 2, 2023
76b980a
fix for standard json
charles-cooper Nov 2, 2023
0681a64
hygiene, use relpath for builtins
charles-cooper Nov 3, 2023
89ec6b8
formatting, notes
charles-cooper Nov 3, 2023
9124df3
fix some lint
charles-cooper Nov 3, 2023
44f8d74
fix some tests
charles-cooper Nov 3, 2023
7d25342
redo how ABI files are handled
charles-cooper Nov 3, 2023
306c63c
fix vyper_compile tests
charles-cooper Nov 3, 2023
d70eb01
remove interface_codes from compile_code calls
charles-cooper Nov 3, 2023
48d8cce
update json tests, remove code referencing get_interfaces
charles-cooper Nov 4, 2023
6669300
refactor input bundle json parsing
charles-cooper Nov 4, 2023
5cda829
fix a bunch of interface tests
charles-cooper Nov 4, 2023
08be231
remove a dead function
charles-cooper Nov 4, 2023
021bc07
fix a bunch of tests
charles-cooper Nov 5, 2023
8e96f3a
fix a bunch of tests
charles-cooper Nov 5, 2023
79ce767
fix some tests, mypy
charles-cooper Nov 5, 2023
6ba4260
fix some tests, lint
charles-cooper Nov 5, 2023
83a27e6
fix mypy
charles-cooper Nov 5, 2023
0a1cdff
fix some tests
charles-cooper Nov 5, 2023
f94412b
fix more tests
charles-cooper Nov 5, 2023
508a94b
rename a test file
charles-cooper Nov 5, 2023
e18de7b
add some tests for input bundles
charles-cooper Nov 5, 2023
fdfed5e
clean up vyper_compile tests
charles-cooper Nov 6, 2023
abe9f7d
simplify tests/cli/vyper_json
charles-cooper Nov 6, 2023
a96c53e
merge test_get_inputs.py and test_interfaces.py
charles-cooper Nov 6, 2023
25f8b29
clean up test_compile_json
charles-cooper Nov 6, 2023
f86977c
fix lint
charles-cooper Nov 6, 2023
8bb906c
fix a bad loop variable
charles-cooper Nov 6, 2023
a54363d
small cleanup
charles-cooper Nov 6, 2023
42ea90f
add some commentary
charles-cooper Nov 6, 2023
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
13 changes: 7 additions & 6 deletions tests/base_conftest.py
Original file line number Diff line number Diff line change
Expand Up @@ -112,16 +112,18 @@ def w3(tester):
return w3


def _get_contract(w3, source_code, optimize, *args, override_opt_level=None, **kwargs):
def _get_contract(
w3, source_code, optimize, *args, override_opt_level=None, input_bundle=None, **kwargs
):
settings = Settings()
settings.evm_version = kwargs.pop("evm_version", None)
settings.optimize = override_opt_level or optimize
out = compiler.compile_code(
source_code,
# test that metadata and natspecs get generated
["abi", "bytecode", "metadata", "userdoc", "devdoc"],
output_formats=["abi", "bytecode", "metadata", "userdoc", "devdoc"],
settings=settings,
interface_codes=kwargs.pop("interface_codes", None),
input_bundle=input_bundle,
show_gas_estimates=True, # Enable gas estimates for testing
)
parse_vyper_source(source_code) # Test grammar.
Expand All @@ -145,7 +147,6 @@ def _deploy_blueprint_for(w3, source_code, optimize, initcode_prefix=b"", **kwar
out = compiler.compile_code(
source_code,
["abi", "bytecode"],
interface_codes=kwargs.pop("interface_codes", None),
settings=settings,
show_gas_estimates=True, # Enable gas estimates for testing
)
Expand Down Expand Up @@ -187,10 +188,10 @@ def deploy_blueprint_for(source_code, *args, **kwargs):

@pytest.fixture(scope="module")
def get_contract(w3, optimize):
def get_contract(source_code, *args, **kwargs):
def fn(source_code, *args, **kwargs):
return _get_contract(w3, source_code, optimize, *args, **kwargs)

return get_contract
return fn


@pytest.fixture
Expand Down
8 changes: 5 additions & 3 deletions tests/cli/vyper_compile/test_compile_files.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
from pathlib import Path

import pytest

from vyper.cli.vyper_compile import compile_files
Expand All @@ -19,10 +21,10 @@ def test_combined_json_keys(tmp_path):
"userdoc",
"devdoc",
}
compile_data = compile_files([bar_path], ["combined_json"], root_folder=tmp_path)
compile_data = compile_files(["bar.vy"], ["combined_json"], root_folder=tmp_path)

assert set(compile_data.keys()) == {"bar.vy", "version"}
assert set(compile_data["bar.vy"].keys()) == combined_keys
assert set(compile_data.keys()) == {Path("bar.vy"), "version"}
assert set(compile_data[Path("bar.vy")].keys()) == combined_keys


def test_invalid_root_path():
Expand Down
31 changes: 3 additions & 28 deletions tests/cli/vyper_compile/test_import_paths.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import pytest

from vyper.cli.vyper_compile import compile_files, get_interface_file_path
from vyper.cli.vyper_compile import compile_files

FOO_CODE = """
{}
Expand Down Expand Up @@ -117,9 +117,8 @@ def test_import_parent_folder(tmp_path, assert_compile_failed):
fp.write(BAR_CODE)

assert compile_files([foo_path], ["combined_json"], root_folder=tmp_path)
# Cannot perform relative import outside of base folder
with pytest.raises(FileNotFoundError):
compile_files([foo_path], ["combined_json"], root_folder=tmp_path.joinpath("contracts"))
# perform relative import outside of base folder
compile_files([foo_path], ["combined_json"], root_folder=tmp_path.joinpath("contracts"))


META_IMPORT_STMT = [
Expand Down Expand Up @@ -224,30 +223,6 @@ def test_local_namespace(tmp_path):
assert compile_files(compile_paths, ["combined_json"], root_folder=tmp_path)


def test_get_interface_file_path(tmp_path):
for file_name in ("foo.vy", "foo.json", "bar.vy", "baz.json", "potato"):
with tmp_path.joinpath(file_name).open("w") as fp:
fp.write("")

tmp_path.joinpath("interfaces").mkdir()
for file_name in ("interfaces/foo.json", "interfaces/bar"):
with tmp_path.joinpath(file_name).open("w") as fp:
fp.write("")

base_paths = [tmp_path, tmp_path.joinpath("interfaces")]
assert get_interface_file_path(base_paths, "foo") == tmp_path.joinpath("foo.vy")
assert get_interface_file_path(base_paths, "bar") == tmp_path.joinpath("bar.vy")
assert get_interface_file_path(base_paths, "baz") == tmp_path.joinpath("baz.json")

base_paths = [tmp_path.joinpath("interfaces"), tmp_path]
assert get_interface_file_path(base_paths, "foo") == tmp_path.joinpath("interfaces/foo.json")
assert get_interface_file_path(base_paths, "bar") == tmp_path.joinpath("bar.vy")
assert get_interface_file_path(base_paths, "baz") == tmp_path.joinpath("baz.json")

with pytest.raises(Exception):
get_interface_file_path(base_paths, "potato")


def test_compile_outside_root_path(tmp_path):
foo_path = tmp_path.joinpath("foo.vy")
with foo_path.open("w") as fp:
Expand Down
23 changes: 15 additions & 8 deletions tests/cli/vyper_json/test_compile_from_input_dict.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
#!/usr/bin/env python3

from copy import deepcopy
from pathlib import PurePath

import pytest

Expand Down Expand Up @@ -48,7 +49,6 @@ def oopsie(a: uint256) -> bool:
"inputs": [{"type": "uint256", "name": "a"}],
"stateMutability": "nonpayable",
"type": "function",
"gas": 313,
}
]

Expand All @@ -58,14 +58,14 @@ def oopsie(a: uint256) -> bool:
"contracts/foo.vy": {"content": FOO_CODE},
"contracts/bar.vy": {"content": BAR_CODE},
},
"interfaces": {"contracts/bar.json": {"abi": BAR_ABI}},
"interfaces": {"contracts/ibar.json": {"abi": BAR_ABI}},
"settings": {"outputSelection": {"*": ["*"]}},
}


def test_root_folder_not_exists():
with pytest.raises(FileNotFoundError):
compile_from_input_dict({}, root_folder="/path/that/does/not/exist")
compile_from_input_dict(INPUT_JSON, root_folder="/path/that/does/not/exist")


def test_wrong_language():
Expand All @@ -87,7 +87,7 @@ def test_exc_handler_to_dict_syntax():
assert "errors" in result
assert len(result["errors"]) == 1
error = result["errors"][0]
assert error["component"] == "parser"
assert error["component"] == "compiler", error
assert error["type"] == "SyntaxException"


Expand All @@ -114,14 +114,21 @@ def test_source_ids_increment():
input_json = deepcopy(INPUT_JSON)
input_json["settings"]["outputSelection"] = {"*": ["evm.deployedBytecode.sourceMap"]}
result, _ = compile_from_input_dict(input_json)
assert result["contracts/bar.vy"]["source_map"]["pc_pos_map_compressed"].startswith("-1:-1:0")
assert result["contracts/foo.vy"]["source_map"]["pc_pos_map_compressed"].startswith("-1:-1:1")
assert result[PurePath("contracts/foo.vy")]["source_map"]["pc_pos_map_compressed"].startswith(
"-1:-1:0"
)
assert result[PurePath("contracts/bar.vy")]["source_map"]["pc_pos_map_compressed"].startswith(
"-1:-1:1"
)


def test_outputs():
result, _ = compile_from_input_dict(INPUT_JSON)
assert sorted(result.keys()) == ["contracts/bar.vy", "contracts/foo.vy"]
assert sorted(result["contracts/bar.vy"].keys()) == sorted(set(TRANSLATE_MAP.values()))
assert list(result.keys()) == [PurePath("contracts/foo.vy"), PurePath("contracts/bar.vy")]

output_formats = list(TRANSLATE_MAP.values())
output_formats.append("source_id")
assert sorted(result[PurePath("contracts/bar.vy")].keys()) == sorted(set(output_formats))


def test_relative_import_paths():
Expand Down
2 changes: 1 addition & 1 deletion tests/cli/vyper_json/test_compile_json.py
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ def bar(a: uint256) -> bool:
"contracts/foo.vy": {"content": FOO_CODE},
"contracts/bar.vy": {"content": BAR_CODE},
},
"interfaces": {"contracts/bar.json": {"abi": BAR_ABI}},
"interfaces": {"contracts/ibar.json": {"abi": BAR_ABI}},
"settings": {"outputSelection": {"*": ["*"]}},
}

Expand Down
30 changes: 16 additions & 14 deletions tests/cli/vyper_json/test_get_contracts.py
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
#!/usr/bin/env python3
from pathlib import PurePath

import pytest

from vyper.cli.vyper_json import get_input_dict_contracts
from vyper.cli.vyper_json import get_inputs
from vyper.exceptions import JSONError
from vyper.utils import keccak256

Expand All @@ -23,49 +23,51 @@ def bar(a: uint256) -> bool:

def test_no_sources():
with pytest.raises(KeyError):
get_input_dict_contracts({})
get_inputs({})


def test_contracts_urls():
with pytest.raises(JSONError):
get_input_dict_contracts({"sources": {"foo.vy": {"urls": ["https://foo.code.com/"]}}})
get_inputs({"sources": {"foo.vy": {"urls": ["https://foo.code.com/"]}}})


def test_contracts_no_content_key():
with pytest.raises(JSONError):
get_input_dict_contracts({"sources": {"foo.vy": FOO_CODE}})
get_inputs({"sources": {"foo.vy": FOO_CODE}})


def test_contracts_keccak():
hash_ = keccak256(FOO_CODE.encode()).hex()

input_json = {"sources": {"foo.vy": {"content": FOO_CODE, "keccak256": hash_}}}
get_input_dict_contracts(input_json)
get_inputs(input_json)

input_json["sources"]["foo.vy"]["keccak256"] = "0x" + hash_
get_input_dict_contracts(input_json)
get_inputs(input_json)

input_json["sources"]["foo.vy"]["keccak256"] = "0x1234567890"
with pytest.raises(JSONError):
get_input_dict_contracts(input_json)
get_inputs(input_json)


def test_contracts_bad_path():
def test_contracts_outside_pwd():
input_json = {"sources": {"../foo.vy": {"content": FOO_CODE}}}
with pytest.raises(JSONError):
get_input_dict_contracts(input_json)
get_inputs(input_json)


def test_contract_collision():
# ./foo.vy and foo.vy will resolve to the same path
input_json = {"sources": {"./foo.vy": {"content": FOO_CODE}, "foo.vy": {"content": FOO_CODE}}}
with pytest.raises(JSONError):
get_input_dict_contracts(input_json)
get_inputs(input_json)


def test_contracts_return_value():
input_json = {
"sources": {"foo.vy": {"content": FOO_CODE}, "contracts/bar.vy": {"content": BAR_CODE}}
}
result = get_input_dict_contracts(input_json)
assert result == {"foo.vy": FOO_CODE, "contracts/bar.vy": BAR_CODE}
result = get_inputs(input_json)
assert result == {
PurePath("foo.vy"): {"content": FOO_CODE},
PurePath("contracts/bar.vy"): {"content": BAR_CODE},
}
Loading