Skip to content

Pre v0.5.0 Tweaks #34

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

Merged
merged 8 commits into from
Nov 8, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
15 changes: 15 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,21 @@

* Original logo including _ALT_ link to graviton journal article in the following tag: `<img width="345" alt="http://cds.cern.ch/record/2315186/files/scoap3-fulltext.pdf" src="https://user-images.githubusercontent.com/291133/160721859-21a3560a-0a82-4249-aa54-5ede4c60f8d2.png">`

## `v0.5.0` (_aka_ 🐘)

### Added

* Ability to handle `dryrun_accounts` in dry run executions
* New assertable dryrun properties `budgetAdded` and `budgetConsumed` including the rewiring of `cost` to be computed as `budgetConsumed - budgetAdded`

### Fixed

* New `mypy` errors arising from stricter enforcement of setting of `None` to non-optional types

### Upgraded

* Various dependencies including `py-algorand-sdk>=1.16.1`

## `v0.4.0` (_aka_ 🐕)

### Added
Expand Down
18 changes: 9 additions & 9 deletions graviton/abi_strategy.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,19 +7,19 @@
from collections import OrderedDict
import random
import string
from typing import Callable, Dict, List, Optional, Sequence, Union, cast
from typing import Callable, Dict, List, Optional, cast

from algosdk import abi, encoding

PY_TYPES = Union[bool, int, Sequence, str, bytes]
from graviton.models import PyTypes


class ABIStrategy(ABC):
@abstractmethod
def get(self) -> PY_TYPES:
def get(self) -> PyTypes:
pass

def get_many(self, n: int) -> List[PY_TYPES]:
def get_many(self, n: int) -> List[PyTypes]:
return [self.get() for _ in range(n)]


