Skip to content

Commit 3b0736a

Browse files
bbyalcinkayarv-auditortothtamas28
authored
Refactor str paths to Path (#293)
* Refactor `str` paths to `Path` * Set Version: 0.1.85 * Set Version: 0.1.86 * Apply suggestions from code review Co-authored-by: Tamás Tóth <[email protected]> * Set Version: 0.1.87 --------- Co-authored-by: devops <[email protected]> Co-authored-by: Tamás Tóth <[email protected]>
1 parent bae4758 commit 3b0736a

File tree

6 files changed

+62
-82
lines changed

6 files changed

+62
-82
lines changed

kmultiversx/pyproject.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ build-backend = "poetry.core.masonry.api"
44

55
[tool.poetry]
66
name = "kmultiversx"
7-
version = "0.1.86"
7+
version = "0.1.87"
88
description = "Python tools for Elrond semantics"
99
authors = [
1010
"Runtime Verification, Inc. <[email protected]>",

kmultiversx/src/kmultiversx/kasmer.py

Lines changed: 8 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,8 @@
11
from __future__ import annotations
22

3-
import glob
43
import json
54
import sys
6-
from os.path import join
5+
from pathlib import Path
76
from subprocess import SubprocessError
87
from typing import TYPE_CHECKING, cast
98

@@ -42,7 +41,6 @@
4241

4342
if TYPE_CHECKING:
4443
from collections.abc import Iterable, Mapping
45-
from pathlib import Path
4644

4745
from hypothesis.strategies import SearchStrategy
4846
from pyk.kast.inner import KInner
@@ -60,25 +58,8 @@
6058
REC_LIMIT = 4000
6159

6260

63-
def load_input_json(test_dir: str) -> dict:
64-
try:
65-
with open(join(test_dir, INPUT_FILE_NAME)) as f:
66-
return json.load(f)
67-
except FileNotFoundError:
68-
raise FileNotFoundError(f'{INPUT_FILE_NAME!r} not found in "{test_dir!r}"') from None
69-
70-
71-
def find_test_wasm_path(test_dir: str) -> str:
72-
test_wasm_path = glob.glob(test_dir + '/output/*.wasm')
73-
# TODO this loads the first wasm file in the directory. what if there are multiple wasm files?
74-
if test_wasm_path:
75-
return test_wasm_path[0]
76-
else:
77-
raise ValueError(f'WASM file not found: {test_dir}/output/?.wasm')
78-
79-
80-
def load_contract_wasms(contract_wasm_paths: Iterable[str]) -> dict[bytes, KInner]:
81-
contract_wasm_modules = {bytes(f, 'ascii'): load_wasm(f) for f in contract_wasm_paths}
61+
def load_contract_wasms(contract_wasm_paths: Iterable[Path]) -> dict[bytes, KInner]:
62+
contract_wasm_modules = {bytes(str(f), 'ascii'): load_wasm(f) for f in contract_wasm_paths}
8263

8364
return contract_wasm_modules
8465

@@ -167,15 +148,15 @@ def run_config_and_check_empty(
167148
# Test metadata
168149

169150

170-
def get_test_endpoints(test_dir: str) -> Mapping[str, tuple[str, ...]]:
171-
abi_paths = glob.glob(test_dir + '/output/*.abi.json')
172-
# TODO this loads the first wasm file in the directory. what if there are multiple wasm files?
151+
def get_test_endpoints(test_dir: Path) -> Mapping[str, tuple[str, ...]]:
152+
abi_paths = list(test_dir.glob('./output/*.abi.json'))
153+
# Test contracts are not supposed to be multi-contract, there should be only 1 abi file
173154
if abi_paths:
174-
abi_path = abi_paths[0]
155+
abi_path = Path(abi_paths[0])
175156
else:
176157
raise ValueError(f'ABI file not found: {test_dir}/output/?.abi.json')
177158

178-
with open(abi_path) as f:
159+
with abi_path.open() as f:
179160
abi_json = json.load(f)
180161

181162
endpoints = {}

kmultiversx/src/kmultiversx/runtime.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,7 @@ def main() -> None:
4545
)
4646

4747
for definition_dir, output_path in targets:
48-
esdt_wasm = load_wasm(str(args.esdt_wasm_path))
48+
esdt_wasm = load_wasm(args.esdt_wasm_path)
4949

5050
krun = KRun(definition_dir)
5151
config = load_runtime(krun, esdt_wasm)

kmultiversx/src/kmultiversx/scenario.py

Lines changed: 44 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -2,18 +2,20 @@
22

33
import argparse
44
import json
5-
import os
65
import subprocess
76
import sys
87
import tempfile
8+
from pathlib import Path
99
from typing import TYPE_CHECKING
1010

1111
from Cryptodome.Hash import keccak
12+
from pyk.cli.utils import file_path
1213
from pyk.kast.inner import KApply, KSequence, KToken, Subst
1314
from pyk.kast.manip import split_config_from
1415
from pyk.kdist import kdist
1516
from pyk.ktool.krun import KRun
1617
from pyk.prelude.collections import set_of
18+
from pyk.utils import abs_or_rel_to, check_file_path
1719
from pykwasm.kwasm_ast import KBytes, KInt, KString
1820

1921
from kmultiversx.utils import (
@@ -294,7 +296,7 @@ def mandos_arguments_to_klist(arguments: list[str]) -> KInner:
294296
return ListBytes(wrapped)
295297

296298

297-
def mandos_to_set_account(address: str, sections: dict, filename: str, output_dir: str) -> list[KApply]:
299+
def mandos_to_set_account(address: str, sections: dict, filename: Path, output_dir: Path) -> list[KApply]:
298300
"""Creates a K account cell from a Mandos account description."""
299301
address_value = mandos_argument_to_kbytes(address)
300302
nonce_value = mandos_int_to_kint(sections.get('nonce', '0'))
@@ -404,7 +406,7 @@ def str_to_kast(s: str) -> KInner:
404406
return [str_to_kast(r) for r in v['roles']]
405407

406408

407-
def mandos_to_check_account(address: str, sections: dict, filename: str) -> list:
409+
def mandos_to_check_account(address: str, sections: dict, filename: Path) -> list:
408410
k_steps: list[KInner] = []
409411
address_value = mandos_argument_to_kbytes(address)
410412
if ('nonce' in sections) and (sections['nonce'] != '*'):
@@ -424,9 +426,8 @@ def mandos_to_check_account(address: str, sections: dict, filename: str) -> list
424426
storage_value = KMapBytesToBytes(wrapped_pairs)
425427
k_steps.append(KApply('checkAccountStorage', [address_value, storage_value]))
426428
if ('code' in sections) and (sections['code'] != '*'):
427-
code_path = get_contract_code(sections['code'], filename)
428-
if code_path is None:
429-
code_path = ''
429+
code_path_ = get_contract_code(sections['code'], filename)
430+
code_path = '' if code_path_ is None else str(code_path_)
430431
k_code_path = KString(code_path)
431432
k_steps.append(KApply('checkAccountCode', [address_value, k_code_path]))
432433
if ('esdt' in sections) and (sections['esdt'] != '*'):
@@ -447,15 +448,15 @@ def mandos_to_check_account(address: str, sections: dict, filename: str) -> list
447448
return k_steps
448449

449450

450-
def mandos_to_deploy_tx(tx: dict, filename: str, output_dir: str) -> KInner:
451+
def mandos_to_deploy_tx(tx: dict, filename: Path, output_dir: Path) -> KInner:
451452
sender = mandos_argument_to_kbytes(tx['from'])
452453
value = mandos_int_to_kint(get_egld_value(tx))
453454
arguments = mandos_arguments_to_klist(tx['arguments'])
454455
gas_limit = mandos_int_to_kint(tx['gasLimit'])
455456
gas_price = mandos_int_to_kint(tx.get('gasPrice', '0'), default_when_empty=0)
456457

457458
code = get_contract_code(tx['contractCode'], filename)
458-
assert isinstance(code, str)
459+
assert code is not None
459460
module = file_to_module_decl(code, output_dir)
460461

461462
return KApply('deployTx', [sender, value, module, arguments, gas_limit, gas_price])
@@ -576,24 +577,25 @@ def register(with_name: str) -> KInner:
576577
return KApply('register', [KString(with_name)])
577578

578579

579-
def file_to_module_decl(filename: str, output_dir: str) -> KInner:
580-
if filename[-5:] == '.wasm':
580+
def file_to_module_decl(filename: Path, output_dir: Path) -> KInner:
581+
if filename.suffix == '.wasm':
581582
return load_wasm(filename)
582-
if filename[-5:] == '.wast' or filename[-4:] == '.wat':
583+
if filename.suffix == '.wast' or filename.suffix == '.wat':
583584
return wat_file_to_module_decl(filename, output_dir)
584-
if filename[-10:] == '.mxsc.json':
585+
if filename.name.endswith('.mxsc.json'):
585586
return load_wasm_from_mxsc(filename)
586587

587588
raise ValueError(f'Filetype not yet supported: {filename}')
588589

589590

590-
def wat_file_to_module_decl(filename: str, output_dir: str) -> KInner:
591-
if not os.path.exists(filename):
592-
raise Exception(f'file {filename} does not exist')
591+
def wat_file_to_module_decl(file_path: Path, output_dir: Path) -> KInner:
592+
file_path = file_path.resolve()
593+
check_file_path(file_path)
594+
595+
new_wasm_file_path = output_dir / file_path.with_suffix('.wasm').name
593596

594-
new_wasm_filename = os.path.join(output_dir, os.path.basename(filename) + '.wasm')
595597
try:
596-
subprocess.check_output(f'wat2wasm {filename} --output={new_wasm_filename}', shell=True)
598+
subprocess.check_output(f'wat2wasm {file_path} --output={new_wasm_file_path}', shell=True)
597599
except subprocess.CalledProcessError as e:
598600
print('Failed: %s' % e.cmd)
599601
print('return code: %d' % e.returncode)
@@ -602,24 +604,22 @@ def wat_file_to_module_decl(filename: str, output_dir: str) -> KInner:
602604
print('stderr:')
603605
print(e.stderr)
604606
raise e
605-
return load_wasm(new_wasm_filename)
607+
return load_wasm(new_wasm_file_path)
606608

607609

608-
def get_external_file_path(test_file: str, rel_path_to_new_file: str) -> str:
609-
test_file_path = os.path.dirname(test_file)
610-
ext_file = os.path.normpath(os.path.join(test_file_path, rel_path_to_new_file))
611-
return ext_file
610+
def get_external_file_path(test_file: Path, rel_path_to_new_file: Path) -> Path:
611+
return abs_or_rel_to(rel_path_to_new_file, test_file.parent).resolve()
612612

613613

614-
def get_contract_code(code: str, filename: str) -> str | None:
614+
def get_contract_code(code: str, filename: Path) -> Path | None:
615615
if code[0:5] in ('file:', 'mxsc:'):
616-
return get_external_file_path(filename, code[5:])
616+
return get_external_file_path(filename, Path(code[5:]))
617617
if code == '':
618618
return None
619619
raise Exception('Currently only support getting code from file, or empty code.')
620620

621621

622-
def get_steps_sc_deploy(step: dict, filename: str, output_dir: str) -> list:
622+
def get_steps_sc_deploy(step: dict, filename: Path, output_dir: Path) -> list:
623623
k_steps = []
624624
tx = mandos_to_deploy_tx(step['tx'], filename, output_dir)
625625
k_steps.append(tx)
@@ -682,7 +682,7 @@ def get_steps_new_addresses(new_addresses: dict | None) -> list[KApply]:
682682
return ret
683683

684684

685-
def get_steps_set_state(step: dict, filename: str, output_dir: str) -> list[KApply]:
685+
def get_steps_set_state(step: dict, filename: Path, output_dir: Path) -> list[KApply]:
686686
k_steps: list[KApply] = []
687687
if 'accounts' in step:
688688
set_accounts = [
@@ -706,7 +706,7 @@ def get_steps_set_state(step: dict, filename: str, output_dir: str) -> list[KApp
706706
return k_steps
707707

708708

709-
def get_steps_check_state(step: dict, filename: str) -> list:
709+
def get_steps_check_state(step: dict, filename: Path) -> list:
710710
k_steps = []
711711
if 'accounts' in step:
712712
for address, sections in step['accounts'].items():
@@ -720,8 +720,8 @@ def get_steps_check_state(step: dict, filename: str) -> list:
720720
return k_steps
721721

722722

723-
def get_steps_as_kseq(filename: str, output_dir: str, args: argparse.Namespace) -> list:
724-
with open(filename) as f:
723+
def get_steps_as_kseq(filename: Path, output_dir: Path, args: argparse.Namespace) -> list:
724+
with filename.open() as f:
725725
mandos_test = json.loads(f.read())
726726
if 'name' in mandos_test:
727727
if args.verbose:
@@ -743,7 +743,7 @@ def get_steps_as_kseq(filename: str, output_dir: str, args: argparse.Namespace)
743743
elif step['step'] == 'checkState':
744744
k_steps.append((step['step'], get_steps_check_state(step, filename)))
745745
elif step['step'] == 'externalSteps':
746-
steps_file = get_external_file_path(filename, step['path'])
746+
steps_file = get_external_file_path(filename, Path(step['path']))
747747
print('Load external: %s' % steps_file)
748748
k_steps = k_steps + get_steps_as_kseq(steps_file, output_dir, args)
749749
elif step['step'] == 'transfer':
@@ -758,11 +758,11 @@ def get_steps_as_kseq(filename: str, output_dir: str, args: argparse.Namespace)
758758
def run_test_file(
759759
krun: KRun,
760760
template_wasm_config: KInner,
761-
test_file_path: str,
762-
output_dir: str,
761+
test_file_path: Path,
762+
output_dir: Path,
763763
cmd_args: argparse.Namespace,
764764
) -> KInner:
765-
test_name = os.path.basename(test_file_path)
765+
test_name = test_file_path.stem
766766
k_steps = get_steps_as_kseq(test_file_path, output_dir, cmd_args)
767767
final_config = template_wasm_config
768768

@@ -805,17 +805,17 @@ def run_test_file(
805805
# ... Setup Elrond Wasm
806806

807807

808-
def log_intermediate_state(krun: KRun, name: str, config: KInner, output_dir: str) -> None:
809-
with open(f'{output_dir}/{name}', 'w') as f:
810-
f.write(kast_to_json_str(config))
811-
with open(f'{output_dir}/{name}.pretty.k', 'w') as f:
812-
pretty = krun.pretty_print(config)
813-
f.write(pretty)
808+
def log_intermediate_state(krun: KRun, name: str, config: KInner, output_dir: Path) -> None:
809+
json_path = output_dir / name
810+
json_path.write_text(kast_to_json_str(config))
811+
812+
kore_path = output_dir / (name + '.pretty.k')
813+
kore_path.write_text(krun.pretty_print(config))
814814

815815

816816
def run_tests() -> None:
817817
test_args = argparse.ArgumentParser(description='')
818-
test_args.add_argument('files', metavar='N', type=str, nargs='+', help='')
818+
test_args.add_argument('files', metavar='N', type=file_path, nargs='+', help='')
819819
test_args.add_argument('--log-level', choices=['none', 'per-file', 'per-step'], default='per-file')
820820
test_args.add_argument('--verbose', action='store_true', help='')
821821
test_args.add_argument(
@@ -838,14 +838,13 @@ def run_tests() -> None:
838838
for test in tests:
839839
if args.verbose:
840840
print('Running test %s' % test)
841-
tmpdir = tempfile.mkdtemp(prefix='mandos_')
841+
tmpdir = Path(tempfile.mkdtemp(prefix='mandos_'))
842842
if args.verbose:
843843
print('Intermediate test outputs stored in:\n%s' % tmpdir)
844844

845-
initial_name = '0000_initial_config'
846-
with open(f'{tmpdir}/{initial_name}', 'w') as f:
847-
f.write(kast_to_json_str(template_wasm_config))
848-
845+
initial_path = tmpdir / '0000_initial_config'
846+
initial_path.write_text(kast_to_json_str(template_wasm_config))
847+
assert isinstance(test, Path)
849848
run_test_file(krun, template_wasm_config, test, tmpdir, args)
850849

851850
if args.verbose:

kmultiversx/src/kmultiversx/utils.py

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@ def read_kasmer_runtime() -> KInner:
3333

3434

3535
def read_kinner_json(path: Path) -> KInner:
36-
with open(str(path)) as f:
36+
with path.open() as f:
3737
config_json = json.load(f)
3838
return KInner.from_dict(config_json['term'])
3939

@@ -50,17 +50,17 @@ def flatten(l: list[list[T]]) -> list[T]:
5050
return [item for sublist in l for item in sublist]
5151

5252

53-
def load_wasm(filename: str) -> KInner:
54-
with open(filename, 'rb') as f:
55-
return wasm2kast.wasm2kast(f, filename)
53+
def load_wasm(file_path: Path) -> KInner:
54+
with file_path.open(mode='rb') as f:
55+
return wasm2kast.wasm2kast(f, str(file_path))
5656

5757

58-
def load_wasm_from_mxsc(filename: str) -> KInner:
59-
with open(filename) as f:
58+
def load_wasm_from_mxsc(file_path: Path) -> KInner:
59+
with file_path.open() as f:
6060
contract_json = json.load(f)
6161
code_hex = contract_json['code']
6262
code_bytes = bytes.fromhex(code_hex)
63-
return wasm2kast.wasm2kast(BytesIO(code_bytes), filename)
63+
return wasm2kast.wasm2kast(BytesIO(code_bytes), str(file_path))
6464

6565

6666
def krun_config(krun: KRun, conf: KInner, pipe_stderr: bool = False) -> KInner:

package/version

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
0.1.86
1+
0.1.87

0 commit comments

Comments
 (0)