-
Notifications
You must be signed in to change notification settings - Fork 114
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Feature Gates without a Config File (#687)
- Loading branch information
Showing
45 changed files
with
749 additions
and
546 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
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,61 @@ | ||
""" | ||
This example shows how to use the source map feature to for a PyTeal program. | ||
To enable the source mapping (at the time of this writing 3/14/2023) | ||
one must import `FeatureGate` from `feature_gates` and call `FeatureGate.set_sourcemap_enabled(True)`. | ||
This import must occur before any object from PyTeal is imported, as PyTeal will | ||
default to its own sourcemap configuration if not set beforehand, and PyTeal imports have | ||
the side effect of importing expressions that the sourcemapper needs to be aware of. | ||
""" | ||
|
||
from feature_gates import FeatureGates | ||
|
||
FeatureGates.set_sourcemap_enabled(True) | ||
|
||
# INTENTIONALLY importing pyteal and objects _AFTER_ enabling the sourcemap feature | ||
import pyteal as pt # noqa: E402 | ||
from pyteal import Compilation, Mode # noqa: E402 | ||
|
||
|
||
def program(): | ||
@pt.Subroutine(pt.TealType.uint64) | ||
def is_even(i): | ||
return ( | ||
pt.If(i == pt.Int(0)) | ||
.Then(pt.Int(1)) | ||
.ElseIf(i == pt.Int(1)) | ||
.Then(pt.Int(0)) | ||
.Else(is_even(i - pt.Int(2))) | ||
) | ||
|
||
n = pt.Btoi(arg0 := pt.Txn.application_args[0]) | ||
|
||
return pt.Seq( | ||
pt.Log(pt.Bytes("n:")), | ||
pt.Log(arg0), | ||
pt.Log(pt.Bytes("is_even(n):")), | ||
pt.Log(pt.Itob(is_even(n))), | ||
pt.Int(1), | ||
) | ||
|
||
|
||
if __name__ == "__main__": | ||
# This assumes running as follows: | ||
# cd examples/application | ||
# python sourcemap.py | ||
approval_program = program() | ||
|
||
results = Compilation(approval_program, mode=Mode.Application, version=8).compile( | ||
with_sourcemap=True, annotate_teal=True, annotate_teal_headers=True | ||
) | ||
|
||
teal = "teal/sourcemap.teal" | ||
annotated = "teal/sourcemap_annotated.teal" | ||
|
||
with open(teal, "w") as f: | ||
f.write(results.teal) | ||
|
||
with open(annotated, "w") as f: | ||
f.write(results.sourcemap.annotated_teal) | ||
|
||
print(f"SUCCESS!!! Please check out {teal} and {annotated}") |
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,38 @@ | ||
#pragma version 8 | ||
byte "n:" | ||
log | ||
txna ApplicationArgs 0 | ||
log | ||
byte "is_even(n):" | ||
log | ||
txna ApplicationArgs 0 | ||
btoi | ||
callsub iseven_0 | ||
itob | ||
log | ||
int 1 | ||
return | ||
|
||
// is_even | ||
iseven_0: | ||
proto 1 1 | ||
frame_dig -1 | ||
int 0 | ||
== | ||
bnz iseven_0_l4 | ||
frame_dig -1 | ||
int 1 | ||
== | ||
bnz iseven_0_l3 | ||
frame_dig -1 | ||
int 2 | ||
- | ||
callsub iseven_0 | ||
b iseven_0_l5 | ||
iseven_0_l3: | ||
int 0 | ||
b iseven_0_l5 | ||
iseven_0_l4: | ||
int 1 | ||
iseven_0_l5: | ||
retsub |
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,39 @@ | ||
// GENERATED TEAL // PYTEAL PATH LINE PYTEAL | ||
#pragma version 8 // sourcemap.py 48 Compilation(approval_program, mode=Mode.Application, version=8).compile(with_sourcemap=True, annotate_teal=True, annotate_teal_headers=True) | ||
byte "n:" // 34 pt.Bytes('n:') | ||
log // pt.Log(pt.Bytes('n:')) | ||
txna ApplicationArgs 0 // 31 pt.Txn.application_args[0] | ||
log // 35 pt.Log(arg0) | ||
byte "is_even(n):" // 36 pt.Bytes('is_even(n):') | ||
log // pt.Log(pt.Bytes('is_even(n):')) | ||
txna ApplicationArgs 0 // 31 pt.Txn.application_args[0] | ||
btoi // pt.Btoi((arg0 := pt.Txn.application_args[0])) | ||
callsub iseven_0 // 37 is_even(n) | ||
itob // pt.Itob(is_even(n)) | ||
log // pt.Log(pt.Itob(is_even(n))) | ||
int 1 // 38 pt.Int(1) | ||
return // 48 Compilation(approval_program, mode=Mode.Application, version=8).compile(with_sourcemap=True, annotate_teal=True, annotate_teal_headers=True) | ||
// 22 def is_even(i): | ||
// is_even // | ||
iseven_0: // | ||
proto 1 1 // | ||
frame_dig -1 // 48 Compilation(approval_program, mode=Mode.Application, version=8).compile(with_sourcemap=True, annotate_teal=True, annotate_teal_headers=True) | ||
int 0 // 24 pt.Int(0) | ||
== // i == pt.Int(0) | ||
bnz iseven_0_l4 // pt.If(i == pt.Int(0)) | ||
frame_dig -1 // 48 Compilation(approval_program, mode=Mode.Application, version=8).compile(with_sourcemap=True, annotate_teal=True, annotate_teal_headers=True) | ||
int 1 // 26 pt.Int(1) | ||
== // i == pt.Int(1) | ||
bnz iseven_0_l3 // | ||
frame_dig -1 // 48 Compilation(approval_program, mode=Mode.Application, version=8).compile(with_sourcemap=True, annotate_teal=True, annotate_teal_headers=True) | ||
int 2 // 28 pt.Int(2) | ||
- // i - pt.Int(2) | ||
callsub iseven_0 // is_even(i - pt.Int(2)) | ||
b iseven_0_l5 // 26 pt.If(i == pt.Int(0)).Then(pt.Int(1)).ElseIf(i == pt.Int(1)) | ||
iseven_0_l3: // i == pt.Int(1) | ||
int 0 // 27 pt.Int(0) | ||
b iseven_0_l5 // 48 Compilation(approval_program, mode=Mode.Application, version=8).compile(with_sourcemap=True, annotate_teal=True, annotate_teal_headers=True) | ||
iseven_0_l4: // 24 pt.If(i == pt.Int(0)) | ||
int 1 // 25 pt.Int(1) | ||
iseven_0_l5: // 26 pt.If(i == pt.Int(0)).Then(pt.Int(1)).ElseIf(i == pt.Int(1)) | ||
retsub // 22 def is_even(i): |
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
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
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,65 @@ | ||
from dataclasses import dataclass | ||
from typing import Final | ||
|
||
|
||
@dataclass | ||
class _FeatureGatesConfig: | ||
""" | ||
Configuration for feature gates. | ||
We follow the following convention: | ||
feature_property: True/False | ||
""" | ||
|
||
sourcemap_enabled: bool | ||
sourcemap_debug: bool | ||
|
||
|
||
class FeatureGates: | ||
""" | ||
Feature gates work as follows: | ||
1. Add a new feature gate to the _FeatureGatesConfig dataclass | ||
2. Set the default value for the feature gate in the _gates field below | ||
Automagically, a new setter and getter will be available for the feature gate. | ||
For example, given feature `foo_on` by adding _FeatureGatesConfig.foo_on, | ||
the following methods will be available: | ||
* FeatureGates.foo_on() -> bool | ||
* FeatureGates.set_foo_on(gate: bool) | ||
""" | ||
|
||
# default values for feature gates: | ||
_gates: _FeatureGatesConfig = _FeatureGatesConfig( | ||
sourcemap_enabled=False, | ||
sourcemap_debug=False, | ||
) | ||
_features: Final[set[str]] = set(vars(_gates).keys()) | ||
|
||
@classmethod | ||
def _make_feature(cls, feature: str): | ||
setattr(cls, feature, classmethod(lambda cls: cls.get(feature))) | ||
setattr( | ||
cls, f"set_{feature}", classmethod(lambda cls, gate: cls.set(feature, gate)) | ||
) | ||
|
||
@classmethod | ||
def get(cls, feature: str) -> bool | None: | ||
if feature not in cls._features: | ||
raise ValueError( | ||
f"Unknown {feature=} (available features: {cls._features}))" | ||
) | ||
|
||
return getattr(cls._gates, feature) | ||
|
||
@classmethod | ||
def set(cls, feature: str, gate: bool) -> None: | ||
if feature not in cls._features: | ||
raise ValueError( | ||
f"Cannot set unknown {feature=} (available features: {cls._features}))" | ||
) | ||
setattr(cls._gates, feature, gate) | ||
|
||
|
||
for feature in FeatureGates._features: | ||
FeatureGates._make_feature(feature) |
This file was deleted.
Oops, something went wrong.
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 |
---|---|---|
@@ -1,69 +1,69 @@ | ||
from pyteal.ast import * | ||
from pyteal.ast import __all__ as ast_all | ||
from pyteal.pragma import pragma | ||
from pyteal.ir import * | ||
from pyteal.ir import __all__ as ir_all | ||
from pyteal.compiler import ( | ||
MAX_TEAL_VERSION, | ||
MIN_TEAL_VERSION, | ||
DEFAULT_PROGRAM_VERSION, | ||
DEFAULT_TEAL_VERSION, | ||
MAX_PROGRAM_VERSION, | ||
MAX_TEAL_VERSION, | ||
MIN_PROGRAM_VERSION, | ||
DEFAULT_PROGRAM_VERSION, | ||
CompileOptions, | ||
MIN_TEAL_VERSION, | ||
Compilation, | ||
compileTeal, | ||
CompileOptions, | ||
OptimizeOptions, | ||
PyTealSourceMap, | ||
compileTeal, | ||
) | ||
from pyteal.config import ( | ||
MAX_GROUP_SIZE, | ||
METHOD_ARG_NUM_CUTOFF, | ||
NUM_SLOTS, | ||
RETURN_HASH_PREFIX, | ||
) | ||
from pyteal.types import TealType | ||
from pyteal.errors import ( | ||
AlgodClientError, | ||
SourceMapDisabledError, | ||
TealInternalError, | ||
TealTypeError, | ||
TealSeqError, | ||
TealInputError, | ||
TealCompileError, | ||
TealInputError, | ||
TealInternalError, | ||
TealPragmaError, | ||
TealSeqError, | ||
TealTypeError, | ||
) | ||
from pyteal.config import ( | ||
MAX_GROUP_SIZE, | ||
NUM_SLOTS, | ||
RETURN_HASH_PREFIX, | ||
METHOD_ARG_NUM_CUTOFF, | ||
) | ||
from pyteal.ir import * | ||
from pyteal.ir import __all__ as ir_all | ||
from pyteal.pragma import pragma | ||
from pyteal.types import TealType | ||
|
||
# begin __all__ | ||
__all__ = ( | ||
ast_all | ||
+ ir_all | ||
+ [ | ||
"MAX_TEAL_VERSION", | ||
"MIN_TEAL_VERSION", | ||
"AlgodClientError", | ||
"Compilation", | ||
"CompileOptions", | ||
"compileTeal", | ||
"DEFAULT_PROGRAM_VERSION", | ||
"DEFAULT_TEAL_VERSION", | ||
"MAX_GROUP_SIZE", | ||
"MAX_PROGRAM_VERSION", | ||
"MAX_TEAL_VERSION", | ||
"METHOD_ARG_NUM_CUTOFF", | ||
"MIN_PROGRAM_VERSION", | ||
"DEFAULT_PROGRAM_VERSION", | ||
"CompileOptions", | ||
"pragma", | ||
"Compilation", | ||
"compileTeal", | ||
"MIN_TEAL_VERSION", | ||
"NUM_SLOTS", | ||
"OptimizeOptions", | ||
"pragma", | ||
"PyTealSourceMap", | ||
"TealType", | ||
"AlgodClientError", | ||
"RETURN_HASH_PREFIX", | ||
"SourceMapDisabledError", | ||
"TealInternalError", | ||
"TealTypeError", | ||
"TealSeqError", | ||
"TealInputError", | ||
"TealCompileError", | ||
"TealInputError", | ||
"TealInternalError", | ||
"TealPragmaError", | ||
"MAX_GROUP_SIZE", | ||
"NUM_SLOTS", | ||
"RETURN_HASH_PREFIX", | ||
"METHOD_ARG_NUM_CUTOFF", | ||
"TealSeqError", | ||
"TealType", | ||
"TealTypeError", | ||
] | ||
) | ||
# end __all__ |
Oops, something went wrong.