Expand Down Expand Up @@ -56,7 +56,7 @@ def __init__(self, abi_instance: abi.ABIType, dynamic_length: Optional[int] = No
self.abi_type: abi.ABIType = abi_instance
self.dynamic_length: Optional[int] = dynamic_length

def get(self) -> PY_TYPES:
def get(self) -> PyTypes:
if isinstance(self.abi_type, abi.UfixedType):
raise NotImplementedError(
f"Currently cannot get a random sample for {self.abi_type}"
Expand Down Expand Up @@ -114,16 +114,16 @@ def get(self) -> PY_TYPES:

def map(
self,
waterfall: Dict[abi.ABIType, Callable[..., PY_TYPES]],
waterfall: Dict[abi.ABIType, Callable[..., PyTypes]],
*args,
**kwargs,
) -> PY_TYPES:
) -> PyTypes:
for abi_type, call in waterfall.items():
if isinstance(self.abi_type, abi_type):
return call(*args, **kwargs)
return waterfall["DEFAULT"](*args, **kwargs)

def mutate_for_roundtrip(self, py_abi_instance: PY_TYPES) -> PY_TYPES:
def mutate_for_roundtrip(self, py_abi_instance: PyTypes) -> PyTypes:
def not_implemented(_):
raise NotImplementedError(f"Currently cannot handle type {self.abi_type}")

Expand Down Expand Up @@ -193,7 +193,7 @@ def __init__(
):
super().__init__(abi_instance, dynamic_length=dynamic_length)

def get(self) -> PY_TYPES:
def get(self) -> PyTypes:
full_random = super().get()

if not isinstance(self.abi_type, abi.UintType):
Expand Down
140 changes: 70 additions & 70 deletions graviton/blackbox.py
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@

from algosdk import atomic_transaction_composer as atc

from graviton.abi_strategy import PY_TYPES, ABIStrategy, RandomABIStrategy
from graviton.abi_strategy import PyTypes, ABIStrategy, RandomABIStrategy
from graviton.dryrun import (
assert_error,
assert_no_error,
Expand Down Expand Up @@ -267,8 +267,8 @@ class DryRunEncoder:
@classmethod
def encode_args(
cls,
args: Sequence[PY_TYPES],
abi_types: List[Optional[abi.ABIType]] = None,
args: Sequence[PyTypes],
abi_types: Optional[List[Optional[abi.ABIType]]] = None,
) -> List[ArgType]:
"""
Encoding convention for Black Box Testing.
Expand Down Expand Up @@ -348,7 +348,7 @@ def _to_bytes(

@classmethod
def _encode_arg(
cls, arg: PY_TYPES, idx: int, abi_type: Optional[abi.ABIType]
cls, arg: PyTypes, idx: int, abi_type: Optional[abi.ABIType]
) -> Union[str, bytes]:
partial = cls._partial_encode_assert(
arg, abi_type, f"problem encoding arg ({arg!r}) at index ({idx})"
Expand All @@ -369,7 +369,7 @@ def _encode_arg(

@classmethod
def _partial_encode_assert(
cls, arg: PY_TYPES, abi_type: Optional[abi.ABIType], msg: str = ""
cls, arg: PyTypes, abi_type: Optional[abi.ABIType], msg: str = ""
) -> Optional[bytes]:
"""
When have an `abi_type` is present, attempt to encode `arg` accordingly (returning `bytes`)
Expand Down Expand Up @@ -414,27 +414,27 @@ def dryrun_app(
cls,
algod: AlgodClient,
teal: str,
args: Sequence[PY_TYPES],
abi_argument_types: List[Optional[abi.ABIType]] = None,
args: Sequence[PyTypes],
abi_argument_types: Optional[List[Optional[abi.ABIType]]] = None,
abi_return_type: abi.ABIType = None,
is_app_create: bool = False,
on_complete: OnComplete = OnComplete.NoOpOC,
*,
sender: str = None,
sp: SuggestedParams = None,
index: int = None,
local_schema: StateSchema = None,
global_schema: StateSchema = None,
approval_program: str = None,
clear_program: str = None,
app_args: Sequence[Union[str, int]] = None,
accounts: List[str] = None,
foreign_apps: List[str] = None,
foreign_assets: List[str] = None,
note: str = None,
lease: str = None,
rekey_to: str = None,
extra_pages: int = None,
sender: Optional[str] = None,
sp: Optional[SuggestedParams] = None,
index: Optional[int] = None,
local_schema: Optional[StateSchema] = None,
global_schema: Optional[StateSchema] = None,
approval_program: Optional[str] = None,
clear_program: Optional[str] = None,
app_args: Optional[Sequence[Union[str, int]]] = None,
accounts: Optional[List[str]] = None,
foreign_apps: Optional[List[str]] = None,
foreign_assets: Optional[List[str]] = None,
note: Optional[str] = None,
lease: Optional[str] = None,
rekey_to: Optional[str] = None,
extra_pages: Optional[int] = None,
dryrun_accounts: List[DryRunAccountType] = [],
) -> "DryRunInspector":
"""
Expand Down Expand Up @@ -487,18 +487,18 @@ def dryrun_logicsig(
cls,
algod: AlgodClient,
teal: str,
args: Sequence[Union[bytes, str, int]],
abi_argument_types: List[Optional[abi.ABIType]] = None,
abi_return_type: abi.ABIType = None,
args: Sequence[PyTypes],
abi_argument_types: Optional[List[Optional[abi.ABIType]]] = None,
abi_return_type: Optional[abi.ABIType] = None,
*,
sender: str = ZERO_ADDRESS,
sp: SuggestedParams = None,
receiver: str = None,
amt: int = None,
close_remainder_to: str = None,
note: str = None,
lease: str = None,
rekey_to: str = None,
sp: Optional[SuggestedParams] = None,
receiver: Optional[str] = None,
amt: Optional[int] = None,
close_remainder_to: Optional[str] = None,
note: Optional[str] = None,
lease: Optional[str] = None,
rekey_to: Optional[str] = None,
) -> "DryRunInspector":
return cls.execute_one_dryrun(
algod,
Expand All @@ -524,9 +524,9 @@ def dryrun_app_on_sequence(
cls,
algod: AlgodClient,
teal: str,
inputs: List[Sequence[PY_TYPES]],
abi_argument_types: List[Optional[abi.ABIType]] = None,
abi_return_type: abi.ABIType = None,
inputs: List[Sequence[PyTypes]],
abi_argument_types: Optional[List[Optional[abi.ABIType]]] = None,
abi_return_type: Optional[abi.ABIType] = None,
is_app_create: bool = False,
on_complete: OnComplete = OnComplete.NoOpOC,
dryrun_accounts: List[DryRunAccountType] = [],
Expand All @@ -553,9 +553,9 @@ def dryrun_logicsig_on_sequence(
cls,
algod: AlgodClient,
teal: str,
inputs: List[Sequence[Union[str, int]]],
abi_argument_types: List[Optional[abi.ABIType]] = None,
abi_return_type: abi.ABIType = None,
inputs: List[Sequence[PyTypes]],
abi_argument_types: Optional[List[Optional[abi.ABIType]]] = None,
abi_return_type: Optional[abi.ABIType] = None,
) -> List["DryRunInspector"]:
# TODO: handle txn_params
return list(
Expand All @@ -576,10 +576,10 @@ def execute_one_dryrun(
cls,
algod: AlgodClient,
teal: str,
args: Sequence[PY_TYPES],
args: Sequence[PyTypes],
mode: ExecutionMode,
abi_argument_types: List[Optional[abi.ABIType]] = None,
abi_return_type: abi.ABIType = None,
abi_argument_types: Optional[List[Optional[abi.ABIType]]] = None,
abi_return_type: Optional[abi.ABIType] = None,
txn_params: dict = {},
accounts: List[DryRunAccountType] = [],
) -> "DryRunInspector":
Expand Down Expand Up @@ -609,27 +609,27 @@ def transaction_params(
cls,
*,
# generic:
sender: str = None,
sp: SuggestedParams = None,
note: str = None,
lease: str = None,
rekey_to: str = None,
sender: Optional[str] = None,
sp: Optional[SuggestedParams] = None,
note: Optional[str] = None,
lease: Optional[str] = None,
rekey_to: Optional[str] = None,
# payments:
receiver: str = None,
amt: int = None,
close_remainder_to: str = None,
receiver: Optional[str] = None,
amt: Optional[int] = None,
close_remainder_to: Optional[str] = None,
# apps:
index: int = None,
on_complete: OnComplete = None,
local_schema: StateSchema = None,
global_schema: StateSchema = None,
approval_program: str = None,
clear_program: str = None,
app_args: Sequence[Union[str, int]] = None,
accounts: List[str] = None,
foreign_apps: List[str] = None,
foreign_assets: List[str] = None,
extra_pages: int = None,
index: Optional[int] = None,
on_complete: Optional[OnComplete] = None,
local_schema: Optional[StateSchema] = None,
global_schema: Optional[StateSchema] = None,
approval_program: Optional[str] = None,
clear_program: Optional[str] = None,
app_args: Optional[Sequence[Union[str, int]]] = None,
accounts: Optional[List[str]] = None,
foreign_apps: Optional[List[str]] = None,
foreign_assets: Optional[List[str]] = None,
extra_pages: Optional[int] = None,
) -> Dict[str, Any]:
"""
Returns a `dict` with keys the same as method params, after removing all `None` values
Expand Down Expand Up @@ -692,7 +692,7 @@ def return_type(self, method: Optional[str] = None) -> Optional[abi.ABIType]:

return return_type

def generate_inputs(self, method: Optional[str]) -> List[Sequence[PY_TYPES]]:
def generate_inputs(self, method: Optional[str]) -> List[Sequence[PyTypes]]:
assert (
self.argument_strategy
), "cannot generate inputs without an argument_strategy"
Expand All @@ -716,7 +716,7 @@ def gen_args():

return [gen_args() for _ in range(self.dry_runs)]

def validate_inputs(self, method: Optional[str], inputs: List[Sequence[PY_TYPES]]):
def validate_inputs(self, method: Optional[str], inputs: List[Sequence[PyTypes]]):
if not method:
assert not any(
inputs
Expand All @@ -733,7 +733,7 @@ def validate_inputs(self, method: Optional[str], inputs: List[Sequence[PY_TYPES]
def _validate_args(
cls,
method_selector: Optional[str],
args: Sequence[PY_TYPES],
args: Sequence[PyTypes],
arg_types: List[abi.ABIType],
) -> Optional[str]:
if not isinstance(args, tuple):
Expand Down Expand Up @@ -761,7 +761,7 @@ def dry_run_on_sequence(
method: Optional[str] = None,
is_app_create: bool = False,
on_complete: OnComplete = OnComplete.NoOpOC,
inputs: Optional[List[Sequence[PY_TYPES]]] = None,
inputs: Optional[List[Sequence[PyTypes]]] = None,
*,
arg_types: Optional[List[abi.ABIType]] = None,
return_type: Optional[abi.ABIType] = None,
Expand Down Expand Up @@ -864,7 +864,7 @@ def __init__(
self,
dryrun_resp: dict,
txn_index: int,
args: Sequence[PY_TYPES],
args: Sequence[PyTypes],
encoded_args: List[ArgType],
abi_type: abi.ABIType = None,
):
Expand Down Expand Up @@ -931,7 +931,7 @@ def get_txn_mode(cls, txn: dict) -> ExecutionMode:
def from_single_response(
cls,
dryrun_resp: dict,
args: Sequence[PY_TYPES],
args: Sequence[PyTypes],
encoded_args: List[ArgType],
abi_type: abi.ABIType = None,
) -> "DryRunInspector":
Expand Down Expand Up @@ -1222,7 +1222,7 @@ def empty_hack(se):

def report(
self,
args: Optional[Sequence[PY_TYPES]] = None,
args: Optional[Sequence[PyTypes]] = None,
msg: str = "Dry Run Inspector Report",
row: int = 0,
last_steps: int = 100,
Expand Down Expand Up @@ -1266,8 +1266,8 @@ def report(
"""

def csv_row(
self, row_num: int, args: Sequence[PY_TYPES]
) -> Dict[str, Optional[PY_TYPES]]:
self, row_num: int, args: Sequence[PyTypes]
) -> Dict[str, Optional[PyTypes]]:
return {
" Run": row_num,
" cost": self.cost(),
Expand All @@ -1284,7 +1284,7 @@ def csv_report(
cls,
inputs: List[Sequence[Union[str, int]]],
dr_resps: List["DryRunInspector"],
txns: List[Dict[str, Any]] = None,
txns: Optional[List[Dict[str, Any]]] = None,
) -> str:
"""Produce a Comma Separated Values report string capturing important statistics
for a sequence of dry runs.
Expand Down
Loading