generated from ApeWorX/project-template
-
-
Notifications
You must be signed in to change notification settings - Fork 9
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
* feat: contract flattener * fix: add missing dep vyper * fix: try lowering vyper min version for Python 3.8 support * fix(test): install necessary vyper versions in test * fix: compiler version handling in compiler.compile_code() * style(lint): unused import * fix(test): explicitly install compiler in test_pc_map * feat: adds `ape vyper flatten` command * test: add CLI test for flattener * chore: bump minimum eth-ape version to 0.7.12 * docs: adds Contract Flattening section to README * chore: bump eth-ape minimum ersion to 0.7.13 * fix(docs): fix warning directive in README * docs: update return value docstring Co-authored-by: antazoey <[email protected]> * docs: speeling Co-authored-by: antazoey <[email protected]> * refactor: splitlines() * refactor: limit `vyper flatten` command to vyper only Co-authored-by: antazoey <[email protected]> * fix(docs): bad bug report link Co-authored-by: antazoey <[email protected]> * style(docs): period Co-authored-by: antazoey <[email protected]> * fix(docs): comment spelling Co-authored-by: antazoey <[email protected]> * fix(docs): comment spelling Co-authored-by: antazoey <[email protected]> * refactor: splitlines Co-authored-by: antazoey <[email protected]> * fix: missing type hint Co-authored-by: antazoey <[email protected]> * docs: how to format returns Co-authored-by: antazoey <[email protected]> * refactor: not is None Co-authored-by: antazoey <[email protected]> * refactor: check with installed versions when compiling before installing during no-pragma fallback --------- Co-authored-by: antazoey <[email protected]>
- Loading branch information
1 parent
3555cb4
commit 15b7598
Showing
10 changed files
with
530 additions
and
10 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,25 @@ | ||
from pathlib import Path | ||
|
||
import ape | ||
import click | ||
from ape.cli import ape_cli_context | ||
|
||
|
||
@click.group | ||
def cli(): | ||
"""`vyper` command group""" | ||
|
||
|
||
@cli.command(short_help="Flatten select contract source files") | ||
@ape_cli_context() | ||
@click.argument("CONTRACT", type=click.Path(exists=True, resolve_path=True)) | ||
@click.argument("OUTFILE", type=click.Path(exists=False, resolve_path=True, writable=True)) | ||
def flatten(cli_ctx, contract: Path, outfile: Path): | ||
""" | ||
Flatten a contract into a single file | ||
""" | ||
with Path(outfile).open("w") as fout: | ||
content = ape.compilers.vyper.flatten_contract( | ||
Path(contract), base_path=ape.project.contracts_folder | ||
) | ||
fout.write(str(content)) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,101 @@ | ||
"""Utilities for dealing with Vyper AST""" | ||
|
||
from typing import List | ||
|
||
from ethpm_types import ABI, MethodABI | ||
from ethpm_types.abi import ABIType | ||
from vyper.ast import parse_to_ast # type: ignore | ||
from vyper.ast.nodes import FunctionDef, Module, Name, Subscript # type: ignore | ||
|
||
DEFAULT_VYPER_MUTABILITY = "nonpayable" | ||
DECORATOR_MUTABILITY = { | ||
"pure", # Function does not read contract state or environment variables | ||
"view", # Function does not alter contract state | ||
"payable", # Function is able to receive Ether and may alter state | ||
"nonpayable", # Function may alter sate | ||
} | ||
|
||
|
||
def funcdef_decorators(funcdef: FunctionDef) -> List[str]: | ||
return [d.id for d in funcdef.get("decorator_list") or []] | ||
|
||
|
||
def funcdef_inputs(funcdef: FunctionDef) -> List[ABIType]: | ||
"""Get a FunctionDef's defined input args""" | ||
args = funcdef.get("args") | ||
# TODO: Does Vyper allow complex input types, like structs and arrays? | ||
return ( | ||
[ABIType.model_validate({"name": arg.arg, "type": arg.annotation.id}) for arg in args.args] | ||
if args | ||
else [] | ||
) | ||
|
||
|
||
def funcdef_outputs(funcdef: FunctionDef) -> List[ABIType]: | ||
"""Get a FunctionDef's outputs, or return values""" | ||
returns = funcdef.get("returns") | ||
|
||
if not returns: | ||
return [] | ||
|
||
if isinstance(returns, Name): | ||
# TODO: Structs fall in here. I think they're supposed to be a tuple of types in the ABI. | ||
# Need to dig into that more. | ||
return [ABIType.model_validate({"type": returns.id})] | ||
|
||
elif isinstance(returns, Subscript): | ||
# An array type | ||
length = returns.slice.value.value | ||
array_type = returns.value.id | ||
# TOOD: Is this an acurrate way to define a fixed length array for ABI? | ||
return [ABIType.model_validate({"type": f"{array_type}[{length}]"})] | ||
|
||
raise NotImplementedError(f"Unhandled return type {type(returns)}") | ||
|
||
|
||
def funcdef_state_mutability(funcdef: FunctionDef) -> str: | ||
"""Get a FunctionDef's declared state mutability""" | ||
for decorator in funcdef_decorators(funcdef): | ||
if decorator in DECORATOR_MUTABILITY: | ||
return decorator | ||
return DEFAULT_VYPER_MUTABILITY | ||
|
||
|
||
def funcdef_is_external(funcdef: FunctionDef) -> bool: | ||
"""Check if a FunctionDef is declared external""" | ||
for decorator in funcdef_decorators(funcdef): | ||
if decorator == "external": | ||
return True | ||
return False | ||
|
||
|
||
def funcdef_to_abi(func: FunctionDef) -> ABI: | ||
"""Return a MethodABI instance for a Vyper FunctionDef""" | ||
return MethodABI.model_validate( | ||
{ | ||
"name": func.get("name"), | ||
"inputs": funcdef_inputs(func), | ||
"outputs": funcdef_outputs(func), | ||
"stateMutability": funcdef_state_mutability(func), | ||
} | ||
) | ||
|
||
|
||
def module_to_abi(module: Module) -> List[ABI]: | ||
""" | ||
Create a list of MethodABIs from a Vyper AST Module instance. | ||
""" | ||
abi = [] | ||
for child in module.get_children(): | ||
if isinstance(child, FunctionDef): | ||
abi.append(funcdef_to_abi(child)) | ||
return abi | ||
|
||
|
||
def source_to_abi(source: str) -> List[ABI]: | ||
""" | ||
Given Vyper source code, return a list of Ape ABI elements needed for an external interface. | ||
This currently does not include complex types or events. | ||
""" | ||
module = parse_to_ast(source) | ||
return module_to_abi(module) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.