diff --git a/.github/release.yml b/.github/release.yml new file mode 100644 index 0000000..7aa8ef7 --- /dev/null +++ b/.github/release.yml @@ -0,0 +1,11 @@ +changelog: + categories: + - title: 🏕 Features + labels: + - '*' + exclude: + labels: + - dependencies + - title: 👒 Dependencies + labels: + - dependencies diff --git a/.github/workflows/python-publish.yml b/.github/workflows/python-publish.yml index c57c4de..4736020 100644 --- a/.github/workflows/python-publish.yml +++ b/.github/workflows/python-publish.yml @@ -8,6 +8,14 @@ jobs: runs-on: ubuntu-latest steps: - uses: actions/checkout@v3 + # If there isn't a release for this version, create a new one. + - uses: ncipollo/release-action@v1 + with: + generateReleaseNotes: true + makeLatest: true + prerelease: true + skipIfReleaseExists: true + # Build and publish the package to pypi. - name: Build and publish to pypi uses: JRubics/poetry-publish@v1.16 with: diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 61fc3bf..c625900 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -7,4 +7,4 @@ repos: # supported by your project here, or alternatively use # pre-commit's default_language_version, see # https://pre-commit.com/#top_level-default_language_version - language_version: python3.8 + language_version: python3.10 diff --git a/.travis.yml b/.travis.yml index 01b4be9..fa8eb9b 100644 --- a/.travis.yml +++ b/.travis.yml @@ -29,6 +29,10 @@ script: coverage run -a --source=hebi -m hebi compile_pluto examples/smart_contracts/assert_sum.py - > coverage run -a --source=hebi -m hebi build examples/smart_contracts/assert_sum.py +- > + for i in $(find examples -type f -name "*.py" -not \( -name "broken*" -o -name "extract*" \)); do + coverage run -a --source=hebi -m hebi compile "$i" + done after_success: - coverage report diff --git a/README.md b/README.md index 4526094..b7035e6 100644 --- a/README.md +++ b/README.md @@ -5,11 +5,11 @@

hebi


-Build Status +Build Status PyPI version PyPI - Python Version PyPI - Status -Coverage Status +Coverage Status @@ -85,8 +85,8 @@ A short non-complete introduction in starting to write smart contracts follows. 2. Make sure you understand python. hebi works like python and uses python. There are tons of tutorials for python, choose what suits you best. 3. Make sure your contract is valid python and the types check out. Write simple contracts first and run them using `hebi eval` to get a feeling for how they work. 4. Make sure your contract is valid hebi code. Run `hebi compile` and look at the compiler erros for guidance along what works and doesn't work and why. -5. Dig into the [`examples`](https://github.com/OpShin/hebi/tree/master/examples) to understand common patterns. Check out the [`prelude`](https://opshin.github.io/hebi/prelude.html) for understanding how the Script Context is structured and how complex datums are defined. -6. Check out the [sample repository](https://github.com/OpShin/eopsin-example) to find a sample setup for developing your own contract. +5. Dig into the [`examples`](https://github.com/OpShin/hebi/tree/main/examples) to understand common patterns. Check out the [`prelude`](https://hebi.opshin.dev/hebi/prelude.html) for understanding how the Script Context is structured and how complex datums are defined. +6. Check out the [sample repository](https://github.com/OpShin/opshin-starter-kit) to find a sample setup for developing your own contract. In summary, a smart contract in hebi is defined by the function `validator` in your contract file. @@ -109,20 +109,20 @@ and how to build transactions with the contract. ```python3 from hebi.prelude import * -@dataclass() -class CancelDatum(PlutusData): +@dataclass +class WithdrawDatum(PlutusData): pubkeyhash: bytes -def validator(datum: CancelDatum, redeemer: None, context: ScriptContext) -> None: +def validator(datum: WithdrawDatum, redeemer: None, context: ScriptContext) -> None: assert datum.pubkeyhash in context.tx_info.signatories, "Required signature missing" ``` All contracts written in hebi are 100% valid python. Minting policies expect only a redeemer and script context as argument. -Check out the [Architecture guide](https://github.com/OpShin/hebi/blob/master/ARCHITECTURE.md#minting-policy---spending-validator-double-function) +Check out the [Architecture guide](https://github.com/OpShin/hebi/blob/main/ARCHITECTURE.md#minting-policy---spending-validator-double-function) for details on how to write double functioning contracts. -The [`examples`](https://github.com/OpShin/hebi/blob/master/examples) folder contains more examples. +The [`examples`](https://github.com/OpShin/hebi/blob/main/examples) folder contains more examples. Also check out the [opshin-pioneer-program]( https://github.com/OpShin/opshin-pioneer-program) and [opshin-starter-kit]( @@ -217,4 +217,4 @@ The main sponsor of this project is [Inversion](https://inversion.dev/cardano/). > At Inversion, we pride ourselves on our passion for life and our ability to create exceptional software solutions for our clients. Our team of experts, with over a century of cumulative experience, is dedicated to harnessing the power of the Cardano blockchain to bring innovative and scalable decentralized applications to life. We've successfully built applications for NFT management, staking and delegation, chain data monitoring, analytics, and web3 integrations, as well as countless non-blockchain systems. With a focus on security, transparency, and sustainability, our team is excited to contribute to the Cardano ecosystem, pushing the boundaries of decentralized technologies to improve lives worldwide. Trust Inversion to be your go-to partner for robust, effective, and forward-thinking solutions, whether blockchain based, traditional systems, or a mix of the two. They have recently started a podcast, called "Africa On Chain", which you can check out here: -https://www.youtube.com/@africaonchain \ No newline at end of file +https://www.youtube.com/@africaonchain diff --git a/docs/hebi/builder.html b/docs/hebi/builder.html index 9d1fc01..8bd2b6c 100644 --- a/docs/hebi/builder.html +++ b/docs/hebi/builder.html @@ -78,6 +78,8 @@

Module hebi.builder

import cbor2 import pycardano +from .util import datum_to_cbor + @dataclasses.dataclass class ScriptArtifacts: @@ -88,7 +90,12 @@

Module hebi.builder

policy_id: str -def build(contract_file: str, *args: pycardano.PlutusData, force_three_params=False): +def build( + contract_file: str, + *args: pycardano.Datum, + force_three_params=False, + validator_function_name="validator", +): """ Expects a python module and returns the build artifacts from compiling it """ @@ -105,7 +112,7 @@

Module hebi.builder

code = code.term # UPLC lambdas may only take one argument at a time, so we evaluate by repeatedly applying for d in args: - code = uplc.ast.Apply(code, uplc.ast.data_from_cbor(d.to_cbor("bytes"))) + code = uplc.ast.Apply(code, uplc.ast.data_from_cbor(datum_to_cbor(d))) code = uplc.ast.Program((1, 0, 0), code) return _build(code) @@ -113,18 +120,22 @@

Module hebi.builder

def _build(contract: uplc.ast.Program): # create cbor file for use with pycardano/lucid cbor = flatten(contract) - cbor_hex = cbor.hex() + return pycardano.PlutusV2Script(cbor) + + +def generate_artifacts(contract: pycardano.PlutusV2Script): + cbor_hex = contract.hex() # double wrap - cbor_wrapped = cbor2.dumps(cbor) + cbor_wrapped = cbor2.dumps(contract) cbor_wrapped_hex = cbor_wrapped.hex() # create plutus file d = { "type": "PlutusScriptV2", - "description": f"opshin {__version__} Smart Contract", + "description": f"hebi {__version__} Smart Contract", "cborHex": cbor_wrapped_hex, } plutus_json = json.dumps(d, indent=2) - script_hash = pycardano.plutus_script_hash(pycardano.PlutusV2Script(cbor)) + script_hash = pycardano.plutus_script_hash(pycardano.PlutusV2Script(contract)) policy_id = script_hash.to_primitive().hex() # generate policy ids addr_mainnet = pycardano.Address( @@ -151,7 +162,7 @@

Module hebi.builder

Functions

-def build(contract_file: str, *args: pycardano.plutus.PlutusData, force_three_params=False) +def build(contract_file: str, *args: Union[pycardano.plutus.PlutusData, dict, pycardano.serialization.IndefiniteList, int, bytes, pycardano.serialization.RawCBOR, pycardano.plutus.RawPlutusData], force_three_params=False, validator_function_name='validator')

Expects a python module and returns the build artifacts from compiling it

@@ -159,7 +170,12 @@

Functions

Expand source code -
def build(contract_file: str, *args: pycardano.PlutusData, force_three_params=False):
+
def build(
+    contract_file: str,
+    *args: pycardano.Datum,
+    force_three_params=False,
+    validator_function_name="validator",
+):
     """
     Expects a python module and returns the build artifacts from compiling it
     """
@@ -176,11 +192,51 @@ 

Functions

code = code.term # UPLC lambdas may only take one argument at a time, so we evaluate by repeatedly applying for d in args: - code = uplc.ast.Apply(code, uplc.ast.data_from_cbor(d.to_cbor("bytes"))) + code = uplc.ast.Apply(code, uplc.ast.data_from_cbor(datum_to_cbor(d))) code = uplc.ast.Program((1, 0, 0), code) return _build(code)
+
+def generate_artifacts(contract: pycardano.plutus.PlutusV2Script) +
+
+
+
+ +Expand source code + +
def generate_artifacts(contract: pycardano.PlutusV2Script):
+    cbor_hex = contract.hex()
+    # double wrap
+    cbor_wrapped = cbor2.dumps(contract)
+    cbor_wrapped_hex = cbor_wrapped.hex()
+    # create plutus file
+    d = {
+        "type": "PlutusScriptV2",
+        "description": f"hebi {__version__} Smart Contract",
+        "cborHex": cbor_wrapped_hex,
+    }
+    plutus_json = json.dumps(d, indent=2)
+    script_hash = pycardano.plutus_script_hash(pycardano.PlutusV2Script(contract))
+    policy_id = script_hash.to_primitive().hex()
+    # generate policy ids
+    addr_mainnet = pycardano.Address(
+        script_hash, network=pycardano.Network.MAINNET
+    ).encode()
+    # generate addresses
+    addr_testnet = pycardano.Address(
+        script_hash, network=pycardano.Network.TESTNET
+    ).encode()
+    return ScriptArtifacts(
+        cbor_hex,
+        plutus_json,
+        addr_mainnet,
+        addr_testnet,
+        policy_id,
+    )
+
+
@@ -297,6 +353,7 @@

Index

  • Functions

  • Classes

    diff --git a/docs/hebi/compiler.html b/docs/hebi/compiler.html index 4539547..3d3e45d 100644 --- a/docs/hebi/compiler.html +++ b/docs/hebi/compiler.html @@ -72,6 +72,7 @@

    Module hebi.compiler

    from logging import getLogger from ast import fix_missing_locations +from .optimize.optimize_remove_comments import OptimizeRemoveDeadconstants from .rewrite.rewrite_forbidden_overwrites import RewriteForbiddenOverwrites from .rewrite.rewrite_import import RewriteImport from .rewrite.rewrite_import_dataclasses import RewriteImportDataclasses @@ -189,8 +190,9 @@

    Module hebi.compiler

    step = "Compiling python statements to UPLC" - def __init__(self, force_three_params=False): + def __init__(self, force_three_params=False, validator_function_name="validator"): self.force_three_params = force_three_params + self.validator_function_name = validator_function_name def visit_sequence( self, node_seq: typing.List[typedstmt] @@ -256,20 +258,24 @@

    Module hebi.compiler

    # TODO can use more sophisiticated procedure here i.e. functions marked by comment main_fun: typing.Optional[InstanceType] = None for s in node.body: - if isinstance(s, FunctionDef) and s.name == "validator": + if ( + isinstance(s, FunctionDef) + and s.orig_name == self.validator_function_name + ): main_fun = s - assert main_fun is not None, "Could not find function named validator" - main_fun_typ = main_fun.typ - main_fun_typ_typ: FunctionType = main_fun_typ.typ + assert ( + main_fun is not None + ), f"Could not find function named {self.validator_function_name}" + main_fun_typ: FunctionType = main_fun.typ.typ assert isinstance( - main_fun_typ_typ, FunctionType - ), "Variable named validator is not of type function" + main_fun_typ, FunctionType + ), f"Variable named {self.validator_function_name} is not of type function" # check if this is a contract written to double function enable_double_func_mint_spend = False - if len(main_fun_typ_typ.argtyps) >= 3 and self.force_three_params: + if len(main_fun_typ.typ.argtyps) >= 3 and self.force_three_params: # check if is possible - second_last_arg = main_fun_typ_typ.argtyps[-2] + second_last_arg = main_fun_typ.typ.argtyps[-2] assert isinstance( second_last_arg, InstanceType ), "Can not pass Class into validator" @@ -293,14 +299,16 @@

    Module hebi.compiler

    body = node.body + [ TypedReturn( - value=Name(id="validator", typ=main_fun_typ, ctx=Load()), - typ=main_fun_typ_typ.rettyp, + value=Name( + id=self.validator_function_name, typ=main_fun_typ, ctx=Load() + ), + typ=main_fun_typ.typ.rettyp, ) ] validator = plt.Lambda( - [f"p{i}" for i, _ in enumerate(main_fun_typ_typ.argtyps)], - transform_output_map(main_fun_typ_typ.rettyp)( + [f"p{i}" for i, _ in enumerate(main_fun_typ.typ.argtyps)], + transform_output_map(main_fun_typ.typ.rettyp)( plt.Let( [ ( @@ -313,7 +321,7 @@

    Module hebi.compiler

    plt.Var("val"), *[ transform_ext_params_map(a)(plt.Var(f"p{i}")) - for i, a in enumerate(main_fun_typ_typ.argtyps) + for i, a in enumerate(main_fun_typ.typ.argtyps) ], ), ), @@ -321,7 +329,7 @@

    Module hebi.compiler

    ) if enable_double_func_mint_spend: validator = wrap_validator_double_function( - validator, pass_through=len(main_fun_typ_typ.argtyps) - 3 + validator, pass_through=len(main_fun_typ.typ.argtyps) - 3 ) elif self.force_three_params: # Error if the double function is enforced but not possible @@ -369,6 +377,12 @@

    Module hebi.compiler

    # we need to map this as it will originate from PlutusData # AnyType is the only type other than the builtin itself that can be cast to builtin values val = transform_ext_params_map(node.target.typ)(val) + if isinstance(node.target.typ, InstanceType) and isinstance( + node.target.typ.typ, AnyType + ): + # we need to map this back as it will be treated as PlutusData + # AnyType is the only type other than the builtin itself that can be cast to from builtin values + val = transform_output_map(node.value.typ)(val) return lambda x: plt.Let([(node.target.id, val)], x) def visit_Name(self, node: TypedName) -> plt.AST: @@ -440,7 +454,11 @@

    Module hebi.compiler

    def visit_Return(self, node: TypedReturn) -> typing.Callable[[plt.AST], plt.AST]: # Throw away the term we were passed, this is going to be the last! - return lambda x: self.visit(node.value) + compiled_return = self.visit(node.value) + if isinstance(node.typ.typ.rettyp.typ, AnyType): + # if the function returns generic data, wrap the function return value + compiled_return = transform_output_map(node.value.typ)(compiled_return) + return lambda _: compiled_return def visit_Pass(self, node: TypedPass) -> typing.Callable[[plt.AST], plt.AST]: return lambda x: x @@ -465,6 +483,28 @@

    Module hebi.compiler

    index, len(node.value.typ.typ.typs), ) + if isinstance(node.value.typ.typ, PairType): + assert isinstance( + node.slice, Constant + ), "Only constant index access for pairs is supported" + assert isinstance( + node.slice.value, int + ), "Only constant index integer access for pairs is supported" + index = node.slice.value + if index < 0: + index += 2 + assert isinstance(node.ctx, Load), "Pairs are read-only" + assert ( + 0 <= index < 2 + ), f"Pairs only have 2 elements, index should be 0 or 1, is {node.slice.value}" + member_func = plt.FstPair if index == 0 else plt.SndPair + # the content of pairs is always Data, so we need to unwrap + member_typ = node.typ + return transform_ext_params_map(member_typ)( + member_func( + self.visit(node.value), + ), + ) if isinstance(node.value.typ.typ, ListType): assert ( node.slice.typ == IntegerInstanceType @@ -489,6 +529,34 @@

    Module hebi.compiler

    ], plt.IndexAccessList(plt.Var("l"), plt.Var("i")), ) + elif isinstance(node.value.typ.typ, DictType): + dict_typ = node.value.typ.typ + if not isinstance(node.slice, Slice): + return plt.Let( + [ + ( + "key", + self.visit(node.slice), + ) + ], + transform_ext_params_map(dict_typ.value_typ)( + plt.SndPair( + plt.FindList( + self.visit(node.value), + plt.Lambda( + ["x"], + plt.EqualsData( + transform_output_map(dict_typ.key_typ)( + plt.Var("key") + ), + plt.FstPair(plt.Var("x")), + ), + ), + plt.TraceError("KeyError"), + ), + ), + ), + ) elif isinstance(node.value.typ.typ, ByteStringType): if not isinstance(node.slice, Slice): return plt.Let( @@ -518,7 +586,10 @@

    Module hebi.compiler

    elif isinstance(node.slice, Slice): return plt.Let( [ - ("bs", self.visit(node.value)), + ( + "bs", + self.visit(node.value), + ), ( "raw_i", self.visit(node.slice.lower), @@ -572,7 +643,9 @@

    Module hebi.compiler

    ), ), ) - raise NotImplementedError(f"Could not implement subscript of {node}") + raise NotImplementedError( + f'Could not implement subscript "{node.slice}" of "{node.value}"' + ) def visit_Tuple(self, node: TypedTuple) -> plt.AST: return plt.FunctionalTuple(*(self.visit(e) for e in node.elts)) @@ -678,7 +751,12 @@

    Module hebi.compiler

    raise NotImplementedError(f"Can not compile {node}") -def compile(prog: AST, filename=None, force_three_params=False): +def compile( + prog: AST, + filename=None, + force_three_params=False, + validator_function_name="validator", +): rewrite_steps = [ # Important to call this one first - it imports all further files RewriteImport(filename=filename), @@ -707,10 +785,13 @@

    Module hebi.compiler

    compile_pipeline = [ # Apply optimizations OptimizeRemoveDeadvars(), - # OptimizeVarlen(), + OptimizeRemoveDeadconstants(), OptimizeRemovePass(), # the compiler runs last - UPLCCompiler(force_three_params=force_three_params), + UPLCCompiler( + force_three_params=force_three_params, + validator_function_name=validator_function_name, + ), ] for s in compile_pipeline: prog = s.visit(prog) @@ -726,7 +807,7 @@

    Module hebi.compiler

    Functions

    -def compile(prog: _ast.AST, filename=None, force_three_params=False) +def compile(prog: _ast.AST, filename=None, force_three_params=False, validator_function_name='validator')
    @@ -734,7 +815,12 @@

    Functions

    Expand source code -
    def compile(prog: AST, filename=None, force_three_params=False):
    +
    def compile(
    +    prog: AST,
    +    filename=None,
    +    force_three_params=False,
    +    validator_function_name="validator",
    +):
         rewrite_steps = [
             # Important to call this one first - it imports all further files
             RewriteImport(filename=filename),
    @@ -763,10 +849,13 @@ 

    Functions

    compile_pipeline = [ # Apply optimizations OptimizeRemoveDeadvars(), - # OptimizeVarlen(), + OptimizeRemoveDeadconstants(), OptimizeRemovePass(), # the compiler runs last - UPLCCompiler(force_three_params=force_three_params), + UPLCCompiler( + force_three_params=force_three_params, + validator_function_name=validator_function_name, + ), ] for s in compile_pipeline: prog = s.visit(prog) @@ -820,7 +909,7 @@

    Classes

    class UPLCCompiler -(force_three_params=False) +(force_three_params=False, validator_function_name='validator')

    Expects a TypedAST and returns UPLC/Pluto like code

    @@ -835,8 +924,9 @@

    Classes

    step = "Compiling python statements to UPLC" - def __init__(self, force_three_params=False): + def __init__(self, force_three_params=False, validator_function_name="validator"): self.force_three_params = force_three_params + self.validator_function_name = validator_function_name def visit_sequence( self, node_seq: typing.List[typedstmt] @@ -902,20 +992,24 @@

    Classes

    # TODO can use more sophisiticated procedure here i.e. functions marked by comment main_fun: typing.Optional[InstanceType] = None for s in node.body: - if isinstance(s, FunctionDef) and s.name == "validator": + if ( + isinstance(s, FunctionDef) + and s.orig_name == self.validator_function_name + ): main_fun = s - assert main_fun is not None, "Could not find function named validator" - main_fun_typ = main_fun.typ - main_fun_typ_typ: FunctionType = main_fun_typ.typ + assert ( + main_fun is not None + ), f"Could not find function named {self.validator_function_name}" + main_fun_typ: FunctionType = main_fun.typ.typ assert isinstance( - main_fun_typ_typ, FunctionType - ), "Variable named validator is not of type function" + main_fun_typ, FunctionType + ), f"Variable named {self.validator_function_name} is not of type function" # check if this is a contract written to double function enable_double_func_mint_spend = False - if len(main_fun_typ_typ.argtyps) >= 3 and self.force_three_params: + if len(main_fun_typ.typ.argtyps) >= 3 and self.force_three_params: # check if is possible - second_last_arg = main_fun_typ_typ.argtyps[-2] + second_last_arg = main_fun_typ.typ.argtyps[-2] assert isinstance( second_last_arg, InstanceType ), "Can not pass Class into validator" @@ -939,14 +1033,16 @@

    Classes

    body = node.body + [ TypedReturn( - value=Name(id="validator", typ=main_fun_typ, ctx=Load()), - typ=main_fun_typ_typ.rettyp, + value=Name( + id=self.validator_function_name, typ=main_fun_typ, ctx=Load() + ), + typ=main_fun_typ.typ.rettyp, ) ] validator = plt.Lambda( - [f"p{i}" for i, _ in enumerate(main_fun_typ_typ.argtyps)], - transform_output_map(main_fun_typ_typ.rettyp)( + [f"p{i}" for i, _ in enumerate(main_fun_typ.typ.argtyps)], + transform_output_map(main_fun_typ.typ.rettyp)( plt.Let( [ ( @@ -959,7 +1055,7 @@

    Classes

    plt.Var("val"), *[ transform_ext_params_map(a)(plt.Var(f"p{i}")) - for i, a in enumerate(main_fun_typ_typ.argtyps) + for i, a in enumerate(main_fun_typ.typ.argtyps) ], ), ), @@ -967,7 +1063,7 @@

    Classes

    ) if enable_double_func_mint_spend: validator = wrap_validator_double_function( - validator, pass_through=len(main_fun_typ_typ.argtyps) - 3 + validator, pass_through=len(main_fun_typ.typ.argtyps) - 3 ) elif self.force_three_params: # Error if the double function is enforced but not possible @@ -1015,6 +1111,12 @@

    Classes

    # we need to map this as it will originate from PlutusData # AnyType is the only type other than the builtin itself that can be cast to builtin values val = transform_ext_params_map(node.target.typ)(val) + if isinstance(node.target.typ, InstanceType) and isinstance( + node.target.typ.typ, AnyType + ): + # we need to map this back as it will be treated as PlutusData + # AnyType is the only type other than the builtin itself that can be cast to from builtin values + val = transform_output_map(node.value.typ)(val) return lambda x: plt.Let([(node.target.id, val)], x) def visit_Name(self, node: TypedName) -> plt.AST: @@ -1086,7 +1188,11 @@

    Classes

    def visit_Return(self, node: TypedReturn) -> typing.Callable[[plt.AST], plt.AST]: # Throw away the term we were passed, this is going to be the last! - return lambda x: self.visit(node.value) + compiled_return = self.visit(node.value) + if isinstance(node.typ.typ.rettyp.typ, AnyType): + # if the function returns generic data, wrap the function return value + compiled_return = transform_output_map(node.value.typ)(compiled_return) + return lambda _: compiled_return def visit_Pass(self, node: TypedPass) -> typing.Callable[[plt.AST], plt.AST]: return lambda x: x @@ -1111,6 +1217,28 @@

    Classes

    index, len(node.value.typ.typ.typs), ) + if isinstance(node.value.typ.typ, PairType): + assert isinstance( + node.slice, Constant + ), "Only constant index access for pairs is supported" + assert isinstance( + node.slice.value, int + ), "Only constant index integer access for pairs is supported" + index = node.slice.value + if index < 0: + index += 2 + assert isinstance(node.ctx, Load), "Pairs are read-only" + assert ( + 0 <= index < 2 + ), f"Pairs only have 2 elements, index should be 0 or 1, is {node.slice.value}" + member_func = plt.FstPair if index == 0 else plt.SndPair + # the content of pairs is always Data, so we need to unwrap + member_typ = node.typ + return transform_ext_params_map(member_typ)( + member_func( + self.visit(node.value), + ), + ) if isinstance(node.value.typ.typ, ListType): assert ( node.slice.typ == IntegerInstanceType @@ -1135,6 +1263,34 @@

    Classes

    ], plt.IndexAccessList(plt.Var("l"), plt.Var("i")), ) + elif isinstance(node.value.typ.typ, DictType): + dict_typ = node.value.typ.typ + if not isinstance(node.slice, Slice): + return plt.Let( + [ + ( + "key", + self.visit(node.slice), + ) + ], + transform_ext_params_map(dict_typ.value_typ)( + plt.SndPair( + plt.FindList( + self.visit(node.value), + plt.Lambda( + ["x"], + plt.EqualsData( + transform_output_map(dict_typ.key_typ)( + plt.Var("key") + ), + plt.FstPair(plt.Var("x")), + ), + ), + plt.TraceError("KeyError"), + ), + ), + ), + ) elif isinstance(node.value.typ.typ, ByteStringType): if not isinstance(node.slice, Slice): return plt.Let( @@ -1164,7 +1320,10 @@

    Classes

    elif isinstance(node.slice, Slice): return plt.Let( [ - ("bs", self.visit(node.value)), + ( + "bs", + self.visit(node.value), + ), ( "raw_i", self.visit(node.slice.lower), @@ -1218,7 +1377,9 @@

    Classes

    ), ), ) - raise NotImplementedError(f"Could not implement subscript of {node}") + raise NotImplementedError( + f'Could not implement subscript "{node.slice}" of "{node.value}"' + ) def visit_Tuple(self, node: TypedTuple) -> plt.AST: return plt.FunctionalTuple(*(self.visit(e) for e in node.elts)) @@ -1387,6 +1548,12 @@

    Methods

    # we need to map this as it will originate from PlutusData # AnyType is the only type other than the builtin itself that can be cast to builtin values val = transform_ext_params_map(node.target.typ)(val) + if isinstance(node.target.typ, InstanceType) and isinstance( + node.target.typ.typ, AnyType + ): + # we need to map this back as it will be treated as PlutusData + # AnyType is the only type other than the builtin itself that can be cast to from builtin values + val = transform_output_map(node.value.typ)(val) return lambda x: plt.Let([(node.target.id, val)], x)
    @@ -1774,20 +1941,24 @@

    Methods

    # TODO can use more sophisiticated procedure here i.e. functions marked by comment main_fun: typing.Optional[InstanceType] = None for s in node.body: - if isinstance(s, FunctionDef) and s.name == "validator": + if ( + isinstance(s, FunctionDef) + and s.orig_name == self.validator_function_name + ): main_fun = s - assert main_fun is not None, "Could not find function named validator" - main_fun_typ = main_fun.typ - main_fun_typ_typ: FunctionType = main_fun_typ.typ + assert ( + main_fun is not None + ), f"Could not find function named {self.validator_function_name}" + main_fun_typ: FunctionType = main_fun.typ.typ assert isinstance( - main_fun_typ_typ, FunctionType - ), "Variable named validator is not of type function" + main_fun_typ, FunctionType + ), f"Variable named {self.validator_function_name} is not of type function" # check if this is a contract written to double function enable_double_func_mint_spend = False - if len(main_fun_typ_typ.argtyps) >= 3 and self.force_three_params: + if len(main_fun_typ.typ.argtyps) >= 3 and self.force_three_params: # check if is possible - second_last_arg = main_fun_typ_typ.argtyps[-2] + second_last_arg = main_fun_typ.typ.argtyps[-2] assert isinstance( second_last_arg, InstanceType ), "Can not pass Class into validator" @@ -1811,14 +1982,16 @@

    Methods

    body = node.body + [ TypedReturn( - value=Name(id="validator", typ=main_fun_typ, ctx=Load()), - typ=main_fun_typ_typ.rettyp, + value=Name( + id=self.validator_function_name, typ=main_fun_typ, ctx=Load() + ), + typ=main_fun_typ.typ.rettyp, ) ] validator = plt.Lambda( - [f"p{i}" for i, _ in enumerate(main_fun_typ_typ.argtyps)], - transform_output_map(main_fun_typ_typ.rettyp)( + [f"p{i}" for i, _ in enumerate(main_fun_typ.typ.argtyps)], + transform_output_map(main_fun_typ.typ.rettyp)( plt.Let( [ ( @@ -1831,7 +2004,7 @@

    Methods

    plt.Var("val"), *[ transform_ext_params_map(a)(plt.Var(f"p{i}")) - for i, a in enumerate(main_fun_typ_typ.argtyps) + for i, a in enumerate(main_fun_typ.typ.argtyps) ], ), ), @@ -1839,7 +2012,7 @@

    Methods

    ) if enable_double_func_mint_spend: validator = wrap_validator_double_function( - validator, pass_through=len(main_fun_typ_typ.argtyps) - 3 + validator, pass_through=len(main_fun_typ.typ.argtyps) - 3 ) elif self.force_three_params: # Error if the double function is enforced but not possible @@ -1919,7 +2092,11 @@

    Methods

    def visit_Return(self, node: TypedReturn) -> typing.Callable[[plt.AST], plt.AST]:
         # Throw away the term we were passed, this is going to be the last!
    -    return lambda x: self.visit(node.value)
    + compiled_return = self.visit(node.value) + if isinstance(node.typ.typ.rettyp.typ, AnyType): + # if the function returns generic data, wrap the function return value + compiled_return = transform_output_map(node.value.typ)(compiled_return) + return lambda _: compiled_return
    @@ -1951,6 +2128,28 @@

    Methods

    index, len(node.value.typ.typ.typs), ) + if isinstance(node.value.typ.typ, PairType): + assert isinstance( + node.slice, Constant + ), "Only constant index access for pairs is supported" + assert isinstance( + node.slice.value, int + ), "Only constant index integer access for pairs is supported" + index = node.slice.value + if index < 0: + index += 2 + assert isinstance(node.ctx, Load), "Pairs are read-only" + assert ( + 0 <= index < 2 + ), f"Pairs only have 2 elements, index should be 0 or 1, is {node.slice.value}" + member_func = plt.FstPair if index == 0 else plt.SndPair + # the content of pairs is always Data, so we need to unwrap + member_typ = node.typ + return transform_ext_params_map(member_typ)( + member_func( + self.visit(node.value), + ), + ) if isinstance(node.value.typ.typ, ListType): assert ( node.slice.typ == IntegerInstanceType @@ -1975,6 +2174,34 @@

    Methods

    ], plt.IndexAccessList(plt.Var("l"), plt.Var("i")), ) + elif isinstance(node.value.typ.typ, DictType): + dict_typ = node.value.typ.typ + if not isinstance(node.slice, Slice): + return plt.Let( + [ + ( + "key", + self.visit(node.slice), + ) + ], + transform_ext_params_map(dict_typ.value_typ)( + plt.SndPair( + plt.FindList( + self.visit(node.value), + plt.Lambda( + ["x"], + plt.EqualsData( + transform_output_map(dict_typ.key_typ)( + plt.Var("key") + ), + plt.FstPair(plt.Var("x")), + ), + ), + plt.TraceError("KeyError"), + ), + ), + ), + ) elif isinstance(node.value.typ.typ, ByteStringType): if not isinstance(node.slice, Slice): return plt.Let( @@ -2004,7 +2231,10 @@

    Methods

    elif isinstance(node.slice, Slice): return plt.Let( [ - ("bs", self.visit(node.value)), + ( + "bs", + self.visit(node.value), + ), ( "raw_i", self.visit(node.slice.lower), @@ -2058,7 +2288,9 @@

    Methods

    ), ), ) - raise NotImplementedError(f"Could not implement subscript of {node}")
    + raise NotImplementedError( + f'Could not implement subscript "{node.slice}" of "{node.value}"' + )
    diff --git a/docs/hebi/index.html b/docs/hebi/index.html index 6f2c274..1534f54 100644 --- a/docs/hebi/index.html +++ b/docs/hebi/index.html @@ -68,11 +68,11 @@

    Package hebi

    hebi


    -Build Status +Build Status PyPI version PyPI - Python Version PyPI - Status -Coverage Status +Coverage Status

    You are building what you want. Why not also build how you want?

    @@ -126,8 +126,8 @@

    Writing a Smart Contract

  • Make sure you understand python. hebi works like python and uses python. There are tons of tutorials for python, choose what suits you best.
  • Make sure your contract is valid python and the types check out. Write simple contracts first and run them using hebi eval to get a feeling for how they work.
  • Make sure your contract is valid hebi code. Run hebi compile and look at the compiler erros for guidance along what works and doesn't work and why.
  • -
  • Dig into the examples to understand common patterns. Check out the prelude for understanding how the Script Context is structured and how complex datums are defined.
  • -
  • Check out the sample repository to find a sample setup for developing your own contract.
  • +
  • Dig into the examples to understand common patterns. Check out the prelude for understanding how the Script Context is structured and how complex datums are defined.
  • +
  • Check out the sample repository to find a sample setup for developing your own contract.
  • In summary, a smart contract in hebi is defined by the function validator in your contract file. The function validates that a specific value can be spent, minted, burned, withdrawn etc, depending @@ -147,19 +147,19 @@

    Writing a Smart Contract

    and how to build transactions with the contract.

    from hebi.prelude import *
     
    -@dataclass()
    -class CancelDatum(PlutusData):
    +@dataclass
    +class WithdrawDatum(PlutusData):
         pubkeyhash: bytes
     
     
    -def validator(datum: CancelDatum, redeemer: None, context: ScriptContext) -> None:
    +def validator(datum: WithdrawDatum, redeemer: None, context: ScriptContext) -> None:
         assert datum.pubkeyhash in context.tx_info.signatories, "Required signature missing"
     

    All contracts written in hebi are 100% valid python. Minting policies expect only a redeemer and script context as argument. -Check out the Architecture guide +Check out the Architecture guide for details on how to write double functioning contracts. -The examples folder contains more examples. +The examples folder contains more examples. Also check out the opshin-pioneer-program and opshin-starter-kit repo.

    Compiling

    @@ -247,7 +247,7 @@

    Supporters

    except ImportError as e: warnings.warn(ImportWarning(e)) -__version__ = "0.1.1.0.11.0" +__version__ = "0.1.1.0.12.3" __author__ = "nielstron" __author_email__ = "n.muendler@web.de" __copyright__ = "Copyright (C) 2023 nielstron" @@ -282,6 +282,10 @@

    Sub-modules

    +
    hebi.std
    +
    +
    +
    hebi.tests
    @@ -396,6 +400,7 @@

    Index

  • hebi.optimize
  • hebi.prelude
  • hebi.rewrite
  • +
  • hebi.std
  • hebi.tests
  • hebi.type_inference
  • hebi.typed_ast
  • diff --git a/docs/hebi/ledger/api_v2.html b/docs/hebi/ledger/api_v2.html new file mode 100644 index 0000000..7780e1b --- /dev/null +++ b/docs/hebi/ledger/api_v2.html @@ -0,0 +1,2364 @@ + + + + + + + + +hebi.ledger.api_v2 API documentation + + + + + + + + + + + +
    + + + + +
    +
    +

    Module hebi.ledger.api_v2

    +
    +
    +

    The PlutusV2 ledger API

    +
    + +Expand source code + +
    """
    +The PlutusV2 ledger API
    +"""
    +from dataclasses import dataclass
    +from typing import Dict, List, Union
    +
    +from pycardano import Datum as Anything, PlutusData
    +
    +
    +# Plutus V2
    +@dataclass(unsafe_hash=True)
    +class TxId(PlutusData):
    +    """
    +    A transaction id, a 64 bytes long hash of the transaction body (also called transaction hash).
    +
    +    Example value: TxId(bytes.fromhex("842a4d37b036da6ab3c04331240e67d81746beb44f23ad79703e026705361956"))
    +    """
    +
    +    tx_id: bytes
    +
    +
    +@dataclass(unsafe_hash=True)
    +class Nothing(PlutusData):
    +    """
    +    Nothing, can be used to signify non-importance of a parameter to a function
    +
    +    Example value: Nothing()
    +    """
    +
    +    # The maximimum constructor ID for simple cbor types, chosen to minimize probability of collision while keeping the corresponding cbor small
    +    CONSTR_ID = 6
    +
    +
    +@dataclass(unsafe_hash=True)
    +class TrueData(PlutusData):
    +    """
    +    A Datum that represents True in Haskell implementations.
    +    It is thus used as an encoding for True in the ScriptContext.
    +
    +    Example value: TrueData()
    +    """
    +
    +    CONSTR_ID = 0
    +
    +
    +@dataclass(unsafe_hash=True)
    +class FalseData(PlutusData):
    +    """
    +    A Datum that represents False in Haskell implementations.
    +    It is thus used as an encoding for False in the ScriptContext.
    +
    +    Example value: FalseData()
    +    """
    +
    +    CONSTR_ID = 1
    +
    +
    +# A Datum that represents a boolean value in Haskell implementations.
    +# It is thus used as an encoding for booleans in the ScriptContext.
    +#
    +# Example value: TrueData()
    +BoolData = Union[TrueData, FalseData]
    +
    +
    +@dataclass(unsafe_hash=True)
    +class TxOutRef(PlutusData):
    +    """
    +    A reference to a transaction output (hash/id + index)
    +    """
    +
    +    id: TxId
    +    idx: int
    +
    +
    +# A public key hash, used to identify signatures provided by a wallet
    +PubKeyHash = bytes
    +
    +
    +@dataclass(unsafe_hash=True)
    +class PubKeyCredential(PlutusData):
    +    """
    +    Part of an address that is authenticated by a public key hash
    +
    +    Example value: PubKeyCredential(bytes.fromhex("c06ddaad12fc4ded18e56feac72957c1aa75fce6096b40e63ec88274"))
    +    """
    +
    +    CONSTR_ID = 0
    +    credential_hash: PubKeyHash
    +
    +
    +# A validator hash, used to identify signatures provided by a smart contract
    +ValidatorHash = bytes
    +
    +
    +@dataclass(unsafe_hash=True)
    +class ScriptCredential(PlutusData):
    +    """
    +    Part of an address that is authenticated by a smart cotnract
    +
    +    Example value: ScriptCredential(bytes.fromhex("c06ddaad12fc4ded18e56feac72957c1aa75fce6096b40e63ec88274"))
    +    """
    +
    +    CONSTR_ID = 1
    +    credential_hash: ValidatorHash
    +
    +
    +# A credential, either smart contract or public key hash
    +Credential = Union[PubKeyCredential, ScriptCredential]
    +
    +
    +@dataclass(unsafe_hash=True)
    +class StakingHash(PlutusData):
    +    """
    +    Indicates that the stake of this address is controlled by the associated credential
    +    """
    +
    +    CONSTR_ID = 0
    +    value: Credential
    +
    +
    +@dataclass(unsafe_hash=True)
    +class StakingPtr(PlutusData):
    +    """
    +    Indicates that the stake of this address is controlled by the associated pointer.
    +
    +    In an address, a chain pointer refers to a point of the chain containing a stake key registration certificate.
    +    A point is identified by the 3 coordinates in this object.
    +    """
    +
    +    CONSTR_ID = 1
    +    # an absolute slot number
    +    slot_no: int
    +    # a transaction index (within that slot)
    +    tx_index: int
    +    # a (delegation) certificate index (within that transaction)
    +    cert_index: int
    +
    +
    +# Part of an address that controls who can delegate the stake associated with an address
    +StakingCredential = Union[StakingHash, StakingPtr]
    +
    +
    +@dataclass(unsafe_hash=True)
    +class NoStakingCredential(PlutusData):
    +    """
    +    Indicates that this address has no staking credentials.
    +    Its funds can not be delegated.
    +    """
    +
    +    CONSTR_ID = 1
    +
    +
    +@dataclass(unsafe_hash=True)
    +class SomeStakingCredential(PlutusData):
    +    """
    +    Indicates that this address has staking credentials.
    +    Its funds can be delegated by the credentialed user.
    +    """
    +
    +    CONSTR_ID = 0
    +    staking_credential: StakingCredential
    +
    +
    +@dataclass(unsafe_hash=True)
    +class Address(PlutusData):
    +    """
    +    A Shelley address, consisting of a payment and staking credential
    +    """
    +
    +    payment_credential: Credential
    +    staking_credential: Union[NoStakingCredential, SomeStakingCredential]
    +
    +
    +# The policy Id of a token
    +PolicyId = bytes
    +
    +# The name of a token in bytes (not textual representation!)
    +TokenName = bytes
    +
    +# The Plutus representation of amounts of tokens being spent, sent or minted
    +# It is a two-layered dictionary that stores for each policy id and token name
    +# the amount of the token that is being sent/minted/burned etc
    +#
    +# Lovelace is represented with policy id b"" and token name b""
    +Value = Dict[PolicyId, Dict[TokenName, int]]
    +
    +# A hash of a Datum
    +DatumHash = bytes
    +
    +
    +@dataclass(unsafe_hash=True)
    +class SomeDatumHash(PlutusData):
    +    """
    +    Indicates that there is a datum associated with this output, which has the given hash.
    +    """
    +
    +    CONSTR_ID = 1
    +    datum_hash: DatumHash
    +
    +
    +@dataclass(unsafe_hash=True)
    +class SomeScriptHash(PlutusData):
    +    """
    +    Indicates that there is a script associated with this output, which has the given hash.
    +    """
    +
    +    CONSTR_ID = 0
    +    script_hash: DatumHash
    +
    +
    +# The abstract super type of any object in opshin.
    +# Use if you don't know what kind of object is being passed or if it doesn't matter.
    +BuiltinData = Anything
    +
    +
    +# An abstract type annotation that something is supposed to be used as a redeemer.
    +Redeemer = BuiltinData
    +
    +
    +# An abstract type annotation that something is supposed to be used as a datum.
    +Datum = BuiltinData
    +
    +
    +@dataclass(unsafe_hash=True)
    +class NoOutputDatum(PlutusData):
    +    """
    +    Indicates that there is no datum associated with an output
    +    """
    +
    +    CONSTR_ID = 0
    +
    +
    +@dataclass(unsafe_hash=True)
    +class SomeOutputDatumHash(PlutusData):
    +    """
    +    Indicates that there is an datum associated with an output, which has the attached hash
    +    """
    +
    +    CONSTR_ID = 1
    +    datum_hash: DatumHash
    +
    +
    +@dataclass(unsafe_hash=True)
    +class SomeOutputDatum(PlutusData):
    +    """
    +    Indicates that there is an datum associated with an output, which is inlined and equal to the attached datum
    +    """
    +
    +    CONSTR_ID = 2
    +    datum: Datum
    +
    +
    +# Possible cases of datum association with an output
    +OutputDatum = Union[NoOutputDatum, SomeOutputDatumHash, SomeOutputDatum]
    +
    +
    +@dataclass(unsafe_hash=True)
    +class NoScriptHash(PlutusData):
    +    """
    +    Indicates that there is no script associated with an output
    +    """
    +
    +    CONSTR_ID = 1
    +
    +
    +@dataclass(unsafe_hash=True)
    +class TxOut(PlutusData):
    +    """
    +    The plutus representation of an transaction output, consisting of
    +    - address: address owning this output
    +    - value: tokens associated with this output
    +    - datum: datum associated with this output
    +    - reference_script: reference script associated with this output
    +    """
    +
    +    address: Address
    +    value: Value
    +    datum: OutputDatum
    +    reference_script: Union[NoScriptHash, SomeScriptHash]
    +
    +
    +@dataclass(unsafe_hash=True)
    +class TxInInfo(PlutusData):
    +    """
    +    The plutus representation of an transaction output, that is consumed by the transaction.
    +    """
    +
    +    out_ref: TxOutRef
    +    resolved: TxOut
    +
    +
    +@dataclass(unsafe_hash=True)
    +class DCertDelegRegKey(PlutusData):
    +    CONSTR_ID = 0
    +    value: StakingCredential
    +
    +
    +@dataclass(unsafe_hash=True)
    +class DCertDelegDeRegKey(PlutusData):
    +    CONSTR_ID = 1
    +    value: StakingCredential
    +
    +
    +@dataclass(unsafe_hash=True)
    +class DCertDelegDelegate(PlutusData):
    +    CONSTR_ID = 2
    +    delegator: StakingCredential
    +    delegatee: PubKeyHash
    +
    +
    +@dataclass(unsafe_hash=True)
    +class DCertPoolRegister(PlutusData):
    +    CONSTR_ID = 3
    +    pool_id: PubKeyHash
    +    pool_vfr: PubKeyHash
    +
    +
    +@dataclass(unsafe_hash=True)
    +class DCertPoolRetire(PlutusData):
    +    CONSTR_ID = 4
    +    retirement_certificate: PubKeyHash
    +    epoch: int
    +
    +
    +@dataclass(unsafe_hash=True)
    +class DCertGenesis(PlutusData):
    +    CONSTR_ID = 5
    +
    +
    +@dataclass(unsafe_hash=True)
    +class DCertMir(PlutusData):
    +    CONSTR_ID = 6
    +
    +
    +DCert = Union[
    +    DCertDelegRegKey,
    +    DCertDelegDeRegKey,
    +    DCertDelegDelegate,
    +    DCertPoolRegister,
    +    DCertPoolRetire,
    +    DCertGenesis,
    +    DCertMir,
    +]
    +
    +
    +POSIXTime = int
    +
    +
    +@dataclass(unsafe_hash=True)
    +class NegInfPOSIXTime(PlutusData):
    +    """
    +    Negative infinite POSIX time, used to indicate that there is no lower bound for the execution of this transaction
    +    """
    +
    +    CONSTR_ID = 0
    +
    +
    +@dataclass(unsafe_hash=True)
    +class FinitePOSIXTime(PlutusData):
    +    """
    +    Finite POSIX time, used to indicate that there is a lower or upper bound for the execution of this transaction
    +    """
    +
    +    CONSTR_ID = 1
    +    time: POSIXTime
    +
    +
    +@dataclass(unsafe_hash=True)
    +class PosInfPOSIXTime(PlutusData):
    +    """
    +    Infinite POSIX time, used to indicate that there is no upper bound for the execution of this transaction
    +    """
    +
    +    CONSTR_ID = 2
    +
    +
    +ExtendedPOSIXTime = Union[NegInfPOSIXTime, FinitePOSIXTime, PosInfPOSIXTime]
    +
    +
    +@dataclass(unsafe_hash=True)
    +class UpperBoundPOSIXTime(PlutusData):
    +    """
    +    Upper bound for the execution of this transaction
    +    """
    +
    +    CONSTR_ID = 0
    +    limit: ExtendedPOSIXTime
    +    closed: BoolData
    +
    +
    +@dataclass(unsafe_hash=True)
    +class LowerBoundPOSIXTime(PlutusData):
    +    """
    +    Lower bound for the execution of this transaction
    +    """
    +
    +    CONSTR_ID = 0
    +    limit: ExtendedPOSIXTime
    +    closed: BoolData
    +
    +
    +@dataclass(unsafe_hash=True)
    +class POSIXTimeRange(PlutusData):
    +    """
    +    Time range in which this transaction can be executed
    +    """
    +
    +    lower_bound: LowerBoundPOSIXTime
    +    upper_bound: UpperBoundPOSIXTime
    +
    +
    +@dataclass(unsafe_hash=True)
    +class Minting(PlutusData):
    +    """
    +    Script purpose indicating that the given policy id is being minted or burned
    +    """
    +
    +    CONSTR_ID = 0
    +    policy_id: PolicyId
    +
    +
    +@dataclass(unsafe_hash=True)
    +class Spending(PlutusData):
    +    """
    +    Script purpose indicating that the given transaction output is being spent, which is
    +    owned by the invoked contract
    +    """
    +
    +    CONSTR_ID = 1
    +    tx_out_ref: TxOutRef
    +
    +
    +@dataclass(unsafe_hash=True)
    +class Rewarding(PlutusData):
    +    CONSTR_ID = 2
    +    staking_credential: StakingCredential
    +
    +
    +@dataclass(unsafe_hash=True)
    +class Certifying(PlutusData):
    +    CONSTR_ID = 3
    +    d_cert: DCert
    +
    +
    +# The reason that this script is being invoked
    +ScriptPurpose = Union[Minting, Spending, Rewarding, Certifying]
    +
    +
    +@dataclass(unsafe_hash=True)
    +class TxInfo(PlutusData):
    +    """
    +    A complex agglomeration of everything that could be of interest to the executed script, regarding the transaction
    +    that invoked the script
    +    """
    +
    +    inputs: List[TxInInfo]
    +    reference_inputs: List[TxInInfo]
    +    outputs: List[TxOut]
    +    fee: Value
    +    mint: Value
    +    dcert: List[DCert]
    +    wdrl: Dict[StakingCredential, int]
    +    valid_range: POSIXTimeRange
    +    signatories: List[PubKeyHash]
    +    redeemers: Dict[ScriptPurpose, Redeemer]
    +    data: Dict[DatumHash, Datum]
    +    id: TxId
    +
    +
    +@dataclass(unsafe_hash=True)
    +class ScriptContext(PlutusData):
    +    """
    +    Auxiliary information about the transaction and reason for invocation of the called script.
    +    """
    +
    +    tx_info: TxInfo
    +    purpose: ScriptPurpose
    +
    +
    +
    +
    +
    +
    +
    +
    +
    +

    Classes

    +
    +
    +class Address +(payment_credential: Union[PubKeyCredentialScriptCredential], staking_credential: Union[NoStakingCredentialSomeStakingCredential]) +
    +
    +

    A Shelley address, consisting of a payment and staking credential

    +
    + +Expand source code + +
    class Address(PlutusData):
    +    """
    +    A Shelley address, consisting of a payment and staking credential
    +    """
    +
    +    payment_credential: Credential
    +    staking_credential: Union[NoStakingCredential, SomeStakingCredential]
    +
    +

    Ancestors

    +
      +
    • pycardano.plutus.PlutusData
    • +
    • pycardano.serialization.ArrayCBORSerializable
    • +
    • pycardano.serialization.CBORSerializable
    • +
    +

    Class variables

    +
    +
    var payment_credential : Union[PubKeyCredentialScriptCredential]
    +
    +
    +
    +
    var staking_credential : Union[NoStakingCredentialSomeStakingCredential]
    +
    +
    +
    +
    +
    +
    +class Certifying +(d_cert: Union[DCertDelegRegKeyDCertDelegDeRegKeyDCertDelegDelegateDCertPoolRegisterDCertPoolRetireDCertGenesisDCertMir]) +
    +
    +

    Certifying(d_cert: Union[hebi.ledger.api_v2.DCertDelegRegKey, hebi.ledger.api_v2.DCertDelegDeRegKey, hebi.ledger.api_v2.DCertDelegDelegate, hebi.ledger.api_v2.DCertPoolRegister, hebi.ledger.api_v2.DCertPoolRetire, hebi.ledger.api_v2.DCertGenesis, hebi.ledger.api_v2.DCertMir])

    +
    + +Expand source code + +
    class Certifying(PlutusData):
    +    CONSTR_ID = 3
    +    d_cert: DCert
    +
    +

    Ancestors

    +
      +
    • pycardano.plutus.PlutusData
    • +
    • pycardano.serialization.ArrayCBORSerializable
    • +
    • pycardano.serialization.CBORSerializable
    • +
    +

    Class variables

    +
    +
    var CONSTR_ID : ClassVar[int]
    +
    +
    +
    +
    var d_cert : Union[DCertDelegRegKeyDCertDelegDeRegKeyDCertDelegDelegateDCertPoolRegisterDCertPoolRetireDCertGenesisDCertMir]
    +
    +
    +
    +
    +
    +
    +class DCertDelegDeRegKey +(value: Union[StakingHashStakingPtr]) +
    +
    +

    DCertDelegDeRegKey(value: Union[hebi.ledger.api_v2.StakingHash, hebi.ledger.api_v2.StakingPtr])

    +
    + +Expand source code + +
    class DCertDelegDeRegKey(PlutusData):
    +    CONSTR_ID = 1
    +    value: StakingCredential
    +
    +

    Ancestors

    +
      +
    • pycardano.plutus.PlutusData
    • +
    • pycardano.serialization.ArrayCBORSerializable
    • +
    • pycardano.serialization.CBORSerializable
    • +
    +

    Class variables

    +
    +
    var CONSTR_ID : ClassVar[int]
    +
    +
    +
    +
    var value : Union[StakingHashStakingPtr]
    +
    +
    +
    +
    +
    +
    +class DCertDelegDelegate +(delegator: Union[StakingHashStakingPtr], delegatee: bytes) +
    +
    +

    DCertDelegDelegate(delegator: Union[hebi.ledger.api_v2.StakingHash, hebi.ledger.api_v2.StakingPtr], delegatee: bytes)

    +
    + +Expand source code + +
    class DCertDelegDelegate(PlutusData):
    +    CONSTR_ID = 2
    +    delegator: StakingCredential
    +    delegatee: PubKeyHash
    +
    +

    Ancestors

    +
      +
    • pycardano.plutus.PlutusData
    • +
    • pycardano.serialization.ArrayCBORSerializable
    • +
    • pycardano.serialization.CBORSerializable
    • +
    +

    Class variables

    +
    +
    var CONSTR_ID : ClassVar[int]
    +
    +
    +
    +
    var delegatee : bytes
    +
    +
    +
    +
    var delegator : Union[StakingHashStakingPtr]
    +
    +
    +
    +
    +
    +
    +class DCertDelegRegKey +(value: Union[StakingHashStakingPtr]) +
    +
    +

    DCertDelegRegKey(value: Union[hebi.ledger.api_v2.StakingHash, hebi.ledger.api_v2.StakingPtr])

    +
    + +Expand source code + +
    class DCertDelegRegKey(PlutusData):
    +    CONSTR_ID = 0
    +    value: StakingCredential
    +
    +

    Ancestors

    +
      +
    • pycardano.plutus.PlutusData
    • +
    • pycardano.serialization.ArrayCBORSerializable
    • +
    • pycardano.serialization.CBORSerializable
    • +
    +

    Class variables

    +
    +
    var CONSTR_ID : ClassVar[int]
    +
    +
    +
    +
    var value : Union[StakingHashStakingPtr]
    +
    +
    +
    +
    +
    +
    +class DCertGenesis +
    +
    +

    DCertGenesis()

    +
    + +Expand source code + +
    class DCertGenesis(PlutusData):
    +    CONSTR_ID = 5
    +
    +

    Ancestors

    +
      +
    • pycardano.plutus.PlutusData
    • +
    • pycardano.serialization.ArrayCBORSerializable
    • +
    • pycardano.serialization.CBORSerializable
    • +
    +

    Class variables

    +
    +
    var CONSTR_ID : ClassVar[int]
    +
    +
    +
    +
    +
    +
    +class DCertMir +
    +
    +

    DCertMir()

    +
    + +Expand source code + +
    class DCertMir(PlutusData):
    +    CONSTR_ID = 6
    +
    +

    Ancestors

    +
      +
    • pycardano.plutus.PlutusData
    • +
    • pycardano.serialization.ArrayCBORSerializable
    • +
    • pycardano.serialization.CBORSerializable
    • +
    +

    Class variables

    +
    +
    var CONSTR_ID : ClassVar[int]
    +
    +
    +
    +
    +
    +
    +class DCertPoolRegister +(pool_id: bytes, pool_vfr: bytes) +
    +
    +

    DCertPoolRegister(pool_id: bytes, pool_vfr: bytes)

    +
    + +Expand source code + +
    class DCertPoolRegister(PlutusData):
    +    CONSTR_ID = 3
    +    pool_id: PubKeyHash
    +    pool_vfr: PubKeyHash
    +
    +

    Ancestors

    +
      +
    • pycardano.plutus.PlutusData
    • +
    • pycardano.serialization.ArrayCBORSerializable
    • +
    • pycardano.serialization.CBORSerializable
    • +
    +

    Class variables

    +
    +
    var CONSTR_ID : ClassVar[int]
    +
    +
    +
    +
    var pool_id : bytes
    +
    +
    +
    +
    var pool_vfr : bytes
    +
    +
    +
    +
    +
    +
    +class DCertPoolRetire +(retirement_certificate: bytes, epoch: int) +
    +
    +

    DCertPoolRetire(retirement_certificate: bytes, epoch: int)

    +
    + +Expand source code + +
    class DCertPoolRetire(PlutusData):
    +    CONSTR_ID = 4
    +    retirement_certificate: PubKeyHash
    +    epoch: int
    +
    +

    Ancestors

    +
      +
    • pycardano.plutus.PlutusData
    • +
    • pycardano.serialization.ArrayCBORSerializable
    • +
    • pycardano.serialization.CBORSerializable
    • +
    +

    Class variables

    +
    +
    var CONSTR_ID : ClassVar[int]
    +
    +
    +
    +
    var epoch : int
    +
    +
    +
    +
    var retirement_certificate : bytes
    +
    +
    +
    +
    +
    +
    +class FalseData +
    +
    +

    A Datum that represents False in Haskell implementations. +It is thus used as an encoding for False in the ScriptContext.

    +

    Example value: FalseData()

    +
    + +Expand source code + +
    class FalseData(PlutusData):
    +    """
    +    A Datum that represents False in Haskell implementations.
    +    It is thus used as an encoding for False in the ScriptContext.
    +
    +    Example value: FalseData()
    +    """
    +
    +    CONSTR_ID = 1
    +
    +

    Ancestors

    +
      +
    • pycardano.plutus.PlutusData
    • +
    • pycardano.serialization.ArrayCBORSerializable
    • +
    • pycardano.serialization.CBORSerializable
    • +
    +

    Class variables

    +
    +
    var CONSTR_ID : ClassVar[int]
    +
    +
    +
    +
    +
    +
    +class FinitePOSIXTime +(time: int) +
    +
    +

    Finite POSIX time, used to indicate that there is a lower or upper bound for the execution of this transaction

    +
    + +Expand source code + +
    class FinitePOSIXTime(PlutusData):
    +    """
    +    Finite POSIX time, used to indicate that there is a lower or upper bound for the execution of this transaction
    +    """
    +
    +    CONSTR_ID = 1
    +    time: POSIXTime
    +
    +

    Ancestors

    +
      +
    • pycardano.plutus.PlutusData
    • +
    • pycardano.serialization.ArrayCBORSerializable
    • +
    • pycardano.serialization.CBORSerializable
    • +
    +

    Class variables

    +
    +
    var CONSTR_ID : ClassVar[int]
    +
    +
    +
    +
    var time : int
    +
    +
    +
    +
    +
    +
    +class LowerBoundPOSIXTime +(limit: Union[NegInfPOSIXTimeFinitePOSIXTimePosInfPOSIXTime], closed: Union[TrueDataFalseData]) +
    +
    +

    Lower bound for the execution of this transaction

    +
    + +Expand source code + +
    class LowerBoundPOSIXTime(PlutusData):
    +    """
    +    Lower bound for the execution of this transaction
    +    """
    +
    +    CONSTR_ID = 0
    +    limit: ExtendedPOSIXTime
    +    closed: BoolData
    +
    +

    Ancestors

    +
      +
    • pycardano.plutus.PlutusData
    • +
    • pycardano.serialization.ArrayCBORSerializable
    • +
    • pycardano.serialization.CBORSerializable
    • +
    +

    Class variables

    +
    +
    var CONSTR_ID : ClassVar[int]
    +
    +
    +
    +
    var closed : Union[TrueDataFalseData]
    +
    +
    +
    +
    var limit : Union[NegInfPOSIXTimeFinitePOSIXTimePosInfPOSIXTime]
    +
    +
    +
    +
    +
    +
    +class Minting +(policy_id: bytes) +
    +
    +

    Script purpose indicating that the given policy id is being minted or burned

    +
    + +Expand source code + +
    class Minting(PlutusData):
    +    """
    +    Script purpose indicating that the given policy id is being minted or burned
    +    """
    +
    +    CONSTR_ID = 0
    +    policy_id: PolicyId
    +
    +

    Ancestors

    +
      +
    • pycardano.plutus.PlutusData
    • +
    • pycardano.serialization.ArrayCBORSerializable
    • +
    • pycardano.serialization.CBORSerializable
    • +
    +

    Class variables

    +
    +
    var CONSTR_ID : ClassVar[int]
    +
    +
    +
    +
    var policy_id : bytes
    +
    +
    +
    +
    +
    +
    +class NegInfPOSIXTime +
    +
    +

    Negative infinite POSIX time, used to indicate that there is no lower bound for the execution of this transaction

    +
    + +Expand source code + +
    class NegInfPOSIXTime(PlutusData):
    +    """
    +    Negative infinite POSIX time, used to indicate that there is no lower bound for the execution of this transaction
    +    """
    +
    +    CONSTR_ID = 0
    +
    +

    Ancestors

    +
      +
    • pycardano.plutus.PlutusData
    • +
    • pycardano.serialization.ArrayCBORSerializable
    • +
    • pycardano.serialization.CBORSerializable
    • +
    +

    Class variables

    +
    +
    var CONSTR_ID : ClassVar[int]
    +
    +
    +
    +
    +
    +
    +class NoOutputDatum +
    +
    +

    Indicates that there is no datum associated with an output

    +
    + +Expand source code + +
    class NoOutputDatum(PlutusData):
    +    """
    +    Indicates that there is no datum associated with an output
    +    """
    +
    +    CONSTR_ID = 0
    +
    +

    Ancestors

    +
      +
    • pycardano.plutus.PlutusData
    • +
    • pycardano.serialization.ArrayCBORSerializable
    • +
    • pycardano.serialization.CBORSerializable
    • +
    +

    Class variables

    +
    +
    var CONSTR_ID : ClassVar[int]
    +
    +
    +
    +
    +
    +
    +class NoScriptHash +
    +
    +

    Indicates that there is no script associated with an output

    +
    + +Expand source code + +
    class NoScriptHash(PlutusData):
    +    """
    +    Indicates that there is no script associated with an output
    +    """
    +
    +    CONSTR_ID = 1
    +
    +

    Ancestors

    +
      +
    • pycardano.plutus.PlutusData
    • +
    • pycardano.serialization.ArrayCBORSerializable
    • +
    • pycardano.serialization.CBORSerializable
    • +
    +

    Class variables

    +
    +
    var CONSTR_ID : ClassVar[int]
    +
    +
    +
    +
    +
    +
    +class NoStakingCredential +
    +
    +

    Indicates that this address has no staking credentials. +Its funds can not be delegated.

    +
    + +Expand source code + +
    class NoStakingCredential(PlutusData):
    +    """
    +    Indicates that this address has no staking credentials.
    +    Its funds can not be delegated.
    +    """
    +
    +    CONSTR_ID = 1
    +
    +

    Ancestors

    +
      +
    • pycardano.plutus.PlutusData
    • +
    • pycardano.serialization.ArrayCBORSerializable
    • +
    • pycardano.serialization.CBORSerializable
    • +
    +

    Class variables

    +
    +
    var CONSTR_ID : ClassVar[int]
    +
    +
    +
    +
    +
    +
    +class Nothing +
    +
    +

    Nothing, can be used to signify non-importance of a parameter to a function

    +

    Example value: Nothing()

    +
    + +Expand source code + +
    class Nothing(PlutusData):
    +    """
    +    Nothing, can be used to signify non-importance of a parameter to a function
    +
    +    Example value: Nothing()
    +    """
    +
    +    # The maximimum constructor ID for simple cbor types, chosen to minimize probability of collision while keeping the corresponding cbor small
    +    CONSTR_ID = 6
    +
    +

    Ancestors

    +
      +
    • pycardano.plutus.PlutusData
    • +
    • pycardano.serialization.ArrayCBORSerializable
    • +
    • pycardano.serialization.CBORSerializable
    • +
    +

    Class variables

    +
    +
    var CONSTR_ID : ClassVar[int]
    +
    +
    +
    +
    +
    +
    +class POSIXTimeRange +(lower_bound: LowerBoundPOSIXTime, upper_bound: UpperBoundPOSIXTime) +
    +
    +

    Time range in which this transaction can be executed

    +
    + +Expand source code + +
    class POSIXTimeRange(PlutusData):
    +    """
    +    Time range in which this transaction can be executed
    +    """
    +
    +    lower_bound: LowerBoundPOSIXTime
    +    upper_bound: UpperBoundPOSIXTime
    +
    +

    Ancestors

    +
      +
    • pycardano.plutus.PlutusData
    • +
    • pycardano.serialization.ArrayCBORSerializable
    • +
    • pycardano.serialization.CBORSerializable
    • +
    +

    Class variables

    +
    +
    var lower_boundLowerBoundPOSIXTime
    +
    +
    +
    +
    var upper_boundUpperBoundPOSIXTime
    +
    +
    +
    +
    +
    +
    +class PosInfPOSIXTime +
    +
    +

    Infinite POSIX time, used to indicate that there is no upper bound for the execution of this transaction

    +
    + +Expand source code + +
    class PosInfPOSIXTime(PlutusData):
    +    """
    +    Infinite POSIX time, used to indicate that there is no upper bound for the execution of this transaction
    +    """
    +
    +    CONSTR_ID = 2
    +
    +

    Ancestors

    +
      +
    • pycardano.plutus.PlutusData
    • +
    • pycardano.serialization.ArrayCBORSerializable
    • +
    • pycardano.serialization.CBORSerializable
    • +
    +

    Class variables

    +
    +
    var CONSTR_ID : ClassVar[int]
    +
    +
    +
    +
    +
    +
    +class PubKeyCredential +(credential_hash: bytes) +
    +
    +

    Part of an address that is authenticated by a public key hash

    +

    Example value: PubKeyCredential(bytes.fromhex("c06ddaad12fc4ded18e56feac72957c1aa75fce6096b40e63ec88274"))

    +
    + +Expand source code + +
    class PubKeyCredential(PlutusData):
    +    """
    +    Part of an address that is authenticated by a public key hash
    +
    +    Example value: PubKeyCredential(bytes.fromhex("c06ddaad12fc4ded18e56feac72957c1aa75fce6096b40e63ec88274"))
    +    """
    +
    +    CONSTR_ID = 0
    +    credential_hash: PubKeyHash
    +
    +

    Ancestors

    +
      +
    • pycardano.plutus.PlutusData
    • +
    • pycardano.serialization.ArrayCBORSerializable
    • +
    • pycardano.serialization.CBORSerializable
    • +
    +

    Class variables

    +
    +
    var CONSTR_ID : ClassVar[int]
    +
    +
    +
    +
    var credential_hash : bytes
    +
    +
    +
    +
    +
    +
    +class Rewarding +(staking_credential: Union[StakingHashStakingPtr]) +
    +
    +

    Rewarding(staking_credential: Union[hebi.ledger.api_v2.StakingHash, hebi.ledger.api_v2.StakingPtr])

    +
    + +Expand source code + +
    class Rewarding(PlutusData):
    +    CONSTR_ID = 2
    +    staking_credential: StakingCredential
    +
    +

    Ancestors

    +
      +
    • pycardano.plutus.PlutusData
    • +
    • pycardano.serialization.ArrayCBORSerializable
    • +
    • pycardano.serialization.CBORSerializable
    • +
    +

    Class variables

    +
    +
    var CONSTR_ID : ClassVar[int]
    +
    +
    +
    +
    var staking_credential : Union[StakingHashStakingPtr]
    +
    +
    +
    +
    +
    +
    +class ScriptContext +(tx_info: TxInfo, purpose: Union[MintingSpendingRewardingCertifying]) +
    +
    +

    Auxiliary information about the transaction and reason for invocation of the called script.

    +
    + +Expand source code + +
    class ScriptContext(PlutusData):
    +    """
    +    Auxiliary information about the transaction and reason for invocation of the called script.
    +    """
    +
    +    tx_info: TxInfo
    +    purpose: ScriptPurpose
    +
    +

    Ancestors

    +
      +
    • pycardano.plutus.PlutusData
    • +
    • pycardano.serialization.ArrayCBORSerializable
    • +
    • pycardano.serialization.CBORSerializable
    • +
    +

    Class variables

    +
    +
    var purpose : Union[MintingSpendingRewardingCertifying]
    +
    +
    +
    +
    var tx_infoTxInfo
    +
    +
    +
    +
    +
    +
    +class ScriptCredential +(credential_hash: bytes) +
    +
    +

    Part of an address that is authenticated by a smart cotnract

    +

    Example value: ScriptCredential(bytes.fromhex("c06ddaad12fc4ded18e56feac72957c1aa75fce6096b40e63ec88274"))

    +
    + +Expand source code + +
    class ScriptCredential(PlutusData):
    +    """
    +    Part of an address that is authenticated by a smart cotnract
    +
    +    Example value: ScriptCredential(bytes.fromhex("c06ddaad12fc4ded18e56feac72957c1aa75fce6096b40e63ec88274"))
    +    """
    +
    +    CONSTR_ID = 1
    +    credential_hash: ValidatorHash
    +
    +

    Ancestors

    +
      +
    • pycardano.plutus.PlutusData
    • +
    • pycardano.serialization.ArrayCBORSerializable
    • +
    • pycardano.serialization.CBORSerializable
    • +
    +

    Class variables

    +
    +
    var CONSTR_ID : ClassVar[int]
    +
    +
    +
    +
    var credential_hash : bytes
    +
    +
    +
    +
    +
    +
    +class SomeDatumHash +(datum_hash: bytes) +
    +
    +

    Indicates that there is a datum associated with this output, which has the given hash.

    +
    + +Expand source code + +
    class SomeDatumHash(PlutusData):
    +    """
    +    Indicates that there is a datum associated with this output, which has the given hash.
    +    """
    +
    +    CONSTR_ID = 1
    +    datum_hash: DatumHash
    +
    +

    Ancestors

    +
      +
    • pycardano.plutus.PlutusData
    • +
    • pycardano.serialization.ArrayCBORSerializable
    • +
    • pycardano.serialization.CBORSerializable
    • +
    +

    Class variables

    +
    +
    var CONSTR_ID : ClassVar[int]
    +
    +
    +
    +
    var datum_hash : bytes
    +
    +
    +
    +
    +
    +
    +class SomeOutputDatum +(datum: Union[pycardano.plutus.PlutusData, dict, pycardano.serialization.IndefiniteList, int, bytes, pycardano.serialization.RawCBOR, pycardano.plutus.RawPlutusData]) +
    +
    +

    Indicates that there is an datum associated with an output, which is inlined and equal to the attached datum

    +
    + +Expand source code + +
    class SomeOutputDatum(PlutusData):
    +    """
    +    Indicates that there is an datum associated with an output, which is inlined and equal to the attached datum
    +    """
    +
    +    CONSTR_ID = 2
    +    datum: Datum
    +
    +

    Ancestors

    +
      +
    • pycardano.plutus.PlutusData
    • +
    • pycardano.serialization.ArrayCBORSerializable
    • +
    • pycardano.serialization.CBORSerializable
    • +
    +

    Class variables

    +
    +
    var CONSTR_ID : ClassVar[int]
    +
    +
    +
    +
    var datum : Union[pycardano.plutus.PlutusData, dict, pycardano.serialization.IndefiniteList, int, bytes, pycardano.serialization.RawCBOR, pycardano.plutus.RawPlutusData]
    +
    +
    +
    +
    +
    +
    +class SomeOutputDatumHash +(datum_hash: bytes) +
    +
    +

    Indicates that there is an datum associated with an output, which has the attached hash

    +
    + +Expand source code + +
    class SomeOutputDatumHash(PlutusData):
    +    """
    +    Indicates that there is an datum associated with an output, which has the attached hash
    +    """
    +
    +    CONSTR_ID = 1
    +    datum_hash: DatumHash
    +
    +

    Ancestors

    +
      +
    • pycardano.plutus.PlutusData
    • +
    • pycardano.serialization.ArrayCBORSerializable
    • +
    • pycardano.serialization.CBORSerializable
    • +
    +

    Class variables

    +
    +
    var CONSTR_ID : ClassVar[int]
    +
    +
    +
    +
    var datum_hash : bytes
    +
    +
    +
    +
    +
    +
    +class SomeScriptHash +(script_hash: bytes) +
    +
    +

    Indicates that there is a script associated with this output, which has the given hash.

    +
    + +Expand source code + +
    class SomeScriptHash(PlutusData):
    +    """
    +    Indicates that there is a script associated with this output, which has the given hash.
    +    """
    +
    +    CONSTR_ID = 0
    +    script_hash: DatumHash
    +
    +

    Ancestors

    +
      +
    • pycardano.plutus.PlutusData
    • +
    • pycardano.serialization.ArrayCBORSerializable
    • +
    • pycardano.serialization.CBORSerializable
    • +
    +

    Class variables

    +
    +
    var CONSTR_ID : ClassVar[int]
    +
    +
    +
    +
    var script_hash : bytes
    +
    +
    +
    +
    +
    +
    +class SomeStakingCredential +(staking_credential: Union[StakingHashStakingPtr]) +
    +
    +

    Indicates that this address has staking credentials. +Its funds can be delegated by the credentialed user.

    +
    + +Expand source code + +
    class SomeStakingCredential(PlutusData):
    +    """
    +    Indicates that this address has staking credentials.
    +    Its funds can be delegated by the credentialed user.
    +    """
    +
    +    CONSTR_ID = 0
    +    staking_credential: StakingCredential
    +
    +

    Ancestors

    +
      +
    • pycardano.plutus.PlutusData
    • +
    • pycardano.serialization.ArrayCBORSerializable
    • +
    • pycardano.serialization.CBORSerializable
    • +
    +

    Class variables

    +
    +
    var CONSTR_ID : ClassVar[int]
    +
    +
    +
    +
    var staking_credential : Union[StakingHashStakingPtr]
    +
    +
    +
    +
    +
    +
    +class Spending +(tx_out_ref: TxOutRef) +
    +
    +

    Script purpose indicating that the given transaction output is being spent, which is +owned by the invoked contract

    +
    + +Expand source code + +
    class Spending(PlutusData):
    +    """
    +    Script purpose indicating that the given transaction output is being spent, which is
    +    owned by the invoked contract
    +    """
    +
    +    CONSTR_ID = 1
    +    tx_out_ref: TxOutRef
    +
    +

    Ancestors

    +
      +
    • pycardano.plutus.PlutusData
    • +
    • pycardano.serialization.ArrayCBORSerializable
    • +
    • pycardano.serialization.CBORSerializable
    • +
    +

    Class variables

    +
    +
    var CONSTR_ID : ClassVar[int]
    +
    +
    +
    +
    var tx_out_refTxOutRef
    +
    +
    +
    +
    +
    +
    +class StakingHash +(value: Union[PubKeyCredentialScriptCredential]) +
    +
    +

    Indicates that the stake of this address is controlled by the associated credential

    +
    + +Expand source code + +
    class StakingHash(PlutusData):
    +    """
    +    Indicates that the stake of this address is controlled by the associated credential
    +    """
    +
    +    CONSTR_ID = 0
    +    value: Credential
    +
    +

    Ancestors

    +
      +
    • pycardano.plutus.PlutusData
    • +
    • pycardano.serialization.ArrayCBORSerializable
    • +
    • pycardano.serialization.CBORSerializable
    • +
    +

    Class variables

    +
    +
    var CONSTR_ID : ClassVar[int]
    +
    +
    +
    +
    var value : Union[PubKeyCredentialScriptCredential]
    +
    +
    +
    +
    +
    +
    +class StakingPtr +(slot_no: int, tx_index: int, cert_index: int) +
    +
    +

    Indicates that the stake of this address is controlled by the associated pointer.

    +

    In an address, a chain pointer refers to a point of the chain containing a stake key registration certificate. +A point is identified by the 3 coordinates in this object.

    +
    + +Expand source code + +
    class StakingPtr(PlutusData):
    +    """
    +    Indicates that the stake of this address is controlled by the associated pointer.
    +
    +    In an address, a chain pointer refers to a point of the chain containing a stake key registration certificate.
    +    A point is identified by the 3 coordinates in this object.
    +    """
    +
    +    CONSTR_ID = 1
    +    # an absolute slot number
    +    slot_no: int
    +    # a transaction index (within that slot)
    +    tx_index: int
    +    # a (delegation) certificate index (within that transaction)
    +    cert_index: int
    +
    +

    Ancestors

    +
      +
    • pycardano.plutus.PlutusData
    • +
    • pycardano.serialization.ArrayCBORSerializable
    • +
    • pycardano.serialization.CBORSerializable
    • +
    +

    Class variables

    +
    +
    var CONSTR_ID : ClassVar[int]
    +
    +
    +
    +
    var cert_index : int
    +
    +
    +
    +
    var slot_no : int
    +
    +
    +
    +
    var tx_index : int
    +
    +
    +
    +
    +
    +
    +class TrueData +
    +
    +

    A Datum that represents True in Haskell implementations. +It is thus used as an encoding for True in the ScriptContext.

    +

    Example value: TrueData()

    +
    + +Expand source code + +
    class TrueData(PlutusData):
    +    """
    +    A Datum that represents True in Haskell implementations.
    +    It is thus used as an encoding for True in the ScriptContext.
    +
    +    Example value: TrueData()
    +    """
    +
    +    CONSTR_ID = 0
    +
    +

    Ancestors

    +
      +
    • pycardano.plutus.PlutusData
    • +
    • pycardano.serialization.ArrayCBORSerializable
    • +
    • pycardano.serialization.CBORSerializable
    • +
    +

    Class variables

    +
    +
    var CONSTR_ID : ClassVar[int]
    +
    +
    +
    +
    +
    +
    +class TxId +(tx_id: bytes) +
    +
    +

    A transaction id, a 64 bytes long hash of the transaction body (also called transaction hash).

    +

    Example value: TxId(bytes.fromhex("842a4d37b036da6ab3c04331240e67d81746beb44f23ad79703e026705361956"))

    +
    + +Expand source code + +
    class TxId(PlutusData):
    +    """
    +    A transaction id, a 64 bytes long hash of the transaction body (also called transaction hash).
    +
    +    Example value: TxId(bytes.fromhex("842a4d37b036da6ab3c04331240e67d81746beb44f23ad79703e026705361956"))
    +    """
    +
    +    tx_id: bytes
    +
    +

    Ancestors

    +
      +
    • pycardano.plutus.PlutusData
    • +
    • pycardano.serialization.ArrayCBORSerializable
    • +
    • pycardano.serialization.CBORSerializable
    • +
    +

    Class variables

    +
    +
    var tx_id : bytes
    +
    +
    +
    +
    +
    +
    +class TxInInfo +(out_ref: TxOutRef, resolved: TxOut) +
    +
    +

    The plutus representation of an transaction output, that is consumed by the transaction.

    +
    + +Expand source code + +
    class TxInInfo(PlutusData):
    +    """
    +    The plutus representation of an transaction output, that is consumed by the transaction.
    +    """
    +
    +    out_ref: TxOutRef
    +    resolved: TxOut
    +
    +

    Ancestors

    +
      +
    • pycardano.plutus.PlutusData
    • +
    • pycardano.serialization.ArrayCBORSerializable
    • +
    • pycardano.serialization.CBORSerializable
    • +
    +

    Class variables

    +
    +
    var out_refTxOutRef
    +
    +
    +
    +
    var resolvedTxOut
    +
    +
    +
    +
    +
    +
    +class TxInfo +(inputs: List[TxInInfo], reference_inputs: List[TxInInfo], outputs: List[TxOut], fee: Dict[bytes, Dict[bytes, int]], mint: Dict[bytes, Dict[bytes, int]], dcert: List[Union[DCertDelegRegKeyDCertDelegDeRegKeyDCertDelegDelegateDCertPoolRegisterDCertPoolRetireDCertGenesisDCertMir]], wdrl: Dict[Union[StakingHashStakingPtr], int], valid_range: POSIXTimeRange, signatories: List[bytes], redeemers: Dict[Union[MintingSpendingRewardingCertifying], Union[pycardano.plutus.PlutusData, dict, pycardano.serialization.IndefiniteList, int, bytes, pycardano.serialization.RawCBOR, pycardano.plutus.RawPlutusData]], data: Dict[bytes, Union[pycardano.plutus.PlutusData, dict, pycardano.serialization.IndefiniteList, int, bytes, pycardano.serialization.RawCBOR, pycardano.plutus.RawPlutusData]], id: TxId) +
    +
    +

    A complex agglomeration of everything that could be of interest to the executed script, regarding the transaction +that invoked the script

    +
    + +Expand source code + +
    class TxInfo(PlutusData):
    +    """
    +    A complex agglomeration of everything that could be of interest to the executed script, regarding the transaction
    +    that invoked the script
    +    """
    +
    +    inputs: List[TxInInfo]
    +    reference_inputs: List[TxInInfo]
    +    outputs: List[TxOut]
    +    fee: Value
    +    mint: Value
    +    dcert: List[DCert]
    +    wdrl: Dict[StakingCredential, int]
    +    valid_range: POSIXTimeRange
    +    signatories: List[PubKeyHash]
    +    redeemers: Dict[ScriptPurpose, Redeemer]
    +    data: Dict[DatumHash, Datum]
    +    id: TxId
    +
    +

    Ancestors

    +
      +
    • pycardano.plutus.PlutusData
    • +
    • pycardano.serialization.ArrayCBORSerializable
    • +
    • pycardano.serialization.CBORSerializable
    • +
    +

    Class variables

    +
    +
    var data : Dict[bytes, Union[pycardano.plutus.PlutusData, dict, pycardano.serialization.IndefiniteList, int, bytes, pycardano.serialization.RawCBOR, pycardano.plutus.RawPlutusData]]
    +
    +
    +
    +
    var dcert : List[Union[DCertDelegRegKeyDCertDelegDeRegKeyDCertDelegDelegateDCertPoolRegisterDCertPoolRetireDCertGenesisDCertMir]]
    +
    +
    +
    +
    var fee : Dict[bytes, Dict[bytes, int]]
    +
    +
    +
    +
    var idTxId
    +
    +
    +
    +
    var inputs : List[TxInInfo]
    +
    +
    +
    +
    var mint : Dict[bytes, Dict[bytes, int]]
    +
    +
    +
    +
    var outputs : List[TxOut]
    +
    +
    +
    +
    var redeemers : Dict[Union[MintingSpendingRewardingCertifying], Union[pycardano.plutus.PlutusData, dict, pycardano.serialization.IndefiniteList, int, bytes, pycardano.serialization.RawCBOR, pycardano.plutus.RawPlutusData]]
    +
    +
    +
    +
    var reference_inputs : List[TxInInfo]
    +
    +
    +
    +
    var signatories : List[bytes]
    +
    +
    +
    +
    var valid_rangePOSIXTimeRange
    +
    +
    +
    +
    var wdrl : Dict[Union[StakingHashStakingPtr], int]
    +
    +
    +
    +
    +
    +
    +class TxOut +(address: Address, value: Dict[bytes, Dict[bytes, int]], datum: Union[NoOutputDatumSomeOutputDatumHashSomeOutputDatum], reference_script: Union[NoScriptHashSomeScriptHash]) +
    +
    +

    The plutus representation of an transaction output, consisting of +- address: address owning this output +- value: tokens associated with this output +- datum: datum associated with this output +- reference_script: reference script associated with this output

    +
    + +Expand source code + +
    class TxOut(PlutusData):
    +    """
    +    The plutus representation of an transaction output, consisting of
    +    - address: address owning this output
    +    - value: tokens associated with this output
    +    - datum: datum associated with this output
    +    - reference_script: reference script associated with this output
    +    """
    +
    +    address: Address
    +    value: Value
    +    datum: OutputDatum
    +    reference_script: Union[NoScriptHash, SomeScriptHash]
    +
    +

    Ancestors

    +
      +
    • pycardano.plutus.PlutusData
    • +
    • pycardano.serialization.ArrayCBORSerializable
    • +
    • pycardano.serialization.CBORSerializable
    • +
    +

    Class variables

    +
    +
    var addressAddress
    +
    +
    +
    +
    var datum : Union[NoOutputDatumSomeOutputDatumHashSomeOutputDatum]
    +
    +
    +
    +
    var reference_script : Union[NoScriptHashSomeScriptHash]
    +
    +
    +
    +
    var value : Dict[bytes, Dict[bytes, int]]
    +
    +
    +
    +
    +
    +
    +class TxOutRef +(id: TxId, idx: int) +
    +
    +

    A reference to a transaction output (hash/id + index)

    +
    + +Expand source code + +
    class TxOutRef(PlutusData):
    +    """
    +    A reference to a transaction output (hash/id + index)
    +    """
    +
    +    id: TxId
    +    idx: int
    +
    +

    Ancestors

    +
      +
    • pycardano.plutus.PlutusData
    • +
    • pycardano.serialization.ArrayCBORSerializable
    • +
    • pycardano.serialization.CBORSerializable
    • +
    +

    Class variables

    +
    +
    var idTxId
    +
    +
    +
    +
    var idx : int
    +
    +
    +
    +
    +
    +
    +class UpperBoundPOSIXTime +(limit: Union[NegInfPOSIXTimeFinitePOSIXTimePosInfPOSIXTime], closed: Union[TrueDataFalseData]) +
    +
    +

    Upper bound for the execution of this transaction

    +
    + +Expand source code + +
    class UpperBoundPOSIXTime(PlutusData):
    +    """
    +    Upper bound for the execution of this transaction
    +    """
    +
    +    CONSTR_ID = 0
    +    limit: ExtendedPOSIXTime
    +    closed: BoolData
    +
    +

    Ancestors

    +
      +
    • pycardano.plutus.PlutusData
    • +
    • pycardano.serialization.ArrayCBORSerializable
    • +
    • pycardano.serialization.CBORSerializable
    • +
    +

    Class variables

    +
    +
    var CONSTR_ID : ClassVar[int]
    +
    +
    +
    +
    var closed : Union[TrueDataFalseData]
    +
    +
    +
    +
    var limit : Union[NegInfPOSIXTimeFinitePOSIXTimePosInfPOSIXTime]
    +
    +
    +
    +
    +
    +
    +
    +
    + +
    + + + \ No newline at end of file diff --git a/docs/hebi/ledger/index.html b/docs/hebi/ledger/index.html index 0ebd698..29d1a8c 100644 --- a/docs/hebi/ledger/index.html +++ b/docs/hebi/ledger/index.html @@ -68,6 +68,10 @@

    Module hebi.ledger

    Sub-modules

    +
    hebi.ledger.api_v2
    +
    +

    The PlutusV2 ledger API

    +
    hebi.ledger.interval
    @@ -147,6 +151,7 @@

    Index

  • Sub-modules

  • diff --git a/docs/hebi/ledger/interval.html b/docs/hebi/ledger/interval.html index bba4101..76aea09 100644 --- a/docs/hebi/ledger/interval.html +++ b/docs/hebi/ledger/interval.html @@ -142,7 +142,7 @@

    Module hebi.ledger.interval

    def contains(a: POSIXTimeRange, b: POSIXTimeRange) -> bool: - # Returns True if the interval `b` is entirely contained in `a`. + """Returns True if the interval `b` is entirely contained in `a`.""" lower = compare_lower_bound(a.lower_bound, b.lower_bound) upper = compare_upper_bound(a.upper_bound, b.upper_bound) return (lower == 1 or lower == 0) and (upper == 0 or upper == -1) @@ -151,26 +151,31 @@

    Module hebi.ledger.interval

    def make_range( lower_bound: POSIXTime, upper_bound: POSIXTime, - lower_closed: BoolData, - upper_closed: BoolData, ) -> POSIXTimeRange: + """ + Create a bounded interval from the given time `lower_bound` up to the given `upper_bound`, including the given time + """ return POSIXTimeRange( - LowerBoundPOSIXTime(FinitePOSIXTime(lower_bound), lower_closed), - UpperBoundPOSIXTime(FinitePOSIXTime(upper_bound), upper_closed), + LowerBoundPOSIXTime(FinitePOSIXTime(lower_bound), TrueData()), + UpperBoundPOSIXTime(FinitePOSIXTime(upper_bound), TrueData()), ) -def make_from(lower_bound: POSIXTime, lower_closed: BoolData) -> POSIXTimeRange: +def make_from(lower_bound: POSIXTime) -> POSIXTimeRange: + """Create a bounded interval from the given time `lower_bound` up to infinity, including the given time""" return POSIXTimeRange( - LowerBoundPOSIXTime(FinitePOSIXTime(lower_bound), lower_closed), + LowerBoundPOSIXTime(FinitePOSIXTime(lower_bound), TrueData()), UpperBoundPOSIXTime(PosInfPOSIXTime(), TrueData()), ) -def make_to(upper_bound: POSIXTime, upper_closed: BoolData) -> POSIXTimeRange: +def make_to(upper_bound: POSIXTime) -> POSIXTimeRange: + """ + Create a bounded interval from negative infinity up to the given `upper_bound`, including the given time + """ return POSIXTimeRange( LowerBoundPOSIXTime(NegInfPOSIXTime(), TrueData()), - UpperBoundPOSIXTime(FinitePOSIXTime(upper_bound), upper_closed), + UpperBoundPOSIXTime(FinitePOSIXTime(upper_bound), TrueData()), )
    @@ -203,7 +208,7 @@

    Functions

    -def compare_extended(a: Union[NegInfPOSIXTimeFinitePOSIXTimePosInfPOSIXTime], b: Union[NegInfPOSIXTimeFinitePOSIXTimePosInfPOSIXTime]) ‑> int +def compare_extended(a: Union[NegInfPOSIXTimeFinitePOSIXTimePosInfPOSIXTime], b: Union[NegInfPOSIXTimeFinitePOSIXTimePosInfPOSIXTime]) ‑> int
    @@ -226,7 +231,7 @@

    Functions

    -def compare_extended_helper(time: Union[NegInfPOSIXTimeFinitePOSIXTimePosInfPOSIXTime]) ‑> int +def compare_extended_helper(time: Union[NegInfPOSIXTimeFinitePOSIXTimePosInfPOSIXTime]) ‑> int
    @@ -246,7 +251,7 @@

    Functions

    -def compare_lower_bound(a: LowerBoundPOSIXTime, b: LowerBoundPOSIXTime) ‑> int +def compare_lower_bound(a: LowerBoundPOSIXTime, b: LowerBoundPOSIXTime) ‑> int
    @@ -268,7 +273,7 @@

    Functions

    -def compare_upper_bound(a: UpperBoundPOSIXTime, b: UpperBoundPOSIXTime) ‑> int +def compare_upper_bound(a: UpperBoundPOSIXTime, b: UpperBoundPOSIXTime) ‑> int
    @@ -290,23 +295,23 @@

    Functions

    -def contains(a: POSIXTimeRange, b: POSIXTimeRange) ‑> bool +def contains(a: POSIXTimeRange, b: POSIXTimeRange) ‑> bool
    -
    +

    Returns True if the interval b is entirely contained in a.

    Expand source code
    def contains(a: POSIXTimeRange, b: POSIXTimeRange) -> bool:
    -    # Returns True if the interval `b` is entirely contained in `a`.
    +    """Returns True if the interval `b` is entirely contained in `a`."""
         lower = compare_lower_bound(a.lower_bound, b.lower_bound)
         upper = compare_upper_bound(a.upper_bound, b.upper_bound)
         return (lower == 1 or lower == 0) and (upper == 0 or upper == -1)
    -def get_bool(b: Union[TrueDataFalseData]) ‑> bool +def get_bool(b: Union[TrueDataFalseData]) ‑> bool
    @@ -322,26 +327,27 @@

    Functions

    -def make_from(lower_bound: int, lower_closed: Union[TrueDataFalseData]) ‑> POSIXTimeRange +def make_from(lower_bound: int) ‑> POSIXTimeRange
    -
    +

    Create a bounded interval from the given time lower_bound up to infinity, including the given time

    Expand source code -
    def make_from(lower_bound: POSIXTime, lower_closed: BoolData) -> POSIXTimeRange:
    +
    def make_from(lower_bound: POSIXTime) -> POSIXTimeRange:
    +    """Create a bounded interval from the given time `lower_bound` up to infinity, including the given time"""
         return POSIXTimeRange(
    -        LowerBoundPOSIXTime(FinitePOSIXTime(lower_bound), lower_closed),
    +        LowerBoundPOSIXTime(FinitePOSIXTime(lower_bound), TrueData()),
             UpperBoundPOSIXTime(PosInfPOSIXTime(), TrueData()),
         )
    -def make_range(lower_bound: int, upper_bound: int, lower_closed: Union[TrueDataFalseData], upper_closed: Union[TrueDataFalseData]) ‑> POSIXTimeRange +def make_range(lower_bound: int, upper_bound: int) ‑> POSIXTimeRange
    -
    +

    Create a bounded interval from the given time lower_bound up to the given upper_bound, including the given time

    Expand source code @@ -349,28 +355,32 @@

    Functions

    def make_range(
         lower_bound: POSIXTime,
         upper_bound: POSIXTime,
    -    lower_closed: BoolData,
    -    upper_closed: BoolData,
     ) -> POSIXTimeRange:
    +    """
    +    Create a bounded interval from the given time `lower_bound` up to the given `upper_bound`, including the given time
    +    """
         return POSIXTimeRange(
    -        LowerBoundPOSIXTime(FinitePOSIXTime(lower_bound), lower_closed),
    -        UpperBoundPOSIXTime(FinitePOSIXTime(upper_bound), upper_closed),
    +        LowerBoundPOSIXTime(FinitePOSIXTime(lower_bound), TrueData()),
    +        UpperBoundPOSIXTime(FinitePOSIXTime(upper_bound), TrueData()),
         )
    -def make_to(upper_bound: int, upper_closed: Union[TrueDataFalseData]) ‑> POSIXTimeRange +def make_to(upper_bound: int) ‑> POSIXTimeRange
    -
    +

    Create a bounded interval from negative infinity up to the given upper_bound, including the given time

    Expand source code -
    def make_to(upper_bound: POSIXTime, upper_closed: BoolData) -> POSIXTimeRange:
    +
    def make_to(upper_bound: POSIXTime) -> POSIXTimeRange:
    +    """
    +    Create a bounded interval from negative infinity up to the given `upper_bound`, including the given time
    +    """
         return POSIXTimeRange(
             LowerBoundPOSIXTime(NegInfPOSIXTime(), TrueData()),
    -        UpperBoundPOSIXTime(FinitePOSIXTime(upper_bound), upper_closed),
    +        UpperBoundPOSIXTime(FinitePOSIXTime(upper_bound), TrueData()),
         )
    diff --git a/docs/hebi/optimize/index.html b/docs/hebi/optimize/index.html index eead172..13d4d0f 100644 --- a/docs/hebi/optimize/index.html +++ b/docs/hebi/optimize/index.html @@ -68,6 +68,10 @@

    Module hebi.optimize

    Sub-modules

    +
    hebi.optimize.optimize_remove_comments
    +
    +
    +
    hebi.optimize.optimize_remove_deadvars
    @@ -155,6 +159,7 @@

    Index

  • Sub-modules

      +
    • hebi.optimize.optimize_remove_comments
    • hebi.optimize.optimize_remove_deadvars
    • hebi.optimize.optimize_remove_pass
    • hebi.optimize.optimize_varlen
    • diff --git a/docs/hebi/optimize/optimize_remove_comments.html b/docs/hebi/optimize/optimize_remove_comments.html new file mode 100644 index 0000000..b1ef368 --- /dev/null +++ b/docs/hebi/optimize/optimize_remove_comments.html @@ -0,0 +1,270 @@ + + + + + + + + +hebi.optimize.optimize_remove_comments API documentation + + + + + + + + + + + +
      + + + + +
      +
      +

      Module hebi.optimize.optimize_remove_comments

      +
      +
      +
      + +Expand source code + +
      from ast import *
      +
      +from ..util import CompilingNodeTransformer
      +
      +"""
      +Removes expressions that return constants in sequences of statements (i.e. string comments)
      +"""
      +
      +
      +class OptimizeRemoveDeadconstants(CompilingNodeTransformer):
      +    step = "Removing constants (i.e. string comments)"
      +
      +    def visit_Expr(self, node: Expr):
      +        if isinstance(node.value, Constant):
      +            return None
      +        return node
      +
      +
      +
      +
      +
      +
      +
      +
      +
      +

      Classes

      +
      +
      +class OptimizeRemoveDeadconstants +
      +
      +

      A :class:NodeVisitor subclass that walks the abstract syntax tree and +allows modification of nodes.

      +

      The NodeTransformer will walk the AST and use the return value of the +visitor methods to replace or remove the old node. +If the return value of +the visitor method is None, the node will be removed from its location, +otherwise it is replaced with the return value. +The return value may be the +original node in which case no replacement takes place.

      +

      Here is an example transformer that rewrites all occurrences of name lookups +(foo) to data['foo']::

      +

      class RewriteName(NodeTransformer):

      +
         def visit_Name(self, node):
      +       return Subscript(
      +           value=Name(id='data', ctx=Load()),
      +           slice=Index(value=Str(s=node.id)),
      +           ctx=node.ctx
      +       )
      +
      +

      Keep in mind that if the node you're operating on has child nodes you must +either transform the child nodes yourself or call the :meth:generic_visit +method for the node first.

      +

      For nodes that were part of a collection of statements (that applies to all +statement nodes), the visitor may also return a list of nodes rather than +just a single node.

      +

      Usually you use the transformer like this::

      +

      node = YourTransformer().visit(node)

      +
      + +Expand source code + +
      class OptimizeRemoveDeadconstants(CompilingNodeTransformer):
      +    step = "Removing constants (i.e. string comments)"
      +
      +    def visit_Expr(self, node: Expr):
      +        if isinstance(node.value, Constant):
      +            return None
      +        return node
      +
      +

      Ancestors

      + +

      Class variables

      +
      +
      var step
      +
      +
      +
      +
      +

      Methods

      +
      +
      +def visit(self, node) +
      +
      +

      +Inherited from: +CompilingNodeTransformer.visit +

      +

      Visit a node.

      +
      +
      +def visit_Expr(self, node: _ast.Expr) +
      +
      +
      +
      + +Expand source code + +
      def visit_Expr(self, node: Expr):
      +    if isinstance(node.value, Constant):
      +        return None
      +    return node
      +
      +
      +
      +
      +
      +
      +
      + +
      + + + \ No newline at end of file diff --git a/docs/hebi/prelude.html b/docs/hebi/prelude.html index 7a8de0f..3f6dd5e 100644 --- a/docs/hebi/prelude.html +++ b/docs/hebi/prelude.html @@ -68,483 +68,11 @@

      Module hebi.prelude

      Expand source code -
      from dataclasses import dataclass
      -from typing import Dict, List, Union
      -from hashlib import sha256, sha3_256, blake2b
      +
      from hashlib import sha256, sha3_256, blake2b
      +from hebi.ledger.api_v2 import *
       
      -from pycardano import Datum as Anything, PlutusData
       
      -# Plutus V2
      -@dataclass()
      -class TxId(PlutusData):
      -    """
      -    A transaction id, a 64 bytes long hash of the transaction body (also called transaction hash).
      -
      -    Example value: TxId(bytes.fromhex("842a4d37b036da6ab3c04331240e67d81746beb44f23ad79703e026705361956"))
      -    """
      -
      -    tx_id: bytes
      -
      -
      -@dataclass()
      -class Nothing(PlutusData):
      -    """
      -    Nothing, can be used to signify non-importance of a parameter to a function
      -
      -    Example value: Nothing()
      -    """
      -
      -    # The maximimum constructor ID for simple cbor types, chosen to minimize probability of collision while keeping the corresponding cbor small
      -    CONSTR_ID = 6
      -
      -
      -@dataclass()
      -class TrueData(PlutusData):
      -    """
      -    A Datum that represents True in Haskell implementations.
      -    It is thus used as an encoding for True in the ScriptContext.
      -
      -    Example value: TrueData()
      -    """
      -
      -    CONSTR_ID = 0
      -
      -
      -@dataclass()
      -class FalseData(PlutusData):
      -    """
      -    A Datum that represents False in Haskell implementations.
      -    It is thus used as an encoding for False in the ScriptContext.
      -
      -    Example value: FalseData()
      -    """
      -
      -    CONSTR_ID = 1
      -
      -
      -# A Datum that represents a boolean value in Haskell implementations.
      -# It is thus used as an encoding for booleans in the ScriptContext.
      -#
      -# Example value: TrueData()
      -BoolData = Union[TrueData, FalseData]
      -
      -
      -@dataclass()
      -class TxOutRef(PlutusData):
      -    """
      -    A reference to a transaction output (hash/id + index)
      -    """
      -
      -    id: TxId
      -    idx: int
      -
      -
      -# A public key hash, used to identify signatures provided by a wallet
      -PubKeyHash = bytes
      -
      -
      -@dataclass()
      -class PubKeyCredential(PlutusData):
      -    """
      -    Part of an address that is authenticated by a public key hash
      -
      -    Example value: PubKeyCredential(bytes.fromhex("c06ddaad12fc4ded18e56feac72957c1aa75fce6096b40e63ec88274"))
      -    """
      -
      -    CONSTR_ID = 0
      -    credential_hash: PubKeyHash
      -
      -
      -# A validator hash, used to identify signatures provided by a smart contract
      -ValidatorHash = bytes
      -
      -
      -@dataclass()
      -class ScriptCredential(PlutusData):
      -    """
      -    Part of an address that is authenticated by a smart cotnract
      -
      -    Example value: ScriptCredential(bytes.fromhex("c06ddaad12fc4ded18e56feac72957c1aa75fce6096b40e63ec88274"))
      -    """
      -
      -    CONSTR_ID = 1
      -    credential_hash: ValidatorHash
      -
      -
      -# A credential, either smart contract or public key hash
      -Credential = Union[PubKeyCredential, ScriptCredential]
      -
      -
      -@dataclass()
      -class StakingHash(PlutusData):
      -    """
      -    Indicates that the stake of this address is controlled by the associated credential
      -    """
      -
      -    CONSTR_ID = 0
      -    value: Credential
      -
      -
      -@dataclass()
      -class StakingPtr(PlutusData):
      -    """
      -    Indicates that the stake of this address is controlled by the associated pointer.
      -
      -    In an address, a chain pointer refers to a point of the chain containing a stake key registration certificate.
      -    A point is identified by the 3 coordinates in this object.
      -    """
      -
      -    CONSTR_ID = 1
      -    # an absolute slot number
      -    slot_no: int
      -    # a transaction index (within that slot)
      -    tx_index: int
      -    # a (delegation) certificate index (within that transaction)
      -    cert_index: int
      -
      -
      -# Part of an address that controls who can delegate the stake associated with an address
      -StakingCredential = Union[StakingHash, StakingPtr]
      -
      -
      -@dataclass()
      -class NoStakingCredential(PlutusData):
      -    """
      -    Indicates that this address has no staking credentials.
      -    Its funds can not be delegated.
      -    """
      -
      -    CONSTR_ID = 1
      -
      -
      -@dataclass()
      -class SomeStakingCredential(PlutusData):
      -    """
      -    Indicates that this address has staking credentials.
      -    Its funds can be delegated by the credentialed user.
      -    """
      -
      -    CONSTR_ID = 0
      -    staking_credential: StakingCredential
      -
      -
      -@dataclass()
      -class Address(PlutusData):
      -    """
      -    A Shelley address, consisting of a payment and staking credential
      -    """
      -
      -    payment_credential: Credential
      -    staking_credential: Union[NoStakingCredential, SomeStakingCredential]
      -
      -
      -# The policy Id of a token
      -PolicyId = bytes
      -
      -# The name of a token in bytes (not textual representation!)
      -TokenName = bytes
      -
      -# The Plutus representation of amounts of tokens being spent, sent or minted
      -# It is a two-layered dictionary that stores for each policy id and token name
      -# the amount of the token that is being sent/minted/burned etc
      -#
      -# Lovelace is represented with policy id b"" and token name b""
      -Value = Dict[PolicyId, Dict[TokenName, int]]
      -
      -# A hash of a Datum
      -DatumHash = bytes
      -
      -
      -@dataclass()
      -class SomeDatumHash(PlutusData):
      -    """
      -    Indicates that there is a datum associated with this output, which has the given hash.
      -    """
      -
      -    CONSTR_ID = 1
      -    datum_hash: DatumHash
      -
      -
      -@dataclass()
      -class SomeScriptHash(PlutusData):
      -    """
      -    Indicates that there is a script associated with this output, which has the given hash.
      -    """
      -
      -    CONSTR_ID = 0
      -    script_hash: DatumHash
      -
      -
      -# The abstract super type of any object in opshin.
      -# Use if you don't know what kind of object is being passed or if it doesn't matter.
      -BuiltinData = Anything
      -
      -
      -# An abstract type annotation that something is supposed to be used as a redeemer.
      -Redeemer = BuiltinData
      -
      -
      -# An abstract type annotation that something is supposed to be used as a datum.
      -Datum = BuiltinData
      -
      -
      -@dataclass()
      -class NoOutputDatum(PlutusData):
      -    """
      -    Indicates that there is no datum associated with an output
      -    """
      -
      -    CONSTR_ID = 0
      -
      -
      -@dataclass()
      -class SomeOutputDatumHash(PlutusData):
      -    """
      -    Indicates that there is an datum associated with an output, which has the attached hash
      -    """
      -
      -    CONSTR_ID = 1
      -    datum_hash: DatumHash
      -
      -
      -@dataclass()
      -class SomeOutputDatum(PlutusData):
      -    """
      -    Indicates that there is an datum associated with an output, which is inlined and equal to the attached datum
      -    """
      -
      -    CONSTR_ID = 2
      -    datum: Datum
      -
      -
      -# Possible cases of datum association with an output
      -OutputDatum = Union[NoOutputDatum, SomeOutputDatumHash, SomeOutputDatum]
      -
      -
      -@dataclass()
      -class NoScriptHash(PlutusData):
      -    """
      -    Indicates that there is no script associated with an output
      -    """
      -
      -    CONSTR_ID = 1
      -
      -
      -@dataclass()
      -class TxOut(PlutusData):
      -    """
      -    The plutus representation of an transaction output, consisting of
      -    - address: address owning this output
      -    - value: tokens associated with this output
      -    - datum: datum associated with this output
      -    - reference_script: reference script associated with this output
      -    """
      -
      -    address: Address
      -    value: Value
      -    datum: OutputDatum
      -    reference_script: Union[NoScriptHash, SomeScriptHash]
      -
      -
      -@dataclass()
      -class TxInInfo(PlutusData):
      -    """
      -    The plutus representation of an transaction output, that is consumed by the transaction.
      -    """
      -
      -    out_ref: TxOutRef
      -    resolved: TxOut
      -
      -
      -@dataclass()
      -class DCertDelegRegKey(PlutusData):
      -    CONSTR_ID = 0
      -    value: StakingCredential
      -
      -
      -@dataclass()
      -class DCertDelegDeRegKey(PlutusData):
      -    CONSTR_ID = 1
      -    value: StakingCredential
      -
      -
      -@dataclass()
      -class DCertDelegDelegate(PlutusData):
      -    CONSTR_ID = 2
      -    delegator: StakingCredential
      -    delegatee: PubKeyHash
      -
      -
      -@dataclass()
      -class DCertPoolRegister(PlutusData):
      -    CONSTR_ID = 3
      -    pool_id: PubKeyHash
      -    pool_vfr: PubKeyHash
      -
      -
      -@dataclass()
      -class DCertPoolRetire(PlutusData):
      -    CONSTR_ID = 4
      -    retirement_certificate: PubKeyHash
      -    epoch: int
      -
      -
      -@dataclass()
      -class DCertGenesis(PlutusData):
      -    CONSTR_ID = 5
      -
      -
      -@dataclass()
      -class DCertMir(PlutusData):
      -    CONSTR_ID = 6
      -
      -
      -DCert = Union[
      -    DCertDelegRegKey,
      -    DCertDelegDeRegKey,
      -    DCertDelegDelegate,
      -    DCertPoolRegister,
      -    DCertPoolRetire,
      -    DCertGenesis,
      -    DCertMir,
      -]
      -
      -
      -POSIXTime = int
      -
      -
      -@dataclass()
      -class NegInfPOSIXTime(PlutusData):
      -    """
      -    Negative infinite POSIX time, used to indicate that there is no lower bound for the execution of this transaction
      -    """
      -
      -    CONSTR_ID = 0
      -
      -
      -@dataclass()
      -class FinitePOSIXTime(PlutusData):
      -    """
      -    Finite POSIX time, used to indicate that there is a lower or upper bound for the execution of this transaction
      -    """
      -
      -    CONSTR_ID = 1
      -    time: POSIXTime
      -
      -
      -@dataclass()
      -class PosInfPOSIXTime(PlutusData):
      -    """
      -    Infinite POSIX time, used to indicate that there is no upper bound for the execution of this transaction
      -    """
      -
      -    CONSTR_ID = 2
      -
      -
      -ExtendedPOSIXTime = Union[NegInfPOSIXTime, FinitePOSIXTime, PosInfPOSIXTime]
      -
      -
      -@dataclass()
      -class UpperBoundPOSIXTime(PlutusData):
      -    """
      -    Upper bound for the execution of this transaction
      -    """
      -
      -    CONSTR_ID = 0
      -    limit: ExtendedPOSIXTime
      -    closed: BoolData
      -
      -
      -@dataclass()
      -class LowerBoundPOSIXTime(PlutusData):
      -    """
      -    Lower bound for the execution of this transaction
      -    """
      -
      -    CONSTR_ID = 0
      -    limit: ExtendedPOSIXTime
      -    closed: BoolData
      -
      -
      -@dataclass()
      -class POSIXTimeRange(PlutusData):
      -    """
      -    Time range in which this transaction can be executed
      -    """
      -
      -    lower_bound: LowerBoundPOSIXTime
      -    upper_bound: UpperBoundPOSIXTime
      -
      -
      -@dataclass()
      -class Minting(PlutusData):
      -    """
      -    Script purpose indicating that the given policy id is being minted or burned
      -    """
      -
      -    CONSTR_ID = 0
      -    policy_id: PolicyId
      -
      -
      -@dataclass()
      -class Spending(PlutusData):
      -    """
      -    Script purpose indicating that the given transaction output is being spent, which is
      -    owned by the invoked contract
      -    """
      -
      -    CONSTR_ID = 1
      -    tx_out_ref: TxOutRef
      -
      -
      -@dataclass()
      -class Rewarding(PlutusData):
      -    CONSTR_ID = 2
      -    staking_credential: StakingCredential
      -
      -
      -@dataclass()
      -class Certifying(PlutusData):
      -    CONSTR_ID = 3
      -    d_cert: DCert
      -
      -
      -# The reason that this script is being invoked
      -ScriptPurpose = Union[Minting, Spending, Rewarding, Certifying]
      -
      -
      -@dataclass()
      -class TxInfo(PlutusData):
      -    """
      -    A complex agglomeration of everything that could be of interest to the executed script, regarding the transaction
      -    that invoked the script
      -    """
      -
      -    inputs: List[TxInInfo]
      -    reference_inputs: List[TxInInfo]
      -    outputs: List[TxOut]
      -    fee: Value
      -    mint: Value
      -    dcert: List[DCert]
      -    wdrl: Dict[StakingCredential, int]
      -    valid_range: POSIXTimeRange
      -    signatories: List[PubKeyHash]
      -    redeemers: Dict[ScriptPurpose, Redeemer]
      -    data: Dict[DatumHash, Datum]
      -    id: TxId
      -
      -
      -@dataclass()
      -class ScriptContext(PlutusData):
      -    """
      -    Auxiliary information about the transaction and reason for invocation of the called script.
      -    """
      -
      -    tx_info: TxInfo
      -    purpose: ScriptPurpose
      -
      -
      -@dataclass()
      +@dataclass(unsafe_hash=True)
       class Token(PlutusData):
           """
           A token, represented by policy id and token name
      @@ -601,7 +129,41 @@ 

      Module hebi.prelude

      def resolve_spent_utxo(txins: List[TxInInfo], p: Spending) -> TxOut: """Returns the UTxO whose spending should be validated""" - return [txi.resolved for txi in txins if txi.out_ref == p.tx_out_ref][0]
      + return [txi.resolved for txi in txins if txi.out_ref == p.tx_out_ref][0] + + +def resolve_datum_unsafe(txout: TxOut, tx_info: TxInfo) -> BuiltinData: + """ + Returns the datum attached to a given transaction output, independent of whether it was inlined or embedded. + Raises an exception if no datum was attached. + """ + attached_datum = txout.datum + if isinstance(attached_datum, SomeOutputDatumHash): + res = tx_info.data[attached_datum.datum_hash] + elif isinstance(attached_datum, SomeOutputDatum): + res = attached_datum.datum + else: + # no datum attached + assert False, "No datum was attached to the given transaction output" + return res + + +def resolve_datum( + txout: TxOut, tx_info: TxInfo +) -> Union[SomeOutputDatum, NoOutputDatum]: + """ + Returns SomeOutputDatum with the datum attached to a given transaction output, + independent of whether it was inlined or embedded, if there was an attached datum. + Otherwise it returns NoOutputDatum. + """ + attached_datum = txout.datum + if isinstance(attached_datum, SomeOutputDatumHash): + res: Union[SomeOutputDatum, NoOutputDatum] = SomeOutputDatum( + tx_info.data[attached_datum.datum_hash] + ) + else: + res: Union[SomeOutputDatum, NoOutputDatum] = attached_datum + return res
  • @@ -612,7 +174,7 @@

    Module hebi.prelude

    Functions

    -def all_tokens_locked_at_address(txouts: List[TxOut], address: Address, token: Token) ‑> int +def all_tokens_locked_at_address(txouts: List[TxOut], address: Address, token: Token) ‑> int

    Returns how many tokens of specified type are locked at the given address

    @@ -634,7 +196,7 @@

    Functions

    -def all_tokens_locked_at_address_with_datum(txouts: List[TxOut], address: Address, token: Token, output_datum: Union[NoOutputDatumSomeOutputDatumHashSomeOutputDatum]) ‑> int +def all_tokens_locked_at_address_with_datum(txouts: List[TxOut], address: Address, token: Token, output_datum: Union[NoOutputDatumSomeOutputDatumHashSomeOutputDatum]) ‑> int

    Returns how many tokens of specified type are locked at then given address with the specified datum

    @@ -656,7 +218,7 @@

    Functions

    -def all_tokens_unlocked_from_address(txins: List[TxInInfo], address: Address, token: Token) ‑> int +def all_tokens_unlocked_from_address(txins: List[TxInInfo], address: Address, token: Token) ‑> int

    Returns how many tokens of specified type are unlocked from given address

    @@ -677,8 +239,63 @@

    Functions

    )
    +
    +def resolve_datum(txout: TxOut, tx_info: TxInfo) ‑> Union[SomeOutputDatumNoOutputDatum] +
    +
    +

    Returns SomeOutputDatum with the datum attached to a given transaction output, +independent of whether it was inlined or embedded, if there was an attached datum. +Otherwise it returns NoOutputDatum.

    +
    + +Expand source code + +
    def resolve_datum(
    +    txout: TxOut, tx_info: TxInfo
    +) -> Union[SomeOutputDatum, NoOutputDatum]:
    +    """
    +    Returns SomeOutputDatum with the datum attached to a given transaction output,
    +    independent of whether it was inlined or embedded, if there was an attached datum.
    +    Otherwise it returns NoOutputDatum.
    +    """
    +    attached_datum = txout.datum
    +    if isinstance(attached_datum, SomeOutputDatumHash):
    +        res: Union[SomeOutputDatum, NoOutputDatum] = SomeOutputDatum(
    +            tx_info.data[attached_datum.datum_hash]
    +        )
    +    else:
    +        res: Union[SomeOutputDatum, NoOutputDatum] = attached_datum
    +    return res
    +
    +
    +
    +def resolve_datum_unsafe(txout: TxOut, tx_info: TxInfo) ‑> Union[pycardano.plutus.PlutusData, dict, pycardano.serialization.IndefiniteList, int, bytes, pycardano.serialization.RawCBOR, pycardano.plutus.RawPlutusData] +
    +
    +

    Returns the datum attached to a given transaction output, independent of whether it was inlined or embedded. +Raises an exception if no datum was attached.

    +
    + +Expand source code + +
    def resolve_datum_unsafe(txout: TxOut, tx_info: TxInfo) -> BuiltinData:
    +    """
    +    Returns the datum attached to a given transaction output, independent of whether it was inlined or embedded.
    +    Raises an exception if no datum was attached.
    +    """
    +    attached_datum = txout.datum
    +    if isinstance(attached_datum, SomeOutputDatumHash):
    +        res = tx_info.data[attached_datum.datum_hash]
    +    elif isinstance(attached_datum, SomeOutputDatum):
    +        res = attached_datum.datum
    +    else:
    +        # no datum attached
    +        assert False, "No datum was attached to the given transaction output"
    +    return res
    +
    +
    -def resolve_spent_utxo(txins: List[TxInInfo], p: Spending) ‑> TxOut +def resolve_spent_utxo(txins: List[TxInInfo], p: Spending) ‑> TxOut

    Returns the UTxO whose spending should be validated

    @@ -696,23 +313,23 @@

    Functions

    Classes

    -
    -class Address -(payment_credential: Union[PubKeyCredentialScriptCredential], staking_credential: Union[NoStakingCredentialSomeStakingCredential]) +
    +class Token +(policy_id: bytes, token_name: bytes)
    -

    A Shelley address, consisting of a payment and staking credential

    +

    A token, represented by policy id and token name

    Expand source code -
    class Address(PlutusData):
    +
    class Token(PlutusData):
         """
    -    A Shelley address, consisting of a payment and staking credential
    +    A token, represented by policy id and token name
         """
     
    -    payment_credential: Credential
    -    staking_credential: Union[NoStakingCredential, SomeStakingCredential]
    + policy_id: PolicyId + token_name: TokenName

    Ancestors

      @@ -722,1490 +339,11 @@

      Ancestors

    Class variables

    -
    var payment_credential : Union[PubKeyCredentialScriptCredential]
    +
    var policy_id : bytes
    -
    var staking_credential : Union[NoStakingCredentialSomeStakingCredential]
    -
    -
    -
    -
    -
    -
    -class Certifying -(d_cert: Union[DCertDelegRegKeyDCertDelegDeRegKeyDCertDelegDelegateDCertPoolRegisterDCertPoolRetireDCertGenesisDCertMir]) -
    -
    -

    Certifying(d_cert: Union[hebi.prelude.DCertDelegRegKey, hebi.prelude.DCertDelegDeRegKey, hebi.prelude.DCertDelegDelegate, hebi.prelude.DCertPoolRegister, hebi.prelude.DCertPoolRetire, hebi.prelude.DCertGenesis, hebi.prelude.DCertMir])

    -
    - -Expand source code - -
    class Certifying(PlutusData):
    -    CONSTR_ID = 3
    -    d_cert: DCert
    -
    -

    Ancestors

    -
      -
    • pycardano.plutus.PlutusData
    • -
    • pycardano.serialization.ArrayCBORSerializable
    • -
    • pycardano.serialization.CBORSerializable
    • -
    -

    Class variables

    -
    -
    var CONSTR_ID : ClassVar[int]
    -
    -
    -
    -
    var d_cert : Union[DCertDelegRegKeyDCertDelegDeRegKeyDCertDelegDelegateDCertPoolRegisterDCertPoolRetireDCertGenesisDCertMir]
    -
    -
    -
    -
    -
    -
    -class DCertDelegDeRegKey -(value: Union[StakingHashStakingPtr]) -
    -
    -

    DCertDelegDeRegKey(value: Union[hebi.prelude.StakingHash, hebi.prelude.StakingPtr])

    -
    - -Expand source code - -
    class DCertDelegDeRegKey(PlutusData):
    -    CONSTR_ID = 1
    -    value: StakingCredential
    -
    -

    Ancestors

    -
      -
    • pycardano.plutus.PlutusData
    • -
    • pycardano.serialization.ArrayCBORSerializable
    • -
    • pycardano.serialization.CBORSerializable
    • -
    -

    Class variables

    -
    -
    var CONSTR_ID : ClassVar[int]
    -
    -
    -
    -
    var value : Union[StakingHashStakingPtr]
    -
    -
    -
    -
    -
    -
    -class DCertDelegDelegate -(delegator: Union[StakingHashStakingPtr], delegatee: bytes) -
    -
    -

    DCertDelegDelegate(delegator: Union[hebi.prelude.StakingHash, hebi.prelude.StakingPtr], delegatee: bytes)

    -
    - -Expand source code - -
    class DCertDelegDelegate(PlutusData):
    -    CONSTR_ID = 2
    -    delegator: StakingCredential
    -    delegatee: PubKeyHash
    -
    -

    Ancestors

    -
      -
    • pycardano.plutus.PlutusData
    • -
    • pycardano.serialization.ArrayCBORSerializable
    • -
    • pycardano.serialization.CBORSerializable
    • -
    -

    Class variables

    -
    -
    var CONSTR_ID : ClassVar[int]
    -
    -
    -
    -
    var delegatee : bytes
    -
    -
    -
    -
    var delegator : Union[StakingHashStakingPtr]
    -
    -
    -
    -
    -
    -
    -class DCertDelegRegKey -(value: Union[StakingHashStakingPtr]) -
    -
    -

    DCertDelegRegKey(value: Union[hebi.prelude.StakingHash, hebi.prelude.StakingPtr])

    -
    - -Expand source code - -
    class DCertDelegRegKey(PlutusData):
    -    CONSTR_ID = 0
    -    value: StakingCredential
    -
    -

    Ancestors

    -
      -
    • pycardano.plutus.PlutusData
    • -
    • pycardano.serialization.ArrayCBORSerializable
    • -
    • pycardano.serialization.CBORSerializable
    • -
    -

    Class variables

    -
    -
    var CONSTR_ID : ClassVar[int]
    -
    -
    -
    -
    var value : Union[StakingHashStakingPtr]
    -
    -
    -
    -
    -
    -
    -class DCertGenesis -
    -
    -

    DCertGenesis()

    -
    - -Expand source code - -
    class DCertGenesis(PlutusData):
    -    CONSTR_ID = 5
    -
    -

    Ancestors

    -
      -
    • pycardano.plutus.PlutusData
    • -
    • pycardano.serialization.ArrayCBORSerializable
    • -
    • pycardano.serialization.CBORSerializable
    • -
    -

    Class variables

    -
    -
    var CONSTR_ID : ClassVar[int]
    -
    -
    -
    -
    -
    -
    -class DCertMir -
    -
    -

    DCertMir()

    -
    - -Expand source code - -
    class DCertMir(PlutusData):
    -    CONSTR_ID = 6
    -
    -

    Ancestors

    -
      -
    • pycardano.plutus.PlutusData
    • -
    • pycardano.serialization.ArrayCBORSerializable
    • -
    • pycardano.serialization.CBORSerializable
    • -
    -

    Class variables

    -
    -
    var CONSTR_ID : ClassVar[int]
    -
    -
    -
    -
    -
    -
    -class DCertPoolRegister -(pool_id: bytes, pool_vfr: bytes) -
    -
    -

    DCertPoolRegister(pool_id: bytes, pool_vfr: bytes)

    -
    - -Expand source code - -
    class DCertPoolRegister(PlutusData):
    -    CONSTR_ID = 3
    -    pool_id: PubKeyHash
    -    pool_vfr: PubKeyHash
    -
    -

    Ancestors

    -
      -
    • pycardano.plutus.PlutusData
    • -
    • pycardano.serialization.ArrayCBORSerializable
    • -
    • pycardano.serialization.CBORSerializable
    • -
    -

    Class variables

    -
    -
    var CONSTR_ID : ClassVar[int]
    -
    -
    -
    -
    var pool_id : bytes
    -
    -
    -
    -
    var pool_vfr : bytes
    -
    -
    -
    -
    -
    -
    -class DCertPoolRetire -(retirement_certificate: bytes, epoch: int) -
    -
    -

    DCertPoolRetire(retirement_certificate: bytes, epoch: int)

    -
    - -Expand source code - -
    class DCertPoolRetire(PlutusData):
    -    CONSTR_ID = 4
    -    retirement_certificate: PubKeyHash
    -    epoch: int
    -
    -

    Ancestors

    -
      -
    • pycardano.plutus.PlutusData
    • -
    • pycardano.serialization.ArrayCBORSerializable
    • -
    • pycardano.serialization.CBORSerializable
    • -
    -

    Class variables

    -
    -
    var CONSTR_ID : ClassVar[int]
    -
    -
    -
    -
    var epoch : int
    -
    -
    -
    -
    var retirement_certificate : bytes
    -
    -
    -
    -
    -
    -
    -class FalseData -
    -
    -

    A Datum that represents False in Haskell implementations. -It is thus used as an encoding for False in the ScriptContext.

    -

    Example value: FalseData()

    -
    - -Expand source code - -
    class FalseData(PlutusData):
    -    """
    -    A Datum that represents False in Haskell implementations.
    -    It is thus used as an encoding for False in the ScriptContext.
    -
    -    Example value: FalseData()
    -    """
    -
    -    CONSTR_ID = 1
    -
    -

    Ancestors

    -
      -
    • pycardano.plutus.PlutusData
    • -
    • pycardano.serialization.ArrayCBORSerializable
    • -
    • pycardano.serialization.CBORSerializable
    • -
    -

    Class variables

    -
    -
    var CONSTR_ID : ClassVar[int]
    -
    -
    -
    -
    -
    -
    -class FinitePOSIXTime -(time: int) -
    -
    -

    Finite POSIX time, used to indicate that there is a lower or upper bound for the execution of this transaction

    -
    - -Expand source code - -
    class FinitePOSIXTime(PlutusData):
    -    """
    -    Finite POSIX time, used to indicate that there is a lower or upper bound for the execution of this transaction
    -    """
    -
    -    CONSTR_ID = 1
    -    time: POSIXTime
    -
    -

    Ancestors

    -
      -
    • pycardano.plutus.PlutusData
    • -
    • pycardano.serialization.ArrayCBORSerializable
    • -
    • pycardano.serialization.CBORSerializable
    • -
    -

    Class variables

    -
    -
    var CONSTR_ID : ClassVar[int]
    -
    -
    -
    -
    var time : int
    -
    -
    -
    -
    -
    -
    -class LowerBoundPOSIXTime -(limit: Union[NegInfPOSIXTimeFinitePOSIXTimePosInfPOSIXTime], closed: Union[TrueDataFalseData]) -
    -
    -

    Lower bound for the execution of this transaction

    -
    - -Expand source code - -
    class LowerBoundPOSIXTime(PlutusData):
    -    """
    -    Lower bound for the execution of this transaction
    -    """
    -
    -    CONSTR_ID = 0
    -    limit: ExtendedPOSIXTime
    -    closed: BoolData
    -
    -

    Ancestors

    -
      -
    • pycardano.plutus.PlutusData
    • -
    • pycardano.serialization.ArrayCBORSerializable
    • -
    • pycardano.serialization.CBORSerializable
    • -
    -

    Class variables

    -
    -
    var CONSTR_ID : ClassVar[int]
    -
    -
    -
    -
    var closed : Union[TrueDataFalseData]
    -
    -
    -
    -
    var limit : Union[NegInfPOSIXTimeFinitePOSIXTimePosInfPOSIXTime]
    -
    -
    -
    -
    -
    -
    -class Minting -(policy_id: bytes) -
    -
    -

    Script purpose indicating that the given policy id is being minted or burned

    -
    - -Expand source code - -
    class Minting(PlutusData):
    -    """
    -    Script purpose indicating that the given policy id is being minted or burned
    -    """
    -
    -    CONSTR_ID = 0
    -    policy_id: PolicyId
    -
    -

    Ancestors

    -
      -
    • pycardano.plutus.PlutusData
    • -
    • pycardano.serialization.ArrayCBORSerializable
    • -
    • pycardano.serialization.CBORSerializable
    • -
    -

    Class variables

    -
    -
    var CONSTR_ID : ClassVar[int]
    -
    -
    -
    -
    var policy_id : bytes
    -
    -
    -
    -
    -
    -
    -class NegInfPOSIXTime -
    -
    -

    Negative infinite POSIX time, used to indicate that there is no lower bound for the execution of this transaction

    -
    - -Expand source code - -
    class NegInfPOSIXTime(PlutusData):
    -    """
    -    Negative infinite POSIX time, used to indicate that there is no lower bound for the execution of this transaction
    -    """
    -
    -    CONSTR_ID = 0
    -
    -

    Ancestors

    -
      -
    • pycardano.plutus.PlutusData
    • -
    • pycardano.serialization.ArrayCBORSerializable
    • -
    • pycardano.serialization.CBORSerializable
    • -
    -

    Class variables

    -
    -
    var CONSTR_ID : ClassVar[int]
    -
    -
    -
    -
    -
    -
    -class NoOutputDatum -
    -
    -

    Indicates that there is no datum associated with an output

    -
    - -Expand source code - -
    class NoOutputDatum(PlutusData):
    -    """
    -    Indicates that there is no datum associated with an output
    -    """
    -
    -    CONSTR_ID = 0
    -
    -

    Ancestors

    -
      -
    • pycardano.plutus.PlutusData
    • -
    • pycardano.serialization.ArrayCBORSerializable
    • -
    • pycardano.serialization.CBORSerializable
    • -
    -

    Class variables

    -
    -
    var CONSTR_ID : ClassVar[int]
    -
    -
    -
    -
    -
    -
    -class NoScriptHash -
    -
    -

    Indicates that there is no script associated with an output

    -
    - -Expand source code - -
    class NoScriptHash(PlutusData):
    -    """
    -    Indicates that there is no script associated with an output
    -    """
    -
    -    CONSTR_ID = 1
    -
    -

    Ancestors

    -
      -
    • pycardano.plutus.PlutusData
    • -
    • pycardano.serialization.ArrayCBORSerializable
    • -
    • pycardano.serialization.CBORSerializable
    • -
    -

    Class variables

    -
    -
    var CONSTR_ID : ClassVar[int]
    -
    -
    -
    -
    -
    -
    -class NoStakingCredential -
    -
    -

    Indicates that this address has no staking credentials. -Its funds can not be delegated.

    -
    - -Expand source code - -
    class NoStakingCredential(PlutusData):
    -    """
    -    Indicates that this address has no staking credentials.
    -    Its funds can not be delegated.
    -    """
    -
    -    CONSTR_ID = 1
    -
    -

    Ancestors

    -
      -
    • pycardano.plutus.PlutusData
    • -
    • pycardano.serialization.ArrayCBORSerializable
    • -
    • pycardano.serialization.CBORSerializable
    • -
    -

    Class variables

    -
    -
    var CONSTR_ID : ClassVar[int]
    -
    -
    -
    -
    -
    -
    -class Nothing -
    -
    -

    Nothing, can be used to signify non-importance of a parameter to a function

    -

    Example value: Nothing()

    -
    - -Expand source code - -
    class Nothing(PlutusData):
    -    """
    -    Nothing, can be used to signify non-importance of a parameter to a function
    -
    -    Example value: Nothing()
    -    """
    -
    -    # The maximimum constructor ID for simple cbor types, chosen to minimize probability of collision while keeping the corresponding cbor small
    -    CONSTR_ID = 6
    -
    -

    Ancestors

    -
      -
    • pycardano.plutus.PlutusData
    • -
    • pycardano.serialization.ArrayCBORSerializable
    • -
    • pycardano.serialization.CBORSerializable
    • -
    -

    Class variables

    -
    -
    var CONSTR_ID : ClassVar[int]
    -
    -
    -
    -
    -
    -
    -class NoRedeemer -
    -
    -

    Nothing, can be used to signify non-importance of a parameter to a function

    -

    Example value: Nothing()

    -
    - -Expand source code - -
    class Nothing(PlutusData):
    -    """
    -    Nothing, can be used to signify non-importance of a parameter to a function
    -
    -    Example value: Nothing()
    -    """
    -
    -    # The maximimum constructor ID for simple cbor types, chosen to minimize probability of collision while keeping the corresponding cbor small
    -    CONSTR_ID = 6
    -
    -

    Ancestors

    -
      -
    • pycardano.plutus.PlutusData
    • -
    • pycardano.serialization.ArrayCBORSerializable
    • -
    • pycardano.serialization.CBORSerializable
    • -
    -

    Class variables

    -
    -
    var CONSTR_ID : ClassVar[int]
    -
    -
    -
    -
    -
    -
    -class POSIXTimeRange -(lower_bound: LowerBoundPOSIXTime, upper_bound: UpperBoundPOSIXTime) -
    -
    -

    Time range in which this transaction can be executed

    -
    - -Expand source code - -
    class POSIXTimeRange(PlutusData):
    -    """
    -    Time range in which this transaction can be executed
    -    """
    -
    -    lower_bound: LowerBoundPOSIXTime
    -    upper_bound: UpperBoundPOSIXTime
    -
    -

    Ancestors

    -
      -
    • pycardano.plutus.PlutusData
    • -
    • pycardano.serialization.ArrayCBORSerializable
    • -
    • pycardano.serialization.CBORSerializable
    • -
    -

    Class variables

    -
    -
    var lower_boundLowerBoundPOSIXTime
    -
    -
    -
    -
    var upper_boundUpperBoundPOSIXTime
    -
    -
    -
    -
    -
    -
    -class PosInfPOSIXTime -
    -
    -

    Infinite POSIX time, used to indicate that there is no upper bound for the execution of this transaction

    -
    - -Expand source code - -
    class PosInfPOSIXTime(PlutusData):
    -    """
    -    Infinite POSIX time, used to indicate that there is no upper bound for the execution of this transaction
    -    """
    -
    -    CONSTR_ID = 2
    -
    -

    Ancestors

    -
      -
    • pycardano.plutus.PlutusData
    • -
    • pycardano.serialization.ArrayCBORSerializable
    • -
    • pycardano.serialization.CBORSerializable
    • -
    -

    Class variables

    -
    -
    var CONSTR_ID : ClassVar[int]
    -
    -
    -
    -
    -
    -
    -class PubKeyCredential -(credential_hash: bytes) -
    -
    -

    Part of an address that is authenticated by a public key hash

    -

    Example value: PubKeyCredential(bytes.fromhex("c06ddaad12fc4ded18e56feac72957c1aa75fce6096b40e63ec88274"))

    -
    - -Expand source code - -
    class PubKeyCredential(PlutusData):
    -    """
    -    Part of an address that is authenticated by a public key hash
    -
    -    Example value: PubKeyCredential(bytes.fromhex("c06ddaad12fc4ded18e56feac72957c1aa75fce6096b40e63ec88274"))
    -    """
    -
    -    CONSTR_ID = 0
    -    credential_hash: PubKeyHash
    -
    -

    Ancestors

    -
      -
    • pycardano.plutus.PlutusData
    • -
    • pycardano.serialization.ArrayCBORSerializable
    • -
    • pycardano.serialization.CBORSerializable
    • -
    -

    Class variables

    -
    -
    var CONSTR_ID : ClassVar[int]
    -
    -
    -
    -
    var credential_hash : bytes
    -
    -
    -
    -
    -
    -
    -class Rewarding -(staking_credential: Union[StakingHashStakingPtr]) -
    -
    -

    Rewarding(staking_credential: Union[hebi.prelude.StakingHash, hebi.prelude.StakingPtr])

    -
    - -Expand source code - -
    class Rewarding(PlutusData):
    -    CONSTR_ID = 2
    -    staking_credential: StakingCredential
    -
    -

    Ancestors

    -
      -
    • pycardano.plutus.PlutusData
    • -
    • pycardano.serialization.ArrayCBORSerializable
    • -
    • pycardano.serialization.CBORSerializable
    • -
    -

    Class variables

    -
    -
    var CONSTR_ID : ClassVar[int]
    -
    -
    -
    -
    var staking_credential : Union[StakingHashStakingPtr]
    -
    -
    -
    -
    -
    -
    -class ScriptContext -(tx_info: TxInfo, purpose: Union[MintingSpendingRewardingCertifying]) -
    -
    -

    Auxiliary information about the transaction and reason for invocation of the called script.

    -
    - -Expand source code - -
    class ScriptContext(PlutusData):
    -    """
    -    Auxiliary information about the transaction and reason for invocation of the called script.
    -    """
    -
    -    tx_info: TxInfo
    -    purpose: ScriptPurpose
    -
    -

    Ancestors

    -
      -
    • pycardano.plutus.PlutusData
    • -
    • pycardano.serialization.ArrayCBORSerializable
    • -
    • pycardano.serialization.CBORSerializable
    • -
    -

    Class variables

    -
    -
    var purpose : Union[MintingSpendingRewardingCertifying]
    -
    -
    -
    -
    var tx_infoTxInfo
    -
    -
    -
    -
    -
    -
    -class ScriptCredential -(credential_hash: bytes) -
    -
    -

    Part of an address that is authenticated by a smart cotnract

    -

    Example value: ScriptCredential(bytes.fromhex("c06ddaad12fc4ded18e56feac72957c1aa75fce6096b40e63ec88274"))

    -
    - -Expand source code - -
    class ScriptCredential(PlutusData):
    -    """
    -    Part of an address that is authenticated by a smart cotnract
    -
    -    Example value: ScriptCredential(bytes.fromhex("c06ddaad12fc4ded18e56feac72957c1aa75fce6096b40e63ec88274"))
    -    """
    -
    -    CONSTR_ID = 1
    -    credential_hash: ValidatorHash
    -
    -

    Ancestors

    -
      -
    • pycardano.plutus.PlutusData
    • -
    • pycardano.serialization.ArrayCBORSerializable
    • -
    • pycardano.serialization.CBORSerializable
    • -
    -

    Class variables

    -
    -
    var CONSTR_ID : ClassVar[int]
    -
    -
    -
    -
    var credential_hash : bytes
    -
    -
    -
    -
    -
    -
    -class SomeDatumHash -(datum_hash: bytes) -
    -
    -

    Indicates that there is a datum associated with this output, which has the given hash.

    -
    - -Expand source code - -
    class SomeDatumHash(PlutusData):
    -    """
    -    Indicates that there is a datum associated with this output, which has the given hash.
    -    """
    -
    -    CONSTR_ID = 1
    -    datum_hash: DatumHash
    -
    -

    Ancestors

    -
      -
    • pycardano.plutus.PlutusData
    • -
    • pycardano.serialization.ArrayCBORSerializable
    • -
    • pycardano.serialization.CBORSerializable
    • -
    -

    Class variables

    -
    -
    var CONSTR_ID : ClassVar[int]
    -
    -
    -
    -
    var datum_hash : bytes
    -
    -
    -
    -
    -
    -
    -class SomeOutputDatum -(datum: Union[pycardano.plutus.PlutusData, dict, pycardano.serialization.IndefiniteList, int, bytes, pycardano.serialization.RawCBOR, pycardano.plutus.RawPlutusData]) -
    -
    -

    Indicates that there is an datum associated with an output, which is inlined and equal to the attached datum

    -
    - -Expand source code - -
    class SomeOutputDatum(PlutusData):
    -    """
    -    Indicates that there is an datum associated with an output, which is inlined and equal to the attached datum
    -    """
    -
    -    CONSTR_ID = 2
    -    datum: Datum
    -
    -

    Ancestors

    -
      -
    • pycardano.plutus.PlutusData
    • -
    • pycardano.serialization.ArrayCBORSerializable
    • -
    • pycardano.serialization.CBORSerializable
    • -
    -

    Class variables

    -
    -
    var CONSTR_ID : ClassVar[int]
    -
    -
    -
    -
    var datum : Union[pycardano.plutus.PlutusData, dict, pycardano.serialization.IndefiniteList, int, bytes, pycardano.serialization.RawCBOR, pycardano.plutus.RawPlutusData]
    -
    -
    -
    -
    -
    -
    -class SomeOutputDatumHash -(datum_hash: bytes) -
    -
    -

    Indicates that there is an datum associated with an output, which has the attached hash

    -
    - -Expand source code - -
    class SomeOutputDatumHash(PlutusData):
    -    """
    -    Indicates that there is an datum associated with an output, which has the attached hash
    -    """
    -
    -    CONSTR_ID = 1
    -    datum_hash: DatumHash
    -
    -

    Ancestors

    -
      -
    • pycardano.plutus.PlutusData
    • -
    • pycardano.serialization.ArrayCBORSerializable
    • -
    • pycardano.serialization.CBORSerializable
    • -
    -

    Class variables

    -
    -
    var CONSTR_ID : ClassVar[int]
    -
    -
    -
    -
    var datum_hash : bytes
    -
    -
    -
    -
    -
    -
    -class SomeScriptHash -(script_hash: bytes) -
    -
    -

    Indicates that there is a script associated with this output, which has the given hash.

    -
    - -Expand source code - -
    class SomeScriptHash(PlutusData):
    -    """
    -    Indicates that there is a script associated with this output, which has the given hash.
    -    """
    -
    -    CONSTR_ID = 0
    -    script_hash: DatumHash
    -
    -

    Ancestors

    -
      -
    • pycardano.plutus.PlutusData
    • -
    • pycardano.serialization.ArrayCBORSerializable
    • -
    • pycardano.serialization.CBORSerializable
    • -
    -

    Class variables

    -
    -
    var CONSTR_ID : ClassVar[int]
    -
    -
    -
    -
    var script_hash : bytes
    -
    -
    -
    -
    -
    -
    -class SomeStakingCredential -(staking_credential: Union[StakingHashStakingPtr]) -
    -
    -

    Indicates that this address has staking credentials. -Its funds can be delegated by the credentialed user.

    -
    - -Expand source code - -
    class SomeStakingCredential(PlutusData):
    -    """
    -    Indicates that this address has staking credentials.
    -    Its funds can be delegated by the credentialed user.
    -    """
    -
    -    CONSTR_ID = 0
    -    staking_credential: StakingCredential
    -
    -

    Ancestors

    -
      -
    • pycardano.plutus.PlutusData
    • -
    • pycardano.serialization.ArrayCBORSerializable
    • -
    • pycardano.serialization.CBORSerializable
    • -
    -

    Class variables

    -
    -
    var CONSTR_ID : ClassVar[int]
    -
    -
    -
    -
    var staking_credential : Union[StakingHashStakingPtr]
    -
    -
    -
    -
    -
    -
    -class Spending -(tx_out_ref: TxOutRef) -
    -
    -

    Script purpose indicating that the given transaction output is being spent, which is -owned by the invoked contract

    -
    - -Expand source code - -
    class Spending(PlutusData):
    -    """
    -    Script purpose indicating that the given transaction output is being spent, which is
    -    owned by the invoked contract
    -    """
    -
    -    CONSTR_ID = 1
    -    tx_out_ref: TxOutRef
    -
    -

    Ancestors

    -
      -
    • pycardano.plutus.PlutusData
    • -
    • pycardano.serialization.ArrayCBORSerializable
    • -
    • pycardano.serialization.CBORSerializable
    • -
    -

    Class variables

    -
    -
    var CONSTR_ID : ClassVar[int]
    -
    -
    -
    -
    var tx_out_refTxOutRef
    -
    -
    -
    -
    -
    -
    -class StakingHash -(value: Union[PubKeyCredentialScriptCredential]) -
    -
    -

    Indicates that the stake of this address is controlled by the associated credential

    -
    - -Expand source code - -
    class StakingHash(PlutusData):
    -    """
    -    Indicates that the stake of this address is controlled by the associated credential
    -    """
    -
    -    CONSTR_ID = 0
    -    value: Credential
    -
    -

    Ancestors

    -
      -
    • pycardano.plutus.PlutusData
    • -
    • pycardano.serialization.ArrayCBORSerializable
    • -
    • pycardano.serialization.CBORSerializable
    • -
    -

    Class variables

    -
    -
    var CONSTR_ID : ClassVar[int]
    -
    -
    -
    -
    var value : Union[PubKeyCredentialScriptCredential]
    -
    -
    -
    -
    -
    -
    -class StakingPtr -(slot_no: int, tx_index: int, cert_index: int) -
    -
    -

    Indicates that the stake of this address is controlled by the associated pointer.

    -

    In an address, a chain pointer refers to a point of the chain containing a stake key registration certificate. -A point is identified by the 3 coordinates in this object.

    -
    - -Expand source code - -
    class StakingPtr(PlutusData):
    -    """
    -    Indicates that the stake of this address is controlled by the associated pointer.
    -
    -    In an address, a chain pointer refers to a point of the chain containing a stake key registration certificate.
    -    A point is identified by the 3 coordinates in this object.
    -    """
    -
    -    CONSTR_ID = 1
    -    # an absolute slot number
    -    slot_no: int
    -    # a transaction index (within that slot)
    -    tx_index: int
    -    # a (delegation) certificate index (within that transaction)
    -    cert_index: int
    -
    -

    Ancestors

    -
      -
    • pycardano.plutus.PlutusData
    • -
    • pycardano.serialization.ArrayCBORSerializable
    • -
    • pycardano.serialization.CBORSerializable
    • -
    -

    Class variables

    -
    -
    var CONSTR_ID : ClassVar[int]
    -
    -
    -
    -
    var cert_index : int
    -
    -
    -
    -
    var slot_no : int
    -
    -
    -
    -
    var tx_index : int
    -
    -
    -
    -
    -
    -
    -class Token -(policy_id: bytes, token_name: bytes) -
    -
    -

    A token, represented by policy id and token name

    -
    - -Expand source code - -
    class Token(PlutusData):
    -    """
    -    A token, represented by policy id and token name
    -    """
    -
    -    policy_id: PolicyId
    -    token_name: TokenName
    -
    -

    Ancestors

    -
      -
    • pycardano.plutus.PlutusData
    • -
    • pycardano.serialization.ArrayCBORSerializable
    • -
    • pycardano.serialization.CBORSerializable
    • -
    -

    Class variables

    -
    -
    var policy_id : bytes
    -
    -
    -
    -
    var token_name : bytes
    -
    -
    -
    -
    -
    -
    -class TrueData -
    -
    -

    A Datum that represents True in Haskell implementations. -It is thus used as an encoding for True in the ScriptContext.

    -

    Example value: TrueData()

    -
    - -Expand source code - -
    class TrueData(PlutusData):
    -    """
    -    A Datum that represents True in Haskell implementations.
    -    It is thus used as an encoding for True in the ScriptContext.
    -
    -    Example value: TrueData()
    -    """
    -
    -    CONSTR_ID = 0
    -
    -

    Ancestors

    -
      -
    • pycardano.plutus.PlutusData
    • -
    • pycardano.serialization.ArrayCBORSerializable
    • -
    • pycardano.serialization.CBORSerializable
    • -
    -

    Class variables

    -
    -
    var CONSTR_ID : ClassVar[int]
    -
    -
    -
    -
    -
    -
    -class TxId -(tx_id: bytes) -
    -
    -

    A transaction id, a 64 bytes long hash of the transaction body (also called transaction hash).

    -

    Example value: TxId(bytes.fromhex("842a4d37b036da6ab3c04331240e67d81746beb44f23ad79703e026705361956"))

    -
    - -Expand source code - -
    class TxId(PlutusData):
    -    """
    -    A transaction id, a 64 bytes long hash of the transaction body (also called transaction hash).
    -
    -    Example value: TxId(bytes.fromhex("842a4d37b036da6ab3c04331240e67d81746beb44f23ad79703e026705361956"))
    -    """
    -
    -    tx_id: bytes
    -
    -

    Ancestors

    -
      -
    • pycardano.plutus.PlutusData
    • -
    • pycardano.serialization.ArrayCBORSerializable
    • -
    • pycardano.serialization.CBORSerializable
    • -
    -

    Class variables

    -
    -
    var tx_id : bytes
    -
    -
    -
    -
    -
    -
    -class TxInInfo -(out_ref: TxOutRef, resolved: TxOut) -
    -
    -

    The plutus representation of an transaction output, that is consumed by the transaction.

    -
    - -Expand source code - -
    class TxInInfo(PlutusData):
    -    """
    -    The plutus representation of an transaction output, that is consumed by the transaction.
    -    """
    -
    -    out_ref: TxOutRef
    -    resolved: TxOut
    -
    -

    Ancestors

    -
      -
    • pycardano.plutus.PlutusData
    • -
    • pycardano.serialization.ArrayCBORSerializable
    • -
    • pycardano.serialization.CBORSerializable
    • -
    -

    Class variables

    -
    -
    var out_refTxOutRef
    -
    -
    -
    -
    var resolvedTxOut
    -
    -
    -
    -
    -
    -
    -class TxInfo -(inputs: List[TxInInfo], reference_inputs: List[TxInInfo], outputs: List[TxOut], fee: Dict[bytes, Dict[bytes, int]], mint: Dict[bytes, Dict[bytes, int]], dcert: List[Union[DCertDelegRegKeyDCertDelegDeRegKeyDCertDelegDelegateDCertPoolRegisterDCertPoolRetireDCertGenesisDCertMir]], wdrl: Dict[Union[StakingHashStakingPtr], int], valid_range: POSIXTimeRange, signatories: List[bytes], redeemers: Dict[Union[MintingSpendingRewardingCertifying], Union[pycardano.plutus.PlutusData, dict, pycardano.serialization.IndefiniteList, int, bytes, pycardano.serialization.RawCBOR, pycardano.plutus.RawPlutusData]], data: Dict[bytes, Union[pycardano.plutus.PlutusData, dict, pycardano.serialization.IndefiniteList, int, bytes, pycardano.serialization.RawCBOR, pycardano.plutus.RawPlutusData]], id: TxId) -
    -
    -

    A complex agglomeration of everything that could be of interest to the executed script, regarding the transaction -that invoked the script

    -
    - -Expand source code - -
    class TxInfo(PlutusData):
    -    """
    -    A complex agglomeration of everything that could be of interest to the executed script, regarding the transaction
    -    that invoked the script
    -    """
    -
    -    inputs: List[TxInInfo]
    -    reference_inputs: List[TxInInfo]
    -    outputs: List[TxOut]
    -    fee: Value
    -    mint: Value
    -    dcert: List[DCert]
    -    wdrl: Dict[StakingCredential, int]
    -    valid_range: POSIXTimeRange
    -    signatories: List[PubKeyHash]
    -    redeemers: Dict[ScriptPurpose, Redeemer]
    -    data: Dict[DatumHash, Datum]
    -    id: TxId
    -
    -

    Ancestors

    -
      -
    • pycardano.plutus.PlutusData
    • -
    • pycardano.serialization.ArrayCBORSerializable
    • -
    • pycardano.serialization.CBORSerializable
    • -
    -

    Class variables

    -
    -
    var data : Dict[bytes, Union[pycardano.plutus.PlutusData, dict, pycardano.serialization.IndefiniteList, int, bytes, pycardano.serialization.RawCBOR, pycardano.plutus.RawPlutusData]]
    -
    -
    -
    -
    var dcert : List[Union[DCertDelegRegKeyDCertDelegDeRegKeyDCertDelegDelegateDCertPoolRegisterDCertPoolRetireDCertGenesisDCertMir]]
    -
    -
    -
    -
    var fee : Dict[bytes, Dict[bytes, int]]
    -
    -
    -
    -
    var idTxId
    -
    -
    -
    -
    var inputs : List[TxInInfo]
    -
    -
    -
    -
    var mint : Dict[bytes, Dict[bytes, int]]
    -
    -
    -
    -
    var outputs : List[TxOut]
    -
    -
    -
    -
    var redeemers : Dict[Union[MintingSpendingRewardingCertifying], Union[pycardano.plutus.PlutusData, dict, pycardano.serialization.IndefiniteList, int, bytes, pycardano.serialization.RawCBOR, pycardano.plutus.RawPlutusData]]
    -
    -
    -
    -
    var reference_inputs : List[TxInInfo]
    -
    -
    -
    -
    var signatories : List[bytes]
    -
    -
    -
    -
    var valid_rangePOSIXTimeRange
    -
    -
    -
    -
    var wdrl : Dict[Union[StakingHashStakingPtr], int]
    -
    -
    -
    -
    -
    -
    -class TxOut -(address: Address, value: Dict[bytes, Dict[bytes, int]], datum: Union[NoOutputDatumSomeOutputDatumHashSomeOutputDatum], reference_script: Union[NoScriptHashSomeScriptHash]) -
    -
    -

    The plutus representation of an transaction output, consisting of -- address: address owning this output -- value: tokens associated with this output -- datum: datum associated with this output -- reference_script: reference script associated with this output

    -
    - -Expand source code - -
    class TxOut(PlutusData):
    -    """
    -    The plutus representation of an transaction output, consisting of
    -    - address: address owning this output
    -    - value: tokens associated with this output
    -    - datum: datum associated with this output
    -    - reference_script: reference script associated with this output
    -    """
    -
    -    address: Address
    -    value: Value
    -    datum: OutputDatum
    -    reference_script: Union[NoScriptHash, SomeScriptHash]
    -
    -

    Ancestors

    -
      -
    • pycardano.plutus.PlutusData
    • -
    • pycardano.serialization.ArrayCBORSerializable
    • -
    • pycardano.serialization.CBORSerializable
    • -
    -

    Class variables

    -
    -
    var addressAddress
    -
    -
    -
    -
    var datum : Union[NoOutputDatumSomeOutputDatumHashSomeOutputDatum]
    -
    -
    -
    -
    var reference_script : Union[NoScriptHashSomeScriptHash]
    -
    -
    -
    -
    var value : Dict[bytes, Dict[bytes, int]]
    -
    -
    -
    -
    -
    -
    -class TxOutRef -(id: TxId, idx: int) -
    -
    -

    A reference to a transaction output (hash/id + index)

    -
    - -Expand source code - -
    class TxOutRef(PlutusData):
    -    """
    -    A reference to a transaction output (hash/id + index)
    -    """
    -
    -    id: TxId
    -    idx: int
    -
    -

    Ancestors

    -
      -
    • pycardano.plutus.PlutusData
    • -
    • pycardano.serialization.ArrayCBORSerializable
    • -
    • pycardano.serialization.CBORSerializable
    • -
    -

    Class variables

    -
    -
    var idTxId
    -
    -
    -
    -
    var idx : int
    -
    -
    -
    -
    -
    -
    -class UpperBoundPOSIXTime -(limit: Union[NegInfPOSIXTimeFinitePOSIXTimePosInfPOSIXTime], closed: Union[TrueDataFalseData]) -
    -
    -

    Upper bound for the execution of this transaction

    -
    - -Expand source code - -
    class UpperBoundPOSIXTime(PlutusData):
    -    """
    -    Upper bound for the execution of this transaction
    -    """
    -
    -    CONSTR_ID = 0
    -    limit: ExtendedPOSIXTime
    -    closed: BoolData
    -
    -

    Ancestors

    -
      -
    • pycardano.plutus.PlutusData
    • -
    • pycardano.serialization.ArrayCBORSerializable
    • -
    • pycardano.serialization.CBORSerializable
    • -
    -

    Class variables

    -
    -
    var CONSTR_ID : ClassVar[int]
    -
    -
    -
    -
    var closed : Union[TrueDataFalseData]
    -
    -
    -
    -
    var limit : Union[NegInfPOSIXTimeFinitePOSIXTimePosInfPOSIXTime]
    +
    var token_name : bytes
    @@ -2283,305 +421,20 @@

    Index

  • all_tokens_locked_at_address
  • all_tokens_locked_at_address_with_datum
  • all_tokens_unlocked_from_address
  • +
  • resolve_datum
  • +
  • resolve_datum_unsafe
  • resolve_spent_utxo
  • Classes

  • diff --git a/docs/hebi/rewrite/rewrite_import_dataclasses.html b/docs/hebi/rewrite/rewrite_import_dataclasses.html index 94c181c..a07b41c 100644 --- a/docs/hebi/rewrite/rewrite_import_dataclasses.html +++ b/docs/hebi/rewrite/rewrite_import_dataclasses.html @@ -105,16 +105,19 @@

    Module hebi.rewrite.rewrite_import_dataclasses

    @@ -189,16 +192,19 @@

    Classes

    ), "dataclasses must be imported in order to use datum classes" assert ( len(node.decorator_list) == 1 - ), "Class definitions must have no decorators but @dataclass()" - assert isinstance( - node.decorator_list[0], Call - ), "Class definitions must have no decorators but @dataclass()" + ), "Class definitions must have the decorator @dataclass" + if isinstance(node.decorator_list[0], Call): + node_decorator = node.decorator_list[0].func + elif isinstance(node.decorator_list[0], Name): + node_decorator = node.decorator_list[0] + else: + raise AssertionError("Class definitions must have the decorator @dataclass") assert isinstance( - node.decorator_list[0].func, Name - ), "Class definitions must have no decorators but @dataclass()" + node_decorator, Name + ), "Class definitions must have the decorator @dataclass" assert ( - node.decorator_list[0].func.id == "dataclass" - ), "Class definitions must have no decorators but @dataclass()" + node_decorator.id == "dataclass" + ), "Class definitions must have the decorator @dataclass" return node

    Ancestors

    @@ -246,16 +252,19 @@

    Methods

    ), "dataclasses must be imported in order to use datum classes" assert ( len(node.decorator_list) == 1 - ), "Class definitions must have no decorators but @dataclass()" - assert isinstance( - node.decorator_list[0], Call - ), "Class definitions must have no decorators but @dataclass()" + ), "Class definitions must have the decorator @dataclass" + if isinstance(node.decorator_list[0], Call): + node_decorator = node.decorator_list[0].func + elif isinstance(node.decorator_list[0], Name): + node_decorator = node.decorator_list[0] + else: + raise AssertionError("Class definitions must have the decorator @dataclass") assert isinstance( - node.decorator_list[0].func, Name - ), "Class definitions must have no decorators but @dataclass()" + node_decorator, Name + ), "Class definitions must have the decorator @dataclass" assert ( - node.decorator_list[0].func.id == "dataclass" - ), "Class definitions must have no decorators but @dataclass()" + node_decorator.id == "dataclass" + ), "Class definitions must have the decorator @dataclass" return node
    diff --git a/docs/hebi/rewrite/rewrite_import_hashlib.html b/docs/hebi/rewrite/rewrite_import_hashlib.html index d73a514..d07640a 100644 --- a/docs/hebi/rewrite/rewrite_import_hashlib.html +++ b/docs/hebi/rewrite/rewrite_import_hashlib.html @@ -93,6 +93,9 @@

    Module hebi.rewrite.rewrite_import_hashlib

    return plt.Lambda(["self"], plt.Var("self")) raise NotImplementedError("HashType only has attribute 'digest'") + def __ge__(self, other): + return isinstance(other, HashType) + HashInstanceType = InstanceType(HashType()) @@ -182,7 +185,10 @@

    Classes

    def attribute(self, attr) -> plt.AST: if attr == "digest": return plt.Lambda(["self"], plt.Var("self")) - raise NotImplementedError("HashType only has attribute 'digest'") + raise NotImplementedError("HashType only has attribute 'digest'") + + def __ge__(self, other): + return isinstance(other, HashType)

    Ancestors

      diff --git a/docs/hebi/rewrite/rewrite_tuple_assign.html b/docs/hebi/rewrite/rewrite_tuple_assign.html index 33a8547..26a231f 100644 --- a/docs/hebi/rewrite/rewrite_tuple_assign.html +++ b/docs/hebi/rewrite/rewrite_tuple_assign.html @@ -68,7 +68,9 @@

      Module hebi.rewrite.rewrite_tuple_assign

      Expand source code -
      import typing
      +
      from copy import copy
      +
      +import typing
       from ast import *
       
       from ..util import CompilingNodeTransformer
      @@ -102,7 +104,35 @@ 

      Module hebi.rewrite.rewrite_tuple_assign

      ) # recursively resolve multiple layers of tuples transformed = sum([self.visit(a) for a in assignments], []) - return transformed
      + return transformed + + def visit_For(self, node: For) -> For: + # rewrite deconstruction in for loops + if not isinstance(node.target, Tuple): + return self.generic_visit(node) + new_for = copy(node) + new_for.iter = self.visit(node.iter) + uid = self.unique_id + self.unique_id += 1 + # write the tuple into a singleton variable + new_for.target = Name(f"{uid}_tup", Store()) + assignments = [] + # iteratively assign the deconstructed parts to the original variable names + for i, t in enumerate(node.target.elts): + assignments.append( + Assign( + [t], + Subscript( + value=Name(f"{uid}_tup", Load()), + slice=Constant(i), + ctx=Load(), + ), + ) + ) + new_for.body = assignments + node.body + # recursively resolve multiple layers of tuples + # further layers should be handled by the normal tuple assignment though + return self.visit(new_for)
    @@ -173,7 +203,35 @@

    Classes

    ) # recursively resolve multiple layers of tuples transformed = sum([self.visit(a) for a in assignments], []) - return transformed + return transformed + + def visit_For(self, node: For) -> For: + # rewrite deconstruction in for loops + if not isinstance(node.target, Tuple): + return self.generic_visit(node) + new_for = copy(node) + new_for.iter = self.visit(node.iter) + uid = self.unique_id + self.unique_id += 1 + # write the tuple into a singleton variable + new_for.target = Name(f"{uid}_tup", Store()) + assignments = [] + # iteratively assign the deconstructed parts to the original variable names + for i, t in enumerate(node.target.elts): + assignments.append( + Assign( + [t], + Subscript( + value=Name(f"{uid}_tup", Load()), + slice=Constant(i), + ctx=Load(), + ), + ) + ) + new_for.body = assignments + node.body + # recursively resolve multiple layers of tuples + # further layers should be handled by the normal tuple assignment though + return self.visit(new_for)

    Ancestors

    diff --git a/docs/hebi/std/fractions.html b/docs/hebi/std/fractions.html new file mode 100644 index 0000000..2bbc545 --- /dev/null +++ b/docs/hebi/std/fractions.html @@ -0,0 +1,500 @@ + + + + + + + + +hebi.std.fractions API documentation + + + + + + + + + + + +
    + + + + +
    +
    +

    Module hebi.std.fractions

    +
    +
    +

    An implementation of fractions in opshin +This does not maintain smallest possible notation invariants for the sake of efficiency +- the user has full control over when to normalize the fractions and should do so using norm_fraction

    +
    + +Expand source code + +
    """
    +An implementation of fractions in opshin
    +This does not maintain smallest possible notation invariants for the sake of efficiency
    +- the user has full control over when to normalize the fractions and should do so using norm_fraction
    +"""
    +from dataclasses import dataclass
    +from pycardano import PlutusData
    +
    +
    +@dataclass(unsafe_hash=True)
    +class Fraction(PlutusData):
    +    CONSTR_ID = 1
    +    numerator: int
    +    denominator: int
    +
    +
    +def add_fraction(a: Fraction, b: Fraction) -> Fraction:
    +    """returns a + b"""
    +    return Fraction(
    +        (a.numerator * b.denominator) + (b.numerator * a.denominator),
    +        a.denominator * b.denominator,
    +    )
    +
    +
    +def neg_fraction(a: Fraction) -> Fraction:
    +    """returns -a"""
    +    return Fraction(-a.numerator, a.denominator)
    +
    +
    +def sub_fraction(a: Fraction, b: Fraction) -> Fraction:
    +    """returns a - b"""
    +    return add_fraction(a, neg_fraction(b))
    +
    +
    +def mul_fraction(a: Fraction, b: Fraction) -> Fraction:
    +    """returns a * b"""
    +    return Fraction(a.numerator * b.numerator, a.denominator * b.denominator)
    +
    +
    +def div_fraction(a: Fraction, b: Fraction) -> Fraction:
    +    """returns a / b"""
    +    return Fraction(a.numerator * b.denominator, a.denominator * b.numerator)
    +
    +
    +def _norm_signs_fraction(a: Fraction) -> Fraction:
    +    """Restores the invariant that the denominator is > 0"""
    +    return Fraction(sign(a.denominator) * a.numerator, abs(a.denominator))
    +
    +
    +def _norm_gcd_fraction(a: Fraction) -> Fraction:
    +    """Restores the invariant that num/denom are in the smallest possible denomination"""
    +    g = gcd(a.numerator, a.denominator)
    +    return Fraction(a.numerator // g, a.denominator // g)
    +
    +
    +def norm_fraction(a: Fraction) -> Fraction:
    +    """Restores the invariant that num/denom are in the smallest possible denomination and denominator > 0"""
    +    return _norm_gcd_fraction(_norm_signs_fraction(a))
    +
    +
    +def ge_fraction(a: Fraction, b: Fraction) -> bool:
    +    """returns a >= b"""
    +    if a.denominator * b.denominator >= 0:
    +        res = a.numerator * b.denominator >= a.denominator * b.numerator
    +    else:
    +        res = a.numerator * b.denominator <= a.denominator * b.numerator
    +    return res
    +
    +
    +def le_fraction(a: Fraction, b: Fraction) -> bool:
    +    """returns a <= b"""
    +    if a.denominator * b.denominator >= 0:
    +        res = a.numerator * b.denominator <= a.denominator * b.numerator
    +    else:
    +        res = a.numerator * b.denominator >= a.denominator * b.numerator
    +    return res
    +
    +
    +def eq_fraction(a: Fraction, b: Fraction) -> bool:
    +    """returns a == b"""
    +    return a.numerator * b.denominator == a.denominator * b.numerator
    +
    +
    +def lt_fraction(a: Fraction, b: Fraction) -> bool:
    +    """returns a < b"""
    +    if a.denominator * b.denominator >= 0:
    +        res = a.numerator * b.denominator < a.denominator * b.numerator
    +    else:
    +        res = a.numerator * b.denominator > a.denominator * b.numerator
    +    return res
    +
    +
    +def gt_fraction(a: Fraction, b: Fraction) -> bool:
    +    """returns a > b"""
    +    if a.denominator * b.denominator >= 0:
    +        res = a.numerator * b.denominator > a.denominator * b.numerator
    +    else:
    +        res = a.numerator * b.denominator < a.denominator * b.numerator
    +    return res
    +
    +
    +
    +
    +
    +
    +
    +

    Functions

    +
    +
    +def add_fraction(a: Fraction, b: Fraction) ‑> Fraction +
    +
    +

    returns a + b

    +
    + +Expand source code + +
    def add_fraction(a: Fraction, b: Fraction) -> Fraction:
    +    """returns a + b"""
    +    return Fraction(
    +        (a.numerator * b.denominator) + (b.numerator * a.denominator),
    +        a.denominator * b.denominator,
    +    )
    +
    +
    +
    +def div_fraction(a: Fraction, b: Fraction) ‑> Fraction +
    +
    +

    returns a / b

    +
    + +Expand source code + +
    def div_fraction(a: Fraction, b: Fraction) -> Fraction:
    +    """returns a / b"""
    +    return Fraction(a.numerator * b.denominator, a.denominator * b.numerator)
    +
    +
    +
    +def eq_fraction(a: Fraction, b: Fraction) ‑> bool +
    +
    +

    returns a == b

    +
    + +Expand source code + +
    def eq_fraction(a: Fraction, b: Fraction) -> bool:
    +    """returns a == b"""
    +    return a.numerator * b.denominator == a.denominator * b.numerator
    +
    +
    +
    +def ge_fraction(a: Fraction, b: Fraction) ‑> bool +
    +
    +

    returns a >= b

    +
    + +Expand source code + +
    def ge_fraction(a: Fraction, b: Fraction) -> bool:
    +    """returns a >= b"""
    +    if a.denominator * b.denominator >= 0:
    +        res = a.numerator * b.denominator >= a.denominator * b.numerator
    +    else:
    +        res = a.numerator * b.denominator <= a.denominator * b.numerator
    +    return res
    +
    +
    +
    +def gt_fraction(a: Fraction, b: Fraction) ‑> bool +
    +
    +

    returns a > b

    +
    + +Expand source code + +
    def gt_fraction(a: Fraction, b: Fraction) -> bool:
    +    """returns a > b"""
    +    if a.denominator * b.denominator >= 0:
    +        res = a.numerator * b.denominator > a.denominator * b.numerator
    +    else:
    +        res = a.numerator * b.denominator < a.denominator * b.numerator
    +    return res
    +
    +
    +
    +def le_fraction(a: Fraction, b: Fraction) ‑> bool +
    +
    +

    returns a <= b

    +
    + +Expand source code + +
    def le_fraction(a: Fraction, b: Fraction) -> bool:
    +    """returns a <= b"""
    +    if a.denominator * b.denominator >= 0:
    +        res = a.numerator * b.denominator <= a.denominator * b.numerator
    +    else:
    +        res = a.numerator * b.denominator >= a.denominator * b.numerator
    +    return res
    +
    +
    +
    +def lt_fraction(a: Fraction, b: Fraction) ‑> bool +
    +
    +

    returns a < b

    +
    + +Expand source code + +
    def lt_fraction(a: Fraction, b: Fraction) -> bool:
    +    """returns a < b"""
    +    if a.denominator * b.denominator >= 0:
    +        res = a.numerator * b.denominator < a.denominator * b.numerator
    +    else:
    +        res = a.numerator * b.denominator > a.denominator * b.numerator
    +    return res
    +
    +
    +
    +def mul_fraction(a: Fraction, b: Fraction) ‑> Fraction +
    +
    +

    returns a * b

    +
    + +Expand source code + +
    def mul_fraction(a: Fraction, b: Fraction) -> Fraction:
    +    """returns a * b"""
    +    return Fraction(a.numerator * b.numerator, a.denominator * b.denominator)
    +
    +
    +
    +def neg_fraction(a: Fraction) ‑> Fraction +
    +
    +

    returns -a

    +
    + +Expand source code + +
    def neg_fraction(a: Fraction) -> Fraction:
    +    """returns -a"""
    +    return Fraction(-a.numerator, a.denominator)
    +
    +
    +
    +def norm_fraction(a: Fraction) ‑> Fraction +
    +
    +

    Restores the invariant that num/denom are in the smallest possible denomination and denominator > 0

    +
    + +Expand source code + +
    def norm_fraction(a: Fraction) -> Fraction:
    +    """Restores the invariant that num/denom are in the smallest possible denomination and denominator > 0"""
    +    return _norm_gcd_fraction(_norm_signs_fraction(a))
    +
    +
    +
    +def sub_fraction(a: Fraction, b: Fraction) ‑> Fraction +
    +
    +

    returns a - b

    +
    + +Expand source code + +
    def sub_fraction(a: Fraction, b: Fraction) -> Fraction:
    +    """returns a - b"""
    +    return add_fraction(a, neg_fraction(b))
    +
    +
    +
    +
    +
    +

    Classes

    +
    +
    +class Fraction +(numerator: int, denominator: int) +
    +
    +

    Fraction(numerator: int, denominator: int)

    +
    + +Expand source code + +
    class Fraction(PlutusData):
    +    CONSTR_ID = 1
    +    numerator: int
    +    denominator: int
    +
    +

    Ancestors

    +
      +
    • pycardano.plutus.PlutusData
    • +
    • pycardano.serialization.ArrayCBORSerializable
    • +
    • pycardano.serialization.CBORSerializable
    • +
    +

    Class variables

    +
    +
    var CONSTR_ID : ClassVar[int]
    +
    +
    +
    +
    var denominator : int
    +
    +
    +
    +
    var numerator : int
    +
    +
    +
    +
    +
    +
    +
    +
    + +
    + + + \ No newline at end of file diff --git a/docs/hebi/std/index.html b/docs/hebi/std/index.html new file mode 100644 index 0000000..b6bf9b0 --- /dev/null +++ b/docs/hebi/std/index.html @@ -0,0 +1,167 @@ + + + + + + + + +hebi.std API documentation + + + + + + + + + + + +
    + + + + +
    +
    +

    Module hebi.std

    +
    +
    +
    +
    +

    Sub-modules

    +
    +
    hebi.std.fractions
    +
    +

    An implementation of fractions in opshin +This does not maintain smallest possible notation invariants for the sake of efficiency +- the user has full …

    +
    +
    hebi.std.math
    +
    +

    An implementation of some math operations in opshin

    +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    + +
    + + + \ No newline at end of file diff --git a/docs/hebi/std/math.html b/docs/hebi/std/math.html new file mode 100644 index 0000000..c4dca90 --- /dev/null +++ b/docs/hebi/std/math.html @@ -0,0 +1,228 @@ + + + + + + + + +hebi.std.math API documentation + + + + + + + + + + + +
    + + + + +
    +
    +

    Module hebi.std.math

    +
    +
    +

    An implementation of some math operations in opshin

    +
    + +Expand source code + +
    """ An implementation of some math operations in opshin """
    +
    +
    +def gcd(a: int, b: int) -> int:
    +    while b != 0:
    +        a, b = b, a % b
    +    return abs(a)
    +
    +
    +def sign(a: int) -> int:
    +    return -1 if a < 0 else 1
    +
    +
    +def unsigned_int_from_bytes_big(b: bytes) -> int:
    +    """Converts a bytestring into the corresponding integer, big/network byteorder, unsigned"""
    +    acc = 0
    +    for i in range(len(b)):
    +        acc = acc * 256 + b[i]
    +    return acc
    +
    +
    +
    +
    +
    +
    +
    +

    Functions

    +
    +
    +def gcd(a: int, b: int) ‑> int +
    +
    +
    +
    + +Expand source code + +
    def gcd(a: int, b: int) -> int:
    +    while b != 0:
    +        a, b = b, a % b
    +    return abs(a)
    +
    +
    +
    +def sign(a: int) ‑> int +
    +
    +
    +
    + +Expand source code + +
    def sign(a: int) -> int:
    +    return -1 if a < 0 else 1
    +
    +
    +
    +def unsigned_int_from_bytes_big(b: bytes) ‑> int +
    +
    +

    Converts a bytestring into the corresponding integer, big/network byteorder, unsigned

    +
    + +Expand source code + +
    def unsigned_int_from_bytes_big(b: bytes) -> int:
    +    """Converts a bytestring into the corresponding integer, big/network byteorder, unsigned"""
    +    acc = 0
    +    for i in range(len(b)):
    +        acc = acc * 256 + b[i]
    +    return acc
    +
    +
    +
    +
    +
    +
    +
    + +
    + + + \ No newline at end of file diff --git a/docs/hebi/tests/index.html b/docs/hebi/tests/index.html index d0510ce..b0a52e0 100644 --- a/docs/hebi/tests/index.html +++ b/docs/hebi/tests/index.html @@ -84,6 +84,10 @@

    Sub-modules

    +
    hebi.tests.test_std
    +
    +
    +
    hebi.tests.test_stdlib
    @@ -167,6 +171,7 @@

    Index

  • hebi.tests.test_ledger
  • hebi.tests.test_misc
  • hebi.tests.test_ops
  • +
  • hebi.tests.test_std
  • hebi.tests.test_stdlib
  • diff --git a/docs/hebi/tests/test_builtins.html b/docs/hebi/tests/test_builtins.html index 36aa03a..c8a891c 100644 --- a/docs/hebi/tests/test_builtins.html +++ b/docs/hebi/tests/test_builtins.html @@ -1141,7 +1141,7 @@

    Methods

    -def test_int_string_0_10_00(*a) +def test_int_string_0_10_00(*a, **kw)
    @@ -1150,12 +1150,12 @@

    Methods

    Expand source code
    @wraps(func)
    -def standalone_func(*a):
    -    return func(*(a + p.args), **p.kwargs)
    +def standalone_func(*a, **kw): + return func(*(a + p.args), **p.kwargs, **kw)
    -def test_int_string_1_00(*a) +def test_int_string_1_00(*a, **kw)
    @@ -1164,12 +1164,12 @@

    Methods

    Expand source code
    @wraps(func)
    -def standalone_func(*a):
    -    return func(*(a + p.args), **p.kwargs)
    +def standalone_func(*a, **kw): + return func(*(a + p.args), **p.kwargs, **kw)
    -def test_int_string_2__(*a) +def test_int_string_2__(*a, **kw)
    @@ -1178,12 +1178,12 @@

    Methods

    Expand source code
    @wraps(func)
    -def standalone_func(*a):
    -    return func(*(a + p.args), **p.kwargs)
    +def standalone_func(*a, **kw): + return func(*(a + p.args), **p.kwargs, **kw)
    -def test_int_string_3__1(*a) +def test_int_string_3__1(*a, **kw)
    @@ -1192,12 +1192,12 @@

    Methods

    Expand source code
    @wraps(func)
    -def standalone_func(*a):
    -    return func(*(a + p.args), **p.kwargs)
    +def standalone_func(*a, **kw): + return func(*(a + p.args), **p.kwargs, **kw)
    -def test_int_string_4__10238(*a) +def test_int_string_4__10238(*a, **kw)
    @@ -1206,12 +1206,12 @@

    Methods

    Expand source code
    @wraps(func)
    -def standalone_func(*a):
    -    return func(*(a + p.args), **p.kwargs)
    +def standalone_func(*a, **kw): + return func(*(a + p.args), **p.kwargs, **kw)
    -def test_int_string_5_19293812983721837981(*a) +def test_int_string_5_19293812983721837981(*a, **kw)
    @@ -1220,12 +1220,12 @@

    Methods

    Expand source code
    @wraps(func)
    -def standalone_func(*a):
    -    return func(*(a + p.args), **p.kwargs)
    +def standalone_func(*a, **kw): + return func(*(a + p.args), **p.kwargs, **kw)
    -def test_int_string_6_jakjsdh(*a) +def test_int_string_6_jakjsdh(*a, **kw)
    @@ -1234,8 +1234,8 @@

    Methods

    Expand source code
    @wraps(func)
    -def standalone_func(*a):
    -    return func(*(a + p.args), **p.kwargs)
    +def standalone_func(*a, **kw): + return func(*(a + p.args), **p.kwargs, **kw)
    diff --git a/docs/hebi/tests/test_ledger/index.html b/docs/hebi/tests/test_ledger/index.html index d966b35..295d6f0 100644 --- a/docs/hebi/tests/test_ledger/index.html +++ b/docs/hebi/tests/test_ledger/index.html @@ -68,6 +68,10 @@

    Module hebi.tests.test_ledger

    Sub-modules

    +
    hebi.tests.test_ledger.test_api_v2
    +
    +
    +
    hebi.tests.test_ledger.test_interval
    @@ -147,6 +151,7 @@

    Index

  • Sub-modules

  • diff --git a/docs/hebi/tests/test_ledger/test_api_v2.html b/docs/hebi/tests/test_ledger/test_api_v2.html new file mode 100644 index 0000000..81783dd --- /dev/null +++ b/docs/hebi/tests/test_ledger/test_api_v2.html @@ -0,0 +1,228 @@ + + + + + + + + +hebi.tests.test_ledger.test_api_v2 API documentation + + + + + + + + + + + +
    + + + + +
    +
    +

    Module hebi.tests.test_ledger.test_api_v2

    +
    +
    +
    + +Expand source code + +
    from parameterized import parameterized
    +
    +from hebi.ledger.api_v2 import *
    +
    +
    +@parameterized.expand(
    +    [
    +        (
    +            "d8799fd8799f9fd8799fd8799fd8799f582055d353acacaab6460b37ed0f0e3a1a0aabf056df4a7fa1e265d21149ccacc527ff01ffd8799fd8799fd87a9f581cdbe769758f26efb21f008dc097bb194cffc622acc37fcefc5372eee3ffd87a80ffa140a1401a00989680d87a9f5820dfab81872ce2bbe6ee5af9bbfee4047f91c1f57db5e30da727d5fef1e7f02f4dffd87a80ffffff809fd8799fd8799fd8799f581cdc315c289fee4484eda07038393f21dc4e572aff292d7926018725c2ffd87a80ffa140a14000d87980d87a80ffffa140a14000a140a1400080a0d8799fd8799fd87980d87a80ffd8799fd87b80d87a80ffff80a1d87a9fd8799fd8799f582055d353acacaab6460b37ed0f0e3a1a0aabf056df4a7fa1e265d21149ccacc527ff01ffffd87980a15820dfab81872ce2bbe6ee5af9bbfee4047f91c1f57db5e30da727d5fef1e7f02f4dd8799f581cdc315c289fee4484eda07038393f21dc4e572aff292d7926018725c2ffd8799f5820746957f0eb57f2b11119684e611a98f373afea93473fefbb7632d579af2f6259ffffd87a9fd8799fd8799f582055d353acacaab6460b37ed0f0e3a1a0aabf056df4a7fa1e265d21149ccacc527ff01ffffff"
    +        ),
    +        (
    +            "d8799fd8799f9fd8799fd8799fd8799f582055d353acacaab6460b37ed0f0e3a1a0aabf056df4a7fa1e265d21149ccacc527ff01ffd8799fd8799fd87a9f581cdbe769758f26efb21f008dc097bb194cffc622acc37fcefc5372eee3ffd87a80ffa140a1401a00989680d87a9f5820dfab81872ce2bbe6ee5af9bbfee4047f91c1f57db5e30da727d5fef1e7f02f4dffd87a80ffffff809fd8799fd8799fd8799f581cdc315c289fee4484eda07038393f21dc4e572aff292d7926018725c2ffd87a80ffa140a14000d87980d87a80ffffa140a14000a140a1400080a0d8799fd8799fd87a9f1b000001836ac117d8ffd87a80ffd8799fd87b80d87a80ffff80a1d87a9fd8799fd8799f582055d353acacaab6460b37ed0f0e3a1a0aabf056df4a7fa1e265d21149ccacc527ff01ffffd87980a15820dfab81872ce2bbe6ee5af9bbfee4047f91c1f57db5e30da727d5fef1e7f02f4dd8799f581cdc315c289fee4484eda07038393f21dc4e572aff292d7926018725c2ffd8799f5820797a1e1720b63621c6b185088184cb8e23af6e46b55bd83e7a91024c823a6c2affffd87a9fd8799fd8799f582055d353acacaab6460b37ed0f0e3a1a0aabf056df4a7fa1e265d21149ccacc527ff01ffffff"
    +        ),
    +        (
    +            "d8799fd8799f9fd8799fd8799fd8799f582055d353acacaab6460b37ed0f0e3a1a0aabf056df4a7fa1e265d21149ccacc527ff01ffd8799fd8799fd87a9f581cdbe769758f26efb21f008dc097bb194cffc622acc37fcefc5372eee3ffd87a80ffa140a1401a00989680d87a9f5820dfab81872ce2bbe6ee5af9bbfee4047f91c1f57db5e30da727d5fef1e7f02f4dffd87a80ffffff809fd8799fd8799fd8799f581cdc315c289fee4484eda07038393f21dc4e572aff292d7926018725c2ffd87a80ffa140a14000d87980d87a80ffd8799fd8799fd8799f581cdc315c289fee4484eda07038393f21dc4e572aff292d7926018725c2ffd87a80ffa140a1401a000f4240d87980d87a80ffffa140a14000a140a1400080a0d8799fd8799fd87a9f1b000001836ac117d8ffd87a80ffd8799fd87b80d87a80ffff9f581cdc315c289fee4484eda07038393f21dc4e572aff292d7926018725c2ffa1d87a9fd8799fd8799f582055d353acacaab6460b37ed0f0e3a1a0aabf056df4a7fa1e265d21149ccacc527ff01ffffd87980a15820dfab81872ce2bbe6ee5af9bbfee4047f91c1f57db5e30da727d5fef1e7f02f4dd8799f581cdc315c289fee4484eda07038393f21dc4e572aff292d7926018725c2ffd8799f5820c17c32f6433ae22c2acaebfb796bbfaee3993ff7ebb58a2bac6b4a3bdd2f6d28ffffd87a9fd8799fd8799f582055d353acacaab6460b37ed0f0e3a1a0aabf056df4a7fa1e265d21149ccacc527ff01ffffff"
    +        ),
    +    ]
    +)
    +def test_script_context_repr_correct(p):
    +    # Make sure that this parses correctly and does not throw an error
    +    # Note that this was extracted from a PlutusV2 invocation
    +    # in increasing complexity...
    +    ScriptContext.from_cbor(p)
    +
    +
    +
    +
    +
    +
    +
    +

    Functions

    +
    +
    +def test_script_context_repr_correct_0_d8799fd8799f9fd8799fd8799fd8799f582055d353acacaab6460b37ed0f0e3a1a0aabf056df4a7fa1e265d21149ccacc527ff01ffd8799fd8799fd87a9f581cdbe769758f26efb21f008dc097bb194cffc622acc37fcefc5372eee3ffd87a80ffa140a1401a00989680d87a9f5820dfab81872ce2bbe6ee5af9bbfee4047f91c1f57db5e30da727d5fef1e7f02f4dffd87a80ffffff809fd8799fd8799fd8799f581cdc315c289fee4484eda07038393f21dc4e572aff292d7926018725c2ffd87a80ffa140a14000d87980d87a80ffffa140a14000a140a1400080a0d8799fd8799fd87980d87a80ffd8799fd87b80d87a80ffff80a1d87a9fd8799fd8799f582055d353acacaab6460b37ed0f0e3a1a0aabf056df4a7fa1e265d21149ccacc527ff01ffffd87980a15820dfab81872ce2bbe6ee5af9bbfee4047f91c1f57db5e30da727d5fef1e7f02f4dd8799f581cdc315c289fee4484eda07038393f21dc4e572aff292d7926018725c2ffd8799f5820746957f0eb57f2b11119684e611a98f373afea93473fefbb7632d579af2f6259ffffd87a9fd8799fd8799f582055d353acacaab6460b37ed0f0e3a1a0aabf056df4a7fa1e265d21149ccacc527ff01ffffff(*a, **kw) +
    +
    +
    +
    + +Expand source code + +
    @wraps(func)
    +def standalone_func(*a, **kw):
    +    return func(*(a + p.args), **p.kwargs, **kw)
    +
    +
    +
    +def test_script_context_repr_correct_1_d8799fd8799f9fd8799fd8799fd8799f582055d353acacaab6460b37ed0f0e3a1a0aabf056df4a7fa1e265d21149ccacc527ff01ffd8799fd8799fd87a9f581cdbe769758f26efb21f008dc097bb194cffc622acc37fcefc5372eee3ffd87a80ffa140a1401a00989680d87a9f5820dfab81872ce2bbe6ee5af9bbfee4047f91c1f57db5e30da727d5fef1e7f02f4dffd87a80ffffff809fd8799fd8799fd8799f581cdc315c289fee4484eda07038393f21dc4e572aff292d7926018725c2ffd87a80ffa140a14000d87980d87a80ffffa140a14000a140a1400080a0d8799fd8799fd87a9f1b000001836ac117d8ffd87a80ffd8799fd87b80d87a80ffff80a1d87a9fd8799fd8799f582055d353acacaab6460b37ed0f0e3a1a0aabf056df4a7fa1e265d21149ccacc527ff01ffffd87980a15820dfab81872ce2bbe6ee5af9bbfee4047f91c1f57db5e30da727d5fef1e7f02f4dd8799f581cdc315c289fee4484eda07038393f21dc4e572aff292d7926018725c2ffd8799f5820797a1e1720b63621c6b185088184cb8e23af6e46b55bd83e7a91024c823a6c2affffd87a9fd8799fd8799f582055d353acacaab6460b37ed0f0e3a1a0aabf056df4a7fa1e265d21149ccacc527ff01ffffff(*a, **kw) +
    +
    +
    +
    + +Expand source code + +
    @wraps(func)
    +def standalone_func(*a, **kw):
    +    return func(*(a + p.args), **p.kwargs, **kw)
    +
    +
    +
    +def test_script_context_repr_correct_2_d8799fd8799f9fd8799fd8799fd8799f582055d353acacaab6460b37ed0f0e3a1a0aabf056df4a7fa1e265d21149ccacc527ff01ffd8799fd8799fd87a9f581cdbe769758f26efb21f008dc097bb194cffc622acc37fcefc5372eee3ffd87a80ffa140a1401a00989680d87a9f5820dfab81872ce2bbe6ee5af9bbfee4047f91c1f57db5e30da727d5fef1e7f02f4dffd87a80ffffff809fd8799fd8799fd8799f581cdc315c289fee4484eda07038393f21dc4e572aff292d7926018725c2ffd87a80ffa140a14000d87980d87a80ffd8799fd8799fd8799f581cdc315c289fee4484eda07038393f21dc4e572aff292d7926018725c2ffd87a80ffa140a1401a000f4240d87980d87a80ffffa140a14000a140a1400080a0d8799fd8799fd87a9f1b000001836ac117d8ffd87a80ffd8799fd87b80d87a80ffff9f581cdc315c289fee4484eda07038393f21dc4e572aff292d7926018725c2ffa1d87a9fd8799fd8799f582055d353acacaab6460b37ed0f0e3a1a0aabf056df4a7fa1e265d21149ccacc527ff01ffffd87980a15820dfab81872ce2bbe6ee5af9bbfee4047f91c1f57db5e30da727d5fef1e7f02f4dd8799f581cdc315c289fee4484eda07038393f21dc4e572aff292d7926018725c2ffd8799f5820c17c32f6433ae22c2acaebfb796bbfaee3993ff7ebb58a2bac6b4a3bdd2f6d28ffffd87a9fd8799fd8799f582055d353acacaab6460b37ed0f0e3a1a0aabf056df4a7fa1e265d21149ccacc527ff01ffffff(*a, **kw) +
    +
    +
    +
    + +Expand source code + +
    @wraps(func)
    +def standalone_func(*a, **kw):
    +    return func(*(a + p.args), **p.kwargs, **kw)
    +
    +
    +
    +
    +
    +
    +
    + +
    + + + \ No newline at end of file diff --git a/docs/hebi/tests/test_ledger/test_interval.html b/docs/hebi/tests/test_ledger/test_interval.html index 07a1b3d..716b2be 100644 --- a/docs/hebi/tests/test_ledger/test_interval.html +++ b/docs/hebi/tests/test_ledger/test_interval.html @@ -217,44 +217,34 @@

    Module hebi.tests.test_ledger.test_interval

    @given( lower_bound=st.integers(), - lower_closed=st.one_of(st.builds(FalseData), st.builds(TrueData)), ) def test_fuzz_make_from( lower_bound: int, - lower_closed: BoolData, ) -> None: - make_from(lower_bound=lower_bound, lower_closed=lower_closed) + make_from(lower_bound=lower_bound) @given( lower_bound=st.integers(), upper_bound=st.integers(), - lower_closed=st.one_of(st.builds(FalseData), st.builds(TrueData)), - upper_closed=st.one_of(st.builds(FalseData), st.builds(TrueData)), ) def test_fuzz_make_range( lower_bound: int, upper_bound: int, - lower_closed: BoolData, - upper_closed: BoolData, ) -> None: make_range( lower_bound=lower_bound, upper_bound=upper_bound, - lower_closed=lower_closed, - upper_closed=upper_closed, ) @given( upper_bound=st.integers(), - upper_closed=st.one_of(st.builds(FalseData), st.builds(TrueData)), ) def test_fuzz_make_to( upper_bound: int, - upper_closed: BoolData, ) -> None: - make_to(upper_bound=upper_bound, upper_closed=upper_closed) + make_to(upper_bound=upper_bound) @given( @@ -274,7 +264,37 @@

    Module hebi.tests.test_ledger.test_interval

    bool_data = TrueData() else: bool_data = FalseData() - assert get_bool(bool_data) == b
    + assert get_bool(bool_data) == b + + +@given( + lower_bound=st.integers(), + upper_bound_1=st.integers(), + upper_bound_2=st.integers(), +) +def test_make_to_in_make_range( + lower_bound: int, + upper_bound_1: int, + upper_bound_2: int, +) -> None: + assert contains( + make_to(upper_bound=upper_bound_1), make_range(lower_bound, upper_bound_2) + ) == (upper_bound_1 >= upper_bound_2) + + +@given( + lower_bound_1=st.integers(), + lower_bound_2=st.integers(), + upper_bound=st.integers(), +) +def test_make_from_in_make_range( + lower_bound_1: int, + lower_bound_2: int, + upper_bound: int, +) -> None: + assert contains( + make_from(lower_bound=lower_bound_1), make_range(lower_bound_2, upper_bound) + ) == (lower_bound_1 <= lower_bound_2)
    @@ -392,13 +412,11 @@

    Functions

    @given(
         lower_bound=st.integers(),
    -    lower_closed=st.one_of(st.builds(FalseData), st.builds(TrueData)),
     )
     def test_fuzz_make_from(
         lower_bound: int,
    -    lower_closed: BoolData,
     ) -> None:
    -    make_from(lower_bound=lower_bound, lower_closed=lower_closed)
    + make_from(lower_bound=lower_bound)
    @@ -413,20 +431,14 @@

    Functions

    @given(
         lower_bound=st.integers(),
         upper_bound=st.integers(),
    -    lower_closed=st.one_of(st.builds(FalseData), st.builds(TrueData)),
    -    upper_closed=st.one_of(st.builds(FalseData), st.builds(TrueData)),
     )
     def test_fuzz_make_range(
         lower_bound: int,
         upper_bound: int,
    -    lower_closed: BoolData,
    -    upper_closed: BoolData,
     ) -> None:
         make_range(
             lower_bound=lower_bound,
             upper_bound=upper_bound,
    -        lower_closed=lower_closed,
    -        upper_closed=upper_closed,
         )
    @@ -441,13 +453,11 @@

    Functions

    @given(
         upper_bound=st.integers(),
    -    upper_closed=st.one_of(st.builds(FalseData), st.builds(TrueData)),
     )
     def test_fuzz_make_to(
         upper_bound: int,
    -    upper_closed: BoolData,
     ) -> None:
    -    make_to(upper_bound=upper_bound, upper_closed=upper_closed)
    + make_to(upper_bound=upper_bound)
    @@ -468,6 +478,54 @@

    Functions

    assert get_bool(bool_data) == b
    +
    +def test_make_from_in_make_range() ‑> None +
    +
    +
    +
    + +Expand source code + +
    @given(
    +    lower_bound_1=st.integers(),
    +    lower_bound_2=st.integers(),
    +    upper_bound=st.integers(),
    +)
    +def test_make_from_in_make_range(
    +    lower_bound_1: int,
    +    lower_bound_2: int,
    +    upper_bound: int,
    +) -> None:
    +    assert contains(
    +        make_from(lower_bound=lower_bound_1), make_range(lower_bound_2, upper_bound)
    +    ) == (lower_bound_1 <= lower_bound_2)
    +
    +
    +
    +def test_make_to_in_make_range() ‑> None +
    +
    +
    +
    + +Expand source code + +
    @given(
    +    lower_bound=st.integers(),
    +    upper_bound_1=st.integers(),
    +    upper_bound_2=st.integers(),
    +)
    +def test_make_to_in_make_range(
    +    lower_bound: int,
    +    upper_bound_1: int,
    +    upper_bound_2: int,
    +) -> None:
    +    assert contains(
    +        make_to(upper_bound=upper_bound_1), make_range(lower_bound, upper_bound_2)
    +    ) == (upper_bound_1 >= upper_bound_2)
    +
    +
    def test_ordering_compare() ‑> None
    @@ -664,6 +722,8 @@

    Index

  • test_fuzz_make_range
  • test_fuzz_make_to
  • test_get_bool
  • +
  • test_make_from_in_make_range
  • +
  • test_make_to_in_make_range
  • test_ordering_compare
  • test_ordering_compare_extended
  • test_ordering_compare_lower_bound
  • diff --git a/docs/hebi/tests/test_misc.html b/docs/hebi/tests/test_misc.html index a57762f..4c8e095 100644 --- a/docs/hebi/tests/test_misc.html +++ b/docs/hebi/tests/test_misc.html @@ -234,25 +234,6 @@

    Module hebi.tests.test_misc

    ret, ) - @parameterized.expand( - [ - ( - "d8799fd8799f9fd8799fd8799fd8799f582055d353acacaab6460b37ed0f0e3a1a0aabf056df4a7fa1e265d21149ccacc527ff01ffd8799fd8799fd87a9f581cdbe769758f26efb21f008dc097bb194cffc622acc37fcefc5372eee3ffd87a80ffa140a1401a00989680d87a9f5820dfab81872ce2bbe6ee5af9bbfee4047f91c1f57db5e30da727d5fef1e7f02f4dffd87a80ffffff809fd8799fd8799fd8799f581cdc315c289fee4484eda07038393f21dc4e572aff292d7926018725c2ffd87a80ffa140a14000d87980d87a80ffffa140a14000a140a1400080a0d8799fd8799fd87980d87a80ffd8799fd87b80d87a80ffff80a1d87a9fd8799fd8799f582055d353acacaab6460b37ed0f0e3a1a0aabf056df4a7fa1e265d21149ccacc527ff01ffffd87980a15820dfab81872ce2bbe6ee5af9bbfee4047f91c1f57db5e30da727d5fef1e7f02f4dd8799f581cdc315c289fee4484eda07038393f21dc4e572aff292d7926018725c2ffd8799f5820746957f0eb57f2b11119684e611a98f373afea93473fefbb7632d579af2f6259ffffd87a9fd8799fd8799f582055d353acacaab6460b37ed0f0e3a1a0aabf056df4a7fa1e265d21149ccacc527ff01ffffff" - ), - ( - "d8799fd8799f9fd8799fd8799fd8799f582055d353acacaab6460b37ed0f0e3a1a0aabf056df4a7fa1e265d21149ccacc527ff01ffd8799fd8799fd87a9f581cdbe769758f26efb21f008dc097bb194cffc622acc37fcefc5372eee3ffd87a80ffa140a1401a00989680d87a9f5820dfab81872ce2bbe6ee5af9bbfee4047f91c1f57db5e30da727d5fef1e7f02f4dffd87a80ffffff809fd8799fd8799fd8799f581cdc315c289fee4484eda07038393f21dc4e572aff292d7926018725c2ffd87a80ffa140a14000d87980d87a80ffffa140a14000a140a1400080a0d8799fd8799fd87a9f1b000001836ac117d8ffd87a80ffd8799fd87b80d87a80ffff80a1d87a9fd8799fd8799f582055d353acacaab6460b37ed0f0e3a1a0aabf056df4a7fa1e265d21149ccacc527ff01ffffd87980a15820dfab81872ce2bbe6ee5af9bbfee4047f91c1f57db5e30da727d5fef1e7f02f4dd8799f581cdc315c289fee4484eda07038393f21dc4e572aff292d7926018725c2ffd8799f5820797a1e1720b63621c6b185088184cb8e23af6e46b55bd83e7a91024c823a6c2affffd87a9fd8799fd8799f582055d353acacaab6460b37ed0f0e3a1a0aabf056df4a7fa1e265d21149ccacc527ff01ffffff" - ), - ( - "d8799fd8799f9fd8799fd8799fd8799f582055d353acacaab6460b37ed0f0e3a1a0aabf056df4a7fa1e265d21149ccacc527ff01ffd8799fd8799fd87a9f581cdbe769758f26efb21f008dc097bb194cffc622acc37fcefc5372eee3ffd87a80ffa140a1401a00989680d87a9f5820dfab81872ce2bbe6ee5af9bbfee4047f91c1f57db5e30da727d5fef1e7f02f4dffd87a80ffffff809fd8799fd8799fd8799f581cdc315c289fee4484eda07038393f21dc4e572aff292d7926018725c2ffd87a80ffa140a14000d87980d87a80ffd8799fd8799fd8799f581cdc315c289fee4484eda07038393f21dc4e572aff292d7926018725c2ffd87a80ffa140a1401a000f4240d87980d87a80ffffa140a14000a140a1400080a0d8799fd8799fd87a9f1b000001836ac117d8ffd87a80ffd8799fd87b80d87a80ffff9f581cdc315c289fee4484eda07038393f21dc4e572aff292d7926018725c2ffa1d87a9fd8799fd8799f582055d353acacaab6460b37ed0f0e3a1a0aabf056df4a7fa1e265d21149ccacc527ff01ffffd87980a15820dfab81872ce2bbe6ee5af9bbfee4047f91c1f57db5e30da727d5fef1e7f02f4dd8799f581cdc315c289fee4484eda07038393f21dc4e572aff292d7926018725c2ffd8799f5820c17c32f6433ae22c2acaebfb796bbfaee3993ff7ebb58a2bac6b4a3bdd2f6d28ffffd87a9fd8799fd8799f582055d353acacaab6460b37ed0f0e3a1a0aabf056df4a7fa1e265d21149ccacc527ff01ffffff" - ), - ] - ) - def test_script_context_repr_correct(self, p): - # Make sure that this parses correctly and does not throw an error - # Note that this was extracted from a PlutusV2 invocation - # in increasing complexity... - prelude.ScriptContext.from_cbor(p) - def test_gift_contract_succeed(self): input_file = "examples/smart_contracts/gift.py" with open(input_file) as fp: @@ -750,14 +731,49 @@

    Module hebi.tests.test_misc

    res = uplc_eval(uplc.Apply(code, uplc.PlutusInteger(0))).value self.assertEqual(res, 0) - @unittest.expectedFailure def test_typecast_int_anything(self): - # this should not compile, we can not upcast with this notation - # up to discussion whether this should be allowed, but i.g. it should never be necessary or useful + # this should compile, it happens implicitly anyways when calling a function with Any parameters source_code = """ def validator(x: int) -> Anything: b: Anything = x - return x + return b +""" + ast = compiler.parse(source_code) + code = compiler.compile(ast).compile() + res = uplc_eval(uplc.Apply(code, uplc.PlutusInteger(0))).value + self.assertEqual(res, 0) + + def test_typecast_int_anything_int(self): + source_code = """ +def validator(x: int) -> Anything: + b: Anything = x + c: int = b + return c + 1 +""" + ast = compiler.parse(source_code) + code = compiler.compile(ast).compile() + res = uplc_eval(uplc.Apply(code, uplc.PlutusInteger(0))).value + self.assertEqual(res, 1) + + def test_typecast_anything_int_anything(self): + source_code = """ +def validator(x: Anything) -> Anything: + b: int = x + c: Anything = b + 1 + return c +""" + ast = compiler.parse(source_code) + code = compiler.compile(ast).compile() + res = uplc_eval(uplc.Apply(code, uplc.PlutusInteger(0))).value + self.assertEqual(res, 1) + + @unittest.expectedFailure + def test_typecast_int_str(self): + # this should compile, the two types are unrelated and there is no meaningful way to cast them either direction + source_code = """ +def validator(x: int) -> str: + b: str = x + return b """ ast = compiler.parse(source_code) code = compiler.compile(ast) @@ -823,7 +839,134 @@

    Module hebi.tests.test_misc

    """ ast = compiler.parse(source_code) code = compiler.compile(ast).compile() - res = uplc_eval(uplc.Apply(code, uplc.PlutusInteger(0))) + res = uplc_eval(uplc.Apply(code, uplc.PlutusInteger(0))) + + def test_return_anything(self): + source_code = """ +from opshin.prelude import * + +def validator() -> Anything: + return b"" +""" + ast = compiler.parse(source_code) + code = compiler.compile(ast).compile() + res = uplc_eval(uplc.Apply(code, uplc.PlutusConstr(0, []))) + self.assertEqual(res, uplc.PlutusByteString(b"")) + + def test_no_return_annotation(self): + source_code = """ +from opshin.prelude import * + +def validator(): + return b"" +""" + ast = compiler.parse(source_code) + code = compiler.compile(ast).compile() + res = uplc_eval(uplc.Apply(code, uplc.PlutusConstr(0, []))) + self.assertEqual(res, uplc.PlutusByteString(b"")) + + def test_no_parameter_annotation(self): + source_code = """ +from opshin.prelude import * + +def validator(a) -> bytes: + b: bytes = a + return b +""" + ast = compiler.parse(source_code) + code = compiler.compile(ast).compile() + res = uplc_eval(uplc.Apply(code, uplc.PlutusByteString(b""))) + self.assertEqual(res, uplc.PlutusByteString(b"")) + + @given(xs=st.dictionaries(st.integers(), st.binary())) + def test_dict_items_values_deconstr(self, xs): + # asserts that deconstruction of parameters works for for loops too + source_code = """ +def validator(xs: Dict[int, bytes]) -> bytes: + sum_values = b"" + for _, x in xs.items(): + sum_values += x + return sum_values +""" + ast = compiler.parse(source_code) + code = compiler.compile(ast) + code = code.compile() + f = code.term + # UPLC lambdas may only take one argument at a time, so we evaluate by repeatedly applying + for d in [ + uplc.PlutusMap( + {uplc.PlutusInteger(k): uplc.PlutusByteString(v) for k, v in xs.items()} + ) + ]: + f = uplc.Apply(f, d) + ret = uplc_eval(f).value + self.assertEqual( + ret, + b"".join(xs.values()), + "for loop deconstruction did not behave as expected", + ) + + def test_nested_deconstruction(self): + source_code = """ +def validator(xs) -> int: + a, ((b, c), d) = (1, ((2, 3), 4)) + return a + b + c + d +""" + ast = compiler.parse(source_code) + code = compiler.compile(ast) + code = code.compile() + f = code.term + # UPLC lambdas may only take one argument at a time, so we evaluate by repeatedly applying + f = uplc.Apply(f, uplc.PlutusConstr(0, [])) + ret = uplc_eval(f).value + self.assertEqual( + ret, + 1 + 2 + 3 + 4, + "for loop deconstruction did not behave as expected", + ) + + @given( + xs=st.dictionaries( + st.binary(), + st.dictionaries(st.binary(), st.integers(), max_size=3), + max_size=5, + ) + ) + def test_dict_items_values_deconstr(self, xs): + # nested deconstruction with a Value-like object + source_code = """ +def validator(xs: Dict[bytes, Dict[bytes, int]]) -> int: + sum_values = 0 + for pid, tk_dict in xs.items(): + for tk_name, tk_amount in tk_dict.items(): + sum_values += tk_amount + return sum_values +""" + ast = compiler.parse(source_code) + code = compiler.compile(ast) + code = code.compile() + f = code.term + # UPLC lambdas may only take one argument at a time, so we evaluate by repeatedly applying + for d in [ + uplc.PlutusMap( + { + uplc.PlutusByteString(k): uplc.PlutusMap( + { + uplc.PlutusByteString(k2): uplc.PlutusInteger(v2) + for k2, v2 in v.items() + } + ) + for k, v in xs.items() + } + ) + ]: + f = uplc.Apply(f, d) + ret = uplc_eval(f).value + self.assertEqual( + ret, + sum(v for pid, d in xs.items() for nam, v in d.items()), + "for loop deconstruction did not behave as expected", + )
    @@ -1038,25 +1181,6 @@

    Classes

    ret, ) - @parameterized.expand( - [ - ( - "d8799fd8799f9fd8799fd8799fd8799f582055d353acacaab6460b37ed0f0e3a1a0aabf056df4a7fa1e265d21149ccacc527ff01ffd8799fd8799fd87a9f581cdbe769758f26efb21f008dc097bb194cffc622acc37fcefc5372eee3ffd87a80ffa140a1401a00989680d87a9f5820dfab81872ce2bbe6ee5af9bbfee4047f91c1f57db5e30da727d5fef1e7f02f4dffd87a80ffffff809fd8799fd8799fd8799f581cdc315c289fee4484eda07038393f21dc4e572aff292d7926018725c2ffd87a80ffa140a14000d87980d87a80ffffa140a14000a140a1400080a0d8799fd8799fd87980d87a80ffd8799fd87b80d87a80ffff80a1d87a9fd8799fd8799f582055d353acacaab6460b37ed0f0e3a1a0aabf056df4a7fa1e265d21149ccacc527ff01ffffd87980a15820dfab81872ce2bbe6ee5af9bbfee4047f91c1f57db5e30da727d5fef1e7f02f4dd8799f581cdc315c289fee4484eda07038393f21dc4e572aff292d7926018725c2ffd8799f5820746957f0eb57f2b11119684e611a98f373afea93473fefbb7632d579af2f6259ffffd87a9fd8799fd8799f582055d353acacaab6460b37ed0f0e3a1a0aabf056df4a7fa1e265d21149ccacc527ff01ffffff" - ), - ( - "d8799fd8799f9fd8799fd8799fd8799f582055d353acacaab6460b37ed0f0e3a1a0aabf056df4a7fa1e265d21149ccacc527ff01ffd8799fd8799fd87a9f581cdbe769758f26efb21f008dc097bb194cffc622acc37fcefc5372eee3ffd87a80ffa140a1401a00989680d87a9f5820dfab81872ce2bbe6ee5af9bbfee4047f91c1f57db5e30da727d5fef1e7f02f4dffd87a80ffffff809fd8799fd8799fd8799f581cdc315c289fee4484eda07038393f21dc4e572aff292d7926018725c2ffd87a80ffa140a14000d87980d87a80ffffa140a14000a140a1400080a0d8799fd8799fd87a9f1b000001836ac117d8ffd87a80ffd8799fd87b80d87a80ffff80a1d87a9fd8799fd8799f582055d353acacaab6460b37ed0f0e3a1a0aabf056df4a7fa1e265d21149ccacc527ff01ffffd87980a15820dfab81872ce2bbe6ee5af9bbfee4047f91c1f57db5e30da727d5fef1e7f02f4dd8799f581cdc315c289fee4484eda07038393f21dc4e572aff292d7926018725c2ffd8799f5820797a1e1720b63621c6b185088184cb8e23af6e46b55bd83e7a91024c823a6c2affffd87a9fd8799fd8799f582055d353acacaab6460b37ed0f0e3a1a0aabf056df4a7fa1e265d21149ccacc527ff01ffffff" - ), - ( - "d8799fd8799f9fd8799fd8799fd8799f582055d353acacaab6460b37ed0f0e3a1a0aabf056df4a7fa1e265d21149ccacc527ff01ffd8799fd8799fd87a9f581cdbe769758f26efb21f008dc097bb194cffc622acc37fcefc5372eee3ffd87a80ffa140a1401a00989680d87a9f5820dfab81872ce2bbe6ee5af9bbfee4047f91c1f57db5e30da727d5fef1e7f02f4dffd87a80ffffff809fd8799fd8799fd8799f581cdc315c289fee4484eda07038393f21dc4e572aff292d7926018725c2ffd87a80ffa140a14000d87980d87a80ffd8799fd8799fd8799f581cdc315c289fee4484eda07038393f21dc4e572aff292d7926018725c2ffd87a80ffa140a1401a000f4240d87980d87a80ffffa140a14000a140a1400080a0d8799fd8799fd87a9f1b000001836ac117d8ffd87a80ffd8799fd87b80d87a80ffff9f581cdc315c289fee4484eda07038393f21dc4e572aff292d7926018725c2ffa1d87a9fd8799fd8799f582055d353acacaab6460b37ed0f0e3a1a0aabf056df4a7fa1e265d21149ccacc527ff01ffffd87980a15820dfab81872ce2bbe6ee5af9bbfee4047f91c1f57db5e30da727d5fef1e7f02f4dd8799f581cdc315c289fee4484eda07038393f21dc4e572aff292d7926018725c2ffd8799f5820c17c32f6433ae22c2acaebfb796bbfaee3993ff7ebb58a2bac6b4a3bdd2f6d28ffffd87a9fd8799fd8799f582055d353acacaab6460b37ed0f0e3a1a0aabf056df4a7fa1e265d21149ccacc527ff01ffffff" - ), - ] - ) - def test_script_context_repr_correct(self, p): - # Make sure that this parses correctly and does not throw an error - # Note that this was extracted from a PlutusV2 invocation - # in increasing complexity... - prelude.ScriptContext.from_cbor(p) - def test_gift_contract_succeed(self): input_file = "examples/smart_contracts/gift.py" with open(input_file) as fp: @@ -1554,14 +1678,49 @@

    Classes

    res = uplc_eval(uplc.Apply(code, uplc.PlutusInteger(0))).value self.assertEqual(res, 0) - @unittest.expectedFailure def test_typecast_int_anything(self): - # this should not compile, we can not upcast with this notation - # up to discussion whether this should be allowed, but i.g. it should never be necessary or useful + # this should compile, it happens implicitly anyways when calling a function with Any parameters source_code = """ def validator(x: int) -> Anything: b: Anything = x - return x + return b +""" + ast = compiler.parse(source_code) + code = compiler.compile(ast).compile() + res = uplc_eval(uplc.Apply(code, uplc.PlutusInteger(0))).value + self.assertEqual(res, 0) + + def test_typecast_int_anything_int(self): + source_code = """ +def validator(x: int) -> Anything: + b: Anything = x + c: int = b + return c + 1 +""" + ast = compiler.parse(source_code) + code = compiler.compile(ast).compile() + res = uplc_eval(uplc.Apply(code, uplc.PlutusInteger(0))).value + self.assertEqual(res, 1) + + def test_typecast_anything_int_anything(self): + source_code = """ +def validator(x: Anything) -> Anything: + b: int = x + c: Anything = b + 1 + return c +""" + ast = compiler.parse(source_code) + code = compiler.compile(ast).compile() + res = uplc_eval(uplc.Apply(code, uplc.PlutusInteger(0))).value + self.assertEqual(res, 1) + + @unittest.expectedFailure + def test_typecast_int_str(self): + # this should compile, the two types are unrelated and there is no meaningful way to cast them either direction + source_code = """ +def validator(x: int) -> str: + b: str = x + return b """ ast = compiler.parse(source_code) code = compiler.compile(ast) @@ -1627,19 +1786,139 @@

    Classes

    """ ast = compiler.parse(source_code) code = compiler.compile(ast).compile() - res = uplc_eval(uplc.Apply(code, uplc.PlutusInteger(0))) + res = uplc_eval(uplc.Apply(code, uplc.PlutusInteger(0))) + + def test_return_anything(self): + source_code = """ +from opshin.prelude import * + +def validator() -> Anything: + return b"" +""" + ast = compiler.parse(source_code) + code = compiler.compile(ast).compile() + res = uplc_eval(uplc.Apply(code, uplc.PlutusConstr(0, []))) + self.assertEqual(res, uplc.PlutusByteString(b"")) + + def test_no_return_annotation(self): + source_code = """ +from opshin.prelude import * + +def validator(): + return b"" +""" + ast = compiler.parse(source_code) + code = compiler.compile(ast).compile() + res = uplc_eval(uplc.Apply(code, uplc.PlutusConstr(0, []))) + self.assertEqual(res, uplc.PlutusByteString(b"")) + + def test_no_parameter_annotation(self): + source_code = """ +from opshin.prelude import * + +def validator(a) -> bytes: + b: bytes = a + return b +""" + ast = compiler.parse(source_code) + code = compiler.compile(ast).compile() + res = uplc_eval(uplc.Apply(code, uplc.PlutusByteString(b""))) + self.assertEqual(res, uplc.PlutusByteString(b"")) + + @given(xs=st.dictionaries(st.integers(), st.binary())) + def test_dict_items_values_deconstr(self, xs): + # asserts that deconstruction of parameters works for for loops too + source_code = """ +def validator(xs: Dict[int, bytes]) -> bytes: + sum_values = b"" + for _, x in xs.items(): + sum_values += x + return sum_values +""" + ast = compiler.parse(source_code) + code = compiler.compile(ast) + code = code.compile() + f = code.term + # UPLC lambdas may only take one argument at a time, so we evaluate by repeatedly applying + for d in [ + uplc.PlutusMap( + {uplc.PlutusInteger(k): uplc.PlutusByteString(v) for k, v in xs.items()} + ) + ]: + f = uplc.Apply(f, d) + ret = uplc_eval(f).value + self.assertEqual( + ret, + b"".join(xs.values()), + "for loop deconstruction did not behave as expected", + ) + + def test_nested_deconstruction(self): + source_code = """ +def validator(xs) -> int: + a, ((b, c), d) = (1, ((2, 3), 4)) + return a + b + c + d +""" + ast = compiler.parse(source_code) + code = compiler.compile(ast) + code = code.compile() + f = code.term + # UPLC lambdas may only take one argument at a time, so we evaluate by repeatedly applying + f = uplc.Apply(f, uplc.PlutusConstr(0, [])) + ret = uplc_eval(f).value + self.assertEqual( + ret, + 1 + 2 + 3 + 4, + "for loop deconstruction did not behave as expected", + ) + + @given( + xs=st.dictionaries( + st.binary(), + st.dictionaries(st.binary(), st.integers(), max_size=3), + max_size=5, + ) + ) + def test_dict_items_values_deconstr(self, xs): + # nested deconstruction with a Value-like object + source_code = """ +def validator(xs: Dict[bytes, Dict[bytes, int]]) -> int: + sum_values = 0 + for pid, tk_dict in xs.items(): + for tk_name, tk_amount in tk_dict.items(): + sum_values += tk_amount + return sum_values +""" + ast = compiler.parse(source_code) + code = compiler.compile(ast) + code = code.compile() + f = code.term + # UPLC lambdas may only take one argument at a time, so we evaluate by repeatedly applying + for d in [ + uplc.PlutusMap( + { + uplc.PlutusByteString(k): uplc.PlutusMap( + { + uplc.PlutusByteString(k2): uplc.PlutusInteger(v2) + for k2, v2 in v.items() + } + ) + for k, v in xs.items() + } + ) + ]: + f = uplc.Apply(f, d) + ret = uplc_eval(f).value + self.assertEqual( + ret, + sum(v for pid, d in xs.items() for nam, v in d.items()), + "for loop deconstruction did not behave as expected", + )

    Ancestors

    • unittest.case.TestCase
    -

    Class variables

    -
    -
    var test_script_context_repr_correct
    -
    -
    -
    -

    Methods

    @@ -1818,6 +2097,59 @@

    Methods

    self.assertTrue(failed, "Machine did validate the content")
    +
    +def test_dict_items_values_deconstr(self) ‑> None +
    +
    +
    +
    + +Expand source code + +
        @given(
    +        xs=st.dictionaries(
    +            st.binary(),
    +            st.dictionaries(st.binary(), st.integers(), max_size=3),
    +            max_size=5,
    +        )
    +    )
    +    def test_dict_items_values_deconstr(self, xs):
    +        # nested deconstruction with a Value-like object
    +        source_code = """
    +def validator(xs: Dict[bytes, Dict[bytes, int]]) -> int:
    +    sum_values = 0
    +    for pid, tk_dict in xs.items():
    +        for tk_name, tk_amount in tk_dict.items():
    +            sum_values += tk_amount
    +    return sum_values
    +"""
    +        ast = compiler.parse(source_code)
    +        code = compiler.compile(ast)
    +        code = code.compile()
    +        f = code.term
    +        # UPLC lambdas may only take one argument at a time, so we evaluate by repeatedly applying
    +        for d in [
    +            uplc.PlutusMap(
    +                {
    +                    uplc.PlutusByteString(k): uplc.PlutusMap(
    +                        {
    +                            uplc.PlutusByteString(k2): uplc.PlutusInteger(v2)
    +                            for k2, v2 in v.items()
    +                        }
    +                    )
    +                    for k, v in xs.items()
    +                }
    +            )
    +        ]:
    +            f = uplc.Apply(f, d)
    +        ret = uplc_eval(f).value
    +        self.assertEqual(
    +            ret,
    +            sum(v for pid, d in xs.items() for nam, v in d.items()),
    +            "for loop deconstruction did not behave as expected",
    +        )
    +
    +
    def test_dual_use_compile(self)
    @@ -2141,6 +2473,58 @@

    Methods

    pass +
    +def test_nested_deconstruction(self) +
    +
    +
    +
    + +Expand source code + +
        def test_nested_deconstruction(self):
    +        source_code = """
    +def validator(xs) -> int:
    +    a, ((b, c), d) = (1, ((2, 3), 4))
    +    return a + b + c + d
    +"""
    +        ast = compiler.parse(source_code)
    +        code = compiler.compile(ast)
    +        code = code.compile()
    +        f = code.term
    +        # UPLC lambdas may only take one argument at a time, so we evaluate by repeatedly applying
    +        f = uplc.Apply(f, uplc.PlutusConstr(0, []))
    +        ret = uplc_eval(f).value
    +        self.assertEqual(
    +            ret,
    +            1 + 2 + 3 + 4,
    +            "for loop deconstruction did not behave as expected",
    +        )
    +
    +
    +
    +def test_no_parameter_annotation(self) +
    +
    +
    +
    + +Expand source code + +
        def test_no_parameter_annotation(self):
    +        source_code = """
    +from opshin.prelude import *
    +
    +def validator(a) -> bytes:
    +    b: bytes = a
    +    return b
    +"""
    +        ast = compiler.parse(source_code)
    +        code = compiler.compile(ast).compile()
    +        res = uplc_eval(uplc.Apply(code, uplc.PlutusByteString(b"")))
    +        self.assertEqual(res, uplc.PlutusByteString(b""))
    +
    +
    def test_no_reassign(self)
    @@ -2165,6 +2549,28 @@

    Methods

    pass +
    +def test_no_return_annotation(self) +
    +
    +
    +
    + +Expand source code + +
        def test_no_return_annotation(self):
    +        source_code = """
    +from opshin.prelude import *
    +
    +def validator():
    +    return b""
    +"""
    +        ast = compiler.parse(source_code)
    +        code = compiler.compile(ast).compile()
    +        res = uplc_eval(uplc.Apply(code, uplc.PlutusConstr(0, [])))
    +        self.assertEqual(res, uplc.PlutusByteString(b""))
    +
    +
    def test_opt_shared_var(self)
    @@ -2317,8 +2723,8 @@

    Methods

    self.assertEqual(ret, bytes([2, 3]), "Machine did validate the content") -
    -def test_script_context_repr_correct_0_d8799fd8799f9fd8799fd8799fd8799f582055d353acacaab6460b37ed0f0e3a1a0aabf056df4a7fa1e265d21149ccacc527ff01ffd8799fd8799fd87a9f581cdbe769758f26efb21f008dc097bb194cffc622acc37fcefc5372eee3ffd87a80ffa140a1401a00989680d87a9f5820dfab81872ce2bbe6ee5af9bbfee4047f91c1f57db5e30da727d5fef1e7f02f4dffd87a80ffffff809fd8799fd8799fd8799f581cdc315c289fee4484eda07038393f21dc4e572aff292d7926018725c2ffd87a80ffa140a14000d87980d87a80ffffa140a14000a140a1400080a0d8799fd8799fd87980d87a80ffd8799fd87b80d87a80ffff80a1d87a9fd8799fd8799f582055d353acacaab6460b37ed0f0e3a1a0aabf056df4a7fa1e265d21149ccacc527ff01ffffd87980a15820dfab81872ce2bbe6ee5af9bbfee4047f91c1f57db5e30da727d5fef1e7f02f4dd8799f581cdc315c289fee4484eda07038393f21dc4e572aff292d7926018725c2ffd8799f5820746957f0eb57f2b11119684e611a98f373afea93473fefbb7632d579af2f6259ffffd87a9fd8799fd8799f582055d353acacaab6460b37ed0f0e3a1a0aabf056df4a7fa1e265d21149ccacc527ff01ffffff(*a) +
    +def test_return_anything(self)
    @@ -2326,37 +2732,17 @@

    Methods

    Expand source code -
    @wraps(func)
    -def standalone_func(*a):
    -    return func(*(a + p.args), **p.kwargs)
    - -
    -
    -def test_script_context_repr_correct_1_d8799fd8799f9fd8799fd8799fd8799f582055d353acacaab6460b37ed0f0e3a1a0aabf056df4a7fa1e265d21149ccacc527ff01ffd8799fd8799fd87a9f581cdbe769758f26efb21f008dc097bb194cffc622acc37fcefc5372eee3ffd87a80ffa140a1401a00989680d87a9f5820dfab81872ce2bbe6ee5af9bbfee4047f91c1f57db5e30da727d5fef1e7f02f4dffd87a80ffffff809fd8799fd8799fd8799f581cdc315c289fee4484eda07038393f21dc4e572aff292d7926018725c2ffd87a80ffa140a14000d87980d87a80ffffa140a14000a140a1400080a0d8799fd8799fd87a9f1b000001836ac117d8ffd87a80ffd8799fd87b80d87a80ffff80a1d87a9fd8799fd8799f582055d353acacaab6460b37ed0f0e3a1a0aabf056df4a7fa1e265d21149ccacc527ff01ffffd87980a15820dfab81872ce2bbe6ee5af9bbfee4047f91c1f57db5e30da727d5fef1e7f02f4dd8799f581cdc315c289fee4484eda07038393f21dc4e572aff292d7926018725c2ffd8799f5820797a1e1720b63621c6b185088184cb8e23af6e46b55bd83e7a91024c823a6c2affffd87a9fd8799fd8799f582055d353acacaab6460b37ed0f0e3a1a0aabf056df4a7fa1e265d21149ccacc527ff01ffffff(*a) -
    -
    -
    -
    - -Expand source code - -
    @wraps(func)
    -def standalone_func(*a):
    -    return func(*(a + p.args), **p.kwargs)
    -
    -
    -
    -def test_script_context_repr_correct_2_d8799fd8799f9fd8799fd8799fd8799f582055d353acacaab6460b37ed0f0e3a1a0aabf056df4a7fa1e265d21149ccacc527ff01ffd8799fd8799fd87a9f581cdbe769758f26efb21f008dc097bb194cffc622acc37fcefc5372eee3ffd87a80ffa140a1401a00989680d87a9f5820dfab81872ce2bbe6ee5af9bbfee4047f91c1f57db5e30da727d5fef1e7f02f4dffd87a80ffffff809fd8799fd8799fd8799f581cdc315c289fee4484eda07038393f21dc4e572aff292d7926018725c2ffd87a80ffa140a14000d87980d87a80ffd8799fd8799fd8799f581cdc315c289fee4484eda07038393f21dc4e572aff292d7926018725c2ffd87a80ffa140a1401a000f4240d87980d87a80ffffa140a14000a140a1400080a0d8799fd8799fd87a9f1b000001836ac117d8ffd87a80ffd8799fd87b80d87a80ffff9f581cdc315c289fee4484eda07038393f21dc4e572aff292d7926018725c2ffa1d87a9fd8799fd8799f582055d353acacaab6460b37ed0f0e3a1a0aabf056df4a7fa1e265d21149ccacc527ff01ffffd87980a15820dfab81872ce2bbe6ee5af9bbfee4047f91c1f57db5e30da727d5fef1e7f02f4dd8799f581cdc315c289fee4484eda07038393f21dc4e572aff292d7926018725c2ffd8799f5820c17c32f6433ae22c2acaebfb796bbfaee3993ff7ebb58a2bac6b4a3bdd2f6d28ffffd87a9fd8799fd8799f582055d353acacaab6460b37ed0f0e3a1a0aabf056df4a7fa1e265d21149ccacc527ff01ffffff(*a) -
    -
    -
    -
    - -Expand source code - -
    @wraps(func)
    -def standalone_func(*a):
    -    return func(*(a + p.args), **p.kwargs)
    +
        def test_return_anything(self):
    +        source_code = """
    +from opshin.prelude import *
    +
    +def validator() -> Anything:
    +    return b""
    +"""
    +        ast = compiler.parse(source_code)
    +        code = compiler.compile(ast).compile()
    +        res = uplc_eval(uplc.Apply(code, uplc.PlutusConstr(0, [])))
    +        self.assertEqual(res, uplc.PlutusByteString(b""))
    @@ -2435,6 +2821,28 @@

    Methods

    self.assertEqual(res, 0)
    +
    +def test_typecast_anything_int_anything(self) +
    +
    +
    +
    + +Expand source code + +
        def test_typecast_anything_int_anything(self):
    +        source_code = """
    +def validator(x: Anything) -> Anything:
    +    b: int = x
    +    c: Anything = b + 1
    +    return c
    +"""
    +        ast = compiler.parse(source_code)
    +        code = compiler.compile(ast).compile()
    +        res = uplc_eval(uplc.Apply(code, uplc.PlutusInteger(0))).value
    +        self.assertEqual(res, 1)
    +
    +
    def test_typecast_int_anything(self)
    @@ -2444,17 +2852,39 @@

    Methods

    Expand source code -
        @unittest.expectedFailure
    -    def test_typecast_int_anything(self):
    -        # this should not compile, we can not upcast with this notation
    -        # up to discussion whether this should be allowed, but i.g. it should never be necessary or useful
    +
        def test_typecast_int_anything(self):
    +        # this should compile, it happens implicitly anyways when calling a function with Any parameters
             source_code = """
     def validator(x: int) -> Anything:
         b: Anything = x
    -    return x
    +    return b
     """
             ast = compiler.parse(source_code)
    -        code = compiler.compile(ast)
    + code = compiler.compile(ast).compile() + res = uplc_eval(uplc.Apply(code, uplc.PlutusInteger(0))).value + self.assertEqual(res, 0)
    + + +
    +def test_typecast_int_anything_int(self) +
    +
    +
    +
    + +Expand source code + +
        def test_typecast_int_anything_int(self):
    +        source_code = """
    +def validator(x: int) -> Anything:
    +    b: Anything = x
    +    c: int = b
    +    return c + 1
    +"""
    +        ast = compiler.parse(source_code)
    +        code = compiler.compile(ast).compile()
    +        res = uplc_eval(uplc.Apply(code, uplc.PlutusInteger(0))).value
    +        self.assertEqual(res, 1)
    @@ -2478,6 +2908,27 @@

    Methods

    self.assertEqual(res, 0)
    +
    +def test_typecast_int_str(self) +
    +
    +
    +
    + +Expand source code + +
        @unittest.expectedFailure
    +    def test_typecast_int_str(self):
    +        # this should compile, the two types are unrelated and there is no meaningful way to cast them either direction
    +        source_code = """
    +def validator(x: int) -> str:
    +    b: str = x
    +    return b
    +"""
    +        ast = compiler.parse(source_code)
    +        code = compiler.compile(ast)
    +
    +
    def test_union_type_all_records_same_constr(self)
    @@ -2866,6 +3317,7 @@

    test_complex_datum_correct_vals
  • test_datum_cast
  • test_dict_datum
  • +
  • test_dict_items_values_deconstr
  • test_dual_use_compile
  • test_fib_rec
  • test_gift_contract_fail
  • @@ -2877,21 +3329,24 @@

    test_list_expr
  • test_marketplace_compile
  • test_marketplace_compile_fail
  • +
  • test_nested_deconstruction
  • +
  • test_no_parameter_annotation
  • test_no_reassign
  • +
  • test_no_return_annotation
  • test_opt_shared_var
  • test_overopt_removedeadvar
  • test_parameterized_compile
  • test_recursion
  • test_redefine_constr
  • -
  • test_script_context_repr_correct
  • -
  • test_script_context_repr_correct_0_d8799fd8799f9fd8799fd8799fd8799f582055d353acacaab6460b37ed0f0e3a1a0aabf056df4a7fa1e265d21149ccacc527ff01ffd8799fd8799fd87a9f581cdbe769758f26efb21f008dc097bb194cffc622acc37fcefc5372eee3ffd87a80ffa140a1401a00989680d87a9f5820dfab81872ce2bbe6ee5af9bbfee4047f91c1f57db5e30da727d5fef1e7f02f4dffd87a80ffffff809fd8799fd8799fd8799f581cdc315c289fee4484eda07038393f21dc4e572aff292d7926018725c2ffd87a80ffa140a14000d87980d87a80ffffa140a14000a140a1400080a0d8799fd8799fd87980d87a80ffd8799fd87b80d87a80ffff80a1d87a9fd8799fd8799f582055d353acacaab6460b37ed0f0e3a1a0aabf056df4a7fa1e265d21149ccacc527ff01ffffd87980a15820dfab81872ce2bbe6ee5af9bbfee4047f91c1f57db5e30da727d5fef1e7f02f4dd8799f581cdc315c289fee4484eda07038393f21dc4e572aff292d7926018725c2ffd8799f5820746957f0eb57f2b11119684e611a98f373afea93473fefbb7632d579af2f6259ffffd87a9fd8799fd8799f582055d353acacaab6460b37ed0f0e3a1a0aabf056df4a7fa1e265d21149ccacc527ff01ffffff
  • -
  • test_script_context_repr_correct_1_d8799fd8799f9fd8799fd8799fd8799f582055d353acacaab6460b37ed0f0e3a1a0aabf056df4a7fa1e265d21149ccacc527ff01ffd8799fd8799fd87a9f581cdbe769758f26efb21f008dc097bb194cffc622acc37fcefc5372eee3ffd87a80ffa140a1401a00989680d87a9f5820dfab81872ce2bbe6ee5af9bbfee4047f91c1f57db5e30da727d5fef1e7f02f4dffd87a80ffffff809fd8799fd8799fd8799f581cdc315c289fee4484eda07038393f21dc4e572aff292d7926018725c2ffd87a80ffa140a14000d87980d87a80ffffa140a14000a140a1400080a0d8799fd8799fd87a9f1b000001836ac117d8ffd87a80ffd8799fd87b80d87a80ffff80a1d87a9fd8799fd8799f582055d353acacaab6460b37ed0f0e3a1a0aabf056df4a7fa1e265d21149ccacc527ff01ffffd87980a15820dfab81872ce2bbe6ee5af9bbfee4047f91c1f57db5e30da727d5fef1e7f02f4dd8799f581cdc315c289fee4484eda07038393f21dc4e572aff292d7926018725c2ffd8799f5820797a1e1720b63621c6b185088184cb8e23af6e46b55bd83e7a91024c823a6c2affffd87a9fd8799fd8799f582055d353acacaab6460b37ed0f0e3a1a0aabf056df4a7fa1e265d21149ccacc527ff01ffffff
  • -
  • test_script_context_repr_correct_2_d8799fd8799f9fd8799fd8799fd8799f582055d353acacaab6460b37ed0f0e3a1a0aabf056df4a7fa1e265d21149ccacc527ff01ffd8799fd8799fd87a9f581cdbe769758f26efb21f008dc097bb194cffc622acc37fcefc5372eee3ffd87a80ffa140a1401a00989680d87a9f5820dfab81872ce2bbe6ee5af9bbfee4047f91c1f57db5e30da727d5fef1e7f02f4dffd87a80ffffff809fd8799fd8799fd8799f581cdc315c289fee4484eda07038393f21dc4e572aff292d7926018725c2ffd87a80ffa140a14000d87980d87a80ffd8799fd8799fd8799f581cdc315c289fee4484eda07038393f21dc4e572aff292d7926018725c2ffd87a80ffa140a1401a000f4240d87980d87a80ffffa140a14000a140a1400080a0d8799fd8799fd87a9f1b000001836ac117d8ffd87a80ffd8799fd87b80d87a80ffff9f581cdc315c289fee4484eda07038393f21dc4e572aff292d7926018725c2ffa1d87a9fd8799fd8799f582055d353acacaab6460b37ed0f0e3a1a0aabf056df4a7fa1e265d21149ccacc527ff01ffffd87980a15820dfab81872ce2bbe6ee5af9bbfee4047f91c1f57db5e30da727d5fef1e7f02f4dd8799f581cdc315c289fee4484eda07038393f21dc4e572aff292d7926018725c2ffd8799f5820c17c32f6433ae22c2acaebfb796bbfaee3993ff7ebb58a2bac6b4a3bdd2f6d28ffffd87a9fd8799fd8799f582055d353acacaab6460b37ed0f0e3a1a0aabf056df4a7fa1e265d21149ccacc527ff01ffffff
  • +
  • test_return_anything
  • test_showcase
  • test_sum
  • test_typecast_anything_int
  • +
  • test_typecast_anything_int_anything
  • test_typecast_int_anything
  • +
  • test_typecast_int_anything_int
  • test_typecast_int_int
  • +
  • test_typecast_int_str
  • test_union_type_all_records_same_constr
  • test_union_type_attr_access_all_records
  • test_union_type_attr_access_all_records_same_constr
  • diff --git a/docs/hebi/tests/test_std/index.html b/docs/hebi/tests/test_std/index.html new file mode 100644 index 0000000..e8d1414 --- /dev/null +++ b/docs/hebi/tests/test_std/index.html @@ -0,0 +1,165 @@ + + + + + + + + +hebi.tests.test_std API documentation + + + + + + + + + + + +
    + + + + + + +
    + + + \ No newline at end of file diff --git a/docs/hebi/tests/test_std/test_fractions.html b/docs/hebi/tests/test_std/test_fractions.html new file mode 100644 index 0000000..d350c4b --- /dev/null +++ b/docs/hebi/tests/test_std/test_fractions.html @@ -0,0 +1,500 @@ + + + + + + + + +hebi.tests.test_std.test_fractions API documentation + + + + + + + + + + + +
    + + + + +
    +
    +

    Module hebi.tests.test_std.test_fractions

    +
    +
    +
    + +Expand source code + +
    import hypothesis
    +import hypothesis.strategies as hst
    +
    +from hebi.std import fractions as oc_fractions
    +
    +import fractions as native_fractions
    +
    +non_null = hst.one_of(hst.integers(min_value=1), hst.integers(max_value=-1))
    +denormalized_fractions = hst.builds(oc_fractions.Fraction, hst.integers(), non_null)
    +denormalized_fractions_non_null = hst.builds(oc_fractions.Fraction, non_null, non_null)
    +
    +
    +def native_fraction_from_oc_fraction(f: oc_fractions.Fraction):
    +    return native_fractions.Fraction(f.numerator, f.denominator)
    +
    +
    +@hypothesis.given(denormalized_fractions, denormalized_fractions)
    +def test_add(a: oc_fractions.Fraction, b: oc_fractions.Fraction):
    +    oc_added = oc_fractions.add_fraction(a, b)
    +    oc_normalized = native_fraction_from_oc_fraction(oc_added)
    +    assert oc_normalized == (
    +        native_fraction_from_oc_fraction(a) + native_fraction_from_oc_fraction(b)
    +    ), "Invalid add"
    +
    +
    +@hypothesis.given(denormalized_fractions, denormalized_fractions)
    +def test_sub(a: oc_fractions.Fraction, b: oc_fractions.Fraction):
    +    oc_subbed = oc_fractions.sub_fraction(a, b)
    +    oc_normalized = native_fraction_from_oc_fraction(oc_subbed)
    +    assert oc_normalized == (
    +        native_fraction_from_oc_fraction(a) - native_fraction_from_oc_fraction(b)
    +    ), "Invalid sub"
    +
    +
    +@hypothesis.given(denormalized_fractions)
    +def test_neg(a: oc_fractions.Fraction):
    +    oc_negged = oc_fractions.neg_fraction(a)
    +    oc_normalized = native_fraction_from_oc_fraction(oc_negged)
    +    assert oc_normalized == -native_fraction_from_oc_fraction(a), "Invalid neg"
    +
    +
    +@hypothesis.given(denormalized_fractions, denormalized_fractions)
    +def test_mul(a: oc_fractions.Fraction, b: oc_fractions.Fraction):
    +    oc_mulled = oc_fractions.mul_fraction(a, b)
    +    oc_normalized = native_fraction_from_oc_fraction(oc_mulled)
    +    assert oc_normalized == (
    +        native_fraction_from_oc_fraction(a) * native_fraction_from_oc_fraction(b)
    +    ), "Invalid mul"
    +
    +
    +@hypothesis.given(denormalized_fractions, denormalized_fractions_non_null)
    +def test_div(a: oc_fractions.Fraction, b: oc_fractions.Fraction):
    +    oc_divved = oc_fractions.div_fraction(a, b)
    +    oc_normalized = native_fraction_from_oc_fraction(oc_divved)
    +    assert oc_normalized == (
    +        native_fraction_from_oc_fraction(a) / native_fraction_from_oc_fraction(b)
    +    ), "Invalid div"
    +
    +
    +@hypothesis.given(denormalized_fractions)
    +def test_norm_sign(a: oc_fractions.Fraction):
    +    oc_normed = oc_fractions._norm_signs_fraction(a)
    +    assert oc_normed.denominator > 0, "invalid norm_signs"
    +    oc_normalized = native_fraction_from_oc_fraction(oc_normed)
    +    oc_a_normalized = native_fraction_from_oc_fraction(a)
    +    assert oc_normalized == oc_a_normalized, "invalid norm_signs"
    +
    +
    +@hypothesis.given(denormalized_fractions)
    +@hypothesis.example(oc_fractions.Fraction(0, -1))
    +def test_norm(a: oc_fractions.Fraction):
    +    oc_normed = oc_fractions.norm_fraction(a)
    +    oc_normalized = native_fraction_from_oc_fraction(a)
    +    assert oc_normed.numerator == oc_normalized.numerator, "Invalid norm"
    +    assert oc_normed.denominator == oc_normalized.denominator, "Invalid norm"
    +
    +
    +@hypothesis.given(denormalized_fractions, denormalized_fractions)
    +def test_ge(a: oc_fractions.Fraction, b: oc_fractions.Fraction):
    +    oc_ge = oc_fractions.ge_fraction(a, b)
    +    ge = native_fraction_from_oc_fraction(a) >= native_fraction_from_oc_fraction(b)
    +    assert oc_ge == ge, "Invalid ge"
    +
    +
    +@hypothesis.given(denormalized_fractions, denormalized_fractions)
    +def test_le(a: oc_fractions.Fraction, b: oc_fractions.Fraction):
    +    oc_le = oc_fractions.le_fraction(a, b)
    +    le = native_fraction_from_oc_fraction(a) <= native_fraction_from_oc_fraction(b)
    +    assert oc_le == le, "Invalid le"
    +
    +
    +@hypothesis.given(denormalized_fractions, denormalized_fractions)
    +def test_lt(a: oc_fractions.Fraction, b: oc_fractions.Fraction):
    +    oc_lt = oc_fractions.lt_fraction(a, b)
    +    lt = native_fraction_from_oc_fraction(a) < native_fraction_from_oc_fraction(b)
    +    assert oc_lt == lt, "Invalid lt"
    +
    +
    +@hypothesis.given(denormalized_fractions, denormalized_fractions)
    +def test_gt(a: oc_fractions.Fraction, b: oc_fractions.Fraction):
    +    oc_gt = oc_fractions.gt_fraction(a, b)
    +    gt = native_fraction_from_oc_fraction(a) > native_fraction_from_oc_fraction(b)
    +    assert oc_gt == gt, "Invalid gt"
    +
    +
    +@hypothesis.given(denormalized_fractions, denormalized_fractions)
    +def test_eq(a: oc_fractions.Fraction, b: oc_fractions.Fraction):
    +    oc_eq = oc_fractions.eq_fraction(a, b)
    +    eq = native_fraction_from_oc_fraction(a) == native_fraction_from_oc_fraction(b)
    +    assert oc_eq == eq, "Invalid eq"
    +
    +
    +
    +
    +
    +
    +
    +

    Functions

    +
    +
    +def native_fraction_from_oc_fraction(f: Fraction) +
    +
    +
    +
    + +Expand source code + +
    def native_fraction_from_oc_fraction(f: oc_fractions.Fraction):
    +    return native_fractions.Fraction(f.numerator, f.denominator)
    +
    +
    +
    +def test_add() ‑> None +
    +
    +
    +
    + +Expand source code + +
    @hypothesis.given(denormalized_fractions, denormalized_fractions)
    +def test_add(a: oc_fractions.Fraction, b: oc_fractions.Fraction):
    +    oc_added = oc_fractions.add_fraction(a, b)
    +    oc_normalized = native_fraction_from_oc_fraction(oc_added)
    +    assert oc_normalized == (
    +        native_fraction_from_oc_fraction(a) + native_fraction_from_oc_fraction(b)
    +    ), "Invalid add"
    +
    +
    +
    +def test_div() ‑> None +
    +
    +
    +
    + +Expand source code + +
    @hypothesis.given(denormalized_fractions, denormalized_fractions_non_null)
    +def test_div(a: oc_fractions.Fraction, b: oc_fractions.Fraction):
    +    oc_divved = oc_fractions.div_fraction(a, b)
    +    oc_normalized = native_fraction_from_oc_fraction(oc_divved)
    +    assert oc_normalized == (
    +        native_fraction_from_oc_fraction(a) / native_fraction_from_oc_fraction(b)
    +    ), "Invalid div"
    +
    +
    +
    +def test_eq() ‑> None +
    +
    +
    +
    + +Expand source code + +
    @hypothesis.given(denormalized_fractions, denormalized_fractions)
    +def test_eq(a: oc_fractions.Fraction, b: oc_fractions.Fraction):
    +    oc_eq = oc_fractions.eq_fraction(a, b)
    +    eq = native_fraction_from_oc_fraction(a) == native_fraction_from_oc_fraction(b)
    +    assert oc_eq == eq, "Invalid eq"
    +
    +
    +
    +def test_ge() ‑> None +
    +
    +
    +
    + +Expand source code + +
    @hypothesis.given(denormalized_fractions, denormalized_fractions)
    +def test_ge(a: oc_fractions.Fraction, b: oc_fractions.Fraction):
    +    oc_ge = oc_fractions.ge_fraction(a, b)
    +    ge = native_fraction_from_oc_fraction(a) >= native_fraction_from_oc_fraction(b)
    +    assert oc_ge == ge, "Invalid ge"
    +
    +
    +
    +def test_gt() ‑> None +
    +
    +
    +
    + +Expand source code + +
    @hypothesis.given(denormalized_fractions, denormalized_fractions)
    +def test_gt(a: oc_fractions.Fraction, b: oc_fractions.Fraction):
    +    oc_gt = oc_fractions.gt_fraction(a, b)
    +    gt = native_fraction_from_oc_fraction(a) > native_fraction_from_oc_fraction(b)
    +    assert oc_gt == gt, "Invalid gt"
    +
    +
    +
    +def test_le() ‑> None +
    +
    +
    +
    + +Expand source code + +
    @hypothesis.given(denormalized_fractions, denormalized_fractions)
    +def test_le(a: oc_fractions.Fraction, b: oc_fractions.Fraction):
    +    oc_le = oc_fractions.le_fraction(a, b)
    +    le = native_fraction_from_oc_fraction(a) <= native_fraction_from_oc_fraction(b)
    +    assert oc_le == le, "Invalid le"
    +
    +
    +
    +def test_lt() ‑> None +
    +
    +
    +
    + +Expand source code + +
    @hypothesis.given(denormalized_fractions, denormalized_fractions)
    +def test_lt(a: oc_fractions.Fraction, b: oc_fractions.Fraction):
    +    oc_lt = oc_fractions.lt_fraction(a, b)
    +    lt = native_fraction_from_oc_fraction(a) < native_fraction_from_oc_fraction(b)
    +    assert oc_lt == lt, "Invalid lt"
    +
    +
    +
    +def test_mul() ‑> None +
    +
    +
    +
    + +Expand source code + +
    @hypothesis.given(denormalized_fractions, denormalized_fractions)
    +def test_mul(a: oc_fractions.Fraction, b: oc_fractions.Fraction):
    +    oc_mulled = oc_fractions.mul_fraction(a, b)
    +    oc_normalized = native_fraction_from_oc_fraction(oc_mulled)
    +    assert oc_normalized == (
    +        native_fraction_from_oc_fraction(a) * native_fraction_from_oc_fraction(b)
    +    ), "Invalid mul"
    +
    +
    +
    +def test_neg() ‑> None +
    +
    +
    +
    + +Expand source code + +
    @hypothesis.given(denormalized_fractions)
    +def test_neg(a: oc_fractions.Fraction):
    +    oc_negged = oc_fractions.neg_fraction(a)
    +    oc_normalized = native_fraction_from_oc_fraction(oc_negged)
    +    assert oc_normalized == -native_fraction_from_oc_fraction(a), "Invalid neg"
    +
    +
    +
    +def test_norm() ‑> None +
    +
    +
    +
    + +Expand source code + +
    @hypothesis.given(denormalized_fractions)
    +@hypothesis.example(oc_fractions.Fraction(0, -1))
    +def test_norm(a: oc_fractions.Fraction):
    +    oc_normed = oc_fractions.norm_fraction(a)
    +    oc_normalized = native_fraction_from_oc_fraction(a)
    +    assert oc_normed.numerator == oc_normalized.numerator, "Invalid norm"
    +    assert oc_normed.denominator == oc_normalized.denominator, "Invalid norm"
    +
    +
    +
    +def test_norm_sign() ‑> None +
    +
    +
    +
    + +Expand source code + +
    @hypothesis.given(denormalized_fractions)
    +def test_norm_sign(a: oc_fractions.Fraction):
    +    oc_normed = oc_fractions._norm_signs_fraction(a)
    +    assert oc_normed.denominator > 0, "invalid norm_signs"
    +    oc_normalized = native_fraction_from_oc_fraction(oc_normed)
    +    oc_a_normalized = native_fraction_from_oc_fraction(a)
    +    assert oc_normalized == oc_a_normalized, "invalid norm_signs"
    +
    +
    +
    +def test_sub() ‑> None +
    +
    +
    +
    + +Expand source code + +
    @hypothesis.given(denormalized_fractions, denormalized_fractions)
    +def test_sub(a: oc_fractions.Fraction, b: oc_fractions.Fraction):
    +    oc_subbed = oc_fractions.sub_fraction(a, b)
    +    oc_normalized = native_fraction_from_oc_fraction(oc_subbed)
    +    assert oc_normalized == (
    +        native_fraction_from_oc_fraction(a) - native_fraction_from_oc_fraction(b)
    +    ), "Invalid sub"
    +
    +
    +
    +
    +
    +
    +
    + +
    + + + \ No newline at end of file diff --git a/docs/hebi/tests/test_std/test_math.html b/docs/hebi/tests/test_std/test_math.html new file mode 100644 index 0000000..bca4efe --- /dev/null +++ b/docs/hebi/tests/test_std/test_math.html @@ -0,0 +1,232 @@ + + + + + + + + +hebi.tests.test_std.test_math API documentation + + + + + + + + + + + +
    + + + + +
    +
    +

    Module hebi.tests.test_std.test_math

    +
    +
    +
    + +Expand source code + +
    import hypothesis
    +import hypothesis.strategies as hst
    +
    +from hebi.std import math as oc_math
    +
    +import math
    +
    +pos_int = hst.integers(min_value=0)
    +
    +
    +@hypothesis.given(pos_int, pos_int)
    +def test_gcd(a: int, b: int):
    +    assert oc_math.gcd(a, b) == math.gcd(a, b), "Invalid gcd"
    +
    +
    +@hypothesis.given(hst.integers())
    +def test_sign(a: int):
    +    assert oc_math.sign(a) == math.copysign(1, a), "Invalid sign"
    +
    +
    +@hypothesis.given(hst.binary())
    +def test_unsigned_int_from_bytes_big(b: bytes):
    +    assert oc_math.unsigned_int_from_bytes_big(b) == int.from_bytes(
    +        b, byteorder="big", signed=False
    +    ), "Invalid from bytes"
    +
    +
    +
    +
    +
    +
    +
    +

    Functions

    +
    +
    +def test_gcd() ‑> None +
    +
    +
    +
    + +Expand source code + +
    @hypothesis.given(pos_int, pos_int)
    +def test_gcd(a: int, b: int):
    +    assert oc_math.gcd(a, b) == math.gcd(a, b), "Invalid gcd"
    +
    +
    +
    +def test_sign() ‑> None +
    +
    +
    +
    + +Expand source code + +
    @hypothesis.given(hst.integers())
    +def test_sign(a: int):
    +    assert oc_math.sign(a) == math.copysign(1, a), "Invalid sign"
    +
    +
    +
    +def test_unsigned_int_from_bytes_big() ‑> None +
    +
    +
    +
    + +Expand source code + +
    @hypothesis.given(hst.binary())
    +def test_unsigned_int_from_bytes_big(b: bytes):
    +    assert oc_math.unsigned_int_from_bytes_big(b) == int.from_bytes(
    +        b, byteorder="big", signed=False
    +    ), "Invalid from bytes"
    +
    +
    +
    +
    +
    +
    +
    + +
    + + + \ No newline at end of file diff --git a/docs/hebi/tests/test_stdlib.html b/docs/hebi/tests/test_stdlib.html index dbb58ab..f2ae0b4 100644 --- a/docs/hebi/tests/test_stdlib.html +++ b/docs/hebi/tests/test_stdlib.html @@ -78,6 +78,65 @@

    Module hebi.tests.test_stdlib

    class StdlibTest(unittest.TestCase): + @given(st.data()) + def test_dict_get(self, data): + # this tests that errors that are caused by assignments are actually triggered at the time of assigning + source_code = """ +def validator(x: Dict[int, bytes], y: int, z: bytes) -> bytes: + return x.get(y, z) + """ + ast = compiler.parse(source_code) + code = compiler.compile(ast) + code = code.compile() + f = code.term + + x = data.draw(st.dictionaries(st.integers(), st.binary())) + y = data.draw(st.one_of(st.sampled_from(sorted(x.keys()) + [0]), st.integers())) + z = data.draw(st.binary()) + # UPLC lambdas may only take one argument at a time, so we evaluate by repeatedly applying + for d in [ + uplc.PlutusMap( + {uplc.PlutusInteger(k): uplc.PlutusByteString(v) for k, v in x.items()} + ), + uplc.PlutusInteger(y), + uplc.PlutusByteString(z), + ]: + f = uplc.Apply(f, d) + ret = uplc_eval(f).value + self.assertEqual(ret, x.get(y, z), "dict.get returned wrong value") + + @given(st.data()) + def test_dict_subscript(self, data): + # this tests that errors that are caused by assignments are actually triggered at the time of assigning + source_code = """ +def validator(x: Dict[int, bytes], y: int) -> bytes: + return x[y] + """ + ast = compiler.parse(source_code) + code = compiler.compile(ast) + code = code.compile() + f = code.term + + x = data.draw(st.dictionaries(st.integers(), st.binary())) + y = data.draw(st.one_of(st.sampled_from(sorted(x.keys()) + [0]), st.integers())) + # UPLC lambdas may only take one argument at a time, so we evaluate by repeatedly applying + for d in [ + uplc.PlutusMap( + {uplc.PlutusInteger(k): uplc.PlutusByteString(v) for k, v in x.items()} + ), + uplc.PlutusInteger(y), + ]: + f = uplc.Apply(f, d) + try: + ret = uplc_eval(f).value + except RuntimeError: + ret = None + try: + exp = x[y] + except KeyError: + exp = None + self.assertEqual(ret, exp, "dict[] returned wrong value") + @given(xs=st.dictionaries(st.integers(), st.binary())) def test_dict_keys(self, xs): # this tests that errors that are caused by assignments are actually triggered at the time of assigning @@ -120,6 +179,54 @@

    Module hebi.tests.test_stdlib

    ret = [x.value for x in uplc_eval(f).value] self.assertEqual(ret, list(xs.values()), "dict.keys returned wrong value") + @given(xs=st.dictionaries(st.integers(), st.binary())) + def test_dict_items_keys_sum(self, xs): + # this tests that errors that are caused by assignments are actually triggered at the time of assigning + source_code = """ +def validator(xs: Dict[int, bytes]) -> int: + sum_keys = 0 + for x in xs.items(): + sum_keys += x[0] + return sum_keys +""" + ast = compiler.parse(source_code) + code = compiler.compile(ast) + code = code.compile() + f = code.term + # UPLC lambdas may only take one argument at a time, so we evaluate by repeatedly applying + for d in [ + uplc.PlutusMap( + {uplc.PlutusInteger(k): uplc.PlutusByteString(v) for k, v in xs.items()} + ) + ]: + f = uplc.Apply(f, d) + ret = uplc_eval(f).value + self.assertEqual(ret, sum(xs.keys()), "dict.items returned wrong value") + + @given(xs=st.dictionaries(st.integers(), st.binary())) + def test_dict_items_values_sum(self, xs): + # this tests that errors that are caused by assignments are actually triggered at the time of assigning + source_code = """ +def validator(xs: Dict[int, bytes]) -> bytes: + sum_values = b"" + for x in xs.items(): + sum_values += x[1] + return sum_values +""" + ast = compiler.parse(source_code) + code = compiler.compile(ast) + code = code.compile() + f = code.term + # UPLC lambdas may only take one argument at a time, so we evaluate by repeatedly applying + for d in [ + uplc.PlutusMap( + {uplc.PlutusInteger(k): uplc.PlutusByteString(v) for k, v in xs.items()} + ) + ]: + f = uplc.Apply(f, d) + ret = uplc_eval(f).value + self.assertEqual(ret, b"".join(xs.values()), "dict.items returned wrong value") + @given(xs=st.text()) def test_str_encode(self, xs): # this tests that errors that are caused by assignments are actually triggered at the time of assigning @@ -289,6 +396,65 @@

    Classes

    Expand source code
    class StdlibTest(unittest.TestCase):
    +    @given(st.data())
    +    def test_dict_get(self, data):
    +        # this tests that errors that are caused by assignments are actually triggered at the time of assigning
    +        source_code = """
    +def validator(x: Dict[int, bytes], y: int, z: bytes) -> bytes:
    +    return x.get(y, z)
    +            """
    +        ast = compiler.parse(source_code)
    +        code = compiler.compile(ast)
    +        code = code.compile()
    +        f = code.term
    +
    +        x = data.draw(st.dictionaries(st.integers(), st.binary()))
    +        y = data.draw(st.one_of(st.sampled_from(sorted(x.keys()) + [0]), st.integers()))
    +        z = data.draw(st.binary())
    +        # UPLC lambdas may only take one argument at a time, so we evaluate by repeatedly applying
    +        for d in [
    +            uplc.PlutusMap(
    +                {uplc.PlutusInteger(k): uplc.PlutusByteString(v) for k, v in x.items()}
    +            ),
    +            uplc.PlutusInteger(y),
    +            uplc.PlutusByteString(z),
    +        ]:
    +            f = uplc.Apply(f, d)
    +        ret = uplc_eval(f).value
    +        self.assertEqual(ret, x.get(y, z), "dict.get returned wrong value")
    +
    +    @given(st.data())
    +    def test_dict_subscript(self, data):
    +        # this tests that errors that are caused by assignments are actually triggered at the time of assigning
    +        source_code = """
    +def validator(x: Dict[int, bytes], y: int) -> bytes:
    +    return x[y]
    +            """
    +        ast = compiler.parse(source_code)
    +        code = compiler.compile(ast)
    +        code = code.compile()
    +        f = code.term
    +
    +        x = data.draw(st.dictionaries(st.integers(), st.binary()))
    +        y = data.draw(st.one_of(st.sampled_from(sorted(x.keys()) + [0]), st.integers()))
    +        # UPLC lambdas may only take one argument at a time, so we evaluate by repeatedly applying
    +        for d in [
    +            uplc.PlutusMap(
    +                {uplc.PlutusInteger(k): uplc.PlutusByteString(v) for k, v in x.items()}
    +            ),
    +            uplc.PlutusInteger(y),
    +        ]:
    +            f = uplc.Apply(f, d)
    +        try:
    +            ret = uplc_eval(f).value
    +        except RuntimeError:
    +            ret = None
    +        try:
    +            exp = x[y]
    +        except KeyError:
    +            exp = None
    +        self.assertEqual(ret, exp, "dict[] returned wrong value")
    +
         @given(xs=st.dictionaries(st.integers(), st.binary()))
         def test_dict_keys(self, xs):
             # this tests that errors that are caused by assignments are actually triggered at the time of assigning
    @@ -331,6 +497,54 @@ 

    Classes

    ret = [x.value for x in uplc_eval(f).value] self.assertEqual(ret, list(xs.values()), "dict.keys returned wrong value") + @given(xs=st.dictionaries(st.integers(), st.binary())) + def test_dict_items_keys_sum(self, xs): + # this tests that errors that are caused by assignments are actually triggered at the time of assigning + source_code = """ +def validator(xs: Dict[int, bytes]) -> int: + sum_keys = 0 + for x in xs.items(): + sum_keys += x[0] + return sum_keys +""" + ast = compiler.parse(source_code) + code = compiler.compile(ast) + code = code.compile() + f = code.term + # UPLC lambdas may only take one argument at a time, so we evaluate by repeatedly applying + for d in [ + uplc.PlutusMap( + {uplc.PlutusInteger(k): uplc.PlutusByteString(v) for k, v in xs.items()} + ) + ]: + f = uplc.Apply(f, d) + ret = uplc_eval(f).value + self.assertEqual(ret, sum(xs.keys()), "dict.items returned wrong value") + + @given(xs=st.dictionaries(st.integers(), st.binary())) + def test_dict_items_values_sum(self, xs): + # this tests that errors that are caused by assignments are actually triggered at the time of assigning + source_code = """ +def validator(xs: Dict[int, bytes]) -> bytes: + sum_values = b"" + for x in xs.items(): + sum_values += x[1] + return sum_values +""" + ast = compiler.parse(source_code) + code = compiler.compile(ast) + code = code.compile() + f = code.term + # UPLC lambdas may only take one argument at a time, so we evaluate by repeatedly applying + for d in [ + uplc.PlutusMap( + {uplc.PlutusInteger(k): uplc.PlutusByteString(v) for k, v in xs.items()} + ) + ]: + f = uplc.Apply(f, d) + ret = uplc_eval(f).value + self.assertEqual(ret, b"".join(xs.values()), "dict.items returned wrong value") + @given(xs=st.text()) def test_str_encode(self, xs): # this tests that errors that are caused by assignments are actually triggered at the time of assigning @@ -588,6 +802,111 @@

    Methods

    self.assertEqual(ret, uplc.BuiltinUnit(), "literal None returned wrong value")
    +
    +def test_dict_get(self) ‑> None +
    +
    +
    +
    + +Expand source code + +
        @given(st.data())
    +    def test_dict_get(self, data):
    +        # this tests that errors that are caused by assignments are actually triggered at the time of assigning
    +        source_code = """
    +def validator(x: Dict[int, bytes], y: int, z: bytes) -> bytes:
    +    return x.get(y, z)
    +            """
    +        ast = compiler.parse(source_code)
    +        code = compiler.compile(ast)
    +        code = code.compile()
    +        f = code.term
    +
    +        x = data.draw(st.dictionaries(st.integers(), st.binary()))
    +        y = data.draw(st.one_of(st.sampled_from(sorted(x.keys()) + [0]), st.integers()))
    +        z = data.draw(st.binary())
    +        # UPLC lambdas may only take one argument at a time, so we evaluate by repeatedly applying
    +        for d in [
    +            uplc.PlutusMap(
    +                {uplc.PlutusInteger(k): uplc.PlutusByteString(v) for k, v in x.items()}
    +            ),
    +            uplc.PlutusInteger(y),
    +            uplc.PlutusByteString(z),
    +        ]:
    +            f = uplc.Apply(f, d)
    +        ret = uplc_eval(f).value
    +        self.assertEqual(ret, x.get(y, z), "dict.get returned wrong value")
    +
    +
    +
    +def test_dict_items_keys_sum(self) ‑> None +
    +
    +
    +
    + +Expand source code + +
        @given(xs=st.dictionaries(st.integers(), st.binary()))
    +    def test_dict_items_keys_sum(self, xs):
    +        # this tests that errors that are caused by assignments are actually triggered at the time of assigning
    +        source_code = """
    +def validator(xs: Dict[int, bytes]) -> int:
    +    sum_keys = 0
    +    for x in xs.items():
    +        sum_keys += x[0]
    +    return sum_keys
    +"""
    +        ast = compiler.parse(source_code)
    +        code = compiler.compile(ast)
    +        code = code.compile()
    +        f = code.term
    +        # UPLC lambdas may only take one argument at a time, so we evaluate by repeatedly applying
    +        for d in [
    +            uplc.PlutusMap(
    +                {uplc.PlutusInteger(k): uplc.PlutusByteString(v) for k, v in xs.items()}
    +            )
    +        ]:
    +            f = uplc.Apply(f, d)
    +        ret = uplc_eval(f).value
    +        self.assertEqual(ret, sum(xs.keys()), "dict.items returned wrong value")
    +
    +
    +
    +def test_dict_items_values_sum(self) ‑> None +
    +
    +
    +
    + +Expand source code + +
        @given(xs=st.dictionaries(st.integers(), st.binary()))
    +    def test_dict_items_values_sum(self, xs):
    +        # this tests that errors that are caused by assignments are actually triggered at the time of assigning
    +        source_code = """
    +def validator(xs: Dict[int, bytes]) -> bytes:
    +    sum_values = b""
    +    for x in xs.items():
    +        sum_values += x[1]
    +    return sum_values
    +"""
    +        ast = compiler.parse(source_code)
    +        code = compiler.compile(ast)
    +        code = code.compile()
    +        f = code.term
    +        # UPLC lambdas may only take one argument at a time, so we evaluate by repeatedly applying
    +        for d in [
    +            uplc.PlutusMap(
    +                {uplc.PlutusInteger(k): uplc.PlutusByteString(v) for k, v in xs.items()}
    +            )
    +        ]:
    +            f = uplc.Apply(f, d)
    +        ret = uplc_eval(f).value
    +        self.assertEqual(ret, b"".join(xs.values()), "dict.items returned wrong value")
    +
    +
    def test_dict_keys(self) ‑> None
    @@ -619,6 +938,48 @@

    Methods

    self.assertEqual(ret, list(xs.keys()), "dict.keys returned wrong value")
    +
    +def test_dict_subscript(self) ‑> None +
    +
    +
    +
    + +Expand source code + +
        @given(st.data())
    +    def test_dict_subscript(self, data):
    +        # this tests that errors that are caused by assignments are actually triggered at the time of assigning
    +        source_code = """
    +def validator(x: Dict[int, bytes], y: int) -> bytes:
    +    return x[y]
    +            """
    +        ast = compiler.parse(source_code)
    +        code = compiler.compile(ast)
    +        code = code.compile()
    +        f = code.term
    +
    +        x = data.draw(st.dictionaries(st.integers(), st.binary()))
    +        y = data.draw(st.one_of(st.sampled_from(sorted(x.keys()) + [0]), st.integers()))
    +        # UPLC lambdas may only take one argument at a time, so we evaluate by repeatedly applying
    +        for d in [
    +            uplc.PlutusMap(
    +                {uplc.PlutusInteger(k): uplc.PlutusByteString(v) for k, v in x.items()}
    +            ),
    +            uplc.PlutusInteger(y),
    +        ]:
    +            f = uplc.Apply(f, d)
    +        try:
    +            ret = uplc_eval(f).value
    +        except RuntimeError:
    +            ret = None
    +        try:
    +            exp = x[y]
    +        except KeyError:
    +            exp = None
    +        self.assertEqual(ret, exp, "dict[] returned wrong value")
    +
    +
    def test_dict_values(self) ‑> None
    @@ -790,7 +1151,11 @@

    test_constant_integer
  • test_constant_string
  • test_constant_unit
  • +
  • test_dict_get
  • +
  • test_dict_items_keys_sum
  • +
  • test_dict_items_values_sum
  • test_dict_keys
  • +
  • test_dict_subscript
  • test_dict_values
  • test_str_decode
  • test_str_encode
  • diff --git a/docs/hebi/type_inference.html b/docs/hebi/type_inference.html index bf3ec6e..6b81272 100644 --- a/docs/hebi/type_inference.html +++ b/docs/hebi/type_inference.html @@ -143,7 +143,10 @@

    Module hebi.type_inference

    self.scopes.pop() def set_variable_type(self, name: str, typ: Type, force=False): - if not force and name in self.scopes[-1] and typ != self.scopes[-1][name]: + if not force and name in self.scopes[-1] and self.scopes[-1][name] != typ: + if self.scopes[-1][name] >= typ: + # the specified type is broader, we pass on this + return raise TypeInferenceError( f"Type {self.scopes[-1][name]} of variable {name} in local scope does not match inferred type {typ}" ) @@ -213,9 +216,7 @@

    Module hebi.type_inference

    "Only Union, Dict and List are allowed as Generic types" ) if ann is None: - raise TypeInferenceError( - "Type annotation is missing for a function argument or return value" - ) + return AnyType() raise NotImplementedError(f"Annotation type {ann.__class__} is not supported") def visit_ClassDef(self, node: ClassDef) -> TypedClassDef: @@ -291,9 +292,10 @@

    Module hebi.type_inference

    node.target.id, InstanceType(typed_ass.annotation), force=True ) typed_ass.target = self.visit(node.target) - assert typed_ass.value.typ >= InstanceType( - typed_ass.annotation - ), "Can only downcast to a specialized type" + assert ( + typed_ass.value.typ >= InstanceType(typed_ass.annotation) + or InstanceType(typed_ass.annotation) >= typed_ass.value.typ + ), "Can only cast between related types" return typed_ass def visit_If(self, node: If) -> TypedIf: @@ -507,7 +509,18 @@

    Module hebi.type_inference

    ts.typ = ts.value.typ.typ.typs[ts.slice.value] else: raise TypeInferenceError( - f"Could not infer type of subscript of typ {ts.value.typ.__class__}" + f"Could not infer type of subscript of typ {ts.value.typ.typ.__class__}" + ) + elif isinstance(ts.value.typ.typ, PairType): + if isinstance(ts.slice, Constant) and isinstance(ts.slice.value, int): + ts.typ = ( + ts.value.typ.typ.l_typ + if ts.slice.value == 0 + else ts.value.typ.typ.r_typ + ) + else: + raise TypeInferenceError( + f"Could not infer type of subscript of typ {ts.value.typ.typ.__class__}" ) elif isinstance(ts.value.typ.typ, ListType): ts.typ = ts.value.typ.typ.typ @@ -542,9 +555,16 @@

    Module hebi.type_inference

    ) elif isinstance(ts.value.typ.typ, DictType): # TODO could be implemented with potentially just erroring. It might be desired to avoid this though. - raise TypeInferenceError( - f"Could not infer type of subscript of dict. Use 'get' with a default value instead." - ) + if not isinstance(ts.slice, Slice): + ts.slice = self.visit(node.slice) + assert ( + ts.slice.typ == ts.value.typ.typ.key_typ + ), f"Dict subscript must have dict key type {ts.value.typ.typ.key_typ} but has type {ts.slice.typ}" + ts.typ = ts.value.typ.typ.value_typ + else: + raise TypeInferenceError( + f"Could not infer type of subscript of dict with a slice." + ) else: raise TypeInferenceError( f"Could not infer type of subscript of typ {ts.value.typ.__class__}" @@ -844,7 +864,10 @@

    Classes

    self.scopes.pop() def set_variable_type(self, name: str, typ: Type, force=False): - if not force and name in self.scopes[-1] and typ != self.scopes[-1][name]: + if not force and name in self.scopes[-1] and self.scopes[-1][name] != typ: + if self.scopes[-1][name] >= typ: + # the specified type is broader, we pass on this + return raise TypeInferenceError( f"Type {self.scopes[-1][name]} of variable {name} in local scope does not match inferred type {typ}" ) @@ -914,9 +937,7 @@

    Classes

    "Only Union, Dict and List are allowed as Generic types" ) if ann is None: - raise TypeInferenceError( - "Type annotation is missing for a function argument or return value" - ) + return AnyType() raise NotImplementedError(f"Annotation type {ann.__class__} is not supported") def visit_ClassDef(self, node: ClassDef) -> TypedClassDef: @@ -992,9 +1013,10 @@

    Classes

    node.target.id, InstanceType(typed_ass.annotation), force=True ) typed_ass.target = self.visit(node.target) - assert typed_ass.value.typ >= InstanceType( - typed_ass.annotation - ), "Can only downcast to a specialized type" + assert ( + typed_ass.value.typ >= InstanceType(typed_ass.annotation) + or InstanceType(typed_ass.annotation) >= typed_ass.value.typ + ), "Can only cast between related types" return typed_ass def visit_If(self, node: If) -> TypedIf: @@ -1208,7 +1230,18 @@

    Classes

    ts.typ = ts.value.typ.typ.typs[ts.slice.value] else: raise TypeInferenceError( - f"Could not infer type of subscript of typ {ts.value.typ.__class__}" + f"Could not infer type of subscript of typ {ts.value.typ.typ.__class__}" + ) + elif isinstance(ts.value.typ.typ, PairType): + if isinstance(ts.slice, Constant) and isinstance(ts.slice.value, int): + ts.typ = ( + ts.value.typ.typ.l_typ + if ts.slice.value == 0 + else ts.value.typ.typ.r_typ + ) + else: + raise TypeInferenceError( + f"Could not infer type of subscript of typ {ts.value.typ.typ.__class__}" ) elif isinstance(ts.value.typ.typ, ListType): ts.typ = ts.value.typ.typ.typ @@ -1243,9 +1276,16 @@

    Classes

    ) elif isinstance(ts.value.typ.typ, DictType): # TODO could be implemented with potentially just erroring. It might be desired to avoid this though. - raise TypeInferenceError( - f"Could not infer type of subscript of dict. Use 'get' with a default value instead." - ) + if not isinstance(ts.slice, Slice): + ts.slice = self.visit(node.slice) + assert ( + ts.slice.typ == ts.value.typ.typ.key_typ + ), f"Dict subscript must have dict key type {ts.value.typ.typ.key_typ} but has type {ts.slice.typ}" + ts.typ = ts.value.typ.typ.value_typ + else: + raise TypeInferenceError( + f"Could not infer type of subscript of dict with a slice." + ) else: raise TypeInferenceError( f"Could not infer type of subscript of typ {ts.value.typ.__class__}" @@ -1452,7 +1492,10 @@

    Methods

    Expand source code
    def set_variable_type(self, name: str, typ: Type, force=False):
    -    if not force and name in self.scopes[-1] and typ != self.scopes[-1][name]:
    +    if not force and name in self.scopes[-1] and self.scopes[-1][name] != typ:
    +        if self.scopes[-1][name] >= typ:
    +            # the specified type is broader, we pass on this
    +            return
             raise TypeInferenceError(
                 f"Type {self.scopes[-1][name]} of variable {name} in local scope does not match inferred type {typ}"
             )
    @@ -1532,9 +1575,7 @@ 

    Methods

    "Only Union, Dict and List are allowed as Generic types" ) if ann is None: - raise TypeInferenceError( - "Type annotation is missing for a function argument or return value" - ) + return AnyType() raise NotImplementedError(f"Annotation type {ann.__class__} is not supported")
    @@ -1585,9 +1626,10 @@

    Methods

    node.target.id, InstanceType(typed_ass.annotation), force=True ) typed_ass.target = self.visit(node.target) - assert typed_ass.value.typ >= InstanceType( - typed_ass.annotation - ), "Can only downcast to a specialized type" + assert ( + typed_ass.value.typ >= InstanceType(typed_ass.annotation) + or InstanceType(typed_ass.annotation) >= typed_ass.value.typ + ), "Can only cast between related types" return typed_ass @@ -2152,7 +2194,18 @@

    Methods

    ts.typ = ts.value.typ.typ.typs[ts.slice.value] else: raise TypeInferenceError( - f"Could not infer type of subscript of typ {ts.value.typ.__class__}" + f"Could not infer type of subscript of typ {ts.value.typ.typ.__class__}" + ) + elif isinstance(ts.value.typ.typ, PairType): + if isinstance(ts.slice, Constant) and isinstance(ts.slice.value, int): + ts.typ = ( + ts.value.typ.typ.l_typ + if ts.slice.value == 0 + else ts.value.typ.typ.r_typ + ) + else: + raise TypeInferenceError( + f"Could not infer type of subscript of typ {ts.value.typ.typ.__class__}" ) elif isinstance(ts.value.typ.typ, ListType): ts.typ = ts.value.typ.typ.typ @@ -2187,9 +2240,16 @@

    Methods

    ) elif isinstance(ts.value.typ.typ, DictType): # TODO could be implemented with potentially just erroring. It might be desired to avoid this though. - raise TypeInferenceError( - f"Could not infer type of subscript of dict. Use 'get' with a default value instead." - ) + if not isinstance(ts.slice, Slice): + ts.slice = self.visit(node.slice) + assert ( + ts.slice.typ == ts.value.typ.typ.key_typ + ), f"Dict subscript must have dict key type {ts.value.typ.typ.key_typ} but has type {ts.slice.typ}" + ts.typ = ts.value.typ.typ.value_typ + else: + raise TypeInferenceError( + f"Could not infer type of subscript of dict with a slice." + ) else: raise TypeInferenceError( f"Could not infer type of subscript of typ {ts.value.typ.__class__}" diff --git a/docs/hebi/typed_ast.html b/docs/hebi/typed_ast.html index 7fe6e95..9f0a9da 100644 --- a/docs/hebi/typed_ast.html +++ b/docs/hebi/typed_ast.html @@ -350,6 +350,20 @@

    Module hebi.typed_ast

    ) +@dataclass(frozen=True, unsafe_hash=True) +class PairType(ClassType): + """An internal type representing built-in PlutusData pairs""" + + l_typ: Type + r_typ: Type + + def __ge__(self, other): + return isinstance(other, PairType) and all( + t >= ot + for t, ot in zip((self.l_typ, self.r_typ), (other.l_typ, other.r_typ)) + ) + + @dataclass(frozen=True, unsafe_hash=True) class ListType(ClassType): typ: Type @@ -374,6 +388,15 @@

    Module hebi.typed_ast

    return InstanceType( FunctionType([], InstanceType(ListType(self.value_typ))) ) + if attr == "items": + return InstanceType( + FunctionType( + [], + InstanceType( + ListType(InstanceType(PairType(self.key_typ, self.value_typ))) + ), + ) + ) raise TypeInferenceError( f"Type of attribute '{attr}' is unknown for type Dict." ) @@ -432,6 +455,11 @@

    Module hebi.typed_ast

    empty_list(self.value_typ), ), ) + if attr == "items": + return plt.Lambda( + ["self", "_"], + plt.Var("self"), + ) raise NotImplementedError(f"Attribute '{attr}' of Dict is unknown.") def __ge__(self, other): @@ -1915,6 +1943,7 @@

    Subclasses

  • FunctionType
  • InaccessibleType
  • ListType
  • +
  • PairType
  • PolymorphicFunctionType
  • RecordType
  • TupleType
  • @@ -1999,6 +2028,15 @@

    Methods

    return InstanceType( FunctionType([], InstanceType(ListType(self.value_typ))) ) + if attr == "items": + return InstanceType( + FunctionType( + [], + InstanceType( + ListType(InstanceType(PairType(self.key_typ, self.value_typ))) + ), + ) + ) raise TypeInferenceError( f"Type of attribute '{attr}' is unknown for type Dict." ) @@ -2057,6 +2095,11 @@

    Methods

    empty_list(self.value_typ), ), ) + if attr == "items": + return plt.Lambda( + ["self", "_"], + plt.Var("self"), + ) raise NotImplementedError(f"Attribute '{attr}' of Dict is unknown.") def __ge__(self, other): @@ -2151,6 +2194,11 @@

    Methods

    empty_list(self.value_typ), ), ) + if attr == "items": + return plt.Lambda( + ["self", "_"], + plt.Var("self"), + ) raise NotImplementedError(f"Attribute '{attr}' of Dict is unknown.") @@ -2178,6 +2226,15 @@

    Methods

    return InstanceType( FunctionType([], InstanceType(ListType(self.value_typ))) ) + if attr == "items": + return InstanceType( + FunctionType( + [], + InstanceType( + ListType(InstanceType(PairType(self.key_typ, self.value_typ))) + ), + ) + ) raise TypeInferenceError( f"Type of attribute '{attr}' is unknown for type Dict." ) @@ -3012,6 +3069,98 @@

    Methods

    +
    +class PairType +(l_typ: Type, r_typ: Type) +
    +
    +

    An internal type representing built-in PlutusData pairs

    +
    + +Expand source code + +
    class PairType(ClassType):
    +    """An internal type representing built-in PlutusData pairs"""
    +
    +    l_typ: Type
    +    r_typ: Type
    +
    +    def __ge__(self, other):
    +        return isinstance(other, PairType) and all(
    +            t >= ot
    +            for t, ot in zip((self.l_typ, self.r_typ), (other.l_typ, other.r_typ))
    +        )
    +
    +

    Ancestors

    + +

    Class variables

    +
    +
    var l_typType
    +
    +
    +
    +
    var r_typType
    +
    +
    +
    +
    +

    Methods

    +
    +
    +def attribute(self, attr) ‑> pluthon.pluthon_ast.AST +
    +
    +

    +Inherited from: +ClassType.attribute +

    +

    The attributes of this class. Needs to be a lambda that expects as first argument the object itself

    +
    +
    +def attribute_type(self, attr) ‑> Type +
    +
    +

    +Inherited from: +ClassType.attribute_type +

    +

    The types of the named attributes of this class

    +
    +
    +def cmp(self, op: _ast.cmpop, o: Type) ‑> pluthon.pluthon_ast.AST +
    +
    +

    +Inherited from: +ClassType.cmp +

    +

    The implementation of comparing this type to type o via operator op. Returns a lambda that expects as first argument the object itself and as second …

    +
    +
    +def constr(self) ‑> pluthon.pluthon_ast.AST +
    +
    +

    +Inherited from: +ClassType.constr +

    +

    The constructor for this class

    +
    +
    +def constr_type(self) ‑> InstanceType +
    +
    +

    +Inherited from: +ClassType.constr_type +

    +

    The type of the constructor for this class

    +
    +
    +
    class PolymorphicFunction
    @@ -5881,6 +6030,18 @@

    Lis
  • +

    PairType

    + +
  • +
  • PolymorphicFunction

    • impl_from_args
    • diff --git a/docs/hebi/util.html b/docs/hebi/util.html index 78baff6..ff39b93 100644 --- a/docs/hebi/util.html +++ b/docs/hebi/util.html @@ -69,6 +69,7 @@

      Module hebi.util

      Expand source code
      import ast
      +import pycardano
       from enum import Enum, auto
       
       from .typed_ast import *
      @@ -618,7 +619,15 @@ 

      Module hebi.util

      return uplc.PlutusConstr( j["constructor"], list(map(data_from_json, j["fields"])) ) - raise NotImplementedError(f"Unknown datum representation {j}")
      + raise NotImplementedError(f"Unknown datum representation {j}") + + +def datum_to_cbor(d: pycardano.Datum) -> bytes: + return pycardano.PlutusData.to_cbor(d, encoding="bytes") + + +def datum_to_json(d: pycardano.Datum) -> str: + return pycardano.PlutusData.to_json(d)
  • @@ -653,6 +662,32 @@

    Functions

    raise NotImplementedError(f"Unknown datum representation {j}") +
    +def datum_to_cbor(d: Union[pycardano.plutus.PlutusData, dict, pycardano.serialization.IndefiniteList, int, bytes, pycardano.serialization.RawCBOR, pycardano.plutus.RawPlutusData]) ‑> bytes +
    +
    +
    +
    + +Expand source code + +
    def datum_to_cbor(d: pycardano.Datum) -> bytes:
    +    return pycardano.PlutusData.to_cbor(d, encoding="bytes")
    +
    +
    +
    +def datum_to_json(d: Union[pycardano.plutus.PlutusData, dict, pycardano.serialization.IndefiniteList, int, bytes, pycardano.serialization.RawCBOR, pycardano.plutus.RawPlutusData]) ‑> str +
    +
    +
    +
    + +Expand source code + +
    def datum_to_json(d: pycardano.Datum) -> str:
    +    return pycardano.PlutusData.to_json(d)
    +
    +
    @@ -735,6 +770,7 @@

    Ancestors

    Subclasses

    • UPLCCompiler
    • +
    • OptimizeRemoveDeadconstants
    • OptimizeRemoveDeadvars
    • OptimizeRemovePass
    • OptimizeVarlen
    • @@ -1542,6 +1578,8 @@

      Index

    • Functions

    • Classes

      diff --git a/docs/index.js b/docs/index.js index 0f66a5c..8f50089 100644 --- a/docs/index.js +++ b/docs/index.js @@ -7,14 +7,20 @@ URLS=[ "hebi/tests/test_ops.html", "hebi/tests/test_ledger/index.html", "hebi/tests/test_ledger/test_interval.html", +"hebi/tests/test_ledger/test_api_v2.html", +"hebi/tests/test_std/index.html", +"hebi/tests/test_std/test_math.html", +"hebi/tests/test_std/test_fractions.html", "hebi/tests/test_stdlib.html", "hebi/builder.html", "hebi/ledger/index.html", +"hebi/ledger/api_v2.html", "hebi/ledger/interval.html", "hebi/optimize/index.html", "hebi/optimize/optimize_varlen.html", "hebi/util.html", "hebi/optimize/optimize_remove_pass.html", +"hebi/optimize/optimize_remove_comments.html", "hebi/optimize/optimize_remove_deadvars.html", "hebi/compiler.html", "hebi/rewrite/index.html", @@ -31,6 +37,9 @@ URLS=[ "hebi/rewrite/rewrite_import_hashlib.html", "hebi/rewrite/rewrite_tuple_assign.html", "hebi/rewrite/rewrite_import.html", +"hebi/std/index.html", +"hebi/std/math.html", +"hebi/std/fractions.html", "hebi/type_inference.html", "hebi/prelude.html" ]; @@ -38,7 +47,7 @@ INDEX=[ { "ref":"hebi", "url":0, -"doc":" hebi > You are building what you want. Why not also build how you want? This is an implementation of smart contracts for Cardano which are written in a very strict subset of valid Python. The general philosophy of this project is to write a compiler that ensure the following: If the program compiles then: 1. it is a valid Python program 2. the output running it with python is the same as running it on-chain. > Note this is the sister project of [eopsin](https: github.com/ImperatorLang/eopsin). It uses an even more restricted subset of python (for example no while loops). The benefit is that the resulting code is greatly reduced in size and cpu/memory consumption. Why hebi? - 100% valid Python. Leverage the existing tool stack for Python, syntax highlighting, linting, debugging, unit-testing, [property-based testing](https: hypothesis.readthedocs.io/), [verification](https: github.com/marcoeilers/nagini) - Intuitive. Just like Python. - Functional. Forces you to write elegant, functional code in Python. - Efficient & Secure. Static type inference ensures strict typing and optimized code Eopsin is more comfortable to use than hebi. If you want to start building, write your contract in eopsin first. Then, after everything works to your pleasing, try to port to hebi and enjoy the performance gains. Getting Started OpShin Pioneer Program Check out the [opshin-pioneer-program]( https: github.com/OpShin/opshin-pioneer-program) for a host of educational example contracts, test cases and off-chain code. Example repository Check out the [opshin-starter-kit]( https: github.com/OpShin/opshin-starter-kit) repository for a quick start in setting up a development environment and compiling some sample contracts yourself. You can replace the contracts in your local copy of the repository with code from the examples section here to start exploring different contracts. Developer Community and Questions The eopsin repository contains a discussions page. Feel free to open up a new discussion with questions regarding development using hebi and using certain features. Others may be able to help you and will also benefit from the previously shared questions. Check out the community [here](https: github.com/OpShin/opshin/discussions) You can also chat with other developers [in the welcoming discord community](https: discord.gg/umR3A2g4uw) of OpShin Installation Install Python 3.8, 3.9 or 3.10. Then run python3 -m pip install hebi Writing a Smart Contract A short non-complete introduction in starting to write smart contracts follows. 1. Make sure you understand EUTxOs, Addresses, Validators etc on Cardano. [There is a wonderful crashcourse by @KtorZ](https: aiken-lang.org/fundamentals/eutxo). The contract will work on these concepts 2. Make sure you understand python. hebi works like python and uses python. There are tons of tutorials for python, choose what suits you best. 3. Make sure your contract is valid python and the types check out. Write simple contracts first and run them using hebi eval to get a feeling for how they work. 4. Make sure your contract is valid hebi code. Run hebi compile and look at the compiler erros for guidance along what works and doesn't work and why. 5. Dig into the [ examples ](https: github.com/OpShin/hebi/tree/master/examples) to understand common patterns. Check out the [ prelude ](https: opshin.github.io/hebi/prelude.html) for understanding how the Script Context is structured and how complex datums are defined. 6. Check out the [sample repository](https: github.com/OpShin/eopsin-example) to find a sample setup for developing your own contract. In summary, a smart contract in hebi is defined by the function validator in your contract file. The function validates that a specific value can be spent, minted, burned, withdrawn etc, depending on where it is invoked/used as a credential. If the function fails (i.e. raises an error of any kind such as a KeyError or AssertionError ) the validation is denied, and the funds can not be spent, minted, burned etc. > There is a subtle difference here in comparison to most other Smart Contract languages. > In hebi a validator may return anything (in particular also False ) - as long as it does not fail, the execution is considered valid. > This is more similar to how contracts in Solidity always pass, unless they run out of gas or hit an error. > So make sure to assert what you want to ensure to hold for validation! A simple contract called the \"Gift Contract\" verifies that only specific wallets can withdraw money. They are authenticated by a signature. If you don't understand what a pubkeyhash is and how this validates anything, check out [this gentle introduction into Cardanos EUTxO](https: aiken-lang.org/fundamentals/eutxo). Also see the [tutorial by pycardano ](https: pycardano.readthedocs.io/en/latest/guides/plutus.html) for explanations on what each of the parameters to the validator means and how to build transactions with the contract. from hebi.prelude import @dataclass() class CancelDatum(PlutusData): pubkeyhash: bytes def validator(datum: CancelDatum, redeemer: None, context: ScriptContext) -> None: assert datum.pubkeyhash in context.tx_info.signatories, \"Required signature missing\" All contracts written in hebi are 100% valid python. Minting policies expect only a redeemer and script context as argument. Check out the [Architecture guide](https: github.com/OpShin/hebi/blob/master/ARCHITECTURE.md minting-policy -spending-validator-double-function) for details on how to write double functioning contracts. The [ examples ](https: github.com/OpShin/hebi/blob/master/examples) folder contains more examples. Also check out the [opshin-pioneer-program]( https: github.com/OpShin/opshin-pioneer-program) and [opshin-starter-kit]( https: github.com/OpShin/opshin-starter-kit) repo. Compiling Write your program in python. You may start with the content of examples . Arguments to scripts are passed in as Plutus Data objects in JSON notation. You can run any of the following commands Evaluate script in Python - this can be used to make sure there are no obvious errors hebi eval examples/smart_contracts/assert_sum.py \"{\\\"int\\\": 4}\" \"{\\\"int\\\": 38}\" \"{\\\"constructor\\\": 0, \\\"fields\\\": []}\" Compile script to 'uplc', the Cardano Smart Contract assembly hebi compile examples/smart_contracts/assert_sum.py Deploying The deploy process generates all artifacts required for usage with common libraries like [pycardano](https: github.com/Python-Cardano/pycardano), [lucid](https: github.com/spacebudz/lucid) and the [cardano-cli](https: github.com/input-output-hk/cardano-node). Automatically generate all artifacts needed for using this contract hebi build examples/smart_contracts/assert_sum.py See the [tutorial by pycardano ](https: pycardano.readthedocs.io/en/latest/guides/plutus.html) for explanations how to build transactions with opshin contracts. The small print _Not every valid python program is a valid smart contract_. Not all language features of python will or can be supported. The reasons are mainly of practical nature (i.e. we can't infer types when functions like eval are allowed). Specifically, only a pure subset of python is allowed. Further, only immutable objects may be generated. For your program to be accepted, make sure to only make use of language constructs supported by the compiler. You will be notified of which constructs are not supported when trying to compile. Name Hebi is japanese for \"snake\", which is a play on words on python , the underlying language. Versioning scheme Since this project builds on top of eopsin, it has a particular versioning scheme. The first three numbers indicate the version of hebi (starting at 0.1.0 ). Then follows the latest version number of eopsin which was merged into the project (starting at 0.9.3 ). This is intended to help navigating releases among both packages, where it might be important that a recent eopsin release is integrated that contains a security patch. Contributing Architecture This program consists of a few independent components: 1. An aggressive static type inferencer 2. Rewriting tools to simplify complex python expressions 3. A compiler from a subset of python into UPLC Debugging artefacts For debugging purposes, you can also run Compile script to 'uplc', and evaluate the script in UPLC (for debugging purposes) python3 -m hebi eval_uplc examples/smart_contracts/assert_sum.py \"{\\\"int\\\": 4}\" \"{\\\"int\\\": 38}\" \"{\\\"constructor\\\": 0, \\\"fields\\\": []}\" Compile script to 'pluto', an intermediate language (for debugging purposes) python3 -m hebi compile_pluto examples/smart_contracts/assert_sum.py Sponsoring You can sponsor the development of hebi through GitHub or [Teiki](https: alpha.teiki.network/projects/opshin) or just by sending ADA. Drop me a message on social media and let me know what it is for. - [Teiki](https: alpha.teiki.network/projects/opshin) Stake your ada to support OpShin at [Teiki](https: alpha.teiki.network/projects/opshin) - GitHub Sponsor the developers of this project through the button \"Sponsor\" next to them - ADA Donation in ADA can be submitted to $opshin or addr1qyz3vgd5xxevjy2rvqevz9n7n7dney8n6hqggp23479fm6vwpj9clsvsf85cd4xc59zjztr5zwpummwckmzr2myjwjns74lhmr . Supporters The main sponsor of this project is [Inversion](https: inversion.dev/cardano/). Here is a word from them! > At Inversion, we pride ourselves on our passion for life and our ability to create exceptional software solutions for our clients. Our team of experts, with over a century of cumulative experience, is dedicated to harnessing the power of the Cardano blockchain to bring innovative and scalable decentralized applications to life. We've successfully built applications for NFT management, staking and delegation, chain data monitoring, analytics, and web3 integrations, as well as countless non-blockchain systems. With a focus on security, transparency, and sustainability, our team is excited to contribute to the Cardano ecosystem, pushing the boundaries of decentralized technologies to improve lives worldwide. Trust Inversion to be your go-to partner for robust, effective, and forward-thinking solutions, whether blockchain based, traditional systems, or a mix of the two. They have recently started a podcast, called \"Africa On Chain\", which you can check out here: https: www.youtube.com/@africaonchain" +"doc":" hebi > You are building what you want. Why not also build how you want? This is an implementation of smart contracts for Cardano which are written in a very strict subset of valid Python. The general philosophy of this project is to write a compiler that ensure the following: If the program compiles then: 1. it is a valid Python program 2. the output running it with python is the same as running it on-chain. > Note this is the sister project of [eopsin](https: github.com/ImperatorLang/eopsin). It uses an even more restricted subset of python (for example no while loops). The benefit is that the resulting code is greatly reduced in size and cpu/memory consumption. Why hebi? - 100% valid Python. Leverage the existing tool stack for Python, syntax highlighting, linting, debugging, unit-testing, [property-based testing](https: hypothesis.readthedocs.io/), [verification](https: github.com/marcoeilers/nagini) - Intuitive. Just like Python. - Functional. Forces you to write elegant, functional code in Python. - Efficient & Secure. Static type inference ensures strict typing and optimized code Eopsin is more comfortable to use than hebi. If you want to start building, write your contract in eopsin first. Then, after everything works to your pleasing, try to port to hebi and enjoy the performance gains. Getting Started OpShin Pioneer Program Check out the [opshin-pioneer-program]( https: github.com/OpShin/opshin-pioneer-program) for a host of educational example contracts, test cases and off-chain code. Example repository Check out the [opshin-starter-kit]( https: github.com/OpShin/opshin-starter-kit) repository for a quick start in setting up a development environment and compiling some sample contracts yourself. You can replace the contracts in your local copy of the repository with code from the examples section here to start exploring different contracts. Developer Community and Questions The eopsin repository contains a discussions page. Feel free to open up a new discussion with questions regarding development using hebi and using certain features. Others may be able to help you and will also benefit from the previously shared questions. Check out the community [here](https: github.com/OpShin/opshin/discussions) You can also chat with other developers [in the welcoming discord community](https: discord.gg/umR3A2g4uw) of OpShin Installation Install Python 3.8, 3.9 or 3.10. Then run python3 -m pip install hebi Writing a Smart Contract A short non-complete introduction in starting to write smart contracts follows. 1. Make sure you understand EUTxOs, Addresses, Validators etc on Cardano. [There is a wonderful crashcourse by @KtorZ](https: aiken-lang.org/fundamentals/eutxo). The contract will work on these concepts 2. Make sure you understand python. hebi works like python and uses python. There are tons of tutorials for python, choose what suits you best. 3. Make sure your contract is valid python and the types check out. Write simple contracts first and run them using hebi eval to get a feeling for how they work. 4. Make sure your contract is valid hebi code. Run hebi compile and look at the compiler erros for guidance along what works and doesn't work and why. 5. Dig into the [ examples ](https: github.com/OpShin/hebi/tree/main/examples) to understand common patterns. Check out the [ prelude ](https: hebi.opshin.dev/hebi/prelude.html) for understanding how the Script Context is structured and how complex datums are defined. 6. Check out the [sample repository](https: github.com/OpShin/opshin-starter-kit) to find a sample setup for developing your own contract. In summary, a smart contract in hebi is defined by the function validator in your contract file. The function validates that a specific value can be spent, minted, burned, withdrawn etc, depending on where it is invoked/used as a credential. If the function fails (i.e. raises an error of any kind such as a KeyError or AssertionError ) the validation is denied, and the funds can not be spent, minted, burned etc. > There is a subtle difference here in comparison to most other Smart Contract languages. > In hebi a validator may return anything (in particular also False ) - as long as it does not fail, the execution is considered valid. > This is more similar to how contracts in Solidity always pass, unless they run out of gas or hit an error. > So make sure to assert what you want to ensure to hold for validation! A simple contract called the \"Gift Contract\" verifies that only specific wallets can withdraw money. They are authenticated by a signature. If you don't understand what a pubkeyhash is and how this validates anything, check out [this gentle introduction into Cardanos EUTxO](https: aiken-lang.org/fundamentals/eutxo). Also see the [tutorial by pycardano ](https: pycardano.readthedocs.io/en/latest/guides/plutus.html) for explanations on what each of the parameters to the validator means and how to build transactions with the contract. from hebi.prelude import @dataclass class WithdrawDatum(PlutusData): pubkeyhash: bytes def validator(datum: WithdrawDatum, redeemer: None, context: ScriptContext) -> None: assert datum.pubkeyhash in context.tx_info.signatories, \"Required signature missing\" All contracts written in hebi are 100% valid python. Minting policies expect only a redeemer and script context as argument. Check out the [Architecture guide](https: github.com/OpShin/hebi/blob/main/ARCHITECTURE.md minting-policy -spending-validator-double-function) for details on how to write double functioning contracts. The [ examples ](https: github.com/OpShin/hebi/blob/main/examples) folder contains more examples. Also check out the [opshin-pioneer-program]( https: github.com/OpShin/opshin-pioneer-program) and [opshin-starter-kit]( https: github.com/OpShin/opshin-starter-kit) repo. Compiling Write your program in python. You may start with the content of examples . Arguments to scripts are passed in as Plutus Data objects in JSON notation. You can run any of the following commands Evaluate script in Python - this can be used to make sure there are no obvious errors hebi eval examples/smart_contracts/assert_sum.py \"{\\\"int\\\": 4}\" \"{\\\"int\\\": 38}\" \"{\\\"constructor\\\": 0, \\\"fields\\\": []}\" Compile script to 'uplc', the Cardano Smart Contract assembly hebi compile examples/smart_contracts/assert_sum.py Deploying The deploy process generates all artifacts required for usage with common libraries like [pycardano](https: github.com/Python-Cardano/pycardano), [lucid](https: github.com/spacebudz/lucid) and the [cardano-cli](https: github.com/input-output-hk/cardano-node). Automatically generate all artifacts needed for using this contract hebi build examples/smart_contracts/assert_sum.py See the [tutorial by pycardano ](https: pycardano.readthedocs.io/en/latest/guides/plutus.html) for explanations how to build transactions with opshin contracts. The small print _Not every valid python program is a valid smart contract_. Not all language features of python will or can be supported. The reasons are mainly of practical nature (i.e. we can't infer types when functions like eval are allowed). Specifically, only a pure subset of python is allowed. Further, only immutable objects may be generated. For your program to be accepted, make sure to only make use of language constructs supported by the compiler. You will be notified of which constructs are not supported when trying to compile. Name Hebi is japanese for \"snake\", which is a play on words on python , the underlying language. Versioning scheme Since this project builds on top of eopsin, it has a particular versioning scheme. The first three numbers indicate the version of hebi (starting at 0.1.0 ). Then follows the latest version number of eopsin which was merged into the project (starting at 0.9.3 ). This is intended to help navigating releases among both packages, where it might be important that a recent eopsin release is integrated that contains a security patch. Contributing Architecture This program consists of a few independent components: 1. An aggressive static type inferencer 2. Rewriting tools to simplify complex python expressions 3. A compiler from a subset of python into UPLC Debugging artefacts For debugging purposes, you can also run Compile script to 'uplc', and evaluate the script in UPLC (for debugging purposes) python3 -m hebi eval_uplc examples/smart_contracts/assert_sum.py \"{\\\"int\\\": 4}\" \"{\\\"int\\\": 38}\" \"{\\\"constructor\\\": 0, \\\"fields\\\": []}\" Compile script to 'pluto', an intermediate language (for debugging purposes) python3 -m hebi compile_pluto examples/smart_contracts/assert_sum.py Sponsoring You can sponsor the development of hebi through GitHub or [Teiki](https: alpha.teiki.network/projects/opshin) or just by sending ADA. Drop me a message on social media and let me know what it is for. - [Teiki](https: alpha.teiki.network/projects/opshin) Stake your ada to support OpShin at [Teiki](https: alpha.teiki.network/projects/opshin) - GitHub Sponsor the developers of this project through the button \"Sponsor\" next to them - ADA Donation in ADA can be submitted to $opshin or addr1qyz3vgd5xxevjy2rvqevz9n7n7dney8n6hqggp23479fm6vwpj9clsvsf85cd4xc59zjztr5zwpummwckmzr2myjwjns74lhmr . Supporters The main sponsor of this project is [Inversion](https: inversion.dev/cardano/). Here is a word from them! > At Inversion, we pride ourselves on our passion for life and our ability to create exceptional software solutions for our clients. Our team of experts, with over a century of cumulative experience, is dedicated to harnessing the power of the Cardano blockchain to bring innovative and scalable decentralized applications to life. We've successfully built applications for NFT management, staking and delegation, chain data monitoring, analytics, and web3 integrations, as well as countless non-blockchain systems. With a focus on security, transparency, and sustainability, our team is excited to contribute to the Cardano ecosystem, pushing the boundaries of decentralized technologies to improve lives worldwide. Trust Inversion to be your go-to partner for robust, effective, and forward-thinking solutions, whether blockchain based, traditional systems, or a mix of the two. They have recently started a podcast, called \"Africa On Chain\", which you can check out here: https: www.youtube.com/@africaonchain" }, { "ref":"hebi.typed_ast", @@ -383,6 +392,51 @@ INDEX=[ "func":1 }, { +"ref":"hebi.typed_ast.PairType", +"url":1, +"doc":"An internal type representing built-in PlutusData pairs" +}, +{ +"ref":"hebi.typed_ast.PairType.l_typ", +"url":1, +"doc":"" +}, +{ +"ref":"hebi.typed_ast.PairType.r_typ", +"url":1, +"doc":"" +}, +{ +"ref":"hebi.typed_ast.PairType.constr_type", +"url":1, +"doc":"The type of the constructor for this class", +"func":1 +}, +{ +"ref":"hebi.typed_ast.PairType.constr", +"url":1, +"doc":"The constructor for this class", +"func":1 +}, +{ +"ref":"hebi.typed_ast.PairType.attribute_type", +"url":1, +"doc":"The types of the named attributes of this class", +"func":1 +}, +{ +"ref":"hebi.typed_ast.PairType.attribute", +"url":1, +"doc":"The attributes of this class. Needs to be a lambda that expects as first argument the object itself", +"func":1 +}, +{ +"ref":"hebi.typed_ast.PairType.cmp", +"url":1, +"doc":"The implementation of comparing this type to type o via operator op. Returns a lambda that expects as first argument the object itself and as second the comparison.", +"func":1 +}, +{ "ref":"hebi.typed_ast.ListType", "url":1, "doc":"ListType(typ: hebi.typed_ast.Type)" @@ -1573,29 +1627,6 @@ INDEX=[ "func":1 }, { -"ref":"hebi.tests.test_misc.MiscTest.test_script_context_repr_correct_0_d8799fd8799f9fd8799fd8799fd8799f582055d353acacaab6460b37ed0f0e3a1a0aabf056df4a7fa1e265d21149ccacc527ff01ffd8799fd8799fd87a9f581cdbe769758f26efb21f008dc097bb194cffc622acc37fcefc5372eee3ffd87a80ffa140a1401a00989680d87a9f5820dfab81872ce2bbe6ee5af9bbfee4047f91c1f57db5e30da727d5fef1e7f02f4dffd87a80ffffff809fd8799fd8799fd8799f581cdc315c289fee4484eda07038393f21dc4e572aff292d7926018725c2ffd87a80ffa140a14000d87980d87a80ffffa140a14000a140a1400080a0d8799fd8799fd87980d87a80ffd8799fd87b80d87a80ffff80a1d87a9fd8799fd8799f582055d353acacaab6460b37ed0f0e3a1a0aabf056df4a7fa1e265d21149ccacc527ff01ffffd87980a15820dfab81872ce2bbe6ee5af9bbfee4047f91c1f57db5e30da727d5fef1e7f02f4dd8799f581cdc315c289fee4484eda07038393f21dc4e572aff292d7926018725c2ffd8799f5820746957f0eb57f2b11119684e611a98f373afea93473fefbb7632d579af2f6259ffffd87a9fd8799fd8799f582055d353acacaab6460b37ed0f0e3a1a0aabf056df4a7fa1e265d21149ccacc527ff01ffffff", -"url":4, -"doc":"", -"func":1 -}, -{ -"ref":"hebi.tests.test_misc.MiscTest.test_script_context_repr_correct_1_d8799fd8799f9fd8799fd8799fd8799f582055d353acacaab6460b37ed0f0e3a1a0aabf056df4a7fa1e265d21149ccacc527ff01ffd8799fd8799fd87a9f581cdbe769758f26efb21f008dc097bb194cffc622acc37fcefc5372eee3ffd87a80ffa140a1401a00989680d87a9f5820dfab81872ce2bbe6ee5af9bbfee4047f91c1f57db5e30da727d5fef1e7f02f4dffd87a80ffffff809fd8799fd8799fd8799f581cdc315c289fee4484eda07038393f21dc4e572aff292d7926018725c2ffd87a80ffa140a14000d87980d87a80ffffa140a14000a140a1400080a0d8799fd8799fd87a9f1b000001836ac117d8ffd87a80ffd8799fd87b80d87a80ffff80a1d87a9fd8799fd8799f582055d353acacaab6460b37ed0f0e3a1a0aabf056df4a7fa1e265d21149ccacc527ff01ffffd87980a15820dfab81872ce2bbe6ee5af9bbfee4047f91c1f57db5e30da727d5fef1e7f02f4dd8799f581cdc315c289fee4484eda07038393f21dc4e572aff292d7926018725c2ffd8799f5820797a1e1720b63621c6b185088184cb8e23af6e46b55bd83e7a91024c823a6c2affffd87a9fd8799fd8799f582055d353acacaab6460b37ed0f0e3a1a0aabf056df4a7fa1e265d21149ccacc527ff01ffffff", -"url":4, -"doc":"", -"func":1 -}, -{ -"ref":"hebi.tests.test_misc.MiscTest.test_script_context_repr_correct_2_d8799fd8799f9fd8799fd8799fd8799f582055d353acacaab6460b37ed0f0e3a1a0aabf056df4a7fa1e265d21149ccacc527ff01ffd8799fd8799fd87a9f581cdbe769758f26efb21f008dc097bb194cffc622acc37fcefc5372eee3ffd87a80ffa140a1401a00989680d87a9f5820dfab81872ce2bbe6ee5af9bbfee4047f91c1f57db5e30da727d5fef1e7f02f4dffd87a80ffffff809fd8799fd8799fd8799f581cdc315c289fee4484eda07038393f21dc4e572aff292d7926018725c2ffd87a80ffa140a14000d87980d87a80ffd8799fd8799fd8799f581cdc315c289fee4484eda07038393f21dc4e572aff292d7926018725c2ffd87a80ffa140a1401a000f4240d87980d87a80ffffa140a14000a140a1400080a0d8799fd8799fd87a9f1b000001836ac117d8ffd87a80ffd8799fd87b80d87a80ffff9f581cdc315c289fee4484eda07038393f21dc4e572aff292d7926018725c2ffa1d87a9fd8799fd8799f582055d353acacaab6460b37ed0f0e3a1a0aabf056df4a7fa1e265d21149ccacc527ff01ffffd87980a15820dfab81872ce2bbe6ee5af9bbfee4047f91c1f57db5e30da727d5fef1e7f02f4dd8799f581cdc315c289fee4484eda07038393f21dc4e572aff292d7926018725c2ffd8799f5820c17c32f6433ae22c2acaebfb796bbfaee3993ff7ebb58a2bac6b4a3bdd2f6d28ffffd87a9fd8799fd8799f582055d353acacaab6460b37ed0f0e3a1a0aabf056df4a7fa1e265d21149ccacc527ff01ffffff", -"url":4, -"doc":"", -"func":1 -}, -{ -"ref":"hebi.tests.test_misc.MiscTest.test_script_context_repr_correct", -"url":4, -"doc":"" -}, -{ "ref":"hebi.tests.test_misc.MiscTest.test_gift_contract_succeed", "url":4, "doc":"", @@ -1746,6 +1777,24 @@ INDEX=[ "func":1 }, { +"ref":"hebi.tests.test_misc.MiscTest.test_typecast_int_anything_int", +"url":4, +"doc":"", +"func":1 +}, +{ +"ref":"hebi.tests.test_misc.MiscTest.test_typecast_anything_int_anything", +"url":4, +"doc":"", +"func":1 +}, +{ +"ref":"hebi.tests.test_misc.MiscTest.test_typecast_int_str", +"url":4, +"doc":"", +"func":1 +}, +{ "ref":"hebi.tests.test_misc.MiscTest.test_typecast_int_int", "url":4, "doc":"", @@ -1776,6 +1825,36 @@ INDEX=[ "func":1 }, { +"ref":"hebi.tests.test_misc.MiscTest.test_return_anything", +"url":4, +"doc":"", +"func":1 +}, +{ +"ref":"hebi.tests.test_misc.MiscTest.test_no_return_annotation", +"url":4, +"doc":"", +"func":1 +}, +{ +"ref":"hebi.tests.test_misc.MiscTest.test_no_parameter_annotation", +"url":4, +"doc":"", +"func":1 +}, +{ +"ref":"hebi.tests.test_misc.MiscTest.test_dict_items_values_deconstr", +"url":4, +"doc":"", +"func":1 +}, +{ +"ref":"hebi.tests.test_misc.MiscTest.test_nested_deconstruction", +"url":4, +"doc":"", +"func":1 +}, +{ "ref":"hebi.tests.test_ops", "url":5, "doc":"" @@ -1994,2382 +2073,2729 @@ INDEX=[ "func":1 }, { -"ref":"hebi.tests.test_stdlib", -"url":8, -"doc":"" -}, -{ -"ref":"hebi.tests.test_stdlib.StdlibTest", -"url":8, -"doc":"A class whose instances are single test cases. By default, the test code itself should be placed in a method named 'runTest'. If the fixture may be used for many test cases, create as many test methods as are needed. When instantiating such a TestCase subclass, specify in the constructor arguments the name of the test method that the instance is to execute. Test authors should subclass TestCase for their own tests. Construction and deconstruction of the test's environment ('fixture') can be implemented by overriding the 'setUp' and 'tearDown' methods respectively. If it is necessary to override the __init__ method, the base class __init__ method must always be called. It is important that subclasses should not change the signature of their __init__ method, since instances of the classes are instantiated automatically by parts of the framework in order to be run. When subclassing TestCase, you can set these attributes: failureException: determines which exception will be raised when the instance's assertion methods fail; test methods raising this exception will be deemed to have 'failed' rather than 'errored'. longMessage: determines whether long messages (including repr of objects used in assert methods) will be printed on failure in addition to any explicit message passed. maxDiff: sets the maximum length of a diff in failure messages by assert methods using difflib. It is looked up as an instance attribute so can be configured by individual tests if required. Create an instance of the class that will use the named test method when executed. Raises a ValueError if the instance does not have a method with the specified name." -}, -{ -"ref":"hebi.tests.test_stdlib.StdlibTest.test_dict_keys", -"url":8, -"doc":"", -"func":1 -}, -{ -"ref":"hebi.tests.test_stdlib.StdlibTest.test_dict_values", -"url":8, -"doc":"", -"func":1 -}, -{ -"ref":"hebi.tests.test_stdlib.StdlibTest.test_str_encode", -"url":8, -"doc":"", -"func":1 -}, -{ -"ref":"hebi.tests.test_stdlib.StdlibTest.test_str_decode", -"url":8, +"ref":"hebi.tests.test_ledger.test_interval.test_make_to_in_make_range", +"url":7, "doc":"", "func":1 }, { -"ref":"hebi.tests.test_stdlib.StdlibTest.test_constant_bytestring", -"url":8, +"ref":"hebi.tests.test_ledger.test_interval.test_make_from_in_make_range", +"url":7, "doc":"", "func":1 }, { -"ref":"hebi.tests.test_stdlib.StdlibTest.test_constant_integer", +"ref":"hebi.tests.test_ledger.test_api_v2", "url":8, -"doc":"", -"func":1 +"doc":"" }, { -"ref":"hebi.tests.test_stdlib.StdlibTest.test_constant_string", +"ref":"hebi.tests.test_ledger.test_api_v2.test_script_context_repr_correct_0_d8799fd8799f9fd8799fd8799fd8799f582055d353acacaab6460b37ed0f0e3a1a0aabf056df4a7fa1e265d21149ccacc527ff01ffd8799fd8799fd87a9f581cdbe769758f26efb21f008dc097bb194cffc622acc37fcefc5372eee3ffd87a80ffa140a1401a00989680d87a9f5820dfab81872ce2bbe6ee5af9bbfee4047f91c1f57db5e30da727d5fef1e7f02f4dffd87a80ffffff809fd8799fd8799fd8799f581cdc315c289fee4484eda07038393f21dc4e572aff292d7926018725c2ffd87a80ffa140a14000d87980d87a80ffffa140a14000a140a1400080a0d8799fd8799fd87980d87a80ffd8799fd87b80d87a80ffff80a1d87a9fd8799fd8799f582055d353acacaab6460b37ed0f0e3a1a0aabf056df4a7fa1e265d21149ccacc527ff01ffffd87980a15820dfab81872ce2bbe6ee5af9bbfee4047f91c1f57db5e30da727d5fef1e7f02f4dd8799f581cdc315c289fee4484eda07038393f21dc4e572aff292d7926018725c2ffd8799f5820746957f0eb57f2b11119684e611a98f373afea93473fefbb7632d579af2f6259ffffd87a9fd8799fd8799f582055d353acacaab6460b37ed0f0e3a1a0aabf056df4a7fa1e265d21149ccacc527ff01ffffff", "url":8, "doc":"", "func":1 }, { -"ref":"hebi.tests.test_stdlib.StdlibTest.test_constant_unit", +"ref":"hebi.tests.test_ledger.test_api_v2.test_script_context_repr_correct_1_d8799fd8799f9fd8799fd8799fd8799f582055d353acacaab6460b37ed0f0e3a1a0aabf056df4a7fa1e265d21149ccacc527ff01ffd8799fd8799fd87a9f581cdbe769758f26efb21f008dc097bb194cffc622acc37fcefc5372eee3ffd87a80ffa140a1401a00989680d87a9f5820dfab81872ce2bbe6ee5af9bbfee4047f91c1f57db5e30da727d5fef1e7f02f4dffd87a80ffffff809fd8799fd8799fd8799f581cdc315c289fee4484eda07038393f21dc4e572aff292d7926018725c2ffd87a80ffa140a14000d87980d87a80ffffa140a14000a140a1400080a0d8799fd8799fd87a9f1b000001836ac117d8ffd87a80ffd8799fd87b80d87a80ffff80a1d87a9fd8799fd8799f582055d353acacaab6460b37ed0f0e3a1a0aabf056df4a7fa1e265d21149ccacc527ff01ffffd87980a15820dfab81872ce2bbe6ee5af9bbfee4047f91c1f57db5e30da727d5fef1e7f02f4dd8799f581cdc315c289fee4484eda07038393f21dc4e572aff292d7926018725c2ffd8799f5820797a1e1720b63621c6b185088184cb8e23af6e46b55bd83e7a91024c823a6c2affffd87a9fd8799fd8799f582055d353acacaab6460b37ed0f0e3a1a0aabf056df4a7fa1e265d21149ccacc527ff01ffffff", "url":8, "doc":"", "func":1 }, { -"ref":"hebi.tests.test_stdlib.StdlibTest.test_constant_bool", +"ref":"hebi.tests.test_ledger.test_api_v2.test_script_context_repr_correct_2_d8799fd8799f9fd8799fd8799fd8799f582055d353acacaab6460b37ed0f0e3a1a0aabf056df4a7fa1e265d21149ccacc527ff01ffd8799fd8799fd87a9f581cdbe769758f26efb21f008dc097bb194cffc622acc37fcefc5372eee3ffd87a80ffa140a1401a00989680d87a9f5820dfab81872ce2bbe6ee5af9bbfee4047f91c1f57db5e30da727d5fef1e7f02f4dffd87a80ffffff809fd8799fd8799fd8799f581cdc315c289fee4484eda07038393f21dc4e572aff292d7926018725c2ffd87a80ffa140a14000d87980d87a80ffd8799fd8799fd8799f581cdc315c289fee4484eda07038393f21dc4e572aff292d7926018725c2ffd87a80ffa140a1401a000f4240d87980d87a80ffffa140a14000a140a1400080a0d8799fd8799fd87a9f1b000001836ac117d8ffd87a80ffd8799fd87b80d87a80ffff9f581cdc315c289fee4484eda07038393f21dc4e572aff292d7926018725c2ffa1d87a9fd8799fd8799f582055d353acacaab6460b37ed0f0e3a1a0aabf056df4a7fa1e265d21149ccacc527ff01ffffd87980a15820dfab81872ce2bbe6ee5af9bbfee4047f91c1f57db5e30da727d5fef1e7f02f4dd8799f581cdc315c289fee4484eda07038393f21dc4e572aff292d7926018725c2ffd8799f5820c17c32f6433ae22c2acaebfb796bbfaee3993ff7ebb58a2bac6b4a3bdd2f6d28ffffd87a9fd8799fd8799f582055d353acacaab6460b37ed0f0e3a1a0aabf056df4a7fa1e265d21149ccacc527ff01ffffff", "url":8, "doc":"", "func":1 }, { -"ref":"hebi.builder", +"ref":"hebi.tests.test_std", "url":9, "doc":"" }, { -"ref":"hebi.builder.ScriptArtifacts", -"url":9, -"doc":"ScriptArtifacts(cbor_hex: str, plutus_json: str, mainnet_addr: str, testnet_addr: str, policy_id: str)" -}, -{ -"ref":"hebi.builder.ScriptArtifacts.cbor_hex", -"url":9, +"ref":"hebi.tests.test_std.test_math", +"url":10, "doc":"" }, { -"ref":"hebi.builder.ScriptArtifacts.plutus_json", -"url":9, -"doc":"" +"ref":"hebi.tests.test_std.test_math.test_gcd", +"url":10, +"doc":"", +"func":1 }, { -"ref":"hebi.builder.ScriptArtifacts.mainnet_addr", -"url":9, -"doc":"" +"ref":"hebi.tests.test_std.test_math.test_sign", +"url":10, +"doc":"", +"func":1 }, { -"ref":"hebi.builder.ScriptArtifacts.testnet_addr", -"url":9, -"doc":"" +"ref":"hebi.tests.test_std.test_math.test_unsigned_int_from_bytes_big", +"url":10, +"doc":"", +"func":1 }, { -"ref":"hebi.builder.ScriptArtifacts.policy_id", -"url":9, +"ref":"hebi.tests.test_std.test_fractions", +"url":11, "doc":"" }, { -"ref":"hebi.builder.build", -"url":9, -"doc":"Expects a python module and returns the build artifacts from compiling it", +"ref":"hebi.tests.test_std.test_fractions.native_fraction_from_oc_fraction", +"url":11, +"doc":"", "func":1 }, { -"ref":"hebi.ledger", -"url":10, -"doc":"" +"ref":"hebi.tests.test_std.test_fractions.test_add", +"url":11, +"doc":"", +"func":1 }, { -"ref":"hebi.ledger.interval", +"ref":"hebi.tests.test_std.test_fractions.test_sub", "url":11, -"doc":"" +"doc":"", +"func":1 }, { -"ref":"hebi.ledger.interval.compare", +"ref":"hebi.tests.test_std.test_fractions.test_neg", "url":11, "doc":"", "func":1 }, { -"ref":"hebi.ledger.interval.compare_extended_helper", +"ref":"hebi.tests.test_std.test_fractions.test_mul", "url":11, "doc":"", "func":1 }, { -"ref":"hebi.ledger.interval.compare_extended", +"ref":"hebi.tests.test_std.test_fractions.test_div", "url":11, "doc":"", "func":1 }, { -"ref":"hebi.ledger.interval.get_bool", +"ref":"hebi.tests.test_std.test_fractions.test_norm_sign", "url":11, "doc":"", "func":1 }, { -"ref":"hebi.ledger.interval.compare_upper_bound", +"ref":"hebi.tests.test_std.test_fractions.test_norm", "url":11, "doc":"", "func":1 }, { -"ref":"hebi.ledger.interval.compare_lower_bound", +"ref":"hebi.tests.test_std.test_fractions.test_ge", "url":11, "doc":"", "func":1 }, { -"ref":"hebi.ledger.interval.contains", +"ref":"hebi.tests.test_std.test_fractions.test_le", "url":11, "doc":"", "func":1 }, { -"ref":"hebi.ledger.interval.make_range", +"ref":"hebi.tests.test_std.test_fractions.test_lt", "url":11, "doc":"", "func":1 }, { -"ref":"hebi.ledger.interval.make_from", +"ref":"hebi.tests.test_std.test_fractions.test_gt", "url":11, "doc":"", "func":1 }, { -"ref":"hebi.ledger.interval.make_to", +"ref":"hebi.tests.test_std.test_fractions.test_eq", "url":11, "doc":"", "func":1 }, { -"ref":"hebi.optimize", +"ref":"hebi.tests.test_stdlib", "url":12, "doc":"" }, { -"ref":"hebi.optimize.optimize_varlen", -"url":13, -"doc":"" -}, -{ -"ref":"hebi.optimize.optimize_varlen.NameCollector", -"url":13, -"doc":"A node visitor base class that walks the abstract syntax tree and calls a visitor function for every node found. This function may return a value which is forwarded by the visit method. This class is meant to be subclassed, with the subclass adding visitor methods. Per default the visitor functions for the nodes are 'visit_' + class name of the node. So a TryFinally node visit function would be visit_TryFinally . This behavior can be changed by overriding the visit method. If no visitor function exists for a node (return value None ) the generic_visit visitor is used instead. Don't use the NodeVisitor if you want to apply changes to nodes during traversing. For this a special visitor exists ( NodeTransformer ) that allows modifications." -}, -{ -"ref":"hebi.optimize.optimize_varlen.NameCollector.step", -"url":13, -"doc":"" +"ref":"hebi.tests.test_stdlib.StdlibTest", +"url":12, +"doc":"A class whose instances are single test cases. By default, the test code itself should be placed in a method named 'runTest'. If the fixture may be used for many test cases, create as many test methods as are needed. When instantiating such a TestCase subclass, specify in the constructor arguments the name of the test method that the instance is to execute. Test authors should subclass TestCase for their own tests. Construction and deconstruction of the test's environment ('fixture') can be implemented by overriding the 'setUp' and 'tearDown' methods respectively. If it is necessary to override the __init__ method, the base class __init__ method must always be called. It is important that subclasses should not change the signature of their __init__ method, since instances of the classes are instantiated automatically by parts of the framework in order to be run. When subclassing TestCase, you can set these attributes: failureException: determines which exception will be raised when the instance's assertion methods fail; test methods raising this exception will be deemed to have 'failed' rather than 'errored'. longMessage: determines whether long messages (including repr of objects used in assert methods) will be printed on failure in addition to any explicit message passed. maxDiff: sets the maximum length of a diff in failure messages by assert methods using difflib. It is looked up as an instance attribute so can be configured by individual tests if required. Create an instance of the class that will use the named test method when executed. Raises a ValueError if the instance does not have a method with the specified name." }, { -"ref":"hebi.optimize.optimize_varlen.NameCollector.visit_Name", -"url":13, +"ref":"hebi.tests.test_stdlib.StdlibTest.test_dict_get", +"url":12, "doc":"", "func":1 }, { -"ref":"hebi.optimize.optimize_varlen.NameCollector.visit_ClassDef", -"url":13, +"ref":"hebi.tests.test_stdlib.StdlibTest.test_dict_subscript", +"url":12, "doc":"", "func":1 }, { -"ref":"hebi.optimize.optimize_varlen.NameCollector.visit_FunctionDef", -"url":13, +"ref":"hebi.tests.test_stdlib.StdlibTest.test_dict_keys", +"url":12, "doc":"", "func":1 }, { -"ref":"hebi.optimize.optimize_varlen.NameCollector.visit", -"url":14, -"doc":"Visit a node.", +"ref":"hebi.tests.test_stdlib.StdlibTest.test_dict_values", +"url":12, +"doc":"", "func":1 }, { -"ref":"hebi.optimize.optimize_varlen.bs_from_int", -"url":13, +"ref":"hebi.tests.test_stdlib.StdlibTest.test_dict_items_keys_sum", +"url":12, "doc":"", "func":1 }, { -"ref":"hebi.optimize.optimize_varlen.OptimizeVarlen", -"url":13, -"doc":"A :class: NodeVisitor subclass that walks the abstract syntax tree and allows modification of nodes. The NodeTransformer will walk the AST and use the return value of the visitor methods to replace or remove the old node. If the return value of the visitor method is None , the node will be removed from its location, otherwise it is replaced with the return value. The return value may be the original node in which case no replacement takes place. Here is an example transformer that rewrites all occurrences of name lookups ( foo ) to data['foo'] class RewriteName(NodeTransformer): def visit_Name(self, node): return Subscript( value=Name(id='data', ctx=Load( , slice=Index(value=Str(s=node.id , ctx=node.ctx ) Keep in mind that if the node you're operating on has child nodes you must either transform the child nodes yourself or call the :meth: generic_visit method for the node first. For nodes that were part of a collection of statements (that applies to all statement nodes), the visitor may also return a list of nodes rather than just a single node. Usually you use the transformer like this node = YourTransformer().visit(node)" -}, -{ -"ref":"hebi.optimize.optimize_varlen.OptimizeVarlen.step", -"url":13, -"doc":"" -}, -{ -"ref":"hebi.optimize.optimize_varlen.OptimizeVarlen.varmap", -"url":13, -"doc":"" +"ref":"hebi.tests.test_stdlib.StdlibTest.test_dict_items_values_sum", +"url":12, +"doc":"", +"func":1 }, { -"ref":"hebi.optimize.optimize_varlen.OptimizeVarlen.visit_Module", -"url":13, +"ref":"hebi.tests.test_stdlib.StdlibTest.test_str_encode", +"url":12, "doc":"", "func":1 }, { -"ref":"hebi.optimize.optimize_varlen.OptimizeVarlen.visit_Name", -"url":13, +"ref":"hebi.tests.test_stdlib.StdlibTest.test_str_decode", +"url":12, "doc":"", "func":1 }, { -"ref":"hebi.optimize.optimize_varlen.OptimizeVarlen.visit_ClassDef", -"url":13, +"ref":"hebi.tests.test_stdlib.StdlibTest.test_constant_bytestring", +"url":12, "doc":"", "func":1 }, { -"ref":"hebi.optimize.optimize_varlen.OptimizeVarlen.visit_FunctionDef", +"ref":"hebi.tests.test_stdlib.StdlibTest.test_constant_integer", +"url":12, +"doc":"", +"func":1 +}, +{ +"ref":"hebi.tests.test_stdlib.StdlibTest.test_constant_string", +"url":12, +"doc":"", +"func":1 +}, +{ +"ref":"hebi.tests.test_stdlib.StdlibTest.test_constant_unit", +"url":12, +"doc":"", +"func":1 +}, +{ +"ref":"hebi.tests.test_stdlib.StdlibTest.test_constant_bool", +"url":12, +"doc":"", +"func":1 +}, +{ +"ref":"hebi.builder", +"url":13, +"doc":"" +}, +{ +"ref":"hebi.builder.ScriptArtifacts", +"url":13, +"doc":"ScriptArtifacts(cbor_hex: str, plutus_json: str, mainnet_addr: str, testnet_addr: str, policy_id: str)" +}, +{ +"ref":"hebi.builder.ScriptArtifacts.cbor_hex", +"url":13, +"doc":"" +}, +{ +"ref":"hebi.builder.ScriptArtifacts.plutus_json", +"url":13, +"doc":"" +}, +{ +"ref":"hebi.builder.ScriptArtifacts.mainnet_addr", +"url":13, +"doc":"" +}, +{ +"ref":"hebi.builder.ScriptArtifacts.testnet_addr", +"url":13, +"doc":"" +}, +{ +"ref":"hebi.builder.ScriptArtifacts.policy_id", +"url":13, +"doc":"" +}, +{ +"ref":"hebi.builder.build", +"url":13, +"doc":"Expects a python module and returns the build artifacts from compiling it", +"func":1 +}, +{ +"ref":"hebi.builder.generate_artifacts", "url":13, "doc":"", "func":1 }, { -"ref":"hebi.optimize.optimize_varlen.OptimizeVarlen.visit", +"ref":"hebi.ledger", "url":14, -"doc":"Visit a node.", -"func":1 +"doc":"" }, { -"ref":"hebi.optimize.optimize_remove_pass", +"ref":"hebi.ledger.api_v2", +"url":15, +"doc":"The PlutusV2 ledger API" +}, +{ +"ref":"hebi.ledger.api_v2.TxId", +"url":15, +"doc":"A transaction id, a 64 bytes long hash of the transaction body (also called transaction hash). Example value: TxId(bytes.fromhex(\"842a4d37b036da6ab3c04331240e67d81746beb44f23ad79703e026705361956\" " +}, +{ +"ref":"hebi.ledger.api_v2.TxId.tx_id", "url":15, "doc":"" }, { -"ref":"hebi.optimize.optimize_remove_pass.OptimizeRemovePass", +"ref":"hebi.ledger.api_v2.Nothing", "url":15, -"doc":"A :class: NodeVisitor subclass that walks the abstract syntax tree and allows modification of nodes. The NodeTransformer will walk the AST and use the return value of the visitor methods to replace or remove the old node. If the return value of the visitor method is None , the node will be removed from its location, otherwise it is replaced with the return value. The return value may be the original node in which case no replacement takes place. Here is an example transformer that rewrites all occurrences of name lookups ( foo ) to data['foo'] class RewriteName(NodeTransformer): def visit_Name(self, node): return Subscript( value=Name(id='data', ctx=Load( , slice=Index(value=Str(s=node.id , ctx=node.ctx ) Keep in mind that if the node you're operating on has child nodes you must either transform the child nodes yourself or call the :meth: generic_visit method for the node first. For nodes that were part of a collection of statements (that applies to all statement nodes), the visitor may also return a list of nodes rather than just a single node. Usually you use the transformer like this node = YourTransformer().visit(node)" +"doc":"Nothing, can be used to signify non-importance of a parameter to a function Example value: Nothing()" }, { -"ref":"hebi.optimize.optimize_remove_pass.OptimizeRemovePass.step", +"ref":"hebi.ledger.api_v2.Nothing.CONSTR_ID", "url":15, "doc":"" }, { -"ref":"hebi.optimize.optimize_remove_pass.OptimizeRemovePass.visit_Pass", +"ref":"hebi.ledger.api_v2.TrueData", "url":15, -"doc":"", -"func":1 +"doc":"A Datum that represents True in Haskell implementations. It is thus used as an encoding for True in the ScriptContext. Example value: TrueData()" }, { -"ref":"hebi.optimize.optimize_remove_pass.OptimizeRemovePass.visit", -"url":14, -"doc":"Visit a node.", -"func":1 +"ref":"hebi.ledger.api_v2.TrueData.CONSTR_ID", +"url":15, +"doc":"" }, { -"ref":"hebi.optimize.optimize_remove_deadvars", -"url":16, +"ref":"hebi.ledger.api_v2.FalseData", +"url":15, +"doc":"A Datum that represents False in Haskell implementations. It is thus used as an encoding for False in the ScriptContext. Example value: FalseData()" +}, +{ +"ref":"hebi.ledger.api_v2.FalseData.CONSTR_ID", +"url":15, "doc":"" }, { -"ref":"hebi.optimize.optimize_remove_deadvars.NameLoadCollector", -"url":16, -"doc":"A node visitor base class that walks the abstract syntax tree and calls a visitor function for every node found. This function may return a value which is forwarded by the visit method. This class is meant to be subclassed, with the subclass adding visitor methods. Per default the visitor functions for the nodes are 'visit_' + class name of the node. So a TryFinally node visit function would be visit_TryFinally . This behavior can be changed by overriding the visit method. If no visitor function exists for a node (return value None ) the generic_visit visitor is used instead. Don't use the NodeVisitor if you want to apply changes to nodes during traversing. For this a special visitor exists ( NodeTransformer ) that allows modifications." +"ref":"hebi.ledger.api_v2.TxOutRef", +"url":15, +"doc":"A reference to a transaction output (hash/id + index)" }, { -"ref":"hebi.optimize.optimize_remove_deadvars.NameLoadCollector.step", -"url":16, +"ref":"hebi.ledger.api_v2.TxOutRef.id", +"url":15, "doc":"" }, { -"ref":"hebi.optimize.optimize_remove_deadvars.NameLoadCollector.visit_Name", -"url":16, -"doc":"", -"func":1 +"ref":"hebi.ledger.api_v2.TxOutRef.idx", +"url":15, +"doc":"" }, { -"ref":"hebi.optimize.optimize_remove_deadvars.NameLoadCollector.visit_ClassDef", -"url":16, -"doc":"", -"func":1 +"ref":"hebi.ledger.api_v2.PubKeyCredential", +"url":15, +"doc":"Part of an address that is authenticated by a public key hash Example value: PubKeyCredential(bytes.fromhex(\"c06ddaad12fc4ded18e56feac72957c1aa75fce6096b40e63ec88274\" " }, { -"ref":"hebi.optimize.optimize_remove_deadvars.NameLoadCollector.visit_FunctionDef", -"url":16, -"doc":"", -"func":1 +"ref":"hebi.ledger.api_v2.PubKeyCredential.credential_hash", +"url":15, +"doc":"" }, { -"ref":"hebi.optimize.optimize_remove_deadvars.NameLoadCollector.visit", -"url":14, -"doc":"Visit a node.", -"func":1 +"ref":"hebi.ledger.api_v2.PubKeyCredential.CONSTR_ID", +"url":15, +"doc":"" }, { -"ref":"hebi.optimize.optimize_remove_deadvars.SafeOperationVisitor", -"url":16, -"doc":"A node visitor base class that walks the abstract syntax tree and calls a visitor function for every node found. This function may return a value which is forwarded by the visit method. This class is meant to be subclassed, with the subclass adding visitor methods. Per default the visitor functions for the nodes are 'visit_' + class name of the node. So a TryFinally node visit function would be visit_TryFinally . This behavior can be changed by overriding the visit method. If no visitor function exists for a node (return value None ) the generic_visit visitor is used instead. Don't use the NodeVisitor if you want to apply changes to nodes during traversing. For this a special visitor exists ( NodeTransformer ) that allows modifications." +"ref":"hebi.ledger.api_v2.ScriptCredential", +"url":15, +"doc":"Part of an address that is authenticated by a smart cotnract Example value: ScriptCredential(bytes.fromhex(\"c06ddaad12fc4ded18e56feac72957c1aa75fce6096b40e63ec88274\" " }, { -"ref":"hebi.optimize.optimize_remove_deadvars.SafeOperationVisitor.step", -"url":16, +"ref":"hebi.ledger.api_v2.ScriptCredential.credential_hash", +"url":15, "doc":"" }, { -"ref":"hebi.optimize.optimize_remove_deadvars.SafeOperationVisitor.generic_visit", -"url":16, -"doc":"Called if no explicit visitor function exists for a node.", -"func":1 +"ref":"hebi.ledger.api_v2.ScriptCredential.CONSTR_ID", +"url":15, +"doc":"" }, { -"ref":"hebi.optimize.optimize_remove_deadvars.SafeOperationVisitor.visit_Lambda", -"url":16, -"doc":"", -"func":1 +"ref":"hebi.ledger.api_v2.StakingHash", +"url":15, +"doc":"Indicates that the stake of this address is controlled by the associated credential" }, { -"ref":"hebi.optimize.optimize_remove_deadvars.SafeOperationVisitor.visit_Constant", -"url":16, -"doc":"", -"func":1 +"ref":"hebi.ledger.api_v2.StakingHash.value", +"url":15, +"doc":"" }, { -"ref":"hebi.optimize.optimize_remove_deadvars.SafeOperationVisitor.visit_RawPlutoExpr", -"url":16, -"doc":"", -"func":1 +"ref":"hebi.ledger.api_v2.StakingHash.CONSTR_ID", +"url":15, +"doc":"" }, { -"ref":"hebi.optimize.optimize_remove_deadvars.SafeOperationVisitor.visit_Name", -"url":16, -"doc":"", -"func":1 +"ref":"hebi.ledger.api_v2.StakingPtr", +"url":15, +"doc":"Indicates that the stake of this address is controlled by the associated pointer. In an address, a chain pointer refers to a point of the chain containing a stake key registration certificate. A point is identified by the 3 coordinates in this object." }, { -"ref":"hebi.optimize.optimize_remove_deadvars.SafeOperationVisitor.visit", -"url":14, -"doc":"Visit a node.", -"func":1 +"ref":"hebi.ledger.api_v2.StakingPtr.slot_no", +"url":15, +"doc":"" +}, +{ +"ref":"hebi.ledger.api_v2.StakingPtr.tx_index", +"url":15, +"doc":"" +}, +{ +"ref":"hebi.ledger.api_v2.StakingPtr.cert_index", +"url":15, +"doc":"" +}, +{ +"ref":"hebi.ledger.api_v2.StakingPtr.CONSTR_ID", +"url":15, +"doc":"" +}, +{ +"ref":"hebi.ledger.api_v2.NoStakingCredential", +"url":15, +"doc":"Indicates that this address has no staking credentials. Its funds can not be delegated." +}, +{ +"ref":"hebi.ledger.api_v2.NoStakingCredential.CONSTR_ID", +"url":15, +"doc":"" +}, +{ +"ref":"hebi.ledger.api_v2.SomeStakingCredential", +"url":15, +"doc":"Indicates that this address has staking credentials. Its funds can be delegated by the credentialed user." +}, +{ +"ref":"hebi.ledger.api_v2.SomeStakingCredential.staking_credential", +"url":15, +"doc":"" +}, +{ +"ref":"hebi.ledger.api_v2.SomeStakingCredential.CONSTR_ID", +"url":15, +"doc":"" +}, +{ +"ref":"hebi.ledger.api_v2.Address", +"url":15, +"doc":"A Shelley address, consisting of a payment and staking credential" +}, +{ +"ref":"hebi.ledger.api_v2.Address.payment_credential", +"url":15, +"doc":"" +}, +{ +"ref":"hebi.ledger.api_v2.Address.staking_credential", +"url":15, +"doc":"" +}, +{ +"ref":"hebi.ledger.api_v2.SomeDatumHash", +"url":15, +"doc":"Indicates that there is a datum associated with this output, which has the given hash." +}, +{ +"ref":"hebi.ledger.api_v2.SomeDatumHash.datum_hash", +"url":15, +"doc":"" +}, +{ +"ref":"hebi.ledger.api_v2.SomeDatumHash.CONSTR_ID", +"url":15, +"doc":"" +}, +{ +"ref":"hebi.ledger.api_v2.SomeScriptHash", +"url":15, +"doc":"Indicates that there is a script associated with this output, which has the given hash." +}, +{ +"ref":"hebi.ledger.api_v2.SomeScriptHash.script_hash", +"url":15, +"doc":"" +}, +{ +"ref":"hebi.ledger.api_v2.SomeScriptHash.CONSTR_ID", +"url":15, +"doc":"" +}, +{ +"ref":"hebi.ledger.api_v2.NoOutputDatum", +"url":15, +"doc":"Indicates that there is no datum associated with an output" +}, +{ +"ref":"hebi.ledger.api_v2.NoOutputDatum.CONSTR_ID", +"url":15, +"doc":"" +}, +{ +"ref":"hebi.ledger.api_v2.SomeOutputDatumHash", +"url":15, +"doc":"Indicates that there is an datum associated with an output, which has the attached hash" +}, +{ +"ref":"hebi.ledger.api_v2.SomeOutputDatumHash.datum_hash", +"url":15, +"doc":"" +}, +{ +"ref":"hebi.ledger.api_v2.SomeOutputDatumHash.CONSTR_ID", +"url":15, +"doc":"" +}, +{ +"ref":"hebi.ledger.api_v2.SomeOutputDatum", +"url":15, +"doc":"Indicates that there is an datum associated with an output, which is inlined and equal to the attached datum" +}, +{ +"ref":"hebi.ledger.api_v2.SomeOutputDatum.datum", +"url":15, +"doc":"" +}, +{ +"ref":"hebi.ledger.api_v2.SomeOutputDatum.CONSTR_ID", +"url":15, +"doc":"" +}, +{ +"ref":"hebi.ledger.api_v2.NoScriptHash", +"url":15, +"doc":"Indicates that there is no script associated with an output" +}, +{ +"ref":"hebi.ledger.api_v2.NoScriptHash.CONSTR_ID", +"url":15, +"doc":"" +}, +{ +"ref":"hebi.ledger.api_v2.TxOut", +"url":15, +"doc":"The plutus representation of an transaction output, consisting of - address: address owning this output - value: tokens associated with this output - datum: datum associated with this output - reference_script: reference script associated with this output" +}, +{ +"ref":"hebi.ledger.api_v2.TxOut.address", +"url":15, +"doc":"" +}, +{ +"ref":"hebi.ledger.api_v2.TxOut.value", +"url":15, +"doc":"" +}, +{ +"ref":"hebi.ledger.api_v2.TxOut.datum", +"url":15, +"doc":"" +}, +{ +"ref":"hebi.ledger.api_v2.TxOut.reference_script", +"url":15, +"doc":"" +}, +{ +"ref":"hebi.ledger.api_v2.TxInInfo", +"url":15, +"doc":"The plutus representation of an transaction output, that is consumed by the transaction." +}, +{ +"ref":"hebi.ledger.api_v2.TxInInfo.out_ref", +"url":15, +"doc":"" +}, +{ +"ref":"hebi.ledger.api_v2.TxInInfo.resolved", +"url":15, +"doc":"" +}, +{ +"ref":"hebi.ledger.api_v2.DCertDelegRegKey", +"url":15, +"doc":"DCertDelegRegKey(value: Union[hebi.ledger.api_v2.StakingHash, hebi.ledger.api_v2.StakingPtr])" +}, +{ +"ref":"hebi.ledger.api_v2.DCertDelegRegKey.value", +"url":15, +"doc":"" +}, +{ +"ref":"hebi.ledger.api_v2.DCertDelegRegKey.CONSTR_ID", +"url":15, +"doc":"" +}, +{ +"ref":"hebi.ledger.api_v2.DCertDelegDeRegKey", +"url":15, +"doc":"DCertDelegDeRegKey(value: Union[hebi.ledger.api_v2.StakingHash, hebi.ledger.api_v2.StakingPtr])" +}, +{ +"ref":"hebi.ledger.api_v2.DCertDelegDeRegKey.value", +"url":15, +"doc":"" +}, +{ +"ref":"hebi.ledger.api_v2.DCertDelegDeRegKey.CONSTR_ID", +"url":15, +"doc":"" +}, +{ +"ref":"hebi.ledger.api_v2.DCertDelegDelegate", +"url":15, +"doc":"DCertDelegDelegate(delegator: Union[hebi.ledger.api_v2.StakingHash, hebi.ledger.api_v2.StakingPtr], delegatee: bytes)" +}, +{ +"ref":"hebi.ledger.api_v2.DCertDelegDelegate.delegator", +"url":15, +"doc":"" +}, +{ +"ref":"hebi.ledger.api_v2.DCertDelegDelegate.delegatee", +"url":15, +"doc":"" +}, +{ +"ref":"hebi.ledger.api_v2.DCertDelegDelegate.CONSTR_ID", +"url":15, +"doc":"" +}, +{ +"ref":"hebi.ledger.api_v2.DCertPoolRegister", +"url":15, +"doc":"DCertPoolRegister(pool_id: bytes, pool_vfr: bytes)" +}, +{ +"ref":"hebi.ledger.api_v2.DCertPoolRegister.pool_id", +"url":15, +"doc":"" +}, +{ +"ref":"hebi.ledger.api_v2.DCertPoolRegister.pool_vfr", +"url":15, +"doc":"" +}, +{ +"ref":"hebi.ledger.api_v2.DCertPoolRegister.CONSTR_ID", +"url":15, +"doc":"" +}, +{ +"ref":"hebi.ledger.api_v2.DCertPoolRetire", +"url":15, +"doc":"DCertPoolRetire(retirement_certificate: bytes, epoch: int)" +}, +{ +"ref":"hebi.ledger.api_v2.DCertPoolRetire.retirement_certificate", +"url":15, +"doc":"" +}, +{ +"ref":"hebi.ledger.api_v2.DCertPoolRetire.epoch", +"url":15, +"doc":"" +}, +{ +"ref":"hebi.ledger.api_v2.DCertPoolRetire.CONSTR_ID", +"url":15, +"doc":"" +}, +{ +"ref":"hebi.ledger.api_v2.DCertGenesis", +"url":15, +"doc":"DCertGenesis()" +}, +{ +"ref":"hebi.ledger.api_v2.DCertGenesis.CONSTR_ID", +"url":15, +"doc":"" +}, +{ +"ref":"hebi.ledger.api_v2.DCertMir", +"url":15, +"doc":"DCertMir()" +}, +{ +"ref":"hebi.ledger.api_v2.DCertMir.CONSTR_ID", +"url":15, +"doc":"" +}, +{ +"ref":"hebi.ledger.api_v2.NegInfPOSIXTime", +"url":15, +"doc":"Negative infinite POSIX time, used to indicate that there is no lower bound for the execution of this transaction" +}, +{ +"ref":"hebi.ledger.api_v2.NegInfPOSIXTime.CONSTR_ID", +"url":15, +"doc":"" +}, +{ +"ref":"hebi.ledger.api_v2.FinitePOSIXTime", +"url":15, +"doc":"Finite POSIX time, used to indicate that there is a lower or upper bound for the execution of this transaction" +}, +{ +"ref":"hebi.ledger.api_v2.FinitePOSIXTime.time", +"url":15, +"doc":"" +}, +{ +"ref":"hebi.ledger.api_v2.FinitePOSIXTime.CONSTR_ID", +"url":15, +"doc":"" +}, +{ +"ref":"hebi.ledger.api_v2.PosInfPOSIXTime", +"url":15, +"doc":"Infinite POSIX time, used to indicate that there is no upper bound for the execution of this transaction" }, { -"ref":"hebi.optimize.optimize_remove_deadvars.OptimizeRemoveDeadvars", -"url":16, -"doc":"A :class: NodeVisitor subclass that walks the abstract syntax tree and allows modification of nodes. The NodeTransformer will walk the AST and use the return value of the visitor methods to replace or remove the old node. If the return value of the visitor method is None , the node will be removed from its location, otherwise it is replaced with the return value. The return value may be the original node in which case no replacement takes place. Here is an example transformer that rewrites all occurrences of name lookups ( foo ) to data['foo'] class RewriteName(NodeTransformer): def visit_Name(self, node): return Subscript( value=Name(id='data', ctx=Load( , slice=Index(value=Str(s=node.id , ctx=node.ctx ) Keep in mind that if the node you're operating on has child nodes you must either transform the child nodes yourself or call the :meth: generic_visit method for the node first. For nodes that were part of a collection of statements (that applies to all statement nodes), the visitor may also return a list of nodes rather than just a single node. Usually you use the transformer like this node = YourTransformer().visit(node)" +"ref":"hebi.ledger.api_v2.PosInfPOSIXTime.CONSTR_ID", +"url":15, +"doc":"" }, { -"ref":"hebi.optimize.optimize_remove_deadvars.OptimizeRemoveDeadvars.step", -"url":16, -"doc":"" +"ref":"hebi.ledger.api_v2.UpperBoundPOSIXTime", +"url":15, +"doc":"Upper bound for the execution of this transaction" }, { -"ref":"hebi.optimize.optimize_remove_deadvars.OptimizeRemoveDeadvars.loaded_vars", -"url":16, +"ref":"hebi.ledger.api_v2.UpperBoundPOSIXTime.limit", +"url":15, "doc":"" }, { -"ref":"hebi.optimize.optimize_remove_deadvars.OptimizeRemoveDeadvars.guaranteed_avail_names", -"url":16, +"ref":"hebi.ledger.api_v2.UpperBoundPOSIXTime.closed", +"url":15, "doc":"" }, { -"ref":"hebi.optimize.optimize_remove_deadvars.OptimizeRemoveDeadvars.guaranteed", -"url":16, -"doc":"", -"func":1 +"ref":"hebi.ledger.api_v2.UpperBoundPOSIXTime.CONSTR_ID", +"url":15, +"doc":"" }, { -"ref":"hebi.optimize.optimize_remove_deadvars.OptimizeRemoveDeadvars.enter_scope", -"url":16, -"doc":"", -"func":1 +"ref":"hebi.ledger.api_v2.LowerBoundPOSIXTime", +"url":15, +"doc":"Lower bound for the execution of this transaction" }, { -"ref":"hebi.optimize.optimize_remove_deadvars.OptimizeRemoveDeadvars.exit_scope", -"url":16, -"doc":"", -"func":1 +"ref":"hebi.ledger.api_v2.LowerBoundPOSIXTime.limit", +"url":15, +"doc":"" }, { -"ref":"hebi.optimize.optimize_remove_deadvars.OptimizeRemoveDeadvars.set_guaranteed", -"url":16, -"doc":"", -"func":1 +"ref":"hebi.ledger.api_v2.LowerBoundPOSIXTime.closed", +"url":15, +"doc":"" }, { -"ref":"hebi.optimize.optimize_remove_deadvars.OptimizeRemoveDeadvars.visit_Module", -"url":16, -"doc":"", -"func":1 +"ref":"hebi.ledger.api_v2.LowerBoundPOSIXTime.CONSTR_ID", +"url":15, +"doc":"" }, { -"ref":"hebi.optimize.optimize_remove_deadvars.OptimizeRemoveDeadvars.visit_If", -"url":16, -"doc":"", -"func":1 +"ref":"hebi.ledger.api_v2.POSIXTimeRange", +"url":15, +"doc":"Time range in which this transaction can be executed" }, { -"ref":"hebi.optimize.optimize_remove_deadvars.OptimizeRemoveDeadvars.visit_While", -"url":16, -"doc":"", -"func":1 +"ref":"hebi.ledger.api_v2.POSIXTimeRange.lower_bound", +"url":15, +"doc":"" }, { -"ref":"hebi.optimize.optimize_remove_deadvars.OptimizeRemoveDeadvars.visit_For", -"url":16, -"doc":"", -"func":1 +"ref":"hebi.ledger.api_v2.POSIXTimeRange.upper_bound", +"url":15, +"doc":"" }, { -"ref":"hebi.optimize.optimize_remove_deadvars.OptimizeRemoveDeadvars.visit_Assign", -"url":16, -"doc":"", -"func":1 +"ref":"hebi.ledger.api_v2.Minting", +"url":15, +"doc":"Script purpose indicating that the given policy id is being minted or burned" }, { -"ref":"hebi.optimize.optimize_remove_deadvars.OptimizeRemoveDeadvars.visit_AnnAssign", -"url":16, -"doc":"", -"func":1 +"ref":"hebi.ledger.api_v2.Minting.policy_id", +"url":15, +"doc":"" }, { -"ref":"hebi.optimize.optimize_remove_deadvars.OptimizeRemoveDeadvars.visit_ClassDef", -"url":16, -"doc":"", -"func":1 +"ref":"hebi.ledger.api_v2.Minting.CONSTR_ID", +"url":15, +"doc":"" }, { -"ref":"hebi.optimize.optimize_remove_deadvars.OptimizeRemoveDeadvars.visit_FunctionDef", -"url":16, -"doc":"", -"func":1 +"ref":"hebi.ledger.api_v2.Spending", +"url":15, +"doc":"Script purpose indicating that the given transaction output is being spent, which is owned by the invoked contract" }, { -"ref":"hebi.optimize.optimize_remove_deadvars.OptimizeRemoveDeadvars.visit", -"url":14, -"doc":"Visit a node.", -"func":1 +"ref":"hebi.ledger.api_v2.Spending.tx_out_ref", +"url":15, +"doc":"" }, { -"ref":"hebi.compiler", -"url":17, +"ref":"hebi.ledger.api_v2.Spending.CONSTR_ID", +"url":15, "doc":"" }, { -"ref":"hebi.compiler.wrap_validator_double_function", -"url":17, -"doc":"Wraps the validator function to enable a double function as minting script pass_through defines how many parameters x would normally take and should be passed through to x", -"func":1 +"ref":"hebi.ledger.api_v2.Rewarding", +"url":15, +"doc":"Rewarding(staking_credential: Union[hebi.ledger.api_v2.StakingHash, hebi.ledger.api_v2.StakingPtr])" }, { -"ref":"hebi.compiler.UPLCCompiler", -"url":17, -"doc":"Expects a TypedAST and returns UPLC/Pluto like code" +"ref":"hebi.ledger.api_v2.Rewarding.staking_credential", +"url":15, +"doc":"" }, { -"ref":"hebi.compiler.UPLCCompiler.step", -"url":17, +"ref":"hebi.ledger.api_v2.Rewarding.CONSTR_ID", +"url":15, "doc":"" }, { -"ref":"hebi.compiler.UPLCCompiler.visit_sequence", -"url":17, -"doc":"", -"func":1 +"ref":"hebi.ledger.api_v2.Certifying", +"url":15, +"doc":"Certifying(d_cert: Union[hebi.ledger.api_v2.DCertDelegRegKey, hebi.ledger.api_v2.DCertDelegDeRegKey, hebi.ledger.api_v2.DCertDelegDelegate, hebi.ledger.api_v2.DCertPoolRegister, hebi.ledger.api_v2.DCertPoolRetire, hebi.ledger.api_v2.DCertGenesis, hebi.ledger.api_v2.DCertMir])" }, { -"ref":"hebi.compiler.UPLCCompiler.visit_BinOp", -"url":17, -"doc":"", -"func":1 +"ref":"hebi.ledger.api_v2.Certifying.d_cert", +"url":15, +"doc":"" }, { -"ref":"hebi.compiler.UPLCCompiler.visit_BoolOp", -"url":17, -"doc":"", -"func":1 +"ref":"hebi.ledger.api_v2.Certifying.CONSTR_ID", +"url":15, +"doc":"" }, { -"ref":"hebi.compiler.UPLCCompiler.visit_UnaryOp", -"url":17, -"doc":"", -"func":1 +"ref":"hebi.ledger.api_v2.TxInfo", +"url":15, +"doc":"A complex agglomeration of everything that could be of interest to the executed script, regarding the transaction that invoked the script" }, { -"ref":"hebi.compiler.UPLCCompiler.visit_Compare", -"url":17, -"doc":"", -"func":1 +"ref":"hebi.ledger.api_v2.TxInfo.inputs", +"url":15, +"doc":"" }, { -"ref":"hebi.compiler.UPLCCompiler.visit_Module", -"url":17, -"doc":"", -"func":1 +"ref":"hebi.ledger.api_v2.TxInfo.reference_inputs", +"url":15, +"doc":"" }, { -"ref":"hebi.compiler.UPLCCompiler.visit_Constant", -"url":17, -"doc":"", -"func":1 +"ref":"hebi.ledger.api_v2.TxInfo.outputs", +"url":15, +"doc":"" }, { -"ref":"hebi.compiler.UPLCCompiler.visit_NoneType", -"url":17, -"doc":"", -"func":1 +"ref":"hebi.ledger.api_v2.TxInfo.fee", +"url":15, +"doc":"" }, { -"ref":"hebi.compiler.UPLCCompiler.visit_Assign", -"url":17, -"doc":"", -"func":1 +"ref":"hebi.ledger.api_v2.TxInfo.mint", +"url":15, +"doc":"" }, { -"ref":"hebi.compiler.UPLCCompiler.visit_AnnAssign", -"url":17, -"doc":"", -"func":1 +"ref":"hebi.ledger.api_v2.TxInfo.dcert", +"url":15, +"doc":"" }, { -"ref":"hebi.compiler.UPLCCompiler.visit_Name", -"url":17, -"doc":"", -"func":1 +"ref":"hebi.ledger.api_v2.TxInfo.wdrl", +"url":15, +"doc":"" }, { -"ref":"hebi.compiler.UPLCCompiler.visit_Expr", -"url":17, -"doc":"", -"func":1 +"ref":"hebi.ledger.api_v2.TxInfo.valid_range", +"url":15, +"doc":"" }, { -"ref":"hebi.compiler.UPLCCompiler.visit_Call", -"url":17, -"doc":"", -"func":1 +"ref":"hebi.ledger.api_v2.TxInfo.signatories", +"url":15, +"doc":"" }, { -"ref":"hebi.compiler.UPLCCompiler.visit_FunctionDef", -"url":17, -"doc":"", -"func":1 +"ref":"hebi.ledger.api_v2.TxInfo.redeemers", +"url":15, +"doc":"" }, { -"ref":"hebi.compiler.UPLCCompiler.visit_If", -"url":17, -"doc":"", -"func":1 +"ref":"hebi.ledger.api_v2.TxInfo.data", +"url":15, +"doc":"" }, { -"ref":"hebi.compiler.UPLCCompiler.visit_Return", -"url":17, -"doc":"", -"func":1 +"ref":"hebi.ledger.api_v2.TxInfo.id", +"url":15, +"doc":"" }, { -"ref":"hebi.compiler.UPLCCompiler.visit_Pass", -"url":17, -"doc":"", -"func":1 +"ref":"hebi.ledger.api_v2.ScriptContext", +"url":15, +"doc":"Auxiliary information about the transaction and reason for invocation of the called script." }, { -"ref":"hebi.compiler.UPLCCompiler.visit_Subscript", -"url":17, -"doc":"", -"func":1 +"ref":"hebi.ledger.api_v2.ScriptContext.tx_info", +"url":15, +"doc":"" }, { -"ref":"hebi.compiler.UPLCCompiler.visit_Tuple", -"url":17, -"doc":"", -"func":1 +"ref":"hebi.ledger.api_v2.ScriptContext.purpose", +"url":15, +"doc":"" }, { -"ref":"hebi.compiler.UPLCCompiler.visit_ClassDef", -"url":17, +"ref":"hebi.ledger.interval", +"url":16, +"doc":"" +}, +{ +"ref":"hebi.ledger.interval.compare", +"url":16, "doc":"", "func":1 }, { -"ref":"hebi.compiler.UPLCCompiler.visit_Attribute", -"url":17, +"ref":"hebi.ledger.interval.compare_extended_helper", +"url":16, "doc":"", "func":1 }, { -"ref":"hebi.compiler.UPLCCompiler.visit_Assert", -"url":17, +"ref":"hebi.ledger.interval.compare_extended", +"url":16, "doc":"", "func":1 }, { -"ref":"hebi.compiler.UPLCCompiler.visit_RawPlutoExpr", -"url":17, +"ref":"hebi.ledger.interval.get_bool", +"url":16, "doc":"", "func":1 }, { -"ref":"hebi.compiler.UPLCCompiler.visit_List", -"url":17, +"ref":"hebi.ledger.interval.compare_upper_bound", +"url":16, "doc":"", "func":1 }, { -"ref":"hebi.compiler.UPLCCompiler.visit_Dict", -"url":17, +"ref":"hebi.ledger.interval.compare_lower_bound", +"url":16, "doc":"", "func":1 }, { -"ref":"hebi.compiler.UPLCCompiler.visit_IfExp", -"url":17, -"doc":"", +"ref":"hebi.ledger.interval.contains", +"url":16, +"doc":"Returns True if the interval b is entirely contained in a .", "func":1 }, { -"ref":"hebi.compiler.UPLCCompiler.visit_ListComp", -"url":17, -"doc":"", +"ref":"hebi.ledger.interval.make_range", +"url":16, +"doc":"Create a bounded interval from the given time lower_bound up to the given upper_bound , including the given time", "func":1 }, { -"ref":"hebi.compiler.UPLCCompiler.generic_visit", -"url":17, -"doc":"Called if no explicit visitor function exists for a node.", +"ref":"hebi.ledger.interval.make_from", +"url":16, +"doc":"Create a bounded interval from the given time lower_bound up to infinity, including the given time", "func":1 }, { -"ref":"hebi.compiler.UPLCCompiler.visit", -"url":14, -"doc":"Visit a node.", +"ref":"hebi.ledger.interval.make_to", +"url":16, +"doc":"Create a bounded interval from negative infinity up to the given upper_bound , including the given time", "func":1 }, { -"ref":"hebi.compiler.compile", +"ref":"hebi.optimize", "url":17, -"doc":"", -"func":1 +"doc":"" }, { -"ref":"hebi.rewrite", +"ref":"hebi.optimize.optimize_varlen", "url":18, "doc":"" }, { -"ref":"hebi.rewrite.rewrite_remove_type_stuff", -"url":19, +"ref":"hebi.optimize.optimize_varlen.NameCollector", +"url":18, +"doc":"A node visitor base class that walks the abstract syntax tree and calls a visitor function for every node found. This function may return a value which is forwarded by the visit method. This class is meant to be subclassed, with the subclass adding visitor methods. Per default the visitor functions for the nodes are 'visit_' + class name of the node. So a TryFinally node visit function would be visit_TryFinally . This behavior can be changed by overriding the visit method. If no visitor function exists for a node (return value None ) the generic_visit visitor is used instead. Don't use the NodeVisitor if you want to apply changes to nodes during traversing. For this a special visitor exists ( NodeTransformer ) that allows modifications." +}, +{ +"ref":"hebi.optimize.optimize_varlen.NameCollector.step", +"url":18, "doc":"" }, { -"ref":"hebi.rewrite.rewrite_remove_type_stuff.RewriteRemoveTypeStuff", -"url":19, -"doc":"A :class: NodeVisitor subclass that walks the abstract syntax tree and allows modification of nodes. The NodeTransformer will walk the AST and use the return value of the visitor methods to replace or remove the old node. If the return value of the visitor method is None , the node will be removed from its location, otherwise it is replaced with the return value. The return value may be the original node in which case no replacement takes place. Here is an example transformer that rewrites all occurrences of name lookups ( foo ) to data['foo'] class RewriteName(NodeTransformer): def visit_Name(self, node): return Subscript( value=Name(id='data', ctx=Load( , slice=Index(value=Str(s=node.id , ctx=node.ctx ) Keep in mind that if the node you're operating on has child nodes you must either transform the child nodes yourself or call the :meth: generic_visit method for the node first. For nodes that were part of a collection of statements (that applies to all statement nodes), the visitor may also return a list of nodes rather than just a single node. Usually you use the transformer like this node = YourTransformer().visit(node)" +"ref":"hebi.optimize.optimize_varlen.NameCollector.visit_Name", +"url":18, +"doc":"", +"func":1 }, { -"ref":"hebi.rewrite.rewrite_remove_type_stuff.RewriteRemoveTypeStuff.step", -"url":19, -"doc":"" +"ref":"hebi.optimize.optimize_varlen.NameCollector.visit_ClassDef", +"url":18, +"doc":"", +"func":1 }, { -"ref":"hebi.rewrite.rewrite_remove_type_stuff.RewriteRemoveTypeStuff.visit_Assign", -"url":19, +"ref":"hebi.optimize.optimize_varlen.NameCollector.visit_FunctionDef", +"url":18, "doc":"", "func":1 }, { -"ref":"hebi.rewrite.rewrite_remove_type_stuff.RewriteRemoveTypeStuff.visit", -"url":14, +"ref":"hebi.optimize.optimize_varlen.NameCollector.visit", +"url":19, "doc":"Visit a node.", "func":1 }, { -"ref":"hebi.rewrite.rewrite_duplicate_assignment", -"url":20, -"doc":"" +"ref":"hebi.optimize.optimize_varlen.bs_from_int", +"url":18, +"doc":"", +"func":1 }, { -"ref":"hebi.rewrite.rewrite_duplicate_assignment.RewriteDuplicateAssignment", -"url":20, +"ref":"hebi.optimize.optimize_varlen.OptimizeVarlen", +"url":18, "doc":"A :class: NodeVisitor subclass that walks the abstract syntax tree and allows modification of nodes. The NodeTransformer will walk the AST and use the return value of the visitor methods to replace or remove the old node. If the return value of the visitor method is None , the node will be removed from its location, otherwise it is replaced with the return value. The return value may be the original node in which case no replacement takes place. Here is an example transformer that rewrites all occurrences of name lookups ( foo ) to data['foo'] class RewriteName(NodeTransformer): def visit_Name(self, node): return Subscript( value=Name(id='data', ctx=Load( , slice=Index(value=Str(s=node.id , ctx=node.ctx ) Keep in mind that if the node you're operating on has child nodes you must either transform the child nodes yourself or call the :meth: generic_visit method for the node first. For nodes that were part of a collection of statements (that applies to all statement nodes), the visitor may also return a list of nodes rather than just a single node. Usually you use the transformer like this node = YourTransformer().visit(node)" }, { -"ref":"hebi.rewrite.rewrite_duplicate_assignment.RewriteDuplicateAssignment.step", -"url":20, +"ref":"hebi.optimize.optimize_varlen.OptimizeVarlen.step", +"url":18, "doc":"" }, { -"ref":"hebi.rewrite.rewrite_duplicate_assignment.RewriteDuplicateAssignment.avail_names", -"url":20, +"ref":"hebi.optimize.optimize_varlen.OptimizeVarlen.varmap", +"url":18, "doc":"" }, { -"ref":"hebi.rewrite.rewrite_duplicate_assignment.RewriteDuplicateAssignment.avail", -"url":20, -"doc":"", -"func":1 -}, -{ -"ref":"hebi.rewrite.rewrite_duplicate_assignment.RewriteDuplicateAssignment.in_current_scope", -"url":20, -"doc":"", -"func":1 -}, -{ -"ref":"hebi.rewrite.rewrite_duplicate_assignment.RewriteDuplicateAssignment.enter_scope", -"url":20, +"ref":"hebi.optimize.optimize_varlen.OptimizeVarlen.visit_Module", +"url":18, "doc":"", "func":1 }, { -"ref":"hebi.rewrite.rewrite_duplicate_assignment.RewriteDuplicateAssignment.exit_scope", -"url":20, +"ref":"hebi.optimize.optimize_varlen.OptimizeVarlen.visit_Name", +"url":18, "doc":"", "func":1 }, { -"ref":"hebi.rewrite.rewrite_duplicate_assignment.RewriteDuplicateAssignment.set_avail", -"url":20, +"ref":"hebi.optimize.optimize_varlen.OptimizeVarlen.visit_ClassDef", +"url":18, "doc":"", "func":1 }, { -"ref":"hebi.rewrite.rewrite_duplicate_assignment.RewriteDuplicateAssignment.visit_Module", -"url":20, +"ref":"hebi.optimize.optimize_varlen.OptimizeVarlen.visit_FunctionDef", +"url":18, "doc":"", "func":1 }, { -"ref":"hebi.rewrite.rewrite_duplicate_assignment.RewriteDuplicateAssignment.visit_If", -"url":20, -"doc":"", +"ref":"hebi.optimize.optimize_varlen.OptimizeVarlen.visit", +"url":19, +"doc":"Visit a node.", "func":1 }, { -"ref":"hebi.rewrite.rewrite_duplicate_assignment.RewriteDuplicateAssignment.visit_Assign", +"ref":"hebi.optimize.optimize_remove_pass", "url":20, -"doc":"", -"func":1 +"doc":"" }, { -"ref":"hebi.rewrite.rewrite_duplicate_assignment.RewriteDuplicateAssignment.visit_AnnAssign", +"ref":"hebi.optimize.optimize_remove_pass.OptimizeRemovePass", "url":20, -"doc":"", -"func":1 +"doc":"A :class: NodeVisitor subclass that walks the abstract syntax tree and allows modification of nodes. The NodeTransformer will walk the AST and use the return value of the visitor methods to replace or remove the old node. If the return value of the visitor method is None , the node will be removed from its location, otherwise it is replaced with the return value. The return value may be the original node in which case no replacement takes place. Here is an example transformer that rewrites all occurrences of name lookups ( foo ) to data['foo'] class RewriteName(NodeTransformer): def visit_Name(self, node): return Subscript( value=Name(id='data', ctx=Load( , slice=Index(value=Str(s=node.id , ctx=node.ctx ) Keep in mind that if the node you're operating on has child nodes you must either transform the child nodes yourself or call the :meth: generic_visit method for the node first. For nodes that were part of a collection of statements (that applies to all statement nodes), the visitor may also return a list of nodes rather than just a single node. Usually you use the transformer like this node = YourTransformer().visit(node)" }, { -"ref":"hebi.rewrite.rewrite_duplicate_assignment.RewriteDuplicateAssignment.visit_ClassDef", +"ref":"hebi.optimize.optimize_remove_pass.OptimizeRemovePass.step", "url":20, -"doc":"", -"func":1 +"doc":"" }, { -"ref":"hebi.rewrite.rewrite_duplicate_assignment.RewriteDuplicateAssignment.visit_FunctionDef", +"ref":"hebi.optimize.optimize_remove_pass.OptimizeRemovePass.visit_Pass", "url":20, "doc":"", "func":1 }, { -"ref":"hebi.rewrite.rewrite_duplicate_assignment.RewriteDuplicateAssignment.visit", -"url":14, +"ref":"hebi.optimize.optimize_remove_pass.OptimizeRemovePass.visit", +"url":19, "doc":"Visit a node.", "func":1 }, { -"ref":"hebi.rewrite.rewrite_import_typing", +"ref":"hebi.optimize.optimize_remove_comments", "url":21, "doc":"" }, { -"ref":"hebi.rewrite.rewrite_import_typing.RewriteImportTyping", +"ref":"hebi.optimize.optimize_remove_comments.OptimizeRemoveDeadconstants", "url":21, "doc":"A :class: NodeVisitor subclass that walks the abstract syntax tree and allows modification of nodes. The NodeTransformer will walk the AST and use the return value of the visitor methods to replace or remove the old node. If the return value of the visitor method is None , the node will be removed from its location, otherwise it is replaced with the return value. The return value may be the original node in which case no replacement takes place. Here is an example transformer that rewrites all occurrences of name lookups ( foo ) to data['foo'] class RewriteName(NodeTransformer): def visit_Name(self, node): return Subscript( value=Name(id='data', ctx=Load( , slice=Index(value=Str(s=node.id , ctx=node.ctx ) Keep in mind that if the node you're operating on has child nodes you must either transform the child nodes yourself or call the :meth: generic_visit method for the node first. For nodes that were part of a collection of statements (that applies to all statement nodes), the visitor may also return a list of nodes rather than just a single node. Usually you use the transformer like this node = YourTransformer().visit(node)" }, { -"ref":"hebi.rewrite.rewrite_import_typing.RewriteImportTyping.step", -"url":21, -"doc":"" -}, -{ -"ref":"hebi.rewrite.rewrite_import_typing.RewriteImportTyping.imports_typing", +"ref":"hebi.optimize.optimize_remove_comments.OptimizeRemoveDeadconstants.step", "url":21, "doc":"" }, { -"ref":"hebi.rewrite.rewrite_import_typing.RewriteImportTyping.visit_ImportFrom", -"url":21, -"doc":"", -"func":1 -}, -{ -"ref":"hebi.rewrite.rewrite_import_typing.RewriteImportTyping.visit_ClassDef", +"ref":"hebi.optimize.optimize_remove_comments.OptimizeRemoveDeadconstants.visit_Expr", "url":21, "doc":"", "func":1 }, { -"ref":"hebi.rewrite.rewrite_import_typing.RewriteImportTyping.visit", -"url":14, +"ref":"hebi.optimize.optimize_remove_comments.OptimizeRemoveDeadconstants.visit", +"url":19, "doc":"Visit a node.", "func":1 }, { -"ref":"hebi.rewrite.rewrite_inject_builtin_constr", +"ref":"hebi.optimize.optimize_remove_deadvars", "url":22, "doc":"" }, { -"ref":"hebi.rewrite.rewrite_inject_builtin_constr.RewriteInjectBuiltinsConstr", +"ref":"hebi.optimize.optimize_remove_deadvars.NameLoadCollector", "url":22, -"doc":"A :class: NodeVisitor subclass that walks the abstract syntax tree and allows modification of nodes. The NodeTransformer will walk the AST and use the return value of the visitor methods to replace or remove the old node. If the return value of the visitor method is None , the node will be removed from its location, otherwise it is replaced with the return value. The return value may be the original node in which case no replacement takes place. Here is an example transformer that rewrites all occurrences of name lookups ( foo ) to data['foo'] class RewriteName(NodeTransformer): def visit_Name(self, node): return Subscript( value=Name(id='data', ctx=Load( , slice=Index(value=Str(s=node.id , ctx=node.ctx ) Keep in mind that if the node you're operating on has child nodes you must either transform the child nodes yourself or call the :meth: generic_visit method for the node first. For nodes that were part of a collection of statements (that applies to all statement nodes), the visitor may also return a list of nodes rather than just a single node. Usually you use the transformer like this node = YourTransformer().visit(node)" +"doc":"A node visitor base class that walks the abstract syntax tree and calls a visitor function for every node found. This function may return a value which is forwarded by the visit method. This class is meant to be subclassed, with the subclass adding visitor methods. Per default the visitor functions for the nodes are 'visit_' + class name of the node. So a TryFinally node visit function would be visit_TryFinally . This behavior can be changed by overriding the visit method. If no visitor function exists for a node (return value None ) the generic_visit visitor is used instead. Don't use the NodeVisitor if you want to apply changes to nodes during traversing. For this a special visitor exists ( NodeTransformer ) that allows modifications." }, { -"ref":"hebi.rewrite.rewrite_inject_builtin_constr.RewriteInjectBuiltinsConstr.step", +"ref":"hebi.optimize.optimize_remove_deadvars.NameLoadCollector.step", "url":22, "doc":"" }, { -"ref":"hebi.rewrite.rewrite_inject_builtin_constr.RewriteInjectBuiltinsConstr.visit_Module", +"ref":"hebi.optimize.optimize_remove_deadvars.NameLoadCollector.visit_Name", "url":22, "doc":"", "func":1 }, { -"ref":"hebi.rewrite.rewrite_inject_builtin_constr.RewriteInjectBuiltinsConstr.visit", -"url":14, +"ref":"hebi.optimize.optimize_remove_deadvars.NameLoadCollector.visit_ClassDef", +"url":22, +"doc":"", +"func":1 +}, +{ +"ref":"hebi.optimize.optimize_remove_deadvars.NameLoadCollector.visit_FunctionDef", +"url":22, +"doc":"", +"func":1 +}, +{ +"ref":"hebi.optimize.optimize_remove_deadvars.NameLoadCollector.visit", +"url":19, "doc":"Visit a node.", "func":1 }, { -"ref":"hebi.rewrite.rewrite_import_dataclasses", -"url":23, +"ref":"hebi.optimize.optimize_remove_deadvars.SafeOperationVisitor", +"url":22, +"doc":"A node visitor base class that walks the abstract syntax tree and calls a visitor function for every node found. This function may return a value which is forwarded by the visit method. This class is meant to be subclassed, with the subclass adding visitor methods. Per default the visitor functions for the nodes are 'visit_' + class name of the node. So a TryFinally node visit function would be visit_TryFinally . This behavior can be changed by overriding the visit method. If no visitor function exists for a node (return value None ) the generic_visit visitor is used instead. Don't use the NodeVisitor if you want to apply changes to nodes during traversing. For this a special visitor exists ( NodeTransformer ) that allows modifications." +}, +{ +"ref":"hebi.optimize.optimize_remove_deadvars.SafeOperationVisitor.step", +"url":22, "doc":"" }, { -"ref":"hebi.rewrite.rewrite_import_dataclasses.RewriteImportDataclasses", -"url":23, -"doc":"A :class: NodeVisitor subclass that walks the abstract syntax tree and allows modification of nodes. The NodeTransformer will walk the AST and use the return value of the visitor methods to replace or remove the old node. If the return value of the visitor method is None , the node will be removed from its location, otherwise it is replaced with the return value. The return value may be the original node in which case no replacement takes place. Here is an example transformer that rewrites all occurrences of name lookups ( foo ) to data['foo'] class RewriteName(NodeTransformer): def visit_Name(self, node): return Subscript( value=Name(id='data', ctx=Load( , slice=Index(value=Str(s=node.id , ctx=node.ctx ) Keep in mind that if the node you're operating on has child nodes you must either transform the child nodes yourself or call the :meth: generic_visit method for the node first. For nodes that were part of a collection of statements (that applies to all statement nodes), the visitor may also return a list of nodes rather than just a single node. Usually you use the transformer like this node = YourTransformer().visit(node)" +"ref":"hebi.optimize.optimize_remove_deadvars.SafeOperationVisitor.generic_visit", +"url":22, +"doc":"Called if no explicit visitor function exists for a node.", +"func":1 }, { -"ref":"hebi.rewrite.rewrite_import_dataclasses.RewriteImportDataclasses.step", -"url":23, -"doc":"" +"ref":"hebi.optimize.optimize_remove_deadvars.SafeOperationVisitor.visit_Lambda", +"url":22, +"doc":"", +"func":1 }, { -"ref":"hebi.rewrite.rewrite_import_dataclasses.RewriteImportDataclasses.imports_dataclasses", -"url":23, -"doc":"" +"ref":"hebi.optimize.optimize_remove_deadvars.SafeOperationVisitor.visit_Constant", +"url":22, +"doc":"", +"func":1 }, { -"ref":"hebi.rewrite.rewrite_import_dataclasses.RewriteImportDataclasses.visit_ImportFrom", -"url":23, +"ref":"hebi.optimize.optimize_remove_deadvars.SafeOperationVisitor.visit_RawPlutoExpr", +"url":22, "doc":"", "func":1 }, { -"ref":"hebi.rewrite.rewrite_import_dataclasses.RewriteImportDataclasses.visit_ClassDef", -"url":23, +"ref":"hebi.optimize.optimize_remove_deadvars.SafeOperationVisitor.visit_Name", +"url":22, "doc":"", "func":1 }, { -"ref":"hebi.rewrite.rewrite_import_dataclasses.RewriteImportDataclasses.visit", -"url":14, +"ref":"hebi.optimize.optimize_remove_deadvars.SafeOperationVisitor.visit", +"url":19, "doc":"Visit a node.", "func":1 }, { -"ref":"hebi.rewrite.rewrite_subscript38", -"url":24, +"ref":"hebi.optimize.optimize_remove_deadvars.OptimizeRemoveDeadvars", +"url":22, +"doc":"A :class: NodeVisitor subclass that walks the abstract syntax tree and allows modification of nodes. The NodeTransformer will walk the AST and use the return value of the visitor methods to replace or remove the old node. If the return value of the visitor method is None , the node will be removed from its location, otherwise it is replaced with the return value. The return value may be the original node in which case no replacement takes place. Here is an example transformer that rewrites all occurrences of name lookups ( foo ) to data['foo'] class RewriteName(NodeTransformer): def visit_Name(self, node): return Subscript( value=Name(id='data', ctx=Load( , slice=Index(value=Str(s=node.id , ctx=node.ctx ) Keep in mind that if the node you're operating on has child nodes you must either transform the child nodes yourself or call the :meth: generic_visit method for the node first. For nodes that were part of a collection of statements (that applies to all statement nodes), the visitor may also return a list of nodes rather than just a single node. Usually you use the transformer like this node = YourTransformer().visit(node)" +}, +{ +"ref":"hebi.optimize.optimize_remove_deadvars.OptimizeRemoveDeadvars.step", +"url":22, "doc":"" }, { -"ref":"hebi.rewrite.rewrite_subscript38.RewriteSubscript38", -"url":24, -"doc":"A :class: NodeVisitor subclass that walks the abstract syntax tree and allows modification of nodes. The NodeTransformer will walk the AST and use the return value of the visitor methods to replace or remove the old node. If the return value of the visitor method is None , the node will be removed from its location, otherwise it is replaced with the return value. The return value may be the original node in which case no replacement takes place. Here is an example transformer that rewrites all occurrences of name lookups ( foo ) to data['foo'] class RewriteName(NodeTransformer): def visit_Name(self, node): return Subscript( value=Name(id='data', ctx=Load( , slice=Index(value=Str(s=node.id , ctx=node.ctx ) Keep in mind that if the node you're operating on has child nodes you must either transform the child nodes yourself or call the :meth: generic_visit method for the node first. For nodes that were part of a collection of statements (that applies to all statement nodes), the visitor may also return a list of nodes rather than just a single node. Usually you use the transformer like this node = YourTransformer().visit(node)" +"ref":"hebi.optimize.optimize_remove_deadvars.OptimizeRemoveDeadvars.loaded_vars", +"url":22, +"doc":"" }, { -"ref":"hebi.rewrite.rewrite_subscript38.RewriteSubscript38.step", -"url":24, +"ref":"hebi.optimize.optimize_remove_deadvars.OptimizeRemoveDeadvars.guaranteed_avail_names", +"url":22, "doc":"" }, { -"ref":"hebi.rewrite.rewrite_subscript38.RewriteSubscript38.visit_Index", -"url":24, +"ref":"hebi.optimize.optimize_remove_deadvars.OptimizeRemoveDeadvars.guaranteed", +"url":22, "doc":"", "func":1 }, { -"ref":"hebi.rewrite.rewrite_subscript38.RewriteSubscript38.visit", -"url":14, -"doc":"Visit a node.", +"ref":"hebi.optimize.optimize_remove_deadvars.OptimizeRemoveDeadvars.enter_scope", +"url":22, +"doc":"", "func":1 }, { -"ref":"hebi.rewrite.rewrite_forbidden_overwrites", -"url":25, -"doc":"" +"ref":"hebi.optimize.optimize_remove_deadvars.OptimizeRemoveDeadvars.exit_scope", +"url":22, +"doc":"", +"func":1 }, { -"ref":"hebi.rewrite.rewrite_forbidden_overwrites.ForbiddenOverwriteError", -"url":25, -"doc":"Inappropriate argument value (of correct type)." +"ref":"hebi.optimize.optimize_remove_deadvars.OptimizeRemoveDeadvars.set_guaranteed", +"url":22, +"doc":"", +"func":1 }, { -"ref":"hebi.rewrite.rewrite_forbidden_overwrites.RewriteForbiddenOverwrites", -"url":25, -"doc":"A :class: NodeVisitor subclass that walks the abstract syntax tree and allows modification of nodes. The NodeTransformer will walk the AST and use the return value of the visitor methods to replace or remove the old node. If the return value of the visitor method is None , the node will be removed from its location, otherwise it is replaced with the return value. The return value may be the original node in which case no replacement takes place. Here is an example transformer that rewrites all occurrences of name lookups ( foo ) to data['foo'] class RewriteName(NodeTransformer): def visit_Name(self, node): return Subscript( value=Name(id='data', ctx=Load( , slice=Index(value=Str(s=node.id , ctx=node.ctx ) Keep in mind that if the node you're operating on has child nodes you must either transform the child nodes yourself or call the :meth: generic_visit method for the node first. For nodes that were part of a collection of statements (that applies to all statement nodes), the visitor may also return a list of nodes rather than just a single node. Usually you use the transformer like this node = YourTransformer().visit(node)" +"ref":"hebi.optimize.optimize_remove_deadvars.OptimizeRemoveDeadvars.visit_Module", +"url":22, +"doc":"", +"func":1 }, { -"ref":"hebi.rewrite.rewrite_forbidden_overwrites.RewriteForbiddenOverwrites.step", -"url":25, -"doc":"" +"ref":"hebi.optimize.optimize_remove_deadvars.OptimizeRemoveDeadvars.visit_If", +"url":22, +"doc":"", +"func":1 }, { -"ref":"hebi.rewrite.rewrite_forbidden_overwrites.RewriteForbiddenOverwrites.visit_Name", -"url":25, +"ref":"hebi.optimize.optimize_remove_deadvars.OptimizeRemoveDeadvars.visit_While", +"url":22, "doc":"", "func":1 }, { -"ref":"hebi.rewrite.rewrite_forbidden_overwrites.RewriteForbiddenOverwrites.visit", -"url":14, -"doc":"Visit a node.", +"ref":"hebi.optimize.optimize_remove_deadvars.OptimizeRemoveDeadvars.visit_For", +"url":22, +"doc":"", "func":1 }, { -"ref":"hebi.rewrite.rewrite_inject_builtins", -"url":26, -"doc":"" +"ref":"hebi.optimize.optimize_remove_deadvars.OptimizeRemoveDeadvars.visit_Assign", +"url":22, +"doc":"", +"func":1 }, { -"ref":"hebi.rewrite.rewrite_inject_builtins.RewriteInjectBuiltins", -"url":26, -"doc":"A :class: NodeVisitor subclass that walks the abstract syntax tree and allows modification of nodes. The NodeTransformer will walk the AST and use the return value of the visitor methods to replace or remove the old node. If the return value of the visitor method is None , the node will be removed from its location, otherwise it is replaced with the return value. The return value may be the original node in which case no replacement takes place. Here is an example transformer that rewrites all occurrences of name lookups ( foo ) to data['foo'] class RewriteName(NodeTransformer): def visit_Name(self, node): return Subscript( value=Name(id='data', ctx=Load( , slice=Index(value=Str(s=node.id , ctx=node.ctx ) Keep in mind that if the node you're operating on has child nodes you must either transform the child nodes yourself or call the :meth: generic_visit method for the node first. For nodes that were part of a collection of statements (that applies to all statement nodes), the visitor may also return a list of nodes rather than just a single node. Usually you use the transformer like this node = YourTransformer().visit(node)" +"ref":"hebi.optimize.optimize_remove_deadvars.OptimizeRemoveDeadvars.visit_AnnAssign", +"url":22, +"doc":"", +"func":1 }, { -"ref":"hebi.rewrite.rewrite_inject_builtins.RewriteInjectBuiltins.step", -"url":26, -"doc":"" +"ref":"hebi.optimize.optimize_remove_deadvars.OptimizeRemoveDeadvars.visit_ClassDef", +"url":22, +"doc":"", +"func":1 }, { -"ref":"hebi.rewrite.rewrite_inject_builtins.RewriteInjectBuiltins.visit_Module", -"url":26, +"ref":"hebi.optimize.optimize_remove_deadvars.OptimizeRemoveDeadvars.visit_FunctionDef", +"url":22, "doc":"", "func":1 }, { -"ref":"hebi.rewrite.rewrite_inject_builtins.RewriteInjectBuiltins.visit", -"url":14, +"ref":"hebi.optimize.optimize_remove_deadvars.OptimizeRemoveDeadvars.visit", +"url":19, "doc":"Visit a node.", "func":1 }, { -"ref":"hebi.rewrite.rewrite_import_plutusdata", -"url":27, +"ref":"hebi.compiler", +"url":23, "doc":"" }, { -"ref":"hebi.rewrite.rewrite_import_plutusdata.RewriteImportPlutusData", -"url":27, -"doc":"A :class: NodeVisitor subclass that walks the abstract syntax tree and allows modification of nodes. The NodeTransformer will walk the AST and use the return value of the visitor methods to replace or remove the old node. If the return value of the visitor method is None , the node will be removed from its location, otherwise it is replaced with the return value. The return value may be the original node in which case no replacement takes place. Here is an example transformer that rewrites all occurrences of name lookups ( foo ) to data['foo'] class RewriteName(NodeTransformer): def visit_Name(self, node): return Subscript( value=Name(id='data', ctx=Load( , slice=Index(value=Str(s=node.id , ctx=node.ctx ) Keep in mind that if the node you're operating on has child nodes you must either transform the child nodes yourself or call the :meth: generic_visit method for the node first. For nodes that were part of a collection of statements (that applies to all statement nodes), the visitor may also return a list of nodes rather than just a single node. Usually you use the transformer like this node = YourTransformer().visit(node)" +"ref":"hebi.compiler.wrap_validator_double_function", +"url":23, +"doc":"Wraps the validator function to enable a double function as minting script pass_through defines how many parameters x would normally take and should be passed through to x", +"func":1 }, { -"ref":"hebi.rewrite.rewrite_import_plutusdata.RewriteImportPlutusData.step", -"url":27, -"doc":"" +"ref":"hebi.compiler.UPLCCompiler", +"url":23, +"doc":"Expects a TypedAST and returns UPLC/Pluto like code" }, { -"ref":"hebi.rewrite.rewrite_import_plutusdata.RewriteImportPlutusData.imports_plutus_data", -"url":27, +"ref":"hebi.compiler.UPLCCompiler.step", +"url":23, "doc":"" }, { -"ref":"hebi.rewrite.rewrite_import_plutusdata.RewriteImportPlutusData.visit_ImportFrom", -"url":27, +"ref":"hebi.compiler.UPLCCompiler.visit_sequence", +"url":23, "doc":"", "func":1 }, { -"ref":"hebi.rewrite.rewrite_import_plutusdata.RewriteImportPlutusData.visit_ClassDef", -"url":27, +"ref":"hebi.compiler.UPLCCompiler.visit_BinOp", +"url":23, "doc":"", "func":1 }, { -"ref":"hebi.rewrite.rewrite_import_plutusdata.RewriteImportPlutusData.visit", -"url":14, -"doc":"Visit a node.", +"ref":"hebi.compiler.UPLCCompiler.visit_BoolOp", +"url":23, +"doc":"", "func":1 }, { -"ref":"hebi.rewrite.rewrite_zero_ary", -"url":28, -"doc":"" -}, -{ -"ref":"hebi.rewrite.rewrite_zero_ary.RewriteZeroAry", -"url":28, -"doc":"A :class: NodeVisitor subclass that walks the abstract syntax tree and allows modification of nodes. The NodeTransformer will walk the AST and use the return value of the visitor methods to replace or remove the old node. If the return value of the visitor method is None , the node will be removed from its location, otherwise it is replaced with the return value. The return value may be the original node in which case no replacement takes place. Here is an example transformer that rewrites all occurrences of name lookups ( foo ) to data['foo'] class RewriteName(NodeTransformer): def visit_Name(self, node): return Subscript( value=Name(id='data', ctx=Load( , slice=Index(value=Str(s=node.id , ctx=node.ctx ) Keep in mind that if the node you're operating on has child nodes you must either transform the child nodes yourself or call the :meth: generic_visit method for the node first. For nodes that were part of a collection of statements (that applies to all statement nodes), the visitor may also return a list of nodes rather than just a single node. Usually you use the transformer like this node = YourTransformer().visit(node)" -}, -{ -"ref":"hebi.rewrite.rewrite_zero_ary.RewriteZeroAry.step", -"url":28, -"doc":"" +"ref":"hebi.compiler.UPLCCompiler.visit_UnaryOp", +"url":23, +"doc":"", +"func":1 }, { -"ref":"hebi.rewrite.rewrite_zero_ary.RewriteZeroAry.visit_FunctionDef", -"url":28, +"ref":"hebi.compiler.UPLCCompiler.visit_Compare", +"url":23, "doc":"", "func":1 }, { -"ref":"hebi.rewrite.rewrite_zero_ary.RewriteZeroAry.visit_Call", -"url":28, +"ref":"hebi.compiler.UPLCCompiler.visit_Module", +"url":23, "doc":"", "func":1 }, { -"ref":"hebi.rewrite.rewrite_zero_ary.RewriteZeroAry.visit", -"url":14, -"doc":"Visit a node.", +"ref":"hebi.compiler.UPLCCompiler.visit_Constant", +"url":23, +"doc":"", "func":1 }, { -"ref":"hebi.rewrite.rewrite_import_hashlib", -"url":29, -"doc":"" +"ref":"hebi.compiler.UPLCCompiler.visit_NoneType", +"url":23, +"doc":"", +"func":1 }, { -"ref":"hebi.rewrite.rewrite_import_hashlib.HashType", -"url":29, -"doc":"A pseudo class that is the result of python hash functions that need a 'digest' call" +"ref":"hebi.compiler.UPLCCompiler.visit_Assign", +"url":23, +"doc":"", +"func":1 }, { -"ref":"hebi.rewrite.rewrite_import_hashlib.HashType.attribute_type", -"url":29, -"doc":"The types of the named attributes of this class", +"ref":"hebi.compiler.UPLCCompiler.visit_AnnAssign", +"url":23, +"doc":"", "func":1 }, { -"ref":"hebi.rewrite.rewrite_import_hashlib.HashType.attribute", -"url":29, -"doc":"The attributes of this class. Needs to be a lambda that expects as first argument the object itself", +"ref":"hebi.compiler.UPLCCompiler.visit_Name", +"url":23, +"doc":"", "func":1 }, { -"ref":"hebi.rewrite.rewrite_import_hashlib.HashType.constr_type", -"url":1, -"doc":"The type of the constructor for this class", +"ref":"hebi.compiler.UPLCCompiler.visit_Expr", +"url":23, +"doc":"", "func":1 }, { -"ref":"hebi.rewrite.rewrite_import_hashlib.HashType.constr", -"url":1, -"doc":"The constructor for this class", +"ref":"hebi.compiler.UPLCCompiler.visit_Call", +"url":23, +"doc":"", "func":1 }, { -"ref":"hebi.rewrite.rewrite_import_hashlib.HashType.cmp", -"url":1, -"doc":"The implementation of comparing this type to type o via operator op. Returns a lambda that expects as first argument the object itself and as second the comparison.", +"ref":"hebi.compiler.UPLCCompiler.visit_FunctionDef", +"url":23, +"doc":"", "func":1 }, { -"ref":"hebi.rewrite.rewrite_import_hashlib.PythonHashlib", -"url":29, -"doc":"An enumeration." +"ref":"hebi.compiler.UPLCCompiler.visit_If", +"url":23, +"doc":"", +"func":1 }, { -"ref":"hebi.rewrite.rewrite_import_hashlib.PythonHashlib.sha256", -"url":29, -"doc":"" +"ref":"hebi.compiler.UPLCCompiler.visit_Return", +"url":23, +"doc":"", +"func":1 }, { -"ref":"hebi.rewrite.rewrite_import_hashlib.PythonHashlib.sha3_256", -"url":29, -"doc":"" +"ref":"hebi.compiler.UPLCCompiler.visit_Pass", +"url":23, +"doc":"", +"func":1 }, { -"ref":"hebi.rewrite.rewrite_import_hashlib.PythonHashlib.blake2b", -"url":29, -"doc":"" +"ref":"hebi.compiler.UPLCCompiler.visit_Subscript", +"url":23, +"doc":"", +"func":1 }, { -"ref":"hebi.rewrite.rewrite_import_hashlib.RewriteImportHashlib", -"url":29, -"doc":"A :class: NodeVisitor subclass that walks the abstract syntax tree and allows modification of nodes. The NodeTransformer will walk the AST and use the return value of the visitor methods to replace or remove the old node. If the return value of the visitor method is None , the node will be removed from its location, otherwise it is replaced with the return value. The return value may be the original node in which case no replacement takes place. Here is an example transformer that rewrites all occurrences of name lookups ( foo ) to data['foo'] class RewriteName(NodeTransformer): def visit_Name(self, node): return Subscript( value=Name(id='data', ctx=Load( , slice=Index(value=Str(s=node.id , ctx=node.ctx ) Keep in mind that if the node you're operating on has child nodes you must either transform the child nodes yourself or call the :meth: generic_visit method for the node first. For nodes that were part of a collection of statements (that applies to all statement nodes), the visitor may also return a list of nodes rather than just a single node. Usually you use the transformer like this node = YourTransformer().visit(node)" +"ref":"hebi.compiler.UPLCCompiler.visit_Tuple", +"url":23, +"doc":"", +"func":1 }, { -"ref":"hebi.rewrite.rewrite_import_hashlib.RewriteImportHashlib.step", -"url":29, -"doc":"" +"ref":"hebi.compiler.UPLCCompiler.visit_ClassDef", +"url":23, +"doc":"", +"func":1 }, { -"ref":"hebi.rewrite.rewrite_import_hashlib.RewriteImportHashlib.imports_hashlib", -"url":29, -"doc":"" +"ref":"hebi.compiler.UPLCCompiler.visit_Attribute", +"url":23, +"doc":"", +"func":1 }, { -"ref":"hebi.rewrite.rewrite_import_hashlib.RewriteImportHashlib.visit_ImportFrom", -"url":29, +"ref":"hebi.compiler.UPLCCompiler.visit_Assert", +"url":23, "doc":"", "func":1 }, { -"ref":"hebi.rewrite.rewrite_import_hashlib.RewriteImportHashlib.visit", -"url":14, -"doc":"Visit a node.", +"ref":"hebi.compiler.UPLCCompiler.visit_RawPlutoExpr", +"url":23, +"doc":"", "func":1 }, { -"ref":"hebi.rewrite.rewrite_tuple_assign", -"url":30, -"doc":"" +"ref":"hebi.compiler.UPLCCompiler.visit_List", +"url":23, +"doc":"", +"func":1 }, { -"ref":"hebi.rewrite.rewrite_tuple_assign.RewriteTupleAssign", -"url":30, -"doc":"A :class: NodeVisitor subclass that walks the abstract syntax tree and allows modification of nodes. The NodeTransformer will walk the AST and use the return value of the visitor methods to replace or remove the old node. If the return value of the visitor method is None , the node will be removed from its location, otherwise it is replaced with the return value. The return value may be the original node in which case no replacement takes place. Here is an example transformer that rewrites all occurrences of name lookups ( foo ) to data['foo'] class RewriteName(NodeTransformer): def visit_Name(self, node): return Subscript( value=Name(id='data', ctx=Load( , slice=Index(value=Str(s=node.id , ctx=node.ctx ) Keep in mind that if the node you're operating on has child nodes you must either transform the child nodes yourself or call the :meth: generic_visit method for the node first. For nodes that were part of a collection of statements (that applies to all statement nodes), the visitor may also return a list of nodes rather than just a single node. Usually you use the transformer like this node = YourTransformer().visit(node)" +"ref":"hebi.compiler.UPLCCompiler.visit_Dict", +"url":23, +"doc":"", +"func":1 }, { -"ref":"hebi.rewrite.rewrite_tuple_assign.RewriteTupleAssign.step", -"url":30, -"doc":"" +"ref":"hebi.compiler.UPLCCompiler.visit_IfExp", +"url":23, +"doc":"", +"func":1 }, { -"ref":"hebi.rewrite.rewrite_tuple_assign.RewriteTupleAssign.unique_id", -"url":30, -"doc":"" +"ref":"hebi.compiler.UPLCCompiler.visit_ListComp", +"url":23, +"doc":"", +"func":1 }, { -"ref":"hebi.rewrite.rewrite_tuple_assign.RewriteTupleAssign.visit_Assign", -"url":30, -"doc":"", +"ref":"hebi.compiler.UPLCCompiler.generic_visit", +"url":23, +"doc":"Called if no explicit visitor function exists for a node.", "func":1 }, { -"ref":"hebi.rewrite.rewrite_tuple_assign.RewriteTupleAssign.visit", -"url":14, +"ref":"hebi.compiler.UPLCCompiler.visit", +"url":19, "doc":"Visit a node.", "func":1 }, { -"ref":"hebi.rewrite.rewrite_import", -"url":31, +"ref":"hebi.compiler.compile", +"url":23, +"doc":"", +"func":1 +}, +{ +"ref":"hebi.rewrite", +"url":24, "doc":"" }, { -"ref":"hebi.rewrite.rewrite_import.import_module", -"url":31, -"doc":"An approximate implementation of import.", -"func":1 +"ref":"hebi.rewrite.rewrite_remove_type_stuff", +"url":25, +"doc":"" }, { -"ref":"hebi.rewrite.rewrite_import.RewriteImport", -"url":31, +"ref":"hebi.rewrite.rewrite_remove_type_stuff.RewriteRemoveTypeStuff", +"url":25, "doc":"A :class: NodeVisitor subclass that walks the abstract syntax tree and allows modification of nodes. The NodeTransformer will walk the AST and use the return value of the visitor methods to replace or remove the old node. If the return value of the visitor method is None , the node will be removed from its location, otherwise it is replaced with the return value. The return value may be the original node in which case no replacement takes place. Here is an example transformer that rewrites all occurrences of name lookups ( foo ) to data['foo'] class RewriteName(NodeTransformer): def visit_Name(self, node): return Subscript( value=Name(id='data', ctx=Load( , slice=Index(value=Str(s=node.id , ctx=node.ctx ) Keep in mind that if the node you're operating on has child nodes you must either transform the child nodes yourself or call the :meth: generic_visit method for the node first. For nodes that were part of a collection of statements (that applies to all statement nodes), the visitor may also return a list of nodes rather than just a single node. Usually you use the transformer like this node = YourTransformer().visit(node)" }, { -"ref":"hebi.rewrite.rewrite_import.RewriteImport.step", -"url":31, +"ref":"hebi.rewrite.rewrite_remove_type_stuff.RewriteRemoveTypeStuff.step", +"url":25, "doc":"" }, { -"ref":"hebi.rewrite.rewrite_import.RewriteImport.visit_ImportFrom", -"url":31, +"ref":"hebi.rewrite.rewrite_remove_type_stuff.RewriteRemoveTypeStuff.visit_Assign", +"url":25, "doc":"", "func":1 }, { -"ref":"hebi.rewrite.rewrite_import.RewriteImport.visit", -"url":14, +"ref":"hebi.rewrite.rewrite_remove_type_stuff.RewriteRemoveTypeStuff.visit", +"url":19, "doc":"Visit a node.", "func":1 }, { -"ref":"hebi.type_inference", -"url":32, +"ref":"hebi.rewrite.rewrite_duplicate_assignment", +"url":26, "doc":"" }, { -"ref":"hebi.type_inference.ReturnExtractor", -"url":32, -"doc":"Utility to find all Return statements in an AST subtree" -}, -{ -"ref":"hebi.type_inference.ReturnExtractor.visit_Return", -"url":32, -"doc":"", -"func":1 -}, -{ -"ref":"hebi.type_inference.AggressiveTypeInferencer", -"url":32, +"ref":"hebi.rewrite.rewrite_duplicate_assignment.RewriteDuplicateAssignment", +"url":26, "doc":"A :class: NodeVisitor subclass that walks the abstract syntax tree and allows modification of nodes. The NodeTransformer will walk the AST and use the return value of the visitor methods to replace or remove the old node. If the return value of the visitor method is None , the node will be removed from its location, otherwise it is replaced with the return value. The return value may be the original node in which case no replacement takes place. Here is an example transformer that rewrites all occurrences of name lookups ( foo ) to data['foo'] class RewriteName(NodeTransformer): def visit_Name(self, node): return Subscript( value=Name(id='data', ctx=Load( , slice=Index(value=Str(s=node.id , ctx=node.ctx ) Keep in mind that if the node you're operating on has child nodes you must either transform the child nodes yourself or call the :meth: generic_visit method for the node first. For nodes that were part of a collection of statements (that applies to all statement nodes), the visitor may also return a list of nodes rather than just a single node. Usually you use the transformer like this node = YourTransformer().visit(node)" }, { -"ref":"hebi.type_inference.AggressiveTypeInferencer.step", -"url":32, +"ref":"hebi.rewrite.rewrite_duplicate_assignment.RewriteDuplicateAssignment.step", +"url":26, "doc":"" }, { -"ref":"hebi.type_inference.AggressiveTypeInferencer.scopes", -"url":32, +"ref":"hebi.rewrite.rewrite_duplicate_assignment.RewriteDuplicateAssignment.avail_names", +"url":26, "doc":"" }, { -"ref":"hebi.type_inference.AggressiveTypeInferencer.variable_type", -"url":32, -"doc":"", -"func":1 -}, -{ -"ref":"hebi.type_inference.AggressiveTypeInferencer.enter_scope", -"url":32, +"ref":"hebi.rewrite.rewrite_duplicate_assignment.RewriteDuplicateAssignment.avail", +"url":26, "doc":"", "func":1 }, { -"ref":"hebi.type_inference.AggressiveTypeInferencer.exit_scope", -"url":32, +"ref":"hebi.rewrite.rewrite_duplicate_assignment.RewriteDuplicateAssignment.in_current_scope", +"url":26, "doc":"", "func":1 }, { -"ref":"hebi.type_inference.AggressiveTypeInferencer.set_variable_type", -"url":32, +"ref":"hebi.rewrite.rewrite_duplicate_assignment.RewriteDuplicateAssignment.enter_scope", +"url":26, "doc":"", "func":1 }, { -"ref":"hebi.type_inference.AggressiveTypeInferencer.type_from_annotation", -"url":32, +"ref":"hebi.rewrite.rewrite_duplicate_assignment.RewriteDuplicateAssignment.exit_scope", +"url":26, "doc":"", "func":1 }, { -"ref":"hebi.type_inference.AggressiveTypeInferencer.visit_ClassDef", -"url":32, +"ref":"hebi.rewrite.rewrite_duplicate_assignment.RewriteDuplicateAssignment.set_avail", +"url":26, "doc":"", "func":1 }, { -"ref":"hebi.type_inference.AggressiveTypeInferencer.visit_Constant", -"url":32, +"ref":"hebi.rewrite.rewrite_duplicate_assignment.RewriteDuplicateAssignment.visit_Module", +"url":26, "doc":"", "func":1 }, { -"ref":"hebi.type_inference.AggressiveTypeInferencer.visit_Tuple", -"url":32, +"ref":"hebi.rewrite.rewrite_duplicate_assignment.RewriteDuplicateAssignment.visit_If", +"url":26, "doc":"", "func":1 }, { -"ref":"hebi.type_inference.AggressiveTypeInferencer.visit_List", -"url":32, +"ref":"hebi.rewrite.rewrite_duplicate_assignment.RewriteDuplicateAssignment.visit_Assign", +"url":26, "doc":"", "func":1 }, { -"ref":"hebi.type_inference.AggressiveTypeInferencer.visit_Dict", -"url":32, +"ref":"hebi.rewrite.rewrite_duplicate_assignment.RewriteDuplicateAssignment.visit_AnnAssign", +"url":26, "doc":"", "func":1 }, { -"ref":"hebi.type_inference.AggressiveTypeInferencer.visit_Assign", -"url":32, +"ref":"hebi.rewrite.rewrite_duplicate_assignment.RewriteDuplicateAssignment.visit_ClassDef", +"url":26, "doc":"", "func":1 }, { -"ref":"hebi.type_inference.AggressiveTypeInferencer.visit_AnnAssign", -"url":32, +"ref":"hebi.rewrite.rewrite_duplicate_assignment.RewriteDuplicateAssignment.visit_FunctionDef", +"url":26, "doc":"", "func":1 }, { -"ref":"hebi.type_inference.AggressiveTypeInferencer.visit_If", -"url":32, -"doc":"", +"ref":"hebi.rewrite.rewrite_duplicate_assignment.RewriteDuplicateAssignment.visit", +"url":19, +"doc":"Visit a node.", "func":1 }, { -"ref":"hebi.type_inference.AggressiveTypeInferencer.visit_While", -"url":32, -"doc":"", -"func":1 +"ref":"hebi.rewrite.rewrite_import_typing", +"url":27, +"doc":"" }, { -"ref":"hebi.type_inference.AggressiveTypeInferencer.visit_For", -"url":32, -"doc":"", -"func":1 +"ref":"hebi.rewrite.rewrite_import_typing.RewriteImportTyping", +"url":27, +"doc":"A :class: NodeVisitor subclass that walks the abstract syntax tree and allows modification of nodes. The NodeTransformer will walk the AST and use the return value of the visitor methods to replace or remove the old node. If the return value of the visitor method is None , the node will be removed from its location, otherwise it is replaced with the return value. The return value may be the original node in which case no replacement takes place. Here is an example transformer that rewrites all occurrences of name lookups ( foo ) to data['foo'] class RewriteName(NodeTransformer): def visit_Name(self, node): return Subscript( value=Name(id='data', ctx=Load( , slice=Index(value=Str(s=node.id , ctx=node.ctx ) Keep in mind that if the node you're operating on has child nodes you must either transform the child nodes yourself or call the :meth: generic_visit method for the node first. For nodes that were part of a collection of statements (that applies to all statement nodes), the visitor may also return a list of nodes rather than just a single node. Usually you use the transformer like this node = YourTransformer().visit(node)" }, { -"ref":"hebi.type_inference.AggressiveTypeInferencer.visit_Name", -"url":32, -"doc":"", -"func":1 +"ref":"hebi.rewrite.rewrite_import_typing.RewriteImportTyping.step", +"url":27, +"doc":"" }, { -"ref":"hebi.type_inference.AggressiveTypeInferencer.visit_Compare", -"url":32, -"doc":"", -"func":1 +"ref":"hebi.rewrite.rewrite_import_typing.RewriteImportTyping.imports_typing", +"url":27, +"doc":"" }, { -"ref":"hebi.type_inference.AggressiveTypeInferencer.visit_arg", -"url":32, +"ref":"hebi.rewrite.rewrite_import_typing.RewriteImportTyping.visit_ImportFrom", +"url":27, "doc":"", "func":1 }, { -"ref":"hebi.type_inference.AggressiveTypeInferencer.visit_arguments", -"url":32, +"ref":"hebi.rewrite.rewrite_import_typing.RewriteImportTyping.visit_ClassDef", +"url":27, "doc":"", "func":1 }, { -"ref":"hebi.type_inference.AggressiveTypeInferencer.visit_FunctionDef", -"url":32, -"doc":"", +"ref":"hebi.rewrite.rewrite_import_typing.RewriteImportTyping.visit", +"url":19, +"doc":"Visit a node.", "func":1 }, { -"ref":"hebi.type_inference.AggressiveTypeInferencer.visit_Module", -"url":32, -"doc":"", -"func":1 +"ref":"hebi.rewrite.rewrite_inject_builtin_constr", +"url":28, +"doc":"" }, { -"ref":"hebi.type_inference.AggressiveTypeInferencer.visit_Expr", -"url":32, -"doc":"", -"func":1 +"ref":"hebi.rewrite.rewrite_inject_builtin_constr.RewriteInjectBuiltinsConstr", +"url":28, +"doc":"A :class: NodeVisitor subclass that walks the abstract syntax tree and allows modification of nodes. The NodeTransformer will walk the AST and use the return value of the visitor methods to replace or remove the old node. If the return value of the visitor method is None , the node will be removed from its location, otherwise it is replaced with the return value. The return value may be the original node in which case no replacement takes place. Here is an example transformer that rewrites all occurrences of name lookups ( foo ) to data['foo'] class RewriteName(NodeTransformer): def visit_Name(self, node): return Subscript( value=Name(id='data', ctx=Load( , slice=Index(value=Str(s=node.id , ctx=node.ctx ) Keep in mind that if the node you're operating on has child nodes you must either transform the child nodes yourself or call the :meth: generic_visit method for the node first. For nodes that were part of a collection of statements (that applies to all statement nodes), the visitor may also return a list of nodes rather than just a single node. Usually you use the transformer like this node = YourTransformer().visit(node)" }, { -"ref":"hebi.type_inference.AggressiveTypeInferencer.visit_BinOp", -"url":32, -"doc":"", -"func":1 +"ref":"hebi.rewrite.rewrite_inject_builtin_constr.RewriteInjectBuiltinsConstr.step", +"url":28, +"doc":"" }, { -"ref":"hebi.type_inference.AggressiveTypeInferencer.visit_BoolOp", -"url":32, +"ref":"hebi.rewrite.rewrite_inject_builtin_constr.RewriteInjectBuiltinsConstr.visit_Module", +"url":28, "doc":"", "func":1 }, { -"ref":"hebi.type_inference.AggressiveTypeInferencer.visit_UnaryOp", -"url":32, -"doc":"", +"ref":"hebi.rewrite.rewrite_inject_builtin_constr.RewriteInjectBuiltinsConstr.visit", +"url":19, +"doc":"Visit a node.", "func":1 }, { -"ref":"hebi.type_inference.AggressiveTypeInferencer.visit_Subscript", -"url":32, -"doc":"", -"func":1 +"ref":"hebi.rewrite.rewrite_import_dataclasses", +"url":29, +"doc":"" }, { -"ref":"hebi.type_inference.AggressiveTypeInferencer.visit_Call", -"url":32, -"doc":"", -"func":1 +"ref":"hebi.rewrite.rewrite_import_dataclasses.RewriteImportDataclasses", +"url":29, +"doc":"A :class: NodeVisitor subclass that walks the abstract syntax tree and allows modification of nodes. The NodeTransformer will walk the AST and use the return value of the visitor methods to replace or remove the old node. If the return value of the visitor method is None , the node will be removed from its location, otherwise it is replaced with the return value. The return value may be the original node in which case no replacement takes place. Here is an example transformer that rewrites all occurrences of name lookups ( foo ) to data['foo'] class RewriteName(NodeTransformer): def visit_Name(self, node): return Subscript( value=Name(id='data', ctx=Load( , slice=Index(value=Str(s=node.id , ctx=node.ctx ) Keep in mind that if the node you're operating on has child nodes you must either transform the child nodes yourself or call the :meth: generic_visit method for the node first. For nodes that were part of a collection of statements (that applies to all statement nodes), the visitor may also return a list of nodes rather than just a single node. Usually you use the transformer like this node = YourTransformer().visit(node)" }, { -"ref":"hebi.type_inference.AggressiveTypeInferencer.visit_Pass", -"url":32, -"doc":"", -"func":1 +"ref":"hebi.rewrite.rewrite_import_dataclasses.RewriteImportDataclasses.step", +"url":29, +"doc":"" }, { -"ref":"hebi.type_inference.AggressiveTypeInferencer.visit_Return", -"url":32, -"doc":"", -"func":1 +"ref":"hebi.rewrite.rewrite_import_dataclasses.RewriteImportDataclasses.imports_dataclasses", +"url":29, +"doc":"" }, { -"ref":"hebi.type_inference.AggressiveTypeInferencer.visit_Attribute", -"url":32, +"ref":"hebi.rewrite.rewrite_import_dataclasses.RewriteImportDataclasses.visit_ImportFrom", +"url":29, "doc":"", "func":1 }, { -"ref":"hebi.type_inference.AggressiveTypeInferencer.visit_Assert", -"url":32, +"ref":"hebi.rewrite.rewrite_import_dataclasses.RewriteImportDataclasses.visit_ClassDef", +"url":29, "doc":"", "func":1 }, { -"ref":"hebi.type_inference.AggressiveTypeInferencer.visit_RawPlutoExpr", -"url":32, -"doc":"", +"ref":"hebi.rewrite.rewrite_import_dataclasses.RewriteImportDataclasses.visit", +"url":19, +"doc":"Visit a node.", "func":1 }, { -"ref":"hebi.type_inference.AggressiveTypeInferencer.visit_IfExp", -"url":32, -"doc":"", -"func":1 +"ref":"hebi.rewrite.rewrite_subscript38", +"url":30, +"doc":"" }, { -"ref":"hebi.type_inference.AggressiveTypeInferencer.visit_comprehension", -"url":32, -"doc":"", -"func":1 +"ref":"hebi.rewrite.rewrite_subscript38.RewriteSubscript38", +"url":30, +"doc":"A :class: NodeVisitor subclass that walks the abstract syntax tree and allows modification of nodes. The NodeTransformer will walk the AST and use the return value of the visitor methods to replace or remove the old node. If the return value of the visitor method is None , the node will be removed from its location, otherwise it is replaced with the return value. The return value may be the original node in which case no replacement takes place. Here is an example transformer that rewrites all occurrences of name lookups ( foo ) to data['foo'] class RewriteName(NodeTransformer): def visit_Name(self, node): return Subscript( value=Name(id='data', ctx=Load( , slice=Index(value=Str(s=node.id , ctx=node.ctx ) Keep in mind that if the node you're operating on has child nodes you must either transform the child nodes yourself or call the :meth: generic_visit method for the node first. For nodes that were part of a collection of statements (that applies to all statement nodes), the visitor may also return a list of nodes rather than just a single node. Usually you use the transformer like this node = YourTransformer().visit(node)" }, { -"ref":"hebi.type_inference.AggressiveTypeInferencer.visit_ListComp", -"url":32, -"doc":"", -"func":1 +"ref":"hebi.rewrite.rewrite_subscript38.RewriteSubscript38.step", +"url":30, +"doc":"" }, { -"ref":"hebi.type_inference.AggressiveTypeInferencer.generic_visit", -"url":32, -"doc":"Called if no explicit visitor function exists for a node.", +"ref":"hebi.rewrite.rewrite_subscript38.RewriteSubscript38.visit_Index", +"url":30, +"doc":"", "func":1 }, { -"ref":"hebi.type_inference.AggressiveTypeInferencer.visit", -"url":14, +"ref":"hebi.rewrite.rewrite_subscript38.RewriteSubscript38.visit", +"url":19, "doc":"Visit a node.", "func":1 }, { -"ref":"hebi.type_inference.RecordReader", -"url":32, -"doc":"A node visitor base class that walks the abstract syntax tree and calls a visitor function for every node found. This function may return a value which is forwarded by the visit method. This class is meant to be subclassed, with the subclass adding visitor methods. Per default the visitor functions for the nodes are 'visit_' + class name of the node. So a TryFinally node visit function would be visit_TryFinally . This behavior can be changed by overriding the visit method. If no visitor function exists for a node (return value None ) the generic_visit visitor is used instead. Don't use the NodeVisitor if you want to apply changes to nodes during traversing. For this a special visitor exists ( NodeTransformer ) that allows modifications." +"ref":"hebi.rewrite.rewrite_forbidden_overwrites", +"url":31, +"doc":"" }, { -"ref":"hebi.type_inference.RecordReader.name", -"url":32, -"doc":"" +"ref":"hebi.rewrite.rewrite_forbidden_overwrites.ForbiddenOverwriteError", +"url":31, +"doc":"Inappropriate argument value (of correct type)." }, { -"ref":"hebi.type_inference.RecordReader.constructor", -"url":32, -"doc":"" +"ref":"hebi.rewrite.rewrite_forbidden_overwrites.RewriteForbiddenOverwrites", +"url":31, +"doc":"A :class: NodeVisitor subclass that walks the abstract syntax tree and allows modification of nodes. The NodeTransformer will walk the AST and use the return value of the visitor methods to replace or remove the old node. If the return value of the visitor method is None , the node will be removed from its location, otherwise it is replaced with the return value. The return value may be the original node in which case no replacement takes place. Here is an example transformer that rewrites all occurrences of name lookups ( foo ) to data['foo'] class RewriteName(NodeTransformer): def visit_Name(self, node): return Subscript( value=Name(id='data', ctx=Load( , slice=Index(value=Str(s=node.id , ctx=node.ctx ) Keep in mind that if the node you're operating on has child nodes you must either transform the child nodes yourself or call the :meth: generic_visit method for the node first. For nodes that were part of a collection of statements (that applies to all statement nodes), the visitor may also return a list of nodes rather than just a single node. Usually you use the transformer like this node = YourTransformer().visit(node)" }, { -"ref":"hebi.type_inference.RecordReader.attributes", -"url":32, +"ref":"hebi.rewrite.rewrite_forbidden_overwrites.RewriteForbiddenOverwrites.step", +"url":31, "doc":"" }, { -"ref":"hebi.type_inference.RecordReader.extract", -"url":32, +"ref":"hebi.rewrite.rewrite_forbidden_overwrites.RewriteForbiddenOverwrites.visit_Name", +"url":31, "doc":"", "func":1 }, { -"ref":"hebi.type_inference.RecordReader.visit_AnnAssign", -"url":32, -"doc":"", +"ref":"hebi.rewrite.rewrite_forbidden_overwrites.RewriteForbiddenOverwrites.visit", +"url":19, +"doc":"Visit a node.", "func":1 }, { -"ref":"hebi.type_inference.RecordReader.visit_ClassDef", +"ref":"hebi.rewrite.rewrite_inject_builtins", "url":32, -"doc":"", -"func":1 +"doc":"" }, { -"ref":"hebi.type_inference.RecordReader.visit_Pass", +"ref":"hebi.rewrite.rewrite_inject_builtins.RewriteInjectBuiltins", "url":32, -"doc":"", -"func":1 +"doc":"A :class: NodeVisitor subclass that walks the abstract syntax tree and allows modification of nodes. The NodeTransformer will walk the AST and use the return value of the visitor methods to replace or remove the old node. If the return value of the visitor method is None , the node will be removed from its location, otherwise it is replaced with the return value. The return value may be the original node in which case no replacement takes place. Here is an example transformer that rewrites all occurrences of name lookups ( foo ) to data['foo'] class RewriteName(NodeTransformer): def visit_Name(self, node): return Subscript( value=Name(id='data', ctx=Load( , slice=Index(value=Str(s=node.id , ctx=node.ctx ) Keep in mind that if the node you're operating on has child nodes you must either transform the child nodes yourself or call the :meth: generic_visit method for the node first. For nodes that were part of a collection of statements (that applies to all statement nodes), the visitor may also return a list of nodes rather than just a single node. Usually you use the transformer like this node = YourTransformer().visit(node)" }, { -"ref":"hebi.type_inference.RecordReader.visit_Assign", +"ref":"hebi.rewrite.rewrite_inject_builtins.RewriteInjectBuiltins.step", "url":32, -"doc":"", -"func":1 +"doc":"" }, { -"ref":"hebi.type_inference.RecordReader.visit_Expr", +"ref":"hebi.rewrite.rewrite_inject_builtins.RewriteInjectBuiltins.visit_Module", "url":32, "doc":"", "func":1 }, { -"ref":"hebi.type_inference.RecordReader.generic_visit", -"url":32, -"doc":"Called if no explicit visitor function exists for a node.", -"func":1 -}, -{ -"ref":"hebi.type_inference.typed_ast", -"url":32, -"doc":"", +"ref":"hebi.rewrite.rewrite_inject_builtins.RewriteInjectBuiltins.visit", +"url":19, +"doc":"Visit a node.", "func":1 }, { -"ref":"hebi.util", -"url":14, -"doc":"" -}, -{ -"ref":"hebi.util.PythonBuiltIn", -"url":14, -"doc":"An enumeration." -}, -{ -"ref":"hebi.util.PythonBuiltIn.all", -"url":14, -"doc":"" -}, -{ -"ref":"hebi.util.PythonBuiltIn.any", -"url":14, +"ref":"hebi.rewrite.rewrite_import_plutusdata", +"url":33, "doc":"" }, { -"ref":"hebi.util.PythonBuiltIn.abs", -"url":14, -"doc":"" +"ref":"hebi.rewrite.rewrite_import_plutusdata.RewriteImportPlutusData", +"url":33, +"doc":"A :class: NodeVisitor subclass that walks the abstract syntax tree and allows modification of nodes. The NodeTransformer will walk the AST and use the return value of the visitor methods to replace or remove the old node. If the return value of the visitor method is None , the node will be removed from its location, otherwise it is replaced with the return value. The return value may be the original node in which case no replacement takes place. Here is an example transformer that rewrites all occurrences of name lookups ( foo ) to data['foo'] class RewriteName(NodeTransformer): def visit_Name(self, node): return Subscript( value=Name(id='data', ctx=Load( , slice=Index(value=Str(s=node.id , ctx=node.ctx ) Keep in mind that if the node you're operating on has child nodes you must either transform the child nodes yourself or call the :meth: generic_visit method for the node first. For nodes that were part of a collection of statements (that applies to all statement nodes), the visitor may also return a list of nodes rather than just a single node. Usually you use the transformer like this node = YourTransformer().visit(node)" }, { -"ref":"hebi.util.PythonBuiltIn.chr", -"url":14, +"ref":"hebi.rewrite.rewrite_import_plutusdata.RewriteImportPlutusData.step", +"url":33, "doc":"" }, { -"ref":"hebi.util.PythonBuiltIn.breakpoint", -"url":14, +"ref":"hebi.rewrite.rewrite_import_plutusdata.RewriteImportPlutusData.imports_plutus_data", +"url":33, "doc":"" }, { -"ref":"hebi.util.PythonBuiltIn.hex", -"url":14, -"doc":"" +"ref":"hebi.rewrite.rewrite_import_plutusdata.RewriteImportPlutusData.visit_ImportFrom", +"url":33, +"doc":"", +"func":1 }, { -"ref":"hebi.util.PythonBuiltIn.len", -"url":14, -"doc":"" +"ref":"hebi.rewrite.rewrite_import_plutusdata.RewriteImportPlutusData.visit_ClassDef", +"url":33, +"doc":"", +"func":1 }, { -"ref":"hebi.util.PythonBuiltIn.max", -"url":14, -"doc":"" +"ref":"hebi.rewrite.rewrite_import_plutusdata.RewriteImportPlutusData.visit", +"url":19, +"doc":"Visit a node.", +"func":1 }, { -"ref":"hebi.util.PythonBuiltIn.min", -"url":14, +"ref":"hebi.rewrite.rewrite_zero_ary", +"url":34, "doc":"" }, { -"ref":"hebi.util.PythonBuiltIn.print", -"url":14, -"doc":"" +"ref":"hebi.rewrite.rewrite_zero_ary.RewriteZeroAry", +"url":34, +"doc":"A :class: NodeVisitor subclass that walks the abstract syntax tree and allows modification of nodes. The NodeTransformer will walk the AST and use the return value of the visitor methods to replace or remove the old node. If the return value of the visitor method is None , the node will be removed from its location, otherwise it is replaced with the return value. The return value may be the original node in which case no replacement takes place. Here is an example transformer that rewrites all occurrences of name lookups ( foo ) to data['foo'] class RewriteName(NodeTransformer): def visit_Name(self, node): return Subscript( value=Name(id='data', ctx=Load( , slice=Index(value=Str(s=node.id , ctx=node.ctx ) Keep in mind that if the node you're operating on has child nodes you must either transform the child nodes yourself or call the :meth: generic_visit method for the node first. For nodes that were part of a collection of statements (that applies to all statement nodes), the visitor may also return a list of nodes rather than just a single node. Usually you use the transformer like this node = YourTransformer().visit(node)" }, { -"ref":"hebi.util.PythonBuiltIn.pow", -"url":14, +"ref":"hebi.rewrite.rewrite_zero_ary.RewriteZeroAry.step", +"url":34, "doc":"" }, { -"ref":"hebi.util.PythonBuiltIn.oct", -"url":14, -"doc":"" +"ref":"hebi.rewrite.rewrite_zero_ary.RewriteZeroAry.visit_FunctionDef", +"url":34, +"doc":"", +"func":1 }, { -"ref":"hebi.util.PythonBuiltIn.range", -"url":14, -"doc":"" +"ref":"hebi.rewrite.rewrite_zero_ary.RewriteZeroAry.visit_Call", +"url":34, +"doc":"", +"func":1 }, { -"ref":"hebi.util.PythonBuiltIn.reversed", -"url":14, -"doc":"" +"ref":"hebi.rewrite.rewrite_zero_ary.RewriteZeroAry.visit", +"url":19, +"doc":"Visit a node.", +"func":1 }, { -"ref":"hebi.util.PythonBuiltIn.sum", -"url":14, +"ref":"hebi.rewrite.rewrite_import_hashlib", +"url":35, "doc":"" }, { -"ref":"hebi.util.LenImpl", -"url":14, -"doc":"" +"ref":"hebi.rewrite.rewrite_import_hashlib.HashType", +"url":35, +"doc":"A pseudo class that is the result of python hash functions that need a 'digest' call" }, { -"ref":"hebi.util.LenImpl.type_from_args", -"url":14, -"doc":"", +"ref":"hebi.rewrite.rewrite_import_hashlib.HashType.attribute_type", +"url":35, +"doc":"The types of the named attributes of this class", "func":1 }, { -"ref":"hebi.util.LenImpl.impl_from_args", -"url":14, -"doc":"", +"ref":"hebi.rewrite.rewrite_import_hashlib.HashType.attribute", +"url":35, +"doc":"The attributes of this class. Needs to be a lambda that expects as first argument the object itself", "func":1 }, { -"ref":"hebi.util.ReversedImpl", -"url":14, -"doc":"" +"ref":"hebi.rewrite.rewrite_import_hashlib.HashType.constr_type", +"url":1, +"doc":"The type of the constructor for this class", +"func":1 }, { -"ref":"hebi.util.ReversedImpl.type_from_args", -"url":14, -"doc":"", +"ref":"hebi.rewrite.rewrite_import_hashlib.HashType.constr", +"url":1, +"doc":"The constructor for this class", "func":1 }, { -"ref":"hebi.util.ReversedImpl.impl_from_args", -"url":14, -"doc":"", +"ref":"hebi.rewrite.rewrite_import_hashlib.HashType.cmp", +"url":1, +"doc":"The implementation of comparing this type to type o via operator op. Returns a lambda that expects as first argument the object itself and as second the comparison.", "func":1 }, { -"ref":"hebi.util.CompilerError", -"url":14, -"doc":"Common base class for all non-exit exceptions." +"ref":"hebi.rewrite.rewrite_import_hashlib.PythonHashlib", +"url":35, +"doc":"An enumeration." }, { -"ref":"hebi.util.CompilingNodeTransformer", -"url":14, -"doc":"A :class: NodeVisitor subclass that walks the abstract syntax tree and allows modification of nodes. The NodeTransformer will walk the AST and use the return value of the visitor methods to replace or remove the old node. If the return value of the visitor method is None , the node will be removed from its location, otherwise it is replaced with the return value. The return value may be the original node in which case no replacement takes place. Here is an example transformer that rewrites all occurrences of name lookups ( foo ) to data['foo'] class RewriteName(NodeTransformer): def visit_Name(self, node): return Subscript( value=Name(id='data', ctx=Load( , slice=Index(value=Str(s=node.id , ctx=node.ctx ) Keep in mind that if the node you're operating on has child nodes you must either transform the child nodes yourself or call the :meth: generic_visit method for the node first. For nodes that were part of a collection of statements (that applies to all statement nodes), the visitor may also return a list of nodes rather than just a single node. Usually you use the transformer like this node = YourTransformer().visit(node)" +"ref":"hebi.rewrite.rewrite_import_hashlib.PythonHashlib.sha256", +"url":35, +"doc":"" }, { -"ref":"hebi.util.CompilingNodeTransformer.step", -"url":14, +"ref":"hebi.rewrite.rewrite_import_hashlib.PythonHashlib.sha3_256", +"url":35, "doc":"" }, { -"ref":"hebi.util.CompilingNodeTransformer.visit", -"url":14, -"doc":"Visit a node.", -"func":1 +"ref":"hebi.rewrite.rewrite_import_hashlib.PythonHashlib.blake2b", +"url":35, +"doc":"" }, { -"ref":"hebi.util.CompilingNodeVisitor", -"url":14, -"doc":"A node visitor base class that walks the abstract syntax tree and calls a visitor function for every node found. This function may return a value which is forwarded by the visit method. This class is meant to be subclassed, with the subclass adding visitor methods. Per default the visitor functions for the nodes are 'visit_' + class name of the node. So a TryFinally node visit function would be visit_TryFinally . This behavior can be changed by overriding the visit method. If no visitor function exists for a node (return value None ) the generic_visit visitor is used instead. Don't use the NodeVisitor if you want to apply changes to nodes during traversing. For this a special visitor exists ( NodeTransformer ) that allows modifications." +"ref":"hebi.rewrite.rewrite_import_hashlib.RewriteImportHashlib", +"url":35, +"doc":"A :class: NodeVisitor subclass that walks the abstract syntax tree and allows modification of nodes. The NodeTransformer will walk the AST and use the return value of the visitor methods to replace or remove the old node. If the return value of the visitor method is None , the node will be removed from its location, otherwise it is replaced with the return value. The return value may be the original node in which case no replacement takes place. Here is an example transformer that rewrites all occurrences of name lookups ( foo ) to data['foo'] class RewriteName(NodeTransformer): def visit_Name(self, node): return Subscript( value=Name(id='data', ctx=Load( , slice=Index(value=Str(s=node.id , ctx=node.ctx ) Keep in mind that if the node you're operating on has child nodes you must either transform the child nodes yourself or call the :meth: generic_visit method for the node first. For nodes that were part of a collection of statements (that applies to all statement nodes), the visitor may also return a list of nodes rather than just a single node. Usually you use the transformer like this node = YourTransformer().visit(node)" }, { -"ref":"hebi.util.CompilingNodeVisitor.step", -"url":14, +"ref":"hebi.rewrite.rewrite_import_hashlib.RewriteImportHashlib.step", +"url":35, "doc":"" }, { -"ref":"hebi.util.CompilingNodeVisitor.visit", -"url":14, -"doc":"Visit a node.", -"func":1 +"ref":"hebi.rewrite.rewrite_import_hashlib.RewriteImportHashlib.imports_hashlib", +"url":35, +"doc":"" }, { -"ref":"hebi.util.data_from_json", -"url":14, +"ref":"hebi.rewrite.rewrite_import_hashlib.RewriteImportHashlib.visit_ImportFrom", +"url":35, "doc":"", "func":1 }, { -"ref":"hebi.prelude", -"url":33, -"doc":"" -}, -{ -"ref":"hebi.prelude.TxId", -"url":33, -"doc":"A transaction id, a 64 bytes long hash of the transaction body (also called transaction hash). Example value: TxId(bytes.fromhex(\"842a4d37b036da6ab3c04331240e67d81746beb44f23ad79703e026705361956\" " +"ref":"hebi.rewrite.rewrite_import_hashlib.RewriteImportHashlib.visit", +"url":19, +"doc":"Visit a node.", +"func":1 }, { -"ref":"hebi.prelude.TxId.tx_id", -"url":33, +"ref":"hebi.rewrite.rewrite_tuple_assign", +"url":36, "doc":"" }, { -"ref":"hebi.prelude.Nothing", -"url":33, -"doc":"Nothing, can be used to signify non-importance of a parameter to a function Example value: Nothing()" +"ref":"hebi.rewrite.rewrite_tuple_assign.RewriteTupleAssign", +"url":36, +"doc":"A :class: NodeVisitor subclass that walks the abstract syntax tree and allows modification of nodes. The NodeTransformer will walk the AST and use the return value of the visitor methods to replace or remove the old node. If the return value of the visitor method is None , the node will be removed from its location, otherwise it is replaced with the return value. The return value may be the original node in which case no replacement takes place. Here is an example transformer that rewrites all occurrences of name lookups ( foo ) to data['foo'] class RewriteName(NodeTransformer): def visit_Name(self, node): return Subscript( value=Name(id='data', ctx=Load( , slice=Index(value=Str(s=node.id , ctx=node.ctx ) Keep in mind that if the node you're operating on has child nodes you must either transform the child nodes yourself or call the :meth: generic_visit method for the node first. For nodes that were part of a collection of statements (that applies to all statement nodes), the visitor may also return a list of nodes rather than just a single node. Usually you use the transformer like this node = YourTransformer().visit(node)" }, { -"ref":"hebi.prelude.Nothing.CONSTR_ID", -"url":33, +"ref":"hebi.rewrite.rewrite_tuple_assign.RewriteTupleAssign.step", +"url":36, "doc":"" }, { -"ref":"hebi.prelude.TrueData", -"url":33, -"doc":"A Datum that represents True in Haskell implementations. It is thus used as an encoding for True in the ScriptContext. Example value: TrueData()" -}, -{ -"ref":"hebi.prelude.TrueData.CONSTR_ID", -"url":33, +"ref":"hebi.rewrite.rewrite_tuple_assign.RewriteTupleAssign.unique_id", +"url":36, "doc":"" }, { -"ref":"hebi.prelude.FalseData", -"url":33, -"doc":"A Datum that represents False in Haskell implementations. It is thus used as an encoding for False in the ScriptContext. Example value: FalseData()" +"ref":"hebi.rewrite.rewrite_tuple_assign.RewriteTupleAssign.visit_Assign", +"url":36, +"doc":"", +"func":1 }, { -"ref":"hebi.prelude.FalseData.CONSTR_ID", -"url":33, -"doc":"" +"ref":"hebi.rewrite.rewrite_tuple_assign.RewriteTupleAssign.visit_For", +"url":36, +"doc":"", +"func":1 }, { -"ref":"hebi.prelude.TxOutRef", -"url":33, -"doc":"A reference to a transaction output (hash/id + index)" +"ref":"hebi.rewrite.rewrite_tuple_assign.RewriteTupleAssign.visit", +"url":19, +"doc":"Visit a node.", +"func":1 }, { -"ref":"hebi.prelude.TxOutRef.id", -"url":33, +"ref":"hebi.rewrite.rewrite_import", +"url":37, "doc":"" }, { -"ref":"hebi.prelude.TxOutRef.idx", -"url":33, -"doc":"" +"ref":"hebi.rewrite.rewrite_import.import_module", +"url":37, +"doc":"An approximate implementation of import.", +"func":1 }, { -"ref":"hebi.prelude.PubKeyCredential", -"url":33, -"doc":"Part of an address that is authenticated by a public key hash Example value: PubKeyCredential(bytes.fromhex(\"c06ddaad12fc4ded18e56feac72957c1aa75fce6096b40e63ec88274\" " +"ref":"hebi.rewrite.rewrite_import.RewriteImport", +"url":37, +"doc":"A :class: NodeVisitor subclass that walks the abstract syntax tree and allows modification of nodes. The NodeTransformer will walk the AST and use the return value of the visitor methods to replace or remove the old node. If the return value of the visitor method is None , the node will be removed from its location, otherwise it is replaced with the return value. The return value may be the original node in which case no replacement takes place. Here is an example transformer that rewrites all occurrences of name lookups ( foo ) to data['foo'] class RewriteName(NodeTransformer): def visit_Name(self, node): return Subscript( value=Name(id='data', ctx=Load( , slice=Index(value=Str(s=node.id , ctx=node.ctx ) Keep in mind that if the node you're operating on has child nodes you must either transform the child nodes yourself or call the :meth: generic_visit method for the node first. For nodes that were part of a collection of statements (that applies to all statement nodes), the visitor may also return a list of nodes rather than just a single node. Usually you use the transformer like this node = YourTransformer().visit(node)" }, { -"ref":"hebi.prelude.PubKeyCredential.credential_hash", -"url":33, +"ref":"hebi.rewrite.rewrite_import.RewriteImport.step", +"url":37, "doc":"" }, { -"ref":"hebi.prelude.PubKeyCredential.CONSTR_ID", -"url":33, -"doc":"" +"ref":"hebi.rewrite.rewrite_import.RewriteImport.visit_ImportFrom", +"url":37, +"doc":"", +"func":1 }, { -"ref":"hebi.prelude.ScriptCredential", -"url":33, -"doc":"Part of an address that is authenticated by a smart cotnract Example value: ScriptCredential(bytes.fromhex(\"c06ddaad12fc4ded18e56feac72957c1aa75fce6096b40e63ec88274\" " +"ref":"hebi.rewrite.rewrite_import.RewriteImport.visit", +"url":19, +"doc":"Visit a node.", +"func":1 }, { -"ref":"hebi.prelude.ScriptCredential.credential_hash", -"url":33, +"ref":"hebi.std", +"url":38, "doc":"" }, { -"ref":"hebi.prelude.ScriptCredential.CONSTR_ID", -"url":33, -"doc":"" +"ref":"hebi.std.math", +"url":39, +"doc":"An implementation of some math operations in opshin" }, { -"ref":"hebi.prelude.StakingHash", -"url":33, -"doc":"Indicates that the stake of this address is controlled by the associated credential" +"ref":"hebi.std.math.gcd", +"url":39, +"doc":"", +"func":1 }, { -"ref":"hebi.prelude.StakingHash.value", -"url":33, -"doc":"" +"ref":"hebi.std.math.sign", +"url":39, +"doc":"", +"func":1 }, { -"ref":"hebi.prelude.StakingHash.CONSTR_ID", -"url":33, -"doc":"" +"ref":"hebi.std.math.unsigned_int_from_bytes_big", +"url":39, +"doc":"Converts a bytestring into the corresponding integer, big/network byteorder, unsigned", +"func":1 }, { -"ref":"hebi.prelude.StakingPtr", -"url":33, -"doc":"Indicates that the stake of this address is controlled by the associated pointer. In an address, a chain pointer refers to a point of the chain containing a stake key registration certificate. A point is identified by the 3 coordinates in this object." +"ref":"hebi.std.fractions", +"url":40, +"doc":"An implementation of fractions in opshin This does not maintain smallest possible notation invariants for the sake of efficiency - the user has full control over when to normalize the fractions and should do so using norm_fraction" }, { -"ref":"hebi.prelude.StakingPtr.slot_no", -"url":33, -"doc":"" +"ref":"hebi.std.fractions.Fraction", +"url":40, +"doc":"Fraction(numerator: int, denominator: int)" }, { -"ref":"hebi.prelude.StakingPtr.tx_index", -"url":33, +"ref":"hebi.std.fractions.Fraction.numerator", +"url":40, "doc":"" }, { -"ref":"hebi.prelude.StakingPtr.cert_index", -"url":33, +"ref":"hebi.std.fractions.Fraction.denominator", +"url":40, "doc":"" }, { -"ref":"hebi.prelude.StakingPtr.CONSTR_ID", -"url":33, +"ref":"hebi.std.fractions.Fraction.CONSTR_ID", +"url":40, "doc":"" }, { -"ref":"hebi.prelude.NoStakingCredential", -"url":33, -"doc":"Indicates that this address has no staking credentials. Its funds can not be delegated." +"ref":"hebi.std.fractions.add_fraction", +"url":40, +"doc":"returns a + b", +"func":1 }, { -"ref":"hebi.prelude.NoStakingCredential.CONSTR_ID", -"url":33, -"doc":"" +"ref":"hebi.std.fractions.neg_fraction", +"url":40, +"doc":"returns -a", +"func":1 }, { -"ref":"hebi.prelude.SomeStakingCredential", -"url":33, -"doc":"Indicates that this address has staking credentials. Its funds can be delegated by the credentialed user." +"ref":"hebi.std.fractions.sub_fraction", +"url":40, +"doc":"returns a - b", +"func":1 }, { -"ref":"hebi.prelude.SomeStakingCredential.staking_credential", -"url":33, -"doc":"" +"ref":"hebi.std.fractions.mul_fraction", +"url":40, +"doc":"returns a b", +"func":1 }, { -"ref":"hebi.prelude.SomeStakingCredential.CONSTR_ID", -"url":33, -"doc":"" +"ref":"hebi.std.fractions.div_fraction", +"url":40, +"doc":"returns a / b", +"func":1 }, { -"ref":"hebi.prelude.Address", -"url":33, -"doc":"A Shelley address, consisting of a payment and staking credential" +"ref":"hebi.std.fractions.norm_fraction", +"url":40, +"doc":"Restores the invariant that num/denom are in the smallest possible denomination and denominator > 0", +"func":1 }, { -"ref":"hebi.prelude.Address.payment_credential", -"url":33, -"doc":"" +"ref":"hebi.std.fractions.ge_fraction", +"url":40, +"doc":"returns a >= b", +"func":1 }, { -"ref":"hebi.prelude.Address.staking_credential", -"url":33, -"doc":"" +"ref":"hebi.std.fractions.le_fraction", +"url":40, +"doc":"returns a <= b", +"func":1 }, { -"ref":"hebi.prelude.SomeDatumHash", -"url":33, -"doc":"Indicates that there is a datum associated with this output, which has the given hash." +"ref":"hebi.std.fractions.eq_fraction", +"url":40, +"doc":"returns a b", +"func":1 }, { -"ref":"hebi.prelude.SomeDatumHash.datum_hash", -"url":33, -"doc":"" +"ref":"hebi.std.fractions.lt_fraction", +"url":40, +"doc":"returns a < b", +"func":1 }, { -"ref":"hebi.prelude.SomeDatumHash.CONSTR_ID", -"url":33, -"doc":"" +"ref":"hebi.std.fractions.gt_fraction", +"url":40, +"doc":"returns a > b", +"func":1 }, { -"ref":"hebi.prelude.SomeScriptHash", -"url":33, -"doc":"Indicates that there is a script associated with this output, which has the given hash." +"ref":"hebi.type_inference", +"url":41, +"doc":"" }, { -"ref":"hebi.prelude.SomeScriptHash.script_hash", -"url":33, -"doc":"" +"ref":"hebi.type_inference.ReturnExtractor", +"url":41, +"doc":"Utility to find all Return statements in an AST subtree" }, { -"ref":"hebi.prelude.SomeScriptHash.CONSTR_ID", -"url":33, -"doc":"" +"ref":"hebi.type_inference.ReturnExtractor.visit_Return", +"url":41, +"doc":"", +"func":1 }, { -"ref":"hebi.prelude.NoOutputDatum", -"url":33, -"doc":"Indicates that there is no datum associated with an output" +"ref":"hebi.type_inference.AggressiveTypeInferencer", +"url":41, +"doc":"A :class: NodeVisitor subclass that walks the abstract syntax tree and allows modification of nodes. The NodeTransformer will walk the AST and use the return value of the visitor methods to replace or remove the old node. If the return value of the visitor method is None , the node will be removed from its location, otherwise it is replaced with the return value. The return value may be the original node in which case no replacement takes place. Here is an example transformer that rewrites all occurrences of name lookups ( foo ) to data['foo'] class RewriteName(NodeTransformer): def visit_Name(self, node): return Subscript( value=Name(id='data', ctx=Load( , slice=Index(value=Str(s=node.id , ctx=node.ctx ) Keep in mind that if the node you're operating on has child nodes you must either transform the child nodes yourself or call the :meth: generic_visit method for the node first. For nodes that were part of a collection of statements (that applies to all statement nodes), the visitor may also return a list of nodes rather than just a single node. Usually you use the transformer like this node = YourTransformer().visit(node)" }, { -"ref":"hebi.prelude.NoOutputDatum.CONSTR_ID", -"url":33, +"ref":"hebi.type_inference.AggressiveTypeInferencer.step", +"url":41, "doc":"" }, { -"ref":"hebi.prelude.SomeOutputDatumHash", -"url":33, -"doc":"Indicates that there is an datum associated with an output, which has the attached hash" +"ref":"hebi.type_inference.AggressiveTypeInferencer.scopes", +"url":41, +"doc":"" }, { -"ref":"hebi.prelude.SomeOutputDatumHash.datum_hash", -"url":33, -"doc":"" +"ref":"hebi.type_inference.AggressiveTypeInferencer.variable_type", +"url":41, +"doc":"", +"func":1 }, { -"ref":"hebi.prelude.SomeOutputDatumHash.CONSTR_ID", -"url":33, -"doc":"" +"ref":"hebi.type_inference.AggressiveTypeInferencer.enter_scope", +"url":41, +"doc":"", +"func":1 }, { -"ref":"hebi.prelude.SomeOutputDatum", -"url":33, -"doc":"Indicates that there is an datum associated with an output, which is inlined and equal to the attached datum" +"ref":"hebi.type_inference.AggressiveTypeInferencer.exit_scope", +"url":41, +"doc":"", +"func":1 }, { -"ref":"hebi.prelude.SomeOutputDatum.datum", -"url":33, -"doc":"" +"ref":"hebi.type_inference.AggressiveTypeInferencer.set_variable_type", +"url":41, +"doc":"", +"func":1 }, { -"ref":"hebi.prelude.SomeOutputDatum.CONSTR_ID", -"url":33, -"doc":"" +"ref":"hebi.type_inference.AggressiveTypeInferencer.type_from_annotation", +"url":41, +"doc":"", +"func":1 }, { -"ref":"hebi.prelude.NoScriptHash", -"url":33, -"doc":"Indicates that there is no script associated with an output" +"ref":"hebi.type_inference.AggressiveTypeInferencer.visit_ClassDef", +"url":41, +"doc":"", +"func":1 }, { -"ref":"hebi.prelude.NoScriptHash.CONSTR_ID", -"url":33, -"doc":"" +"ref":"hebi.type_inference.AggressiveTypeInferencer.visit_Constant", +"url":41, +"doc":"", +"func":1 }, { -"ref":"hebi.prelude.TxOut", -"url":33, -"doc":"The plutus representation of an transaction output, consisting of - address: address owning this output - value: tokens associated with this output - datum: datum associated with this output - reference_script: reference script associated with this output" +"ref":"hebi.type_inference.AggressiveTypeInferencer.visit_Tuple", +"url":41, +"doc":"", +"func":1 }, { -"ref":"hebi.prelude.TxOut.address", -"url":33, -"doc":"" +"ref":"hebi.type_inference.AggressiveTypeInferencer.visit_List", +"url":41, +"doc":"", +"func":1 }, { -"ref":"hebi.prelude.TxOut.value", -"url":33, -"doc":"" +"ref":"hebi.type_inference.AggressiveTypeInferencer.visit_Dict", +"url":41, +"doc":"", +"func":1 }, { -"ref":"hebi.prelude.TxOut.datum", -"url":33, -"doc":"" +"ref":"hebi.type_inference.AggressiveTypeInferencer.visit_Assign", +"url":41, +"doc":"", +"func":1 }, { -"ref":"hebi.prelude.TxOut.reference_script", -"url":33, -"doc":"" +"ref":"hebi.type_inference.AggressiveTypeInferencer.visit_AnnAssign", +"url":41, +"doc":"", +"func":1 }, { -"ref":"hebi.prelude.TxInInfo", -"url":33, -"doc":"The plutus representation of an transaction output, that is consumed by the transaction." +"ref":"hebi.type_inference.AggressiveTypeInferencer.visit_If", +"url":41, +"doc":"", +"func":1 }, { -"ref":"hebi.prelude.TxInInfo.out_ref", -"url":33, -"doc":"" +"ref":"hebi.type_inference.AggressiveTypeInferencer.visit_While", +"url":41, +"doc":"", +"func":1 }, { -"ref":"hebi.prelude.TxInInfo.resolved", -"url":33, -"doc":"" +"ref":"hebi.type_inference.AggressiveTypeInferencer.visit_For", +"url":41, +"doc":"", +"func":1 }, { -"ref":"hebi.prelude.DCertDelegRegKey", -"url":33, -"doc":"DCertDelegRegKey(value: Union[hebi.prelude.StakingHash, hebi.prelude.StakingPtr])" +"ref":"hebi.type_inference.AggressiveTypeInferencer.visit_Name", +"url":41, +"doc":"", +"func":1 }, { -"ref":"hebi.prelude.DCertDelegRegKey.value", -"url":33, -"doc":"" +"ref":"hebi.type_inference.AggressiveTypeInferencer.visit_Compare", +"url":41, +"doc":"", +"func":1 }, { -"ref":"hebi.prelude.DCertDelegRegKey.CONSTR_ID", -"url":33, -"doc":"" +"ref":"hebi.type_inference.AggressiveTypeInferencer.visit_arg", +"url":41, +"doc":"", +"func":1 }, { -"ref":"hebi.prelude.DCertDelegDeRegKey", -"url":33, -"doc":"DCertDelegDeRegKey(value: Union[hebi.prelude.StakingHash, hebi.prelude.StakingPtr])" +"ref":"hebi.type_inference.AggressiveTypeInferencer.visit_arguments", +"url":41, +"doc":"", +"func":1 }, { -"ref":"hebi.prelude.DCertDelegDeRegKey.value", -"url":33, -"doc":"" +"ref":"hebi.type_inference.AggressiveTypeInferencer.visit_FunctionDef", +"url":41, +"doc":"", +"func":1 }, { -"ref":"hebi.prelude.DCertDelegDeRegKey.CONSTR_ID", -"url":33, -"doc":"" +"ref":"hebi.type_inference.AggressiveTypeInferencer.visit_Module", +"url":41, +"doc":"", +"func":1 }, { -"ref":"hebi.prelude.DCertDelegDelegate", -"url":33, -"doc":"DCertDelegDelegate(delegator: Union[hebi.prelude.StakingHash, hebi.prelude.StakingPtr], delegatee: bytes)" +"ref":"hebi.type_inference.AggressiveTypeInferencer.visit_Expr", +"url":41, +"doc":"", +"func":1 }, { -"ref":"hebi.prelude.DCertDelegDelegate.delegator", -"url":33, -"doc":"" +"ref":"hebi.type_inference.AggressiveTypeInferencer.visit_BinOp", +"url":41, +"doc":"", +"func":1 }, { -"ref":"hebi.prelude.DCertDelegDelegate.delegatee", -"url":33, -"doc":"" +"ref":"hebi.type_inference.AggressiveTypeInferencer.visit_BoolOp", +"url":41, +"doc":"", +"func":1 }, { -"ref":"hebi.prelude.DCertDelegDelegate.CONSTR_ID", -"url":33, -"doc":"" +"ref":"hebi.type_inference.AggressiveTypeInferencer.visit_UnaryOp", +"url":41, +"doc":"", +"func":1 }, { -"ref":"hebi.prelude.DCertPoolRegister", -"url":33, -"doc":"DCertPoolRegister(pool_id: bytes, pool_vfr: bytes)" +"ref":"hebi.type_inference.AggressiveTypeInferencer.visit_Subscript", +"url":41, +"doc":"", +"func":1 }, { -"ref":"hebi.prelude.DCertPoolRegister.pool_id", -"url":33, -"doc":"" +"ref":"hebi.type_inference.AggressiveTypeInferencer.visit_Call", +"url":41, +"doc":"", +"func":1 }, { -"ref":"hebi.prelude.DCertPoolRegister.pool_vfr", -"url":33, -"doc":"" +"ref":"hebi.type_inference.AggressiveTypeInferencer.visit_Pass", +"url":41, +"doc":"", +"func":1 }, { -"ref":"hebi.prelude.DCertPoolRegister.CONSTR_ID", -"url":33, -"doc":"" +"ref":"hebi.type_inference.AggressiveTypeInferencer.visit_Return", +"url":41, +"doc":"", +"func":1 }, { -"ref":"hebi.prelude.DCertPoolRetire", -"url":33, -"doc":"DCertPoolRetire(retirement_certificate: bytes, epoch: int)" +"ref":"hebi.type_inference.AggressiveTypeInferencer.visit_Attribute", +"url":41, +"doc":"", +"func":1 }, { -"ref":"hebi.prelude.DCertPoolRetire.retirement_certificate", -"url":33, -"doc":"" +"ref":"hebi.type_inference.AggressiveTypeInferencer.visit_Assert", +"url":41, +"doc":"", +"func":1 }, { -"ref":"hebi.prelude.DCertPoolRetire.epoch", -"url":33, -"doc":"" +"ref":"hebi.type_inference.AggressiveTypeInferencer.visit_RawPlutoExpr", +"url":41, +"doc":"", +"func":1 }, { -"ref":"hebi.prelude.DCertPoolRetire.CONSTR_ID", -"url":33, -"doc":"" +"ref":"hebi.type_inference.AggressiveTypeInferencer.visit_IfExp", +"url":41, +"doc":"", +"func":1 }, { -"ref":"hebi.prelude.DCertGenesis", -"url":33, -"doc":"DCertGenesis()" +"ref":"hebi.type_inference.AggressiveTypeInferencer.visit_comprehension", +"url":41, +"doc":"", +"func":1 }, { -"ref":"hebi.prelude.DCertGenesis.CONSTR_ID", -"url":33, -"doc":"" +"ref":"hebi.type_inference.AggressiveTypeInferencer.visit_ListComp", +"url":41, +"doc":"", +"func":1 }, { -"ref":"hebi.prelude.DCertMir", -"url":33, -"doc":"DCertMir()" +"ref":"hebi.type_inference.AggressiveTypeInferencer.generic_visit", +"url":41, +"doc":"Called if no explicit visitor function exists for a node.", +"func":1 }, { -"ref":"hebi.prelude.DCertMir.CONSTR_ID", -"url":33, -"doc":"" +"ref":"hebi.type_inference.AggressiveTypeInferencer.visit", +"url":19, +"doc":"Visit a node.", +"func":1 }, { -"ref":"hebi.prelude.NegInfPOSIXTime", -"url":33, -"doc":"Negative infinite POSIX time, used to indicate that there is no lower bound for the execution of this transaction" +"ref":"hebi.type_inference.RecordReader", +"url":41, +"doc":"A node visitor base class that walks the abstract syntax tree and calls a visitor function for every node found. This function may return a value which is forwarded by the visit method. This class is meant to be subclassed, with the subclass adding visitor methods. Per default the visitor functions for the nodes are 'visit_' + class name of the node. So a TryFinally node visit function would be visit_TryFinally . This behavior can be changed by overriding the visit method. If no visitor function exists for a node (return value None ) the generic_visit visitor is used instead. Don't use the NodeVisitor if you want to apply changes to nodes during traversing. For this a special visitor exists ( NodeTransformer ) that allows modifications." }, { -"ref":"hebi.prelude.NegInfPOSIXTime.CONSTR_ID", -"url":33, +"ref":"hebi.type_inference.RecordReader.name", +"url":41, "doc":"" }, { -"ref":"hebi.prelude.FinitePOSIXTime", -"url":33, -"doc":"Finite POSIX time, used to indicate that there is a lower or upper bound for the execution of this transaction" +"ref":"hebi.type_inference.RecordReader.constructor", +"url":41, +"doc":"" }, { -"ref":"hebi.prelude.FinitePOSIXTime.time", -"url":33, +"ref":"hebi.type_inference.RecordReader.attributes", +"url":41, "doc":"" }, { -"ref":"hebi.prelude.FinitePOSIXTime.CONSTR_ID", -"url":33, -"doc":"" +"ref":"hebi.type_inference.RecordReader.extract", +"url":41, +"doc":"", +"func":1 }, { -"ref":"hebi.prelude.PosInfPOSIXTime", -"url":33, -"doc":"Infinite POSIX time, used to indicate that there is no upper bound for the execution of this transaction" +"ref":"hebi.type_inference.RecordReader.visit_AnnAssign", +"url":41, +"doc":"", +"func":1 }, { -"ref":"hebi.prelude.PosInfPOSIXTime.CONSTR_ID", -"url":33, -"doc":"" +"ref":"hebi.type_inference.RecordReader.visit_ClassDef", +"url":41, +"doc":"", +"func":1 }, { -"ref":"hebi.prelude.UpperBoundPOSIXTime", -"url":33, -"doc":"Upper bound for the execution of this transaction" +"ref":"hebi.type_inference.RecordReader.visit_Pass", +"url":41, +"doc":"", +"func":1 }, { -"ref":"hebi.prelude.UpperBoundPOSIXTime.limit", -"url":33, -"doc":"" +"ref":"hebi.type_inference.RecordReader.visit_Assign", +"url":41, +"doc":"", +"func":1 }, { -"ref":"hebi.prelude.UpperBoundPOSIXTime.closed", -"url":33, -"doc":"" +"ref":"hebi.type_inference.RecordReader.visit_Expr", +"url":41, +"doc":"", +"func":1 }, { -"ref":"hebi.prelude.UpperBoundPOSIXTime.CONSTR_ID", -"url":33, -"doc":"" +"ref":"hebi.type_inference.RecordReader.generic_visit", +"url":41, +"doc":"Called if no explicit visitor function exists for a node.", +"func":1 }, { -"ref":"hebi.prelude.LowerBoundPOSIXTime", -"url":33, -"doc":"Lower bound for the execution of this transaction" +"ref":"hebi.type_inference.typed_ast", +"url":41, +"doc":"", +"func":1 }, { -"ref":"hebi.prelude.LowerBoundPOSIXTime.limit", -"url":33, +"ref":"hebi.util", +"url":19, "doc":"" }, { -"ref":"hebi.prelude.LowerBoundPOSIXTime.closed", -"url":33, -"doc":"" +"ref":"hebi.util.PythonBuiltIn", +"url":19, +"doc":"An enumeration." }, { -"ref":"hebi.prelude.LowerBoundPOSIXTime.CONSTR_ID", -"url":33, +"ref":"hebi.util.PythonBuiltIn.all", +"url":19, "doc":"" }, { -"ref":"hebi.prelude.POSIXTimeRange", -"url":33, -"doc":"Time range in which this transaction can be executed" +"ref":"hebi.util.PythonBuiltIn.any", +"url":19, +"doc":"" }, { -"ref":"hebi.prelude.POSIXTimeRange.lower_bound", -"url":33, +"ref":"hebi.util.PythonBuiltIn.abs", +"url":19, "doc":"" }, { -"ref":"hebi.prelude.POSIXTimeRange.upper_bound", -"url":33, +"ref":"hebi.util.PythonBuiltIn.chr", +"url":19, "doc":"" }, { -"ref":"hebi.prelude.Minting", -"url":33, -"doc":"Script purpose indicating that the given policy id is being minted or burned" +"ref":"hebi.util.PythonBuiltIn.breakpoint", +"url":19, +"doc":"" }, { -"ref":"hebi.prelude.Minting.policy_id", -"url":33, +"ref":"hebi.util.PythonBuiltIn.hex", +"url":19, "doc":"" }, { -"ref":"hebi.prelude.Minting.CONSTR_ID", -"url":33, +"ref":"hebi.util.PythonBuiltIn.len", +"url":19, "doc":"" }, { -"ref":"hebi.prelude.Spending", -"url":33, -"doc":"Script purpose indicating that the given transaction output is being spent, which is owned by the invoked contract" +"ref":"hebi.util.PythonBuiltIn.max", +"url":19, +"doc":"" }, { -"ref":"hebi.prelude.Spending.tx_out_ref", -"url":33, +"ref":"hebi.util.PythonBuiltIn.min", +"url":19, "doc":"" }, { -"ref":"hebi.prelude.Spending.CONSTR_ID", -"url":33, +"ref":"hebi.util.PythonBuiltIn.print", +"url":19, "doc":"" }, { -"ref":"hebi.prelude.Rewarding", -"url":33, -"doc":"Rewarding(staking_credential: Union[hebi.prelude.StakingHash, hebi.prelude.StakingPtr])" +"ref":"hebi.util.PythonBuiltIn.pow", +"url":19, +"doc":"" }, { -"ref":"hebi.prelude.Rewarding.staking_credential", -"url":33, +"ref":"hebi.util.PythonBuiltIn.oct", +"url":19, "doc":"" }, { -"ref":"hebi.prelude.Rewarding.CONSTR_ID", -"url":33, +"ref":"hebi.util.PythonBuiltIn.range", +"url":19, "doc":"" }, { -"ref":"hebi.prelude.Certifying", -"url":33, -"doc":"Certifying(d_cert: Union[hebi.prelude.DCertDelegRegKey, hebi.prelude.DCertDelegDeRegKey, hebi.prelude.DCertDelegDelegate, hebi.prelude.DCertPoolRegister, hebi.prelude.DCertPoolRetire, hebi.prelude.DCertGenesis, hebi.prelude.DCertMir])" +"ref":"hebi.util.PythonBuiltIn.reversed", +"url":19, +"doc":"" }, { -"ref":"hebi.prelude.Certifying.d_cert", -"url":33, +"ref":"hebi.util.PythonBuiltIn.sum", +"url":19, "doc":"" }, { -"ref":"hebi.prelude.Certifying.CONSTR_ID", -"url":33, +"ref":"hebi.util.LenImpl", +"url":19, "doc":"" }, { -"ref":"hebi.prelude.TxInfo", -"url":33, -"doc":"A complex agglomeration of everything that could be of interest to the executed script, regarding the transaction that invoked the script" +"ref":"hebi.util.LenImpl.type_from_args", +"url":19, +"doc":"", +"func":1 }, { -"ref":"hebi.prelude.TxInfo.inputs", -"url":33, -"doc":"" +"ref":"hebi.util.LenImpl.impl_from_args", +"url":19, +"doc":"", +"func":1 }, { -"ref":"hebi.prelude.TxInfo.reference_inputs", -"url":33, +"ref":"hebi.util.ReversedImpl", +"url":19, "doc":"" }, { -"ref":"hebi.prelude.TxInfo.outputs", -"url":33, -"doc":"" +"ref":"hebi.util.ReversedImpl.type_from_args", +"url":19, +"doc":"", +"func":1 }, { -"ref":"hebi.prelude.TxInfo.fee", -"url":33, -"doc":"" +"ref":"hebi.util.ReversedImpl.impl_from_args", +"url":19, +"doc":"", +"func":1 }, { -"ref":"hebi.prelude.TxInfo.mint", -"url":33, -"doc":"" +"ref":"hebi.util.CompilerError", +"url":19, +"doc":"Common base class for all non-exit exceptions." }, { -"ref":"hebi.prelude.TxInfo.dcert", -"url":33, -"doc":"" +"ref":"hebi.util.CompilingNodeTransformer", +"url":19, +"doc":"A :class: NodeVisitor subclass that walks the abstract syntax tree and allows modification of nodes. The NodeTransformer will walk the AST and use the return value of the visitor methods to replace or remove the old node. If the return value of the visitor method is None , the node will be removed from its location, otherwise it is replaced with the return value. The return value may be the original node in which case no replacement takes place. Here is an example transformer that rewrites all occurrences of name lookups ( foo ) to data['foo'] class RewriteName(NodeTransformer): def visit_Name(self, node): return Subscript( value=Name(id='data', ctx=Load( , slice=Index(value=Str(s=node.id , ctx=node.ctx ) Keep in mind that if the node you're operating on has child nodes you must either transform the child nodes yourself or call the :meth: generic_visit method for the node first. For nodes that were part of a collection of statements (that applies to all statement nodes), the visitor may also return a list of nodes rather than just a single node. Usually you use the transformer like this node = YourTransformer().visit(node)" }, { -"ref":"hebi.prelude.TxInfo.wdrl", -"url":33, +"ref":"hebi.util.CompilingNodeTransformer.step", +"url":19, "doc":"" }, { -"ref":"hebi.prelude.TxInfo.valid_range", -"url":33, -"doc":"" +"ref":"hebi.util.CompilingNodeTransformer.visit", +"url":19, +"doc":"Visit a node.", +"func":1 }, { -"ref":"hebi.prelude.TxInfo.signatories", -"url":33, -"doc":"" +"ref":"hebi.util.CompilingNodeVisitor", +"url":19, +"doc":"A node visitor base class that walks the abstract syntax tree and calls a visitor function for every node found. This function may return a value which is forwarded by the visit method. This class is meant to be subclassed, with the subclass adding visitor methods. Per default the visitor functions for the nodes are 'visit_' + class name of the node. So a TryFinally node visit function would be visit_TryFinally . This behavior can be changed by overriding the visit method. If no visitor function exists for a node (return value None ) the generic_visit visitor is used instead. Don't use the NodeVisitor if you want to apply changes to nodes during traversing. For this a special visitor exists ( NodeTransformer ) that allows modifications." }, { -"ref":"hebi.prelude.TxInfo.redeemers", -"url":33, +"ref":"hebi.util.CompilingNodeVisitor.step", +"url":19, "doc":"" }, { -"ref":"hebi.prelude.TxInfo.data", -"url":33, -"doc":"" +"ref":"hebi.util.CompilingNodeVisitor.visit", +"url":19, +"doc":"Visit a node.", +"func":1 }, { -"ref":"hebi.prelude.TxInfo.id", -"url":33, -"doc":"" +"ref":"hebi.util.data_from_json", +"url":19, +"doc":"", +"func":1 }, { -"ref":"hebi.prelude.ScriptContext", -"url":33, -"doc":"Auxiliary information about the transaction and reason for invocation of the called script." +"ref":"hebi.util.datum_to_cbor", +"url":19, +"doc":"", +"func":1 }, { -"ref":"hebi.prelude.ScriptContext.tx_info", -"url":33, -"doc":"" +"ref":"hebi.util.datum_to_json", +"url":19, +"doc":"", +"func":1 }, { -"ref":"hebi.prelude.ScriptContext.purpose", -"url":33, +"ref":"hebi.prelude", +"url":42, "doc":"" }, { "ref":"hebi.prelude.Token", -"url":33, +"url":42, "doc":"A token, represented by policy id and token name" }, { "ref":"hebi.prelude.Token.policy_id", -"url":33, +"url":42, "doc":"" }, { "ref":"hebi.prelude.Token.token_name", -"url":33, -"doc":"" -}, -{ -"ref":"hebi.prelude.Nothing", -"url":33, -"doc":"Nothing, can be used to signify non-importance of a parameter to a function Example value: Nothing()" -}, -{ -"ref":"hebi.prelude.Nothing.CONSTR_ID", -"url":33, +"url":42, "doc":"" }, { "ref":"hebi.prelude.all_tokens_unlocked_from_address", -"url":33, +"url":42, "doc":"Returns how many tokens of specified type are unlocked from given address", "func":1 }, { "ref":"hebi.prelude.all_tokens_locked_at_address_with_datum", -"url":33, +"url":42, "doc":"Returns how many tokens of specified type are locked at then given address with the specified datum", "func":1 }, { "ref":"hebi.prelude.all_tokens_locked_at_address", -"url":33, +"url":42, "doc":"Returns how many tokens of specified type are locked at the given address", "func":1 }, { "ref":"hebi.prelude.resolve_spent_utxo", -"url":33, +"url":42, "doc":"Returns the UTxO whose spending should be validated", "func":1 +}, +{ +"ref":"hebi.prelude.resolve_datum_unsafe", +"url":42, +"doc":"Returns the datum attached to a given transaction output, independent of whether it was inlined or embedded. Raises an exception if no datum was attached.", +"func":1 +}, +{ +"ref":"hebi.prelude.resolve_datum", +"url":42, +"doc":"Returns SomeOutputDatum with the datum attached to a given transaction output, independent of whether it was inlined or embedded, if there was an attached datum. Otherwise it returns NoOutputDatum.", +"func":1 } ] \ No newline at end of file diff --git a/examples/broken.py b/examples/broken.py index 3233844..42ba58c 100644 --- a/examples/broken.py +++ b/examples/broken.py @@ -2,7 +2,7 @@ # inspired by https://github.com/MuesliSwapTeam/muesliswap-cardano-pool-contracts/blob/main/dex/src/MuesliSwapPools/BatchOrder/Types.hs -@dataclass() +@dataclass class BatchOrder(PlutusData): sender: Address receiver: Address diff --git a/examples/complex_datum.py b/examples/complex_datum.py index 3661613..dd2f06e 100644 --- a/examples/complex_datum.py +++ b/examples/complex_datum.py @@ -1,13 +1,13 @@ from hebi.prelude import * -@dataclass() +@dataclass class Deposit(PlutusData): CONSTR_ID = 0 minimum_lp: int -@dataclass() +@dataclass class Withdraw(PlutusData): CONSTR_ID = 1 minimum_coin_a: int @@ -16,8 +16,9 @@ class Withdraw(PlutusData): OrderStep = Union[Deposit, Withdraw] + # inspired by https://github.com/MuesliSwapTeam/muesliswap-cardano-pool-contracts/blob/main/dex/src/MuesliSwapPools/BatchOrder/Types.hs -@dataclass() +@dataclass class BatchOrder(PlutusData): sender: Address receiver: Address diff --git a/examples/datum_cast.py b/examples/datum_cast.py index 75aa3d0..0380569 100644 --- a/examples/datum_cast.py +++ b/examples/datum_cast.py @@ -2,7 +2,7 @@ # inspired by https://github.com/MuesliSwapTeam/muesliswap-cardano-pool-contracts/blob/main/dex/src/MuesliSwapPools/BatchOrder/Types.hs -@dataclass() +@dataclass class BatchOrder(PlutusData): sender: Address receiver: Address diff --git a/examples/dict_datum.py b/examples/dict_datum.py index 7b28c40..000a4fe 100644 --- a/examples/dict_datum.py +++ b/examples/dict_datum.py @@ -1,12 +1,13 @@ from hebi.prelude import * -@dataclass() +# You need to enable hashing in order to allow the data to be the key of a dict +@dataclass(unsafe_hash=True) class D(PlutusData): p: bytes -@dataclass() +@dataclass class D2(PlutusData): dict_field: Dict[D, int] diff --git a/examples/list_datum.py b/examples/list_datum.py index f614662..799331a 100644 --- a/examples/list_datum.py +++ b/examples/list_datum.py @@ -1,7 +1,7 @@ from hebi.prelude import * -@dataclass() +@dataclass class D2(PlutusData): list_field: List[DatumHash] diff --git a/examples/showcase.py b/examples/showcase.py index a60655c..0724cde 100644 --- a/examples/showcase.py +++ b/examples/showcase.py @@ -1,6 +1,3 @@ -from hebi.prelude import * - - def validator(n: int) -> int: # Tuple assignment works a, b = 3, n diff --git a/examples/smart_contracts/always_true.py b/examples/smart_contracts/always_true.py new file mode 100644 index 0000000..6a9fe22 --- /dev/null +++ b/examples/smart_contracts/always_true.py @@ -0,0 +1,5 @@ +from hebi.prelude import * + + +def validator(datum: Anything, redeemer: Anything, context: ScriptContext) -> None: + pass diff --git a/examples/smart_contracts/gift.py b/examples/smart_contracts/gift.py index 98b83ad..d766f33 100644 --- a/examples/smart_contracts/gift.py +++ b/examples/smart_contracts/gift.py @@ -1,7 +1,7 @@ from hebi.prelude import * -@dataclass() +@dataclass class CancelDatum(PlutusData): pubkeyhash: bytes diff --git a/examples/smart_contracts/marketplace.py b/examples/smart_contracts/marketplace.py index e4ec756..e5a857b 100644 --- a/examples/smart_contracts/marketplace.py +++ b/examples/smart_contracts/marketplace.py @@ -1,7 +1,7 @@ from hebi.prelude import * -@dataclass() +@dataclass class Listing(PlutusData): # Price of the listing in lovelace price: int @@ -11,13 +11,13 @@ class Listing(PlutusData): owner: PubKeyHash -@dataclass() +@dataclass class Buy(PlutusData): # Redeemer to buy the listed values CONSTR_ID = 0 -@dataclass() +@dataclass class Unlist(PlutusData): # Redeemer to unlist the values CONSTR_ID = 1 diff --git a/examples/smart_contracts/wrapped_token.py b/examples/smart_contracts/wrapped_token.py index 25e3620..6e2950d 100644 --- a/examples/smart_contracts/wrapped_token.py +++ b/examples/smart_contracts/wrapped_token.py @@ -1,7 +1,7 @@ from hebi.prelude import * -@dataclass() +@dataclass class Empty(PlutusData): pass diff --git a/hebi/__init__.py b/hebi/__init__.py index 33cb5e4..f8a846f 100644 --- a/hebi/__init__.py +++ b/hebi/__init__.py @@ -12,7 +12,7 @@ except ImportError as e: warnings.warn(ImportWarning(e)) -__version__ = "0.1.1.0.11.0" +__version__ = "0.1.1.0.12.3" __author__ = "nielstron" __author_email__ = "n.muendler@web.de" __copyright__ = "Copyright (C) 2023 nielstron" diff --git a/hebi/__main__.py b/hebi/__main__.py index 2ce54d4..47bc3e0 100644 --- a/hebi/__main__.py +++ b/hebi/__main__.py @@ -176,7 +176,7 @@ def main(): else: target_dir = pathlib.Path(args.output_directory) target_dir.mkdir(exist_ok=True, parents=True) - artifacts = builder._build(code) + artifacts = builder.generate_artifacts(builder._build(code)) with (target_dir / "script.cbor").open("w") as fp: fp.write(artifacts.cbor_hex) with (target_dir / "script.plutus").open("w") as fp: diff --git a/hebi/builder.py b/hebi/builder.py index 0ebcc3d..0bcae40 100644 --- a/hebi/builder.py +++ b/hebi/builder.py @@ -8,6 +8,8 @@ import cbor2 import pycardano +from .util import datum_to_cbor + @dataclasses.dataclass class ScriptArtifacts: @@ -18,7 +20,12 @@ class ScriptArtifacts: policy_id: str -def build(contract_file: str, *args: pycardano.PlutusData, force_three_params=False): +def build( + contract_file: str, + *args: pycardano.Datum, + force_three_params=False, + validator_function_name="validator", +): """ Expects a python module and returns the build artifacts from compiling it """ @@ -35,7 +42,7 @@ def build(contract_file: str, *args: pycardano.PlutusData, force_three_params=Fa code = code.term # UPLC lambdas may only take one argument at a time, so we evaluate by repeatedly applying for d in args: - code = uplc.ast.Apply(code, uplc.ast.data_from_cbor(d.to_cbor("bytes"))) + code = uplc.ast.Apply(code, uplc.ast.data_from_cbor(datum_to_cbor(d))) code = uplc.ast.Program((1, 0, 0), code) return _build(code) @@ -43,9 +50,13 @@ def build(contract_file: str, *args: pycardano.PlutusData, force_three_params=Fa def _build(contract: uplc.ast.Program): # create cbor file for use with pycardano/lucid cbor = flatten(contract) - cbor_hex = cbor.hex() + return pycardano.PlutusV2Script(cbor) + + +def generate_artifacts(contract: pycardano.PlutusV2Script): + cbor_hex = contract.hex() # double wrap - cbor_wrapped = cbor2.dumps(cbor) + cbor_wrapped = cbor2.dumps(contract) cbor_wrapped_hex = cbor_wrapped.hex() # create plutus file d = { @@ -54,7 +65,7 @@ def _build(contract: uplc.ast.Program): "cborHex": cbor_wrapped_hex, } plutus_json = json.dumps(d, indent=2) - script_hash = pycardano.plutus_script_hash(pycardano.PlutusV2Script(cbor)) + script_hash = pycardano.plutus_script_hash(pycardano.PlutusV2Script(contract)) policy_id = script_hash.to_primitive().hex() # generate policy ids addr_mainnet = pycardano.Address( diff --git a/hebi/compiler.py b/hebi/compiler.py index a8dbff6..eeb808a 100644 --- a/hebi/compiler.py +++ b/hebi/compiler.py @@ -2,6 +2,7 @@ from logging import getLogger from ast import fix_missing_locations +from .optimize.optimize_remove_comments import OptimizeRemoveDeadconstants from .rewrite.rewrite_forbidden_overwrites import RewriteForbiddenOverwrites from .rewrite.rewrite_import import RewriteImport from .rewrite.rewrite_import_dataclasses import RewriteImportDataclasses @@ -119,8 +120,9 @@ class UPLCCompiler(CompilingNodeTransformer): step = "Compiling python statements to UPLC" - def __init__(self, force_three_params=False): + def __init__(self, force_three_params=False, validator_function_name="validator"): self.force_three_params = force_three_params + self.validator_function_name = validator_function_name def visit_sequence( self, node_seq: typing.List[typedstmt] @@ -186,20 +188,21 @@ def visit_Module(self, node: TypedModule) -> plt.AST: # TODO can use more sophisiticated procedure here i.e. functions marked by comment main_fun: typing.Optional[InstanceType] = None for s in node.body: - if isinstance(s, FunctionDef) and s.name == "validator": + if isinstance(s, FunctionDef) and s.name == self.validator_function_name: main_fun = s - assert main_fun is not None, "Could not find function named validator" - main_fun_typ = main_fun.typ - main_fun_typ_typ: FunctionType = main_fun_typ.typ + assert ( + main_fun is not None + ), f"Could not find function named {self.validator_function_name}" + main_fun_typ: FunctionType = main_fun.typ.typ assert isinstance( - main_fun_typ_typ, FunctionType - ), "Variable named validator is not of type function" + main_fun_typ, FunctionType + ), f"Variable named {self.validator_function_name} is not of type function" # check if this is a contract written to double function enable_double_func_mint_spend = False - if len(main_fun_typ_typ.argtyps) >= 3 and self.force_three_params: + if len(main_fun_typ.argtyps) >= 3 and self.force_three_params: # check if is possible - second_last_arg = main_fun_typ_typ.argtyps[-2] + second_last_arg = main_fun_typ.argtyps[-2] assert isinstance( second_last_arg, InstanceType ), "Can not pass Class into validator" @@ -223,14 +226,18 @@ def visit_Module(self, node: TypedModule) -> plt.AST: body = node.body + [ TypedReturn( - value=Name(id="validator", typ=main_fun_typ, ctx=Load()), - typ=main_fun_typ_typ.rettyp, + value=Name( + id=self.validator_function_name, + typ=InstanceType(main_fun_typ), + ctx=Load(), + ), + typ=InstanceType(main_fun_typ), ) ] validator = plt.Lambda( - [f"p{i}" for i, _ in enumerate(main_fun_typ_typ.argtyps)], - transform_output_map(main_fun_typ_typ.rettyp)( + [f"p{i}" for i, _ in enumerate(main_fun_typ.argtyps)], + transform_output_map(main_fun_typ.rettyp)( plt.Let( [ ( @@ -243,7 +250,7 @@ def visit_Module(self, node: TypedModule) -> plt.AST: plt.Var("val"), *[ transform_ext_params_map(a)(plt.Var(f"p{i}")) - for i, a in enumerate(main_fun_typ_typ.argtyps) + for i, a in enumerate(main_fun_typ.argtyps) ], ), ), @@ -251,7 +258,7 @@ def visit_Module(self, node: TypedModule) -> plt.AST: ) if enable_double_func_mint_spend: validator = wrap_validator_double_function( - validator, pass_through=len(main_fun_typ_typ.argtyps) - 3 + validator, pass_through=len(main_fun_typ.argtyps) - 3 ) elif self.force_three_params: # Error if the double function is enforced but not possible @@ -299,6 +306,12 @@ def visit_AnnAssign(self, node: AnnAssign) -> typing.Callable[[plt.AST], plt.AST # we need to map this as it will originate from PlutusData # AnyType is the only type other than the builtin itself that can be cast to builtin values val = transform_ext_params_map(node.target.typ)(val) + if isinstance(node.target.typ, InstanceType) and isinstance( + node.target.typ.typ, AnyType + ): + # we need to map this back as it will be treated as PlutusData + # AnyType is the only type other than the builtin itself that can be cast to from builtin values + val = transform_output_map(node.value.typ)(val) return lambda x: plt.Let([(node.target.id, val)], x) def visit_Name(self, node: TypedName) -> plt.AST: @@ -370,7 +383,11 @@ def visit_If(self, node: TypedIf) -> typing.Callable[[plt.AST], plt.AST]: def visit_Return(self, node: TypedReturn) -> typing.Callable[[plt.AST], plt.AST]: # Throw away the term we were passed, this is going to be the last! - return lambda x: self.visit(node.value) + compiled_return = self.visit(node.value) + if isinstance(node.typ.typ, AnyType): + # if the function returns generic data, wrap the function return value + compiled_return = transform_output_map(node.value.typ)(compiled_return) + return lambda _: compiled_return def visit_Pass(self, node: TypedPass) -> typing.Callable[[plt.AST], plt.AST]: return lambda x: x @@ -395,6 +412,28 @@ def visit_Subscript(self, node: TypedSubscript) -> plt.AST: index, len(node.value.typ.typ.typs), ) + if isinstance(node.value.typ.typ, PairType): + assert isinstance( + node.slice, Constant + ), "Only constant index access for pairs is supported" + assert isinstance( + node.slice.value, int + ), "Only constant index integer access for pairs is supported" + index = node.slice.value + if index < 0: + index += 2 + assert isinstance(node.ctx, Load), "Pairs are read-only" + assert ( + 0 <= index < 2 + ), f"Pairs only have 2 elements, index should be 0 or 1, is {node.slice.value}" + member_func = plt.FstPair if index == 0 else plt.SndPair + # the content of pairs is always Data, so we need to unwrap + member_typ = node.typ + return transform_ext_params_map(member_typ)( + member_func( + self.visit(node.value), + ), + ) if isinstance(node.value.typ.typ, ListType): assert ( node.slice.typ == IntegerInstanceType @@ -419,6 +458,34 @@ def visit_Subscript(self, node: TypedSubscript) -> plt.AST: ], plt.IndexAccessList(plt.Var("l"), plt.Var("i")), ) + elif isinstance(node.value.typ.typ, DictType): + dict_typ = node.value.typ.typ + if not isinstance(node.slice, Slice): + return plt.Let( + [ + ( + "key", + self.visit(node.slice), + ) + ], + transform_ext_params_map(dict_typ.value_typ)( + plt.SndPair( + plt.FindList( + self.visit(node.value), + plt.Lambda( + ["x"], + plt.EqualsData( + transform_output_map(dict_typ.key_typ)( + plt.Var("key") + ), + plt.FstPair(plt.Var("x")), + ), + ), + plt.TraceError("KeyError"), + ), + ), + ), + ) elif isinstance(node.value.typ.typ, ByteStringType): if not isinstance(node.slice, Slice): return plt.Let( @@ -448,7 +515,10 @@ def visit_Subscript(self, node: TypedSubscript) -> plt.AST: elif isinstance(node.slice, Slice): return plt.Let( [ - ("bs", self.visit(node.value)), + ( + "bs", + self.visit(node.value), + ), ( "raw_i", self.visit(node.slice.lower), @@ -502,7 +572,9 @@ def visit_Subscript(self, node: TypedSubscript) -> plt.AST: ), ), ) - raise NotImplementedError(f"Could not implement subscript of {node}") + raise NotImplementedError( + f'Could not implement subscript "{node.slice}" of "{node.value}"' + ) def visit_Tuple(self, node: TypedTuple) -> plt.AST: return plt.FunctionalTuple(*(self.visit(e) for e in node.elts)) @@ -608,7 +680,12 @@ def generic_visit(self, node: AST) -> plt.AST: raise NotImplementedError(f"Can not compile {node}") -def compile(prog: AST, filename=None, force_three_params=False): +def compile( + prog: AST, + filename=None, + force_three_params=False, + validator_function_name="validator", +): rewrite_steps = [ # Important to call this one first - it imports all further files RewriteImport(filename=filename), @@ -637,10 +714,13 @@ def compile(prog: AST, filename=None, force_three_params=False): compile_pipeline = [ # Apply optimizations OptimizeRemoveDeadvars(), - # OptimizeVarlen(), + OptimizeRemoveDeadconstants(), OptimizeRemovePass(), # the compiler runs last - UPLCCompiler(force_three_params=force_three_params), + UPLCCompiler( + force_three_params=force_three_params, + validator_function_name=validator_function_name, + ), ] for s in compile_pipeline: prog = s.visit(prog) diff --git a/hebi/ledger/api_v2.py b/hebi/ledger/api_v2.py new file mode 100644 index 0000000..ad32477 --- /dev/null +++ b/hebi/ledger/api_v2.py @@ -0,0 +1,477 @@ +""" +The PlutusV2 ledger API +""" +from dataclasses import dataclass +from typing import Dict, List, Union + +from pycardano import Datum as Anything, PlutusData + + +# Plutus V2 +@dataclass(unsafe_hash=True) +class TxId(PlutusData): + """ + A transaction id, a 64 bytes long hash of the transaction body (also called transaction hash). + + Example value: TxId(bytes.fromhex("842a4d37b036da6ab3c04331240e67d81746beb44f23ad79703e026705361956")) + """ + + tx_id: bytes + + +@dataclass(unsafe_hash=True) +class Nothing(PlutusData): + """ + Nothing, can be used to signify non-importance of a parameter to a function + + Example value: Nothing() + """ + + # The maximimum constructor ID for simple cbor types, chosen to minimize probability of collision while keeping the corresponding cbor small + CONSTR_ID = 6 + + +@dataclass(unsafe_hash=True) +class TrueData(PlutusData): + """ + A Datum that represents True in Haskell implementations. + It is thus used as an encoding for True in the ScriptContext. + + Example value: TrueData() + """ + + CONSTR_ID = 0 + + +@dataclass(unsafe_hash=True) +class FalseData(PlutusData): + """ + A Datum that represents False in Haskell implementations. + It is thus used as an encoding for False in the ScriptContext. + + Example value: FalseData() + """ + + CONSTR_ID = 1 + + +# A Datum that represents a boolean value in Haskell implementations. +# It is thus used as an encoding for booleans in the ScriptContext. +# +# Example value: TrueData() +BoolData = Union[TrueData, FalseData] + + +@dataclass(unsafe_hash=True) +class TxOutRef(PlutusData): + """ + A reference to a transaction output (hash/id + index) + """ + + id: TxId + idx: int + + +# A public key hash, used to identify signatures provided by a wallet +PubKeyHash = bytes + + +@dataclass(unsafe_hash=True) +class PubKeyCredential(PlutusData): + """ + Part of an address that is authenticated by a public key hash + + Example value: PubKeyCredential(bytes.fromhex("c06ddaad12fc4ded18e56feac72957c1aa75fce6096b40e63ec88274")) + """ + + CONSTR_ID = 0 + credential_hash: PubKeyHash + + +# A validator hash, used to identify signatures provided by a smart contract +ValidatorHash = bytes + + +@dataclass(unsafe_hash=True) +class ScriptCredential(PlutusData): + """ + Part of an address that is authenticated by a smart cotnract + + Example value: ScriptCredential(bytes.fromhex("c06ddaad12fc4ded18e56feac72957c1aa75fce6096b40e63ec88274")) + """ + + CONSTR_ID = 1 + credential_hash: ValidatorHash + + +# A credential, either smart contract or public key hash +Credential = Union[PubKeyCredential, ScriptCredential] + + +@dataclass(unsafe_hash=True) +class StakingHash(PlutusData): + """ + Indicates that the stake of this address is controlled by the associated credential + """ + + CONSTR_ID = 0 + value: Credential + + +@dataclass(unsafe_hash=True) +class StakingPtr(PlutusData): + """ + Indicates that the stake of this address is controlled by the associated pointer. + + In an address, a chain pointer refers to a point of the chain containing a stake key registration certificate. + A point is identified by the 3 coordinates in this object. + """ + + CONSTR_ID = 1 + # an absolute slot number + slot_no: int + # a transaction index (within that slot) + tx_index: int + # a (delegation) certificate index (within that transaction) + cert_index: int + + +# Part of an address that controls who can delegate the stake associated with an address +StakingCredential = Union[StakingHash, StakingPtr] + + +@dataclass(unsafe_hash=True) +class NoStakingCredential(PlutusData): + """ + Indicates that this address has no staking credentials. + Its funds can not be delegated. + """ + + CONSTR_ID = 1 + + +@dataclass(unsafe_hash=True) +class SomeStakingCredential(PlutusData): + """ + Indicates that this address has staking credentials. + Its funds can be delegated by the credentialed user. + """ + + CONSTR_ID = 0 + staking_credential: StakingCredential + + +@dataclass(unsafe_hash=True) +class Address(PlutusData): + """ + A Shelley address, consisting of a payment and staking credential + """ + + payment_credential: Credential + staking_credential: Union[NoStakingCredential, SomeStakingCredential] + + +# The policy Id of a token +PolicyId = bytes + +# The name of a token in bytes (not textual representation!) +TokenName = bytes + +# The Plutus representation of amounts of tokens being spent, sent or minted +# It is a two-layered dictionary that stores for each policy id and token name +# the amount of the token that is being sent/minted/burned etc +# +# Lovelace is represented with policy id b"" and token name b"" +Value = Dict[PolicyId, Dict[TokenName, int]] + +# A hash of a Datum +DatumHash = bytes + + +@dataclass(unsafe_hash=True) +class SomeDatumHash(PlutusData): + """ + Indicates that there is a datum associated with this output, which has the given hash. + """ + + CONSTR_ID = 1 + datum_hash: DatumHash + + +@dataclass(unsafe_hash=True) +class SomeScriptHash(PlutusData): + """ + Indicates that there is a script associated with this output, which has the given hash. + """ + + CONSTR_ID = 0 + script_hash: DatumHash + + +# The abstract super type of any object in opshin. +# Use if you don't know what kind of object is being passed or if it doesn't matter. +BuiltinData = Anything + + +# An abstract type annotation that something is supposed to be used as a redeemer. +Redeemer = BuiltinData + + +# An abstract type annotation that something is supposed to be used as a datum. +Datum = BuiltinData + + +@dataclass(unsafe_hash=True) +class NoOutputDatum(PlutusData): + """ + Indicates that there is no datum associated with an output + """ + + CONSTR_ID = 0 + + +@dataclass(unsafe_hash=True) +class SomeOutputDatumHash(PlutusData): + """ + Indicates that there is an datum associated with an output, which has the attached hash + """ + + CONSTR_ID = 1 + datum_hash: DatumHash + + +@dataclass(unsafe_hash=True) +class SomeOutputDatum(PlutusData): + """ + Indicates that there is an datum associated with an output, which is inlined and equal to the attached datum + """ + + CONSTR_ID = 2 + datum: Datum + + +# Possible cases of datum association with an output +OutputDatum = Union[NoOutputDatum, SomeOutputDatumHash, SomeOutputDatum] + + +@dataclass(unsafe_hash=True) +class NoScriptHash(PlutusData): + """ + Indicates that there is no script associated with an output + """ + + CONSTR_ID = 1 + + +@dataclass(unsafe_hash=True) +class TxOut(PlutusData): + """ + The plutus representation of an transaction output, consisting of + - address: address owning this output + - value: tokens associated with this output + - datum: datum associated with this output + - reference_script: reference script associated with this output + """ + + address: Address + value: Value + datum: OutputDatum + reference_script: Union[NoScriptHash, SomeScriptHash] + + +@dataclass(unsafe_hash=True) +class TxInInfo(PlutusData): + """ + The plutus representation of an transaction output, that is consumed by the transaction. + """ + + out_ref: TxOutRef + resolved: TxOut + + +@dataclass(unsafe_hash=True) +class DCertDelegRegKey(PlutusData): + CONSTR_ID = 0 + value: StakingCredential + + +@dataclass(unsafe_hash=True) +class DCertDelegDeRegKey(PlutusData): + CONSTR_ID = 1 + value: StakingCredential + + +@dataclass(unsafe_hash=True) +class DCertDelegDelegate(PlutusData): + CONSTR_ID = 2 + delegator: StakingCredential + delegatee: PubKeyHash + + +@dataclass(unsafe_hash=True) +class DCertPoolRegister(PlutusData): + CONSTR_ID = 3 + pool_id: PubKeyHash + pool_vfr: PubKeyHash + + +@dataclass(unsafe_hash=True) +class DCertPoolRetire(PlutusData): + CONSTR_ID = 4 + retirement_certificate: PubKeyHash + epoch: int + + +@dataclass(unsafe_hash=True) +class DCertGenesis(PlutusData): + CONSTR_ID = 5 + + +@dataclass(unsafe_hash=True) +class DCertMir(PlutusData): + CONSTR_ID = 6 + + +DCert = Union[ + DCertDelegRegKey, + DCertDelegDeRegKey, + DCertDelegDelegate, + DCertPoolRegister, + DCertPoolRetire, + DCertGenesis, + DCertMir, +] + + +POSIXTime = int + + +@dataclass(unsafe_hash=True) +class NegInfPOSIXTime(PlutusData): + """ + Negative infinite POSIX time, used to indicate that there is no lower bound for the execution of this transaction + """ + + CONSTR_ID = 0 + + +@dataclass(unsafe_hash=True) +class FinitePOSIXTime(PlutusData): + """ + Finite POSIX time, used to indicate that there is a lower or upper bound for the execution of this transaction + """ + + CONSTR_ID = 1 + time: POSIXTime + + +@dataclass(unsafe_hash=True) +class PosInfPOSIXTime(PlutusData): + """ + Infinite POSIX time, used to indicate that there is no upper bound for the execution of this transaction + """ + + CONSTR_ID = 2 + + +ExtendedPOSIXTime = Union[NegInfPOSIXTime, FinitePOSIXTime, PosInfPOSIXTime] + + +@dataclass(unsafe_hash=True) +class UpperBoundPOSIXTime(PlutusData): + """ + Upper bound for the execution of this transaction + """ + + CONSTR_ID = 0 + limit: ExtendedPOSIXTime + closed: BoolData + + +@dataclass(unsafe_hash=True) +class LowerBoundPOSIXTime(PlutusData): + """ + Lower bound for the execution of this transaction + """ + + CONSTR_ID = 0 + limit: ExtendedPOSIXTime + closed: BoolData + + +@dataclass(unsafe_hash=True) +class POSIXTimeRange(PlutusData): + """ + Time range in which this transaction can be executed + """ + + lower_bound: LowerBoundPOSIXTime + upper_bound: UpperBoundPOSIXTime + + +@dataclass(unsafe_hash=True) +class Minting(PlutusData): + """ + Script purpose indicating that the given policy id is being minted or burned + """ + + CONSTR_ID = 0 + policy_id: PolicyId + + +@dataclass(unsafe_hash=True) +class Spending(PlutusData): + """ + Script purpose indicating that the given transaction output is being spent, which is + owned by the invoked contract + """ + + CONSTR_ID = 1 + tx_out_ref: TxOutRef + + +@dataclass(unsafe_hash=True) +class Rewarding(PlutusData): + CONSTR_ID = 2 + staking_credential: StakingCredential + + +@dataclass(unsafe_hash=True) +class Certifying(PlutusData): + CONSTR_ID = 3 + d_cert: DCert + + +# The reason that this script is being invoked +ScriptPurpose = Union[Minting, Spending, Rewarding, Certifying] + + +@dataclass(unsafe_hash=True) +class TxInfo(PlutusData): + """ + A complex agglomeration of everything that could be of interest to the executed script, regarding the transaction + that invoked the script + """ + + inputs: List[TxInInfo] + reference_inputs: List[TxInInfo] + outputs: List[TxOut] + fee: Value + mint: Value + dcert: List[DCert] + wdrl: Dict[StakingCredential, int] + valid_range: POSIXTimeRange + signatories: List[PubKeyHash] + redeemers: Dict[ScriptPurpose, Redeemer] + data: Dict[DatumHash, Datum] + id: TxId + + +@dataclass(unsafe_hash=True) +class ScriptContext(PlutusData): + """ + Auxiliary information about the transaction and reason for invocation of the called script. + """ + + tx_info: TxInfo + purpose: ScriptPurpose diff --git a/hebi/ledger/interval.py b/hebi/ledger/interval.py index 98540ce..cc4a9db 100644 --- a/hebi/ledger/interval.py +++ b/hebi/ledger/interval.py @@ -72,7 +72,7 @@ def compare_lower_bound(a: LowerBoundPOSIXTime, b: LowerBoundPOSIXTime) -> int: def contains(a: POSIXTimeRange, b: POSIXTimeRange) -> bool: - # Returns True if the interval `b` is entirely contained in `a`. + """Returns True if the interval `b` is entirely contained in `a`.""" lower = compare_lower_bound(a.lower_bound, b.lower_bound) upper = compare_upper_bound(a.upper_bound, b.upper_bound) return (lower == 1 or lower == 0) and (upper == 0 or upper == -1) @@ -81,24 +81,29 @@ def contains(a: POSIXTimeRange, b: POSIXTimeRange) -> bool: def make_range( lower_bound: POSIXTime, upper_bound: POSIXTime, - lower_closed: BoolData, - upper_closed: BoolData, ) -> POSIXTimeRange: + """ + Create a bounded interval from the given time `lower_bound` up to the given `upper_bound`, including the given time + """ return POSIXTimeRange( - LowerBoundPOSIXTime(FinitePOSIXTime(lower_bound), lower_closed), - UpperBoundPOSIXTime(FinitePOSIXTime(upper_bound), upper_closed), + LowerBoundPOSIXTime(FinitePOSIXTime(lower_bound), TrueData()), + UpperBoundPOSIXTime(FinitePOSIXTime(upper_bound), TrueData()), ) -def make_from(lower_bound: POSIXTime, lower_closed: BoolData) -> POSIXTimeRange: +def make_from(lower_bound: POSIXTime) -> POSIXTimeRange: + """Create a bounded interval from the given time `lower_bound` up to infinity, including the given time""" return POSIXTimeRange( - LowerBoundPOSIXTime(FinitePOSIXTime(lower_bound), lower_closed), + LowerBoundPOSIXTime(FinitePOSIXTime(lower_bound), TrueData()), UpperBoundPOSIXTime(PosInfPOSIXTime(), TrueData()), ) -def make_to(upper_bound: POSIXTime, upper_closed: BoolData) -> POSIXTimeRange: +def make_to(upper_bound: POSIXTime) -> POSIXTimeRange: + """ + Create a bounded interval from negative infinity up to the given `upper_bound`, including the given time + """ return POSIXTimeRange( LowerBoundPOSIXTime(NegInfPOSIXTime(), TrueData()), - UpperBoundPOSIXTime(FinitePOSIXTime(upper_bound), upper_closed), + UpperBoundPOSIXTime(FinitePOSIXTime(upper_bound), TrueData()), ) diff --git a/hebi/optimize/optimize_remove_comments.py b/hebi/optimize/optimize_remove_comments.py new file mode 100644 index 0000000..fe9d166 --- /dev/null +++ b/hebi/optimize/optimize_remove_comments.py @@ -0,0 +1,16 @@ +from ast import * + +from ..util import CompilingNodeTransformer + +""" +Removes expressions that return constants in sequences of statements (i.e. string comments) +""" + + +class OptimizeRemoveDeadconstants(CompilingNodeTransformer): + step = "Removing constants (i.e. string comments)" + + def visit_Expr(self, node: Expr): + if isinstance(node.value, Constant): + return None + return node diff --git a/hebi/prelude.py b/hebi/prelude.py index f442f6c..cd307f2 100644 --- a/hebi/prelude.py +++ b/hebi/prelude.py @@ -1,480 +1,8 @@ -from dataclasses import dataclass -from typing import Dict, List, Union from hashlib import sha256, sha3_256, blake2b +from hebi.ledger.api_v2 import * -from pycardano import Datum as Anything, PlutusData -# Plutus V2 -@dataclass() -class TxId(PlutusData): - """ - A transaction id, a 64 bytes long hash of the transaction body (also called transaction hash). - - Example value: TxId(bytes.fromhex("842a4d37b036da6ab3c04331240e67d81746beb44f23ad79703e026705361956")) - """ - - tx_id: bytes - - -@dataclass() -class Nothing(PlutusData): - """ - Nothing, can be used to signify non-importance of a parameter to a function - - Example value: Nothing() - """ - - # The maximimum constructor ID for simple cbor types, chosen to minimize probability of collision while keeping the corresponding cbor small - CONSTR_ID = 6 - - -@dataclass() -class TrueData(PlutusData): - """ - A Datum that represents True in Haskell implementations. - It is thus used as an encoding for True in the ScriptContext. - - Example value: TrueData() - """ - - CONSTR_ID = 0 - - -@dataclass() -class FalseData(PlutusData): - """ - A Datum that represents False in Haskell implementations. - It is thus used as an encoding for False in the ScriptContext. - - Example value: FalseData() - """ - - CONSTR_ID = 1 - - -# A Datum that represents a boolean value in Haskell implementations. -# It is thus used as an encoding for booleans in the ScriptContext. -# -# Example value: TrueData() -BoolData = Union[TrueData, FalseData] - - -@dataclass() -class TxOutRef(PlutusData): - """ - A reference to a transaction output (hash/id + index) - """ - - id: TxId - idx: int - - -# A public key hash, used to identify signatures provided by a wallet -PubKeyHash = bytes - - -@dataclass() -class PubKeyCredential(PlutusData): - """ - Part of an address that is authenticated by a public key hash - - Example value: PubKeyCredential(bytes.fromhex("c06ddaad12fc4ded18e56feac72957c1aa75fce6096b40e63ec88274")) - """ - - CONSTR_ID = 0 - credential_hash: PubKeyHash - - -# A validator hash, used to identify signatures provided by a smart contract -ValidatorHash = bytes - - -@dataclass() -class ScriptCredential(PlutusData): - """ - Part of an address that is authenticated by a smart cotnract - - Example value: ScriptCredential(bytes.fromhex("c06ddaad12fc4ded18e56feac72957c1aa75fce6096b40e63ec88274")) - """ - - CONSTR_ID = 1 - credential_hash: ValidatorHash - - -# A credential, either smart contract or public key hash -Credential = Union[PubKeyCredential, ScriptCredential] - - -@dataclass() -class StakingHash(PlutusData): - """ - Indicates that the stake of this address is controlled by the associated credential - """ - - CONSTR_ID = 0 - value: Credential - - -@dataclass() -class StakingPtr(PlutusData): - """ - Indicates that the stake of this address is controlled by the associated pointer. - - In an address, a chain pointer refers to a point of the chain containing a stake key registration certificate. - A point is identified by the 3 coordinates in this object. - """ - - CONSTR_ID = 1 - # an absolute slot number - slot_no: int - # a transaction index (within that slot) - tx_index: int - # a (delegation) certificate index (within that transaction) - cert_index: int - - -# Part of an address that controls who can delegate the stake associated with an address -StakingCredential = Union[StakingHash, StakingPtr] - - -@dataclass() -class NoStakingCredential(PlutusData): - """ - Indicates that this address has no staking credentials. - Its funds can not be delegated. - """ - - CONSTR_ID = 1 - - -@dataclass() -class SomeStakingCredential(PlutusData): - """ - Indicates that this address has staking credentials. - Its funds can be delegated by the credentialed user. - """ - - CONSTR_ID = 0 - staking_credential: StakingCredential - - -@dataclass() -class Address(PlutusData): - """ - A Shelley address, consisting of a payment and staking credential - """ - - payment_credential: Credential - staking_credential: Union[NoStakingCredential, SomeStakingCredential] - - -# The policy Id of a token -PolicyId = bytes - -# The name of a token in bytes (not textual representation!) -TokenName = bytes - -# The Plutus representation of amounts of tokens being spent, sent or minted -# It is a two-layered dictionary that stores for each policy id and token name -# the amount of the token that is being sent/minted/burned etc -# -# Lovelace is represented with policy id b"" and token name b"" -Value = Dict[PolicyId, Dict[TokenName, int]] - -# A hash of a Datum -DatumHash = bytes - - -@dataclass() -class SomeDatumHash(PlutusData): - """ - Indicates that there is a datum associated with this output, which has the given hash. - """ - - CONSTR_ID = 1 - datum_hash: DatumHash - - -@dataclass() -class SomeScriptHash(PlutusData): - """ - Indicates that there is a script associated with this output, which has the given hash. - """ - - CONSTR_ID = 0 - script_hash: DatumHash - - -# The abstract super type of any object in opshin. -# Use if you don't know what kind of object is being passed or if it doesn't matter. -BuiltinData = Anything - - -# An abstract type annotation that something is supposed to be used as a redeemer. -Redeemer = BuiltinData - - -# An abstract type annotation that something is supposed to be used as a datum. -Datum = BuiltinData - - -@dataclass() -class NoOutputDatum(PlutusData): - """ - Indicates that there is no datum associated with an output - """ - - CONSTR_ID = 0 - - -@dataclass() -class SomeOutputDatumHash(PlutusData): - """ - Indicates that there is an datum associated with an output, which has the attached hash - """ - - CONSTR_ID = 1 - datum_hash: DatumHash - - -@dataclass() -class SomeOutputDatum(PlutusData): - """ - Indicates that there is an datum associated with an output, which is inlined and equal to the attached datum - """ - - CONSTR_ID = 2 - datum: Datum - - -# Possible cases of datum association with an output -OutputDatum = Union[NoOutputDatum, SomeOutputDatumHash, SomeOutputDatum] - - -@dataclass() -class NoScriptHash(PlutusData): - """ - Indicates that there is no script associated with an output - """ - - CONSTR_ID = 1 - - -@dataclass() -class TxOut(PlutusData): - """ - The plutus representation of an transaction output, consisting of - - address: address owning this output - - value: tokens associated with this output - - datum: datum associated with this output - - reference_script: reference script associated with this output - """ - - address: Address - value: Value - datum: OutputDatum - reference_script: Union[NoScriptHash, SomeScriptHash] - - -@dataclass() -class TxInInfo(PlutusData): - """ - The plutus representation of an transaction output, that is consumed by the transaction. - """ - - out_ref: TxOutRef - resolved: TxOut - - -@dataclass() -class DCertDelegRegKey(PlutusData): - CONSTR_ID = 0 - value: StakingCredential - - -@dataclass() -class DCertDelegDeRegKey(PlutusData): - CONSTR_ID = 1 - value: StakingCredential - - -@dataclass() -class DCertDelegDelegate(PlutusData): - CONSTR_ID = 2 - delegator: StakingCredential - delegatee: PubKeyHash - - -@dataclass() -class DCertPoolRegister(PlutusData): - CONSTR_ID = 3 - pool_id: PubKeyHash - pool_vfr: PubKeyHash - - -@dataclass() -class DCertPoolRetire(PlutusData): - CONSTR_ID = 4 - retirement_certificate: PubKeyHash - epoch: int - - -@dataclass() -class DCertGenesis(PlutusData): - CONSTR_ID = 5 - - -@dataclass() -class DCertMir(PlutusData): - CONSTR_ID = 6 - - -DCert = Union[ - DCertDelegRegKey, - DCertDelegDeRegKey, - DCertDelegDelegate, - DCertPoolRegister, - DCertPoolRetire, - DCertGenesis, - DCertMir, -] - - -POSIXTime = int - - -@dataclass() -class NegInfPOSIXTime(PlutusData): - """ - Negative infinite POSIX time, used to indicate that there is no lower bound for the execution of this transaction - """ - - CONSTR_ID = 0 - - -@dataclass() -class FinitePOSIXTime(PlutusData): - """ - Finite POSIX time, used to indicate that there is a lower or upper bound for the execution of this transaction - """ - - CONSTR_ID = 1 - time: POSIXTime - - -@dataclass() -class PosInfPOSIXTime(PlutusData): - """ - Infinite POSIX time, used to indicate that there is no upper bound for the execution of this transaction - """ - - CONSTR_ID = 2 - - -ExtendedPOSIXTime = Union[NegInfPOSIXTime, FinitePOSIXTime, PosInfPOSIXTime] - - -@dataclass() -class UpperBoundPOSIXTime(PlutusData): - """ - Upper bound for the execution of this transaction - """ - - CONSTR_ID = 0 - limit: ExtendedPOSIXTime - closed: BoolData - - -@dataclass() -class LowerBoundPOSIXTime(PlutusData): - """ - Lower bound for the execution of this transaction - """ - - CONSTR_ID = 0 - limit: ExtendedPOSIXTime - closed: BoolData - - -@dataclass() -class POSIXTimeRange(PlutusData): - """ - Time range in which this transaction can be executed - """ - - lower_bound: LowerBoundPOSIXTime - upper_bound: UpperBoundPOSIXTime - - -@dataclass() -class Minting(PlutusData): - """ - Script purpose indicating that the given policy id is being minted or burned - """ - - CONSTR_ID = 0 - policy_id: PolicyId - - -@dataclass() -class Spending(PlutusData): - """ - Script purpose indicating that the given transaction output is being spent, which is - owned by the invoked contract - """ - - CONSTR_ID = 1 - tx_out_ref: TxOutRef - - -@dataclass() -class Rewarding(PlutusData): - CONSTR_ID = 2 - staking_credential: StakingCredential - - -@dataclass() -class Certifying(PlutusData): - CONSTR_ID = 3 - d_cert: DCert - - -# The reason that this script is being invoked -ScriptPurpose = Union[Minting, Spending, Rewarding, Certifying] - - -@dataclass() -class TxInfo(PlutusData): - """ - A complex agglomeration of everything that could be of interest to the executed script, regarding the transaction - that invoked the script - """ - - inputs: List[TxInInfo] - reference_inputs: List[TxInInfo] - outputs: List[TxOut] - fee: Value - mint: Value - dcert: List[DCert] - wdrl: Dict[StakingCredential, int] - valid_range: POSIXTimeRange - signatories: List[PubKeyHash] - redeemers: Dict[ScriptPurpose, Redeemer] - data: Dict[DatumHash, Datum] - id: TxId - - -@dataclass() -class ScriptContext(PlutusData): - """ - Auxiliary information about the transaction and reason for invocation of the called script. - """ - - tx_info: TxInfo - purpose: ScriptPurpose - - -@dataclass() +@dataclass(unsafe_hash=True) class Token(PlutusData): """ A token, represented by policy id and token name @@ -532,3 +60,37 @@ def all_tokens_locked_at_address( def resolve_spent_utxo(txins: List[TxInInfo], p: Spending) -> TxOut: """Returns the UTxO whose spending should be validated""" return [txi.resolved for txi in txins if txi.out_ref == p.tx_out_ref][0] + + +def resolve_datum_unsafe(txout: TxOut, tx_info: TxInfo) -> BuiltinData: + """ + Returns the datum attached to a given transaction output, independent of whether it was inlined or embedded. + Raises an exception if no datum was attached. + """ + attached_datum = txout.datum + if isinstance(attached_datum, SomeOutputDatumHash): + res = tx_info.data[attached_datum.datum_hash] + elif isinstance(attached_datum, SomeOutputDatum): + res = attached_datum.datum + else: + # no datum attached + assert False, "No datum was attached to the given transaction output" + return res + + +def resolve_datum( + txout: TxOut, tx_info: TxInfo +) -> Union[SomeOutputDatum, NoOutputDatum]: + """ + Returns SomeOutputDatum with the datum attached to a given transaction output, + independent of whether it was inlined or embedded, if there was an attached datum. + Otherwise it returns NoOutputDatum. + """ + attached_datum = txout.datum + if isinstance(attached_datum, SomeOutputDatumHash): + res: Union[SomeOutputDatum, NoOutputDatum] = SomeOutputDatum( + tx_info.data[attached_datum.datum_hash] + ) + else: + res: Union[SomeOutputDatum, NoOutputDatum] = attached_datum + return res diff --git a/hebi/rewrite/rewrite_import_dataclasses.py b/hebi/rewrite/rewrite_import_dataclasses.py index c59d3b6..ca3717f 100644 --- a/hebi/rewrite/rewrite_import_dataclasses.py +++ b/hebi/rewrite/rewrite_import_dataclasses.py @@ -35,14 +35,17 @@ def visit_ClassDef(self, node: ClassDef) -> ClassDef: ), "dataclasses must be imported in order to use datum classes" assert ( len(node.decorator_list) == 1 - ), "Class definitions must have no decorators but @dataclass()" + ), "Class definitions must have the decorator @dataclass" + if isinstance(node.decorator_list[0], Call): + node_decorator = node.decorator_list[0].func + elif isinstance(node.decorator_list[0], Name): + node_decorator = node.decorator_list[0] + else: + raise AssertionError("Class definitions must have the decorator @dataclass") assert isinstance( - node.decorator_list[0], Call - ), "Class definitions must have no decorators but @dataclass()" - assert isinstance( - node.decorator_list[0].func, Name - ), "Class definitions must have no decorators but @dataclass()" + node_decorator, Name + ), "Class definitions must have the decorator @dataclass" assert ( - node.decorator_list[0].func.id == "dataclass" - ), "Class definitions must have no decorators but @dataclass()" + node_decorator.id == "dataclass" + ), "Class definitions must have the decorator @dataclass" return node diff --git a/hebi/rewrite/rewrite_import_hashlib.py b/hebi/rewrite/rewrite_import_hashlib.py index 2f194fb..eb23d89 100644 --- a/hebi/rewrite/rewrite_import_hashlib.py +++ b/hebi/rewrite/rewrite_import_hashlib.py @@ -23,6 +23,9 @@ def attribute(self, attr) -> plt.AST: return plt.Lambda(["self"], plt.Var("self")) raise NotImplementedError("HashType only has attribute 'digest'") + def __ge__(self, other): + return isinstance(other, HashType) + HashInstanceType = InstanceType(HashType()) diff --git a/hebi/rewrite/rewrite_tuple_assign.py b/hebi/rewrite/rewrite_tuple_assign.py index 0bc4b89..23a1721 100644 --- a/hebi/rewrite/rewrite_tuple_assign.py +++ b/hebi/rewrite/rewrite_tuple_assign.py @@ -1,3 +1,5 @@ +from copy import copy + import typing from ast import * @@ -33,3 +35,31 @@ def visit_Assign(self, node: Assign) -> typing.List[stmt]: # recursively resolve multiple layers of tuples transformed = sum([self.visit(a) for a in assignments], []) return transformed + + def visit_For(self, node: For) -> For: + # rewrite deconstruction in for loops + if not isinstance(node.target, Tuple): + return self.generic_visit(node) + new_for = copy(node) + new_for.iter = self.visit(node.iter) + uid = self.unique_id + self.unique_id += 1 + # write the tuple into a singleton variable + new_for.target = Name(f"{uid}_tup", Store()) + assignments = [] + # iteratively assign the deconstructed parts to the original variable names + for i, t in enumerate(node.target.elts): + assignments.append( + Assign( + [t], + Subscript( + value=Name(f"{uid}_tup", Load()), + slice=Constant(i), + ctx=Load(), + ), + ) + ) + new_for.body = assignments + node.body + # recursively resolve multiple layers of tuples + # further layers should be handled by the normal tuple assignment though + return self.visit(new_for) diff --git a/hebi/std/__init__.py b/hebi/std/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/hebi/std/fractions.py b/hebi/std/fractions.py new file mode 100644 index 0000000..435400a --- /dev/null +++ b/hebi/std/fractions.py @@ -0,0 +1,101 @@ +""" +An implementation of fractions in opshin +This does not maintain smallest possible notation invariants for the sake of efficiency +- the user has full control over when to normalize the fractions and should do so using norm_fraction +""" +from dataclasses import dataclass +from pycardano import PlutusData + +from hebi.std.math import * + + +@dataclass(unsafe_hash=True) +class Fraction(PlutusData): + CONSTR_ID = 1 + numerator: int + denominator: int + + +def add_fraction(a: Fraction, b: Fraction) -> Fraction: + """returns a + b""" + return Fraction( + (a.numerator * b.denominator) + (b.numerator * a.denominator), + a.denominator * b.denominator, + ) + + +def neg_fraction(a: Fraction) -> Fraction: + """returns -a""" + return Fraction(-a.numerator, a.denominator) + + +def sub_fraction(a: Fraction, b: Fraction) -> Fraction: + """returns a - b""" + return add_fraction(a, neg_fraction(b)) + + +def mul_fraction(a: Fraction, b: Fraction) -> Fraction: + """returns a * b""" + return Fraction(a.numerator * b.numerator, a.denominator * b.denominator) + + +def div_fraction(a: Fraction, b: Fraction) -> Fraction: + """returns a / b""" + return Fraction(a.numerator * b.denominator, a.denominator * b.numerator) + + +def _norm_signs_fraction(a: Fraction) -> Fraction: + """Restores the invariant that the denominator is > 0""" + return Fraction(sign(a.denominator) * a.numerator, abs(a.denominator)) + + +def _norm_gcd_fraction(a: Fraction) -> Fraction: + """Restores the invariant that num/denom are in the smallest possible denomination""" + g = gcd(a.numerator, a.denominator) + return Fraction(a.numerator // g, a.denominator // g) + + +def norm_fraction(a: Fraction) -> Fraction: + """Restores the invariant that num/denom are in the smallest possible denomination and denominator > 0""" + return _norm_gcd_fraction(_norm_signs_fraction(a)) + + +def ge_fraction(a: Fraction, b: Fraction) -> bool: + """returns a >= b""" + if a.denominator * b.denominator >= 0: + res = a.numerator * b.denominator >= a.denominator * b.numerator + else: + res = a.numerator * b.denominator <= a.denominator * b.numerator + return res + + +def le_fraction(a: Fraction, b: Fraction) -> bool: + """returns a <= b""" + if a.denominator * b.denominator >= 0: + res = a.numerator * b.denominator <= a.denominator * b.numerator + else: + res = a.numerator * b.denominator >= a.denominator * b.numerator + return res + + +def eq_fraction(a: Fraction, b: Fraction) -> bool: + """returns a == b""" + return a.numerator * b.denominator == a.denominator * b.numerator + + +def lt_fraction(a: Fraction, b: Fraction) -> bool: + """returns a < b""" + if a.denominator * b.denominator >= 0: + res = a.numerator * b.denominator < a.denominator * b.numerator + else: + res = a.numerator * b.denominator > a.denominator * b.numerator + return res + + +def gt_fraction(a: Fraction, b: Fraction) -> bool: + """returns a > b""" + if a.denominator * b.denominator >= 0: + res = a.numerator * b.denominator > a.denominator * b.numerator + else: + res = a.numerator * b.denominator < a.denominator * b.numerator + return res diff --git a/hebi/std/math.py b/hebi/std/math.py new file mode 100644 index 0000000..19eb852 --- /dev/null +++ b/hebi/std/math.py @@ -0,0 +1,19 @@ +""" An implementation of some math operations in opshin """ + + +def gcd(a: int, b: int) -> int: + while b != 0: + a, b = b, a % b + return abs(a) + + +def sign(a: int) -> int: + return -1 if a < 0 else 1 + + +def unsigned_int_from_bytes_big(b: bytes) -> int: + """Converts a bytestring into the corresponding integer, big/network byteorder, unsigned""" + acc = 0 + for i in range(len(b)): + acc = acc * 256 + b[i] + return acc diff --git a/hebi/tests/test_ledger/test_api_v2.py b/hebi/tests/test_ledger/test_api_v2.py new file mode 100644 index 0000000..11106c7 --- /dev/null +++ b/hebi/tests/test_ledger/test_api_v2.py @@ -0,0 +1,23 @@ +from parameterized import parameterized + +from hebi.ledger.api_v2 import * + + +@parameterized.expand( + [ + ( + "d8799fd8799f9fd8799fd8799fd8799f582055d353acacaab6460b37ed0f0e3a1a0aabf056df4a7fa1e265d21149ccacc527ff01ffd8799fd8799fd87a9f581cdbe769758f26efb21f008dc097bb194cffc622acc37fcefc5372eee3ffd87a80ffa140a1401a00989680d87a9f5820dfab81872ce2bbe6ee5af9bbfee4047f91c1f57db5e30da727d5fef1e7f02f4dffd87a80ffffff809fd8799fd8799fd8799f581cdc315c289fee4484eda07038393f21dc4e572aff292d7926018725c2ffd87a80ffa140a14000d87980d87a80ffffa140a14000a140a1400080a0d8799fd8799fd87980d87a80ffd8799fd87b80d87a80ffff80a1d87a9fd8799fd8799f582055d353acacaab6460b37ed0f0e3a1a0aabf056df4a7fa1e265d21149ccacc527ff01ffffd87980a15820dfab81872ce2bbe6ee5af9bbfee4047f91c1f57db5e30da727d5fef1e7f02f4dd8799f581cdc315c289fee4484eda07038393f21dc4e572aff292d7926018725c2ffd8799f5820746957f0eb57f2b11119684e611a98f373afea93473fefbb7632d579af2f6259ffffd87a9fd8799fd8799f582055d353acacaab6460b37ed0f0e3a1a0aabf056df4a7fa1e265d21149ccacc527ff01ffffff" + ), + ( + "d8799fd8799f9fd8799fd8799fd8799f582055d353acacaab6460b37ed0f0e3a1a0aabf056df4a7fa1e265d21149ccacc527ff01ffd8799fd8799fd87a9f581cdbe769758f26efb21f008dc097bb194cffc622acc37fcefc5372eee3ffd87a80ffa140a1401a00989680d87a9f5820dfab81872ce2bbe6ee5af9bbfee4047f91c1f57db5e30da727d5fef1e7f02f4dffd87a80ffffff809fd8799fd8799fd8799f581cdc315c289fee4484eda07038393f21dc4e572aff292d7926018725c2ffd87a80ffa140a14000d87980d87a80ffffa140a14000a140a1400080a0d8799fd8799fd87a9f1b000001836ac117d8ffd87a80ffd8799fd87b80d87a80ffff80a1d87a9fd8799fd8799f582055d353acacaab6460b37ed0f0e3a1a0aabf056df4a7fa1e265d21149ccacc527ff01ffffd87980a15820dfab81872ce2bbe6ee5af9bbfee4047f91c1f57db5e30da727d5fef1e7f02f4dd8799f581cdc315c289fee4484eda07038393f21dc4e572aff292d7926018725c2ffd8799f5820797a1e1720b63621c6b185088184cb8e23af6e46b55bd83e7a91024c823a6c2affffd87a9fd8799fd8799f582055d353acacaab6460b37ed0f0e3a1a0aabf056df4a7fa1e265d21149ccacc527ff01ffffff" + ), + ( + "d8799fd8799f9fd8799fd8799fd8799f582055d353acacaab6460b37ed0f0e3a1a0aabf056df4a7fa1e265d21149ccacc527ff01ffd8799fd8799fd87a9f581cdbe769758f26efb21f008dc097bb194cffc622acc37fcefc5372eee3ffd87a80ffa140a1401a00989680d87a9f5820dfab81872ce2bbe6ee5af9bbfee4047f91c1f57db5e30da727d5fef1e7f02f4dffd87a80ffffff809fd8799fd8799fd8799f581cdc315c289fee4484eda07038393f21dc4e572aff292d7926018725c2ffd87a80ffa140a14000d87980d87a80ffd8799fd8799fd8799f581cdc315c289fee4484eda07038393f21dc4e572aff292d7926018725c2ffd87a80ffa140a1401a000f4240d87980d87a80ffffa140a14000a140a1400080a0d8799fd8799fd87a9f1b000001836ac117d8ffd87a80ffd8799fd87b80d87a80ffff9f581cdc315c289fee4484eda07038393f21dc4e572aff292d7926018725c2ffa1d87a9fd8799fd8799f582055d353acacaab6460b37ed0f0e3a1a0aabf056df4a7fa1e265d21149ccacc527ff01ffffd87980a15820dfab81872ce2bbe6ee5af9bbfee4047f91c1f57db5e30da727d5fef1e7f02f4dd8799f581cdc315c289fee4484eda07038393f21dc4e572aff292d7926018725c2ffd8799f5820c17c32f6433ae22c2acaebfb796bbfaee3993ff7ebb58a2bac6b4a3bdd2f6d28ffffd87a9fd8799fd8799f582055d353acacaab6460b37ed0f0e3a1a0aabf056df4a7fa1e265d21149ccacc527ff01ffffff" + ), + ] +) +def test_script_context_repr_correct(p): + # Make sure that this parses correctly and does not throw an error + # Note that this was extracted from a PlutusV2 invocation + # in increasing complexity... + ScriptContext.from_cbor(p) diff --git a/hebi/tests/test_ledger/test_interval.py b/hebi/tests/test_ledger/test_interval.py index 003b01f..fb83541 100644 --- a/hebi/tests/test_ledger/test_interval.py +++ b/hebi/tests/test_ledger/test_interval.py @@ -147,44 +147,34 @@ def test_contains(a: POSIXTimeRange, b: POSIXTimeRange): @given( lower_bound=st.integers(), - lower_closed=st.one_of(st.builds(FalseData), st.builds(TrueData)), ) def test_fuzz_make_from( lower_bound: int, - lower_closed: BoolData, ) -> None: - make_from(lower_bound=lower_bound, lower_closed=lower_closed) + make_from(lower_bound=lower_bound) @given( lower_bound=st.integers(), upper_bound=st.integers(), - lower_closed=st.one_of(st.builds(FalseData), st.builds(TrueData)), - upper_closed=st.one_of(st.builds(FalseData), st.builds(TrueData)), ) def test_fuzz_make_range( lower_bound: int, upper_bound: int, - lower_closed: BoolData, - upper_closed: BoolData, ) -> None: make_range( lower_bound=lower_bound, upper_bound=upper_bound, - lower_closed=lower_closed, - upper_closed=upper_closed, ) @given( upper_bound=st.integers(), - upper_closed=st.one_of(st.builds(FalseData), st.builds(TrueData)), ) def test_fuzz_make_to( upper_bound: int, - upper_closed: BoolData, ) -> None: - make_to(upper_bound=upper_bound, upper_closed=upper_closed) + make_to(upper_bound=upper_bound) @given( @@ -205,3 +195,33 @@ def test_get_bool(b: bool) -> None: else: bool_data = FalseData() assert get_bool(bool_data) == b + + +@given( + lower_bound=st.integers(), + upper_bound_1=st.integers(), + upper_bound_2=st.integers(), +) +def test_make_to_in_make_range( + lower_bound: int, + upper_bound_1: int, + upper_bound_2: int, +) -> None: + assert contains( + make_to(upper_bound=upper_bound_1), make_range(lower_bound, upper_bound_2) + ) == (upper_bound_1 >= upper_bound_2) + + +@given( + lower_bound_1=st.integers(), + lower_bound_2=st.integers(), + upper_bound=st.integers(), +) +def test_make_from_in_make_range( + lower_bound_1: int, + lower_bound_2: int, + upper_bound: int, +) -> None: + assert contains( + make_from(lower_bound=lower_bound_1), make_range(lower_bound_2, upper_bound) + ) == (lower_bound_1 <= lower_bound_2) diff --git a/hebi/tests/test_misc.py b/hebi/tests/test_misc.py index 97c6e39..f4f172e 100644 --- a/hebi/tests/test_misc.py +++ b/hebi/tests/test_misc.py @@ -164,25 +164,6 @@ def test_fib_rec(self, n): ret, ) - @parameterized.expand( - [ - ( - "d8799fd8799f9fd8799fd8799fd8799f582055d353acacaab6460b37ed0f0e3a1a0aabf056df4a7fa1e265d21149ccacc527ff01ffd8799fd8799fd87a9f581cdbe769758f26efb21f008dc097bb194cffc622acc37fcefc5372eee3ffd87a80ffa140a1401a00989680d87a9f5820dfab81872ce2bbe6ee5af9bbfee4047f91c1f57db5e30da727d5fef1e7f02f4dffd87a80ffffff809fd8799fd8799fd8799f581cdc315c289fee4484eda07038393f21dc4e572aff292d7926018725c2ffd87a80ffa140a14000d87980d87a80ffffa140a14000a140a1400080a0d8799fd8799fd87980d87a80ffd8799fd87b80d87a80ffff80a1d87a9fd8799fd8799f582055d353acacaab6460b37ed0f0e3a1a0aabf056df4a7fa1e265d21149ccacc527ff01ffffd87980a15820dfab81872ce2bbe6ee5af9bbfee4047f91c1f57db5e30da727d5fef1e7f02f4dd8799f581cdc315c289fee4484eda07038393f21dc4e572aff292d7926018725c2ffd8799f5820746957f0eb57f2b11119684e611a98f373afea93473fefbb7632d579af2f6259ffffd87a9fd8799fd8799f582055d353acacaab6460b37ed0f0e3a1a0aabf056df4a7fa1e265d21149ccacc527ff01ffffff" - ), - ( - "d8799fd8799f9fd8799fd8799fd8799f582055d353acacaab6460b37ed0f0e3a1a0aabf056df4a7fa1e265d21149ccacc527ff01ffd8799fd8799fd87a9f581cdbe769758f26efb21f008dc097bb194cffc622acc37fcefc5372eee3ffd87a80ffa140a1401a00989680d87a9f5820dfab81872ce2bbe6ee5af9bbfee4047f91c1f57db5e30da727d5fef1e7f02f4dffd87a80ffffff809fd8799fd8799fd8799f581cdc315c289fee4484eda07038393f21dc4e572aff292d7926018725c2ffd87a80ffa140a14000d87980d87a80ffffa140a14000a140a1400080a0d8799fd8799fd87a9f1b000001836ac117d8ffd87a80ffd8799fd87b80d87a80ffff80a1d87a9fd8799fd8799f582055d353acacaab6460b37ed0f0e3a1a0aabf056df4a7fa1e265d21149ccacc527ff01ffffd87980a15820dfab81872ce2bbe6ee5af9bbfee4047f91c1f57db5e30da727d5fef1e7f02f4dd8799f581cdc315c289fee4484eda07038393f21dc4e572aff292d7926018725c2ffd8799f5820797a1e1720b63621c6b185088184cb8e23af6e46b55bd83e7a91024c823a6c2affffd87a9fd8799fd8799f582055d353acacaab6460b37ed0f0e3a1a0aabf056df4a7fa1e265d21149ccacc527ff01ffffff" - ), - ( - "d8799fd8799f9fd8799fd8799fd8799f582055d353acacaab6460b37ed0f0e3a1a0aabf056df4a7fa1e265d21149ccacc527ff01ffd8799fd8799fd87a9f581cdbe769758f26efb21f008dc097bb194cffc622acc37fcefc5372eee3ffd87a80ffa140a1401a00989680d87a9f5820dfab81872ce2bbe6ee5af9bbfee4047f91c1f57db5e30da727d5fef1e7f02f4dffd87a80ffffff809fd8799fd8799fd8799f581cdc315c289fee4484eda07038393f21dc4e572aff292d7926018725c2ffd87a80ffa140a14000d87980d87a80ffd8799fd8799fd8799f581cdc315c289fee4484eda07038393f21dc4e572aff292d7926018725c2ffd87a80ffa140a1401a000f4240d87980d87a80ffffa140a14000a140a1400080a0d8799fd8799fd87a9f1b000001836ac117d8ffd87a80ffd8799fd87b80d87a80ffff9f581cdc315c289fee4484eda07038393f21dc4e572aff292d7926018725c2ffa1d87a9fd8799fd8799f582055d353acacaab6460b37ed0f0e3a1a0aabf056df4a7fa1e265d21149ccacc527ff01ffffd87980a15820dfab81872ce2bbe6ee5af9bbfee4047f91c1f57db5e30da727d5fef1e7f02f4dd8799f581cdc315c289fee4484eda07038393f21dc4e572aff292d7926018725c2ffd8799f5820c17c32f6433ae22c2acaebfb796bbfaee3993ff7ebb58a2bac6b4a3bdd2f6d28ffffd87a9fd8799fd8799f582055d353acacaab6460b37ed0f0e3a1a0aabf056df4a7fa1e265d21149ccacc527ff01ffffff" - ), - ] - ) - def test_script_context_repr_correct(self, p): - # Make sure that this parses correctly and does not throw an error - # Note that this was extracted from a PlutusV2 invocation - # in increasing complexity... - prelude.ScriptContext.from_cbor(p) - def test_gift_contract_succeed(self): input_file = "examples/smart_contracts/gift.py" with open(input_file) as fp: @@ -680,14 +661,49 @@ def validator(x: Anything) -> int: res = uplc_eval(uplc.Apply(code, uplc.PlutusInteger(0))).value self.assertEqual(res, 0) - @unittest.expectedFailure def test_typecast_int_anything(self): - # this should not compile, we can not upcast with this notation - # up to discussion whether this should be allowed, but i.g. it should never be necessary or useful + # this should compile, it happens implicitly anyways when calling a function with Any parameters source_code = """ def validator(x: int) -> Anything: b: Anything = x - return x + return b +""" + ast = compiler.parse(source_code) + code = compiler.compile(ast).compile() + res = uplc_eval(uplc.Apply(code, uplc.PlutusInteger(0))).value + self.assertEqual(res, 0) + + def test_typecast_int_anything_int(self): + source_code = """ +def validator(x: int) -> Anything: + b: Anything = x + c: int = b + return c + 1 +""" + ast = compiler.parse(source_code) + code = compiler.compile(ast).compile() + res = uplc_eval(uplc.Apply(code, uplc.PlutusInteger(0))).value + self.assertEqual(res, 1) + + def test_typecast_anything_int_anything(self): + source_code = """ +def validator(x: Anything) -> Anything: + b: int = x + c: Anything = b + 1 + return c +""" + ast = compiler.parse(source_code) + code = compiler.compile(ast).compile() + res = uplc_eval(uplc.Apply(code, uplc.PlutusInteger(0))).value + self.assertEqual(res, 1) + + @unittest.expectedFailure + def test_typecast_int_str(self): + # this should compile, the two types are unrelated and there is no meaningful way to cast them either direction + source_code = """ +def validator(x: int) -> str: + b: str = x + return b """ ast = compiler.parse(source_code) code = compiler.compile(ast) @@ -754,3 +770,76 @@ def validator(x: None) -> None: ast = compiler.parse(source_code) code = compiler.compile(ast).compile() res = uplc_eval(uplc.Apply(code, uplc.PlutusInteger(0))) + + def test_return_anything(self): + source_code = """ +from hebi.prelude import * + +def validator() -> Anything: + return b"" +""" + ast = compiler.parse(source_code) + code = compiler.compile(ast).compile() + res = uplc_eval(uplc.Apply(code, uplc.PlutusConstr(0, []))) + self.assertEqual(res, uplc.PlutusByteString(b"")) + + def test_no_return_annotation(self): + source_code = """ +from hebi.prelude import * + +def validator(): + return b"" +""" + ast = compiler.parse(source_code) + code = compiler.compile(ast).compile() + res = uplc_eval(uplc.Apply(code, uplc.PlutusConstr(0, []))) + self.assertEqual(res, uplc.PlutusByteString(b"")) + + def test_no_parameter_annotation(self): + source_code = """ +from hebi.prelude import * + +def validator(a) -> bytes: + b: bytes = a + return b +""" + ast = compiler.parse(source_code) + code = compiler.compile(ast).compile() + res = uplc_eval(uplc.Apply(code, uplc.PlutusByteString(b""))) + self.assertEqual(res, uplc.PlutusByteString(b"")) + + def test_nested_deconstruction(self): + source_code = """ +def validator(xs) -> int: + a, ((b, c), d) = (1, ((2, 3), 4)) + return a + b + c + d +""" + ast = compiler.parse(source_code) + code = compiler.compile(ast) + code = code.compile() + f = code.term + # UPLC lambdas may only take one argument at a time, so we evaluate by repeatedly applying + f = uplc.Apply(f, uplc.PlutusConstr(0, [])) + ret = uplc_eval(f).value + self.assertEqual( + ret, + 1 + 2 + 3 + 4, + "for loop deconstruction did not behave as expected", + ) + + def test_different_return_types_anything(self): + source_code = """ +from hebi.prelude import * + +def validator(a: int) -> Anything: + if a > 0: + return b"" + else: + return 0 +""" + ast = compiler.parse(source_code) + code = compiler.compile(ast).compile() + res = uplc_eval(uplc.Apply(code, uplc.PlutusInteger(1))) + self.assertEqual(res, uplc.PlutusByteString(b"")) + res = uplc_eval(uplc.Apply(code, uplc.PlutusInteger(-1))) + self.assertEqual(res, uplc.PlutusInteger(0)) diff --git a/hebi/tests/test_std/__init__.py b/hebi/tests/test_std/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/hebi/tests/test_std/test_fractions.py b/hebi/tests/test_std/test_fractions.py new file mode 100644 index 0000000..90caa6c --- /dev/null +++ b/hebi/tests/test_std/test_fractions.py @@ -0,0 +1,110 @@ +import hypothesis +import hypothesis.strategies as hst + +from hebi.std import fractions as oc_fractions + +import fractions as native_fractions + +non_null = hst.one_of(hst.integers(min_value=1), hst.integers(max_value=-1)) +denormalized_fractions = hst.builds(oc_fractions.Fraction, hst.integers(), non_null) +denormalized_fractions_non_null = hst.builds(oc_fractions.Fraction, non_null, non_null) + + +def native_fraction_from_oc_fraction(f: oc_fractions.Fraction): + return native_fractions.Fraction(f.numerator, f.denominator) + + +@hypothesis.given(denormalized_fractions, denormalized_fractions) +def test_add(a: oc_fractions.Fraction, b: oc_fractions.Fraction): + oc_added = oc_fractions.add_fraction(a, b) + oc_normalized = native_fraction_from_oc_fraction(oc_added) + assert oc_normalized == ( + native_fraction_from_oc_fraction(a) + native_fraction_from_oc_fraction(b) + ), "Invalid add" + + +@hypothesis.given(denormalized_fractions, denormalized_fractions) +def test_sub(a: oc_fractions.Fraction, b: oc_fractions.Fraction): + oc_subbed = oc_fractions.sub_fraction(a, b) + oc_normalized = native_fraction_from_oc_fraction(oc_subbed) + assert oc_normalized == ( + native_fraction_from_oc_fraction(a) - native_fraction_from_oc_fraction(b) + ), "Invalid sub" + + +@hypothesis.given(denormalized_fractions) +def test_neg(a: oc_fractions.Fraction): + oc_negged = oc_fractions.neg_fraction(a) + oc_normalized = native_fraction_from_oc_fraction(oc_negged) + assert oc_normalized == -native_fraction_from_oc_fraction(a), "Invalid neg" + + +@hypothesis.given(denormalized_fractions, denormalized_fractions) +def test_mul(a: oc_fractions.Fraction, b: oc_fractions.Fraction): + oc_mulled = oc_fractions.mul_fraction(a, b) + oc_normalized = native_fraction_from_oc_fraction(oc_mulled) + assert oc_normalized == ( + native_fraction_from_oc_fraction(a) * native_fraction_from_oc_fraction(b) + ), "Invalid mul" + + +@hypothesis.given(denormalized_fractions, denormalized_fractions_non_null) +def test_div(a: oc_fractions.Fraction, b: oc_fractions.Fraction): + oc_divved = oc_fractions.div_fraction(a, b) + oc_normalized = native_fraction_from_oc_fraction(oc_divved) + assert oc_normalized == ( + native_fraction_from_oc_fraction(a) / native_fraction_from_oc_fraction(b) + ), "Invalid div" + + +@hypothesis.given(denormalized_fractions) +def test_norm_sign(a: oc_fractions.Fraction): + oc_normed = oc_fractions._norm_signs_fraction(a) + assert oc_normed.denominator > 0, "invalid norm_signs" + oc_normalized = native_fraction_from_oc_fraction(oc_normed) + oc_a_normalized = native_fraction_from_oc_fraction(a) + assert oc_normalized == oc_a_normalized, "invalid norm_signs" + + +@hypothesis.given(denormalized_fractions) +@hypothesis.example(oc_fractions.Fraction(0, -1)) +def test_norm(a: oc_fractions.Fraction): + oc_normed = oc_fractions.norm_fraction(a) + oc_normalized = native_fraction_from_oc_fraction(a) + assert oc_normed.numerator == oc_normalized.numerator, "Invalid norm" + assert oc_normed.denominator == oc_normalized.denominator, "Invalid norm" + + +@hypothesis.given(denormalized_fractions, denormalized_fractions) +def test_ge(a: oc_fractions.Fraction, b: oc_fractions.Fraction): + oc_ge = oc_fractions.ge_fraction(a, b) + ge = native_fraction_from_oc_fraction(a) >= native_fraction_from_oc_fraction(b) + assert oc_ge == ge, "Invalid ge" + + +@hypothesis.given(denormalized_fractions, denormalized_fractions) +def test_le(a: oc_fractions.Fraction, b: oc_fractions.Fraction): + oc_le = oc_fractions.le_fraction(a, b) + le = native_fraction_from_oc_fraction(a) <= native_fraction_from_oc_fraction(b) + assert oc_le == le, "Invalid le" + + +@hypothesis.given(denormalized_fractions, denormalized_fractions) +def test_lt(a: oc_fractions.Fraction, b: oc_fractions.Fraction): + oc_lt = oc_fractions.lt_fraction(a, b) + lt = native_fraction_from_oc_fraction(a) < native_fraction_from_oc_fraction(b) + assert oc_lt == lt, "Invalid lt" + + +@hypothesis.given(denormalized_fractions, denormalized_fractions) +def test_gt(a: oc_fractions.Fraction, b: oc_fractions.Fraction): + oc_gt = oc_fractions.gt_fraction(a, b) + gt = native_fraction_from_oc_fraction(a) > native_fraction_from_oc_fraction(b) + assert oc_gt == gt, "Invalid gt" + + +@hypothesis.given(denormalized_fractions, denormalized_fractions) +def test_eq(a: oc_fractions.Fraction, b: oc_fractions.Fraction): + oc_eq = oc_fractions.eq_fraction(a, b) + eq = native_fraction_from_oc_fraction(a) == native_fraction_from_oc_fraction(b) + assert oc_eq == eq, "Invalid eq" diff --git a/hebi/tests/test_std/test_math.py b/hebi/tests/test_std/test_math.py new file mode 100644 index 0000000..e768063 --- /dev/null +++ b/hebi/tests/test_std/test_math.py @@ -0,0 +1,25 @@ +import hypothesis +import hypothesis.strategies as hst + +from hebi.std import math as oc_math + +import math + +pos_int = hst.integers(min_value=0) + + +@hypothesis.given(pos_int, pos_int) +def test_gcd(a: int, b: int): + assert oc_math.gcd(a, b) == math.gcd(a, b), "Invalid gcd" + + +@hypothesis.given(hst.integers()) +def test_sign(a: int): + assert oc_math.sign(a) == math.copysign(1, a), "Invalid sign" + + +@hypothesis.given(hst.binary()) +def test_unsigned_int_from_bytes_big(b: bytes): + assert oc_math.unsigned_int_from_bytes_big(b) == int.from_bytes( + b, byteorder="big", signed=False + ), "Invalid from bytes" diff --git a/hebi/tests/test_stdlib.py b/hebi/tests/test_stdlib.py index 62d1066..c7d89d2 100644 --- a/hebi/tests/test_stdlib.py +++ b/hebi/tests/test_stdlib.py @@ -8,6 +8,65 @@ class StdlibTest(unittest.TestCase): + @given(st.data()) + def test_dict_get(self, data): + # this tests that errors that are caused by assignments are actually triggered at the time of assigning + source_code = """ +def validator(x: Dict[int, bytes], y: int, z: bytes) -> bytes: + return x.get(y, z) + """ + ast = compiler.parse(source_code) + code = compiler.compile(ast) + code = code.compile() + f = code.term + + x = data.draw(st.dictionaries(st.integers(), st.binary())) + y = data.draw(st.one_of(st.sampled_from(sorted(x.keys()) + [0]), st.integers())) + z = data.draw(st.binary()) + # UPLC lambdas may only take one argument at a time, so we evaluate by repeatedly applying + for d in [ + uplc.PlutusMap( + {uplc.PlutusInteger(k): uplc.PlutusByteString(v) for k, v in x.items()} + ), + uplc.PlutusInteger(y), + uplc.PlutusByteString(z), + ]: + f = uplc.Apply(f, d) + ret = uplc_eval(f).value + self.assertEqual(ret, x.get(y, z), "dict.get returned wrong value") + + @given(st.data()) + def test_dict_subscript(self, data): + # this tests that errors that are caused by assignments are actually triggered at the time of assigning + source_code = """ +def validator(x: Dict[int, bytes], y: int) -> bytes: + return x[y] + """ + ast = compiler.parse(source_code) + code = compiler.compile(ast) + code = code.compile() + f = code.term + + x = data.draw(st.dictionaries(st.integers(), st.binary())) + y = data.draw(st.one_of(st.sampled_from(sorted(x.keys()) + [0]), st.integers())) + # UPLC lambdas may only take one argument at a time, so we evaluate by repeatedly applying + for d in [ + uplc.PlutusMap( + {uplc.PlutusInteger(k): uplc.PlutusByteString(v) for k, v in x.items()} + ), + uplc.PlutusInteger(y), + ]: + f = uplc.Apply(f, d) + try: + ret = uplc_eval(f).value + except RuntimeError: + ret = None + try: + exp = x[y] + except KeyError: + exp = None + self.assertEqual(ret, exp, "dict[] returned wrong value") + @given(xs=st.dictionaries(st.integers(), st.binary())) def test_dict_keys(self, xs): # this tests that errors that are caused by assignments are actually triggered at the time of assigning @@ -50,6 +109,50 @@ def validator(x: Dict[int, bytes]) -> List[bytes]: ret = [x.value for x in uplc_eval(f).value] self.assertEqual(ret, list(xs.values()), "dict.keys returned wrong value") + @given(xs=st.dictionaries(st.integers(), st.binary())) + def test_dict_items_keys_sum(self, xs): + # this tests that errors that are caused by assignments are actually triggered at the time of assigning + source_code = """ +def validator(xs: Dict[int, bytes]) -> int: + sum_keys = sum([x[0] for x in xs.items()]) + return sum_keys +""" + ast = compiler.parse(source_code) + code = compiler.compile(ast) + code = code.compile() + f = code.term + # UPLC lambdas may only take one argument at a time, so we evaluate by repeatedly applying + for d in [ + uplc.PlutusMap( + {uplc.PlutusInteger(k): uplc.PlutusByteString(v) for k, v in xs.items()} + ) + ]: + f = uplc.Apply(f, d) + ret = uplc_eval(f).value + self.assertEqual(ret, sum(xs.keys()), "dict.items returned wrong value") + + @given(xs=st.dictionaries(st.binary(), st.integers())) + def test_dict_items_values_sum(self, xs): + # this tests that errors that are caused by assignments are actually triggered at the time of assigning + source_code = """ +def validator(xs: Dict[bytes, int]) -> int: + sum_values = sum([x[1] for x in xs.items()]) + return sum_values +""" + ast = compiler.parse(source_code) + code = compiler.compile(ast) + code = code.compile() + f = code.term + # UPLC lambdas may only take one argument at a time, so we evaluate by repeatedly applying + for d in [ + uplc.PlutusMap( + {uplc.PlutusByteString(k): uplc.PlutusInteger(v) for k, v in xs.items()} + ) + ]: + f = uplc.Apply(f, d) + ret = uplc_eval(f).value + self.assertEqual(ret, sum(xs.values()), "dict.items returned wrong value") + @given(xs=st.text()) def test_str_encode(self, xs): # this tests that errors that are caused by assignments are actually triggered at the time of assigning diff --git a/hebi/type_inference.py b/hebi/type_inference.py index f343780..bb432fd 100644 --- a/hebi/type_inference.py +++ b/hebi/type_inference.py @@ -2,7 +2,7 @@ import ast from .typed_ast import * -from .util import PythonBuiltInTypes, CompilingNodeTransformer +from .util import PythonBuiltInTypes, CompilingNodeTransformer, ReturnExtractor # from frozendict import frozendict @@ -42,21 +42,12 @@ ) -class ReturnExtractor(NodeVisitor): - """Utility to find all Return statements in an AST subtree""" - - def __init__(self): - self.returns = [] - - def visit_Return(self, node: Return) -> None: - self.returns.append(node) - - class AggressiveTypeInferencer(CompilingNodeTransformer): step = "Static Type Inference" # A stack of dictionaries for storing scoped knowledge of variable types scopes = [INITIAL_SCOPE] + current_ret_type = [] # Obtain the type of a variable name in the current scope def variable_type(self, name: str) -> Type: @@ -73,7 +64,10 @@ def exit_scope(self): self.scopes.pop() def set_variable_type(self, name: str, typ: Type, force=False): - if not force and name in self.scopes[-1] and typ != self.scopes[-1][name]: + if not force and name in self.scopes[-1] and self.scopes[-1][name] != typ: + if self.scopes[-1][name] >= typ: + # the specified type is broader, we pass on this + return raise TypeInferenceError( f"Type {self.scopes[-1][name]} of variable {name} in local scope does not match inferred type {typ}" ) @@ -143,9 +137,7 @@ def type_from_annotation(self, ann: expr): "Only Union, Dict and List are allowed as Generic types" ) if ann is None: - raise TypeInferenceError( - "Type annotation is missing for a function argument or return value" - ) + return AnyType() raise NotImplementedError(f"Annotation type {ann.__class__} is not supported") def visit_ClassDef(self, node: ClassDef) -> TypedClassDef: @@ -221,9 +213,10 @@ def visit_AnnAssign(self, node: AnnAssign) -> TypedAnnAssign: node.target.id, InstanceType(typed_ass.annotation), force=True ) typed_ass.target = self.visit(node.target) - assert typed_ass.value.typ >= InstanceType( - typed_ass.annotation - ), "Can only downcast to a specialized type" + assert ( + typed_ass.value.typ >= InstanceType(typed_ass.annotation) + or InstanceType(typed_ass.annotation) >= typed_ass.value.typ + ), "Can only cast between related types" return typed_ass def visit_If(self, node: If) -> TypedIf: @@ -348,11 +341,13 @@ def visit_arguments(self, node: arguments) -> typedarguments: def visit_FunctionDef(self, node: FunctionDef) -> TypedFunctionDef: tfd = copy(node) assert not node.decorator_list, "Functions may not have decorators" + rettyp = InstanceType(self.type_from_annotation(tfd.returns)) self.enter_scope() + self.current_ret_type.append(rettyp) tfd.args = self.visit(node.args) functyp = FunctionType( [t.typ for t in tfd.args.args], - InstanceType(self.type_from_annotation(tfd.returns)), + rettyp, ) tfd.typ = InstanceType(functyp) # We need the function type inside for recursion @@ -372,6 +367,7 @@ def visit_FunctionDef(self, node: FunctionDef) -> TypedFunctionDef: functyp.rettyp >= r.typ for r in rets ), f"Function '{node.name}' annotated return type does not match actual return type" self.exit_scope() + self.current_ret_type.pop(-1) # We need the function type outside for usage self.set_variable_type(node.name, tfd.typ) return tfd @@ -437,7 +433,18 @@ def visit_Subscript(self, node: Subscript) -> TypedSubscript: ts.typ = ts.value.typ.typ.typs[ts.slice.value] else: raise TypeInferenceError( - f"Could not infer type of subscript of typ {ts.value.typ.__class__}" + f"Could not infer type of subscript of typ {ts.value.typ.typ.__class__}" + ) + elif isinstance(ts.value.typ.typ, PairType): + if isinstance(ts.slice, Constant) and isinstance(ts.slice.value, int): + ts.typ = ( + ts.value.typ.typ.l_typ + if ts.slice.value == 0 + else ts.value.typ.typ.r_typ + ) + else: + raise TypeInferenceError( + f"Could not infer type of subscript of typ {ts.value.typ.typ.__class__}" ) elif isinstance(ts.value.typ.typ, ListType): ts.typ = ts.value.typ.typ.typ @@ -472,9 +479,16 @@ def visit_Subscript(self, node: Subscript) -> TypedSubscript: ) elif isinstance(ts.value.typ.typ, DictType): # TODO could be implemented with potentially just erroring. It might be desired to avoid this though. - raise TypeInferenceError( - f"Could not infer type of subscript of dict. Use 'get' with a default value instead." - ) + if not isinstance(ts.slice, Slice): + ts.slice = self.visit(node.slice) + assert ( + ts.slice.typ == ts.value.typ.typ.key_typ + ), f"Dict subscript must have dict key type {ts.value.typ.typ.key_typ} but has type {ts.slice.typ}" + ts.typ = ts.value.typ.typ.value_typ + else: + raise TypeInferenceError( + f"Could not infer type of subscript of dict with a slice." + ) else: raise TypeInferenceError( f"Could not infer type of subscript of typ {ts.value.typ.__class__}" @@ -521,7 +535,9 @@ def visit_Pass(self, node: Pass) -> TypedPass: def visit_Return(self, node: Return) -> TypedReturn: tp = copy(node) tp.value = self.visit(node.value) - tp.typ = tp.value.typ + tp.typ = ( + tp.value.typ if not self.current_ret_type else self.current_ret_type[-1] + ) return tp def visit_Attribute(self, node: Attribute) -> TypedAttribute: diff --git a/hebi/typed_ast.py b/hebi/typed_ast.py index 20c3530..15fd487 100644 --- a/hebi/typed_ast.py +++ b/hebi/typed_ast.py @@ -280,6 +280,20 @@ def __ge__(self, other): ) +@dataclass(frozen=True, unsafe_hash=True) +class PairType(ClassType): + """An internal type representing built-in PlutusData pairs""" + + l_typ: Type + r_typ: Type + + def __ge__(self, other): + return isinstance(other, PairType) and all( + t >= ot + for t, ot in zip((self.l_typ, self.r_typ), (other.l_typ, other.r_typ)) + ) + + @dataclass(frozen=True, unsafe_hash=True) class ListType(ClassType): typ: Type @@ -304,6 +318,15 @@ def attribute_type(self, attr) -> "Type": return InstanceType( FunctionType([], InstanceType(ListType(self.value_typ))) ) + if attr == "items": + return InstanceType( + FunctionType( + [], + InstanceType( + ListType(InstanceType(PairType(self.key_typ, self.value_typ))) + ), + ) + ) raise TypeInferenceError( f"Type of attribute '{attr}' is unknown for type Dict." ) @@ -362,6 +385,11 @@ def attribute(self, attr) -> plt.AST: empty_list(self.value_typ), ), ) + if attr == "items": + return plt.Lambda( + ["self", "_"], + plt.Var("self"), + ) raise NotImplementedError(f"Attribute '{attr}' of Dict is unknown.") def __ge__(self, other): diff --git a/hebi/util.py b/hebi/util.py index 7411c25..3585a93 100644 --- a/hebi/util.py +++ b/hebi/util.py @@ -1,4 +1,5 @@ import ast +import pycardano from enum import Enum, auto from .typed_ast import * @@ -549,3 +550,21 @@ def data_from_json(j: typing.Dict[str, typing.Any]) -> uplc.PlutusData: j["constructor"], list(map(data_from_json, j["fields"])) ) raise NotImplementedError(f"Unknown datum representation {j}") + + +def datum_to_cbor(d: pycardano.Datum) -> bytes: + return pycardano.PlutusData.to_cbor(d, encoding="bytes") + + +def datum_to_json(d: pycardano.Datum) -> str: + return pycardano.PlutusData.to_json(d) + + +class ReturnExtractor(TypedNodeVisitor): + """Utility to find all Return statements in an AST subtree""" + + def __init__(self): + self.returns = [] + + def visit_Return(self, node: Return) -> None: + self.returns.append(node) diff --git a/poetry.lock b/poetry.lock index 7d148cd..99488a2 100644 --- a/poetry.lock +++ b/poetry.lock @@ -1,4 +1,4 @@ -# This file is automatically @generated by Poetry 1.4.0 and should not be changed by hand. +# This file is automatically @generated by Poetry 1.4.1 and should not be changed by hand. [[package]] name = "appdirs" @@ -45,32 +45,46 @@ tests-no-zope = ["cloudpickle", "cloudpickle", "hypothesis", "hypothesis", "mypy [[package]] name = "black" -version = "22.12.0" +version = "23.3.0" description = "The uncompromising code formatter." category = "dev" optional = false python-versions = ">=3.7" files = [ - {file = "black-22.12.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9eedd20838bd5d75b80c9f5487dbcb06836a43833a37846cf1d8c1cc01cef59d"}, - {file = "black-22.12.0-cp310-cp310-win_amd64.whl", hash = "sha256:159a46a4947f73387b4d83e87ea006dbb2337eab6c879620a3ba52699b1f4351"}, - {file = "black-22.12.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d30b212bffeb1e252b31dd269dfae69dd17e06d92b87ad26e23890f3efea366f"}, - {file = "black-22.12.0-cp311-cp311-win_amd64.whl", hash = "sha256:7412e75863aa5c5411886804678b7d083c7c28421210180d67dfd8cf1221e1f4"}, - {file = "black-22.12.0-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c116eed0efb9ff870ded8b62fe9f28dd61ef6e9ddd28d83d7d264a38417dcee2"}, - {file = "black-22.12.0-cp37-cp37m-win_amd64.whl", hash = "sha256:1f58cbe16dfe8c12b7434e50ff889fa479072096d79f0a7f25e4ab8e94cd8350"}, - {file = "black-22.12.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:77d86c9f3db9b1bf6761244bc0b3572a546f5fe37917a044e02f3166d5aafa7d"}, - {file = "black-22.12.0-cp38-cp38-win_amd64.whl", hash = "sha256:82d9fe8fee3401e02e79767016b4907820a7dc28d70d137eb397b92ef3cc5bfc"}, - {file = "black-22.12.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:101c69b23df9b44247bd88e1d7e90154336ac4992502d4197bdac35dd7ee3320"}, - {file = "black-22.12.0-cp39-cp39-win_amd64.whl", hash = "sha256:559c7a1ba9a006226f09e4916060982fd27334ae1998e7a38b3f33a37f7a2148"}, - {file = "black-22.12.0-py3-none-any.whl", hash = "sha256:436cc9167dd28040ad90d3b404aec22cedf24a6e4d7de221bec2730ec0c97bcf"}, - {file = "black-22.12.0.tar.gz", hash = "sha256:229351e5a18ca30f447bf724d007f890f97e13af070bb6ad4c0a441cd7596a2f"}, + {file = "black-23.3.0-cp310-cp310-macosx_10_16_arm64.whl", hash = "sha256:0945e13506be58bf7db93ee5853243eb368ace1c08a24c65ce108986eac65915"}, + {file = "black-23.3.0-cp310-cp310-macosx_10_16_universal2.whl", hash = "sha256:67de8d0c209eb5b330cce2469503de11bca4085880d62f1628bd9972cc3366b9"}, + {file = "black-23.3.0-cp310-cp310-macosx_10_16_x86_64.whl", hash = "sha256:7c3eb7cea23904399866c55826b31c1f55bbcd3890ce22ff70466b907b6775c2"}, + {file = "black-23.3.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:32daa9783106c28815d05b724238e30718f34155653d4d6e125dc7daec8e260c"}, + {file = "black-23.3.0-cp310-cp310-win_amd64.whl", hash = "sha256:35d1381d7a22cc5b2be2f72c7dfdae4072a3336060635718cc7e1ede24221d6c"}, + {file = "black-23.3.0-cp311-cp311-macosx_10_16_arm64.whl", hash = "sha256:a8a968125d0a6a404842fa1bf0b349a568634f856aa08ffaff40ae0dfa52e7c6"}, + {file = "black-23.3.0-cp311-cp311-macosx_10_16_universal2.whl", hash = "sha256:c7ab5790333c448903c4b721b59c0d80b11fe5e9803d8703e84dcb8da56fec1b"}, + {file = "black-23.3.0-cp311-cp311-macosx_10_16_x86_64.whl", hash = "sha256:a6f6886c9869d4daae2d1715ce34a19bbc4b95006d20ed785ca00fa03cba312d"}, + {file = "black-23.3.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6f3c333ea1dd6771b2d3777482429864f8e258899f6ff05826c3a4fcc5ce3f70"}, + {file = "black-23.3.0-cp311-cp311-win_amd64.whl", hash = "sha256:11c410f71b876f961d1de77b9699ad19f939094c3a677323f43d7a29855fe326"}, + {file = "black-23.3.0-cp37-cp37m-macosx_10_16_x86_64.whl", hash = "sha256:1d06691f1eb8de91cd1b322f21e3bfc9efe0c7ca1f0e1eb1db44ea367dff656b"}, + {file = "black-23.3.0-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:50cb33cac881766a5cd9913e10ff75b1e8eb71babf4c7104f2e9c52da1fb7de2"}, + {file = "black-23.3.0-cp37-cp37m-win_amd64.whl", hash = "sha256:e114420bf26b90d4b9daa597351337762b63039752bdf72bf361364c1aa05925"}, + {file = "black-23.3.0-cp38-cp38-macosx_10_16_arm64.whl", hash = "sha256:48f9d345675bb7fbc3dd85821b12487e1b9a75242028adad0333ce36ed2a6d27"}, + {file = "black-23.3.0-cp38-cp38-macosx_10_16_universal2.whl", hash = "sha256:714290490c18fb0126baa0fca0a54ee795f7502b44177e1ce7624ba1c00f2331"}, + {file = "black-23.3.0-cp38-cp38-macosx_10_16_x86_64.whl", hash = "sha256:064101748afa12ad2291c2b91c960be28b817c0c7eaa35bec09cc63aa56493c5"}, + {file = "black-23.3.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:562bd3a70495facf56814293149e51aa1be9931567474993c7942ff7d3533961"}, + {file = "black-23.3.0-cp38-cp38-win_amd64.whl", hash = "sha256:e198cf27888ad6f4ff331ca1c48ffc038848ea9f031a3b40ba36aced7e22f2c8"}, + {file = "black-23.3.0-cp39-cp39-macosx_10_16_arm64.whl", hash = "sha256:3238f2aacf827d18d26db07524e44741233ae09a584273aa059066d644ca7b30"}, + {file = "black-23.3.0-cp39-cp39-macosx_10_16_universal2.whl", hash = "sha256:f0bd2f4a58d6666500542b26354978218a9babcdc972722f4bf90779524515f3"}, + {file = "black-23.3.0-cp39-cp39-macosx_10_16_x86_64.whl", hash = "sha256:92c543f6854c28a3c7f39f4d9b7694f9a6eb9d3c5e2ece488c327b6e7ea9b266"}, + {file = "black-23.3.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3a150542a204124ed00683f0db1f5cf1c2aaaa9cc3495b7a3b5976fb136090ab"}, + {file = "black-23.3.0-cp39-cp39-win_amd64.whl", hash = "sha256:6b39abdfb402002b8a7d030ccc85cf5afff64ee90fa4c5aebc531e3ad0175ddb"}, + {file = "black-23.3.0-py3-none-any.whl", hash = "sha256:ec751418022185b0c1bb7d7736e6933d40bbb14c14a0abcf9123d1b159f98dd4"}, + {file = "black-23.3.0.tar.gz", hash = "sha256:1c7b8d606e728a41ea1ccbd7264677e494e87cf630e399262ced92d4a8dac940"}, ] [package.dependencies] click = ">=8.0.0" mypy-extensions = ">=0.4.3" +packaging = ">=22.0" pathspec = ">=0.9.0" platformdirs = ">=2" -tomli = {version = ">=1.1.0", markers = "python_full_version < \"3.11.0a7\""} +tomli = {version = ">=1.1.0", markers = "python_version < \"3.11\""} typing-extensions = {version = ">=3.10.0.0", markers = "python_version < \"3.10\""} [package.extras] @@ -81,14 +95,14 @@ uvloop = ["uvloop (>=0.15.2)"] [[package]] name = "blockfrost-python" -version = "0.5.2" +version = "0.5.3" description = "The official Python SDK for Blockfrost API v0.1.37" category = "main" optional = false python-versions = ">=3.7, <4" files = [ - {file = "blockfrost-python-0.5.2.tar.gz", hash = "sha256:e8c046feb542b066f9baf6dba6eed79344d10a2139f6edb638f8aee70b5b8f81"}, - {file = "blockfrost_python-0.5.2-py3-none-any.whl", hash = "sha256:222d3ba83128cada09519115dabee915c1c7f2b8e38f0357f2829ebf0f7d80a8"}, + {file = "blockfrost-python-0.5.3.tar.gz", hash = "sha256:3154b99867e7714c90064c9e1a37e3b7af97c107b64549dd0d424aaa3209017e"}, + {file = "blockfrost_python-0.5.3-py3-none-any.whl", hash = "sha256:b0e73f09f1ff06977c85ccd63f6afe7ec30fa1b5c48e94a15d8bc8cf1f61997b"}, ] [package.dependencies] @@ -550,31 +564,31 @@ files = [ [[package]] name = "cryptography" -version = "40.0.1" +version = "40.0.2" description = "cryptography is a package which provides cryptographic recipes and primitives to Python developers." category = "main" optional = false python-versions = ">=3.6" files = [ - {file = "cryptography-40.0.1-cp36-abi3-macosx_10_12_universal2.whl", hash = "sha256:918cb89086c7d98b1b86b9fdb70c712e5a9325ba6f7d7cfb509e784e0cfc6917"}, - {file = "cryptography-40.0.1-cp36-abi3-macosx_10_12_x86_64.whl", hash = "sha256:9618a87212cb5200500e304e43691111570e1f10ec3f35569fdfcd17e28fd797"}, - {file = "cryptography-40.0.1-cp36-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3a4805a4ca729d65570a1b7cac84eac1e431085d40387b7d3bbaa47e39890b88"}, - {file = "cryptography-40.0.1-cp36-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:63dac2d25c47f12a7b8aa60e528bfb3c51c5a6c5a9f7c86987909c6c79765554"}, - {file = "cryptography-40.0.1-cp36-abi3-manylinux_2_28_aarch64.whl", hash = "sha256:0a4e3406cfed6b1f6d6e87ed243363652b2586b2d917b0609ca4f97072994405"}, - {file = "cryptography-40.0.1-cp36-abi3-manylinux_2_28_x86_64.whl", hash = "sha256:1e0af458515d5e4028aad75f3bb3fe7a31e46ad920648cd59b64d3da842e4356"}, - {file = "cryptography-40.0.1-cp36-abi3-musllinux_1_1_aarch64.whl", hash = "sha256:d8aa3609d337ad85e4eb9bb0f8bcf6e4409bfb86e706efa9a027912169e89122"}, - {file = "cryptography-40.0.1-cp36-abi3-musllinux_1_1_x86_64.whl", hash = "sha256:cf91e428c51ef692b82ce786583e214f58392399cf65c341bc7301d096fa3ba2"}, - {file = "cryptography-40.0.1-cp36-abi3-win32.whl", hash = "sha256:650883cc064297ef3676b1db1b7b1df6081794c4ada96fa457253c4cc40f97db"}, - {file = "cryptography-40.0.1-cp36-abi3-win_amd64.whl", hash = "sha256:a805a7bce4a77d51696410005b3e85ae2839bad9aa38894afc0aa99d8e0c3160"}, - {file = "cryptography-40.0.1-pp38-pypy38_pp73-macosx_10_12_x86_64.whl", hash = "sha256:cd033d74067d8928ef00a6b1327c8ea0452523967ca4463666eeba65ca350d4c"}, - {file = "cryptography-40.0.1-pp38-pypy38_pp73-manylinux_2_28_aarch64.whl", hash = "sha256:d36bbeb99704aabefdca5aee4eba04455d7a27ceabd16f3b3ba9bdcc31da86c4"}, - {file = "cryptography-40.0.1-pp38-pypy38_pp73-manylinux_2_28_x86_64.whl", hash = "sha256:32057d3d0ab7d4453778367ca43e99ddb711770477c4f072a51b3ca69602780a"}, - {file = "cryptography-40.0.1-pp38-pypy38_pp73-win_amd64.whl", hash = "sha256:f5d7b79fa56bc29580faafc2ff736ce05ba31feaa9d4735048b0de7d9ceb2b94"}, - {file = "cryptography-40.0.1-pp39-pypy39_pp73-macosx_10_12_x86_64.whl", hash = "sha256:7c872413353c70e0263a9368c4993710070e70ab3e5318d85510cc91cce77e7c"}, - {file = "cryptography-40.0.1-pp39-pypy39_pp73-manylinux_2_28_aarch64.whl", hash = "sha256:28d63d75bf7ae4045b10de5413fb1d6338616e79015999ad9cf6fc538f772d41"}, - {file = "cryptography-40.0.1-pp39-pypy39_pp73-manylinux_2_28_x86_64.whl", hash = "sha256:6f2bbd72f717ce33100e6467572abaedc61f1acb87b8d546001328d7f466b778"}, - {file = "cryptography-40.0.1-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:cc3a621076d824d75ab1e1e530e66e7e8564e357dd723f2533225d40fe35c60c"}, - {file = "cryptography-40.0.1.tar.gz", hash = "sha256:2803f2f8b1e95f614419926c7e6f55d828afc614ca5ed61543877ae668cc3472"}, + {file = "cryptography-40.0.2-cp36-abi3-macosx_10_12_universal2.whl", hash = "sha256:8f79b5ff5ad9d3218afb1e7e20ea74da5f76943ee5edb7f76e56ec5161ec782b"}, + {file = "cryptography-40.0.2-cp36-abi3-macosx_10_12_x86_64.whl", hash = "sha256:05dc219433b14046c476f6f09d7636b92a1c3e5808b9a6536adf4932b3b2c440"}, + {file = "cryptography-40.0.2-cp36-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:4df2af28d7bedc84fe45bd49bc35d710aede676e2a4cb7fc6d103a2adc8afe4d"}, + {file = "cryptography-40.0.2-cp36-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0dcca15d3a19a66e63662dc8d30f8036b07be851a8680eda92d079868f106288"}, + {file = "cryptography-40.0.2-cp36-abi3-manylinux_2_28_aarch64.whl", hash = "sha256:a04386fb7bc85fab9cd51b6308633a3c271e3d0d3eae917eebab2fac6219b6d2"}, + {file = "cryptography-40.0.2-cp36-abi3-manylinux_2_28_x86_64.whl", hash = "sha256:adc0d980fd2760c9e5de537c28935cc32b9353baaf28e0814df417619c6c8c3b"}, + {file = "cryptography-40.0.2-cp36-abi3-musllinux_1_1_aarch64.whl", hash = "sha256:d5a1bd0e9e2031465761dfa920c16b0065ad77321d8a8c1f5ee331021fda65e9"}, + {file = "cryptography-40.0.2-cp36-abi3-musllinux_1_1_x86_64.whl", hash = "sha256:a95f4802d49faa6a674242e25bfeea6fc2acd915b5e5e29ac90a32b1139cae1c"}, + {file = "cryptography-40.0.2-cp36-abi3-win32.whl", hash = "sha256:aecbb1592b0188e030cb01f82d12556cf72e218280f621deed7d806afd2113f9"}, + {file = "cryptography-40.0.2-cp36-abi3-win_amd64.whl", hash = "sha256:b12794f01d4cacfbd3177b9042198f3af1c856eedd0a98f10f141385c809a14b"}, + {file = "cryptography-40.0.2-pp38-pypy38_pp73-macosx_10_12_x86_64.whl", hash = "sha256:142bae539ef28a1c76794cca7f49729e7c54423f615cfd9b0b1fa90ebe53244b"}, + {file = "cryptography-40.0.2-pp38-pypy38_pp73-manylinux_2_28_aarch64.whl", hash = "sha256:956ba8701b4ffe91ba59665ed170a2ebbdc6fc0e40de5f6059195d9f2b33ca0e"}, + {file = "cryptography-40.0.2-pp38-pypy38_pp73-manylinux_2_28_x86_64.whl", hash = "sha256:4f01c9863da784558165f5d4d916093737a75203a5c5286fde60e503e4276c7a"}, + {file = "cryptography-40.0.2-pp38-pypy38_pp73-win_amd64.whl", hash = "sha256:3daf9b114213f8ba460b829a02896789751626a2a4e7a43a28ee77c04b5e4958"}, + {file = "cryptography-40.0.2-pp39-pypy39_pp73-macosx_10_12_x86_64.whl", hash = "sha256:48f388d0d153350f378c7f7b41497a54ff1513c816bcbbcafe5b829e59b9ce5b"}, + {file = "cryptography-40.0.2-pp39-pypy39_pp73-manylinux_2_28_aarch64.whl", hash = "sha256:c0764e72b36a3dc065c155e5b22f93df465da9c39af65516fe04ed3c68c92636"}, + {file = "cryptography-40.0.2-pp39-pypy39_pp73-manylinux_2_28_x86_64.whl", hash = "sha256:cbaba590180cba88cb99a5f76f90808a624f18b169b90a4abb40c1fd8c19420e"}, + {file = "cryptography-40.0.2-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:7a38250f433cd41df7fcb763caa3ee9362777fdb4dc642b9a349721d2bf47404"}, + {file = "cryptography-40.0.2.tar.gz", hash = "sha256:c33c0d32b8594fa647d2e01dbccc303478e16fdd7cf98652d5b3ed11aa5e5c99"}, ] [package.dependencies] @@ -736,18 +750,18 @@ test = ["pytest (>=6)"] [[package]] name = "filelock" -version = "3.10.7" +version = "3.11.0" description = "A platform independent file lock." category = "dev" optional = false python-versions = ">=3.7" files = [ - {file = "filelock-3.10.7-py3-none-any.whl", hash = "sha256:bde48477b15fde2c7e5a0713cbe72721cb5a5ad32ee0b8f419907960b9d75536"}, - {file = "filelock-3.10.7.tar.gz", hash = "sha256:892be14aa8efc01673b5ed6589dbccb95f9a8596f0507e232626155495c18105"}, + {file = "filelock-3.11.0-py3-none-any.whl", hash = "sha256:f08a52314748335c6460fc8fe40cd5638b85001225db78c2aa01c8c0db83b318"}, + {file = "filelock-3.11.0.tar.gz", hash = "sha256:3618c0da67adcc0506b015fd11ef7faf1b493f0b40d87728e19986b536890c37"}, ] [package.extras] -docs = ["furo (>=2022.12.7)", "sphinx (>=6.1.3)", "sphinx-autodoc-typehints (>=1.22,!=1.23.4)"] +docs = ["furo (>=2023.3.27)", "sphinx (>=6.1.3)", "sphinx-autodoc-typehints (>=1.22,!=1.23.4)"] testing = ["covdefaults (>=2.3)", "coverage (>=7.2.2)", "diff-cover (>=7.5)", "pytest (>=7.2.2)", "pytest-cov (>=4)", "pytest-mock (>=3.10)", "pytest-timeout (>=2.1)"] [[package]] @@ -885,14 +899,14 @@ lxml = ["lxml"] [[package]] name = "hypothesis" -version = "6.70.0" +version = "6.71.0" description = "A library for property-based testing" category = "dev" optional = false python-versions = ">=3.7" files = [ - {file = "hypothesis-6.70.0-py3-none-any.whl", hash = "sha256:be395f71d6337a5e8ed2f695c568360a686056c3b00c98bd818874c674b24586"}, - {file = "hypothesis-6.70.0.tar.gz", hash = "sha256:f5cae09417d0ffc7711f602cdcfa3b7baf344597a672a84658186605b04f4a4f"}, + {file = "hypothesis-6.71.0-py3-none-any.whl", hash = "sha256:06235b8ab3c4090bec96b07dfc2347611c1392e5b4ffa48c069f2c1337968725"}, + {file = "hypothesis-6.71.0.tar.gz", hash = "sha256:b2c3bbead72189c0bba6e12848b484ceafadb6e872ac31e40013228239366221"}, ] [package.dependencies] @@ -901,7 +915,7 @@ exceptiongroup = {version = ">=1.0.0", markers = "python_version < \"3.11\""} sortedcontainers = ">=2.1.0,<3.0.0" [package.extras] -all = ["backports.zoneinfo (>=0.2.1)", "black (>=19.10b0)", "click (>=7.0)", "django (>=3.2)", "dpcontracts (>=0.4)", "importlib-metadata (>=3.6)", "lark (>=0.10.1)", "libcst (>=0.3.16)", "numpy (>=1.9.0)", "pandas (>=1.0)", "pytest (>=4.6)", "python-dateutil (>=1.4)", "pytz (>=2014.1)", "redis (>=3.0.0)", "rich (>=9.0.0)", "tzdata (>=2022.7)"] +all = ["backports.zoneinfo (>=0.2.1)", "black (>=19.10b0)", "click (>=7.0)", "django (>=3.2)", "dpcontracts (>=0.4)", "importlib-metadata (>=3.6)", "lark (>=0.10.1)", "libcst (>=0.3.16)", "numpy (>=1.9.0)", "pandas (>=1.0)", "pytest (>=4.6)", "python-dateutil (>=1.4)", "pytz (>=2014.1)", "redis (>=3.0.0)", "rich (>=9.0.0)", "tzdata (>=2023.3)"] cli = ["black (>=19.10b0)", "click (>=7.0)", "rich (>=9.0.0)"] codemods = ["libcst (>=0.3.16)"] dateutil = ["python-dateutil (>=1.4)"] @@ -914,7 +928,7 @@ pandas = ["pandas (>=1.0)"] pytest = ["pytest (>=4.6)"] pytz = ["pytz (>=2014.1)"] redis = ["redis (>=3.0.0)"] -zoneinfo = ["backports.zoneinfo (>=0.2.1)", "tzdata (>=2022.7)"] +zoneinfo = ["backports.zoneinfo (>=0.2.1)", "tzdata (>=2023.3)"] [[package]] name = "identify" @@ -945,14 +959,14 @@ files = [ [[package]] name = "importlib-metadata" -version = "6.1.0" +version = "6.4.1" description = "Read metadata from Python packages" category = "dev" optional = false python-versions = ">=3.7" files = [ - {file = "importlib_metadata-6.1.0-py3-none-any.whl", hash = "sha256:ff80f3b5394912eb1b108fcfd444dc78b7f1f3e16b16188054bd01cb9cb86f09"}, - {file = "importlib_metadata-6.1.0.tar.gz", hash = "sha256:43ce9281e097583d758c2c708c4376371261a02c34682491a8e98352365aad20"}, + {file = "importlib_metadata-6.4.1-py3-none-any.whl", hash = "sha256:63ace321e24167d12fbb176b6015f4dbe06868c54a2af4f15849586afb9027fd"}, + {file = "importlib_metadata-6.4.1.tar.gz", hash = "sha256:eb1a7933041f0f85c94cd130258df3fb0dec060ad8c1c9318892ef4192c47ce1"}, ] [package.dependencies] @@ -1241,26 +1255,26 @@ asn1crypto = ">=1.5.1" [[package]] name = "packaging" -version = "23.0" +version = "23.1" description = "Core utilities for Python packages" category = "dev" optional = false python-versions = ">=3.7" files = [ - {file = "packaging-23.0-py3-none-any.whl", hash = "sha256:714ac14496c3e68c99c29b00845f7a2b85f3bb6f1078fd9f72fd20f0570002b2"}, - {file = "packaging-23.0.tar.gz", hash = "sha256:b6ad297f8907de0fa2fe1ccbd26fdaf387f5f47c7275fedf8cce89f99446cf97"}, + {file = "packaging-23.1-py3-none-any.whl", hash = "sha256:994793af429502c4ea2ebf6bf664629d07c1a9fe974af92966e4b8d2df7edc61"}, + {file = "packaging-23.1.tar.gz", hash = "sha256:a392980d2b6cffa644431898be54b0045151319d1e7ec34f0cfed48767dd334f"}, ] [[package]] name = "parameterized" -version = "0.8.1" +version = "0.9.0" description = "Parameterized testing with any Python test framework" category = "dev" optional = false -python-versions = "*" +python-versions = ">=3.7" files = [ - {file = "parameterized-0.8.1-py2.py3-none-any.whl", hash = "sha256:9cbb0b69a03e8695d68b3399a8a5825200976536fe1cb79db60ed6a4c8c9efe9"}, - {file = "parameterized-0.8.1.tar.gz", hash = "sha256:41bbff37d6186430f77f900d777e5bb6a24928a1c46fb1de692f8b52b8833b5c"}, + {file = "parameterized-0.9.0-py2.py3-none-any.whl", hash = "sha256:4e0758e3d41bea3bbd05ec14fc2c24736723f243b28d702081aef438c9372b1b"}, + {file = "parameterized-0.9.0.tar.gz", hash = "sha256:7fc905272cefa4f364c1a3429cbbe9c0f98b793988efb5bf90aac80f08db09b1"}, ] [package.extras] @@ -1354,29 +1368,29 @@ testing = ["pytest", "pytest-benchmark"] [[package]] name = "pluthon" -version = "0.3.2" +version = "0.3.3" description = "Pluto-like programming language for Cardano Smart Contracts in Python" category = "main" optional = false python-versions = ">=3" files = [ - {file = "pluthon-0.3.2-py3-none-any.whl", hash = "sha256:918e2da1f48032268b2257075966c808bd379ba256e8879f1830154226ab4566"}, - {file = "pluthon-0.3.2.tar.gz", hash = "sha256:d086bdbf12f1fb91b8edea87d80fc0ba3ffec296b569181866e6aa80b91c2f99"}, + {file = "pluthon-0.3.3-py3-none-any.whl", hash = "sha256:e80e290dc41f96e009d8f2d41c915a742237d648d63506f795a06bde5a0da762"}, + {file = "pluthon-0.3.3.tar.gz", hash = "sha256:137bd1c06fa8f4dabeee76775880f3e882e6b7ce947a9648cbfdfdfe063deffe"}, ] [package.dependencies] -uplc = "0.6.0" +uplc = "0.6.1" [[package]] name = "poetry" -version = "1.4.1" +version = "1.4.2" description = "Python dependency management and packaging made easy." category = "dev" optional = false python-versions = ">=3.7,<4.0" files = [ - {file = "poetry-1.4.1-py3-none-any.whl", hash = "sha256:c0c24de00b8e42eb7f4bba9803a59720a299e1805ecf699e0823a30f9a8edb1f"}, - {file = "poetry-1.4.1.tar.gz", hash = "sha256:9a0c9f5f862678d475ac2fd2451ea612facd02efb054bb758763893f7d85053e"}, + {file = "poetry-1.4.2-py3-none-any.whl", hash = "sha256:c39c483cde7930915c992f932c163994ce3d870765efb8235ad0139cd65f0c5b"}, + {file = "poetry-1.4.2.tar.gz", hash = "sha256:0bd580a42482579635e774c5286ef73b8df3427567123cdb128b286cec671b3c"}, ] [package.dependencies] @@ -1471,14 +1485,14 @@ files = [ [[package]] name = "pre-commit" -version = "3.2.1" +version = "3.2.2" description = "A framework for managing and maintaining multi-language pre-commit hooks." category = "dev" optional = false python-versions = ">=3.8" files = [ - {file = "pre_commit-3.2.1-py2.py3-none-any.whl", hash = "sha256:a06a7fcce7f420047a71213c175714216498b49ebc81fe106f7716ca265f5bb6"}, - {file = "pre_commit-3.2.1.tar.gz", hash = "sha256:b5aee7d75dbba21ee161ba641b01e7ae10c5b91967ebf7b2ab0dfae12d07e1f1"}, + {file = "pre_commit-3.2.2-py2.py3-none-any.whl", hash = "sha256:0b4210aea813fe81144e87c5a291f09ea66f199f367fa1df41b55e1d26e1e2b4"}, + {file = "pre_commit-3.2.2.tar.gz", hash = "sha256:5b808fcbda4afbccf6d6633a56663fed35b6c2bc08096fd3d47ce197ac351d9d"}, ] [package.dependencies] @@ -1502,18 +1516,18 @@ files = [ [[package]] name = "pycardano" -version = "0.7.2" +version = "0.8.0" description = "A Cardano library in Python" category = "main" optional = false python-versions = ">=3.7,<4.0" files = [ - {file = "pycardano-0.7.2-py3-none-any.whl", hash = "sha256:1cd3f7813f24f3501a229f1eb8fb3ddc4517842d792e2e0839b3c616a23a4054"}, - {file = "pycardano-0.7.2.tar.gz", hash = "sha256:2cac70b8317f5834e1bb402e8848d7cce6f0955b643d2a52831f76f9cb4b26f1"}, + {file = "pycardano-0.8.0-py3-none-any.whl", hash = "sha256:0d396b1589957ec084a292ef87c5ad659ad7343429e506aa66b456c8e78f3226"}, + {file = "pycardano-0.8.0.tar.gz", hash = "sha256:f7478463a27b3bcffc901cd48a4992ed1cdc80b0c911b1c75ff46f3676c257a2"}, ] [package.dependencies] -blockfrost-python = "0.5.2" +blockfrost-python = "0.5.3" cbor2 = ">=5.4.3,<6.0.0" cose = "0.9.dev8" ECPy = ">=1.2.5,<2.0.0" @@ -1669,18 +1683,17 @@ files = [ [[package]] name = "pytest" -version = "7.2.2" +version = "7.3.1" description = "pytest: simple powerful testing with Python" category = "dev" optional = false python-versions = ">=3.7" files = [ - {file = "pytest-7.2.2-py3-none-any.whl", hash = "sha256:130328f552dcfac0b1cec75c12e3f005619dc5f874f0a06e8ff7263f0ee6225e"}, - {file = "pytest-7.2.2.tar.gz", hash = "sha256:c99ab0c73aceb050f68929bc93af19ab6db0558791c6a0715723abe9d0ade9d4"}, + {file = "pytest-7.3.1-py3-none-any.whl", hash = "sha256:3799fa815351fea3a5e96ac7e503a96fa51cc9942c3753cda7651b93c1cfa362"}, + {file = "pytest-7.3.1.tar.gz", hash = "sha256:434afafd78b1d78ed0addf160ad2b77a30d35d4bdf8af234fe621919d9ed15e3"}, ] [package.dependencies] -attrs = ">=19.2.0" colorama = {version = "*", markers = "sys_platform == \"win32\""} exceptiongroup = {version = ">=1.0.0rc8", markers = "python_version < \"3.11\""} iniconfig = "*" @@ -1689,7 +1702,7 @@ pluggy = ">=0.12,<2.0" tomli = {version = ">=1.0.0", markers = "python_version < \"3.11\""} [package.extras] -testing = ["argcomplete", "hypothesis (>=3.56)", "mock", "nose", "pygments (>=2.7.2)", "requests", "xmlschema"] +testing = ["argcomplete", "attrs (>=19.2.0)", "hypothesis (>=3.56)", "mock", "nose", "pygments (>=2.7.2)", "requests", "xmlschema"] [[package]] name = "python-secp256k1-cardano" @@ -1770,101 +1783,104 @@ files = [ [[package]] name = "rapidfuzz" -version = "2.13.7" +version = "2.15.1" description = "rapid fuzzy string matching" category = "dev" optional = false python-versions = ">=3.7" files = [ - {file = "rapidfuzz-2.13.7-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:b75dd0928ce8e216f88660ab3d5c5ffe990f4dd682fd1709dba29d5dafdde6de"}, - {file = "rapidfuzz-2.13.7-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:24d3fea10680d085fd0a4d76e581bfb2b1074e66e78fd5964d4559e1fcd2a2d4"}, - {file = "rapidfuzz-2.13.7-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:8109e0324d21993d5b2d111742bf5958f3516bf8c59f297c5d1cc25a2342eb66"}, - {file = "rapidfuzz-2.13.7-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b5f705652360d520c2de52bee11100c92f59b3e3daca308ebb150cbc58aecdad"}, - {file = "rapidfuzz-2.13.7-cp310-cp310-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:7496e8779905b02abc0ab4ba2a848e802ab99a6e20756ffc967a0de4900bd3da"}, - {file = "rapidfuzz-2.13.7-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:24eb6b843492bdc63c79ee4b2f104059b7a2201fef17f25177f585d3be03405a"}, - {file = "rapidfuzz-2.13.7-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:467c1505362823a5af12b10234cb1c4771ccf124c00e3fc9a43696512bd52293"}, - {file = "rapidfuzz-2.13.7-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:53dcae85956853b787c27c1cb06f18bb450e22cf57a4ad3444cf03b8ff31724a"}, - {file = "rapidfuzz-2.13.7-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:46b9b8aa09998bc48dd800854e8d9b74bc534d7922c1d6e1bbf783e7fa6ac29c"}, - {file = "rapidfuzz-2.13.7-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:1fbad8fb28d98980f5bff33c7842efef0315d42f0cd59082108482a7e6b61410"}, - {file = "rapidfuzz-2.13.7-cp310-cp310-musllinux_1_1_ppc64le.whl", hash = "sha256:43fb8cb030f888c3f076d40d428ed5eb4331f5dd6cf1796cfa39c67bf0f0fc1e"}, - {file = "rapidfuzz-2.13.7-cp310-cp310-musllinux_1_1_s390x.whl", hash = "sha256:b6bad92de071cbffa2acd4239c1779f66851b60ffbbda0e4f4e8a2e9b17e7eef"}, - {file = "rapidfuzz-2.13.7-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:d00df2e4a81ffa56a6b1ec4d2bc29afdcb7f565e0b8cd3092fece2290c4c7a79"}, - {file = "rapidfuzz-2.13.7-cp310-cp310-win32.whl", hash = "sha256:2c836f0f2d33d4614c3fbaf9a1eb5407c0fe23f8876f47fd15b90f78daa64c34"}, - {file = "rapidfuzz-2.13.7-cp310-cp310-win_amd64.whl", hash = "sha256:c36fd260084bb636b9400bb92016c6bd81fd80e59ed47f2466f85eda1fc9f782"}, - {file = "rapidfuzz-2.13.7-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:b34e8c0e492949ecdd5da46a1cfc856a342e2f0389b379b1a45a3cdcd3176a6e"}, - {file = "rapidfuzz-2.13.7-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:875d51b3497439a72e2d76183e1cb5468f3f979ab2ddfc1d1f7dde3b1ecfb42f"}, - {file = "rapidfuzz-2.13.7-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:ae33a72336059213996fe4baca4e0e4860913905c2efb7c991eab33b95a98a0a"}, - {file = "rapidfuzz-2.13.7-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a5585189b3d90d81ccd62d4f18530d5ac8972021f0aaaa1ffc6af387ff1dce75"}, - {file = "rapidfuzz-2.13.7-cp311-cp311-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:42085d4b154a8232767de8296ac39c8af5bccee6b823b0507de35f51c9cbc2d7"}, - {file = "rapidfuzz-2.13.7-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:585206112c294e335d84de5d5f179c0f932837752d7420e3de21db7fdc476278"}, - {file = "rapidfuzz-2.13.7-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:f891b98f8bc6c9d521785816085e9657212621e93f223917fb8e32f318b2957e"}, - {file = "rapidfuzz-2.13.7-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:08590905a95ccfa43f4df353dcc5d28c15d70664299c64abcad8721d89adce4f"}, - {file = "rapidfuzz-2.13.7-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:b5dd713a1734574c2850c566ac4286594bacbc2d60b9170b795bee4b68656625"}, - {file = "rapidfuzz-2.13.7-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:988f8f6abfba7ee79449f8b50687c174733b079521c3cc121d65ad2d38831846"}, - {file = "rapidfuzz-2.13.7-cp311-cp311-musllinux_1_1_ppc64le.whl", hash = "sha256:b3210869161a864f3831635bb13d24f4708c0aa7208ef5baac1ac4d46e9b4208"}, - {file = "rapidfuzz-2.13.7-cp311-cp311-musllinux_1_1_s390x.whl", hash = "sha256:f6fe570e20e293eb50491ae14ddeef71a6a7e5f59d7e791393ffa99b13f1f8c2"}, - {file = "rapidfuzz-2.13.7-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:6120f2995f5154057454c5de99d86b4ef3b38397899b5da1265467e8980b2f60"}, - {file = "rapidfuzz-2.13.7-cp311-cp311-win32.whl", hash = "sha256:b20141fa6cee041917801de0bab503447196d372d4c7ee9a03721b0a8edf5337"}, - {file = "rapidfuzz-2.13.7-cp311-cp311-win_amd64.whl", hash = "sha256:ec55a81ac2b0f41b8d6fb29aad16e55417036c7563bad5568686931aa4ff08f7"}, - {file = "rapidfuzz-2.13.7-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:7d005e058d86f2a968a8d28ca6f2052fab1f124a39035aa0523261d6baf21e1f"}, - {file = "rapidfuzz-2.13.7-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:fe59a0c21a032024edb0c8e43f5dee5623fef0b65a1e3c1281836d9ce199af3b"}, - {file = "rapidfuzz-2.13.7-cp37-cp37m-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:cdfc04f7647c29fb48da7a04082c34cdb16f878d3c6d098d62d5715c0ad3000c"}, - {file = "rapidfuzz-2.13.7-cp37-cp37m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:68a89bb06d5a331511961f4d3fa7606f8e21237467ba9997cae6f67a1c2c2b9e"}, - {file = "rapidfuzz-2.13.7-cp37-cp37m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:effe182767d102cb65dfbbf74192237dbd22d4191928d59415aa7d7c861d8c88"}, - {file = "rapidfuzz-2.13.7-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:25b4cedf2aa19fb7212894ce5f5219010cce611b60350e9a0a4d492122e7b351"}, - {file = "rapidfuzz-2.13.7-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:3a9bd02e1679c0fd2ecf69b72d0652dbe2a9844eaf04a36ddf4adfbd70010e95"}, - {file = "rapidfuzz-2.13.7-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:5e2b3d020219baa75f82a4e24b7c8adcb598c62f0e54e763c39361a9e5bad510"}, - {file = "rapidfuzz-2.13.7-cp37-cp37m-musllinux_1_1_ppc64le.whl", hash = "sha256:cf62dacb3f9234f3fddd74e178e6d25c68f2067fde765f1d95f87b1381248f58"}, - {file = "rapidfuzz-2.13.7-cp37-cp37m-musllinux_1_1_s390x.whl", hash = "sha256:fa263135b892686e11d5b84f6a1892523123a00b7e5882eff4fbdabb38667347"}, - {file = "rapidfuzz-2.13.7-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:fa4c598ed77f74ec973247ca776341200b0f93ec3883e34c222907ce72cb92a4"}, - {file = "rapidfuzz-2.13.7-cp37-cp37m-win32.whl", hash = "sha256:c2523f8180ebd9796c18d809e9a19075a1060b1a170fde3799e83db940c1b6d5"}, - {file = "rapidfuzz-2.13.7-cp37-cp37m-win_amd64.whl", hash = "sha256:5ada0a14c67452358c1ee52ad14b80517a87b944897aaec3e875279371a9cb96"}, - {file = "rapidfuzz-2.13.7-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:ca8a23097c1f50e0fdb4de9e427537ca122a18df2eead06ed39c3a0bef6d9d3a"}, - {file = "rapidfuzz-2.13.7-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:9be02162af0376d64b840f2fc8ee3366794fc149f1e06d095a6a1d42447d97c5"}, - {file = "rapidfuzz-2.13.7-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:af4f7c3c904ca709493eb66ca9080b44190c38e9ecb3b48b96d38825d5672559"}, - {file = "rapidfuzz-2.13.7-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1f50d1227e6e2a0e3ae1fb1c9a2e1c59577d3051af72c7cab2bcc430cb5e18da"}, - {file = "rapidfuzz-2.13.7-cp38-cp38-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:c71d9d512b76f05fa00282227c2ae884abb60e09f08b5ca3132b7e7431ac7f0d"}, - {file = "rapidfuzz-2.13.7-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:b52ac2626945cd21a2487aeefed794c14ee31514c8ae69b7599170418211e6f6"}, - {file = "rapidfuzz-2.13.7-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:ca00fafd2756bc9649bf80f1cf72c647dce38635f0695d7ce804bc0f759aa756"}, - {file = "rapidfuzz-2.13.7-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d248a109699ce9992304e79c1f8735c82cc4c1386cd8e27027329c0549f248a2"}, - {file = "rapidfuzz-2.13.7-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:c88adbcb933f6b8612f6c593384bf824e562bb35fc8a0f55fac690ab5b3486e5"}, - {file = "rapidfuzz-2.13.7-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:c8601a66fbfc0052bb7860d2eacd303fcde3c14e87fdde409eceff516d659e77"}, - {file = "rapidfuzz-2.13.7-cp38-cp38-musllinux_1_1_ppc64le.whl", hash = "sha256:27be9c63215d302ede7d654142a2e21f0d34ea6acba512a4ae4cfd52bbaa5b59"}, - {file = "rapidfuzz-2.13.7-cp38-cp38-musllinux_1_1_s390x.whl", hash = "sha256:3dcffe1f3cbda0dc32133a2ae2255526561ca594f15f9644384549037b355245"}, - {file = "rapidfuzz-2.13.7-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:8450d15f7765482e86ef9be2ad1a05683cd826f59ad236ef7b9fb606464a56aa"}, - {file = "rapidfuzz-2.13.7-cp38-cp38-win32.whl", hash = "sha256:460853983ab88f873173e27cc601c5276d469388e6ad6e08c4fd57b2a86f1064"}, - {file = "rapidfuzz-2.13.7-cp38-cp38-win_amd64.whl", hash = "sha256:424f82c35dbe4f83bdc3b490d7d696a1dc6423b3d911460f5493b7ffae999fd2"}, - {file = "rapidfuzz-2.13.7-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:c3fbe449d869ea4d0909fc9d862007fb39a584fb0b73349a6aab336f0d90eaed"}, - {file = "rapidfuzz-2.13.7-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:16080c05a63d6042643ae9b6cfec1aefd3e61cef53d0abe0df3069b9d4b72077"}, - {file = "rapidfuzz-2.13.7-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:dbcf5371ea704759fcce772c66a07647751d1f5dbdec7818331c9b31ae996c77"}, - {file = "rapidfuzz-2.13.7-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:114810491efb25464016fd554fdf1e20d390309cecef62587494fc474d4b926f"}, - {file = "rapidfuzz-2.13.7-cp39-cp39-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:99a84ab9ac9a823e7e93b4414f86344052a5f3e23b23aa365cda01393ad895bd"}, - {file = "rapidfuzz-2.13.7-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:81642a24798851b118f82884205fc1bd9ff70b655c04018c467824b6ecc1fabc"}, - {file = "rapidfuzz-2.13.7-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:c3741cb0bf9794783028e8b0cf23dab917fa5e37a6093b94c4c2f805f8e36b9f"}, - {file = "rapidfuzz-2.13.7-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:759a3361711586a29bc753d3d1bdb862983bd9b9f37fbd7f6216c24f7c972554"}, - {file = "rapidfuzz-2.13.7-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:1333fb3d603d6b1040e365dca4892ba72c7e896df77a54eae27dc07db90906e3"}, - {file = "rapidfuzz-2.13.7-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:916bc2e6cf492c77ad6deb7bcd088f0ce9c607aaeabc543edeb703e1fbc43e31"}, - {file = "rapidfuzz-2.13.7-cp39-cp39-musllinux_1_1_ppc64le.whl", hash = "sha256:23524635840500ce6f4d25005c9529a97621689c85d2f727c52eed1782839a6a"}, - {file = "rapidfuzz-2.13.7-cp39-cp39-musllinux_1_1_s390x.whl", hash = "sha256:ebe303cd9839af69dd1f7942acaa80b1ba90bacef2e7ded9347fbed4f1654672"}, - {file = "rapidfuzz-2.13.7-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:fe56659ccadbee97908132135de4b875543353351e0c92e736b7c57aee298b5a"}, - {file = "rapidfuzz-2.13.7-cp39-cp39-win32.whl", hash = "sha256:3f11a7eff7bc6301cd6a5d43f309e22a815af07e1f08eeb2182892fca04c86cb"}, - {file = "rapidfuzz-2.13.7-cp39-cp39-win_amd64.whl", hash = "sha256:e8914dad106dacb0775718e54bf15e528055c4e92fb2677842996f2d52da5069"}, - {file = "rapidfuzz-2.13.7-pp37-pypy37_pp73-macosx_10_9_x86_64.whl", hash = "sha256:7f7930adf84301797c3f09c94b9c5a9ed90a9e8b8ed19b41d2384937e0f9f5bd"}, - {file = "rapidfuzz-2.13.7-pp37-pypy37_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c31022d9970177f6affc6d5dd757ed22e44a10890212032fabab903fdee3bfe7"}, - {file = "rapidfuzz-2.13.7-pp37-pypy37_pp73-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:f42b82f268689f429def9ecfb86fa65ceea0eaf3fed408b570fe113311bf5ce7"}, - {file = "rapidfuzz-2.13.7-pp37-pypy37_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8b477b43ced896301665183a5e0faec0f5aea2373005648da8bdcb3c4b73f280"}, - {file = "rapidfuzz-2.13.7-pp37-pypy37_pp73-win_amd64.whl", hash = "sha256:d63def9bbc6b35aef4d76dc740301a4185867e8870cbb8719ec9de672212fca8"}, - {file = "rapidfuzz-2.13.7-pp38-pypy38_pp73-macosx_10_9_x86_64.whl", hash = "sha256:c66546e30addb04a16cd864f10f5821272a1bfe6462ee5605613b4f1cb6f7b48"}, - {file = "rapidfuzz-2.13.7-pp38-pypy38_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f799d1d6c33d81e983d3682571cc7d993ae7ff772c19b3aabb767039c33f6d1e"}, - {file = "rapidfuzz-2.13.7-pp38-pypy38_pp73-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:d82f20c0060ffdaadaf642b88ab0aa52365b56dffae812e188e5bdb998043588"}, - {file = "rapidfuzz-2.13.7-pp38-pypy38_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:042644133244bfa7b20de635d500eb9f46af7097f3d90b1724f94866f17cb55e"}, - {file = "rapidfuzz-2.13.7-pp38-pypy38_pp73-win_amd64.whl", hash = "sha256:75c45dcd595f8178412367e302fd022860ea025dc4a78b197b35428081ed33d5"}, - {file = "rapidfuzz-2.13.7-pp39-pypy39_pp73-macosx_10_9_x86_64.whl", hash = "sha256:3d8b081988d0a49c486e4e845a547565fee7c6e7ad8be57ff29c3d7c14c6894c"}, - {file = "rapidfuzz-2.13.7-pp39-pypy39_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:16ffad751f43ab61001187b3fb4a9447ec2d1aedeff7c5bac86d3b95f9980cc3"}, - {file = "rapidfuzz-2.13.7-pp39-pypy39_pp73-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:020858dd89b60ce38811cd6e37875c4c3c8d7fcd8bc20a0ad2ed1f464b34dc4e"}, - {file = "rapidfuzz-2.13.7-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:cda1e2f66bb4ba7261a0f4c2d052d5d909798fca557cbff68f8a79a87d66a18f"}, - {file = "rapidfuzz-2.13.7-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:b6389c50d8d214c9cd11a77f6d501529cb23279a9c9cafe519a3a4b503b5f72a"}, - {file = "rapidfuzz-2.13.7.tar.gz", hash = "sha256:8d3e252d4127c79b4d7c2ae47271636cbaca905c8bb46d80c7930ab906cf4b5c"}, + {file = "rapidfuzz-2.15.1-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:fc0bc259ebe3b93e7ce9df50b3d00e7345335d35acbd735163b7c4b1957074d3"}, + {file = "rapidfuzz-2.15.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:d59fb3a410d253f50099d7063855c2b95df1ef20ad93ea3a6b84115590899f25"}, + {file = "rapidfuzz-2.15.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:c525a3da17b6d79d61613096c8683da86e3573e807dfaecf422eea09e82b5ba6"}, + {file = "rapidfuzz-2.15.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d4deae6a918ecc260d0c4612257be8ba321d8e913ccb43155403842758c46fbe"}, + {file = "rapidfuzz-2.15.1-cp310-cp310-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:2577463d10811386e704a3ab58b903eb4e2a31b24dfd9886d789b0084d614b01"}, + {file = "rapidfuzz-2.15.1-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:f67d5f56aa48c0da9de4ab81bffb310683cf7815f05ea38e5aa64f3ba4368339"}, + {file = "rapidfuzz-2.15.1-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:d7927722ff43690e52b3145b5bd3089151d841d350c6f8378c3cfac91f67573a"}, + {file = "rapidfuzz-2.15.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6534afc787e32c4104f65cdeb55f6abe4d803a2d0553221d00ef9ce12788dcde"}, + {file = "rapidfuzz-2.15.1-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:d0ae6ec79a1931929bb9dd57bc173eb5ba4c7197461bf69e3a34b6dd314feed2"}, + {file = "rapidfuzz-2.15.1-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:be7ccc45c4d1a7dfb595f260e8022a90c6cb380c2a346ee5aae93f85c96d362b"}, + {file = "rapidfuzz-2.15.1-cp310-cp310-musllinux_1_1_ppc64le.whl", hash = "sha256:8ba013500a2b68c64b2aecc5fb56a2dad6c2872cf545a0308fd044827b6e5f6a"}, + {file = "rapidfuzz-2.15.1-cp310-cp310-musllinux_1_1_s390x.whl", hash = "sha256:4d9f7d10065f657f960b48699e7dddfce14ab91af4bab37a215f0722daf0d716"}, + {file = "rapidfuzz-2.15.1-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:7e24a1b802cea04160b3fccd75d2d0905065783ebc9de157d83c14fb9e1c6ce2"}, + {file = "rapidfuzz-2.15.1-cp310-cp310-win32.whl", hash = "sha256:dffdf03499e0a5b3442951bb82b556333b069e0661e80568752786c79c5b32de"}, + {file = "rapidfuzz-2.15.1-cp310-cp310-win_amd64.whl", hash = "sha256:7d150d90a7c6caae7962f29f857a4e61d42038cfd82c9df38508daf30c648ae7"}, + {file = "rapidfuzz-2.15.1-cp310-cp310-win_arm64.whl", hash = "sha256:87c30e9184998ff6eb0fa9221f94282ce7c908fd0da96a1ef66ecadfaaa4cdb7"}, + {file = "rapidfuzz-2.15.1-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:6986413cb37035eb796e32f049cbc8c13d8630a4ac1e0484e3e268bb3662bd1b"}, + {file = "rapidfuzz-2.15.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:a72f26e010d4774b676f36e43c0fc8a2c26659efef4b3be3fd7714d3491e9957"}, + {file = "rapidfuzz-2.15.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:b5cd54c98a387cca111b3b784fc97a4f141244bbc28a92d4bde53f164464112e"}, + {file = "rapidfuzz-2.15.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:da7fac7c3da39f93e6b2ebe386ed0ffe1cefec91509b91857f6e1204509e931f"}, + {file = "rapidfuzz-2.15.1-cp311-cp311-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:f976e76ac72f650790b3a5402431612175b2ac0363179446285cb3c901136ca9"}, + {file = "rapidfuzz-2.15.1-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:abde47e1595902a490ed14d4338d21c3509156abb2042a99e6da51f928e0c117"}, + {file = "rapidfuzz-2.15.1-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:ca8f1747007a3ce919739a60fa95c5325f7667cccf6f1c1ef18ae799af119f5e"}, + {file = "rapidfuzz-2.15.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c35da09ab9797b020d0d4f07a66871dfc70ea6566363811090353ea971748b5a"}, + {file = "rapidfuzz-2.15.1-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:a3a769ca7580686a66046b77df33851b3c2d796dc1eb60c269b68f690f3e1b65"}, + {file = "rapidfuzz-2.15.1-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:d50622efefdb03a640a51a6123748cd151d305c1f0431af762e833d6ffef71f0"}, + {file = "rapidfuzz-2.15.1-cp311-cp311-musllinux_1_1_ppc64le.whl", hash = "sha256:b7461b0a7651d68bc23f0896bffceea40f62887e5ab8397bf7caa883592ef5cb"}, + {file = "rapidfuzz-2.15.1-cp311-cp311-musllinux_1_1_s390x.whl", hash = "sha256:074ee9e17912e025c72a5780ee4c7c413ea35cd26449719cc399b852d4e42533"}, + {file = "rapidfuzz-2.15.1-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:7025fb105a11f503943f17718cdb8241ea3bb4d812c710c609e69bead40e2ff0"}, + {file = "rapidfuzz-2.15.1-cp311-cp311-win32.whl", hash = "sha256:2084d36b95139413cef25e9487257a1cc892b93bd1481acd2a9656f7a1d9930c"}, + {file = "rapidfuzz-2.15.1-cp311-cp311-win_amd64.whl", hash = "sha256:5a738fcd24e34bce4b19126b92fdae15482d6d3a90bd687fd3d24ce9d28ce82d"}, + {file = "rapidfuzz-2.15.1-cp311-cp311-win_arm64.whl", hash = "sha256:dc3cafa68cfa54638632bdcadf9aab89a3d182b4a3f04d2cad7585ed58ea8731"}, + {file = "rapidfuzz-2.15.1-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:3c53d57ba7a88f7bf304d4ea5a14a0ca112db0e0178fff745d9005acf2879f7d"}, + {file = "rapidfuzz-2.15.1-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a6ee758eec4cf2215dc8d8eafafcea0d1f48ad4b0135767db1b0f7c5c40a17dd"}, + {file = "rapidfuzz-2.15.1-cp37-cp37m-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:2d93ba3ae59275e7a3a116dac4ffdb05e9598bf3ee0861fecc5b60fb042d539e"}, + {file = "rapidfuzz-2.15.1-cp37-cp37m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:7c3ff75e647908ddbe9aa917fbe39a112d5631171f3fcea5809e2363e525a59d"}, + {file = "rapidfuzz-2.15.1-cp37-cp37m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:6d89c421702474c6361245b6b199e6e9783febacdbfb6b002669e6cb3ef17a09"}, + {file = "rapidfuzz-2.15.1-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4f69e6199fec0f58f9a89afbbaea78d637c7ce77f656a03a1d6ea6abdc1d44f8"}, + {file = "rapidfuzz-2.15.1-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:41dfea282844d0628279b4db2929da0dacb8ac317ddc5dcccc30093cf16357c1"}, + {file = "rapidfuzz-2.15.1-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:2dd03477feefeccda07b7659dd614f6738cfc4f9b6779dd61b262a73b0a9a178"}, + {file = "rapidfuzz-2.15.1-cp37-cp37m-musllinux_1_1_ppc64le.whl", hash = "sha256:5efe035aa76ff37d1b5fa661de3c4b4944de9ff227a6c0b2e390a95c101814c0"}, + {file = "rapidfuzz-2.15.1-cp37-cp37m-musllinux_1_1_s390x.whl", hash = "sha256:ed2cf7c69102c7a0a06926d747ed855bc836f52e8d59a5d1e3adfd980d1bd165"}, + {file = "rapidfuzz-2.15.1-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:a0e441d4c2025110ec3eba5d54f11f78183269a10152b3a757a739ffd1bb12bf"}, + {file = "rapidfuzz-2.15.1-cp37-cp37m-win32.whl", hash = "sha256:a4a54efe17cc9f53589c748b53f28776dfdfb9bc83619685740cb7c37985ac2f"}, + {file = "rapidfuzz-2.15.1-cp37-cp37m-win_amd64.whl", hash = "sha256:bb8318116ecac4dfb84841d8b9b461f9bb0c3be5b616418387d104f72d2a16d1"}, + {file = "rapidfuzz-2.15.1-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:e9296c530e544f68858c3416ad1d982a1854f71e9d2d3dcedb5b216e6d54f067"}, + {file = "rapidfuzz-2.15.1-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:49c4bcdb9238f11f8c4eba1b898937f09b92280d6f900023a8216008f299b41a"}, + {file = "rapidfuzz-2.15.1-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:ebb40a279e134bb3fef099a8b58ed5beefb201033d29bdac005bddcdb004ef71"}, + {file = "rapidfuzz-2.15.1-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a7381c11cb590bbd4e6f2d8779a0b34fdd2234dfa13d0211f6aee8ca166d9d05"}, + {file = "rapidfuzz-2.15.1-cp38-cp38-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:cfdcdedfd12a0077193f2cf3626ff6722c5a184adf0d2d51f1ec984bf21c23c3"}, + {file = "rapidfuzz-2.15.1-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:f85bece1ec59bda8b982bd719507d468d4df746dfb1988df11d916b5e9fe19e8"}, + {file = "rapidfuzz-2.15.1-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:b1b393f4a1eaa6867ffac6aef58cfb04bab2b3d7d8e40b9fe2cf40dd1d384601"}, + {file = "rapidfuzz-2.15.1-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:53de456ef020a77bf9d7c6c54860a48e2e902584d55d3001766140ac45c54bc7"}, + {file = "rapidfuzz-2.15.1-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:2492330bc38b76ed967eab7bdaea63a89b6ceb254489e2c65c3824efcbf72993"}, + {file = "rapidfuzz-2.15.1-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:099e4c6befaa8957a816bdb67ce664871f10aaec9bebf2f61368cf7e0869a7a1"}, + {file = "rapidfuzz-2.15.1-cp38-cp38-musllinux_1_1_ppc64le.whl", hash = "sha256:46599b2ad4045dd3f794a24a6db1e753d23304699d4984462cf1ead02a51ddf3"}, + {file = "rapidfuzz-2.15.1-cp38-cp38-musllinux_1_1_s390x.whl", hash = "sha256:591f19d16758a3c55c9d7a0b786b40d95599a5b244d6eaef79c7a74fcf5104d8"}, + {file = "rapidfuzz-2.15.1-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:ed17359061840eb249f8d833cb213942e8299ffc4f67251a6ed61833a9f2ea20"}, + {file = "rapidfuzz-2.15.1-cp38-cp38-win32.whl", hash = "sha256:aa1e5aad325168e29bf8e17006479b97024aa9d2fdbe12062bd2f8f09080acf8"}, + {file = "rapidfuzz-2.15.1-cp38-cp38-win_amd64.whl", hash = "sha256:c2bb68832b140c551dbed691290bef4ee6719d4e8ce1b7226a3736f61a9d1a83"}, + {file = "rapidfuzz-2.15.1-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:3fac40972cf7b6c14dded88ae2331eb50dfbc278aa9195473ef6fc6bfe49f686"}, + {file = "rapidfuzz-2.15.1-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:f0e456cbdc0abf39352800309dab82fd3251179fa0ff6573fa117f51f4e84be8"}, + {file = "rapidfuzz-2.15.1-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:22b9d22022b9d09fd4ece15102270ab9b6a5cfea8b6f6d1965c1df7e3783f5ff"}, + {file = "rapidfuzz-2.15.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:46754fe404a9a6f5cbf7abe02d74af390038d94c9b8c923b3f362467606bfa28"}, + {file = "rapidfuzz-2.15.1-cp39-cp39-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:91abb8bf7610efe326394adc1d45e1baca8f360e74187f3fa0ef3df80cdd3ba6"}, + {file = "rapidfuzz-2.15.1-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:e40a2f60024f9d3c15401e668f732800114a023f3f8d8c40f1521a62081ff054"}, + {file = "rapidfuzz-2.15.1-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:a48ee83916401ac73938526d7bd804e01d2a8fe61809df7f1577b0b3b31049a3"}, + {file = "rapidfuzz-2.15.1-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c71580052f9dbac443c02f60484e5a2e5f72ad4351b84b2009fbe345b1f38422"}, + {file = "rapidfuzz-2.15.1-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:82b86d5b8c1b9bcbc65236d75f81023c78d06a721c3e0229889ff4ed5c858169"}, + {file = "rapidfuzz-2.15.1-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:fc4528b7736e5c30bc954022c2cf410889abc19504a023abadbc59cdf9f37cae"}, + {file = "rapidfuzz-2.15.1-cp39-cp39-musllinux_1_1_ppc64le.whl", hash = "sha256:e1e0e569108a5760d8f01d0f2148dd08cc9a39ead79fbefefca9e7c7723c7e88"}, + {file = "rapidfuzz-2.15.1-cp39-cp39-musllinux_1_1_s390x.whl", hash = "sha256:94e1c97f0ad45b05003806f8a13efc1fc78983e52fa2ddb00629003acf4676ef"}, + {file = "rapidfuzz-2.15.1-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:47e81767a962e41477a85ad7ac937e34d19a7d2a80be65614f008a5ead671c56"}, + {file = "rapidfuzz-2.15.1-cp39-cp39-win32.whl", hash = "sha256:79fc574aaf2d7c27ec1022e29c9c18f83cdaf790c71c05779528901e0caad89b"}, + {file = "rapidfuzz-2.15.1-cp39-cp39-win_amd64.whl", hash = "sha256:f3dd4bcef2d600e0aa121e19e6e62f6f06f22a89f82ef62755e205ce14727874"}, + {file = "rapidfuzz-2.15.1-cp39-cp39-win_arm64.whl", hash = "sha256:cac095cbdf44bc286339a77214bbca6d4d228c9ebae3da5ff6a80aaeb7c35634"}, + {file = "rapidfuzz-2.15.1-pp37-pypy37_pp73-macosx_10_9_x86_64.whl", hash = "sha256:b89d1126be65c85763d56e3b47d75f1a9b7c5529857b4d572079b9a636eaa8a7"}, + {file = "rapidfuzz-2.15.1-pp37-pypy37_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:19b7460e91168229768be882ea365ba0ac7da43e57f9416e2cfadc396a7df3c2"}, + {file = "rapidfuzz-2.15.1-pp37-pypy37_pp73-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:93c33c03e7092642c38f8a15ca2d8fc38da366f2526ec3b46adf19d5c7aa48ba"}, + {file = "rapidfuzz-2.15.1-pp37-pypy37_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:040faca2e26d9dab5541b45ce72b3f6c0e36786234703fc2ac8c6f53bb576743"}, + {file = "rapidfuzz-2.15.1-pp37-pypy37_pp73-win_amd64.whl", hash = "sha256:6e2a3b23e1e9aa13474b3c710bba770d0dcc34d517d3dd6f97435a32873e3f28"}, + {file = "rapidfuzz-2.15.1-pp38-pypy38_pp73-macosx_10_9_x86_64.whl", hash = "sha256:2e597b9dfd6dd180982684840975c458c50d447e46928efe3e0120e4ec6f6686"}, + {file = "rapidfuzz-2.15.1-pp38-pypy38_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d14752c9dd2036c5f36ebe8db5f027275fa7d6b3ec6484158f83efb674bab84e"}, + {file = "rapidfuzz-2.15.1-pp38-pypy38_pp73-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:558224b6fc6124d13fa32d57876f626a7d6188ba2a97cbaea33a6ee38a867e31"}, + {file = "rapidfuzz-2.15.1-pp38-pypy38_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3c89cfa88dc16fd8c9bcc0c7f0b0073f7ef1e27cceb246c9f5a3f7004fa97c4d"}, + {file = "rapidfuzz-2.15.1-pp38-pypy38_pp73-win_amd64.whl", hash = "sha256:509c5b631cd64df69f0f011893983eb15b8be087a55bad72f3d616b6ae6a0f96"}, + {file = "rapidfuzz-2.15.1-pp39-pypy39_pp73-macosx_10_9_x86_64.whl", hash = "sha256:0f73a04135a03a6e40393ecd5d46a7a1049d353fc5c24b82849830d09817991f"}, + {file = "rapidfuzz-2.15.1-pp39-pypy39_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8c99d53138a2dfe8ada67cb2855719f934af2733d726fbf73247844ce4dd6dd5"}, + {file = "rapidfuzz-2.15.1-pp39-pypy39_pp73-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:f01fa757f0fb332a1f045168d29b0d005de6c39ee5ce5d6c51f2563bb53c601b"}, + {file = "rapidfuzz-2.15.1-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:60368e1add6e550faae65614844c43f8a96e37bf99404643b648bf2dba92c0fb"}, + {file = "rapidfuzz-2.15.1-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:785744f1270828cc632c5a3660409dee9bcaac6931a081bae57542c93e4d46c4"}, + {file = "rapidfuzz-2.15.1.tar.gz", hash = "sha256:d62137c2ca37aea90a11003ad7dc109c8f1739bfbe5a9a217f3cdb07d7ac00f6"}, ] [package.extras] @@ -2057,21 +2073,21 @@ files = [ [[package]] name = "uplc" -version = "0.6.0" +version = "0.6.1" description = "Python implementation of untyped plutus language core" category = "main" optional = false python-versions = ">=3" files = [ - {file = "uplc-0.6.0-py3-none-any.whl", hash = "sha256:3a1b458325735b6b2427a7cd7881164a5b1a955953587f6f3715f7af77b80976"}, - {file = "uplc-0.6.0.tar.gz", hash = "sha256:eaf50d0c57860b2976012b4f1f148b3c6cbc95f82ddfc1e4e02b738bf4a104b6"}, + {file = "uplc-0.6.1-py3-none-any.whl", hash = "sha256:74e0af02562539fa035f196783532b1121734a694a90c6d478bd75b144c38e9d"}, + {file = "uplc-0.6.1.tar.gz", hash = "sha256:1115d15ba1cd149568306591fbce67ef526687ad0479a4702cbd73962bf407d9"}, ] [package.dependencies] cbor2 = "5.4.6" frozendict = "2.3.4" frozenlist = "1.3.3" -pycardano = "0.7.2" +pycardano = "0.8.0" python-secp256k1-cardano = "0.2.3" rply = "0.7.8" @@ -2267,4 +2283,4 @@ testing = ["big-O", "flake8 (<5)", "jaraco.functools", "jaraco.itertools", "more [metadata] lock-version = "2.0" python-versions = ">=3.8, <3.12" -content-hash = "073265a1db59654d2b29ad8002995b2f4d76f6f802b31a24e16682f789275d77" +content-hash = "1afd8e591b3ce059ed86945517c939cc0b2724269b71c993d3a2a64f7ddb8a43" diff --git a/pyproject.toml b/pyproject.toml index a4b16c5..9861de0 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,6 +1,6 @@ [tool.poetry] name = "hebi" -version = "0.1.1.0.11.0" +version = "0.1.1.0.12.3" description = "A simple and fast pythonic programming language for Smart Contracts on Cardano" authors = ["nielstron "] license = "MIT" @@ -22,15 +22,15 @@ packages = [{include = "hebi"}] [tool.poetry.dependencies] python = ">=3.8, <3.12" -uplc = "0.6.0" -pluthon = "0.3.2" -pycardano = "0.7.2" -frozenlist = "1.3.3" +uplc = "^0.6.1" +pluthon = "^0.3.3" +pycardano = "^0.8.0" +frozenlist = "^1.3.3" [tool.poetry.group.dev.dependencies] -hypothesis = "6.70.0" -parameterized = "0.8.1" -black = "22.12.0" +hypothesis = "6.71.0" +parameterized = "0.9.0" +black = "23.3.0" pre-commit = "^3.1.1" coverage = "<7.0" pytest = "^7.2.2"