Skip to content

Commit

Permalink
Merge branch 'master' into feat/improve-event-kwargs-recommendation
Browse files Browse the repository at this point in the history
  • Loading branch information
charles-cooper authored Oct 17, 2024
2 parents c4cc839 + b3ea663 commit 106bbfa
Show file tree
Hide file tree
Showing 72 changed files with 1,131 additions and 678 deletions.
1 change: 1 addition & 0 deletions .github/ISSUE_TEMPLATE/bug.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
---
name: Bug Report
about: Any general feedback or bug reports about the Vyper Compiler. No new features proposals.
labels: ["needs triage"]
---

### Version Information
Expand Down
1 change: 1 addition & 0 deletions .github/ISSUE_TEMPLATE/vip.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
---
name: Vyper Improvement Proposal (VIP)
about: This is the suggested template for new VIPs.
labels: ["needs triage"]
---
## Simple Summary
"If you can't explain it simply, you don't understand it well enough." Provide a simplified and layman-accessible explanation of the VIP.
Expand Down
8 changes: 8 additions & 0 deletions .github/workflows/build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,10 @@ jobs:
# need to fetch unshallow so that setuptools_scm can infer the version
fetch-depth: 0

# debug
- name: Git shorthash
run: git rev-parse --short HEAD

- name: Python
uses: actions/setup-python@v5
with:
Expand Down Expand Up @@ -60,6 +64,10 @@ jobs:
# need to fetch unshallow so that setuptools_scm can infer the version
fetch-depth: 0

# debug
- name: Git shorthash
run: git rev-parse --short HEAD

- name: Python
uses: actions/setup-python@v5
with:
Expand Down
8 changes: 8 additions & 0 deletions .github/workflows/release-pypi.yml
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,14 @@ jobs:

steps:
- uses: actions/checkout@v4
with:
# fetch unshallow so commit hash matches github release.
# see https://github.com/vyperlang/vyper/blob/8f9a8cac49aafb3fbc9dde78f0f6125c390c32f0/.github/workflows/build.yml#L27-L32
fetch-depth: 0

# debug
- name: Git shorthash
run: git rev-parse --short HEAD

- name: Python
uses: actions/setup-python@v5
Expand Down
3 changes: 2 additions & 1 deletion docs/types.rst
Original file line number Diff line number Diff line change
Expand Up @@ -359,11 +359,12 @@ A byte array with a max size.
The syntax being ``Bytes[maxLen]``, where ``maxLen`` is an integer which denotes the maximum number of bytes.
On the ABI level the Fixed-size bytes array is annotated as ``bytes``.

Bytes literals may be given as bytes strings.
Bytes literals may be given as bytes strings or as hex strings.

.. code-block:: vyper
bytes_string: Bytes[100] = b"\x01"
bytes_string: Bytes[100] = x"01"
.. index:: !string

Expand Down
8 changes: 1 addition & 7 deletions tests/conftest.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
from tests.utils import working_directory
from vyper import compiler
from vyper.codegen.ir_node import IRnode
from vyper.compiler.input_bundle import FilesystemInputBundle, InputBundle
from vyper.compiler.input_bundle import FilesystemInputBundle
from vyper.compiler.settings import OptimizationLevel, Settings, set_global_settings
from vyper.exceptions import EvmVersionException
from vyper.ir import compile_ir, optimizer
Expand Down Expand Up @@ -166,12 +166,6 @@ def fn(sources_dict):
return fn


# for tests which just need an input bundle, doesn't matter what it is
@pytest.fixture
def dummy_input_bundle():
return InputBundle([])


@pytest.fixture(scope="module")
def gas_limit():
# set absurdly high gas limit so that london basefee never adjusts
Expand Down
4 changes: 2 additions & 2 deletions tests/functional/codegen/features/test_clampers.py
Original file line number Diff line number Diff line change
Expand Up @@ -429,7 +429,7 @@ def foo(b: int128[6][1][2]) -> int128[6][1][2]:

c = get_contract(code)
with tx_failed():
_make_tx(env, c.address, "foo(int128[6][1][2]])", values)
_make_tx(env, c.address, "foo(int128[6][1][2])", values)


