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

Convenience wrapper for running subroutines #23

Open
zejoeh opened this issue Jun 18, 2022 · 4 comments
Open

Convenience wrapper for running subroutines #23

zejoeh opened this issue Jun 18, 2022 · 4 comments

Comments

@zejoeh
Copy link

zejoeh commented Jun 18, 2022

Hi, found your project on the Algorand Discord and it's made my testing significantly easier, great job and thanks! I hope it will be fully integrated into PyTeal very soon.

While incorporating it into my own unit tests, I wrote an additional wrapper around the BlackboxWrapper that you included in the PyTeal repository to skip some of the steps that I was doing repeatedly, like compiling the TEAL, arranging inputs correctly, casting to numeric types etc.

This wrapper allows you to write tests like this:

import pyteal as pt

@SubroutineRunner(input_types=[pt.TealType.uint64, pt.TealType.uint64])
@pt.Subroutine(pt.TealType.uint64)
def uint64_subr(x: pt.Expr, y: pt.Expr) -> pt.Expr:
    return pt.Div(x, y)

@SubroutineRunner(input_types=[pt.TealType.uint64, pt.TealType.uint64])
@pt.Subroutine(pt.TealType.bytes)
def bytes_subr(x: pt.Expr, y: pt.Expr) -> pt.Expr:
    return pt.BytesDiv(pt.BytesMul(pt.Itob(x), pt.Bytes("base16", "0x03e8")), pt.Itob(y))

x, y = [8, 10, 50], [2, 9, 10]
for input, output in uint64_subr.run_sequence(y=y, x=x).inout:
    assert output == input["x"] // input["y"]
for input, output in bytes_subr.run_sequence(x=x, y=y).inout:
    assert output == (1000 * input["x"]) // input["y"]

...which I think maybe could be of interest to others. It automatically takes care of mapping keyword arguments to the correct order when calling the subroutine, calls stack_top() for uint64 and last_log() for bytes and converts to Python ints and calls the dryrun for apps or logicsigs depending on an optional pt.Mode argument in the decorator, but is otherwise a pretty simple extra wrapper that just gives a shorter path from the subroutine to the dryruns.

The PyTeal repository doesn't seem like the place to share it, since right now graviton is only used within the tests, so I don't know where I could do a pull request, as it depends on code I found within the PyTeal repo. In case you think it's of any interest now or in the future, just let me know where you think is the best place to share the code, otherwise feel free to close it. :)

@tzaffi
Copy link
Contributor

tzaffi commented Jun 18, 2022

Hi @zejoeh. I'm glad you are finding graviton useful in your PyTEAL development work.

Integration with PyTeal has been steadily improving. In particular, the soon to be merged feature/abi branch has the class PyTealDryRunExecutor which sounds like it has some overlap with your @SubroutineRunner decorator. I recommend you have a look at the existing code and see if it could be integrated or leveraged in some way. It may also be the case that the functionality that you are proposing is an obvious improvement. We welcome pull requests. We can also continue the discussion via this issue.

@zejoeh
Copy link
Author

zejoeh commented Jun 18, 2022

Hi @tzaffi, yes this indeed looks already like a step in the same direction I was going. I wrote this decorator based on the code in the current master branch, so didn't see you already had a similar thing in the feature branch. I will hopefully find some time in the next days to have a closer look at the feature/abi branch and see if I can contribute anything there.

Probably the only "improvement" from my version is that it returns an instance of a container dataclass for the list of DryRunInspectors on sequences, which also stores the inputs in a format consistent with the output and lets you skip writing out list comprehensions each time you want to retrieve the same attribute for many dryruns. I found it pretty nice for writing out many short tests where you only care about evaluating some output quickly and just want to iterate over the inputs and outputs in pairs, but you could of course achieve exactly the same with a range loop or enumerating over one of the input lists and accessing the elements directly.

@tzaffi
Copy link
Contributor

tzaffi commented Jun 18, 2022

Thanks for looking at feature/abi. Keep me posted!

@zejoeh
Copy link
Author

zejoeh commented Jun 19, 2022

Hi @tzaffi, I added a draft pull request on the PyTeal repository. Happy to receive feedback, but still adding improvements as they come up in my own project. I think it can be improved significantly by making use of all the work put into the ABI typing, but I have not had the time yet to dig into it.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

3 participants