@pytest.mark.parametrize("value", [0, 1, -1, 2**127 - 1, -(2**127)])
Expand All @@ -453,7 +453,7 @@ def test_int128_dynarray_clamper_failing(env, tx_failed, get_contract, bad_value
# ensure the invalid value is detected at all locations in the array
code = """
@external
def foo(b: int128[5]) -> int128[5]:
def foo(b: DynArray[int128, 5]) -> DynArray[int128, 5]:
return b
"""

Expand Down
28 changes: 28 additions & 0 deletions tests/functional/codegen/modules/test_interface_imports.py
Original file line number Diff line number Diff line change
Expand Up @@ -58,3 +58,31 @@ def foo() -> bool:
c = get_contract(main, input_bundle=input_bundle)

assert c.foo() is True


def test_import_interface_flags(make_input_bundle, get_contract):
ifaces = """
flag Foo:
BOO
MOO
POO
interface IFoo:
def foo() -> Foo: nonpayable
"""

contract = """
import ifaces
implements: ifaces
@external
def foo() -> ifaces.Foo:
return ifaces.Foo.POO
"""

input_bundle = make_input_bundle({"ifaces.vyi": ifaces})

c = get_contract(contract, input_bundle=input_bundle)

assert c.foo() == 4
48 changes: 48 additions & 0 deletions tests/functional/codegen/test_interfaces.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
)


# TODO CMC 2024-10-13: this should probably be in tests/unit/compiler/
def test_basic_extract_interface():
code = """
# Events
Expand All @@ -22,6 +23,7 @@ def test_basic_extract_interface():
_to: address
_value: uint256
# Functions
@view
Expand All @@ -37,6 +39,7 @@ def allowance(_owner: address, _spender: address) -> (uint256, uint256):
assert code_pass.strip() == out.strip()


# TODO CMC 2024-10-13: this should probably be in tests/unit/compiler/
def test_basic_extract_external_interface():
code = """
@view
Expand Down Expand Up @@ -68,6 +71,7 @@ def test(_owner: address): nonpayable
assert interface.strip() == out.strip()


# TODO CMC 2024-10-13: should probably be in syntax tests
def test_basic_interface_implements(assert_compile_failed):
code = """
from ethereum.ercs import IERC20
Expand All @@ -82,6 +86,7 @@ def test() -> bool:
assert_compile_failed(lambda: compile_code(code), InterfaceViolation)


# TODO CMC 2024-10-13: should probably be in syntax tests
def test_external_interface_parsing(make_input_bundle, assert_compile_failed):
interface_code = """
@external
Expand Down Expand Up @@ -126,6 +131,7 @@ def foo() -> uint256:
compile_code(not_implemented_code, input_bundle=input_bundle)


# TODO CMC 2024-10-13: should probably be in syntax tests
def test_log_interface_event(make_input_bundle, assert_compile_failed):
interface_code = """
event Foo:
Expand Down Expand Up @@ -160,6 +166,7 @@ def bar() -> uint256:
]


# TODO CMC 2024-10-13: should probably be in syntax tests
@pytest.mark.parametrize("code,filename", VALID_IMPORT_CODE)
def test_extract_file_interface_imports(code, filename, make_input_bundle):
input_bundle = make_input_bundle({filename: ""})
Expand All @@ -177,6 +184,7 @@ def test_extract_file_interface_imports(code, filename, make_input_bundle):
]


# TODO CMC 2024-10-13: should probably be in syntax tests
@pytest.mark.parametrize("code,exception_type", BAD_IMPORT_CODE)
def test_extract_file_interface_imports_raises(
code, exception_type, assert_compile_failed, make_input_bundle
Expand Down Expand Up @@ -726,3 +734,43 @@ def bar() -> uint256:
c = get_contract(code, input_bundle=input_bundle)

assert c.foo() == c.bar() == 1


def test_interface_with_structures():
code = """
struct MyStruct:
a: address
b: uint256
event Transfer:
sender: indexed(address)
receiver: indexed(address)
value: uint256
struct Voter:
weight: int128
voted: bool
delegate: address
vote: int128
@external
def bar():
pass
event Buy:
buyer: indexed(address)
buy_order: uint256
@external
@view
def foo(s: MyStruct) -> MyStruct:
return s
"""

out = compile_code(code, contract_path="code.vy", output_formats=["interface"])["interface"]

assert "# Structs" in out
assert "struct MyStruct:" in out
assert "b: uint256" in out
assert "struct Voter:" in out
assert "voted: bool" in out
2 changes: 1 addition & 1 deletion tests/functional/codegen/types/numbers/test_decimals.py
Original file line number Diff line number Diff line change
Expand Up @@ -299,7 +299,7 @@ def foo():
compile_code(code)


def test_replace_decimal_nested_intermediate_underflow(dummy_input_bundle):
def test_replace_decimal_nested_intermediate_underflow():
code = """
@external
def foo():
Expand Down
22 changes: 22 additions & 0 deletions tests/functional/codegen/types/test_bytes.py
Original file line number Diff line number Diff line change
Expand Up @@ -259,6 +259,28 @@ def test2(l: bytes{m} = {vyper_literal}) -> bool:
assert c.test2(vyper_literal) is True


@pytest.mark.parametrize("m,val", [(2, "ab"), (3, "ab"), (4, "abcd")])
def test_native_hex_literals(get_contract, m, val):
vyper_literal = bytes.fromhex(val)
code = f"""
@external
def test() -> bool:
l: Bytes[{m}] = x"{val}"
return l == {vyper_literal}
@external
def test2(l: Bytes[{m}] = x"{val}") -> bool:
return l == {vyper_literal}
"""
print(code)

c = get_contract(code)

assert c.test() is True
assert c.test2() is True
assert c.test2(vyper_literal) is True


def test_zero_padding_with_private(get_contract):
code = """
counter: uint256
Expand Down
4 changes: 2 additions & 2 deletions tests/functional/grammar/test_grammar.py
Original file line number Diff line number Diff line change
Expand Up @@ -102,6 +102,6 @@ def has_no_docstrings(c):
max_examples=500, suppress_health_check=[HealthCheck.too_slow, HealthCheck.filter_too_much]
)
def test_grammar_bruteforce(code):
_, _, _, reformatted_code = pre_parse(code + "\n")
tree = parse_to_ast(reformatted_code)
pre_parse_result = pre_parse(code + "\n")
tree = parse_to_ast(pre_parse_result.reformatted_code)
assert isinstance(tree, Module)
9 changes: 9 additions & 0 deletions tests/functional/syntax/test_bytes.py
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,15 @@ def test() -> Bytes[1]:
(
"""
@external
def test() -> Bytes[2]:
a: Bytes[2] = x"abc"
return a
""",
SyntaxException,
),
(
"""
@external
def foo():
a: Bytes = b"abc"
""",
Expand Down
13 changes: 11 additions & 2 deletions tests/functional/syntax/test_interfaces.py
Original file line number Diff line number Diff line change
Expand Up @@ -381,13 +381,22 @@ def test_interfaces_success(good_code):


def test_imports_and_implements_within_interface(make_input_bundle):
interface_code = """
ibar_code = """
@external
def foobar():
...
"""
ifoo_code = """
import bar
input_bundle = make_input_bundle({"foo.vyi": interface_code})
implements: bar
@external
def foobar():
...
"""

input_bundle = make_input_bundle({"foo.vyi": ifoo_code, "bar.vyi": ibar_code})

code = """
import foo as Foo
Expand Down
19 changes: 19 additions & 0 deletions tests/integration/test_pickle_ast.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
import copy
import pickle

from vyper.compiler.phases import CompilerData


def test_pickle_ast():
code = """
@external
def foo():
self.bar()
y: uint256 = 5
x: uint256 = 5
def bar():
pass
"""
f = CompilerData(code)
copy.deepcopy(f.annotated_vyper_module)
pickle.loads(pickle.dumps(f.annotated_vyper_module))
4 changes: 2 additions & 2 deletions tests/unit/ast/nodes/test_hex.py
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ def foo():


@pytest.mark.parametrize("code", code_invalid_checksum)
def test_invalid_checksum(code, dummy_input_bundle):
def test_invalid_checksum(code):
with pytest.raises(InvalidLiteral):
vyper_module = vy_ast.parse_to_ast(code)
semantics.analyze_module(vyper_module, dummy_input_bundle)
semantics.analyze_module(vyper_module)
8 changes: 4 additions & 4 deletions tests/unit/ast/test_annotate_and_optimize_ast.py
Original file line number Diff line number Diff line change
Expand Up @@ -28,12 +28,12 @@ def foo() -> int128:


def get_contract_info(source_code):
_, loop_var_annotations, class_types, reformatted_code = pre_parse(source_code)
py_ast = python_ast.parse(reformatted_code)
pre_parse_result = pre_parse(source_code)
py_ast = python_ast.parse(pre_parse_result.reformatted_code)

annotate_python_ast(py_ast, reformatted_code, loop_var_annotations, class_types)
annotate_python_ast(py_ast, pre_parse_result.reformatted_code, pre_parse_result)

return py_ast, reformatted_code
return py_ast, pre_parse_result.reformatted_code


def test_it_annotates_ast_with_source_code():
Expand Down
Loading

0 comments on commit 106bbfa

Please sign in to comment.